tiny-essentials 1.10.2 → 1.11.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 (56) hide show
  1. package/README.md +1 -1
  2. package/dist/{TinyEssentials.js → v1/TinyEssentials.js} +804 -0
  3. package/dist/v1/TinyEssentials.min.js +2 -0
  4. package/dist/v1/TinyNotifyCenter.js +461 -0
  5. package/dist/v1/TinyNotifyCenter.min.js +1 -0
  6. package/dist/v1/TinyToastNotify.js +417 -0
  7. package/dist/v1/TinyToastNotify.min.js +1 -0
  8. package/dist/v1/build/TinyNotifyCenter.cjs +7 -0
  9. package/dist/v1/build/TinyNotifyCenter.d.mts +3 -0
  10. package/dist/v1/build/TinyNotifyCenter.mjs +2 -0
  11. package/dist/v1/build/TinyToastNotify.cjs +7 -0
  12. package/dist/v1/build/TinyToastNotify.d.mts +3 -0
  13. package/dist/v1/build/TinyToastNotify.mjs +2 -0
  14. package/dist/v1/css/TinyNotify.css +350 -0
  15. package/dist/v1/css/TinyNotify.min.css +1 -0
  16. package/dist/v1/index.cjs +4 -0
  17. package/dist/v1/index.d.mts +3 -1
  18. package/dist/v1/index.mjs +3 -1
  19. package/dist/v1/libs/TinyNotifyCenter.cjs +422 -0
  20. package/dist/v1/libs/TinyNotifyCenter.d.mts +166 -0
  21. package/dist/v1/libs/TinyNotifyCenter.mjs +385 -0
  22. package/dist/v1/libs/TinyToastNotify.cjs +378 -0
  23. package/dist/v1/libs/TinyToastNotify.d.mts +157 -0
  24. package/dist/v1/libs/TinyToastNotify.mjs +332 -0
  25. package/docs/{README.md → v1/README.md} +2 -0
  26. package/docs/{basics → v1/basics}/text.md +2 -2
  27. package/docs/v1/libs/TinyNotifyCenter.md +291 -0
  28. package/docs/v1/libs/TinyToastNotify.md +290 -0
  29. package/package.json +4 -2
  30. package/dist/TinyEssentials.min.js +0 -2
  31. package/dist/v1/libs/TinyRateLimit.cjs +0 -196
  32. package/dist/v1/libs/TinyRateLimit.d.mts +0 -86
  33. package/dist/v1/libs/TinyRateLimit.mjs +0 -171
  34. /package/dist/{ColorSafeStringify.js → v1/ColorSafeStringify.js} +0 -0
  35. /package/dist/{ColorSafeStringify.min.js → v1/ColorSafeStringify.min.js} +0 -0
  36. /package/dist/{TinyBasicsEs.js → v1/TinyBasicsEs.js} +0 -0
  37. /package/dist/{TinyBasicsEs.min.js → v1/TinyBasicsEs.min.js} +0 -0
  38. /package/dist/{TinyBasicsEs.min.js.LICENSE.txt → v1/TinyBasicsEs.min.js.LICENSE.txt} +0 -0
  39. /package/dist/{TinyEssentials.min.js.LICENSE.txt → v1/TinyEssentials.min.js.LICENSE.txt} +0 -0
  40. /package/dist/{TinyLevelUp.js → v1/TinyLevelUp.js} +0 -0
  41. /package/dist/{TinyLevelUp.min.js → v1/TinyLevelUp.min.js} +0 -0
  42. /package/dist/{TinyPromiseQueue.js → v1/TinyPromiseQueue.js} +0 -0
  43. /package/dist/{TinyPromiseQueue.min.js → v1/TinyPromiseQueue.min.js} +0 -0
  44. /package/dist/{TinyRateLimiter.js → v1/TinyRateLimiter.js} +0 -0
  45. /package/dist/{TinyRateLimiter.min.js → v1/TinyRateLimiter.min.js} +0 -0
  46. /package/dist/{aiMarker.css → v1/css/aiMarker.css} +0 -0
  47. /package/dist/{aiMarker.min.css → v1/css/aiMarker.min.css} +0 -0
  48. /package/docs/{basics → v1/basics}/array.md +0 -0
  49. /package/docs/{basics → v1/basics}/asyncReplace.md +0 -0
  50. /package/docs/{basics → v1/basics}/clock.md +0 -0
  51. /package/docs/{basics → v1/basics}/objFilter.md +0 -0
  52. /package/docs/{basics → v1/basics}/simpleMath.md +0 -0
  53. /package/docs/{libs → v1/libs}/ColorSafeStringify.md +0 -0
  54. /package/docs/{libs → v1/libs}/TinyLevelUp.md +0 -0
  55. /package/docs/{libs → v1/libs}/TinyPromiseQueue.md +0 -0
  56. /package/docs/{libs → v1/libs}/TinyRateLimiter.md +0 -0
