admin-lte 4.0.4 → 4.2.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 (59) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/README.md +6 -6
  3. package/dist/css/adminlte-docs.css +878 -0
  4. package/dist/css/adminlte-docs.css.map +1 -0
  5. package/dist/css/adminlte-docs.min.css +7 -0
  6. package/dist/css/adminlte-docs.min.css.map +1 -0
  7. package/dist/css/adminlte-docs.rtl.css +877 -0
  8. package/dist/css/adminlte-docs.rtl.css.map +1 -0
  9. package/dist/css/adminlte-docs.rtl.min.css +7 -0
  10. package/dist/css/adminlte-docs.rtl.min.css.map +1 -0
  11. package/dist/css/adminlte.css +132 -912
  12. package/dist/css/adminlte.css.map +1 -1
  13. package/dist/css/adminlte.min.css +2 -2
  14. package/dist/css/adminlte.min.css.map +1 -1
  15. package/dist/css/adminlte.rtl.css +132 -912
  16. package/dist/css/adminlte.rtl.css.map +1 -1
  17. package/dist/css/adminlte.rtl.min.css +2 -2
  18. package/dist/css/adminlte.rtl.min.css.map +1 -1
  19. package/dist/js/adminlte.esm.js +1406 -0
  20. package/dist/js/adminlte.esm.js.map +1 -0
  21. package/dist/js/adminlte.esm.min.js +7 -0
  22. package/dist/js/adminlte.esm.min.js.map +1 -0
  23. package/dist/js/adminlte.js +449 -215
  24. package/dist/js/adminlte.js.map +1 -1
  25. package/dist/js/adminlte.min.js +2 -2
  26. package/dist/js/adminlte.min.js.map +1 -1
  27. package/dist/js/types/accessibility.d.ts +46 -0
  28. package/dist/js/types/adminlte.d.ts +10 -0
  29. package/dist/js/types/base-component.d.ts +60 -0
  30. package/dist/js/types/card-widget.d.ts +30 -0
  31. package/dist/js/types/color-mode.d.ts +74 -0
  32. package/dist/js/types/direct-chat.d.ts +19 -0
  33. package/dist/js/types/fullscreen.d.ts +21 -0
  34. package/dist/js/types/layout.d.ts +19 -0
  35. package/dist/js/types/push-menu.d.ts +123 -0
  36. package/dist/js/types/treeview.d.ts +27 -0
  37. package/dist/js/types/util/index.d.ts +79 -0
  38. package/package.json +52 -25
  39. package/src/scss/_app-header.scss +3 -1
  40. package/src/scss/_app-main.scss +4 -0
  41. package/src/scss/_app-sidebar.scss +3 -1
  42. package/src/scss/_bootstrap-overrides.scss +60 -0
  43. package/src/scss/_info-box.scss +3 -1
  44. package/src/scss/_progress-bars.scss +3 -1
  45. package/src/scss/_table.scss +4 -2
  46. package/src/scss/adminlte-docs.scss +25 -0
  47. package/src/scss/adminlte.scss +5 -4
  48. package/src/scss/pages/_login_and_register.scss +3 -1
  49. package/src/ts/accessibility.ts +6 -2
  50. package/src/ts/adminlte.ts +7 -3
  51. package/src/ts/base-component.ts +111 -0
  52. package/src/ts/card-widget.ts +124 -100
  53. package/src/ts/color-mode.ts +254 -0
  54. package/src/ts/direct-chat.ts +38 -32
  55. package/src/ts/fullscreen.ts +32 -23
  56. package/src/ts/push-menu.ts +106 -43
  57. package/src/ts/treeview.ts +84 -50
  58. package/src/ts/util/index.ts +80 -16
  59. package/src/scss/_bootstrap-variables.scss +0 -1766
