ngp-accessibility 1.0.2 → 1.0.5
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 +78 -5
- package/dist/AccessibilityContext.d.ts +11 -3
- package/dist/AccessibilityDropdown.d.ts +21 -2
- package/dist/AccessibilityToolbar.d.ts +14 -2
- package/dist/index.d.ts +8 -6
- package/dist/index.esm.js +356 -90
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +356 -90
- package/dist/index.js.map +1 -1
- package/dist/styles.css +483 -32
- package/dist/translations.d.ts +12 -0
- package/package.json +4 -4
package/dist/index.esm.js
CHANGED
|
@@ -2,46 +2,81 @@ import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
|
2
2
|
|
|
3
3
|
const translations = {
|
|
4
4
|
en: {
|
|
5
|
-
increaseText:
|
|
6
|
-
decreaseText:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
increaseText: "Increase Text",
|
|
6
|
+
decreaseText: "Decrease Text",
|
|
7
|
+
textMagnifier: "Text Magnifier",
|
|
8
|
+
highContrast: "High Contrast",
|
|
9
|
+
negativeContrast: "Negative Contrast",
|
|
10
|
+
lightBackground: "Light Background",
|
|
11
|
+
underlineLinks: "Underline Links",
|
|
12
|
+
highlightTitles: "Highlight Titles",
|
|
13
|
+
readableFont: "Readable Font",
|
|
14
|
+
pauseAnimations: "Pause Animations",
|
|
15
|
+
readingGuide: "Reading Guide",
|
|
16
|
+
voiceCommand: "Voice Command",
|
|
13
17
|
},
|
|
14
18
|
tl: {
|
|
15
|
-
increaseText:
|
|
16
|
-
decreaseText:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
increaseText: "Palakihin ang Teksto",
|
|
20
|
+
decreaseText: "Paliitin ang Teksto",
|
|
21
|
+
textMagnifier: "Text Magnifier",
|
|
22
|
+
highContrast: "Mataas na Contrast",
|
|
23
|
+
negativeContrast: "Negatibong Contrast",
|
|
24
|
+
lightBackground: "Maliwanag na Background",
|
|
25
|
+
underlineLinks: "May Guhit na Links",
|
|
26
|
+
highlightTitles: "I-highlight ang Mga Pamagat",
|
|
27
|
+
readableFont: "Madaling Basahin na Font",
|
|
28
|
+
pauseAnimations: "I-pause ang mga Animation",
|
|
29
|
+
readingGuide: "Reading Guide",
|
|
30
|
+
voiceCommand: "Voice Command",
|
|
23
31
|
},
|
|
24
32
|
ceb: {
|
|
25
|
-
increaseText:
|
|
26
|
-
decreaseText:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
increaseText: "Padak-on ang Teksto",
|
|
34
|
+
decreaseText: "Pagamay-on ang Teksto",
|
|
35
|
+
textMagnifier: "Text Magnifier",
|
|
36
|
+
highContrast: "Taas nga Contrast",
|
|
37
|
+
negativeContrast: "Negatibo nga Contrast",
|
|
38
|
+
lightBackground: "Hayag nga Background",
|
|
39
|
+
underlineLinks: "Linya sa Ubos sa Links",
|
|
40
|
+
highlightTitles: "I-highlight ang mga Ulohan",
|
|
41
|
+
readableFont: "Sayon Basahon nga Font",
|
|
42
|
+
pauseAnimations: "Ihunong ang mga Animation",
|
|
43
|
+
readingGuide: "Reading Guide",
|
|
44
|
+
voiceCommand: "Voice Command",
|
|
33
45
|
},
|
|
34
46
|
};
|
|
35
47
|
|
|
48
|
+
const normalizeMagnifierText = (value) => value.replace(/\s+/g, " ").trim();
|
|
49
|
+
const magnifierSelector = "p, li, button, h1, h2, h3, h4, h5, h6, [role=heading]";
|
|
50
|
+
const getMagnifierElement = (target) => {
|
|
51
|
+
if (!(target instanceof HTMLElement))
|
|
52
|
+
return null;
|
|
53
|
+
if (target.closest(".a11y-root"))
|
|
54
|
+
return null;
|
|
55
|
+
const element = target.closest(magnifierSelector);
|
|
56
|
+
return element instanceof HTMLElement ? element : null;
|
|
57
|
+
};
|
|
58
|
+
const getMagnifierText = (target) => {
|
|
59
|
+
const element = getMagnifierElement(target);
|
|
60
|
+
if (!element)
|
|
61
|
+
return "";
|
|
62
|
+
const ariaLabel = normalizeMagnifierText(element.getAttribute("aria-label") || "");
|
|
63
|
+
if (ariaLabel)
|
|
64
|
+
return ariaLabel;
|
|
65
|
+
return normalizeMagnifierText(element.innerText || element.textContent || "");
|
|
66
|
+
};
|
|
36
67
|
const AccessibilityContext = createContext(undefined);
|
|
37
|
-
const AccessibilityProvider = ({ children, translations: customTranslations }) => {
|
|
68
|
+
const AccessibilityProvider = ({ children, translations: customTranslations, }) => {
|
|
38
69
|
const [state, setState] = useState({
|
|
39
|
-
language:
|
|
70
|
+
language: "en",
|
|
40
71
|
textSize: 100,
|
|
72
|
+
textMagnifier: false,
|
|
73
|
+
pauseAnimations: false,
|
|
74
|
+
readingGuide: false,
|
|
41
75
|
highContrast: false,
|
|
42
76
|
negativeContrast: false,
|
|
43
77
|
lightBackground: false,
|
|
44
78
|
underlineLinks: false,
|
|
79
|
+
highlightTitles: false,
|
|
45
80
|
readableFont: false,
|
|
46
81
|
voiceEnabled: false,
|
|
47
82
|
});
|
|
@@ -49,57 +84,258 @@ const AccessibilityProvider = ({ children, translations: customTranslations }) =
|
|
|
49
84
|
useEffect(() => {
|
|
50
85
|
const root = document.documentElement;
|
|
51
86
|
root.style.fontSize = `${state.textSize}%`;
|
|
52
|
-
root.classList.toggle(
|
|
53
|
-
root.classList.toggle(
|
|
54
|
-
root.classList.toggle(
|
|
55
|
-
root.classList.toggle(
|
|
56
|
-
root.classList.toggle(
|
|
87
|
+
root.classList.toggle("high-contrast", state.highContrast);
|
|
88
|
+
root.classList.toggle("negative-contrast", state.negativeContrast);
|
|
89
|
+
root.classList.toggle("light-background", state.lightBackground);
|
|
90
|
+
root.classList.toggle("underline-links", state.underlineLinks);
|
|
91
|
+
root.classList.toggle("highlight-titles", state.highlightTitles);
|
|
92
|
+
root.classList.toggle("readable-font", state.readableFont);
|
|
93
|
+
root.classList.toggle("pause-animations", state.pauseAnimations);
|
|
57
94
|
}, [state]);
|
|
58
95
|
useEffect(() => {
|
|
59
|
-
if (!state.
|
|
96
|
+
if (!state.readingGuide)
|
|
97
|
+
return;
|
|
98
|
+
const guide = document.createElement("div");
|
|
99
|
+
guide.className = "a11y-reading-guide";
|
|
100
|
+
guide.setAttribute("aria-hidden", "true");
|
|
101
|
+
guide.innerHTML = `
|
|
102
|
+
<div class="a11y-reading-guide-top"></div>
|
|
103
|
+
<div class="a11y-reading-guide-focus"></div>
|
|
104
|
+
<div class="a11y-reading-guide-line"></div>
|
|
105
|
+
<div class="a11y-reading-guide-bottom"></div>
|
|
106
|
+
`;
|
|
107
|
+
document.body.appendChild(guide);
|
|
108
|
+
const topMask = guide.querySelector(".a11y-reading-guide-top");
|
|
109
|
+
const focusBand = guide.querySelector(".a11y-reading-guide-focus");
|
|
110
|
+
const focusLine = guide.querySelector(".a11y-reading-guide-line");
|
|
111
|
+
const bottomMask = guide.querySelector(".a11y-reading-guide-bottom");
|
|
112
|
+
const bandHeight = 72;
|
|
113
|
+
const halfBandHeight = bandHeight / 2;
|
|
114
|
+
const updateGuide = (clientY) => {
|
|
115
|
+
const safeY = Math.min(Math.max(halfBandHeight + 12, clientY), window.innerHeight - halfBandHeight - 12);
|
|
116
|
+
const top = Math.max(0, safeY - halfBandHeight);
|
|
117
|
+
const bottom = Math.min(window.innerHeight, safeY + halfBandHeight);
|
|
118
|
+
topMask.style.height = `${top}px`;
|
|
119
|
+
focusBand.style.top = `${top}px`;
|
|
120
|
+
focusBand.style.height = `${bottom - top}px`;
|
|
121
|
+
focusLine.style.top = `${safeY}px`;
|
|
122
|
+
bottomMask.style.top = `${bottom}px`;
|
|
123
|
+
bottomMask.style.height = `${Math.max(0, window.innerHeight - bottom)}px`;
|
|
124
|
+
};
|
|
125
|
+
const resetGuide = () => updateGuide(window.innerHeight / 2);
|
|
126
|
+
const handleMouseMove = (event) => updateGuide(event.clientY);
|
|
127
|
+
const handleTouchStart = (event) => {
|
|
128
|
+
const touch = event.touches[0];
|
|
129
|
+
if (touch)
|
|
130
|
+
updateGuide(touch.clientY);
|
|
131
|
+
};
|
|
132
|
+
const handleTouchMove = (event) => {
|
|
133
|
+
const touch = event.touches[0];
|
|
134
|
+
if (touch)
|
|
135
|
+
updateGuide(touch.clientY);
|
|
136
|
+
};
|
|
137
|
+
resetGuide();
|
|
138
|
+
document.addEventListener("mousemove", handleMouseMove, true);
|
|
139
|
+
document.addEventListener("touchstart", handleTouchStart, true);
|
|
140
|
+
document.addEventListener("touchmove", handleTouchMove, true);
|
|
141
|
+
window.addEventListener("resize", resetGuide);
|
|
142
|
+
return () => {
|
|
143
|
+
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
144
|
+
document.removeEventListener("touchstart", handleTouchStart, true);
|
|
145
|
+
document.removeEventListener("touchmove", handleTouchMove, true);
|
|
146
|
+
window.removeEventListener("resize", resetGuide);
|
|
147
|
+
guide.remove();
|
|
148
|
+
};
|
|
149
|
+
}, [state.readingGuide]);
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (!state.textMagnifier)
|
|
152
|
+
return;
|
|
153
|
+
const tooltip = document.createElement("div");
|
|
154
|
+
tooltip.className = "a11y-text-magnifier-tooltip";
|
|
155
|
+
tooltip.setAttribute("aria-hidden", "true");
|
|
156
|
+
document.body.appendChild(tooltip);
|
|
157
|
+
const hideTooltip = () => {
|
|
158
|
+
tooltip.removeAttribute("data-visible");
|
|
159
|
+
tooltip.textContent = "";
|
|
160
|
+
};
|
|
161
|
+
const showTooltip = (text) => {
|
|
162
|
+
tooltip.textContent = text;
|
|
163
|
+
tooltip.setAttribute("data-visible", "true");
|
|
164
|
+
};
|
|
165
|
+
const updateTooltipPosition = (clientX, clientY) => {
|
|
166
|
+
const tooltipWidth = tooltip.offsetWidth || 320;
|
|
167
|
+
const tooltipHeight = tooltip.offsetHeight || 56;
|
|
168
|
+
const left = Math.min(Math.max(12, clientX + 18), window.innerWidth - tooltipWidth - 12);
|
|
169
|
+
const top = clientY + tooltipHeight + 18 > window.innerHeight
|
|
170
|
+
? Math.max(12, clientY - tooltipHeight - 18)
|
|
171
|
+
: clientY + 18;
|
|
172
|
+
tooltip.style.left = `${left}px`;
|
|
173
|
+
tooltip.style.top = `${top}px`;
|
|
174
|
+
};
|
|
175
|
+
const handleMouseMove = (event) => {
|
|
176
|
+
const text = getMagnifierText(event.target);
|
|
177
|
+
if (!text) {
|
|
178
|
+
hideTooltip();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
showTooltip(text);
|
|
182
|
+
updateTooltipPosition(event.clientX, event.clientY);
|
|
183
|
+
};
|
|
184
|
+
let touchTimer = null;
|
|
185
|
+
let activeTouchId = null;
|
|
186
|
+
let activeText = "";
|
|
187
|
+
let pressPoint = null;
|
|
188
|
+
const clearTouchTimer = () => {
|
|
189
|
+
if (touchTimer !== null) {
|
|
190
|
+
window.clearTimeout(touchTimer);
|
|
191
|
+
touchTimer = null;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const resetTouchState = () => {
|
|
195
|
+
clearTouchTimer();
|
|
196
|
+
activeTouchId = null;
|
|
197
|
+
activeText = "";
|
|
198
|
+
pressPoint = null;
|
|
199
|
+
hideTooltip();
|
|
200
|
+
};
|
|
201
|
+
const getTrackedTouch = (touches) => {
|
|
202
|
+
if (activeTouchId === null)
|
|
203
|
+
return null;
|
|
204
|
+
for (const touch of Array.from(touches)) {
|
|
205
|
+
if (touch.identifier === activeTouchId)
|
|
206
|
+
return touch;
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
};
|
|
210
|
+
const handleTouchStart = (event) => {
|
|
211
|
+
const touch = event.changedTouches[0];
|
|
212
|
+
if (!touch)
|
|
213
|
+
return;
|
|
214
|
+
const text = getMagnifierText(event.target);
|
|
215
|
+
if (!text) {
|
|
216
|
+
resetTouchState();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
clearTouchTimer();
|
|
220
|
+
activeTouchId = touch.identifier;
|
|
221
|
+
activeText = text;
|
|
222
|
+
pressPoint = { x: touch.clientX, y: touch.clientY };
|
|
223
|
+
touchTimer = window.setTimeout(() => {
|
|
224
|
+
showTooltip(activeText);
|
|
225
|
+
updateTooltipPosition(touch.clientX, touch.clientY);
|
|
226
|
+
touchTimer = null;
|
|
227
|
+
}, 450);
|
|
228
|
+
};
|
|
229
|
+
const handleTouchMove = (event) => {
|
|
230
|
+
const touch = getTrackedTouch(event.touches);
|
|
231
|
+
if (!touch)
|
|
232
|
+
return;
|
|
233
|
+
if (!tooltip.hasAttribute("data-visible")) {
|
|
234
|
+
if (pressPoint &&
|
|
235
|
+
(Math.abs(touch.clientX - pressPoint.x) > 10 ||
|
|
236
|
+
Math.abs(touch.clientY - pressPoint.y) > 10)) {
|
|
237
|
+
resetTouchState();
|
|
238
|
+
}
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
updateTooltipPosition(touch.clientX, touch.clientY);
|
|
242
|
+
};
|
|
243
|
+
const handleTouchEnd = () => resetTouchState();
|
|
244
|
+
const handleTouchCancel = () => resetTouchState();
|
|
245
|
+
const handlePointerLeave = () => hideTooltip();
|
|
246
|
+
document.addEventListener("mousemove", handleMouseMove, true);
|
|
247
|
+
document.addEventListener("touchstart", handleTouchStart, true);
|
|
248
|
+
document.addEventListener("touchmove", handleTouchMove, true);
|
|
249
|
+
document.addEventListener("touchend", handleTouchEnd, true);
|
|
250
|
+
document.addEventListener("touchcancel", handleTouchCancel, true);
|
|
251
|
+
document.addEventListener("scroll", hideTooltip, true);
|
|
252
|
+
window.addEventListener("blur", handlePointerLeave);
|
|
253
|
+
return () => {
|
|
254
|
+
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
255
|
+
document.removeEventListener("touchstart", handleTouchStart, true);
|
|
256
|
+
document.removeEventListener("touchmove", handleTouchMove, true);
|
|
257
|
+
document.removeEventListener("touchend", handleTouchEnd, true);
|
|
258
|
+
document.removeEventListener("touchcancel", handleTouchCancel, true);
|
|
259
|
+
document.removeEventListener("scroll", hideTooltip, true);
|
|
260
|
+
window.removeEventListener("blur", handlePointerLeave);
|
|
261
|
+
clearTouchTimer();
|
|
262
|
+
tooltip.remove();
|
|
263
|
+
};
|
|
264
|
+
}, [state.textMagnifier]);
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (!state.voiceEnabled ||
|
|
267
|
+
!("webkitSpeechRecognition" in window || "SpeechRecognition" in window))
|
|
60
268
|
return;
|
|
61
|
-
const SpeechRecognition = window.SpeechRecognition ||
|
|
269
|
+
const SpeechRecognition = window.SpeechRecognition ||
|
|
270
|
+
window.webkitSpeechRecognition;
|
|
62
271
|
const recognition = new SpeechRecognition();
|
|
63
272
|
recognition.continuous = true;
|
|
64
|
-
recognition.lang =
|
|
273
|
+
recognition.lang =
|
|
274
|
+
state.language === "tl"
|
|
275
|
+
? "tl-PH"
|
|
276
|
+
: state.language === "ceb"
|
|
277
|
+
? "ceb-PH"
|
|
278
|
+
: "en-US";
|
|
65
279
|
recognition.onresult = (event) => {
|
|
66
280
|
const transcript = event.results[event.results.length - 1][0].transcript.toLowerCase();
|
|
67
|
-
if (transcript.includes(
|
|
281
|
+
if (transcript.includes("increase text") ||
|
|
282
|
+
transcript.includes("palakihin"))
|
|
68
283
|
increaseText();
|
|
69
|
-
if (transcript.includes(
|
|
284
|
+
if (transcript.includes("decrease text") ||
|
|
285
|
+
transcript.includes("paliitin"))
|
|
70
286
|
decreaseText();
|
|
71
|
-
if (transcript.includes(
|
|
287
|
+
if (transcript.includes("high contrast") || transcript.includes("mataas"))
|
|
72
288
|
toggleHighContrast();
|
|
73
|
-
if (transcript.includes(
|
|
289
|
+
if (transcript.includes("negative contrast") ||
|
|
290
|
+
transcript.includes("negatibo"))
|
|
74
291
|
toggleNegativeContrast();
|
|
75
|
-
if (transcript.includes(
|
|
292
|
+
if (transcript.includes("light background") ||
|
|
293
|
+
transcript.includes("maliwanag"))
|
|
76
294
|
toggleLightBackground();
|
|
77
|
-
if (transcript.includes(
|
|
295
|
+
if (transcript.includes("underline") || transcript.includes("guhit"))
|
|
78
296
|
toggleUnderlineLinks();
|
|
79
|
-
if (transcript.includes(
|
|
297
|
+
if (transcript.includes("highlight titles") ||
|
|
298
|
+
transcript.includes("title highlight"))
|
|
299
|
+
toggleHighlightTitles();
|
|
300
|
+
if (transcript.includes("pause animations") ||
|
|
301
|
+
transcript.includes("stop animations"))
|
|
302
|
+
togglePauseAnimations();
|
|
303
|
+
if (transcript.includes("reading guide") ||
|
|
304
|
+
transcript.includes("reading line"))
|
|
305
|
+
toggleReadingGuide();
|
|
306
|
+
if (transcript.includes("readable font") ||
|
|
307
|
+
transcript.includes("madaling"))
|
|
80
308
|
toggleReadableFont();
|
|
81
309
|
};
|
|
82
310
|
recognition.start();
|
|
83
311
|
return () => recognition.stop();
|
|
84
312
|
}, [state.voiceEnabled, state.language]);
|
|
85
|
-
const setLanguage = (lang) => setState(s => (Object.assign(Object.assign({}, s), { language: lang })));
|
|
86
|
-
const increaseText = () => setState(s => (Object.assign(Object.assign({}, s), { textSize: Math.min(s.textSize + 10, 200) })));
|
|
87
|
-
const decreaseText = () => setState(s => (Object.assign(Object.assign({}, s), { textSize: Math.max(s.textSize - 10, 80) })));
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
const
|
|
313
|
+
const setLanguage = (lang) => setState((s) => (Object.assign(Object.assign({}, s), { language: lang })));
|
|
314
|
+
const increaseText = () => setState((s) => (Object.assign(Object.assign({}, s), { textSize: Math.min(s.textSize + 10, 200) })));
|
|
315
|
+
const decreaseText = () => setState((s) => (Object.assign(Object.assign({}, s), { textSize: Math.max(s.textSize - 10, 80) })));
|
|
316
|
+
const toggleTextMagnifier = () => setState((s) => (Object.assign(Object.assign({}, s), { textMagnifier: !s.textMagnifier })));
|
|
317
|
+
const togglePauseAnimations = () => setState((s) => (Object.assign(Object.assign({}, s), { pauseAnimations: !s.pauseAnimations })));
|
|
318
|
+
const toggleReadingGuide = () => setState((s) => (Object.assign(Object.assign({}, s), { readingGuide: !s.readingGuide })));
|
|
319
|
+
const toggleHighContrast = () => setState((s) => (Object.assign(Object.assign({}, s), { highContrast: !s.highContrast, negativeContrast: false })));
|
|
320
|
+
const toggleNegativeContrast = () => setState((s) => (Object.assign(Object.assign({}, s), { negativeContrast: !s.negativeContrast, highContrast: false })));
|
|
321
|
+
const toggleLightBackground = () => setState((s) => (Object.assign(Object.assign({}, s), { lightBackground: !s.lightBackground })));
|
|
322
|
+
const toggleUnderlineLinks = () => setState((s) => (Object.assign(Object.assign({}, s), { underlineLinks: !s.underlineLinks })));
|
|
323
|
+
const toggleHighlightTitles = () => setState((s) => (Object.assign(Object.assign({}, s), { highlightTitles: !s.highlightTitles })));
|
|
324
|
+
const toggleReadableFont = () => setState((s) => (Object.assign(Object.assign({}, s), { readableFont: !s.readableFont })));
|
|
325
|
+
const toggleVoice = () => setState((s) => (Object.assign(Object.assign({}, s), { voiceEnabled: !s.voiceEnabled })));
|
|
94
326
|
const translate = (key) => translations[state.language][key];
|
|
95
327
|
const t = (key) => { var _a; return ((_a = allTranslations[state.language]) === null || _a === void 0 ? void 0 : _a[key]) || key; };
|
|
96
328
|
return (React.createElement(AccessibilityContext.Provider, { value: Object.assign(Object.assign({}, state), { setLanguage,
|
|
97
329
|
increaseText,
|
|
98
330
|
decreaseText,
|
|
331
|
+
toggleTextMagnifier,
|
|
332
|
+
togglePauseAnimations,
|
|
333
|
+
toggleReadingGuide,
|
|
99
334
|
toggleHighContrast,
|
|
100
335
|
toggleNegativeContrast,
|
|
101
336
|
toggleLightBackground,
|
|
102
337
|
toggleUnderlineLinks,
|
|
338
|
+
toggleHighlightTitles,
|
|
103
339
|
toggleReadableFont,
|
|
104
340
|
toggleVoice,
|
|
105
341
|
translate,
|
|
@@ -108,61 +344,91 @@ const AccessibilityProvider = ({ children, translations: customTranslations }) =
|
|
|
108
344
|
const useAccessibility = () => {
|
|
109
345
|
const context = useContext(AccessibilityContext);
|
|
110
346
|
if (!context)
|
|
111
|
-
throw new Error(
|
|
347
|
+
throw new Error("useAccessibility must be used within AccessibilityProvider");
|
|
112
348
|
return context;
|
|
113
349
|
};
|
|
114
350
|
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
351
|
+
const cn$1 = (...parts) => parts.filter(Boolean).join(" ");
|
|
352
|
+
const AccessibilityToolbar = ({ className, style, classes, }) => {
|
|
353
|
+
const { language, setLanguage, increaseText, decreaseText, toggleTextMagnifier, togglePauseAnimations, toggleReadingGuide, toggleHighContrast, toggleNegativeContrast, toggleLightBackground, toggleUnderlineLinks, toggleHighlightTitles, toggleReadableFont, toggleVoice, translate, textMagnifier, pauseAnimations, readingGuide, highContrast, negativeContrast, lightBackground, underlineLinks, highlightTitles, readableFont, voiceEnabled, } = useAccessibility();
|
|
354
|
+
return (React.createElement("div", { className: cn$1("accessibility-toolbar", classes === null || classes === void 0 ? void 0 : classes.root, className), style: style },
|
|
355
|
+
React.createElement("select", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.select), value: language, onChange: (e) => setLanguage(e.target.value) },
|
|
119
356
|
React.createElement("option", { value: "en" }, "English"),
|
|
120
357
|
React.createElement("option", { value: "tl" }, "Tagalog"),
|
|
121
358
|
React.createElement("option", { value: "ceb" }, "Cebuano")),
|
|
122
|
-
React.createElement("button", { onClick: increaseText },
|
|
359
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button), onClick: increaseText },
|
|
123
360
|
"+ ",
|
|
124
|
-
translate(
|
|
125
|
-
React.createElement("button", { onClick: decreaseText },
|
|
361
|
+
translate("increaseText")),
|
|
362
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button), onClick: decreaseText },
|
|
126
363
|
"- ",
|
|
127
|
-
translate(
|
|
128
|
-
React.createElement("button", {
|
|
129
|
-
React.createElement("button", {
|
|
130
|
-
React.createElement("button", {
|
|
131
|
-
React.createElement("button", {
|
|
132
|
-
React.createElement("button", {
|
|
133
|
-
React.createElement("button", {
|
|
364
|
+
translate("decreaseText")),
|
|
365
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, textMagnifier && "active", textMagnifier && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": textMagnifier, onClick: toggleTextMagnifier }, translate("textMagnifier")),
|
|
366
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, highContrast && "active", highContrast && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": highContrast, onClick: toggleHighContrast }, translate("highContrast")),
|
|
367
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, negativeContrast && "active", negativeContrast && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": negativeContrast, onClick: toggleNegativeContrast }, translate("negativeContrast")),
|
|
368
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, lightBackground && "active", lightBackground && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": lightBackground, onClick: toggleLightBackground }, translate("lightBackground")),
|
|
369
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, underlineLinks && "active", underlineLinks && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": underlineLinks, onClick: toggleUnderlineLinks }, translate("underlineLinks")),
|
|
370
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, highlightTitles && "active", highlightTitles && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": highlightTitles, onClick: toggleHighlightTitles }, translate("highlightTitles")),
|
|
371
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, readableFont && "active", readableFont && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": readableFont, onClick: toggleReadableFont }, translate("readableFont")),
|
|
372
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, pauseAnimations && "active", pauseAnimations && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": pauseAnimations, onClick: togglePauseAnimations }, translate("pauseAnimations")),
|
|
373
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, readingGuide && "active", readingGuide && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": readingGuide, onClick: toggleReadingGuide }, translate("readingGuide")),
|
|
374
|
+
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button, classes === null || classes === void 0 ? void 0 : classes.voiceButton, voiceEnabled && "active", voiceEnabled && (classes === null || classes === void 0 ? void 0 : classes.activeButton)), "data-active": voiceEnabled, onClick: toggleVoice },
|
|
134
375
|
"\uD83C\uDFA4 ",
|
|
135
|
-
translate(
|
|
376
|
+
translate("voiceCommand"))));
|
|
136
377
|
};
|
|
137
378
|
|
|
138
|
-
const
|
|
379
|
+
const cn = (...parts) => parts.filter(Boolean).join(" ");
|
|
380
|
+
const AccessibilityDropdown = ({ className, style, classes, triggerLabel = "♿ Accessibility", renderTrigger, }) => {
|
|
139
381
|
const [isOpen, setIsOpen] = useState(false);
|
|
140
|
-
const { language, setLanguage, increaseText, decreaseText, toggleHighContrast, toggleNegativeContrast, toggleLightBackground, toggleUnderlineLinks, toggleReadableFont, toggleVoice, translate, highContrast, negativeContrast, lightBackground, underlineLinks, readableFont, voiceEnabled, } = useAccessibility();
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
382
|
+
const { language, setLanguage, textSize, increaseText, decreaseText, toggleTextMagnifier, togglePauseAnimations, toggleReadingGuide, toggleHighContrast, toggleNegativeContrast, toggleLightBackground, toggleUnderlineLinks, toggleHighlightTitles, toggleReadableFont, toggleVoice, translate, textMagnifier, pauseAnimations, readingGuide, highContrast, negativeContrast, lightBackground, underlineLinks, highlightTitles, readableFont, voiceEnabled, } = useAccessibility();
|
|
383
|
+
const toggle = () => setIsOpen(!isOpen);
|
|
384
|
+
const closePanel = () => setIsOpen(false);
|
|
385
|
+
const textScaleDelta = textSize - 100;
|
|
386
|
+
const textScaleLabel = textScaleDelta === 0
|
|
387
|
+
? "Default"
|
|
388
|
+
: `${textScaleDelta > 0 ? "+" : ""}${textScaleDelta}%`;
|
|
389
|
+
return (React.createElement("div", { className: cn("a11y-root", classes === null || classes === void 0 ? void 0 : classes.root, className), style: style },
|
|
390
|
+
renderTrigger ? (renderTrigger({
|
|
391
|
+
isOpen,
|
|
392
|
+
toggle,
|
|
393
|
+
className: cn("a11y-trigger", classes === null || classes === void 0 ? void 0 : classes.trigger),
|
|
394
|
+
})) : (React.createElement("button", { className: cn("a11y-trigger", classes === null || classes === void 0 ? void 0 : classes.trigger), onClick: toggle }, triggerLabel)),
|
|
395
|
+
isOpen && (React.createElement("div", { className: cn("a11y-panel", classes === null || classes === void 0 ? void 0 : classes.panel) },
|
|
396
|
+
React.createElement("div", { className: cn("a11y-panel-header", classes === null || classes === void 0 ? void 0 : classes.panelHeader) },
|
|
397
|
+
React.createElement("div", { className: "a11y-panel-heading" },
|
|
398
|
+
React.createElement("span", { className: "a11y-panel-eyebrow" }, "NGP"),
|
|
399
|
+
React.createElement("label", { className: "a11y-panel-title" }, "Accessibility Options")),
|
|
400
|
+
React.createElement("button", { type: "button", className: cn("a11y-panel-close", classes === null || classes === void 0 ? void 0 : classes.closeButton), onClick: closePanel, "aria-label": "Close accessibility panel" }, "\u00D7")),
|
|
401
|
+
React.createElement("div", { className: "a11y-language" },
|
|
402
|
+
React.createElement("label", { htmlFor: "a11y-language-select" }, "Language"),
|
|
403
|
+
React.createElement("select", { id: "a11y-language-select", value: language, onChange: (e) => setLanguage(e.target.value) },
|
|
147
404
|
React.createElement("option", { value: "en" }, "English"),
|
|
148
405
|
React.createElement("option", { value: "tl" }, "Tagalog"),
|
|
149
406
|
React.createElement("option", { value: "ceb" }, "Cebuano"))),
|
|
150
|
-
React.createElement("
|
|
151
|
-
React.createElement("
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
React.createElement("
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
407
|
+
React.createElement("section", { className: "a11y-section" },
|
|
408
|
+
React.createElement("h3", { className: "a11y-section-title" }, "Content Adjustments"),
|
|
409
|
+
React.createElement("div", { className: "a11y-card" },
|
|
410
|
+
React.createElement("span", { className: "a11y-card-title" }, "Content Scaling"),
|
|
411
|
+
React.createElement("div", { className: "a11y-stepper" },
|
|
412
|
+
React.createElement("button", { onClick: decreaseText }, "\u2212"),
|
|
413
|
+
React.createElement("span", { className: "a11y-stepper-value" }, textScaleLabel),
|
|
414
|
+
React.createElement("button", { onClick: increaseText }, "+"))),
|
|
415
|
+
React.createElement("div", { className: "a11y-grid" },
|
|
416
|
+
React.createElement("button", { className: cn("a11y-card", textMagnifier && "active"), onClick: toggleTextMagnifier }, translate("textMagnifier")),
|
|
417
|
+
React.createElement("button", { className: cn("a11y-card", readableFont && "active"), onClick: toggleReadableFont }, "Readable Font"),
|
|
418
|
+
React.createElement("button", { className: cn("a11y-card", underlineLinks && "active"), onClick: toggleUnderlineLinks }, "Highlight Links"),
|
|
419
|
+
React.createElement("button", { className: cn("a11y-card", highlightTitles && "active"), onClick: toggleHighlightTitles }, "Highlight Titles"))),
|
|
420
|
+
React.createElement("section", { className: "a11y-section" },
|
|
421
|
+
React.createElement("h3", { className: "a11y-section-title" }, "Color Adjustments"),
|
|
422
|
+
React.createElement("div", { className: "a11y-grid" },
|
|
423
|
+
React.createElement("button", { className: cn("a11y-card", highContrast && "active"), onClick: toggleHighContrast }, translate("highContrast")),
|
|
424
|
+
React.createElement("button", { className: cn("a11y-card", negativeContrast && "active"), onClick: toggleNegativeContrast }, translate("negativeContrast")),
|
|
425
|
+
React.createElement("button", { className: cn("a11y-card", lightBackground && "active"), onClick: toggleLightBackground }, translate("lightBackground")))),
|
|
426
|
+
React.createElement("section", { className: "a11y-section" },
|
|
427
|
+
React.createElement("h3", { className: "a11y-section-title" }, "Accessibility Tools"),
|
|
428
|
+
React.createElement("div", { className: "a11y-grid" },
|
|
429
|
+
React.createElement("button", { className: cn("a11y-card", pauseAnimations && "active"), onClick: togglePauseAnimations }, translate("pauseAnimations")),
|
|
430
|
+
React.createElement("button", { className: cn("a11y-card", readingGuide && "active"), onClick: toggleReadingGuide }, translate("readingGuide")),
|
|
431
|
+
React.createElement("button", { className: cn("a11y-card", voiceEnabled && "active"), onClick: toggleVoice }, translate("voiceCommand"))))))));
|
|
166
432
|
};
|
|
167
433
|
|
|
168
434
|
const T = ({ k, children }) => {
|