@react-aria/dnd 3.0.0-alpha.9 → 3.0.0-nightly-4980928d3-240906
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/DragManager.main.js +432 -0
- package/dist/DragManager.main.js.map +1 -0
- package/dist/DragManager.mjs +423 -0
- package/dist/DragManager.module.js +423 -0
- package/dist/DragManager.module.js.map +1 -0
- package/dist/DragPreview.main.js +59 -0
- package/dist/DragPreview.main.js.map +1 -0
- package/dist/DragPreview.mjs +50 -0
- package/dist/DragPreview.module.js +50 -0
- package/dist/DragPreview.module.js.map +1 -0
- package/dist/ListDropTargetDelegate.main.js +123 -0
- package/dist/ListDropTargetDelegate.main.js.map +1 -0
- package/dist/ListDropTargetDelegate.mjs +118 -0
- package/dist/ListDropTargetDelegate.module.js +118 -0
- package/dist/ListDropTargetDelegate.module.js.map +1 -0
- package/dist/ar-AE.main.js +44 -0
- package/dist/ar-AE.main.js.map +1 -0
- package/dist/ar-AE.mjs +46 -0
- package/dist/ar-AE.module.js +46 -0
- package/dist/ar-AE.module.js.map +1 -0
- package/dist/bg-BG.main.js +44 -0
- package/dist/bg-BG.main.js.map +1 -0
- package/dist/bg-BG.mjs +46 -0
- package/dist/bg-BG.module.js +46 -0
- package/dist/bg-BG.module.js.map +1 -0
- package/dist/constants.main.js +65 -0
- package/dist/constants.main.js.map +1 -0
- package/dist/constants.mjs +53 -0
- package/dist/constants.module.js +53 -0
- package/dist/constants.module.js.map +1 -0
- package/dist/cs-CZ.main.js +45 -0
- package/dist/cs-CZ.main.js.map +1 -0
- package/dist/cs-CZ.mjs +47 -0
- package/dist/cs-CZ.module.js +47 -0
- package/dist/cs-CZ.module.js.map +1 -0
- package/dist/da-DK.main.js +44 -0
- package/dist/da-DK.main.js.map +1 -0
- package/dist/da-DK.mjs +46 -0
- package/dist/da-DK.module.js +46 -0
- package/dist/da-DK.module.js.map +1 -0
- package/dist/de-DE.main.js +44 -0
- package/dist/de-DE.main.js.map +1 -0
- package/dist/de-DE.mjs +46 -0
- package/dist/de-DE.module.js +46 -0
- package/dist/de-DE.module.js.map +1 -0
- package/dist/el-GR.main.js +44 -0
- package/dist/el-GR.main.js.map +1 -0
- package/dist/el-GR.mjs +46 -0
- package/dist/el-GR.module.js +46 -0
- package/dist/el-GR.module.js.map +1 -0
- package/dist/en-US.main.js +44 -0
- package/dist/en-US.main.js.map +1 -0
- package/dist/en-US.mjs +46 -0
- package/dist/en-US.module.js +46 -0
- package/dist/en-US.module.js.map +1 -0
- package/dist/es-ES.main.js +44 -0
- package/dist/es-ES.main.js.map +1 -0
- package/dist/es-ES.mjs +46 -0
- package/dist/es-ES.module.js +46 -0
- package/dist/es-ES.module.js.map +1 -0
- package/dist/et-EE.main.js +44 -0
- package/dist/et-EE.main.js.map +1 -0
- package/dist/et-EE.mjs +46 -0
- package/dist/et-EE.module.js +46 -0
- package/dist/et-EE.module.js.map +1 -0
- package/dist/fi-FI.main.js +44 -0
- package/dist/fi-FI.main.js.map +1 -0
- package/dist/fi-FI.mjs +46 -0
- package/dist/fi-FI.module.js +46 -0
- package/dist/fi-FI.module.js.map +1 -0
- package/dist/fr-FR.main.js +44 -0
- package/dist/fr-FR.main.js.map +1 -0
- package/dist/fr-FR.mjs +46 -0
- package/dist/fr-FR.module.js +46 -0
- package/dist/fr-FR.module.js.map +1 -0
- package/dist/he-IL.main.js +44 -0
- package/dist/he-IL.main.js.map +1 -0
- package/dist/he-IL.mjs +46 -0
- package/dist/he-IL.module.js +46 -0
- package/dist/he-IL.module.js.map +1 -0
- package/dist/hr-HR.main.js +44 -0
- package/dist/hr-HR.main.js.map +1 -0
- package/dist/hr-HR.mjs +46 -0
- package/dist/hr-HR.module.js +46 -0
- package/dist/hr-HR.module.js.map +1 -0
- package/dist/hu-HU.main.js +44 -0
- package/dist/hu-HU.main.js.map +1 -0
- package/dist/hu-HU.mjs +46 -0
- package/dist/hu-HU.module.js +46 -0
- package/dist/hu-HU.module.js.map +1 -0
- package/dist/import.mjs +39 -0
- package/dist/intlStrings.main.js +108 -0
- package/dist/intlStrings.main.js.map +1 -0
- package/dist/intlStrings.mjs +110 -0
- package/dist/intlStrings.module.js +110 -0
- package/dist/intlStrings.module.js.map +1 -0
- package/dist/it-IT.main.js +44 -0
- package/dist/it-IT.main.js.map +1 -0
- package/dist/it-IT.mjs +46 -0
- package/dist/it-IT.module.js +46 -0
- package/dist/it-IT.module.js.map +1 -0
- package/dist/ja-JP.main.js +44 -0
- package/dist/ja-JP.main.js.map +1 -0
- package/dist/ja-JP.mjs +46 -0
- package/dist/ja-JP.module.js +46 -0
- package/dist/ja-JP.module.js.map +1 -0
- package/dist/ko-KR.main.js +44 -0
- package/dist/ko-KR.main.js.map +1 -0
- package/dist/ko-KR.mjs +46 -0
- package/dist/ko-KR.module.js +46 -0
- package/dist/ko-KR.module.js.map +1 -0
- package/dist/lt-LT.main.js +44 -0
- package/dist/lt-LT.main.js.map +1 -0
- package/dist/lt-LT.mjs +46 -0
- package/dist/lt-LT.module.js +46 -0
- package/dist/lt-LT.module.js.map +1 -0
- package/dist/lv-LV.main.js +44 -0
- package/dist/lv-LV.main.js.map +1 -0
- package/dist/lv-LV.mjs +46 -0
- package/dist/lv-LV.module.js +46 -0
- package/dist/lv-LV.module.js.map +1 -0
- package/dist/main.js +39 -1873
- package/dist/main.js.map +1 -1
- package/dist/module.js +24 -1853
- package/dist/module.js.map +1 -1
- package/dist/nb-NO.main.js +44 -0
- package/dist/nb-NO.main.js.map +1 -0
- package/dist/nb-NO.mjs +46 -0
- package/dist/nb-NO.module.js +46 -0
- package/dist/nb-NO.module.js.map +1 -0
- package/dist/nl-NL.main.js +44 -0
- package/dist/nl-NL.main.js.map +1 -0
- package/dist/nl-NL.mjs +46 -0
- package/dist/nl-NL.module.js +46 -0
- package/dist/nl-NL.module.js.map +1 -0
- package/dist/pl-PL.main.js +44 -0
- package/dist/pl-PL.main.js.map +1 -0
- package/dist/pl-PL.mjs +46 -0
- package/dist/pl-PL.module.js +46 -0
- package/dist/pl-PL.module.js.map +1 -0
- package/dist/pt-BR.main.js +44 -0
- package/dist/pt-BR.main.js.map +1 -0
- package/dist/pt-BR.mjs +46 -0
- package/dist/pt-BR.module.js +46 -0
- package/dist/pt-BR.module.js.map +1 -0
- package/dist/pt-PT.main.js +44 -0
- package/dist/pt-PT.main.js.map +1 -0
- package/dist/pt-PT.mjs +46 -0
- package/dist/pt-PT.module.js +46 -0
- package/dist/pt-PT.module.js.map +1 -0
- package/dist/ro-RO.main.js +44 -0
- package/dist/ro-RO.main.js.map +1 -0
- package/dist/ro-RO.mjs +46 -0
- package/dist/ro-RO.module.js +46 -0
- package/dist/ro-RO.module.js.map +1 -0
- package/dist/ru-RU.main.js +44 -0
- package/dist/ru-RU.main.js.map +1 -0
- package/dist/ru-RU.mjs +46 -0
- package/dist/ru-RU.module.js +46 -0
- package/dist/ru-RU.module.js.map +1 -0
- package/dist/sk-SK.main.js +44 -0
- package/dist/sk-SK.main.js.map +1 -0
- package/dist/sk-SK.mjs +46 -0
- package/dist/sk-SK.module.js +46 -0
- package/dist/sk-SK.module.js.map +1 -0
- package/dist/sl-SI.main.js +44 -0
- package/dist/sl-SI.main.js.map +1 -0
- package/dist/sl-SI.mjs +46 -0
- package/dist/sl-SI.module.js +46 -0
- package/dist/sl-SI.module.js.map +1 -0
- package/dist/sr-SP.main.js +44 -0
- package/dist/sr-SP.main.js.map +1 -0
- package/dist/sr-SP.mjs +46 -0
- package/dist/sr-SP.module.js +46 -0
- package/dist/sr-SP.module.js.map +1 -0
- package/dist/sv-SE.main.js +44 -0
- package/dist/sv-SE.main.js.map +1 -0
- package/dist/sv-SE.mjs +46 -0
- package/dist/sv-SE.module.js +46 -0
- package/dist/sv-SE.module.js.map +1 -0
- package/dist/tr-TR.main.js +44 -0
- package/dist/tr-TR.main.js.map +1 -0
- package/dist/tr-TR.mjs +46 -0
- package/dist/tr-TR.module.js +46 -0
- package/dist/tr-TR.module.js.map +1 -0
- package/dist/types.d.ts +177 -29
- package/dist/types.d.ts.map +1 -1
- package/dist/uk-UA.main.js +44 -0
- package/dist/uk-UA.main.js.map +1 -0
- package/dist/uk-UA.mjs +46 -0
- package/dist/uk-UA.module.js +46 -0
- package/dist/uk-UA.module.js.map +1 -0
- package/dist/useAutoScroll.main.js +89 -0
- package/dist/useAutoScroll.main.js.map +1 -0
- package/dist/useAutoScroll.mjs +84 -0
- package/dist/useAutoScroll.module.js +84 -0
- package/dist/useAutoScroll.module.js.map +1 -0
- package/dist/useClipboard.main.js +107 -0
- package/dist/useClipboard.main.js.map +1 -0
- package/dist/useClipboard.mjs +102 -0
- package/dist/useClipboard.module.js +102 -0
- package/dist/useClipboard.module.js.map +1 -0
- package/dist/useDrag.main.js +286 -0
- package/dist/useDrag.main.js.map +1 -0
- package/dist/useDrag.mjs +281 -0
- package/dist/useDrag.module.js +281 -0
- package/dist/useDrag.module.js.map +1 -0
- package/dist/useDraggableCollection.main.js +27 -0
- package/dist/useDraggableCollection.main.js.map +1 -0
- package/dist/useDraggableCollection.mjs +22 -0
- package/dist/useDraggableCollection.module.js +22 -0
- package/dist/useDraggableCollection.module.js.map +1 -0
- package/dist/useDraggableItem.main.js +128 -0
- package/dist/useDraggableItem.main.js.map +1 -0
- package/dist/useDraggableItem.mjs +123 -0
- package/dist/useDraggableItem.module.js +123 -0
- package/dist/useDraggableItem.module.js.map +1 -0
- package/dist/useDrop.main.js +299 -0
- package/dist/useDrop.main.js.map +1 -0
- package/dist/useDrop.mjs +294 -0
- package/dist/useDrop.module.js +294 -0
- package/dist/useDrop.module.js.map +1 -0
- package/dist/useDropIndicator.main.js +93 -0
- package/dist/useDropIndicator.main.js.map +1 -0
- package/dist/useDropIndicator.mjs +88 -0
- package/dist/useDropIndicator.module.js +88 -0
- package/dist/useDropIndicator.module.js.map +1 -0
- package/dist/useDroppableCollection.main.js +592 -0
- package/dist/useDroppableCollection.main.js.map +1 -0
- package/dist/useDroppableCollection.mjs +587 -0
- package/dist/useDroppableCollection.module.js +587 -0
- package/dist/useDroppableCollection.module.js.map +1 -0
- package/dist/useDroppableItem.main.js +79 -0
- package/dist/useDroppableItem.main.js.map +1 -0
- package/dist/useDroppableItem.mjs +74 -0
- package/dist/useDroppableItem.module.js +74 -0
- package/dist/useDroppableItem.module.js.map +1 -0
- package/dist/useVirtualDrop.main.js +56 -0
- package/dist/useVirtualDrop.main.js.map +1 -0
- package/dist/useVirtualDrop.mjs +51 -0
- package/dist/useVirtualDrop.module.js +51 -0
- package/dist/useVirtualDrop.module.js.map +1 -0
- package/dist/utils.main.js +283 -0
- package/dist/utils.main.js.map +1 -0
- package/dist/utils.mjs +255 -0
- package/dist/utils.module.js +255 -0
- package/dist/utils.module.js.map +1 -0
- package/dist/zh-CN.main.js +44 -0
- package/dist/zh-CN.main.js.map +1 -0
- package/dist/zh-CN.mjs +46 -0
- package/dist/zh-CN.module.js +46 -0
- package/dist/zh-CN.module.js.map +1 -0
- package/dist/zh-TW.main.js +44 -0
- package/dist/zh-TW.main.js.map +1 -0
- package/dist/zh-TW.mjs +46 -0
- package/dist/zh-TW.module.js +46 -0
- package/dist/zh-TW.module.js.map +1 -0
- package/package.json +20 -16
- package/src/DragManager.ts +87 -52
- package/src/DragPreview.tsx +3 -3
- package/src/ListDropTargetDelegate.ts +173 -0
- package/src/constants.ts +2 -0
- package/src/index.ts +55 -9
- package/src/useAutoScroll.ts +26 -6
- package/src/useClipboard.ts +65 -59
- package/src/useDrag.ts +179 -31
- package/src/useDraggableCollection.ts +29 -0
- package/src/useDraggableItem.ts +105 -12
- package/src/useDrop.ts +273 -93
- package/src/useDropIndicator.ts +47 -21
- package/src/useDroppableCollection.ts +315 -115
- package/src/useDroppableItem.ts +33 -17
- package/src/useVirtualDrop.ts +5 -5
- package/src/utils.ts +92 -17
- package/LICENSE +0 -201
|
@@ -10,23 +10,47 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
clearGlobalDnDState,
|
|
15
|
+
DIRECTORY_DRAG_TYPE,
|
|
16
|
+
droppableCollectionMap,
|
|
17
|
+
getTypes,
|
|
18
|
+
globalDndState,
|
|
19
|
+
isInternalDropOperation,
|
|
20
|
+
setDropCollectionRef
|
|
21
|
+
} from './utils';
|
|
22
|
+
import {
|
|
23
|
+
Collection,
|
|
24
|
+
DropEvent,
|
|
25
|
+
DropOperation,
|
|
26
|
+
DroppableCollectionDropEvent,
|
|
27
|
+
DroppableCollectionProps,
|
|
28
|
+
DropPosition,
|
|
29
|
+
DropTarget,
|
|
30
|
+
DropTargetDelegate,
|
|
31
|
+
Key,
|
|
32
|
+
KeyboardDelegate,
|
|
33
|
+
Node,
|
|
34
|
+
RefObject
|
|
35
|
+
} from '@react-types/shared';
|
|
14
36
|
import * as DragManager from './DragManager';
|
|
15
37
|
import {DroppableCollectionState} from '@react-stately/dnd';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {mergeProps, useLayoutEffect} from '@react-aria/utils';
|
|
38
|
+
import {HTMLAttributes, useCallback, useEffect, useRef} from 'react';
|
|
39
|
+
import {mergeProps, useId, useLayoutEffect} from '@react-aria/utils';
|
|
19
40
|
import {setInteractionModality} from '@react-aria/interactions';
|
|
20
41
|
import {useAutoScroll} from './useAutoScroll';
|
|
21
42
|
import {useDrop} from './useDrop';
|
|
22
|
-
import {
|
|
43
|
+
import {useLocale} from '@react-aria/i18n';
|
|
23
44
|
|
|
24
45
|
export interface DroppableCollectionOptions extends DroppableCollectionProps {
|
|
46
|
+
/** A delegate object that implements behavior for keyboard focus movement. */
|
|
25
47
|
keyboardDelegate: KeyboardDelegate,
|
|
26
|
-
|
|
48
|
+
/** A delegate object that provides drop targets for pointer coordinates within the collection. */
|
|
49
|
+
dropTargetDelegate: DropTargetDelegate
|
|
27
50
|
}
|
|
28
51
|
|
|
29
52
|
export interface DroppableCollectionResult {
|
|
53
|
+
/** Props for the collection element. */
|
|
30
54
|
collectionProps: HTMLAttributes<HTMLElement>
|
|
31
55
|
}
|
|
32
56
|
|
|
@@ -34,12 +58,20 @@ interface DroppingState {
|
|
|
34
58
|
collection: Collection<Node<unknown>>,
|
|
35
59
|
focusedKey: Key,
|
|
36
60
|
selectedKeys: Set<Key>,
|
|
37
|
-
|
|
61
|
+
target: DropTarget,
|
|
62
|
+
draggingKeys: Set<Key>,
|
|
63
|
+
isInternal: boolean,
|
|
64
|
+
timeout: ReturnType<typeof setTimeout>
|
|
38
65
|
}
|
|
39
66
|
|
|
40
67
|
const DROP_POSITIONS: DropPosition[] = ['before', 'on', 'after'];
|
|
68
|
+
const DROP_POSITIONS_RTL: DropPosition[] = ['after', 'on', 'before'];
|
|
41
69
|
|
|
42
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Handles drop interactions for a collection component, with support for traditional mouse and touch
|
|
72
|
+
* based drag and drop, in addition to full parity for keyboard and screen reader users.
|
|
73
|
+
*/
|
|
74
|
+
export function useDroppableCollection(props: DroppableCollectionOptions, state: DroppableCollectionState, ref: RefObject<HTMLElement | null>): DroppableCollectionResult {
|
|
43
75
|
let localState = useRef({
|
|
44
76
|
props,
|
|
45
77
|
state,
|
|
@@ -49,41 +81,113 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
49
81
|
localState.props = props;
|
|
50
82
|
localState.state = state;
|
|
51
83
|
|
|
84
|
+
let defaultOnDrop = useCallback(async (e: DroppableCollectionDropEvent) => {
|
|
85
|
+
let {
|
|
86
|
+
onInsert,
|
|
87
|
+
onRootDrop,
|
|
88
|
+
onItemDrop,
|
|
89
|
+
onReorder,
|
|
90
|
+
acceptedDragTypes = 'all',
|
|
91
|
+
shouldAcceptItemDrop
|
|
92
|
+
} = localState.props;
|
|
93
|
+
|
|
94
|
+
let {draggingKeys} = globalDndState;
|
|
95
|
+
let isInternal = isInternalDropOperation(ref);
|
|
96
|
+
let {
|
|
97
|
+
target,
|
|
98
|
+
dropOperation,
|
|
99
|
+
items
|
|
100
|
+
} = e;
|
|
101
|
+
|
|
102
|
+
let filteredItems = items;
|
|
103
|
+
if (acceptedDragTypes !== 'all' || shouldAcceptItemDrop) {
|
|
104
|
+
filteredItems = items.filter(item => {
|
|
105
|
+
let itemTypes: Set<string | symbol>;
|
|
106
|
+
if (item.kind === 'directory') {
|
|
107
|
+
itemTypes = new Set([DIRECTORY_DRAG_TYPE]);
|
|
108
|
+
} else {
|
|
109
|
+
itemTypes = item.kind === 'file' ? new Set([item.type]) : item.types;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (acceptedDragTypes === 'all' || acceptedDragTypes.some(type => itemTypes.has(type))) {
|
|
113
|
+
// If we are performing a on item drop, check if the item in question accepts the dropped item since the item may have heavier restrictions
|
|
114
|
+
// than the droppable collection itself
|
|
115
|
+
if (target.type === 'item' && target.dropPosition === 'on' && shouldAcceptItemDrop) {
|
|
116
|
+
return shouldAcceptItemDrop(target, itemTypes);
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return false;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (filteredItems.length > 0) {
|
|
126
|
+
if (target.type === 'root' && onRootDrop) {
|
|
127
|
+
await onRootDrop({items: filteredItems, dropOperation});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (target.type === 'item') {
|
|
131
|
+
if (target.dropPosition === 'on' && onItemDrop) {
|
|
132
|
+
await onItemDrop({items: filteredItems, dropOperation, isInternal, target});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (target.dropPosition !== 'on') {
|
|
136
|
+
if (!isInternal && onInsert) {
|
|
137
|
+
await onInsert({items: filteredItems, dropOperation, target});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (isInternal && onReorder) {
|
|
141
|
+
await onReorder({keys: draggingKeys, dropOperation, target});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}, [localState, ref]);
|
|
147
|
+
|
|
52
148
|
let autoScroll = useAutoScroll(ref);
|
|
53
149
|
let {dropProps} = useDrop({
|
|
54
150
|
ref,
|
|
55
|
-
onDropEnter(
|
|
56
|
-
|
|
57
|
-
state.setTarget(target);
|
|
151
|
+
onDropEnter() {
|
|
152
|
+
state.setTarget(localState.nextTarget);
|
|
58
153
|
},
|
|
59
154
|
onDropMove(e) {
|
|
60
155
|
state.setTarget(localState.nextTarget);
|
|
61
156
|
autoScroll.move(e.x, e.y);
|
|
62
157
|
},
|
|
63
158
|
getDropOperationForPoint(types, allowedOperations, x, y) {
|
|
64
|
-
let
|
|
159
|
+
let {draggingKeys, dropCollectionRef} = globalDndState;
|
|
160
|
+
let isInternal = isInternalDropOperation(ref);
|
|
161
|
+
let isValidDropTarget = (target) => state.getDropOperation({target, types, allowedOperations, isInternal, draggingKeys}) !== 'cancel';
|
|
162
|
+
let target = props.dropTargetDelegate.getDropTargetFromPoint(x, y, isValidDropTarget);
|
|
65
163
|
if (!target) {
|
|
66
164
|
localState.dropOperation = 'cancel';
|
|
67
165
|
localState.nextTarget = null;
|
|
68
166
|
return 'cancel';
|
|
69
167
|
}
|
|
70
168
|
|
|
71
|
-
localState.dropOperation = state.getDropOperation(target, types, allowedOperations);
|
|
169
|
+
localState.dropOperation = state.getDropOperation({target, types, allowedOperations, isInternal, draggingKeys});
|
|
72
170
|
|
|
73
171
|
// If the target doesn't accept the drop, see if the root accepts it instead.
|
|
74
172
|
if (localState.dropOperation === 'cancel') {
|
|
75
173
|
let rootTarget: DropTarget = {type: 'root'};
|
|
76
|
-
let dropOperation = state.getDropOperation(rootTarget, types, allowedOperations);
|
|
174
|
+
let dropOperation = state.getDropOperation({target: rootTarget, types, allowedOperations, isInternal, draggingKeys});
|
|
77
175
|
if (dropOperation !== 'cancel') {
|
|
78
176
|
target = rootTarget;
|
|
79
177
|
localState.dropOperation = dropOperation;
|
|
80
178
|
}
|
|
81
179
|
}
|
|
82
180
|
|
|
181
|
+
// Only set dropCollectionRef if there is a valid drop target since we cleanup dropCollectionRef in onDropExit
|
|
182
|
+
// which only runs when leaving a valid drop target or if the dropEffect become none (mouse dnd only).
|
|
183
|
+
if (target && localState.dropOperation !== 'cancel' && ref?.current !== dropCollectionRef?.current) {
|
|
184
|
+
setDropCollectionRef(ref);
|
|
185
|
+
}
|
|
83
186
|
localState.nextTarget = localState.dropOperation === 'cancel' ? null : target;
|
|
84
187
|
return localState.dropOperation;
|
|
85
188
|
},
|
|
86
189
|
onDropExit() {
|
|
190
|
+
setDropCollectionRef(undefined);
|
|
87
191
|
state.setTarget(null);
|
|
88
192
|
autoScroll.stop();
|
|
89
193
|
},
|
|
@@ -98,29 +202,112 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
98
202
|
}
|
|
99
203
|
},
|
|
100
204
|
onDrop(e) {
|
|
101
|
-
|
|
205
|
+
setDropCollectionRef(ref);
|
|
206
|
+
if (state.target) {
|
|
102
207
|
onDrop(e, state.target);
|
|
103
208
|
}
|
|
209
|
+
|
|
210
|
+
// If there wasn't a collection being tracked as a dragged collection, then we are in a case where a non RSP drag is dropped on a
|
|
211
|
+
// RSP collection and thus we don't need to preserve the global DnD state for onDragEnd
|
|
212
|
+
let {draggingCollectionRef} = globalDndState;
|
|
213
|
+
if (draggingCollectionRef == null) {
|
|
214
|
+
clearGlobalDnDState();
|
|
215
|
+
}
|
|
104
216
|
}
|
|
105
217
|
});
|
|
106
218
|
|
|
107
219
|
let droppingState = useRef<DroppingState>(null);
|
|
108
|
-
let
|
|
220
|
+
let updateFocusAfterDrop = useCallback(() => {
|
|
109
221
|
let {state} = localState;
|
|
222
|
+
if (droppingState.current) {
|
|
223
|
+
let {
|
|
224
|
+
target,
|
|
225
|
+
collection: prevCollection,
|
|
226
|
+
selectedKeys: prevSelectedKeys,
|
|
227
|
+
focusedKey: prevFocusedKey,
|
|
228
|
+
isInternal,
|
|
229
|
+
draggingKeys
|
|
230
|
+
} = droppingState.current;
|
|
231
|
+
|
|
232
|
+
// If an insert occurs during a drop, we want to immediately select these items to give
|
|
233
|
+
// feedback to the user that a drop occurred. Only do this if the selection didn't change
|
|
234
|
+
// since the drop started so we don't override if the user or application did something.
|
|
235
|
+
if (
|
|
236
|
+
state.collection.size > prevCollection.size &&
|
|
237
|
+
state.selectionManager.isSelectionEqual(prevSelectedKeys)
|
|
238
|
+
) {
|
|
239
|
+
let newKeys = new Set<Key>();
|
|
240
|
+
for (let key of state.collection.getKeys()) {
|
|
241
|
+
if (!prevCollection.getItem(key)) {
|
|
242
|
+
newKeys.add(key);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
state.selectionManager.setSelectedKeys(newKeys);
|
|
247
|
+
|
|
248
|
+
// If the focused item didn't change since the drop occurred, also focus the first
|
|
249
|
+
// inserted item. If selection is disabled, then also show the focus ring so there
|
|
250
|
+
// is some indication that items were added.
|
|
251
|
+
if (state.selectionManager.focusedKey === prevFocusedKey) {
|
|
252
|
+
let first = newKeys.keys().next().value;
|
|
253
|
+
let item = state.collection.getItem(first);
|
|
110
254
|
|
|
111
|
-
|
|
112
|
-
|
|
255
|
+
// If this is a cell, focus the parent row.
|
|
256
|
+
if (item?.type === 'cell') {
|
|
257
|
+
first = item.parentKey;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
state.selectionManager.setFocusedKey(first);
|
|
261
|
+
|
|
262
|
+
if (state.selectionManager.selectionMode === 'none') {
|
|
263
|
+
setInteractionModality('keyboard');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} else if (
|
|
267
|
+
state.selectionManager.focusedKey === prevFocusedKey &&
|
|
268
|
+
isInternal &&
|
|
269
|
+
target.type === 'item' &&
|
|
270
|
+
target.dropPosition !== 'on' &&
|
|
271
|
+
draggingKeys.has(state.collection.getItem(prevFocusedKey)?.parentKey)
|
|
272
|
+
) {
|
|
273
|
+
// Focus row instead of cell when reordering.
|
|
274
|
+
state.selectionManager.setFocusedKey(state.collection.getItem(prevFocusedKey).parentKey);
|
|
275
|
+
setInteractionModality('keyboard');
|
|
276
|
+
} else if (
|
|
277
|
+
state.selectionManager.focusedKey === prevFocusedKey &&
|
|
278
|
+
target.type === 'item' &&
|
|
279
|
+
target.dropPosition === 'on' &&
|
|
280
|
+
state.collection.getItem(target.key) != null
|
|
281
|
+
) {
|
|
282
|
+
// If focus didn't move already (e.g. due to an insert), and the user dropped on an item,
|
|
283
|
+
// focus that item and show the focus ring to give the user feedback that the drop occurred.
|
|
284
|
+
// Also show the focus ring if the focused key is not selected, e.g. in case of a reorder.
|
|
285
|
+
state.selectionManager.setFocusedKey(target.key);
|
|
286
|
+
setInteractionModality('keyboard');
|
|
287
|
+
} else if (!state.selectionManager.isSelected(state.selectionManager.focusedKey)) {
|
|
288
|
+
setInteractionModality('keyboard');
|
|
289
|
+
}
|
|
113
290
|
|
|
291
|
+
state.selectionManager.setFocused(true);
|
|
292
|
+
}
|
|
293
|
+
}, [localState]);
|
|
294
|
+
|
|
295
|
+
let onDrop = useCallback((e: DropEvent, target: DropTarget) => {
|
|
296
|
+
let {state} = localState;
|
|
297
|
+
|
|
114
298
|
// Save some state of the collection/selection before the drop occurs so we can compare later.
|
|
115
|
-
let focusedKey = state.selectionManager.focusedKey;
|
|
116
299
|
droppingState.current = {
|
|
117
300
|
timeout: null,
|
|
118
|
-
focusedKey,
|
|
301
|
+
focusedKey: state.selectionManager.focusedKey,
|
|
119
302
|
collection: state.collection,
|
|
120
|
-
selectedKeys: state.selectionManager.selectedKeys
|
|
303
|
+
selectedKeys: state.selectionManager.selectedKeys,
|
|
304
|
+
draggingKeys: globalDndState.draggingKeys,
|
|
305
|
+
isInternal: isInternalDropOperation(ref),
|
|
306
|
+
target
|
|
121
307
|
};
|
|
122
308
|
|
|
123
|
-
localState.props.onDrop
|
|
309
|
+
let onDropFn = localState.props.onDrop || defaultOnDrop;
|
|
310
|
+
onDropFn({
|
|
124
311
|
type: 'drop',
|
|
125
312
|
x: e.x, // todo
|
|
126
313
|
y: e.y,
|
|
@@ -130,27 +317,13 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
130
317
|
});
|
|
131
318
|
|
|
132
319
|
// Wait for a short time period after the onDrop is called to allow the data to be read asynchronously
|
|
133
|
-
// and for React to re-render. If
|
|
134
|
-
//
|
|
135
|
-
// selecting and focusing those items themselves.
|
|
320
|
+
// and for React to re-render. If the collection didn't already change during this time (handled below),
|
|
321
|
+
// update the focused key here.
|
|
136
322
|
droppingState.current.timeout = setTimeout(() => {
|
|
137
|
-
|
|
138
|
-
// focus that item and show the focus ring to give the user feedback that the drop occurred.
|
|
139
|
-
// Also show the focus ring if the focused key is not selected, e.g. in case of a reorder.
|
|
140
|
-
let {state} = localState;
|
|
141
|
-
if (state.selectionManager.focusedKey === focusedKey) {
|
|
142
|
-
if (target.type === 'item' && target.dropPosition === 'on' && state.collection.getItem(target.key) != null) {
|
|
143
|
-
state.selectionManager.setFocusedKey(target.key);
|
|
144
|
-
state.selectionManager.setFocused(true);
|
|
145
|
-
setInteractionModality('keyboard');
|
|
146
|
-
} else if (!state.selectionManager.isSelected(focusedKey)) {
|
|
147
|
-
setInteractionModality('keyboard');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
323
|
+
updateFocusAfterDrop();
|
|
151
324
|
droppingState.current = null;
|
|
152
325
|
}, 50);
|
|
153
|
-
}, [localState]);
|
|
326
|
+
}, [localState, defaultOnDrop, ref, updateFocusAfterDrop]);
|
|
154
327
|
|
|
155
328
|
// eslint-disable-next-line arrow-body-style
|
|
156
329
|
useEffect(() => {
|
|
@@ -162,42 +335,15 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
162
335
|
}, []);
|
|
163
336
|
|
|
164
337
|
useLayoutEffect(() => {
|
|
165
|
-
// If
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
droppingState.current &&
|
|
170
|
-
state.selectionManager.isFocused &&
|
|
171
|
-
state.collection.size > droppingState.current.collection.size &&
|
|
172
|
-
state.selectionManager.isSelectionEqual(droppingState.current.selectedKeys)
|
|
173
|
-
) {
|
|
174
|
-
let newKeys = new Set<Key>();
|
|
175
|
-
for (let key of state.collection.getKeys()) {
|
|
176
|
-
if (!droppingState.current.collection.getItem(key)) {
|
|
177
|
-
newKeys.add(key);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
state.selectionManager.setSelectedKeys(newKeys);
|
|
182
|
-
|
|
183
|
-
// If the focused item didn't change since the drop occurred, also focus the first
|
|
184
|
-
// inserted item. If selection is disabled, then also show the focus ring so there
|
|
185
|
-
// is some indication that items were added.
|
|
186
|
-
if (state.selectionManager.focusedKey === droppingState.current.focusedKey) {
|
|
187
|
-
let first = newKeys.keys().next().value;
|
|
188
|
-
state.selectionManager.setFocusedKey(first);
|
|
189
|
-
|
|
190
|
-
if (state.selectionManager.selectionMode === 'none') {
|
|
191
|
-
setInteractionModality('keyboard');
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
droppingState.current = null;
|
|
338
|
+
// If the collection changed after a drop, update the focused key.
|
|
339
|
+
if (droppingState.current && state.collection !== droppingState.current.collection) {
|
|
340
|
+
updateFocusAfterDrop();
|
|
196
341
|
}
|
|
197
342
|
});
|
|
198
343
|
|
|
344
|
+
let {direction} = useLocale();
|
|
199
345
|
useEffect(() => {
|
|
200
|
-
let getNextTarget = (target: DropTarget, wrap = true): DropTarget => {
|
|
346
|
+
let getNextTarget = (target: DropTarget, wrap = true, horizontal = false): DropTarget => {
|
|
201
347
|
if (!target) {
|
|
202
348
|
return {
|
|
203
349
|
type: 'root'
|
|
@@ -205,26 +351,38 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
205
351
|
}
|
|
206
352
|
|
|
207
353
|
let {keyboardDelegate} = localState.props;
|
|
208
|
-
let nextKey
|
|
209
|
-
|
|
210
|
-
: keyboardDelegate.
|
|
211
|
-
|
|
354
|
+
let nextKey: Key;
|
|
355
|
+
if (target?.type === 'item') {
|
|
356
|
+
nextKey = horizontal ? keyboardDelegate.getKeyRightOf(target.key) : keyboardDelegate.getKeyBelow(target.key);
|
|
357
|
+
} else {
|
|
358
|
+
nextKey = horizontal && direction === 'rtl' ? keyboardDelegate.getLastKey() : keyboardDelegate.getFirstKey();
|
|
359
|
+
}
|
|
360
|
+
let dropPositions = horizontal && direction === 'rtl' ? DROP_POSITIONS_RTL : DROP_POSITIONS;
|
|
361
|
+
let dropPosition: DropPosition = dropPositions[0];
|
|
212
362
|
|
|
213
363
|
if (target.type === 'item') {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
364
|
+
// If the the keyboard delegate returned the next key in the collection,
|
|
365
|
+
// first try the other positions in the current key. Otherwise (e.g. in a grid layout),
|
|
366
|
+
// jump to the same drop position in the new key.
|
|
367
|
+
let nextCollectionKey = horizontal && direction === 'rtl' ? localState.state.collection.getKeyBefore(target.key) : localState.state.collection.getKeyAfter(target.key);
|
|
368
|
+
if (nextKey == null || nextKey === nextCollectionKey) {
|
|
369
|
+
let positionIndex = dropPositions.indexOf(target.dropPosition);
|
|
370
|
+
let nextDropPosition = dropPositions[positionIndex + 1];
|
|
371
|
+
if (positionIndex < dropPositions.length - 1 && !(nextDropPosition === dropPositions[2] && nextKey != null)) {
|
|
372
|
+
return {
|
|
373
|
+
type: 'item',
|
|
374
|
+
key: target.key,
|
|
375
|
+
dropPosition: nextDropPosition
|
|
376
|
+
};
|
|
377
|
+
}
|
|
223
378
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
379
|
+
// If the last drop position was 'after', then 'before' on the next key is equivalent.
|
|
380
|
+
// Switch to 'on' instead.
|
|
381
|
+
if (target.dropPosition === dropPositions[2]) {
|
|
382
|
+
dropPosition = 'on';
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
dropPosition = target.dropPosition;
|
|
228
386
|
}
|
|
229
387
|
}
|
|
230
388
|
|
|
@@ -245,28 +403,40 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
245
403
|
};
|
|
246
404
|
};
|
|
247
405
|
|
|
248
|
-
let getPreviousTarget = (target: DropTarget, wrap = true): DropTarget => {
|
|
406
|
+
let getPreviousTarget = (target: DropTarget, wrap = true, horizontal = false): DropTarget => {
|
|
249
407
|
let {keyboardDelegate} = localState.props;
|
|
250
|
-
let nextKey
|
|
251
|
-
|
|
252
|
-
: keyboardDelegate.
|
|
253
|
-
|
|
408
|
+
let nextKey: Key;
|
|
409
|
+
if (target?.type === 'item') {
|
|
410
|
+
nextKey = horizontal ? keyboardDelegate.getKeyLeftOf(target.key) : keyboardDelegate.getKeyAbove(target.key);
|
|
411
|
+
} else {
|
|
412
|
+
nextKey = horizontal && direction === 'rtl' ? keyboardDelegate.getFirstKey() : keyboardDelegate.getLastKey();
|
|
413
|
+
}
|
|
414
|
+
let dropPositions = horizontal && direction === 'rtl' ? DROP_POSITIONS_RTL : DROP_POSITIONS;
|
|
415
|
+
let dropPosition: DropPosition = !target || target.type === 'root' ? dropPositions[2] : 'on';
|
|
254
416
|
|
|
255
417
|
if (target?.type === 'item') {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
418
|
+
// If the the keyboard delegate returned the previous key in the collection,
|
|
419
|
+
// first try the other positions in the current key. Otherwise (e.g. in a grid layout),
|
|
420
|
+
// jump to the same drop position in the new key.
|
|
421
|
+
let prevCollectionKey = horizontal && direction === 'rtl' ? localState.state.collection.getKeyAfter(target.key) : localState.state.collection.getKeyBefore(target.key);
|
|
422
|
+
if (nextKey == null || nextKey === prevCollectionKey) {
|
|
423
|
+
let positionIndex = dropPositions.indexOf(target.dropPosition);
|
|
424
|
+
let nextDropPosition = dropPositions[positionIndex - 1];
|
|
425
|
+
if (positionIndex > 0 && nextDropPosition !== dropPositions[2]) {
|
|
426
|
+
return {
|
|
427
|
+
type: 'item',
|
|
428
|
+
key: target.key,
|
|
429
|
+
dropPosition: nextDropPosition
|
|
430
|
+
};
|
|
431
|
+
}
|
|
265
432
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
433
|
+
// If the last drop position was 'before', then 'after' on the previous key is equivalent.
|
|
434
|
+
// Switch to 'on' instead.
|
|
435
|
+
if (target.dropPosition === dropPositions[0]) {
|
|
436
|
+
dropPosition = 'on';
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
dropPosition = target.dropPosition;
|
|
270
440
|
}
|
|
271
441
|
}
|
|
272
442
|
|
|
@@ -296,13 +466,15 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
296
466
|
): DropTarget => {
|
|
297
467
|
let seenRoot = 0;
|
|
298
468
|
let operation: DropOperation;
|
|
469
|
+
let {draggingKeys} = globalDndState;
|
|
470
|
+
let isInternal = isInternalDropOperation(ref);
|
|
299
471
|
do {
|
|
300
472
|
let nextTarget = getNextTarget(target, wrap);
|
|
301
473
|
if (!nextTarget) {
|
|
302
474
|
return null;
|
|
303
475
|
}
|
|
304
476
|
target = nextTarget;
|
|
305
|
-
operation = localState.state.getDropOperation(nextTarget, types, allowedDropOperations);
|
|
477
|
+
operation = localState.state.getDropOperation({target: nextTarget, types, allowedOperations: allowedDropOperations, isInternal, draggingKeys});
|
|
306
478
|
if (target.type === 'root') {
|
|
307
479
|
seenRoot++;
|
|
308
480
|
}
|
|
@@ -321,9 +493,12 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
321
493
|
|
|
322
494
|
return DragManager.registerDropTarget({
|
|
323
495
|
element: ref.current,
|
|
496
|
+
preventFocusOnDrop: true,
|
|
324
497
|
getDropOperation(types, allowedOperations) {
|
|
325
498
|
if (localState.state.target) {
|
|
326
|
-
|
|
499
|
+
let {draggingKeys} = globalDndState;
|
|
500
|
+
let isInternal = isInternalDropOperation(ref);
|
|
501
|
+
return localState.state.getDropOperation({target: localState.state.target, types, allowedOperations, isInternal, draggingKeys});
|
|
327
502
|
}
|
|
328
503
|
|
|
329
504
|
// Check if any of the targets accept the drop.
|
|
@@ -335,6 +510,8 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
335
510
|
let types = getTypes(drag.items);
|
|
336
511
|
let selectionManager = localState.state.selectionManager;
|
|
337
512
|
let target: DropTarget;
|
|
513
|
+
// Update the drop collection ref tracker for useDroppableItem's getDropOperation isInternal check
|
|
514
|
+
setDropCollectionRef(ref);
|
|
338
515
|
|
|
339
516
|
// When entering the droppable collection for the first time, the default drop target
|
|
340
517
|
// is after the focused key.
|
|
@@ -367,8 +544,10 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
367
544
|
dropPosition
|
|
368
545
|
};
|
|
369
546
|
|
|
547
|
+
let {draggingKeys} = globalDndState;
|
|
548
|
+
let isInternal = isInternalDropOperation(ref);
|
|
370
549
|
// If the default target is not valid, find the next one that is.
|
|
371
|
-
if (localState.state.getDropOperation(target, types, drag.allowedDropOperations) === 'cancel') {
|
|
550
|
+
if (localState.state.getDropOperation({target, types, allowedOperations: drag.allowedDropOperations, isInternal, draggingKeys}) === 'cancel') {
|
|
372
551
|
target = nextValidTarget(target, types, drag.allowedDropOperations, getNextTarget, false)
|
|
373
552
|
?? nextValidTarget(target, types, drag.allowedDropOperations, getPreviousTarget, false);
|
|
374
553
|
}
|
|
@@ -382,6 +561,7 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
382
561
|
localState.state.setTarget(target);
|
|
383
562
|
},
|
|
384
563
|
onDropExit() {
|
|
564
|
+
setDropCollectionRef(undefined);
|
|
385
565
|
localState.state.setTarget(null);
|
|
386
566
|
},
|
|
387
567
|
onDropTargetEnter(target) {
|
|
@@ -402,7 +582,8 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
402
582
|
}
|
|
403
583
|
},
|
|
404
584
|
onDrop(e, target) {
|
|
405
|
-
|
|
585
|
+
setDropCollectionRef(ref);
|
|
586
|
+
if (localState.state.target) {
|
|
406
587
|
onDrop(e, target || localState.state.target);
|
|
407
588
|
}
|
|
408
589
|
},
|
|
@@ -424,6 +605,20 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
424
605
|
}
|
|
425
606
|
break;
|
|
426
607
|
}
|
|
608
|
+
case 'ArrowLeft': {
|
|
609
|
+
if (keyboardDelegate.getKeyLeftOf) {
|
|
610
|
+
let target = nextValidTarget(localState.state.target, types, drag.allowedDropOperations, (target, wrap) => getPreviousTarget(target, wrap, true));
|
|
611
|
+
localState.state.setTarget(target);
|
|
612
|
+
}
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
case 'ArrowRight': {
|
|
616
|
+
if (keyboardDelegate.getKeyRightOf) {
|
|
617
|
+
let target = nextValidTarget(localState.state.target, types, drag.allowedDropOperations, (target, wrap) => getNextTarget(target, wrap, true));
|
|
618
|
+
localState.state.setTarget(target);
|
|
619
|
+
}
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
427
622
|
case 'Home': {
|
|
428
623
|
if (keyboardDelegate.getFirstKey) {
|
|
429
624
|
let target = nextValidTarget(null, types, drag.allowedDropOperations, getNextTarget);
|
|
@@ -466,7 +661,9 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
466
661
|
|
|
467
662
|
// If the target does not accept the drop, find the next valid target.
|
|
468
663
|
// If no next valid target, find the previous valid target.
|
|
469
|
-
let
|
|
664
|
+
let {draggingCollectionRef, draggingKeys} = globalDndState;
|
|
665
|
+
let isInternal = draggingCollectionRef?.current === ref?.current;
|
|
666
|
+
let operation = localState.state.getDropOperation({target, types, allowedOperations: drag.allowedDropOperations, isInternal, draggingKeys});
|
|
470
667
|
if (operation === 'cancel') {
|
|
471
668
|
target = nextValidTarget(target, types, drag.allowedDropOperations, getNextTarget, false)
|
|
472
669
|
?? nextValidTarget(target, types, drag.allowedDropOperations, getPreviousTarget, false);
|
|
@@ -508,7 +705,9 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
508
705
|
|
|
509
706
|
// If the target does not accept the drop, find the previous valid target.
|
|
510
707
|
// If no next valid target, find the next valid target.
|
|
511
|
-
let
|
|
708
|
+
let {draggingKeys} = globalDndState;
|
|
709
|
+
let isInternal = isInternalDropOperation(ref);
|
|
710
|
+
let operation = localState.state.getDropOperation({target, types, allowedOperations: drag.allowedDropOperations, isInternal, draggingKeys});
|
|
512
711
|
if (operation === 'cancel') {
|
|
513
712
|
target = nextValidTarget(target, types, drag.allowedDropOperations, getPreviousTarget, false)
|
|
514
713
|
?? nextValidTarget(target, types, drag.allowedDropOperations, getNextTarget, false);
|
|
@@ -521,9 +720,10 @@ export function useDroppableCollection(props: DroppableCollectionOptions, state:
|
|
|
521
720
|
}
|
|
522
721
|
}
|
|
523
722
|
});
|
|
524
|
-
}, [localState, ref, onDrop]);
|
|
723
|
+
}, [localState, ref, onDrop, direction]);
|
|
525
724
|
|
|
526
|
-
let id =
|
|
725
|
+
let id = useId();
|
|
726
|
+
droppableCollectionMap.set(state, {id, ref});
|
|
527
727
|
return {
|
|
528
728
|
collectionProps: mergeProps(dropProps, {
|
|
529
729
|
id,
|