From 652f7d6e073db400bf0c905ae3beccb6f1a352df Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Tue, 10 May 2022 22:14:31 -0700 Subject: [PATCH] SortableList: switch to clauderic/dnd-kit --- .../components/general/SortableList.tsx | 95 ++--- .../components/general/SortableListItem.tsx | 112 ++---- .../settings-modal/lists/MountPointsList.tsx | 26 +- .../lists/TorrentListColumnsList.tsx | 30 +- package-lock.json | 377 ++++++------------ package.json | 8 +- 6 files changed, 223 insertions(+), 425 deletions(-) diff --git a/client/src/javascript/components/general/SortableList.tsx b/client/src/javascript/components/general/SortableList.tsx index e6300723..d06ef4ff 100644 --- a/client/src/javascript/components/general/SortableList.tsx +++ b/client/src/javascript/components/general/SortableList.tsx @@ -1,42 +1,38 @@ +import {arrayMove, SortableContext, verticalListSortingStrategy} from '@dnd-kit/sortable'; import classnames from 'classnames'; -import {HTML5toTouch} from 'rdndmb-html5-to-touch'; -import {DndProvider} from 'react-dnd-multi-backend'; +import {DndContext, KeyboardSensor, MouseSensor, TouchSensor, useSensor} from '@dnd-kit/core'; import {FC, MouseEvent, ReactNode, useState} from 'react'; +import {restrictToParentElement, restrictToVerticalAxis} from '@dnd-kit/modifiers'; import SortableListItem from './SortableListItem'; -export type ListItem = { - id: string; - visible: boolean; -}; - interface SortableListProps { - id: string; className: string; lockedIDs: Array; - items: Array; - renderItem: (item: ListItem, index: number) => ReactNode; + items: string[]; + renderItem: (id: string, index: number) => ReactNode; onMouseDown?: (event: MouseEvent) => void; - onMove?: (items: this['items']) => void; onDrop?: (items: this['items']) => void; } const SortableList: FC = ({ className, - id: listID, items, lockedIDs, renderItem, onMouseDown, - onMove, onDrop, }: SortableListProps) => { const [currentItems, setCurrentItems] = useState(items); const classes = classnames('sortable-list', className); + const keyboardSensor = useSensor(KeyboardSensor); + const mouseSensor = useSensor(MouseSensor, {activationConstraint: {distance: 10}}); + const touchSensor = useSensor(TouchSensor, {activationConstraint: {distance: 10}}); + return (
{ if (onMouseDown) { @@ -44,53 +40,50 @@ const SortableList: FC = ({ } }} > - -
    - {currentItems.map((item, index) => { - const {id, visible} = item; - return ( - { - if (onDrop) { - onDrop(currentItems); - } - }} - onMove={(dragIndex, hoverIndex) => { - const draggedItem = currentItems[dragIndex]; + { + if (over == null) { + return; + } - const newItems = currentItems.slice(); + if (active.id === over.id) { + return; + } - // Remove the item being dragged. - newItems.splice(dragIndex, 1); - // Add the item being dragged in its new position. - newItems.splice(hoverIndex, 0, draggedItem); + const newItems = arrayMove( + items, + items.findIndex((id) => id === active.id), + items.findIndex((id) => id === over.id), + ); - setCurrentItems(newItems); + setCurrentItems(newItems); - if (onMove) { - onMove(newItems); - } - }} - > - {renderItem(item, index)} - - ); - })} -
-
+ if (onDrop) { + onDrop(newItems); + } + }} + modifiers={[restrictToVerticalAxis, restrictToParentElement]} + autoScroll={false} + > + +
    + {currentItems.map((id, index) => { + return ( + + {renderItem(id, index)} + + ); + })} +
+
+
); }; SortableList.defaultProps = { onMouseDown: undefined, - onMove: undefined, onDrop: undefined, }; diff --git a/client/src/javascript/components/general/SortableListItem.tsx b/client/src/javascript/components/general/SortableListItem.tsx index 71adf629..8d8af70b 100644 --- a/client/src/javascript/components/general/SortableListItem.tsx +++ b/client/src/javascript/components/general/SortableListItem.tsx @@ -1,102 +1,40 @@ import classnames from 'classnames'; -import {DragElementWrapper, DragPreviewOptions, DragSource, DragSourceOptions, DropTarget} from 'react-dnd'; -import {FC, ReactNode, useEffect} from 'react'; -import flow from 'lodash/flow'; -import {getEmptyImage} from 'react-dnd-html5-backend'; +import {CSS} from '@dnd-kit/utilities'; +import {FC, ReactNode} from 'react'; +import {useSortable} from '@dnd-kit/sortable'; import {Lock} from '@client/ui/icons'; interface SortableListItemProps { children?: ReactNode; - list: string; id: string; - index: number; - isVisible: boolean; - isDragging?: boolean; - isLocked?: boolean; - onDrop: () => void; - onMove: (sourceIndex: number, targetIndex: number) => void; - connectDragPreview: DragElementWrapper; - connectDragSource: DragElementWrapper; - connectDropTarget: DragElementWrapper; + disabled?: boolean; } const SortableListItem: FC = (props: SortableListItemProps) => { - const {children, isDragging, isLocked, connectDragPreview, connectDragSource, connectDropTarget} = props; + const {children, id, disabled} = props; + const {attributes, setNodeRef, listeners, transform, transition, isDragging} = useSortable({id, disabled}); - useEffect(() => { - connectDragPreview(getEmptyImage(), { - captureDraggingState: true, - }); - }); + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; - return connectDragSource( - connectDropTarget( -
- {isLocked ? : null} - {children} -
, - ), + return ( +
+ {disabled ? : null} + {children} +
); }; -export default flow([ - DragSource( - 'globally-draggable-item', - { - beginDrag({list, id, index, isVisible}: SortableListItemProps) { - return {list, id, index, isVisible}; - }, - - canDrag({isLocked}: SortableListItemProps) { - if (isLocked) { - return false; - } - - return true; - }, - }, - (connect, monitor) => ({ - connectDragPreview: connect.dragPreview(), - connectDragSource: connect.dragSource(), - isDragging: monitor.isDragging(), - }), - ), - DropTarget( - 'globally-draggable-item', - { - drop({onDrop}: SortableListItemProps) { - if (onDrop) { - onDrop(); - } - }, - - hover(props, monitor) { - const item: SortableListItemProps = monitor.getItem(); - - // Don't replace items with themselves - if (props.isLocked || item.index === props.index) { - return; - } - - // Don't drop item to another list - if (item.list !== props.list) { - return; - } - - props.onMove(item.index, props.index); - item.index = props.index; - }, - }, - (connect) => ({ - connectDropTarget: connect.dropTarget(), - }), - ), -])(SortableListItem) as FC< - Omit ->; +export default SortableListItem; diff --git a/client/src/javascript/components/modals/settings-modal/lists/MountPointsList.tsx b/client/src/javascript/components/modals/settings-modal/lists/MountPointsList.tsx index 6ec2b464..a81041c8 100644 --- a/client/src/javascript/components/modals/settings-modal/lists/MountPointsList.tsx +++ b/client/src/javascript/components/modals/settings-modal/lists/MountPointsList.tsx @@ -4,7 +4,7 @@ import {Trans} from '@lingui/react'; import {Checkbox} from '@client/ui'; import DiskUsageStore from '@client/stores/DiskUsageStore'; import SettingStore from '@client/stores/SettingStore'; -import SortableList, {ListItem} from '@client/components/general/SortableList'; +import SortableList from '@client/components/general/SortableList'; import type {FloodSettings} from '@shared/types/FloodSettings'; @@ -13,8 +13,8 @@ interface MountPointsListProps { } const MountPointsList: FC = ({onSettingsChange}: MountPointsListProps) => { - const [diskItems, setDiskItems] = useState( - ((): ListItem[] => { + const [diskItems, setDiskItems] = useState( + (() => { const {mountPoints} = SettingStore.floodSettings; const disks = Object.assign( {}, @@ -40,24 +40,28 @@ const MountPointsList: FC = ({onSettingsChange}: MountPoin })(), ); + const diskItemVisiblity = diskItems.reduce((memo, {id, visible}) => { + memo[id] = visible; + return memo; + }, {} as Record); + return ( id)} lockedIDs={[]} - onDrop={(items: Array): void => { - setDiskItems(items); + onDrop={(items) => { + setDiskItems(items.map((id) => ({id, visible: diskItemVisiblity[id]}))); }} - renderItem={(item: ListItem) => { - const {id, visible} = item; - + renderItem={(id) => { const checkbox = ( { + diskItemVisiblity[id] = (event.target as HTMLInputElement).checked; + const newItems = diskItems.map((disk) => { if (disk.id === id) { return {...disk, visible: (event.target as HTMLInputElement).checked}; diff --git a/client/src/javascript/components/modals/settings-modal/lists/TorrentListColumnsList.tsx b/client/src/javascript/components/modals/settings-modal/lists/TorrentListColumnsList.tsx index c633c578..270b7273 100644 --- a/client/src/javascript/components/modals/settings-modal/lists/TorrentListColumnsList.tsx +++ b/client/src/javascript/components/modals/settings-modal/lists/TorrentListColumnsList.tsx @@ -1,4 +1,4 @@ -import {FC, ReactNode, useRef, useState} from 'react'; +import {FC, useRef, useState} from 'react'; import {Trans} from '@lingui/react'; import {Checkbox} from '@client/ui'; @@ -7,12 +7,11 @@ import SettingStore from '@client/stores/SettingStore'; import TorrentListColumns from '@client/constants/TorrentListColumns'; import type {FloodSettings} from '@shared/types/FloodSettings'; +import type {TorrentListColumn} from '@client/constants/TorrentListColumns'; import SortableList from '../../../general/SortableList'; import Tooltip from '../../../general/Tooltip'; -import type {ListItem} from '../../../general/SortableList'; - interface TorrentListColumnsListProps { torrentListViewSize: FloodSettings['torrentListViewSize']; onSettingsChange: (changedSettings: Partial) => void; @@ -23,6 +22,7 @@ const TorrentListColumnsList: FC = ({ onSettingsChange, }: TorrentListColumnsListProps) => { const tooltipRef = useRef(null); + const [torrentListColumns, setTorrentListColumns] = useState([ ...SettingStore.floodSettings.torrentListColumns.filter((column) => TorrentListColumns[column.id] != null).slice(), ...Object.keys(TorrentListColumns) @@ -33,25 +33,28 @@ const TorrentListColumnsList: FC = ({ })), ]); + const torrentListColumnVisiblity = torrentListColumns.reduce((memo, {id, visible}) => { + memo[id] = visible; + return memo; + }, {} as Record); + const lockedIDs = torrentListViewSize === 'expanded' ? ['name', 'eta', 'downRate', 'percentComplete', 'downTotal', 'upRate'] : []; return ( id)} lockedIDs={lockedIDs} onMouseDown={(): void => { tooltipRef.current?.dismissTooltip(); }} - onDrop={(items: Array): void => { - const newItems = items.slice(); + onDrop={(items) => { + const newItems = items.map((id) => ({id, visible: torrentListColumnVisiblity[id]})); onSettingsChange({torrentListColumns: newItems as FloodSettings['torrentListColumns']}); setTorrentListColumns(newItems); }} - renderItem={(item: ListItem, index: number): ReactNode => { - const {id, visible} = item as FloodSettings['torrentListColumns'][number]; + renderItem={(id, index) => { let checkbox = null; let warning = null; @@ -59,17 +62,20 @@ const TorrentListColumnsList: FC = ({ checkbox = ( { + torrentListColumnVisiblity[id] = (event.target as HTMLInputElement).checked; + const changedTorrentListColumns = torrentListColumns.map((column) => ({ id: column.id, visible: column.id === id ? (event.target as HTMLInputElement).checked : column.visible, })); + + setTorrentListColumns(changedTorrentListColumns); onSettingsChange({ torrentListColumns: changedTorrentListColumns as FloodSettings['torrentListColumns'], }); - setTorrentListColumns(changedTorrentListColumns); }} > @@ -100,7 +106,7 @@ const TorrentListColumnsList: FC = ({
{warning} - + {checkbox}
diff --git a/package-lock.json b/package-lock.json index f6b258b1..4f7ebed6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,9 @@ "@babel/preset-env": "^7.17.10", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.16.7", + "@dnd-kit/core": "^5.0.3", + "@dnd-kit/modifiers": "^5.0.0", + "@dnd-kit/sortable": "^6.0.1", "@emotion/babel-plugin": "^11.9.2", "@emotion/css": "^11.9.0", "@emotion/react": "^11.9.0", @@ -125,13 +128,8 @@ "postcss-loader": "^6.2.1", "prettier": "^2.6.2", "promise": "^8.1.0", - "rdndmb-html5-to-touch": "^7.0.0-alpha.4", "react": "^17.0.2", "react-dev-utils": "^12.0.1", - "react-dnd": "^13.1.1", - "react-dnd-html5-backend": "^12.1.1", - "react-dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-touch-backend": "^12.0.0", "react-dom": "^17.0.2", "react-dropzone": "^14.2.1", "react-measure": "^2.5.2", @@ -2094,6 +2092,72 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz", + "integrity": "sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-5.0.3.tgz", + "integrity": "sha512-IribcBLsaPqHdYLpc5xG0TqwYIaD+65offdEYxoKh38WDjzRxUjDmrt7hj9oa/ooUKL0epux20u+mBTd92i/zw==", + "dev": true, + "dependencies": { + "@dnd-kit/accessibility": "^3.0.0", + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-5.0.0.tgz", + "integrity": "sha512-ZVOfa5dKmvAPBxjjnI4QTm8fHV4/gMdS6k0zY5Z8p/p9HkL/3QEHn2fYgqM2zVDpxf5maqrZ4MvqXILSPNQPMQ==", + "dev": true, + "dependencies": { + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^5.0.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-6.0.1.tgz", + "integrity": "sha512-FGpRHBcflpwWpSP8bMJ4zNcDywDXssZDJBwGYuHd1RqUU/+JX43pEU0u0OHw06LabEZMOLBbyWoIaZJ0abCOEA==", + "dev": true, + "dependencies": { + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^5.0.2", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.1.0.tgz", + "integrity": "sha512-2JBdIgjJ7xjMRpKagdMuYKWJdDoVVw9Wc6lfMrLjrq8t4QlMEjtsab5JVUlzWvHgANn7w3Y3VhalFfbp4dQrKg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.9.2", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz", @@ -3129,24 +3193,6 @@ "node": ">= 8" } }, - "node_modules/@react-dnd/asap": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", - "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==", - "dev": true - }, - "node_modules/@react-dnd/invariant": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz", - "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==", - "dev": true - }, - "node_modules/@react-dnd/shallowequal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", - "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", - "dev": true - }, "node_modules/@rushstack/eslint-patch": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", @@ -6796,23 +6842,6 @@ "node": ">=8" } }, - "node_modules/dnd-core": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-12.0.1.tgz", - "integrity": "sha512-KzfKXQM9t9uSBO7DFmrILVgXUCShpY3/MbnLPF9/wg1Wcvq2KblbeT72GhjcrplS9cz0DFXilE1NXy43n8plag==", - "dev": true, - "dependencies": { - "@react-dnd/asap": "^4.0.0", - "@react-dnd/invariant": "^2.0.0", - "redux": "^4.0.5" - } - }, - "node_modules/dnd-multi-backend": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/dnd-multi-backend/-/dnd-multi-backend-7.0.0-alpha.4.tgz", - "integrity": "sha512-815RKk7d8Lg08DpINCe7uv7q0ia7rBT+vCTkQnNSsAVQWaPpbwTRyMKNDiLwqh25vu7d5M8jZUnICrs1StiLjg==", - "dev": true - }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -13965,17 +13994,6 @@ "node": ">= 0.8" } }, - "node_modules/rdndmb-html5-to-touch": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/rdndmb-html5-to-touch/-/rdndmb-html5-to-touch-7.0.0-alpha.4.tgz", - "integrity": "sha512-7HJs+84TJ+KftJJ+hmn1yrQqn7pE9ntEIkAbOBqN48BrxgYzyHXLk4EJ9/vbss7ka0gFf2MgRCviAgiQ02FwFw==", - "dev": true, - "dependencies": { - "dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-html5-backend": "^12.1.1", - "react-dnd-touch-backend": "^12.0.0" - } - }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -14033,89 +14051,6 @@ "node": ">= 12.13.0" } }, - "node_modules/react-dnd": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-13.1.1.tgz", - "integrity": "sha512-oxQW8846omV1l3Pm2zY/atvNxryx+blW1rxnSmoGvFMgmxXpOHulaXrlXgxRH+OLRvLt2cfVTSxZ4ykbzBypaw==", - "dev": true, - "dependencies": { - "@react-dnd/invariant": "^2.0.0", - "@react-dnd/shallowequal": "^2.0.0", - "dnd-core": "12.0.1", - "hoist-non-react-statics": "^3.3.2" - }, - "peerDependencies": { - "@types/hoist-non-react-statics": ">= 3.3.1", - "@types/node": ">= 12", - "@types/react": ">= 16", - "react": ">= 16.14" - }, - "peerDependenciesMeta": { - "@types/hoist-non-react-statics": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-dnd-html5-backend": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-12.1.1.tgz", - "integrity": "sha512-cQZgfuSGQEwHdvdoPtfUOvcrS8rye/V0hU046LjY/BLSgcrdjtQVviE2d/81QQaeJpvK00JizctsZqVY7IvHgA==", - "dev": true, - "dependencies": { - "dnd-core": "12.0.1" - } - }, - "node_modules/react-dnd-multi-backend": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/react-dnd-multi-backend/-/react-dnd-multi-backend-7.0.0-alpha.4.tgz", - "integrity": "sha512-5N+3tWoOeqsuDAUwA/Y0BfQVtJ/lVVf4+UIr93rL2sBO0znjdFVcIkESxWDj38ciYkBiJdUoqbLTYL2NZDTlIA==", - "dev": true, - "dependencies": { - "dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-preview": "^7.0.0-alpha.3" - }, - "peerDependencies": { - "react": "^16.14.0 || ^17.0.2", - "react-dom": "^16.14.0 || ^17.0.2" - } - }, - "node_modules/react-dnd-preview": { - "version": "7.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/react-dnd-preview/-/react-dnd-preview-7.0.0-alpha.3.tgz", - "integrity": "sha512-Fc3IYWAxLYWej/1ZCTj5fAkd1d6k+LcUyJJGQm9kAlJSD2INBIS8yOGr6h6r1BIJyX3zMPrco3rt4t5ajDTKBw==", - "dev": true, - "peerDependencies": { - "react": "^16.14.0 || ^17.0.2", - "react-dnd": "^13.1.1" - } - }, - "node_modules/react-dnd-touch-backend": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-12.0.0.tgz", - "integrity": "sha512-YcXb0S6/87KIGGJQEGvc+dhgVIoPikM23VJs10y9AKrezao9bIXiMtd5+Sg4dDAcUduptvvbohCTpkm0E6mrtg==", - "dev": true, - "dependencies": { - "@react-dnd/invariant": "^2.0.0", - "dnd-core": "12.0.0" - } - }, - "node_modules/react-dnd-touch-backend/node_modules/dnd-core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-12.0.0.tgz", - "integrity": "sha512-7GQTkQfNmmdFBN85hN0aHKXeP6Vf4yFUZQBT02+yHKbR82C80N504onI4Av5ZKm2goY1ppQr3wdDp5pa5tlaYA==", - "dev": true, - "dependencies": { - "@react-dnd/asap": "^4.0.0", - "@react-dnd/invariant": "^2.0.0", - "redux": "^4.0.5" - } - }, "node_modules/react-dom": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", @@ -14329,15 +14264,6 @@ "node": "*" } }, - "node_modules/redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -18454,6 +18380,55 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@dnd-kit/accessibility": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz", + "integrity": "sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "@dnd-kit/core": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-5.0.3.tgz", + "integrity": "sha512-IribcBLsaPqHdYLpc5xG0TqwYIaD+65offdEYxoKh38WDjzRxUjDmrt7hj9oa/ooUKL0epux20u+mBTd92i/zw==", + "dev": true, + "requires": { + "@dnd-kit/accessibility": "^3.0.0", + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/modifiers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-5.0.0.tgz", + "integrity": "sha512-ZVOfa5dKmvAPBxjjnI4QTm8fHV4/gMdS6k0zY5Z8p/p9HkL/3QEHn2fYgqM2zVDpxf5maqrZ4MvqXILSPNQPMQ==", + "dev": true, + "requires": { + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/sortable": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-6.0.1.tgz", + "integrity": "sha512-FGpRHBcflpwWpSP8bMJ4zNcDywDXssZDJBwGYuHd1RqUU/+JX43pEU0u0OHw06LabEZMOLBbyWoIaZJ0abCOEA==", + "dev": true, + "requires": { + "@dnd-kit/utilities": "^3.1.0", + "tslib": "^2.0.0" + } + }, + "@dnd-kit/utilities": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.1.0.tgz", + "integrity": "sha512-2JBdIgjJ7xjMRpKagdMuYKWJdDoVVw9Wc6lfMrLjrq8t4QlMEjtsab5JVUlzWvHgANn7w3Y3VhalFfbp4dQrKg==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, "@emotion/babel-plugin": { "version": "11.9.2", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz", @@ -19245,24 +19220,6 @@ } } }, - "@react-dnd/asap": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", - "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==", - "dev": true - }, - "@react-dnd/invariant": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz", - "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==", - "dev": true - }, - "@react-dnd/shallowequal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", - "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", - "dev": true - }, "@rushstack/eslint-patch": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", @@ -22202,23 +22159,6 @@ "path-type": "^4.0.0" } }, - "dnd-core": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-12.0.1.tgz", - "integrity": "sha512-KzfKXQM9t9uSBO7DFmrILVgXUCShpY3/MbnLPF9/wg1Wcvq2KblbeT72GhjcrplS9cz0DFXilE1NXy43n8plag==", - "dev": true, - "requires": { - "@react-dnd/asap": "^4.0.0", - "@react-dnd/invariant": "^2.0.0", - "redux": "^4.0.5" - } - }, - "dnd-multi-backend": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/dnd-multi-backend/-/dnd-multi-backend-7.0.0-alpha.4.tgz", - "integrity": "sha512-815RKk7d8Lg08DpINCe7uv7q0ia7rBT+vCTkQnNSsAVQWaPpbwTRyMKNDiLwqh25vu7d5M8jZUnICrs1StiLjg==", - "dev": true - }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -27500,17 +27440,6 @@ "unpipe": "1.0.0" } }, - "rdndmb-html5-to-touch": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/rdndmb-html5-to-touch/-/rdndmb-html5-to-touch-7.0.0-alpha.4.tgz", - "integrity": "sha512-7HJs+84TJ+KftJJ+hmn1yrQqn7pE9ntEIkAbOBqN48BrxgYzyHXLk4EJ9/vbss7ka0gFf2MgRCviAgiQ02FwFw==", - "dev": true, - "requires": { - "dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-html5-backend": "^12.1.1", - "react-dnd-touch-backend": "^12.0.0" - } - }, "react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -27561,67 +27490,6 @@ } } }, - "react-dnd": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-13.1.1.tgz", - "integrity": "sha512-oxQW8846omV1l3Pm2zY/atvNxryx+blW1rxnSmoGvFMgmxXpOHulaXrlXgxRH+OLRvLt2cfVTSxZ4ykbzBypaw==", - "dev": true, - "requires": { - "@react-dnd/invariant": "^2.0.0", - "@react-dnd/shallowequal": "^2.0.0", - "dnd-core": "12.0.1", - "hoist-non-react-statics": "^3.3.2" - } - }, - "react-dnd-html5-backend": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-12.1.1.tgz", - "integrity": "sha512-cQZgfuSGQEwHdvdoPtfUOvcrS8rye/V0hU046LjY/BLSgcrdjtQVviE2d/81QQaeJpvK00JizctsZqVY7IvHgA==", - "dev": true, - "requires": { - "dnd-core": "12.0.1" - } - }, - "react-dnd-multi-backend": { - "version": "7.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/react-dnd-multi-backend/-/react-dnd-multi-backend-7.0.0-alpha.4.tgz", - "integrity": "sha512-5N+3tWoOeqsuDAUwA/Y0BfQVtJ/lVVf4+UIr93rL2sBO0znjdFVcIkESxWDj38ciYkBiJdUoqbLTYL2NZDTlIA==", - "dev": true, - "requires": { - "dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-preview": "^7.0.0-alpha.3" - } - }, - "react-dnd-preview": { - "version": "7.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/react-dnd-preview/-/react-dnd-preview-7.0.0-alpha.3.tgz", - "integrity": "sha512-Fc3IYWAxLYWej/1ZCTj5fAkd1d6k+LcUyJJGQm9kAlJSD2INBIS8yOGr6h6r1BIJyX3zMPrco3rt4t5ajDTKBw==", - "dev": true, - "requires": {} - }, - "react-dnd-touch-backend": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-12.0.0.tgz", - "integrity": "sha512-YcXb0S6/87KIGGJQEGvc+dhgVIoPikM23VJs10y9AKrezao9bIXiMtd5+Sg4dDAcUduptvvbohCTpkm0E6mrtg==", - "dev": true, - "requires": { - "@react-dnd/invariant": "^2.0.0", - "dnd-core": "12.0.0" - }, - "dependencies": { - "dnd-core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-12.0.0.tgz", - "integrity": "sha512-7GQTkQfNmmdFBN85hN0aHKXeP6Vf4yFUZQBT02+yHKbR82C80N504onI4Av5ZKm2goY1ppQr3wdDp5pa5tlaYA==", - "dev": true, - "requires": { - "@react-dnd/asap": "^4.0.0", - "@react-dnd/invariant": "^2.0.0", - "redux": "^4.0.5" - } - } - } - }, "react-dom": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", @@ -27784,15 +27652,6 @@ } } }, - "redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.9.2" - } - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", diff --git a/package.json b/package.json index 6c9da4d2..a64b8da0 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,9 @@ "@babel/preset-env": "^7.17.10", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.16.7", + "@dnd-kit/core": "^5.0.3", + "@dnd-kit/modifiers": "^5.0.0", + "@dnd-kit/sortable": "^6.0.1", "@emotion/babel-plugin": "^11.9.2", "@emotion/css": "^11.9.0", "@emotion/react": "^11.9.0", @@ -174,13 +177,8 @@ "postcss-loader": "^6.2.1", "prettier": "^2.6.2", "promise": "^8.1.0", - "rdndmb-html5-to-touch": "^7.0.0-alpha.4", "react": "^17.0.2", "react-dev-utils": "^12.0.1", - "react-dnd": "^13.1.1", - "react-dnd-html5-backend": "^12.1.1", - "react-dnd-multi-backend": "^7.0.0-alpha.4", - "react-dnd-touch-backend": "^12.0.0", "react-dom": "^17.0.2", "react-dropzone": "^14.2.1", "react-measure": "^2.5.2",