@hkdigital/lib-sveltekit 0.1.78 → 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,12 +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
- // Could set custom drag image here
149
+ // Create the preview controller with natural offsets already calculated
150
+ const previewController = new PreviewController(event);
151
+
152
+ // Function to get the preview controller
153
+ const getPreviewController = () => previewController;
154
+
155
+ // Call onDragStart with the getPreviewController function
156
+ onDragStart?.({ event, item, source, group, getPreviewController });
157
+
158
+ // Apply default preview if no custom one was set
159
+ if (!previewController.hasCustomPreview()) {
160
+ previewController.applyDefaultPreview();
149
161
  }
150
162
 
151
- onDragStart?.({ event, item, source, group });
163
+ // Additional handlers can be left unchanged
152
164
  }
153
165
 
154
166
  /**
@@ -169,7 +181,7 @@
169
181
  clearTimeout(dragTimeout);
170
182
 
171
183
  // Clear global drag state
172
- dragState.end( draggableId );
184
+ dragState.end(draggableId);
173
185
 
174
186
  // Check if drop was successful
175
187
  const wasDropped = event.dataTransfer.dropEffect !== 'none';
@@ -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<[]>;
@@ -1,12 +1,20 @@
1
1
  @define-mixin component-draggable {
2
2
  [data-component='draggable'] {
3
- cursor: move;
4
3
  user-select: none;
5
4
  transition:
6
5
  opacity 0.2s ease,
7
6
  transform 0.2s ease;
8
7
  }
9
8
 
9
+ [data-component='draggable']:not(.state-dragging):not(.state-drag-disabled) {
10
+ cursor: grab; /* Open hand when hovering draggable items */
11
+ }
12
+
13
+
14
+ /*[data-component='draggable']:active {
15
+ cursor: grabbing;
16
+ }*/
17
+
10
18
  /* State-based styling using state classes */
11
19
  [data-component='draggable'].state-idle {
12
20
  opacity: 1;
@@ -16,6 +24,7 @@
16
24
  [data-component='draggable'].state-dragging {
17
25
  opacity: 0.5;
18
26
  transform: scale(0.95);
27
+ cursor: grabbing;
19
28
  }
20
29
 
21
30
  [data-component='draggable'].state-drag-preview {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-sveltekit",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"