@oksigenia/access-panel 0.7.3 → 0.8.1
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/CHANGELOG.md +16 -0
- package/README.md +17 -0
- package/dist/behavior-CEe_YuMU.d.ts +118 -0
- package/dist/index.d.ts +6 -100
- package/dist/index.js +64 -15
- package/dist/index.js.map +1 -1
- package/dist/web-component.d.ts +8 -0
- package/dist/web-component.js +70 -15
- package/dist/web-component.js.map +1 -1
- package/package.json +1 -1
package/dist/web-component.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { b as PanelChangeDetail } from './behavior-CEe_YuMU.js';
|
|
2
|
+
|
|
1
3
|
declare class OksigeniaAccessPanelElement extends HTMLElement {
|
|
2
4
|
static get observedAttributes(): readonly string[];
|
|
3
5
|
private _controller;
|
|
6
|
+
/** `initial-state` is read on the first render only: later re-renders
|
|
7
|
+
* (another attribute changing) must not undo what the visitor did since. */
|
|
8
|
+
private _initialStateRead;
|
|
4
9
|
private readonly _fxId;
|
|
5
10
|
private readonly _scopeId;
|
|
6
11
|
constructor();
|
|
@@ -33,6 +38,9 @@ declare global {
|
|
|
33
38
|
interface HTMLElementTagNameMap {
|
|
34
39
|
'oksigenia-access-panel': OksigeniaAccessPanelElement;
|
|
35
40
|
}
|
|
41
|
+
interface HTMLElementEventMap {
|
|
42
|
+
'oksiac:change': CustomEvent<PanelChangeDetail>;
|
|
43
|
+
}
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
export { OksigeniaAccessPanelElement };
|
package/dist/web-component.js
CHANGED
|
@@ -283,14 +283,42 @@ var DEFAULT_STATE = Object.freeze({
|
|
|
283
283
|
readingMask: false,
|
|
284
284
|
bigTargets: false
|
|
285
285
|
});
|
|
286
|
+
var LEVEL_MAX = Object.freeze({
|
|
287
|
+
zoom: 4,
|
|
288
|
+
lh: 3,
|
|
289
|
+
align: 3,
|
|
290
|
+
ls: 3,
|
|
291
|
+
colorblind: 3
|
|
292
|
+
});
|
|
293
|
+
function sanitizeState(input) {
|
|
294
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
295
|
+
const src = input;
|
|
296
|
+
const out = { ...DEFAULT_STATE };
|
|
297
|
+
for (const key of Object.keys(DEFAULT_STATE)) {
|
|
298
|
+
const v = src[key];
|
|
299
|
+
if (v === void 0) continue;
|
|
300
|
+
if (key in LEVEL_MAX) {
|
|
301
|
+
if (typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= LEVEL_MAX[key]) {
|
|
302
|
+
out[key] = v;
|
|
303
|
+
}
|
|
304
|
+
} else if (v === true || v === 1) {
|
|
305
|
+
out[key] = true;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
function parseState(json) {
|
|
311
|
+
if (json == null || json.trim() === "") return null;
|
|
312
|
+
try {
|
|
313
|
+
return sanitizeState(JSON.parse(json));
|
|
314
|
+
} catch {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
286
318
|
function loadState(key) {
|
|
287
319
|
try {
|
|
288
320
|
if (typeof localStorage === "undefined") return { ...DEFAULT_STATE };
|
|
289
|
-
|
|
290
|
-
if (!raw) return { ...DEFAULT_STATE };
|
|
291
|
-
const parsed = JSON.parse(raw);
|
|
292
|
-
if (!parsed || typeof parsed !== "object") return { ...DEFAULT_STATE };
|
|
293
|
-
return { ...DEFAULT_STATE, ...parsed };
|
|
321
|
+
return parseState(localStorage.getItem(key)) ?? { ...DEFAULT_STATE };
|
|
294
322
|
} catch {
|
|
295
323
|
return { ...DEFAULT_STATE };
|
|
296
324
|
}
|
|
@@ -385,7 +413,19 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
385
413
|
if (!panel || !closeBtn || !resetBtn) {
|
|
386
414
|
return noopController();
|
|
387
415
|
}
|
|
388
|
-
let state
|
|
416
|
+
let state;
|
|
417
|
+
if (opts.initialState) {
|
|
418
|
+
state = { ...opts.initialState };
|
|
419
|
+
saveState(storageKey, state);
|
|
420
|
+
} else {
|
|
421
|
+
state = loadState(storageKey);
|
|
422
|
+
}
|
|
423
|
+
const emitChange = () => {
|
|
424
|
+
const host = root.host;
|
|
425
|
+
if (!host) return;
|
|
426
|
+
const detail = { state: { ...state } };
|
|
427
|
+
host.dispatchEvent(new CustomEvent("oksiac:change", { bubbles: true, composed: true, detail }));
|
|
428
|
+
};
|
|
389
429
|
const scoped = opts.scopeEl !== void 0;
|
|
390
430
|
const GLOBAL_KEY = "oksiac::global";
|
|
391
431
|
const GLOBAL_MAP = [
|
|
@@ -561,11 +601,13 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
561
601
|
}
|
|
562
602
|
applyState();
|
|
563
603
|
saveState(storageKey, state);
|
|
604
|
+
emitChange();
|
|
564
605
|
};
|
|
565
606
|
const onReset = () => {
|
|
566
607
|
state = { ...DEFAULT_STATE };
|
|
567
608
|
applyState();
|
|
568
609
|
saveState(storageKey, state);
|
|
610
|
+
emitChange();
|
|
569
611
|
if (scoped) {
|
|
570
612
|
const cleared = { bigCursor: false, readingGuide: false, readingMask: false };
|
|
571
613
|
saveGlobal(cleared);
|
|
@@ -939,7 +981,7 @@ var PANEL_CSS = `
|
|
|
939
981
|
font-size: 11px;
|
|
940
982
|
font-weight: 800;
|
|
941
983
|
text-transform: uppercase;
|
|
942
|
-
color: #
|
|
984
|
+
color: #595959;
|
|
943
985
|
}
|
|
944
986
|
/* Screen-reader-only: keeps the category headings in the accessibility tree
|
|
945
987
|
(flat scoped layout) while taking them out of the grid flow so they don't
|
|
@@ -1127,6 +1169,12 @@ body.oks-ls-1 * { letter-spacing: 0.05em !important; }
|
|
|
1127
1169
|
body.oks-ls-2 * { letter-spacing: 0.10em !important; }
|
|
1128
1170
|
body.oks-ls-3 * { letter-spacing: 0.16em !important; }
|
|
1129
1171
|
|
|
1172
|
+
/* Pages that declare a dark theme (Bootstrap 5.3's data-bs-theme, which Moodle
|
|
1173
|
+
5.3's colour modes use, or data-theme): the default focus blue falls under 3:1
|
|
1174
|
+
against a dark background, so the fallback moves to a lighter blue. An explicit
|
|
1175
|
+
--oks-focus-color still wins. */
|
|
1176
|
+
html[data-bs-theme="dark"], html[data-theme="dark"] { --oks-focus-auto: #6ea8fe; }
|
|
1177
|
+
|
|
1130
1178
|
/* Focus highlight colour is themeable via --oks-focus-color (default #005fcc):
|
|
1131
1179
|
set it on :root for a dark theme so the highlight stays visible. The
|
|
1132
1180
|
persistent "all interactive" dashed derives a 45% tint from it; the glow can
|
|
@@ -1136,13 +1184,13 @@ body.oks-a11y-focus button:not(oksigenia-access-panel):not(oksigenia-access-pane
|
|
|
1136
1184
|
body.oks-a11y-focus input,
|
|
1137
1185
|
body.oks-a11y-focus select,
|
|
1138
1186
|
body.oks-a11y-focus textarea {
|
|
1139
|
-
outline: 2px dashed color-mix(in srgb, var(--oks-focus-color, #005fcc) 45%, transparent) !important;
|
|
1187
|
+
outline: 2px dashed color-mix(in srgb, var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) 45%, transparent) !important;
|
|
1140
1188
|
outline-offset: 2px !important;
|
|
1141
1189
|
}
|
|
1142
1190
|
body.oks-a11y-focus *:focus-visible {
|
|
1143
|
-
outline: 3px solid var(--oks-focus-color, #005fcc) !important;
|
|
1191
|
+
outline: 3px solid var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) !important;
|
|
1144
1192
|
outline-offset: 3px !important;
|
|
1145
|
-
box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, #005fcc) 25%, transparent)) !important;
|
|
1193
|
+
box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) 25%, transparent)) !important;
|
|
1146
1194
|
}
|
|
1147
1195
|
|
|
1148
1196
|
body.oks-a11y-contrast.oks-a11y-focus *:focus,
|
|
@@ -1249,7 +1297,8 @@ ${s}.oks-zoom-2 { font-size: 120% !important; }
|
|
|
1249
1297
|
${s}.oks-zoom-3 { font-size: 135% !important; }
|
|
1250
1298
|
${s}.oks-zoom-4 { font-size: 150% !important; }
|
|
1251
1299
|
`;
|
|
1252
|
-
return
|
|
1300
|
+
return `html[data-bs-theme="dark"], html[data-theme="dark"] { --oks-focus-auto: #6ea8fe; }
|
|
1301
|
+
${zoom}
|
|
1253
1302
|
${s}.oks-lh-1 * { line-height: 1.6 !important; }
|
|
1254
1303
|
${s}.oks-lh-2 * { line-height: 1.9 !important; }
|
|
1255
1304
|
${s}.oks-lh-3 * { line-height: 2.2 !important; }
|
|
@@ -1281,13 +1330,13 @@ ${s}.oks-a11y-focus button,
|
|
|
1281
1330
|
${s}.oks-a11y-focus input,
|
|
1282
1331
|
${s}.oks-a11y-focus select,
|
|
1283
1332
|
${s}.oks-a11y-focus textarea {
|
|
1284
|
-
outline: 2px dashed color-mix(in srgb, var(--oks-focus-color, #005fcc) 45%, transparent) !important;
|
|
1333
|
+
outline: 2px dashed color-mix(in srgb, var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) 45%, transparent) !important;
|
|
1285
1334
|
outline-offset: 2px !important;
|
|
1286
1335
|
}
|
|
1287
1336
|
${s}.oks-a11y-focus *:focus-visible {
|
|
1288
|
-
outline: 3px solid var(--oks-focus-color, #005fcc) !important;
|
|
1337
|
+
outline: 3px solid var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) !important;
|
|
1289
1338
|
outline-offset: 3px !important;
|
|
1290
|
-
box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, #005fcc) 25%, transparent)) !important;
|
|
1339
|
+
box-shadow: 0 0 0 6px var(--oks-focus-glow, color-mix(in srgb, var(--oks-focus-color, var(--oks-focus-auto, #005fcc)) 25%, transparent)) !important;
|
|
1291
1340
|
}
|
|
1292
1341
|
|
|
1293
1342
|
${s}.oks-a11y-contrast, ${s}.oks-a11y-contrast * {
|
|
@@ -1383,6 +1432,9 @@ var OksigeniaAccessPanelElement = class extends HTMLElement {
|
|
|
1383
1432
|
return OBSERVED;
|
|
1384
1433
|
}
|
|
1385
1434
|
_controller = null;
|
|
1435
|
+
/** `initial-state` is read on the first render only: later re-renders
|
|
1436
|
+
* (another attribute changing) must not undo what the visitor did since. */
|
|
1437
|
+
_initialStateRead = false;
|
|
1386
1438
|
_fxId = `oks-access-fx-${++fxSeq}`;
|
|
1387
1439
|
_scopeId = `oks-access-scope-${this._fxId.split("-").pop()}`;
|
|
1388
1440
|
constructor() {
|
|
@@ -1498,12 +1550,15 @@ var OksigeniaAccessPanelElement = class extends HTMLElement {
|
|
|
1498
1550
|
});
|
|
1499
1551
|
shadow.innerHTML = `<style>${PANEL_CSS}${positionCss(position, positionMobile)}</style>${html}`;
|
|
1500
1552
|
const scopeEl = scope ? document.querySelector(scope) : void 0;
|
|
1553
|
+
const initialState = this._initialStateRead ? null : parseState(this.getAttribute("initial-state"));
|
|
1554
|
+
this._initialStateRead = true;
|
|
1501
1555
|
this._controller = bindPanelBehavior(shadow, {
|
|
1502
1556
|
storageKey: this.getAttribute("storage-key") ?? void 0,
|
|
1503
1557
|
locale: this.getLocale(),
|
|
1504
1558
|
enabled,
|
|
1505
1559
|
nudgeMax: this.getNudgeMax(),
|
|
1506
|
-
scopeEl
|
|
1560
|
+
scopeEl,
|
|
1561
|
+
initialState
|
|
1507
1562
|
});
|
|
1508
1563
|
this.updateScopeStyle(scope);
|
|
1509
1564
|
this.updateEffectsExclude(scope ?? "body");
|