@os-design/drag-sort 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +19 -12
- package/src/DragAndDrop.tsx +235 -0
- package/src/Draggable.tsx +109 -0
- package/src/Droppable.tsx +142 -0
- package/src/index.ts +7 -0
- package/src/utils/ListStore.ts +47 -0
- package/src/utils/NodeList.ts +245 -0
- package/src/utils/getElementOffset.ts +13 -0
- package/src/utils/getElementScroll.ts +13 -0
- package/src/utils/getNodeRect.ts +29 -0
- package/src/utils/useAppendClassName.ts +20 -0
- package/src/utils/useBlankNode.ts +104 -0
- package/src/utils/useDragAndDrop.ts +32 -0
- package/src/utils/useDragEffect.ts +490 -0
- package/src/utils/useDroppable.ts +21 -0
- package/src/utils/useGeneratedId.ts +6 -0
- package/src/utils/useGetNodeStyle.ts +34 -0
- package/src/utils/useInitRect.ts +17 -0
- package/src/utils/useInitScrollOffset.ts +16 -0
- package/src/utils/useMoveNode.ts +97 -0
- package/src/utils/useScrollEventByPoint.ts +56 -0
- package/src/utils/useTargetList.ts +31 -0
- package/src/utils/useTransitionStyle.ts +26 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getScrollableElements } from '@os-design/use-auto-scroll';
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
const compare = <T>(prevArr: T[], nextArr: T[]) => {
|
|
5
|
+
const remove: T[] = [];
|
|
6
|
+
const add: T[] = [];
|
|
7
|
+
prevArr.forEach((item) => {
|
|
8
|
+
if (!nextArr.includes(item)) remove.push(item);
|
|
9
|
+
});
|
|
10
|
+
nextArr.forEach((item) => {
|
|
11
|
+
if (!prevArr.includes(item)) add.push(item);
|
|
12
|
+
});
|
|
13
|
+
return { remove, add };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface Point {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sets the listener that will be called whenever the scroll event occurs
|
|
23
|
+
* in one of the elements located under the specified point.
|
|
24
|
+
*/
|
|
25
|
+
const useScrollEventByPoint = (
|
|
26
|
+
point: Point | null,
|
|
27
|
+
listener: (e: Event) => void
|
|
28
|
+
) => {
|
|
29
|
+
const listenerRef = useRef(listener);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
listenerRef.current = listener;
|
|
32
|
+
}, [listener]);
|
|
33
|
+
|
|
34
|
+
const eventListener = useCallback((e: Event) => listenerRef.current(e), []);
|
|
35
|
+
const elementsRef = useRef<Element[]>([]);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!point) return;
|
|
39
|
+
const scrollableElements = getScrollableElements(point.x, point.y);
|
|
40
|
+
const { remove, add } = compare(elementsRef.current, scrollableElements);
|
|
41
|
+
const getTarget = (item: Element) =>
|
|
42
|
+
item === document.body ? window : item;
|
|
43
|
+
|
|
44
|
+
remove.forEach((item) => {
|
|
45
|
+
const index = elementsRef.current.indexOf(item);
|
|
46
|
+
if (index >= 0) elementsRef.current.splice(index, 1);
|
|
47
|
+
getTarget(item).removeEventListener('scroll', eventListener);
|
|
48
|
+
});
|
|
49
|
+
add.forEach((item) => {
|
|
50
|
+
elementsRef.current.push(item);
|
|
51
|
+
getTarget(item).addEventListener('scroll', eventListener);
|
|
52
|
+
});
|
|
53
|
+
}, [eventListener, point]);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default useScrollEventByPoint;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Position } from '@os-design/use-drag';
|
|
2
|
+
import useThrottle from '@os-design/use-throttle';
|
|
3
|
+
import { RefObject, useCallback, useMemo, useState } from 'react';
|
|
4
|
+
import ListStore from './ListStore';
|
|
5
|
+
import useScrollEventByPoint from './useScrollEventByPoint';
|
|
6
|
+
|
|
7
|
+
const useTargetList = (
|
|
8
|
+
position: Position | null,
|
|
9
|
+
listStoreRef: RefObject<ListStore>
|
|
10
|
+
) => {
|
|
11
|
+
const [number, setNumber] = useState(0);
|
|
12
|
+
|
|
13
|
+
const targetList = useMemo(() => {
|
|
14
|
+
if (!position || !listStoreRef.current) return null;
|
|
15
|
+
const { x, y } = position;
|
|
16
|
+
const list = listStoreRef.current.findByPosition(x, y);
|
|
17
|
+
return list || null;
|
|
18
|
+
}, [listStoreRef, position, number]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
19
|
+
|
|
20
|
+
const forceUpdate = useCallback(() => {
|
|
21
|
+
setNumber((n) => n + 1);
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
// Update the target list if one of the elements located under the specified point has been scrolled
|
|
25
|
+
const [throttledForceUpdate] = useThrottle(forceUpdate, 100);
|
|
26
|
+
useScrollEventByPoint(position, throttledForceUpdate);
|
|
27
|
+
|
|
28
|
+
return targetList;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default useTargetList;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
interface UseTransitionStyleProps {
|
|
4
|
+
className: string;
|
|
5
|
+
ms: number;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates the global style for setting the transition delay.
|
|
11
|
+
*/
|
|
12
|
+
const useTransitionStyle = (props: UseTransitionStyleProps) => {
|
|
13
|
+
const { className, ms, enabled } = props;
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!enabled) return () => {};
|
|
17
|
+
const style = document.createElement('style');
|
|
18
|
+
style.innerHTML = `.${className}{transition:transform ${ms}ms;}`;
|
|
19
|
+
const child = document.head.appendChild(style);
|
|
20
|
+
return () => {
|
|
21
|
+
document.head.removeChild(child);
|
|
22
|
+
};
|
|
23
|
+
}, [className, enabled, ms]);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default useTransitionStyle;
|