tiny-essentials 1.12.0 → 1.12.2
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/legacy/firebase/index.mjs +5 -5
- package/dist/v1/TinyBasicsEs.js +1 -1257
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyDragger.js +148 -43
- package/dist/v1/TinyDragger.min.js +1 -1
- package/dist/v1/TinyEssentials.js +484 -189
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyUploadClicker.js +478 -190
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/basics/index.cjs +0 -23
- package/dist/v1/basics/index.d.mts +1 -23
- package/dist/v1/basics/index.mjs +1 -2
- package/dist/v1/fileManager/asyncFuncs.cjs +272 -0
- package/dist/v1/fileManager/asyncFuncs.d.mts +93 -0
- package/dist/v1/fileManager/asyncFuncs.mjs +236 -0
- package/dist/v1/fileManager/index.cjs +35 -0
- package/dist/v1/fileManager/index.d.mts +30 -0
- package/dist/v1/fileManager/index.mjs +3 -0
- package/dist/v1/{basics/fileManager.cjs → fileManager/normalFuncs.cjs} +10 -105
- package/dist/v1/{basics/fileManager.d.mts → fileManager/normalFuncs.d.mts} +3 -56
- package/dist/v1/{basics/fileManager.mjs → fileManager/normalFuncs.mjs} +48 -131
- package/dist/v1/index.cjs +30 -23
- package/dist/v1/index.d.mts +29 -23
- package/dist/v1/index.mjs +3 -2
- package/dist/v1/libs/TinyDragger.cjs +148 -43
- package/dist/v1/libs/TinyDragger.d.mts +18 -2
- package/dist/v1/libs/TinyDragger.mjs +132 -38
- package/dist/v1/libs/TinyUploadClicker.cjs +1 -0
- package/docs/v1/README.md +3 -1
- package/docs/v1/{basics/fileManager.md → fileManager/main.md} +12 -0
- package/docs/v1/libs/TinyDragger.md +15 -0
- package/package.json +5 -1
|
@@ -23,6 +23,7 @@ class TinyDragger {
|
|
|
23
23
|
#offsetY = 0;
|
|
24
24
|
#offsetX = 0;
|
|
25
25
|
|
|
26
|
+
#multiCollision = false;
|
|
26
27
|
#lockInsideJail = false;
|
|
27
28
|
#revertOnDrop = false;
|
|
28
29
|
#dragging = false;
|
|
@@ -67,6 +68,7 @@ class TinyDragger {
|
|
|
67
68
|
* @param {string} [options.classDragCollision='dragging-collision'] - CSS class applied to collision element.
|
|
68
69
|
* @param {boolean} [options.lockInsideJail=false] - Restrict movement within the jail container.
|
|
69
70
|
* @param {boolean} [options.dropInJailOnly=false] - Restrict drop within the jail container.
|
|
71
|
+
* @param {boolean} [options.multiCollision=false] - Enables returning multiple collided elements.
|
|
70
72
|
* @param {VibrationPatterns|false} [options.vibration=false] - Vibration feedback configuration.
|
|
71
73
|
* @param {boolean} [options.revertOnDrop=false] - Whether to return to original position on drop.
|
|
72
74
|
* @param {string} [options.classHidden='drag-hidden'] - CSS class to hide original element during dragging.
|
|
@@ -113,6 +115,7 @@ class TinyDragger {
|
|
|
113
115
|
validateBoolean(options.lockInsideJail, 'lockInsideJail');
|
|
114
116
|
validateBoolean(options.dropInJailOnly, 'dropInJailOnly');
|
|
115
117
|
validateBoolean(options.revertOnDrop, 'revertOnDrop');
|
|
118
|
+
validateBoolean(options.multiCollision, 'multiCollision');
|
|
116
119
|
|
|
117
120
|
validateString(options.classDragging, 'classDragging');
|
|
118
121
|
validateString(options.classBodyDragging, 'classBodyDragging');
|
|
@@ -146,6 +149,7 @@ class TinyDragger {
|
|
|
146
149
|
if (typeof options.revertOnDrop === 'boolean') this.#revertOnDrop = options.revertOnDrop;
|
|
147
150
|
if (typeof options.lockInsideJail === 'boolean') this.#lockInsideJail = options.lockInsideJail;
|
|
148
151
|
if (typeof options.dropInJailOnly === 'boolean') this.#dropInJailOnly = options.dropInJailOnly;
|
|
152
|
+
if (typeof options.multiCollision === 'boolean') this.#multiCollision = options.multiCollision;
|
|
149
153
|
|
|
150
154
|
/** @private */
|
|
151
155
|
this._onMouseDown = this.#startDrag.bind(this);
|
|
@@ -337,22 +341,67 @@ class TinyDragger {
|
|
|
337
341
|
this.#dispatchEvent('drag');
|
|
338
342
|
}
|
|
339
343
|
|
|
344
|
+
/** @type {HTMLElement[]} */
|
|
345
|
+
#collisionsMarked = [];
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Marks an element as currently collided by adding the collision CSS class.
|
|
349
|
+
* The element is stored in an internal list for easy removal later.
|
|
350
|
+
*
|
|
351
|
+
* @param {HTMLElement|null} el - The element to mark as collided.
|
|
352
|
+
*/
|
|
353
|
+
#addCollision(el) {
|
|
354
|
+
if (!el) return;
|
|
355
|
+
el.classList.add(this.#classDragCollision);
|
|
356
|
+
this.#collisionsMarked.push(el);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Removes the collision CSS class from all previously marked elements.
|
|
361
|
+
* Also clears the last single collision element, if set.
|
|
362
|
+
*
|
|
363
|
+
*/
|
|
364
|
+
#removeCollision() {
|
|
365
|
+
while (this.#collisionsMarked.length > 0) {
|
|
366
|
+
const el = this.#collisionsMarked.shift();
|
|
367
|
+
if (el) el.classList.remove(this.#classDragCollision);
|
|
368
|
+
}
|
|
369
|
+
if (!this.#lastCollision) return;
|
|
370
|
+
this.#lastCollision.classList.remove(this.#classDragCollision);
|
|
371
|
+
}
|
|
372
|
+
|
|
340
373
|
/**
|
|
341
374
|
* Handles dragging collision.
|
|
342
375
|
* @param {MouseEvent|Touch} event - The drag event.
|
|
343
376
|
*/
|
|
344
377
|
checkDragCollision(event) {
|
|
345
|
-
const {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
378
|
+
const { collidedElements } = this.execCollision(event);
|
|
379
|
+
const first = collidedElements[0] || null;
|
|
380
|
+
|
|
381
|
+
// Removes old marking if necessary
|
|
382
|
+
if (this.#lastCollision && !collidedElements.includes(this.#lastCollision)) {
|
|
383
|
+
this.#removeCollision();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Adds Marking for All Colluded
|
|
387
|
+
collidedElements.forEach((el) => this.#addCollision(el));
|
|
388
|
+
|
|
389
|
+
// Removes markings from who no longer collided
|
|
390
|
+
this.#collidables.forEach((el) => {
|
|
391
|
+
if (!collidedElements.includes(el)) {
|
|
392
|
+
el.classList.remove(this.#classDragCollision);
|
|
349
393
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.#
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
if (
|
|
397
|
+
navigator.vibrate &&
|
|
398
|
+
Array.isArray(this.#vibration.collide) &&
|
|
399
|
+
collidedElements.length > 0
|
|
400
|
+
) {
|
|
401
|
+
navigator.vibrate(this.#vibration.collide);
|
|
355
402
|
}
|
|
403
|
+
|
|
404
|
+
this.#lastCollision = first;
|
|
356
405
|
}
|
|
357
406
|
|
|
358
407
|
/**
|
|
@@ -399,37 +448,48 @@ class TinyDragger {
|
|
|
399
448
|
/**
|
|
400
449
|
* Handles the collision of a drag.
|
|
401
450
|
* @param {MouseEvent|Touch} event - The release event.
|
|
402
|
-
* @returns {{ inJail: boolean;
|
|
451
|
+
* @returns {{ inJail: boolean; collidedElements: (HTMLElement | null)[] }}
|
|
403
452
|
*/
|
|
404
453
|
execCollision(event) {
|
|
405
|
-
if (this.#destroyed || !this.#dragProxy) return { inJail: false,
|
|
454
|
+
if (this.#destroyed || !this.#dragProxy) return { inJail: false, collidedElements: [] };
|
|
406
455
|
|
|
407
|
-
let
|
|
456
|
+
let collidedElements = [];
|
|
408
457
|
let inJail = true;
|
|
409
458
|
const jailRect = this.#jail?.getBoundingClientRect();
|
|
459
|
+
|
|
410
460
|
if (this.#collisionByMouse) {
|
|
411
461
|
const x = event.clientX;
|
|
412
462
|
const y = event.clientY;
|
|
463
|
+
|
|
413
464
|
if (this.#dropInJailOnly && this.#jail && jailRect) {
|
|
414
465
|
inJail =
|
|
415
466
|
x >= jailRect.left && x <= jailRect.right && y >= jailRect.top && y <= jailRect.bottom;
|
|
416
467
|
}
|
|
417
468
|
|
|
418
|
-
|
|
469
|
+
collidedElements = inJail
|
|
470
|
+
? this.#multiCollision
|
|
471
|
+
? this.getAllCollidedElements(x, y)
|
|
472
|
+
: [this.getCollidedElement(x, y)].filter(Boolean)
|
|
473
|
+
: [];
|
|
419
474
|
} else {
|
|
420
|
-
const
|
|
475
|
+
const rect = this.#dragProxy.getBoundingClientRect();
|
|
476
|
+
|
|
421
477
|
if (this.#dropInJailOnly && this.#jail && jailRect) {
|
|
422
478
|
inJail =
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
479
|
+
rect.left >= jailRect.left &&
|
|
480
|
+
rect.right <= jailRect.right &&
|
|
481
|
+
rect.top >= jailRect.top &&
|
|
482
|
+
rect.bottom <= jailRect.bottom;
|
|
427
483
|
}
|
|
428
484
|
|
|
429
|
-
|
|
485
|
+
collidedElements = inJail
|
|
486
|
+
? this.#multiCollision
|
|
487
|
+
? this.getAllCollidedElementsByRect(rect)
|
|
488
|
+
: [this.getCollidedElementByRect(rect)].filter(Boolean)
|
|
489
|
+
: [];
|
|
430
490
|
}
|
|
431
491
|
|
|
432
|
-
return { inJail,
|
|
492
|
+
return { inJail, collidedElements };
|
|
433
493
|
}
|
|
434
494
|
|
|
435
495
|
/**
|
|
@@ -452,7 +512,7 @@ class TinyDragger {
|
|
|
452
512
|
|
|
453
513
|
document.removeEventListener('touchmove', this._onTouchMove);
|
|
454
514
|
document.removeEventListener('touchend', this._onTouchEnd);
|
|
455
|
-
const {
|
|
515
|
+
const { collidedElements } = this.execCollision(event);
|
|
456
516
|
|
|
457
517
|
if (navigator.vibrate && Array.isArray(this.#vibration.end)) {
|
|
458
518
|
navigator.vibrate(this.#vibration.end);
|
|
@@ -465,7 +525,7 @@ class TinyDragger {
|
|
|
465
525
|
this.#dragProxy = null;
|
|
466
526
|
}
|
|
467
527
|
|
|
468
|
-
if (this.#lastCollision) this.#
|
|
528
|
+
if (this.#lastCollision) this.#removeCollision();
|
|
469
529
|
this.#lastCollision = null;
|
|
470
530
|
|
|
471
531
|
this.#target.classList.remove(this.#dragHiddenClass);
|
|
@@ -476,13 +536,50 @@ class TinyDragger {
|
|
|
476
536
|
|
|
477
537
|
const dropEvent = new CustomEvent('drop', {
|
|
478
538
|
detail: {
|
|
479
|
-
|
|
539
|
+
targets: collidedElements,
|
|
540
|
+
first: collidedElements[0] || null,
|
|
480
541
|
},
|
|
481
542
|
});
|
|
482
|
-
|
|
483
543
|
this.#target.dispatchEvent(dropEvent);
|
|
484
544
|
}
|
|
485
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Checks if the provided element intersects with the given bounding rectangle.
|
|
548
|
+
*
|
|
549
|
+
* @param {HTMLElement} el - The element to test for collision.
|
|
550
|
+
* @param {DOMRect} rect - The bounding rectangle to check against.
|
|
551
|
+
* @returns {boolean} True if the element intersects with the rectangle.
|
|
552
|
+
*/
|
|
553
|
+
#getCollidedElementByRect(el, rect) {
|
|
554
|
+
const elRect = el.getBoundingClientRect();
|
|
555
|
+
return !(
|
|
556
|
+
rect.right < elRect.left ||
|
|
557
|
+
rect.left > elRect.right ||
|
|
558
|
+
rect.bottom < elRect.top ||
|
|
559
|
+
rect.top > elRect.bottom
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Returns all elements currently colliding with the given rectangle.
|
|
565
|
+
*
|
|
566
|
+
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
567
|
+
* @returns {HTMLElement[]} A list of all collided elements.
|
|
568
|
+
* @throws {Error} If the input is not a valid DOMRect with numeric bounds.
|
|
569
|
+
*/
|
|
570
|
+
getAllCollidedElementsByRect(rect) {
|
|
571
|
+
this.#checkDestroy();
|
|
572
|
+
if (
|
|
573
|
+
!(rect instanceof DOMRect) ||
|
|
574
|
+
typeof rect.left !== 'number' ||
|
|
575
|
+
typeof rect.right !== 'number' ||
|
|
576
|
+
typeof rect.top !== 'number' ||
|
|
577
|
+
typeof rect.bottom !== 'number'
|
|
578
|
+
)
|
|
579
|
+
throw new Error('getCollidedElementByRect expects a valid DOMRect object.');
|
|
580
|
+
return this.#collidables.filter((el) => this.#getCollidedElementByRect(el, rect));
|
|
581
|
+
}
|
|
582
|
+
|
|
486
583
|
/**
|
|
487
584
|
* Detects collision based on rectangle intersection.
|
|
488
585
|
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
@@ -499,18 +596,32 @@ class TinyDragger {
|
|
|
499
596
|
typeof rect.bottom !== 'number'
|
|
500
597
|
)
|
|
501
598
|
throw new Error('getCollidedElementByRect expects a valid DOMRect object.');
|
|
599
|
+
return this.#collidables.find((el) => this.#getCollidedElementByRect(el, rect)) || null;
|
|
600
|
+
}
|
|
502
601
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Checks whether a given (x, y) coordinate is inside the bounding rectangle of an element.
|
|
604
|
+
*
|
|
605
|
+
* @param {HTMLElement} el - The element to test for collision.
|
|
606
|
+
* @param {number} x - Horizontal screen coordinate.
|
|
607
|
+
* @param {number} y - Vertical screen coordinate.
|
|
608
|
+
* @returns {boolean} True if the point is within the element's bounds.
|
|
609
|
+
*/
|
|
610
|
+
#getCollidedElement(el, x, y) {
|
|
611
|
+
const rect = el.getBoundingClientRect();
|
|
612
|
+
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @param {number} x - Horizontal screen coordinate.
|
|
617
|
+
* @param {number} y - Vertical screen coordinate.
|
|
618
|
+
* @returns {HTMLElement[]} The collided element or null.
|
|
619
|
+
*/
|
|
620
|
+
getAllCollidedElements(x, y) {
|
|
621
|
+
this.#checkDestroy();
|
|
622
|
+
if (typeof x !== 'number' || typeof y !== 'number')
|
|
623
|
+
throw new Error('getCollidedElement expects numeric x and y coordinates.');
|
|
624
|
+
return this.#collidables.filter((el) => this.#getCollidedElement(el, x, y));
|
|
514
625
|
}
|
|
515
626
|
|
|
516
627
|
/**
|
|
@@ -523,13 +634,7 @@ class TinyDragger {
|
|
|
523
634
|
this.#checkDestroy();
|
|
524
635
|
if (typeof x !== 'number' || typeof y !== 'number')
|
|
525
636
|
throw new Error('getCollidedElement expects numeric x and y coordinates.');
|
|
526
|
-
|
|
527
|
-
return (
|
|
528
|
-
this.#collidables.find((el) => {
|
|
529
|
-
const rect = el.getBoundingClientRect();
|
|
530
|
-
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
531
|
-
}) || null
|
|
532
|
-
);
|
|
637
|
+
return this.#collidables.find((el) => this.#getCollidedElement(el, x, y)) || null;
|
|
533
638
|
}
|
|
534
639
|
|
|
535
640
|
/**
|
|
@@ -779,7 +884,7 @@ class TinyDragger {
|
|
|
779
884
|
document.removeEventListener('touchmove', this._onTouchMove);
|
|
780
885
|
document.removeEventListener('touchend', this._onTouchEnd);
|
|
781
886
|
|
|
782
|
-
if (this.#lastCollision) this.#
|
|
887
|
+
if (this.#lastCollision) this.#removeCollision();
|
|
783
888
|
if (this.#dragProxy) {
|
|
784
889
|
this.#dragProxy.remove();
|
|
785
890
|
this.#dragProxy = null;
|
|
@@ -43,6 +43,7 @@ declare class TinyDragger {
|
|
|
43
43
|
* @param {string} [options.classDragCollision='dragging-collision'] - CSS class applied to collision element.
|
|
44
44
|
* @param {boolean} [options.lockInsideJail=false] - Restrict movement within the jail container.
|
|
45
45
|
* @param {boolean} [options.dropInJailOnly=false] - Restrict drop within the jail container.
|
|
46
|
+
* @param {boolean} [options.multiCollision=false] - Enables returning multiple collided elements.
|
|
46
47
|
* @param {VibrationPatterns|false} [options.vibration=false] - Vibration feedback configuration.
|
|
47
48
|
* @param {boolean} [options.revertOnDrop=false] - Whether to return to original position on drop.
|
|
48
49
|
* @param {string} [options.classHidden='drag-hidden'] - CSS class to hide original element during dragging.
|
|
@@ -58,6 +59,7 @@ declare class TinyDragger {
|
|
|
58
59
|
classDragCollision?: string | undefined;
|
|
59
60
|
lockInsideJail?: boolean | undefined;
|
|
60
61
|
dropInJailOnly?: boolean | undefined;
|
|
62
|
+
multiCollision?: boolean | undefined;
|
|
61
63
|
vibration?: false | VibrationPatterns | undefined;
|
|
62
64
|
revertOnDrop?: boolean | undefined;
|
|
63
65
|
classHidden?: string | undefined;
|
|
@@ -140,12 +142,20 @@ declare class TinyDragger {
|
|
|
140
142
|
/**
|
|
141
143
|
* Handles the collision of a drag.
|
|
142
144
|
* @param {MouseEvent|Touch} event - The release event.
|
|
143
|
-
* @returns {{ inJail: boolean;
|
|
145
|
+
* @returns {{ inJail: boolean; collidedElements: (HTMLElement | null)[] }}
|
|
144
146
|
*/
|
|
145
147
|
execCollision(event: MouseEvent | Touch): {
|
|
146
148
|
inJail: boolean;
|
|
147
|
-
|
|
149
|
+
collidedElements: (HTMLElement | null)[];
|
|
148
150
|
};
|
|
151
|
+
/**
|
|
152
|
+
* Returns all elements currently colliding with the given rectangle.
|
|
153
|
+
*
|
|
154
|
+
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
155
|
+
* @returns {HTMLElement[]} A list of all collided elements.
|
|
156
|
+
* @throws {Error} If the input is not a valid DOMRect with numeric bounds.
|
|
157
|
+
*/
|
|
158
|
+
getAllCollidedElementsByRect(rect: DOMRect): HTMLElement[];
|
|
149
159
|
/**
|
|
150
160
|
* Detects collision based on rectangle intersection.
|
|
151
161
|
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
@@ -153,6 +163,12 @@ declare class TinyDragger {
|
|
|
153
163
|
* @throws {Error} If rect is not a DOMRect with valid numeric properties.
|
|
154
164
|
*/
|
|
155
165
|
getCollidedElementByRect(rect: DOMRect): HTMLElement | null;
|
|
166
|
+
/**
|
|
167
|
+
* @param {number} x - Horizontal screen coordinate.
|
|
168
|
+
* @param {number} y - Vertical screen coordinate.
|
|
169
|
+
* @returns {HTMLElement[]} The collided element or null.
|
|
170
|
+
*/
|
|
171
|
+
getAllCollidedElements(x: number, y: number): HTMLElement[];
|
|
156
172
|
/**
|
|
157
173
|
* Detects collision with a point using element bounding rectangles.
|
|
158
174
|
* @param {number} x - Horizontal screen coordinate.
|
|
@@ -17,6 +17,7 @@ class TinyDragger {
|
|
|
17
17
|
#destroyed = false;
|
|
18
18
|
#offsetY = 0;
|
|
19
19
|
#offsetX = 0;
|
|
20
|
+
#multiCollision = false;
|
|
20
21
|
#lockInsideJail = false;
|
|
21
22
|
#revertOnDrop = false;
|
|
22
23
|
#dragging = false;
|
|
@@ -52,6 +53,7 @@ class TinyDragger {
|
|
|
52
53
|
* @param {string} [options.classDragCollision='dragging-collision'] - CSS class applied to collision element.
|
|
53
54
|
* @param {boolean} [options.lockInsideJail=false] - Restrict movement within the jail container.
|
|
54
55
|
* @param {boolean} [options.dropInJailOnly=false] - Restrict drop within the jail container.
|
|
56
|
+
* @param {boolean} [options.multiCollision=false] - Enables returning multiple collided elements.
|
|
55
57
|
* @param {VibrationPatterns|false} [options.vibration=false] - Vibration feedback configuration.
|
|
56
58
|
* @param {boolean} [options.revertOnDrop=false] - Whether to return to original position on drop.
|
|
57
59
|
* @param {string} [options.classHidden='drag-hidden'] - CSS class to hide original element during dragging.
|
|
@@ -90,6 +92,7 @@ class TinyDragger {
|
|
|
90
92
|
validateBoolean(options.lockInsideJail, 'lockInsideJail');
|
|
91
93
|
validateBoolean(options.dropInJailOnly, 'dropInJailOnly');
|
|
92
94
|
validateBoolean(options.revertOnDrop, 'revertOnDrop');
|
|
95
|
+
validateBoolean(options.multiCollision, 'multiCollision');
|
|
93
96
|
validateString(options.classDragging, 'classDragging');
|
|
94
97
|
validateString(options.classBodyDragging, 'classBodyDragging');
|
|
95
98
|
validateString(options.classJailDragging, 'classJailDragging');
|
|
@@ -121,6 +124,8 @@ class TinyDragger {
|
|
|
121
124
|
this.#lockInsideJail = options.lockInsideJail;
|
|
122
125
|
if (typeof options.dropInJailOnly === 'boolean')
|
|
123
126
|
this.#dropInJailOnly = options.dropInJailOnly;
|
|
127
|
+
if (typeof options.multiCollision === 'boolean')
|
|
128
|
+
this.#multiCollision = options.multiCollision;
|
|
124
129
|
/** @private */
|
|
125
130
|
this._onMouseDown = this.#startDrag.bind(this);
|
|
126
131
|
/** @private */
|
|
@@ -282,25 +287,60 @@ class TinyDragger {
|
|
|
282
287
|
this.checkDragCollision(event);
|
|
283
288
|
this.#dispatchEvent('drag');
|
|
284
289
|
}
|
|
290
|
+
/** @type {HTMLElement[]} */
|
|
291
|
+
#collisionsMarked = [];
|
|
292
|
+
/**
|
|
293
|
+
* Marks an element as currently collided by adding the collision CSS class.
|
|
294
|
+
* The element is stored in an internal list for easy removal later.
|
|
295
|
+
*
|
|
296
|
+
* @param {HTMLElement|null} el - The element to mark as collided.
|
|
297
|
+
*/
|
|
298
|
+
#addCollision(el) {
|
|
299
|
+
if (!el)
|
|
300
|
+
return;
|
|
301
|
+
el.classList.add(this.#classDragCollision);
|
|
302
|
+
this.#collisionsMarked.push(el);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Removes the collision CSS class from all previously marked elements.
|
|
306
|
+
* Also clears the last single collision element, if set.
|
|
307
|
+
*
|
|
308
|
+
*/
|
|
309
|
+
#removeCollision() {
|
|
310
|
+
while (this.#collisionsMarked.length > 0) {
|
|
311
|
+
const el = this.#collisionsMarked.shift();
|
|
312
|
+
if (el)
|
|
313
|
+
el.classList.remove(this.#classDragCollision);
|
|
314
|
+
}
|
|
315
|
+
if (!this.#lastCollision)
|
|
316
|
+
return;
|
|
317
|
+
this.#lastCollision.classList.remove(this.#classDragCollision);
|
|
318
|
+
}
|
|
285
319
|
/**
|
|
286
320
|
* Handles dragging collision.
|
|
287
321
|
* @param {MouseEvent|Touch} event - The drag event.
|
|
288
322
|
*/
|
|
289
323
|
checkDragCollision(event) {
|
|
290
|
-
const {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
this.#lastCollision = collided;
|
|
296
|
-
if (this.#lastCollision)
|
|
297
|
-
this.#lastCollision.classList.add(this.#classDragCollision);
|
|
324
|
+
const { collidedElements } = this.execCollision(event);
|
|
325
|
+
const first = collidedElements[0] || null;
|
|
326
|
+
// Removes old marking if necessary
|
|
327
|
+
if (this.#lastCollision && !collidedElements.includes(this.#lastCollision)) {
|
|
328
|
+
this.#removeCollision();
|
|
298
329
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
330
|
+
// Adds Marking for All Colluded
|
|
331
|
+
collidedElements.forEach((el) => this.#addCollision(el));
|
|
332
|
+
// Removes markings from who no longer collided
|
|
333
|
+
this.#collidables.forEach((el) => {
|
|
334
|
+
if (!collidedElements.includes(el)) {
|
|
335
|
+
el.classList.remove(this.#classDragCollision);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
if (navigator.vibrate &&
|
|
339
|
+
Array.isArray(this.#vibration.collide) &&
|
|
340
|
+
collidedElements.length > 0) {
|
|
341
|
+
navigator.vibrate(this.#vibration.collide);
|
|
303
342
|
}
|
|
343
|
+
this.#lastCollision = first;
|
|
304
344
|
}
|
|
305
345
|
/**
|
|
306
346
|
* Handles dragging movement.
|
|
@@ -338,12 +378,12 @@ class TinyDragger {
|
|
|
338
378
|
/**
|
|
339
379
|
* Handles the collision of a drag.
|
|
340
380
|
* @param {MouseEvent|Touch} event - The release event.
|
|
341
|
-
* @returns {{ inJail: boolean;
|
|
381
|
+
* @returns {{ inJail: boolean; collidedElements: (HTMLElement | null)[] }}
|
|
342
382
|
*/
|
|
343
383
|
execCollision(event) {
|
|
344
384
|
if (this.#destroyed || !this.#dragProxy)
|
|
345
|
-
return { inJail: false,
|
|
346
|
-
let
|
|
385
|
+
return { inJail: false, collidedElements: [] };
|
|
386
|
+
let collidedElements = [];
|
|
347
387
|
let inJail = true;
|
|
348
388
|
const jailRect = this.#jail?.getBoundingClientRect();
|
|
349
389
|
if (this.#collisionByMouse) {
|
|
@@ -353,20 +393,28 @@ class TinyDragger {
|
|
|
353
393
|
inJail =
|
|
354
394
|
x >= jailRect.left && x <= jailRect.right && y >= jailRect.top && y <= jailRect.bottom;
|
|
355
395
|
}
|
|
356
|
-
|
|
396
|
+
collidedElements = inJail
|
|
397
|
+
? this.#multiCollision
|
|
398
|
+
? this.getAllCollidedElements(x, y)
|
|
399
|
+
: [this.getCollidedElement(x, y)].filter(Boolean)
|
|
400
|
+
: [];
|
|
357
401
|
}
|
|
358
402
|
else {
|
|
359
|
-
const
|
|
403
|
+
const rect = this.#dragProxy.getBoundingClientRect();
|
|
360
404
|
if (this.#dropInJailOnly && this.#jail && jailRect) {
|
|
361
405
|
inJail =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
406
|
+
rect.left >= jailRect.left &&
|
|
407
|
+
rect.right <= jailRect.right &&
|
|
408
|
+
rect.top >= jailRect.top &&
|
|
409
|
+
rect.bottom <= jailRect.bottom;
|
|
366
410
|
}
|
|
367
|
-
|
|
411
|
+
collidedElements = inJail
|
|
412
|
+
? this.#multiCollision
|
|
413
|
+
? this.getAllCollidedElementsByRect(rect)
|
|
414
|
+
: [this.getCollidedElementByRect(rect)].filter(Boolean)
|
|
415
|
+
: [];
|
|
368
416
|
}
|
|
369
|
-
return { inJail,
|
|
417
|
+
return { inJail, collidedElements };
|
|
370
418
|
}
|
|
371
419
|
/**
|
|
372
420
|
* Handles the end of a drag.
|
|
@@ -388,7 +436,7 @@ class TinyDragger {
|
|
|
388
436
|
document.removeEventListener('mouseup', this._onMouseUp);
|
|
389
437
|
document.removeEventListener('touchmove', this._onTouchMove);
|
|
390
438
|
document.removeEventListener('touchend', this._onTouchEnd);
|
|
391
|
-
const {
|
|
439
|
+
const { collidedElements } = this.execCollision(event);
|
|
392
440
|
if (navigator.vibrate && Array.isArray(this.#vibration.end)) {
|
|
393
441
|
navigator.vibrate(this.#vibration.end);
|
|
394
442
|
}
|
|
@@ -399,7 +447,7 @@ class TinyDragger {
|
|
|
399
447
|
this.#dragProxy = null;
|
|
400
448
|
}
|
|
401
449
|
if (this.#lastCollision)
|
|
402
|
-
this.#
|
|
450
|
+
this.#removeCollision();
|
|
403
451
|
this.#lastCollision = null;
|
|
404
452
|
this.#target.classList.remove(this.#dragHiddenClass);
|
|
405
453
|
if (!this.#revertOnDrop) {
|
|
@@ -408,11 +456,43 @@ class TinyDragger {
|
|
|
408
456
|
}
|
|
409
457
|
const dropEvent = new CustomEvent('drop', {
|
|
410
458
|
detail: {
|
|
411
|
-
|
|
459
|
+
targets: collidedElements,
|
|
460
|
+
first: collidedElements[0] || null,
|
|
412
461
|
},
|
|
413
462
|
});
|
|
414
463
|
this.#target.dispatchEvent(dropEvent);
|
|
415
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Checks if the provided element intersects with the given bounding rectangle.
|
|
467
|
+
*
|
|
468
|
+
* @param {HTMLElement} el - The element to test for collision.
|
|
469
|
+
* @param {DOMRect} rect - The bounding rectangle to check against.
|
|
470
|
+
* @returns {boolean} True if the element intersects with the rectangle.
|
|
471
|
+
*/
|
|
472
|
+
#getCollidedElementByRect(el, rect) {
|
|
473
|
+
const elRect = el.getBoundingClientRect();
|
|
474
|
+
return !(rect.right < elRect.left ||
|
|
475
|
+
rect.left > elRect.right ||
|
|
476
|
+
rect.bottom < elRect.top ||
|
|
477
|
+
rect.top > elRect.bottom);
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Returns all elements currently colliding with the given rectangle.
|
|
481
|
+
*
|
|
482
|
+
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
483
|
+
* @returns {HTMLElement[]} A list of all collided elements.
|
|
484
|
+
* @throws {Error} If the input is not a valid DOMRect with numeric bounds.
|
|
485
|
+
*/
|
|
486
|
+
getAllCollidedElementsByRect(rect) {
|
|
487
|
+
this.#checkDestroy();
|
|
488
|
+
if (!(rect instanceof DOMRect) ||
|
|
489
|
+
typeof rect.left !== 'number' ||
|
|
490
|
+
typeof rect.right !== 'number' ||
|
|
491
|
+
typeof rect.top !== 'number' ||
|
|
492
|
+
typeof rect.bottom !== 'number')
|
|
493
|
+
throw new Error('getCollidedElementByRect expects a valid DOMRect object.');
|
|
494
|
+
return this.#collidables.filter((el) => this.#getCollidedElementByRect(el, rect));
|
|
495
|
+
}
|
|
416
496
|
/**
|
|
417
497
|
* Detects collision based on rectangle intersection.
|
|
418
498
|
* @param {DOMRect} rect - Bounding rectangle of the dragged proxy.
|
|
@@ -427,13 +507,30 @@ class TinyDragger {
|
|
|
427
507
|
typeof rect.top !== 'number' ||
|
|
428
508
|
typeof rect.bottom !== 'number')
|
|
429
509
|
throw new Error('getCollidedElementByRect expects a valid DOMRect object.');
|
|
430
|
-
return
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
510
|
+
return this.#collidables.find((el) => this.#getCollidedElementByRect(el, rect)) || null;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Checks whether a given (x, y) coordinate is inside the bounding rectangle of an element.
|
|
514
|
+
*
|
|
515
|
+
* @param {HTMLElement} el - The element to test for collision.
|
|
516
|
+
* @param {number} x - Horizontal screen coordinate.
|
|
517
|
+
* @param {number} y - Vertical screen coordinate.
|
|
518
|
+
* @returns {boolean} True if the point is within the element's bounds.
|
|
519
|
+
*/
|
|
520
|
+
#getCollidedElement(el, x, y) {
|
|
521
|
+
const rect = el.getBoundingClientRect();
|
|
522
|
+
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* @param {number} x - Horizontal screen coordinate.
|
|
526
|
+
* @param {number} y - Vertical screen coordinate.
|
|
527
|
+
* @returns {HTMLElement[]} The collided element or null.
|
|
528
|
+
*/
|
|
529
|
+
getAllCollidedElements(x, y) {
|
|
530
|
+
this.#checkDestroy();
|
|
531
|
+
if (typeof x !== 'number' || typeof y !== 'number')
|
|
532
|
+
throw new Error('getCollidedElement expects numeric x and y coordinates.');
|
|
533
|
+
return this.#collidables.filter((el) => this.#getCollidedElement(el, x, y));
|
|
437
534
|
}
|
|
438
535
|
/**
|
|
439
536
|
* Detects collision with a point using element bounding rectangles.
|
|
@@ -445,10 +542,7 @@ class TinyDragger {
|
|
|
445
542
|
this.#checkDestroy();
|
|
446
543
|
if (typeof x !== 'number' || typeof y !== 'number')
|
|
447
544
|
throw new Error('getCollidedElement expects numeric x and y coordinates.');
|
|
448
|
-
return
|
|
449
|
-
const rect = el.getBoundingClientRect();
|
|
450
|
-
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
451
|
-
}) || null);
|
|
545
|
+
return this.#collidables.find((el) => this.#getCollidedElement(el, x, y)) || null;
|
|
452
546
|
}
|
|
453
547
|
/**
|
|
454
548
|
* Dispatches a custom event from the target element.
|
|
@@ -671,7 +765,7 @@ class TinyDragger {
|
|
|
671
765
|
document.removeEventListener('touchmove', this._onTouchMove);
|
|
672
766
|
document.removeEventListener('touchend', this._onTouchEnd);
|
|
673
767
|
if (this.#lastCollision)
|
|
674
|
-
this.#
|
|
768
|
+
this.#removeCollision();
|
|
675
769
|
if (this.#dragProxy) {
|
|
676
770
|
this.#dragProxy.remove();
|
|
677
771
|
this.#dragProxy = null;
|
package/docs/v1/README.md
CHANGED
|
@@ -20,7 +20,6 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
20
20
|
- 🔄 **[asyncReplace](./basics/asyncReplace.md)** — Asynchronously replaces matches in a string using a regex and an async function.
|
|
21
21
|
- 🖼️ **[html](./basics/html.md)** — Utilities for handling DOM element interactions like collision detection and basic element manipulation.
|
|
22
22
|
- 📺 **[fullScreen](./basics/fullScreen.md)** — A complete fullscreen API manager with detection, event handling, and cross-browser compatibility.
|
|
23
|
-
* 📁 **[fileManager](./basics/fileManager.mjs.md)** — A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
|
|
24
23
|
|
|
25
24
|
### 2. **`libs/`**
|
|
26
25
|
- 🗂️ **[TinyPromiseQueue](./libs/TinyPromiseQueue.md)** — A class that allows sequential execution of asynchronous tasks, supporting task delays, cancellation, and queue management.
|
|
@@ -33,6 +32,9 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
33
32
|
* 📂 **[TinyUploadClicker](./libs/TinyUploadClicker.md)** — A minimal utility to bind any clickable element to a hidden file input, offering full control over styling, behavior, and upload event hooks.
|
|
34
33
|
* 🧲 **[TinyDragger](./libs/TinyDragger.md)** — A flexible drag-and-drop manager with collision detection, jail constraints, vibration feedback, visual proxies, revert-on-drop, and full custom event support.
|
|
35
34
|
|
|
35
|
+
### 3. **`fileManager/`**
|
|
36
|
+
* 📁 **[main](./fileManager/main.md)** — A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
|
|
37
|
+
|
|
36
38
|
---
|
|
37
39
|
|
|
38
40
|
## 🚀 Usage
|