@versini/ui-liveregion 3.0.2 → 3.1.1

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.d.ts CHANGED
@@ -1,12 +1,87 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { LiveRegionTypes } from '@versini/ui-types';
3
-
4
- /**
5
- * The `LiveRegion` component abstracts the logic for
6
- * rendering live region content that consistently announces
7
- * across assistive technologies (e.g. JAWS, VoiceOver,
8
- * NVDA).
9
- */
10
- declare function LiveRegion({ children, className, politeness: politenessProp, role, announcementDelay, clearAnnouncementDelay, onAnnouncementClear, visible, ...otherProps }: LiveRegionTypes.Props): react_jsx_runtime.JSX.Element;
11
-
12
- export { LiveRegion };
1
+ import { JSX } from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * The `LiveRegion` component abstracts the logic for
5
+ * rendering live region content that consistently announces
6
+ * across assistive technologies (e.g. JAWS, VoiceOver,
7
+ * NVDA).
8
+ */
9
+ export declare function LiveRegion({ children, className, politeness: politenessProp, role, announcementDelay, clearAnnouncementDelay, onAnnouncementClear, visible, ...otherProps }: LiveRegionTypes.Props): JSX.Element;
10
+
11
+ declare namespace LiveRegionTypes {
12
+ type SetTimeoutResult = ReturnType<typeof setTimeout> | null;
13
+ type Action =
14
+ | Record<string, never>
15
+ | {
16
+ type: "SET_ANNOUNCEMENT" | "CLEAR_ANNOUNCEMENT";
17
+ payload?: string | React.ReactNode;
18
+ };
19
+
20
+ type State = {
21
+ announcement: string | React.ReactNode;
22
+ };
23
+
24
+ type PolitenessByRole = {
25
+ [key: string]: any;
26
+ };
27
+
28
+ type ClearAnnouncementProps = {
29
+ dispatch: React.Dispatch<Action>;
30
+ onAnnouncementClear?: () => void;
31
+ };
32
+
33
+ type AnnounceProps = {
34
+ children: React.ReactNode;
35
+ clearAnnouncementTimeoutRef: React.MutableRefObject<SetTimeoutResult>;
36
+ dispatch: React.Dispatch<Action>;
37
+ clearAnnouncementDelay?: number;
38
+ onAnnouncementClear?: () => void;
39
+ };
40
+
41
+ type ConditionallyDelayAnnouncementProps = {
42
+ announcementTimeoutRef: React.MutableRefObject<SetTimeoutResult>;
43
+ children: React.ReactNode;
44
+ clearAnnouncementTimeoutRef: React.MutableRefObject<SetTimeoutResult>;
45
+ dispatch: React.Dispatch<Action>;
46
+ announcementDelay?: number;
47
+ clearAnnouncementDelay?: number;
48
+ onAnnouncementClear?: () => void;
49
+ };
50
+
51
+ type Props = {
52
+ /**
53
+ * The content to be announced by the live region.
54
+ */
55
+ children: React.ReactNode;
56
+ /**
57
+ * The number of milliseconds to wait before announcing the content.
58
+ */
59
+ announcementDelay?: number;
60
+ /**
61
+ * The `className` to apply to the live region.
62
+ */
63
+ className?: string;
64
+ /**
65
+ * The number of milliseconds to wait before clearing the announcement.
66
+ */
67
+ clearAnnouncementDelay?: number;
68
+ /**
69
+ * A callback to be invoked when the announcement is cleared.
70
+ */
71
+ onAnnouncementClear?: () => void;
72
+ /**
73
+ * The `aria-live` politeness level to apply to the live region.
74
+ */
75
+ politeness?: "polite" | "assertive" | "off" | null | undefined;
76
+ /**
77
+ * The `role` to apply to the live region.
78
+ */
79
+ role?: "alert" | "status" | null | undefined;
80
+ /**
81
+ * Whether or not the live region should be visible.
82
+ */
83
+ visible?: boolean;
84
+ };
85
+ }
86
+
87
+ export { }
package/dist/index.js CHANGED
@@ -1,17 +1,257 @@
1
- import { LiveRegion as o } from "./components/LiveRegion/LiveRegion.js";
2
1
  /*!
3
- @versini/ui-liveregion v3.0.2
2
+ @versini/ui-liveregion v3.1.1
4
3
  © 2025 gizmette.com
5
4
  */
