@oksigenia/access-panel 0.7.2 → 0.8.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.
@@ -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 };
@@ -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
- const raw = localStorage.getItem(key);
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 = loadState(storageKey);
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);
@@ -1079,6 +1121,7 @@ var PANEL_CSS = `
1079
1121
  .oks-access-reset { padding: 14px; font-size: 14px; }
1080
1122
  }
1081
1123
  `;
1124
+ var NOT_ICON_FONT = ':not(.fa, [class*="fa-"], .icon, [class^="icon-"], [class*=" icon-"], .dashicons, [class*="dashicons-"], .material-icons, [class^="material-symbols"], .glyphicon, [class^="bi-"], [class*=" bi-"])';
1082
1125
  var EFFECT_CSS = `
1083
1126
  html.oks-colorblind-1 { filter: url('#oks-filter-protanopia'); }
1084
1127
  html.oks-colorblind-2 { filter: url('#oks-filter-deuteranopia'); }
@@ -1106,7 +1149,7 @@ body.oks-lh-3 * { line-height: 2.2 !important; }
1106
1149
 
1107
1150
  body.oks-a11y-font { font-family: Arial, sans-serif !important; }
1108
1151
 
1109
- body.oks-dyslexia * {
1152
+ body.oks-dyslexia *${NOT_ICON_FONT} {
1110
1153
  font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;
1111
1154
  letter-spacing: 0.05em !important;
1112
1155
  word-spacing: 0.1em !important;
@@ -1253,9 +1296,9 @@ ${s}.oks-lh-1 * { line-height: 1.6 !important; }
1253
1296
  ${s}.oks-lh-2 * { line-height: 1.9 !important; }
1254
1297
  ${s}.oks-lh-3 * { line-height: 2.2 !important; }
1255
1298
 
1256
- ${s}.oks-a11y-font, ${s}.oks-a11y-font * { font-family: Arial, sans-serif !important; }
1299
+ ${s}.oks-a11y-font, ${s}.oks-a11y-font *${NOT_ICON_FONT} { font-family: Arial, sans-serif !important; }
1257
1300
 
1258
- ${s}.oks-dyslexia * {
1301
+ ${s}.oks-dyslexia *${NOT_ICON_FONT} {
1259
1302
  font-family: 'Comic Sans MS', 'Verdana', sans-serif !important;
1260
1303
  letter-spacing: 0.05em !important;
1261
1304
  word-spacing: 0.1em !important;
@@ -1382,6 +1425,9 @@ var OksigeniaAccessPanelElement = class extends HTMLElement {
1382
1425
  return OBSERVED;
1383
1426
  }
1384
1427
  _controller = null;
1428
+ /** `initial-state` is read on the first render only: later re-renders
1429
+ * (another attribute changing) must not undo what the visitor did since. */
1430
+ _initialStateRead = false;
1385
1431
  _fxId = `oks-access-fx-${++fxSeq}`;
1386
1432
  _scopeId = `oks-access-scope-${this._fxId.split("-").pop()}`;
1387
1433
  constructor() {
@@ -1497,12 +1543,15 @@ var OksigeniaAccessPanelElement = class extends HTMLElement {
1497
1543
  });
1498
1544
  shadow.innerHTML = `<style>${PANEL_CSS}${positionCss(position, positionMobile)}</style>${html}`;
1499
1545
  const scopeEl = scope ? document.querySelector(scope) : void 0;
1546
+ const initialState = this._initialStateRead ? null : parseState(this.getAttribute("initial-state"));
1547
+ this._initialStateRead = true;
1500
1548
  this._controller = bindPanelBehavior(shadow, {
1501
1549
  storageKey: this.getAttribute("storage-key") ?? void 0,
1502
1550
  locale: this.getLocale(),
1503
1551
  enabled,
1504
1552
  nudgeMax: this.getNudgeMax(),
1505
- scopeEl
1553
+ scopeEl,
1554
+ initialState
1506
1555
  });
1507
1556
  this.updateScopeStyle(scope);
1508
1557
  this.updateEffectsExclude(scope ?? "body");