@hkdigital/lib-sveltekit 0.1.79 → 0.1.80

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.
@@ -3,6 +3,8 @@
3
3
 
4
4
  import { createOrGetDragState } from './drag-state.svelte.js';
5
5
 
6
+ import { PreviewController } from './PreviewController.js';
7
+
6
8
  import { generateLocalId } from '../../util/unique';
7
9
 
8
10
  import {
@@ -31,7 +33,8 @@
31
33
  * event: DragEvent,
32
34
  * item: any,
33
35
  * source: string,
34
- * group: string
36
+ * group: string,
37
+ * getPreviewController: () => PreviewController
35
38
  * }) => void,
36
39
  * onDragging?: (detail: {
37
40
  * event: DragEvent,
@@ -143,24 +146,21 @@
143
146
  event.dataTransfer.effectAllowed = 'move';
144
147
  event.dataTransfer.setData('application/json', JSON.stringify(dragData));
145
148
 
146
- // Set custom drag image if needed
147
- if (event.dataTransfer.setDragImage) {
148
- // Custom drag image
149
- const dragEl = /** @type {HTMLElement} */ (event.currentTarget);
150
-
149
+ // Create the preview controller with natural offsets already calculated
150
+ const previewController = new PreviewController(event);
151
151
 
152
- // Get the bounding rectangle of the element
153
- const rect = dragEl.getBoundingClientRect();
152
+ // Function to get the preview controller
153
+ const getPreviewController = () => previewController;
154
154
 
155
- // Calculate offsets relative to the element's top-left corner
156
- const offsetX = event.clientX - rect.left;
157
- const offsetY = event.clientY - rect.top;
155
+ // Call onDragStart with the getPreviewController function
156
+ onDragStart?.({ event, item, source, group, getPreviewController });
158
157
 
159
- // Use the element as drag image with calculated offsets
160
- event.dataTransfer.setDragImage(dragEl, offsetX, offsetY);
158
+ // Apply default preview if no custom one was set
159
+ if (!previewController.hasCustomPreview()) {
160
+ previewController.applyDefaultPreview();
161
161
  }
162
162
 
163
- onDragStart?.({ event, item, source, group });
163
+ // Additional handlers can be left unchanged
164
164
  }
165
165
 
166
166
  /**
@@ -173,33 +173,33 @@
173
173
  }
174
174
  }
175
175
 
176
- /**
177
- * Handle drag end
178
- * @param {DragEvent} event
179
- */
180
- function handleDragEnd(event) {
181
- clearTimeout(dragTimeout);
176
+ /**
177
+ * Handle drag end
178
+ * @param {DragEvent} event
179
+ */
180
+ function handleDragEnd(event) {
181
+ clearTimeout(dragTimeout);
182
182
 
183
- // Clear global drag state
184
- dragState.end(draggableId);
183
+ // Clear global drag state
184
+ dragState.end(draggableId);
185
185
 
186
- // Check if drop was successful
187
- const wasDropped = event.dataTransfer.dropEffect !== 'none';
186
+ // Check if drop was successful
187
+ const wasDropped = event.dataTransfer.dropEffect !== 'none';
188
188
 
189
- if (wasDropped) {
190
- currentState = DROPPING;
191
- onDrop?.({ event, item, wasDropped: true });
189
+ if (wasDropped) {
190
+ currentState = DROPPING;
191
+ onDrop?.({ event, item, wasDropped: true });
192
192
 
193
- // Brief dropping state before returning to idle
194
- setTimeout(() => {
193
+ // Brief dropping state before returning to idle
194
+ setTimeout(() => {
195
+ currentState = IDLE;
196
+ }, 100);
197
+ } else {
195
198
  currentState = IDLE;
196
- }, 100);
197
- } else {
198
- currentState = IDLE;
199
- }
199
+ }
200
200
 
201
- onDragEnd?.({ event, item, wasDropped });
202
- }
201
+ onDragEnd?.({ event, item, wasDropped });
202
+ }
203
203
 
204
204
  /**
205
205
  * Handle mouse down for drag delay
@@ -20,6 +20,7 @@ type Draggable = {
20
20
  item: any;
21
21
  source: string;
22
22
  group: string;
23
+ getPreviewController: () => PreviewController;
23
24
  }) => void;
24
25
  onDragging?: (detail: {
25
26
  event: DragEvent;
@@ -57,6 +58,7 @@ declare const Draggable: import("svelte").Component<{
57
58
  item: any;
58
59
  source: string;
59
60
  group: string;
61
+ getPreviewController: () => PreviewController;
60
62
  }) => void;
61
63
  onDragging?: (detail: {
62
64
  event: DragEvent;
@@ -74,3 +76,4 @@ declare const Draggable: import("svelte").Component<{
74
76
  }) => void;
75
77
  canDrag?: (item: any) => boolean;
76
78
  }, {}, "isDragging" | "isDropping" | "isDragPreview">;
79
+ import { PreviewController } from './PreviewController.js';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Controller for customizing drag preview images
3
+ */
4
+ export class PreviewController {
5
+ /**
6
+ * @param {DragEvent} event - The drag event
7
+ */
8
+ constructor(event: DragEvent);
9
+ event: DragEvent;
10
+ dataTransfer: DataTransfer;
11
+ targetElement: HTMLElement;
12
+ offsetX: number;
13
+ offsetY: number;
14
+ _previewSet: boolean;
15
+ /**
16
+ * Create a preview image from the current draggable element or a specific child element
17
+ * @param {string} [selector] - Optional CSS selector to target a specific child element
18
+ * @returns {HTMLElement} - The created preview element
19
+ */
20
+ grabPreviewImage(selector?: string): HTMLElement;
21
+ /**
22
+ * Set a custom element as the drag preview image
23
+ * @param {HTMLElement} element - Element to use as drag preview
24
+ * @param {number} [offsetX] - Horizontal offset (uses natural offset if omitted)
25
+ * @param {number} [offsetY] - Vertical offset (uses natural offset if omitted)
26
+ * @returns {boolean} - Whether setting the preview was successful
27
+ */
28
+ setPreviewImage(element: HTMLElement, offsetX?: number, offsetY?: number): boolean;
29
+ /**
30
+ * Check if a custom preview has been set
31
+ * @returns {boolean}
32
+ */
33
+ hasCustomPreview(): boolean;
34
+ /**
35
+ * Apply the default preview (uses the draggable element itself)
36
+ * @returns {boolean}
37
+ */
38
+ applyDefaultPreview(): boolean;
39
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Controller for customizing drag preview images
3
+ */
4
+ export class PreviewController {
5
+ /**
6
+ * @param {DragEvent} event - The drag event
7
+ */
8
+ constructor(event) {
9
+ this.event = event;
10
+ this.dataTransfer = event.dataTransfer;
11
+ this.targetElement = /** @type {HTMLElement} */ (event.currentTarget);
12
+
13
+ // Calculate natural offsets by default (to prevent "jumping")
14
+ const rect = this.targetElement.getBoundingClientRect();
15
+ this.offsetX = event.clientX - rect.left;
16
+ this.offsetY = event.clientY - rect.top;
17
+
18
+ this._previewSet = false;
19
+ }
20
+
21
+ /**
22
+ * Create a preview image from the current draggable element or a specific child element
23
+ * @param {string} [selector] - Optional CSS selector to target a specific child element
24
+ * @returns {HTMLElement} - The created preview element
25
+ */
26
+ grabPreviewImage(selector = null) {
27
+ // Find the source element (either the whole draggable or a specific child)
28
+ const sourceElement = selector
29
+ ? this.targetElement.querySelector(selector)
30
+ : this.targetElement;
31
+
32
+ if (!sourceElement) {
33
+ console.error(`Element with selector "${selector}" not found`);
34
+ return this.grabPreviewImage(); // Fallback to the main element
35
+ }
36
+
37
+ // Clone the element to create the preview
38
+ const previewElement = /** @type {HTMLElement} */ (
39
+ sourceElement.cloneNode(true)
40
+ );
41
+
42
+ // Position off-screen (needed for setDragImage to work properly)
43
+ previewElement.style.position = 'absolute';
44
+ previewElement.style.top = '-9999px';
45
+ previewElement.style.left = '-9999px';
46
+
47
+ // Add to the document temporarily
48
+ document.body.appendChild(previewElement);
49
+
50
+ return previewElement;
51
+ }
52
+
53
+ /**
54
+ * Set a custom element as the drag preview image
55
+ * @param {HTMLElement} element - Element to use as drag preview
56
+ * @param {number} [offsetX] - Horizontal offset (uses natural offset if omitted)
57
+ * @param {number} [offsetY] - Vertical offset (uses natural offset if omitted)
58
+ * @returns {boolean} - Whether setting the preview was successful
59
+ */
60
+ setPreviewImage(element, offsetX, offsetY) {
61
+ if (!this.dataTransfer || !this.dataTransfer.setDragImage) {
62
+ return false;
63
+ }
64
+
65
+ // Use provided offsets or fall back to natural offsets
66
+ const finalOffsetX = offsetX !== undefined ? offsetX : this.offsetX;
67
+ const finalOffsetY = offsetY !== undefined ? offsetY : this.offsetY;
68
+
69
+ try {
70
+ this.dataTransfer.setDragImage(element, finalOffsetX, finalOffsetY);
71
+ this._previewSet = true;
72
+ return true;
73
+ } catch (err) {
74
+ console.error('Failed to set drag preview image:', err);
75
+ return false;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Check if a custom preview has been set
81
+ * @returns {boolean}
82
+ */
83
+ hasCustomPreview() {
84
+ return this._previewSet;
85
+ }
86
+
87
+ /**
88
+ * Apply the default preview (uses the draggable element itself)
89
+ * @returns {boolean}
90
+ */
91
+ applyDefaultPreview() {
92
+ if (
93
+ !this.dataTransfer ||
94
+ !this.dataTransfer.setDragImage ||
95
+ this._previewSet
96
+ ) {
97
+ return false;
98
+ }
99
+
100
+ try {
101
+ this.dataTransfer.setDragImage(
102
+ this.targetElement,
103
+ this.offsetX,
104
+ this.offsetY
105
+ );
106
+ return true;
107
+ } catch (err) {
108
+ console.error('Failed to set default drag preview:', err);
109
+ return false;
110
+ }
111
+ }
112
+ }
@@ -4,8 +4,8 @@ type PanelGridRow = {
4
4
  $set?(props: Partial<{
5
5
  base?: string;
6
6
  bg?: string;
7
- justify?: "start" | "center" | "end" | "between" | "around" | "evenly" | "stretch" | "normal";
8
- justifyItems?: "start" | "center" | "end" | "stretch";
7
+ justify?: "center" | "start" | "end" | "between" | "around" | "evenly" | "stretch" | "normal";
8
+ justifyItems?: "center" | "start" | "end" | "stretch";
9
9
  gap?: string;
10
10
  classes?: string;
11
11
  children?: Snippet<[]>;
@@ -4,8 +4,8 @@ type PanelRow2 = {
4
4
  $set?(props: Partial<{
5
5
  base?: string;
6
6
  bg?: string;
7
- justify?: "start" | "center" | "end" | "between" | "around" | "evenly" | "stretch" | "normal";
8
- justifyItems?: "start" | "center" | "end" | "stretch";
7
+ justify?: "center" | "start" | "end" | "between" | "around" | "evenly" | "stretch" | "normal";
8
+ justifyItems?: "center" | "start" | "end" | "stretch";
9
9
  gap?: string;
10
10
  classes?: string;
11
11
  children?: Snippet<[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-sveltekit",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"