@mk-drag-and-drop/dom 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +460 -0
  3. package/dist/controller/controller-internals.d.ts +5 -0
  4. package/dist/controller/controller-internals.js +11 -0
  5. package/dist/controller/create-drag-controller.d.ts +36 -0
  6. package/dist/controller/create-drag-controller.js +232 -0
  7. package/dist/draggable/create-draggable-binding.d.ts +8 -0
  8. package/dist/draggable/create-draggable-binding.js +52 -0
  9. package/dist/draggable/create-draggable.d.ts +46 -0
  10. package/dist/draggable/create-draggable.js +57 -0
  11. package/dist/droppable/create-drop-container-binding.d.ts +8 -0
  12. package/dist/droppable/create-drop-container-binding.js +28 -0
  13. package/dist/droppable/create-drop-container.d.ts +18 -0
  14. package/dist/droppable/create-drop-container.js +36 -0
  15. package/dist/droppable/create-droppable-binding.d.ts +9 -0
  16. package/dist/droppable/create-droppable-binding.js +29 -0
  17. package/dist/droppable/create-droppable.d.ts +17 -0
  18. package/dist/droppable/create-droppable.js +31 -0
  19. package/dist/geometry/measurement.d.ts +4 -0
  20. package/dist/geometry/measurement.js +33 -0
  21. package/dist/geometry/overlay.d.ts +19 -0
  22. package/dist/geometry/overlay.js +32 -0
  23. package/dist/geometry/rects.d.ts +17 -0
  24. package/dist/geometry/rects.js +34 -0
  25. package/dist/index.d.ts +16 -0
  26. package/dist/index.js +9 -0
  27. package/dist/input/config.d.ts +35 -0
  28. package/dist/input/config.js +56 -0
  29. package/dist/input/create-drag-handle.d.ts +4 -0
  30. package/dist/input/create-drag-handle.js +4 -0
  31. package/dist/input/drag-handle.d.ts +10 -0
  32. package/dist/input/drag-handle.js +74 -0
  33. package/dist/input/keyboard-drag.d.ts +28 -0
  34. package/dist/input/keyboard-drag.js +77 -0
  35. package/dist/input/pointer-activation.d.ts +31 -0
  36. package/dist/input/pointer-activation.js +97 -0
  37. package/dist/integration/index.d.ts +10 -0
  38. package/dist/integration/index.js +6 -0
  39. package/dist/modifiers/built-ins.d.ts +6 -0
  40. package/dist/modifiers/built-ins.js +62 -0
  41. package/dist/modifiers/pipeline.d.ts +18 -0
  42. package/dist/modifiers/pipeline.js +34 -0
  43. package/dist/modifiers/types.d.ts +32 -0
  44. package/dist/modifiers/types.js +1 -0
  45. package/dist/runtime/drag-runtime-handle.d.ts +22 -0
  46. package/dist/runtime/drag-runtime-handle.js +33 -0
  47. package/dist/runtime/drag-runtime.d.ts +96 -0
  48. package/dist/runtime/drag-runtime.js +798 -0
  49. package/dist/runtime/drop-target-registry.d.ts +101 -0
  50. package/dist/runtime/drop-target-registry.js +855 -0
  51. package/dist/runtime/lifecycle.d.ts +44 -0
  52. package/dist/runtime/lifecycle.js +1 -0
  53. package/dist/runtime/types.d.ts +65 -0
  54. package/dist/runtime/types.js +1 -0
  55. package/dist/sortable/create-sortable-binding.d.ts +10 -0
  56. package/dist/sortable/create-sortable-binding.js +58 -0
  57. package/dist/sortable/create-sortable.d.ts +19 -0
  58. package/dist/sortable/create-sortable.js +55 -0
  59. package/dist/sortable/sortable-options.d.ts +17 -0
  60. package/dist/sortable/sortable-options.js +20 -0
  61. package/dist/sortable/sortable-preview.d.ts +79 -0
  62. package/dist/sortable/sortable-preview.js +357 -0
  63. package/dist/sortable/sortable-registry.d.ts +113 -0
  64. package/dist/sortable/sortable-registry.js +145 -0
  65. package/dist/targeting/algorithms.d.ts +6 -0
  66. package/dist/targeting/algorithms.js +56 -0
  67. package/dist/targeting/constraints.d.ts +15 -0
  68. package/dist/targeting/constraints.js +58 -0
  69. package/dist/targeting/types.d.ts +23 -0
  70. package/dist/targeting/types.js +1 -0
  71. package/package.json +60 -0
