tiny-essentials 1.13.2 โ†’ 1.15.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.
Files changed (36) hide show
  1. package/dist/v1/TinyBasicsEs.js +656 -26
  2. package/dist/v1/TinyBasicsEs.min.js +1 -1
  3. package/dist/v1/TinyDragger.js +196 -26
  4. package/dist/v1/TinyEssentials.js +896 -26
  5. package/dist/v1/TinyEssentials.min.js +1 -1
  6. package/dist/v1/TinyNotifications.js +408 -0
  7. package/dist/v1/TinyNotifications.min.js +1 -0
  8. package/dist/v1/TinyUploadClicker.js +198 -26
  9. package/dist/v1/basics/collision.cjs +413 -0
  10. package/dist/v1/basics/collision.d.mts +187 -0
  11. package/dist/v1/basics/collision.mjs +350 -0
  12. package/dist/v1/basics/html.cjs +201 -26
  13. package/dist/v1/basics/html.d.mts +71 -7
  14. package/dist/v1/basics/html.mjs +186 -23
  15. package/dist/v1/basics/index.cjs +24 -0
  16. package/dist/v1/basics/index.d.mts +24 -1
  17. package/dist/v1/basics/index.mjs +4 -3
  18. package/dist/v1/basics/text.cjs +43 -0
  19. package/dist/v1/basics/text.d.mts +16 -0
  20. package/dist/v1/basics/text.mjs +37 -0
  21. package/dist/v1/build/TinyNotifications.cjs +7 -0
  22. package/dist/v1/build/TinyNotifications.d.mts +3 -0
  23. package/dist/v1/build/TinyNotifications.mjs +2 -0
  24. package/dist/v1/index.cjs +26 -0
  25. package/dist/v1/index.d.mts +25 -1
  26. package/dist/v1/index.mjs +5 -3
  27. package/dist/v1/libs/TinyNotifications.cjs +238 -0
  28. package/dist/v1/libs/TinyNotifications.d.mts +106 -0
  29. package/dist/v1/libs/TinyNotifications.mjs +211 -0
  30. package/docs/v1/README.md +5 -3
  31. package/docs/v1/basics/array.md +16 -43
  32. package/docs/v1/basics/collision.md +237 -0
  33. package/docs/v1/basics/html.md +117 -28
  34. package/docs/v1/basics/text.md +44 -14
  35. package/docs/v1/libs/TinyNotifications.md +189 -0
  36. package/package.json +5 -2
