@lessonkit/accessibility 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +22 -10
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +20 -10
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -23,9 +23,11 @@ __export(index_exports, {
|
|
|
23
23
|
createRovingTabIndex: () => createRovingTabIndex,
|
|
24
24
|
focusFirst: () => focusFirst,
|
|
25
25
|
getFocusableElements: () => getFocusableElements,
|
|
26
|
+
getPrefersReducedMotionSnapshot: () => getPrefersReducedMotionSnapshot,
|
|
26
27
|
getReducedMotionPreference: () => getReducedMotionPreference,
|
|
27
28
|
prefersReducedMotion: () => prefersReducedMotion,
|
|
28
29
|
shouldAnimate: () => shouldAnimate,
|
|
30
|
+
subscribeReducedMotion: () => subscribeReducedMotion,
|
|
29
31
|
trapFocus: () => trapFocus,
|
|
30
32
|
visuallyHiddenStyle: () => visuallyHiddenStyle
|
|
31
33
|
});
|
|
@@ -56,8 +58,23 @@ function isHTMLElement(v) {
|
|
|
56
58
|
return typeof HTMLElement !== "undefined" && v instanceof HTMLElement;
|
|
57
59
|
}
|
|
58
60
|
function prefersReducedMotion() {
|
|
61
|
+
return getPrefersReducedMotionSnapshot();
|
|
62
|
+
}
|
|
63
|
+
function getPrefersReducedMotionSnapshot() {
|
|
59
64
|
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
60
65
|
}
|
|
66
|
+
function subscribeReducedMotion(listener) {
|
|
67
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
68
|
+
listener(false);
|
|
69
|
+
return () => {
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
73
|
+
const onChange = () => listener(mq.matches);
|
|
74
|
+
listener(mq.matches);
|
|
75
|
+
mq.addEventListener("change", onChange);
|
|
76
|
+
return () => mq.removeEventListener("change", onChange);
|
|
77
|
+
}
|
|
61
78
|
function getReducedMotionPreference() {
|
|
62
79
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return "unknown";
|
|
63
80
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "reduce" : "no-preference";
|
|
@@ -70,16 +87,7 @@ function shouldAnimate(opts) {
|
|
|
70
87
|
}
|
|
71
88
|
function focusFirst(container) {
|
|
72
89
|
if (!container) return false;
|
|
73
|
-
const el = container.querySelector(
|
|
74
|
-
[
|
|
75
|
-
"a[href]",
|
|
76
|
-
"button:not([disabled])",
|
|
77
|
-
"input:not([disabled])",
|
|
78
|
-
"select:not([disabled])",
|
|
79
|
-
"textarea:not([disabled])",
|
|
80
|
-
"[tabindex]:not([tabindex='-1'])"
|
|
81
|
-
].join(",")
|
|
82
|
-
);
|
|
90
|
+
const el = container.querySelector(FOCUSABLE_SELECTORS);
|
|
83
91
|
el?.focus();
|
|
84
92
|
return Boolean(el);
|
|
85
93
|
}
|
|
@@ -140,10 +148,12 @@ function trapFocus(container, opts) {
|
|
|
140
148
|
prevFocused = restoreFocus && isHTMLElement(document.activeElement) ? document.activeElement : null;
|
|
141
149
|
document.addEventListener("keydown", onKeyDown);
|
|
142
150
|
document.addEventListener("focusin", onFocusIn);
|
|
151
|
+
document.addEventListener("pointerdown", onPointerDownCapture, true);
|
|
143
152
|
document.addEventListener("mousedown", onPointerDownCapture, true);
|
|
144
153
|
removeListeners = () => {
|
|
145
154
|
document.removeEventListener("keydown", onKeyDown);
|
|
146
155
|
document.removeEventListener("focusin", onFocusIn);
|
|
156
|
+
document.removeEventListener("pointerdown", onPointerDownCapture, true);
|
|
147
157
|
document.removeEventListener("mousedown", onPointerDownCapture, true);
|
|
148
158
|
};
|
|
149
159
|
const focusables = getFocusableElements(container);
|
|
@@ -242,9 +252,11 @@ function clampIndex(index, itemCount) {
|
|
|
242
252
|
createRovingTabIndex,
|
|
243
253
|
focusFirst,
|
|
244
254
|
getFocusableElements,
|
|
255
|
+
getPrefersReducedMotionSnapshot,
|
|
245
256
|
getReducedMotionPreference,
|
|
246
257
|
prefersReducedMotion,
|
|
247
258
|
shouldAnimate,
|
|
259
|
+
subscribeReducedMotion,
|
|
248
260
|
trapFocus,
|
|
249
261
|
visuallyHiddenStyle
|
|
250
262
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -30,6 +30,10 @@ type FocusContainer = {
|
|
|
30
30
|
querySelector<T>(selectors: string): T | null;
|
|
31
31
|
};
|
|
32
32
|
declare function prefersReducedMotion(): boolean;
|
|
33
|
+
/** One-shot read of the prefers-reduced-motion media query. */
|
|
34
|
+
declare function getPrefersReducedMotionSnapshot(): boolean;
|
|
35
|
+
/** Subscribe to OS reduced-motion preference changes; returns an unsubscribe function. */
|
|
36
|
+
declare function subscribeReducedMotion(listener: (reduce: boolean) => void): () => void;
|
|
33
37
|
declare function getReducedMotionPreference(): "reduce" | "no-preference" | "unknown";
|
|
34
38
|
declare function shouldAnimate(opts?: {
|
|
35
39
|
default?: boolean;
|
|
@@ -54,4 +58,4 @@ declare function createRovingTabIndex(opts: RovingTabIndexOptions): {
|
|
|
54
58
|
};
|
|
55
59
|
};
|
|
56
60
|
|
|
57
|
-
export { type FocusContainer, type Focusable, type RovingTabIndexOptions, type TrapFocusOptions, type VisuallyHiddenStyle, createRovingTabIndex, focusFirst, getFocusableElements, getReducedMotionPreference, prefersReducedMotion, shouldAnimate, trapFocus, visuallyHiddenStyle };
|
|
61
|
+
export { type FocusContainer, type Focusable, type RovingTabIndexOptions, type TrapFocusOptions, type VisuallyHiddenStyle, createRovingTabIndex, focusFirst, getFocusableElements, getPrefersReducedMotionSnapshot, getReducedMotionPreference, prefersReducedMotion, shouldAnimate, subscribeReducedMotion, trapFocus, visuallyHiddenStyle };
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ type FocusContainer = {
|
|
|
30
30
|
querySelector<T>(selectors: string): T | null;
|
|
31
31
|
};
|
|
32
32
|
declare function prefersReducedMotion(): boolean;
|
|
33
|
+
/** One-shot read of the prefers-reduced-motion media query. */
|
|
34
|
+
declare function getPrefersReducedMotionSnapshot(): boolean;
|
|
35
|
+
/** Subscribe to OS reduced-motion preference changes; returns an unsubscribe function. */
|
|
36
|
+
declare function subscribeReducedMotion(listener: (reduce: boolean) => void): () => void;
|
|
33
37
|
declare function getReducedMotionPreference(): "reduce" | "no-preference" | "unknown";
|
|
34
38
|
declare function shouldAnimate(opts?: {
|
|
35
39
|
default?: boolean;
|
|
@@ -54,4 +58,4 @@ declare function createRovingTabIndex(opts: RovingTabIndexOptions): {
|
|
|
54
58
|
};
|
|
55
59
|
};
|
|
56
60
|
|
|
57
|
-
export { type FocusContainer, type Focusable, type RovingTabIndexOptions, type TrapFocusOptions, type VisuallyHiddenStyle, createRovingTabIndex, focusFirst, getFocusableElements, getReducedMotionPreference, prefersReducedMotion, shouldAnimate, trapFocus, visuallyHiddenStyle };
|
|
61
|
+
export { type FocusContainer, type Focusable, type RovingTabIndexOptions, type TrapFocusOptions, type VisuallyHiddenStyle, createRovingTabIndex, focusFirst, getFocusableElements, getPrefersReducedMotionSnapshot, getReducedMotionPreference, prefersReducedMotion, shouldAnimate, subscribeReducedMotion, trapFocus, visuallyHiddenStyle };
|
package/dist/index.js
CHANGED
|
@@ -25,8 +25,23 @@ function isHTMLElement(v) {
|
|
|
25
25
|
return typeof HTMLElement !== "undefined" && v instanceof HTMLElement;
|
|
26
26
|
}
|
|
27
27
|
function prefersReducedMotion() {
|
|
28
|
+
return getPrefersReducedMotionSnapshot();
|
|
29
|
+
}
|
|
30
|
+
function getPrefersReducedMotionSnapshot() {
|
|
28
31
|
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
29
32
|
}
|
|
33
|
+
function subscribeReducedMotion(listener) {
|
|
34
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
35
|
+
listener(false);
|
|
36
|
+
return () => {
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
40
|
+
const onChange = () => listener(mq.matches);
|
|
41
|
+
listener(mq.matches);
|
|
42
|
+
mq.addEventListener("change", onChange);
|
|
43
|
+
return () => mq.removeEventListener("change", onChange);
|
|
44
|
+
}
|
|
30
45
|
function getReducedMotionPreference() {
|
|
31
46
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return "unknown";
|
|
32
47
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "reduce" : "no-preference";
|
|
@@ -39,16 +54,7 @@ function shouldAnimate(opts) {
|
|
|
39
54
|
}
|
|
40
55
|
function focusFirst(container) {
|
|
41
56
|
if (!container) return false;
|
|
42
|
-
const el = container.querySelector(
|
|
43
|
-
[
|
|
44
|
-
"a[href]",
|
|
45
|
-
"button:not([disabled])",
|
|
46
|
-
"input:not([disabled])",
|
|
47
|
-
"select:not([disabled])",
|
|
48
|
-
"textarea:not([disabled])",
|
|
49
|
-
"[tabindex]:not([tabindex='-1'])"
|
|
50
|
-
].join(",")
|
|
51
|
-
);
|
|
57
|
+
const el = container.querySelector(FOCUSABLE_SELECTORS);
|
|
52
58
|
el?.focus();
|
|
53
59
|
return Boolean(el);
|
|
54
60
|
}
|
|
@@ -109,10 +115,12 @@ function trapFocus(container, opts) {
|
|
|
109
115
|
prevFocused = restoreFocus && isHTMLElement(document.activeElement) ? document.activeElement : null;
|
|
110
116
|
document.addEventListener("keydown", onKeyDown);
|
|
111
117
|
document.addEventListener("focusin", onFocusIn);
|
|
118
|
+
document.addEventListener("pointerdown", onPointerDownCapture, true);
|
|
112
119
|
document.addEventListener("mousedown", onPointerDownCapture, true);
|
|
113
120
|
removeListeners = () => {
|
|
114
121
|
document.removeEventListener("keydown", onKeyDown);
|
|
115
122
|
document.removeEventListener("focusin", onFocusIn);
|
|
123
|
+
document.removeEventListener("pointerdown", onPointerDownCapture, true);
|
|
116
124
|
document.removeEventListener("mousedown", onPointerDownCapture, true);
|
|
117
125
|
};
|
|
118
126
|
const focusables = getFocusableElements(container);
|
|
@@ -210,9 +218,11 @@ export {
|
|
|
210
218
|
createRovingTabIndex,
|
|
211
219
|
focusFirst,
|
|
212
220
|
getFocusableElements,
|
|
221
|
+
getPrefersReducedMotionSnapshot,
|
|
213
222
|
getReducedMotionPreference,
|
|
214
223
|
prefersReducedMotion,
|
|
215
224
|
shouldAnimate,
|
|
225
|
+
subscribeReducedMotion,
|
|
216
226
|
trapFocus,
|
|
217
227
|
visuallyHiddenStyle
|
|
218
228
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lessonkit/accessibility",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Accessibility utilities for LessonKit packages and apps.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"url": "git+https://github.com/eddiethedean/lessonkit.git",
|
|
10
10
|
"directory": "packages/accessibility"
|
|
11
11
|
},
|
|
12
|
-
"homepage": "https://
|
|
12
|
+
"homepage": "https://lessonkit.readthedocs.io/en/latest/reference/accessibility.html",
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/eddiethedean/lessonkit/issues"
|
|
15
15
|
},
|