@@ -13,12 +13,16 @@ import React, {
1313} from 'react' ;
1414import uniq from 'lodash/uniq' ;
1515import {
16- SortableContainer ,
17- SortableContainerProps ,
18- SortableElement ,
19- SortableElementProps ,
20- SortableHandle
21- } from 'react-sortable-hoc' ;
16+ DndContext ,
17+ closestCenter ,
18+ KeyboardSensor ,
19+ PointerSensor ,
20+ useSensor ,
21+ useSensors ,
22+ DragEndEvent
23+ } from '@dnd-kit/core' ;
24+ import { SortableContext , useSortable , verticalListSortingStrategy } from '@dnd-kit/sortable' ;
25+ import { CSS } from '@dnd-kit/utilities' ;
2226import styled , { css } from 'styled-components' ;
2327import Portaled from '../../common/portaled' ;
2428import { Tooltip } from '../../common/styled-components' ;
@@ -220,33 +224,69 @@ const InputText = styled.div.withConfig({shouldForwardProp})<{width: string; tex
220224 }
221225` ;
222226
223- type SortableItemProps = SortableElementProps & {
224- children ?: React . ReactNode ;
227+ type SortableItemProps = {
228+ id : string ;
229+ children : ( listeners : any ) => React . ReactNode ;
225230 className ?: string ;
226231 isSorting : boolean ;
227232} ;
228233
229- const SortableItem = SortableElement < SortableItemProps > ( ( { children, isSorting} ) => (
230- < ColorPaletteItem className = { classnames ( 'custom-palette__sortable-items' , { sorting : isSorting } ) } >
231- { children }
232- </ ColorPaletteItem >
233- ) ) ;
234+ const SortableItem = ( { id, children, isSorting} : SortableItemProps ) => {
235+ const { attributes, listeners, setNodeRef, transform, transition, isDragging} = useSortable ( { id} ) ;
236+ const style = {
237+ transform : CSS . Transform . toString ( transform ) ,
238+ transition,
239+ zIndex : isDragging ? 1 : 0
240+ } ;
241+ return (
242+ < ColorPaletteItem
243+ ref = { setNodeRef }
244+ style = { style }
245+ className = { classnames ( 'custom-palette__sortable-items' , { sorting : isSorting || isDragging } ) }
246+ { ...attributes }
247+ >
248+ { children ( listeners ) }
249+ </ ColorPaletteItem >
250+ ) ;
251+ } ;
234252
235- type WrappedSortableContainerProps = SortableContainerProps & {
253+ type WrappedSortableContainerProps = {
236254 children ?: React . ReactNode ;
237255 className ?: string ;
256+ onSortEnd : ( event : DragEndEvent ) => void ;
257+ onSortStart : ( ) => void ;
238258} ;
239259
240- // TODO: Should className be applied to the div here?
241- const WrappedSortableContainer = SortableContainer < WrappedSortableContainerProps > (
242- ( { children, className} ) => < div className = { className } > { children } </ div >
243- ) ;
244-
245- type DragHandleProps = PropsWithChildren < { className ?: string ; listeners ?: unknown } > ;
260+ const WrappedSortableContainer = ( {
261+ children,
262+ className,
263+ onSortEnd,
264+ onSortStart
265+ } : WrappedSortableContainerProps ) => {
266+ const sensors = useSensors ( useSensor ( PointerSensor ) , useSensor ( KeyboardSensor ) ) ;
267+ return (
268+ < DndContext
269+ sensors = { sensors }
270+ collisionDetection = { closestCenter }
271+ onDragEnd = { onSortEnd }
272+ onDragStart = { onSortStart }
273+ >
274+ < SortableContext
275+ items = { React . Children . map ( children , ( _ , index ) => `${ index } ` ) || [ ] }
276+ strategy = { verticalListSortingStrategy }
277+ >
278+ < div className = { className } > { children } </ div >
279+ </ SortableContext >
280+ </ DndContext >
281+ ) ;
282+ } ;
246283
247- export const DragHandle = SortableHandle < DragHandleProps > ( ( { className, children} ) => (
248- < StyledDragHandle className = { className } > { children } </ StyledDragHandle >
249- ) ) ;
284+ type DragHandleProps = PropsWithChildren < { className ?: string } > ;
285+ const DragHandle = ( { className, children, ...listeners } : DragHandleProps ) => (
286+ < StyledDragHandle className = { className } { ...listeners } >
287+ { children }
288+ </ StyledDragHandle >
289+ ) ;
250290
251291export type ColorPaletteInputProps = {
252292 value : string | number ;
@@ -408,42 +448,46 @@ export const CustomPaletteInput: React.FC<CustomPaletteInputProps> = ({
408448 const showHexInput = ! colorBreaks ;
409449
410450 return (
411- < SortableItem index = { index } isSorting = { isSorting } >
412- < div className = "custom-palette-input__left" >
413- < DragHandle className = "layer__drag-handle" >
414- < actionIcons . sort height = "20px" />
415- </ DragHandle >
416- < ColorSwatch color = { color } onClick = { onClickSwtach } />
417- { showHexInput ? (
418- < StyledColorHexInput >
419- < ColorPaletteInput
420- value = { color . toUpperCase ( ) }
421- onChange = { onColorInput }
422- id = { `input-layer-label-${ index } ` }
423- editable
424- textAlign = "left"
425- width = "70px"
426- />
427- </ StyledColorHexInput >
428- ) : null }
429- { isNumericColorBreaks ( colorBreaks ) ? (
430- < EditableColorRange
431- item = { colorBreaks [ index ] }
432- isLast = { index === colorBreaks . length - 1 }
433- index = { index }
434- editColorMap = { editColorMapValue }
435- editable
436- />
437- ) : null }
438- </ div >
439- < div className = "custom-palette-input__right" >
440- { ! disableAppend ? (
441- < AddColorStop onColorAdd = { onColorAdd } IconComponent = { actionIcons . add } />
442- ) : null }
443- { ! disableDelete ? (
444- < DeleteColorStop onColorDelete = { onColorDelete } IconComponent = { actionIcons . delete } />
445- ) : null }
446- </ div >
451+ < SortableItem id = { `${ index } ` } isSorting = { isSorting } >
452+ { listeners => (
453+ < >
454+ < div className = "custom-palette-input__left" >
455+ < DragHandle className = "layer__drag-handle" { ...listeners } >
456+ < actionIcons . sort height = "20px" />
457+ </ DragHandle >
458+ < ColorSwatch color = { color } onClick = { onClickSwtach } />
459+ { showHexInput ? (
460+ < StyledColorHexInput >
461+ < ColorPaletteInput
462+ value = { color . toUpperCase ( ) }
463+ onChange = { onColorInput }
464+ id = { `input-layer-label-${ index } ` }
465+ editable
466+ textAlign = "left"
467+ width = "70px"
468+ />
469+ </ StyledColorHexInput >
470+ ) : null }
471+ { isNumericColorBreaks ( colorBreaks ) ? (
472+ < EditableColorRange
473+ item = { colorBreaks [ index ] }
474+ isLast = { index === colorBreaks . length - 1 }
475+ index = { index }
476+ editColorMap = { editColorMapValue }
477+ editable
478+ />
479+ ) : null }
480+ </ div >
481+ < div className = "custom-palette-input__right" >
482+ { ! disableAppend ? (
483+ < AddColorStop onColorAdd = { onColorAdd } IconComponent = { actionIcons . add } />
484+ ) : null }
485+ { ! disableDelete ? (
486+ < DeleteColorStop onColorDelete = { onColorDelete } IconComponent = { actionIcons . delete } />
487+ ) : null }
488+ </ div >
489+ </ >
490+ ) }
447491 </ SortableItem >
448492 ) ;
449493} ;
@@ -735,29 +779,33 @@ export const CategoricalCustomPaletteInput: React.FC<CategoricalCustomPaletteInp
735779 const onColorDelete = useCallback ( ( ) => onDelete ( index ) , [ onDelete , index ] ) ;
736780
737781 return (
738- < SortableItem index = { index } isSorting = { isSorting } >
739- < div className = "custom-palette-input__left" >
740- < DragHandle className = "layer__drag-handle" >
741- < actionIcons . sort height = "20px" />
742- </ DragHandle >
743- < ColorSwatch color = { color } onClick = { onClickSwtach } />
744- { colorMap && colorMap [ index ] && (
745- < CategoricalSelector
746- selectedValues = { selectedValues }
747- allValues = { allValues }
748- addColorMapValue = { addColorMapValue }
749- removeColorMapValue = { removeColorMapValue }
750- resetColorMapValue = { resetColorMapValue }
751- selectRestColorMapValue = { selectRestColorMapValue }
752- index = { index }
753- />
754- ) }
755- </ div >
756- < div className = "custom-palette-input__right" >
757- { ! disableDelete ? (
758- < DeleteColorStop onColorDelete = { onColorDelete } IconComponent = { actionIcons . delete } />
759- ) : null }
760- </ div >
782+ < SortableItem id = { `${ index } ` } isSorting = { isSorting } >
783+ { listeners => (
784+ < >
785+ < div className = "custom-palette-input__left" >
786+ < DragHandle className = "layer__drag-handle" { ...listeners } >
787+ < actionIcons . sort height = "20px" />
788+ </ DragHandle >
789+ < ColorSwatch color = { color } onClick = { onClickSwtach } />
790+ { colorMap && colorMap [ index ] && (
791+ < CategoricalSelector
792+ selectedValues = { selectedValues }
793+ allValues = { allValues }
794+ addColorMapValue = { addColorMapValue }
795+ removeColorMapValue = { removeColorMapValue }
796+ resetColorMapValue = { resetColorMapValue }
797+ selectRestColorMapValue = { selectRestColorMapValue }
798+ index = { index }
799+ />
800+ ) }
801+ </ div >
802+ < div className = "custom-palette-input__right" >
803+ { ! disableDelete ? (
804+ < DeleteColorStop onColorDelete = { onColorDelete } IconComponent = { actionIcons . delete } />
805+ ) : null }
806+ </ div >
807+ </ >
808+ ) }
761809 </ SortableItem >
762810 ) ;
763811} ;
@@ -864,14 +912,19 @@ function CustomPaletteFactory(): React.FC<CustomPaletteProps> {
864912 ) ;
865913
866914 const onSortEnd = useCallback (
867- ( { oldIndex, newIndex} ) => {
868- const newCustomPalette = sortCustomPaletteColor ( customPalette , oldIndex , newIndex ) ;
869- setColorPaletteUI ( {
870- customPalette : newCustomPalette
871- } ) ;
915+ ( event : DragEndEvent ) => {
916+ const { active, over} = event ;
917+ if ( over && active . id !== over . id ) {
918+ const oldIndex = colors . findIndex ( ( _ , index ) => `${ index } ` === active . id ) ;
919+ const newIndex = colors . findIndex ( ( _ , index ) => `${ index } ` === over . id ) ;
920+ const newCustomPalette = sortCustomPaletteColor ( customPalette , oldIndex , newIndex ) ;
921+ setColorPaletteUI ( {
922+ customPalette : newCustomPalette
923+ } ) ;
924+ }
872925 setIsSorting ( false ) ;
873926 } ,
874- [ customPalette , setColorPaletteUI , setIsSorting ]
927+ [ colors , customPalette , setIsSorting , setColorPaletteUI ]
875928 ) ;
876929
877930 const onSortStart = useCallback ( ( ) => {
@@ -986,9 +1039,6 @@ function CustomPaletteFactory(): React.FC<CustomPaletteProps> {
9861039 className = "custom-palette__sortable-container"
9871040 onSortEnd = { onSortEnd }
9881041 onSortStart = { onSortStart }
989- lockAxis = "y"
990- helperClass = "sorting-colors"
991- useDragHandle
9921042 >
9931043 { colors . map ( ( color , index ) =>
9941044 customPalette . type === 'custom' ? (
0 commit comments