admin-lte 4.0.4 → 4.1.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 (57) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/css/adminlte-docs.css +878 -0
  3. package/dist/css/adminlte-docs.css.map +1 -0
  4. package/dist/css/adminlte-docs.min.css +7 -0
  5. package/dist/css/adminlte-docs.min.css.map +1 -0
  6. package/dist/css/adminlte-docs.rtl.css +877 -0
  7. package/dist/css/adminlte-docs.rtl.css.map +1 -0
  8. package/dist/css/adminlte-docs.rtl.min.css +7 -0
  9. package/dist/css/adminlte-docs.rtl.min.css.map +1 -0
  10. package/dist/css/adminlte.css +2 -782
  11. package/dist/css/adminlte.css.map +1 -1
  12. package/dist/css/adminlte.min.css +2 -2
  13. package/dist/css/adminlte.min.css.map +1 -1
  14. package/dist/css/adminlte.rtl.css +2 -782
  15. package/dist/css/adminlte.rtl.css.map +1 -1
  16. package/dist/css/adminlte.rtl.min.css +2 -2
  17. package/dist/css/adminlte.rtl.min.css.map +1 -1
  18. package/dist/js/adminlte.esm.js +1365 -0
  19. package/dist/js/adminlte.esm.js.map +1 -0
  20. package/dist/js/adminlte.esm.min.js +7 -0
  21. package/dist/js/adminlte.esm.min.js.map +1 -0
  22. package/dist/js/adminlte.js +391 -200
  23. package/dist/js/adminlte.js.map +1 -1
  24. package/dist/js/adminlte.min.js +2 -2
  25. package/dist/js/adminlte.min.js.map +1 -1
  26. package/dist/js/types/accessibility.d.ts +46 -0
  27. package/dist/js/types/adminlte.d.ts +9 -0
  28. package/dist/js/types/base-component.d.ts +36 -0
  29. package/dist/js/types/card-widget.d.ts +30 -0
  30. package/dist/js/types/color-mode.d.ts +56 -0
  31. package/dist/js/types/direct-chat.d.ts +19 -0
  32. package/dist/js/types/fullscreen.d.ts +21 -0
  33. package/dist/js/types/layout.d.ts +19 -0
  34. package/dist/js/types/push-menu.d.ts +102 -0
  35. package/dist/js/types/treeview.d.ts +27 -0
  36. package/dist/js/types/util/index.d.ts +42 -0
  37. package/package.json +32 -6
  38. package/src/scss/_app-header.scss +3 -1
  39. package/src/scss/_app-main.scss +4 -0
  40. package/src/scss/_app-sidebar.scss +3 -1
  41. package/src/scss/_bootstrap-overrides.scss +60 -0
  42. package/src/scss/_info-box.scss +3 -1
  43. package/src/scss/_progress-bars.scss +3 -1
  44. package/src/scss/_table.scss +4 -2
  45. package/src/scss/adminlte-docs.scss +25 -0
  46. package/src/scss/adminlte.scss +5 -4
  47. package/src/scss/pages/_login_and_register.scss +3 -1
  48. package/src/ts/adminlte.ts +3 -1
  49. package/src/ts/base-component.ts +84 -0
  50. package/src/ts/card-widget.ts +124 -100
  51. package/src/ts/color-mode.ts +174 -0
  52. package/src/ts/direct-chat.ts +38 -32
  53. package/src/ts/fullscreen.ts +32 -23
  54. package/src/ts/push-menu.ts +69 -36
  55. package/src/ts/treeview.ts +84 -50
  56. package/src/ts/util/index.ts +1 -1
  57. package/src/scss/_bootstrap-variables.scss +0 -1766
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * AdminLTE v4.0.4 (https://adminlte.io)
2
+ * AdminLTE v4.1.0 (https://adminlte.io)
3
3
  * Copyright 2014-2026 Colorlib <https://colorlib.com>
4
4
  * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
5
5
  */
@@ -144,13 +144,55 @@
144
144
  }, 400);
145
145
  });
146
146
 
