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