@@ -0,0 +1,211 @@
1
+ import { safeTextTrim } from '../basics/text.mjs';
2
+ /**
3
+ * A utility class to manage browser notifications with sound and custom behavior.
4
+ * Useful for triggering system notifications with optional sound, avatar icon, body truncation, and click actions.
5
+ *
6
+ * @class
7
+ */
8
+ class TinyNotifications {
9
+ /** @type {boolean} Whether notifications are currently allowed by the user. */
10
+ #allowed = false;
11
+ /** @type {boolean} Indicates whether the user has already requested permission at least once. */
12
+ #permissionRequested = false;
13
+ /** @type {HTMLAudioElement|null} Audio element to play when a notification is triggered. */
14
+ #audio = null;
15
+ /** @type {number} Maximum number of characters in the notification body. */
16
+ #bodyLimit = 100;
17
+ /** @type {string|null} Default avatar icon URL for notifications. */
18
+ #defaultIcon = null;
19
+ /** @type {(this: Notification, evt: Event) => any} Default handler when a notification is clicked. */
20
+ #defaultOnClick;
21
+ /**
22
+ * Constructs a new instance of TinyNotifications.
23
+ *
24
+ * @param {Object} [settings={}] - Optional settings to initialize the notification manager.
25
+ * @param {string|HTMLAudioElement|null} [settings.audio] - Path or URL to the audio file for notification sounds.
26
+ * @param {string|null} [settings.defaultIcon] - Default icon URL to be used in notifications.
27
+ * @param {number} [settings.bodyLimit=100] - Maximum number of characters allowed in the notification body.
28
+ * @param {(this: Notification, evt: Event) => any} [settings.defaultOnClick] - Default function to execute when a notification is clicked.
29
+ * @throws {TypeError} If any of the parameters are of an invalid type.
30
+ */
31
+ constructor({ audio = null, defaultIcon = null, bodyLimit = 100, defaultOnClick = function (event) {
32
+ event.preventDefault();
33
+ if (window.focus)
34
+ window.focus();
35
+ this.close();
36
+ }, } = {}) {
37
+ if (!(audio instanceof HTMLAudioElement) && typeof audio !== 'string' && audio !== null)
38
+ throw new TypeError('audio must be an instance of HTMLAudioElement or null.');
39
+ if (defaultIcon !== null && typeof defaultIcon !== 'string')
40
+ throw new TypeError('defaultIcon must be a string or null.');
41
+ if (!Number.isFinite(bodyLimit) || bodyLimit < 0)
42
+ throw new TypeError('bodyLimit must be a non-negative number.');
43
+ if (typeof defaultOnClick !== 'function')
44
+ throw new TypeError('defaultOnClick must be a function.');
45
+ this.#audio = typeof audio !== 'string' ? audio : new Audio(audio);
46
+ this.#defaultIcon = defaultIcon;
47
+ this.#bodyLimit = bodyLimit;
48
+ this.#defaultOnClick = defaultOnClick;
49
+ }
50
+ /**
51
+ * Requests permission from the user to show notifications.
52
+ * Updates the internal `#allowed` flag.
53
+ *
54
+ * @returns {Promise<boolean>} Resolves to `true` if permission is granted, otherwise `false`.
55
+ */
56
+ requestPerm() {
57
+ const tinyThis = this;
58
+ return new Promise((resolve, reject) => {
59
+ if (tinyThis.isCompatible()) {
60
+ if (Notification.permission === 'default') {
61
+ Notification.requestPermission()
62
+ .then((permission) => {
63
+ this.#permissionRequested = true;
64
+ tinyThis.#allowed = permission === 'granted';
65
+ resolve(tinyThis.#allowed);
66
+ })
67
+ .catch(reject);
68
+ }
69
+ else {
70
+ this.#permissionRequested = true;
71
+ tinyThis.#allowed = Notification.permission === 'granted';
72
+ resolve(tinyThis.#allowed);
73
+ }
74
+ }
75
+ else {
76
+ this.#permissionRequested = true;
77
+ tinyThis.#allowed = false;
78
+ resolve(false);
79
+ }
80
+ });
81
+ }
82
+ /**
83
+ * Checks if the Notification API is supported by the current browser.
84
+ *
85
+ * @returns {boolean} Returns `true` if notifications are supported, otherwise `false`.
86
+ */
87
+ isCompatible() {
88
+ return 'Notification' in window;
89
+ }
90
+ /**
91
+ * Sends a browser notification with the provided title and configuration.
92
+ * Truncates the body if necessary and plays a sound if configured.
93
+ *
94
+ * @param {string} title - The title of the notification.
95
+ * @param {NotificationOptions & { vibrate?: number[] }} [config={}] - Optional configuration for the notification.
96
+ * @returns {Notification|null} The created `Notification` instance, or `null` if permission is not granted.
97
+ * @throws {TypeError} If the title is not a string or config is not a valid object.
98
+ */
99
+ send(title, config = {}) {
100
+ if (!this.#permissionRequested)
101
+ throw new Error('You must call requestPerm() before sending a notification.');
102
+ if (typeof title !== 'string')
103
+ throw new TypeError('title must be a string.');
104
+ if (typeof config !== 'object' || config === null)
105
+ throw new TypeError('config must be a non-null object.');
106
+ if (!this.#allowed)
107
+ return null;
108
+ const { icon = this.#defaultIcon || undefined, vibrate = [200, 100, 200] } = config;
109
+ const options = { ...config };
110
+ if (typeof icon === 'string')
111
+ options.icon = icon;
112
+ if (Array.isArray(vibrate))
113
+ options.vibrate = vibrate;
114
+ if (typeof options.body === 'string')
115
+ options.body = safeTextTrim(options.body, this.#bodyLimit);
116
+ const notification = new Notification(title, options);
117
+ notification.addEventListener('show', () => {
118
+ if (!(this.#audio instanceof HTMLAudioElement))
119
+ return;
120
+ this.#audio.currentTime = 0;
121
+ this.#audio.play().catch((err) => console.error(err));
122
+ });
123
+ if (typeof this.#defaultOnClick === 'function')
124
+ notification.addEventListener('click', this.#defaultOnClick);
125
+ return notification;
126
+ }
127
+ // === Getters and Setters ===
128
+ /**
129
+ * Whether the requestPerm() method was already called.
130
+ * @returns {boolean}
131
+ */
132
+ wasPermissionRequested() {
133
+ return this.#permissionRequested;
134
+ }
135
+ /**
136
+ * Returns the current permission status.
137
+ * @returns {boolean} `true` if permission was granted, otherwise `false`.
138
+ */
139
+ isAllowed() {
140
+ return this.#allowed;
141
+ }
142
+ /**
143
+ * Gets the current notification audio.
144
+ * @returns {HTMLAudioElement|null} The sound element, or `null` if not set.
145
+ */
146
+ getAudio() {
147
+ return this.#audio;
148
+ }
149
+ /**
150
+ * Sets the audio element used for notification sounds.
151
+ * @param {HTMLAudioElement|string|null} value - A valid `HTMLAudioElement` or `null` to disable sound.
152
+ * @throws {TypeError} If the value is not an `HTMLAudioElement` or `null`.
153
+ */
154
+ setAudio(value) {
155
+ if (!(value instanceof HTMLAudioElement) && typeof value !== 'string' && value !== null)
156
+ throw new TypeError('sound must be an instance of HTMLAudioElement or null.');
157
+ this.#audio = typeof value !== 'string' ? value : new Audio(value);
158
+ }
159
+ /**
160
+ * Gets the maximum length of the notification body text.
161
+ * @returns {number} Number of characters allowed.
162
+ */
163
+ getBodyLimit() {
164
+ return this.#bodyLimit;
165
+ }
166
+ /**
167
+ * Sets the maximum number of characters allowed in the notification body.
168
+ * @param {number} value - A non-negative integer.
169
+ * @throws {TypeError} If the value is not a valid non-negative number.
170
+ */
171
+ setBodyLimit(value) {
172
+ if (!Number.isFinite(value) || value < 0)
173
+ throw new TypeError('bodyLimit must be a non-negative number.');
174
+ this.#bodyLimit = value;
175
+ }
176
+ /**
177
+ * Gets the default avatar icon URL.
178
+ * @returns {string|null} The URL string or `null`.
179
+ */
180
+ getDefaultAvatar() {
181
+ return this.#defaultIcon;
182
+ }
183
+ /**
184
+ * Sets the default avatar icon URL.
185
+ * @param {string|null} value - A string URL or `null` to disable default icon.
186
+ * @throws {TypeError} If the value is not a string or `null`.
187
+ */
188
+ setDefaultAvatar(value) {
189
+ if (!(typeof value === 'string' || value === null))
190
+ throw new TypeError('defaultIcon must be a string or null.');
191
+ this.#defaultIcon = value;
192
+ }
193
+ /**
194
+ * Gets the default click event handler for notifications.
195
+ * @returns {(this: Notification, evt: Event) => any} The current click handler function.
196
+ */
197
+ getDefaultOnClick() {
198
+ return this.#defaultOnClick;
199
+ }
200
+ /**
201
+ * Sets the default click event handler for notifications.
202
+ * @param {(this: Notification, evt: Event) => any} value - A function to handle the notification click event.
203
+ * @throws {TypeError} If the value is not a function.
204
+ */
205
+ setDefaultOnClick(value) {
206
+ if (typeof value !== 'function')
207
+ throw new TypeError('defaultOnClick must be a function.');
208
+ this.#defaultOnClick = value;
209
+ }
210
+ }
211
+ export default TinyNotifications;
package/docs/v1/README.md CHANGED
@@ -20,6 +20,7 @@ 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
+ - ๐Ÿงฑ **[collision](./basics/collision.md)** โ€” Full-featured rectangle collision detection system with directional analysis, depth calculation, and center offset metrics.
23
24
 
24
25
  ### 2. **`libs/`**
25
26
  - ๐Ÿ—‚๏ธ **[TinyPromiseQueue](./libs/TinyPromiseQueue.md)** โ€” A class that allows sequential execution of asynchronous tasks, supporting task delays, cancellation, and queue management.
@@ -29,9 +30,10 @@ This folder contains the core scripts we have worked on so far. Each file is a m
29
30
  - ๐Ÿ”” **[TinyNotifyCenter](./libs/TinyNotifyCenter.md)** โ€” A dynamic notification center class to display, manage, and interact with notifications, supporting avatars, clickable items, HTML/text modes, and clean UI controls.
30
31
  - ๐Ÿž **[TinyToastNotify](./libs/TinyToastNotify.md)** โ€” A lightweight toast notification system supporting positioning, timing customization, avatars, click actions, and fade-out animations.
31
32
  - ๐Ÿ“ฅ **[TinyDragDropDetector](./libs/TinyDragDropDetector.md)** โ€” A lightweight drag-and-drop detector for files, handling the full drag lifecycle (`enter`, `over`, `leave`, `drop`) with CSS hover management and safe event handling on any DOM element or the full page.
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.
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.
34
- * ๐Ÿ•’ **[TinyDomReadyManager](./libs/TinyDomReadyManager.md)** โ€” A readiness manager for DOM and async conditions, supporting prioritized callbacks, custom filters, and event-based or promise-based bootstrapping.
33
+ - ๐Ÿ“‚ **[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
+ - ๐Ÿงฒ **[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
+ - ๐Ÿ•’ **[TinyDomReadyManager](./libs/TinyDomReadyManager.md)** โ€” A readiness manager for DOM and async conditions, supporting prioritized callbacks, custom filters, and event-based or promise-based bootstrapping.
36
+ - ๐Ÿ“ฃ **[TinyNotifications](./libs/TinyNotifications.md)** โ€” A browser notification utility with sound support, permission management, truncation logic, default icons, and enforced validation to ensure safe and predictable usage.
35
37
 
36
38
  ### 3. **`fileManager/`**
37
39
  * ๐Ÿ“ **[main](./fileManager/main.md)** โ€” A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
@@ -1,16 +1,18 @@
1
1
  # ๐Ÿ“ฆ array.mjs
2
2
 
3
- A tiny utility for shuffling arrays using the good old Fisherโ€“Yates algorithm. Simple, efficient, and perfectly random (as far as JavaScript's `Math.random()` allows, anyway).
3
+ A minimal and handy module offering a couple of focused utilities for working with arrays โ€” from shuffling items randomly to generating smart sort functions for object arrays. Ideal for quick scripting or modular use in larger projects.
4
4
 
5
- ## โœจ Features
5
+ ---
6
+
7
+ ## `shuffleArray(items: string[]): string[]`
6
8
 
7
- - ๐Ÿ“š Uses the classic **Fisherโ€“Yates** algorithm
8
- - ๐Ÿ”„ Shuffles arrays **in-place**
9
- - ๐ŸŽฏ Guarantees **uniform distribution** of permutations
10
- - ๐Ÿ” Well-documented and easy to read
11
- - ๐Ÿงช No dependencies โ€” just plug and play
9
+ ๐Ÿ”„ A tiny utility for shuffling arrays using the good old Fisherโ€“Yates algorithm. Simple, efficient, and perfectly random (as far as JavaScript's `Math.random()` allows, anyway).
12
10
 
13
- ## ๐Ÿš€ Usage
11
+ - **items** โ€” An array of strings to shuffle.
12
+ - **Returns** โ€” The same array instance, but now shuffled.
13
+
14
+
15
+ ### ๐Ÿš€ Usage
14
16
 
15
17
  ```js
16
18
  import { shuffleArray } from './array.mjs';
@@ -23,54 +25,29 @@ console.log(fruits); // ['banana', 'cherry', 'apple', 'date'] (order will vary)
23
25
 
24
26
  > Note: The original array is shuffled in place. If you want to preserve the original order, make a copy before shuffling.
25
27
 
26
- ## ๐Ÿง  How It Works
27
-
28
- This function implements the **Fisherโ€“Yates shuffle** (also known as the Knuth shuffle), which runs in linear time and guarantees uniform randomness:
29
-
30
- ```js
31
- while (currentIndex !== 0) {
32
- randomIndex = Math.floor(Math.random() * currentIndex);
33
- currentIndex--;
34
- [items[currentIndex], items[randomIndex]] = [items[randomIndex], items[currentIndex]];
35
- }
36
- ```
37
-
38
28
  You can find the original discussion here:
39
29
  ๐Ÿ”— https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
40
30
 
41
- ## ๐Ÿ“ API
42
-
43
- ### `shuffleArray(items: string[]): string[]`
44
-
45
- - **items** โ€” An array of strings to shuffle.
46
- - **Returns** โ€” The same array instance, but now shuffled.
47
-
48
31
  ---
49
32
 
50
- # ๐Ÿ“ฆ `arraySortPositions`
33
+ ## ๐Ÿ“ฆ `arraySortPositions`
51
34
 
52
35
  ๐Ÿ”ง **Generates a comparator function** to sort an array of objects by a specified key, with optional reverse order.
53
36
 
54
- ---
55
-
56
- ## ๐Ÿ“Œ Function Signature
37
+ ### ๐Ÿ“Œ Function Signature
57
38
 
58
39
  ```js
59
40
  arraySortPositions(item: string, isReverse?: boolean): (a: Object<string|number, *>, b: Object<string|number, *>) => number
60
41
  ```
61
42
 
62
- ---
63
-
64
- ## ๐Ÿง  Parameters
43
+ ### ๐Ÿง  Parameters
65
44
 
66
45
  | Name | Type | Default | Description |
67
46
  | ----------- | --------- | ------- | ---------------------------------------------------------- |
68
47
  | `item` | `string` | โ€” | ๐Ÿ”‘ The key to sort the objects by. |
69
48
  | `isReverse` | `boolean` | `false` | ๐Ÿ”„ If `true`, the sorting will be in **descending** order. |
70
49
 
71
- ---
72
-
73
- ## ๐ŸŽฏ Returns
50
+ ### ๐ŸŽฏ Returns
74
51
 
75
52
  ๐Ÿงฉ A **comparator function** compatible with `Array.prototype.sort()`:
76
53
 
@@ -80,9 +57,7 @@ arraySortPositions(item: string, isReverse?: boolean): (a: Object<string|number,
80
57
 
81
58
  It compares two objects based on the specified `item` key.
82
59
 
83
- ---
84
-
85
- ## ๐Ÿ’ก Examples
60
+ ### ๐Ÿ’ก Examples
86
61
 
87
62
  ```js
88
63
  const arr = [{ pos: 2 }, { pos: 1 }, { pos: 3 }];
@@ -96,9 +71,7 @@ arr.sort(arraySortPositions('pos', true));
96
71
  // ๐Ÿ”ฝ Descending: [{ pos: 3 }, { pos: 2 }, { pos: 1 }]
97
72
  ```
98
73
 
99
- ---
100
-
101
- ## ๐Ÿ› ๏ธ Use Case
74
+ ### ๐Ÿ› ๏ธ Use Case
102
75
 
103
76
  Great for situations where you need to **dynamically sort objects** by one of their keys, such as:
104
77
 
@@ -0,0 +1,237 @@
1
+ # ๐Ÿ“ฆ Collision Detection Module
2
+
3
+ This module provides a complete and flexible system for detecting collisions between rectangles (like DOM elements), extracting direction, depth, and center alignment data.
4
+
5
+ ---
6
+
7
+ ## ๐Ÿ“ Type Definitions
8
+
9
+ ### `Dirs`
10
+
11
+ ```ts
12
+ 'top' | 'bottom' | 'left' | 'right'
13
+ ```
14
+
15
+ ๐Ÿ” A direction relative to a rectangle. Represents one of the four cardinal sides.
16
+
17
+ ---
18
+
19
+ ### `CollDirs`
20
+
21
+ ```ts
22
+ {
23
+ in: Dirs | 'center' | null;
24
+ x: Dirs | null;
25
+ y: Dirs | null;
26
+ }
27
+ ```
28
+
29
+ ๐Ÿšฆ Represents all directional aspects of a collision:
30
+
31
+ * `in`: Dominant entry direction (`null` if no collision, `'center'` if perfectly aligned).
32
+ * `x`: Collision bias on X axis.
33
+ * `y`: Collision bias on Y axis.
34
+
35
+ ---
36
+
37
+ ### `NegCollDirs`
38
+
39
+ ```ts
40
+ {
41
+ x: Dirs | null;
42
+ y: Dirs | null;
43
+ }
44
+ ```
45
+
46
+ โŒ Negative collision flags indicating **gap** instead of overlap.
47
+
48
+ ---
49
+
50
+ ### `CollData`
51
+
52
+ ```ts
53
+ {
54
+ top: number;
55
+ bottom: number;
56
+ left: number;
57
+ right: number;
58
+ }
59
+ ```
60
+
61
+ ๐Ÿ“ Collision depth (in pixels) from each side of `rect2` into `rect1`.
62
+
63
+ * Positive values = overlap
64
+ * Negative values = no collision (gap)
65
+
66
+ ---
67
+
68
+ ### `CollCenter`
69
+
70
+ ```ts
71
+ {
72
+ x: number;
73
+ y: number;
74
+ }
75
+ ```
76
+
77
+ ๐ŸŽฏ Offset from the center of `rect1` to the center of `rect2`.
78
+
79
+ ---
80
+
81
+ ### `ObjRect`
82
+
83
+ ```ts
84
+ {
85
+ height: number;
86
+ width: number;
87
+ top: number;
88
+ bottom: number;
89
+ left: number;
90
+ right: number;
91
+ }
92
+ ```
93
+
94
+ ๐Ÿ“ฆ Generic rectangle object, similar to `DOMRect`.
95
+
96
+ ---
97
+
98
+ ## ๐Ÿ” Collision Checks
99
+
100
+ ### Loose Collision (Partial Overlap Only)
101
+
102
+ | Function | Description |
103
+ | -------------------------------- | --------------------------------------- |
104
+ | `areElsCollTop(rect1, rect2)` | `rect1` is **above** `rect2` |
105
+ | `areElsCollBottom(rect1, rect2)` | `rect1` is **below** `rect2` |
106
+ | `areElsCollLeft(rect1, rect2)` | `rect1` is **left of** `rect2` |
107
+ | `areElsCollRight(rect1, rect2)` | `rect1` is **right of** `rect2` |
108
+ | `areElsColliding(rect1, rect2)` | Returns `true` if **any side overlaps** |
109
+
110
+ ---
111
+
112
+ ### Perfect Collision (Touch or Overlap)
113
+
114
+ | Function | Description |
115
+ | ------------------------------------ | -------------------------------------------------- |
116
+ | `areElsCollPerfTop(rect1, rect2)` | `rect1` is **fully above** or touching `rect2` |
117
+ | `areElsCollPerfBottom(rect1, rect2)` | `rect1` is **fully below** or touching `rect2` |
118
+ | `areElsCollPerfLeft(rect1, rect2)` | `rect1` is **fully left** or touching `rect2` |
119
+ | `areElsCollPerfRight(rect1, rect2)` | `rect1` is **fully right** or touching `rect2` |
120
+ | `areElsPerfColliding(rect1, rect2)` | Returns `true` if there's **any overlap or touch** |
121
+
122
+ ---
123
+
124
+ ### Collision Direction (Single Side Detection)
125
+
126
+ | Function | Returns |
127
+ | ----------------------------------- | -------------------------------------------------- |
128
+ | `getElsColliding(rect1, rect2)` | `'left'`, `'right'`, `'top'`, `'bottom'` or `null` |
129
+ | `getElsPerfColliding(rect1, rect2)` | Same as above, but includes **touch detection** |
130
+
131
+ ---
132
+
133
+ ## ๐Ÿ”ฌ Overlap & Direction
134
+
135
+ ### `getElsCollOverlap(rect1, rect2)`
136
+
137
+ ๐Ÿ“ Returns the depth of overlap between two rectangles:
138
+
139
+ ```js
140
+ {
141
+ overlapLeft,
142
+ overlapRight,
143
+ overlapTop,
144
+ overlapBottom
145
+ }
146
+ ```
147
+
148
+ ---
149
+
150
+ ### `getElsCollOverlapPos({ overlapLeft, overlapRight, overlapTop, overlapBottom })`
151
+
152
+ ๐Ÿ“ Determines which axis and direction has the strongest collision.
153
+
154
+ ```js
155
+ {
156
+ dirX: 'left' | 'right',
157
+ dirY: 'top' | 'bottom'
158
+ }
159
+ ```
160
+
161
+ ---
162
+
163
+ ## ๐ŸŽฏ Center Detection
164
+
165
+ ### `getRectCenter(rect)`
166
+
167
+ Returns the **center X and Y coordinates** of a rectangle.
168
+
169
+ ---
170
+
171
+ ### `getElsRelativeCenterOffset(rect1, rect2)`
172
+
173
+ Returns the distance from `rect1`'s center to `rect2`'s center:
174
+
175
+ ```js
176
+ {
177
+ x: number,
178
+ y: number
179
+ }
180
+ ```
181
+
182
+ โœ… Values are `0` when centers are aligned.
183
+
184
+ ---
185
+
186
+ ## ๐Ÿง  Direction & Depth
187
+
188
+ ### `getElsCollDirDepth(rect1, rect2)`
189
+
190
+ Detects:
191
+
192
+ * Which axis has the dominant collision
193
+ * Overlap depths
194
+
195
+ ```js
196
+ {
197
+ inDir: 'left' | 'right' | 'top' | 'bottom' | null,
198
+ dirX: 'left' | 'right' | null,
199
+ dirY: 'top' | 'bottom' | null,
200
+ depthX: number,
201
+ depthY: number
202
+ }
203
+ ```
204
+
205
+ ---
206
+
207
+ ### `getElsCollDetails(rect1, rect2)`
208
+
209
+ ๐Ÿ” Full analysis of the collision:
210
+
211
+ * Depth of overlap
212
+ * Direction of entry
213
+ * Negative axis gaps
214
+ * Center hit detection
215
+
216
+ ```js
217
+ {
218
+ depth: CollData,
219
+ dirs: CollDirs,
220
+ isNeg: NegCollDirs
221
+ }
222
+ ```
223
+
224
+ ---
225
+
226
+ ## ๐Ÿงช Example Use
227
+
228
+ ```js
229
+ const box = element1.getBoundingClientRect();
230
+ const wall = element2.getBoundingClientRect();
231
+
232
+ const result = getElsCollDetails(box, wall);
233
+
234
+ console.log(result.depth); // { top, bottom, left, right }
235
+ console.log(result.dirs.in); // e.g. 'left'
236
+ console.log(result.isNeg); // e.g. { x: 'left', y: null }
237
+ ```