@elliemae/ds-drag-and-drop 2.2.0-next.5 → 2.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/cjs/tree/customCollisionDetection.js +88 -92
- package/cjs/tree/getTreeKeyboardCoordinates.js +1 -0
- package/cjs/tree/useTreeActionHandlers.js +6 -5
- package/cjs/tree/useTreeDndkitConfig.js +16 -26
- package/esm/tree/customCollisionDetection.js +88 -92
- package/esm/tree/getTreeKeyboardCoordinates.js +1 -0
- package/esm/tree/useTreeActionHandlers.js +6 -5
- package/esm/tree/useTreeDndkitConfig.js +16 -26
- package/package.json +1 -1
- package/types/hierarchy/types.d.ts +1 -1
- package/types/tree/types.d.ts +13 -17
- package/types/tree/useTreeActionHandlers.d.ts +2 -2
- package/types/tree/useTreeDndkitConfig.d.ts +2 -2
- package/types/tree/useTreePreviewHandlers.d.ts +2 -2
|
@@ -33,109 +33,105 @@ const RECT_DOWN = {
|
|
|
33
33
|
const thresholdRatio = 0.2; // Percentage to be inside
|
|
34
34
|
|
|
35
35
|
const insideThreshold = 0.7;
|
|
36
|
-
const customCollisionDetection = (activeId, visibleItemsDictionary, setDropIndicatorPosition, maxDragAndDropLevel, lastPosition, setLastPosition) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const customCollisionDetection = (activeId, visibleItemsDictionary, setDropIndicatorPosition, maxDragAndDropLevel, lastPosition, setLastPosition) => _ref => {
|
|
37
|
+
var _originalContainer$re;
|
|
38
|
+
|
|
39
|
+
let {
|
|
40
|
+
droppableContainers,
|
|
41
|
+
collisionRect
|
|
42
|
+
} = _ref;
|
|
43
|
+
const originalContainer = droppableContainers.find(_ref2 => {
|
|
40
44
|
let {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
offsetTop: firstRectDownOffsetTop
|
|
74
|
-
} = firstRectDown.rect.current;
|
|
75
|
-
|
|
76
|
-
if (rectOffsetTop + threshold > collisionRect.top && rectOffsetTop < firstRectDownOffsetTop) {
|
|
77
|
-
return container;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return firstRectDown;
|
|
82
|
-
}, {
|
|
83
|
-
id: DUMMY_ID,
|
|
84
|
-
rect: {
|
|
85
|
-
current: RECT_DOWN
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
} else {
|
|
89
|
-
// Down -- We need to find the first rectangle upwards
|
|
90
|
-
collidingContainer = droppableContainers.reduce((firstRectUp, container) => {
|
|
91
|
-
const rect = container.rect.current;
|
|
92
|
-
|
|
93
|
-
if (rect && firstRectUp.rect.current) {
|
|
94
|
-
const {
|
|
95
|
-
offsetTop: rectOffsetTop
|
|
96
|
-
} = rect;
|
|
97
|
-
const {
|
|
98
|
-
offsetTop: firstRectUpOffsetTop
|
|
99
|
-
} = firstRectUp.rect.current;
|
|
100
|
-
|
|
101
|
-
if (rectOffsetTop - threshold < collisionRect.top && rectOffsetTop > firstRectUpOffsetTop) {
|
|
102
|
-
return container;
|
|
103
|
-
}
|
|
45
|
+
id
|
|
46
|
+
} = _ref2;
|
|
47
|
+
return id === activeId;
|
|
48
|
+
});
|
|
49
|
+
const originalRect = originalContainer === null || originalContainer === void 0 ? void 0 : (_originalContainer$re = originalContainer.rect) === null || _originalContainer$re === void 0 ? void 0 : _originalContainer$re.current; // We first check if the item was moved up or down
|
|
50
|
+
// This modifies how to search the matching colliding rect
|
|
51
|
+
|
|
52
|
+
let isUp = lastPosition === 'up';
|
|
53
|
+
|
|
54
|
+
if (originalRect) {
|
|
55
|
+
isUp = originalRect.offsetTop > collisionRect.top;
|
|
56
|
+
} // Threshold
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
const threshold = collisionRect.height * thresholdRatio;
|
|
60
|
+
let collidingContainer = null;
|
|
61
|
+
|
|
62
|
+
if (isUp) {
|
|
63
|
+
// Up -- We need to find the first rectangle downwards
|
|
64
|
+
collidingContainer = droppableContainers.reduce((firstRectDown, container) => {
|
|
65
|
+
const rect = container.rect.current;
|
|
66
|
+
|
|
67
|
+
if (rect && firstRectDown.rect.current) {
|
|
68
|
+
const {
|
|
69
|
+
offsetTop: rectOffsetTop
|
|
70
|
+
} = rect;
|
|
71
|
+
const {
|
|
72
|
+
offsetTop: firstRectDownOffsetTop
|
|
73
|
+
} = firstRectDown.rect.current;
|
|
74
|
+
|
|
75
|
+
if (rectOffsetTop + threshold > collisionRect.top && rectOffsetTop < firstRectDownOffsetTop) {
|
|
76
|
+
return container;
|
|
104
77
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return firstRectDown;
|
|
81
|
+
}, {
|
|
82
|
+
id: DUMMY_ID,
|
|
83
|
+
rect: {
|
|
84
|
+
current: RECT_DOWN
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
// Down -- We need to find the first rectangle upwards
|
|
89
|
+
collidingContainer = droppableContainers.reduce((firstRectUp, container) => {
|
|
90
|
+
const rect = container.rect.current;
|
|
91
|
+
|
|
92
|
+
if (rect && firstRectUp.rect.current) {
|
|
93
|
+
const {
|
|
94
|
+
offsetTop: rectOffsetTop
|
|
95
|
+
} = rect;
|
|
96
|
+
const {
|
|
97
|
+
offsetTop: firstRectUpOffsetTop
|
|
98
|
+
} = firstRectUp.rect.current;
|
|
99
|
+
|
|
100
|
+
if (rectOffsetTop - threshold < collisionRect.top && rectOffsetTop > firstRectUpOffsetTop) {
|
|
101
|
+
return container;
|
|
111
102
|
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return firstRectUp;
|
|
106
|
+
}, {
|
|
107
|
+
id: DUMMY_ID,
|
|
108
|
+
rect: {
|
|
109
|
+
current: RECT_UP
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
} // If we didn't find a match, return null
|
|
115
113
|
|
|
116
|
-
if (collidingContainer.id === DUMMY_ID) {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
114
|
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
if (collidingContainer.id === DUMMY_ID) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
122
118
|
|
|
123
|
-
|
|
119
|
+
const collidingRect = collidingContainer.rect.current;
|
|
120
|
+
if (!collidingRect) return null; // Calculate the intersection interval
|
|
124
121
|
|
|
125
|
-
|
|
122
|
+
const [top, bottom] = [Math.max(collisionRect.top, collidingRect.offsetTop), Math.min(collisionRect.bottom, collidingRect.offsetTop + collidingRect.height)]; // Calculate the percentage of intersection
|
|
126
123
|
|
|
127
|
-
|
|
128
|
-
setDropIndicatorPosition(constants.DropIndicatorPosition.Inside);
|
|
129
|
-
} else {
|
|
130
|
-
setDropIndicatorPosition(isUp ? constants.DropIndicatorPosition.Before : constants.DropIndicatorPosition.After);
|
|
131
|
-
}
|
|
124
|
+
const intersectionPercentage = Math.abs(bottom - top) / collidingRect.height;
|
|
132
125
|
|
|
133
|
-
|
|
126
|
+
if (intersectionPercentage > insideThreshold && visibleItemsDictionary[collidingContainer.id].depth + 1 <= maxDragAndDropLevel && collidingContainer.id !== activeId) {
|
|
127
|
+
setDropIndicatorPosition(constants.DropIndicatorPosition.Inside);
|
|
128
|
+
} else {
|
|
129
|
+
setDropIndicatorPosition(isUp ? constants.DropIndicatorPosition.Before : constants.DropIndicatorPosition.After);
|
|
130
|
+
}
|
|
134
131
|
|
|
135
|
-
|
|
136
|
-
};
|
|
132
|
+
if (isUp && lastPosition !== 'up') setLastPosition('up');else if (!isUp && lastPosition !== 'down') setLastPosition('down'); // Return the id of the match rectangle
|
|
137
133
|
|
|
138
|
-
return
|
|
134
|
+
return collidingContainer.id;
|
|
139
135
|
};
|
|
140
136
|
|
|
141
137
|
exports.customCollisionDetection = customCollisionDetection;
|
|
@@ -22,6 +22,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
22
22
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
23
23
|
const directions = [core.KeyboardCode.Down, core.KeyboardCode.Right, core.KeyboardCode.Up, core.KeyboardCode.Left];
|
|
24
24
|
const horizontal = [core.KeyboardCode.Left, core.KeyboardCode.Right];
|
|
25
|
+
[core.KeyboardCode.Up, core.KeyboardCode.Down];
|
|
25
26
|
|
|
26
27
|
const getVerticalKeyboardCoordinates = _ref => {
|
|
27
28
|
var _droppableContainers$, _droppableContainers$2;
|
|
@@ -17,8 +17,7 @@ const useTreeActionHandlers = _ref => {
|
|
|
17
17
|
onReorder,
|
|
18
18
|
flattenedItems,
|
|
19
19
|
projected,
|
|
20
|
-
dropIndicatorPosition
|
|
21
|
-
isDropValid
|
|
20
|
+
dropIndicatorPosition
|
|
22
21
|
} = _ref;
|
|
23
22
|
const onDragStart = react.useCallback(e => {
|
|
24
23
|
handlePreviewDragStart(e);
|
|
@@ -35,15 +34,17 @@ const useTreeActionHandlers = _ref => {
|
|
|
35
34
|
active,
|
|
36
35
|
over
|
|
37
36
|
} = e;
|
|
38
|
-
if (over === null
|
|
37
|
+
if (over === null) return;
|
|
39
38
|
const activeIndex = flattenedItems.findIndex(item => item.uid === active.id);
|
|
40
39
|
let considerExpanding = null;
|
|
41
40
|
let overIndex = flattenedItems.findIndex(item => item.uid === over.id); // If drop indicator is inside, then put it last,
|
|
42
41
|
// It will be reconstructed well later
|
|
43
42
|
|
|
44
43
|
if (dropIndicatorPosition === constants.DropIndicatorPosition.Inside) {
|
|
44
|
+
var _flattenedItems$overI, _flattenedItems$overI2;
|
|
45
|
+
|
|
45
46
|
considerExpanding = over.id;
|
|
46
|
-
overIndex = flattenedItems[overIndex].realIndex + flattenedItems[overIndex].
|
|
47
|
+
overIndex = flattenedItems[overIndex].realIndex + ((_flattenedItems$overI = (_flattenedItems$overI2 = flattenedItems[overIndex].original.subRows) === null || _flattenedItems$overI2 === void 0 ? void 0 : _flattenedItems$overI2.length) !== null && _flattenedItems$overI !== void 0 ? _flattenedItems$overI : 0) + 1;
|
|
47
48
|
} // If we are dropping the item in a new position, or new depth
|
|
48
49
|
|
|
49
50
|
|
|
@@ -58,7 +59,7 @@ const useTreeActionHandlers = _ref => {
|
|
|
58
59
|
fromIndex: activeIndex
|
|
59
60
|
}, considerExpanding || '');
|
|
60
61
|
}
|
|
61
|
-
}, [handlePreviewDragEnd,
|
|
62
|
+
}, [handlePreviewDragEnd, flattenedItems, projected, onReorder, dropIndicatorPosition]);
|
|
62
63
|
const onDragCancel = react.useCallback(e => {
|
|
63
64
|
handlePreviewDragCancel(e);
|
|
64
65
|
}, [handlePreviewDragCancel]);
|
|
@@ -13,6 +13,7 @@ require('core-js/modules/esnext.async-iterator.filter.js');
|
|
|
13
13
|
require('core-js/modules/esnext.iterator.filter.js');
|
|
14
14
|
var react = require('react');
|
|
15
15
|
var core = require('@dnd-kit/core');
|
|
16
|
+
var sortable = require('@dnd-kit/sortable');
|
|
16
17
|
var useTreePreviewHandlers = require('./useTreePreviewHandlers.js');
|
|
17
18
|
var getTreeKeyboardCoordinates = require('./getTreeKeyboardCoordinates.js');
|
|
18
19
|
var utilities = require('./utilities.js');
|
|
@@ -30,29 +31,25 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
30
31
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
31
32
|
// if second parameter is true, the space will be done on the horizontal axis
|
|
32
33
|
|
|
33
|
-
const adjustTranslate = isHorizontalDnD => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
} = _ref;
|
|
38
|
-
|
|
39
|
-
const newTransform = _objectSpread({}, transform);
|
|
34
|
+
const adjustTranslate = isHorizontalDnD => _ref => {
|
|
35
|
+
let {
|
|
36
|
+
transform
|
|
37
|
+
} = _ref;
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
newTransform.x = transform.x + 25;
|
|
43
|
-
} else {
|
|
44
|
-
newTransform.x = transform.x + 15;
|
|
45
|
-
}
|
|
39
|
+
const newTransform = _objectSpread({}, transform);
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
if (isHorizontalDnD) {
|
|
42
|
+
newTransform.x = transform.x + 25;
|
|
43
|
+
} else {
|
|
44
|
+
newTransform.x = transform.x + 15;
|
|
45
|
+
}
|
|
49
46
|
|
|
50
|
-
return
|
|
47
|
+
return newTransform;
|
|
51
48
|
};
|
|
52
49
|
|
|
53
50
|
const measuring = {
|
|
54
51
|
droppable: {
|
|
55
|
-
strategy: core.MeasuringStrategy.
|
|
52
|
+
strategy: core.MeasuringStrategy.BeforeDragging
|
|
56
53
|
}
|
|
57
54
|
};
|
|
58
55
|
const useTreeDndkitConfig = _ref2 => {
|
|
@@ -64,7 +61,6 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
64
61
|
isHorizontalDnD = false,
|
|
65
62
|
isExpandable = false,
|
|
66
63
|
onReorder,
|
|
67
|
-
getIsDropValid = () => true,
|
|
68
64
|
maxDragAndDropLevel
|
|
69
65
|
} = _ref2;
|
|
70
66
|
const [activeId, setActiveId] = react.useState('');
|
|
@@ -89,10 +85,6 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
89
85
|
});
|
|
90
86
|
return dictionary;
|
|
91
87
|
}, [visibleItems]);
|
|
92
|
-
const isDropValid = react.useMemo(() => {
|
|
93
|
-
if (!activeId || !overId) return true;
|
|
94
|
-
return getIsDropValid(visibleItemsDictionary[activeId], visibleItemsDictionary[overId], ['none', 'before', 'after', 'inside'][dropIndicatorPosition]);
|
|
95
|
-
}, [getIsDropValid, visibleItemsDictionary, activeId, overId, dropIndicatorPosition]);
|
|
96
88
|
const modifiers = react.useMemo(() => [adjustTranslate(isHorizontalDnD)], [isHorizontalDnD]);
|
|
97
89
|
const sensorContext = react.useRef({
|
|
98
90
|
items: visibleItems,
|
|
@@ -121,8 +113,7 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
121
113
|
onReorder,
|
|
122
114
|
projected,
|
|
123
115
|
flattenedItems,
|
|
124
|
-
dropIndicatorPosition
|
|
125
|
-
isDropValid
|
|
116
|
+
dropIndicatorPosition
|
|
126
117
|
}));
|
|
127
118
|
const announcements = useTreeAnnouncements.useTreeAnnouncements(visibleItemsDictionary, dropIndicatorPosition);
|
|
128
119
|
const dndContextProps = react.useMemo(() => _objectSpread({
|
|
@@ -134,12 +125,11 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
134
125
|
}, dragActionHandlers), [announcements, modifiers, sensors, dragActionHandlers, visibleItemsDictionary, setDropIndicatorPosition, activeId, maxDragAndDropLevel, lastPosition, setLastPosition]);
|
|
135
126
|
const sortableContextProps = react.useMemo(() => ({
|
|
136
127
|
items: sortedIds,
|
|
137
|
-
strategy:
|
|
138
|
-
}), [sortedIds]);
|
|
128
|
+
strategy: isHorizontalDnD ? sortable.horizontalListSortingStrategy : sortable.verticalListSortingStrategy
|
|
129
|
+
}), [sortedIds, isHorizontalDnD]);
|
|
139
130
|
return {
|
|
140
131
|
dndContextProps,
|
|
141
132
|
sortableContextProps,
|
|
142
|
-
isDropValid,
|
|
143
133
|
activeId,
|
|
144
134
|
activeIndex: (_visibleItemsDictiona = (_visibleItemsDictiona2 = visibleItemsDictionary[activeId]) === null || _visibleItemsDictiona2 === void 0 ? void 0 : _visibleItemsDictiona2.realIndex) !== null && _visibleItemsDictiona !== void 0 ? _visibleItemsDictiona : -1,
|
|
145
135
|
overId,
|
|
@@ -29,109 +29,105 @@ const RECT_DOWN = {
|
|
|
29
29
|
const thresholdRatio = 0.2; // Percentage to be inside
|
|
30
30
|
|
|
31
31
|
const insideThreshold = 0.7;
|
|
32
|
-
const customCollisionDetection = (activeId, visibleItemsDictionary, setDropIndicatorPosition, maxDragAndDropLevel, lastPosition, setLastPosition) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
const customCollisionDetection = (activeId, visibleItemsDictionary, setDropIndicatorPosition, maxDragAndDropLevel, lastPosition, setLastPosition) => _ref => {
|
|
33
|
+
var _originalContainer$re;
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
droppableContainers,
|
|
37
|
+
collisionRect
|
|
38
|
+
} = _ref;
|
|
39
|
+
const originalContainer = droppableContainers.find(_ref2 => {
|
|
36
40
|
let {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
offsetTop: firstRectDownOffsetTop
|
|
70
|
-
} = firstRectDown.rect.current;
|
|
71
|
-
|
|
72
|
-
if (rectOffsetTop + threshold > collisionRect.top && rectOffsetTop < firstRectDownOffsetTop) {
|
|
73
|
-
return container;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return firstRectDown;
|
|
78
|
-
}, {
|
|
79
|
-
id: DUMMY_ID,
|
|
80
|
-
rect: {
|
|
81
|
-
current: RECT_DOWN
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
} else {
|
|
85
|
-
// Down -- We need to find the first rectangle upwards
|
|
86
|
-
collidingContainer = droppableContainers.reduce((firstRectUp, container) => {
|
|
87
|
-
const rect = container.rect.current;
|
|
88
|
-
|
|
89
|
-
if (rect && firstRectUp.rect.current) {
|
|
90
|
-
const {
|
|
91
|
-
offsetTop: rectOffsetTop
|
|
92
|
-
} = rect;
|
|
93
|
-
const {
|
|
94
|
-
offsetTop: firstRectUpOffsetTop
|
|
95
|
-
} = firstRectUp.rect.current;
|
|
96
|
-
|
|
97
|
-
if (rectOffsetTop - threshold < collisionRect.top && rectOffsetTop > firstRectUpOffsetTop) {
|
|
98
|
-
return container;
|
|
99
|
-
}
|
|
41
|
+
id
|
|
42
|
+
} = _ref2;
|
|
43
|
+
return id === activeId;
|
|
44
|
+
});
|
|
45
|
+
const originalRect = originalContainer === null || originalContainer === void 0 ? void 0 : (_originalContainer$re = originalContainer.rect) === null || _originalContainer$re === void 0 ? void 0 : _originalContainer$re.current; // We first check if the item was moved up or down
|
|
46
|
+
// This modifies how to search the matching colliding rect
|
|
47
|
+
|
|
48
|
+
let isUp = lastPosition === 'up';
|
|
49
|
+
|
|
50
|
+
if (originalRect) {
|
|
51
|
+
isUp = originalRect.offsetTop > collisionRect.top;
|
|
52
|
+
} // Threshold
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
const threshold = collisionRect.height * thresholdRatio;
|
|
56
|
+
let collidingContainer = null;
|
|
57
|
+
|
|
58
|
+
if (isUp) {
|
|
59
|
+
// Up -- We need to find the first rectangle downwards
|
|
60
|
+
collidingContainer = droppableContainers.reduce((firstRectDown, container) => {
|
|
61
|
+
const rect = container.rect.current;
|
|
62
|
+
|
|
63
|
+
if (rect && firstRectDown.rect.current) {
|
|
64
|
+
const {
|
|
65
|
+
offsetTop: rectOffsetTop
|
|
66
|
+
} = rect;
|
|
67
|
+
const {
|
|
68
|
+
offsetTop: firstRectDownOffsetTop
|
|
69
|
+
} = firstRectDown.rect.current;
|
|
70
|
+
|
|
71
|
+
if (rectOffsetTop + threshold > collisionRect.top && rectOffsetTop < firstRectDownOffsetTop) {
|
|
72
|
+
return container;
|
|
100
73
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return firstRectDown;
|
|
77
|
+
}, {
|
|
78
|
+
id: DUMMY_ID,
|
|
79
|
+
rect: {
|
|
80
|
+
current: RECT_DOWN
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
} else {
|
|
84
|
+
// Down -- We need to find the first rectangle upwards
|
|
85
|
+
collidingContainer = droppableContainers.reduce((firstRectUp, container) => {
|
|
86
|
+
const rect = container.rect.current;
|
|
87
|
+
|
|
88
|
+
if (rect && firstRectUp.rect.current) {
|
|
89
|
+
const {
|
|
90
|
+
offsetTop: rectOffsetTop
|
|
91
|
+
} = rect;
|
|
92
|
+
const {
|
|
93
|
+
offsetTop: firstRectUpOffsetTop
|
|
94
|
+
} = firstRectUp.rect.current;
|
|
95
|
+
|
|
96
|
+
if (rectOffsetTop - threshold < collisionRect.top && rectOffsetTop > firstRectUpOffsetTop) {
|
|
97
|
+
return container;
|
|
107
98
|
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return firstRectUp;
|
|
102
|
+
}, {
|
|
103
|
+
id: DUMMY_ID,
|
|
104
|
+
rect: {
|
|
105
|
+
current: RECT_UP
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} // If we didn't find a match, return null
|
|
111
109
|
|
|
112
|
-
if (collidingContainer.id === DUMMY_ID) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
110
|
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
if (collidingContainer.id === DUMMY_ID) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
118
114
|
|
|
119
|
-
|
|
115
|
+
const collidingRect = collidingContainer.rect.current;
|
|
116
|
+
if (!collidingRect) return null; // Calculate the intersection interval
|
|
120
117
|
|
|
121
|
-
|
|
118
|
+
const [top, bottom] = [Math.max(collisionRect.top, collidingRect.offsetTop), Math.min(collisionRect.bottom, collidingRect.offsetTop + collidingRect.height)]; // Calculate the percentage of intersection
|
|
122
119
|
|
|
123
|
-
|
|
124
|
-
setDropIndicatorPosition(DropIndicatorPosition.Inside);
|
|
125
|
-
} else {
|
|
126
|
-
setDropIndicatorPosition(isUp ? DropIndicatorPosition.Before : DropIndicatorPosition.After);
|
|
127
|
-
}
|
|
120
|
+
const intersectionPercentage = Math.abs(bottom - top) / collidingRect.height;
|
|
128
121
|
|
|
129
|
-
|
|
122
|
+
if (intersectionPercentage > insideThreshold && visibleItemsDictionary[collidingContainer.id].depth + 1 <= maxDragAndDropLevel && collidingContainer.id !== activeId) {
|
|
123
|
+
setDropIndicatorPosition(DropIndicatorPosition.Inside);
|
|
124
|
+
} else {
|
|
125
|
+
setDropIndicatorPosition(isUp ? DropIndicatorPosition.Before : DropIndicatorPosition.After);
|
|
126
|
+
}
|
|
130
127
|
|
|
131
|
-
|
|
132
|
-
};
|
|
128
|
+
if (isUp && lastPosition !== 'up') setLastPosition('up');else if (!isUp && lastPosition !== 'down') setLastPosition('down'); // Return the id of the match rectangle
|
|
133
129
|
|
|
134
|
-
return
|
|
130
|
+
return collidingContainer.id;
|
|
135
131
|
};
|
|
136
132
|
|
|
137
133
|
export { customCollisionDetection };
|
|
@@ -14,6 +14,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
14
14
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
15
15
|
const directions = [KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left];
|
|
16
16
|
const horizontal = [KeyboardCode.Left, KeyboardCode.Right];
|
|
17
|
+
[KeyboardCode.Up, KeyboardCode.Down];
|
|
17
18
|
|
|
18
19
|
const getVerticalKeyboardCoordinates = _ref => {
|
|
19
20
|
var _droppableContainers$, _droppableContainers$2;
|
|
@@ -13,8 +13,7 @@ const useTreeActionHandlers = _ref => {
|
|
|
13
13
|
onReorder,
|
|
14
14
|
flattenedItems,
|
|
15
15
|
projected,
|
|
16
|
-
dropIndicatorPosition
|
|
17
|
-
isDropValid
|
|
16
|
+
dropIndicatorPosition
|
|
18
17
|
} = _ref;
|
|
19
18
|
const onDragStart = useCallback(e => {
|
|
20
19
|
handlePreviewDragStart(e);
|
|
@@ -31,15 +30,17 @@ const useTreeActionHandlers = _ref => {
|
|
|
31
30
|
active,
|
|
32
31
|
over
|
|
33
32
|
} = e;
|
|
34
|
-
if (over === null
|
|
33
|
+
if (over === null) return;
|
|
35
34
|
const activeIndex = flattenedItems.findIndex(item => item.uid === active.id);
|
|
36
35
|
let considerExpanding = null;
|
|
37
36
|
let overIndex = flattenedItems.findIndex(item => item.uid === over.id); // If drop indicator is inside, then put it last,
|
|
38
37
|
// It will be reconstructed well later
|
|
39
38
|
|
|
40
39
|
if (dropIndicatorPosition === DropIndicatorPosition.Inside) {
|
|
40
|
+
var _flattenedItems$overI, _flattenedItems$overI2;
|
|
41
|
+
|
|
41
42
|
considerExpanding = over.id;
|
|
42
|
-
overIndex = flattenedItems[overIndex].realIndex + flattenedItems[overIndex].
|
|
43
|
+
overIndex = flattenedItems[overIndex].realIndex + ((_flattenedItems$overI = (_flattenedItems$overI2 = flattenedItems[overIndex].original.subRows) === null || _flattenedItems$overI2 === void 0 ? void 0 : _flattenedItems$overI2.length) !== null && _flattenedItems$overI !== void 0 ? _flattenedItems$overI : 0) + 1;
|
|
43
44
|
} // If we are dropping the item in a new position, or new depth
|
|
44
45
|
|
|
45
46
|
|
|
@@ -54,7 +55,7 @@ const useTreeActionHandlers = _ref => {
|
|
|
54
55
|
fromIndex: activeIndex
|
|
55
56
|
}, considerExpanding || '');
|
|
56
57
|
}
|
|
57
|
-
}, [handlePreviewDragEnd,
|
|
58
|
+
}, [handlePreviewDragEnd, flattenedItems, projected, onReorder, dropIndicatorPosition]);
|
|
58
59
|
const onDragCancel = useCallback(e => {
|
|
59
60
|
handlePreviewDragCancel(e);
|
|
60
61
|
}, [handlePreviewDragCancel]);
|
|
@@ -9,6 +9,7 @@ import 'core-js/modules/esnext.iterator.constructor.js';
|
|
|
9
9
|
import 'core-js/modules/esnext.iterator.for-each.js';
|
|
10
10
|
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
11
11
|
import { MeasuringStrategy, useSensors, useSensor, PointerSensor, KeyboardSensor } from '@dnd-kit/core';
|
|
12
|
+
import { horizontalListSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
12
13
|
import { useTreePreviewHandlers } from './useTreePreviewHandlers.js';
|
|
13
14
|
import { getTreeKeyboardCoordinates } from './getTreeKeyboardCoordinates.js';
|
|
14
15
|
import { removeChildrenOf, getProjection } from './utilities.js';
|
|
@@ -22,29 +23,25 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
22
23
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
23
24
|
// if second parameter is true, the space will be done on the horizontal axis
|
|
24
25
|
|
|
25
|
-
const adjustTranslate = isHorizontalDnD => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} = _ref;
|
|
30
|
-
|
|
31
|
-
const newTransform = _objectSpread({}, transform);
|
|
26
|
+
const adjustTranslate = isHorizontalDnD => _ref => {
|
|
27
|
+
let {
|
|
28
|
+
transform
|
|
29
|
+
} = _ref;
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
newTransform.x = transform.x + 25;
|
|
35
|
-
} else {
|
|
36
|
-
newTransform.x = transform.x + 15;
|
|
37
|
-
}
|
|
31
|
+
const newTransform = _objectSpread({}, transform);
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
if (isHorizontalDnD) {
|
|
34
|
+
newTransform.x = transform.x + 25;
|
|
35
|
+
} else {
|
|
36
|
+
newTransform.x = transform.x + 15;
|
|
37
|
+
}
|
|
41
38
|
|
|
42
|
-
return
|
|
39
|
+
return newTransform;
|
|
43
40
|
};
|
|
44
41
|
|
|
45
42
|
const measuring = {
|
|
46
43
|
droppable: {
|
|
47
|
-
strategy: MeasuringStrategy.
|
|
44
|
+
strategy: MeasuringStrategy.BeforeDragging
|
|
48
45
|
}
|
|
49
46
|
};
|
|
50
47
|
const useTreeDndkitConfig = _ref2 => {
|
|
@@ -56,7 +53,6 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
56
53
|
isHorizontalDnD = false,
|
|
57
54
|
isExpandable = false,
|
|
58
55
|
onReorder,
|
|
59
|
-
getIsDropValid = () => true,
|
|
60
56
|
maxDragAndDropLevel
|
|
61
57
|
} = _ref2;
|
|
62
58
|
const [activeId, setActiveId] = useState('');
|
|
@@ -81,10 +77,6 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
81
77
|
});
|
|
82
78
|
return dictionary;
|
|
83
79
|
}, [visibleItems]);
|
|
84
|
-
const isDropValid = useMemo(() => {
|
|
85
|
-
if (!activeId || !overId) return true;
|
|
86
|
-
return getIsDropValid(visibleItemsDictionary[activeId], visibleItemsDictionary[overId], ['none', 'before', 'after', 'inside'][dropIndicatorPosition]);
|
|
87
|
-
}, [getIsDropValid, visibleItemsDictionary, activeId, overId, dropIndicatorPosition]);
|
|
88
80
|
const modifiers = useMemo(() => [adjustTranslate(isHorizontalDnD)], [isHorizontalDnD]);
|
|
89
81
|
const sensorContext = useRef({
|
|
90
82
|
items: visibleItems,
|
|
@@ -113,8 +105,7 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
113
105
|
onReorder,
|
|
114
106
|
projected,
|
|
115
107
|
flattenedItems,
|
|
116
|
-
dropIndicatorPosition
|
|
117
|
-
isDropValid
|
|
108
|
+
dropIndicatorPosition
|
|
118
109
|
}));
|
|
119
110
|
const announcements = useTreeAnnouncements(visibleItemsDictionary, dropIndicatorPosition);
|
|
120
111
|
const dndContextProps = useMemo(() => _objectSpread({
|
|
@@ -126,12 +117,11 @@ const useTreeDndkitConfig = _ref2 => {
|
|
|
126
117
|
}, dragActionHandlers), [announcements, modifiers, sensors, dragActionHandlers, visibleItemsDictionary, setDropIndicatorPosition, activeId, maxDragAndDropLevel, lastPosition, setLastPosition]);
|
|
127
118
|
const sortableContextProps = useMemo(() => ({
|
|
128
119
|
items: sortedIds,
|
|
129
|
-
strategy:
|
|
130
|
-
}), [sortedIds]);
|
|
120
|
+
strategy: isHorizontalDnD ? horizontalListSortingStrategy : verticalListSortingStrategy
|
|
121
|
+
}), [sortedIds, isHorizontalDnD]);
|
|
131
122
|
return {
|
|
132
123
|
dndContextProps,
|
|
133
124
|
sortableContextProps,
|
|
134
|
-
isDropValid,
|
|
135
125
|
activeId,
|
|
136
126
|
activeIndex: (_visibleItemsDictiona = (_visibleItemsDictiona2 = visibleItemsDictionary[activeId]) === null || _visibleItemsDictiona2 === void 0 ? void 0 : _visibleItemsDictiona2.realIndex) !== null && _visibleItemsDictiona !== void 0 ? _visibleItemsDictiona : -1,
|
|
137
127
|
overId,
|
package/package.json
CHANGED
|
@@ -64,7 +64,7 @@ export declare type useHierarchyDndkitConfigReturn = {
|
|
|
64
64
|
overId: string | null;
|
|
65
65
|
activeIndex: number | undefined;
|
|
66
66
|
};
|
|
67
|
-
export declare type
|
|
67
|
+
export declare type getKeyboardCoordinatesArgs = {
|
|
68
68
|
items: Item[];
|
|
69
69
|
active: Active | null;
|
|
70
70
|
over: Over | null;
|
package/types/tree/types.d.ts
CHANGED
|
@@ -4,13 +4,12 @@ import type { SortingStrategy } from '@dnd-kit/sortable';
|
|
|
4
4
|
import { Coordinates } from '@dnd-kit/core/dist/types';
|
|
5
5
|
import React, { MutableRefObject } from 'react';
|
|
6
6
|
import { DropIndicatorPosition } from './constants';
|
|
7
|
-
export declare type Item
|
|
7
|
+
export declare type Item = {
|
|
8
8
|
uid: string;
|
|
9
9
|
depth: number;
|
|
10
|
-
parentId: string
|
|
10
|
+
parentId: string;
|
|
11
11
|
realIndex: number;
|
|
12
|
-
|
|
13
|
-
original: T;
|
|
12
|
+
original: Record<string, Record<string, any>>;
|
|
14
13
|
};
|
|
15
14
|
export declare type DndContextPropsType = {
|
|
16
15
|
announcements: Announcements;
|
|
@@ -28,51 +27,49 @@ export declare type SortableContextPropsType = {
|
|
|
28
27
|
items: string[];
|
|
29
28
|
strategy: SortingStrategy;
|
|
30
29
|
};
|
|
31
|
-
export declare type
|
|
30
|
+
export declare type useTreePreviewHandlersReturn = {
|
|
32
31
|
handlePreviewDragStart: (e: DragStartEvent) => void;
|
|
33
32
|
handlePreviewDragMove: (e: DragMoveEvent) => void;
|
|
34
33
|
handlePreviewDragOver: (e: DragOverEvent) => void;
|
|
35
34
|
handlePreviewDragEnd: (e: DragEndEvent) => void;
|
|
36
35
|
handlePreviewDragCancel: (e: DragCancelEvent) => void;
|
|
37
36
|
};
|
|
38
|
-
export declare type
|
|
37
|
+
export declare type useTreePreviewHandlersArgs = {
|
|
39
38
|
setOverId: React.Dispatch<React.SetStateAction<string>>;
|
|
40
39
|
setActiveId: React.Dispatch<React.SetStateAction<string>>;
|
|
41
40
|
setDropIndicatorPosition: React.Dispatch<React.SetStateAction<DropIndicatorPosition>>;
|
|
42
41
|
};
|
|
43
|
-
export declare type
|
|
42
|
+
export declare type useTreeActionHandlersArgs = useTreePreviewHandlersReturn & {
|
|
44
43
|
dropIndicatorPosition: DropIndicatorPosition;
|
|
45
44
|
flattenedItems: Item[];
|
|
46
45
|
projected: {
|
|
47
46
|
depth: number;
|
|
48
47
|
parentId: string;
|
|
49
48
|
} | null;
|
|
50
|
-
onReorder:
|
|
49
|
+
onReorder: (newData: Item[], indexes: {
|
|
51
50
|
targetIndex: number;
|
|
52
51
|
fromIndex: number;
|
|
53
52
|
}, considerExpanding: string) => void;
|
|
54
|
-
isDropValid: boolean;
|
|
55
53
|
};
|
|
56
|
-
export declare type
|
|
54
|
+
export declare type useTreeActionHandlersReturn = {
|
|
57
55
|
onDragStart: (e: DragStartEvent) => void;
|
|
58
56
|
onDragMove: (e: DragMoveEvent) => void;
|
|
59
57
|
onDragOver: (e: DragOverEvent) => void;
|
|
60
58
|
onDragEnd: (e: DragEndEvent) => void;
|
|
61
59
|
onDragCancel: (e: DragCancelEvent) => void;
|
|
62
60
|
};
|
|
63
|
-
export declare type
|
|
61
|
+
export declare type useTreeDndkitConfigArgs = {
|
|
64
62
|
flattenedItems: Item[];
|
|
65
63
|
visibleItems: Item[];
|
|
66
64
|
isHorizontalDnD?: boolean;
|
|
67
65
|
isExpandable: boolean;
|
|
68
|
-
onReorder:
|
|
66
|
+
onReorder: (newData: Item[], indexes: {
|
|
69
67
|
targetIndex: number;
|
|
70
68
|
fromIndex: number;
|
|
71
69
|
}, considerExpanding: string) => void;
|
|
72
|
-
getIsDropValid: <S = T>(active: Item<S>, over: Item<S>, dropIndicatorPosition: 'none' | 'before' | 'after' | 'inside') => boolean;
|
|
73
70
|
maxDragAndDropLevel: number;
|
|
74
71
|
};
|
|
75
|
-
export declare type
|
|
72
|
+
export declare type useTreeDndkitConfigReturn = {
|
|
76
73
|
dndContextProps: DndContextPropsType;
|
|
77
74
|
sortableContextProps: SortableContextPropsType;
|
|
78
75
|
activeId: string;
|
|
@@ -80,11 +77,10 @@ export declare type UseTreeDndkitConfigReturn = {
|
|
|
80
77
|
overId: string;
|
|
81
78
|
depth: number;
|
|
82
79
|
dropIndicatorPosition: DropIndicatorPosition;
|
|
83
|
-
isDropValid: boolean;
|
|
84
80
|
visibleItems: Item[];
|
|
85
81
|
};
|
|
86
|
-
export declare type
|
|
87
|
-
export declare type
|
|
82
|
+
export declare type useTreeDndkitConfigType = (args: useTreeDndkitConfigArgs) => useTreeDndkitConfigReturn;
|
|
83
|
+
export declare type getKeyboardCoordinatesArgs = {
|
|
88
84
|
items: Item[];
|
|
89
85
|
active: Active;
|
|
90
86
|
over: Over;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const useTreeActionHandlers: ({ handlePreviewDragStart, handlePreviewDragMove, handlePreviewDragOver, handlePreviewDragEnd, handlePreviewDragCancel, onReorder, flattenedItems, projected, dropIndicatorPosition,
|
|
1
|
+
import type { useTreeActionHandlersReturn, useTreeActionHandlersArgs } from './types';
|
|
2
|
+
export declare const useTreeActionHandlers: ({ handlePreviewDragStart, handlePreviewDragMove, handlePreviewDragOver, handlePreviewDragEnd, handlePreviewDragCancel, onReorder, flattenedItems, projected, dropIndicatorPosition, }: useTreeActionHandlersArgs) => useTreeActionHandlersReturn;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const useTreeDndkitConfig:
|
|
1
|
+
import type { useTreeDndkitConfigType } from './types';
|
|
2
|
+
export declare const useTreeDndkitConfig: useTreeDndkitConfigType;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const useTreePreviewHandlers: ({ setOverId, setActiveId, setDropIndicatorPosition, }:
|
|
1
|
+
import type { useTreePreviewHandlersReturn, useTreePreviewHandlersArgs } from './types';
|
|
2
|
+
export declare const useTreePreviewHandlers: ({ setOverId, setActiveId, setDropIndicatorPosition, }: useTreePreviewHandlersArgs) => useTreePreviewHandlersReturn;
|