@hkdigital/lib-sveltekit 0.2.9 → 0.2.11
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/components/drag-drop/DragDropContext.svelte +2 -3
- package/dist/components/drag-drop/Draggable.svelte +125 -104
- package/dist/components/drag-drop/Draggable.svelte.d.ts +2 -0
- package/dist/components/drag-drop/actions.d.ts +4 -1
- package/dist/components/drag-drop/actions.js +12 -4
- package/dist/components/drag-drop/drag-state.svelte.d.ts +3 -1
- package/dist/components/drag-drop/drag-state.svelte.js +27 -24
- package/dist/components/drag-drop/util.d.ts +0 -32
- package/dist/components/drag-drop/util.js +74 -74
- package/package.json +1 -1
@@ -1,7 +1,7 @@
|
|
1
1
|
<script>
|
2
2
|
import { createDragState } from './drag-state.svelte.js';
|
3
3
|
|
4
|
-
import { activeDragOver,
|
4
|
+
import { activeTouchMove, activeDragOver, activeDrop } from './actions.js';
|
5
5
|
|
6
6
|
/**
|
7
7
|
* @type {{
|
@@ -97,10 +97,9 @@
|
|
97
97
|
ondragenter={onDragEnter}
|
98
98
|
use:activeDragOver={onDragOver}
|
99
99
|
ondragleave={onDragLeave}
|
100
|
-
|
100
|
+
use:activeDrop={onDrop}
|
101
101
|
ondragend={onDragEnd}
|
102
102
|
use:activeTouchMove={(e) => {
|
103
|
-
// Prevent scrolling if we're dragging
|
104
103
|
if (dragState.isDragging()) {
|
105
104
|
e.preventDefault();
|
106
105
|
}
|
@@ -4,7 +4,6 @@
|
|
4
4
|
import { toStateClasses } from '../../util/design-system/index.js';
|
5
5
|
import { createOrGetDragState } from './drag-state.svelte.js';
|
6
6
|
import { DragController } from './DragController.js';
|
7
|
-
import { generateLocalId } from '../../util/unique';
|
8
7
|
import { onDestroy } from 'svelte';
|
9
8
|
import {
|
10
9
|
IDLE,
|
@@ -13,7 +12,6 @@
|
|
13
12
|
DROPPING
|
14
13
|
} from '../../constants/state-labels/drag-states.js';
|
15
14
|
|
16
|
-
|
17
15
|
/** @typedef {import('../../typedef').SimulatedDragEvent} SimulatedDragEvent */
|
18
16
|
|
19
17
|
/**
|
@@ -27,7 +25,8 @@
|
|
27
25
|
* classes?: string,
|
28
26
|
* children: import('svelte').Snippet<[{
|
29
27
|
* element: HTMLElement,
|
30
|
-
* rect: DOMRect
|
28
|
+
* rect: DOMRect,
|
29
|
+
* isDragging: boolean
|
31
30
|
* }]>,
|
32
31
|
* draggingSnippet?: import('svelte').Snippet<[{
|
33
32
|
* element: HTMLElement,
|
@@ -86,7 +85,7 @@
|
|
86
85
|
|
87
86
|
const dragState = createOrGetDragState(contextKey);
|
88
87
|
|
89
|
-
const draggableId =
|
88
|
+
const draggableId = dragState.newDraggableId();
|
90
89
|
|
91
90
|
// svelte-ignore non_reactive_update
|
92
91
|
let draggableElement;
|
@@ -103,24 +102,27 @@
|
|
103
102
|
let customPreviewSet = $state(false);
|
104
103
|
let elementRect = $state(null);
|
105
104
|
|
106
|
-
// Track if current draggable can drop in the active zone
|
107
|
-
let canDropInActiveZone = $derived.by(() => {
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
});
|
113
|
-
|
114
|
-
// Computed state object for CSS classes
|
115
|
-
let stateObject = $derived({
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
105
|
+
// Track if current draggable can drop in the active zone
|
106
|
+
let canDropInActiveZone = $derived.by(() => {
|
107
|
+
if (currentState !== DRAGGING || !dragState.activeDropZone) return false;
|
108
|
+
|
109
|
+
const activeZone = dragState.dropZones.get(dragState.activeDropZone);
|
110
|
+
return activeZone?.canDrop || false;
|
111
|
+
});
|
112
|
+
|
113
|
+
// Computed state object for CSS classes
|
114
|
+
let stateObject = $derived({
|
115
|
+
idle: currentState === IDLE,
|
116
|
+
dragging: currentState === DRAGGING,
|
117
|
+
'drag-preview': currentState === DRAG_PREVIEW,
|
118
|
+
dropping: currentState === DROPPING,
|
119
|
+
'drag-disabled': disabled || !canDrag(item),
|
120
|
+
'can-drop': currentState === DRAGGING && canDropInActiveZone,
|
121
|
+
'cannot-drop':
|
122
|
+
currentState === DRAGGING &&
|
123
|
+
dragState.activeDropZone &&
|
124
|
+
!canDropInActiveZone
|
125
|
+
});
|
124
126
|
|
125
127
|
let stateClasses = $derived(toStateClasses(stateObject));
|
126
128
|
|
@@ -181,10 +183,10 @@ let stateObject = $derived({
|
|
181
183
|
|
182
184
|
let transparentPixel;
|
183
185
|
|
184
|
-
if(
|
185
|
-
{
|
186
|
+
if (browser) {
|
186
187
|
transparentPixel = new Image();
|
187
|
-
transparentPixel.src =
|
188
|
+
transparentPixel.src =
|
189
|
+
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
188
190
|
}
|
189
191
|
|
190
192
|
/**
|
@@ -192,7 +194,6 @@ let stateObject = $derived({
|
|
192
194
|
* @param {DragEvent} event - The drag event
|
193
195
|
*/
|
194
196
|
function startDrag(event) {
|
195
|
-
|
196
197
|
// Set a transparent 1x1 pixel image to hide browser's default preview
|
197
198
|
event.dataTransfer.setDragImage(transparentPixel, 0, 0);
|
198
199
|
|
@@ -213,17 +214,20 @@ let stateObject = $derived({
|
|
213
214
|
group
|
214
215
|
};
|
215
216
|
|
217
|
+
// console.debug('handleDragStart:', draggableId, dragData);
|
218
|
+
|
216
219
|
// Set shared drag state
|
217
220
|
dragState.start(draggableId, dragData);
|
218
221
|
|
219
222
|
// Set minimal data transfer for browser drag and drop API
|
220
223
|
event.dataTransfer.effectAllowed = 'move';
|
221
|
-
event.dataTransfer.setData(
|
222
|
-
'application/json',
|
223
|
-
JSON.stringify({ draggableId })
|
224
|
-
);
|
225
224
|
|
226
|
-
//
|
225
|
+
// Set draggableId as custom mime type, since that value is availabe
|
226
|
+
// during all event types (dragstart, dragenter, dragover, dragleave,
|
227
|
+
// drop and dragend)
|
228
|
+
event.dataTransfer.setData(`application/x-draggable-${draggableId}`, '1');
|
229
|
+
|
230
|
+
// Also keep text/plain for browser compatibility
|
227
231
|
event.dataTransfer.setData('text/plain', draggableId);
|
228
232
|
|
229
233
|
// Create the preview controller
|
@@ -361,10 +365,10 @@ let stateObject = $derived({
|
|
361
365
|
|
362
366
|
// Show preview
|
363
367
|
// if (draggingSnippet) {
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
+
elementRect = rect;
|
369
|
+
previewX = rect.left;
|
370
|
+
previewY = rect.top;
|
371
|
+
showPreview = true;
|
368
372
|
// }
|
369
373
|
|
370
374
|
// Prevent scrolling while dragging
|
@@ -374,6 +378,7 @@ let stateObject = $derived({
|
|
374
378
|
document.addEventListener('touchmove', handleTouchMove, {
|
375
379
|
passive: false
|
376
380
|
});
|
381
|
+
|
377
382
|
document.addEventListener('touchend', handleTouchEnd);
|
378
383
|
}, 150); // 150ms delay to distinguish from scrolling
|
379
384
|
}
|
@@ -382,78 +387,83 @@ let stateObject = $derived({
|
|
382
387
|
* Handle touch move
|
383
388
|
* @param {TouchEvent} event
|
384
389
|
*/
|
385
|
-
function handleTouchMove(event) {
|
386
|
-
|
390
|
+
function handleTouchMove(event) {
|
391
|
+
if (!touchDragging) return;
|
387
392
|
|
388
|
-
|
389
|
-
|
393
|
+
event.preventDefault();
|
394
|
+
const touch = event.touches[0];
|
390
395
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
+
// Update preview position
|
397
|
+
if (showPreview) {
|
398
|
+
previewX = touch.clientX - dragOffsetX;
|
399
|
+
previewY = touch.clientY - dragOffsetY;
|
400
|
+
}
|
396
401
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
402
|
+
/** @type {SimulatedDragEvent} */
|
403
|
+
const simulatedEvent = {
|
404
|
+
type: 'dragover',
|
405
|
+
clientX: touch.clientX,
|
406
|
+
clientY: touch.clientY,
|
407
|
+
dataTransfer: {
|
408
|
+
types: [`application/x-draggable-${draggableId}`, 'text/plain'],
|
409
|
+
getData: () => 1,
|
410
|
+
dropEffect: 'move',
|
411
|
+
effectAllowed: 'move',
|
412
|
+
files: []
|
413
|
+
},
|
414
|
+
|
415
|
+
preventDefault: () => {},
|
416
|
+
stopPropagation: () => {}
|
417
|
+
};
|
418
|
+
|
419
|
+
// Update active dropzone in drag state
|
420
|
+
dragState.updateActiveDropZone(
|
421
|
+
touch.clientX,
|
422
|
+
touch.clientY,
|
423
|
+
simulatedEvent
|
424
|
+
);
|
425
|
+
}
|
416
426
|
|
417
427
|
/**
|
418
428
|
* Handle touch end
|
419
429
|
* @param {TouchEvent} event
|
420
430
|
*/
|
421
431
|
function handleTouchEnd(event) {
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
}
|
432
|
+
clearTimeout(dragTimeout);
|
433
|
+
|
434
|
+
if (!touchDragging) return;
|
435
|
+
|
436
|
+
const touch = event.changedTouches[0];
|
437
|
+
|
438
|
+
/** @type {SimulatedDragEvent} */
|
439
|
+
const simulatedEvent = {
|
440
|
+
type: 'drop',
|
441
|
+
clientX: touch.clientX,
|
442
|
+
clientY: touch.clientY,
|
443
|
+
dataTransfer: {
|
444
|
+
types: [`application/x-draggable-${draggableId}`, 'text/plain'],
|
445
|
+
getData: () => 1,
|
446
|
+
dropEffect: 'move',
|
447
|
+
effectAllowed: 'move',
|
448
|
+
files: []
|
449
|
+
},
|
450
|
+
preventDefault: () => {}, // Add this!
|
451
|
+
stopPropagation: () => {} // And this!
|
452
|
+
};
|
453
|
+
|
454
|
+
// Trigger drop at final touch position
|
455
|
+
dragState.handleDropAtPoint(touch.clientX, touch.clientY, simulatedEvent);
|
456
|
+
|
457
|
+
// Clean up
|
458
|
+
touchDragging = false;
|
459
|
+
currentState = IDLE;
|
460
|
+
showPreview = false;
|
461
|
+
dragState.end(draggableId);
|
462
|
+
|
463
|
+
// Remove document handlers
|
464
|
+
document.removeEventListener('touchmove', handleTouchMove);
|
465
|
+
document.removeEventListener('touchend', handleTouchEnd);
|
466
|
+
}
|
457
467
|
</script>
|
458
468
|
|
459
469
|
<div
|
@@ -470,7 +480,11 @@ function handleTouchMove(event) {
|
|
470
480
|
style="touch-action: none;"
|
471
481
|
{...attrs}
|
472
482
|
>
|
473
|
-
{@render children({
|
483
|
+
{@render children({
|
484
|
+
element: draggableElement,
|
485
|
+
rect: elementRect,
|
486
|
+
isDragging: false
|
487
|
+
})}
|
474
488
|
</div>
|
475
489
|
|
476
490
|
{#if showPreview && elementRect}
|
@@ -481,11 +495,18 @@ function handleTouchMove(event) {
|
|
481
495
|
style:left="{previewX}px"
|
482
496
|
style:top="{previewY}px"
|
483
497
|
>
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
498
|
+
{#if draggingSnippet}
|
499
|
+
{@render draggingSnippet({
|
500
|
+
element: draggableElement,
|
501
|
+
rect: elementRect
|
502
|
+
})}
|
503
|
+
{:else}
|
504
|
+
{@render children({
|
505
|
+
element: draggableElement,
|
506
|
+
rect: elementRect,
|
507
|
+
isDragging: true
|
508
|
+
})}
|
509
|
+
{/if}
|
489
510
|
</div>
|
490
511
|
{/if}
|
491
512
|
|
@@ -13,6 +13,7 @@ type Draggable = {
|
|
13
13
|
children: Snippet<[{
|
14
14
|
element: HTMLElement;
|
15
15
|
rect: DOMRect;
|
16
|
+
isDragging: boolean;
|
16
17
|
}]>;
|
17
18
|
draggingSnippet?: Snippet<[{
|
18
19
|
element: HTMLElement;
|
@@ -58,6 +59,7 @@ declare const Draggable: import("svelte").Component<{
|
|
58
59
|
children: import("svelte").Snippet<[{
|
59
60
|
element: HTMLElement;
|
60
61
|
rect: DOMRect;
|
62
|
+
isDragging: boolean;
|
61
63
|
}]>;
|
62
64
|
draggingSnippet?: import("svelte").Snippet<[{
|
63
65
|
element: HTMLElement;
|
@@ -1,6 +1,9 @@
|
|
1
|
+
export function activeTouchMove(node: any, handler: any): {
|
2
|
+
destroy(): void;
|
3
|
+
};
|
1
4
|
export function activeDragOver(node: any, handler: any): {
|
2
5
|
destroy(): void;
|
3
6
|
};
|
4
|
-
export function
|
7
|
+
export function activeDrop(node: any, handler: any): {
|
5
8
|
destroy(): void;
|
6
9
|
};
|
@@ -1,6 +1,14 @@
|
|
1
|
+
export function activeTouchMove(node, handler) {
|
2
|
+
node.addEventListener('touchmove', handler, { passive: false });
|
3
|
+
return {
|
4
|
+
destroy() {
|
5
|
+
node.removeEventListener('touchmove', handler, { passive: false });
|
6
|
+
}
|
7
|
+
};
|
8
|
+
}
|
9
|
+
|
1
10
|
export function activeDragOver(node, handler) {
|
2
11
|
node.addEventListener('dragover', handler, { passive: false });
|
3
|
-
|
4
12
|
return {
|
5
13
|
destroy() {
|
6
14
|
node.removeEventListener('dragover', handler, { passive: false });
|
@@ -8,11 +16,11 @@ export function activeDragOver(node, handler) {
|
|
8
16
|
};
|
9
17
|
}
|
10
18
|
|
11
|
-
export function
|
12
|
-
node.addEventListener('
|
19
|
+
export function activeDrop(node, handler) {
|
20
|
+
node.addEventListener('drop', handler, { passive: false });
|
13
21
|
return {
|
14
22
|
destroy() {
|
15
|
-
node.removeEventListener('
|
23
|
+
node.removeEventListener('drop', handler, { passive: false });
|
16
24
|
}
|
17
25
|
};
|
18
26
|
}
|
@@ -5,6 +5,7 @@ export type SimulatedDragEvent = import("../../typedef").SimulatedDragEvent;
|
|
5
5
|
/** @typedef {import('../../typedef').SimulatedDragEvent} SimulatedDragEvent */
|
6
6
|
declare class DragState {
|
7
7
|
draggables: Map<any, any>;
|
8
|
+
draggableIdCount: number;
|
8
9
|
dropZones: Map<any, any>;
|
9
10
|
activeDropZone: any;
|
10
11
|
lastActiveDropZone: any;
|
@@ -67,6 +68,7 @@ declare class DragState {
|
|
67
68
|
* @param {string} draggableId
|
68
69
|
*/
|
69
70
|
end(draggableId: string): void;
|
71
|
+
newDraggableId(): string;
|
70
72
|
/**
|
71
73
|
* Get a drag data by draggable id
|
72
74
|
*
|
@@ -79,7 +81,7 @@ declare class DragState {
|
|
79
81
|
*
|
80
82
|
* @param {DragEvent|SimulatedDragEvent} event
|
81
83
|
*
|
82
|
-
* @returns {Object|null} The drag data, or null for file drops
|
84
|
+
* @returns {Object|null} The drag data, or null for file drops or not found
|
83
85
|
*/
|
84
86
|
getDraggable(event: DragEvent | SimulatedDragEvent): any | null;
|
85
87
|
/**
|
@@ -7,6 +7,9 @@ class DragState {
|
|
7
7
|
// Existing draggables map
|
8
8
|
draggables = $state(new Map());
|
9
9
|
|
10
|
+
// Draggable id counter
|
11
|
+
draggableIdCount = 1;
|
12
|
+
|
10
13
|
// New: Registry for dropzones
|
11
14
|
dropZones = $state(new Map());
|
12
15
|
|
@@ -162,6 +165,9 @@ class DragState {
|
|
162
165
|
if (dropZone && dropZone.config.canDrop) {
|
163
166
|
const dragData = this.getDraggable(event);
|
164
167
|
|
168
|
+
console.debug('handleDropAtPoint', event, dragData);
|
169
|
+
|
170
|
+
|
165
171
|
if (dragData && dropZone.config.element) {
|
166
172
|
// Calculate drop position relative to dropzone
|
167
173
|
const rect = dropZone.config.element.getBoundingClientRect();
|
@@ -213,6 +219,7 @@ class DragState {
|
|
213
219
|
* @param {import('../../typedef/drag.js').DragData} dragData
|
214
220
|
*/
|
215
221
|
start(draggableId, dragData) {
|
222
|
+
// console.debug('DragState.start called:', draggableId, dragData);
|
216
223
|
this.draggables.set(draggableId, dragData);
|
217
224
|
}
|
218
225
|
|
@@ -220,6 +227,7 @@ class DragState {
|
|
220
227
|
* @param {string} draggableId
|
221
228
|
*/
|
222
229
|
end(draggableId) {
|
230
|
+
// console.debug('DragState.end called:', draggableId);
|
223
231
|
this.draggables.delete(draggableId);
|
224
232
|
|
225
233
|
// Check both current AND last active dropzone
|
@@ -241,6 +249,10 @@ class DragState {
|
|
241
249
|
this.lastActiveDropZone = null;
|
242
250
|
}
|
243
251
|
|
252
|
+
newDraggableId() {
|
253
|
+
return `${this.draggableIdCount++}`;
|
254
|
+
}
|
255
|
+
|
244
256
|
/**
|
245
257
|
* Get a drag data by draggable id
|
246
258
|
*
|
@@ -256,7 +268,7 @@ class DragState {
|
|
256
268
|
*
|
257
269
|
* @param {DragEvent|SimulatedDragEvent} event
|
258
270
|
*
|
259
|
-
* @returns {Object|null} The drag data, or null for file drops
|
271
|
+
* @returns {Object|null} The drag data, or null for file drops or not found
|
260
272
|
*/
|
261
273
|
getDraggable(event) {
|
262
274
|
// Check if this is a file drop first
|
@@ -268,34 +280,25 @@ class DragState {
|
|
268
280
|
}
|
269
281
|
}
|
270
282
|
|
271
|
-
|
272
|
-
|
273
|
-
if (event.type === 'dragover'|| event.type === 'dragenter') {
|
274
|
-
if (this.draggables.size > 0) {
|
275
|
-
// Return the most recent drag operation
|
276
|
-
return this.current;
|
277
|
-
}
|
278
|
-
}
|
283
|
+
if (event.dataTransfer?.types) {
|
284
|
+
const types = Array.from(event.dataTransfer.types);
|
279
285
|
|
280
|
-
|
281
|
-
if (event.type === 'drop' && event.dataTransfer) {
|
282
|
-
try {
|
283
|
-
const jsonData = event.dataTransfer.getData('application/json');
|
284
|
-
if (jsonData) {
|
285
|
-
const transferData = JSON.parse(jsonData);
|
286
|
-
const draggableId = transferData.draggableId;
|
286
|
+
const PREFIX = 'application/x-draggable-';
|
287
287
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
288
|
+
const dragType = types.find((t) => t.startsWith(PREFIX));
|
289
|
+
|
290
|
+
if (dragType) {
|
291
|
+
const draggableId = dragType.slice(PREFIX.length);
|
292
|
+
|
293
|
+
const entry = this.getDraggableById(draggableId);
|
294
|
+
|
295
|
+
console.debug('getDraggable', draggableId, entry);
|
296
|
+
|
297
|
+
return entry;
|
294
298
|
}
|
295
299
|
}
|
296
300
|
|
297
|
-
|
298
|
-
return this.current;
|
301
|
+
return null;
|
299
302
|
}
|
300
303
|
|
301
304
|
/**
|
@@ -1,32 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Find the source draggable element from an event
|
3
|
-
*
|
4
|
-
* @param {DragEvent} event
|
5
|
-
* @returns {HTMLElement|null}
|
6
|
-
*/
|
7
|
-
export function findDraggableSource(event: DragEvent): HTMLElement | null;
|
8
|
-
/**
|
9
|
-
* Get draggable ID from an event, if available
|
10
|
-
* @param {DragEvent} event
|
11
|
-
* @returns {string|null}
|
12
|
-
*/
|
13
|
-
export function getDraggableIdFromEvent(event: DragEvent): string | null;
|
14
|
-
/**
|
15
|
-
* Process a drop event with the provided data and handlers
|
16
|
-
* @param {DragEvent} event
|
17
|
-
* @param {any} data The drag data
|
18
|
-
* @param {Object} options
|
19
|
-
* @param {Function} options.onDropStart Optional drop start handler
|
20
|
-
* @param {Function} options.onDrop Main drop handler
|
21
|
-
* @param {Function} options.onDropEnd Optional drop end handler
|
22
|
-
* @param {string} options.zone The drop zone identifier
|
23
|
-
* @param {Function} options.setState Function to update component state
|
24
|
-
* @returns {Promise<boolean>} Success status
|
25
|
-
*/
|
26
|
-
export function processDropWithData(event: DragEvent, data: any, { onDropStart, onDrop, onDropEnd, zone, setState }: {
|
27
|
-
onDropStart: Function;
|
28
|
-
onDrop: Function;
|
29
|
-
onDropEnd: Function;
|
30
|
-
zone: string;
|
31
|
-
setState: Function;
|
32
|
-
}): Promise<boolean>;
|
@@ -1,85 +1,85 @@
|
|
1
|
-
import { createOrGetDragState } from './drag-state.svelte.js';
|
1
|
+
// import { createOrGetDragState } from './drag-state.svelte.js';
|
2
2
|
|
3
|
-
/**
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
export function findDraggableSource(event) {
|
10
|
-
|
3
|
+
// /**
|
4
|
+
// * Find the source draggable element from an event
|
5
|
+
// *
|
6
|
+
// * @param {DragEvent} event
|
7
|
+
// * @returns {HTMLElement|null}
|
8
|
+
// */
|
9
|
+
// export function findDraggableSource(event) {
|
10
|
+
// const target = /** @type {Element|EventTarget|null} */ (event.target);
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
// if (!(target instanceof Element)) {
|
13
|
+
// return null;
|
14
|
+
// }
|
15
15
|
|
16
|
-
|
16
|
+
// let element = /** @type {Element|null} */ (target);
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
// // Walk up the DOM tree
|
19
|
+
// while (element !== null && element !== document.body) {
|
20
|
+
// if (element.hasAttribute('data-id')) {
|
21
|
+
// // Return as HTMLElement if needed
|
22
|
+
// return /** @type {HTMLElement} */ (element);
|
23
|
+
// }
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
// element = element.parentElement;
|
26
|
+
// }
|
27
27
|
|
28
|
-
|
29
|
-
}
|
28
|
+
// return null;
|
29
|
+
// }
|
30
30
|
|
31
|
-
/**
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
export function getDraggableIdFromEvent(event) {
|
37
|
-
|
38
|
-
|
39
|
-
}
|
31
|
+
// /**
|
32
|
+
// * Get draggable ID from an event, if available
|
33
|
+
// * @param {DragEvent} event
|
34
|
+
// * @returns {string|null}
|
35
|
+
// */
|
36
|
+
// export function getDraggableIdFromEvent(event) {
|
37
|
+
// const element = findDraggableSource(event);
|
38
|
+
// return element ? element.getAttribute('data-id') : null;
|
39
|
+
// }
|
40
40
|
|
41
|
-
/**
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
export async function processDropWithData(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
) {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
41
|
+
// /**
|
42
|
+
// * Process a drop event with the provided data and handlers
|
43
|
+
// * @param {DragEvent} event
|
44
|
+
// * @param {any} data The drag data
|
45
|
+
// * @param {Object} options
|
46
|
+
// * @param {Function} options.onDropStart Optional drop start handler
|
47
|
+
// * @param {Function} options.onDrop Main drop handler
|
48
|
+
// * @param {Function} options.onDropEnd Optional drop end handler
|
49
|
+
// * @param {string} options.zone The drop zone identifier
|
50
|
+
// * @param {Function} options.setState Function to update component state
|
51
|
+
// * @returns {Promise<boolean>} Success status
|
52
|
+
// */
|
53
|
+
// export async function processDropWithData(
|
54
|
+
// event,
|
55
|
+
// data,
|
56
|
+
// { onDropStart, onDrop, onDropEnd, zone, setState }
|
57
|
+
// ) {
|
58
|
+
// try {
|
59
|
+
// // Update state and notify listeners
|
60
|
+
// setState('ACTIVE_DROP');
|
61
|
+
// onDropStart?.({ event, zone, data });
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
// // Call the onDrop handler
|
64
|
+
// const dropResult = onDrop?.({
|
65
|
+
// event,
|
66
|
+
// zone,
|
67
|
+
// item: data.item,
|
68
|
+
// source: data.source,
|
69
|
+
// metadata: data.metadata
|
70
|
+
// });
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
// // Handle async or sync results
|
73
|
+
// await Promise.resolve(dropResult);
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
}
|
75
|
+
// // Success path
|
76
|
+
// setState('READY');
|
77
|
+
// onDropEnd?.({ event, zone, data, success: true });
|
78
|
+
// return true;
|
79
|
+
// } catch (error) {
|
80
|
+
// // Error path
|
81
|
+
// setState('READY');
|
82
|
+
// onDropEnd?.({ event, zone, data, success: false, error });
|
83
|
+
// return false;
|
84
|
+
// }
|
85
|
+
// }
|