tiny-essentials 1.14.0 → 1.16.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.
- package/dist/v1/TinyBasicsEs.js +4585 -270
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyDragger.js +4386 -471
- package/dist/v1/TinyDragger.min.js +1 -1
- package/dist/v1/TinyEssentials.js +4634 -242
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyHtml.js +4327 -0
- package/dist/v1/TinyHtml.min.js +1 -0
- package/dist/v1/TinyUploadClicker.js +4628 -246
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/basics/collision.cjs +413 -0
- package/dist/v1/basics/collision.d.mts +187 -0
- package/dist/v1/basics/collision.mjs +350 -0
- package/dist/v1/basics/html.cjs +5 -109
- package/dist/v1/basics/html.d.mts +2 -28
- package/dist/v1/basics/html.mjs +5 -91
- package/dist/v1/basics/html_deprecated.cjs +124 -0
- package/dist/v1/basics/html_deprecated.d.mts +40 -0
- package/dist/v1/basics/html_deprecated.mjs +97 -0
- package/dist/v1/basics/index.cjs +27 -5
- package/dist/v1/basics/index.d.mts +26 -6
- package/dist/v1/basics/index.mjs +4 -2
- package/dist/v1/build/TinyHtml.cjs +7 -0
- package/dist/v1/build/TinyHtml.d.mts +3 -0
- package/dist/v1/build/TinyHtml.mjs +2 -0
- package/dist/v1/index.cjs +29 -5
- package/dist/v1/index.d.mts +27 -6
- package/dist/v1/index.mjs +5 -2
- package/dist/v1/libs/TinyDragger.cjs +91 -16
- package/dist/v1/libs/TinyDragger.d.mts +78 -2
- package/dist/v1/libs/TinyDragger.mjs +93 -17
- package/dist/v1/libs/TinyHtml.cjs +3859 -0
- package/dist/v1/libs/TinyHtml.d.mts +2151 -0
- package/dist/v1/libs/TinyHtml.mjs +3457 -0
- package/docs/v1/README.md +2 -0
- package/docs/v1/basics/collision.md +237 -0
- package/docs/v1/basics/html.md +1 -105
- package/docs/v1/basics/html_deprecated.md +127 -0
- package/docs/v1/libs/TinyDragger.md +45 -15
- package/docs/v1/libs/TinyHtml.md +1333 -0
- package/package.json +8 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var TinyHtml = require('./TinyHtml.cjs');
|
|
4
|
+
var collision = require('../basics/collision.cjs');
|
|
4
5
|
var objFilter = require('../basics/objFilter.cjs');
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -17,12 +18,15 @@ var objFilter = require('../basics/objFilter.cjs');
|
|
|
17
18
|
* automatic reverting, proxy dragging, and event dispatching.
|
|
18
19
|
*/
|
|
19
20
|
class TinyDragger {
|
|
21
|
+
static Utils = { ...collision, TinyHtml };
|
|
22
|
+
|
|
20
23
|
#enabled = true;
|
|
21
24
|
#destroyed = false;
|
|
22
25
|
|
|
23
26
|
#offsetY = 0;
|
|
24
27
|
#offsetX = 0;
|
|
25
28
|
|
|
29
|
+
#mirrorElem = true;
|
|
26
30
|
#multiCollision = false;
|
|
27
31
|
#lockInsideJail = false;
|
|
28
32
|
#revertOnDrop = false;
|
|
@@ -45,6 +49,7 @@ class TinyDragger {
|
|
|
45
49
|
/** @type {HTMLElement|null} */
|
|
46
50
|
#jail = null;
|
|
47
51
|
|
|
52
|
+
/** @type {HTMLElement} */
|
|
48
53
|
#target;
|
|
49
54
|
|
|
50
55
|
#dragHiddenClass = 'drag-hidden';
|
|
@@ -53,13 +58,16 @@ class TinyDragger {
|
|
|
53
58
|
#classJailDragging = 'jail-drag-active';
|
|
54
59
|
#classJailDragDisabled = 'jail-drag-disabled';
|
|
55
60
|
#classDragCollision = 'dragging-collision';
|
|
61
|
+
#defaultZIndex = 9999;
|
|
56
62
|
|
|
57
63
|
/** @typedef {(event: TouchEvent) => void} TouchDragEvent */
|
|
58
64
|
|
|
59
65
|
/**
|
|
60
|
-
* @param {HTMLElement} targetElement - The element to make draggable.
|
|
66
|
+
* @param {HTMLElement|TinyHtml} targetElement - The element to make draggable.
|
|
61
67
|
* @param {Object} [options={}] - Configuration options.
|
|
62
68
|
* @param {HTMLElement} [options.jail] - Optional container to restrict dragging within.
|
|
69
|
+
* @param {boolean} [options.mirrorElem=true] - Use a visual clone instead of dragging the original element.
|
|
70
|
+
* @param {number} [options.defaultZIndex] - Sets the z-index value applied when dragging starts.
|
|
63
71
|
* @param {boolean} [options.collisionByMouse=false] - Use mouse position for collision instead of element rect.
|
|
64
72
|
* @param {string} [options.classDragging='dragging'] - CSS class applied to the clone during dragging.
|
|
65
73
|
* @param {string} [options.classBodyDragging='drag-active'] - CSS class applied to <body> during dragging.
|
|
@@ -75,14 +83,16 @@ class TinyDragger {
|
|
|
75
83
|
* @throws {Error} If any option has an invalid type.
|
|
76
84
|
*/
|
|
77
85
|
constructor(targetElement, options = {}) {
|
|
78
|
-
|
|
86
|
+
const targetElem = !(targetElement instanceof TinyHtml) ? targetElement : targetElement.get();
|
|
87
|
+
if (!(targetElem instanceof HTMLElement))
|
|
79
88
|
throw new Error('TinyDragger requires a valid target HTMLElement to initialize.');
|
|
80
89
|
|
|
81
|
-
this.#target =
|
|
90
|
+
this.#target = targetElem;
|
|
82
91
|
|
|
83
92
|
// === Validations ===
|
|
84
93
|
if (options.jail !== undefined && !(options.jail instanceof HTMLElement))
|
|
85
94
|
throw new Error('The "jail" option must be an HTMLElement if provided.');
|
|
95
|
+
if (options.defaultZIndex !== undefined) this.setDefaultZIndex(options.defaultZIndex);
|
|
86
96
|
|
|
87
97
|
if (
|
|
88
98
|
options.vibration !== undefined &&
|
|
@@ -111,6 +121,7 @@ class TinyDragger {
|
|
|
111
121
|
}
|
|
112
122
|
};
|
|
113
123
|
|
|
124
|
+
validateBoolean(options.mirrorElem, 'mirrorElem');
|
|
114
125
|
validateBoolean(options.collisionByMouse, 'collisionByMouse');
|
|
115
126
|
validateBoolean(options.lockInsideJail, 'lockInsideJail');
|
|
116
127
|
validateBoolean(options.dropInJailOnly, 'dropInJailOnly');
|
|
@@ -146,6 +157,7 @@ class TinyDragger {
|
|
|
146
157
|
|
|
147
158
|
if (typeof options.collisionByMouse === 'boolean')
|
|
148
159
|
this.#collisionByMouse = options.collisionByMouse;
|
|
160
|
+
if (typeof options.mirrorElem === 'boolean') this.#mirrorElem = options.mirrorElem;
|
|
149
161
|
if (typeof options.revertOnDrop === 'boolean') this.#revertOnDrop = options.revertOnDrop;
|
|
150
162
|
if (typeof options.lockInsideJail === 'boolean') this.#lockInsideJail = options.lockInsideJail;
|
|
151
163
|
if (typeof options.dropInJailOnly === 'boolean') this.#dropInJailOnly = options.dropInJailOnly;
|
|
@@ -283,7 +295,7 @@ class TinyDragger {
|
|
|
283
295
|
throw new Error('getOffset expects an event with valid clientX and clientY coordinates.');
|
|
284
296
|
|
|
285
297
|
const targetRect = this.#target.getBoundingClientRect();
|
|
286
|
-
const { left: borderLeft, top: borderTop } =
|
|
298
|
+
const { left: borderLeft, top: borderTop } = TinyHtml.borderWidth(this.#target);
|
|
287
299
|
return {
|
|
288
300
|
x: event.clientX - targetRect.left + borderLeft,
|
|
289
301
|
y: event.clientY - targetRect.top + borderTop,
|
|
@@ -298,9 +310,12 @@ class TinyDragger {
|
|
|
298
310
|
if (event instanceof MouseEvent) event.preventDefault();
|
|
299
311
|
if (this.#destroyed || !this.#enabled || !this.#target.parentElement) return;
|
|
300
312
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
313
|
+
if (this.#mirrorElem) {
|
|
314
|
+
const dragProxy = this.#target.cloneNode(true);
|
|
315
|
+
if (!(dragProxy instanceof HTMLElement))
|
|
316
|
+
throw new Error('[TinyDragger] INVALID DRAG ELEMENT!');
|
|
317
|
+
this.#dragProxy = dragProxy;
|
|
318
|
+
} else this.#dragProxy = this.#target;
|
|
304
319
|
|
|
305
320
|
this.#dragging = true;
|
|
306
321
|
|
|
@@ -313,11 +328,13 @@ class TinyDragger {
|
|
|
313
328
|
top: `${this.#target.offsetTop}px`,
|
|
314
329
|
width: `${rect.width}px`,
|
|
315
330
|
height: `${rect.height}px`,
|
|
316
|
-
zIndex:
|
|
331
|
+
zIndex: this.#defaultZIndex,
|
|
317
332
|
});
|
|
318
333
|
|
|
319
|
-
|
|
320
|
-
|
|
334
|
+
if (this.#mirrorElem) {
|
|
335
|
+
this.#target.classList.add(this.#dragHiddenClass);
|
|
336
|
+
this.#target.parentElement.appendChild(this.#dragProxy);
|
|
337
|
+
}
|
|
321
338
|
|
|
322
339
|
const { x: offsetX, y: offsetY } = this.getOffset(event);
|
|
323
340
|
this.#offsetX = offsetX;
|
|
@@ -425,7 +442,7 @@ class TinyDragger {
|
|
|
425
442
|
const jailLeft = jailRect.left - parentRect.left;
|
|
426
443
|
const jailTop = jailRect.top - parentRect.top;
|
|
427
444
|
|
|
428
|
-
const { x: borderX, y: borderY } =
|
|
445
|
+
const { x: borderX, y: borderY } = TinyHtml.borderWidth(this.#jail);
|
|
429
446
|
const maxX = jailLeft + jailRect.width - targetRect.width - borderY;
|
|
430
447
|
const maxY = jailTop + jailRect.height - targetRect.height - borderX;
|
|
431
448
|
|
|
@@ -521,14 +538,25 @@ class TinyDragger {
|
|
|
521
538
|
const newX = this.#dragProxy.style.left;
|
|
522
539
|
const newY = this.#dragProxy.style.top;
|
|
523
540
|
if (this.#dragProxy) {
|
|
524
|
-
this.#dragProxy.remove();
|
|
541
|
+
if (this.#mirrorElem) this.#dragProxy.remove();
|
|
542
|
+
else
|
|
543
|
+
Object.assign(this.#dragProxy.style, {
|
|
544
|
+
position: '',
|
|
545
|
+
pointerEvents: '',
|
|
546
|
+
left: '',
|
|
547
|
+
top: '',
|
|
548
|
+
width: '',
|
|
549
|
+
height: '',
|
|
550
|
+
zIndex: '',
|
|
551
|
+
});
|
|
552
|
+
|
|
525
553
|
this.#dragProxy = null;
|
|
526
554
|
}
|
|
527
555
|
|
|
528
556
|
if (this.#lastCollision) this.#removeCollision();
|
|
529
557
|
this.#lastCollision = null;
|
|
530
558
|
|
|
531
|
-
this.#target.classList.remove(this.#dragHiddenClass);
|
|
559
|
+
if (this.#mirrorElem) this.#target.classList.remove(this.#dragHiddenClass);
|
|
532
560
|
if (!this.#revertOnDrop) {
|
|
533
561
|
this.#target.style.left = newX;
|
|
534
562
|
this.#target.style.top = newY;
|
|
@@ -722,6 +750,42 @@ class TinyDragger {
|
|
|
722
750
|
this.#dropInJailOnly = value;
|
|
723
751
|
}
|
|
724
752
|
|
|
753
|
+
/**
|
|
754
|
+
* Returns the current default z-index used for draggable items.
|
|
755
|
+
* @returns {number}
|
|
756
|
+
*/
|
|
757
|
+
getDefaultZIndex() {
|
|
758
|
+
return this.#defaultZIndex;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Sets a new default z-index for draggable items.
|
|
763
|
+
* @param {number} newZIndex
|
|
764
|
+
*/
|
|
765
|
+
setDefaultZIndex(newZIndex) {
|
|
766
|
+
if (typeof newZIndex !== 'number' || !Number.isFinite(newZIndex))
|
|
767
|
+
throw new TypeError('Z-index must be a finite number.');
|
|
768
|
+
this.#defaultZIndex = newZIndex;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Returns whether the draggable element is mirrored or the original.
|
|
773
|
+
* @returns {boolean}
|
|
774
|
+
*/
|
|
775
|
+
isMirrorEnabled() {
|
|
776
|
+
return this.#mirrorElem;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Sets whether the draggable element should be a mirror or the original.
|
|
781
|
+
* @param {boolean} useMirror
|
|
782
|
+
*/
|
|
783
|
+
setMirrorEnabled(useMirror) {
|
|
784
|
+
if (typeof useMirror !== 'boolean') throw new TypeError('Mirror setting must be a boolean.');
|
|
785
|
+
|
|
786
|
+
this.#mirrorElem = useMirror;
|
|
787
|
+
}
|
|
788
|
+
|
|
725
789
|
/**
|
|
726
790
|
* Returns the original target element being dragged.
|
|
727
791
|
* @returns {HTMLElement}
|
|
@@ -886,7 +950,17 @@ class TinyDragger {
|
|
|
886
950
|
|
|
887
951
|
if (this.#lastCollision) this.#removeCollision();
|
|
888
952
|
if (this.#dragProxy) {
|
|
889
|
-
this.#dragProxy.remove();
|
|
953
|
+
if (this.#mirrorElem) this.#dragProxy.remove();
|
|
954
|
+
else
|
|
955
|
+
Object.assign(this.#dragProxy.style, {
|
|
956
|
+
position: '',
|
|
957
|
+
pointerEvents: '',
|
|
958
|
+
left: '',
|
|
959
|
+
top: '',
|
|
960
|
+
width: '',
|
|
961
|
+
height: '',
|
|
962
|
+
zIndex: '',
|
|
963
|
+
});
|
|
890
964
|
this.#dragProxy = null;
|
|
891
965
|
}
|
|
892
966
|
|
|
@@ -894,7 +968,8 @@ class TinyDragger {
|
|
|
894
968
|
this.#dragging = false;
|
|
895
969
|
this.#lastCollision = null;
|
|
896
970
|
|
|
897
|
-
this.#target.classList.remove(this.#dragHiddenClass
|
|
971
|
+
if (this.#mirrorElem) this.#target.classList.remove(this.#dragHiddenClass);
|
|
972
|
+
this.#target.classList.remove(this.#classDragging);
|
|
898
973
|
document.body.classList.remove(this.#classBodyDragging);
|
|
899
974
|
if (this.#jail)
|
|
900
975
|
this.#jail.classList.remove(this.#classJailDragging, this.#classJailDragDisabled);
|
|
@@ -30,11 +30,63 @@ export type VibrationPatterns = {
|
|
|
30
30
|
* automatic reverting, proxy dragging, and event dispatching.
|
|
31
31
|
*/
|
|
32
32
|
declare class TinyDragger {
|
|
33
|
+
static Utils: {
|
|
34
|
+
TinyHtml: typeof TinyHtml;
|
|
35
|
+
getElsRelativeCenterOffset(rect1: ObjRect, rect2: ObjRect): {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
};
|
|
39
|
+
getElsCollDirDepth(rect1: ObjRect, rect2: ObjRect): {
|
|
40
|
+
inDir: Dirs | null;
|
|
41
|
+
dirX: Dirs | null;
|
|
42
|
+
dirY: Dirs | null;
|
|
43
|
+
depthX: number;
|
|
44
|
+
depthY: number;
|
|
45
|
+
};
|
|
46
|
+
getElsCollDetails(rect1: ObjRect, rect2: ObjRect): {
|
|
47
|
+
depth: CollData;
|
|
48
|
+
dirs: CollDirs;
|
|
49
|
+
isNeg: NegCollDirs;
|
|
50
|
+
};
|
|
51
|
+
areElsCollTop: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
52
|
+
areElsCollBottom: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
53
|
+
areElsCollLeft: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
54
|
+
areElsCollRight: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
55
|
+
areElsCollPerfTop: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
56
|
+
areElsCollPerfBottom: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
57
|
+
areElsCollPerfLeft: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
58
|
+
areElsCollPerfRight: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
59
|
+
areElsColliding: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
60
|
+
areElsPerfColliding: (rect1: ObjRect, rect2: ObjRect) => boolean;
|
|
61
|
+
getElsColliding: (rect1: ObjRect, rect2: ObjRect) => string | null;
|
|
62
|
+
getElsPerfColliding: (rect1: ObjRect, rect2: ObjRect) => "top" | "bottom" | "left" | "right" | null;
|
|
63
|
+
getElsCollOverlap: (rect1: ObjRect, rect2: ObjRect) => {
|
|
64
|
+
overlapLeft: number;
|
|
65
|
+
overlapRight: number;
|
|
66
|
+
overlapTop: number;
|
|
67
|
+
overlapBottom: number;
|
|
68
|
+
};
|
|
69
|
+
getElsCollOverlapPos: ({ overlapLeft, overlapRight, overlapTop, overlapBottom, }?: {
|
|
70
|
+
overlapLeft?: number | undefined;
|
|
71
|
+
overlapRight?: number | undefined;
|
|
72
|
+
overlapTop?: number | undefined;
|
|
73
|
+
overlapBottom?: number | undefined;
|
|
74
|
+
}) => {
|
|
75
|
+
dirX: Dirs;
|
|
76
|
+
dirY: Dirs;
|
|
77
|
+
};
|
|
78
|
+
getRectCenter: (rect: ObjRect) => {
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
33
83
|
/** @typedef {(event: TouchEvent) => void} TouchDragEvent */
|
|
34
84
|
/**
|
|
35
|
-
* @param {HTMLElement} targetElement - The element to make draggable.
|
|
85
|
+
* @param {HTMLElement|TinyHtml} targetElement - The element to make draggable.
|
|
36
86
|
* @param {Object} [options={}] - Configuration options.
|
|
37
87
|
* @param {HTMLElement} [options.jail] - Optional container to restrict dragging within.
|
|
88
|
+
* @param {boolean} [options.mirrorElem=true] - Use a visual clone instead of dragging the original element.
|
|
89
|
+
* @param {number} [options.defaultZIndex] - Sets the z-index value applied when dragging starts.
|
|
38
90
|
* @param {boolean} [options.collisionByMouse=false] - Use mouse position for collision instead of element rect.
|
|
39
91
|
* @param {string} [options.classDragging='dragging'] - CSS class applied to the clone during dragging.
|
|
40
92
|
* @param {string} [options.classBodyDragging='drag-active'] - CSS class applied to <body> during dragging.
|
|
@@ -49,8 +101,10 @@ declare class TinyDragger {
|
|
|
49
101
|
* @param {string} [options.classHidden='drag-hidden'] - CSS class to hide original element during dragging.
|
|
50
102
|
* @throws {Error} If any option has an invalid type.
|
|
51
103
|
*/
|
|
52
|
-
constructor(targetElement: HTMLElement, options?: {
|
|
104
|
+
constructor(targetElement: HTMLElement | TinyHtml, options?: {
|
|
53
105
|
jail?: HTMLElement | undefined;
|
|
106
|
+
mirrorElem?: boolean | undefined;
|
|
107
|
+
defaultZIndex?: number | undefined;
|
|
54
108
|
collisionByMouse?: boolean | undefined;
|
|
55
109
|
classDragging?: string | undefined;
|
|
56
110
|
classBodyDragging?: string | undefined;
|
|
@@ -221,6 +275,26 @@ declare class TinyDragger {
|
|
|
221
275
|
* @param {boolean} value
|
|
222
276
|
*/
|
|
223
277
|
setDropInJailOnly(value: boolean): void;
|
|
278
|
+
/**
|
|
279
|
+
* Returns the current default z-index used for draggable items.
|
|
280
|
+
* @returns {number}
|
|
281
|
+
*/
|
|
282
|
+
getDefaultZIndex(): number;
|
|
283
|
+
/**
|
|
284
|
+
* Sets a new default z-index for draggable items.
|
|
285
|
+
* @param {number} newZIndex
|
|
286
|
+
*/
|
|
287
|
+
setDefaultZIndex(newZIndex: number): void;
|
|
288
|
+
/**
|
|
289
|
+
* Returns whether the draggable element is mirrored or the original.
|
|
290
|
+
* @returns {boolean}
|
|
291
|
+
*/
|
|
292
|
+
isMirrorEnabled(): boolean;
|
|
293
|
+
/**
|
|
294
|
+
* Sets whether the draggable element should be a mirror or the original.
|
|
295
|
+
* @param {boolean} useMirror
|
|
296
|
+
*/
|
|
297
|
+
setMirrorEnabled(useMirror: boolean): void;
|
|
224
298
|
/**
|
|
225
299
|
* Returns the original target element being dragged.
|
|
226
300
|
* @returns {HTMLElement}
|
|
@@ -313,4 +387,6 @@ declare class TinyDragger {
|
|
|
313
387
|
destroy(): void;
|
|
314
388
|
#private;
|
|
315
389
|
}
|
|
390
|
+
import TinyHtml from './TinyHtml.mjs';
|
|
391
|
+
import * as TinyCollision from '../basics/collision.mjs';
|
|
316
392
|
//# sourceMappingURL=TinyDragger.d.mts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import TinyHtml from './TinyHtml.mjs';
|
|
2
|
+
import * as TinyCollision from '../basics/collision.mjs';
|
|
2
3
|
import { isJsonObject } from '../basics/objFilter.mjs';
|
|
3
4
|
/**
|
|
4
5
|
* @typedef {Object} VibrationPatterns
|
|
@@ -13,10 +14,12 @@ import { isJsonObject } from '../basics/objFilter.mjs';
|
|
|
13
14
|
* automatic reverting, proxy dragging, and event dispatching.
|
|
14
15
|
*/
|
|
15
16
|
class TinyDragger {
|
|
17
|
+
static Utils = { ...TinyCollision, TinyHtml };
|
|
16
18
|
#enabled = true;
|
|
17
19
|
#destroyed = false;
|
|
18
20
|
#offsetY = 0;
|
|
19
21
|
#offsetX = 0;
|
|
22
|
+
#mirrorElem = true;
|
|
20
23
|
#multiCollision = false;
|
|
21
24
|
#lockInsideJail = false;
|
|
22
25
|
#revertOnDrop = false;
|
|
@@ -33,6 +36,7 @@ class TinyDragger {
|
|
|
33
36
|
#vibration = { start: false, end: false, collide: false, move: false };
|
|
34
37
|
/** @type {HTMLElement|null} */
|
|
35
38
|
#jail = null;
|
|
39
|
+
/** @type {HTMLElement} */
|
|
36
40
|
#target;
|
|
37
41
|
#dragHiddenClass = 'drag-hidden';
|
|
38
42
|
#classDragging = 'dragging';
|
|
@@ -40,11 +44,14 @@ class TinyDragger {
|
|
|
40
44
|
#classJailDragging = 'jail-drag-active';
|
|
41
45
|
#classJailDragDisabled = 'jail-drag-disabled';
|
|
42
46
|
#classDragCollision = 'dragging-collision';
|
|
47
|
+
#defaultZIndex = 9999;
|
|
43
48
|
/** @typedef {(event: TouchEvent) => void} TouchDragEvent */
|
|
44
49
|
/**
|
|
45
|
-
* @param {HTMLElement} targetElement - The element to make draggable.
|
|
50
|
+
* @param {HTMLElement|TinyHtml} targetElement - The element to make draggable.
|
|
46
51
|
* @param {Object} [options={}] - Configuration options.
|
|
47
52
|
* @param {HTMLElement} [options.jail] - Optional container to restrict dragging within.
|
|
53
|
+
* @param {boolean} [options.mirrorElem=true] - Use a visual clone instead of dragging the original element.
|
|
54
|
+
* @param {number} [options.defaultZIndex] - Sets the z-index value applied when dragging starts.
|
|
48
55
|
* @param {boolean} [options.collisionByMouse=false] - Use mouse position for collision instead of element rect.
|
|
49
56
|
* @param {string} [options.classDragging='dragging'] - CSS class applied to the clone during dragging.
|
|
50
57
|
* @param {string} [options.classBodyDragging='drag-active'] - CSS class applied to <body> during dragging.
|
|
@@ -60,12 +67,15 @@ class TinyDragger {
|
|
|
60
67
|
* @throws {Error} If any option has an invalid type.
|
|
61
68
|
*/
|
|
62
69
|
constructor(targetElement, options = {}) {
|
|
63
|
-
|
|
70
|
+
const targetElem = !(targetElement instanceof TinyHtml) ? targetElement : targetElement.get();
|
|
71
|
+
if (!(targetElem instanceof HTMLElement))
|
|
64
72
|
throw new Error('TinyDragger requires a valid target HTMLElement to initialize.');
|
|
65
|
-
this.#target =
|
|
73
|
+
this.#target = targetElem;
|
|
66
74
|
// === Validations ===
|
|
67
75
|
if (options.jail !== undefined && !(options.jail instanceof HTMLElement))
|
|
68
76
|
throw new Error('The "jail" option must be an HTMLElement if provided.');
|
|
77
|
+
if (options.defaultZIndex !== undefined)
|
|
78
|
+
this.setDefaultZIndex(options.defaultZIndex);
|
|
69
79
|
if (options.vibration !== undefined &&
|
|
70
80
|
options.vibration !== false &&
|
|
71
81
|
!isJsonObject(options.vibration))
|
|
@@ -88,6 +98,7 @@ class TinyDragger {
|
|
|
88
98
|
throw new Error(`The "${name}" option must be a string.`);
|
|
89
99
|
}
|
|
90
100
|
};
|
|
101
|
+
validateBoolean(options.mirrorElem, 'mirrorElem');
|
|
91
102
|
validateBoolean(options.collisionByMouse, 'collisionByMouse');
|
|
92
103
|
validateBoolean(options.lockInsideJail, 'lockInsideJail');
|
|
93
104
|
validateBoolean(options.dropInJailOnly, 'dropInJailOnly');
|
|
@@ -118,6 +129,8 @@ class TinyDragger {
|
|
|
118
129
|
this.#classDragCollision = options.classDragCollision;
|
|
119
130
|
if (typeof options.collisionByMouse === 'boolean')
|
|
120
131
|
this.#collisionByMouse = options.collisionByMouse;
|
|
132
|
+
if (typeof options.mirrorElem === 'boolean')
|
|
133
|
+
this.#mirrorElem = options.mirrorElem;
|
|
121
134
|
if (typeof options.revertOnDrop === 'boolean')
|
|
122
135
|
this.#revertOnDrop = options.revertOnDrop;
|
|
123
136
|
if (typeof options.lockInsideJail === 'boolean')
|
|
@@ -238,7 +251,7 @@ class TinyDragger {
|
|
|
238
251
|
typeof event.clientY !== 'number')
|
|
239
252
|
throw new Error('getOffset expects an event with valid clientX and clientY coordinates.');
|
|
240
253
|
const targetRect = this.#target.getBoundingClientRect();
|
|
241
|
-
const { left: borderLeft, top: borderTop } =
|
|
254
|
+
const { left: borderLeft, top: borderTop } = TinyHtml.borderWidth(this.#target);
|
|
242
255
|
return {
|
|
243
256
|
x: event.clientX - targetRect.left + borderLeft,
|
|
244
257
|
y: event.clientY - targetRect.top + borderTop,
|
|
@@ -253,10 +266,14 @@ class TinyDragger {
|
|
|
253
266
|
event.preventDefault();
|
|
254
267
|
if (this.#destroyed || !this.#enabled || !this.#target.parentElement)
|
|
255
268
|
return;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
269
|
+
if (this.#mirrorElem) {
|
|
270
|
+
const dragProxy = this.#target.cloneNode(true);
|
|
271
|
+
if (!(dragProxy instanceof HTMLElement))
|
|
272
|
+
throw new Error('[TinyDragger] INVALID DRAG ELEMENT!');
|
|
273
|
+
this.#dragProxy = dragProxy;
|
|
274
|
+
}
|
|
275
|
+
else
|
|
276
|
+
this.#dragProxy = this.#target;
|
|
260
277
|
this.#dragging = true;
|
|
261
278
|
const rect = this.#target.getBoundingClientRect();
|
|
262
279
|
Object.assign(this.#dragProxy.style, {
|
|
@@ -266,10 +283,12 @@ class TinyDragger {
|
|
|
266
283
|
top: `${this.#target.offsetTop}px`,
|
|
267
284
|
width: `${rect.width}px`,
|
|
268
285
|
height: `${rect.height}px`,
|
|
269
|
-
zIndex:
|
|
286
|
+
zIndex: this.#defaultZIndex,
|
|
270
287
|
});
|
|
271
|
-
|
|
272
|
-
|
|
288
|
+
if (this.#mirrorElem) {
|
|
289
|
+
this.#target.classList.add(this.#dragHiddenClass);
|
|
290
|
+
this.#target.parentElement.appendChild(this.#dragProxy);
|
|
291
|
+
}
|
|
273
292
|
const { x: offsetX, y: offsetY } = this.getOffset(event);
|
|
274
293
|
this.#offsetX = offsetX;
|
|
275
294
|
this.#offsetY = offsetY;
|
|
@@ -360,7 +379,7 @@ class TinyDragger {
|
|
|
360
379
|
const targetRect = this.#dragProxy.getBoundingClientRect();
|
|
361
380
|
const jailLeft = jailRect.left - parentRect.left;
|
|
362
381
|
const jailTop = jailRect.top - parentRect.top;
|
|
363
|
-
const { x: borderX, y: borderY } =
|
|
382
|
+
const { x: borderX, y: borderY } = TinyHtml.borderWidth(this.#jail);
|
|
364
383
|
const maxX = jailLeft + jailRect.width - targetRect.width - borderY;
|
|
365
384
|
const maxY = jailTop + jailRect.height - targetRect.height - borderX;
|
|
366
385
|
x = Math.max(jailLeft, Math.min(x, maxX));
|
|
@@ -443,13 +462,25 @@ class TinyDragger {
|
|
|
443
462
|
const newX = this.#dragProxy.style.left;
|
|
444
463
|
const newY = this.#dragProxy.style.top;
|
|
445
464
|
if (this.#dragProxy) {
|
|
446
|
-
this.#
|
|
465
|
+
if (this.#mirrorElem)
|
|
466
|
+
this.#dragProxy.remove();
|
|
467
|
+
else
|
|
468
|
+
Object.assign(this.#dragProxy.style, {
|
|
469
|
+
position: '',
|
|
470
|
+
pointerEvents: '',
|
|
471
|
+
left: '',
|
|
472
|
+
top: '',
|
|
473
|
+
width: '',
|
|
474
|
+
height: '',
|
|
475
|
+
zIndex: '',
|
|
476
|
+
});
|
|
447
477
|
this.#dragProxy = null;
|
|
448
478
|
}
|
|
449
479
|
if (this.#lastCollision)
|
|
450
480
|
this.#removeCollision();
|
|
451
481
|
this.#lastCollision = null;
|
|
452
|
-
|
|
482
|
+
if (this.#mirrorElem)
|
|
483
|
+
this.#target.classList.remove(this.#dragHiddenClass);
|
|
453
484
|
if (!this.#revertOnDrop) {
|
|
454
485
|
this.#target.style.left = newX;
|
|
455
486
|
this.#target.style.top = newY;
|
|
@@ -623,6 +654,38 @@ class TinyDragger {
|
|
|
623
654
|
throw new Error('dropInJailOnly must be a boolean.');
|
|
624
655
|
this.#dropInJailOnly = value;
|
|
625
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Returns the current default z-index used for draggable items.
|
|
659
|
+
* @returns {number}
|
|
660
|
+
*/
|
|
661
|
+
getDefaultZIndex() {
|
|
662
|
+
return this.#defaultZIndex;
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Sets a new default z-index for draggable items.
|
|
666
|
+
* @param {number} newZIndex
|
|
667
|
+
*/
|
|
668
|
+
setDefaultZIndex(newZIndex) {
|
|
669
|
+
if (typeof newZIndex !== 'number' || !Number.isFinite(newZIndex))
|
|
670
|
+
throw new TypeError('Z-index must be a finite number.');
|
|
671
|
+
this.#defaultZIndex = newZIndex;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Returns whether the draggable element is mirrored or the original.
|
|
675
|
+
* @returns {boolean}
|
|
676
|
+
*/
|
|
677
|
+
isMirrorEnabled() {
|
|
678
|
+
return this.#mirrorElem;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Sets whether the draggable element should be a mirror or the original.
|
|
682
|
+
* @param {boolean} useMirror
|
|
683
|
+
*/
|
|
684
|
+
setMirrorEnabled(useMirror) {
|
|
685
|
+
if (typeof useMirror !== 'boolean')
|
|
686
|
+
throw new TypeError('Mirror setting must be a boolean.');
|
|
687
|
+
this.#mirrorElem = useMirror;
|
|
688
|
+
}
|
|
626
689
|
/**
|
|
627
690
|
* Returns the original target element being dragged.
|
|
628
691
|
* @returns {HTMLElement}
|
|
@@ -767,13 +830,26 @@ class TinyDragger {
|
|
|
767
830
|
if (this.#lastCollision)
|
|
768
831
|
this.#removeCollision();
|
|
769
832
|
if (this.#dragProxy) {
|
|
770
|
-
this.#
|
|
833
|
+
if (this.#mirrorElem)
|
|
834
|
+
this.#dragProxy.remove();
|
|
835
|
+
else
|
|
836
|
+
Object.assign(this.#dragProxy.style, {
|
|
837
|
+
position: '',
|
|
838
|
+
pointerEvents: '',
|
|
839
|
+
left: '',
|
|
840
|
+
top: '',
|
|
841
|
+
width: '',
|
|
842
|
+
height: '',
|
|
843
|
+
zIndex: '',
|
|
844
|
+
});
|
|
771
845
|
this.#dragProxy = null;
|
|
772
846
|
}
|
|
773
847
|
this.#collidables = [];
|
|
774
848
|
this.#dragging = false;
|
|
775
849
|
this.#lastCollision = null;
|
|
776
|
-
|
|
850
|
+
if (this.#mirrorElem)
|
|
851
|
+
this.#target.classList.remove(this.#dragHiddenClass);
|
|
852
|
+
this.#target.classList.remove(this.#classDragging);
|
|
777
853
|
document.body.classList.remove(this.#classBodyDragging);
|
|
778
854
|
if (this.#jail)
|
|
779
855
|
this.#jail.classList.remove(this.#classJailDragging, this.#classJailDragDisabled);
|