Skip to content

Commit 4237b0a

Browse files
authored
[chore] migrate custom-palette from react-sortable-hoc to dnd-kit (#3128)
* [chore] migrade custom-palette from react-sortable-hoc to dnd-kit Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com> * nit Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com> * nit Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com> * nit Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com> * fix for numeric indexes > string indexes Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com> --------- Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
1 parent 49fbf8f commit 4237b0a

1 file changed

Lines changed: 141 additions & 91 deletions

File tree

src/components/src/side-panel/layer-panel/custom-palette.tsx

Lines changed: 141 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ import React, {
1313
} from 'react';
1414
import uniq from 'lodash/uniq';
1515
import {
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';
2226
import styled, {css} from 'styled-components';
2327
import Portaled from '../../common/portaled';
2428
import {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

251291
export 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

Comments
 (0)