@proyecto-viviana/solidaria 0.2.4 → 0.2.8
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/LICENSE +21 -0
- package/dist/actiongroup/createActionGroup.d.ts +29 -0
- package/dist/actiongroup/createActionGroup.d.ts.map +1 -0
- package/dist/actiongroup/index.d.ts +2 -0
- package/dist/actiongroup/index.d.ts.map +1 -0
- package/dist/autocomplete/createAutocomplete.d.ts +6 -2
- package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
- package/dist/breadcrumbs/createBreadcrumbs.d.ts +2 -0
- package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
- package/dist/button/createToggleButtonGroup.d.ts +32 -0
- package/dist/button/createToggleButtonGroup.d.ts.map +1 -0
- package/dist/button/index.d.ts +2 -0
- package/dist/button/index.d.ts.map +1 -1
- package/dist/calendar/createCalendarCell.d.ts +2 -0
- package/dist/calendar/createCalendarCell.d.ts.map +1 -1
- package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
- package/dist/calendar/createRangeCalendarCell.d.ts +3 -1
- package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
- package/dist/checkbox/createCheckboxGroup.d.ts +5 -1
- package/dist/checkbox/createCheckboxGroup.d.ts.map +1 -1
- package/dist/collections/index.d.ts +56 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/color/createColorArea.d.ts.map +1 -1
- package/dist/color/createColorSlider.d.ts.map +1 -1
- package/dist/color/createColorWheel.d.ts.map +1 -1
- package/dist/combobox/createComboBox.d.ts +6 -0
- package/dist/combobox/createComboBox.d.ts.map +1 -1
- package/dist/datepicker/createDatePicker.d.ts +6 -0
- package/dist/datepicker/createDatePicker.d.ts.map +1 -1
- package/dist/datepicker/createDateRangePicker.d.ts +40 -0
- package/dist/datepicker/createDateRangePicker.d.ts.map +1 -0
- package/dist/datepicker/createDateSegment.d.ts +1 -1
- package/dist/datepicker/createDateSegment.d.ts.map +1 -1
- package/dist/datepicker/createTimeSegment.d.ts +29 -0
- package/dist/datepicker/createTimeSegment.d.ts.map +1 -0
- package/dist/datepicker/index.d.ts +2 -0
- package/dist/datepicker/index.d.ts.map +1 -1
- package/dist/disclosure/createDisclosureGroup.d.ts +2 -1
- package/dist/disclosure/createDisclosureGroup.d.ts.map +1 -1
- package/dist/dnd/createDrag.d.ts.map +1 -1
- package/dist/dnd/createDraggableCollection.d.ts +4 -0
- package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
- package/dist/dnd/createDraggableItem.d.ts.map +1 -1
- package/dist/dnd/createDrop.d.ts.map +1 -1
- package/dist/dnd/createDroppableCollection.d.ts +32 -1
- package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
- package/dist/dnd/createDroppableItem.d.ts.map +1 -1
- package/dist/dnd/index.d.ts +1 -1
- package/dist/dnd/index.d.ts.map +1 -1
- package/dist/grid/createGrid.d.ts.map +1 -1
- package/dist/gridlist/createGridList.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4659 -3452
- package/dist/index.js.map +1 -7
- package/dist/index.ssr.js +4659 -3452
- package/dist/index.ssr.js.map +1 -7
- package/dist/interactions/createFocus.d.ts.map +1 -1
- package/dist/interactions/createFocusWithin.d.ts.map +1 -1
- package/dist/link/createLink.d.ts +10 -0
- package/dist/link/createLink.d.ts.map +1 -1
- package/dist/listbox/createListBox.d.ts +1 -0
- package/dist/listbox/createListBox.d.ts.map +1 -1
- package/dist/listbox/createOption.d.ts.map +1 -1
- package/dist/menu/createMenu.d.ts +1 -0
- package/dist/menu/createMenu.d.ts.map +1 -1
- package/dist/meter/createMeter.d.ts.map +1 -1
- package/dist/numberfield/createNumberField.d.ts +18 -0
- package/dist/numberfield/createNumberField.d.ts.map +1 -1
- package/dist/overlays/createModal.d.ts +16 -0
- package/dist/overlays/createModal.d.ts.map +1 -1
- package/dist/overlays/createOverlay.d.ts.map +1 -1
- package/dist/overlays/index.d.ts +1 -1
- package/dist/overlays/index.d.ts.map +1 -1
- package/dist/popover/createOverlayPosition.d.ts.map +1 -1
- package/dist/popover/createPopover.d.ts.map +1 -1
- package/dist/progress/createProgressBar.d.ts.map +1 -1
- package/dist/radio/createRadioGroup.d.ts +2 -2
- package/dist/radio/createRadioGroup.d.ts.map +1 -1
- package/dist/searchfield/createSearchField.d.ts.map +1 -1
- package/dist/select/createHiddenSelect.d.ts.map +1 -1
- package/dist/select/createSelect.d.ts.map +1 -1
- package/dist/slider/createSlider.d.ts.map +1 -1
- package/dist/table/createTable.d.ts.map +1 -1
- package/dist/tabs/createTabs.d.ts +1 -1
- package/dist/tabs/createTabs.d.ts.map +1 -1
- package/dist/tag/createTag.d.ts.map +1 -1
- package/dist/tag/createTagGroup.d.ts.map +1 -1
- package/dist/toast/createToast.d.ts +4 -0
- package/dist/toast/createToast.d.ts.map +1 -1
- package/dist/toast/createToastRegion.d.ts.map +1 -1
- package/dist/toolbar/createToolbar.d.ts.map +1 -1
- package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
- package/dist/tree/createTree.d.ts.map +1 -1
- package/dist/tree/createTreeItem.d.ts.map +1 -1
- package/dist/tree/types.d.ts +4 -0
- package/dist/tree/types.d.ts.map +1 -1
- package/dist/utils/env.d.ts +1 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/platform.d.ts.map +1 -1
- package/dist/visually-hidden/createVisuallyHidden.d.ts.map +1 -1
- package/package.json +8 -6
- package/src/actiongroup/createActionGroup.ts +324 -0
- package/src/actiongroup/index.ts +8 -0
- package/src/autocomplete/createAutocomplete.ts +32 -9
- package/src/breadcrumbs/createBreadcrumbs.ts +10 -15
- package/src/button/createButton.ts +1 -1
- package/src/button/createToggleButtonGroup.ts +128 -0
- package/src/button/index.ts +9 -0
- package/src/calendar/createCalendarCell.ts +6 -4
- package/src/calendar/createCalendarGrid.ts +27 -18
- package/src/calendar/createRangeCalendarCell.ts +26 -9
- package/src/checkbox/createCheckboxGroup.ts +21 -4
- package/src/collections/index.ts +242 -0
- package/src/color/createColorArea.ts +380 -314
- package/src/color/createColorField.ts +137 -137
- package/src/color/createColorSlider.ts +286 -197
- package/src/color/createColorSwatch.ts +40 -40
- package/src/color/createColorWheel.ts +218 -208
- package/src/color/index.ts +24 -24
- package/src/color/types.ts +116 -116
- package/src/combobox/createComboBox.ts +670 -647
- package/src/combobox/index.ts +6 -6
- package/src/datepicker/createDatePicker.ts +54 -16
- package/src/datepicker/createDateRangePicker.ts +246 -0
- package/src/datepicker/createDateSegment.ts +185 -31
- package/src/datepicker/createTimeSegment.ts +370 -0
- package/src/datepicker/index.ts +14 -0
- package/src/dialog/createDialog.ts +120 -120
- package/src/dialog/index.ts +2 -2
- package/src/dialog/types.ts +19 -19
- package/src/disclosure/createDisclosureGroup.ts +5 -2
- package/src/dnd/createDrag.ts +224 -209
- package/src/dnd/createDraggableCollection.ts +96 -63
- package/src/dnd/createDraggableItem.ts +259 -243
- package/src/dnd/createDrop.ts +322 -321
- package/src/dnd/createDroppableCollection.ts +682 -293
- package/src/dnd/createDroppableItem.ts +215 -213
- package/src/dnd/index.ts +55 -47
- package/src/dnd/types.ts +89 -89
- package/src/dnd/utils.ts +294 -294
- package/src/focus/createAutoFocus.ts +321 -321
- package/src/focus/createFocusRestore.ts +313 -313
- package/src/focus/createVirtualFocus.ts +396 -396
- package/src/form/createFormValidation.ts +224 -224
- package/src/form/index.ts +11 -11
- package/src/grid/createGrid.ts +3 -1
- package/src/gridlist/createGridList.ts +16 -0
- package/src/gridlist/createGridListItem.ts +1 -1
- package/src/i18n/NumberFormatter.ts +266 -266
- package/src/i18n/createCollator.ts +79 -79
- package/src/i18n/createDateFormatter.ts +83 -83
- package/src/i18n/createFilter.ts +131 -131
- package/src/i18n/createNumberFormatter.ts +52 -52
- package/src/i18n/index.ts +40 -40
- package/src/i18n/locale.tsx +188 -188
- package/src/i18n/utils.ts +99 -99
- package/src/index.ts +51 -0
- package/src/interactions/createFocus.ts +6 -5
- package/src/interactions/createFocusWithin.ts +6 -5
- package/src/interactions/createLongPress.ts +174 -174
- package/src/interactions/createMove.ts +289 -289
- package/src/interactions/createPress.ts +5 -5
- package/src/landmark/createLandmark.ts +377 -377
- package/src/landmark/index.ts +8 -8
- package/src/link/createLink.ts +23 -8
- package/src/listbox/createListBox.ts +308 -269
- package/src/listbox/createOption.ts +162 -151
- package/src/listbox/index.ts +12 -12
- package/src/live-announcer/announce.ts +322 -322
- package/src/live-announcer/index.ts +9 -9
- package/src/menu/createMenu.ts +405 -396
- package/src/menu/createMenuItem.ts +149 -149
- package/src/menu/createMenuTrigger.ts +88 -88
- package/src/menu/index.ts +18 -18
- package/src/meter/createMeter.ts +1 -6
- package/src/numberfield/createNumberField.ts +311 -268
- package/src/numberfield/index.ts +5 -5
- package/src/overlays/ariaHideOutside.ts +219 -219
- package/src/overlays/createInteractOutside.ts +149 -149
- package/src/overlays/createModal.tsx +238 -202
- package/src/overlays/createOverlay.ts +165 -155
- package/src/overlays/createOverlayTrigger.ts +85 -85
- package/src/overlays/createPreventScroll.ts +266 -266
- package/src/overlays/index.ts +48 -44
- package/src/popover/calculatePosition.ts +6 -6
- package/src/popover/createOverlayPosition.ts +7 -4
- package/src/popover/createPopover.ts +21 -7
- package/src/progress/createProgressBar.ts +6 -1
- package/src/radio/createRadioGroup.ts +88 -14
- package/src/searchfield/createSearchField.ts +241 -186
- package/src/searchfield/index.ts +2 -2
- package/src/select/createHiddenSelect.tsx +263 -236
- package/src/select/createSelect.ts +373 -395
- package/src/select/index.ts +14 -14
- package/src/slider/createSlider.ts +364 -349
- package/src/slider/index.ts +2 -2
- package/src/ssr/index.tsx +370 -370
- package/src/table/createTable.ts +3 -1
- package/src/table/createTableColumnHeader.ts +1 -1
- package/src/table/createTableRow.ts +1 -1
- package/src/tabs/createTabs.ts +80 -51
- package/src/tag/createTag.ts +135 -6
- package/src/tag/createTagGroup.ts +7 -2
- package/src/toast/createToast.ts +8 -2
- package/src/toast/createToastRegion.ts +0 -1
- package/src/toolbar/createToolbar.ts +75 -1
- package/src/tooltip/createTooltip.ts +79 -79
- package/src/tooltip/createTooltipTrigger.ts +226 -222
- package/src/tooltip/index.ts +6 -6
- package/src/tree/createTree.ts +261 -246
- package/src/tree/createTreeItem.ts +282 -233
- package/src/tree/createTreeSelectionCheckbox.ts +68 -68
- package/src/tree/index.ts +16 -16
- package/src/tree/types.ts +91 -87
- package/src/utils/env.ts +55 -54
- package/src/utils/platform.ts +16 -6
- package/src/visually-hidden/createVisuallyHidden.ts +139 -124
- package/src/visually-hidden/index.ts +6 -6
|
@@ -1,293 +1,682 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createDroppableCollection - ARIA hook for droppable collection targets.
|
|
3
|
-
*
|
|
4
|
-
* Provides accessibility support for dropping items into a collection
|
|
5
|
-
* component like ListBox, GridList, or Table.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createMemo, onCleanup, type Accessor } from 'solid-js';
|
|
9
|
-
import type { JSX } from 'solid-js';
|
|
10
|
-
import type {
|
|
11
|
-
DroppableCollectionState,
|
|
12
|
-
DropTarget,
|
|
13
|
-
DropOperation,
|
|
14
|
-
DropItem,
|
|
15
|
-
DragTypes,
|
|
16
|
-
} from '@proyecto-viviana/solid-stately';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
target: DropTarget
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
target: DropTarget
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
1
|
+
/**
|
|
2
|
+
* createDroppableCollection - ARIA hook for droppable collection targets.
|
|
3
|
+
*
|
|
4
|
+
* Provides accessibility support for dropping items into a collection
|
|
5
|
+
* component like ListBox, GridList, or Table.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createMemo, onCleanup, type Accessor } from 'solid-js';
|
|
9
|
+
import type { JSX } from 'solid-js';
|
|
10
|
+
import type {
|
|
11
|
+
DroppableCollectionState,
|
|
12
|
+
DropTarget,
|
|
13
|
+
DropOperation,
|
|
14
|
+
DropItem,
|
|
15
|
+
DragTypes,
|
|
16
|
+
} from '@proyecto-viviana/solid-stately';
|
|
17
|
+
import { DIRECTORY_DRAG_TYPE } from '@proyecto-viviana/solid-stately';
|
|
18
|
+
import { createDrop } from './createDrop';
|
|
19
|
+
import {
|
|
20
|
+
getGlobalDraggingCollectionRef,
|
|
21
|
+
getGlobalDraggingKeys,
|
|
22
|
+
getGlobalDraggingTypes,
|
|
23
|
+
} from './createDraggableCollection';
|
|
24
|
+
import { getGlobalAllowedDropOperations, DROP_OPERATION } from './utils';
|
|
25
|
+
|
|
26
|
+
// Global state for tracking the drop collection
|
|
27
|
+
let globalDropCollectionRef: HTMLElement | null = null;
|
|
28
|
+
|
|
29
|
+
export function setGlobalDropCollectionRef(ref: HTMLElement | null): void {
|
|
30
|
+
globalDropCollectionRef = ref;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getGlobalDropCollectionRef(): HTMLElement | null {
|
|
34
|
+
return globalDropCollectionRef;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface DropTargetDelegate {
|
|
38
|
+
/**
|
|
39
|
+
* Returns a drop target from a point within the collection.
|
|
40
|
+
*/
|
|
41
|
+
getDropTargetFromPoint(
|
|
42
|
+
x: number,
|
|
43
|
+
y: number,
|
|
44
|
+
isValidDropTarget: (target: DropTarget) => boolean
|
|
45
|
+
): DropTarget | null;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the next keyboard-navigable drop target.
|
|
48
|
+
*/
|
|
49
|
+
getKeyboardNavigationTarget?(
|
|
50
|
+
target: DropTarget | null,
|
|
51
|
+
direction: 'next' | 'previous',
|
|
52
|
+
isValidDropTarget: (target: DropTarget) => boolean
|
|
53
|
+
): DropTarget | null;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the next page-navigable drop target.
|
|
56
|
+
*/
|
|
57
|
+
getKeyboardPageNavigationTarget?(
|
|
58
|
+
target: DropTarget | null,
|
|
59
|
+
direction: 'next' | 'previous',
|
|
60
|
+
isValidDropTarget: (target: DropTarget) => boolean
|
|
61
|
+
): DropTarget | null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface KeyboardDelegateLike {
|
|
65
|
+
getFirstKey?: () => string | number | null;
|
|
66
|
+
getLastKey?: () => string | number | null;
|
|
67
|
+
getKeyBelow?: (key: string | number) => string | number | null;
|
|
68
|
+
getKeyAbove?: (key: string | number) => string | number | null;
|
|
69
|
+
getKeyRightOf?: (key: string | number) => string | number | null;
|
|
70
|
+
getKeyLeftOf?: (key: string | number) => string | number | null;
|
|
71
|
+
getKeyPageBelow?: (key: string | number) => string | number | null;
|
|
72
|
+
getKeyPageAbove?: (key: string | number) => string | number | null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface DroppableCollectionOptions {
|
|
76
|
+
/** Reference to the collection element. */
|
|
77
|
+
ref: Accessor<HTMLElement | null>;
|
|
78
|
+
/** A delegate that provides drop targets for pointer coordinates. */
|
|
79
|
+
dropTargetDelegate: DropTargetDelegate;
|
|
80
|
+
/** Handler called when items are dropped to be inserted. */
|
|
81
|
+
onInsert?: (e: {
|
|
82
|
+
items: DropItem[];
|
|
83
|
+
target: DropTarget;
|
|
84
|
+
dropOperation: DropOperation;
|
|
85
|
+
}) => void;
|
|
86
|
+
/** Handler called when items are dropped on the root. */
|
|
87
|
+
onRootDrop?: (e: { items: DropItem[]; dropOperation: DropOperation }) => void;
|
|
88
|
+
/** Handler called when items are dropped on an item. */
|
|
89
|
+
onItemDrop?: (e: {
|
|
90
|
+
items: DropItem[];
|
|
91
|
+
target: DropTarget;
|
|
92
|
+
dropOperation: DropOperation;
|
|
93
|
+
isInternal: boolean;
|
|
94
|
+
}) => void;
|
|
95
|
+
/** Handler called when items are reordered within the collection. */
|
|
96
|
+
onReorder?: (e: {
|
|
97
|
+
keys: Set<string | number>;
|
|
98
|
+
target: DropTarget;
|
|
99
|
+
dropOperation: DropOperation;
|
|
100
|
+
}) => void;
|
|
101
|
+
/** Handler called when items are moved within/between collections. */
|
|
102
|
+
onMove?: (e: {
|
|
103
|
+
keys: Set<string | number>;
|
|
104
|
+
target: DropTarget;
|
|
105
|
+
dropOperation: DropOperation;
|
|
106
|
+
}) => void;
|
|
107
|
+
/** Handler called when a drop occurs on any collection target. */
|
|
108
|
+
onDrop?: (e: {
|
|
109
|
+
items: DropItem[];
|
|
110
|
+
target: DropTarget;
|
|
111
|
+
dropOperation: DropOperation;
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
}) => void;
|
|
115
|
+
/** Handler called when the drop target is activated (held over). */
|
|
116
|
+
onDropActivate?: (e: { target: DropTarget; x: number; y: number }) => void;
|
|
117
|
+
/** Optional keyboard delegate used as fallback when drop-target delegates do not provide keyboard navigation methods. */
|
|
118
|
+
keyboardDelegate?: KeyboardDelegateLike;
|
|
119
|
+
/** Optional keyboard handler composed with internal drop target navigation keys. */
|
|
120
|
+
onKeyDown?: (e: KeyboardEvent) => void;
|
|
121
|
+
/** Whether the collection is disabled for dropping. */
|
|
122
|
+
isDisabled?: boolean;
|
|
123
|
+
/** Accepted drag types. 'all' accepts any type. */
|
|
124
|
+
acceptedDragTypes?: 'all' | Array<string | symbol>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function getDropItemTypes(item: DropItem): Set<string | symbol> {
|
|
128
|
+
if (item.kind === 'file') {
|
|
129
|
+
return new Set([item.type]);
|
|
130
|
+
}
|
|
131
|
+
if (item.kind === 'text') {
|
|
132
|
+
return new Set(item.types);
|
|
133
|
+
}
|
|
134
|
+
return new Set([DIRECTORY_DRAG_TYPE]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface DroppableCollectionAria {
|
|
138
|
+
/** Props to spread on the collection element. */
|
|
139
|
+
collectionProps: JSX.HTMLAttributes<HTMLElement>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Creates ARIA support for a droppable collection.
|
|
144
|
+
*
|
|
145
|
+
* @param options - Collection options accessor
|
|
146
|
+
* @param state - Droppable collection state
|
|
147
|
+
* @returns Droppable collection ARIA result
|
|
148
|
+
*/
|
|
149
|
+
export function createDroppableCollection(
|
|
150
|
+
options: Accessor<DroppableCollectionOptions>,
|
|
151
|
+
state: DroppableCollectionState
|
|
152
|
+
): DroppableCollectionAria {
|
|
153
|
+
const getOptions = createMemo(() => options());
|
|
154
|
+
|
|
155
|
+
// Track the next target during drag operations
|
|
156
|
+
let nextTarget: DropTarget | null = null;
|
|
157
|
+
let currentDropOperation: DropOperation | null = null;
|
|
158
|
+
|
|
159
|
+
const isInternalDropOperation = (): boolean => {
|
|
160
|
+
const ref = getOptions().ref();
|
|
161
|
+
const draggingRef = getGlobalDraggingCollectionRef();
|
|
162
|
+
return ref !== null && draggingRef === ref;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const getDropOperationForTarget = (
|
|
166
|
+
target: DropTarget,
|
|
167
|
+
types: DragTypes,
|
|
168
|
+
allowedOperations: DropOperation[]
|
|
169
|
+
): DropOperation => {
|
|
170
|
+
return state.getDropOperation(target, types, allowedOperations);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Create base drop behavior
|
|
174
|
+
const drop = createDrop(() => ({
|
|
175
|
+
isDisabled: getOptions().isDisabled,
|
|
176
|
+
getDropOperationForPoint: (types, allowedOperations, x, y) => {
|
|
177
|
+
const opts = getOptions();
|
|
178
|
+
const isValidDropTarget = (target: DropTarget) =>
|
|
179
|
+
getDropOperationForTarget(target, types, allowedOperations) !== 'cancel';
|
|
180
|
+
|
|
181
|
+
const target = opts.dropTargetDelegate.getDropTargetFromPoint(
|
|
182
|
+
x,
|
|
183
|
+
y,
|
|
184
|
+
isValidDropTarget
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
if (!target) {
|
|
188
|
+
currentDropOperation = 'cancel';
|
|
189
|
+
nextTarget = null;
|
|
190
|
+
return 'cancel';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
currentDropOperation = getDropOperationForTarget(
|
|
194
|
+
target,
|
|
195
|
+
types,
|
|
196
|
+
allowedOperations
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// If target doesn't accept, try root
|
|
200
|
+
if (currentDropOperation === 'cancel') {
|
|
201
|
+
const rootTarget: DropTarget = { type: 'root' };
|
|
202
|
+
const rootOp = getDropOperationForTarget(
|
|
203
|
+
rootTarget,
|
|
204
|
+
types,
|
|
205
|
+
allowedOperations
|
|
206
|
+
);
|
|
207
|
+
if (rootOp !== 'cancel') {
|
|
208
|
+
nextTarget = rootTarget;
|
|
209
|
+
currentDropOperation = rootOp;
|
|
210
|
+
return currentDropOperation;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Update drop collection ref
|
|
215
|
+
const ref = opts.ref();
|
|
216
|
+
if (target && currentDropOperation !== 'cancel' && ref !== globalDropCollectionRef) {
|
|
217
|
+
setGlobalDropCollectionRef(ref);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
nextTarget = currentDropOperation === 'cancel' ? null : target;
|
|
221
|
+
return currentDropOperation;
|
|
222
|
+
},
|
|
223
|
+
onDropEnter: () => {
|
|
224
|
+
if (nextTarget) {
|
|
225
|
+
state.setTarget(nextTarget);
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
onDropMove: () => {
|
|
229
|
+
if (nextTarget) {
|
|
230
|
+
state.setTarget(nextTarget);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
onDropExit: () => {
|
|
234
|
+
setGlobalDropCollectionRef(null);
|
|
235
|
+
state.setTarget(null);
|
|
236
|
+
},
|
|
237
|
+
onDropActivate: (e) => {
|
|
238
|
+
const opts = getOptions();
|
|
239
|
+
if (
|
|
240
|
+
state.target?.type === 'item' &&
|
|
241
|
+
state.target.dropPosition === 'on' &&
|
|
242
|
+
typeof opts.onDropActivate === 'function'
|
|
243
|
+
) {
|
|
244
|
+
opts.onDropActivate({
|
|
245
|
+
target: state.target,
|
|
246
|
+
x: e.x,
|
|
247
|
+
y: e.y,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
onDrop: (e) => {
|
|
252
|
+
const opts = getOptions();
|
|
253
|
+
setGlobalDropCollectionRef(opts.ref());
|
|
254
|
+
|
|
255
|
+
if (state.target) {
|
|
256
|
+
opts.onDrop?.({
|
|
257
|
+
items: e.items,
|
|
258
|
+
target: state.target,
|
|
259
|
+
dropOperation: e.dropOperation,
|
|
260
|
+
x: e.x,
|
|
261
|
+
y: e.y,
|
|
262
|
+
});
|
|
263
|
+
handleDrop(e.items, state.target, e.dropOperation);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
}));
|
|
267
|
+
|
|
268
|
+
const handleDrop = async (
|
|
269
|
+
items: DropItem[],
|
|
270
|
+
target: DropTarget,
|
|
271
|
+
dropOperation: DropOperation
|
|
272
|
+
) => {
|
|
273
|
+
const opts = getOptions();
|
|
274
|
+
const isInternal = isInternalDropOperation();
|
|
275
|
+
|
|
276
|
+
// Filter items by accepted types
|
|
277
|
+
let filteredItems = items;
|
|
278
|
+
const acceptedTypes = opts.acceptedDragTypes;
|
|
279
|
+
if (acceptedTypes && acceptedTypes !== 'all') {
|
|
280
|
+
filteredItems = items.filter((item) => {
|
|
281
|
+
const itemTypes = getDropItemTypes(item);
|
|
282
|
+
return acceptedTypes.some((type) => itemTypes.has(type));
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (filteredItems.length === 0) return;
|
|
287
|
+
|
|
288
|
+
// Call appropriate handlers based on target type
|
|
289
|
+
if (target.type === 'root' && opts.onRootDrop) {
|
|
290
|
+
await opts.onRootDrop({ items: filteredItems, dropOperation });
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (target.type === 'item') {
|
|
294
|
+
if (target.dropPosition === 'on' && opts.onItemDrop) {
|
|
295
|
+
await opts.onItemDrop({
|
|
296
|
+
items: filteredItems,
|
|
297
|
+
target,
|
|
298
|
+
dropOperation,
|
|
299
|
+
isInternal,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Handle move for internal operations
|
|
304
|
+
if (opts.onMove && isInternal) {
|
|
305
|
+
const draggingKeys = getGlobalDraggingKeys();
|
|
306
|
+
await opts.onMove({
|
|
307
|
+
keys: draggingKeys,
|
|
308
|
+
target,
|
|
309
|
+
dropOperation,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (target.dropPosition !== 'on') {
|
|
314
|
+
if (!isInternal && opts.onInsert) {
|
|
315
|
+
await opts.onInsert({
|
|
316
|
+
items: filteredItems,
|
|
317
|
+
target,
|
|
318
|
+
dropOperation,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (isInternal && opts.onReorder) {
|
|
323
|
+
const draggingKeys = getGlobalDraggingKeys();
|
|
324
|
+
await opts.onReorder({
|
|
325
|
+
keys: draggingKeys,
|
|
326
|
+
target,
|
|
327
|
+
dropOperation,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// Clean up on unmount
|
|
335
|
+
onCleanup(() => {
|
|
336
|
+
const ref = getOptions().ref();
|
|
337
|
+
if (globalDropCollectionRef === ref) {
|
|
338
|
+
setGlobalDropCollectionRef(null);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const collectionProps = createMemo(() => {
|
|
343
|
+
const baseDropProps = drop.dropProps;
|
|
344
|
+
const onKeyDownBase = baseDropProps.onKeyDown as ((e: KeyboardEvent) => void) | undefined;
|
|
345
|
+
const onKeyDown = (e: KeyboardEvent): void => {
|
|
346
|
+
onKeyDownBase?.(e);
|
|
347
|
+
const opts = getOptions();
|
|
348
|
+
if (opts.isDisabled) return;
|
|
349
|
+
const resolveDirection = (): 'ltr' | 'rtl' => {
|
|
350
|
+
const refEl = opts.ref();
|
|
351
|
+
if (refEl && typeof window !== 'undefined' && typeof window.getComputedStyle === 'function') {
|
|
352
|
+
const computedDir = window.getComputedStyle(refEl).direction;
|
|
353
|
+
if (computedDir === 'rtl') return 'rtl';
|
|
354
|
+
}
|
|
355
|
+
return typeof document !== 'undefined' && document.dir === 'rtl' ? 'rtl' : 'ltr';
|
|
356
|
+
};
|
|
357
|
+
const isRtl = resolveDirection() === 'rtl';
|
|
358
|
+
const forwardHorizontalKey = isRtl ? 'ArrowLeft' : 'ArrowRight';
|
|
359
|
+
const backwardHorizontalKey = isRtl ? 'ArrowRight' : 'ArrowLeft';
|
|
360
|
+
const callUserOnKeyDown = () => opts.onKeyDown?.(e);
|
|
361
|
+
const getKeyboardAllowedOperations = (): DropOperation[] => {
|
|
362
|
+
const allowedBits = getGlobalAllowedDropOperations();
|
|
363
|
+
if (!allowedBits) return ['copy', 'move', 'link'];
|
|
364
|
+
const allowed: DropOperation[] = [];
|
|
365
|
+
if (allowedBits & DROP_OPERATION.copy) allowed.push('copy');
|
|
366
|
+
if (allowedBits & DROP_OPERATION.move) allowed.push('move');
|
|
367
|
+
if (allowedBits & DROP_OPERATION.link) allowed.push('link');
|
|
368
|
+
return allowed.length > 0 ? allowed : ['copy', 'move', 'link'];
|
|
369
|
+
};
|
|
370
|
+
const getKeyboardDragTypes = (): DragTypes => {
|
|
371
|
+
const draggingTypes = getGlobalDraggingTypes();
|
|
372
|
+
if (draggingTypes.size === 0) {
|
|
373
|
+
return { has: () => true };
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
has: (type: string | symbol) => typeof type === 'string' && draggingTypes.has(type),
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
const isValidDropTarget = (target: DropTarget) =>
|
|
380
|
+
state.getDropOperation(target, getKeyboardDragTypes(), getKeyboardAllowedOperations()) !== 'cancel';
|
|
381
|
+
const targetsEqual = (a: DropTarget, b: DropTarget): boolean => {
|
|
382
|
+
if (a.type !== b.type) return false;
|
|
383
|
+
if (a.type === 'root' && b.type === 'root') return true;
|
|
384
|
+
if (a.type !== 'item' || b.type !== 'item') return false;
|
|
385
|
+
return a.key === b.key && a.dropPosition === b.dropPosition;
|
|
386
|
+
};
|
|
387
|
+
const findNextValidTarget = (
|
|
388
|
+
start: DropTarget | null,
|
|
389
|
+
getNext: (target: DropTarget | null) => DropTarget | null
|
|
390
|
+
): DropTarget | null => {
|
|
391
|
+
let current = start;
|
|
392
|
+
let seenRoot = 0;
|
|
393
|
+
let safety = 0;
|
|
394
|
+
while (safety < 256) {
|
|
395
|
+
safety += 1;
|
|
396
|
+
const next = getNext(current);
|
|
397
|
+
if (!next) return null;
|
|
398
|
+
if (current && targetsEqual(current, next)) {
|
|
399
|
+
return isValidDropTarget(next) ? next : null;
|
|
400
|
+
}
|
|
401
|
+
current = next;
|
|
402
|
+
if (next.type === 'root') {
|
|
403
|
+
seenRoot += 1;
|
|
404
|
+
if (seenRoot >= 2) {
|
|
405
|
+
return isValidDropTarget(next) ? next : null;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (isValidDropTarget(next)) return next;
|
|
409
|
+
}
|
|
410
|
+
return null;
|
|
411
|
+
};
|
|
412
|
+
const resolveTargetForKey = (
|
|
413
|
+
key: string | number | null,
|
|
414
|
+
direction: 'next' | 'previous'
|
|
415
|
+
): DropTarget | null => {
|
|
416
|
+
if (key == null) return null;
|
|
417
|
+
const onTarget: DropTarget = { type: 'item', key, dropPosition: 'on' };
|
|
418
|
+
if (isValidDropTarget(onTarget)) return onTarget;
|
|
419
|
+
const insertionOrder: Array<'before' | 'after'> = direction === 'next'
|
|
420
|
+
? ['before', 'after']
|
|
421
|
+
: ['after', 'before'];
|
|
422
|
+
for (const position of insertionOrder) {
|
|
423
|
+
const insertionTarget: DropTarget = { type: 'item', key, dropPosition: position };
|
|
424
|
+
if (isValidDropTarget(insertionTarget)) return insertionTarget;
|
|
425
|
+
}
|
|
426
|
+
return null;
|
|
427
|
+
};
|
|
428
|
+
const resolveBoundaryTargetForDirection = (
|
|
429
|
+
key: string | number | null,
|
|
430
|
+
direction: 'next' | 'previous'
|
|
431
|
+
): DropTarget | null => {
|
|
432
|
+
if (key == null) return null;
|
|
433
|
+
const boundaryOrder: Array<'before' | 'on' | 'after'> = direction === 'next'
|
|
434
|
+
? ['before', 'on', 'after']
|
|
435
|
+
: ['after', 'on', 'before'];
|
|
436
|
+
for (const position of boundaryOrder) {
|
|
437
|
+
const candidate: DropTarget = { type: 'item', key, dropPosition: position };
|
|
438
|
+
if (isValidDropTarget(candidate)) return candidate;
|
|
439
|
+
}
|
|
440
|
+
return null;
|
|
441
|
+
};
|
|
442
|
+
const resolveFallbackKeyboardTarget = (
|
|
443
|
+
keyName: string,
|
|
444
|
+
currentTarget: DropTarget | null = state.target
|
|
445
|
+
): DropTarget | null => {
|
|
446
|
+
const keyboardDelegate = opts.keyboardDelegate;
|
|
447
|
+
if (!keyboardDelegate) return null;
|
|
448
|
+
const currentKey = currentTarget?.type === 'item' ? currentTarget.key : null;
|
|
449
|
+
const keyForDirection = (
|
|
450
|
+
direction: 'next' | 'previous',
|
|
451
|
+
getter: ((key: string | number) => string | number | null) | undefined
|
|
452
|
+
): DropTarget | null => {
|
|
453
|
+
if (currentKey == null) {
|
|
454
|
+
const boundaryKey = direction === 'next'
|
|
455
|
+
? keyboardDelegate.getFirstKey?.()
|
|
456
|
+
: keyboardDelegate.getLastKey?.();
|
|
457
|
+
return resolveBoundaryTargetForDirection(boundaryKey ?? null, direction);
|
|
458
|
+
}
|
|
459
|
+
if (!getter) return null;
|
|
460
|
+
let nextKey = getter(currentKey);
|
|
461
|
+
let safety = 0;
|
|
462
|
+
while (nextKey != null && safety < 256) {
|
|
463
|
+
const resolvedTarget = resolveTargetForKey(nextKey, direction);
|
|
464
|
+
if (resolvedTarget) return resolvedTarget;
|
|
465
|
+
const candidate = getter(nextKey);
|
|
466
|
+
if (candidate === nextKey) break;
|
|
467
|
+
nextKey = candidate;
|
|
468
|
+
safety += 1;
|
|
469
|
+
}
|
|
470
|
+
return null;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
if (keyName === 'ArrowDown') return keyForDirection('next', keyboardDelegate.getKeyBelow);
|
|
474
|
+
if (keyName === 'ArrowUp') return keyForDirection('previous', keyboardDelegate.getKeyAbove);
|
|
475
|
+
if (keyName === forwardHorizontalKey) {
|
|
476
|
+
return keyForDirection('next', isRtl ? keyboardDelegate.getKeyLeftOf : keyboardDelegate.getKeyRightOf);
|
|
477
|
+
}
|
|
478
|
+
if (keyName === backwardHorizontalKey) {
|
|
479
|
+
return keyForDirection('previous', isRtl ? keyboardDelegate.getKeyRightOf : keyboardDelegate.getKeyLeftOf);
|
|
480
|
+
}
|
|
481
|
+
if (keyName === 'Home') return resolveBoundaryTargetForDirection(keyboardDelegate.getFirstKey?.() ?? null, 'next');
|
|
482
|
+
if (keyName === 'End') return resolveBoundaryTargetForDirection(keyboardDelegate.getLastKey?.() ?? null, 'previous');
|
|
483
|
+
if (keyName === 'PageDown') {
|
|
484
|
+
if (currentKey != null && keyboardDelegate.getKeyPageBelow) {
|
|
485
|
+
return resolveTargetForKey(keyboardDelegate.getKeyPageBelow(currentKey), 'next');
|
|
486
|
+
}
|
|
487
|
+
return keyForDirection('next', keyboardDelegate.getKeyBelow);
|
|
488
|
+
}
|
|
489
|
+
if (keyName === 'PageUp') {
|
|
490
|
+
if (currentKey != null && keyboardDelegate.getKeyPageAbove) {
|
|
491
|
+
return resolveTargetForKey(keyboardDelegate.getKeyPageAbove(currentKey), 'previous');
|
|
492
|
+
}
|
|
493
|
+
return keyForDirection('previous', keyboardDelegate.getKeyAbove);
|
|
494
|
+
}
|
|
495
|
+
return null;
|
|
496
|
+
};
|
|
497
|
+
const resolvePageTargetForState = (
|
|
498
|
+
direction: 'next' | 'previous',
|
|
499
|
+
currentTarget: DropTarget
|
|
500
|
+
): DropTarget | null => {
|
|
501
|
+
const keyboardDelegate = opts.keyboardDelegate;
|
|
502
|
+
if (!keyboardDelegate) return null;
|
|
503
|
+
if (direction === 'next') {
|
|
504
|
+
let targetKey = keyboardDelegate.getFirstKey?.() ?? null;
|
|
505
|
+
let dropPosition: 'before' | 'on' | 'after' = 'after';
|
|
506
|
+
if (currentTarget.type === 'item') {
|
|
507
|
+
targetKey = currentTarget.key;
|
|
508
|
+
dropPosition = currentTarget.dropPosition;
|
|
509
|
+
}
|
|
510
|
+
let nextKey = targetKey != null ? keyboardDelegate.getKeyPageBelow?.(targetKey) ?? null : null;
|
|
511
|
+
if (
|
|
512
|
+
nextKey == null ||
|
|
513
|
+
(currentTarget.type === 'item' && currentTarget.key === keyboardDelegate.getLastKey?.())
|
|
514
|
+
) {
|
|
515
|
+
nextKey = keyboardDelegate.getLastKey?.() ?? null;
|
|
516
|
+
dropPosition = 'after';
|
|
517
|
+
}
|
|
518
|
+
if (nextKey == null) return null;
|
|
519
|
+
return {
|
|
520
|
+
type: 'item',
|
|
521
|
+
key: nextKey,
|
|
522
|
+
dropPosition,
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (currentTarget.type === 'item') {
|
|
527
|
+
if (currentTarget.key === keyboardDelegate.getFirstKey?.()) {
|
|
528
|
+
return { type: 'root' };
|
|
529
|
+
}
|
|
530
|
+
let nextKey = keyboardDelegate.getKeyPageAbove?.(currentTarget.key) ?? null;
|
|
531
|
+
let dropPosition: 'before' | 'on' | 'after' = currentTarget.dropPosition;
|
|
532
|
+
if (nextKey == null) {
|
|
533
|
+
nextKey = keyboardDelegate.getFirstKey?.() ?? null;
|
|
534
|
+
dropPosition = 'before';
|
|
535
|
+
}
|
|
536
|
+
if (nextKey == null) return null;
|
|
537
|
+
return {
|
|
538
|
+
type: 'item',
|
|
539
|
+
key: nextKey,
|
|
540
|
+
dropPosition,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return currentTarget.type === 'root' ? currentTarget : null;
|
|
545
|
+
};
|
|
546
|
+
if (e.key === 'PageDown' || e.key === 'PageUp') {
|
|
547
|
+
if (
|
|
548
|
+
(e.key === 'PageDown' && !opts.keyboardDelegate?.getKeyPageBelow) ||
|
|
549
|
+
(e.key === 'PageUp' && !opts.keyboardDelegate?.getKeyPageAbove)
|
|
550
|
+
) {
|
|
551
|
+
callUserOnKeyDown();
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
const direction = e.key === 'PageDown' ? 'next' : 'previous';
|
|
555
|
+
const pageNavigation = opts.dropTargetDelegate.getKeyboardPageNavigationTarget;
|
|
556
|
+
const stepNavigation = opts.dropTargetDelegate.getKeyboardNavigationTarget;
|
|
557
|
+
const resolveStepTarget = (
|
|
558
|
+
target: DropTarget | null,
|
|
559
|
+
navDirection: 'next' | 'previous'
|
|
560
|
+
): DropTarget | null =>
|
|
561
|
+
stepNavigation?.(target, navDirection, isValidDropTarget)
|
|
562
|
+
?? resolveFallbackKeyboardTarget(navDirection === 'next' ? 'ArrowDown' : 'ArrowUp', target)
|
|
563
|
+
?? resolveFallbackKeyboardTarget(navDirection === 'next' ? 'Home' : 'End', target)
|
|
564
|
+
?? null;
|
|
565
|
+
let nextTarget: DropTarget | null = null;
|
|
566
|
+
if (!state.target) {
|
|
567
|
+
nextTarget = findNextValidTarget(null, (target) => resolveStepTarget(target, direction));
|
|
568
|
+
} else {
|
|
569
|
+
const pageTarget = pageNavigation?.(state.target, direction, isValidDropTarget)
|
|
570
|
+
?? resolvePageTargetForState(direction, state.target)
|
|
571
|
+
?? null;
|
|
572
|
+
if (pageTarget && isValidDropTarget(pageTarget)) {
|
|
573
|
+
nextTarget = pageTarget;
|
|
574
|
+
} else {
|
|
575
|
+
const startTarget = pageTarget ?? state.target;
|
|
576
|
+
nextTarget = findNextValidTarget(startTarget, (target) => resolveStepTarget(target, direction))
|
|
577
|
+
?? findNextValidTarget(
|
|
578
|
+
startTarget,
|
|
579
|
+
(target) => resolveStepTarget(target, direction === 'next' ? 'previous' : 'next')
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (nextTarget) {
|
|
584
|
+
e.preventDefault();
|
|
585
|
+
state.setTarget(nextTarget);
|
|
586
|
+
}
|
|
587
|
+
callUserOnKeyDown();
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
if (
|
|
591
|
+
(e.key === 'ArrowDown' ||
|
|
592
|
+
e.key === 'ArrowUp' ||
|
|
593
|
+
e.key === 'ArrowRight' ||
|
|
594
|
+
e.key === 'ArrowLeft' ||
|
|
595
|
+
e.key === 'Home' ||
|
|
596
|
+
e.key === 'End') &&
|
|
597
|
+
opts.dropTargetDelegate.getKeyboardNavigationTarget
|
|
598
|
+
) {
|
|
599
|
+
if (
|
|
600
|
+
(e.key === 'ArrowDown' && !opts.keyboardDelegate?.getKeyBelow) ||
|
|
601
|
+
(e.key === 'ArrowUp' && !opts.keyboardDelegate?.getKeyAbove) ||
|
|
602
|
+
(e.key === 'ArrowLeft' && !opts.keyboardDelegate?.getKeyLeftOf) ||
|
|
603
|
+
(e.key === 'ArrowRight' && !opts.keyboardDelegate?.getKeyRightOf) ||
|
|
604
|
+
(e.key === 'Home' && !opts.keyboardDelegate?.getFirstKey) ||
|
|
605
|
+
(e.key === 'End' && !opts.keyboardDelegate?.getLastKey)
|
|
606
|
+
) {
|
|
607
|
+
callUserOnKeyDown();
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
const isForwardKey = e.key === 'ArrowDown' || e.key === forwardHorizontalKey || e.key === 'Home';
|
|
611
|
+
const direction = isForwardKey ? 'next' : 'previous';
|
|
612
|
+
const navigationStart = e.key === 'Home' || e.key === 'End' ? null : state.target;
|
|
613
|
+
const nextTarget = findNextValidTarget(navigationStart, (target) =>
|
|
614
|
+
opts.dropTargetDelegate.getKeyboardNavigationTarget?.(
|
|
615
|
+
target,
|
|
616
|
+
direction,
|
|
617
|
+
isValidDropTarget
|
|
618
|
+
) ?? resolveFallbackKeyboardTarget(e.key, target)
|
|
619
|
+
);
|
|
620
|
+
if (nextTarget) {
|
|
621
|
+
e.preventDefault();
|
|
622
|
+
state.setTarget(nextTarget);
|
|
623
|
+
}
|
|
624
|
+
callUserOnKeyDown();
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (
|
|
628
|
+
e.key === 'ArrowDown' ||
|
|
629
|
+
e.key === 'ArrowUp' ||
|
|
630
|
+
e.key === 'ArrowRight' ||
|
|
631
|
+
e.key === 'ArrowLeft' ||
|
|
632
|
+
e.key === 'Home' ||
|
|
633
|
+
e.key === 'End'
|
|
634
|
+
) {
|
|
635
|
+
if (
|
|
636
|
+
(e.key === 'ArrowDown' && !opts.keyboardDelegate?.getKeyBelow) ||
|
|
637
|
+
(e.key === 'ArrowUp' && !opts.keyboardDelegate?.getKeyAbove) ||
|
|
638
|
+
(e.key === 'ArrowLeft' && !opts.keyboardDelegate?.getKeyLeftOf) ||
|
|
639
|
+
(e.key === 'ArrowRight' && !opts.keyboardDelegate?.getKeyRightOf) ||
|
|
640
|
+
(e.key === 'Home' && !opts.keyboardDelegate?.getFirstKey) ||
|
|
641
|
+
(e.key === 'End' && !opts.keyboardDelegate?.getLastKey)
|
|
642
|
+
) {
|
|
643
|
+
callUserOnKeyDown();
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const navigationStart = e.key === 'Home' || e.key === 'End' ? null : state.target;
|
|
647
|
+
const nextTarget = findNextValidTarget(navigationStart, (target) =>
|
|
648
|
+
resolveFallbackKeyboardTarget(e.key, target)
|
|
649
|
+
);
|
|
650
|
+
if (nextTarget) {
|
|
651
|
+
e.preventDefault();
|
|
652
|
+
state.setTarget(nextTarget);
|
|
653
|
+
}
|
|
654
|
+
callUserOnKeyDown();
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
if (e.key === 'Enter' && state.target) {
|
|
658
|
+
e.preventDefault();
|
|
659
|
+
state.activateTarget(0, 0);
|
|
660
|
+
callUserOnKeyDown();
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (e.key === 'Escape' && state.target) {
|
|
664
|
+
e.preventDefault();
|
|
665
|
+
state.exitTarget(0, 0);
|
|
666
|
+
callUserOnKeyDown();
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
callUserOnKeyDown();
|
|
670
|
+
};
|
|
671
|
+
return {
|
|
672
|
+
...baseDropProps,
|
|
673
|
+
onKeyDown,
|
|
674
|
+
};
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
return {
|
|
678
|
+
get collectionProps() {
|
|
679
|
+
return collectionProps() as DroppableCollectionAria['collectionProps'];
|
|
680
|
+
},
|
|
681
|
+
};
|
|
682
|
+
}
|