@@ -0,0 +1,332 @@
1
+ /**
2
+ * A callback function used to manually close a notification.
3
+ * Passed as a second argument to `onClick` handlers, allowing programmatic dismissal of the toast.
4
+ *
5
+ * @typedef {() => void} CloseToastFunc
6
+ */
7
+ /**
8
+ * Represents the data used to display a notification.
9
+ * Can be a plain string (used as the message), or an object with more customization options.
10
+ *
11
+ * @typedef {string | {
12
+ * message: string, // The main message to display
13
+ * title?: string, // Optional title to appear above the message
14
+ * onClick?: function(MouseEvent, CloseToastFunc): void, // Optional click handler for the notification
15
+ * html?: boolean, // Whether the message should be interpreted as raw HTML
16
+ * avatar?: string // Optional URL to an avatar image shown on the left
17
+ * }} NotifyData
18
+ */
19
+ /**
20
+ * A lightweight notification system designed to display timed messages inside a container.
21
+ * Supports positioning, timing customization, click actions, HTML content, and optional avatars.
22
+ *
23
+ * ## Features:
24
+ * - Positioning via `x` (`left`, `center`, `right`) and `y` (`top`, `bottom`).
25
+ * - Dynamic display time based on message length.
26
+ * - Optional `title`, `avatar`, `onClick`, and `html` message rendering.
27
+ * - Fade-out animation with customizable duration.
28
+ * - Rigid validation of inputs and internal state.
29
+ *
30
+ * ## Customization via setters:
31
+ * - `setX(position)` — horizontal alignment.
32
+ * - `setY(position)` — vertical alignment.
33
+ * - `setBaseDuration(ms)` — base visible time in milliseconds.
34
+ * - `setExtraPerChar(ms)` — extra time added per character.
35
+ * - `setFadeOutDuration(ms)` — fade-out animation duration in milliseconds.
36
+ *
37
+ * @class
38
+ */
39
+ class TinyToastNotify {
40
+ #y;
41
+ #x;
42
+ #baseDuration;
43
+ #extraPerChar;
44
+ #fadeOutDuration;
45
+ #container;
46
+ /**
47
+ * @param {'top'|'bottom'} y - 'top' or 'bottom'
48
+ * @param {'right'|'left'|'center'} x - 'right', 'left', or 'center'
49
+ * @param {number} baseDuration - Base display time in ms
50
+ * @param {number} extraPerChar - Extra ms per character
51
+ * @param {number} fadeOutDuration - Time in ms for fade-out effect
52
+ * @param {string} [selector='.notify-container'] - Base selector for container
53
+ */
54
+ constructor(y = 'top', x = 'right', baseDuration = 3000, extraPerChar = 50, fadeOutDuration = 300, selector = '.notify-container') {
55
+ this.#validateY(y);
56
+ this.#validateX(x);
57
+ this.#validateTiming(baseDuration, 'baseDuration');
58
+ this.#validateTiming(extraPerChar, 'extraPerChar');
59
+ this.#validateTiming(fadeOutDuration, 'fadeOutDuration');
60
+ this.#y = y;
61
+ this.#x = x;
62
+ this.#baseDuration = baseDuration;
63
+ this.#extraPerChar = extraPerChar;
64
+ this.#fadeOutDuration = fadeOutDuration;
65
+ const container = document.querySelector(`${selector}.${y}.${x}`);
66
+ if (!(container instanceof HTMLElement)) {
67
+ this.#container = document.createElement('div');
68
+ this.#container.className = `notify-container ${y} ${x}`;
69
+ document.body.appendChild(this.#container);
70
+ }
71
+ else
72
+ this.#container = container;
73
+ }
74
+ /**
75
+ * Returns the notification container element.
76
+ * Ensures that the container is a valid HTMLElement.
77
+ *
78
+ * @returns {HTMLElement} The notification container.
79
+ * @throws {Error} If the container is not a valid HTMLElement.
80
+ */
81
+ getContainer() {
82
+ if (!(this.#container instanceof HTMLElement))
83
+ throw new Error('Container is not a valid HTMLElement.');
84
+ return this.#container;
85
+ }
86
+ /**
87
+ * Validates the vertical position value.
88
+ * Must be either 'top' or 'bottom'.
89
+ *
90
+ * @param {string} value - The vertical position to validate.
91
+ * @throws {Error} If the value is not 'top' or 'bottom'.
92
+ */
93
+ #validateY(value) {
94
+ if (!['top', 'bottom'].includes(value)) {
95
+ throw new Error(`Invalid vertical direction "${value}". Expected "top" or "bottom".`);
96
+ }
97
+ }
98
+ /**
99
+ * Validates the horizontal position value.
100
+ * Must be 'left', 'right', or 'center'.
101
+ *
102
+ * @param {string} value - The horizontal position to validate.
103
+ * @throws {Error} If the value is not one of the accepted directions.
104
+ */
105
+ #validateX(value) {
106
+ if (!['left', 'right', 'center'].includes(value)) {
107
+ throw new Error(`Invalid horizontal position "${value}". Expected "left", "right" or "center".`);
108
+ }
109
+ }
110
+ /**
111
+ * Validates a numeric timing value.
112
+ * Must be a non-negative finite number.
113
+ *
114
+ * @param {number} value - The number to validate.
115
+ * @param {string} name - The name of the parameter (used for error messaging).
116
+ * @throws {Error} If the number is invalid.
117
+ */
118
+ #validateTiming(value, name) {
119
+ if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) {
120
+ throw new Error(`Invalid value for "${name}": ${value}. Must be a non-negative finite number.`);
121
+ }
122
+ }
123
+ /**
124
+ * Returns the current vertical position.
125
+ *
126
+ * @returns {'top'|'bottom'} The vertical direction of the notification container.
127
+ */
128
+ getY() {
129
+ return this.#y;
130
+ }
131
+ /**
132
+ * Sets the vertical position of the notification container.
133
+ * Updates the container's class to reflect the new position.
134
+ *
135
+ * @param {'top'|'bottom'} value - The vertical direction to set.
136
+ * @throws {Error} If the value is invalid.
137
+ */
138
+ setY(value) {
139
+ this.#validateY(value);
140
+ const container = this.getContainer();
141
+ container.classList.remove(this.#y);
142
+ container.classList.add(value);
143
+ this.#y = value;
144
+ }
145
+ /**
146
+ * Returns the current horizontal position.
147
+ *
148
+ * @returns {'left'|'right'|'center'} The horizontal direction of the notification container.
149
+ */
150
+ getX() {
151
+ return this.#x;
152
+ }
153
+ /**
154
+ * Sets the horizontal position of the notification container.
155
+ * Updates the container's class to reflect the new position.
156
+ *
157
+ * @param {'left'|'right'|'center'} value - The horizontal direction to set.
158
+ * @throws {Error} If the value is invalid.
159
+ */
160
+ setX(value) {
161
+ this.#validateX(value);
162
+ const container = this.getContainer();
163
+ container.classList.remove(this.#x);
164
+ container.classList.add(value);
165
+ this.#x = value;
166
+ }
167
+ /**
168
+ * Returns the base duration for displaying the notification.
169
+ *
170
+ * @returns {number} Base time (in milliseconds) that a notification stays on screen.
171
+ */
172
+ getBaseDuration() {
173
+ return this.#baseDuration;
174
+ }
175
+ /**
176
+ * Sets the base duration for the notification display time.
177
+ *
178
+ * @param {number} value - Base display time in milliseconds.
179
+ * @throws {Error} If the value is not a valid non-negative finite number.
180
+ */
181
+ setBaseDuration(value) {
182
+ this.#validateTiming(value, 'baseDuration');
183
+ this.#baseDuration = value;
184
+ }
185
+ /**
186
+ * Returns the extra display time added per character.
187
+ *
188
+ * @returns {number} Extra time (in milliseconds) per character in the notification.
189
+ */
190
+ getExtraPerChar() {
191
+ return this.#extraPerChar;
192
+ }
193
+ /**
194
+ * Sets the additional display time per character.
195
+ *
196
+ * @param {number} value - Extra time in milliseconds per character.
197
+ * @throws {Error} If the value is not a valid non-negative finite number.
198
+ */
199
+ setExtraPerChar(value) {
200
+ this.#validateTiming(value, 'extraPerChar');
201
+ this.#extraPerChar = value;
202
+ }
203
+ /**
204
+ * Returns the fade-out duration.
205
+ *
206
+ * @returns {number} Time (in milliseconds) used for fade-out transition.
207
+ */
208
+ getFadeOutDuration() {
209
+ return this.#fadeOutDuration;
210
+ }
211
+ /**
212
+ * Sets the fade-out transition time for notifications.
213
+ *
214
+ * @param {number} value - Fade-out duration in milliseconds.
215
+ * @throws {Error} If the value is not a valid non-negative finite number.
216
+ */
217
+ setFadeOutDuration(value) {
218
+ this.#validateTiming(value, 'fadeOutDuration');
219
+ this.#fadeOutDuration = value;
220
+ }
221
+ /**
222
+ * Displays a notification for a time based on message length.
223
+ * Accepts a string or an object with:
224
+ * {
225
+ * message: string,
226
+ * title?: string,
227
+ * onClick?: function(MouseEvent, CloseToastFunc): void,
228
+ * html?: boolean,
229
+ * avatar?: string // Optional avatar image URL
230
+ * }
231
+ *
232
+ * @param {NotifyData} data
233
+ */
234
+ show(data) {
235
+ let message = '';
236
+ let title = '';
237
+ let onClick = null;
238
+ let useHTML = false;
239
+ let avatarUrl = null;
240
+ const notify = document.createElement('div');
241
+ notify.className = 'notify enter';
242
+ if (typeof data === 'string') {
243
+ message = data;
244
+ }
245
+ else if (typeof data === 'object' && data !== null && typeof data.message === 'string') {
246
+ message = data.message;
247
+ title = typeof data.title === 'string' ? data.title : '';
248
+ useHTML = data.html === true;
249
+ avatarUrl = typeof data.avatar === 'string' ? data.avatar : null;
250
+ if (data.onClick !== undefined) {
251
+ if (typeof data.onClick !== 'function') {
252
+ throw new Error('onClick must be a function if defined');
253
+ }
254
+ onClick = data.onClick;
255
+ notify.classList.add('clickable');
256
+ }
257
+ }
258
+ else {
259
+ throw new Error(`Invalid argument for show(): expected string or { message: string, title?: string, onClick?: function, html?: boolean, avatar?: string }`);
260
+ }
261
+ // Add close button
262
+ const closeBtn = document.createElement('button');
263
+ closeBtn.innerHTML = '&times;';
264
+ closeBtn.className = 'close';
265
+ closeBtn.setAttribute('aria-label', 'Close');
266
+ // Optional hover effect
267
+ closeBtn.addEventListener('mouseenter', () => {
268
+ closeBtn.style.color = 'var(--notif-close-color-hover)';
269
+ });
270
+ closeBtn.addEventListener('mouseleave', () => {
271
+ closeBtn.style.color = 'var(--notif-close-color)';
272
+ });
273
+ // Avatar
274
+ if (avatarUrl) {
275
+ const avatar = document.createElement('img');
276
+ avatar.src = avatarUrl;
277
+ avatar.alt = 'avatar';
278
+ avatar.className = 'avatar';
279
+ notify.appendChild(avatar);
280
+ }
281
+ // Title
282
+ if (title) {
283
+ const titleElem = document.createElement('strong');
284
+ titleElem.textContent = title;
285
+ titleElem.style.display = 'block';
286
+ notify.appendChild(titleElem);
287
+ }
288
+ // Message
289
+ if (useHTML) {
290
+ const msgWrapper = document.createElement('div');
291
+ msgWrapper.innerHTML = message;
292
+ notify.appendChild(msgWrapper);
293
+ }
294
+ else {
295
+ notify.appendChild(document.createTextNode(message));
296
+ }
297
+ notify.appendChild(closeBtn);
298
+ this.getContainer().appendChild(notify);
299
+ const visibleTime = this.#baseDuration + message.length * this.#extraPerChar;
300
+ const totalTime = visibleTime + this.#fadeOutDuration;
301
+ // Close logic
302
+ let removed = false;
303
+ const close = () => {
304
+ if (removed)
305
+ return;
306
+ removed = true;
307
+ notify.classList.remove('enter', 'show');
308
+ notify.classList.add('exit');
309
+ setTimeout(() => notify.remove(), this.#fadeOutDuration);
310
+ };
311
+ // Click handler
312
+ if (typeof onClick === 'function') {
313
+ notify.addEventListener('click', (e) => {
314
+ if (e.target === closeBtn)
315
+ return;
316
+ onClick(e, close);
317
+ });
318
+ }
319
+ // Close button click
320
+ closeBtn.addEventListener('click', (e) => {
321
+ e.stopPropagation();
322
+ close();
323
+ });
324
+ // Transition activation force soon after the element is added
325
+ setTimeout(() => {
326
+ notify.classList.remove('enter');
327
+ notify.classList.add('show');
328
+ }, 1);
329
+ setTimeout(() => close(), totalTime);
330
+ }
331
+ }
332
+ export default TinyToastNotify;
@@ -24,6 +24,8 @@ This folder contains the core scripts we have worked on so far. Each file is a m
24
24
  - 🏅 **[TinyLevelUp](./libs/TinyLevelUp.md)** — A class to manage user level-up logic based on experience points, providing methods for experience validation, addition, removal, and calculation.
25
25
  - 🎨 **[ColorSafeStringify](./libs/ColorSafeStringify.md)** — A utility for applying customizable ANSI colors to JSON strings in terminal outputs, supporting presets and fine-grained type-based highlighting.
26
26
  - 🚦 **[TinyRateLimiter](./libs/TinyRateLimiter.md)** — A flexible per-user rate limiter supporting time windows, hit caps, and automatic cleanup of inactive users.
27
+ * 🔔 **[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.
28
+ * 🍞 **[TinyToastNotify](./libs/TinyToastNotify.md)** — A lightweight toast notification system supporting positioning, timing customization, avatars, click actions, and fade-out animations.
27
29
 
28
30
  ---
29
31
 
@@ -123,7 +123,7 @@ document.addEventListener('DOMContentLoaded', () => {
123
123
 
124
124
  You can use a pre-built CSS template for the `detect-made-by-ai` class, available in the following files:
125
125
 
126
- * `/dist/aiMarker.min.css` – A minified version of the CSS for production use.
127
- * `/dist/aiMarker.css` – The non-minified version for easier readability and customization.
126
+ * `/dist/v1/css/aiMarker.min.css` – A minified version of the CSS for production use.
127
+ * `/dist/v1/css/aiMarker.css` – The non-minified version for easier readability and customization.
128
128
 
129
129
  Simply include the appropriate file in your project to style the elements marked with the `detect-made-by-ai` class.
@@ -0,0 +1,291 @@
1
+ # 🛎️ TinyNotifyCenter
2
+
3
+ ## Overview
4
+
5
+ `TinyNotifyCenter` is a notification center component designed to display interactive alerts in the UI.
6
+
7
+ This class renders a notification overlay on the page, allowing dynamic management of notification items — adding, clearing, and interacting with them in real time.
8
+
9
+ ---
10
+
11
+ ## 🔔 NotifyData Type
12
+
13
+ A notification entry (`NotifyData`) can be either a simple string or an object with extra data:
14
+
15
+ ```ts
16
+ type NotifyData = string | {
17
+ title?: string; // Optional title shown above the message
18
+ message: string; // Required message content (plain text or HTML)
19
+ avatar?: string; // Optional avatar image URL (displayed on the left)
20
+ onClick?: (e: MouseEvent) => void; // Optional click handler for the entire notification
21
+ }
22
+ ```
23
+
24
+ ---
25
+
26
+ ## ✨ Features
27
+
28
+ * Dynamic rendering of notification UI via the `insertTemplate()` method
29
+ * Supports both plain text and HTML content in notifications
30
+ * Optional avatars shown alongside notifications
31
+ * Supports callback functions on notification click events
32
+ * Each notification includes a close button for dismissal
33
+ * Displays a badge with the count of active notifications
34
+
35
+ ---
36
+
37
+ ## 🏗️ Static Methods
38
+
39
+ ### `static getTemplate() : string`
40
+
41
+ Returns the full HTML structure for the notification system as a **string**.
42
+
43
+ This template includes:
44
+
45
+ - A hidden `.notify-overlay` element containing the central notification panel (`#notifCenter`):
46
+ - Header with a **"Notifications"** label
47
+ - A **clear all** button (with checkmark icon)
48
+ - A **close** button (×)
49
+ - A `.list` container to hold dynamically added notification items
50
+ - A bell button (`.notify-bell`) to toggle the notification center, featuring:
51
+ - A bell SVG icon
52
+ - A badge (`#notifBadge`) displaying the number of active notifications
53
+
54
+ > 💡 This HTML can be injected into the DOM using methods like `insertAdjacentHTML()` or parsed into elements with JavaScript or jQuery.
55
+
56
+ ---
57
+
58
+ ### `static insertTemplate(where = 'afterbegin') : void`
59
+
60
+ Injects the full notification center HTML template into the `document.body`.
61
+
62
+ - Uses `insertAdjacentHTML()` to insert the markup.
63
+ - The `where` parameter controls the insertion point relative to the `<body>` element.
64
+
65
+ Possible values for `where`:
66
+
67
+ | Value | Description |
68
+ |---------------|------------------------------------------|
69
+ | `'afterbegin'` (default) | Insert right after the opening `<body>` tag |
70
+ | `'beforeend'` | Insert right before the closing `</body>` tag |
71
+ | `'beforebegin'` or `'afterend'` | Other valid positions supported by `insertAdjacentHTML` |
72
+
73
+ ---
74
+
75
+ ### Example Usage
76
+
77
+ ```js
78
+ // Insert notification center template at the start of <body>
79
+ TinyNotifyCenter.insertTemplate();
80
+
81
+ // Or insert at the end of <body>
82
+ TinyNotifyCenter.insertTemplate('beforeend');
83
+ ````
84
+
85
+ ---
86
+
87
+ ### Visual Structure Preview
88
+
89
+ ```html
90
+ <div class="notify-overlay hidden">
91
+ <div class="notify-center" id="notifCenter">
92
+ <div class="header">
93
+ <div>Notifications</div>
94
+ <div class="options">
95
+ <button class="clear-all" type="button">✔️</button>
96
+ <button class="close">×</button>
97
+ </div>
98
+ </div>
99
+ <div class="list"></div>
100
+ </div>
101
+ </div>
102
+
103
+ <button class="notify-bell" aria-label="Open notifications">
104
+ 🔔 <span class="badge" id="notifBadge">0</span>
105
+ </button>
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 🛠️ Instance Methods & Constructor
111
+
112
+ ### `constructor(options = {})`
113
+
114
+ Creates a new instance of the Notification Center with configurable main elements.
115
+
116
+ | Option | Default Selector | Description |
117
+ |-----------------|----------------------------------------|----------------------------------------------|
118
+ | `center` | `document.getElementById('notifCenter')` | Container element holding notification list |
119
+ | `badge` | `document.getElementById('notifBadge')` | Badge element showing the notification count |
120
+ | `button` | `document.querySelector('.notify-bell')` | Button toggling the notification center |
121
+ | `overlay` | `document.querySelector('.notify-overlay')` | Overlay element shown when center is visible |
122
+
123
+ ⚠️ Throws an error if any of the elements are not valid HTMLElements.
124
+
125
+ **Event Listeners added internally:**
126
+
127
+ - `button` click → toggles notification center
128
+ - `close` button inside center → closes notification center
129
+ - `clear-all` button inside center → clears all notifications
130
+ - Clicking the overlay outside center → closes notification center
131
+
132
+ ---
133
+
134
+ ### ⚙️ Configuration Methods
135
+
136
+ #### `setMarkAllAsReadOnClose(value: boolean)`
137
+
138
+ Enable or disable automatic marking of all notifications as read when the center closes.
139
+
140
+ Throws a `TypeError` if `value` is not a boolean.
141
+
142
+ ---
143
+
144
+ #### `setRemoveDelay(ms: number)`
145
+
146
+ Set the delay (in milliseconds) for the remove animation when notifications are removed.
147
+
148
+ Throws an error if `ms` is not a number.
149
+
150
+ ---
151
+
152
+ ### 📋 Notification Item Accessors
153
+
154
+ #### `getItemMode(index: number) : 'text' | 'html' | null`
155
+
156
+ Returns the rendering mode (`'text'` or `'html'`) of the notification at the given index, or `null` if not found.
157
+
158
+ ---
159
+
160
+ #### `getItem(index: number) : HTMLElement`
161
+
162
+ Returns the notification element at the specified index.
163
+
164
+ Throws an error if the element is not an `HTMLElement`.
165
+
166
+ ---
167
+
168
+ #### `hasItem(index: number) : boolean`
169
+
170
+ Returns `true` if a notification exists at the given index, `false` otherwise.
171
+
172
+ ---
173
+
174
+ ### ✅ Notification State Management
175
+
176
+ #### `markAsRead(index: number | HTMLElement)`
177
+
178
+ Marks the specified notification (by index or element) as read if it was unread, updating the unread count.
179
+
180
+ ---
181
+
182
+ #### `remove(index: number)`
183
+
184
+ Removes the notification at the given index, triggering any removal animations or cleanup.
185
+
186
+ ---
187
+
188
+ #### `clear()`
189
+
190
+ Safely clears all notifications from the list, removing them one by one, handling animations properly.
191
+
192
+ ---
193
+
194
+ ### 🔔 Notification Center Visibility Controls
195
+
196
+ #### `open()`
197
+
198
+ Opens the notification center by showing the overlay and adding the `open` class.
199
+
200
+ ---
201
+
202
+ #### `close()`
203
+
204
+ Closes the notification center by hiding the overlay and removing the `open` class.
205
+
206
+ If `markAllAsReadOnClose` is enabled, marks all unread notifications as read on close.
207
+
208
+ ---
209
+
210
+ #### `toggle()`
211
+
212
+ Toggles the notification center open or closed based on current state.
213
+
214
+ ---
215
+
216
+ ### 🔢 Count Management
217
+
218
+ #### `recount()`
219
+
220
+ Recalculates the number of unread notifications by counting `.item.unread` elements in the DOM list, updating the badge count.
221
+
222
+ ---
223
+
224
+ #### `get count() : number`
225
+
226
+ Returns the current number of unread notifications tracked internally.
227
+
228
+ ---
229
+
230
+ ### ➕ `add(message, mode = 'text')`
231
+
232
+ Adds a new notification to the notification center. 🎉
233
+
234
+ **Parameters:**
235
+
236
+ * `message` (`NotifyData`):
237
+ Can be either a simple string or an object containing:
238
+
239
+ * `title` (optional): notification title 📝
240
+ * `message`: main notification text or HTML content
241
+ * `avatar` (optional): URL for an avatar image 🖼️
242
+ * `onClick` (optional): callback function triggered when the notification is clicked 🎯
243
+
244
+ * `mode` (`'text' | 'html'`, default `'text'`):
245
+ Determines if the message content should be treated as plain text or HTML.
246
+
247
+ ---
248
+
249
+ **How it works:**
250
+
251
+ 1. Creates a new `.item.unread` div to hold the notification.
252
+
253
+ 2. If `message` is an object, it extracts the title, message, avatar URL, and click callback.
254
+ Otherwise, treats `message` as plain text content.
255
+
256
+ 3. If an avatar URL is provided, creates a `.avatar` div with the avatar image as background.
257
+
258
+ 4. Creates a `.content` wrapper containing:
259
+
260
+ * An optional `.title` element if a title exists
261
+ * A `.message` element containing the message, rendered as text or HTML depending on `mode`
262
+
263
+ 5. If `onClick` callback is provided, marks the item `.clickable` and adds a click event listener that triggers the callback — but **prevents clicks on the close button** from triggering it.
264
+
265
+ 6. Adds a close button (`×`) `.notify-close` inside the notification:
266
+ Clicking it removes the notification, stopping event propagation to avoid triggering the main click callback.
267
+
268
+ 7. Prepends the notification to the top of the list, stores its mode, and updates the unread count.
269
+
270
+ ---
271
+
272
+ **In short:**
273
+ You create a rich notification element dynamically, with optional avatar, title, content (text or HTML), clickable actions, and a close button — all neatly wired up! 🚀
274
+
275
+ ---
276
+
277
+ ## 🎨 CSS Files Location
278
+
279
+ The CSS files for the TinyNotify project build can be found in the following folder:
280
+
281
+ ```
282
+ dist/v1/css
283
+ ```
284
+
285
+ Inside this folder, you'll find the main stylesheets:
286
+
287
+ - `TinyNotify.css` — the full, unminified CSS file
288
+ - `TinyNotify.min.css` — the minified, optimized CSS file for production 🚀
289
+
290
+ Use these files to style your notifications!
291
+ Happy coding! ✨