@marianmeres/stuic 1.64.0 → 1.65.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.
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="svelte" />
|
|
2
|
+
import type { Writable } from 'svelte/store';
|
|
3
|
+
export type EffectAllowed = 'copy' | 'none' | 'copyLink' | 'copyMove' | 'link' | 'linkMove' | 'move' | 'all' | 'uninitialized';
|
|
4
|
+
export type DropEffect = 'copy' | 'none' | 'link' | 'move';
|
|
5
|
+
export interface DraggableOptions {
|
|
6
|
+
id?: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
payload?: any;
|
|
9
|
+
effectAllowed?: EffectAllowed;
|
|
10
|
+
isDragged?: Writable<Record<string, boolean>>;
|
|
11
|
+
}
|
|
12
|
+
export declare const draggable: (node: HTMLElement, options: DraggableOptions) => {
|
|
13
|
+
update(newOptions?: DraggableOptions): void;
|
|
14
|
+
destroy(): void;
|
|
15
|
+
};
|
|
16
|
+
export interface DroppableOptions {
|
|
17
|
+
id?: string;
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
onDrop: (data: any, e: DragEvent) => void;
|
|
20
|
+
onDragover?: (data: any) => void;
|
|
21
|
+
dropEffect?: DropEffect;
|
|
22
|
+
isDraggedOver?: Writable<Record<string, boolean>>;
|
|
23
|
+
}
|
|
24
|
+
export declare const droppable: (node: HTMLElement, options: DroppableOptions) => {
|
|
25
|
+
update(newOptions?: DroppableOptions): void;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { createClog } from '@marianmeres/clog';
|
|
2
|
+
const clog = createClog('drag-drop');
|
|
3
|
+
const _isFn = (v) => typeof v === 'function';
|
|
4
|
+
export const draggable = (node, options) => {
|
|
5
|
+
const DEFAULT_OPTIONS = {
|
|
6
|
+
id: 'draggable-' + Math.random().toString(36).slice(2),
|
|
7
|
+
enabled: true,
|
|
8
|
+
effectAllowed: 'all',
|
|
9
|
+
};
|
|
10
|
+
options = { ...DEFAULT_OPTIONS, ...options };
|
|
11
|
+
// initalizer
|
|
12
|
+
const _init = (_opts) => {
|
|
13
|
+
if (_opts.enabled) {
|
|
14
|
+
node.setAttribute('draggable', 'true');
|
|
15
|
+
node.setAttribute('aria-grabbed', 'false');
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
node.removeAttribute('draggable');
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
// init now
|
|
22
|
+
_init(options);
|
|
23
|
+
const _payload = () => (_isFn(options?.payload) ? options.payload() : options.payload);
|
|
24
|
+
//
|
|
25
|
+
const onDragstart = (e) => {
|
|
26
|
+
const pld = _payload();
|
|
27
|
+
if (pld !== undefined) {
|
|
28
|
+
// add "stuic" as a custom data format
|
|
29
|
+
e.dataTransfer?.setData('stuic', JSON.stringify({ id: options.id, payload: pld }));
|
|
30
|
+
e.dataTransfer.effectAllowed = options.effectAllowed;
|
|
31
|
+
}
|
|
32
|
+
options?.isDragged?.update((old) => ({ ...old, [options.id]: true }));
|
|
33
|
+
node.setAttribute('aria-grabbed', 'true');
|
|
34
|
+
};
|
|
35
|
+
const onDrag = (e) => {
|
|
36
|
+
// const el: HTMLElement = e.currentTarget as HTMLElement;
|
|
37
|
+
// clog(el);
|
|
38
|
+
// ?
|
|
39
|
+
};
|
|
40
|
+
const onDragend = (e) => {
|
|
41
|
+
// e.preventDefault();
|
|
42
|
+
options?.isDragged?.update((old) => ({ ...old, [options.id]: false }));
|
|
43
|
+
node.setAttribute('aria-grabbed', 'false');
|
|
44
|
+
};
|
|
45
|
+
node.addEventListener('dragstart', onDragstart);
|
|
46
|
+
node.addEventListener('drag', onDrag);
|
|
47
|
+
node.addEventListener('dragend', onDragend);
|
|
48
|
+
return {
|
|
49
|
+
update(newOptions) {
|
|
50
|
+
options = { ...options, ...(newOptions || {}) };
|
|
51
|
+
// reinit maybe
|
|
52
|
+
_init(options);
|
|
53
|
+
},
|
|
54
|
+
destroy() {
|
|
55
|
+
node.removeEventListener('dragstart', onDragstart);
|
|
56
|
+
node.removeEventListener('drag', onDrag);
|
|
57
|
+
node.removeEventListener('dragend', onDragend);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export const droppable = (node, options) => {
|
|
62
|
+
const DEFAULT_OPTIONS = {
|
|
63
|
+
id: 'droppable-' + Math.random().toString(36).slice(2),
|
|
64
|
+
enabled: true,
|
|
65
|
+
dropEffect: 'move',
|
|
66
|
+
};
|
|
67
|
+
options = { ...DEFAULT_OPTIONS, ...options };
|
|
68
|
+
//
|
|
69
|
+
const onDragenter = (e) => {
|
|
70
|
+
// e.preventDefault();
|
|
71
|
+
// console.log('dragover', e.dataTransfer);
|
|
72
|
+
e.dataTransfer.dropEffect = options.dropEffect;
|
|
73
|
+
options?.isDraggedOver?.update((old) => ({ ...old, [options.id]: true }));
|
|
74
|
+
};
|
|
75
|
+
const onDragover = (e) => {
|
|
76
|
+
e.preventDefault(); // this prevents animation
|
|
77
|
+
};
|
|
78
|
+
const onDragleave = (e) => {
|
|
79
|
+
// e.preventDefault();
|
|
80
|
+
options?.isDraggedOver?.update((old) => ({ ...old, [options.id]: false }));
|
|
81
|
+
};
|
|
82
|
+
const onDrop = (e) => {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
const target = e.target;
|
|
85
|
+
e.dataTransfer.dropEffect = options.dropEffect;
|
|
86
|
+
options?.isDraggedOver?.update((old) => ({ ...old, [options.id]: false }));
|
|
87
|
+
if (_isFn(options.onDrop)) {
|
|
88
|
+
let stuicData = e.dataTransfer?.getData('stuic');
|
|
89
|
+
// prettier-ignore
|
|
90
|
+
try {
|
|
91
|
+
stuicData = JSON.parse(stuicData);
|
|
92
|
+
}
|
|
93
|
+
catch (e) { }
|
|
94
|
+
return options.onDrop(stuicData, e);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const _removeListeners = () => {
|
|
98
|
+
node.removeEventListener('dragenter', onDragenter);
|
|
99
|
+
node.removeEventListener('dragover', onDragover);
|
|
100
|
+
node.removeEventListener('dragleave', onDragleave);
|
|
101
|
+
node.removeEventListener('drop', onDrop);
|
|
102
|
+
};
|
|
103
|
+
//
|
|
104
|
+
let _listens = false;
|
|
105
|
+
const _init = (_opts) => {
|
|
106
|
+
if (_opts.enabled && !_listens) {
|
|
107
|
+
node.addEventListener('dragenter', onDragenter);
|
|
108
|
+
node.addEventListener('dragover', onDragover);
|
|
109
|
+
node.addEventListener('dragleave', onDragleave);
|
|
110
|
+
node.addEventListener('drop', onDrop);
|
|
111
|
+
_listens = true;
|
|
112
|
+
}
|
|
113
|
+
else if (!_opts.enabled && _listens) {
|
|
114
|
+
_removeListeners();
|
|
115
|
+
_listens = false;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
// init now
|
|
119
|
+
_init(options);
|
|
120
|
+
return {
|
|
121
|
+
update(newOptions) {
|
|
122
|
+
options = { ...options, ...(newOptions || {}) };
|
|
123
|
+
// reinit maybe
|
|
124
|
+
_init(options);
|
|
125
|
+
},
|
|
126
|
+
destroy() {
|
|
127
|
+
_removeListeners();
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { default as Switch, SwitchConfig } from './components/Switch/Switch.svel
|
|
|
21
21
|
export { default as Thc, type THC, isTHCNotEmpty } from './components/Thc/Thc.svelte';
|
|
22
22
|
export { default as X } from './components/X/X.svelte';
|
|
23
23
|
export { autogrow } from './actions/autogrow.js';
|
|
24
|
+
export { draggable, droppable, type DraggableOptions, type DroppableOptions, } from './actions/drag-drop.js';
|
|
24
25
|
export { focusTrap } from './actions/focus-trap.js';
|
|
25
26
|
export { onOutside } from './actions/on-outside.js';
|
|
26
27
|
export { preSubmitValidityCheck } from './actions/pre-submit-validity-check.js';
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ export { default as Thc, isTHCNotEmpty } from './components/Thc/Thc.svelte';
|
|
|
36
36
|
export { default as X } from './components/X/X.svelte';
|
|
37
37
|
// actions
|
|
38
38
|
export { autogrow } from './actions/autogrow.js';
|
|
39
|
+
export { draggable, droppable, } from './actions/drag-drop.js';
|
|
39
40
|
export { focusTrap } from './actions/focus-trap.js';
|
|
40
41
|
export { onOutside } from './actions/on-outside.js';
|
|
41
42
|
export { preSubmitValidityCheck } from './actions/pre-submit-validity-check.js';
|