From 586ebb748092d1593b3faafdad67599db5c43bca Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 24 Jun 2022 17:56:05 +0700 Subject: [PATCH] added useSortableActions hook --- .../sortable/DragOverlayItem/index.tsx | 15 +++++ .../DragOverlayItem/styles.module.scss | 6 ++ .../sortable/SortableGrid/index.tsx | 51 +++-------------- .../sortable/SortableGrid/styles.module.scss | 5 -- .../SortableImageGrid/styles.module.scss | 23 -------- src/hooks/sortable/index.ts | 1 + src/hooks/sortable/useSortableActions.ts | 57 +++++++++++++++++++ 7 files changed, 86 insertions(+), 72 deletions(-) create mode 100644 src/components/sortable/DragOverlayItem/index.tsx create mode 100644 src/components/sortable/DragOverlayItem/styles.module.scss delete mode 100644 src/components/sortable/SortableImageGrid/styles.module.scss create mode 100644 src/hooks/sortable/index.ts create mode 100644 src/hooks/sortable/useSortableActions.ts diff --git a/src/components/sortable/DragOverlayItem/index.tsx b/src/components/sortable/DragOverlayItem/index.tsx new file mode 100644 index 00000000..ef265846 --- /dev/null +++ b/src/components/sortable/DragOverlayItem/index.tsx @@ -0,0 +1,15 @@ +import React, { FC } from 'react'; + +import classNames from 'classnames'; + +import styles from './styles.module.scss'; + +interface DragOverlayItemProps { + className?: string; +} + +const DragOverlayItem: FC = ({ className, children }) => ( +
{children}
+); + +export { DragOverlayItem }; diff --git a/src/components/sortable/DragOverlayItem/styles.module.scss b/src/components/sortable/DragOverlayItem/styles.module.scss new file mode 100644 index 00000000..1f6900e3 --- /dev/null +++ b/src/components/sortable/DragOverlayItem/styles.module.scss @@ -0,0 +1,6 @@ +@import "src/styles/variables"; + +.overlay { + box-shadow: rgba(0, 0, 0, 0.3) 5px 5px 10px 2px; + border-radius: $radius; +} diff --git a/src/components/sortable/SortableGrid/index.tsx b/src/components/sortable/SortableGrid/index.tsx index 26e8277c..86a7e238 100644 --- a/src/components/sortable/SortableGrid/index.tsx +++ b/src/components/sortable/SortableGrid/index.tsx @@ -14,6 +14,8 @@ import { DragEndEvent } from '@dnd-kit/core/dist/types'; import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable'; import classNames from 'classnames'; +import { DragOverlayItem } from '~/components/sortable/DragOverlayItem'; +import { useSortableActions } from '~/hooks/sortable'; import { moveArrItem } from '~/utils/fn'; import { DivProps } from '~/utils/types'; @@ -44,47 +46,10 @@ const SortableGrid = ({ onSortEnd, size, }: SortableGridProps) => { - const [draggingItem, setDraggingItem] = useState(null); - - const ids = useMemo(() => items.map(getID), [items]); - - const onDragEnd = useCallback( - ({ active, over }: DragEndEvent) => { - setDraggingItem(null); - - if (!over?.id || active.id === over.id) { - return; - } - - const oldIndex = items.findIndex(it => getID(it) === active.id); - const newIndex = items.findIndex(it => getID(it) === over.id); - - onSortEnd(moveArrItem(oldIndex, newIndex, items)); - }, - [items] - ); - - const onDragStart = useCallback( - ({ active }: DragStartEvent) => { - if (!active.id) { - return; - } - - const activeItem = items.find(it => getID(it) === active.id); - - setDraggingItem(activeItem ?? null); - }, - [items] - ); - - const sensors = useSensors( - useSensor(TouchSensor, { - activationConstraint: { - delay: 200, - tolerance: 5, - }, - }), - useSensor(MouseSensor) + const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions( + items, + getID, + onSortEnd ); const gridStyle = useMemo( @@ -122,9 +87,7 @@ const SortableGrid = ({ {draggingItem ? ( -
- {createElement(renderItem, { item: draggingItem })} -
+ {createElement(renderItem, { item: draggingItem })} ) : null}
diff --git a/src/components/sortable/SortableGrid/styles.module.scss b/src/components/sortable/SortableGrid/styles.module.scss index 42faef8d..daa26015 100644 --- a/src/components/sortable/SortableGrid/styles.module.scss +++ b/src/components/sortable/SortableGrid/styles.module.scss @@ -9,11 +9,6 @@ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } -.overlay { - box-shadow: rgba(0, 0, 0, 0.3) 5px 5px 10px 2px; - border-radius: $radius; -} - .dragging { opacity: 0.1; } diff --git a/src/components/sortable/SortableImageGrid/styles.module.scss b/src/components/sortable/SortableImageGrid/styles.module.scss deleted file mode 100644 index f3294486..00000000 --- a/src/components/sortable/SortableImageGrid/styles.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "src/styles/variables"; - -.grid { - box-sizing: border-box; - - display: grid; - grid-column-gap: $gap; - grid-row-gap: $gap; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - - @media (max-width: 600px) { - grid-template-columns: repeat(auto-fill, minmax(30vw, 1fr)); - } -} - -.overlay { - box-shadow: rgba(0, 0, 0, 0.3) 5px 5px 10px 2px; - border-radius: $radius; -} - -.dragging { - opacity: 0.1; -} diff --git a/src/hooks/sortable/index.ts b/src/hooks/sortable/index.ts new file mode 100644 index 00000000..b6fe883b --- /dev/null +++ b/src/hooks/sortable/index.ts @@ -0,0 +1 @@ +export * from './useSortableActions'; diff --git a/src/hooks/sortable/useSortableActions.ts b/src/hooks/sortable/useSortableActions.ts new file mode 100644 index 00000000..9aa0abb5 --- /dev/null +++ b/src/hooks/sortable/useSortableActions.ts @@ -0,0 +1,57 @@ +import { useCallback, useMemo, useState } from 'react'; + +import { DragStartEvent, MouseSensor, TouchSensor, useSensor, useSensors } from '@dnd-kit/core'; +import { DragEndEvent } from '@dnd-kit/core/dist/types'; + +import { moveArrItem } from '~/utils/fn'; + +export const useSortableActions = ( + items: T[], + getID: (item: T) => string | number, + onSortEnd: (items: T[]) => void +) => { + const [draggingItem, setDraggingItem] = useState(null); + + const ids = useMemo(() => items.map(getID), [items]); + + const onDragEnd = useCallback( + ({ active, over }: DragEndEvent) => { + setDraggingItem(null); + + if (!over?.id || active.id === over.id) { + return; + } + + const oldIndex = items.findIndex(it => getID(it) === active.id); + const newIndex = items.findIndex(it => getID(it) === over.id); + + onSortEnd(moveArrItem(oldIndex, newIndex, items)); + }, + [items] + ); + + const onDragStart = useCallback( + ({ active }: DragStartEvent) => { + if (!active.id) { + return; + } + + const activeItem = items.find(it => getID(it) === active.id); + + setDraggingItem(activeItem ?? null); + }, + [items] + ); + + const sensors = useSensors( + useSensor(TouchSensor, { + activationConstraint: { + delay: 200, + tolerance: 5, + }, + }), + useSensor(MouseSensor) + ); + + return { sensors, onDragEnd, onDragStart, draggingItem, ids }; +};