@@ -0,0 +1,855 @@
1
+ import { documentRectToViewportRect, measureDocumentRect, } from "../geometry/measurement.js";
2
+ import { emptyDragRect } from "../geometry/rects.js";
3
+ const sortableCandidateWindowRadius = 3;
4
+ export class DropTargetRegistry {
5
+ targetsByGroup = new Map();
6
+ targetElements = new WeakMap();
7
+ sortableAxisIndexes = new Map();
8
+ register(id, element, group, options = {}) {
9
+ const groupTargets = this.getOrCreateGroupTargets(group);
10
+ const previousElementTarget = this.targetElements.get(element);
11
+ const removedTargets = [];
12
+ if (previousElementTarget) {
13
+ const previousEntry = this.targetsByGroup
14
+ .get(previousElementTarget.group)
15
+ ?.get(previousElementTarget.id);
16
+ const previousElement = previousEntry
17
+ ? this.resolveEntry(previousEntry)
18
+ : null;
19
+ if (previousElement === element) {
20
+ if (previousElementTarget.group !== group ||
21
+ previousElementTarget.id !== id) {
22
+ removedTargets.push(...this.removeTarget(previousElementTarget.group, previousElementTarget.id));
23
+ }
24
+ }
25
+ else {
26
+ this.targetElements.delete(element);
27
+ }
28
+ }
29
+ const displacedEntry = groupTargets.get(id);
30
+ const displacedElement = displacedEntry
31
+ ? this.resolveEntry(displacedEntry)
32
+ : null;
33
+ if (displacedElement && displacedElement !== element) {
34
+ this.targetElements.delete(displacedElement);
35
+ }
36
+ const entry = {
37
+ id,
38
+ elementRef: new WeakRef(element),
39
+ group,
40
+ containerId: options.containerId ?? null,
41
+ capabilities: {
42
+ container: options.container ?? false,
43
+ sortable: options.sortable ?? false,
44
+ },
45
+ sortableAxis: options.sortable ? options.sortableAxis ?? null : null,
46
+ documentRect: emptyDragRect,
47
+ };
48
+ groupTargets.set(id, entry);
49
+ this.targetElements.set(element, { group, id });
50
+ this.remeasureEntry(entry);
51
+ this.syncSortableAxisIndexAfterRegister(group, entry, element);
52
+ return removedTargets;
53
+ }
54
+ unregister(id, element) {
55
+ if (element) {
56
+ const target = this.targetElements.get(element);
57
+ if (!target || target.id !== id) {
58
+ return [];
59
+ }
60
+ const entry = this.targetsByGroup.get(target.group)?.get(target.id);
61
+ if (!entry || entry.elementRef.deref() !== element) {
62
+ this.targetElements.delete(element);
63
+ return [];
64
+ }
65
+ this.targetElements.delete(element);
66
+ return this.removeTarget(target.group, target.id);
67
+ }
68
+ const removedTargets = [];
69
+ for (const group of Array.from(this.targetsByGroup.keys())) {
70
+ removedTargets.push(...this.removeTarget(group, id));
71
+ }
72
+ return removedTargets;
73
+ }
74
+ pruneDisconnected(group) {
75
+ const removedTargets = [];
76
+ if (group !== undefined) {
77
+ const groupTargets = this.targetsByGroup.get(group);
78
+ return groupTargets
79
+ ? this.pruneDisconnectedGroup(group, groupTargets)
80
+ : removedTargets;
81
+ }
82
+ for (const [targetGroup, groupTargets] of this.targetsByGroup) {
83
+ removedTargets.push(...this.pruneDisconnectedGroup(targetGroup, groupTargets));
84
+ }
85
+ return removedTargets;
86
+ }
87
+ clear() {
88
+ this.targetsByGroup.clear();
89
+ this.targetElements = new WeakMap();
90
+ this.sortableAxisIndexes.clear();
91
+ }
92
+ remeasure(input) {
93
+ if (input === undefined) {
94
+ for (const groupTargets of this.targetsByGroup.values()) {
95
+ for (const target of groupTargets.values()) {
96
+ this.remeasureEntry(target);
97
+ }
98
+ }
99
+ this.sortableAxisIndexes.clear();
100
+ return;
101
+ }
102
+ if (typeof input === "string") {
103
+ for (const group of this.remeasureTarget(input)) {
104
+ this.sortableAxisIndexes.delete(group);
105
+ }
106
+ return;
107
+ }
108
+ if (Array.isArray(input)) {
109
+ const remeasuredGroups = new Set();
110
+ for (const dropTargetId of input) {
111
+ for (const group of this.remeasureTarget(dropTargetId)) {
112
+ remeasuredGroups.add(group);
113
+ }
114
+ }
115
+ for (const group of remeasuredGroups) {
116
+ this.sortableAxisIndexes.delete(group);
117
+ }
118
+ return;
119
+ }
120
+ const groupTargets = this.targetsByGroup.get(input.group);
121
+ if (!groupTargets) {
122
+ return;
123
+ }
124
+ for (const dropTarget of groupTargets.values()) {
125
+ this.remeasureEntry(dropTarget);
126
+ }
127
+ this.sortableAxisIndexes.delete(input.group);
128
+ }
129
+ getViewportRect(id, group) {
130
+ const registration = this.findRegistration(id, { group });
131
+ return registration
132
+ ? documentRectToViewportRect(registration.documentRect)
133
+ : null;
134
+ }
135
+ getDropTargetRegistration(id, group) {
136
+ const registration = this.findRegistration(id, { group });
137
+ return registration ? toPublicRegistration(registration) : null;
138
+ }
139
+ getAvailableDropTargets(input) {
140
+ if (input.group === null) {
141
+ return [];
142
+ }
143
+ const groupTargets = this.targetsByGroup.get(input.group);
144
+ if (!groupTargets) {
145
+ return [];
146
+ }
147
+ const sortableCandidates = this.getNarrowedSortableDropTargetEntries(input, groupTargets);
148
+ if (sortableCandidates) {
149
+ const dropTargets = this.getAvailableDropTargetsFromEntries(sortableCandidates, input);
150
+ if (!input.targetingConstraint || dropTargets.length > 0) {
151
+ return dropTargets;
152
+ }
153
+ }
154
+ return this.getAvailableDropTargetsFromEntries(groupTargets.values(), input);
155
+ }
156
+ getAvailableDropTargetsFromEntries(entries, input) {
157
+ const candidates = [];
158
+ let hasContainerCandidate = false;
159
+ for (const target of entries) {
160
+ const element = this.resolveEntry(target);
161
+ if (!element) {
162
+ continue;
163
+ }
164
+ if (target.capabilities.container) {
165
+ hasContainerCandidate = true;
166
+ }
167
+ candidates.push({
168
+ entry: target,
169
+ element,
170
+ viewportRect: documentRectToViewportRect(target.documentRect),
171
+ });
172
+ }
173
+ const candidateParentElements = hasContainerCandidate
174
+ ? getCandidateParentElements(candidates)
175
+ : null;
176
+ const dropTargets = [];
177
+ for (const candidate of candidates) {
178
+ if (candidate.entry.capabilities.container &&
179
+ candidateParentElements &&
180
+ !shouldIncludeContainerCandidate({
181
+ candidateParentElements,
182
+ containerCandidate: candidate,
183
+ pointerPosition: input.pointerPosition,
184
+ })) {
185
+ continue;
186
+ }
187
+ const candidateDropTarget = {
188
+ dropTargetId: candidate.entry.id,
189
+ dropTargetRect: candidate.viewportRect,
190
+ };
191
+ if (input.targetingConstraint &&
192
+ !input.targetingConstraint({
193
+ pointerPosition: input.pointerPosition,
194
+ overlayRect: input.overlayRect,
195
+ dropTarget: candidateDropTarget,
196
+ })) {
197
+ continue;
198
+ }
199
+ dropTargets.push(candidateDropTarget);
200
+ }
201
+ return dropTargets;
202
+ }
203
+ getSortableDropPlacement(input) {
204
+ if (input.dropTargetId === null || input.group === null) {
205
+ return null;
206
+ }
207
+ const dropTarget = this.findRegistration(input.dropTargetId, {
208
+ group: input.group,
209
+ });
210
+ if (!dropTarget) {
211
+ return null;
212
+ }
213
+ const itemRegistration = this.findRegistration(input.draggableId, {
214
+ group: input.group,
215
+ });
216
+ if (!itemRegistration?.capabilities.sortable) {
217
+ return null;
218
+ }
219
+ if (!dropTarget.capabilities.sortable &&
220
+ !dropTarget.capabilities.container) {
221
+ return null;
222
+ }
223
+ const previewContainer = dropTarget.id === input.draggableId
224
+ ? this.findContainerRegistrationForElement({
225
+ element: itemRegistration?.element.parentElement ?? null,
226
+ group: input.group,
227
+ })
228
+ : null;
229
+ const containerId = previewContainer?.containerId ?? dropTarget.containerId;
230
+ const containerElement = previewContainer?.element ?? getDropTargetContainerElement(dropTarget);
231
+ const siblingPlacement = this.getSiblingPlacement({
232
+ draggableId: input.draggableId,
233
+ group: input.group,
234
+ itemElement: itemRegistration.element,
235
+ dropTarget,
236
+ containerElement,
237
+ });
238
+ const targetPlacement = this.getTargetPlacement({
239
+ draggableId: input.draggableId,
240
+ group: input.group,
241
+ itemElement: itemRegistration.element,
242
+ dropTarget,
243
+ });
244
+ return {
245
+ sourceContainerId: input.sourceContainerId,
246
+ containerId,
247
+ previousDraggableId: siblingPlacement.previousDraggableId,
248
+ nextDraggableId: siblingPlacement.nextDraggableId,
249
+ targetDraggableId: targetPlacement.targetDraggableId,
250
+ side: targetPlacement.side,
251
+ };
252
+ }
253
+ getSortableItemPlacement(draggableId, group) {
254
+ const registration = this.findRegistration(draggableId, { group });
255
+ if (!registration?.capabilities.sortable ||
256
+ !registration.element.parentElement) {
257
+ return null;
258
+ }
259
+ const { element } = registration;
260
+ const itemGroup = registration.group;
261
+ const previousDraggableId = this.getNearestSortableSiblingDraggableId(element.previousElementSibling, itemGroup, "previous");
262
+ const nextDraggableId = this.getNearestSortableSiblingDraggableId(element.nextElementSibling, itemGroup, "next");
263
+ return {
264
+ containerId: registration.containerId,
265
+ previousDraggableId,
266
+ nextDraggableId,
267
+ exactAnchors: this.getExactSortableItemAnchors(element, itemGroup),
268
+ };
269
+ }
270
+ getOrCreateGroupTargets(group) {
271
+ let groupTargets = this.targetsByGroup.get(group);
272
+ if (!groupTargets) {
273
+ groupTargets = new Map();
274
+ this.targetsByGroup.set(group, groupTargets);
275
+ }
276
+ return groupTargets;
277
+ }
278
+ removeTarget(group, id) {
279
+ const groupTargets = this.targetsByGroup.get(group);
280
+ if (!groupTargets?.delete(id)) {
281
+ return [];
282
+ }
283
+ this.sortableAxisIndexes.delete(group);
284
+ if (groupTargets.size === 0) {
285
+ this.targetsByGroup.delete(group);
286
+ }
287
+ return [{ id, group }];
288
+ }
289
+ pruneDisconnectedGroup(group, groupTargets) {
290
+ const removedTargets = [];
291
+ for (const [id, entry] of groupTargets) {
292
+ if (this.resolveEntry(entry)) {
293
+ continue;
294
+ }
295
+ groupTargets.delete(id);
296
+ removedTargets.push({ id, group });
297
+ }
298
+ if (removedTargets.length > 0) {
299
+ this.sortableAxisIndexes.delete(group);
300
+ }
301
+ if (groupTargets.size === 0) {
302
+ this.targetsByGroup.delete(group);
303
+ }
304
+ return removedTargets;
305
+ }
306
+ remeasureTarget(dropTargetId) {
307
+ const remeasuredGroups = [];
308
+ for (const groupTargets of this.targetsByGroup.values()) {
309
+ const dropTarget = groupTargets.get(dropTargetId);
310
+ if (dropTarget) {
311
+ this.remeasureEntry(dropTarget);
312
+ remeasuredGroups.push(dropTarget.group);
313
+ }
314
+ }
315
+ return remeasuredGroups;
316
+ }
317
+ remeasureEntry(registration) {
318
+ const element = this.resolveEntry(registration);
319
+ if (!element) {
320
+ return;
321
+ }
322
+ registration.documentRect = measureDocumentRect(element);
323
+ }
324
+ findRegistration(id, input = {}) {
325
+ const entry = this.findEntry(id, input);
326
+ return entry ? this.resolveRegistration(entry) : null;
327
+ }
328
+ findEntry(id, input = {}) {
329
+ if (input.group !== undefined) {
330
+ return (input.group === null
331
+ ? null
332
+ : this.targetsByGroup.get(input.group)?.get(id) ?? null);
333
+ }
334
+ for (const groupTargets of this.targetsByGroup.values()) {
335
+ const entry = groupTargets.get(id);
336
+ if (entry && this.resolveEntry(entry)) {
337
+ return entry;
338
+ }
339
+ }
340
+ return null;
341
+ }
342
+ resolveRegistration(entry) {
343
+ const element = this.resolveEntry(entry);
344
+ return element
345
+ ? {
346
+ ...entry,
347
+ element,
348
+ }
349
+ : null;
350
+ }
351
+ resolveEntry(entry) {
352
+ const element = entry.elementRef.deref();
353
+ return element?.isConnected ? element : null;
354
+ }
355
+ getNarrowedSortableDropTargetEntries(input, groupTargets) {
356
+ if (input.group === null ||
357
+ !input.targetingAlgorithmKind ||
358
+ !input.draggingDraggableId) {
359
+ return null;
360
+ }
361
+ const index = this.getSortableAxisIndex(input.group, groupTargets);
362
+ if (!index || index.unsupported) {
363
+ return null;
364
+ }
365
+ if (!index.candidatesById.has(input.draggingDraggableId)) {
366
+ return null;
367
+ }
368
+ const axisCoordinate = getSortableQueryAxisCoordinate({
369
+ axis: index.axis,
370
+ overlayRect: input.overlayRect,
371
+ pointerPosition: input.pointerPosition,
372
+ targetingAlgorithmKind: input.targetingAlgorithmKind,
373
+ });
374
+ if (axisCoordinate === null) {
375
+ return null;
376
+ }
377
+ const candidates = new Map();
378
+ const addCandidate = (candidate) => {
379
+ if (candidate) {
380
+ candidates.set(candidate.id, candidate);
381
+ }
382
+ };
383
+ const nearestIndex = getNearestSortableAxisIndex(index.candidatesByCenter, axisCoordinate);
384
+ if (nearestIndex !== null) {
385
+ for (let candidateIndex = Math.max(0, nearestIndex - sortableCandidateWindowRadius); candidateIndex <=
386
+ Math.min(index.candidatesByCenter.length - 1, nearestIndex + sortableCandidateWindowRadius); candidateIndex += 1) {
387
+ addCandidate(index.candidatesByCenter[candidateIndex]);
388
+ }
389
+ }
390
+ addCandidate(findSortableAxisCandidateContainingCoordinate(index.candidatesByStart, axisCoordinate));
391
+ addCandidate(index.candidatesById.get(input.draggingDraggableId));
392
+ addCandidate(input.activeDropTargetId
393
+ ? index.candidatesById.get(input.activeDropTargetId)
394
+ : undefined);
395
+ addCandidate(input.sourceContainerId
396
+ ? index.candidatesById.get(input.sourceContainerId)
397
+ : undefined);
398
+ this.addSortableDomNeighborCandidates({
399
+ candidates,
400
+ group: input.group,
401
+ index,
402
+ targetId: input.draggingDraggableId,
403
+ });
404
+ if (input.activeDropTargetId) {
405
+ this.addSortableDomNeighborCandidates({
406
+ candidates,
407
+ group: input.group,
408
+ index,
409
+ targetId: input.activeDropTargetId,
410
+ });
411
+ }
412
+ return Array.from(candidates.values(), (candidate) => candidate.entry);
413
+ }
414
+ getSortableAxisIndex(group, groupTargets) {
415
+ const existingIndex = this.sortableAxisIndexes.get(group);
416
+ if (existingIndex) {
417
+ return existingIndex;
418
+ }
419
+ const index = this.createSortableAxisIndex(groupTargets);
420
+ if (index) {
421
+ this.sortableAxisIndexes.set(group, index);
422
+ }
423
+ return index;
424
+ }
425
+ createSortableAxisIndex(groupTargets) {
426
+ let axis = null;
427
+ let containerId;
428
+ const candidates = [];
429
+ for (const entry of groupTargets.values()) {
430
+ const element = this.resolveEntry(entry);
431
+ if (!element) {
432
+ continue;
433
+ }
434
+ if (entry.capabilities.container ||
435
+ !entry.capabilities.sortable ||
436
+ entry.sortableAxis === null) {
437
+ return createUnsupportedSortableAxisIndex();
438
+ }
439
+ if (axis === null) {
440
+ axis = entry.sortableAxis;
441
+ }
442
+ else if (axis !== entry.sortableAxis) {
443
+ return createUnsupportedSortableAxisIndex();
444
+ }
445
+ if (containerId === undefined) {
446
+ containerId = entry.containerId;
447
+ }
448
+ else if (containerId !== entry.containerId) {
449
+ return createUnsupportedSortableAxisIndex();
450
+ }
451
+ candidates.push(createSortableAxisCandidate(entry, element, entry.sortableAxis));
452
+ }
453
+ if (axis === null || candidates.length === 0) {
454
+ return null;
455
+ }
456
+ const candidatesByCenter = [...candidates].sort(compareAxisCenter);
457
+ const candidatesByStart = [...candidates].sort(compareAxisStart);
458
+ const index = {
459
+ axis,
460
+ containerId: containerId ?? null,
461
+ candidatesByCenter,
462
+ candidatesByStart,
463
+ candidatesById: new Map(candidates.map((candidate) => [candidate.id, candidate])),
464
+ unsupported: hasOverlappingSortableAxisRanges(candidatesByStart),
465
+ };
466
+ return index;
467
+ }
468
+ syncSortableAxisIndexAfterRegister(group, entry, element) {
469
+ const index = this.sortableAxisIndexes.get(group);
470
+ if (!index) {
471
+ return;
472
+ }
473
+ if (index.unsupported ||
474
+ entry.capabilities.container ||
475
+ !entry.capabilities.sortable ||
476
+ entry.sortableAxis !== index.axis ||
477
+ entry.containerId !== index.containerId) {
478
+ this.sortableAxisIndexes.delete(group);
479
+ return;
480
+ }
481
+ const candidate = index.candidatesById.get(entry.id);
482
+ if (!candidate) {
483
+ this.sortableAxisIndexes.delete(group);
484
+ return;
485
+ }
486
+ const updatedCandidate = createSortableAxisCandidate(entry, element, index.axis);
487
+ candidate.entry = updatedCandidate.entry;
488
+ candidate.element = updatedCandidate.element;
489
+ candidate.containerId = updatedCandidate.containerId;
490
+ candidate.axisStart = updatedCandidate.axisStart;
491
+ candidate.axisEnd = updatedCandidate.axisEnd;
492
+ candidate.axisCenter = updatedCandidate.axisCenter;
493
+ }
494
+ addSortableDomNeighborCandidates(input) {
495
+ const registration = this.findRegistration(input.targetId, {
496
+ group: input.group,
497
+ });
498
+ if (!registration) {
499
+ return;
500
+ }
501
+ const previousDraggableId = this.getNearestSortableSiblingDraggableId(registration.element.previousElementSibling, input.group, "previous");
502
+ const nextDraggableId = this.getNearestSortableSiblingDraggableId(registration.element.nextElementSibling, input.group, "next");
503
+ if (previousDraggableId) {
504
+ const previousCandidate = input.index.candidatesById.get(previousDraggableId);
505
+ if (previousCandidate) {
506
+ input.candidates.set(previousDraggableId, previousCandidate);
507
+ }
508
+ }
509
+ if (nextDraggableId) {
510
+ const nextCandidate = input.index.candidatesById.get(nextDraggableId);
511
+ if (nextCandidate) {
512
+ input.candidates.set(nextDraggableId, nextCandidate);
513
+ }
514
+ }
515
+ }
516
+ findContainerRegistrationForElement(input) {
517
+ if (!input.element) {
518
+ return null;
519
+ }
520
+ const groupTargets = this.targetsByGroup.get(input.group);
521
+ if (!groupTargets) {
522
+ return null;
523
+ }
524
+ for (const entry of groupTargets.values()) {
525
+ const element = this.resolveEntry(entry);
526
+ if (entry.capabilities.container &&
527
+ element &&
528
+ element === input.element) {
529
+ return {
530
+ ...entry,
531
+ element,
532
+ };
533
+ }
534
+ }
535
+ return null;
536
+ }
537
+ getSiblingPlacement(input) {
538
+ if (input.itemElement.parentElement &&
539
+ input.itemElement.parentElement === input.containerElement) {
540
+ return {
541
+ previousDraggableId: this.getNearestSortableSiblingDraggableId(input.itemElement.previousElementSibling, input.group, "previous", input.draggableId),
542
+ nextDraggableId: this.getNearestSortableSiblingDraggableId(input.itemElement.nextElementSibling, input.group, "next", input.draggableId),
543
+ };
544
+ }
545
+ if (input.dropTarget.capabilities.container) {
546
+ return {
547
+ previousDraggableId: this.getNearestSortableSiblingDraggableId(input.dropTarget.element.lastElementChild, input.group, "previous", input.draggableId),
548
+ nextDraggableId: null,
549
+ };
550
+ }
551
+ return {
552
+ previousDraggableId: this.getNearestSortableSiblingDraggableId(input.dropTarget.element.previousElementSibling, input.group, "previous", input.draggableId),
553
+ nextDraggableId: input.dropTarget.id,
554
+ };
555
+ }
556
+ getTargetPlacement(input) {
557
+ if (!input.dropTarget.capabilities.sortable) {
558
+ return {
559
+ targetDraggableId: null,
560
+ side: null,
561
+ };
562
+ }
563
+ if (input.dropTarget.id === input.draggableId) {
564
+ return this.getPreviewDomTargetPlacement({
565
+ draggableId: input.draggableId,
566
+ group: input.group,
567
+ itemElement: input.itemElement,
568
+ });
569
+ }
570
+ return {
571
+ targetDraggableId: input.dropTarget.id,
572
+ side: getSortableTargetSide({
573
+ itemElement: input.itemElement,
574
+ targetElement: input.dropTarget.element,
575
+ }),
576
+ };
577
+ }
578
+ getExactSortableItemAnchors(element, group) {
579
+ const anchors = [];
580
+ const previousDraggableId = this.getSortableDraggableId(element.previousElementSibling, group);
581
+ const nextDraggableId = this.getSortableDraggableId(element.nextElementSibling, group);
582
+ if (previousDraggableId) {
583
+ anchors.push({
584
+ targetDraggableId: previousDraggableId,
585
+ side: "after",
586
+ });
587
+ }
588
+ if (nextDraggableId) {
589
+ anchors.push({
590
+ targetDraggableId: nextDraggableId,
591
+ side: "before",
592
+ });
593
+ }
594
+ return anchors;
595
+ }
596
+ getPreviewDomTargetPlacement(input) {
597
+ const previousElement = input.itemElement.previousElementSibling;
598
+ const nextElement = input.itemElement.nextElementSibling;
599
+ const previousDraggableId = this.getSortableDraggableId(previousElement, input.group);
600
+ const nextDraggableId = this.getSortableDraggableId(nextElement, input.group);
601
+ if (this.isSkippedSortableSibling(previousElement, input.group) &&
602
+ nextDraggableId &&
603
+ nextDraggableId !== input.draggableId) {
604
+ return {
605
+ targetDraggableId: nextDraggableId,
606
+ side: "before",
607
+ };
608
+ }
609
+ if (this.isSkippedSortableSibling(nextElement, input.group) &&
610
+ previousDraggableId &&
611
+ previousDraggableId !== input.draggableId) {
612
+ return {
613
+ targetDraggableId: previousDraggableId,
614
+ side: "after",
615
+ };
616
+ }
617
+ if (previousDraggableId && previousDraggableId !== input.draggableId) {
618
+ return {
619
+ targetDraggableId: previousDraggableId,
620
+ side: "after",
621
+ };
622
+ }
623
+ if (nextDraggableId && nextDraggableId !== input.draggableId) {
624
+ return {
625
+ targetDraggableId: nextDraggableId,
626
+ side: "before",
627
+ };
628
+ }
629
+ const previousNearestDraggableId = this.getNearestSortableSiblingDraggableId(previousElement, input.group, "previous", input.draggableId);
630
+ if (previousNearestDraggableId) {
631
+ return {
632
+ targetDraggableId: previousNearestDraggableId,
633
+ side: "after",
634
+ };
635
+ }
636
+ const nextNearestDraggableId = this.getNearestSortableSiblingDraggableId(nextElement, input.group, "next", input.draggableId);
637
+ if (nextNearestDraggableId) {
638
+ return {
639
+ targetDraggableId: nextNearestDraggableId,
640
+ side: "before",
641
+ };
642
+ }
643
+ return {
644
+ targetDraggableId: null,
645
+ side: null,
646
+ };
647
+ }
648
+ isSkippedSortableSibling(element, group) {
649
+ return (element instanceof HTMLElement &&
650
+ element.dataset.dndSortableDraggable !== undefined &&
651
+ this.getSortableDraggableId(element, group) === null);
652
+ }
653
+ getNearestSortableSiblingDraggableId(element, group, direction, excludeDraggableId) {
654
+ let currentElement = element;
655
+ while (currentElement) {
656
+ const draggableId = this.getSortableDraggableId(currentElement, group);
657
+ if (draggableId && draggableId !== excludeDraggableId) {
658
+ return draggableId;
659
+ }
660
+ currentElement =
661
+ direction === "previous"
662
+ ? currentElement.previousElementSibling
663
+ : currentElement.nextElementSibling;
664
+ }
665
+ return null;
666
+ }
667
+ getSortableDraggableId(element, group) {
668
+ if (!(element instanceof HTMLElement)) {
669
+ return null;
670
+ }
671
+ const target = this.targetElements.get(element);
672
+ const entry = target
673
+ ? this.targetsByGroup.get(group)?.get(target.id) ?? null
674
+ : null;
675
+ if (!entry?.capabilities.sortable || entry.group !== group) {
676
+ return null;
677
+ }
678
+ return this.resolveEntry(entry) === element ? entry.id : null;
679
+ }
680
+ }
681
+ function toPublicRegistration(registration) {
682
+ return {
683
+ id: registration.id,
684
+ element: registration.element,
685
+ group: registration.group,
686
+ containerId: registration.containerId,
687
+ capabilities: registration.capabilities,
688
+ };
689
+ }
690
+ function getDropTargetContainerElement(dropTarget) {
691
+ return dropTarget.capabilities.container
692
+ ? dropTarget.element
693
+ : dropTarget.element.parentElement;
694
+ }
695
+ function getSortableTargetSide(input) {
696
+ if (input.itemElement === input.targetElement ||
697
+ input.itemElement.parentElement !== input.targetElement.parentElement) {
698
+ return null;
699
+ }
700
+ const position = input.targetElement.compareDocumentPosition(input.itemElement);
701
+ if ((position & Node.DOCUMENT_POSITION_FOLLOWING) !== 0) {
702
+ return "after";
703
+ }
704
+ if ((position & Node.DOCUMENT_POSITION_PRECEDING) !== 0) {
705
+ return "before";
706
+ }
707
+ return null;
708
+ }
709
+ function shouldIncludeContainerCandidate(input) {
710
+ if (!isPointInsideRect(input.pointerPosition, input.containerCandidate.viewportRect)) {
711
+ return false;
712
+ }
713
+ return !input.candidateParentElements.has(input.containerCandidate.element);
714
+ }
715
+ function getCandidateParentElements(candidates) {
716
+ const parentElements = new Set();
717
+ for (const candidate of candidates) {
718
+ const parentElement = candidate.element.parentElement;
719
+ if (parentElement) {
720
+ parentElements.add(parentElement);
721
+ }
722
+ }
723
+ return parentElements;
724
+ }
725
+ function createUnsupportedSortableAxisIndex() {
726
+ return {
727
+ axis: "vertical",
728
+ containerId: null,
729
+ candidatesByCenter: [],
730
+ candidatesByStart: [],
731
+ candidatesById: new Map(),
732
+ unsupported: true,
733
+ };
734
+ }
735
+ function createSortableAxisCandidate(entry, element, axis) {
736
+ const coordinates = getSortableAxisCoordinates(entry.documentRect, axis);
737
+ return {
738
+ id: entry.id,
739
+ entry,
740
+ element,
741
+ containerId: entry.containerId,
742
+ axisStart: coordinates.start,
743
+ axisEnd: coordinates.end,
744
+ axisCenter: coordinates.center,
745
+ };
746
+ }
747
+ function getSortableAxisCoordinates(rect, axis) {
748
+ if (axis === "horizontal") {
749
+ return {
750
+ start: rect.left,
751
+ end: rect.right,
752
+ center: rect.left + rect.width / 2,
753
+ };
754
+ }
755
+ return {
756
+ start: rect.top,
757
+ end: rect.bottom,
758
+ center: rect.top + rect.height / 2,
759
+ };
760
+ }
761
+ function getSortableQueryAxisCoordinate(input) {
762
+ if (input.targetingAlgorithmKind === "center-to-center") {
763
+ if (!input.overlayRect) {
764
+ return null;
765
+ }
766
+ const coordinates = getSortableAxisCoordinates(input.overlayRect, input.axis);
767
+ return coordinates.center + getDocumentScrollOffset(input.axis);
768
+ }
769
+ return ((input.axis === "horizontal"
770
+ ? input.pointerPosition.x
771
+ : input.pointerPosition.y) + getDocumentScrollOffset(input.axis));
772
+ }
773
+ function getDocumentScrollOffset(axis) {
774
+ return axis === "horizontal" ? window.scrollX : window.scrollY;
775
+ }
776
+ function getNearestSortableAxisIndex(candidates, axisCoordinate) {
777
+ if (candidates.length === 0) {
778
+ return null;
779
+ }
780
+ let low = 0;
781
+ let high = candidates.length - 1;
782
+ while (low <= high) {
783
+ const mid = Math.floor((low + high) / 2);
784
+ const candidate = candidates[mid];
785
+ if (!candidate) {
786
+ return null;
787
+ }
788
+ if (candidate.axisCenter < axisCoordinate) {
789
+ low = mid + 1;
790
+ }
791
+ else {
792
+ high = mid - 1;
793
+ }
794
+ }
795
+ if (low <= 0) {
796
+ return 0;
797
+ }
798
+ if (low >= candidates.length) {
799
+ return candidates.length - 1;
800
+ }
801
+ const previous = candidates[low - 1];
802
+ const next = candidates[low];
803
+ if (!previous || !next) {
804
+ return low;
805
+ }
806
+ return axisCoordinate - previous.axisCenter <= next.axisCenter - axisCoordinate
807
+ ? low - 1
808
+ : low;
809
+ }
810
+ function findSortableAxisCandidateContainingCoordinate(candidatesByStart, axisCoordinate) {
811
+ let low = 0;
812
+ let high = candidatesByStart.length - 1;
813
+ let lastStartBeforeCoordinate = -1;
814
+ while (low <= high) {
815
+ const mid = Math.floor((low + high) / 2);
816
+ const candidate = candidatesByStart[mid];
817
+ if (!candidate) {
818
+ return undefined;
819
+ }
820
+ if (candidate.axisStart <= axisCoordinate) {
821
+ lastStartBeforeCoordinate = mid;
822
+ low = mid + 1;
823
+ }
824
+ else {
825
+ high = mid - 1;
826
+ }
827
+ }
828
+ if (lastStartBeforeCoordinate === -1) {
829
+ return undefined;
830
+ }
831
+ const candidate = candidatesByStart[lastStartBeforeCoordinate];
832
+ return candidate && candidate.axisEnd >= axisCoordinate ? candidate : undefined;
833
+ }
834
+ function hasOverlappingSortableAxisRanges(candidatesByStart) {
835
+ let previousAxisEnd = Number.NEGATIVE_INFINITY;
836
+ for (const candidate of candidatesByStart) {
837
+ if (candidate.axisStart < previousAxisEnd) {
838
+ return true;
839
+ }
840
+ previousAxisEnd = Math.max(previousAxisEnd, candidate.axisEnd);
841
+ }
842
+ return false;
843
+ }
844
+ function compareAxisCenter(a, b) {
845
+ return a.axisCenter - b.axisCenter;
846
+ }
847
+ function compareAxisStart(a, b) {
848
+ return a.axisStart - b.axisStart;
849
+ }
850
+ function isPointInsideRect(point, rect) {
851
+ return (point.x >= rect.left &&
852
+ point.x <= rect.right &&
853
+ point.y >= rect.top &&
854
+ point.y <= rect.bottom);
855
+ }