1- import React , { useEffect } from "react" ;
2- import { useListData } from "react-stately" ;
1+ import React from "react" ;
32import {
43 Button ,
54 ListBox ,
@@ -13,12 +12,8 @@ import { cn } from "../../utils";
1312import DragAndDropIcon from "../../assets/svgs/drag-and-drop.svg" ;
1413import Trash from "../../assets/svgs/trash.svg" ;
1514import clsx from "clsx" ;
15+ import { ListItem , useList } from "./useList" ;
1616
17- type ListItem = {
18- id : string | number ;
19- name : string ;
20- value : any ;
21- } ;
2217interface IDraggableList
2318 extends Omit <
2419 ListBoxProps < ListBoxItemProps > ,
@@ -53,24 +48,26 @@ function DraggableList({
5348 deletionDisabled = false ,
5449 ...props
5550} : Readonly < IDraggableList > ) {
56- const list = useListData ( {
51+ const {
52+ items : list ,
53+ moveAfter,
54+ moveBefore,
55+ remove,
56+ getItem,
57+ } = useList ( {
5758 initialItems : items ,
59+ onChange : updateCallback ,
5860 } ) ;
5961
60- useEffect ( ( ) => {
61- if ( ! updateCallback ) return ;
62- updateCallback ( list . items ) ;
63- } , [ list , updateCallback , items ] ) ;
64-
6562 const { dragAndDropHooks } = useDragAndDrop ( {
6663 getItems : ( keys ) =>
67- [ ...keys ] . map ( ( key ) => ( { "text/plain" : list . getItem ( key ) ! . name } ) ) ,
64+ [ ...keys ] . map ( ( key ) => ( { "text/plain" : getItem ( key ) ! . name } ) ) ,
6865 getAllowedDropOperations : ( ) => [ "move" ] ,
6966 onReorder ( e ) {
7067 if ( e . target . dropPosition === "before" ) {
71- list . moveBefore ( e . target . key , e . keys ) ;
68+ moveBefore ( e . target . key , e . keys ) ;
7269 } else if ( e . target . dropPosition === "after" ) {
73- list . moveAfter ( e . target . key , e . keys ) ;
70+ moveAfter ( e . target . key , e . keys ) ;
7471 }
7572 } ,
7673 renderDragPreview,
@@ -81,11 +78,11 @@ function DraggableList({
8178 { ...props }
8279 aria-label = { props [ "aria-label" ] ?? "Reorderable list" }
8380 selectionMode = "single"
84- items = { list . items }
81+ items = { list }
8582 dragAndDropHooks = { dragDisabled ? undefined : dragAndDropHooks }
8683 onSelectionChange = { ( keys ) => {
8784 const keyArr = Array . from ( keys ) ;
88- const selectedItem = list . getItem ( keyArr [ 0 ] ) ;
85+ const selectedItem = getItem ( keyArr [ 0 ] ) ;
8986
9087 if ( selectionCallback && selectedItem ) selectionCallback ( selectedItem ) ;
9188 } }
@@ -96,50 +93,54 @@ function DraggableList({
9693 className ,
9794 ) }
9895 >
99- { ( item ) => (
100- < ListBoxItem
101- textValue = { item . name }
102- className = { ( { isHovered, isDragging, isSelected } ) =>
103- cn (
104- "h-11.25 w-full cursor-pointer border-l-3 border-l-transparent" ,
105- "flex items-center gap-4 px-4" ,
106- "focus-visible:outline-klerosUIComponentsPrimaryBlue focus-visible:outline" ,
107- ( isHovered || isSelected ) && "bg-klerosUIComponentsMediumBlue" ,
108- isSelected && "border-l-klerosUIComponentsPrimaryBlue" ,
109- isDragging && "cursor-grabbing opacity-60" ,
110- )
111- }
112- >
113- { ( { isHovered } ) => (
114- < >
115- { dragDisabled ? null : (
116- < DragAndDropIcon className = "size-4 cursor-grab" />
117- ) }
118- < span className = "text-klerosUIComponentsPrimaryText flex-1 text-base" >
119- { item . name }
120- </ span >
121- { isHovered && ! deletionDisabled ? (
122- < Button
123- className = { "cursor-pointer hover:scale-105" }
124- onPress = { ( ) => {
125- list . remove ( item . id ) ;
126- } }
127- >
128- { ( { isHovered : isButtonHovered } ) => (
129- < Trash
130- className = { clsx (
131- "ease-ease size-4 transition" ,
132- isButtonHovered &&
133- "[&_path]:fill-klerosUIComponentsPrimaryBlue" ,
134- ) }
135- />
136- ) }
137- </ Button >
138- ) : null }
139- </ >
140- ) }
141- </ ListBoxItem >
142- ) }
96+ { list . map ( ( item ) => {
97+ return (
98+ < ListBoxItem
99+ id = { item . id }
100+ key = { item . id }
101+ textValue = { item . name }
102+ className = { ( { isHovered, isDragging, isSelected } ) =>
103+ cn (
104+ "h-11.25 w-full cursor-pointer border-l-3 border-l-transparent" ,
105+ "flex items-center gap-4 px-4" ,
106+ "focus-visible:outline-klerosUIComponentsPrimaryBlue focus-visible:outline" ,
107+ ( isHovered || isSelected ) && "bg-klerosUIComponentsMediumBlue" ,
108+ isSelected && "border-l-klerosUIComponentsPrimaryBlue" ,
109+ isDragging && "cursor-grabbing opacity-60" ,
110+ )
111+ }
112+ >
113+ { ( { isHovered, isSelected } ) => (
114+ < >
115+ { dragDisabled ? null : (
116+ < DragAndDropIcon className = "size-4 cursor-grab" />
117+ ) }
118+ < span className = "text-klerosUIComponentsPrimaryText flex-1 text-base" >
119+ { item . name }
120+ </ span >
121+ { ( isHovered || isSelected ) && ! deletionDisabled ? (
122+ < Button
123+ className = { "cursor-pointer hover:scale-105" }
124+ onPress = { ( ) => {
125+ remove ( item . id ) ;
126+ } }
127+ >
128+ { ( { isHovered : isButtonHovered } ) => (
129+ < Trash
130+ className = { clsx (
131+ "ease-ease size-4 transition" ,
132+ ( isButtonHovered || isSelected ) &&
133+ "[&_path]:fill-klerosUIComponentsPrimaryBlue" ,
134+ ) }
135+ />
136+ ) }
137+ </ Button >
138+ ) : null }
139+ </ >
140+ ) }
141+ </ ListBoxItem >
142+ ) ;
143+ } ) }
143144 </ ListBox >
144145 ) ;
145146}
0 commit comments