147
- const DATA_KEY$4 = 'lte.card-widget';
148
- const EVENT_KEY$4 = `.${DATA_KEY$4}`;
149
- const EVENT_COLLAPSED$2 = `collapsed${EVENT_KEY$4}`;
150
- const EVENT_EXPANDED$2 = `expanded${EVENT_KEY$4}`;
151
- const EVENT_REMOVE = `remove${EVENT_KEY$4}`;
152
- const EVENT_MAXIMIZED$1 = `maximized${EVENT_KEY$4}`;
153
- const EVENT_MINIMIZED$1 = `minimized${EVENT_KEY$4}`;
147
+ const componentRegistry = new WeakMap();
148
+ class BaseComponent {
149
+ static get NAME() {
150
+ throw new Error('Component subclasses must override the static NAME getter.');
151
+ }
152
+ static get DATA_KEY() {
153
+ return `lte.${this.NAME}`;
154
+ }
155
+ static _getInstance(element) {
156
+ if (!element) {
157
+ return null;
158
+ }
159
+ return componentRegistry.get(element)?.get(this.DATA_KEY) ?? null;
160
+ }
161
+ _element;
162
+ constructor(element) {
163
+ this._element = element;
164
+ const instances = componentRegistry.get(element) ?? new Map();
165
+ componentRegistry.set(element, instances);
166
+ instances.set(this.constructor.DATA_KEY, this);
167
+ }
168
+ dispose() {
169
+ const instances = componentRegistry.get(this._element);
170
+ instances?.delete(this.constructor.DATA_KEY);
171
+ if (instances?.size === 0) {
172
+ componentRegistry.delete(this._element);
173
+ }
174
+ }
175
+ }
176
+ const dispatchCustomEvent = (element, name, options = {}) => {
177
+ const event = new CustomEvent(name, {
178
+ bubbles: true,
179
+ cancelable: options.cancelable ?? false,
180
+ detail: options.detail
181
+ });
182
+ element.dispatchEvent(event);
183
+ return event;
184
+ };
185
+
186
+ const NAME$4 = 'card-widget';
187
+ const EVENT_KEY$5 = `.lte.${NAME$4}`;
188
+ const EVENT_COLLAPSE$2 = `collapse${EVENT_KEY$5}`;
189
+ const EVENT_EXPAND$1 = `expand${EVENT_KEY$5}`;
190
+ const EVENT_REMOVE = `remove${EVENT_KEY$5}`;
191
+ const EVENT_COLLAPSED$3 = `collapsed${EVENT_KEY$5}`;
192
+ const EVENT_EXPANDED$2 = `expanded${EVENT_KEY$5}`;
193
+ const EVENT_REMOVED = `removed${EVENT_KEY$5}`;
194
+ const EVENT_MAXIMIZED$1 = `maximized${EVENT_KEY$5}`;
195
+ const EVENT_MINIMIZED$1 = `minimized${EVENT_KEY$5}`;
154
196
  const CLASS_NAME_CARD = 'card';
155
197
  const CLASS_NAME_COLLAPSED = 'collapsed-card';
156
198
  const CLASS_NAME_COLLAPSING = 'collapsing-card';
@@ -169,13 +211,20 @@
169
211
  removeTrigger: SELECTOR_DATA_REMOVE,
170
212
  maximizeTrigger: SELECTOR_DATA_MAXIMIZE
171
213
  };
