mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
added useSortableActions hook
This commit is contained in:
parent
3345939670
commit
586ebb7480
7 changed files with 86 additions and 72 deletions
15
src/components/sortable/DragOverlayItem/index.tsx
Normal file
15
src/components/sortable/DragOverlayItem/index.tsx
Normal file
|
@ -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<DragOverlayItemProps> = ({ className, children }) => (
|
||||||
|
<div className={classNames(styles.overlay, className)}>{children}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export { DragOverlayItem };
|
|
@ -0,0 +1,6 @@
|
||||||
|
@import "src/styles/variables";
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.3) 5px 5px 10px 2px;
|
||||||
|
border-radius: $radius;
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ import { DragEndEvent } from '@dnd-kit/core/dist/types';
|
||||||
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable';
|
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { DragOverlayItem } from '~/components/sortable/DragOverlayItem';
|
||||||
|
import { useSortableActions } from '~/hooks/sortable';
|
||||||
import { moveArrItem } from '~/utils/fn';
|
import { moveArrItem } from '~/utils/fn';
|
||||||
import { DivProps } from '~/utils/types';
|
import { DivProps } from '~/utils/types';
|
||||||
|
|
||||||
|
@ -44,47 +46,10 @@ const SortableGrid = <T, R>({
|
||||||
onSortEnd,
|
onSortEnd,
|
||||||
size,
|
size,
|
||||||
}: SortableGridProps<T, R>) => {
|
}: SortableGridProps<T, R>) => {
|
||||||
const [draggingItem, setDraggingItem] = useState<T | null>(null);
|
const { sensors, onDragEnd, onDragStart, draggingItem, ids } = useSortableActions(
|
||||||
|
items,
|
||||||
const ids = useMemo(() => items.map(getID), [items]);
|
getID,
|
||||||
|
onSortEnd
|
||||||
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 gridStyle = useMemo<DivProps['style']>(
|
const gridStyle = useMemo<DivProps['style']>(
|
||||||
|
@ -122,9 +87,7 @@ const SortableGrid = <T, R>({
|
||||||
|
|
||||||
<DragOverlay>
|
<DragOverlay>
|
||||||
{draggingItem ? (
|
{draggingItem ? (
|
||||||
<div className={styles.overlay}>
|
<DragOverlayItem>{createElement(renderItem, { item: draggingItem })}</DragOverlayItem>
|
||||||
{createElement(renderItem, { item: draggingItem })}
|
|
||||||
</div>
|
|
||||||
) : null}
|
) : null}
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
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 {
|
.dragging {
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
1
src/hooks/sortable/index.ts
Normal file
1
src/hooks/sortable/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './useSortableActions';
|
57
src/hooks/sortable/useSortableActions.ts
Normal file
57
src/hooks/sortable/useSortableActions.ts
Normal file
|
@ -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 = <T>(
|
||||||
|
items: T[],
|
||||||
|
getID: (item: T) => string | number,
|
||||||
|
onSortEnd: (items: T[]) => void
|
||||||
|
) => {
|
||||||
|
const [draggingItem, setDraggingItem] = useState<T | null>(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 };
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue