@a.nemreen/a11y 0.1.2 → 0.1.3
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/README.md +1 -0
- package/dist/index.cjs +144 -74
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +144 -74
- package/dist/styles.css +114 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ const a11y = Accessibility.mount({
|
|
|
37
37
|
position: 'end', // end | start | left | right
|
|
38
38
|
stack: 0,
|
|
39
39
|
locale: 'auto', // auto | ar | en
|
|
40
|
+
// syncDocumentLocale: true, // also flip <html lang/dir> when toggling locale
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
Accessibility.createSkipLink({ href: '#main' });
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ var A11yController = class {
|
|
|
35
35
|
this.mqContrast = null;
|
|
36
36
|
this.localeObserver = null;
|
|
37
37
|
this.localeOverride = null;
|
|
38
|
+
this.syncDocumentLocale = false;
|
|
38
39
|
this.destroyed = false;
|
|
39
40
|
this.isOpen = false;
|
|
40
41
|
this.modes = /* @__PURE__ */ new Set();
|
|
@@ -55,6 +56,7 @@ var A11yController = class {
|
|
|
55
56
|
};
|
|
56
57
|
this.doc = options.document ?? document;
|
|
57
58
|
this.storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
59
|
+
this.syncDocumentLocale = options.syncDocumentLocale === true;
|
|
58
60
|
if (options.locale && options.locale !== "auto") {
|
|
59
61
|
this.localeOverride = options.locale;
|
|
60
62
|
this.locale = options.locale;
|
|
@@ -181,10 +183,13 @@ var A11yController = class {
|
|
|
181
183
|
this.maskBand = Math.max(20, Math.min(160, this.maskBand + delta));
|
|
182
184
|
this.notify();
|
|
183
185
|
}
|
|
184
|
-
setMaskY(y) {
|
|
186
|
+
setMaskY(y, options = {}) {
|
|
185
187
|
const vh = this.doc.defaultView?.innerHeight ?? 800;
|
|
186
188
|
this.maskY = Math.max(0, Math.min(vh, y));
|
|
187
|
-
this.
|
|
189
|
+
this.doc.documentElement.style.setProperty("--a11y-mask-y", `${this.maskY}px`);
|
|
190
|
+
if (options.persist === false) return;
|
|
191
|
+
this.persist();
|
|
192
|
+
this.emit();
|
|
188
193
|
}
|
|
189
194
|
reset() {
|
|
190
195
|
this.modes = /* @__PURE__ */ new Set();
|
|
@@ -208,12 +213,14 @@ var A11yController = class {
|
|
|
208
213
|
}
|
|
209
214
|
toggleLocale() {
|
|
210
215
|
const next = this.locale === "ar" ? "en" : "ar";
|
|
211
|
-
const root = this.doc.documentElement;
|
|
212
|
-
root.lang = next;
|
|
213
|
-
root.dir = next === "ar" ? "rtl" : "ltr";
|
|
214
|
-
root.dataset["locale"] = next;
|
|
215
216
|
this.localeOverride = next;
|
|
216
217
|
this.locale = next;
|
|
218
|
+
if (this.syncDocumentLocale) {
|
|
219
|
+
const root = this.doc.documentElement;
|
|
220
|
+
root.lang = next;
|
|
221
|
+
root.dir = next === "ar" ? "rtl" : "ltr";
|
|
222
|
+
root.dataset["locale"] = next;
|
|
223
|
+
}
|
|
217
224
|
this.emit();
|
|
218
225
|
return next;
|
|
219
226
|
}
|
|
@@ -676,8 +683,28 @@ var ICONS = {
|
|
|
676
683
|
sun: '<path d="M12 4V2m0 20v-2m8-8h2M2 12h2m13.7 5.7 1.4 1.4M4.9 4.9l1.4 1.4m0 11.4-1.4 1.4M19.1 4.9l-1.4 1.4M12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"/>',
|
|
677
684
|
colorPicker: '<path d="M12 3a7 7 0 0 1 0 14h-1l-4 4v-5a7 7 0 0 1 5-13Z"/>'
|
|
678
685
|
};
|
|
686
|
+
var STROKE_ICONS = /* @__PURE__ */ new Set([
|
|
687
|
+
"close",
|
|
688
|
+
"heading",
|
|
689
|
+
"linkAlt",
|
|
690
|
+
"pause",
|
|
691
|
+
"textFont",
|
|
692
|
+
"textAlign",
|
|
693
|
+
"textUnderline",
|
|
694
|
+
"letterSpacing",
|
|
695
|
+
"maximize",
|
|
696
|
+
"minus",
|
|
697
|
+
"plus",
|
|
698
|
+
"glasses",
|
|
699
|
+
"sun",
|
|
700
|
+
"touch",
|
|
701
|
+
"mask"
|
|
702
|
+
]);
|
|
679
703
|
function iconSvg(name, size = 18) {
|
|
680
704
|
const path = ICONS[name] ?? ICONS.access;
|
|
705
|
+
if (STROKE_ICONS.has(name)) {
|
|
706
|
+
return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${path}</svg>`;
|
|
707
|
+
}
|
|
681
708
|
return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false">${path}</svg>`;
|
|
682
709
|
}
|
|
683
710
|
|
|
@@ -714,13 +741,25 @@ var A11yWidget = class {
|
|
|
714
741
|
this.resetArmed = false;
|
|
715
742
|
this.resetTimer = null;
|
|
716
743
|
this.draggingMask = false;
|
|
744
|
+
this.wasOpen = false;
|
|
745
|
+
this.panelScrollTop = 0;
|
|
717
746
|
this.onKeyDown = (e) => this.handleKey(e);
|
|
718
747
|
this.onPointerMove = (e) => {
|
|
719
748
|
if (!this.draggingMask) return;
|
|
720
|
-
this.ctrl.setMaskY(e.clientY);
|
|
749
|
+
this.ctrl.setMaskY(e.clientY, { persist: false });
|
|
750
|
+
this.syncMaskDom();
|
|
721
751
|
};
|
|
722
752
|
this.onPointerUp = () => {
|
|
753
|
+
if (!this.draggingMask) return;
|
|
723
754
|
this.draggingMask = false;
|
|
755
|
+
this.ctrl.setMaskY(this.ctrl.maskY, { persist: true });
|
|
756
|
+
};
|
|
757
|
+
this.onRootClick = (e) => this.handleClick(e);
|
|
758
|
+
this.onRootPointerDown = (e) => {
|
|
759
|
+
const t = e.target?.closest?.('[data-a11y-action="mask-drag"]');
|
|
760
|
+
if (!t || !this.rootEl?.contains(t)) return;
|
|
761
|
+
e.preventDefault();
|
|
762
|
+
this.draggingMask = true;
|
|
724
763
|
};
|
|
725
764
|
this.ctrl = ctrl;
|
|
726
765
|
this.position = options.position ?? "end";
|
|
@@ -733,6 +772,8 @@ var A11yWidget = class {
|
|
|
733
772
|
this.rootEl.className = "a11y-root";
|
|
734
773
|
this.rootEl.setAttribute("data-a11y-ui", "");
|
|
735
774
|
this.mountRoot.appendChild(this.rootEl);
|
|
775
|
+
this.rootEl.addEventListener("click", this.onRootClick);
|
|
776
|
+
this.rootEl.addEventListener("pointerdown", this.onRootPointerDown);
|
|
736
777
|
this.unsub = this.ctrl.subscribe(() => this.render());
|
|
737
778
|
document.addEventListener("keydown", this.onKeyDown);
|
|
738
779
|
document.addEventListener("pointermove", this.onPointerMove);
|
|
@@ -742,6 +783,8 @@ var A11yWidget = class {
|
|
|
742
783
|
destroy() {
|
|
743
784
|
this.unsub?.();
|
|
744
785
|
this.unsub = null;
|
|
786
|
+
this.rootEl?.removeEventListener("click", this.onRootClick);
|
|
787
|
+
this.rootEl?.removeEventListener("pointerdown", this.onRootPointerDown);
|
|
745
788
|
document.removeEventListener("keydown", this.onKeyDown);
|
|
746
789
|
document.removeEventListener("pointermove", this.onPointerMove);
|
|
747
790
|
document.removeEventListener("pointerup", this.onPointerUp);
|
|
@@ -814,7 +857,16 @@ var A11yWidget = class {
|
|
|
814
857
|
const chips = this.activeChips();
|
|
815
858
|
const badge = chips.length;
|
|
816
859
|
const open = this.ctrl.isOpen;
|
|
860
|
+
const opening = open && !this.wasOpen;
|
|
861
|
+
const stayingOpen = open && this.wasOpen;
|
|
817
862
|
const readingMask = this.ctrl.hasEffectiveMode("reading-mask");
|
|
863
|
+
const dir = this.ctrl.locale === "ar" ? "rtl" : "ltr";
|
|
864
|
+
if (stayingOpen) {
|
|
865
|
+
const body = this.rootEl.querySelector(".a11y-panel__body");
|
|
866
|
+
if (body) this.panelScrollTop = body.scrollTop;
|
|
867
|
+
}
|
|
868
|
+
this.rootEl.lang = this.ctrl.locale;
|
|
869
|
+
this.rootEl.dir = dir;
|
|
818
870
|
this.rootEl.innerHTML = `
|
|
819
871
|
<svg class="a11y-deuteranopia-svg" aria-hidden="true" focusable="false">
|
|
820
872
|
<filter id="a11y-deuteranopia">
|
|
@@ -840,23 +892,42 @@ var A11yWidget = class {
|
|
|
840
892
|
${badge > 0 ? `<span class="a11y-fab__badge" aria-hidden="true">${badge > 9 ? "9+" : badge}</span>` : ""}
|
|
841
893
|
</button>
|
|
842
894
|
|
|
843
|
-
${open ? this.renderPanel(c, chips) : ""}
|
|
895
|
+
${open ? this.renderPanel(c, chips, stayingOpen) : ""}
|
|
844
896
|
${readingMask ? this.renderMask(c) : ""}
|
|
845
897
|
`;
|
|
846
|
-
|
|
847
|
-
|
|
898
|
+
if (stayingOpen) {
|
|
899
|
+
const body = this.rootEl.querySelector(".a11y-panel__body");
|
|
900
|
+
if (body) body.scrollTop = this.panelScrollTop;
|
|
901
|
+
}
|
|
902
|
+
if (opening) {
|
|
848
903
|
const closeBtn = this.rootEl.querySelector('[data-a11y-action="close"]');
|
|
849
904
|
queueMicrotask(() => closeBtn?.focus());
|
|
850
905
|
}
|
|
906
|
+
this.wasOpen = open;
|
|
851
907
|
}
|
|
852
|
-
|
|
908
|
+
syncMaskDom() {
|
|
909
|
+
if (!this.rootEl) return;
|
|
910
|
+
const shades = this.rootEl.querySelectorAll(".a11y-mask-shade");
|
|
911
|
+
const toolbar = this.rootEl.querySelector(".a11y-mask-toolbar");
|
|
912
|
+
if (shades[0]) {
|
|
913
|
+
shades[0].style.height = "calc(var(--a11y-mask-y) - var(--a11y-mask-band))";
|
|
914
|
+
}
|
|
915
|
+
if (shades[1]) {
|
|
916
|
+
shades[1].style.top = "calc(var(--a11y-mask-y) + var(--a11y-mask-band))";
|
|
917
|
+
}
|
|
918
|
+
if (toolbar) {
|
|
919
|
+
toolbar.style.top = "calc(var(--a11y-mask-y) + var(--a11y-mask-band) + 8px)";
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
renderPanel(c, chips, staticPanel) {
|
|
853
923
|
const profileCount = this.ctrl.activeModeCount("modes");
|
|
924
|
+
const panelClass = staticPanel ? `a11y-panel a11y-panel--${this.position} a11y-panel--static` : `a11y-panel a11y-panel--${this.position}`;
|
|
854
925
|
return `
|
|
855
926
|
<div class="a11y-layer" role="presentation">
|
|
856
927
|
<div class="a11y-backdrop" data-a11y-action="close" aria-hidden="true"></div>
|
|
857
928
|
<aside
|
|
858
929
|
id="${PANEL_ID}"
|
|
859
|
-
class="
|
|
930
|
+
class="${panelClass}"
|
|
860
931
|
role="dialog"
|
|
861
932
|
aria-modal="true"
|
|
862
933
|
aria-label="${escapeAttr(c.panelLabel)}"
|
|
@@ -1050,67 +1121,65 @@ var A11yWidget = class {
|
|
|
1050
1121
|
</button>
|
|
1051
1122
|
</div>`;
|
|
1052
1123
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
this.rootEl
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
this.rootEl.
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
});
|
|
1113
|
-
});
|
|
1124
|
+
handleClick(e) {
|
|
1125
|
+
const target = e.target;
|
|
1126
|
+
if (!target || !this.rootEl) return;
|
|
1127
|
+
const actionEl = target.closest("[data-a11y-action]");
|
|
1128
|
+
if (actionEl && this.rootEl.contains(actionEl)) {
|
|
1129
|
+
const action = actionEl.getAttribute("data-a11y-action");
|
|
1130
|
+
if (action === "toggle") {
|
|
1131
|
+
this.ctrl.toggle(actionEl);
|
|
1132
|
+
} else if (action === "close") {
|
|
1133
|
+
this.ctrl.close();
|
|
1134
|
+
} else if (action === "reset") {
|
|
1135
|
+
this.onReset();
|
|
1136
|
+
} else if (action === "mask-smaller") {
|
|
1137
|
+
this.ctrl.adjustMaskBand(-20);
|
|
1138
|
+
} else if (action === "mask-larger") {
|
|
1139
|
+
this.ctrl.adjustMaskBand(20);
|
|
1140
|
+
} else if (action === "mask-close") {
|
|
1141
|
+
this.ctrl.setMode("reading-mask", false);
|
|
1142
|
+
}
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
const bundleEl = target.closest("[data-a11y-bundle]");
|
|
1146
|
+
if (bundleEl && this.rootEl.contains(bundleEl)) {
|
|
1147
|
+
const id = bundleEl.getAttribute("data-a11y-bundle");
|
|
1148
|
+
this.ctrl.setMode(id, !this.ctrl.hasMode(id));
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
const toggleEl = target.closest("[data-a11y-toggle]");
|
|
1152
|
+
if (toggleEl && this.rootEl.contains(toggleEl)) {
|
|
1153
|
+
const mode = toggleEl.getAttribute("data-a11y-toggle");
|
|
1154
|
+
this.ctrl.setMode(mode, !this.ctrl.hasEffectiveMode(mode));
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
const filterEl = target.closest("[data-a11y-filter]");
|
|
1158
|
+
if (filterEl && this.rootEl.contains(filterEl)) {
|
|
1159
|
+
const filter = filterEl.getAttribute("data-a11y-filter");
|
|
1160
|
+
this.ctrl.setVisualFilter(filter);
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const stepEl = target.closest("[data-a11y-step]");
|
|
1164
|
+
if (stepEl && this.rootEl.contains(stepEl)) {
|
|
1165
|
+
e.preventDefault();
|
|
1166
|
+
const id = stepEl.getAttribute("data-a11y-step");
|
|
1167
|
+
const delta = Number(stepEl.getAttribute("data-delta") || "1");
|
|
1168
|
+
if (id === "font") this.ctrl.stepFontStep(delta);
|
|
1169
|
+
else if (id === "align") this.ctrl.stepTextAlign(delta);
|
|
1170
|
+
else if (id === "line") this.ctrl.stepLineHeight(delta);
|
|
1171
|
+
else if (id === "letter") this.ctrl.stepLetterSpacing(delta);
|
|
1172
|
+
else if (id === "word") this.ctrl.stepWordSpacing(delta);
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
const focusEl = target.closest("[data-a11y-focus]");
|
|
1176
|
+
if (focusEl && this.rootEl.contains(focusEl)) {
|
|
1177
|
+
const id = focusEl.getAttribute("data-a11y-focus");
|
|
1178
|
+
const control = this.rootEl.querySelector(`[data-a11y-control="${id}"]`);
|
|
1179
|
+
control?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
1180
|
+
const focusable = control?.querySelector("button, [tabindex]");
|
|
1181
|
+
focusable?.focus();
|
|
1182
|
+
}
|
|
1114
1183
|
}
|
|
1115
1184
|
onReset() {
|
|
1116
1185
|
if (!this.resetArmed) {
|
|
@@ -1182,7 +1251,8 @@ function mount(options = {}) {
|
|
|
1182
1251
|
ensureStyles();
|
|
1183
1252
|
const controller = new A11yController({
|
|
1184
1253
|
storageKey: options.storageKey,
|
|
1185
|
-
locale: options.locale
|
|
1254
|
+
locale: options.locale,
|
|
1255
|
+
syncDocumentLocale: options.syncDocumentLocale
|
|
1186
1256
|
});
|
|
1187
1257
|
let widget = null;
|
|
1188
1258
|
if (!options.headless) {
|
package/dist/index.d.cts
CHANGED
|
@@ -16,6 +16,11 @@ interface A11yMountOptions {
|
|
|
16
16
|
stack?: number;
|
|
17
17
|
/** UI locale. Default: `auto` (from `<html lang>` / `data-locale`). */
|
|
18
18
|
locale?: A11yLocale | 'auto';
|
|
19
|
+
/**
|
|
20
|
+
* When true, `toggleLocale()` also updates `<html lang>` / `dir`.
|
|
21
|
+
* Default: `false` (widget UI only — avoids flipping the host page).
|
|
22
|
+
*/
|
|
23
|
+
syncDocumentLocale?: boolean;
|
|
19
24
|
/** localStorage key. Default: `dga-a11y`. */
|
|
20
25
|
storageKey?: string;
|
|
21
26
|
/** Mount root. Default: `document.body`. */
|
|
@@ -48,6 +53,7 @@ declare class A11yController {
|
|
|
48
53
|
private mqContrast;
|
|
49
54
|
private localeObserver;
|
|
50
55
|
private localeOverride;
|
|
56
|
+
private syncDocumentLocale;
|
|
51
57
|
private destroyed;
|
|
52
58
|
isOpen: boolean;
|
|
53
59
|
modes: Set<A11yMode>;
|
|
@@ -63,6 +69,7 @@ declare class A11yController {
|
|
|
63
69
|
constructor(options?: {
|
|
64
70
|
storageKey?: string;
|
|
65
71
|
locale?: A11yLocale | 'auto';
|
|
72
|
+
syncDocumentLocale?: boolean;
|
|
66
73
|
document?: Document;
|
|
67
74
|
});
|
|
68
75
|
subscribe(listener: A11yListener): () => void;
|
|
@@ -84,7 +91,9 @@ declare class A11yController {
|
|
|
84
91
|
stepLetterSpacing(delta: number): void;
|
|
85
92
|
stepWordSpacing(delta: number): void;
|
|
86
93
|
adjustMaskBand(delta: number): void;
|
|
87
|
-
setMaskY(y: number
|
|
94
|
+
setMaskY(y: number, options?: {
|
|
95
|
+
persist?: boolean;
|
|
96
|
+
}): void;
|
|
88
97
|
reset(): void;
|
|
89
98
|
announce(msg: string): void;
|
|
90
99
|
toggleLocale(): A11yLocale;
|
|
@@ -126,9 +135,13 @@ declare class A11yWidget {
|
|
|
126
135
|
private resetArmed;
|
|
127
136
|
private resetTimer;
|
|
128
137
|
private draggingMask;
|
|
138
|
+
private wasOpen;
|
|
139
|
+
private panelScrollTop;
|
|
129
140
|
private onKeyDown;
|
|
130
141
|
private onPointerMove;
|
|
131
142
|
private onPointerUp;
|
|
143
|
+
private onRootClick;
|
|
144
|
+
private onRootPointerDown;
|
|
132
145
|
constructor(ctrl: A11yController, options?: A11yWidgetOptions);
|
|
133
146
|
mount(): void;
|
|
134
147
|
destroy(): void;
|
|
@@ -136,10 +149,11 @@ declare class A11yWidget {
|
|
|
136
149
|
private fabBottom;
|
|
137
150
|
private activeChips;
|
|
138
151
|
private render;
|
|
152
|
+
private syncMaskDom;
|
|
139
153
|
private renderPanel;
|
|
140
154
|
private renderSteppers;
|
|
141
155
|
private renderMask;
|
|
142
|
-
private
|
|
156
|
+
private handleClick;
|
|
143
157
|
private onReset;
|
|
144
158
|
private handleKey;
|
|
145
159
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,11 @@ interface A11yMountOptions {
|
|
|
16
16
|
stack?: number;
|
|
17
17
|
/** UI locale. Default: `auto` (from `<html lang>` / `data-locale`). */
|
|
18
18
|
locale?: A11yLocale | 'auto';
|
|
19
|
+
/**
|
|
20
|
+
* When true, `toggleLocale()` also updates `<html lang>` / `dir`.
|
|
21
|
+
* Default: `false` (widget UI only — avoids flipping the host page).
|
|
22
|
+
*/
|
|
23
|
+
syncDocumentLocale?: boolean;
|
|
19
24
|
/** localStorage key. Default: `dga-a11y`. */
|
|
20
25
|
storageKey?: string;
|
|
21
26
|
/** Mount root. Default: `document.body`. */
|
|
@@ -48,6 +53,7 @@ declare class A11yController {
|
|
|
48
53
|
private mqContrast;
|
|
49
54
|
private localeObserver;
|
|
50
55
|
private localeOverride;
|
|
56
|
+
private syncDocumentLocale;
|
|
51
57
|
private destroyed;
|
|
52
58
|
isOpen: boolean;
|
|
53
59
|
modes: Set<A11yMode>;
|
|
@@ -63,6 +69,7 @@ declare class A11yController {
|
|
|
63
69
|
constructor(options?: {
|
|
64
70
|
storageKey?: string;
|
|
65
71
|
locale?: A11yLocale | 'auto';
|
|
72
|
+
syncDocumentLocale?: boolean;
|
|
66
73
|
document?: Document;
|
|
67
74
|
});
|
|
68
75
|
subscribe(listener: A11yListener): () => void;
|
|
@@ -84,7 +91,9 @@ declare class A11yController {
|
|
|
84
91
|
stepLetterSpacing(delta: number): void;
|
|
85
92
|
stepWordSpacing(delta: number): void;
|
|
86
93
|
adjustMaskBand(delta: number): void;
|
|
87
|
-
setMaskY(y: number
|
|
94
|
+
setMaskY(y: number, options?: {
|
|
95
|
+
persist?: boolean;
|
|
96
|
+
}): void;
|
|
88
97
|
reset(): void;
|
|
89
98
|
announce(msg: string): void;
|
|
90
99
|
toggleLocale(): A11yLocale;
|
|
@@ -126,9 +135,13 @@ declare class A11yWidget {
|
|
|
126
135
|
private resetArmed;
|
|
127
136
|
private resetTimer;
|
|
128
137
|
private draggingMask;
|
|
138
|
+
private wasOpen;
|
|
139
|
+
private panelScrollTop;
|
|
129
140
|
private onKeyDown;
|
|
130
141
|
private onPointerMove;
|
|
131
142
|
private onPointerUp;
|
|
143
|
+
private onRootClick;
|
|
144
|
+
private onRootPointerDown;
|
|
132
145
|
constructor(ctrl: A11yController, options?: A11yWidgetOptions);
|
|
133
146
|
mount(): void;
|
|
134
147
|
destroy(): void;
|
|
@@ -136,10 +149,11 @@ declare class A11yWidget {
|
|
|
136
149
|
private fabBottom;
|
|
137
150
|
private activeChips;
|
|
138
151
|
private render;
|
|
152
|
+
private syncMaskDom;
|
|
139
153
|
private renderPanel;
|
|
140
154
|
private renderSteppers;
|
|
141
155
|
private renderMask;
|
|
142
|
-
private
|
|
156
|
+
private handleClick;
|
|
143
157
|
private onReset;
|
|
144
158
|
private handleKey;
|
|
145
159
|
}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ var A11yController = class {
|
|
|
33
33
|
this.mqContrast = null;
|
|
34
34
|
this.localeObserver = null;
|
|
35
35
|
this.localeOverride = null;
|
|
36
|
+
this.syncDocumentLocale = false;
|
|
36
37
|
this.destroyed = false;
|
|
37
38
|
this.isOpen = false;
|
|
38
39
|
this.modes = /* @__PURE__ */ new Set();
|
|
@@ -53,6 +54,7 @@ var A11yController = class {
|
|
|
53
54
|
};
|
|
54
55
|
this.doc = options.document ?? document;
|
|
55
56
|
this.storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;
|
|
57
|
+
this.syncDocumentLocale = options.syncDocumentLocale === true;
|
|
56
58
|
if (options.locale && options.locale !== "auto") {
|
|
57
59
|
this.localeOverride = options.locale;
|
|
58
60
|
this.locale = options.locale;
|
|
@@ -179,10 +181,13 @@ var A11yController = class {
|
|
|
179
181
|
this.maskBand = Math.max(20, Math.min(160, this.maskBand + delta));
|
|
180
182
|
this.notify();
|
|
181
183
|
}
|
|
182
|
-
setMaskY(y) {
|
|
184
|
+
setMaskY(y, options = {}) {
|
|
183
185
|
const vh = this.doc.defaultView?.innerHeight ?? 800;
|
|
184
186
|
this.maskY = Math.max(0, Math.min(vh, y));
|
|
185
|
-
this.
|
|
187
|
+
this.doc.documentElement.style.setProperty("--a11y-mask-y", `${this.maskY}px`);
|
|
188
|
+
if (options.persist === false) return;
|
|
189
|
+
this.persist();
|
|
190
|
+
this.emit();
|
|
186
191
|
}
|
|
187
192
|
reset() {
|
|
188
193
|
this.modes = /* @__PURE__ */ new Set();
|
|
@@ -206,12 +211,14 @@ var A11yController = class {
|
|
|
206
211
|
}
|
|
207
212
|
toggleLocale() {
|
|
208
213
|
const next = this.locale === "ar" ? "en" : "ar";
|
|
209
|
-
const root = this.doc.documentElement;
|
|
210
|
-
root.lang = next;
|
|
211
|
-
root.dir = next === "ar" ? "rtl" : "ltr";
|
|
212
|
-
root.dataset["locale"] = next;
|
|
213
214
|
this.localeOverride = next;
|
|
214
215
|
this.locale = next;
|
|
216
|
+
if (this.syncDocumentLocale) {
|
|
217
|
+
const root = this.doc.documentElement;
|
|
218
|
+
root.lang = next;
|
|
219
|
+
root.dir = next === "ar" ? "rtl" : "ltr";
|
|
220
|
+
root.dataset["locale"] = next;
|
|
221
|
+
}
|
|
215
222
|
this.emit();
|
|
216
223
|
return next;
|
|
217
224
|
}
|
|
@@ -674,8 +681,28 @@ var ICONS = {
|
|
|
674
681
|
sun: '<path d="M12 4V2m0 20v-2m8-8h2M2 12h2m13.7 5.7 1.4 1.4M4.9 4.9l1.4 1.4m0 11.4-1.4 1.4M19.1 4.9l-1.4 1.4M12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"/>',
|
|
675
682
|
colorPicker: '<path d="M12 3a7 7 0 0 1 0 14h-1l-4 4v-5a7 7 0 0 1 5-13Z"/>'
|
|
676
683
|
};
|
|
684
|
+
var STROKE_ICONS = /* @__PURE__ */ new Set([
|
|
685
|
+
"close",
|
|
686
|
+
"heading",
|
|
687
|
+
"linkAlt",
|
|
688
|
+
"pause",
|
|
689
|
+
"textFont",
|
|
690
|
+
"textAlign",
|
|
691
|
+
"textUnderline",
|
|
692
|
+
"letterSpacing",
|
|
693
|
+
"maximize",
|
|
694
|
+
"minus",
|
|
695
|
+
"plus",
|
|
696
|
+
"glasses",
|
|
697
|
+
"sun",
|
|
698
|
+
"touch",
|
|
699
|
+
"mask"
|
|
700
|
+
]);
|
|
677
701
|
function iconSvg(name, size = 18) {
|
|
678
702
|
const path = ICONS[name] ?? ICONS.access;
|
|
703
|
+
if (STROKE_ICONS.has(name)) {
|
|
704
|
+
return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${path}</svg>`;
|
|
705
|
+
}
|
|
679
706
|
return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false">${path}</svg>`;
|
|
680
707
|
}
|
|
681
708
|
|
|
@@ -712,13 +739,25 @@ var A11yWidget = class {
|
|
|
712
739
|
this.resetArmed = false;
|
|
713
740
|
this.resetTimer = null;
|
|
714
741
|
this.draggingMask = false;
|
|
742
|
+
this.wasOpen = false;
|
|
743
|
+
this.panelScrollTop = 0;
|
|
715
744
|
this.onKeyDown = (e) => this.handleKey(e);
|
|
716
745
|
this.onPointerMove = (e) => {
|
|
717
746
|
if (!this.draggingMask) return;
|
|
718
|
-
this.ctrl.setMaskY(e.clientY);
|
|
747
|
+
this.ctrl.setMaskY(e.clientY, { persist: false });
|
|
748
|
+
this.syncMaskDom();
|
|
719
749
|
};
|
|
720
750
|
this.onPointerUp = () => {
|
|
751
|
+
if (!this.draggingMask) return;
|
|
721
752
|
this.draggingMask = false;
|
|
753
|
+
this.ctrl.setMaskY(this.ctrl.maskY, { persist: true });
|
|
754
|
+
};
|
|
755
|
+
this.onRootClick = (e) => this.handleClick(e);
|
|
756
|
+
this.onRootPointerDown = (e) => {
|
|
757
|
+
const t = e.target?.closest?.('[data-a11y-action="mask-drag"]');
|
|
758
|
+
if (!t || !this.rootEl?.contains(t)) return;
|
|
759
|
+
e.preventDefault();
|
|
760
|
+
this.draggingMask = true;
|
|
722
761
|
};
|
|
723
762
|
this.ctrl = ctrl;
|
|
724
763
|
this.position = options.position ?? "end";
|
|
@@ -731,6 +770,8 @@ var A11yWidget = class {
|
|
|
731
770
|
this.rootEl.className = "a11y-root";
|
|
732
771
|
this.rootEl.setAttribute("data-a11y-ui", "");
|
|
733
772
|
this.mountRoot.appendChild(this.rootEl);
|
|
773
|
+
this.rootEl.addEventListener("click", this.onRootClick);
|
|
774
|
+
this.rootEl.addEventListener("pointerdown", this.onRootPointerDown);
|
|
734
775
|
this.unsub = this.ctrl.subscribe(() => this.render());
|
|
735
776
|
document.addEventListener("keydown", this.onKeyDown);
|
|
736
777
|
document.addEventListener("pointermove", this.onPointerMove);
|
|
@@ -740,6 +781,8 @@ var A11yWidget = class {
|
|
|
740
781
|
destroy() {
|
|
741
782
|
this.unsub?.();
|
|
742
783
|
this.unsub = null;
|
|
784
|
+
this.rootEl?.removeEventListener("click", this.onRootClick);
|
|
785
|
+
this.rootEl?.removeEventListener("pointerdown", this.onRootPointerDown);
|
|
743
786
|
document.removeEventListener("keydown", this.onKeyDown);
|
|
744
787
|
document.removeEventListener("pointermove", this.onPointerMove);
|
|
745
788
|
document.removeEventListener("pointerup", this.onPointerUp);
|
|
@@ -812,7 +855,16 @@ var A11yWidget = class {
|
|
|
812
855
|
const chips = this.activeChips();
|
|
813
856
|
const badge = chips.length;
|
|
814
857
|
const open = this.ctrl.isOpen;
|
|
858
|
+
const opening = open && !this.wasOpen;
|
|
859
|
+
const stayingOpen = open && this.wasOpen;
|
|
815
860
|
const readingMask = this.ctrl.hasEffectiveMode("reading-mask");
|
|
861
|
+
const dir = this.ctrl.locale === "ar" ? "rtl" : "ltr";
|
|
862
|
+
if (stayingOpen) {
|
|
863
|
+
const body = this.rootEl.querySelector(".a11y-panel__body");
|
|
864
|
+
if (body) this.panelScrollTop = body.scrollTop;
|
|
865
|
+
}
|
|
866
|
+
this.rootEl.lang = this.ctrl.locale;
|
|
867
|
+
this.rootEl.dir = dir;
|
|
816
868
|
this.rootEl.innerHTML = `
|
|
817
869
|
<svg class="a11y-deuteranopia-svg" aria-hidden="true" focusable="false">
|
|
818
870
|
<filter id="a11y-deuteranopia">
|
|
@@ -838,23 +890,42 @@ var A11yWidget = class {
|
|
|
838
890
|
${badge > 0 ? `<span class="a11y-fab__badge" aria-hidden="true">${badge > 9 ? "9+" : badge}</span>` : ""}
|
|
839
891
|
</button>
|
|
840
892
|
|
|
841
|
-
${open ? this.renderPanel(c, chips) : ""}
|
|
893
|
+
${open ? this.renderPanel(c, chips, stayingOpen) : ""}
|
|
842
894
|
${readingMask ? this.renderMask(c) : ""}
|
|
843
895
|
`;
|
|
844
|
-
|
|
845
|
-
|
|
896
|
+
if (stayingOpen) {
|
|
897
|
+
const body = this.rootEl.querySelector(".a11y-panel__body");
|
|
898
|
+
if (body) body.scrollTop = this.panelScrollTop;
|
|
899
|
+
}
|
|
900
|
+
if (opening) {
|
|
846
901
|
const closeBtn = this.rootEl.querySelector('[data-a11y-action="close"]');
|
|
847
902
|
queueMicrotask(() => closeBtn?.focus());
|
|
848
903
|
}
|
|
904
|
+
this.wasOpen = open;
|
|
849
905
|
}
|
|
850
|
-
|
|
906
|
+
syncMaskDom() {
|
|
907
|
+
if (!this.rootEl) return;
|
|
908
|
+
const shades = this.rootEl.querySelectorAll(".a11y-mask-shade");
|
|
909
|
+
const toolbar = this.rootEl.querySelector(".a11y-mask-toolbar");
|
|
910
|
+
if (shades[0]) {
|
|
911
|
+
shades[0].style.height = "calc(var(--a11y-mask-y) - var(--a11y-mask-band))";
|
|
912
|
+
}
|
|
913
|
+
if (shades[1]) {
|
|
914
|
+
shades[1].style.top = "calc(var(--a11y-mask-y) + var(--a11y-mask-band))";
|
|
915
|
+
}
|
|
916
|
+
if (toolbar) {
|
|
917
|
+
toolbar.style.top = "calc(var(--a11y-mask-y) + var(--a11y-mask-band) + 8px)";
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
renderPanel(c, chips, staticPanel) {
|
|
851
921
|
const profileCount = this.ctrl.activeModeCount("modes");
|
|
922
|
+
const panelClass = staticPanel ? `a11y-panel a11y-panel--${this.position} a11y-panel--static` : `a11y-panel a11y-panel--${this.position}`;
|
|
852
923
|
return `
|
|
853
924
|
<div class="a11y-layer" role="presentation">
|
|
854
925
|
<div class="a11y-backdrop" data-a11y-action="close" aria-hidden="true"></div>
|
|
855
926
|
<aside
|
|
856
927
|
id="${PANEL_ID}"
|
|
857
|
-
class="
|
|
928
|
+
class="${panelClass}"
|
|
858
929
|
role="dialog"
|
|
859
930
|
aria-modal="true"
|
|
860
931
|
aria-label="${escapeAttr(c.panelLabel)}"
|
|
@@ -1048,67 +1119,65 @@ var A11yWidget = class {
|
|
|
1048
1119
|
</button>
|
|
1049
1120
|
</div>`;
|
|
1050
1121
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
this.rootEl
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
this.rootEl.
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
});
|
|
1111
|
-
});
|
|
1122
|
+
handleClick(e) {
|
|
1123
|
+
const target = e.target;
|
|
1124
|
+
if (!target || !this.rootEl) return;
|
|
1125
|
+
const actionEl = target.closest("[data-a11y-action]");
|
|
1126
|
+
if (actionEl && this.rootEl.contains(actionEl)) {
|
|
1127
|
+
const action = actionEl.getAttribute("data-a11y-action");
|
|
1128
|
+
if (action === "toggle") {
|
|
1129
|
+
this.ctrl.toggle(actionEl);
|
|
1130
|
+
} else if (action === "close") {
|
|
1131
|
+
this.ctrl.close();
|
|
1132
|
+
} else if (action === "reset") {
|
|
1133
|
+
this.onReset();
|
|
1134
|
+
} else if (action === "mask-smaller") {
|
|
1135
|
+
this.ctrl.adjustMaskBand(-20);
|
|
1136
|
+
} else if (action === "mask-larger") {
|
|
1137
|
+
this.ctrl.adjustMaskBand(20);
|
|
1138
|
+
} else if (action === "mask-close") {
|
|
1139
|
+
this.ctrl.setMode("reading-mask", false);
|
|
1140
|
+
}
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
const bundleEl = target.closest("[data-a11y-bundle]");
|
|
1144
|
+
if (bundleEl && this.rootEl.contains(bundleEl)) {
|
|
1145
|
+
const id = bundleEl.getAttribute("data-a11y-bundle");
|
|
1146
|
+
this.ctrl.setMode(id, !this.ctrl.hasMode(id));
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
const toggleEl = target.closest("[data-a11y-toggle]");
|
|
1150
|
+
if (toggleEl && this.rootEl.contains(toggleEl)) {
|
|
1151
|
+
const mode = toggleEl.getAttribute("data-a11y-toggle");
|
|
1152
|
+
this.ctrl.setMode(mode, !this.ctrl.hasEffectiveMode(mode));
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
const filterEl = target.closest("[data-a11y-filter]");
|
|
1156
|
+
if (filterEl && this.rootEl.contains(filterEl)) {
|
|
1157
|
+
const filter = filterEl.getAttribute("data-a11y-filter");
|
|
1158
|
+
this.ctrl.setVisualFilter(filter);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const stepEl = target.closest("[data-a11y-step]");
|
|
1162
|
+
if (stepEl && this.rootEl.contains(stepEl)) {
|
|
1163
|
+
e.preventDefault();
|
|
1164
|
+
const id = stepEl.getAttribute("data-a11y-step");
|
|
1165
|
+
const delta = Number(stepEl.getAttribute("data-delta") || "1");
|
|
1166
|
+
if (id === "font") this.ctrl.stepFontStep(delta);
|
|
1167
|
+
else if (id === "align") this.ctrl.stepTextAlign(delta);
|
|
1168
|
+
else if (id === "line") this.ctrl.stepLineHeight(delta);
|
|
1169
|
+
else if (id === "letter") this.ctrl.stepLetterSpacing(delta);
|
|
1170
|
+
else if (id === "word") this.ctrl.stepWordSpacing(delta);
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
const focusEl = target.closest("[data-a11y-focus]");
|
|
1174
|
+
if (focusEl && this.rootEl.contains(focusEl)) {
|
|
1175
|
+
const id = focusEl.getAttribute("data-a11y-focus");
|
|
1176
|
+
const control = this.rootEl.querySelector(`[data-a11y-control="${id}"]`);
|
|
1177
|
+
control?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
1178
|
+
const focusable = control?.querySelector("button, [tabindex]");
|
|
1179
|
+
focusable?.focus();
|
|
1180
|
+
}
|
|
1112
1181
|
}
|
|
1113
1182
|
onReset() {
|
|
1114
1183
|
if (!this.resetArmed) {
|
|
@@ -1180,7 +1249,8 @@ function mount(options = {}) {
|
|
|
1180
1249
|
ensureStyles();
|
|
1181
1250
|
const controller = new A11yController({
|
|
1182
1251
|
storageKey: options.storageKey,
|
|
1183
|
-
locale: options.locale
|
|
1252
|
+
locale: options.locale,
|
|
1253
|
+
syncDocumentLocale: options.syncDocumentLocale
|
|
1184
1254
|
});
|
|
1185
1255
|
let widget = null;
|
|
1186
1256
|
if (!options.headless) {
|
package/dist/styles.css
CHANGED
|
@@ -12,11 +12,93 @@
|
|
|
12
12
|
border: 0 !important;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
/* Font scale
|
|
15
|
+
/* Font scale — rem-based layouts follow html font-size */
|
|
16
16
|
html {
|
|
17
17
|
font-size: calc(100% * var(--user-font-scale, var(--dga-font-scale, 1)));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* Make spacing / align apply broadly so host pages notice the change */
|
|
21
|
+
[data-a11y~='has-line-height'] body,
|
|
22
|
+
[data-a11y~='has-line-height'] p,
|
|
23
|
+
[data-a11y~='has-line-height'] li,
|
|
24
|
+
[data-a11y~='has-line-height'] h1,
|
|
25
|
+
[data-a11y~='has-line-height'] h2,
|
|
26
|
+
[data-a11y~='has-line-height'] h3,
|
|
27
|
+
[data-a11y~='has-line-height'] h4,
|
|
28
|
+
[data-a11y~='has-line-height'] h5,
|
|
29
|
+
[data-a11y~='has-line-height'] h6,
|
|
30
|
+
[data-a11y~='has-line-height'] td,
|
|
31
|
+
[data-a11y~='has-line-height'] th,
|
|
32
|
+
[data-a11y~='has-line-height'] label,
|
|
33
|
+
[data-a11y~='has-line-height'] .lede,
|
|
34
|
+
[data-a11y~='has-line-height'] .section-lede {
|
|
35
|
+
line-height: var(--user-line-height, 1.6) !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
[data-a11y~='has-letter-spacing'] body,
|
|
39
|
+
[data-a11y~='has-letter-spacing'] p,
|
|
40
|
+
[data-a11y~='has-letter-spacing'] li,
|
|
41
|
+
[data-a11y~='has-letter-spacing'] h1,
|
|
42
|
+
[data-a11y~='has-letter-spacing'] h2,
|
|
43
|
+
[data-a11y~='has-letter-spacing'] h3,
|
|
44
|
+
[data-a11y~='has-letter-spacing'] h4,
|
|
45
|
+
[data-a11y~='has-letter-spacing'] h5,
|
|
46
|
+
[data-a11y~='has-letter-spacing'] h6,
|
|
47
|
+
[data-a11y~='has-letter-spacing'] label {
|
|
48
|
+
letter-spacing: var(--user-letter-spacing, 0) !important;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[data-a11y~='has-word-spacing'] body,
|
|
52
|
+
[data-a11y~='has-word-spacing'] p,
|
|
53
|
+
[data-a11y~='has-word-spacing'] li,
|
|
54
|
+
[data-a11y~='has-word-spacing'] h1,
|
|
55
|
+
[data-a11y~='has-word-spacing'] h2,
|
|
56
|
+
[data-a11y~='has-word-spacing'] h3,
|
|
57
|
+
[data-a11y~='has-word-spacing'] h4,
|
|
58
|
+
[data-a11y~='has-word-spacing'] h5,
|
|
59
|
+
[data-a11y~='has-word-spacing'] h6 {
|
|
60
|
+
word-spacing: var(--user-word-spacing, 0) !important;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
[data-a11y~='text-align-start'] body,
|
|
64
|
+
[data-a11y~='text-align-start'] main,
|
|
65
|
+
[data-a11y~='text-align-start'] article,
|
|
66
|
+
[data-a11y~='text-align-start'] section,
|
|
67
|
+
[data-a11y~='text-align-start'] p,
|
|
68
|
+
[data-a11y~='text-align-start'] li,
|
|
69
|
+
[data-a11y~='text-align-start'] h1,
|
|
70
|
+
[data-a11y~='text-align-start'] h2,
|
|
71
|
+
[data-a11y~='text-align-start'] h3,
|
|
72
|
+
[data-a11y~='text-align-start'] h4,
|
|
73
|
+
[data-a11y~='text-align-start'] h5,
|
|
74
|
+
[data-a11y~='text-align-start'] h6 {
|
|
75
|
+
text-align: start !important;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[data-a11y~='text-align-end'] body,
|
|
79
|
+
[data-a11y~='text-align-end'] main,
|
|
80
|
+
[data-a11y~='text-align-end'] article,
|
|
81
|
+
[data-a11y~='text-align-end'] section,
|
|
82
|
+
[data-a11y~='text-align-end'] p,
|
|
83
|
+
[data-a11y~='text-align-end'] li,
|
|
84
|
+
[data-a11y~='text-align-end'] h1,
|
|
85
|
+
[data-a11y~='text-align-end'] h2,
|
|
86
|
+
[data-a11y~='text-align-end'] h3,
|
|
87
|
+
[data-a11y~='text-align-end'] h4,
|
|
88
|
+
[data-a11y~='text-align-end'] h5,
|
|
89
|
+
[data-a11y~='text-align-end'] h6 {
|
|
90
|
+
text-align: end !important;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
[data-a11y~='text-align-justify'] body,
|
|
94
|
+
[data-a11y~='text-align-justify'] main,
|
|
95
|
+
[data-a11y~='text-align-justify'] article,
|
|
96
|
+
[data-a11y~='text-align-justify'] section,
|
|
97
|
+
[data-a11y~='text-align-justify'] p,
|
|
98
|
+
[data-a11y~='text-align-justify'] li {
|
|
99
|
+
text-align: justify !important;
|
|
100
|
+
}
|
|
101
|
+
|
|
20
102
|
/* ——— Document effects ——— */
|
|
21
103
|
|
|
22
104
|
[data-a11y~='reduce-motion'] *,
|
|
@@ -152,42 +234,6 @@ html {
|
|
|
152
234
|
outline-offset: 4px !important;
|
|
153
235
|
}
|
|
154
236
|
|
|
155
|
-
[data-a11y~='has-line-height'] body,
|
|
156
|
-
[data-a11y~='has-line-height'] p,
|
|
157
|
-
[data-a11y~='has-line-height'] li {
|
|
158
|
-
line-height: var(--user-line-height, 1.6) !important;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
[data-a11y~='has-letter-spacing'] body,
|
|
162
|
-
[data-a11y~='has-letter-spacing'] p,
|
|
163
|
-
[data-a11y~='has-letter-spacing'] li {
|
|
164
|
-
letter-spacing: var(--user-letter-spacing, 0) !important;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
[data-a11y~='has-word-spacing'] body,
|
|
168
|
-
[data-a11y~='has-word-spacing'] p,
|
|
169
|
-
[data-a11y~='has-word-spacing'] li {
|
|
170
|
-
word-spacing: var(--user-word-spacing, 0) !important;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
[data-a11y~='text-align-start'] body,
|
|
174
|
-
[data-a11y~='text-align-start'] p,
|
|
175
|
-
[data-a11y~='text-align-start'] li {
|
|
176
|
-
text-align: start !important;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
[data-a11y~='text-align-end'] body,
|
|
180
|
-
[data-a11y~='text-align-end'] p,
|
|
181
|
-
[data-a11y~='text-align-end'] li {
|
|
182
|
-
text-align: end !important;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
[data-a11y~='text-align-justify'] body,
|
|
186
|
-
[data-a11y~='text-align-justify'] p,
|
|
187
|
-
[data-a11y~='text-align-justify'] li {
|
|
188
|
-
text-align: justify !important;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
237
|
@media not (forced-colors: active) {
|
|
192
238
|
html[data-a11y-filter='monochrome'] {
|
|
193
239
|
filter: grayscale(1);
|
|
@@ -233,12 +279,21 @@ html {
|
|
|
233
279
|
--a11y-fab-size: 3.5rem;
|
|
234
280
|
--a11y-fab-edge: 2rem;
|
|
235
281
|
--a11y-fab-stack-step: 4.25rem;
|
|
282
|
+
/* Isolate widget chrome from page font-scale / spacing modes */
|
|
236
283
|
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
237
284
|
font-size: 14px;
|
|
238
285
|
line-height: 1.4;
|
|
286
|
+
letter-spacing: normal !important;
|
|
287
|
+
word-spacing: normal !important;
|
|
288
|
+
text-align: start;
|
|
239
289
|
color: var(--a11y-text);
|
|
240
290
|
}
|
|
241
291
|
|
|
292
|
+
.a11y-root * {
|
|
293
|
+
letter-spacing: normal;
|
|
294
|
+
word-spacing: normal;
|
|
295
|
+
}
|
|
296
|
+
|
|
242
297
|
.a11y-fab {
|
|
243
298
|
position: fixed;
|
|
244
299
|
z-index: 390;
|
|
@@ -357,6 +412,10 @@ html {
|
|
|
357
412
|
animation-name: a11y-panel-from-start;
|
|
358
413
|
}
|
|
359
414
|
|
|
415
|
+
.a11y-panel--static {
|
|
416
|
+
animation: none !important;
|
|
417
|
+
}
|
|
418
|
+
|
|
360
419
|
[dir='rtl'] .a11y-panel--end {
|
|
361
420
|
animation-name: a11y-panel-from-start;
|
|
362
421
|
}
|
|
@@ -365,6 +424,10 @@ html {
|
|
|
365
424
|
animation-name: a11y-panel-from-end;
|
|
366
425
|
}
|
|
367
426
|
|
|
427
|
+
[dir='rtl'] .a11y-panel--static {
|
|
428
|
+
animation: none !important;
|
|
429
|
+
}
|
|
430
|
+
|
|
368
431
|
.a11y-panel__header,
|
|
369
432
|
.a11y-panel__footer {
|
|
370
433
|
flex-shrink: 0;
|
|
@@ -510,6 +573,20 @@ html {
|
|
|
510
573
|
background: var(--a11y-neutral);
|
|
511
574
|
}
|
|
512
575
|
|
|
576
|
+
.a11y-stepper .a11y-btn {
|
|
577
|
+
width: 1.75rem;
|
|
578
|
+
height: 1.75rem;
|
|
579
|
+
min-height: 1.75rem;
|
|
580
|
+
padding: 0;
|
|
581
|
+
flex-shrink: 0;
|
|
582
|
+
color: var(--a11y-text);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.a11y-stepper .a11y-icon {
|
|
586
|
+
display: block;
|
|
587
|
+
flex-shrink: 0;
|
|
588
|
+
}
|
|
589
|
+
|
|
513
590
|
.a11y-stepper__value {
|
|
514
591
|
min-width: 4.5rem;
|
|
515
592
|
text-align: center;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a.nemreen/a11y",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Framework-agnostic accessibility tools widget — profiles, readable experience, visual filters. Works with Angular, React, Vue, and plain HTML.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ahmed Nemreen",
|