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