@@ -0,0 +1,1406 @@
1
+ /*!
2
+ * AdminLTE v4.2.0 (https://adminlte.io)
3
+ * Copyright 2014-2026 Colorlib <https://colorlib.com>
4
+ * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
5
+ */
6
+ const lifecycleCallbacks = [];
7
+ const lifecycleState = {
8
+ controller: new AbortController(),
9
+ hasInitialized: false,
10
+ isReplaying: false
11
+ };
12
+ const getLifecycleSignal = () => lifecycleState.controller.signal;
13
+ const runLifecycleCallbacks = () => {
14
+ if (lifecycleState.hasInitialized) {
15
+ return;
16
+ }
17
+ lifecycleState.hasInitialized = true;
18
+ lifecycleState.isReplaying = true;
19
+ try {
20
+ for (const callback of lifecycleCallbacks) {
21
+ callback();
22
+ }
23
+ }
24
+ finally {
25
+ lifecycleState.isReplaying = false;
26
+ }
27
+ };
28
+ const onDOMContentLoaded = (callback) => {
29
+ lifecycleCallbacks.push(callback);
30
+ if (lifecycleState.hasInitialized) {
31
+ callback();
32
+ }
33
+ };
34
+ const teardown = () => {
35
+ lifecycleState.controller.abort();
36
+ lifecycleState.controller = new AbortController();
37
+ lifecycleState.hasInitialized = false;
38
+ };
39
+ const initialize = () => {
40
+ if (lifecycleState.isReplaying) {
41
+ return;
42
+ }
43
+ teardown();
44
+ runLifecycleCallbacks();
45
+ };
46
+ if (document.readyState === 'loading') {
47
+ document.addEventListener('DOMContentLoaded', initialize, { once: true });
48
+ }
49
+ else {
50
+ runLifecycleCallbacks();
51
+ }
52
+ document.addEventListener('turbo:before-render', teardown);
53
+ document.addEventListener('turbo:load', runLifecycleCallbacks);
54
+ const slideTimers = new WeakMap();
55
+ const cancelSlide = (target) => {
56
+ const timers = slideTimers.get(target) ?? [];
57
+ for (const timer of timers) {
58
+ globalThis.clearTimeout(timer);
59
+ }
60
+ slideTimers.delete(target);
61
+ };
62
+ const clearSlideStyles = (target) => {
63
+ for (const property of ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']) {
64
+ target.style.removeProperty(property);
65
+ }
66
+ };
67
+ const slideUp = (target, duration = 500) => {
68
+ cancelSlide(target);
69
+ if (duration <= 1) {
70
+ target.style.display = 'none';
71
+ clearSlideStyles(target);
72
+ return;
73
+ }
74
+ target.style.transitionProperty = 'height, margin, padding';
75
+ target.style.transitionDuration = `${duration}ms`;
76
+ target.style.boxSizing = 'border-box';
77
+ target.style.height = `${target.offsetHeight}px`;
78
+ target.style.overflow = 'hidden';
79
+ const stepTimer = globalThis.setTimeout(() => {
80
+ target.style.height = '0';
81
+ target.style.paddingTop = '0';
82
+ target.style.paddingBottom = '0';
83
+ target.style.marginTop = '0';
84
+ target.style.marginBottom = '0';
85
+ }, 1);
86
+ const cleanupTimer = globalThis.setTimeout(() => {
87
+ target.style.display = 'none';
88
+ clearSlideStyles(target);
89
+ slideTimers.delete(target);
90
+ }, duration);
91
+ slideTimers.set(target, [stepTimer, cleanupTimer]);
92
+ };
93
+ const slideDown = (target, duration = 500) => {
94
+ cancelSlide(target);
95
+ clearSlideStyles(target);
96
+ target.style.removeProperty('display');
97
+ let { display } = globalThis.getComputedStyle(target);
98
+ if (display === 'none') {
99
+ display = 'block';
100
+ }
101
+ target.style.display = display;
102
+ if (duration <= 1) {
103
+ return;
104
+ }
105
+ const height = target.offsetHeight;
106
+ target.style.overflow = 'hidden';
107
+ target.style.height = '0';
108
+ target.style.paddingTop = '0';
109
+ target.style.paddingBottom = '0';
110
+ target.style.marginTop = '0';
111
+ target.style.marginBottom = '0';
112
+ const stepTimer = globalThis.setTimeout(() => {
113
+ target.style.boxSizing = 'border-box';
114
+ target.style.transitionProperty = 'height, margin, padding';
115
+ target.style.transitionDuration = `${duration}ms`;
116
+ target.style.height = `${height}px`;
117
+ target.style.removeProperty('padding-top');
118
+ target.style.removeProperty('padding-bottom');
119
+ target.style.removeProperty('margin-top');
120
+ target.style.removeProperty('margin-bottom');
121
+ }, 1);
122
+ const cleanupTimer = globalThis.setTimeout(() => {
123
+ clearSlideStyles(target);
124
+ slideTimers.delete(target);
125
+ }, duration);
126
+ slideTimers.set(target, [stepTimer, cleanupTimer]);
127
+ };
128
+
129
+ const CLASS_NAME_HOLD_TRANSITIONS = 'hold-transition';
130
+ const CLASS_NAME_APP_LOADED = 'app-loaded';
131
+ class Layout {
132
+ _element;
133
+ _holdTransitionTimer;
134
+ constructor(element) {
135
+ this._element = element;
136
+ this._holdTransitionTimer = undefined;
137
+ }
138
+ holdTransition(time = 100) {
139
+ if (this._holdTransitionTimer) {
140
+ clearTimeout(this._holdTransitionTimer);
141
+ }
142
+ document.body.classList.add(CLASS_NAME_HOLD_TRANSITIONS);
143
+ this._holdTransitionTimer = setTimeout(() => {
144
+ document.body.classList.remove(CLASS_NAME_HOLD_TRANSITIONS);
145
+ }, time);
146
+ }
147
+ }
148
+ onDOMContentLoaded(() => {
149
+ const layout = new Layout(document.body);
150
+ window.addEventListener('resize', () => layout.holdTransition(200), { signal: getLifecycleSignal() });
151
+ setTimeout(() => {
152
+ document.body.classList.add(CLASS_NAME_APP_LOADED);
153
+ }, 400);
154
+ });
155
+
156
+ const componentRegistry = new WeakMap();
157
+ class BaseComponent {
158
+ static get NAME() {
159
+ throw new Error('Component subclasses must override the static NAME getter.');
160
+ }
161
+ static get DATA_KEY() {
162
+ return `lte.${this.NAME}`;
163
+ }
164
+ static _getInstance(element) {
165
+ if (!element) {
166
+ return null;
167
+ }
168
+ return componentRegistry.get(element)?.get(this.DATA_KEY) ?? null;
169
+ }
170
+ _element;
171
+ constructor(element) {
172
+ this._element = element;
173
+ const instances = componentRegistry.get(element) ?? new Map();
174
+ componentRegistry.set(element, instances);
175
+ instances.set(this.constructor.DATA_KEY, this);
176
+ }
177
+ dispose() {
178
+ const instances = componentRegistry.get(this._element);
179
+ instances?.delete(this.constructor.DATA_KEY);
180
+ if (instances?.size === 0) {
181
+ componentRegistry.delete(this._element);
182
+ }
183
+ }
184
+ }
185
+ const dispatchCustomEvent = (element, name, options = {}) => {
186
+ const event = new CustomEvent(name, {
187
+ bubbles: true,
188
+ cancelable: options.cancelable ?? false,
189
+ detail: options.detail
190
+ });
191
+ element.dispatchEvent(event);
192
+ return event;
193
+ };
194
+
195
+ const NAME$4 = 'card-widget';
196
+ const EVENT_KEY$5 = `.lte.${NAME$4}`;
197
+ const EVENT_COLLAPSE$2 = `collapse${EVENT_KEY$5}`;
198
+ const EVENT_EXPAND$1 = `expand${EVENT_KEY$5}`;
199
+ const EVENT_REMOVE = `remove${EVENT_KEY$5}`;
200
+ const EVENT_COLLAPSED$3 = `collapsed${EVENT_KEY$5}`;
201
+ const EVENT_EXPANDED$2 = `expanded${EVENT_KEY$5}`;
202
+ const EVENT_REMOVED = `removed${EVENT_KEY$5}`;
203
+ const EVENT_MAXIMIZED$1 = `maximized${EVENT_KEY$5}`;
204
+ const EVENT_MINIMIZED$1 = `minimized${EVENT_KEY$5}`;
205
+ const CLASS_NAME_CARD = 'card';
206
+ const CLASS_NAME_COLLAPSED = 'collapsed-card';
207
+ const CLASS_NAME_COLLAPSING = 'collapsing-card';
208
+ const CLASS_NAME_EXPANDING = 'expanding-card';
209
+ const CLASS_NAME_WAS_COLLAPSED = 'was-collapsed';
210
+ const CLASS_NAME_MAXIMIZED = 'maximized-card';
211
+ const SELECTOR_DATA_REMOVE = '[data-lte-toggle="card-remove"]';
212
+ const SELECTOR_DATA_COLLAPSE = '[data-lte-toggle="card-collapse"]';
213
+ const SELECTOR_DATA_MAXIMIZE = '[data-lte-toggle="card-maximize"]';
214
+ const SELECTOR_CARD = `.${CLASS_NAME_CARD}`;
215
+ const SELECTOR_CARD_BODY = '.card-body';
216
+ const SELECTOR_CARD_FOOTER = '.card-footer';
217
+ const Default$1 = {
218
+ animationSpeed: 500,
219
+ collapseTrigger: SELECTOR_DATA_COLLAPSE,
220
+ removeTrigger: SELECTOR_DATA_REMOVE,
221
+ maximizeTrigger: SELECTOR_DATA_MAXIMIZE
222
+ };
223
+ class CardWidget extends BaseComponent {
224
+ static get NAME() {
225
+ return NAME$4;
226
+ }
227
+ static getInstance(element) {
228
+ return this._getInstance(element);
229
+ }
230
+ static getOrCreateInstance(element, config = {}) {
231
+ return this.getInstance(element) ?? new this(element, config);
232
+ }
233
+ _parent;
234
+ _config;
235
+ constructor(element, config = {}) {
236
+ super(element);
237
+ this._parent = element.closest(SELECTOR_CARD);
238
+ if (element.classList.contains(CLASS_NAME_CARD)) {
239
+ this._parent = element;
240
+ }
241
+ this._config = { ...Default$1, ...config };
242
+ }
243
+ collapse() {
244
+ if (!this._parent) {
245
+ return;
246
+ }
247
+ if (dispatchCustomEvent(this._parent, EVENT_COLLAPSE$2, { cancelable: true }).defaultPrevented) {
248
+ return;
249
+ }
250
+ this._parent.classList.add(CLASS_NAME_COLLAPSING);
251
+ this._parent.classList.remove(CLASS_NAME_EXPANDING);
252
+ const elm = this._parent.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
253
+ elm.forEach(el => {
254
+ if (el instanceof HTMLElement) {
255
+ slideUp(el, this._config.animationSpeed);
256
+ }
257
+ });
258
+ setTimeout(() => {
259
+ if (this._parent?.classList.contains(CLASS_NAME_COLLAPSING)) {
260
+ this._parent.classList.add(CLASS_NAME_COLLAPSED);
261
+ this._parent.classList.remove(CLASS_NAME_COLLAPSING);
262
+ dispatchCustomEvent(this._parent, EVENT_COLLAPSED$3);
263
+ }
264
+ }, this._config.animationSpeed);
265
+ }
266
+ expand() {
267
+ if (!this._parent) {
268
+ return;
269
+ }
270
+ if (dispatchCustomEvent(this._parent, EVENT_EXPAND$1, { cancelable: true }).defaultPrevented) {
271
+ return;
272
+ }
273
+ this._parent.classList.add(CLASS_NAME_EXPANDING);
274
+ this._parent.classList.remove(CLASS_NAME_COLLAPSING, CLASS_NAME_COLLAPSED);
275
+ const elm = this._parent.querySelectorAll(`:scope > ${SELECTOR_CARD_BODY}, :scope > ${SELECTOR_CARD_FOOTER}`);
276
+ elm.forEach(el => {
277
+ if (el instanceof HTMLElement) {
278
+ slideDown(el, this._config.animationSpeed);
279
+ }
280
+ });
281
+ setTimeout(() => {
282
+ if (this._parent?.classList.contains(CLASS_NAME_EXPANDING)) {
283
+ this._parent.classList.remove(CLASS_NAME_EXPANDING);
284
+ dispatchCustomEvent(this._parent, EVENT_EXPANDED$2);
285
+ }
286
+ }, this._config.animationSpeed);
287
+ }
288
+ remove() {
289
+ if (!this._parent) {
290
+ return;
291
+ }
292
+ if (dispatchCustomEvent(this._parent, EVENT_REMOVE, { cancelable: true }).defaultPrevented) {
293
+ return;
294
+ }
295
+ const parent = this._parent;
296
+ slideUp(parent, this._config.animationSpeed);
297
+ setTimeout(() => {
298
+ dispatchCustomEvent(parent, EVENT_REMOVED);
299
+ parent.remove();
300
+ this.dispose();
301
+ }, this._config.animationSpeed);
302
+ }
303
+ toggle() {
304
+ if (this._parent?.classList.contains(CLASS_NAME_COLLAPSED) || this._parent?.classList.contains(CLASS_NAME_COLLAPSING)) {
305
+ this.expand();
306
+ return;
307
+ }
308
+ this.collapse();
309
+ }
310
+ maximize() {
311
+ if (this._parent) {
312
+ this._parent.style.height = `${this._parent.offsetHeight}px`;
313
+ this._parent.style.width = `${this._parent.offsetWidth}px`;
314
+ this._parent.style.transition = 'all .15s';
315
+ setTimeout(() => {
316
+ const htmlTag = document.querySelector('html');
317
+ if (htmlTag) {
318
+ htmlTag.classList.add(CLASS_NAME_MAXIMIZED);
319
+ }
320
+ if (this._parent) {
321
+ this._parent.classList.add(CLASS_NAME_MAXIMIZED);
322
+ if (this._parent.classList.contains(CLASS_NAME_COLLAPSED)) {
323
+ this._parent.classList.add(CLASS_NAME_WAS_COLLAPSED);
324
+ }
325
+ dispatchCustomEvent(this._parent, EVENT_MAXIMIZED$1);
326
+ }
327
+ }, 150);
328
+ }
329
+ }
330
+ minimize() {
331
+ if (this._parent) {
332
+ this._parent.style.height = 'auto';
333
+ this._parent.style.width = 'auto';
334
+ this._parent.style.transition = 'all .15s';
335
+ setTimeout(() => {
336
+ const htmlTag = document.querySelector('html');
337
+ if (htmlTag) {
338
+ htmlTag.classList.remove(CLASS_NAME_MAXIMIZED);
339
+ }
340
+ if (this._parent) {
341
+ this._parent.classList.remove(CLASS_NAME_MAXIMIZED);
342
+ if (this._parent?.classList.contains(CLASS_NAME_WAS_COLLAPSED)) {
343
+ this._parent.classList.remove(CLASS_NAME_WAS_COLLAPSED);
344
+ }
345
+ dispatchCustomEvent(this._parent, EVENT_MINIMIZED$1);
346
+ setTimeout(() => {
347
+ this._parent?.style.removeProperty('height');
348
+ this._parent?.style.removeProperty('width');
349
+ this._parent?.style.removeProperty('transition');
350
+ }, 150);
351
+ }
352
+ }, 10);
353
+ }
354
+ }
355
+ toggleMaximize() {
356
+ if (this._parent?.classList.contains(CLASS_NAME_MAXIMIZED)) {
357
+ this.minimize();
358
+ return;
359
+ }
360
+ this.maximize();
361
+ }
362
+ }
363
+ document.addEventListener('click', event => {
364
+ const target = event.target;
365
+ if (!(target instanceof Element)) {
366
+ return;
367
+ }
368
+ const collapseTrigger = target.closest(SELECTOR_DATA_COLLAPSE);
369
+ const removeTrigger = target.closest(SELECTOR_DATA_REMOVE);
370
+ const maximizeTrigger = target.closest(SELECTOR_DATA_MAXIMIZE);
371
+ const trigger = collapseTrigger ?? removeTrigger ?? maximizeTrigger;
372
+ if (!trigger) {
373
+ return;
374
+ }
375
+ event.preventDefault();
376
+ const card = trigger.closest(SELECTOR_CARD);
377
+ if (!card) {
378
+ return;
379
+ }
380
+ const widget = CardWidget.getOrCreateInstance(card);
381
+ if (collapseTrigger) {
382
+ widget.toggle();
383
+ }
384
+ else if (removeTrigger) {
385
+ widget.remove();
386
+ }
387
+ else {
388
+ widget.toggleMaximize();
389
+ }
390
+ });
391
+
392
+ const NAME$3 = 'treeview';
393
+ const EVENT_KEY$4 = `.lte.${NAME$3}`;
394
+ const EVENT_EXPAND = `expand${EVENT_KEY$4}`;
395
+ const EVENT_COLLAPSE$1 = `collapse${EVENT_KEY$4}`;
396
+ const EVENT_EXPANDED$1 = `expanded${EVENT_KEY$4}`;
397
+ const EVENT_COLLAPSED$2 = `collapsed${EVENT_KEY$4}`;
398
+ const EVENT_LOAD_DATA_API = `load${EVENT_KEY$4}`;
399
+ const CLASS_NAME_MENU_OPEN = 'menu-open';
400
+ const SELECTOR_NAV_ITEM = '.nav-item';
401
+ const SELECTOR_NAV_LINK = '.nav-link';
402
+ const SELECTOR_TREEVIEW_MENU = '.nav-treeview';
403
+ const SELECTOR_DATA_TOGGLE$1 = '[data-lte-toggle="treeview"]';
404
+ const Default = {
405
+ animationSpeed: 300,
406
+ accordion: true
407
+ };
408
+ const setAriaExpanded = (navItem, expanded) => {
409
+ const link = navItem.querySelector(`:scope > ${SELECTOR_NAV_LINK}`);
410
+ link?.setAttribute('aria-expanded', String(expanded));
411
+ };
412
+ class Treeview extends BaseComponent {
413
+ static get NAME() {
414
+ return NAME$3;
415
+ }
416
+ static getInstance(element) {
417
+ return this._getInstance(element);
418
+ }
419
+ static getOrCreateInstance(element, config = {}) {
420
+ return this.getInstance(element) ?? new this(element, config);
421
+ }
422
+ _config;
423
+ constructor(element, config = {}) {
424
+ super(element);
425
+ this._config = { ...Default, ...config };
426
+ }
427
+ open() {
428
+ if (dispatchCustomEvent(this._element, EVENT_EXPAND, { cancelable: true }).defaultPrevented) {
429
+ return;
430
+ }
431
+ if (this._config.accordion) {
432
+ const openMenuList = this._element.parentElement?.querySelectorAll(`${SELECTOR_NAV_ITEM}.${CLASS_NAME_MENU_OPEN}`);
433
+ openMenuList?.forEach(openMenu => {
434
+ if (!this._element.contains(openMenu)) {
435
+ openMenu.classList.remove(CLASS_NAME_MENU_OPEN);
436
+ setAriaExpanded(openMenu, false);
437
+ const childElement = openMenu?.querySelector(SELECTOR_TREEVIEW_MENU);
438
+ if (childElement) {
439
+ slideUp(childElement, this._config.animationSpeed);
440
+ }
441
+ }
442
+ });
443
+ }
444
+ this._element.classList.add(CLASS_NAME_MENU_OPEN);
445
+ setAriaExpanded(this._element, true);
446
+ const childElement = this._element.querySelector(SELECTOR_TREEVIEW_MENU);
447
+ if (childElement) {
448
+ slideDown(childElement, this._config.animationSpeed);
449
+ }
450
+ setTimeout(() => {
451
+ if (this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
452
+ dispatchCustomEvent(this._element, EVENT_EXPANDED$1);
453
+ }
454
+ }, this._config.animationSpeed);
455
+ }
456
+ close() {
457
+ if (dispatchCustomEvent(this._element, EVENT_COLLAPSE$1, { cancelable: true }).defaultPrevented) {
458
+ return;
459
+ }
460
+ this._element.classList.remove(CLASS_NAME_MENU_OPEN);
461
+ setAriaExpanded(this._element, false);
462
+ const childElement = this._element.querySelector(SELECTOR_TREEVIEW_MENU);
463
+ if (childElement) {
464
+ slideUp(childElement, this._config.animationSpeed);
465
+ }
466
+ setTimeout(() => {
467
+ if (!this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
468
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED$2);
469
+ }
470
+ }, this._config.animationSpeed);
471
+ }
472
+ toggle() {
473
+ if (this._element.classList.contains(CLASS_NAME_MENU_OPEN)) {
474
+ this.close();
475
+ }
476
+ else {
477
+ this.open();
478
+ }
479
+ }
480
+ }
481
+ document.addEventListener('click', event => {
482
+ const target = event.target;
483
+ if (!(target instanceof Element)) {
484
+ return;
485
+ }
486
+ const toggleRoot = target.closest(SELECTOR_DATA_TOGGLE$1);
487
+ if (!toggleRoot) {
488
+ return;
489
+ }
490
+ const targetItem = target.closest(SELECTOR_NAV_ITEM);
491
+ const targetLink = target.closest(SELECTOR_NAV_LINK);
492
+ if (!targetItem?.querySelector(SELECTOR_TREEVIEW_MENU)) {
493
+ return;
494
+ }
495
+ if (target.getAttribute('href') === '#' || targetLink?.getAttribute('href') === '#') {
496
+ event.preventDefault();
497
+ }
498
+ const accordionAttr = toggleRoot.dataset.accordion;
499
+ const animationSpeedAttr = toggleRoot.dataset.animationSpeed;
500
+ const config = {
501
+ accordion: accordionAttr === undefined ? Default.accordion : accordionAttr === 'true',
502
+ animationSpeed: animationSpeedAttr === undefined ? Default.animationSpeed : Number(animationSpeedAttr)
503
+ };
504
+ Treeview.getOrCreateInstance(targetItem, config).toggle();
505
+ });
506
+ onDOMContentLoaded(() => {
507
+ const openMenuItems = document.querySelectorAll(`${SELECTOR_NAV_ITEM}.${CLASS_NAME_MENU_OPEN}`);
508
+ openMenuItems.forEach(menuItem => {
509
+ const childElement = menuItem.querySelector(SELECTOR_TREEVIEW_MENU);
510
+ if (childElement) {
511
+ slideDown(childElement, 0);
512
+ const event = new Event(EVENT_LOAD_DATA_API);
513
+ menuItem.dispatchEvent(event);
514
+ }
515
+ });
516
+ document.querySelectorAll(SELECTOR_DATA_TOGGLE$1).forEach(root => {
517
+ root.querySelectorAll(SELECTOR_NAV_ITEM).forEach(item => {
518
+ if (item.querySelector(`:scope > ${SELECTOR_TREEVIEW_MENU}`)) {
519
+ setAriaExpanded(item, item.classList.contains(CLASS_NAME_MENU_OPEN));
520
+ }
521
+ });
522
+ });
523
+ });
524
+
525
+ const NAME$2 = 'direct-chat';
526
+ const EVENT_KEY$3 = `.lte.${NAME$2}`;
527
+ const EVENT_EXPANDED = `expanded${EVENT_KEY$3}`;
528
+ const EVENT_COLLAPSED$1 = `collapsed${EVENT_KEY$3}`;
529
+ const SELECTOR_DATA_TOGGLE = '[data-lte-toggle="chat-pane"]';
530
+ const SELECTOR_DIRECT_CHAT = '.direct-chat';
531
+ const CLASS_NAME_DIRECT_CHAT_OPEN = 'direct-chat-contacts-open';
532
+ class DirectChat extends BaseComponent {
533
+ static get NAME() {
534
+ return NAME$2;
535
+ }
536
+ static getInstance(element) {
537
+ return this._getInstance(element);
538
+ }
539
+ static getOrCreateInstance(element) {
540
+ return this.getInstance(element) ?? new this(element);
541
+ }
542
+ toggle() {
543
+ if (this._element.classList.contains(CLASS_NAME_DIRECT_CHAT_OPEN)) {
544
+ this._element.classList.remove(CLASS_NAME_DIRECT_CHAT_OPEN);
545
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED$1);
546
+ }
547
+ else {
548
+ this._element.classList.add(CLASS_NAME_DIRECT_CHAT_OPEN);
549
+ dispatchCustomEvent(this._element, EVENT_EXPANDED);
550
+ }
551
+ }
552
+ }
553
+ document.addEventListener('click', event => {
554
+ const target = event.target;
555
+ if (!(target instanceof Element)) {
556
+ return;
557
+ }
558
+ const trigger = target.closest(SELECTOR_DATA_TOGGLE);
559
+ if (!trigger) {
560
+ return;
561
+ }
562
+ event.preventDefault();
563
+ const chatPane = trigger.closest(SELECTOR_DIRECT_CHAT);
564
+ if (chatPane) {
565
+ DirectChat.getOrCreateInstance(chatPane).toggle();
566
+ }
567
+ });
568
+
569
+ const NAME$1 = 'fullscreen';
570
+ const EVENT_KEY$2 = `.lte.${NAME$1}`;
571
+ const EVENT_MAXIMIZED = `maximized${EVENT_KEY$2}`;
572
+ const EVENT_MINIMIZED = `minimized${EVENT_KEY$2}`;
573
+ const SELECTOR_FULLSCREEN_TOGGLE = '[data-lte-toggle="fullscreen"]';
574
+ const SELECTOR_MAXIMIZE_ICON = '[data-lte-icon="maximize"]';
575
+ const SELECTOR_MINIMIZE_ICON = '[data-lte-icon="minimize"]';
576
+ function syncFullScreenState() {
577
+ const iconMaximize = document.querySelector(SELECTOR_MAXIMIZE_ICON);
578
+ const iconMinimize = document.querySelector(SELECTOR_MINIMIZE_ICON);
579
+ const isFullScreen = Boolean(document.fullscreenElement);
580
+ iconMaximize?.classList.toggle('d-none', isFullScreen);
581
+ iconMinimize?.classList.toggle('d-none', !isFullScreen);
582
+ const eventName = isFullScreen ? EVENT_MAXIMIZED : EVENT_MINIMIZED;
583
+ document.querySelectorAll(SELECTOR_FULLSCREEN_TOGGLE).forEach(button => {
584
+ dispatchCustomEvent(button, eventName);
585
+ });
586
+ }
587
+ class FullScreen extends BaseComponent {
588
+ static get NAME() {
589
+ return NAME$1;
590
+ }
591
+ static getInstance(element) {
592
+ return this._getInstance(element);
593
+ }
594
+ static getOrCreateInstance(element) {
595
+ return this.getInstance(element) ?? new this(element);
596
+ }
597
+ inFullScreen() {
598
+ void document.documentElement.requestFullscreen().catch(() => {
599
+ });
600
+ }
601
+ outFullscreen() {
602
+ void document.exitFullscreen().catch(() => {
603
+ });
604
+ }
605
+ toggleFullScreen() {
606
+ if (!document.fullscreenEnabled) {
607
+ return;
608
+ }
609
+ if (document.fullscreenElement) {
610
+ this.outFullscreen();
611
+ }
612
+ else {
613
+ this.inFullScreen();
614
+ }
615
+ }
616
+ }
617
+ document.addEventListener('click', event => {
618
+ const target = event.target;
619
+ if (!(target instanceof Element)) {
620
+ return;
621
+ }
622
+ const button = target.closest(SELECTOR_FULLSCREEN_TOGGLE);
623
+ if (!button) {
624
+ return;
625
+ }
626
+ event.preventDefault();
627
+ FullScreen.getOrCreateInstance(button).toggleFullScreen();
628
+ });
629
+ onDOMContentLoaded(() => {
630
+ document.addEventListener('fullscreenchange', syncFullScreenState, { signal: getLifecycleSignal() });
631
+ });
632
+
633
+ const NAME = 'push-menu';
634
+ const EVENT_KEY$1 = `.lte.${NAME}`;
635
+ const EVENT_OPEN = `open${EVENT_KEY$1}`;
636
+ const EVENT_COLLAPSE = `collapse${EVENT_KEY$1}`;
637
+ const EVENT_OPENED = `opened${EVENT_KEY$1}`;
638
+ const EVENT_COLLAPSED = `collapsed${EVENT_KEY$1}`;
639
+ const CLASS_NAME_SIDEBAR_MINI = 'sidebar-mini';
640
+ const CLASS_NAME_SIDEBAR_EXPAND = 'sidebar-expand';
641
+ const CLASS_NAME_SIDEBAR_OVERLAY = 'sidebar-overlay';
642
+ const CLASS_NAME_SIDEBAR_COLLAPSE = 'sidebar-collapse';
643
+ const CLASS_NAME_SIDEBAR_OPEN = 'sidebar-open';
644
+ const SELECTOR_APP_SIDEBAR = '.app-sidebar';
645
+ const SELECTOR_APP_WRAPPER = '.app-wrapper';
646
+ const SELECTOR_SIDEBAR_EXPAND = `[class*="${CLASS_NAME_SIDEBAR_EXPAND}"]`;
647
+ const SELECTOR_SIDEBAR_TOGGLE = '[data-lte-toggle="sidebar"]';
648
+ const STORAGE_KEY_SIDEBAR_STATE = 'lte.sidebar.state';
649
+ const Defaults = {
650
+ sidebarBreakpoint: 991.98,
651
+ enablePersistence: false
652
+ };
653
+ class PushMenu extends BaseComponent {
654
+ static get NAME() {
655
+ return NAME;
656
+ }
657
+ static getInstance(element) {
658
+ return this._getInstance(element);
659
+ }
660
+ static getOrCreateInstance(element, config = {}) {
661
+ return this.getInstance(element) ?? new this(element, config);
662
+ }
663
+ _config;
664
+ constructor(element, config = {}) {
665
+ super(element);
666
+ this._config = { ...Defaults, ...config };
667
+ }
668
+ isCollapsed() {
669
+ return document.body.classList.contains(CLASS_NAME_SIDEBAR_COLLAPSE);
670
+ }
671
+ isExplicitlyOpen() {
672
+ return document.body.classList.contains(CLASS_NAME_SIDEBAR_OPEN);
673
+ }
674
+ isMiniMode() {
675
+ return document.body.classList.contains(CLASS_NAME_SIDEBAR_MINI);
676
+ }
677
+ isMobileSize() {
678
+ return globalThis.innerWidth <= this._config.sidebarBreakpoint;
679
+ }
680
+ expand() {
681
+ if (dispatchCustomEvent(this._element, EVENT_OPEN, { cancelable: true }).defaultPrevented) {
682
+ return;
683
+ }
684
+ document.body.classList.remove(CLASS_NAME_SIDEBAR_COLLAPSE);
685
+ if (this.isMobileSize()) {
686
+ document.body.classList.add(CLASS_NAME_SIDEBAR_OPEN);
687
+ }
688
+ dispatchCustomEvent(this._element, EVENT_OPENED);
689
+ }
690
+ collapse() {
691
+ if (dispatchCustomEvent(this._element, EVENT_COLLAPSE, { cancelable: true }).defaultPrevented) {
692
+ return;
693
+ }
694
+ document.body.classList.remove(CLASS_NAME_SIDEBAR_OPEN);
695
+ document.body.classList.add(CLASS_NAME_SIDEBAR_COLLAPSE);
696
+ dispatchCustomEvent(this._element, EVENT_COLLAPSED);
697
+ }
698
+ toggle() {
699
+ const isCollapsed = this.isCollapsed();
700
+ if (isCollapsed) {
701
+ this.expand();
702
+ }
703
+ else {
704
+ this.collapse();
705
+ }
706
+ if (this._config.enablePersistence) {
707
+ this.saveSidebarState(isCollapsed ? CLASS_NAME_SIDEBAR_OPEN : CLASS_NAME_SIDEBAR_COLLAPSE);
708
+ }
709
+ }
710
+ setupSidebarBreakPoint() {
711
+ const sidebarExpand = document.querySelector(SELECTOR_SIDEBAR_EXPAND);
712
+ if (!sidebarExpand) {
713
+ return;
714
+ }
715
+ const content = globalThis.getComputedStyle(sidebarExpand, '::before')
716
+ .getPropertyValue('content');
717
+ if (!content || content === 'none') {
718
+ return;
719
+ }
720
+ const breakpointValue = Number(content.replace(/[^\d.-]/g, ''));
721
+ if (Number.isNaN(breakpointValue)) {
722
+ return;
723
+ }
724
+ this._config = { ...this._config, sidebarBreakpoint: breakpointValue };
725
+ }
726
+ updateStateByResponsiveLogic() {
727
+ if (this.isMobileSize()) {
728
+ if (!this.isExplicitlyOpen()) {
729
+ this.collapse();
730
+ }
731
+ }
732
+ else {
733
+ if (!(this.isMiniMode() && this.isCollapsed())) {
734
+ this.expand();
735
+ }
736
+ }
737
+ }
738
+ saveSidebarState(state) {
739
+ if (globalThis.localStorage === undefined) {
740
+ return;
741
+ }
742
+ try {
743
+ localStorage.setItem(STORAGE_KEY_SIDEBAR_STATE, state);
744
+ }
745
+ catch {
746
+ }
747
+ }
748
+ loadSidebarState() {
749
+ if (globalThis.localStorage === undefined) {
750
+ return;
751
+ }
752
+ try {
753
+ const storedState = localStorage.getItem(STORAGE_KEY_SIDEBAR_STATE);
754
+ if (storedState === CLASS_NAME_SIDEBAR_COLLAPSE) {
755
+ this.collapse();
756
+ }
757
+ else if (storedState === CLASS_NAME_SIDEBAR_OPEN) {
758
+ this.expand();
759
+ }
760
+ else {
761
+ this.updateStateByResponsiveLogic();
762
+ }
763
+ }
764
+ catch {
765
+ this.updateStateByResponsiveLogic();
766
+ }
767
+ }
768
+ clearSidebarState() {
769
+ if (globalThis.localStorage === undefined) {
770
+ return;
771
+ }
772
+ try {
773
+ localStorage.removeItem(STORAGE_KEY_SIDEBAR_STATE);
774
+ }
775
+ catch {
776
+ }
777
+ }
778
+ init() {
779
+ this.setupSidebarBreakPoint();
780
+ if (!this._config.enablePersistence) {
781
+ this.clearSidebarState();
782
+ }
783
+ if (this._config.enablePersistence && !this.isMobileSize()) {
784
+ this.loadSidebarState();
785
+ }
786
+ else if (!this.isCollapsed()) {
787
+ this.updateStateByResponsiveLogic();
788
+ }
789
+ }
790
+ }
791
+ document.addEventListener('click', event => {
792
+ const target = event.target;
793
+ if (!(target instanceof Element)) {
794
+ return;
795
+ }
796
+ const button = target.closest(SELECTOR_SIDEBAR_TOGGLE);
797
+ if (!button) {
798
+ return;
799
+ }
800
+ event.preventDefault();
801
+ const sidebar = document.querySelector(SELECTOR_APP_SIDEBAR);
802
+ if (sidebar) {
803
+ PushMenu.getOrCreateInstance(sidebar).toggle();
804
+ }
805
+ });
806
+ onDOMContentLoaded(() => {
807
+ const sidebar = document.querySelector(SELECTOR_APP_SIDEBAR);
808
+ if (!sidebar) {
809
+ return;
810
+ }
811
+ const sidebarBreakpointAttr = sidebar.dataset.sidebarBreakpoint;
812
+ const enablePersistenceAttr = sidebar.dataset.enablePersistence;
813
+ const config = {
814
+ sidebarBreakpoint: sidebarBreakpointAttr === undefined ?
815
+ Defaults.sidebarBreakpoint :
816
+ Number(sidebarBreakpointAttr),
817
+ enablePersistence: enablePersistenceAttr === undefined ?
818
+ Defaults.enablePersistence :
819
+ enablePersistenceAttr === 'true'
820
+ };
821
+ const pushMenu = PushMenu.getOrCreateInstance(sidebar, config);
822
+ pushMenu.init();
823
+ const breakpointQuery = globalThis.matchMedia(`(max-width: ${pushMenu._config.sidebarBreakpoint}px)`);
824
+ breakpointQuery.addEventListener('change', () => {
825
+ pushMenu.updateStateByResponsiveLogic();
826
+ }, { signal: getLifecycleSignal() });
827
+ const appWrapper = document.querySelector(SELECTOR_APP_WRAPPER);
828
+ let sidebarOverlay = appWrapper?.querySelector(`:scope > .${CLASS_NAME_SIDEBAR_OVERLAY}`);
829
+ if (!sidebarOverlay) {
830
+ sidebarOverlay = document.createElement('div');
831
+ sidebarOverlay.className = CLASS_NAME_SIDEBAR_OVERLAY;
832
+ appWrapper?.append(sidebarOverlay);
833
+ }
834
+ const overlaySignal = getLifecycleSignal();
835
+ let overlayTouchMoved = false;
836
+ sidebarOverlay.addEventListener('touchstart', () => {
837
+ overlayTouchMoved = false;
838
+ }, { passive: true, signal: overlaySignal });
839
+ sidebarOverlay.addEventListener('touchmove', () => {
840
+ overlayTouchMoved = true;
841
+ }, { passive: true, signal: overlaySignal });
842
+ sidebarOverlay.addEventListener('touchend', event => {
843
+ if (!overlayTouchMoved) {
844
+ event.preventDefault();
845
+ pushMenu.collapse();
846
+ }
847
+ overlayTouchMoved = false;
848
+ }, { passive: false, signal: overlaySignal });
849
+ sidebarOverlay.addEventListener('click', event => {
850
+ event.preventDefault();
851
+ pushMenu.collapse();
852
+ }, { signal: overlaySignal });
853
+ });
854
+
855
+ const DATA_KEY = 'lte.color-mode';
856
+ const EVENT_KEY = `.${DATA_KEY}`;
857
+ const EVENT_CHANGED = `changed${EVENT_KEY}`;
858
+ const STORAGE_KEY = 'lte-theme';
859
+ const ATTRIBUTE_THEME = 'data-bs-theme';
860
+ const ATTRIBUTE_TOGGLE = 'data-bs-theme-value';
861
+ const ATTRIBUTE_DISABLED = 'data-lte-color-mode';
862
+ const ATTRIBUTE_RESOLVED = 'data-lte-theme-resolved';
863
+ const SELECTOR_TOGGLE = `[${ATTRIBUTE_TOGGLE}]`;
864
+ const SELECTOR_ICON = '[data-lte-theme-icon]';
865
+ const THEMES = new Set(['light', 'dark', 'auto']);
866
+ const isValidTheme = (value) => THEMES.has(value);
867
+ const isDisabled = () => document.documentElement.getAttribute(ATTRIBUTE_DISABLED) === 'off';
868
+ const readMarkupTheme = () => {
869
+ const { documentElement } = document;
870
+ if (documentElement.hasAttribute(ATTRIBUTE_RESOLVED)) {
871
+ return null;
872
+ }
873
+ const declared = documentElement.getAttribute(ATTRIBUTE_THEME);
874
+ return declared && isValidTheme(declared) ? declared : null;
875
+ };
876
+ const MARKUP_THEME = readMarkupTheme();
877
+ class ColorMode {
878
+ getStoredTheme() {
879
+ try {
880
+ const stored = localStorage.getItem(STORAGE_KEY);
881
+ return stored && isValidTheme(stored) ? stored : null;
882
+ }
883
+ catch {
884
+ return null;
885
+ }
886
+ }
887
+ getMarkupTheme() {
888
+ return MARKUP_THEME;
889
+ }
890
+ getPreferredTheme() {
891
+ const preferred = this.getStoredTheme() ?? this.getMarkupTheme();
892
+ if (preferred) {
893
+ return preferred;
894
+ }
895
+ return this._prefersDark() ? 'dark' : 'light';
896
+ }
897
+ resolveTheme(theme) {
898
+ if (theme === 'auto') {
899
+ return this._prefersDark() ? 'dark' : 'light';
900
+ }
901
+ return theme;
902
+ }
903
+ setTheme(theme) {
904
+ try {
905
+ localStorage.setItem(STORAGE_KEY, theme);
906
+ }
907
+ catch {
908
+ }
909
+ this._applyTheme(theme);
910
+ this._showActiveTheme(theme);
911
+ document.dispatchEvent(new CustomEvent(EVENT_CHANGED, {
912
+ detail: { theme, resolved: this.resolveTheme(theme) }
913
+ }));
914
+ }
915
+ _applyTheme(theme) {
916
+ const resolved = this.resolveTheme(theme);
917
+ document.documentElement.setAttribute(ATTRIBUTE_THEME, resolved);
918
+ document.documentElement.style.colorScheme = resolved;
919
+ }
920
+ _prefersDark() {
921
+ return globalThis.matchMedia('(prefers-color-scheme: dark)').matches;
922
+ }
923
+ _showActiveTheme(theme) {
924
+ document.querySelectorAll(SELECTOR_TOGGLE).forEach(toggle => {
925
+ const isActive = toggle.getAttribute(ATTRIBUTE_TOGGLE) === theme;
926
+ toggle.classList.toggle('active', isActive);
927
+ toggle.setAttribute('aria-pressed', String(isActive));
928
+ toggle.querySelector('.bi-check-lg')?.classList.toggle('d-none', !isActive);
929
+ });
930
+ document.querySelectorAll(SELECTOR_ICON).forEach(icon => {
931
+ icon.classList.toggle('d-none', icon.dataset.lteThemeIcon !== theme);
932
+ });
933
+ }
934
+ init() {
935
+ if (isDisabled()) {
936
+ return;
937
+ }
938
+ const theme = this.getPreferredTheme();
939
+ this._applyTheme(theme);
940
+ this._showActiveTheme(theme);
941
+ }
942
+ }
943
+ document.addEventListener('click', event => {
944
+ const target = event.target;
945
+ if (!(target instanceof Element) || isDisabled()) {
946
+ return;
947
+ }
948
+ const toggle = target.closest(SELECTOR_TOGGLE);
949
+ const theme = toggle?.getAttribute(ATTRIBUTE_TOGGLE);
950
+ if (theme && isValidTheme(theme)) {
951
+ new ColorMode().setTheme(theme);
952
+ }
953
+ });
954
+ onDOMContentLoaded(() => {
955
+ const colorMode = new ColorMode();
956
+ colorMode.init();
957
+ globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
958
+ if (isDisabled()) {
959
+ return;
960
+ }
961
+ const preferred = colorMode.getStoredTheme() ?? colorMode.getMarkupTheme();
962
+ if (!preferred || preferred === 'auto') {
963
+ colorMode._applyTheme('auto');
964
+ colorMode._showActiveTheme(preferred ?? 'auto');
965
+ }
966
+ }, { signal: getLifecycleSignal() });
967
+ });
968
+
969
+ class AccessibilityManager {
970
+ config;
971
+ liveRegion = null;
972
+ focusHistory = [];
973
+ signal = getLifecycleSignal();
974
+ constructor(config = {}) {
975
+ this.config = {
976
+ announcements: true,
977
+ skipLinks: true,
978
+ focusManagement: true,
979
+ keyboardNavigation: true,
980
+ reducedMotion: true,
981
+ ...config
982
+ };
983
+ this.init();
984
+ }
985
+ init() {
986
+ if (this.config.announcements) {
987
+ this.createLiveRegion();
988
+ }
989
+ if (this.config.skipLinks) {
990
+ this.addSkipLinks();
991
+ }
992
+ if (this.config.focusManagement) {
993
+ this.initFocusManagement();
994
+ }
995
+ if (this.config.keyboardNavigation) {
996
+ this.initKeyboardNavigation();
997
+ }
998
+ if (this.config.reducedMotion) {
999
+ this.respectReducedMotion();
1000
+ }
1001
+ this.initErrorAnnouncements();
1002
+ this.initTableAccessibility();
1003
+ this.initFormAccessibility();
1004
+ }
1005
+ createLiveRegion() {
1006
+ if (this.liveRegion)
1007
+ return;
1008
+ const existingRegion = document.getElementById('live-region');
1009
+ if (existingRegion) {
1010
+ this.liveRegion = existingRegion;
1011
+ return;
1012
+ }
1013
+ this.liveRegion = document.createElement('div');
1014
+ this.liveRegion.id = 'live-region';
1015
+ this.liveRegion.className = 'live-region';
1016
+ this.liveRegion.setAttribute('aria-live', 'polite');
1017
+ this.liveRegion.setAttribute('aria-atomic', 'true');
1018
+ this.liveRegion.setAttribute('role', 'status');
1019
+ document.body.append(this.liveRegion);
1020
+ }
1021
+ addSkipLinks() {
1022
+ if (document.querySelector('.skip-links')) {
1023
+ this.ensureSkipTargets();
1024
+ return;
1025
+ }
1026
+ const skipLinksContainer = document.createElement('div');
1027
+ skipLinksContainer.className = 'skip-links';
1028
+ const skipToMain = document.createElement('a');
1029
+ skipToMain.href = '#main';
1030
+ skipToMain.className = 'skip-link';
1031
+ skipToMain.textContent = 'Skip to main content';
1032
+ const skipToNav = document.createElement('a');
1033
+ skipToNav.href = '#navigation';
1034
+ skipToNav.className = 'skip-link';
1035
+ skipToNav.textContent = 'Skip to navigation';
1036
+ skipLinksContainer.append(skipToMain);
1037
+ skipLinksContainer.append(skipToNav);
1038
+ document.body.insertBefore(skipLinksContainer, document.body.firstChild);
1039
+ this.ensureSkipTargets();
1040
+ }
1041
+ ensureSkipTargets() {
1042
+ const main = document.querySelector('#main, main, [role="main"]');
1043
+ if (main && !main.id) {
1044
+ main.id = 'main';
1045
+ }
1046
+ if (main && !main.hasAttribute('tabindex')) {
1047
+ main.setAttribute('tabindex', '-1');
1048
+ }
1049
+ const nav = document.querySelector('#navigation, nav, [role="navigation"]');
1050
+ if (nav && !nav.id) {
1051
+ nav.id = 'navigation';
1052
+ }
1053
+ if (nav && !nav.hasAttribute('tabindex')) {
1054
+ nav.setAttribute('tabindex', '-1');
1055
+ }
1056
+ }
1057
+ initFocusManagement() {
1058
+ document.addEventListener('keydown', (event) => {
1059
+ if (event.key === 'Escape') {
1060
+ this.handleEscapeKey(event);
1061
+ }
1062
+ }, { signal: this.signal });
1063
+ this.initModalFocusManagement();
1064
+ this.initDropdownFocusManagement();
1065
+ }
1066
+ handleEscapeKey(event) {
1067
+ const activeModal = document.querySelector('.modal.show');
1068
+ if (activeModal) {
1069
+ return;
1070
+ }
1071
+ const activeDropdown = document.querySelector('.dropdown-menu.show');
1072
+ if (activeDropdown) {
1073
+ const toggleButton = document.querySelector('[data-bs-toggle="dropdown"][aria-expanded="true"]');
1074
+ toggleButton?.click();
1075
+ event.preventDefault();
1076
+ }
1077
+ }
1078
+ initKeyboardNavigation() {
1079
+ document.addEventListener('keydown', (event) => {
1080
+ const target = event.target;
1081
+ if (target.matches('input, textarea, select, [contenteditable], [contenteditable] *')) {
1082
+ return;
1083
+ }
1084
+ if (target.closest('.nav, .navbar-nav, .dropdown-menu')) {
1085
+ this.handleMenuNavigation(event);
1086
+ }
1087
+ if ((event.key === 'Enter' || event.key === ' ') && target.hasAttribute('role') && target.getAttribute('role') === 'button' && !target.matches('button, input[type="button"], input[type="submit"]')) {
1088
+ event.preventDefault();
1089
+ target.click();
1090
+ }
1091
+ }, { signal: this.signal });
1092
+ }
1093
+ handleMenuNavigation(event) {
1094
+ if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
1095
+ return;
1096
+ }
1097
+ const currentElement = event.target;
1098
+ const menuItems = Array.from(currentElement.closest('.nav, .navbar-nav, .dropdown-menu')?.querySelectorAll('a, button') || [])
1099
+ .filter(item => item.offsetParent !== null);
1100
+ const currentIndex = menuItems.indexOf(currentElement);
1101
+ if (currentIndex === -1) {
1102
+ return;
1103
+ }
1104
+ let nextIndex;
1105
+ switch (event.key) {
1106
+ case 'ArrowDown':
1107
+ case 'ArrowRight': {
1108
+ nextIndex = currentIndex < menuItems.length - 1 ? currentIndex + 1 : 0;
1109
+ break;
1110
+ }
1111
+ case 'ArrowUp':
1112
+ case 'ArrowLeft': {
1113
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : menuItems.length - 1;
1114
+ break;
1115
+ }
1116
+ case 'Home': {
1117
+ nextIndex = 0;
1118
+ break;
1119
+ }
1120
+ case 'End': {
1121
+ nextIndex = menuItems.length - 1;
1122
+ break;
1123
+ }
1124
+ default: {
1125
+ return;
1126
+ }
1127
+ }
1128
+ event.preventDefault();
1129
+ menuItems[nextIndex]?.focus();
1130
+ }
1131
+ respectReducedMotion() {
1132
+ const prefersReducedMotion = globalThis.matchMedia('(prefers-reduced-motion: reduce)').matches;
1133
+ if (prefersReducedMotion) {
1134
+ document.body.classList.add('reduce-motion');
1135
+ document.documentElement.style.scrollBehavior = 'auto';
1136
+ if (!document.getElementById('adminlte-reduce-motion')) {
1137
+ const style = document.createElement('style');
1138
+ style.id = 'adminlte-reduce-motion';
1139
+ style.textContent = `
1140
+ *, *::before, *::after {
1141
+ animation-duration: 0.01ms !important;
1142
+ animation-iteration-count: 1 !important;
1143
+ transition-duration: 0.01ms !important;
1144
+ }
1145
+ `;
1146
+ document.head.append(style);
1147
+ }
1148
+ }
1149
+ }
1150
+ initErrorAnnouncements() {
1151
+ const observer = new MutationObserver((mutations) => {
1152
+ mutations.forEach((mutation) => {
1153
+ mutation.addedNodes.forEach((node) => {
1154
+ if (node.nodeType === Node.ELEMENT_NODE) {
1155
+ const element = node;
1156
+ if (element.matches('.alert-danger, .invalid-feedback, .error')) {
1157
+ this.announce(element.textContent || 'Error occurred', 'assertive');
1158
+ }
1159
+ if (element.matches('.alert-success, .success')) {
1160
+ this.announce(element.textContent || 'Success', 'polite');
1161
+ }
1162
+ }
1163
+ });
1164
+ });
1165
+ });
1166
+ observer.observe(document.body, {
1167
+ childList: true,
1168
+ subtree: true
1169
+ });
1170
+ this.signal.addEventListener('abort', () => {
1171
+ observer.disconnect();
1172
+ }, { once: true });
1173
+ }
1174
+ initTableAccessibility() {
1175
+ document.querySelectorAll('table').forEach((table) => {
1176
+ if (!table.hasAttribute('role')) {
1177
+ table.setAttribute('role', 'table');
1178
+ }
1179
+ table.querySelectorAll('th').forEach((th) => {
1180
+ if (!th.hasAttribute('scope')) {
1181
+ const isInThead = th.closest('thead');
1182
+ const isFirstColumn = th.cellIndex === 0;
1183
+ if (isInThead) {
1184
+ th.setAttribute('scope', 'col');
1185
+ }
1186
+ else if (isFirstColumn) {
1187
+ th.setAttribute('scope', 'row');
1188
+ }
1189
+ }
1190
+ });
1191
+ if (!table.querySelector('caption') && table.hasAttribute('title')) {
1192
+ const caption = document.createElement('caption');
1193
+ caption.textContent = table.getAttribute('title') || '';
1194
+ table.insertBefore(caption, table.firstChild);
1195
+ }
1196
+ });
1197
+ }
1198
+ initFormAccessibility() {
1199
+ document.querySelectorAll('input, select, textarea').forEach((input) => {
1200
+ const htmlInput = input;
1201
+ if (!htmlInput.labels?.length && !htmlInput.hasAttribute('aria-label') && !htmlInput.hasAttribute('aria-labelledby')) {
1202
+ const placeholder = htmlInput.getAttribute('placeholder');
1203
+ if (placeholder) {
1204
+ htmlInput.setAttribute('aria-label', placeholder);
1205
+ }
1206
+ }
1207
+ if (htmlInput.hasAttribute('required')) {
1208
+ const label = htmlInput.labels?.[0];
1209
+ if (label && !label.querySelector('.required-indicator')) {
1210
+ const indicator = document.createElement('span');
1211
+ indicator.className = 'required-indicator sr-only';
1212
+ indicator.textContent = ' (required)';
1213
+ label.append(indicator);
1214
+ }
1215
+ }
1216
+ if (!htmlInput.classList.contains('disable-adminlte-validations')) {
1217
+ htmlInput.addEventListener('invalid', () => {
1218
+ this.handleFormError(htmlInput);
1219
+ }, { signal: this.signal });
1220
+ }
1221
+ });
1222
+ }
1223
+ handleFormError(input) {
1224
+ if (!input.id && !input.name) {
1225
+ input.id = accessibilityUtils.generateId('field');
1226
+ }
1227
+ const errorId = `${input.id || input.name}-error`;
1228
+ let errorElement = document.getElementById(errorId);
1229
+ if (!errorElement) {
1230
+ errorElement = document.createElement('div');
1231
+ errorElement.id = errorId;
1232
+ errorElement.className = 'invalid-feedback';
1233
+ errorElement.setAttribute('role', 'alert');
1234
+ input.parentNode?.append(errorElement);
1235
+ }
1236
+ errorElement.textContent = input.validationMessage;
1237
+ const describedBy = (input.getAttribute('aria-describedby') || '').split(/\s+/).filter(Boolean);
1238
+ if (!describedBy.includes(errorId)) {
1239
+ describedBy.push(errorId);
1240
+ }
1241
+ input.setAttribute('aria-describedby', describedBy.join(' '));
1242
+ input.classList.add('is-invalid');
1243
+ this.announce(`Error in ${input.labels?.[0]?.textContent || input.name}: ${input.validationMessage}`, 'assertive');
1244
+ }
1245
+ initModalFocusManagement() {
1246
+ document.addEventListener('show.bs.modal', () => {
1247
+ this.focusHistory.push(document.activeElement);
1248
+ }, { signal: this.signal });
1249
+ document.addEventListener('shown.bs.modal', (event) => {
1250
+ const modal = event.target;
1251
+ const autofocusElement = modal.querySelector('[autofocus]');
1252
+ const firstFocusable = autofocusElement ||
1253
+ modal.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
1254
+ firstFocusable?.focus();
1255
+ }, { signal: this.signal });
1256
+ document.addEventListener('hidden.bs.modal', () => {
1257
+ const previousElement = this.focusHistory.pop();
1258
+ if (previousElement?.isConnected) {
1259
+ previousElement.focus();
1260
+ }
1261
+ }, { signal: this.signal });
1262
+ }
1263
+ initDropdownFocusManagement() {
1264
+ document.addEventListener('shown.bs.dropdown', (event) => {
1265
+ const dropdown = event.target;
1266
+ const menu = dropdown.querySelector('.dropdown-menu');
1267
+ const firstItem = menu?.querySelector('a, button');
1268
+ if (firstItem) {
1269
+ firstItem.focus();
1270
+ }
1271
+ }, { signal: this.signal });
1272
+ }
1273
+ announce(message, priority = 'polite') {
1274
+ if (!this.liveRegion) {
1275
+ this.createLiveRegion();
1276
+ }
1277
+ if (this.liveRegion) {
1278
+ this.liveRegion.setAttribute('aria-live', priority);
1279
+ this.liveRegion.textContent = message;
1280
+ setTimeout(() => {
1281
+ if (this.liveRegion) {
1282
+ this.liveRegion.textContent = '';
1283
+ }
1284
+ }, 1000);
1285
+ }
1286
+ }
1287
+ focusElement(selector) {
1288
+ const element = document.querySelector(selector);
1289
+ if (element) {
1290
+ element.focus();
1291
+ element.scrollIntoView({ behavior: 'smooth', block: 'center' });
1292
+ }
1293
+ }
1294
+ trapFocus(container) {
1295
+ const focusableElements = container.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
1296
+ const focusableArray = Array.from(focusableElements);
1297
+ const firstElement = focusableArray[0];
1298
+ const lastElement = focusableArray.at(-1);
1299
+ container.addEventListener('keydown', (event) => {
1300
+ if (event.key === 'Tab') {
1301
+ if (event.shiftKey) {
1302
+ if (document.activeElement === firstElement) {
1303
+ lastElement?.focus();
1304
+ event.preventDefault();
1305
+ }
1306
+ }
1307
+ else if (document.activeElement === lastElement) {
1308
+ firstElement.focus();
1309
+ event.preventDefault();
1310
+ }
1311
+ }
1312
+ }, { signal: this.signal });
1313
+ }
1314
+ addLandmarks() {
1315
+ const main = document.querySelector('main');
1316
+ if (!main) {
1317
+ const appMain = document.querySelector('.app-main');
1318
+ if (appMain) {
1319
+ appMain.setAttribute('role', 'main');
1320
+ if (!appMain.id) {
1321
+ appMain.id = 'main';
1322
+ }
1323
+ }
1324
+ }
1325
+ document.querySelectorAll('.navbar-nav, .nav').forEach((nav, index) => {
1326
+ if (nav.tagName === 'UL' || nav.tagName === 'OL') {
1327
+ return;
1328
+ }
1329
+ if (!nav.hasAttribute('role')) {
1330
+ nav.setAttribute('role', 'navigation');
1331
+ }
1332
+ if (!nav.hasAttribute('aria-label')) {
1333
+ nav.setAttribute('aria-label', `Navigation ${index + 1}`);
1334
+ }
1335
+ });
1336
+ const searchForm = document.querySelector('form[role="search"], .navbar-search');
1337
+ if (searchForm && !searchForm.hasAttribute('role')) {
1338
+ searchForm.setAttribute('role', 'search');
1339
+ }
1340
+ }
1341
+ }
1342
+ const initAccessibility = (config) => {
1343
+ return new AccessibilityManager(config);
1344
+ };
1345
+ const parseColorChannels = (color) => {
1346
+ const hexMatch = /^#([\da-f]{3}|[\da-f]{6})$/i.exec(color.trim());
1347
+ if (hexMatch) {
1348
+ let hex = hexMatch[1];
1349
+ if (hex.length === 3) {
1350
+ hex = [...hex].map(character => character + character).join('');
1351
+ }
1352
+ return [
1353
+ Number.parseInt(hex.slice(0, 2), 16),
1354
+ Number.parseInt(hex.slice(2, 4), 16),
1355
+ Number.parseInt(hex.slice(4, 6), 16)
1356
+ ];
1357
+ }
1358
+ return color.match(/\d+/g)?.map(Number) || [0, 0, 0];
1359
+ };
1360
+ const getLuminance = (color) => {
1361
+ const [r, g, b] = parseColorChannels(color).map(c => {
1362
+ c = c / 255;
1363
+ return c <= 0.039_28 ? c / 12.92 : (c + 0.055) ** 2.4 / (1.055 ** 2.4);
1364
+ });
1365
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
1366
+ };
1367
+ const accessibilityUtils = {
1368
+ checkColorContrast: (foreground, background) => {
1369
+ const l1 = getLuminance(foreground);
1370
+ const l2 = getLuminance(background);
1371
+ const ratio = (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
1372
+ return {
1373
+ ratio: Math.round(ratio * 100) / 100,
1374
+ passes: ratio >= 4.5
1375
+ };
1376
+ },
1377
+ generateId: (prefix = 'a11y') => {
1378
+ return `${prefix}-${Math.random().toString(36).slice(2, 11)}`;
1379
+ },
1380
+ isFocusable: (element) => {
1381
+ const focusableSelectors = [
1382
+ 'a[href]',
1383
+ 'button:not([disabled])',
1384
+ 'input:not([disabled])',
1385
+ 'select:not([disabled])',
1386
+ 'textarea:not([disabled])',
1387
+ '[tabindex]:not([tabindex="-1"])',
1388
+ '[contenteditable="true"]'
1389
+ ];
1390
+ return focusableSelectors.some(selector => element.matches(selector));
1391
+ }
1392
+ };
1393
+
1394
+ onDOMContentLoaded(() => {
1395
+ const accessibilityManager = initAccessibility({
1396
+ announcements: true,
1397
+ skipLinks: true,
1398
+ focusManagement: true,
1399
+ keyboardNavigation: true,
1400
+ reducedMotion: true
1401
+ });
1402
+ accessibilityManager.addLandmarks();
1403
+ });
1404
+
1405
+ export { CardWidget, ColorMode, DirectChat, FullScreen, Layout, PushMenu, Treeview, initAccessibility, initialize, teardown };
1406
+ //# sourceMappingURL=adminlte.esm.js.map