@lucasols/dnd-kit-core 0.1.3 → 0.2.0
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/dist/index.d.ts +655 -12
- package/dist/index.js +2626 -7
- package/dist/index.js.map +1 -0
- package/package.json +21 -17
- package/dist/components/Accessibility/Accessibility.d.ts +0 -10
- package/dist/components/Accessibility/components/RestoreFocus.d.ts +0 -5
- package/dist/components/Accessibility/components/index.d.ts +0 -1
- package/dist/components/Accessibility/defaults.d.ts +0 -3
- package/dist/components/Accessibility/index.d.ts +0 -4
- package/dist/components/Accessibility/types.d.ts +0 -15
- package/dist/components/DndContext/DndContext.d.ts +0 -35
- package/dist/components/DndContext/defaults.d.ts +0 -13
- package/dist/components/DndContext/hooks/index.d.ts +0 -2
- package/dist/components/DndContext/hooks/useLayoutShiftScrollCompensation.d.ts +0 -14
- package/dist/components/DndContext/hooks/useMeasuringConfiguration.d.ts +0 -3
- package/dist/components/DndContext/index.d.ts +0 -3
- package/dist/components/DndContext/types.d.ts +0 -16
- package/dist/components/DndMonitor/context.d.ts +0 -3
- package/dist/components/DndMonitor/index.d.ts +0 -4
- package/dist/components/DndMonitor/types.d.ts +0 -14
- package/dist/components/DndMonitor/useDndMonitor.d.ts +0 -2
- package/dist/components/DndMonitor/useDndMonitorProvider.d.ts +0 -2
- package/dist/components/DragOverlay/DragOverlay.d.ts +0 -11
- package/dist/components/DragOverlay/components/AnimationManager/AnimationManager.d.ts +0 -8
- package/dist/components/DragOverlay/components/AnimationManager/index.d.ts +0 -2
- package/dist/components/DragOverlay/components/NullifiedContextProvider/NullifiedContextProvider.d.ts +0 -6
- package/dist/components/DragOverlay/components/NullifiedContextProvider/index.d.ts +0 -1
- package/dist/components/DragOverlay/components/PositionedOverlay/PositionedOverlay.d.ts +0 -18
- package/dist/components/DragOverlay/components/PositionedOverlay/index.d.ts +0 -2
- package/dist/components/DragOverlay/components/index.d.ts +0 -5
- package/dist/components/DragOverlay/hooks/index.d.ts +0 -3
- package/dist/components/DragOverlay/hooks/useDropAnimation.d.ts +0 -65
- package/dist/components/DragOverlay/hooks/useKey.d.ts +0 -2
- package/dist/components/DragOverlay/index.d.ts +0 -4
- package/dist/components/index.d.ts +0 -8
- package/dist/dnd-kit-core.cjs.development.js +0 -3924
- package/dist/dnd-kit-core.cjs.development.js.map +0 -1
- package/dist/dnd-kit-core.cjs.production.min.js +0 -2
- package/dist/dnd-kit-core.cjs.production.min.js.map +0 -1
- package/dist/dnd-kit-core.esm.js +0 -3903
- package/dist/dnd-kit-core.esm.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/useDndContext.d.ts +0 -4
- package/dist/hooks/useDraggable.d.ts +0 -37
- package/dist/hooks/useDroppable.d.ts +0 -29
- package/dist/hooks/utilities/index.d.ts +0 -21
- package/dist/hooks/utilities/useAutoScroller.d.ts +0 -40
- package/dist/hooks/utilities/useCachedNode.d.ts +0 -3
- package/dist/hooks/utilities/useCombineActivators.d.ts +0 -3
- package/dist/hooks/utilities/useDragOverlayMeasuring.d.ts +0 -7
- package/dist/hooks/utilities/useDroppableMeasuring.d.ts +0 -27
- package/dist/hooks/utilities/useInitialRect.d.ts +0 -2
- package/dist/hooks/utilities/useInitialValue.d.ts +0 -3
- package/dist/hooks/utilities/useMutationObserver.d.ts +0 -10
- package/dist/hooks/utilities/useRect.d.ts +0 -2
- package/dist/hooks/utilities/useRectDelta.d.ts +0 -2
- package/dist/hooks/utilities/useRects.d.ts +0 -5
- package/dist/hooks/utilities/useResizeObserver.d.ts +0 -10
- package/dist/hooks/utilities/useScrollIntoViewIfNeeded.d.ts +0 -1
- package/dist/hooks/utilities/useScrollOffsets.d.ts +0 -2
- package/dist/hooks/utilities/useScrollOffsetsDelta.d.ts +0 -2
- package/dist/hooks/utilities/useScrollableAncestors.d.ts +0 -1
- package/dist/hooks/utilities/useSensorSetup.d.ts +0 -2
- package/dist/hooks/utilities/useSyntheticListeners.d.ts +0 -9
- package/dist/hooks/utilities/useWindowRect.d.ts +0 -1
- package/dist/modifiers/applyModifiers.d.ts +0 -3
- package/dist/modifiers/index.d.ts +0 -2
- package/dist/modifiers/types.d.ts +0 -17
- package/dist/sensors/events.d.ts +0 -11
- package/dist/sensors/index.d.ts +0 -11
- package/dist/sensors/keyboard/KeyboardSensor.d.ts +0 -27
- package/dist/sensors/keyboard/defaults.d.ts +0 -3
- package/dist/sensors/keyboard/index.d.ts +0 -4
- package/dist/sensors/keyboard/types.d.ts +0 -21
- package/dist/sensors/mouse/MouseSensor.d.ts +0 -13
- package/dist/sensors/mouse/index.d.ts +0 -2
- package/dist/sensors/pointer/AbstractPointerSensor.d.ts +0 -48
- package/dist/sensors/pointer/PointerSensor.d.ts +0 -13
- package/dist/sensors/pointer/index.d.ts +0 -4
- package/dist/sensors/touch/TouchSensor.d.ts +0 -14
- package/dist/sensors/touch/index.d.ts +0 -2
- package/dist/sensors/types.d.ts +0 -60
- package/dist/sensors/useSensor.d.ts +0 -2
- package/dist/sensors/useSensors.d.ts +0 -2
- package/dist/sensors/utilities/Listeners.d.ts +0 -7
- package/dist/sensors/utilities/getEventListenerTarget.d.ts +0 -1
- package/dist/sensors/utilities/hasExceededDistance.d.ts +0 -2
- package/dist/sensors/utilities/index.d.ts +0 -3
- package/dist/store/actions.d.ts +0 -36
- package/dist/store/constructors.d.ts +0 -10
- package/dist/store/context.d.ts +0 -6
- package/dist/store/index.d.ts +0 -4
- package/dist/store/reducer.d.ts +0 -4
- package/dist/store/types.d.ts +0 -98
- package/dist/types/coordinates.d.ts +0 -9
- package/dist/types/direction.d.ts +0 -4
- package/dist/types/events.d.ts +0 -21
- package/dist/types/index.d.ts +0 -6
- package/dist/types/other.d.ts +0 -1
- package/dist/types/react.d.ts +0 -3
- package/dist/types/rect.d.ts +0 -8
- package/dist/utilities/algorithms/closestCenter.d.ts +0 -6
- package/dist/utilities/algorithms/closestCorners.d.ts +0 -6
- package/dist/utilities/algorithms/helpers.d.ts +0 -24
- package/dist/utilities/algorithms/index.d.ts +0 -6
- package/dist/utilities/algorithms/pointerWithin.d.ts +0 -5
- package/dist/utilities/algorithms/rectIntersection.d.ts +0 -11
- package/dist/utilities/algorithms/types.d.ts +0 -20
- package/dist/utilities/coordinates/constants.d.ts +0 -2
- package/dist/utilities/coordinates/distanceBetweenPoints.d.ts +0 -5
- package/dist/utilities/coordinates/getRelativeTransformOrigin.d.ts +0 -2
- package/dist/utilities/coordinates/index.d.ts +0 -3
- package/dist/utilities/index.d.ts +0 -6
- package/dist/utilities/nodes/getMeasurableNode.d.ts +0 -1
- package/dist/utilities/nodes/index.d.ts +0 -1
- package/dist/utilities/other/index.d.ts +0 -1
- package/dist/utilities/other/noop.d.ts +0 -1
- package/dist/utilities/rect/Rect.d.ts +0 -11
- package/dist/utilities/rect/adjustScale.d.ts +0 -3
- package/dist/utilities/rect/getRect.d.ts +0 -25
- package/dist/utilities/rect/getRectDelta.d.ts +0 -2
- package/dist/utilities/rect/getWindowClientRect.d.ts +0 -2
- package/dist/utilities/rect/index.d.ts +0 -6
- package/dist/utilities/rect/rectAdjustment.d.ts +0 -3
- package/dist/utilities/scroll/documentScrollingElement.d.ts +0 -1
- package/dist/utilities/scroll/getScrollCoordinates.d.ts +0 -4
- package/dist/utilities/scroll/getScrollDirectionAndSpeed.d.ts +0 -17
- package/dist/utilities/scroll/getScrollElementRect.d.ts +0 -8
- package/dist/utilities/scroll/getScrollOffsets.d.ts +0 -4
- package/dist/utilities/scroll/getScrollPosition.d.ts +0 -14
- package/dist/utilities/scroll/getScrollableAncestors.d.ts +0 -2
- package/dist/utilities/scroll/getScrollableElement.d.ts +0 -1
- package/dist/utilities/scroll/index.d.ts +0 -10
- package/dist/utilities/scroll/isFixed.d.ts +0 -1
- package/dist/utilities/scroll/isScrollable.d.ts +0 -1
- package/dist/utilities/scroll/scrollIntoViewIfNeeded.d.ts +0 -2
- package/dist/utilities/transform/index.d.ts +0 -2
- package/dist/utilities/transform/inverseTransform.d.ts +0 -2
- package/dist/utilities/transform/parseTransform.d.ts +0 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,2627 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import React, { cloneElement, createContext, forwardRef, memo, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
|
+
import { createPortal } from "react-dom";
|
|
3
|
+
import { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isWindow, subtract, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId } from "@lucasols/dnd-kit-utilities";
|
|
4
|
+
import { HiddenText, LiveRegion, useAnnouncement } from "@lucasols/dnd-kit-accessibility";
|
|
5
|
+
//#region src/components/DndMonitor/context.ts
|
|
6
|
+
const DndMonitorContext = createContext(null);
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/components/DndMonitor/useDndMonitor.ts
|
|
9
|
+
function useDndMonitor(listener) {
|
|
10
|
+
const registerListener = useContext(DndMonitorContext);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!registerListener) throw new Error("useDndMonitor must be used within a children of <DndContext>");
|
|
13
|
+
return registerListener(listener);
|
|
14
|
+
}, [listener, registerListener]);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/components/DndMonitor/useDndMonitorProvider.tsx
|
|
18
|
+
function useDndMonitorProvider() {
|
|
19
|
+
const [listeners] = useState(() => /* @__PURE__ */ new Set());
|
|
20
|
+
const registerListener = useCallback((listener) => {
|
|
21
|
+
listeners.add(listener);
|
|
22
|
+
return () => listeners.delete(listener);
|
|
23
|
+
}, [listeners]);
|
|
24
|
+
return [useCallback(({ type, event }) => {
|
|
25
|
+
listeners.forEach((listener) => listener[type]?.(event));
|
|
26
|
+
}, [listeners]), registerListener];
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/components/Accessibility/defaults.ts
|
|
30
|
+
const defaultScreenReaderInstructions = { draggable: `
|
|
31
|
+
To pick up a draggable item, press the space bar.
|
|
32
|
+
While dragging, use the arrow keys to move the item.
|
|
33
|
+
Press space again to drop the item in its new position, or press escape to cancel.
|
|
34
|
+
` };
|
|
35
|
+
const defaultAnnouncements = {
|
|
36
|
+
onDragStart({ active }) {
|
|
37
|
+
return `Picked up draggable item ${active.id}.`;
|
|
38
|
+
},
|
|
39
|
+
onDragOver({ active, over }) {
|
|
40
|
+
if (over) return `Draggable item ${active.id} was moved over droppable area ${over.id}.`;
|
|
41
|
+
return `Draggable item ${active.id} is no longer over a droppable area.`;
|
|
42
|
+
},
|
|
43
|
+
onDragEnd({ active, over }) {
|
|
44
|
+
if (over) return `Draggable item ${active.id} was dropped over droppable area ${over.id}`;
|
|
45
|
+
return `Draggable item ${active.id} was dropped.`;
|
|
46
|
+
},
|
|
47
|
+
onDragCancel({ active }) {
|
|
48
|
+
return `Dragging was cancelled. Draggable item ${active.id} was dropped.`;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/components/Accessibility/Accessibility.tsx
|
|
53
|
+
function Accessibility({ announcements = defaultAnnouncements, container, hiddenTextDescribedById, screenReaderInstructions = defaultScreenReaderInstructions }) {
|
|
54
|
+
const { announce, announcement } = useAnnouncement();
|
|
55
|
+
const liveRegionId = useUniqueId(`DndLiveRegion`);
|
|
56
|
+
const [mounted, setMounted] = useState(false);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
setMounted(true);
|
|
59
|
+
}, []);
|
|
60
|
+
useDndMonitor(useMemo(() => ({
|
|
61
|
+
onDragStart({ active }) {
|
|
62
|
+
announce(announcements.onDragStart({ active }));
|
|
63
|
+
},
|
|
64
|
+
onDragMove({ active, over }) {
|
|
65
|
+
if (announcements.onDragMove) announce(announcements.onDragMove({
|
|
66
|
+
active,
|
|
67
|
+
over
|
|
68
|
+
}));
|
|
69
|
+
},
|
|
70
|
+
onDragOver({ active, over }) {
|
|
71
|
+
announce(announcements.onDragOver({
|
|
72
|
+
active,
|
|
73
|
+
over
|
|
74
|
+
}));
|
|
75
|
+
},
|
|
76
|
+
onDragEnd({ active, over }) {
|
|
77
|
+
announce(announcements.onDragEnd({
|
|
78
|
+
active,
|
|
79
|
+
over
|
|
80
|
+
}));
|
|
81
|
+
},
|
|
82
|
+
onDragCancel({ active, over }) {
|
|
83
|
+
announce(announcements.onDragCancel({
|
|
84
|
+
active,
|
|
85
|
+
over
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
}), [announce, announcements]));
|
|
89
|
+
if (!mounted) return null;
|
|
90
|
+
const markup = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(HiddenText, {
|
|
91
|
+
id: hiddenTextDescribedById,
|
|
92
|
+
value: screenReaderInstructions.draggable
|
|
93
|
+
}), /* @__PURE__ */ React.createElement(LiveRegion, {
|
|
94
|
+
id: liveRegionId,
|
|
95
|
+
announcement
|
|
96
|
+
}));
|
|
97
|
+
return container ? createPortal(markup, container) : markup;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/utilities/other/noop.ts
|
|
101
|
+
function noop(..._args) {}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/sensors/useSensor.ts
|
|
104
|
+
function useSensor(sensor, options) {
|
|
105
|
+
return useMemo(() => ({
|
|
106
|
+
sensor,
|
|
107
|
+
options: options ?? {}
|
|
108
|
+
}), [sensor, options]);
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/sensors/useSensors.ts
|
|
112
|
+
function useSensors(...sensors) {
|
|
113
|
+
return useMemo(() => [...sensors].filter((sensor) => sensor != null), [...sensors]);
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/utilities/coordinates/constants.ts
|
|
117
|
+
const defaultCoordinates = Object.freeze({
|
|
118
|
+
x: 0,
|
|
119
|
+
y: 0
|
|
120
|
+
});
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/utilities/coordinates/distanceBetweenPoints.ts
|
|
123
|
+
/**
|
|
124
|
+
* Returns the distance between two points
|
|
125
|
+
*/
|
|
126
|
+
function distanceBetween(p1, p2) {
|
|
127
|
+
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/utilities/coordinates/getRelativeTransformOrigin.ts
|
|
131
|
+
function getRelativeTransformOrigin(event, rect) {
|
|
132
|
+
const eventCoordinates = getEventCoordinates(event);
|
|
133
|
+
if (!eventCoordinates) return "0 0";
|
|
134
|
+
const transformOrigin = {
|
|
135
|
+
x: (eventCoordinates.x - rect.left) / rect.width * 100,
|
|
136
|
+
y: (eventCoordinates.y - rect.top) / rect.height * 100
|
|
137
|
+
};
|
|
138
|
+
return `${transformOrigin.x}% ${transformOrigin.y}%`;
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/utilities/algorithms/helpers.ts
|
|
142
|
+
/**
|
|
143
|
+
* Sort collisions from smallest to greatest value
|
|
144
|
+
*/
|
|
145
|
+
function sortCollisionsAsc({ data: { value: a } }, { data: { value: b } }) {
|
|
146
|
+
return a - b;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Sort collisions from greatest to smallest value
|
|
150
|
+
*/
|
|
151
|
+
function sortCollisionsDesc({ data: { value: a } }, { data: { value: b } }) {
|
|
152
|
+
return b - a;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Returns the coordinates of the corners of a given rectangle:
|
|
156
|
+
* [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]
|
|
157
|
+
*/
|
|
158
|
+
function cornersOfRectangle({ left, top, height, width }) {
|
|
159
|
+
return [
|
|
160
|
+
{
|
|
161
|
+
x: left,
|
|
162
|
+
y: top
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
x: left + width,
|
|
166
|
+
y: top
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
x: left,
|
|
170
|
+
y: top + height
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
x: left + width,
|
|
174
|
+
y: top + height
|
|
175
|
+
}
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
function getFirstCollision(collisions, property) {
|
|
179
|
+
if (!collisions || collisions.length === 0) return null;
|
|
180
|
+
const [firstCollision] = collisions;
|
|
181
|
+
return property ? firstCollision[property] : firstCollision;
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/utilities/algorithms/closestCenter.ts
|
|
185
|
+
/**
|
|
186
|
+
* Returns the coordinates of the center of a given ClientRect
|
|
187
|
+
*/
|
|
188
|
+
function centerOfRectangle(rect, left = rect.left, top = rect.top) {
|
|
189
|
+
return {
|
|
190
|
+
x: left + rect.width * .5,
|
|
191
|
+
y: top + rect.height * .5
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Returns the closest rectangles from an array of rectangles to the center of a given
|
|
196
|
+
* rectangle.
|
|
197
|
+
*/
|
|
198
|
+
const closestCenter = ({ collisionRect, droppableRects, droppableContainers }) => {
|
|
199
|
+
const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);
|
|
200
|
+
const collisions = [];
|
|
201
|
+
for (const droppableContainer of droppableContainers) {
|
|
202
|
+
const { id } = droppableContainer;
|
|
203
|
+
const rect = droppableRects.get(id);
|
|
204
|
+
if (rect) {
|
|
205
|
+
const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);
|
|
206
|
+
collisions.push({
|
|
207
|
+
id,
|
|
208
|
+
data: {
|
|
209
|
+
droppableContainer,
|
|
210
|
+
value: distBetween
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return collisions.sort(sortCollisionsAsc);
|
|
216
|
+
};
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/utilities/algorithms/closestCorners.ts
|
|
219
|
+
/**
|
|
220
|
+
* Returns the closest rectangles from an array of rectangles to the corners of
|
|
221
|
+
* another rectangle.
|
|
222
|
+
*/
|
|
223
|
+
const closestCorners = ({ collisionRect, droppableRects, droppableContainers }) => {
|
|
224
|
+
const corners = cornersOfRectangle(collisionRect);
|
|
225
|
+
const collisions = [];
|
|
226
|
+
for (const droppableContainer of droppableContainers) {
|
|
227
|
+
const { id } = droppableContainer;
|
|
228
|
+
const rect = droppableRects.get(id);
|
|
229
|
+
if (rect) {
|
|
230
|
+
const rectCorners = cornersOfRectangle(rect);
|
|
231
|
+
const distances = corners.reduce((accumulator, corner, index) => {
|
|
232
|
+
return accumulator + distanceBetween(rectCorners[index], corner);
|
|
233
|
+
}, 0);
|
|
234
|
+
const effectiveDistance = Number((distances / 4).toFixed(4));
|
|
235
|
+
collisions.push({
|
|
236
|
+
id,
|
|
237
|
+
data: {
|
|
238
|
+
droppableContainer,
|
|
239
|
+
value: effectiveDistance
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return collisions.sort(sortCollisionsAsc);
|
|
245
|
+
};
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/utilities/algorithms/rectIntersection.ts
|
|
248
|
+
/**
|
|
249
|
+
* Returns the intersecting rectangle area between two rectangles
|
|
250
|
+
*/
|
|
251
|
+
function getIntersectionRatio(entry, target) {
|
|
252
|
+
const top = Math.max(target.top, entry.top);
|
|
253
|
+
const left = Math.max(target.left, entry.left);
|
|
254
|
+
const right = Math.min(target.left + target.width, entry.left + entry.width);
|
|
255
|
+
const bottom = Math.min(target.top + target.height, entry.top + entry.height);
|
|
256
|
+
const width = right - left;
|
|
257
|
+
const height = bottom - top;
|
|
258
|
+
if (left < right && top < bottom) {
|
|
259
|
+
const targetArea = target.width * target.height;
|
|
260
|
+
const entryArea = entry.width * entry.height;
|
|
261
|
+
const intersectionArea = width * height;
|
|
262
|
+
const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);
|
|
263
|
+
return Number(intersectionRatio.toFixed(4));
|
|
264
|
+
}
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Returns the rectangles that has the greatest intersection area with a given
|
|
269
|
+
* rectangle in an array of rectangles.
|
|
270
|
+
*/
|
|
271
|
+
const rectIntersection = ({ collisionRect, droppableRects, droppableContainers }) => {
|
|
272
|
+
const collisions = [];
|
|
273
|
+
for (const droppableContainer of droppableContainers) {
|
|
274
|
+
const { id } = droppableContainer;
|
|
275
|
+
const rect = droppableRects.get(id);
|
|
276
|
+
if (rect) {
|
|
277
|
+
const intersectionRatio = getIntersectionRatio(rect, collisionRect);
|
|
278
|
+
if (intersectionRatio > 0) collisions.push({
|
|
279
|
+
id,
|
|
280
|
+
data: {
|
|
281
|
+
droppableContainer,
|
|
282
|
+
value: intersectionRatio
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return collisions.sort(sortCollisionsDesc);
|
|
288
|
+
};
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region src/utilities/algorithms/pointerWithin.ts
|
|
291
|
+
/**
|
|
292
|
+
* Check if a given point is contained within a bounding rectangle
|
|
293
|
+
*/
|
|
294
|
+
function isPointWithinRect(point, rect) {
|
|
295
|
+
const { top, left, bottom, right } = rect;
|
|
296
|
+
return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Returns the rectangles that the pointer is hovering over
|
|
300
|
+
*/
|
|
301
|
+
const pointerWithin = ({ droppableContainers, droppableRects, pointerCoordinates }) => {
|
|
302
|
+
if (!pointerCoordinates) return [];
|
|
303
|
+
const collisions = [];
|
|
304
|
+
for (const droppableContainer of droppableContainers) {
|
|
305
|
+
const { id } = droppableContainer;
|
|
306
|
+
const rect = droppableRects.get(id);
|
|
307
|
+
if (rect && isPointWithinRect(pointerCoordinates, rect)) {
|
|
308
|
+
const distances = cornersOfRectangle(rect).reduce((accumulator, corner) => {
|
|
309
|
+
return accumulator + distanceBetween(pointerCoordinates, corner);
|
|
310
|
+
}, 0);
|
|
311
|
+
const effectiveDistance = Number((distances / 4).toFixed(4));
|
|
312
|
+
collisions.push({
|
|
313
|
+
id,
|
|
314
|
+
data: {
|
|
315
|
+
droppableContainer,
|
|
316
|
+
value: effectiveDistance
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return collisions.sort(sortCollisionsAsc);
|
|
322
|
+
};
|
|
323
|
+
//#endregion
|
|
324
|
+
//#region src/utilities/rect/adjustScale.ts
|
|
325
|
+
function adjustScale(transform, rect1, rect2) {
|
|
326
|
+
return {
|
|
327
|
+
...transform,
|
|
328
|
+
scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,
|
|
329
|
+
scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/utilities/rect/getRectDelta.ts
|
|
334
|
+
function getRectDelta(rect1, rect2) {
|
|
335
|
+
return rect1 && rect2 ? {
|
|
336
|
+
x: rect1.left - rect2.left,
|
|
337
|
+
y: rect1.top - rect2.top
|
|
338
|
+
} : defaultCoordinates;
|
|
339
|
+
}
|
|
340
|
+
//#endregion
|
|
341
|
+
//#region src/utilities/rect/rectAdjustment.ts
|
|
342
|
+
function createRectAdjustmentFn(modifier) {
|
|
343
|
+
return function adjustClientRect(rect, ...adjustments) {
|
|
344
|
+
return adjustments.reduce((acc, adjustment) => ({
|
|
345
|
+
...acc,
|
|
346
|
+
top: acc.top + modifier * adjustment.y,
|
|
347
|
+
bottom: acc.bottom + modifier * adjustment.y,
|
|
348
|
+
left: acc.left + modifier * adjustment.x,
|
|
349
|
+
right: acc.right + modifier * adjustment.x
|
|
350
|
+
}), { ...rect });
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const getAdjustedRect = createRectAdjustmentFn(1);
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/utilities/transform/parseTransform.ts
|
|
356
|
+
function parseTransform(transform) {
|
|
357
|
+
if (transform.startsWith("matrix3d(")) {
|
|
358
|
+
const transformArray = transform.slice(9, -1).split(/, /);
|
|
359
|
+
return {
|
|
360
|
+
x: +transformArray[12],
|
|
361
|
+
y: +transformArray[13],
|
|
362
|
+
scaleX: +transformArray[0],
|
|
363
|
+
scaleY: +transformArray[5]
|
|
364
|
+
};
|
|
365
|
+
} else if (transform.startsWith("matrix(")) {
|
|
366
|
+
const transformArray = transform.slice(7, -1).split(/, /);
|
|
367
|
+
return {
|
|
368
|
+
x: +transformArray[4],
|
|
369
|
+
y: +transformArray[5],
|
|
370
|
+
scaleX: +transformArray[0],
|
|
371
|
+
scaleY: +transformArray[3]
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/utilities/transform/inverseTransform.ts
|
|
378
|
+
function inverseTransform(rect, transform, transformOrigin) {
|
|
379
|
+
const parsedTransform = parseTransform(transform);
|
|
380
|
+
if (!parsedTransform) return rect;
|
|
381
|
+
const { scaleX, scaleY, x: translateX, y: translateY } = parsedTransform;
|
|
382
|
+
const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);
|
|
383
|
+
const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(" ") + 1));
|
|
384
|
+
const w = scaleX ? rect.width / scaleX : rect.width;
|
|
385
|
+
const h = scaleY ? rect.height / scaleY : rect.height;
|
|
386
|
+
return {
|
|
387
|
+
width: w,
|
|
388
|
+
height: h,
|
|
389
|
+
top: y,
|
|
390
|
+
right: x + w,
|
|
391
|
+
bottom: y + h,
|
|
392
|
+
left: x
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
396
|
+
//#region src/utilities/rect/getRect.ts
|
|
397
|
+
const defaultOptions = { ignoreTransform: false };
|
|
398
|
+
/**
|
|
399
|
+
* Returns the bounding client rect of an element relative to the viewport.
|
|
400
|
+
*/
|
|
401
|
+
function getClientRect(element, options = defaultOptions) {
|
|
402
|
+
let rect = element.getBoundingClientRect();
|
|
403
|
+
if (options.ignoreTransform) {
|
|
404
|
+
const { transform, transformOrigin } = getWindow(element).getComputedStyle(element);
|
|
405
|
+
if (transform) rect = inverseTransform(rect, transform, transformOrigin);
|
|
406
|
+
}
|
|
407
|
+
const { top, left, width, height, bottom, right } = rect;
|
|
408
|
+
return {
|
|
409
|
+
top,
|
|
410
|
+
left,
|
|
411
|
+
width,
|
|
412
|
+
height,
|
|
413
|
+
bottom,
|
|
414
|
+
right
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Returns the bounding client rect of an element relative to the viewport.
|
|
419
|
+
*
|
|
420
|
+
* @remarks
|
|
421
|
+
* The ClientRect returned by this method does not take into account transforms
|
|
422
|
+
* applied to the element it measures.
|
|
423
|
+
*
|
|
424
|
+
*/
|
|
425
|
+
function getTransformAgnosticClientRect(element) {
|
|
426
|
+
return getClientRect(element, { ignoreTransform: true });
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/utilities/rect/getWindowClientRect.ts
|
|
430
|
+
function getWindowClientRect(element) {
|
|
431
|
+
const width = element.innerWidth;
|
|
432
|
+
const height = element.innerHeight;
|
|
433
|
+
return {
|
|
434
|
+
top: 0,
|
|
435
|
+
left: 0,
|
|
436
|
+
right: width,
|
|
437
|
+
bottom: height,
|
|
438
|
+
width,
|
|
439
|
+
height
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/utilities/scroll/isFixed.ts
|
|
444
|
+
function isFixed(node, computedStyle = getWindow(node).getComputedStyle(node)) {
|
|
445
|
+
return computedStyle.position === "fixed";
|
|
446
|
+
}
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region src/utilities/scroll/isScrollable.ts
|
|
449
|
+
function isScrollable(element, computedStyle = getWindow(element).getComputedStyle(element)) {
|
|
450
|
+
const overflowRegex = /(auto|scroll|overlay)/;
|
|
451
|
+
return [
|
|
452
|
+
"overflow",
|
|
453
|
+
"overflowX",
|
|
454
|
+
"overflowY"
|
|
455
|
+
].some((property) => {
|
|
456
|
+
const value = computedStyle[property];
|
|
457
|
+
return typeof value === "string" ? overflowRegex.test(value) : false;
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/utilities/scroll/getScrollableAncestors.ts
|
|
462
|
+
function getScrollableAncestors(element, limit) {
|
|
463
|
+
const scrollParents = [];
|
|
464
|
+
function findScrollableAncestors(node) {
|
|
465
|
+
if (limit != null && scrollParents.length >= limit) return scrollParents;
|
|
466
|
+
if (!node) return scrollParents;
|
|
467
|
+
if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {
|
|
468
|
+
scrollParents.push(node.scrollingElement);
|
|
469
|
+
return scrollParents;
|
|
470
|
+
}
|
|
471
|
+
if (!isHTMLElement(node) || isSVGElement(node)) return scrollParents;
|
|
472
|
+
if (scrollParents.includes(node)) return scrollParents;
|
|
473
|
+
const computedStyle = getWindow(element).getComputedStyle(node);
|
|
474
|
+
if (node !== element) {
|
|
475
|
+
if (isScrollable(node, computedStyle)) scrollParents.push(node);
|
|
476
|
+
}
|
|
477
|
+
if (isFixed(node, computedStyle)) return scrollParents;
|
|
478
|
+
return findScrollableAncestors(node.parentNode);
|
|
479
|
+
}
|
|
480
|
+
if (!element) return scrollParents;
|
|
481
|
+
return findScrollableAncestors(element);
|
|
482
|
+
}
|
|
483
|
+
function getFirstScrollableAncestor(node) {
|
|
484
|
+
const [firstScrollableAncestor] = getScrollableAncestors(node, 1);
|
|
485
|
+
return firstScrollableAncestor ?? null;
|
|
486
|
+
}
|
|
487
|
+
//#endregion
|
|
488
|
+
//#region src/utilities/scroll/getScrollableElement.ts
|
|
489
|
+
function getScrollableElement(element) {
|
|
490
|
+
if (!canUseDOM || !element) return null;
|
|
491
|
+
if (isWindow(element)) return element;
|
|
492
|
+
if (!isNode(element)) return null;
|
|
493
|
+
if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) return window;
|
|
494
|
+
if (isHTMLElement(element)) return element;
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/utilities/scroll/getScrollCoordinates.ts
|
|
499
|
+
function getScrollXCoordinate(element) {
|
|
500
|
+
if (isWindow(element)) return element.scrollX;
|
|
501
|
+
return element.scrollLeft;
|
|
502
|
+
}
|
|
503
|
+
function getScrollYCoordinate(element) {
|
|
504
|
+
if (isWindow(element)) return element.scrollY;
|
|
505
|
+
return element.scrollTop;
|
|
506
|
+
}
|
|
507
|
+
function getScrollCoordinates(element) {
|
|
508
|
+
return {
|
|
509
|
+
x: getScrollXCoordinate(element),
|
|
510
|
+
y: getScrollYCoordinate(element)
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/utilities/scroll/documentScrollingElement.ts
|
|
515
|
+
function isDocumentScrollingElement(element) {
|
|
516
|
+
if (!canUseDOM || !element) return false;
|
|
517
|
+
return element === document.scrollingElement;
|
|
518
|
+
}
|
|
519
|
+
//#endregion
|
|
520
|
+
//#region src/utilities/scroll/getScrollPosition.ts
|
|
521
|
+
function getScrollPosition(scrollingContainer) {
|
|
522
|
+
const minScroll = {
|
|
523
|
+
x: 0,
|
|
524
|
+
y: 0
|
|
525
|
+
};
|
|
526
|
+
const dimensions = isDocumentScrollingElement(scrollingContainer) ? {
|
|
527
|
+
height: window.innerHeight,
|
|
528
|
+
width: window.innerWidth
|
|
529
|
+
} : {
|
|
530
|
+
height: scrollingContainer.clientHeight,
|
|
531
|
+
width: scrollingContainer.clientWidth
|
|
532
|
+
};
|
|
533
|
+
const maxScroll = {
|
|
534
|
+
x: scrollingContainer.scrollWidth - dimensions.width,
|
|
535
|
+
y: scrollingContainer.scrollHeight - dimensions.height
|
|
536
|
+
};
|
|
537
|
+
return {
|
|
538
|
+
isTop: scrollingContainer.scrollTop <= minScroll.y,
|
|
539
|
+
isLeft: scrollingContainer.scrollLeft <= minScroll.x,
|
|
540
|
+
isBottom: scrollingContainer.scrollTop >= maxScroll.y,
|
|
541
|
+
isRight: scrollingContainer.scrollLeft >= maxScroll.x,
|
|
542
|
+
maxScroll,
|
|
543
|
+
minScroll
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/utilities/scroll/getScrollDirectionAndSpeed.ts
|
|
548
|
+
const defaultThreshold = {
|
|
549
|
+
x: .2,
|
|
550
|
+
y: .2
|
|
551
|
+
};
|
|
552
|
+
function getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, { top, left, right, bottom }, acceleration = 10, thresholdPercentage = defaultThreshold) {
|
|
553
|
+
const { isTop, isBottom, isLeft, isRight } = getScrollPosition(scrollContainer);
|
|
554
|
+
const direction = {
|
|
555
|
+
x: 0,
|
|
556
|
+
y: 0
|
|
557
|
+
};
|
|
558
|
+
const speed = {
|
|
559
|
+
x: 0,
|
|
560
|
+
y: 0
|
|
561
|
+
};
|
|
562
|
+
const threshold = {
|
|
563
|
+
height: scrollContainerRect.height * thresholdPercentage.y,
|
|
564
|
+
width: scrollContainerRect.width * thresholdPercentage.x
|
|
565
|
+
};
|
|
566
|
+
if (!isTop && top <= scrollContainerRect.top + threshold.height) {
|
|
567
|
+
direction.y = -1;
|
|
568
|
+
speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);
|
|
569
|
+
} else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {
|
|
570
|
+
direction.y = 1;
|
|
571
|
+
speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);
|
|
572
|
+
}
|
|
573
|
+
if (!isRight && right >= scrollContainerRect.right - threshold.width) {
|
|
574
|
+
direction.x = 1;
|
|
575
|
+
speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);
|
|
576
|
+
} else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {
|
|
577
|
+
direction.x = -1;
|
|
578
|
+
speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);
|
|
579
|
+
}
|
|
580
|
+
return {
|
|
581
|
+
direction,
|
|
582
|
+
speed
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/utilities/scroll/getScrollElementRect.ts
|
|
587
|
+
function getScrollElementRect(element) {
|
|
588
|
+
if (element === document.scrollingElement) {
|
|
589
|
+
const { innerWidth, innerHeight } = window;
|
|
590
|
+
return {
|
|
591
|
+
top: 0,
|
|
592
|
+
left: 0,
|
|
593
|
+
right: innerWidth,
|
|
594
|
+
bottom: innerHeight,
|
|
595
|
+
width: innerWidth,
|
|
596
|
+
height: innerHeight
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
const { top, left, right, bottom } = element.getBoundingClientRect();
|
|
600
|
+
return {
|
|
601
|
+
top,
|
|
602
|
+
left,
|
|
603
|
+
right,
|
|
604
|
+
bottom,
|
|
605
|
+
width: element.clientWidth,
|
|
606
|
+
height: element.clientHeight
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region src/utilities/scroll/getScrollOffsets.ts
|
|
611
|
+
function getScrollOffsets(scrollableAncestors) {
|
|
612
|
+
return scrollableAncestors.reduce((acc, node) => {
|
|
613
|
+
return add(acc, getScrollCoordinates(node));
|
|
614
|
+
}, defaultCoordinates);
|
|
615
|
+
}
|
|
616
|
+
function getScrollXOffset(scrollableAncestors) {
|
|
617
|
+
return scrollableAncestors.reduce((acc, node) => {
|
|
618
|
+
return acc + getScrollXCoordinate(node);
|
|
619
|
+
}, 0);
|
|
620
|
+
}
|
|
621
|
+
function getScrollYOffset(scrollableAncestors) {
|
|
622
|
+
return scrollableAncestors.reduce((acc, node) => {
|
|
623
|
+
return acc + getScrollYCoordinate(node);
|
|
624
|
+
}, 0);
|
|
625
|
+
}
|
|
626
|
+
//#endregion
|
|
627
|
+
//#region src/utilities/scroll/scrollIntoViewIfNeeded.ts
|
|
628
|
+
function scrollIntoViewIfNeeded(element, measure = getClientRect) {
|
|
629
|
+
if (!element) return;
|
|
630
|
+
const { top, left, bottom, right } = measure(element);
|
|
631
|
+
if (!getFirstScrollableAncestor(element)) return;
|
|
632
|
+
if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) element.scrollIntoView({
|
|
633
|
+
block: "center",
|
|
634
|
+
inline: "center"
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/utilities/rect/Rect.ts
|
|
639
|
+
const properties = [[
|
|
640
|
+
"x",
|
|
641
|
+
["left", "right"],
|
|
642
|
+
getScrollXOffset
|
|
643
|
+
], [
|
|
644
|
+
"y",
|
|
645
|
+
["top", "bottom"],
|
|
646
|
+
getScrollYOffset
|
|
647
|
+
]];
|
|
648
|
+
var Rect = class {
|
|
649
|
+
constructor(rect, element) {
|
|
650
|
+
const scrollableAncestors = getScrollableAncestors(element);
|
|
651
|
+
const scrollOffsets = getScrollOffsets(scrollableAncestors);
|
|
652
|
+
this.rect = { ...rect };
|
|
653
|
+
this.width = rect.width;
|
|
654
|
+
this.height = rect.height;
|
|
655
|
+
for (const [axis, keys, getScrollOffset] of properties) for (const key of keys) Object.defineProperty(this, key, {
|
|
656
|
+
get: () => {
|
|
657
|
+
const currentOffsets = getScrollOffset(scrollableAncestors);
|
|
658
|
+
const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;
|
|
659
|
+
return this.rect[key] + scrollOffsetsDeltla;
|
|
660
|
+
},
|
|
661
|
+
enumerable: true
|
|
662
|
+
});
|
|
663
|
+
Object.defineProperty(this, "rect", { enumerable: false });
|
|
664
|
+
}
|
|
665
|
+
rect;
|
|
666
|
+
width;
|
|
667
|
+
height;
|
|
668
|
+
top;
|
|
669
|
+
bottom;
|
|
670
|
+
right;
|
|
671
|
+
left;
|
|
672
|
+
};
|
|
673
|
+
//#endregion
|
|
674
|
+
//#region src/sensors/utilities/Listeners.ts
|
|
675
|
+
var Listeners = class {
|
|
676
|
+
target;
|
|
677
|
+
listeners = [];
|
|
678
|
+
constructor(target) {
|
|
679
|
+
this.target = target;
|
|
680
|
+
}
|
|
681
|
+
add(eventName, handler, options) {
|
|
682
|
+
this.target?.addEventListener(eventName, handler, options);
|
|
683
|
+
this.listeners.push([
|
|
684
|
+
eventName,
|
|
685
|
+
handler,
|
|
686
|
+
options
|
|
687
|
+
]);
|
|
688
|
+
}
|
|
689
|
+
removeAll = () => {
|
|
690
|
+
this.listeners.forEach((listener) => this.target?.removeEventListener(...listener));
|
|
691
|
+
};
|
|
692
|
+
};
|
|
693
|
+
//#endregion
|
|
694
|
+
//#region src/sensors/utilities/getEventListenerTarget.ts
|
|
695
|
+
function getEventListenerTarget(target) {
|
|
696
|
+
const { EventTarget } = getWindow(target);
|
|
697
|
+
return target instanceof EventTarget ? target : getOwnerDocument(target);
|
|
698
|
+
}
|
|
699
|
+
//#endregion
|
|
700
|
+
//#region src/sensors/utilities/hasExceededDistance.ts
|
|
701
|
+
function hasExceededDistance(delta, measurement) {
|
|
702
|
+
const dx = Math.abs(delta.x);
|
|
703
|
+
const dy = Math.abs(delta.y);
|
|
704
|
+
if (typeof measurement === "number") return Math.sqrt(dx ** 2 + dy ** 2) > measurement;
|
|
705
|
+
if ("x" in measurement && "y" in measurement) return dx > measurement.x && dy > measurement.y;
|
|
706
|
+
if ("x" in measurement) return dx > measurement.x;
|
|
707
|
+
if ("y" in measurement) return dy > measurement.y;
|
|
708
|
+
return false;
|
|
8
709
|
}
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/sensors/events.ts
|
|
712
|
+
function preventDefault(event) {
|
|
713
|
+
event.preventDefault();
|
|
714
|
+
}
|
|
715
|
+
function stopPropagation(event) {
|
|
716
|
+
event.stopPropagation();
|
|
717
|
+
}
|
|
718
|
+
//#endregion
|
|
719
|
+
//#region src/sensors/keyboard/types.ts
|
|
720
|
+
let KeyboardCode = /* @__PURE__ */ function(KeyboardCode) {
|
|
721
|
+
KeyboardCode["Space"] = "Space";
|
|
722
|
+
KeyboardCode["Down"] = "ArrowDown";
|
|
723
|
+
KeyboardCode["Right"] = "ArrowRight";
|
|
724
|
+
KeyboardCode["Left"] = "ArrowLeft";
|
|
725
|
+
KeyboardCode["Up"] = "ArrowUp";
|
|
726
|
+
KeyboardCode["Esc"] = "Escape";
|
|
727
|
+
KeyboardCode["Enter"] = "Enter";
|
|
728
|
+
return KeyboardCode;
|
|
729
|
+
}({});
|
|
730
|
+
//#endregion
|
|
731
|
+
//#region src/sensors/keyboard/defaults.ts
|
|
732
|
+
const defaultKeyboardCodes = {
|
|
733
|
+
start: ["Space", "Enter"],
|
|
734
|
+
cancel: ["Escape"],
|
|
735
|
+
end: ["Space", "Enter"]
|
|
736
|
+
};
|
|
737
|
+
const defaultKeyboardCoordinateGetter = (event, { currentCoordinates }) => {
|
|
738
|
+
switch (event.code) {
|
|
739
|
+
case "ArrowRight": return {
|
|
740
|
+
...currentCoordinates,
|
|
741
|
+
x: currentCoordinates.x + 25
|
|
742
|
+
};
|
|
743
|
+
case "ArrowLeft": return {
|
|
744
|
+
...currentCoordinates,
|
|
745
|
+
x: currentCoordinates.x - 25
|
|
746
|
+
};
|
|
747
|
+
case "ArrowDown": return {
|
|
748
|
+
...currentCoordinates,
|
|
749
|
+
y: currentCoordinates.y + 25
|
|
750
|
+
};
|
|
751
|
+
case "ArrowUp": return {
|
|
752
|
+
...currentCoordinates,
|
|
753
|
+
y: currentCoordinates.y - 25
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
//#endregion
|
|
758
|
+
//#region src/sensors/keyboard/KeyboardSensor.ts
|
|
759
|
+
var KeyboardSensor = class {
|
|
760
|
+
props;
|
|
761
|
+
autoScrollEnabled = false;
|
|
762
|
+
referenceCoordinates;
|
|
763
|
+
listeners;
|
|
764
|
+
windowListeners;
|
|
765
|
+
constructor(props) {
|
|
766
|
+
this.props = props;
|
|
767
|
+
const { event: { target } } = props;
|
|
768
|
+
this.listeners = new Listeners(getOwnerDocument(target));
|
|
769
|
+
this.windowListeners = new Listeners(getWindow(target));
|
|
770
|
+
this.handleKeyDown = this.handleKeyDown.bind(this);
|
|
771
|
+
this.handleCancel = this.handleCancel.bind(this);
|
|
772
|
+
this.attach();
|
|
773
|
+
}
|
|
774
|
+
attach() {
|
|
775
|
+
this.handleStart();
|
|
776
|
+
this.windowListeners.add("resize", this.handleCancel);
|
|
777
|
+
this.windowListeners.add("visibilitychange", this.handleCancel);
|
|
778
|
+
setTimeout(() => this.listeners.add("keydown", this.handleKeyDown));
|
|
779
|
+
}
|
|
780
|
+
handleStart() {
|
|
781
|
+
const { activeNode, onStart } = this.props;
|
|
782
|
+
const node = activeNode.node.current;
|
|
783
|
+
if (node) scrollIntoViewIfNeeded(node);
|
|
784
|
+
onStart(defaultCoordinates);
|
|
785
|
+
}
|
|
786
|
+
handleKeyDown(event) {
|
|
787
|
+
if (isKeyboardEvent(event)) {
|
|
788
|
+
const { active, context, options } = this.props;
|
|
789
|
+
const { keyboardCodes = defaultKeyboardCodes, coordinateGetter = defaultKeyboardCoordinateGetter, scrollBehavior = "smooth" } = options;
|
|
790
|
+
const { code } = event;
|
|
791
|
+
if (keyboardCodes.end.includes(code)) {
|
|
792
|
+
this.handleEnd(event);
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (keyboardCodes.cancel.includes(code)) {
|
|
796
|
+
this.handleCancel(event);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
const { collisionRect } = context.current;
|
|
800
|
+
const currentCoordinates = collisionRect ? {
|
|
801
|
+
x: collisionRect.left,
|
|
802
|
+
y: collisionRect.top
|
|
803
|
+
} : defaultCoordinates;
|
|
804
|
+
if (!this.referenceCoordinates) this.referenceCoordinates = currentCoordinates;
|
|
805
|
+
const newCoordinates = coordinateGetter(event, {
|
|
806
|
+
active,
|
|
807
|
+
context: context.current,
|
|
808
|
+
currentCoordinates
|
|
809
|
+
});
|
|
810
|
+
if (newCoordinates) {
|
|
811
|
+
const coordinatesDelta = subtract(newCoordinates, currentCoordinates);
|
|
812
|
+
const scrollDelta = {
|
|
813
|
+
x: 0,
|
|
814
|
+
y: 0
|
|
815
|
+
};
|
|
816
|
+
const { scrollableAncestors } = context.current;
|
|
817
|
+
for (const scrollContainer of scrollableAncestors) {
|
|
818
|
+
const direction = event.code;
|
|
819
|
+
const { isTop, isRight, isLeft, isBottom, maxScroll, minScroll } = getScrollPosition(scrollContainer);
|
|
820
|
+
const scrollElementRect = getScrollElementRect(scrollContainer);
|
|
821
|
+
const clampedCoordinates = {
|
|
822
|
+
x: Math.min(direction === "ArrowRight" ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === "ArrowRight" ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),
|
|
823
|
+
y: Math.min(direction === "ArrowDown" ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === "ArrowDown" ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))
|
|
824
|
+
};
|
|
825
|
+
const canScrollX = direction === "ArrowRight" && !isRight || direction === "ArrowLeft" && !isLeft;
|
|
826
|
+
const canScrollY = direction === "ArrowDown" && !isBottom || direction === "ArrowUp" && !isTop;
|
|
827
|
+
if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {
|
|
828
|
+
const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;
|
|
829
|
+
const canScrollToNewCoordinates = direction === "ArrowRight" && newScrollCoordinates <= maxScroll.x || direction === "ArrowLeft" && newScrollCoordinates >= minScroll.x;
|
|
830
|
+
if (canScrollToNewCoordinates && !coordinatesDelta.y) {
|
|
831
|
+
scrollContainer.scrollTo({
|
|
832
|
+
left: newScrollCoordinates,
|
|
833
|
+
behavior: scrollBehavior
|
|
834
|
+
});
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (canScrollToNewCoordinates) scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;
|
|
838
|
+
else scrollDelta.x = direction === "ArrowRight" ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;
|
|
839
|
+
if (scrollDelta.x) scrollContainer.scrollBy({
|
|
840
|
+
left: -scrollDelta.x,
|
|
841
|
+
behavior: scrollBehavior
|
|
842
|
+
});
|
|
843
|
+
break;
|
|
844
|
+
} else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {
|
|
845
|
+
const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;
|
|
846
|
+
const canScrollToNewCoordinates = direction === "ArrowDown" && newScrollCoordinates <= maxScroll.y || direction === "ArrowUp" && newScrollCoordinates >= minScroll.y;
|
|
847
|
+
if (canScrollToNewCoordinates && !coordinatesDelta.x) {
|
|
848
|
+
scrollContainer.scrollTo({
|
|
849
|
+
top: newScrollCoordinates,
|
|
850
|
+
behavior: scrollBehavior
|
|
851
|
+
});
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
if (canScrollToNewCoordinates) scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;
|
|
855
|
+
else scrollDelta.y = direction === "ArrowDown" ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;
|
|
856
|
+
if (scrollDelta.y) scrollContainer.scrollBy({
|
|
857
|
+
top: -scrollDelta.y,
|
|
858
|
+
behavior: scrollBehavior
|
|
859
|
+
});
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
handleMove(event, coordinates) {
|
|
868
|
+
const { onMove } = this.props;
|
|
869
|
+
event.preventDefault();
|
|
870
|
+
onMove(coordinates);
|
|
871
|
+
}
|
|
872
|
+
handleEnd(event) {
|
|
873
|
+
const { onEnd } = this.props;
|
|
874
|
+
event.preventDefault();
|
|
875
|
+
this.detach();
|
|
876
|
+
onEnd();
|
|
877
|
+
}
|
|
878
|
+
handleCancel(event) {
|
|
879
|
+
const { onCancel } = this.props;
|
|
880
|
+
event.preventDefault();
|
|
881
|
+
this.detach();
|
|
882
|
+
onCancel();
|
|
883
|
+
}
|
|
884
|
+
detach() {
|
|
885
|
+
this.listeners.removeAll();
|
|
886
|
+
this.windowListeners.removeAll();
|
|
887
|
+
}
|
|
888
|
+
static activators = [{
|
|
889
|
+
eventName: "onKeyDown",
|
|
890
|
+
handler: (event, { keyboardCodes = defaultKeyboardCodes, onActivation }, { active }) => {
|
|
891
|
+
const { code } = event.nativeEvent;
|
|
892
|
+
if (keyboardCodes.start.includes(code)) {
|
|
893
|
+
const activator = active.activatorNode.current;
|
|
894
|
+
if (activator && event.target !== activator) return false;
|
|
895
|
+
event.preventDefault();
|
|
896
|
+
onActivation?.({ event: event.nativeEvent });
|
|
897
|
+
return true;
|
|
898
|
+
}
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
}];
|
|
902
|
+
};
|
|
903
|
+
//#endregion
|
|
904
|
+
//#region src/sensors/pointer/AbstractPointerSensor.ts
|
|
905
|
+
function isDistanceConstraint(constraint) {
|
|
906
|
+
return Boolean(constraint && "distance" in constraint);
|
|
907
|
+
}
|
|
908
|
+
function isDelayConstraint(constraint) {
|
|
909
|
+
return Boolean(constraint && "delay" in constraint);
|
|
910
|
+
}
|
|
911
|
+
var AbstractPointerSensor = class {
|
|
912
|
+
props;
|
|
913
|
+
events;
|
|
914
|
+
autoScrollEnabled = true;
|
|
915
|
+
document;
|
|
916
|
+
activated = false;
|
|
917
|
+
initialCoordinates;
|
|
918
|
+
timeoutId = null;
|
|
919
|
+
listeners;
|
|
920
|
+
documentListeners;
|
|
921
|
+
windowListeners;
|
|
922
|
+
constructor(props, events, listenerTarget = getEventListenerTarget(props.event.target)) {
|
|
923
|
+
this.props = props;
|
|
924
|
+
this.events = events;
|
|
925
|
+
const { event } = props;
|
|
926
|
+
const { target } = event;
|
|
927
|
+
this.document = getOwnerDocument(target);
|
|
928
|
+
this.documentListeners = new Listeners(this.document);
|
|
929
|
+
this.listeners = new Listeners(listenerTarget);
|
|
930
|
+
this.windowListeners = new Listeners(getWindow(target));
|
|
931
|
+
this.initialCoordinates = getEventCoordinates(event) ?? defaultCoordinates;
|
|
932
|
+
this.handleStart = this.handleStart.bind(this);
|
|
933
|
+
this.handleMove = this.handleMove.bind(this);
|
|
934
|
+
this.handleEnd = this.handleEnd.bind(this);
|
|
935
|
+
this.handleCancel = this.handleCancel.bind(this);
|
|
936
|
+
this.handleKeydown = this.handleKeydown.bind(this);
|
|
937
|
+
this.removeTextSelection = this.removeTextSelection.bind(this);
|
|
938
|
+
this.attach();
|
|
939
|
+
}
|
|
940
|
+
attach() {
|
|
941
|
+
const { events, props: { options: { activationConstraint } } } = this;
|
|
942
|
+
this.listeners.add(events.move.name, this.handleMove, { passive: false });
|
|
943
|
+
this.listeners.add(events.end.name, this.handleEnd);
|
|
944
|
+
this.windowListeners.add("resize", this.handleCancel);
|
|
945
|
+
this.windowListeners.add("dragstart", preventDefault);
|
|
946
|
+
this.windowListeners.add("visibilitychange", this.handleCancel);
|
|
947
|
+
this.windowListeners.add("contextmenu", preventDefault);
|
|
948
|
+
this.documentListeners.add("keydown", this.handleKeydown);
|
|
949
|
+
if (activationConstraint) {
|
|
950
|
+
if (isDistanceConstraint(activationConstraint)) return;
|
|
951
|
+
if (isDelayConstraint(activationConstraint)) {
|
|
952
|
+
this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
this.handleStart();
|
|
957
|
+
}
|
|
958
|
+
detach() {
|
|
959
|
+
this.listeners.removeAll();
|
|
960
|
+
this.windowListeners.removeAll();
|
|
961
|
+
setTimeout(this.documentListeners.removeAll, 50);
|
|
962
|
+
if (this.timeoutId !== null) {
|
|
963
|
+
clearTimeout(this.timeoutId);
|
|
964
|
+
this.timeoutId = null;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
handleStart() {
|
|
968
|
+
const { initialCoordinates } = this;
|
|
969
|
+
const { onStart } = this.props;
|
|
970
|
+
if (initialCoordinates) {
|
|
971
|
+
this.activated = true;
|
|
972
|
+
this.documentListeners.add("click", stopPropagation, { capture: true });
|
|
973
|
+
this.removeTextSelection();
|
|
974
|
+
this.documentListeners.add("selectionchange", this.removeTextSelection);
|
|
975
|
+
onStart(initialCoordinates);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
handleMove(event) {
|
|
979
|
+
const { activated, initialCoordinates, props } = this;
|
|
980
|
+
const { onMove, options: { activationConstraint } } = props;
|
|
981
|
+
if (!initialCoordinates) return;
|
|
982
|
+
const coordinates = getEventCoordinates(event) ?? defaultCoordinates;
|
|
983
|
+
const delta = subtract(initialCoordinates, coordinates);
|
|
984
|
+
if (!activated && activationConstraint) {
|
|
985
|
+
if (isDelayConstraint(activationConstraint)) {
|
|
986
|
+
if (hasExceededDistance(delta, activationConstraint.tolerance)) return this.handleCancel();
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
if (isDistanceConstraint(activationConstraint)) {
|
|
990
|
+
if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) return this.handleCancel();
|
|
991
|
+
if (hasExceededDistance(delta, activationConstraint.distance)) return this.handleStart();
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
if (event.cancelable) event.preventDefault();
|
|
996
|
+
onMove(coordinates);
|
|
997
|
+
}
|
|
998
|
+
handleEnd() {
|
|
999
|
+
const { onEnd } = this.props;
|
|
1000
|
+
this.detach();
|
|
1001
|
+
onEnd();
|
|
1002
|
+
}
|
|
1003
|
+
handleCancel() {
|
|
1004
|
+
const { onCancel } = this.props;
|
|
1005
|
+
this.detach();
|
|
1006
|
+
onCancel();
|
|
1007
|
+
}
|
|
1008
|
+
handleKeydown(event) {
|
|
1009
|
+
if (event.code === "Escape") this.handleCancel();
|
|
1010
|
+
}
|
|
1011
|
+
removeTextSelection() {
|
|
1012
|
+
this.document.getSelection()?.removeAllRanges();
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
//#endregion
|
|
1016
|
+
//#region src/sensors/pointer/PointerSensor.ts
|
|
1017
|
+
const events$2 = {
|
|
1018
|
+
move: { name: "pointermove" },
|
|
1019
|
+
end: { name: "pointerup" }
|
|
1020
|
+
};
|
|
1021
|
+
var PointerSensor = class extends AbstractPointerSensor {
|
|
1022
|
+
constructor(props) {
|
|
1023
|
+
const { event } = props;
|
|
1024
|
+
const listenerTarget = getOwnerDocument(event.target);
|
|
1025
|
+
super(props, events$2, listenerTarget);
|
|
1026
|
+
}
|
|
1027
|
+
static activators = [{
|
|
1028
|
+
eventName: "onPointerDown",
|
|
1029
|
+
handler: ({ nativeEvent: event }, { onActivation }) => {
|
|
1030
|
+
if (!event.isPrimary || event.button !== 0) return false;
|
|
1031
|
+
onActivation?.({ event });
|
|
1032
|
+
return true;
|
|
1033
|
+
}
|
|
1034
|
+
}];
|
|
1035
|
+
};
|
|
1036
|
+
//#endregion
|
|
1037
|
+
//#region src/sensors/mouse/MouseSensor.ts
|
|
1038
|
+
const events$1 = {
|
|
1039
|
+
move: { name: "mousemove" },
|
|
1040
|
+
end: { name: "mouseup" }
|
|
1041
|
+
};
|
|
1042
|
+
var MouseSensor = class extends AbstractPointerSensor {
|
|
1043
|
+
constructor(props) {
|
|
1044
|
+
super(props, events$1, getOwnerDocument(props.event.target));
|
|
1045
|
+
}
|
|
1046
|
+
static activators = [{
|
|
1047
|
+
eventName: "onMouseDown",
|
|
1048
|
+
handler: ({ nativeEvent: event }, { onActivation }) => {
|
|
1049
|
+
if (event.button === 2) return false;
|
|
1050
|
+
onActivation?.({ event });
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
}];
|
|
1054
|
+
};
|
|
1055
|
+
//#endregion
|
|
1056
|
+
//#region src/sensors/touch/TouchSensor.ts
|
|
1057
|
+
const events = {
|
|
1058
|
+
move: { name: "touchmove" },
|
|
1059
|
+
end: { name: "touchend" }
|
|
1060
|
+
};
|
|
1061
|
+
var TouchSensor = class extends AbstractPointerSensor {
|
|
1062
|
+
constructor(props) {
|
|
1063
|
+
super(props, events);
|
|
1064
|
+
}
|
|
1065
|
+
static activators = [{
|
|
1066
|
+
eventName: "onTouchStart",
|
|
1067
|
+
handler: ({ nativeEvent: event }, { onActivation }) => {
|
|
1068
|
+
const { touches } = event;
|
|
1069
|
+
if (touches.length > 1) return false;
|
|
1070
|
+
onActivation?.({ event });
|
|
1071
|
+
return true;
|
|
1072
|
+
}
|
|
1073
|
+
}];
|
|
1074
|
+
static setup() {
|
|
1075
|
+
window.addEventListener(events.move.name, noop, {
|
|
1076
|
+
capture: false,
|
|
1077
|
+
passive: false
|
|
1078
|
+
});
|
|
1079
|
+
return function teardown() {
|
|
1080
|
+
window.removeEventListener(events.move.name, noop);
|
|
1081
|
+
};
|
|
1082
|
+
function noop() {}
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
//#endregion
|
|
1086
|
+
//#region src/hooks/utilities/useAutoScroller.ts
|
|
1087
|
+
let AutoScrollActivator = /* @__PURE__ */ function(AutoScrollActivator) {
|
|
1088
|
+
AutoScrollActivator[AutoScrollActivator["Pointer"] = 0] = "Pointer";
|
|
1089
|
+
AutoScrollActivator[AutoScrollActivator["DraggableRect"] = 1] = "DraggableRect";
|
|
1090
|
+
return AutoScrollActivator;
|
|
1091
|
+
}({});
|
|
1092
|
+
let TraversalOrder = /* @__PURE__ */ function(TraversalOrder) {
|
|
1093
|
+
TraversalOrder[TraversalOrder["TreeOrder"] = 0] = "TreeOrder";
|
|
1094
|
+
TraversalOrder[TraversalOrder["ReversedTreeOrder"] = 1] = "ReversedTreeOrder";
|
|
1095
|
+
return TraversalOrder;
|
|
1096
|
+
}({});
|
|
1097
|
+
function useAutoScroller({ acceleration, activator = 0, canScroll, draggingRect, enabled, interval = 5, order = 0, pointerCoordinates, scrollableAncestors, scrollableAncestorRects, delta, threshold }) {
|
|
1098
|
+
const scrollIntent = useScrollIntent({
|
|
1099
|
+
delta,
|
|
1100
|
+
disabled: !enabled
|
|
1101
|
+
});
|
|
1102
|
+
const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();
|
|
1103
|
+
const scrollSpeed = useRef({
|
|
1104
|
+
x: 0,
|
|
1105
|
+
y: 0
|
|
1106
|
+
});
|
|
1107
|
+
const scrollDirection = useRef({
|
|
1108
|
+
x: 0,
|
|
1109
|
+
y: 0
|
|
1110
|
+
});
|
|
1111
|
+
const rect = useMemo(() => {
|
|
1112
|
+
switch (activator) {
|
|
1113
|
+
case 0: return pointerCoordinates ? {
|
|
1114
|
+
top: pointerCoordinates.y,
|
|
1115
|
+
bottom: pointerCoordinates.y,
|
|
1116
|
+
left: pointerCoordinates.x,
|
|
1117
|
+
right: pointerCoordinates.x
|
|
1118
|
+
} : null;
|
|
1119
|
+
case 1: return draggingRect;
|
|
1120
|
+
}
|
|
1121
|
+
}, [
|
|
1122
|
+
activator,
|
|
1123
|
+
draggingRect,
|
|
1124
|
+
pointerCoordinates
|
|
1125
|
+
]);
|
|
1126
|
+
const scrollContainerRef = useRef(null);
|
|
1127
|
+
const autoScroll = useCallback(() => {
|
|
1128
|
+
const scrollContainer = scrollContainerRef.current;
|
|
1129
|
+
if (!scrollContainer) return;
|
|
1130
|
+
const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;
|
|
1131
|
+
const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;
|
|
1132
|
+
scrollContainer.scrollBy(Math.round(scrollLeft), Math.round(scrollTop));
|
|
1133
|
+
}, []);
|
|
1134
|
+
const sortedScrollableAncestors = useMemo(() => order === 0 ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);
|
|
1135
|
+
useEffect(() => {
|
|
1136
|
+
if (!enabled || !scrollableAncestors.length || !rect) {
|
|
1137
|
+
clearAutoScrollInterval();
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
for (const scrollContainer of sortedScrollableAncestors) {
|
|
1141
|
+
if (canScroll?.(scrollContainer) === false) continue;
|
|
1142
|
+
const scrollContainerRect = scrollableAncestorRects.find(({ element }) => element === scrollContainer)?.rect;
|
|
1143
|
+
if (!scrollContainerRect) continue;
|
|
1144
|
+
const { direction, speed } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);
|
|
1145
|
+
for (const axis of ["x", "y"]) if (!scrollIntent[axis][direction[axis]]) {
|
|
1146
|
+
speed[axis] = 0;
|
|
1147
|
+
direction[axis] = 0;
|
|
1148
|
+
}
|
|
1149
|
+
if (speed.x > 0 || speed.y > 0) {
|
|
1150
|
+
clearAutoScrollInterval();
|
|
1151
|
+
scrollContainerRef.current = scrollContainer;
|
|
1152
|
+
setAutoScrollInterval(autoScroll, interval);
|
|
1153
|
+
scrollSpeed.current = speed;
|
|
1154
|
+
scrollDirection.current = direction;
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
scrollSpeed.current = {
|
|
1159
|
+
x: 0,
|
|
1160
|
+
y: 0
|
|
1161
|
+
};
|
|
1162
|
+
scrollDirection.current = {
|
|
1163
|
+
x: 0,
|
|
1164
|
+
y: 0
|
|
1165
|
+
};
|
|
1166
|
+
clearAutoScrollInterval();
|
|
1167
|
+
}, [
|
|
1168
|
+
acceleration,
|
|
1169
|
+
autoScroll,
|
|
1170
|
+
canScroll,
|
|
1171
|
+
clearAutoScrollInterval,
|
|
1172
|
+
enabled,
|
|
1173
|
+
interval,
|
|
1174
|
+
JSON.stringify(rect),
|
|
1175
|
+
JSON.stringify(scrollIntent),
|
|
1176
|
+
setAutoScrollInterval,
|
|
1177
|
+
scrollableAncestors,
|
|
1178
|
+
sortedScrollableAncestors,
|
|
1179
|
+
scrollableAncestorRects,
|
|
1180
|
+
JSON.stringify(threshold)
|
|
1181
|
+
]);
|
|
1182
|
+
}
|
|
1183
|
+
const defaultScrollIntent = {
|
|
1184
|
+
x: {
|
|
1185
|
+
[-1]: false,
|
|
1186
|
+
[1]: false
|
|
1187
|
+
},
|
|
1188
|
+
y: {
|
|
1189
|
+
[-1]: false,
|
|
1190
|
+
[1]: false
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
function useScrollIntent({ delta, disabled }) {
|
|
1194
|
+
const previousDelta = usePrevious(delta);
|
|
1195
|
+
return useLazyMemo((previousIntent) => {
|
|
1196
|
+
if (disabled || !previousDelta || !previousIntent) return defaultScrollIntent;
|
|
1197
|
+
const direction = {
|
|
1198
|
+
x: Math.sign(delta.x - previousDelta.x),
|
|
1199
|
+
y: Math.sign(delta.y - previousDelta.y)
|
|
1200
|
+
};
|
|
1201
|
+
return {
|
|
1202
|
+
x: {
|
|
1203
|
+
[-1]: previousIntent.x[-1] || direction.x === -1,
|
|
1204
|
+
[1]: previousIntent.x[1] || direction.x === 1
|
|
1205
|
+
},
|
|
1206
|
+
y: {
|
|
1207
|
+
[-1]: previousIntent.y[-1] || direction.y === -1,
|
|
1208
|
+
[1]: previousIntent.y[1] || direction.y === 1
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
}, [
|
|
1212
|
+
disabled,
|
|
1213
|
+
delta,
|
|
1214
|
+
previousDelta
|
|
1215
|
+
]);
|
|
1216
|
+
}
|
|
1217
|
+
//#endregion
|
|
1218
|
+
//#region src/hooks/utilities/useCachedNode.ts
|
|
1219
|
+
function useCachedNode(draggableNodes, id) {
|
|
1220
|
+
const draggableNode = id !== null ? draggableNodes.get(id) : void 0;
|
|
1221
|
+
const node = draggableNode ? draggableNode.node.current : null;
|
|
1222
|
+
return useLazyMemo((cachedNode) => {
|
|
1223
|
+
if (id === null) return null;
|
|
1224
|
+
return node ?? cachedNode ?? null;
|
|
1225
|
+
}, [node, id]);
|
|
1226
|
+
}
|
|
1227
|
+
//#endregion
|
|
1228
|
+
//#region src/hooks/utilities/useCombineActivators.ts
|
|
1229
|
+
function useCombineActivators(sensors, getSyntheticHandler) {
|
|
1230
|
+
return useMemo(() => sensors.reduce((accumulator, sensor) => {
|
|
1231
|
+
const { sensor: Sensor } = sensor;
|
|
1232
|
+
const sensorActivators = Sensor.activators.map((activator) => ({
|
|
1233
|
+
eventName: activator.eventName,
|
|
1234
|
+
handler: getSyntheticHandler(activator.handler, sensor)
|
|
1235
|
+
}));
|
|
1236
|
+
return [...accumulator, ...sensorActivators];
|
|
1237
|
+
}, []), [sensors, getSyntheticHandler]);
|
|
1238
|
+
}
|
|
1239
|
+
//#endregion
|
|
1240
|
+
//#region src/hooks/utilities/useDroppableMeasuring.ts
|
|
1241
|
+
let MeasuringStrategy = /* @__PURE__ */ function(MeasuringStrategy) {
|
|
1242
|
+
MeasuringStrategy[MeasuringStrategy["Always"] = 0] = "Always";
|
|
1243
|
+
MeasuringStrategy[MeasuringStrategy["BeforeDragging"] = 1] = "BeforeDragging";
|
|
1244
|
+
MeasuringStrategy[MeasuringStrategy["WhileDragging"] = 2] = "WhileDragging";
|
|
1245
|
+
return MeasuringStrategy;
|
|
1246
|
+
}({});
|
|
1247
|
+
let MeasuringFrequency = /* @__PURE__ */ function(MeasuringFrequency) {
|
|
1248
|
+
MeasuringFrequency["Optimized"] = "optimized";
|
|
1249
|
+
return MeasuringFrequency;
|
|
1250
|
+
}({});
|
|
1251
|
+
const defaultValue$2 = /* @__PURE__ */ new Map();
|
|
1252
|
+
function useDroppableMeasuring(containers, { dragging, dependencies, config }) {
|
|
1253
|
+
const [queue, setQueue] = useState(null);
|
|
1254
|
+
const { frequency, measure, strategy } = config;
|
|
1255
|
+
const containersRef = useRef(containers);
|
|
1256
|
+
const disabled = isDisabled();
|
|
1257
|
+
const disabledRef = useLatestValue(disabled);
|
|
1258
|
+
const measureDroppableContainers = useCallback((ids = []) => {
|
|
1259
|
+
if (disabledRef.current) return;
|
|
1260
|
+
setQueue((value) => {
|
|
1261
|
+
if (value === null) return ids;
|
|
1262
|
+
return value.concat(ids.filter((id) => !value.includes(id)));
|
|
1263
|
+
});
|
|
1264
|
+
}, [disabledRef]);
|
|
1265
|
+
const timeoutId = useRef(null);
|
|
1266
|
+
const droppableRects = useLazyMemo((previousValue) => {
|
|
1267
|
+
if (disabled && !dragging) return defaultValue$2;
|
|
1268
|
+
if (!previousValue || previousValue === defaultValue$2 || containersRef.current !== containers || queue != null) {
|
|
1269
|
+
const map = /* @__PURE__ */ new Map();
|
|
1270
|
+
for (let container of containers) {
|
|
1271
|
+
if (!container) continue;
|
|
1272
|
+
if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {
|
|
1273
|
+
map.set(container.id, container.rect.current);
|
|
1274
|
+
continue;
|
|
1275
|
+
}
|
|
1276
|
+
const node = container.node.current;
|
|
1277
|
+
const rect = node ? new Rect(measure(node), node) : null;
|
|
1278
|
+
container.rect.current = rect;
|
|
1279
|
+
if (rect) map.set(container.id, rect);
|
|
1280
|
+
}
|
|
1281
|
+
return map;
|
|
1282
|
+
}
|
|
1283
|
+
return previousValue;
|
|
1284
|
+
}, [
|
|
1285
|
+
containers,
|
|
1286
|
+
queue,
|
|
1287
|
+
dragging,
|
|
1288
|
+
disabled,
|
|
1289
|
+
measure
|
|
1290
|
+
]);
|
|
1291
|
+
useEffect(() => {
|
|
1292
|
+
containersRef.current = containers;
|
|
1293
|
+
}, [containers]);
|
|
1294
|
+
useEffect(() => {
|
|
1295
|
+
if (disabled) return;
|
|
1296
|
+
measureDroppableContainers();
|
|
1297
|
+
}, [dragging, disabled]);
|
|
1298
|
+
useEffect(() => {
|
|
1299
|
+
if (queue && queue.length > 0) setQueue(null);
|
|
1300
|
+
}, [JSON.stringify(queue)]);
|
|
1301
|
+
useEffect(() => {
|
|
1302
|
+
if (disabled || typeof frequency !== "number" || timeoutId.current !== null) return;
|
|
1303
|
+
timeoutId.current = setTimeout(() => {
|
|
1304
|
+
measureDroppableContainers();
|
|
1305
|
+
timeoutId.current = null;
|
|
1306
|
+
}, frequency);
|
|
1307
|
+
}, [
|
|
1308
|
+
frequency,
|
|
1309
|
+
disabled,
|
|
1310
|
+
measureDroppableContainers,
|
|
1311
|
+
...dependencies
|
|
1312
|
+
]);
|
|
1313
|
+
return {
|
|
1314
|
+
droppableRects,
|
|
1315
|
+
measureDroppableContainers,
|
|
1316
|
+
measuringScheduled: queue != null
|
|
1317
|
+
};
|
|
1318
|
+
function isDisabled() {
|
|
1319
|
+
switch (strategy) {
|
|
1320
|
+
case 0: return false;
|
|
1321
|
+
case 1: return dragging;
|
|
1322
|
+
default: return !dragging;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
//#endregion
|
|
1327
|
+
//#region src/hooks/utilities/useInitialValue.ts
|
|
1328
|
+
function useInitialValue(value, computeFn) {
|
|
1329
|
+
return useLazyMemo((previousValue) => {
|
|
1330
|
+
if (!value) return null;
|
|
1331
|
+
if (previousValue) return previousValue;
|
|
1332
|
+
return typeof computeFn === "function" ? computeFn(value) : value;
|
|
1333
|
+
}, [computeFn, value]);
|
|
1334
|
+
}
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region src/hooks/utilities/useInitialRect.ts
|
|
1337
|
+
function useInitialRect(node, measure) {
|
|
1338
|
+
return useInitialValue(node, measure);
|
|
1339
|
+
}
|
|
1340
|
+
//#endregion
|
|
1341
|
+
//#region src/hooks/utilities/useMutationObserver.ts
|
|
1342
|
+
/**
|
|
1343
|
+
* Returns a new MutationObserver instance.
|
|
1344
|
+
* If `MutationObserver` is undefined in the execution environment, returns `undefined`.
|
|
1345
|
+
*/
|
|
1346
|
+
function useMutationObserver({ callback, disabled }) {
|
|
1347
|
+
const handleMutations = useEvent(callback);
|
|
1348
|
+
const mutationObserver = useMemo(() => {
|
|
1349
|
+
if (disabled || typeof window === "undefined" || typeof window.MutationObserver === "undefined") return;
|
|
1350
|
+
const { MutationObserver } = window;
|
|
1351
|
+
return new MutationObserver(handleMutations);
|
|
1352
|
+
}, [handleMutations, disabled]);
|
|
1353
|
+
useEffect(() => {
|
|
1354
|
+
return () => mutationObserver?.disconnect();
|
|
1355
|
+
}, [mutationObserver]);
|
|
1356
|
+
return mutationObserver;
|
|
1357
|
+
}
|
|
1358
|
+
//#endregion
|
|
1359
|
+
//#region src/hooks/utilities/useResizeObserver.ts
|
|
1360
|
+
/**
|
|
1361
|
+
* Returns a new ResizeObserver instance bound to the `onResize` callback.
|
|
1362
|
+
* If `ResizeObserver` is undefined in the execution environment, returns `undefined`.
|
|
1363
|
+
*/
|
|
1364
|
+
function useResizeObserver({ callback, disabled }) {
|
|
1365
|
+
const handleResize = useEvent(callback);
|
|
1366
|
+
const resizeObserver = useMemo(() => {
|
|
1367
|
+
if (disabled || typeof window === "undefined" || typeof window.ResizeObserver === "undefined") return;
|
|
1368
|
+
const { ResizeObserver } = window;
|
|
1369
|
+
return new ResizeObserver(handleResize);
|
|
1370
|
+
}, [disabled]);
|
|
1371
|
+
useEffect(() => {
|
|
1372
|
+
return () => resizeObserver?.disconnect();
|
|
1373
|
+
}, [resizeObserver]);
|
|
1374
|
+
return resizeObserver;
|
|
1375
|
+
}
|
|
1376
|
+
//#endregion
|
|
1377
|
+
//#region src/hooks/utilities/useRect.ts
|
|
1378
|
+
function defaultMeasure(element) {
|
|
1379
|
+
return new Rect(getClientRect(element), element);
|
|
1380
|
+
}
|
|
1381
|
+
function useRect(element, measure = defaultMeasure, fallbackRect) {
|
|
1382
|
+
const [rect, measureRect] = useReducer(reducer, null);
|
|
1383
|
+
const mutationObserver = useMutationObserver({ callback(records) {
|
|
1384
|
+
if (!element) return;
|
|
1385
|
+
for (const record of records) {
|
|
1386
|
+
const { type, target } = record;
|
|
1387
|
+
if (type === "childList" && target instanceof HTMLElement && target.contains(element)) {
|
|
1388
|
+
measureRect();
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
} });
|
|
1393
|
+
const resizeObserver = useResizeObserver({ callback: measureRect });
|
|
1394
|
+
useIsomorphicLayoutEffect(() => {
|
|
1395
|
+
measureRect();
|
|
1396
|
+
if (element) {
|
|
1397
|
+
resizeObserver?.observe(element);
|
|
1398
|
+
mutationObserver?.observe(document.body, {
|
|
1399
|
+
childList: true,
|
|
1400
|
+
subtree: true
|
|
1401
|
+
});
|
|
1402
|
+
} else {
|
|
1403
|
+
resizeObserver?.disconnect();
|
|
1404
|
+
mutationObserver?.disconnect();
|
|
1405
|
+
}
|
|
1406
|
+
}, [element]);
|
|
1407
|
+
return rect;
|
|
1408
|
+
function reducer(currentRect) {
|
|
1409
|
+
if (!element) return null;
|
|
1410
|
+
if (element.isConnected === false) return currentRect ?? fallbackRect ?? null;
|
|
1411
|
+
const newRect = measure(element);
|
|
1412
|
+
if (JSON.stringify(currentRect) === JSON.stringify(newRect)) return currentRect;
|
|
1413
|
+
return newRect;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
//#endregion
|
|
1417
|
+
//#region src/hooks/utilities/useRectDelta.ts
|
|
1418
|
+
function useRectDelta(rect) {
|
|
1419
|
+
return getRectDelta(rect, useInitialValue(rect));
|
|
1420
|
+
}
|
|
1421
|
+
//#endregion
|
|
1422
|
+
//#region src/hooks/utilities/useScrollableAncestors.ts
|
|
1423
|
+
const defaultValue$1 = [];
|
|
1424
|
+
function useScrollableAncestors(node) {
|
|
1425
|
+
const previousNode = useRef(node);
|
|
1426
|
+
const ancestors = useLazyMemo((previousValue) => {
|
|
1427
|
+
if (!node) return defaultValue$1;
|
|
1428
|
+
if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) return previousValue;
|
|
1429
|
+
return getScrollableAncestors(node);
|
|
1430
|
+
}, [node]);
|
|
1431
|
+
useEffect(() => {
|
|
1432
|
+
previousNode.current = node;
|
|
1433
|
+
}, [node]);
|
|
1434
|
+
return ancestors;
|
|
1435
|
+
}
|
|
1436
|
+
//#endregion
|
|
1437
|
+
//#region src/hooks/utilities/useScrollOffsets.ts
|
|
1438
|
+
function useScrollOffsets(elements) {
|
|
1439
|
+
const [scrollCoordinates, setScrollCoordinates] = useState(null);
|
|
1440
|
+
const prevElements = useRef(elements);
|
|
1441
|
+
const handleScroll = useCallback((event) => {
|
|
1442
|
+
const scrollingElement = getScrollableElement(event.target);
|
|
1443
|
+
if (!scrollingElement) return;
|
|
1444
|
+
setScrollCoordinates((scrollCoordinates) => {
|
|
1445
|
+
if (!scrollCoordinates) return null;
|
|
1446
|
+
scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));
|
|
1447
|
+
return new Map(scrollCoordinates);
|
|
1448
|
+
});
|
|
1449
|
+
}, []);
|
|
1450
|
+
useEffect(() => {
|
|
1451
|
+
const previousElements = prevElements.current;
|
|
1452
|
+
if (elements !== previousElements) {
|
|
1453
|
+
cleanup(previousElements);
|
|
1454
|
+
const entries = elements.map((element) => {
|
|
1455
|
+
const scrollableElement = getScrollableElement(element);
|
|
1456
|
+
if (scrollableElement) {
|
|
1457
|
+
scrollableElement.addEventListener("scroll", handleScroll, { passive: true });
|
|
1458
|
+
return [scrollableElement, getScrollCoordinates(scrollableElement)];
|
|
1459
|
+
}
|
|
1460
|
+
return null;
|
|
1461
|
+
}).filter((entry) => entry != null);
|
|
1462
|
+
setScrollCoordinates(entries.length ? new Map(entries) : null);
|
|
1463
|
+
prevElements.current = elements;
|
|
1464
|
+
}
|
|
1465
|
+
return () => {
|
|
1466
|
+
cleanup(elements);
|
|
1467
|
+
cleanup(previousElements);
|
|
1468
|
+
};
|
|
1469
|
+
function cleanup(elements) {
|
|
1470
|
+
elements.forEach((element) => {
|
|
1471
|
+
getScrollableElement(element)?.removeEventListener("scroll", handleScroll);
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
}, [handleScroll, elements]);
|
|
1475
|
+
return useMemo(() => {
|
|
1476
|
+
if (elements.length) return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);
|
|
1477
|
+
return defaultCoordinates;
|
|
1478
|
+
}, [elements, scrollCoordinates]);
|
|
1479
|
+
}
|
|
1480
|
+
//#endregion
|
|
1481
|
+
//#region src/hooks/utilities/useScrollOffsetsDelta.ts
|
|
1482
|
+
function useScrollOffsetsDelta(scrollOffsets, dependencies = []) {
|
|
1483
|
+
const initialScrollOffsets = useRef(null);
|
|
1484
|
+
useEffect(() => {
|
|
1485
|
+
initialScrollOffsets.current = null;
|
|
1486
|
+
}, dependencies);
|
|
1487
|
+
useEffect(() => {
|
|
1488
|
+
const hasScrollOffsets = scrollOffsets !== defaultCoordinates;
|
|
1489
|
+
if (hasScrollOffsets && !initialScrollOffsets.current) initialScrollOffsets.current = scrollOffsets;
|
|
1490
|
+
if (!hasScrollOffsets && initialScrollOffsets.current) initialScrollOffsets.current = null;
|
|
1491
|
+
}, [scrollOffsets]);
|
|
1492
|
+
return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;
|
|
1493
|
+
}
|
|
1494
|
+
//#endregion
|
|
1495
|
+
//#region src/hooks/utilities/useSensorSetup.ts
|
|
1496
|
+
function useSensorSetup(sensors) {
|
|
1497
|
+
useEffect(() => {
|
|
1498
|
+
if (!canUseDOM) return;
|
|
1499
|
+
const teardownFns = sensors.map(({ sensor }) => sensor.setup?.());
|
|
1500
|
+
return () => {
|
|
1501
|
+
for (const teardown of teardownFns) teardown?.();
|
|
1502
|
+
};
|
|
1503
|
+
}, sensors.map(({ sensor }) => sensor));
|
|
1504
|
+
}
|
|
1505
|
+
//#endregion
|
|
1506
|
+
//#region src/hooks/utilities/useSyntheticListeners.ts
|
|
1507
|
+
function useSyntheticListeners(listeners, id) {
|
|
1508
|
+
return useMemo(() => {
|
|
1509
|
+
return listeners.reduce((acc, { eventName, handler }) => {
|
|
1510
|
+
acc[eventName] = (event) => {
|
|
1511
|
+
handler(event, id);
|
|
1512
|
+
};
|
|
1513
|
+
return acc;
|
|
1514
|
+
}, {});
|
|
1515
|
+
}, [listeners, id]);
|
|
1516
|
+
}
|
|
1517
|
+
//#endregion
|
|
1518
|
+
//#region src/hooks/utilities/useWindowRect.ts
|
|
1519
|
+
function useWindowRect(element) {
|
|
1520
|
+
return useMemo(() => element ? getWindowClientRect(element) : null, [element]);
|
|
1521
|
+
}
|
|
1522
|
+
//#endregion
|
|
1523
|
+
//#region src/hooks/utilities/useRects.ts
|
|
1524
|
+
const defaultValue = [];
|
|
1525
|
+
function useRects(elements, measure = getClientRect) {
|
|
1526
|
+
const [firstElement] = elements;
|
|
1527
|
+
const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);
|
|
1528
|
+
const [rects, measureRects] = useReducer(reducer, defaultValue);
|
|
1529
|
+
const resizeObserver = useResizeObserver({ callback: measureRects });
|
|
1530
|
+
if (elements.length > 0 && rects === defaultValue) measureRects();
|
|
1531
|
+
useIsomorphicLayoutEffect(() => {
|
|
1532
|
+
if (elements.length) elements.forEach((element) => resizeObserver?.observe(element));
|
|
1533
|
+
else {
|
|
1534
|
+
resizeObserver?.disconnect();
|
|
1535
|
+
measureRects();
|
|
1536
|
+
}
|
|
1537
|
+
}, [elements]);
|
|
1538
|
+
return rects;
|
|
1539
|
+
function reducer() {
|
|
1540
|
+
if (!elements.length) return defaultValue;
|
|
1541
|
+
return elements.map((element) => isDocumentScrollingElement(element) ? {
|
|
1542
|
+
rect: windowRect,
|
|
1543
|
+
element
|
|
1544
|
+
} : {
|
|
1545
|
+
rect: new Rect(measure(element), element),
|
|
1546
|
+
element
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
//#endregion
|
|
1551
|
+
//#region src/utilities/nodes/getMeasurableNode.ts
|
|
1552
|
+
function getMeasurableNode(node) {
|
|
1553
|
+
if (!node) return null;
|
|
1554
|
+
if (node.children.length > 1) return node;
|
|
1555
|
+
const firstChild = node.children[0];
|
|
1556
|
+
return isHTMLElement(firstChild) ? firstChild : node;
|
|
1557
|
+
}
|
|
1558
|
+
//#endregion
|
|
1559
|
+
//#region src/hooks/utilities/useDragOverlayMeasuring.ts
|
|
1560
|
+
function useDragOverlayMeasuring({ measure }) {
|
|
1561
|
+
const [rect, setRect] = useState(null);
|
|
1562
|
+
const resizeObserver = useResizeObserver({ callback: useCallback((entries) => {
|
|
1563
|
+
for (const { target } of entries) if (isHTMLElement(target)) {
|
|
1564
|
+
setRect((rect) => {
|
|
1565
|
+
const newRect = measure(target);
|
|
1566
|
+
return rect ? {
|
|
1567
|
+
...rect,
|
|
1568
|
+
width: newRect.width,
|
|
1569
|
+
height: newRect.height
|
|
1570
|
+
} : newRect;
|
|
1571
|
+
});
|
|
1572
|
+
break;
|
|
1573
|
+
}
|
|
1574
|
+
}, [measure]) });
|
|
1575
|
+
const handleNodeChange = useCallback((element) => {
|
|
1576
|
+
const node = getMeasurableNode(element);
|
|
1577
|
+
resizeObserver?.disconnect();
|
|
1578
|
+
if (node) resizeObserver?.observe(node);
|
|
1579
|
+
setRect(node ? measure(node) : null);
|
|
1580
|
+
}, [measure, resizeObserver]);
|
|
1581
|
+
const [nodeRef, setRef] = useNodeRef(handleNodeChange);
|
|
1582
|
+
return useMemo(() => ({
|
|
1583
|
+
nodeRef,
|
|
1584
|
+
rect,
|
|
1585
|
+
setRef
|
|
1586
|
+
}), [
|
|
1587
|
+
rect,
|
|
1588
|
+
nodeRef,
|
|
1589
|
+
setRef
|
|
1590
|
+
]);
|
|
1591
|
+
}
|
|
1592
|
+
//#endregion
|
|
1593
|
+
//#region src/components/DndContext/defaults.ts
|
|
1594
|
+
const defaultSensors = [{
|
|
1595
|
+
sensor: PointerSensor,
|
|
1596
|
+
options: {}
|
|
1597
|
+
}, {
|
|
1598
|
+
sensor: KeyboardSensor,
|
|
1599
|
+
options: {}
|
|
1600
|
+
}];
|
|
1601
|
+
const defaultData = { current: {} };
|
|
1602
|
+
const defaultMeasuringConfiguration = {
|
|
1603
|
+
draggable: { measure: getTransformAgnosticClientRect },
|
|
1604
|
+
droppable: {
|
|
1605
|
+
measure: getTransformAgnosticClientRect,
|
|
1606
|
+
strategy: 2,
|
|
1607
|
+
frequency: "optimized"
|
|
1608
|
+
},
|
|
1609
|
+
dragOverlay: { measure: getClientRect }
|
|
1610
|
+
};
|
|
1611
|
+
//#endregion
|
|
1612
|
+
//#region src/store/constructors.ts
|
|
1613
|
+
var DroppableContainersMap = class extends Map {
|
|
1614
|
+
get(id) {
|
|
1615
|
+
return id != null ? super.get(id) ?? void 0 : void 0;
|
|
1616
|
+
}
|
|
1617
|
+
toArray() {
|
|
1618
|
+
return Array.from(this.values());
|
|
1619
|
+
}
|
|
1620
|
+
getEnabled() {
|
|
1621
|
+
return this.toArray().filter(({ disabled }) => !disabled);
|
|
1622
|
+
}
|
|
1623
|
+
getNodeFor(id) {
|
|
1624
|
+
return this.get(id)?.node.current ?? void 0;
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
//#endregion
|
|
1628
|
+
//#region src/store/context.ts
|
|
1629
|
+
const defaultPublicContext = {
|
|
1630
|
+
activatorEvent: null,
|
|
1631
|
+
active: null,
|
|
1632
|
+
activeNode: null,
|
|
1633
|
+
activeNodeRect: null,
|
|
1634
|
+
collisions: null,
|
|
1635
|
+
containerNodeRect: null,
|
|
1636
|
+
draggableNodes: /* @__PURE__ */ new Map(),
|
|
1637
|
+
droppableRects: /* @__PURE__ */ new Map(),
|
|
1638
|
+
droppableContainers: new DroppableContainersMap(),
|
|
1639
|
+
over: null,
|
|
1640
|
+
dragOverlay: {
|
|
1641
|
+
nodeRef: { current: null },
|
|
1642
|
+
rect: null,
|
|
1643
|
+
setRef: noop
|
|
1644
|
+
},
|
|
1645
|
+
scrollableAncestors: [],
|
|
1646
|
+
scrollableAncestorRects: [],
|
|
1647
|
+
measuringConfiguration: defaultMeasuringConfiguration,
|
|
1648
|
+
measureDroppableContainers: noop,
|
|
1649
|
+
windowRect: null,
|
|
1650
|
+
measuringScheduled: false
|
|
1651
|
+
};
|
|
1652
|
+
const defaultInternalContext = {
|
|
1653
|
+
activatorEvent: null,
|
|
1654
|
+
activators: [],
|
|
1655
|
+
active: null,
|
|
1656
|
+
activeNodeRect: null,
|
|
1657
|
+
ariaDescribedById: { draggable: "" },
|
|
1658
|
+
dispatch: noop,
|
|
1659
|
+
draggableNodes: /* @__PURE__ */ new Map(),
|
|
1660
|
+
over: null,
|
|
1661
|
+
measureDroppableContainers: noop
|
|
1662
|
+
};
|
|
1663
|
+
const InternalContext = createContext(defaultInternalContext);
|
|
1664
|
+
const PublicContext = createContext(defaultPublicContext);
|
|
1665
|
+
//#endregion
|
|
1666
|
+
//#region src/store/reducer.ts
|
|
1667
|
+
function getInitialState() {
|
|
1668
|
+
return {
|
|
1669
|
+
draggable: {
|
|
1670
|
+
active: null,
|
|
1671
|
+
initialCoordinates: {
|
|
1672
|
+
x: 0,
|
|
1673
|
+
y: 0
|
|
1674
|
+
},
|
|
1675
|
+
nodes: /* @__PURE__ */ new Map(),
|
|
1676
|
+
translate: {
|
|
1677
|
+
x: 0,
|
|
1678
|
+
y: 0
|
|
1679
|
+
}
|
|
1680
|
+
},
|
|
1681
|
+
droppable: { containers: new DroppableContainersMap() }
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
function reducer(state, action) {
|
|
1685
|
+
switch (action.type) {
|
|
1686
|
+
case "dragStart": return {
|
|
1687
|
+
...state,
|
|
1688
|
+
draggable: {
|
|
1689
|
+
...state.draggable,
|
|
1690
|
+
initialCoordinates: action.initialCoordinates,
|
|
1691
|
+
active: action.active
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
case "dragMove":
|
|
1695
|
+
if (!state.draggable.active) return state;
|
|
1696
|
+
return {
|
|
1697
|
+
...state,
|
|
1698
|
+
draggable: {
|
|
1699
|
+
...state.draggable,
|
|
1700
|
+
translate: {
|
|
1701
|
+
x: action.coordinates.x - state.draggable.initialCoordinates.x,
|
|
1702
|
+
y: action.coordinates.y - state.draggable.initialCoordinates.y
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
case "dragEnd":
|
|
1707
|
+
case "dragCancel": return {
|
|
1708
|
+
...state,
|
|
1709
|
+
draggable: {
|
|
1710
|
+
...state.draggable,
|
|
1711
|
+
active: null,
|
|
1712
|
+
initialCoordinates: {
|
|
1713
|
+
x: 0,
|
|
1714
|
+
y: 0
|
|
1715
|
+
},
|
|
1716
|
+
translate: {
|
|
1717
|
+
x: 0,
|
|
1718
|
+
y: 0
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
case "registerDroppable": {
|
|
1723
|
+
const { element } = action;
|
|
1724
|
+
const { id } = element;
|
|
1725
|
+
const containers = new DroppableContainersMap(state.droppable.containers);
|
|
1726
|
+
containers.set(id, element);
|
|
1727
|
+
return {
|
|
1728
|
+
...state,
|
|
1729
|
+
droppable: {
|
|
1730
|
+
...state.droppable,
|
|
1731
|
+
containers
|
|
1732
|
+
}
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
case "setDroppableDisabled": {
|
|
1736
|
+
const { id, key, disabled } = action;
|
|
1737
|
+
const element = state.droppable.containers.get(id);
|
|
1738
|
+
if (!element || key !== element.key) return state;
|
|
1739
|
+
const containers = new DroppableContainersMap(state.droppable.containers);
|
|
1740
|
+
containers.set(id, {
|
|
1741
|
+
...element,
|
|
1742
|
+
disabled
|
|
1743
|
+
});
|
|
1744
|
+
return {
|
|
1745
|
+
...state,
|
|
1746
|
+
droppable: {
|
|
1747
|
+
...state.droppable,
|
|
1748
|
+
containers
|
|
1749
|
+
}
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
case "unregisterDroppable": {
|
|
1753
|
+
const { id, key } = action;
|
|
1754
|
+
const element = state.droppable.containers.get(id);
|
|
1755
|
+
if (!element || key !== element.key) return state;
|
|
1756
|
+
const containers = new DroppableContainersMap(state.droppable.containers);
|
|
1757
|
+
containers.delete(id);
|
|
1758
|
+
return {
|
|
1759
|
+
...state,
|
|
1760
|
+
droppable: {
|
|
1761
|
+
...state.droppable,
|
|
1762
|
+
containers
|
|
1763
|
+
}
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
default: return state;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
//#endregion
|
|
1770
|
+
//#region src/components/Accessibility/components/RestoreFocus.tsx
|
|
1771
|
+
function RestoreFocus({ disabled }) {
|
|
1772
|
+
const { active, activatorEvent, draggableNodes } = useContext(InternalContext);
|
|
1773
|
+
const previousActivatorEvent = usePrevious(activatorEvent);
|
|
1774
|
+
const previousActiveId = usePrevious(active?.id);
|
|
1775
|
+
useEffect(() => {
|
|
1776
|
+
if (disabled) return;
|
|
1777
|
+
if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {
|
|
1778
|
+
if (!isKeyboardEvent(previousActivatorEvent)) return;
|
|
1779
|
+
if (document.activeElement === previousActivatorEvent.target) return;
|
|
1780
|
+
const draggableNode = draggableNodes.get(previousActiveId);
|
|
1781
|
+
if (!draggableNode) return;
|
|
1782
|
+
const { activatorNode, node } = draggableNode;
|
|
1783
|
+
if (!activatorNode.current && !node.current) return;
|
|
1784
|
+
requestAnimationFrame(() => {
|
|
1785
|
+
for (const element of [activatorNode.current, node.current]) {
|
|
1786
|
+
if (!element) continue;
|
|
1787
|
+
const focusableNode = findFirstFocusableNode(element);
|
|
1788
|
+
if (focusableNode) {
|
|
1789
|
+
focusableNode.focus();
|
|
1790
|
+
break;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1795
|
+
}, [
|
|
1796
|
+
activatorEvent,
|
|
1797
|
+
disabled,
|
|
1798
|
+
draggableNodes,
|
|
1799
|
+
previousActiveId,
|
|
1800
|
+
previousActivatorEvent
|
|
1801
|
+
]);
|
|
1802
|
+
return null;
|
|
1803
|
+
}
|
|
1804
|
+
//#endregion
|
|
1805
|
+
//#region src/modifiers/applyModifiers.ts
|
|
1806
|
+
function applyModifiers(modifiers, { transform, ...args }) {
|
|
1807
|
+
return modifiers?.length ? modifiers.reduce((accumulator, modifier) => {
|
|
1808
|
+
return modifier({
|
|
1809
|
+
transform: accumulator,
|
|
1810
|
+
...args
|
|
1811
|
+
});
|
|
1812
|
+
}, transform) : transform;
|
|
1813
|
+
}
|
|
1814
|
+
//#endregion
|
|
1815
|
+
//#region src/components/DndContext/hooks/useMeasuringConfiguration.ts
|
|
1816
|
+
function useMeasuringConfiguration(config) {
|
|
1817
|
+
return useMemo(() => ({
|
|
1818
|
+
draggable: {
|
|
1819
|
+
...defaultMeasuringConfiguration.draggable,
|
|
1820
|
+
...config?.draggable
|
|
1821
|
+
},
|
|
1822
|
+
droppable: {
|
|
1823
|
+
...defaultMeasuringConfiguration.droppable,
|
|
1824
|
+
...config?.droppable
|
|
1825
|
+
},
|
|
1826
|
+
dragOverlay: {
|
|
1827
|
+
...defaultMeasuringConfiguration.dragOverlay,
|
|
1828
|
+
...config?.dragOverlay
|
|
1829
|
+
}
|
|
1830
|
+
}), [
|
|
1831
|
+
config?.draggable,
|
|
1832
|
+
config?.droppable,
|
|
1833
|
+
config?.dragOverlay
|
|
1834
|
+
]);
|
|
1835
|
+
}
|
|
1836
|
+
//#endregion
|
|
1837
|
+
//#region src/components/DndContext/hooks/useLayoutShiftScrollCompensation.ts
|
|
1838
|
+
function useLayoutShiftScrollCompensation({ activeNode, measure, initialRect, config = true }) {
|
|
1839
|
+
const initialized = useRef(false);
|
|
1840
|
+
const { x, y } = typeof config === "boolean" ? {
|
|
1841
|
+
x: config,
|
|
1842
|
+
y: config
|
|
1843
|
+
} : config;
|
|
1844
|
+
useIsomorphicLayoutEffect(() => {
|
|
1845
|
+
if (!x && !y || !activeNode) {
|
|
1846
|
+
initialized.current = false;
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
if (initialized.current || !initialRect) return;
|
|
1850
|
+
const node = activeNode?.node.current;
|
|
1851
|
+
if (!node || node.isConnected === false) return;
|
|
1852
|
+
const rectDelta = getRectDelta(measure(node), initialRect);
|
|
1853
|
+
if (!x) rectDelta.x = 0;
|
|
1854
|
+
if (!y) rectDelta.y = 0;
|
|
1855
|
+
initialized.current = true;
|
|
1856
|
+
if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {
|
|
1857
|
+
const firstScrollableAncestor = getFirstScrollableAncestor(node);
|
|
1858
|
+
if (firstScrollableAncestor) firstScrollableAncestor.scrollBy({
|
|
1859
|
+
top: rectDelta.y,
|
|
1860
|
+
left: rectDelta.x
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
}, [
|
|
1864
|
+
activeNode,
|
|
1865
|
+
x,
|
|
1866
|
+
y,
|
|
1867
|
+
initialRect,
|
|
1868
|
+
measure
|
|
1869
|
+
]);
|
|
1870
|
+
}
|
|
1871
|
+
//#endregion
|
|
1872
|
+
//#region src/components/DndContext/DndContext.tsx
|
|
1873
|
+
const ActiveDraggableContext = createContext({
|
|
1874
|
+
...defaultCoordinates,
|
|
1875
|
+
scaleX: 1,
|
|
1876
|
+
scaleY: 1
|
|
1877
|
+
});
|
|
1878
|
+
const DndContext = memo(function DndContext({ id, accessibility, autoScroll = true, children, sensors = defaultSensors, collisionDetection = rectIntersection, measuring, modifiers, ...props }) {
|
|
1879
|
+
const [state, dispatch] = useReducer(reducer, void 0, getInitialState);
|
|
1880
|
+
const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();
|
|
1881
|
+
const [status, setStatus] = useState(0);
|
|
1882
|
+
const isInitialized = status === 2;
|
|
1883
|
+
const { draggable: { active: activeId, nodes: draggableNodes, translate }, droppable: { containers: droppableContainers } } = state;
|
|
1884
|
+
const node = activeId ? draggableNodes.get(activeId) : null;
|
|
1885
|
+
const activeRects = useRef({
|
|
1886
|
+
initial: null,
|
|
1887
|
+
translated: null
|
|
1888
|
+
});
|
|
1889
|
+
const active = useMemo(() => activeId != null ? {
|
|
1890
|
+
id: activeId,
|
|
1891
|
+
data: node?.data ?? defaultData,
|
|
1892
|
+
rect: activeRects
|
|
1893
|
+
} : null, [activeId, node]);
|
|
1894
|
+
const activeRef = useRef(null);
|
|
1895
|
+
const [activeSensor, setActiveSensor] = useState(null);
|
|
1896
|
+
const [activatorEvent, setActivatorEvent] = useState(null);
|
|
1897
|
+
const latestProps = useLatestValue(props, Object.values(props));
|
|
1898
|
+
const draggableDescribedById = useUniqueId(`DndDescribedBy`, id);
|
|
1899
|
+
const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);
|
|
1900
|
+
const measuringConfiguration = useMeasuringConfiguration(measuring);
|
|
1901
|
+
const { droppableRects, measureDroppableContainers, measuringScheduled } = useDroppableMeasuring(enabledDroppableContainers, {
|
|
1902
|
+
dragging: isInitialized,
|
|
1903
|
+
dependencies: [translate.x, translate.y],
|
|
1904
|
+
config: measuringConfiguration.droppable
|
|
1905
|
+
});
|
|
1906
|
+
const activeNode = useCachedNode(draggableNodes, activeId);
|
|
1907
|
+
const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);
|
|
1908
|
+
const autoScrollOptions = getAutoScrollerOptions();
|
|
1909
|
+
const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);
|
|
1910
|
+
useLayoutShiftScrollCompensation({
|
|
1911
|
+
activeNode: activeId ? draggableNodes.get(activeId) : null,
|
|
1912
|
+
config: autoScrollOptions.layoutShiftCompensation,
|
|
1913
|
+
initialRect: initialActiveNodeRect,
|
|
1914
|
+
measure: measuringConfiguration.draggable.measure
|
|
1915
|
+
});
|
|
1916
|
+
const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);
|
|
1917
|
+
const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);
|
|
1918
|
+
const sensorContext = useRef({
|
|
1919
|
+
activatorEvent: null,
|
|
1920
|
+
active: null,
|
|
1921
|
+
activeNode,
|
|
1922
|
+
collisionRect: null,
|
|
1923
|
+
collisions: null,
|
|
1924
|
+
droppableRects,
|
|
1925
|
+
draggableNodes,
|
|
1926
|
+
draggingNode: null,
|
|
1927
|
+
draggingNodeRect: null,
|
|
1928
|
+
droppableContainers,
|
|
1929
|
+
over: null,
|
|
1930
|
+
scrollableAncestors: [],
|
|
1931
|
+
scrollAdjustedTranslate: null
|
|
1932
|
+
});
|
|
1933
|
+
const overNode = droppableContainers.getNodeFor(sensorContext.current.over?.id);
|
|
1934
|
+
const dragOverlay = useDragOverlayMeasuring({ measure: measuringConfiguration.dragOverlay.measure });
|
|
1935
|
+
const draggingNode = dragOverlay.nodeRef.current ?? activeNode;
|
|
1936
|
+
const draggingNodeRect = isInitialized ? dragOverlay.rect ?? activeNodeRect : null;
|
|
1937
|
+
const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect);
|
|
1938
|
+
const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect);
|
|
1939
|
+
const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null);
|
|
1940
|
+
const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode ?? activeNode : null);
|
|
1941
|
+
const scrollableAncestorRects = useRects(scrollableAncestors);
|
|
1942
|
+
const scrollableAncestorRectsRects = useMemo(() => scrollableAncestorRects.map(({ rect }) => rect), [scrollableAncestorRects]);
|
|
1943
|
+
const modifiedTranslate = applyModifiers(modifiers, {
|
|
1944
|
+
transform: {
|
|
1945
|
+
x: translate.x - nodeRectDelta.x,
|
|
1946
|
+
y: translate.y - nodeRectDelta.y,
|
|
1947
|
+
scaleX: 1,
|
|
1948
|
+
scaleY: 1
|
|
1949
|
+
},
|
|
1950
|
+
activatorEvent,
|
|
1951
|
+
active,
|
|
1952
|
+
activeNodeRect,
|
|
1953
|
+
containerNodeRect,
|
|
1954
|
+
draggingNodeRect,
|
|
1955
|
+
over: sensorContext.current.over,
|
|
1956
|
+
overlayNodeRect: dragOverlay.rect,
|
|
1957
|
+
scrollableAncestors,
|
|
1958
|
+
scrollableAncestorRects: scrollableAncestorRectsRects,
|
|
1959
|
+
windowRect
|
|
1960
|
+
});
|
|
1961
|
+
const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;
|
|
1962
|
+
const scrollOffsets = useScrollOffsets(scrollableAncestors);
|
|
1963
|
+
const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets);
|
|
1964
|
+
const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);
|
|
1965
|
+
const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);
|
|
1966
|
+
const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;
|
|
1967
|
+
const collisions = active && collisionRect ? collisionDetection({
|
|
1968
|
+
active,
|
|
1969
|
+
collisionRect,
|
|
1970
|
+
droppableRects,
|
|
1971
|
+
droppableContainers: enabledDroppableContainers,
|
|
1972
|
+
pointerCoordinates
|
|
1973
|
+
}) : null;
|
|
1974
|
+
const overId = getFirstCollision(collisions, "id");
|
|
1975
|
+
const [over, setOver] = useState(null);
|
|
1976
|
+
const transform = adjustScale(usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta), over?.rect ?? null, activeNodeRect);
|
|
1977
|
+
const instantiateSensor = useCallback((event, { sensor: Sensor, options }) => {
|
|
1978
|
+
if (activeRef.current == null) return;
|
|
1979
|
+
const activeNode = draggableNodes.get(activeRef.current);
|
|
1980
|
+
if (!activeNode) return;
|
|
1981
|
+
const activatorEvent = event.nativeEvent;
|
|
1982
|
+
const sensorInstance = new Sensor({
|
|
1983
|
+
active: activeRef.current,
|
|
1984
|
+
activeNode,
|
|
1985
|
+
event: activatorEvent,
|
|
1986
|
+
options,
|
|
1987
|
+
context: sensorContext,
|
|
1988
|
+
onStart(initialCoordinates) {
|
|
1989
|
+
const id = activeRef.current;
|
|
1990
|
+
if (id == null) return;
|
|
1991
|
+
const draggableNode = draggableNodes.get(id);
|
|
1992
|
+
if (!draggableNode) return;
|
|
1993
|
+
const { onDragStart } = latestProps.current;
|
|
1994
|
+
const event = { active: {
|
|
1995
|
+
id,
|
|
1996
|
+
data: draggableNode.data,
|
|
1997
|
+
rect: activeRects
|
|
1998
|
+
} };
|
|
1999
|
+
onDragStart?.(event);
|
|
2000
|
+
setStatus(1);
|
|
2001
|
+
dispatch({
|
|
2002
|
+
type: "dragStart",
|
|
2003
|
+
initialCoordinates,
|
|
2004
|
+
active: id
|
|
2005
|
+
});
|
|
2006
|
+
dispatchMonitorEvent({
|
|
2007
|
+
type: "onDragStart",
|
|
2008
|
+
event
|
|
2009
|
+
});
|
|
2010
|
+
},
|
|
2011
|
+
onMove(coordinates) {
|
|
2012
|
+
dispatch({
|
|
2013
|
+
type: "dragMove",
|
|
2014
|
+
coordinates
|
|
2015
|
+
});
|
|
2016
|
+
},
|
|
2017
|
+
onEnd: createHandler("dragEnd"),
|
|
2018
|
+
onCancel: createHandler("dragCancel")
|
|
2019
|
+
});
|
|
2020
|
+
setActiveSensor(sensorInstance);
|
|
2021
|
+
setActivatorEvent(event.nativeEvent);
|
|
2022
|
+
function createHandler(type) {
|
|
2023
|
+
return async function handler() {
|
|
2024
|
+
const { active, collisions, over, scrollAdjustedTranslate } = sensorContext.current;
|
|
2025
|
+
let event = null;
|
|
2026
|
+
if (active && scrollAdjustedTranslate) {
|
|
2027
|
+
const { cancelDrop } = latestProps.current;
|
|
2028
|
+
event = {
|
|
2029
|
+
activatorEvent,
|
|
2030
|
+
active,
|
|
2031
|
+
collisions,
|
|
2032
|
+
delta: scrollAdjustedTranslate,
|
|
2033
|
+
over
|
|
2034
|
+
};
|
|
2035
|
+
if (type === "dragEnd" && typeof cancelDrop === "function") {
|
|
2036
|
+
if (await Promise.resolve(cancelDrop(event))) type = "dragCancel";
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
activeRef.current = null;
|
|
2040
|
+
dispatch({ type });
|
|
2041
|
+
setStatus(0);
|
|
2042
|
+
setOver(null);
|
|
2043
|
+
setActiveSensor(null);
|
|
2044
|
+
setActivatorEvent(null);
|
|
2045
|
+
const eventName = type === "dragEnd" ? "onDragEnd" : "onDragCancel";
|
|
2046
|
+
if (event) {
|
|
2047
|
+
const handler = latestProps.current[eventName];
|
|
2048
|
+
handler?.(event);
|
|
2049
|
+
dispatchMonitorEvent({
|
|
2050
|
+
type: eventName,
|
|
2051
|
+
event
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
}, [draggableNodes]);
|
|
2057
|
+
const activators = useCombineActivators(sensors, useCallback((handler, sensor) => {
|
|
2058
|
+
return (event, active) => {
|
|
2059
|
+
const nativeEvent = event.nativeEvent;
|
|
2060
|
+
const activeDraggableNode = draggableNodes.get(active);
|
|
2061
|
+
if (activeRef.current !== null || !activeDraggableNode || nativeEvent.dndKit || nativeEvent.defaultPrevented) return;
|
|
2062
|
+
const activationContext = { active: activeDraggableNode };
|
|
2063
|
+
if (handler(event, sensor.options, activationContext) === true) {
|
|
2064
|
+
nativeEvent.dndKit = { capturedBy: sensor.sensor };
|
|
2065
|
+
activeRef.current = active;
|
|
2066
|
+
instantiateSensor(event, sensor);
|
|
2067
|
+
}
|
|
2068
|
+
};
|
|
2069
|
+
}, [draggableNodes, instantiateSensor]));
|
|
2070
|
+
useSensorSetup(sensors);
|
|
2071
|
+
useIsomorphicLayoutEffect(() => {
|
|
2072
|
+
if (activeNodeRect && status === 1) setStatus(2);
|
|
2073
|
+
}, [activeNodeRect, status]);
|
|
2074
|
+
useEffect(() => {
|
|
2075
|
+
const { onDragMove } = latestProps.current;
|
|
2076
|
+
const { active, activatorEvent, collisions, over } = sensorContext.current;
|
|
2077
|
+
if (!active || !activatorEvent) return;
|
|
2078
|
+
const event = {
|
|
2079
|
+
active,
|
|
2080
|
+
activatorEvent,
|
|
2081
|
+
collisions,
|
|
2082
|
+
delta: {
|
|
2083
|
+
x: scrollAdjustedTranslate.x,
|
|
2084
|
+
y: scrollAdjustedTranslate.y
|
|
2085
|
+
},
|
|
2086
|
+
over
|
|
2087
|
+
};
|
|
2088
|
+
onDragMove?.(event);
|
|
2089
|
+
dispatchMonitorEvent({
|
|
2090
|
+
type: "onDragMove",
|
|
2091
|
+
event
|
|
2092
|
+
});
|
|
2093
|
+
}, [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);
|
|
2094
|
+
useEffect(() => {
|
|
2095
|
+
const { active, activatorEvent, collisions, droppableContainers, scrollAdjustedTranslate } = sensorContext.current;
|
|
2096
|
+
if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) return;
|
|
2097
|
+
const { onDragOver } = latestProps.current;
|
|
2098
|
+
const overContainer = droppableContainers.get(overId);
|
|
2099
|
+
const over = overContainer && overContainer.rect.current ? {
|
|
2100
|
+
id: overContainer.id,
|
|
2101
|
+
rect: overContainer.rect.current,
|
|
2102
|
+
data: overContainer.data,
|
|
2103
|
+
disabled: overContainer.disabled
|
|
2104
|
+
} : null;
|
|
2105
|
+
const event = {
|
|
2106
|
+
active,
|
|
2107
|
+
activatorEvent,
|
|
2108
|
+
collisions,
|
|
2109
|
+
delta: {
|
|
2110
|
+
x: scrollAdjustedTranslate.x,
|
|
2111
|
+
y: scrollAdjustedTranslate.y
|
|
2112
|
+
},
|
|
2113
|
+
over
|
|
2114
|
+
};
|
|
2115
|
+
setOver(over);
|
|
2116
|
+
onDragOver?.(event);
|
|
2117
|
+
dispatchMonitorEvent({
|
|
2118
|
+
type: "onDragOver",
|
|
2119
|
+
event
|
|
2120
|
+
});
|
|
2121
|
+
}, [overId]);
|
|
2122
|
+
useIsomorphicLayoutEffect(() => {
|
|
2123
|
+
sensorContext.current = {
|
|
2124
|
+
activatorEvent,
|
|
2125
|
+
active,
|
|
2126
|
+
activeNode,
|
|
2127
|
+
collisionRect,
|
|
2128
|
+
collisions,
|
|
2129
|
+
droppableRects,
|
|
2130
|
+
draggableNodes,
|
|
2131
|
+
draggingNode,
|
|
2132
|
+
draggingNodeRect,
|
|
2133
|
+
droppableContainers,
|
|
2134
|
+
over,
|
|
2135
|
+
scrollableAncestors,
|
|
2136
|
+
scrollAdjustedTranslate
|
|
2137
|
+
};
|
|
2138
|
+
activeRects.current = {
|
|
2139
|
+
initial: draggingNodeRect,
|
|
2140
|
+
translated: collisionRect
|
|
2141
|
+
};
|
|
2142
|
+
}, [
|
|
2143
|
+
active,
|
|
2144
|
+
activeNode,
|
|
2145
|
+
collisions,
|
|
2146
|
+
collisionRect,
|
|
2147
|
+
draggableNodes,
|
|
2148
|
+
draggingNode,
|
|
2149
|
+
draggingNodeRect,
|
|
2150
|
+
droppableRects,
|
|
2151
|
+
droppableContainers,
|
|
2152
|
+
over,
|
|
2153
|
+
scrollableAncestors,
|
|
2154
|
+
scrollAdjustedTranslate
|
|
2155
|
+
]);
|
|
2156
|
+
useAutoScroller({
|
|
2157
|
+
...autoScrollOptions,
|
|
2158
|
+
delta: translate,
|
|
2159
|
+
draggingRect: collisionRect,
|
|
2160
|
+
pointerCoordinates,
|
|
2161
|
+
scrollableAncestors,
|
|
2162
|
+
scrollableAncestorRects
|
|
2163
|
+
});
|
|
2164
|
+
const publicContext = useMemo(() => {
|
|
2165
|
+
return {
|
|
2166
|
+
active,
|
|
2167
|
+
activeNode,
|
|
2168
|
+
activeNodeRect,
|
|
2169
|
+
activatorEvent,
|
|
2170
|
+
collisions,
|
|
2171
|
+
containerNodeRect,
|
|
2172
|
+
dragOverlay,
|
|
2173
|
+
draggableNodes,
|
|
2174
|
+
droppableContainers,
|
|
2175
|
+
droppableRects,
|
|
2176
|
+
over,
|
|
2177
|
+
measureDroppableContainers,
|
|
2178
|
+
scrollableAncestors,
|
|
2179
|
+
scrollableAncestorRects: scrollableAncestorRectsRects,
|
|
2180
|
+
measuringConfiguration,
|
|
2181
|
+
measuringScheduled,
|
|
2182
|
+
windowRect
|
|
2183
|
+
};
|
|
2184
|
+
}, [
|
|
2185
|
+
active,
|
|
2186
|
+
activeNode,
|
|
2187
|
+
activeNodeRect,
|
|
2188
|
+
activatorEvent,
|
|
2189
|
+
collisions,
|
|
2190
|
+
containerNodeRect,
|
|
2191
|
+
dragOverlay,
|
|
2192
|
+
draggableNodes,
|
|
2193
|
+
droppableContainers,
|
|
2194
|
+
droppableRects,
|
|
2195
|
+
over,
|
|
2196
|
+
measureDroppableContainers,
|
|
2197
|
+
scrollableAncestors,
|
|
2198
|
+
scrollableAncestorRects,
|
|
2199
|
+
measuringConfiguration,
|
|
2200
|
+
measuringScheduled,
|
|
2201
|
+
windowRect
|
|
2202
|
+
]);
|
|
2203
|
+
const internalContext = useMemo(() => {
|
|
2204
|
+
return {
|
|
2205
|
+
activatorEvent,
|
|
2206
|
+
activators,
|
|
2207
|
+
active,
|
|
2208
|
+
activeNodeRect,
|
|
2209
|
+
ariaDescribedById: { draggable: draggableDescribedById },
|
|
2210
|
+
dispatch,
|
|
2211
|
+
draggableNodes,
|
|
2212
|
+
over,
|
|
2213
|
+
measureDroppableContainers
|
|
2214
|
+
};
|
|
2215
|
+
}, [
|
|
2216
|
+
activatorEvent,
|
|
2217
|
+
activators,
|
|
2218
|
+
active,
|
|
2219
|
+
activeNodeRect,
|
|
2220
|
+
dispatch,
|
|
2221
|
+
draggableDescribedById,
|
|
2222
|
+
draggableNodes,
|
|
2223
|
+
over,
|
|
2224
|
+
measureDroppableContainers
|
|
2225
|
+
]);
|
|
2226
|
+
return /* @__PURE__ */ React.createElement(DndMonitorContext.Provider, { value: registerMonitorListener }, /* @__PURE__ */ React.createElement(InternalContext.Provider, { value: internalContext }, /* @__PURE__ */ React.createElement(PublicContext.Provider, { value: publicContext }, /* @__PURE__ */ React.createElement(ActiveDraggableContext.Provider, { value: transform }, children)), /* @__PURE__ */ React.createElement(RestoreFocus, { disabled: accessibility?.restoreFocus === false })), /* @__PURE__ */ React.createElement(Accessibility, {
|
|
2227
|
+
...accessibility,
|
|
2228
|
+
hiddenTextDescribedById: draggableDescribedById
|
|
2229
|
+
}));
|
|
2230
|
+
function getAutoScrollerOptions() {
|
|
2231
|
+
const activeSensorDisablesAutoscroll = activeSensor?.autoScrollEnabled === false;
|
|
2232
|
+
const autoScrollGloballyDisabled = typeof autoScroll === "object" ? autoScroll.enabled === false : autoScroll === false;
|
|
2233
|
+
const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;
|
|
2234
|
+
if (typeof autoScroll === "object") return {
|
|
2235
|
+
...autoScroll,
|
|
2236
|
+
enabled
|
|
2237
|
+
};
|
|
2238
|
+
return { enabled };
|
|
2239
|
+
}
|
|
2240
|
+
});
|
|
2241
|
+
//#endregion
|
|
2242
|
+
//#region src/hooks/useDraggable.ts
|
|
2243
|
+
const NullContext = createContext(null);
|
|
2244
|
+
const defaultRole = "button";
|
|
2245
|
+
const ID_PREFIX$1 = "Droppable";
|
|
2246
|
+
function useDraggable({ id, data, disabled = false, attributes }) {
|
|
2247
|
+
const key = useUniqueId(ID_PREFIX$1);
|
|
2248
|
+
const { activators, activatorEvent, active, activeNodeRect, ariaDescribedById, draggableNodes, over } = useContext(InternalContext);
|
|
2249
|
+
const { role = defaultRole, roleDescription = "draggable", tabIndex = 0 } = attributes ?? {};
|
|
2250
|
+
const isDragging = active?.id === id;
|
|
2251
|
+
const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);
|
|
2252
|
+
const [node, setNodeRef] = useNodeRef();
|
|
2253
|
+
const [activatorNode, setActivatorNodeRef] = useNodeRef();
|
|
2254
|
+
const listeners = useSyntheticListeners(activators, id);
|
|
2255
|
+
const dataRef = useLatestValue(data);
|
|
2256
|
+
useIsomorphicLayoutEffect(() => {
|
|
2257
|
+
draggableNodes.set(id, {
|
|
2258
|
+
id,
|
|
2259
|
+
key,
|
|
2260
|
+
node,
|
|
2261
|
+
activatorNode,
|
|
2262
|
+
data: dataRef
|
|
2263
|
+
});
|
|
2264
|
+
return () => {
|
|
2265
|
+
const node = draggableNodes.get(id);
|
|
2266
|
+
if (node && node.key === key) draggableNodes.delete(id);
|
|
2267
|
+
};
|
|
2268
|
+
}, [draggableNodes, id]);
|
|
2269
|
+
return {
|
|
2270
|
+
active,
|
|
2271
|
+
activatorEvent,
|
|
2272
|
+
activeNodeRect,
|
|
2273
|
+
attributes: useMemo(() => ({
|
|
2274
|
+
role,
|
|
2275
|
+
tabIndex,
|
|
2276
|
+
"aria-disabled": disabled,
|
|
2277
|
+
"aria-pressed": isDragging && role === defaultRole ? true : void 0,
|
|
2278
|
+
"aria-roledescription": roleDescription,
|
|
2279
|
+
"aria-describedby": ariaDescribedById.draggable
|
|
2280
|
+
}), [
|
|
2281
|
+
disabled,
|
|
2282
|
+
role,
|
|
2283
|
+
tabIndex,
|
|
2284
|
+
isDragging,
|
|
2285
|
+
roleDescription,
|
|
2286
|
+
ariaDescribedById.draggable
|
|
2287
|
+
]),
|
|
2288
|
+
isDragging,
|
|
2289
|
+
listeners: disabled ? void 0 : listeners,
|
|
2290
|
+
node,
|
|
2291
|
+
over,
|
|
2292
|
+
setNodeRef,
|
|
2293
|
+
setActivatorNodeRef,
|
|
2294
|
+
transform
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
//#endregion
|
|
2298
|
+
//#region src/hooks/useDndContext.ts
|
|
2299
|
+
function useDndContext() {
|
|
2300
|
+
return useContext(PublicContext);
|
|
2301
|
+
}
|
|
2302
|
+
//#endregion
|
|
2303
|
+
//#region src/hooks/useDroppable.ts
|
|
2304
|
+
const ID_PREFIX = "Droppable";
|
|
2305
|
+
const defaultResizeObserverConfig = { timeout: 25 };
|
|
2306
|
+
function useDroppable({ data, disabled = false, id, resizeObserverConfig }) {
|
|
2307
|
+
const key = useUniqueId(ID_PREFIX);
|
|
2308
|
+
const { active, dispatch, over, measureDroppableContainers } = useContext(InternalContext);
|
|
2309
|
+
const previous = useRef({ disabled });
|
|
2310
|
+
const resizeObserverConnected = useRef(false);
|
|
2311
|
+
const rect = useRef(null);
|
|
2312
|
+
const callbackId = useRef(null);
|
|
2313
|
+
const { disabled: resizeObserverDisabled, updateMeasurementsFor, timeout: resizeObserverTimeout } = {
|
|
2314
|
+
...defaultResizeObserverConfig,
|
|
2315
|
+
...resizeObserverConfig
|
|
2316
|
+
};
|
|
2317
|
+
const ids = useLatestValue(updateMeasurementsFor ?? id);
|
|
2318
|
+
const resizeObserver = useResizeObserver({
|
|
2319
|
+
callback: useCallback(() => {
|
|
2320
|
+
if (!resizeObserverConnected.current) {
|
|
2321
|
+
resizeObserverConnected.current = true;
|
|
2322
|
+
return;
|
|
2323
|
+
}
|
|
2324
|
+
if (callbackId.current != null) clearTimeout(callbackId.current);
|
|
2325
|
+
callbackId.current = setTimeout(() => {
|
|
2326
|
+
measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);
|
|
2327
|
+
callbackId.current = null;
|
|
2328
|
+
}, resizeObserverTimeout);
|
|
2329
|
+
}, [resizeObserverTimeout]),
|
|
2330
|
+
disabled: resizeObserverDisabled || !active
|
|
2331
|
+
});
|
|
2332
|
+
const handleNodeChange = useCallback((newElement, previousElement) => {
|
|
2333
|
+
if (!resizeObserver) return;
|
|
2334
|
+
if (previousElement) {
|
|
2335
|
+
resizeObserver.unobserve(previousElement);
|
|
2336
|
+
resizeObserverConnected.current = false;
|
|
2337
|
+
}
|
|
2338
|
+
if (newElement) resizeObserver.observe(newElement);
|
|
2339
|
+
}, [resizeObserver]);
|
|
2340
|
+
const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);
|
|
2341
|
+
const dataRef = useLatestValue(data);
|
|
2342
|
+
useEffect(() => {
|
|
2343
|
+
if (!resizeObserver || !nodeRef.current) return;
|
|
2344
|
+
resizeObserver.disconnect();
|
|
2345
|
+
resizeObserverConnected.current = false;
|
|
2346
|
+
resizeObserver.observe(nodeRef.current);
|
|
2347
|
+
}, [nodeRef, resizeObserver]);
|
|
2348
|
+
useIsomorphicLayoutEffect(() => {
|
|
2349
|
+
dispatch({
|
|
2350
|
+
type: "registerDroppable",
|
|
2351
|
+
element: {
|
|
2352
|
+
id,
|
|
2353
|
+
key,
|
|
2354
|
+
disabled,
|
|
2355
|
+
node: nodeRef,
|
|
2356
|
+
rect,
|
|
2357
|
+
data: dataRef
|
|
2358
|
+
}
|
|
2359
|
+
});
|
|
2360
|
+
return () => dispatch({
|
|
2361
|
+
type: "unregisterDroppable",
|
|
2362
|
+
key,
|
|
2363
|
+
id
|
|
2364
|
+
});
|
|
2365
|
+
}, [id]);
|
|
2366
|
+
useEffect(() => {
|
|
2367
|
+
if (disabled !== previous.current.disabled) {
|
|
2368
|
+
dispatch({
|
|
2369
|
+
type: "setDroppableDisabled",
|
|
2370
|
+
id,
|
|
2371
|
+
key,
|
|
2372
|
+
disabled
|
|
2373
|
+
});
|
|
2374
|
+
previous.current.disabled = disabled;
|
|
2375
|
+
}
|
|
2376
|
+
}, [
|
|
2377
|
+
id,
|
|
2378
|
+
key,
|
|
2379
|
+
disabled,
|
|
2380
|
+
dispatch
|
|
2381
|
+
]);
|
|
2382
|
+
return {
|
|
2383
|
+
active,
|
|
2384
|
+
rect,
|
|
2385
|
+
isOver: over?.id === id,
|
|
2386
|
+
node: nodeRef,
|
|
2387
|
+
over,
|
|
2388
|
+
setNodeRef
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
//#endregion
|
|
2392
|
+
//#region src/components/DragOverlay/components/AnimationManager/AnimationManager.tsx
|
|
2393
|
+
function AnimationManager({ animation, children }) {
|
|
2394
|
+
const [clonedChildren, setClonedChildren] = useState(null);
|
|
2395
|
+
const [element, setElement] = useState(null);
|
|
2396
|
+
const previousChildren = usePrevious(children);
|
|
2397
|
+
if (!children && !clonedChildren && previousChildren) setClonedChildren(previousChildren);
|
|
2398
|
+
useIsomorphicLayoutEffect(() => {
|
|
2399
|
+
if (!element) return;
|
|
2400
|
+
const key = clonedChildren?.key;
|
|
2401
|
+
const id = clonedChildren?.props.id;
|
|
2402
|
+
if (key == null || id == null) {
|
|
2403
|
+
setClonedChildren(null);
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
Promise.resolve(animation(id, element)).then(() => {
|
|
2407
|
+
setClonedChildren(null);
|
|
2408
|
+
});
|
|
2409
|
+
}, [
|
|
2410
|
+
animation,
|
|
2411
|
+
clonedChildren,
|
|
2412
|
+
element
|
|
2413
|
+
]);
|
|
2414
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, { ref: setElement }) : null);
|
|
2415
|
+
}
|
|
2416
|
+
//#endregion
|
|
2417
|
+
//#region src/components/DragOverlay/components/NullifiedContextProvider/NullifiedContextProvider.tsx
|
|
2418
|
+
const defaultTransform = {
|
|
2419
|
+
x: 0,
|
|
2420
|
+
y: 0,
|
|
2421
|
+
scaleX: 1,
|
|
2422
|
+
scaleY: 1
|
|
2423
|
+
};
|
|
2424
|
+
function NullifiedContextProvider({ children }) {
|
|
2425
|
+
return /* @__PURE__ */ React.createElement(InternalContext.Provider, { value: defaultInternalContext }, /* @__PURE__ */ React.createElement(ActiveDraggableContext.Provider, { value: defaultTransform }, children));
|
|
2426
|
+
}
|
|
2427
|
+
//#endregion
|
|
2428
|
+
//#region src/components/DragOverlay/components/PositionedOverlay/PositionedOverlay.tsx
|
|
2429
|
+
const baseStyles = {
|
|
2430
|
+
position: "fixed",
|
|
2431
|
+
touchAction: "none"
|
|
2432
|
+
};
|
|
2433
|
+
const defaultTransition = (activatorEvent) => {
|
|
2434
|
+
return isKeyboardEvent(activatorEvent) ? "transform 250ms ease" : void 0;
|
|
2435
|
+
};
|
|
2436
|
+
const PositionedOverlay = forwardRef(({ as, activatorEvent, adjustScale, children, className, rect, style, transform, transition = defaultTransition }, ref) => {
|
|
2437
|
+
if (!rect) return null;
|
|
2438
|
+
const scaleAdjustedTransform = adjustScale ? transform : {
|
|
2439
|
+
...transform,
|
|
2440
|
+
scaleX: 1,
|
|
2441
|
+
scaleY: 1
|
|
2442
|
+
};
|
|
2443
|
+
const styles = {
|
|
2444
|
+
...baseStyles,
|
|
2445
|
+
width: rect.width,
|
|
2446
|
+
height: rect.height,
|
|
2447
|
+
top: rect.top,
|
|
2448
|
+
left: rect.left,
|
|
2449
|
+
transform: CSS.Transform.toString(scaleAdjustedTransform),
|
|
2450
|
+
transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : void 0,
|
|
2451
|
+
transition: typeof transition === "function" ? transition(activatorEvent) : transition,
|
|
2452
|
+
...style
|
|
2453
|
+
};
|
|
2454
|
+
return React.createElement(as, {
|
|
2455
|
+
className,
|
|
2456
|
+
style: styles,
|
|
2457
|
+
ref
|
|
2458
|
+
}, children);
|
|
2459
|
+
});
|
|
2460
|
+
//#endregion
|
|
2461
|
+
//#region src/components/DragOverlay/hooks/useDropAnimation.ts
|
|
2462
|
+
const defaultDropAnimationSideEffects = (options) => ({ active, dragOverlay }) => {
|
|
2463
|
+
const originalStyles = {};
|
|
2464
|
+
const { styles, className } = options;
|
|
2465
|
+
if (styles?.active) for (const [key, value] of Object.entries(styles.active)) {
|
|
2466
|
+
if (value === void 0) continue;
|
|
2467
|
+
originalStyles[key] = active.node.style.getPropertyValue(key);
|
|
2468
|
+
active.node.style.setProperty(key, value);
|
|
2469
|
+
}
|
|
2470
|
+
if (styles?.dragOverlay) for (const [key, value] of Object.entries(styles.dragOverlay)) {
|
|
2471
|
+
if (value === void 0) continue;
|
|
2472
|
+
dragOverlay.node.style.setProperty(key, value);
|
|
2473
|
+
}
|
|
2474
|
+
if (className?.active) active.node.classList.add(className.active);
|
|
2475
|
+
if (className?.dragOverlay) dragOverlay.node.classList.add(className.dragOverlay);
|
|
2476
|
+
return function cleanup() {
|
|
2477
|
+
for (const [key, value] of Object.entries(originalStyles)) active.node.style.setProperty(key, value);
|
|
2478
|
+
if (className?.active) active.node.classList.remove(className.active);
|
|
2479
|
+
};
|
|
2480
|
+
};
|
|
2481
|
+
const defaultKeyframeResolver = ({ transform: { initial, final } }) => [{ transform: CSS.Transform.toString(initial) }, { transform: CSS.Transform.toString(final) }];
|
|
2482
|
+
const defaultDropAnimationConfiguration = {
|
|
2483
|
+
duration: 250,
|
|
2484
|
+
easing: "ease",
|
|
2485
|
+
keyframes: defaultKeyframeResolver,
|
|
2486
|
+
sideEffects: defaultDropAnimationSideEffects({ styles: { active: { opacity: "0" } } })
|
|
2487
|
+
};
|
|
2488
|
+
function useDropAnimation({ config, draggableNodes, droppableContainers, measuringConfiguration }) {
|
|
2489
|
+
return useEvent((id, node) => {
|
|
2490
|
+
if (config === null) return;
|
|
2491
|
+
const activeDraggable = draggableNodes.get(id);
|
|
2492
|
+
if (!activeDraggable) return;
|
|
2493
|
+
const activeNode = activeDraggable.node.current;
|
|
2494
|
+
if (!activeNode) return;
|
|
2495
|
+
const measurableNode = getMeasurableNode(node);
|
|
2496
|
+
if (!measurableNode) return;
|
|
2497
|
+
const { transform } = getWindow(node).getComputedStyle(node);
|
|
2498
|
+
const parsedTransform = parseTransform(transform);
|
|
2499
|
+
if (!parsedTransform) return;
|
|
2500
|
+
const animation = typeof config === "function" ? config : createDefaultDropAnimation(config);
|
|
2501
|
+
scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);
|
|
2502
|
+
return animation({
|
|
2503
|
+
active: {
|
|
2504
|
+
id,
|
|
2505
|
+
data: activeDraggable.data,
|
|
2506
|
+
node: activeNode,
|
|
2507
|
+
rect: measuringConfiguration.draggable.measure(activeNode)
|
|
2508
|
+
},
|
|
2509
|
+
draggableNodes,
|
|
2510
|
+
dragOverlay: {
|
|
2511
|
+
node,
|
|
2512
|
+
rect: measuringConfiguration.dragOverlay.measure(measurableNode)
|
|
2513
|
+
},
|
|
2514
|
+
droppableContainers,
|
|
2515
|
+
measuringConfiguration,
|
|
2516
|
+
transform: parsedTransform
|
|
2517
|
+
});
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
function createDefaultDropAnimation(options) {
|
|
2521
|
+
const { duration, easing, sideEffects, keyframes } = {
|
|
2522
|
+
...defaultDropAnimationConfiguration,
|
|
2523
|
+
...options
|
|
2524
|
+
};
|
|
2525
|
+
return ({ active, dragOverlay, transform, ...rest }) => {
|
|
2526
|
+
if (!duration) return;
|
|
2527
|
+
const delta = {
|
|
2528
|
+
x: dragOverlay.rect.left - active.rect.left,
|
|
2529
|
+
y: dragOverlay.rect.top - active.rect.top
|
|
2530
|
+
};
|
|
2531
|
+
const scale = {
|
|
2532
|
+
scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,
|
|
2533
|
+
scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1
|
|
2534
|
+
};
|
|
2535
|
+
const finalTransform = {
|
|
2536
|
+
x: transform.x - delta.x,
|
|
2537
|
+
y: transform.y - delta.y,
|
|
2538
|
+
...scale
|
|
2539
|
+
};
|
|
2540
|
+
const animationKeyframes = keyframes({
|
|
2541
|
+
...rest,
|
|
2542
|
+
active,
|
|
2543
|
+
dragOverlay,
|
|
2544
|
+
transform: {
|
|
2545
|
+
initial: transform,
|
|
2546
|
+
final: finalTransform
|
|
2547
|
+
}
|
|
2548
|
+
});
|
|
2549
|
+
const [firstKeyframe] = animationKeyframes;
|
|
2550
|
+
const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];
|
|
2551
|
+
if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) return;
|
|
2552
|
+
const cleanup = sideEffects?.({
|
|
2553
|
+
active,
|
|
2554
|
+
dragOverlay,
|
|
2555
|
+
...rest
|
|
2556
|
+
});
|
|
2557
|
+
const animation = dragOverlay.node.animate(animationKeyframes, {
|
|
2558
|
+
duration,
|
|
2559
|
+
easing,
|
|
2560
|
+
fill: "forwards"
|
|
2561
|
+
});
|
|
2562
|
+
return new Promise((resolve) => {
|
|
2563
|
+
animation.onfinish = () => {
|
|
2564
|
+
cleanup?.();
|
|
2565
|
+
resolve();
|
|
2566
|
+
};
|
|
2567
|
+
});
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
//#endregion
|
|
2571
|
+
//#region src/components/DragOverlay/hooks/useKey.ts
|
|
2572
|
+
let key = 0;
|
|
2573
|
+
function useKey(id) {
|
|
2574
|
+
return useMemo(() => {
|
|
2575
|
+
if (id == null) return;
|
|
2576
|
+
key++;
|
|
2577
|
+
return key;
|
|
2578
|
+
}, [id]);
|
|
2579
|
+
}
|
|
2580
|
+
//#endregion
|
|
2581
|
+
//#region src/components/DragOverlay/DragOverlay.tsx
|
|
2582
|
+
const DragOverlay = React.memo(({ adjustScale = false, children, dropAnimation: dropAnimationConfig, style, transition, modifiers, wrapperElement = "div", className, zIndex = 999 }) => {
|
|
2583
|
+
const { activatorEvent, active, activeNodeRect, containerNodeRect, draggableNodes, droppableContainers, dragOverlay, over, measuringConfiguration, scrollableAncestors, scrollableAncestorRects, windowRect } = useDndContext();
|
|
2584
|
+
const transform = useContext(ActiveDraggableContext);
|
|
2585
|
+
const key = useKey(active?.id);
|
|
2586
|
+
const modifiedTransform = applyModifiers(modifiers, {
|
|
2587
|
+
activatorEvent,
|
|
2588
|
+
active,
|
|
2589
|
+
activeNodeRect,
|
|
2590
|
+
containerNodeRect,
|
|
2591
|
+
draggingNodeRect: dragOverlay.rect,
|
|
2592
|
+
over,
|
|
2593
|
+
overlayNodeRect: dragOverlay.rect,
|
|
2594
|
+
scrollableAncestors,
|
|
2595
|
+
scrollableAncestorRects,
|
|
2596
|
+
transform,
|
|
2597
|
+
windowRect
|
|
2598
|
+
});
|
|
2599
|
+
const initialRect = useInitialValue(activeNodeRect);
|
|
2600
|
+
const dropAnimation = useDropAnimation({
|
|
2601
|
+
config: dropAnimationConfig,
|
|
2602
|
+
draggableNodes,
|
|
2603
|
+
droppableContainers,
|
|
2604
|
+
measuringConfiguration
|
|
2605
|
+
});
|
|
2606
|
+
const ref = initialRect ? dragOverlay.setRef : void 0;
|
|
2607
|
+
return /* @__PURE__ */ React.createElement(NullifiedContextProvider, null, /* @__PURE__ */ React.createElement(AnimationManager, { animation: dropAnimation }, active && key ? /* @__PURE__ */ React.createElement(PositionedOverlay, {
|
|
2608
|
+
key,
|
|
2609
|
+
id: active.id,
|
|
2610
|
+
ref,
|
|
2611
|
+
as: wrapperElement,
|
|
2612
|
+
activatorEvent,
|
|
2613
|
+
adjustScale,
|
|
2614
|
+
className,
|
|
2615
|
+
transition,
|
|
2616
|
+
rect: initialRect,
|
|
2617
|
+
style: {
|
|
2618
|
+
zIndex,
|
|
2619
|
+
...style
|
|
2620
|
+
},
|
|
2621
|
+
transform: modifiedTransform
|
|
2622
|
+
}, children) : null));
|
|
2623
|
+
});
|
|
2624
|
+
//#endregion
|
|
2625
|
+
export { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };
|
|
2626
|
+
|
|
2627
|
+
//# sourceMappingURL=index.js.map
|