ngp-accessibility 1.0.3 → 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/dist/AccessibilityContext.d.ts +8 -0
- package/dist/AccessibilityDropdown.d.ts +11 -14
- package/dist/index.esm.js +296 -49
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +296 -49
- package/dist/index.js.map +1 -1
- package/dist/styles.css +434 -1
- package/dist/translations.d.ts +12 -0
- package/package.json +4 -4
|
@@ -3,10 +3,14 @@ import { Language, TranslationKey } from "./translations";
|
|
|
3
3
|
interface AccessibilityState {
|
|
4
4
|
language: Language;
|
|
5
5
|
textSize: number;
|
|
6
|
+
textMagnifier: boolean;
|
|
7
|
+
pauseAnimations: boolean;
|
|
8
|
+
readingGuide: boolean;
|
|
6
9
|
highContrast: boolean;
|
|
7
10
|
negativeContrast: boolean;
|
|
8
11
|
lightBackground: boolean;
|
|
9
12
|
underlineLinks: boolean;
|
|
13
|
+
highlightTitles: boolean;
|
|
10
14
|
readableFont: boolean;
|
|
11
15
|
voiceEnabled: boolean;
|
|
12
16
|
}
|
|
@@ -14,10 +18,14 @@ interface AccessibilityContextType extends AccessibilityState {
|
|
|
14
18
|
setLanguage: (lang: Language) => void;
|
|
15
19
|
increaseText: () => void;
|
|
16
20
|
decreaseText: () => void;
|
|
21
|
+
toggleTextMagnifier: () => void;
|
|
22
|
+
togglePauseAnimations: () => void;
|
|
23
|
+
toggleReadingGuide: () => void;
|
|
17
24
|
toggleHighContrast: () => void;
|
|
18
25
|
toggleNegativeContrast: () => void;
|
|
19
26
|
toggleLightBackground: () => void;
|
|
20
27
|
toggleUnderlineLinks: () => void;
|
|
28
|
+
toggleHighlightTitles: () => void;
|
|
21
29
|
toggleReadableFont: () => void;
|
|
22
30
|
toggleVoice: () => void;
|
|
23
31
|
translate: (key: TranslationKey) => string;
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export interface AccessibilityDropdownClasses {
|
|
3
3
|
root?: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
trigger?: string;
|
|
5
|
+
panel?: string;
|
|
6
|
+
panelHeader?: string;
|
|
7
|
+
closeButton?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AccessibilityDropdownRenderTriggerProps {
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
toggle: () => void;
|
|
12
|
+
className: string;
|
|
12
13
|
}
|
|
13
14
|
export interface AccessibilityDropdownProps {
|
|
14
15
|
className?: string;
|
|
15
16
|
style?: React.CSSProperties;
|
|
16
17
|
classes?: AccessibilityDropdownClasses;
|
|
17
|
-
triggerLabel?:
|
|
18
|
-
renderTrigger?: (
|
|
19
|
-
isOpen: boolean;
|
|
20
|
-
toggle: () => void;
|
|
21
|
-
className: string;
|
|
22
|
-
}) => React.ReactNode;
|
|
18
|
+
triggerLabel?: string;
|
|
19
|
+
renderTrigger?: (props: AccessibilityDropdownRenderTriggerProps) => React.ReactNode;
|
|
23
20
|
}
|
|
24
21
|
export declare const AccessibilityDropdown: React.FC<AccessibilityDropdownProps>;
|
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
68
|
const AccessibilityProvider = ({ children, translations: customTranslations, }) => {
|
|
38
69
|
const [state, setState] = useState({
|
|
39
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
|
});
|
|
@@ -53,8 +88,180 @@ const AccessibilityProvider = ({ children, translations: customTranslations, })
|
|
|
53
88
|
root.classList.toggle("negative-contrast", state.negativeContrast);
|
|
54
89
|
root.classList.toggle("light-background", state.lightBackground);
|
|
55
90
|
root.classList.toggle("underline-links", state.underlineLinks);
|
|
91
|
+
root.classList.toggle("highlight-titles", state.highlightTitles);
|
|
56
92
|
root.classList.toggle("readable-font", state.readableFont);
|
|
93
|
+
root.classList.toggle("pause-animations", state.pauseAnimations);
|
|
57
94
|
}, [state]);
|
|
95
|
+
useEffect(() => {
|
|
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]);
|
|
58
265
|
useEffect(() => {
|
|
59
266
|
if (!state.voiceEnabled ||
|
|
60
267
|
!("webkitSpeechRecognition" in window || "SpeechRecognition" in window))
|
|
@@ -87,6 +294,15 @@ const AccessibilityProvider = ({ children, translations: customTranslations, })
|
|
|
87
294
|
toggleLightBackground();
|
|
88
295
|
if (transcript.includes("underline") || transcript.includes("guhit"))
|
|
89
296
|
toggleUnderlineLinks();
|
|
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();
|
|
90
306
|
if (transcript.includes("readable font") ||
|
|
91
307
|
transcript.includes("madaling"))
|
|
92
308
|
toggleReadableFont();
|
|
@@ -97,10 +313,14 @@ const AccessibilityProvider = ({ children, translations: customTranslations, })
|
|
|
97
313
|
const setLanguage = (lang) => setState((s) => (Object.assign(Object.assign({}, s), { language: lang })));
|
|
98
314
|
const increaseText = () => setState((s) => (Object.assign(Object.assign({}, s), { textSize: Math.min(s.textSize + 10, 200) })));
|
|
99
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 })));
|
|
100
319
|
const toggleHighContrast = () => setState((s) => (Object.assign(Object.assign({}, s), { highContrast: !s.highContrast, negativeContrast: false })));
|
|
101
320
|
const toggleNegativeContrast = () => setState((s) => (Object.assign(Object.assign({}, s), { negativeContrast: !s.negativeContrast, highContrast: false })));
|
|
102
321
|
const toggleLightBackground = () => setState((s) => (Object.assign(Object.assign({}, s), { lightBackground: !s.lightBackground })));
|
|
103
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 })));
|
|
104
324
|
const toggleReadableFont = () => setState((s) => (Object.assign(Object.assign({}, s), { readableFont: !s.readableFont })));
|
|
105
325
|
const toggleVoice = () => setState((s) => (Object.assign(Object.assign({}, s), { voiceEnabled: !s.voiceEnabled })));
|
|
106
326
|
const translate = (key) => translations[state.language][key];
|
|
@@ -108,10 +328,14 @@ const AccessibilityProvider = ({ children, translations: customTranslations, })
|
|
|
108
328
|
return (React.createElement(AccessibilityContext.Provider, { value: Object.assign(Object.assign({}, state), { setLanguage,
|
|
109
329
|
increaseText,
|
|
110
330
|
decreaseText,
|
|
331
|
+
toggleTextMagnifier,
|
|
332
|
+
togglePauseAnimations,
|
|
333
|
+
toggleReadingGuide,
|
|
111
334
|
toggleHighContrast,
|
|
112
335
|
toggleNegativeContrast,
|
|
113
336
|
toggleLightBackground,
|
|
114
337
|
toggleUnderlineLinks,
|
|
338
|
+
toggleHighlightTitles,
|
|
115
339
|
toggleReadableFont,
|
|
116
340
|
toggleVoice,
|
|
117
341
|
translate,
|
|
@@ -126,7 +350,7 @@ const useAccessibility = () => {
|
|
|
126
350
|
|
|
127
351
|
const cn$1 = (...parts) => parts.filter(Boolean).join(" ");
|
|
128
352
|
const AccessibilityToolbar = ({ className, style, classes, }) => {
|
|
129
|
-
const { language, setLanguage, increaseText, decreaseText, toggleHighContrast, toggleNegativeContrast, toggleLightBackground, toggleUnderlineLinks, toggleReadableFont, toggleVoice, translate, highContrast, negativeContrast, lightBackground, underlineLinks, readableFont, voiceEnabled, } = useAccessibility();
|
|
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();
|
|
130
354
|
return (React.createElement("div", { className: cn$1("accessibility-toolbar", classes === null || classes === void 0 ? void 0 : classes.root, className), style: style },
|
|
131
355
|
React.createElement("select", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.select), value: language, onChange: (e) => setLanguage(e.target.value) },
|
|
132
356
|
React.createElement("option", { value: "en" }, "English"),
|
|
@@ -138,11 +362,15 @@ const AccessibilityToolbar = ({ className, style, classes, }) => {
|
|
|
138
362
|
React.createElement("button", { className: cn$1(classes === null || classes === void 0 ? void 0 : classes.button), onClick: decreaseText },
|
|
139
363
|
"- ",
|
|
140
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")),
|
|
141
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")),
|
|
142
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")),
|
|
143
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")),
|
|
144
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")),
|
|
145
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")),
|
|
146
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 },
|
|
147
375
|
"\uD83C\uDFA4 ",
|
|
148
376
|
translate("voiceCommand"))));
|
|
@@ -151,37 +379,56 @@ const AccessibilityToolbar = ({ className, style, classes, }) => {
|
|
|
151
379
|
const cn = (...parts) => parts.filter(Boolean).join(" ");
|
|
152
380
|
const AccessibilityDropdown = ({ className, style, classes, triggerLabel = "♿ Accessibility", renderTrigger, }) => {
|
|
153
381
|
const [isOpen, setIsOpen] = useState(false);
|
|
154
|
-
const { language, setLanguage, increaseText, decreaseText, toggleHighContrast, toggleNegativeContrast, toggleLightBackground, toggleUnderlineLinks, toggleReadableFont, toggleVoice, translate, highContrast, negativeContrast, lightBackground, underlineLinks, readableFont, voiceEnabled, } = useAccessibility();
|
|
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();
|
|
155
383
|
const toggle = () => setIsOpen(!isOpen);
|
|
156
|
-
|
|
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 },
|
|
157
390
|
renderTrigger ? (renderTrigger({
|
|
158
391
|
isOpen,
|
|
159
392
|
toggle,
|
|
160
|
-
className: cn("
|
|
161
|
-
})) : (React.createElement("button", { className: cn("
|
|
162
|
-
isOpen && (React.createElement("div", { className: cn("
|
|
163
|
-
React.createElement("div", { className: cn("
|
|
164
|
-
React.createElement("
|
|
165
|
-
|
|
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) },
|
|
166
404
|
React.createElement("option", { value: "en" }, "English"),
|
|
167
405
|
React.createElement("option", { value: "tl" }, "Tagalog"),
|
|
168
406
|
React.createElement("option", { value: "ceb" }, "Cebuano"))),
|
|
169
|
-
React.createElement("
|
|
170
|
-
React.createElement("
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
React.createElement("
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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"))))))));
|
|
185
432
|
};
|
|
186
433
|
|
|
187
434
|
const T = ({ k, children }) => {
|