6
5
  try {
7
- window.__VERSINI_UI_LIVEREGION__ || (window.__VERSINI_UI_LIVEREGION__ = {
8
- version: "3.0.2",
9
- buildTime: "10/17/2025 12:52 PM EDT",
10
- homepage: "https://github.com/aversini/ui-components",
11
- license: "MIT"
12
- });
13
- } catch {
6
+ if (!window.__VERSINI_UI_LIVEREGION__) {
7
+ window.__VERSINI_UI_LIVEREGION__ = {
8
+ version: "3.1.1",
9
+ buildTime: "11/30/2025 06:52 PM EST",
10
+ homepage: "https://github.com/aversini/ui-components",
11
+ license: "MIT",
12
+ };
13
+ }
14
+ } catch (error) {
15
+ // nothing to declare officer
14
16
  }
15
- export {
16
- o as LiveRegion
17
+
18
+ import { jsx } from "react/jsx-runtime";
19
+ import clsx from "clsx";
20
+ import { useEffect, useReducer, useRef } from "react";
21
+
22
+ ;// CONCATENATED MODULE: external "react/jsx-runtime"
23
+
24
+ ;// CONCATENATED MODULE: external "clsx"
25
+
26
+ ;// CONCATENATED MODULE: external "react"
27
+
28
+ ;// CONCATENATED MODULE: ./src/components/LiveRegion/constants.ts
29
+ const ACTION_SET_ANNOUNCEMENT = "SET_ANNOUNCEMENT";
30
+ const ACTION_CLEAR_ANNOUNCEMENT = "CLEAR_ANNOUNCEMENT";
31
+ /**
32
+ * The default politeness value for each role.
33
+ *
34
+ * @enum {String}
35
+ */ const DEFAULT_POLITENESS_BY_ROLE = {
36
+ alert: null,
37
+ alertdialog: null,
38
+ log: "polite",
39
+ marquee: null,
40
+ progressbar: null,
41
+ status: "polite",
42
+ timer: "assertive"
17
43
  };
44
+ /**
45
+ * All supported `LiveRegion` roles.
46
+ *
47
+ * @enum {String}
48
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#Live_Region_Roles
49
+ */ const ROLES = (/* unused pure expression or super */ null && ({
50
+ /**
51
+ * A message with important, and usually time-sensitive
52
+ * information.
53
+ *
54
+ * Default politeness is `null` (does not add the
55
+ * `aria-live` attribute).
56
+ *
57
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Alert_Role
58
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#alert
59
+ */ ALERT: "alert",
60
+ /**
61
+ * A type of dialog that contains an alert message, where
62
+ * initial focus goes to the dialog or an element
63
+ * within it.
64
+ *
65
+ * Authors SHOULD use aria-describedby on an alertdialog
66
+ * to point to the alert message element in the
67
+ * dialog.
68
+ *
69
+ * Default politeness is `null` (does not add the
70
+ * `aria-live` attribute).
71
+ *
72
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_alertdialog_role
73
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#alertdialog
74
+ */ ALERTDIALOG: "alertdialog",
75
+ /**
76
+ * A type of live region where new information is added in
77
+ * meaningful order and old information may
78
+ * disappear.
79
+ *
80
+ * Default politeness is `"polite"`.
81
+ *
82
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_log_role
83
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#log
84
+ */ LOG: "log",
85
+ /**
86
+ * A type of live region where non-essential information
87
+ * changes frequently. The primary difference
88
+ * between a marquee and a log is that logs usually have
89
+ * a meaningful order or sequence of important
90
+ * content changes.
91
+ *
92
+ * Default politeness is `null` (does not add the
93
+ * `aria-live` attribute).
94
+ */ MARQUEE: "marquee",
95
+ /**
96
+ * An element that displays the progress status for tasks
97
+ * that take a long time.
98
+ *
99
+ * Default politeness is `null` (does not add the
100
+ * `aria-live` attribute).
101
+ *
102
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#progressbar
103
+ */ PROGRESSBAR: "progressbar",
104
+ /**
105
+ * A container whose content is advisory information for
106
+ * the user but is not important enough to justify
107
+ * an alert.
108
+ *
109
+ * Default politeness is `"polite"`.
110
+ *
111
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_status_role
112
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#status
113
+ */ STATUS: "status",
114
+ /**
115
+ * A numerical counter which indicates an amount of
116
+ * elapsed time from a start point, or the time remaining
117
+ * until an end point.
118
+ *
119
+ * Default politeness is `"assertive"`.
120
+ *
121
+ * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/ARIA_timer_role
122
+ * @see https://www.w3.org/TR/2009/WD-wai-aria-20091215/roles#timer
123
+ */ TIMER: "timer"
124
+ }));
125
+
126
+ ;// CONCATENATED MODULE: ./src/components/LiveRegion/reducer.ts
127
+
128
+ const reducer = (state, action)=>{
129
+ switch(action?.type){
130
+ case ACTION_SET_ANNOUNCEMENT:
131
+ return {
132
+ ...state,
133
+ announcement: action.payload
134
+ };
135
+ case ACTION_CLEAR_ANNOUNCEMENT:
136
+ return {
137
+ ...state,
138
+ announcement: null
139
+ };
140
+ default:
141
+ return state;
142
+ }
143
+ };
144
+
145
+ ;// CONCATENATED MODULE: ./src/components/LiveRegion/utilities.ts
146
+
147
+ /**
148
+ * Removes the content from the live region.
149
+ */ const clearAnnouncement = ({ onAnnouncementClear, dispatch })=>{
150
+ dispatch({
151
+ type: ACTION_CLEAR_ANNOUNCEMENT
152
+ });
153
+ if (typeof onAnnouncementClear === "function") {
154
+ onAnnouncementClear();
155
+ }
156
+ };
157
+ /**
158
+ * Announce the content of "children".
159
+ */ const announce = ({ children, clearAnnouncementDelay, clearAnnouncementTimeoutRef, onAnnouncementClear, dispatch })=>{
160
+ clearTimeout(clearAnnouncementTimeoutRef.current);
161
+ if (children !== null) {
162
+ dispatch({
163
+ type: ACTION_SET_ANNOUNCEMENT,
164
+ payload: children
165
+ });
166
+ }
167
+ if (clearAnnouncementDelay) {
168
+ clearAnnouncementTimeoutRef.current = setTimeout(()=>clearAnnouncement({
169
+ onAnnouncementClear,
170
+ dispatch
171
+ }), clearAnnouncementDelay);
172
+ }
173
+ };
174
+ /**
175
+ * Inserts the content into the live region with some
176
+ * delay if the announcementDelay prop is supplied.
177
+ * Otherwise inserts the content immediately.
178
+ */ const conditionallyDelayAnnouncement = ({ children, announcementTimeoutRef, announcementDelay, clearAnnouncementDelay, clearAnnouncementTimeoutRef, onAnnouncementClear, dispatch })=>{
179
+ clearTimeout(announcementTimeoutRef.current);
180
+ if (announcementDelay) {
181
+ announcementTimeoutRef.current = setTimeout(announce, announcementDelay, {
182
+ children,
183
+ clearAnnouncementDelay,
184
+ clearAnnouncementTimeoutRef,
185
+ onAnnouncementClear,
186
+ dispatch
187
+ });
188
+ } else {
189
+ announce({
190
+ children,
191
+ clearAnnouncementDelay,
192
+ clearAnnouncementTimeoutRef,
193
+ onAnnouncementClear,
194
+ dispatch
195
+ });
196
+ }
197
+ };
198
+
199
+ ;// CONCATENATED MODULE: ./src/components/LiveRegion/LiveRegion.tsx
200
+
201
+
202
+
203
+
204
+
205
+
206
+ /**
207
+ * The `LiveRegion` component abstracts the logic for
208
+ * rendering live region content that consistently announces
209
+ * across assistive technologies (e.g. JAWS, VoiceOver,
210
+ * NVDA).
211
+ */ function LiveRegion({ children, className, politeness: politenessProp, role = null, announcementDelay, clearAnnouncementDelay, onAnnouncementClear, visible, ...otherProps }) {
212
+ const announcementTimeoutRef = useRef(null);
213
+ const clearAnnouncementTimeoutRef = useRef(null);
214
+ const [state, dispatch] = useReducer(reducer, {
215
+ announcement: null
216
+ });
217
+ let politeness = politenessProp;
218
+ /**
219
+ * We check `undefined` since it is our default,
220
+ * and we want to honor when the user supplies `null`.
221
+ */ if (typeof politeness === "undefined") {
222
+ politeness = role ? DEFAULT_POLITENESS_BY_ROLE[role] : "assertive";
223
+ }
224
+ useEffect(()=>{
225
+ conditionallyDelayAnnouncement({
226
+ announcementTimeoutRef,
227
+ announcementDelay,
228
+ children,
229
+ clearAnnouncementDelay,
230
+ clearAnnouncementTimeoutRef,
231
+ onAnnouncementClear,
232
+ dispatch
233
+ });
234
+ }, [
235
+ children,
236
+ announcementDelay,
237
+ clearAnnouncementDelay,
238
+ onAnnouncementClear
239
+ ]);
240
+ const generatedClassName = clsx(className, {
241
+ "sr-only": !visible
242
+ });
243
+ return /*#__PURE__*/ jsx("div", {
244
+ "aria-live": politeness,
245
+ ...role && {
246
+ role: role
247
+ },
248
+ className: generatedClassName,
249
+ ...otherProps,
250
+ children: state.announcement
251
+ });
252
+ }
253
+
254
+ ;// CONCATENATED MODULE: ./src/components/index.ts
255
+ /* v8 ignore next 1 */
256
+
257
+ export { LiveRegion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@versini/ui-liveregion",
3
- "version": "3.0.2",
3
+ "version": "3.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "publishConfig": {
@@ -20,13 +20,13 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "build:check": "tsc",
23
- "build:js": "vite build",
24
- "build:types": "tsup",
25
- "build": "npm-run-all --serial clean build:check build:js build:types",
23
+ "build:js": "rslib build",
24
+ "build:types": "echo 'Types now built with rslib'",
25
+ "build": "npm-run-all --serial clean build:check build:js",
26
26
  "clean": "rimraf dist tmp",
27
- "dev:js": "vite build --watch --mode development",
28
- "dev:types": "tsup --watch src",
29
- "dev": "npm-run-all clean --parallel dev:js dev:types",
27
+ "dev:js": "rslib build --watch",
28
+ "dev:types": "echo 'Types now watched with rslib'",
29
+ "dev": "rslib build --watch",
30
30
  "lint": "biome lint src",
31
31
  "lint:fix": "biome check src --write --no-errors-on-unmatched",
32
32
  "prettier": "biome check --write --no-errors-on-unmatched",
@@ -38,10 +38,10 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/jest-dom": "6.9.1",
41
- "@versini/ui-types": "6.0.2"
41
+ "@versini/ui-types": "7.0.0"
42
42
  },
43
43
  "sideEffects": [
44
44
  "**/*.css"
45
45
  ],
46
- "gitHead": "67e049c9b2e46e8f52509bf6198ca0cdaf5d970a"
46
+ "gitHead": "4795cf3239cceaf83dde13addc5254caa12dee6f"
47
47
  }
