@incursa/ui-kit 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI-AGENT-INSTRUCTIONS.md +42 -28
- package/LLMS.txt +56 -40
- package/README.md +190 -73
- package/dist/inc-design-language.css +430 -247
- package/dist/inc-design-language.css.map +1 -1
- package/dist/inc-design-language.js +520 -0
- package/dist/inc-design-language.min.css +1 -1
- package/dist/inc-design-language.min.css.map +1 -1
- package/dist/web-components/README.md +92 -0
- package/dist/web-components/RUNTIME-NOTES.md +40 -0
- package/dist/web-components/base-element.js +193 -0
- package/dist/web-components/components/feedback.js +1074 -0
- package/dist/web-components/components/forms.js +979 -0
- package/dist/web-components/components/layout.js +408 -0
- package/dist/web-components/components/navigation.js +854 -0
- package/dist/web-components/components/overlays.js +634 -0
- package/dist/web-components/controllers/focus.js +101 -0
- package/dist/web-components/controllers/overlay.js +128 -0
- package/dist/web-components/controllers/selection.js +145 -0
- package/dist/web-components/controllers/theme.js +173 -0
- package/dist/web-components/index.js +886 -0
- package/dist/web-components/package.json +3 -0
- package/dist/web-components/registry.js +74 -0
- package/dist/web-components/shared.js +186 -0
- package/dist/web-components/style.css +6 -0
- package/package.json +16 -4
- package/src/inc-design-language.js +520 -0
- package/src/inc-design-language.scss +456 -257
- package/src/web-components/README.md +92 -0
- package/src/web-components/RUNTIME-NOTES.md +40 -0
- package/src/web-components/base-element.js +193 -0
- package/src/web-components/components/feedback.js +1074 -0
- package/src/web-components/components/forms.js +979 -0
- package/src/web-components/components/layout.js +408 -0
- package/src/web-components/components/navigation.js +854 -0
- package/src/web-components/components/overlays.js +634 -0
- package/src/web-components/controllers/focus.js +101 -0
- package/src/web-components/controllers/overlay.js +128 -0
- package/src/web-components/controllers/selection.js +145 -0
- package/src/web-components/controllers/theme.js +173 -0
- package/src/web-components/index.js +886 -0
- package/src/web-components/package.json +3 -0
- package/src/web-components/registry.js +74 -0
- package/src/web-components/shared.js +186 -0
- package/src/web-components/style.css +6 -0
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
menu: ".inc-dropdown__menu",
|
|
7
7
|
collapseToggle: '[data-inc-toggle="collapse"]',
|
|
8
8
|
tabToggle: '[data-inc-toggle="tab"]',
|
|
9
|
+
themeMode: "[data-inc-theme-mode]:not(html)",
|
|
10
|
+
themeToggle: "[data-inc-theme-toggle]",
|
|
11
|
+
themeSelect: "[data-inc-theme-select]",
|
|
12
|
+
themeLabel: "[data-inc-theme-label]",
|
|
13
|
+
themeSwitcher: "[data-inc-theme-switcher], details.inc-theme-switcher",
|
|
9
14
|
nativeDialogOpen: "[data-inc-native-dialog-open]",
|
|
10
15
|
autoRefresh: "[data-inc-auto-refresh]",
|
|
11
16
|
autoRefreshToggle: '[data-inc-action="auto-refresh-toggle"]',
|
|
@@ -30,6 +35,411 @@
|
|
|
30
35
|
|
|
31
36
|
const autoRefreshControllers = [];
|
|
32
37
|
let autoRefreshReloadScheduled = false;
|
|
38
|
+
const themeModes = ["light", "dark", "system"];
|
|
39
|
+
const themeDescriptions = {
|
|
40
|
+
light: "Use the brighter application palette.",
|
|
41
|
+
dark: "Use the darker application palette.",
|
|
42
|
+
system: "Match the device preference automatically.",
|
|
43
|
+
};
|
|
44
|
+
const themeStorageKey = "inc-theme-mode";
|
|
45
|
+
const themeState = {
|
|
46
|
+
mode: "system",
|
|
47
|
+
resolved: "light",
|
|
48
|
+
};
|
|
49
|
+
let themeMediaQuery = null;
|
|
50
|
+
let themeMediaListenerBound = false;
|
|
51
|
+
let themeStorageListenerBound = false;
|
|
52
|
+
let themeInitialized = false;
|
|
53
|
+
|
|
54
|
+
function isThemeMode(value) {
|
|
55
|
+
return themeModes.includes(value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getThemeLabel(mode) {
|
|
59
|
+
if (!isThemeMode(mode)) {
|
|
60
|
+
return "System";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getThemeStatusLabel(mode = themeState.mode, resolved = themeState.resolved) {
|
|
67
|
+
return mode === "system"
|
|
68
|
+
? `${getThemeLabel(mode)} (${getThemeLabel(resolved)})`
|
|
69
|
+
: getThemeLabel(mode);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getStoredThemeMode() {
|
|
73
|
+
try {
|
|
74
|
+
const stored = window.localStorage.getItem(themeStorageKey);
|
|
75
|
+
return isThemeMode(stored) ? stored : null;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getConfiguredThemeMode() {
|
|
82
|
+
const root = document.documentElement;
|
|
83
|
+
|
|
84
|
+
return root.getAttribute("data-inc-theme-mode")
|
|
85
|
+
|| root.dataset.incThemeMode
|
|
86
|
+
|| root.getAttribute("data-bs-theme")
|
|
87
|
+
|| "system";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function persistThemeMode(mode) {
|
|
91
|
+
try {
|
|
92
|
+
if (mode === "system") {
|
|
93
|
+
window.localStorage.removeItem(themeStorageKey);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
window.localStorage.setItem(themeStorageKey, mode);
|
|
98
|
+
} catch {
|
|
99
|
+
// Ignore storage failures in private mode or restricted contexts.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getSystemTheme() {
|
|
104
|
+
if (!window.matchMedia) {
|
|
105
|
+
return "light";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function resolveThemeMode(mode) {
|
|
112
|
+
return mode === "system" ? getSystemTheme() : mode;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function syncThemeControls(mode, resolved) {
|
|
116
|
+
document.querySelectorAll(selectors.themeMode).forEach((control) => {
|
|
117
|
+
if (!(control instanceof HTMLElement)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const controlMode = control.getAttribute("data-inc-theme-mode");
|
|
122
|
+
const isSelected = controlMode === mode;
|
|
123
|
+
const role = control.getAttribute("role");
|
|
124
|
+
|
|
125
|
+
control.classList.toggle("active", isSelected);
|
|
126
|
+
control.classList.toggle("is-selected", isSelected);
|
|
127
|
+
|
|
128
|
+
if (role === "menuitemradio" || role === "radio") {
|
|
129
|
+
control.setAttribute("aria-checked", isSelected ? "true" : "false");
|
|
130
|
+
} else if (control.tagName === "BUTTON" || control.tagName === "A") {
|
|
131
|
+
control.setAttribute("aria-pressed", isSelected ? "true" : "false");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (control.tagName === "INPUT" && (control.type === "radio" || control.type === "checkbox")) {
|
|
135
|
+
control.checked = isSelected;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (control.tagName === "OPTION") {
|
|
139
|
+
control.selected = isSelected;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
document.querySelectorAll(selectors.themeSelect).forEach((control) => {
|
|
144
|
+
if (control instanceof HTMLSelectElement) {
|
|
145
|
+
control.value = mode;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
document.querySelectorAll(selectors.themeLabel).forEach((label) => {
|
|
150
|
+
if (!(label instanceof HTMLElement)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const labelType = label.getAttribute("data-inc-theme-label") || "status";
|
|
155
|
+
|
|
156
|
+
if (labelType === "resolved") {
|
|
157
|
+
label.textContent = getThemeLabel(resolved);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (labelType === "mode") {
|
|
162
|
+
label.textContent = getThemeLabel(mode);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
label.textContent = getThemeStatusLabel(mode, resolved);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
document.querySelectorAll(selectors.themeSwitcher).forEach((switcher) => {
|
|
170
|
+
if (!(switcher instanceof HTMLElement)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
switcher.dataset.incThemeModeState = mode;
|
|
175
|
+
switcher.dataset.incThemeResolved = resolved;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function publishThemeChange() {
|
|
180
|
+
document.documentElement.dispatchEvent(new CustomEvent("inc-theme-change", {
|
|
181
|
+
bubbles: true,
|
|
182
|
+
composed: true,
|
|
183
|
+
detail: {
|
|
184
|
+
mode: themeState.mode,
|
|
185
|
+
resolved: themeState.resolved,
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function applyThemeMode(mode, options = {}) {
|
|
191
|
+
const nextMode = isThemeMode(mode) ? mode : "system";
|
|
192
|
+
const resolved = resolveThemeMode(nextMode);
|
|
193
|
+
const root = document.documentElement;
|
|
194
|
+
|
|
195
|
+
themeState.mode = nextMode;
|
|
196
|
+
themeState.resolved = resolved;
|
|
197
|
+
|
|
198
|
+
root.setAttribute("data-inc-theme-mode", nextMode);
|
|
199
|
+
root.setAttribute("data-bs-theme", resolved);
|
|
200
|
+
root.style.colorScheme = resolved;
|
|
201
|
+
root.dataset.incThemeModeState = nextMode;
|
|
202
|
+
root.dataset.incThemeResolved = resolved;
|
|
203
|
+
|
|
204
|
+
if (options.persist !== false) {
|
|
205
|
+
persistThemeMode(nextMode);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (options.syncControls !== false) {
|
|
209
|
+
syncThemeControls(nextMode, resolved);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (options.dispatch !== false) {
|
|
213
|
+
publishThemeChange();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return themeState;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function cycleThemeMode() {
|
|
220
|
+
const currentIndex = themeModes.indexOf(themeState.mode);
|
|
221
|
+
const nextMode = themeModes[(currentIndex + 1) % themeModes.length];
|
|
222
|
+
|
|
223
|
+
return applyThemeMode(nextMode);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createThemeSwitcherOption(mode) {
|
|
227
|
+
const button = document.createElement("button");
|
|
228
|
+
const body = document.createElement("span");
|
|
229
|
+
const label = document.createElement("span");
|
|
230
|
+
const detail = document.createElement("span");
|
|
231
|
+
|
|
232
|
+
button.type = "button";
|
|
233
|
+
button.className = "inc-theme-switcher__option";
|
|
234
|
+
button.setAttribute("data-inc-theme-mode", mode);
|
|
235
|
+
button.setAttribute("role", "menuitemradio");
|
|
236
|
+
|
|
237
|
+
body.className = "inc-theme-switcher__option-body";
|
|
238
|
+
label.className = "inc-theme-switcher__option-label";
|
|
239
|
+
label.textContent = getThemeLabel(mode);
|
|
240
|
+
detail.className = "inc-theme-switcher__option-detail";
|
|
241
|
+
detail.textContent = themeDescriptions[mode];
|
|
242
|
+
|
|
243
|
+
body.append(label, detail);
|
|
244
|
+
button.append(body);
|
|
245
|
+
|
|
246
|
+
return button;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function createThemeSwitcher(options = {}) {
|
|
250
|
+
const switcher = document.createElement("details");
|
|
251
|
+
const summary = document.createElement("summary");
|
|
252
|
+
const meta = document.createElement("span");
|
|
253
|
+
const label = document.createElement("span");
|
|
254
|
+
const status = document.createElement("span");
|
|
255
|
+
const panel = document.createElement("div");
|
|
256
|
+
const header = document.createElement("div");
|
|
257
|
+
|
|
258
|
+
switcher.className = "inc-native-menu inc-theme-switcher";
|
|
259
|
+
|
|
260
|
+
if (options.variant === "navbar") {
|
|
261
|
+
switcher.classList.add("inc-native-menu--navbar");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (options.block) {
|
|
265
|
+
switcher.classList.add("inc-native-menu--block");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
summary.className = "inc-native-menu__summary inc-theme-switcher__summary";
|
|
269
|
+
meta.className = "inc-theme-switcher__meta";
|
|
270
|
+
label.className = "inc-theme-switcher__label";
|
|
271
|
+
label.textContent = options.label || "Theme";
|
|
272
|
+
status.className = "inc-theme-switcher__status";
|
|
273
|
+
status.setAttribute("data-inc-theme-label", "status");
|
|
274
|
+
status.textContent = getThemeStatusLabel();
|
|
275
|
+
meta.append(label, status);
|
|
276
|
+
summary.append(meta);
|
|
277
|
+
|
|
278
|
+
panel.className = "inc-native-menu__panel inc-theme-switcher__panel";
|
|
279
|
+
panel.setAttribute("role", "menu");
|
|
280
|
+
panel.setAttribute("aria-label", options.menuLabel || "Theme");
|
|
281
|
+
|
|
282
|
+
header.className = "inc-native-menu__header";
|
|
283
|
+
header.textContent = options.heading || "Choose appearance";
|
|
284
|
+
panel.append(header);
|
|
285
|
+
|
|
286
|
+
themeModes.forEach((mode) => {
|
|
287
|
+
panel.append(createThemeSwitcherOption(mode));
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
switcher.append(summary, panel);
|
|
291
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
292
|
+
|
|
293
|
+
return switcher;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function mountThemeSwitcher(target, options = {}) {
|
|
297
|
+
let host = target;
|
|
298
|
+
|
|
299
|
+
if (typeof target === "string") {
|
|
300
|
+
host = document.querySelector(target);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!(host instanceof HTMLElement)) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const switcher = createThemeSwitcher(options);
|
|
308
|
+
host.replaceChildren(switcher);
|
|
309
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
310
|
+
|
|
311
|
+
return switcher;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function getThemeSwitcherOptions(control) {
|
|
315
|
+
const panel = control.closest(".inc-theme-switcher__panel");
|
|
316
|
+
|
|
317
|
+
if (!panel) {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return Array.from(panel.querySelectorAll(selectors.themeMode)).filter((option) => option.closest(".inc-theme-switcher__panel") === panel);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function focusThemeSwitcherOption(control, direction) {
|
|
325
|
+
const options = getThemeSwitcherOptions(control);
|
|
326
|
+
|
|
327
|
+
if (!options.length) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const activeIndex = options.findIndex((option) => option === control);
|
|
332
|
+
|
|
333
|
+
if (direction === "first") {
|
|
334
|
+
options[0]?.focus();
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (direction === "last") {
|
|
339
|
+
options[options.length - 1]?.focus();
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const delta = direction === "next" ? 1 : -1;
|
|
344
|
+
const startIndex = activeIndex === -1 ? 0 : activeIndex;
|
|
345
|
+
const nextIndex = (startIndex + delta + options.length) % options.length;
|
|
346
|
+
options[nextIndex]?.focus();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function initializeThemeSwitchers() {
|
|
350
|
+
document.querySelectorAll(selectors.themeSwitcher).forEach((switcher) => {
|
|
351
|
+
if (!(switcher instanceof HTMLElement) || switcher.dataset.incThemeSwitcherInitialized === "true") {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
switcher.dataset.incThemeSwitcherInitialized = "true";
|
|
356
|
+
|
|
357
|
+
if (switcher.matches("details.inc-theme-switcher")) {
|
|
358
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (switcher.querySelector(selectors.themeMode)) {
|
|
363
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
mountThemeSwitcher(switcher, {
|
|
368
|
+
variant: switcher.getAttribute("data-inc-theme-switcher-variant")
|
|
369
|
+
|| (switcher.closest(".inc-navbar, .inc-navbar__utilities") ? "navbar" : undefined),
|
|
370
|
+
block: switcher.hasAttribute("data-inc-theme-switcher-block"),
|
|
371
|
+
label: switcher.getAttribute("data-inc-theme-switcher-label") || "Theme",
|
|
372
|
+
menuLabel: switcher.getAttribute("data-inc-theme-switcher-menu-label") || "Theme",
|
|
373
|
+
heading: switcher.getAttribute("data-inc-theme-switcher-heading") || "Choose appearance",
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function bindThemeMediaListener() {
|
|
379
|
+
if (themeMediaListenerBound || !window.matchMedia) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
themeMediaListenerBound = true;
|
|
384
|
+
themeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
385
|
+
|
|
386
|
+
const handleThemePreferenceChange = () => {
|
|
387
|
+
if (themeState.mode === "system") {
|
|
388
|
+
applyThemeMode("system", { persist: false });
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
if (typeof themeMediaQuery.addEventListener === "function") {
|
|
393
|
+
themeMediaQuery.addEventListener("change", handleThemePreferenceChange);
|
|
394
|
+
} else if (typeof themeMediaQuery.addListener === "function") {
|
|
395
|
+
themeMediaQuery.addListener(handleThemePreferenceChange);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function bindThemeStorageListener() {
|
|
400
|
+
if (themeStorageListenerBound) {
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
themeStorageListenerBound = true;
|
|
405
|
+
|
|
406
|
+
window.addEventListener("storage", (event) => {
|
|
407
|
+
if (event.key !== themeStorageKey) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
applyThemeMode(getStoredThemeMode() || getConfiguredThemeMode(), {
|
|
412
|
+
persist: false,
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function initializeTheme() {
|
|
418
|
+
if (themeInitialized) {
|
|
419
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
420
|
+
initializeThemeSwitchers();
|
|
421
|
+
return themeState;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
themeInitialized = true;
|
|
425
|
+
|
|
426
|
+
applyThemeMode(getStoredThemeMode() || getConfiguredThemeMode(), {
|
|
427
|
+
persist: false,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
bindThemeMediaListener();
|
|
431
|
+
bindThemeStorageListener();
|
|
432
|
+
initializeThemeSwitchers();
|
|
433
|
+
syncThemeControls(themeState.mode, themeState.resolved);
|
|
434
|
+
|
|
435
|
+
return themeState;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
applyThemeMode(getStoredThemeMode() || getConfiguredThemeMode(), {
|
|
439
|
+
dispatch: false,
|
|
440
|
+
persist: false,
|
|
441
|
+
syncControls: false,
|
|
442
|
+
});
|
|
33
443
|
|
|
34
444
|
function getTarget(trigger) {
|
|
35
445
|
const rawTarget = trigger.getAttribute("data-inc-target")
|
|
@@ -766,6 +1176,34 @@
|
|
|
766
1176
|
|
|
767
1177
|
function attachEventHandlers() {
|
|
768
1178
|
document.addEventListener("click", (event) => {
|
|
1179
|
+
const themeToggle = event.target.closest(selectors.themeToggle);
|
|
1180
|
+
|
|
1181
|
+
if (themeToggle) {
|
|
1182
|
+
event.preventDefault();
|
|
1183
|
+
cycleThemeMode();
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
const themeModeControl = event.target.closest(selectors.themeMode);
|
|
1188
|
+
|
|
1189
|
+
if (themeModeControl && themeModeControl.tagName !== "INPUT") {
|
|
1190
|
+
event.preventDefault();
|
|
1191
|
+
applyThemeMode(themeModeControl.getAttribute("data-inc-theme-mode"));
|
|
1192
|
+
|
|
1193
|
+
const owningSwitcher = themeModeControl.closest("details.inc-theme-switcher");
|
|
1194
|
+
const switcherSummary = owningSwitcher?.querySelector("summary");
|
|
1195
|
+
|
|
1196
|
+
if (owningSwitcher instanceof HTMLDetailsElement) {
|
|
1197
|
+
owningSwitcher.open = false;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
if (switcherSummary instanceof HTMLElement) {
|
|
1201
|
+
switcherSummary.focus();
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
769
1207
|
const autoRefreshToggle = event.target.closest(selectors.autoRefreshToggle);
|
|
770
1208
|
|
|
771
1209
|
if (autoRefreshToggle) {
|
|
@@ -879,12 +1317,69 @@
|
|
|
879
1317
|
}
|
|
880
1318
|
});
|
|
881
1319
|
|
|
1320
|
+
document.addEventListener("change", (event) => {
|
|
1321
|
+
const themeModeControl = event.target.closest(selectors.themeMode);
|
|
1322
|
+
|
|
1323
|
+
if (themeModeControl) {
|
|
1324
|
+
applyThemeMode(themeModeControl.getAttribute("data-inc-theme-mode"));
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
const themeSelect = event.target.closest(selectors.themeSelect);
|
|
1329
|
+
|
|
1330
|
+
if (themeSelect) {
|
|
1331
|
+
applyThemeMode(themeSelect.value);
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
882
1335
|
document.addEventListener("keydown", (event) => {
|
|
883
1336
|
const menuToggle = event.target.closest(selectors.menuToggle);
|
|
884
1337
|
const menu = event.target.closest(selectors.menu);
|
|
885
1338
|
const tabToggle = event.target.closest(selectors.tabToggle);
|
|
1339
|
+
const themeModeControl = event.target.closest(selectors.themeMode);
|
|
886
1340
|
const openOverlay = getTopOpenOverlay();
|
|
887
1341
|
|
|
1342
|
+
if (themeModeControl && themeModeControl.closest(".inc-theme-switcher__panel")) {
|
|
1343
|
+
if (event.key === "ArrowDown") {
|
|
1344
|
+
event.preventDefault();
|
|
1345
|
+
focusThemeSwitcherOption(themeModeControl, "next");
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
if (event.key === "ArrowUp") {
|
|
1350
|
+
event.preventDefault();
|
|
1351
|
+
focusThemeSwitcherOption(themeModeControl, "previous");
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
if (event.key === "Home") {
|
|
1356
|
+
event.preventDefault();
|
|
1357
|
+
focusThemeSwitcherOption(themeModeControl, "first");
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
if (event.key === "End") {
|
|
1362
|
+
event.preventDefault();
|
|
1363
|
+
focusThemeSwitcherOption(themeModeControl, "last");
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
if (event.key === "Escape") {
|
|
1368
|
+
const owningSwitcher = themeModeControl.closest("details.inc-theme-switcher");
|
|
1369
|
+
const switcherSummary = owningSwitcher?.querySelector("summary");
|
|
1370
|
+
|
|
1371
|
+
if (owningSwitcher instanceof HTMLDetailsElement) {
|
|
1372
|
+
owningSwitcher.open = false;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
if (switcherSummary instanceof HTMLElement) {
|
|
1376
|
+
switcherSummary.focus();
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
|
|
888
1383
|
if (menuToggle) {
|
|
889
1384
|
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
890
1385
|
event.preventDefault();
|
|
@@ -1000,7 +1495,32 @@
|
|
|
1000
1495
|
});
|
|
1001
1496
|
}
|
|
1002
1497
|
|
|
1498
|
+
window.IncTheme = {
|
|
1499
|
+
getMode() {
|
|
1500
|
+
return themeState.mode;
|
|
1501
|
+
},
|
|
1502
|
+
getResolvedTheme() {
|
|
1503
|
+
return themeState.resolved;
|
|
1504
|
+
},
|
|
1505
|
+
setMode(mode) {
|
|
1506
|
+
return applyThemeMode(mode);
|
|
1507
|
+
},
|
|
1508
|
+
cycleMode() {
|
|
1509
|
+
return cycleThemeMode();
|
|
1510
|
+
},
|
|
1511
|
+
createSwitcher(options = {}) {
|
|
1512
|
+
return createThemeSwitcher(options);
|
|
1513
|
+
},
|
|
1514
|
+
mountSwitcher(target, options = {}) {
|
|
1515
|
+
return mountThemeSwitcher(target, options);
|
|
1516
|
+
},
|
|
1517
|
+
init() {
|
|
1518
|
+
return initializeTheme();
|
|
1519
|
+
},
|
|
1520
|
+
};
|
|
1521
|
+
|
|
1003
1522
|
function initialize() {
|
|
1523
|
+
initializeTheme();
|
|
1004
1524
|
initializeMenus();
|
|
1005
1525
|
initializeCollapses();
|
|
1006
1526
|
initializeTabs();
|