@oksigenia/access-panel 0.4.3 → 0.5.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/CHANGELOG.md +24 -0
- package/README.md +26 -2
- package/dist/index.d.ts +65 -21
- package/dist/index.js +320 -74
- package/dist/index.js.map +1 -1
- package/dist/web-component.d.ts +14 -1
- package/dist/web-component.js +405 -92
- package/dist/web-component.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/translations.ts
|
|
2
2
|
var DICT = {
|
|
3
|
-
es: { title: "Accesibilidad", close: "Cerrar", txt: "Texto", size: "Tama\xF1o", lh: "Interlineado", align: "Alineaci\xF3n", font: "Legible", dyslexia: "Fuente Dislexia", vis: "Visual", contrast: "Contraste", gray: "Grises", hide: "Ocultar Img", links: "Links", ori: "Orientaci\xF3n", guide: "Gu\xEDa", mask: "M\xE1scara", targets: "\xC1reas Grandes", cursor: "Cursor Grande", pause: "Parar Animac.", reset: "Restablecer Todo", dev: "Desarrollado por", ls: "Espaciado", cb: "Daltonismo", focus: "Foco", presets: "Perfiles", pLow: "Baja Visi\xF3n", pDys: "Dislexia", pMot: "Motor", pCalm: "Sin Distrac." },
|
|
4
|
-
en: { title: "Accessibility", close: "Close", txt: "Text", size: "Size", lh: "Line Height", align: "Align", font: "Readable Font", dyslexia: "Dyslexia Font", vis: "Visual", contrast: "Contrast", gray: "Grayscale", hide: "Hide Images", links: "Highlight Links", ori: "Orientation", guide: "Reading Guide", mask: "Reading Mask", targets: "Big Targets", cursor: "Big Cursor", pause: "Pause Anim.", reset: "Reset All", dev: "Developed by", ls: "Letter Spacing", cb: "Color Blind", focus: "Focus", presets: "Profiles", pLow: "Low Vision", pDys: "Dyslexia", pMot: "Motor", pCalm: "No Distract." },
|
|
5
|
-
gn: { title: "Oikeha (Accesibilidad)", close: "Mboty", txt: "Mo\xF1e'\u1EBDr\xE3", size: "Tuichakue", lh: "Jei", align: "Mbojoja", font: "Letra Por\xE3", dyslexia: "Dislexia", vis: "Hechapy", contrast: "Sa'y", gray: "H\u0169 ha T\u0129", hide: "Moka\xF1y Ta'anga", links: "Joajuha", ori: "S\xE3mbyhy", guide: "S\xE3mbyhyha", mask: "Mbohov\xE1i", targets: "Tenda Guasu", cursor: "Cursor Guasu", pause: "Mboopyta", reset: "Mbojevy", dev: "Apojare", ls: "Rapykue", cb: "Sa'yvy", focus: "\xD1emoha", presets: "Tekor\xE3", pLow: "Hechapy Vai", pDys: "Dislexia", pMot: "Po-rehegua", pCalm: "Py\u02BCa Guapy" },
|
|
6
|
-
fr: { title: "Accessibilit\xE9", close: "Fermer", txt: "Texte", size: "Taille", lh: "Interligne", align: "Alignement", font: "Police Lisible", dyslexia: "Police Dyslexie", vis: "Visuel", contrast: "Contraste", gray: "Niveaux Gris", hide: "Masquer Img", links: "Liens", ori: "Orientation", guide: "Guide Lecture", mask: "Masque Lecture", targets: "Grandes Cibles", cursor: "Grand Curseur", pause: "Pause Anim.", reset: "R\xE9initialiser", dev: "D\xE9velopp\xE9 par", ls: "Espacement", cb: "Daltonisme", focus: "Focus", presets: "Profils", pLow: "Basse Vision", pDys: "Dyslexie", pMot: "Moteur", pCalm: "Sans Distrac." },
|
|
7
|
-
it: { title: "Accessibilit\xE0", close: "Chiudi", txt: "Testo", size: "Dimensione", lh: "Interlinea", align: "Allineamento", font: "Leggibile", dyslexia: "Font Dislessia", vis: "Visivo", contrast: "Contrasto", gray: "Scala Grig.", hide: "Nascondi Img", links: "Link", ori: "Orientamento", guide: "Guida", mask: "Maschera", targets: "Aree Grandi", cursor: "Cursore Grande", pause: "Pausa Anim.", reset: "Reimposta", dev: "Sviluppato da", ls: "Spaziatura", cb: "Daltonismo", focus: "Focus", presets: "Profili", pLow: "Ipovisione", pDys: "Dislessia", pMot: "Motorio", pCalm: "No Distraz." },
|
|
8
|
-
de: { title: "Barrierefreiheit", close: "Schlie\xDFen", txt: "Text", size: "Gr\xF6\xDFe", lh: "Zeilenh\xF6he", align: "Ausrichtung", font: "Lesbar", dyslexia: "Dyslexie", vis: "Visuell", contrast: "Kontrast", gray: "Graustufen", hide: "Bilder Aus", links: "Links", ori: "Orientierung", guide: "Lesehilfe", mask: "Lesemaske", targets: "Gro\xDFe Ziele", cursor: "Gro\xDFer Cursor", pause: "Anim. Stopp", reset: "Zur\xFCcksetzen", dev: "Entwickelt von", ls: "Buchst.abst.", cb: "Farbblindheit", focus: "Fokus", presets: "Profile", pLow: "Sehschw\xE4che", pDys: "Dyslexie", pMot: "Motorik", pCalm: "Ohne Ablenk." },
|
|
9
|
-
nl: { title: "Toegankelijkheid", close: "Sluiten", txt: "Tekst", size: "Grootte", lh: "Regelhoogte", align: "Uitlijning", font: "Leesbaar", dyslexia: "Dyslexie", vis: "Visueel", contrast: "Contrast", gray: "Grijstinten", hide: "Verberg Afb.", links: "Links", ori: "Ori\xEBntatie", guide: "Leesgids", mask: "Leesmasker", targets: "Grote Doelen", cursor: "Grote Cursor", pause: "Anim. Pauze", reset: "Resetten", dev: "Ontwikkeld door", ls: "Letterspatie", cb: "Kleurenblind", focus: "Focus", presets: "Profielen", pLow: "Slechtziend", pDys: "Dyslexie", pMot: "Motoriek", pCalm: "Geen Afleid." },
|
|
10
|
-
sv: { title: "Tillg\xE4nglighet", close: "St\xE4ng", txt: "Text", size: "Storlek", lh: "Radh\xF6jd", align: "Justering", font: "L\xE4sbar", dyslexia: "Dyslexi", vis: "Visuell", contrast: "Kontrast", gray: "Gr\xE5skala", hide: "D\xF6lj Bilder", links: "L\xE4nkar", ori: "Orientering", guide: "L\xE4slinjal", mask: "L\xE4smask", targets: "Stora Ytor", cursor: "Stor Mark\xF6r", pause: "Pausa Anim.", reset: "\xC5terst\xE4ll", dev: "Utvecklad av", ls: "Bokstavsavst.", cb: "F\xE4rgblindhet", focus: "Fokus", presets: "Profiler", pLow: "Synneds\xE4tt.", pDys: "Dyslexi", pMot: "Motorik", pCalm: "Inga Distrak." }
|
|
3
|
+
es: { title: "Accesibilidad", close: "Cerrar", txt: "Texto", size: "Tama\xF1o", lh: "Interlineado", align: "Alineaci\xF3n", font: "Legible", dyslexia: "Fuente Dislexia", vis: "Visual", contrast: "Contraste", gray: "Grises", hide: "Ocultar Img", links: "Links", ori: "Orientaci\xF3n", guide: "Gu\xEDa", mask: "M\xE1scara", targets: "\xC1reas Grandes", cursor: "Cursor Grande", pause: "Parar Animac.", reset: "Restablecer Todo", dev: "Desarrollado por", ls: "Espaciado", cb: "Daltonismo", focus: "Foco", presets: "Perfiles", pLow: "Baja Visi\xF3n", pDys: "Dislexia", pMot: "Motor", pCalm: "Sin Distrac.", level: (l, n, m) => `${l}, nivel ${n} de ${m}` },
|
|
4
|
+
en: { title: "Accessibility", close: "Close", txt: "Text", size: "Size", lh: "Line Height", align: "Align", font: "Readable Font", dyslexia: "Dyslexia Font", vis: "Visual", contrast: "Contrast", gray: "Grayscale", hide: "Hide Images", links: "Highlight Links", ori: "Orientation", guide: "Reading Guide", mask: "Reading Mask", targets: "Big Targets", cursor: "Big Cursor", pause: "Pause Anim.", reset: "Reset All", dev: "Developed by", ls: "Letter Spacing", cb: "Color Blind", focus: "Focus", presets: "Profiles", pLow: "Low Vision", pDys: "Dyslexia", pMot: "Motor", pCalm: "No Distract.", level: (l, n, m) => `${l}, level ${n} of ${m}` },
|
|
5
|
+
gn: { title: "Oikeha (Accesibilidad)", close: "Mboty", txt: "Mo\xF1e'\u1EBDr\xE3", size: "Tuichakue", lh: "Jei", align: "Mbojoja", font: "Letra Por\xE3", dyslexia: "Dislexia", vis: "Hechapy", contrast: "Sa'y", gray: "H\u0169 ha T\u0129", hide: "Moka\xF1y Ta'anga", links: "Joajuha", ori: "S\xE3mbyhy", guide: "S\xE3mbyhyha", mask: "Mbohov\xE1i", targets: "Tenda Guasu", cursor: "Cursor Guasu", pause: "Mboopyta", reset: "Mbojevy", dev: "Apojare", ls: "Rapykue", cb: "Sa'yvy", focus: "\xD1emoha", presets: "Tekor\xE3", pLow: "Hechapy Vai", pDys: "Dislexia", pMot: "Po-rehegua", pCalm: "Py\u02BCa Guapy", level: (l, n, m) => `${l}, ${n}/${m}` },
|
|
6
|
+
fr: { title: "Accessibilit\xE9", close: "Fermer", txt: "Texte", size: "Taille", lh: "Interligne", align: "Alignement", font: "Police Lisible", dyslexia: "Police Dyslexie", vis: "Visuel", contrast: "Contraste", gray: "Niveaux Gris", hide: "Masquer Img", links: "Liens", ori: "Orientation", guide: "Guide Lecture", mask: "Masque Lecture", targets: "Grandes Cibles", cursor: "Grand Curseur", pause: "Pause Anim.", reset: "R\xE9initialiser", dev: "D\xE9velopp\xE9 par", ls: "Espacement", cb: "Daltonisme", focus: "Focus", presets: "Profils", pLow: "Basse Vision", pDys: "Dyslexie", pMot: "Moteur", pCalm: "Sans Distrac.", level: (l, n, m) => `${l}, niveau ${n} sur ${m}` },
|
|
7
|
+
it: { title: "Accessibilit\xE0", close: "Chiudi", txt: "Testo", size: "Dimensione", lh: "Interlinea", align: "Allineamento", font: "Leggibile", dyslexia: "Font Dislessia", vis: "Visivo", contrast: "Contrasto", gray: "Scala Grig.", hide: "Nascondi Img", links: "Link", ori: "Orientamento", guide: "Guida", mask: "Maschera", targets: "Aree Grandi", cursor: "Cursore Grande", pause: "Pausa Anim.", reset: "Reimposta", dev: "Sviluppato da", ls: "Spaziatura", cb: "Daltonismo", focus: "Focus", presets: "Profili", pLow: "Ipovisione", pDys: "Dislessia", pMot: "Motorio", pCalm: "No Distraz.", level: (l, n, m) => `${l}, livello ${n} di ${m}` },
|
|
8
|
+
de: { title: "Barrierefreiheit", close: "Schlie\xDFen", txt: "Text", size: "Gr\xF6\xDFe", lh: "Zeilenh\xF6he", align: "Ausrichtung", font: "Lesbar", dyslexia: "Dyslexie", vis: "Visuell", contrast: "Kontrast", gray: "Graustufen", hide: "Bilder Aus", links: "Links", ori: "Orientierung", guide: "Lesehilfe", mask: "Lesemaske", targets: "Gro\xDFe Ziele", cursor: "Gro\xDFer Cursor", pause: "Anim. Stopp", reset: "Zur\xFCcksetzen", dev: "Entwickelt von", ls: "Buchst.abst.", cb: "Farbblindheit", focus: "Fokus", presets: "Profile", pLow: "Sehschw\xE4che", pDys: "Dyslexie", pMot: "Motorik", pCalm: "Ohne Ablenk.", level: (l, n, m) => `${l}, Stufe ${n} von ${m}` },
|
|
9
|
+
nl: { title: "Toegankelijkheid", close: "Sluiten", txt: "Tekst", size: "Grootte", lh: "Regelhoogte", align: "Uitlijning", font: "Leesbaar", dyslexia: "Dyslexie", vis: "Visueel", contrast: "Contrast", gray: "Grijstinten", hide: "Verberg Afb.", links: "Links", ori: "Ori\xEBntatie", guide: "Leesgids", mask: "Leesmasker", targets: "Grote Doelen", cursor: "Grote Cursor", pause: "Anim. Pauze", reset: "Resetten", dev: "Ontwikkeld door", ls: "Letterspatie", cb: "Kleurenblind", focus: "Focus", presets: "Profielen", pLow: "Slechtziend", pDys: "Dyslexie", pMot: "Motoriek", pCalm: "Geen Afleid.", level: (l, n, m) => `${l}, niveau ${n} van ${m}` },
|
|
10
|
+
sv: { title: "Tillg\xE4nglighet", close: "St\xE4ng", txt: "Text", size: "Storlek", lh: "Radh\xF6jd", align: "Justering", font: "L\xE4sbar", dyslexia: "Dyslexi", vis: "Visuell", contrast: "Kontrast", gray: "Gr\xE5skala", hide: "D\xF6lj Bilder", links: "L\xE4nkar", ori: "Orientering", guide: "L\xE4slinjal", mask: "L\xE4smask", targets: "Stora Ytor", cursor: "Stor Mark\xF6r", pause: "Pausa Anim.", reset: "\xC5terst\xE4ll", dev: "Utvecklad av", ls: "Bokstavsavst.", cb: "F\xE4rgblindhet", focus: "Fokus", presets: "Profiler", pLow: "Synneds\xE4tt.", pDys: "Dyslexi", pMot: "Motorik", pCalm: "Inga Distrak.", level: (l, n, m) => `${l}, niv\xE5 ${n} av ${m}` }
|
|
11
11
|
};
|
|
12
12
|
function getTranslation(locale) {
|
|
13
13
|
const lc = locale.toLowerCase();
|
|
@@ -37,75 +37,173 @@ var ICON_COLORBLIND = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12
|
|
|
37
37
|
var ICON_FOCUS = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 7V3h4v2H5v2H3zm14-4h4v4h-2V5h-2V3zm4 14v4h-4v-2h2v-2h2zM7 21H3v-4h2v2h2v2z"/></svg>';
|
|
38
38
|
var ICON_MASK = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M2 4h20v6H2zm0 10h20v6H2zm2-9v4h16V5zm0 10v4h16v-4z" opacity=".55"/><rect x="2" y="10" width="20" height="4"/></svg>';
|
|
39
39
|
var ICON_TARGETS = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 3h4v2H5v2H3zm14 0h4v4h-2V5h-2zm0 18v-2h2v-2h2v4zM3 21v-4h2v2h2v2zM12 8a4 4 0 100 8 4 4 0 000-8zm0 2a2 2 0 110 4 2 2 0 010-4z"/></svg>';
|
|
40
|
+
var UNIVERSAL_GLYPH = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"/></svg>';
|
|
40
41
|
var TRIGGER_ICONS = {
|
|
41
42
|
vitruvian: '<svg viewBox="0 0 122.88 122.88" fill="currentColor"><path d="M61.44,0A61.46,61.46,0,1,1,18,18,61.21,61.21,0,0,1,61.44,0Zm-.39,74.18L52.1,98.91a4.94,4.94,0,0,1-2.58,2.83A5,5,0,0,1,42.7,95.5l6.24-17.28a26.3,26.3,0,0,0,1.17-4,40.64,40.64,0,0,0,.54-4.18c.24-2.53.41-5.27.54-7.9s.22-5.18.29-7.29c.09-2.63-.62-2.8-2.73-3.3l-.44-.1-18-3.39A5,5,0,0,1,27.08,46a5,5,0,0,1,5.05-7.74l19.34,3.63c.77.07,1.52.16,2.31.25a57.64,57.64,0,0,0,7.18.53A81.13,81.13,0,0,0,69.9,42c.9-.1,1.75-.21,2.6-.29l18.25-3.42A5,5,0,0,1,94.5,39a5,5,0,0,1,1.3,7,5,5,0,0,1-3.21,2.09L75.15,51.37c-.58.13-1.1.22-1.56.29-1.82.31-2.72.47-2.61,3.06.08,1.89.31,4.15.61,6.51.35,2.77.81,5.71,1.29,8.4.31,1.77.6,3.19,1,4.55s.79,2.75,1.39,4.42l6.11,16.9a5,5,0,0,1-6.82,6.24,4.94,4.94,0,0,1-2.58-2.83L63,74.23,62,72.4l-1,1.78Zm.39-53.52a8.83,8.83,0,1,1-6.24,2.59,8.79,8.79,0,0,1,6.24-2.59Zm36.35,4.43a51.42,51.42,0,1,0,15,36.35,51.27,51.27,0,0,0-15-36.35Z"/></svg>',
|
|
42
43
|
wheelchair: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M19 13v-2c-1.54.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.01H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2-2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.76 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07zM12 6c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/></svg>',
|
|
43
44
|
eye: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>',
|
|
44
|
-
universal:
|
|
45
|
+
universal: UNIVERSAL_GLYPH,
|
|
46
|
+
porthole: UNIVERSAL_GLYPH
|
|
45
47
|
};
|
|
46
48
|
var ICON_CLOSE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
|
|
47
49
|
var COLORBLIND_FILTERS_SVG = '<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;width:0;height:0;overflow:hidden;" aria-hidden="true"><defs><filter id="oks-filter-protanopia"><feColorMatrix type="matrix" values="0.567 0.433 0 0 0 0.558 0.442 0 0 0 0 0.242 0.758 0 0 0 0 0 1 0"/></filter><filter id="oks-filter-deuteranopia"><feColorMatrix type="matrix" values="0.625 0.375 0 0 0 0.7 0.3 0 0 0 0 0.3 0.7 0 0 0 0 0 1 0"/></filter><filter id="oks-filter-tritanopia"><feColorMatrix type="matrix" values="0.95 0.05 0 0 0 0 0.433 0.567 0 0 0 0.475 0.525 0 0 0 0 0 1 0"/></filter></defs></svg>';
|
|
48
50
|
|
|
51
|
+
// src/controls.ts
|
|
52
|
+
var ALL_CONTROLS = [
|
|
53
|
+
"text-size",
|
|
54
|
+
"line-height",
|
|
55
|
+
"text-align",
|
|
56
|
+
"readable-font",
|
|
57
|
+
"dyslexia-font",
|
|
58
|
+
"letter-spacing",
|
|
59
|
+
"contrast",
|
|
60
|
+
"grayscale",
|
|
61
|
+
"hide-images",
|
|
62
|
+
"highlight-links",
|
|
63
|
+
"colorblind",
|
|
64
|
+
"reading-guide",
|
|
65
|
+
"reading-mask",
|
|
66
|
+
"big-cursor",
|
|
67
|
+
"big-targets",
|
|
68
|
+
"pause-anim",
|
|
69
|
+
"focus"
|
|
70
|
+
];
|
|
71
|
+
var CONTROL_STATE_KEY = {
|
|
72
|
+
"text-size": "zoom",
|
|
73
|
+
"line-height": "lh",
|
|
74
|
+
"text-align": "align",
|
|
75
|
+
"readable-font": "font",
|
|
76
|
+
"dyslexia-font": "dyslexia",
|
|
77
|
+
"letter-spacing": "ls",
|
|
78
|
+
"contrast": "contrast",
|
|
79
|
+
"grayscale": "grayOverlay",
|
|
80
|
+
"hide-images": "hideImages",
|
|
81
|
+
"highlight-links": "highlightLinks",
|
|
82
|
+
"colorblind": "colorblind",
|
|
83
|
+
"reading-guide": "readingGuide",
|
|
84
|
+
"reading-mask": "readingMask",
|
|
85
|
+
"big-cursor": "bigCursor",
|
|
86
|
+
"big-targets": "bigTargets",
|
|
87
|
+
"pause-anim": "pauseAnim",
|
|
88
|
+
"focus": "focusOutline"
|
|
89
|
+
};
|
|
90
|
+
var STATE_KEY_CONTROL = Object.fromEntries(
|
|
91
|
+
Object.entries(CONTROL_STATE_KEY).map(([control, key]) => [key, control])
|
|
92
|
+
);
|
|
93
|
+
var PRESETS = {
|
|
94
|
+
lowvision: { zoom: 2, contrast: true, highlightLinks: true, bigCursor: true, focusOutline: true },
|
|
95
|
+
dyslexia: { dyslexia: true, lh: 2, ls: 2, readingGuide: true },
|
|
96
|
+
motor: { bigCursor: true, bigTargets: true, focusOutline: true },
|
|
97
|
+
calm: { hideImages: true, pauseAnim: true }
|
|
98
|
+
};
|
|
99
|
+
var PRESET_IDS = ["lowvision", "dyslexia", "motor", "calm"];
|
|
100
|
+
function presetControlIds(id) {
|
|
101
|
+
return Object.keys(PRESETS[id]).map((k) => STATE_KEY_CONTROL[k]);
|
|
102
|
+
}
|
|
103
|
+
function resolveEnabledControls(controlsAttr, excludeAttr) {
|
|
104
|
+
const valid = new Set(ALL_CONTROLS);
|
|
105
|
+
const parse = (raw) => (raw ?? "").split(",").map((s) => s.trim().toLowerCase()).filter((s) => valid.has(s));
|
|
106
|
+
const whitelist = controlsAttr != null ? parse(controlsAttr) : null;
|
|
107
|
+
let enabled = whitelist && whitelist.length > 0 ? new Set(whitelist) : new Set(ALL_CONTROLS);
|
|
108
|
+
if (excludeAttr != null) {
|
|
109
|
+
for (const id of parse(excludeAttr)) enabled.delete(id);
|
|
110
|
+
}
|
|
111
|
+
return enabled;
|
|
112
|
+
}
|
|
113
|
+
function filterPresetForEnabled(id, enabled) {
|
|
114
|
+
const out = {};
|
|
115
|
+
for (const [k, v] of Object.entries(PRESETS[id])) {
|
|
116
|
+
if (enabled.has(STATE_KEY_CONTROL[k])) out[k] = v;
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
function presetIsAvailable(id, enabled) {
|
|
121
|
+
return presetControlIds(id).filter((c) => enabled.has(c)).length >= 2;
|
|
122
|
+
}
|
|
123
|
+
|
|
49
124
|
// src/render.ts
|
|
125
|
+
var PRESET_ICON = {
|
|
126
|
+
lowvision: ICON_CONTRAST,
|
|
127
|
+
dyslexia: ICON_DYSLEXIA,
|
|
128
|
+
motor: ICON_CURSOR,
|
|
129
|
+
calm: ICON_HIDE
|
|
130
|
+
};
|
|
50
131
|
function buildPanelHtml(opts) {
|
|
51
132
|
const { t, triggerIcon } = opts;
|
|
133
|
+
const enabled = opts.enabled ?? new Set(ALL_CONTROLS);
|
|
134
|
+
const showTrigger = opts.showTrigger ?? true;
|
|
135
|
+
const showPresets = opts.showPresets ?? true;
|
|
52
136
|
const trig = TRIGGER_ICONS[triggerIcon];
|
|
53
|
-
const
|
|
54
|
-
|
|
137
|
+
const multi = (id, prefix, levels, label, icon, full = false) => {
|
|
138
|
+
if (!enabled.has(id)) return "";
|
|
139
|
+
const action = id === "colorblind" ? "colorblind" : "multi";
|
|
55
140
|
const fullClass = full ? " full-width" : "";
|
|
56
141
|
const dots = Array.from({ length: levels }, () => "<span></span>").join("");
|
|
57
|
-
return `<button class="oks-access-opt multi-step${fullClass}" data-action="${action}" data-prefix="${prefix}" data-levels="${levels}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span><div class="oks-levels">${dots}</div></button>`;
|
|
142
|
+
return `<button class="oks-access-opt multi-step${fullClass}" data-control="${id}" data-action="${action}" data-prefix="${prefix}" data-levels="${levels}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span><div class="oks-levels">${dots}</div></button>`;
|
|
143
|
+
};
|
|
144
|
+
const toggle = (id, klass, label, icon) => {
|
|
145
|
+
if (!enabled.has(id)) return "";
|
|
146
|
+
return `<button class="oks-access-opt" data-control="${id}" data-action="toggle" data-class="${klass}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
|
|
147
|
+
};
|
|
148
|
+
const overlay = (id, target, label, icon) => {
|
|
149
|
+
if (!enabled.has(id)) return "";
|
|
150
|
+
return `<button class="oks-access-opt" data-control="${id}" data-action="overlay" data-target="${target}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
|
|
151
|
+
};
|
|
152
|
+
const simple = (id, action, label, icon) => {
|
|
153
|
+
if (!enabled.has(id)) return "";
|
|
154
|
+
return `<button class="oks-access-opt" data-control="${id}" data-action="${action}" aria-pressed="false" type="button"><span class="oks-icon">${icon}</span><span class="oks-label">${label}</span></button>`;
|
|
58
155
|
};
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
156
|
+
const preset = (id, label) => `<button class="oks-preset" data-action="preset" data-preset="${id}" type="button"><span class="oks-icon">${PRESET_ICON[id]}</span><span class="oks-label">${label}</span></button>`;
|
|
157
|
+
const section = (title, rows) => {
|
|
158
|
+
const kept = rows.filter(Boolean);
|
|
159
|
+
if (kept.length === 0) return "";
|
|
160
|
+
return `<h4 class="oks-access-title">${escapeHtml(title)}</h4><div class="oks-access-grid">${kept.join("")}</div>`;
|
|
161
|
+
};
|
|
162
|
+
const presetLabels = {
|
|
163
|
+
lowvision: t.pLow,
|
|
164
|
+
dyslexia: t.pDys,
|
|
165
|
+
motor: t.pMot,
|
|
166
|
+
calm: t.pCalm
|
|
167
|
+
};
|
|
168
|
+
const presetButtons = showPresets ? PRESET_IDS.filter((id) => presetIsAvailable(id, enabled)).map((id) => preset(id, presetLabels[id])) : [];
|
|
169
|
+
const presetsBlock = presetButtons.length ? `<h4 class="oks-access-title">${escapeHtml(t.presets)}</h4><div class="oks-access-presets">${presetButtons.join("")}</div>` : "";
|
|
170
|
+
const triggerBlock = showTrigger ? `
|
|
65
171
|
<div class="oks-access-wrapper" id="oks-wrapper" data-position="${opts.position}">
|
|
66
|
-
<button class="oks-access-btn" id="oks-trigger" aria-label="${escapeAttr(t.title)}" aria-expanded="false" aria-controls="oks-panel" type="button">
|
|
172
|
+
<button class="oks-access-btn" id="oks-trigger" part="trigger" data-trigger-icon="${triggerIcon}" aria-label="${escapeAttr(t.title)}" aria-expanded="false" aria-controls="oks-panel" type="button">
|
|
67
173
|
${trig}
|
|
68
174
|
</button>
|
|
69
175
|
<span class="oks-active-badge"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="4"><polyline points="20 6 9 17 4 12"/></svg></span>
|
|
70
|
-
</div
|
|
176
|
+
</div>` : "";
|
|
177
|
+
return `${triggerBlock}
|
|
71
178
|
<div class="oks-access-panel" id="oks-panel" role="dialog" aria-modal="true" aria-labelledby="oks-panel-title" inert>
|
|
72
179
|
<div class="oks-access-header">
|
|
73
180
|
<h3 id="oks-panel-title">${escapeHtml(t.title)}</h3>
|
|
74
181
|
<button class="oks-access-close" id="oks-close" aria-label="${escapeAttr(t.close)}" type="button">${ICON_CLOSE}</button>
|
|
75
182
|
</div>
|
|
76
183
|
<div class="oks-access-content">
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
${grid([
|
|
86
|
-
multi("multi", "oks-zoom", 4, t.size, ICON_TXT),
|
|
87
|
-
multi("multi", "oks-lh", 3, t.lh, ICON_LH),
|
|
88
|
-
multi("multi", "oks-align", 3, t.align, ICON_ALIGN),
|
|
89
|
-
toggle("oks-a11y-font", t.font, ICON_FONT),
|
|
90
|
-
toggle("oks-dyslexia", t.dyslexia, ICON_DYSLEXIA),
|
|
91
|
-
multi("multi", "oks-ls", 3, t.ls, ICON_LS)
|
|
184
|
+
${presetsBlock}
|
|
185
|
+
${section(t.txt, [
|
|
186
|
+
multi("text-size", "oks-zoom", 4, t.size, ICON_TXT),
|
|
187
|
+
multi("line-height", "oks-lh", 3, t.lh, ICON_LH),
|
|
188
|
+
multi("text-align", "oks-align", 3, t.align, ICON_ALIGN),
|
|
189
|
+
toggle("readable-font", "oks-a11y-font", t.font, ICON_FONT),
|
|
190
|
+
toggle("dyslexia-font", "oks-dyslexia", t.dyslexia, ICON_DYSLEXIA),
|
|
191
|
+
multi("letter-spacing", "oks-ls", 3, t.ls, ICON_LS)
|
|
92
192
|
])}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
toggle("oks-a11y-
|
|
98
|
-
toggle("oks-a11y-links", t.links, ICON_LINK),
|
|
193
|
+
${section(t.vis, [
|
|
194
|
+
toggle("contrast", "oks-a11y-contrast", t.contrast, ICON_CONTRAST),
|
|
195
|
+
overlay("grayscale", "oks-overlay-gray", t.gray, ICON_GRAY),
|
|
196
|
+
toggle("hide-images", "oks-a11y-hide", t.hide, ICON_HIDE),
|
|
197
|
+
toggle("highlight-links", "oks-a11y-links", t.links, ICON_LINK),
|
|
99
198
|
multi("colorblind", "oks-colorblind", 3, t.cb, ICON_COLORBLIND, true)
|
|
100
199
|
])}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
toggle("oks-
|
|
106
|
-
toggle("oks-a11y-
|
|
107
|
-
toggle("oks-a11y-
|
|
108
|
-
toggle("oks-a11y-focus", t.focus, ICON_FOCUS)
|
|
200
|
+
${section(t.ori, [
|
|
201
|
+
simple("reading-guide", "guide", t.guide, ICON_GUIDE),
|
|
202
|
+
simple("reading-mask", "mask", t.mask, ICON_MASK),
|
|
203
|
+
toggle("big-cursor", "oks-big-cursor", t.cursor, ICON_CURSOR),
|
|
204
|
+
toggle("big-targets", "oks-a11y-bigtargets", t.targets, ICON_TARGETS),
|
|
205
|
+
toggle("pause-anim", "oks-a11y-pause", t.pause, ICON_PAUSE),
|
|
206
|
+
toggle("focus", "oks-a11y-focus", t.focus, ICON_FOCUS)
|
|
109
207
|
])}
|
|
110
208
|
</div>
|
|
111
209
|
<div class="oks-access-footer">
|
|
@@ -130,14 +228,20 @@ function positionRules(position) {
|
|
|
130
228
|
switch (position) {
|
|
131
229
|
case "top-left":
|
|
132
230
|
return { wrap: "top: 20px; left: 20px;", panel: "top: 80px; left: 20px;" };
|
|
231
|
+
case "top-center":
|
|
232
|
+
return { wrap: "top: 20px; left: 50%; transform: translateX(-50%);", panel: "top: 80px; left: 50%; transform: translateX(-50%);" };
|
|
133
233
|
case "top-right":
|
|
134
234
|
return { wrap: "top: 20px; right: 20px;", panel: "top: 80px; right: 20px;" };
|
|
135
235
|
case "mid-left":
|
|
136
236
|
return { wrap: "top: 50%; left: 20px; transform: translateY(-50%);", panel: "top: 50%; left: 90px; transform: translateY(-50%);" };
|
|
237
|
+
case "mid-center":
|
|
238
|
+
return { wrap: "top: 50%; left: 50%; transform: translate(-50%, -50%);", panel: "top: 50%; left: 50%; transform: translate(-50%, -50%);" };
|
|
137
239
|
case "mid-right":
|
|
138
240
|
return { wrap: "top: 50%; right: 20px; transform: translateY(-50%);", panel: "top: 50%; right: 90px; transform: translateY(-50%);" };
|
|
139
241
|
case "bottom-left":
|
|
140
242
|
return { wrap: "bottom: 20px; left: 20px;", panel: "bottom: 100px; left: 20px;" };
|
|
243
|
+
case "bottom-center":
|
|
244
|
+
return { wrap: "bottom: 20px; left: 50%; transform: translateX(-50%);", panel: "bottom: 100px; left: 50%; transform: translateX(-50%);" };
|
|
141
245
|
case "bottom-right":
|
|
142
246
|
return { wrap: "bottom: 20px; right: 20px;", panel: "bottom: 100px; right: 20px;" };
|
|
143
247
|
}
|
|
@@ -231,37 +335,45 @@ var TOGGLE_KEYS = {
|
|
|
231
335
|
"oks-a11y-focus": "focusOutline",
|
|
232
336
|
"oks-a11y-bigtargets": "bigTargets"
|
|
233
337
|
};
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
};
|
|
338
|
+
function noopController() {
|
|
339
|
+
return Object.assign(() => {
|
|
340
|
+
}, { open() {
|
|
341
|
+
}, close() {
|
|
342
|
+
}, toggle() {
|
|
343
|
+
} });
|
|
344
|
+
}
|
|
345
|
+
function deepActiveElement() {
|
|
346
|
+
let a = document.activeElement;
|
|
347
|
+
while (a?.shadowRoot?.activeElement) a = a.shadowRoot.activeElement;
|
|
348
|
+
return a;
|
|
349
|
+
}
|
|
240
350
|
function bindPanelBehavior(root, opts = {}) {
|
|
241
351
|
const storageKey = opts.storageKey ?? "oksiacSettings";
|
|
352
|
+
const t = getTranslation(opts.locale ?? "en");
|
|
353
|
+
const enabled = opts.enabled ?? new Set(ALL_CONTROLS);
|
|
354
|
+
const nudgeMax = Math.max(0, opts.nudgeMax ?? 0);
|
|
242
355
|
const trigger = root.getElementById("oks-trigger");
|
|
243
356
|
const panel = root.getElementById("oks-panel");
|
|
244
357
|
const closeBtn = root.getElementById("oks-close");
|
|
245
358
|
const resetBtn = root.getElementById("oks-reset");
|
|
246
359
|
const wrapper = root.getElementById("oks-wrapper");
|
|
247
360
|
const opts$ = Array.from(root.querySelectorAll(".oks-access-opt, .oks-preset"));
|
|
248
|
-
if (!
|
|
249
|
-
return ()
|
|
250
|
-
};
|
|
361
|
+
if (!panel || !closeBtn || !resetBtn) {
|
|
362
|
+
return noopController();
|
|
251
363
|
}
|
|
252
364
|
let state = loadState(storageKey);
|
|
253
365
|
function applyState() {
|
|
254
366
|
const body = document.body;
|
|
255
|
-
const
|
|
367
|
+
const rootEl = document.documentElement;
|
|
256
368
|
for (const cls of Array.from(body.classList)) {
|
|
257
369
|
if (cls.startsWith("oks-")) body.classList.remove(cls);
|
|
258
370
|
}
|
|
259
|
-
[1, 2, 3].forEach((l) =>
|
|
371
|
+
[1, 2, 3].forEach((l) => rootEl.classList.remove(`oks-colorblind-${l}`));
|
|
260
372
|
if (state.zoom > 0) body.classList.add(`oks-zoom-${state.zoom}`);
|
|
261
373
|
if (state.lh > 0) body.classList.add(`oks-lh-${state.lh}`);
|
|
262
374
|
if (state.align > 0) body.classList.add(`oks-align-${state.align}`);
|
|
263
375
|
if (state.ls > 0) body.classList.add(`oks-ls-${state.ls}`);
|
|
264
|
-
if (state.colorblind > 0)
|
|
376
|
+
if (state.colorblind > 0) rootEl.classList.add(`oks-colorblind-${state.colorblind}`);
|
|
265
377
|
if (state.font) body.classList.add("oks-a11y-font");
|
|
266
378
|
if (state.dyslexia) body.classList.add("oks-dyslexia");
|
|
267
379
|
if (state.contrast) body.classList.add("oks-a11y-contrast");
|
|
@@ -289,6 +401,10 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
289
401
|
btn.setAttribute("data-level", String(lvl));
|
|
290
402
|
btn.classList.toggle("is-active", lvl > 0);
|
|
291
403
|
btn.setAttribute("aria-pressed", lvl > 0 ? "true" : "false");
|
|
404
|
+
const max = parseInt(btn.getAttribute("data-levels") ?? "0", 10);
|
|
405
|
+
const lbl = btn.querySelector(".oks-label")?.textContent?.trim() ?? "";
|
|
406
|
+
if (lvl > 0 && max > 0) btn.setAttribute("aria-label", t.level(lbl, lvl, max));
|
|
407
|
+
else btn.removeAttribute("aria-label");
|
|
292
408
|
} else if (action === "toggle") {
|
|
293
409
|
const klass = btn.getAttribute("data-class") ?? "";
|
|
294
410
|
const key = TOGGLE_KEYS[klass];
|
|
@@ -334,9 +450,8 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
334
450
|
} else if (action === "mask") {
|
|
335
451
|
state.readingMask = !state.readingMask;
|
|
336
452
|
} else if (action === "preset") {
|
|
337
|
-
const id = btn.getAttribute("data-preset")
|
|
338
|
-
|
|
339
|
-
if (preset) Object.assign(state, preset);
|
|
453
|
+
const id = btn.getAttribute("data-preset");
|
|
454
|
+
if (id && PRESETS[id]) Object.assign(state, filterPresetForEnabled(id, enabled));
|
|
340
455
|
btn.classList.add("is-flashing");
|
|
341
456
|
setTimeout(() => btn.classList.remove("is-flashing"), 250);
|
|
342
457
|
}
|
|
@@ -348,28 +463,50 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
348
463
|
applyState();
|
|
349
464
|
saveState(storageKey, state);
|
|
350
465
|
};
|
|
466
|
+
let opener = null;
|
|
467
|
+
let ignoreDocClose = false;
|
|
351
468
|
const openPanel = () => {
|
|
469
|
+
if (panel.classList.contains("is-open")) return;
|
|
470
|
+
opener = deepActiveElement();
|
|
352
471
|
panel.classList.add("is-open");
|
|
353
472
|
panel.removeAttribute("inert");
|
|
354
|
-
trigger
|
|
473
|
+
trigger?.setAttribute("aria-expanded", "true");
|
|
474
|
+
ignoreDocClose = true;
|
|
475
|
+
setTimeout(() => {
|
|
476
|
+
ignoreDocClose = false;
|
|
477
|
+
}, 0);
|
|
355
478
|
const first = panel.querySelector("button:not([disabled])");
|
|
356
479
|
first?.focus();
|
|
357
480
|
};
|
|
358
481
|
const closePanel = () => {
|
|
482
|
+
if (!panel.classList.contains("is-open")) return;
|
|
359
483
|
panel.classList.remove("is-open");
|
|
360
484
|
panel.setAttribute("inert", "");
|
|
361
|
-
trigger
|
|
362
|
-
trigger.focus();
|
|
485
|
+
trigger?.setAttribute("aria-expanded", "false");
|
|
486
|
+
if (trigger) trigger.focus();
|
|
487
|
+
else if (opener?.isConnected) opener.focus();
|
|
488
|
+
opener = null;
|
|
363
489
|
};
|
|
364
|
-
const
|
|
365
|
-
e.stopPropagation();
|
|
490
|
+
const togglePanel = () => {
|
|
366
491
|
if (panel.classList.contains("is-open")) closePanel();
|
|
367
492
|
else openPanel();
|
|
368
493
|
};
|
|
494
|
+
let suppressClick = false;
|
|
495
|
+
const onTriggerClick = (e) => {
|
|
496
|
+
e.stopPropagation();
|
|
497
|
+
if (suppressClick) {
|
|
498
|
+
suppressClick = false;
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
togglePanel();
|
|
502
|
+
};
|
|
369
503
|
const onDocClick = (e) => {
|
|
370
504
|
if (!panel.classList.contains("is-open")) return;
|
|
505
|
+
if (ignoreDocClose) return;
|
|
371
506
|
const path = e.composedPath();
|
|
372
|
-
if (path.includes(panel)
|
|
507
|
+
if (path.includes(panel)) return;
|
|
508
|
+
if (trigger && path.includes(trigger)) return;
|
|
509
|
+
if (wrapper && path.includes(wrapper)) return;
|
|
373
510
|
closePanel();
|
|
374
511
|
};
|
|
375
512
|
const onKeyDown = (e) => {
|
|
@@ -396,6 +533,88 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
396
533
|
}
|
|
397
534
|
}
|
|
398
535
|
};
|
|
536
|
+
const NUDGE_KEY = `${storageKey}::pos`;
|
|
537
|
+
const clampMax = (v) => Math.max(-nudgeMax, Math.min(nudgeMax, v));
|
|
538
|
+
let nudge = { x: 0, y: 0 };
|
|
539
|
+
const loadNudge = () => {
|
|
540
|
+
if (nudgeMax <= 0) return;
|
|
541
|
+
try {
|
|
542
|
+
const raw = localStorage.getItem(NUDGE_KEY);
|
|
543
|
+
if (!raw) return;
|
|
544
|
+
const p = JSON.parse(raw);
|
|
545
|
+
if (typeof p?.x === "number" && typeof p?.y === "number") {
|
|
546
|
+
nudge = { x: clampMax(p.x), y: clampMax(p.y) };
|
|
547
|
+
}
|
|
548
|
+
} catch {
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const saveNudge = () => {
|
|
552
|
+
try {
|
|
553
|
+
if (nudge.x === 0 && nudge.y === 0) localStorage.removeItem(NUDGE_KEY);
|
|
554
|
+
else localStorage.setItem(NUDGE_KEY, JSON.stringify(nudge));
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
const applyNudge = () => {
|
|
559
|
+
if (wrapper) wrapper.style.translate = `${nudge.x}px ${nudge.y}px`;
|
|
560
|
+
};
|
|
561
|
+
const clampOffset = (x, y) => {
|
|
562
|
+
x = clampMax(x);
|
|
563
|
+
y = clampMax(y);
|
|
564
|
+
if (wrapper) {
|
|
565
|
+
const r = wrapper.getBoundingClientRect();
|
|
566
|
+
const pad = 4;
|
|
567
|
+
const baseLeft = r.left - nudge.x;
|
|
568
|
+
const baseTop = r.top - nudge.y;
|
|
569
|
+
const vw = window.innerWidth || 0;
|
|
570
|
+
const vh = window.innerHeight || 0;
|
|
571
|
+
if (r.width > 0 && vw > 0) x = Math.max(pad - baseLeft, Math.min(vw - pad - r.width - baseLeft, x));
|
|
572
|
+
if (r.height > 0 && vh > 0) y = Math.max(pad - baseTop, Math.min(vh - pad - r.height - baseTop, y));
|
|
573
|
+
}
|
|
574
|
+
return { x, y };
|
|
575
|
+
};
|
|
576
|
+
let dragStart = null;
|
|
577
|
+
let didDrag = false;
|
|
578
|
+
const DRAG_THRESHOLD = 4;
|
|
579
|
+
const onPointerDown = (e) => {
|
|
580
|
+
if (nudgeMax <= 0 || e.button !== 0) return;
|
|
581
|
+
dragStart = { px: e.clientX, py: e.clientY, ox: nudge.x, oy: nudge.y };
|
|
582
|
+
didDrag = false;
|
|
583
|
+
trigger?.setPointerCapture?.(e.pointerId);
|
|
584
|
+
};
|
|
585
|
+
const onPointerMove = (e) => {
|
|
586
|
+
if (!dragStart) return;
|
|
587
|
+
const dx = e.clientX - dragStart.px;
|
|
588
|
+
const dy = e.clientY - dragStart.py;
|
|
589
|
+
if (!didDrag && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
590
|
+
didDrag = true;
|
|
591
|
+
nudge = clampOffset(dragStart.ox + dx, dragStart.oy + dy);
|
|
592
|
+
applyNudge();
|
|
593
|
+
e.preventDefault();
|
|
594
|
+
};
|
|
595
|
+
const onPointerUp = () => {
|
|
596
|
+
if (!dragStart) return;
|
|
597
|
+
dragStart = null;
|
|
598
|
+
if (didDrag) {
|
|
599
|
+
saveNudge();
|
|
600
|
+
suppressClick = true;
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
const onTriggerKey = (e) => {
|
|
604
|
+
if (nudgeMax <= 0) return;
|
|
605
|
+
const step = e.shiftKey ? 1 : 10;
|
|
606
|
+
let dx = 0;
|
|
607
|
+
let dy = 0;
|
|
608
|
+
if (e.key === "ArrowLeft") dx = -step;
|
|
609
|
+
else if (e.key === "ArrowRight") dx = step;
|
|
610
|
+
else if (e.key === "ArrowUp") dy = -step;
|
|
611
|
+
else if (e.key === "ArrowDown") dy = step;
|
|
612
|
+
else return;
|
|
613
|
+
e.preventDefault();
|
|
614
|
+
nudge = clampOffset(nudge.x + dx, nudge.y + dy);
|
|
615
|
+
applyNudge();
|
|
616
|
+
saveNudge();
|
|
617
|
+
};
|
|
399
618
|
const onMove = (e) => {
|
|
400
619
|
if (!state.readingGuide && !state.readingMask) return;
|
|
401
620
|
const y = e.touches?.[0]?.clientY ?? e.clientY;
|
|
@@ -409,7 +628,7 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
409
628
|
if (mask) mask.style.setProperty("--oks-mask-y", `${y}px`);
|
|
410
629
|
}
|
|
411
630
|
};
|
|
412
|
-
trigger
|
|
631
|
+
trigger?.addEventListener("click", onTriggerClick);
|
|
413
632
|
closeBtn.addEventListener("click", closePanel);
|
|
414
633
|
resetBtn.addEventListener("click", onReset);
|
|
415
634
|
for (const btn of opts$) btn.addEventListener("click", onOptClick);
|
|
@@ -417,9 +636,19 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
417
636
|
document.addEventListener("keydown", onKeyDown);
|
|
418
637
|
document.addEventListener("mousemove", onMove);
|
|
419
638
|
document.addEventListener("touchmove", onMove, { passive: true });
|
|
639
|
+
if (nudgeMax > 0 && trigger) {
|
|
640
|
+
loadNudge();
|
|
641
|
+
applyNudge();
|
|
642
|
+
trigger.style.cursor = "grab";
|
|
643
|
+
trigger.style.touchAction = "none";
|
|
644
|
+
trigger.addEventListener("pointerdown", onPointerDown);
|
|
645
|
+
document.addEventListener("pointermove", onPointerMove);
|
|
646
|
+
document.addEventListener("pointerup", onPointerUp);
|
|
647
|
+
trigger.addEventListener("keydown", onTriggerKey);
|
|
648
|
+
}
|
|
420
649
|
applyState();
|
|
421
|
-
|
|
422
|
-
trigger
|
|
650
|
+
const dispose = () => {
|
|
651
|
+
trigger?.removeEventListener("click", onTriggerClick);
|
|
423
652
|
closeBtn.removeEventListener("click", closePanel);
|
|
424
653
|
resetBtn.removeEventListener("click", onReset);
|
|
425
654
|
for (const btn of opts$) btn.removeEventListener("click", onOptClick);
|
|
@@ -427,7 +656,12 @@ function bindPanelBehavior(root, opts = {}) {
|
|
|
427
656
|
document.removeEventListener("keydown", onKeyDown);
|
|
428
657
|
document.removeEventListener("mousemove", onMove);
|
|
429
658
|
document.removeEventListener("touchmove", onMove);
|
|
659
|
+
trigger?.removeEventListener("pointerdown", onPointerDown);
|
|
660
|
+
document.removeEventListener("pointermove", onPointerMove);
|
|
661
|
+
document.removeEventListener("pointerup", onPointerUp);
|
|
662
|
+
trigger?.removeEventListener("keydown", onTriggerKey);
|
|
430
663
|
};
|
|
664
|
+
return Object.assign(dispose, { open: openPanel, close: closePanel, toggle: togglePanel });
|
|
431
665
|
}
|
|
432
666
|
function ensureOverlay() {
|
|
433
667
|
let el = document.getElementById("oks-overlay-gray");
|
|
@@ -482,6 +716,12 @@ var PANEL_CSS = `
|
|
|
482
716
|
width: 60%;
|
|
483
717
|
height: 60%;
|
|
484
718
|
}
|
|
719
|
+
/* Porthole preset: a brushed-metal ring framing the standard glyph. The glyph
|
|
720
|
+
itself is untouched (discoverability), only the button gets the frame.
|
|
721
|
+
Hosts wanting a bespoke frame can target ::part(trigger) from light DOM. */
|
|
722
|
+
.oks-access-btn[data-trigger-icon="porthole"] {
|
|
723
|
+
box-shadow: 0 0 0 4px #b0bec5, 0 0 0 7px #546e7a, 0 6px 18px rgba(0,0,0,0.3);
|
|
724
|
+
}
|
|
485
725
|
.oks-active-badge {
|
|
486
726
|
position: absolute;
|
|
487
727
|
top: -2px;
|
|
@@ -650,6 +890,12 @@ var PANEL_CSS = `
|
|
|
650
890
|
.oks-access-branding { margin-top: 12px; font-size: 12px; color: #000; font-weight: 700; }
|
|
651
891
|
.oks-access-branding a { color: #000; text-decoration: none; border-bottom: 1px dotted #000; }
|
|
652
892
|
|
|
893
|
+
@media (prefers-reduced-motion: reduce) {
|
|
894
|
+
.oks-access-btn, .oks-access-panel, .oks-access-close,
|
|
895
|
+
.oks-preset, .oks-access-opt { transition: none; }
|
|
896
|
+
.oks-access-btn:hover { transform: scale(1); }
|
|
897
|
+
.oks-preset.is-flashing { transform: none; }
|
|
898
|
+
}
|
|
653
899
|
@media (max-width: 768px) {
|
|
654
900
|
.oks-access-panel {
|
|
655
901
|
width: 100%; height: 100%; max-height: 100%;
|
|
@@ -827,6 +1073,6 @@ body.oks-a11y-bigtargets summary:not(oksigenia-access-panel):not(oksigenia-acces
|
|
|
827
1073
|
}
|
|
828
1074
|
`;
|
|
829
1075
|
|
|
830
|
-
export { COLORBLIND_FILTERS_SVG, DEFAULT_STATE, EFFECT_CSS, PANEL_CSS, bindPanelBehavior, buildPanelHtml, getTranslation, isStateEmpty, loadState, positionCss, saveState, supportedLocales };
|
|
1076
|
+
export { ALL_CONTROLS, COLORBLIND_FILTERS_SVG, DEFAULT_STATE, EFFECT_CSS, PANEL_CSS, PRESETS, PRESET_IDS, bindPanelBehavior, buildPanelHtml, getTranslation, isStateEmpty, loadState, positionCss, resolveEnabledControls, saveState, supportedLocales };
|
|
831
1077
|
//# sourceMappingURL=index.js.map
|
|
832
1078
|
//# sourceMappingURL=index.js.map
|