@@ -1,121 +0,0 @@
1
- import { jsx as O } from "react/jsx-runtime";
2
- import C from "clsx";
3
- import { useRef as i, useReducer as L, useEffect as g } from "react";
4
- const c = "SET_ANNOUNCEMENT", E = "CLEAR_ANNOUNCEMENT", v = {
5
- alert: null,
6
- alertdialog: null,
7
- log: "polite",
8
- marquee: null,
9
- progressbar: null,
10
- status: "polite",
11
- timer: "assertive"
12
- }, y = (t, e) => {
13
- switch (e?.type) {
14
- case c:
15
- return {
16
- ...t,
17
- announcement: e.payload
18
- };
19
- case E:
20
- return {
21
- ...t,
22
- announcement: null
23
- };
24
- default:
25
- return t;
26
- }
27
- }, R = ({
28
- onAnnouncementClear: t,
29
- dispatch: e
30
- }) => {
31
- e({
32
- type: E
33
- }), typeof t == "function" && t();
34
- }, N = ({
35
- children: t,
36
- clearAnnouncementDelay: e,
37
- clearAnnouncementTimeoutRef: o,
38
- onAnnouncementClear: s,
39
- dispatch: u
40
- }) => {
41
- clearTimeout(o.current), t !== null && u({
42
- type: c,
43
- payload: t
44
- }), e && (o.current = setTimeout(
45
- () => R({
46
- onAnnouncementClear: s,
47
- dispatch: u
48
- }),
49
- e
50
- ));
51
- }, U = ({
52
- children: t,
53
- announcementTimeoutRef: e,
54
- announcementDelay: o,
55
- clearAnnouncementDelay: s,
56
- clearAnnouncementTimeoutRef: u,
57
- onAnnouncementClear: r,
58
- dispatch: l
59
- }) => {
60
- clearTimeout(e.current), o ? e.current = setTimeout(N, o, {
61
- children: t,
62
- clearAnnouncementDelay: s,
63
- clearAnnouncementTimeoutRef: u,
64
- onAnnouncementClear: r,
65
- dispatch: l
66
- }) : N({
67
- children: t,
68
- clearAnnouncementDelay: s,
69
- clearAnnouncementTimeoutRef: u,
70
- onAnnouncementClear: r,
71
- dispatch: l
72
- });
73
- };
74
- function x({
75
- children: t,
76
- className: e,
77
- politeness: o,
78
- role: s = null,
79
- announcementDelay: u,
80
- clearAnnouncementDelay: r,
81
- onAnnouncementClear: l,
82
- visible: f,
83
- ...a
84
- }) {
85
- const p = i(null), T = i(null), [m, _] = L(y, {
86
- announcement: null
87
- });
88
- let n = o;
89
- typeof n > "u" && (n = s ? v[s] : "assertive"), g(() => {
90
- U({
91
- announcementTimeoutRef: p,
92
- announcementDelay: u,
93
- children: t,
94
- clearAnnouncementDelay: r,
95
- clearAnnouncementTimeoutRef: T,
96
- onAnnouncementClear: l,
97
- dispatch: _
98
- });
99
- }, [
100
- t,
101
- u,
102
- r,
103
- l
104
- ]);
105
- const d = C(e, {
106
- "sr-only": !f
107
- });
108
- return /* @__PURE__ */ O(
109
- "div",
110
- {
111
- "aria-live": n,
112
- ...s && { role: s },
113
- className: d,
114
- ...a,
115
- children: m.announcement
116
- }
117
- );
118
- }
119
- export {
120
- x as LiveRegion
121
- };