172
- class CardWidget {
173
- _element;
214
+ class CardWidget extends BaseComponent {
215
+ static get NAME() {
216
+ return NAME$4;
217
+ }
218
+ static getInstance(element) {
219
+ return this._getInstance(element);
220
+ }
221
+ static getOrCreateInstance(element, config = {}) {
222
+ return this.getInstance(element) ?? new this(element, config);
223
+ }
174
224
  _parent;
175
- _clone;
176
225
  _config;
177
- constructor(element, config) {
178
- this._element = element;
226
+ constructor(element, config = {}) {
227
+ super(element);
179
228
  this._parent = element.closest(SELECTOR_CARD);
180
229
  if (element.classList.contains(CLASS_NAME_CARD)) {
181
230
  this._parent = element;
@@ -183,54 +232,64 @@
183
232
  this._config = { ...Default$1, ...config };
184
233
  }
185
234
  collapse() {
186
- const event = new Event(EVENT_COLLAPSED$2);
187
- if (this._parent) {
188
- this._parent.classList.add(CLASS_NAME_COLLAPSING);
189
- this._parent.classList.remove(CLASS_NAME_EXPANDING);
190
- const elm = this._parent?.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
191
- elm.forEach(el => {
192
- if (el instanceof HTMLElement) {
193
- slideUp(el, this._config.animationSpeed);
194
- }
195
- });
196
- setTimeout(() => {
197
- if (this._parent?.classList.contains(CLASS_NAME_COLLAPSING)) {
198
- this._parent.classList.add(CLASS_NAME_COLLAPSED);
199
- this._parent.classList.remove(CLASS_NAME_COLLAPSING);
200
- }
201
- }, this._config.animationSpeed);
235
+ if (!this._parent) {
236
+ return;
202
237
  }
203
- this._element?.dispatchEvent(event);
238
+ if (dispatchCustomEvent(this._parent, EVENT_COLLAPSE$2, { cancelable: true }).defaultPrevented) {
239
+ return;
240
+ }
241
+ this._parent.classList.add(CLASS_NAME_COLLAPSING);
242
+ this._parent.classList.remove(CLASS_NAME_EXPANDING);
243
+ const elm = this._parent.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
244
+ elm.forEach(el => {
245
+ if (el instanceof HTMLElement) {
246
+ slideUp(el, this._config.animationSpeed);
247
+ }
248
+ });
249
+ setTimeout(() => {
250
+ if (this._parent?.classList.contains(CLASS_NAME_COLLAPSING)) {
251
+ this._parent.classList.add(CLASS_NAME_COLLAPSED);
252
+ this._parent.classList.remove(CLASS_NAME_COLLAPSING);
253
+ dispatchCustomEvent(this._parent, EVENT_COLLAPSED$3);
254
+ }
255
+ }, this._config.animationSpeed);
204
256
  }
205
257
  expand() {
206
- const event = new Event(EVENT_EXPANDED$2);
207
- if (this._parent) {
208
- this._parent.classList.add(CLASS_NAME_EXPANDING);
209
- this._parent.classList.remove(CLASS_NAME_COLLAPSING, CLASS_NAME_COLLAPSED);
210
- const elm = this._parent?.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
211
- elm.forEach(el => {
212
- if (el instanceof HTMLElement) {
213
- slideDown(el, this._config.animationSpeed);
214
- }
215
- });
216
- setTimeout(() => {
217
- if (this._parent?.classList.contains(CLASS_NAME_EXPANDING)) {
218
- this._parent.classList.remove(CLASS_NAME_EXPANDING);
219
- }
220
- }, this._config.animationSpeed);
258
+ if (!this._parent) {
259
+ return;
221
260
  }
222
- this._element?.dispatchEvent(event);
261
+ if (dispatchCustomEvent(this._parent, EVENT_EXPAND$1, { cancelable: true }).defaultPrevented) {
262
+ return;
263
+ }
264
+ this._parent.classList.add(CLASS_NAME_EXPANDING);
265
+ this._parent.classList.remove(CLASS_NAME_COLLAPSING, CLASS_NAME_COLLAPSED);
266
+ const elm = this._parent.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
267
+ elm.forEach(el => {
268
+ if (el instanceof HTMLElement) {
269
+ slideDown(el, this._config.animationSpeed);
270
+ }
271
+ });
272
+ setTimeout(() => {
273
+ if (this._parent?.classList.contains(CLASS_NAME_EXPANDING)) {
274
+ this._parent.classList.remove(CLASS_NAME_EXPANDING);
275
+ dispatchCustomEvent(this._parent, EVENT_EXPANDED$2);
276
+ }
277
+ }, this._config.animationSpeed);
223
278
  }
224
279
  remove() {
225
- const event = new Event(EVENT_REMOVE);
226
- if (this._parent) {
227
- const parent = this._parent;
228
- slideUp(parent, this._config.animationSpeed);
229
- setTimeout(() => {
230
- parent.remove();
231
- }, this._config.animationSpeed);
280
+ if (!this._parent) {
281
+ return;
232
282
  }
233
- this._element?.dispatchEvent(event);
283
+ if (dispatchCustomEvent(this._parent, EVENT_REMOVE, { cancelable: true }).defaultPrevented) {
284
+ return;
285
+ }
286
+ const parent = this._parent;
287
+ slideUp(parent, this._config.animationSpeed);
288
+ setTimeout(() => {
289
+ dispatchCustomEvent(parent, EVENT_REMOVED);
290
+ parent.remove();
291
+ this.dispose();
292
+ }, this._config.animationSpeed);
234
293
  }
235
294
  toggle() {
236
295
  if (this._parent?.classList.contains(CLASS_NAME_COLLAPSED) || this._parent?.classList.contains(CLASS_NAME_COLLAPSING)) {
@@ -240,7 +299,6 @@
240
299
  this.collapse();
241
300
  }
242
301
  maximize() {
243
- const event = new Event(EVENT_MAXIMIZED$1);
244
302
  if (this._parent) {
245
303
  this._parent.style.height = `${this._parent.offsetHeight}px`;
246
304
  this._parent.style.width = `${this._parent.offsetWidth}px`;
@@ -255,13 +313,12 @@
255
313
  if (this._parent.classList.contains(CLASS_NAME_COLLAPSED)) {
256
314
  this._parent.classList.add(CLASS_NAME_WAS_COLLAPSED);
257
315
  }
316
+ dispatchCustomEvent(this._parent, EVENT_MAXIMIZED$1);
258
317
  }
259
318
  }, 150);
260
319
  }
261
- this._element?.dispatchEvent(event);
262
320
  }
263
321
  minimize() {
264
- const event = new Event(EVENT_MINIMIZED$1);
265
322
  if (this._parent) {
266
323
  this._parent.style.height = 'auto';
267
324
  this._parent.style.width = 'auto';
@@ -276,6 +333,7 @@
276
333
  if (this._parent?.classList.contains(CLASS_NAME_WAS_COLLAPSED)) {
277
334
  this._parent.classList.remove(CLASS_NAME_WAS_COLLAPSED);
278
335
  }
336
+ dispatchCustomEvent(this._parent, EVENT_MINIMIZED$1);
279
337
  setTimeout(() => {
280
338
  this._parent?.style.removeProperty('height');
281
339
  this._parent?.style.removeProperty('width');
@@ -284,7 +342,6 @@
284
342
  }
285
343
  }, 10);
286
344
  }
287
- this._element?.dispatchEvent(event);
288
345
  }
289
346
  toggleMaximize() {
290
347
  if (this._parent?.classList.contains(CLASS_NAME_MAXIMIZED)) {
@@ -294,41 +351,42 @@
294
351
  this.maximize();
295
352
  }
296
353
  }
297
- onDOMContentLoaded(() => {
298
- const collapseBtn = document.querySelectorAll(SELECTOR_DATA_COLLAPSE);
299
- collapseBtn.forEach(btn => {
300
- btn.addEventListener('click', event => {
301
- event.preventDefault();
302
- const target = event.currentTarget;
303
- const data = new CardWidget(target, Default$1);
304
- data.toggle();
305
- });
306
- });
307
- const removeBtn = document.querySelectorAll(SELECTOR_DATA_REMOVE);
308
- removeBtn.forEach(btn => {
309
- btn.addEventListener('click', event => {
310
- event.preventDefault();
311
- const target = event.currentTarget;
312
- const data = new CardWidget(target, Default$1);
313
- data.remove();
314
- });
315
- });
316
- const maxBtn = document.querySelectorAll(SELECTOR_DATA_MAXIMIZE);
317
- maxBtn.forEach(btn => {
318
- btn.addEventListener('click', event => {
319
- event.preventDefault();
320
- const target = event.currentTarget;
321
- const data = new CardWidget(target, Default$1);
322
- data.toggleMaximize();
323
- });
324
- });
354
+ document.addEventListener('click', event => {
355
+ const target = event.target;
356
+ if (!(target instanceof Element)) {
357
+ return;
358
+ }
359
+ const collapseTrigger = target.closest(SELECTOR_DATA_COLLAPSE);
360
+ const removeTrigger = target.closest(SELECTOR_DATA_REMOVE);
361
+ const maximizeTrigger = target.closest(SELECTOR_DATA_MAXIMIZE);
362
+ const trigger = collapseTrigger ?? removeTrigger ?? maximizeTrigger;
363
+ if (!trigger) {
364
+ return;
365
+ }
366
+ event.preventDefault();
367
+ const card = trigger.closest(SELECTOR_CARD);
368
+ if (!card) {
369
+ return;
370
+ }
371
+ const widget = CardWidget.getOrCreateInstance(card);
372
+ if (collapseTrigger) {
373
+ widget.toggle();
374
+ }
375
+ else if (removeTrigger) {
376
+ widget.remove();
377
+ }
378
+ else {
379
+ widget.toggleMaximize();
380
+ }
325
381
  });
326
382
 
327
- const DATA_KEY$3 = 'lte.treeview';
328
- const EVENT_KEY$3 = `.${DATA_KEY$3}`;
329
- const EVENT_EXPANDED$1 = `expanded${EVENT_KEY$3}`;
330
- const EVENT_COLLAPSED$1 = `collapsed${EVENT_KEY$3}`;
331
- const EVENT_LOAD_DATA_API = `load${EVENT_KEY$3}`;
383
+ const NAME$3 = 'treeview';
384
+ const EVENT_KEY$4 = `.lte.${NAME$3}`;
385
+ const EVENT_EXPAND = `expand${EVENT_KEY$4}`;
386
+ const EVENT_COLLAPSE$1 = `collapse${EVENT_KEY$4}`;
387
+ const EVENT_EXPANDED$1 = `expanded${EVENT_KEY$4}`;
388
+ const EVENT_COLLAPSED$2 = `collapsed${EVENT_KEY$4}`;
389
+ const EVENT_LOAD_DATA_API = `load${EVENT_KEY$4}`;
332
390
  const CLASS_NAME_MENU_OPEN = 'menu-open';
333
391
  const SELECTOR_NAV_ITEM = '.nav-item';
334
392
  const SELECTOR_NAV_LINK = '.nav-link';
@@ -342,15 +400,25 @@
342
400
  const link = navItem.querySelector(`:scope > ${SELECTOR_NAV_LINK}`);
343
401
  link?.setAttribute('aria-expanded', String(expanded));
344
402
  };
345
- class Treeview {
346
- _element;
403
+ class Treeview extends BaseComponent {
404
+ static get NAME() {
405
+ return NAME$3;
406
+ }
407
+ static getInstance(element) {
408
+ return this._getInstance(element);
409
+ }
410
+ static getOrCreateInstance(element, config = {}) {
411
+ return this.getInstance(element) ?? new this(element, config);
412
+ }
347
413
  _config;
348
- constructor(element, config) {
349
- this._element = element;
414
+ constructor(element, config = {}) {
415
+ super(element);
350
416
  this._config = { ...Default, ...config };
351
417
  }
352
418
  open() {
353
- const event = new Event(EVENT_EXPANDED$1);
419
+ if (dispatchCustomEvent(this._element, EVENT_EXPAND, { cancelable: true }).defaultPrevented) {
420
+ return;
421
+ }
354
422
  if (this._config.accordion) {
355
423
  const openMenuList = this._element.parentElement?.querySelectorAll(`${SELECTOR_NAV_ITEM}.${CLASS_NAME_MENU_OPEN}`);
356
424
  openMenuList?.forEach(openMenu => {
@@ -366,21 +434,31 @@
366
434
  }
367
435
  this._element.classList.add(CLASS_NAME_MENU_OPEN);
368
436
  setAriaExpanded(this._element, true);
369
- const childElement = this._element?.querySelector(SELECTOR_TREEVIEW_MENU);
437
+ const childElement = this._element.querySelector(SELECTOR_TREEVIEW_MENU);
370
438
  if (childElement) {
371
439
  slideDown(childElement, this._config.animationSpeed);
372
440
  }
373
- this._element.dispatchEvent(event);
441
+ setTimeout(() => {
442
+ if (this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
443
+ dispatchCustomEvent(this._element, EVENT_EXPANDED$1);
444
+ }
445
+ }, this._config.animationSpeed);
374
446
  }
375
447
  close() {
376
- const event = new Event(EVENT_COLLAPSED$1);
448
+ if (dispatchCustomEvent(this._element, EVENT_COLLAPSE$1, { cancelable: true }).defaultPrevented) {
449
+ return;
450
+ }
377
451
  this._element.classList.remove(CLASS_NAME_MENU_OPEN);
378
452
  setAriaExpanded(this._element, false);
379
- const childElement = this._element?.querySelector(SELECTOR_TREEVIEW_MENU);
453
+ const childElement = this._element.querySelector(SELECTOR_TREEVIEW_MENU);
380
454
  if (childElement) {
381
455
  slideUp(childElement, this._config.animationSpeed);
382
456
  }
383
- this._element.dispatchEvent(event);
457
+ setTimeout(() => {
458
+ if (!this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
459
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED$2);
460
+ }
461
+ }, this._config.animationSpeed);
384
462
  }
385
463
  toggle() {
386
464
  if (this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
@@ -391,6 +469,31 @@
391
469
  }
392
470
  }
393
471
  }
472
+ document.addEventListener('click', event => {
473
+ const target = event.target;
474
+ if (!(target instanceof Element)) {
475
+ return;
476
+ }
477
+ const toggleRoot = target.closest(SELECTOR_DATA_TOGGLE$1);
478
+ if (!toggleRoot) {
479
+ return;
480
+ }
481
+ const targetItem = target.closest(SELECTOR_NAV_ITEM);
482
+ const targetLink = target.closest(SELECTOR_NAV_LINK);
483
+ if (!targetItem?.querySelector(SELECTOR_TREEVIEW_MENU)) {
484
+ return;
485
+ }
486
+ if (target.getAttribute('href') === '#' || targetLink?.getAttribute('href') === '#') {
487
+ event.preventDefault();
488
+ }
489
+ const accordionAttr = toggleRoot.dataset.accordion;
490
+ const animationSpeedAttr = toggleRoot.dataset.animationSpeed;
491
+ const config = {
492
+ accordion: accordionAttr === undefined ? Default.accordion : accordionAttr === 'true',
493
+ animationSpeed: animationSpeedAttr === undefined ? Default.animationSpeed : Number(animationSpeedAttr)
494
+ };
495
+ Treeview.getOrCreateInstance(targetItem, config).toggle();
496
+ });
394
497
  onDOMContentLoaded(() => {
395
498
  const openMenuItems = document.querySelectorAll(`${SELECTOR_NAV_ITEM}.${CLASS_NAME_MENU_OPEN}`);
396
499
  openMenuItems.forEach(menuItem => {
@@ -408,78 +511,56 @@
408
511
  }
409
512
  });
410
513
  });
411
- const button = document.querySelectorAll(SELECTOR_DATA_TOGGLE$1);
412
- button.forEach(btn => {
413
- btn.addEventListener('click', event => {
414
- const target = event.target;
415
- const targetItem = target.closest(SELECTOR_NAV_ITEM);
416
- const targetLink = target.closest(SELECTOR_NAV_LINK);
417
- const targetTreeviewMenu = targetItem?.querySelector(SELECTOR_TREEVIEW_MENU);
418
- const lteToggleElement = event.currentTarget;
419
- if (!targetTreeviewMenu) {
420
- return;
421
- }
422
- if (target?.getAttribute('href') === '#' || targetLink?.getAttribute('href') === '#') {
423
- event.preventDefault();
424
- }
425
- if (targetItem) {
426
- const accordionAttr = lteToggleElement.dataset.accordion;
427
- const animationSpeedAttr = lteToggleElement.dataset.animationSpeed;
428
- const config = {
429
- accordion: accordionAttr === undefined ? Default.accordion : accordionAttr === 'true',
430
- animationSpeed: animationSpeedAttr === undefined ? Default.animationSpeed : Number(animationSpeedAttr)
431
- };
432
- const data = new Treeview(targetItem, config);
433
- data.toggle();
434
- }
435
- });
436
- });
437
514
  });
438
515
 
439
- const DATA_KEY$2 = 'lte.direct-chat';
440
- const EVENT_KEY$2 = `.${DATA_KEY$2}`;
441
- const EVENT_EXPANDED = `expanded${EVENT_KEY$2}`;
442
- const EVENT_COLLAPSED = `collapsed${EVENT_KEY$2}`;
516
+ const NAME$2 = 'direct-chat';
517
+ const EVENT_KEY$3 = `.lte.${NAME$2}`;
518
+ const EVENT_EXPANDED = `expanded${EVENT_KEY$3}`;
519
+ const EVENT_COLLAPSED$1 = `collapsed${EVENT_KEY$3}`;
443
520
  const SELECTOR_DATA_TOGGLE = '[data-lte-toggle="chat-pane"]';
444
521
  const SELECTOR_DIRECT_CHAT = '.direct-chat';
445
522
  const CLASS_NAME_DIRECT_CHAT_OPEN = 'direct-chat-contacts-open';
446
- class DirectChat {
447
- _element;
448
- constructor(element) {
449
- this._element = element;
523
+ class DirectChat extends BaseComponent {
524
+ static get NAME() {
525
+ return NAME$2;
526
+ }
527
+ static getInstance(element) {
528
+ return this._getInstance(element);
529
+ }
530
+ static getOrCreateInstance(element) {
531
+ return this.getInstance(element) ?? new this(element);
450
532
  }
451
533
  toggle() {
452
534
  if (this._element.classList.contains(CLASS_NAME_DIRECT_CHAT_OPEN)) {
453
- const event = new Event(EVENT_COLLAPSED);
454
535
  this._element.classList.remove(CLASS_NAME_DIRECT_CHAT_OPEN);
455
- this._element.dispatchEvent(event);
536
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED$1);
456
537
  }
457
538
  else {
458
- const event = new Event(EVENT_EXPANDED);
459
539
  this._element.classList.add(CLASS_NAME_DIRECT_CHAT_OPEN);
460
- this._element.dispatchEvent(event);
540
+ dispatchCustomEvent(this._element, EVENT_EXPANDED);
461
541
  }
462
542
  }
463
543
  }
464
- onDOMContentLoaded(() => {
465
- const button = document.querySelectorAll(SELECTOR_DATA_TOGGLE);
466
- button.forEach(btn => {
467
- btn.addEventListener('click', event => {
468
- event.preventDefault();
469
- const target = event.target;
470
- const chatPane = target.closest(SELECTOR_DIRECT_CHAT);
471
- if (chatPane) {
472
- const data = new DirectChat(chatPane);
473
- data.toggle();
474
- }
475
- });
476
- });
544
+ document.addEventListener('click', event => {
545
+ const target = event.target;
546
+ if (!(target instanceof Element)) {
547
+ return;
548
+ }
549
+ const trigger = target.closest(SELECTOR_DATA_TOGGLE);
550
+ if (!trigger) {
551
+ return;
552
+ }
553
+ event.preventDefault();
554
+ const chatPane = trigger.closest(SELECTOR_DIRECT_CHAT);
555
+ if (chatPane) {
556
+ DirectChat.getOrCreateInstance(chatPane).toggle();
557
+ }
477
558
  });
478
559
 
479
- const DATA_KEY$1 = 'lte.fullscreen';
480
- const EVENT_KEY$1 = `.${DATA_KEY$1}`;
481
- const EVENT_MAXIMIZED = `maximized${EVENT_KEY$1}`;
482
- const EVENT_MINIMIZED = `minimized${EVENT_KEY$1}`;
560
+ const NAME$1 = 'fullscreen';
561
+ const EVENT_KEY$2 = `.lte.${NAME$1}`;
562
+ const EVENT_MAXIMIZED = `maximized${EVENT_KEY$2}`;
563
+ const EVENT_MINIMIZED = `minimized${EVENT_KEY$2}`;
483
564
  const SELECTOR_FULLSCREEN_TOGGLE = '[data-lte-toggle="fullscreen"]';
484
565
  const SELECTOR_MAXIMIZE_ICON = '[data-lte-icon="maximize"]';
485
566
  const SELECTOR_MINIMIZE_ICON = '[data-lte-icon="minimize"]';
@@ -491,15 +572,18 @@
491
572
  iconMinimize?.classList.toggle('d-none', !isFullScreen);
492
573
  const eventName = isFullScreen ? EVENT_MAXIMIZED : EVENT_MINIMIZED;
493
574
  document.querySelectorAll(SELECTOR_FULLSCREEN_TOGGLE).forEach(button => {
494
- button.dispatchEvent(new Event(eventName));
575
+ dispatchCustomEvent(button, eventName);
495
576
  });
496
577
  }
497
- class FullScreen {
498
- _element;
499
- _config;
500
- constructor(element, config) {
501
- this._element = element;
502
- this._config = config;
578
+ class FullScreen extends BaseComponent {
579
+ static get NAME() {
580
+ return NAME$1;
581
+ }
582
+ static getInstance(element) {
583
+ return this._getInstance(element);
584
+ }
585
+ static getOrCreateInstance(element) {
586
+ return this.getInstance(element) ?? new this(element);
503
587
  }
504
588
  inFullScreen() {
505
589
  void document.documentElement.requestFullscreen().catch(() => {
@@ -521,26 +605,28 @@
521
605
  }
522
606
  }
523
607
  }
608
+ document.addEventListener('click', event => {
609
+ const target = event.target;
610
+ if (!(target instanceof Element)) {
611
+ return;
612
+ }
613
+ const button = target.closest(SELECTOR_FULLSCREEN_TOGGLE);
614
+ if (!button) {
615
+ return;
616
+ }
617
+ event.preventDefault();
618
+ FullScreen.getOrCreateInstance(button).toggleFullScreen();
619
+ });
524
620
  onDOMContentLoaded(() => {
525
621
  document.addEventListener('fullscreenchange', syncFullScreenState, { signal: getLifecycleSignal() });
526
- const buttons = document.querySelectorAll(SELECTOR_FULLSCREEN_TOGGLE);
527
- buttons.forEach(btn => {
528
- btn.addEventListener('click', event => {
529
- event.preventDefault();
530
- const target = event.target;
531
- const button = target.closest(SELECTOR_FULLSCREEN_TOGGLE);
532
- if (button) {
533
- const data = new FullScreen(button, undefined);
534
- data.toggleFullScreen();
535
- }
536
- });
537
- });
538
622
  });
539
623
 
540
- const DATA_KEY = 'lte.push-menu';
541
- const EVENT_KEY = `.${DATA_KEY}`;
542
- const EVENT_OPEN = `open${EVENT_KEY}`;
543
- const EVENT_COLLAPSE = `collapse${EVENT_KEY}`;
624
+ const NAME = 'push-menu';
625
+ const EVENT_KEY$1 = `.lte.${NAME}`;
626
+ const EVENT_OPEN = `open${EVENT_KEY$1}`;
627
+ const EVENT_COLLAPSE = `collapse${EVENT_KEY$1}`;
628
+ const EVENT_OPENED = `opened${EVENT_KEY$1}`;
629
+ const EVENT_COLLAPSED = `collapsed${EVENT_KEY$1}`;
544
630
  const CLASS_NAME_SIDEBAR_MINI = 'sidebar-mini';
545
631
  const CLASS_NAME_SIDEBAR_EXPAND = 'sidebar-expand';
546
632
  const CLASS_NAME_SIDEBAR_OVERLAY = 'sidebar-overlay';
@@ -555,11 +641,19 @@
555
641
  sidebarBreakpoint: 991.98,
556
642
  enablePersistence: false
557
643
  };
558
- class PushMenu {
559
- _element;
644
+ class PushMenu extends BaseComponent {
645
+ static get NAME() {
646
+ return NAME;
647
+ }
648
+ static getInstance(element) {
649
+ return this._getInstance(element);
650
+ }
651
+ static getOrCreateInstance(element, config = {}) {
652
+ return this.getInstance(element) ?? new this(element, config);
653
+ }
560
654
  _config;
561
- constructor(element, config) {
562
- this._element = element;
655
+ constructor(element, config = {}) {
656
+ super(element);
563
657
  this._config = { ...Defaults, ...config };
564
658
  }
565
659
  isCollapsed() {
@@ -575,16 +669,22 @@
575
669
  return globalThis.innerWidth <= this._config.sidebarBreakpoint;
576
670
  }
577
671
  expand() {
672
+ if (dispatchCustomEvent(this._element, EVENT_OPEN, { cancelable: true }).defaultPrevented) {
673
+ return;
674
+ }
578
675
  document.body.classList.remove(CLASS_NAME_SIDEBAR_COLLAPSE);
579
676
  if (this.isMobileSize()) {
580
677
  document.body.classList.add(CLASS_NAME_SIDEBAR_OPEN);
581
678
  }
582
- this._element.dispatchEvent(new Event(EVENT_OPEN));
679
+ dispatchCustomEvent(this._element, EVENT_OPENED);
583
680
  }
584
681
  collapse() {
682
+ if (dispatchCustomEvent(this._element, EVENT_COLLAPSE, { cancelable: true }).defaultPrevented) {
683
+ return;
684
+ }
585
685
  document.body.classList.remove(CLASS_NAME_SIDEBAR_OPEN);
586
686
  document.body.classList.add(CLASS_NAME_SIDEBAR_COLLAPSE);
587
- this._element.dispatchEvent(new Event(EVENT_COLLAPSE));
687
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED);
588
688
  }
589
689
  toggle() {
590
690
  const isCollapsed = this.isCollapsed();
@@ -679,8 +779,23 @@
679
779
  }
680
780
  }
681
781
  }
782
+ document.addEventListener('click', event => {
783
+ const target = event.target;
784
+ if (!(target instanceof Element)) {
785
+ return;
786
+ }
787
+ const button = target.closest(SELECTOR_SIDEBAR_TOGGLE);
788
+ if (!button) {
789
+ return;
790
+ }
791
+ event.preventDefault();
792
+ const sidebar = document.querySelector(SELECTOR_APP_SIDEBAR);
793
+ if (sidebar) {
794
+ PushMenu.getOrCreateInstance(sidebar).toggle();
795
+ }
796
+ });
682
797
  onDOMContentLoaded(() => {
683
- const sidebar = document?.querySelector(SELECTOR_APP_SIDEBAR);
798
+ const sidebar = document.querySelector(SELECTOR_APP_SIDEBAR);
684
799
  if (!sidebar) {
685
800
  return;
686
801
  }
@@ -694,7 +809,7 @@
694
809
  Defaults.enablePersistence :
695
810
  enablePersistenceAttr === 'true'
696
811
  };
697
- const pushMenu = new PushMenu(sidebar, config);
812
+ const pushMenu = PushMenu.getOrCreateInstance(sidebar, config);
698
813
  pushMenu.init();
699
814
  const breakpointQuery = globalThis.matchMedia(`(max-width: ${pushMenu._config.sidebarBreakpoint}px)`);
700
815
  breakpointQuery.addEventListener('change', () => {
@@ -725,20 +840,95 @@
725
840
  event.preventDefault();
726
841
  pushMenu.collapse();
727
842
  });
728
- const fullBtn = document.querySelectorAll(SELECTOR_SIDEBAR_TOGGLE);
729
- fullBtn.forEach(btn => {
730
- btn.addEventListener('click', event => {
731
- event.preventDefault();
732
- let button = event.currentTarget;
733
- if (button?.dataset.lteToggle !== 'sidebar') {
734
- button = button?.closest(SELECTOR_SIDEBAR_TOGGLE);
735
- }
736
- if (button) {
737
- event?.preventDefault();
738
- pushMenu.toggle();
739
- }
843
+ });
844
+
845
+ const DATA_KEY = 'lte.color-mode';
846
+ const EVENT_KEY = `.${DATA_KEY}`;
847
+ const EVENT_CHANGED = `changed${EVENT_KEY}`;
848
+ const STORAGE_KEY = 'lte-theme';
849
+ const SELECTOR_TOGGLE = '[data-bs-theme-value]';
850
+ const SELECTOR_ICON = '[data-lte-theme-icon]';
851
+ class ColorMode {
852
+ getStoredTheme() {
853
+ try {
854
+ const stored = localStorage.getItem(STORAGE_KEY);
855
+ return stored && ['light', 'dark', 'auto'].includes(stored) ? stored : null;
856
+ }
857
+ catch {
858
+ return null;
859
+ }
860
+ }
861
+ getPreferredTheme() {
862
+ const stored = this.getStoredTheme();
863
+ if (stored) {
864
+ return stored;
865
+ }
866
+ return this._prefersDark() ? 'dark' : 'light';
867
+ }
868
+ resolveTheme(theme) {
869
+ if (theme === 'auto') {
870
+ return this._prefersDark() ? 'dark' : 'light';
871
+ }
872
+ return theme;
873
+ }
874
+ setTheme(theme) {
875
+ try {
876
+ localStorage.setItem(STORAGE_KEY, theme);
877
+ }
878
+ catch {
879
+ }
880
+ this._applyTheme(theme);
881
+ this._showActiveTheme(theme);
882
+ document.dispatchEvent(new CustomEvent(EVENT_CHANGED, {
883
+ detail: { theme, resolved: this.resolveTheme(theme) }
884
+ }));
885
+ }
886
+ _applyTheme(theme) {
887
+ const resolved = this.resolveTheme(theme);
888
+ document.documentElement.setAttribute('data-bs-theme', resolved);
889
+ document.documentElement.style.colorScheme = resolved;
890
+ }
891
+ _prefersDark() {
892
+ return globalThis.matchMedia('(prefers-color-scheme: dark)').matches;
893
+ }
894
+ _showActiveTheme(theme) {
895
+ document.querySelectorAll(SELECTOR_TOGGLE).forEach(toggle => {
896
+ const isActive = toggle.getAttribute('data-bs-theme-value') === theme;
897
+ toggle.classList.toggle('active', isActive);
898
+ toggle.setAttribute('aria-pressed', String(isActive));
899
+ toggle.querySelector('.bi-check-lg')?.classList.toggle('d-none', !isActive);
740
900
  });
741
- });
901
+ document.querySelectorAll(SELECTOR_ICON).forEach(icon => {
902
+ icon.classList.toggle('d-none', icon.dataset.lteThemeIcon !== theme);
903
+ });
904
+ }
905
+ init() {
906
+ const theme = this.getPreferredTheme();
907
+ this._applyTheme(theme);
908
+ this._showActiveTheme(theme);
909
+ }
910
+ }
911
+ document.addEventListener('click', event => {
912
+ const target = event.target;
913
+ if (!(target instanceof Element)) {
914
+ return;
915
+ }
916
+ const toggle = target.closest(SELECTOR_TOGGLE);
917
+ const theme = toggle?.getAttribute('data-bs-theme-value');
918
+ if (theme) {
919
+ new ColorMode().setTheme(theme);
920
+ }
921
+ });
922
+ onDOMContentLoaded(() => {
923
+ const colorMode = new ColorMode();
924
+ colorMode.init();
925
+ globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
926
+ const stored = colorMode.getStoredTheme();
927
+ if (!stored || stored === 'auto') {
928
+ colorMode._applyTheme('auto');
929
+ colorMode._showActiveTheme(stored ?? 'auto');
930
+ }
931
+ }, { signal: getLifecycleSignal() });
742
932
  });
743
933
 
744
934
  class AccessibilityManager {
@@ -1178,6 +1368,7 @@
1178
1368
  });
1179
1369
 
1180
1370
  exports.CardWidget = CardWidget;
1371
+ exports.ColorMode = ColorMode;
1181
1372
  exports.DirectChat = DirectChat;
1182
1373
  exports.FullScreen = FullScreen;
1183
1374
  exports.Layout = Layout;