@huin-core/react-announce 1.0.2 → 1.0.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.
@@ -0,0 +1,68 @@
1
+ import * as React from 'react';
2
+ import { Primitive } from '@huin-core/react-primitive';
3
+
4
+ type RegionType = 'polite' | 'assertive' | 'off';
5
+ type RegionRole = 'status' | 'alert' | 'log' | 'none';
6
+ type PrimitiveDivProps = React.ComponentPropsWithoutRef<typeof Primitive.div>;
7
+ interface AnnounceProps extends PrimitiveDivProps {
8
+ /**
9
+ * Mirrors the `aria-atomic` DOM attribute for live regions. It is an optional attribute that
10
+ * indicates whether assistive technologies will present all, or only parts of, the changed region
11
+ * based on the change notifications defined by the `aria-relevant` attribute.
12
+ *
13
+ * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-atomic
14
+ * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html
15
+ */
16
+ 'aria-atomic'?: boolean;
17
+ /**
18
+ * Mirrors the `aria-relevant` DOM attribute for live regions. It is an optional attribute used to
19
+ * describe what types of changes have occurred to the region, and which changes are relevant and
20
+ * should be announced. Any change that is not relevant acts in the same manner it would if the
21
+ * `aria-live` attribute were set to off.
22
+ *
23
+ * Unfortunately, `aria-relevant` doesn't behave as expected across all device/screen reader
24
+ * combinations. It's important to test its implementation before relying on it to work for your
25
+ * users. The attribute is omitted by default.
26
+ *
27
+ * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-relevant
28
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-relevant_attribute
29
+ * @see Opinion https://medium.com/dev-channel/why-authors-should-avoid-aria-relevant-5d3164fab1e3
30
+ * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html
31
+ */
32
+ 'aria-relevant'?: PrimitiveDivProps['aria-relevant'];
33
+ /**
34
+ * React children of your component. Children can be mirrored directly or modified to optimize for
35
+ * screen reader user experience.
36
+ */
37
+ children: React.ReactNode;
38
+ /**
39
+ * An optional unique identifier for the live region.
40
+ *
41
+ * By default, `Announce` components create, at most, two unique `aria-live` regions in the
42
+ * document (one for all `polite` notifications, one for all `assertive` notifications). In some
43
+ * cases you may wish to append additional `aria-live` regions for distinct purposes (for example,
44
+ * simple status updates may need to be separated from a stack of toast-style notifications). By
45
+ * passing an id, you indicate that any content rendered by components with the same identifier
46
+ * should be mirrored in a separate `aria-live` region.
47
+ */
48
+ regionIdentifier?: string;
49
+ /**
50
+ * Mirrors the `role` DOM attribute. This is optional and may be useful as an override in some
51
+ * cases. By default, the role is determined by the `type` prop.
52
+ *
53
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles
54
+ */
55
+ role?: RegionRole;
56
+ /**
57
+ * Mirrors the `aria-live` DOM attribute. The `aria-live=POLITENESS_SETTING` is used to set the
58
+ * priority with which screen reader should treat updates to live regions. Its possible settings
59
+ * are: off, polite or assertive. Defaults to `polite`.
60
+ *
61
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
62
+ */
63
+ type?: RegionType;
64
+ }
65
+ declare const Announce: React.ForwardRefExoticComponent<AnnounceProps & React.RefAttributes<HTMLDivElement>>;
66
+ declare const Root: React.ForwardRefExoticComponent<AnnounceProps & React.RefAttributes<HTMLDivElement>>;
67
+
68
+ export { Announce, type AnnounceProps, Root };
@@ -0,0 +1,68 @@
1
+ import * as React from 'react';
2
+ import { Primitive } from '@huin-core/react-primitive';
3
+
4
+ type RegionType = 'polite' | 'assertive' | 'off';
5
+ type RegionRole = 'status' | 'alert' | 'log' | 'none';
6
+ type PrimitiveDivProps = React.ComponentPropsWithoutRef<typeof Primitive.div>;
7
+ interface AnnounceProps extends PrimitiveDivProps {
8
+ /**
9
+ * Mirrors the `aria-atomic` DOM attribute for live regions. It is an optional attribute that
10
+ * indicates whether assistive technologies will present all, or only parts of, the changed region
11
+ * based on the change notifications defined by the `aria-relevant` attribute.
12
+ *
13
+ * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-atomic
14
+ * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html
15
+ */
16
+ 'aria-atomic'?: boolean;
17
+ /**
18
+ * Mirrors the `aria-relevant` DOM attribute for live regions. It is an optional attribute used to
19
+ * describe what types of changes have occurred to the region, and which changes are relevant and
20
+ * should be announced. Any change that is not relevant acts in the same manner it would if the
21
+ * `aria-live` attribute were set to off.
22
+ *
23
+ * Unfortunately, `aria-relevant` doesn't behave as expected across all device/screen reader
24
+ * combinations. It's important to test its implementation before relying on it to work for your
25
+ * users. The attribute is omitted by default.
26
+ *
27
+ * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-relevant
28
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-relevant_attribute
29
+ * @see Opinion https://medium.com/dev-channel/why-authors-should-avoid-aria-relevant-5d3164fab1e3
30
+ * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html
31
+ */
32
+ 'aria-relevant'?: PrimitiveDivProps['aria-relevant'];
33
+ /**
34
+ * React children of your component. Children can be mirrored directly or modified to optimize for
35
+ * screen reader user experience.
36
+ */
37
+ children: React.ReactNode;
38
+ /**
39
+ * An optional unique identifier for the live region.
40
+ *
41
+ * By default, `Announce` components create, at most, two unique `aria-live` regions in the
42
+ * document (one for all `polite` notifications, one for all `assertive` notifications). In some
43
+ * cases you may wish to append additional `aria-live` regions for distinct purposes (for example,
44
+ * simple status updates may need to be separated from a stack of toast-style notifications). By
45
+ * passing an id, you indicate that any content rendered by components with the same identifier
46
+ * should be mirrored in a separate `aria-live` region.
47
+ */
48
+ regionIdentifier?: string;
49
+ /**
50
+ * Mirrors the `role` DOM attribute. This is optional and may be useful as an override in some
51
+ * cases. By default, the role is determined by the `type` prop.
52
+ *
53
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles
54
+ */
55
+ role?: RegionRole;
56
+ /**
57
+ * Mirrors the `aria-live` DOM attribute. The `aria-live=POLITENESS_SETTING` is used to set the
58
+ * priority with which screen reader should treat updates to live regions. Its possible settings
59
+ * are: off, polite or assertive. Defaults to `polite`.
60
+ *
61
+ * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
62
+ */
63
+ type?: RegionType;
64
+ }
65
+ declare const Announce: React.ForwardRefExoticComponent<AnnounceProps & React.RefAttributes<HTMLDivElement>>;
66
+ declare const Root: React.ForwardRefExoticComponent<AnnounceProps & React.RefAttributes<HTMLDivElement>>;
67
+
68
+ export { Announce, type AnnounceProps, Root };
package/dist/index.js ADDED
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // packages/react/announce/src/index.ts
32
+ var src_exports = {};
33
+ __export(src_exports, {
34
+ Announce: () => Announce,
35
+ Root: () => Root
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // packages/react/announce/src/Announce.tsx
40
+ var React = __toESM(require("react"));
41
+ var import_react_dom = __toESM(require("react-dom"));
42
+ var import_react_compose_refs = require("@huin-core/react-compose-refs");
43
+ var import_react_primitive = require("@huin-core/react-primitive");
44
+ var import_react_use_layout_effect = require("@huin-core/react-use-layout-effect");
45
+ var import_jsx_runtime = require("react/jsx-runtime");
46
+ var ROLES = {
47
+ polite: "status",
48
+ assertive: "alert",
49
+ off: "none"
50
+ };
51
+ var listenerMap = /* @__PURE__ */ new Map();
52
+ var NAME = "Announce";
53
+ var Announce = React.forwardRef((props, forwardedRef) => {
54
+ const {
55
+ "aria-relevant": ariaRelevant,
56
+ children,
57
+ type = "polite",
58
+ role = ROLES[type],
59
+ regionIdentifier,
60
+ ...regionProps
61
+ } = props;
62
+ const ariaAtomic = ["true", true].includes(regionProps["aria-atomic"]);
63
+ const ownerDocumentRef = React.useRef(document);
64
+ const setOwnerDocumentFromRef = React.useCallback((node) => {
65
+ if (node) {
66
+ ownerDocumentRef.current = node.ownerDocument;
67
+ }
68
+ }, []);
69
+ const ownRef = React.useRef(null);
70
+ const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ownRef, setOwnerDocumentFromRef);
71
+ const [region, setRegion] = React.useState();
72
+ const relevant = ariaRelevant ? Array.isArray(ariaRelevant) ? ariaRelevant.join(" ") : ariaRelevant : void 0;
73
+ const getLiveRegionElement = React.useCallback(() => {
74
+ const ownerDocument = ownerDocumentRef.current;
75
+ const regionConfig = { type, role, relevant, id: regionIdentifier, atomic: ariaAtomic };
76
+ const regionSelector = buildSelector(regionConfig);
77
+ const element = ownerDocument.querySelector(regionSelector);
78
+ return element || buildLiveRegionElement(ownerDocument, regionConfig);
79
+ }, [ariaAtomic, relevant, role, type, regionIdentifier]);
80
+ (0, import_react_use_layout_effect.useLayoutEffect)(() => {
81
+ setRegion(getLiveRegionElement());
82
+ }, [getLiveRegionElement]);
83
+ React.useEffect(() => {
84
+ const ownerDocument = ownerDocumentRef.current;
85
+ function updateAttributesOnVisibilityChange() {
86
+ regionElement.setAttribute("role", ownerDocument.hidden ? "none" : role);
87
+ regionElement.setAttribute("aria-live", ownerDocument.hidden ? "off" : type);
88
+ }
89
+ const regionElement = getLiveRegionElement();
90
+ if (!listenerMap.get(regionElement)) {
91
+ ownerDocument.addEventListener("visibilitychange", updateAttributesOnVisibilityChange);
92
+ listenerMap.set(regionElement, 1);
93
+ } else {
94
+ const announceCount = listenerMap.get(regionElement);
95
+ listenerMap.set(regionElement, announceCount + 1);
96
+ }
97
+ return function() {
98
+ const announceCount = listenerMap.get(regionElement);
99
+ listenerMap.set(regionElement, announceCount - 1);
100
+ if (announceCount === 1) {
101
+ ownerDocument.removeEventListener("visibilitychange", updateAttributesOnVisibilityChange);
102
+ }
103
+ };
104
+ }, [getLiveRegionElement, role, type]);
105
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(React.Fragment, { children: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...regionProps, ref, children }),
107
+ region && import_react_dom.default.createPortal(/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children }), region)
108
+ ] });
109
+ });
110
+ Announce.displayName = NAME;
111
+ function buildLiveRegionElement(ownerDocument, { type, relevant, role, atomic, id }) {
112
+ const element = ownerDocument.createElement("div");
113
+ element.setAttribute(getLiveRegionPartDataAttr(id), "");
114
+ element.setAttribute(
115
+ "style",
116
+ "position: absolute; top: -1px; width: 1px; height: 1px; overflow: hidden;"
117
+ );
118
+ ownerDocument.body.appendChild(element);
119
+ element.setAttribute("aria-live", type);
120
+ element.setAttribute("aria-atomic", String(atomic || false));
121
+ element.setAttribute("role", role);
122
+ if (relevant) {
123
+ element.setAttribute("aria-relevant", relevant);
124
+ }
125
+ return element;
126
+ }
127
+ function buildSelector({ type, relevant, role, atomic, id }) {
128
+ return `[${getLiveRegionPartDataAttr(id)}]${[
129
+ ["aria-live", type],
130
+ ["aria-atomic", atomic],
131
+ ["aria-relevant", relevant],
132
+ ["role", role]
133
+ ].filter(([, val]) => !!val).map(([attr, val]) => `[${attr}=${val}]`).join("")}`;
134
+ }
135
+ function getLiveRegionPartDataAttr(id) {
136
+ return "data-huin-core-announce-region" + (id ? `-${id}` : "");
137
+ }
138
+ var Root = Announce;
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../src/Announce.tsx"],
4
+ "sourcesContent": ["'use client';\nexport {\n Announce,\n //\n Root,\n} from './Announce';\nexport type { AnnounceProps } from './Announce';\n", "import * as React from 'react';\nimport ReactDOM from 'react-dom';\nimport { useComposedRefs } from '@huin-core/react-compose-refs';\nimport { Primitive } from '@huin-core/react-primitive';\nimport { useLayoutEffect } from '@huin-core/react-use-layout-effect';\n\ntype RegionType = 'polite' | 'assertive' | 'off';\ntype RegionRole = 'status' | 'alert' | 'log' | 'none';\n\nconst ROLES: { [key in RegionType]: RegionRole } = {\n polite: 'status',\n assertive: 'alert',\n off: 'none',\n};\n\nconst listenerMap = new Map<Element, number>();\n\n/* -------------------------------------------------------------------------------------------------\n * Announce\n * -----------------------------------------------------------------------------------------------*/\n\nconst NAME = 'Announce';\n\ntype AnnounceElement = React.ElementRef<typeof Primitive.div>;\ntype PrimitiveDivProps = React.ComponentPropsWithoutRef<typeof Primitive.div>;\ninterface AnnounceProps extends PrimitiveDivProps {\n /**\n * Mirrors the `aria-atomic` DOM attribute for live regions. It is an optional attribute that\n * indicates whether assistive technologies will present all, or only parts of, the changed region\n * based on the change notifications defined by the `aria-relevant` attribute.\n *\n * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-atomic\n * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html\n */\n 'aria-atomic'?: boolean;\n /**\n * Mirrors the `aria-relevant` DOM attribute for live regions. It is an optional attribute used to\n * describe what types of changes have occurred to the region, and which changes are relevant and\n * should be announced. Any change that is not relevant acts in the same manner it would if the\n * `aria-live` attribute were set to off.\n *\n * Unfortunately, `aria-relevant` doesn't behave as expected across all device/screen reader\n * combinations. It's important to test its implementation before relying on it to work for your\n * users. The attribute is omitted by default.\n *\n * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-relevant\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-relevant_attribute\n * @see Opinion https://medium.com/dev-channel/why-authors-should-avoid-aria-relevant-5d3164fab1e3\n * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html\n */\n 'aria-relevant'?: PrimitiveDivProps['aria-relevant'];\n /**\n * React children of your component. Children can be mirrored directly or modified to optimize for\n * screen reader user experience.\n */\n children: React.ReactNode;\n /**\n * An optional unique identifier for the live region.\n *\n * By default, `Announce` components create, at most, two unique `aria-live` regions in the\n * document (one for all `polite` notifications, one for all `assertive` notifications). In some\n * cases you may wish to append additional `aria-live` regions for distinct purposes (for example,\n * simple status updates may need to be separated from a stack of toast-style notifications). By\n * passing an id, you indicate that any content rendered by components with the same identifier\n * should be mirrored in a separate `aria-live` region.\n */\n regionIdentifier?: string;\n /**\n * Mirrors the `role` DOM attribute. This is optional and may be useful as an override in some\n * cases. By default, the role is determined by the `type` prop.\n *\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles\n */\n role?: RegionRole;\n /**\n * Mirrors the `aria-live` DOM attribute. The `aria-live=POLITENESS_SETTING` is used to set the\n * priority with which screen reader should treat updates to live regions. Its possible settings\n * are: off, polite or assertive. Defaults to `polite`.\n *\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions\n */\n type?: RegionType;\n}\n\nconst Announce = React.forwardRef<AnnounceElement, AnnounceProps>((props, forwardedRef) => {\n const {\n 'aria-relevant': ariaRelevant,\n children,\n type = 'polite',\n role = ROLES[type],\n regionIdentifier,\n ...regionProps\n } = props;\n\n const ariaAtomic = ['true', true].includes(regionProps['aria-atomic'] as any);\n\n // The region is appended to the root document node, which is usually the global `document` but in\n // some contexts may be another node. After the Announce element ref is attached, we set the\n // ownerDocumentRef to make sure we have the right root node. We should only need to do this once.\n const ownerDocumentRef = React.useRef(document);\n const setOwnerDocumentFromRef = React.useCallback((node: HTMLDivElement) => {\n if (node) {\n ownerDocumentRef.current = node.ownerDocument;\n }\n }, []);\n const ownRef = React.useRef<HTMLDivElement | null>(null);\n const ref = useComposedRefs(forwardedRef, ownRef, setOwnerDocumentFromRef);\n\n const [region, setRegion] = React.useState<HTMLElement>();\n const relevant = ariaRelevant\n ? Array.isArray(ariaRelevant)\n ? ariaRelevant.join(' ')\n : ariaRelevant\n : undefined;\n\n const getLiveRegionElement = React.useCallback(() => {\n const ownerDocument = ownerDocumentRef.current;\n const regionConfig = { type, role, relevant, id: regionIdentifier, atomic: ariaAtomic };\n const regionSelector = buildSelector(regionConfig);\n const element = ownerDocument.querySelector(regionSelector);\n\n return element || buildLiveRegionElement(ownerDocument, regionConfig);\n }, [ariaAtomic, relevant, role, type, regionIdentifier]);\n\n useLayoutEffect(() => {\n setRegion(getLiveRegionElement() as HTMLElement);\n }, [getLiveRegionElement]);\n\n // In some screen reader/browser combinations, alerts coming from an inactive browser tab may be\n // announced, which is a confusing experience for a user interacting with a completely different\n // page. When the page visibility changes we'll update the `role` and `aria-live` attributes of\n // our region element to prevent that.\n // https://inclusive-components.design/notifications/#restrictingmessagestocontexts\n React.useEffect(() => {\n const ownerDocument = ownerDocumentRef.current;\n function updateAttributesOnVisibilityChange() {\n regionElement.setAttribute('role', ownerDocument.hidden ? 'none' : role);\n regionElement.setAttribute('aria-live', ownerDocument.hidden ? 'off' : type);\n }\n\n // Ok, so this might look a little weird and confusing, but here's what's going on:\n // - We need to hide `aria-live` regions via a global event listener, as noted in the comment\n // above.\n // - We only need one listener per region. Keep in mind that each `Announce` does not\n // necessarily generate a unique live region element.\n // - We track whether or not a listener has already been attached for a given region in a map\n // so we can skip these effects after `Announce` is used again with a shared live region.\n const regionElement = getLiveRegionElement();\n\n if (!listenerMap.get(regionElement)) {\n ownerDocument.addEventListener('visibilitychange', updateAttributesOnVisibilityChange);\n listenerMap.set(regionElement, 1);\n } else {\n const announceCount = listenerMap.get(regionElement)!;\n listenerMap.set(regionElement, announceCount + 1);\n }\n\n return function () {\n const announceCount = listenerMap.get(regionElement)!;\n listenerMap.set(regionElement, announceCount - 1);\n if (announceCount === 1) {\n ownerDocument.removeEventListener('visibilitychange', updateAttributesOnVisibilityChange);\n }\n };\n }, [getLiveRegionElement, role, type]);\n\n return (\n <React.Fragment>\n <Primitive.div {...regionProps} ref={ref}>\n {children}\n </Primitive.div>\n\n {/* portal into live region for screen reader announcements */}\n {region && ReactDOM.createPortal(<div>{children}</div>, region)}\n </React.Fragment>\n );\n});\n\nAnnounce.displayName = NAME;\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype LiveRegionOptions = {\n type: string;\n relevant?: string;\n role: string;\n atomic?: boolean;\n id?: string;\n};\n\nfunction buildLiveRegionElement(\n ownerDocument: Document,\n { type, relevant, role, atomic, id }: LiveRegionOptions\n) {\n const element = ownerDocument.createElement('div');\n element.setAttribute(getLiveRegionPartDataAttr(id), '');\n element.setAttribute(\n 'style',\n 'position: absolute; top: -1px; width: 1px; height: 1px; overflow: hidden;'\n );\n ownerDocument.body.appendChild(element);\n\n element.setAttribute('aria-live', type);\n element.setAttribute('aria-atomic', String(atomic || false));\n element.setAttribute('role', role);\n if (relevant) {\n element.setAttribute('aria-relevant', relevant);\n }\n\n return element;\n}\n\nfunction buildSelector({ type, relevant, role, atomic, id }: LiveRegionOptions) {\n return `[${getLiveRegionPartDataAttr(id)}]${[\n ['aria-live', type],\n ['aria-atomic', atomic],\n ['aria-relevant', relevant],\n ['role', role],\n ]\n .filter(([, val]) => !!val)\n .map(([attr, val]) => `[${attr}=${val}]`)\n .join('')}`;\n}\n\nfunction getLiveRegionPartDataAttr(id?: string) {\n return 'data-huin-core-announce-region' + (id ? `-${id}` : '');\n}\n\nconst Root = Announce;\n\nexport {\n Announce,\n //\n Root,\n};\nexport type { AnnounceProps };\n"],
5
+ "mappings": "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",
6
+ "names": ["ReactDOM"]
7
+ }
package/dist/index.mjs ADDED
@@ -0,0 +1,107 @@
1
+ "use client";
2
+
3
+ // packages/react/announce/src/Announce.tsx
4
+ import * as React from "react";
5
+ import ReactDOM from "react-dom";
6
+ import { useComposedRefs } from "@huin-core/react-compose-refs";
7
+ import { Primitive } from "@huin-core/react-primitive";
8
+ import { useLayoutEffect } from "@huin-core/react-use-layout-effect";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var ROLES = {
11
+ polite: "status",
12
+ assertive: "alert",
13
+ off: "none"
14
+ };
15
+ var listenerMap = /* @__PURE__ */ new Map();
16
+ var NAME = "Announce";
17
+ var Announce = React.forwardRef((props, forwardedRef) => {
18
+ const {
19
+ "aria-relevant": ariaRelevant,
20
+ children,
21
+ type = "polite",
22
+ role = ROLES[type],
23
+ regionIdentifier,
24
+ ...regionProps
25
+ } = props;
26
+ const ariaAtomic = ["true", true].includes(regionProps["aria-atomic"]);
27
+ const ownerDocumentRef = React.useRef(document);
28
+ const setOwnerDocumentFromRef = React.useCallback((node) => {
29
+ if (node) {
30
+ ownerDocumentRef.current = node.ownerDocument;
31
+ }
32
+ }, []);
33
+ const ownRef = React.useRef(null);
34
+ const ref = useComposedRefs(forwardedRef, ownRef, setOwnerDocumentFromRef);
35
+ const [region, setRegion] = React.useState();
36
+ const relevant = ariaRelevant ? Array.isArray(ariaRelevant) ? ariaRelevant.join(" ") : ariaRelevant : void 0;
37
+ const getLiveRegionElement = React.useCallback(() => {
38
+ const ownerDocument = ownerDocumentRef.current;
39
+ const regionConfig = { type, role, relevant, id: regionIdentifier, atomic: ariaAtomic };
40
+ const regionSelector = buildSelector(regionConfig);
41
+ const element = ownerDocument.querySelector(regionSelector);
42
+ return element || buildLiveRegionElement(ownerDocument, regionConfig);
43
+ }, [ariaAtomic, relevant, role, type, regionIdentifier]);
44
+ useLayoutEffect(() => {
45
+ setRegion(getLiveRegionElement());
46
+ }, [getLiveRegionElement]);
47
+ React.useEffect(() => {
48
+ const ownerDocument = ownerDocumentRef.current;
49
+ function updateAttributesOnVisibilityChange() {
50
+ regionElement.setAttribute("role", ownerDocument.hidden ? "none" : role);
51
+ regionElement.setAttribute("aria-live", ownerDocument.hidden ? "off" : type);
52
+ }
53
+ const regionElement = getLiveRegionElement();
54
+ if (!listenerMap.get(regionElement)) {
55
+ ownerDocument.addEventListener("visibilitychange", updateAttributesOnVisibilityChange);
56
+ listenerMap.set(regionElement, 1);
57
+ } else {
58
+ const announceCount = listenerMap.get(regionElement);
59
+ listenerMap.set(regionElement, announceCount + 1);
60
+ }
61
+ return function() {
62
+ const announceCount = listenerMap.get(regionElement);
63
+ listenerMap.set(regionElement, announceCount - 1);
64
+ if (announceCount === 1) {
65
+ ownerDocument.removeEventListener("visibilitychange", updateAttributesOnVisibilityChange);
66
+ }
67
+ };
68
+ }, [getLiveRegionElement, role, type]);
69
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
70
+ /* @__PURE__ */ jsx(Primitive.div, { ...regionProps, ref, children }),
71
+ region && ReactDOM.createPortal(/* @__PURE__ */ jsx("div", { children }), region)
72
+ ] });
73
+ });
74
+ Announce.displayName = NAME;
75
+ function buildLiveRegionElement(ownerDocument, { type, relevant, role, atomic, id }) {
76
+ const element = ownerDocument.createElement("div");
77
+ element.setAttribute(getLiveRegionPartDataAttr(id), "");
78
+ element.setAttribute(
79
+ "style",
80
+ "position: absolute; top: -1px; width: 1px; height: 1px; overflow: hidden;"
81
+ );
82
+ ownerDocument.body.appendChild(element);
83
+ element.setAttribute("aria-live", type);
84
+ element.setAttribute("aria-atomic", String(atomic || false));
85
+ element.setAttribute("role", role);
86
+ if (relevant) {
87
+ element.setAttribute("aria-relevant", relevant);
88
+ }
89
+ return element;
90
+ }
91
+ function buildSelector({ type, relevant, role, atomic, id }) {
92
+ return `[${getLiveRegionPartDataAttr(id)}]${[
93
+ ["aria-live", type],
94
+ ["aria-atomic", atomic],
95
+ ["aria-relevant", relevant],
96
+ ["role", role]
97
+ ].filter(([, val]) => !!val).map(([attr, val]) => `[${attr}=${val}]`).join("")}`;
98
+ }
99
+ function getLiveRegionPartDataAttr(id) {
100
+ return "data-huin-core-announce-region" + (id ? `-${id}` : "");
101
+ }
102
+ var Root = Announce;
103
+ export {
104
+ Announce,
105
+ Root
106
+ };
107
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/Announce.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport ReactDOM from 'react-dom';\nimport { useComposedRefs } from '@huin-core/react-compose-refs';\nimport { Primitive } from '@huin-core/react-primitive';\nimport { useLayoutEffect } from '@huin-core/react-use-layout-effect';\n\ntype RegionType = 'polite' | 'assertive' | 'off';\ntype RegionRole = 'status' | 'alert' | 'log' | 'none';\n\nconst ROLES: { [key in RegionType]: RegionRole } = {\n polite: 'status',\n assertive: 'alert',\n off: 'none',\n};\n\nconst listenerMap = new Map<Element, number>();\n\n/* -------------------------------------------------------------------------------------------------\n * Announce\n * -----------------------------------------------------------------------------------------------*/\n\nconst NAME = 'Announce';\n\ntype AnnounceElement = React.ElementRef<typeof Primitive.div>;\ntype PrimitiveDivProps = React.ComponentPropsWithoutRef<typeof Primitive.div>;\ninterface AnnounceProps extends PrimitiveDivProps {\n /**\n * Mirrors the `aria-atomic` DOM attribute for live regions. It is an optional attribute that\n * indicates whether assistive technologies will present all, or only parts of, the changed region\n * based on the change notifications defined by the `aria-relevant` attribute.\n *\n * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-atomic\n * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html\n */\n 'aria-atomic'?: boolean;\n /**\n * Mirrors the `aria-relevant` DOM attribute for live regions. It is an optional attribute used to\n * describe what types of changes have occurred to the region, and which changes are relevant and\n * should be announced. Any change that is not relevant acts in the same manner it would if the\n * `aria-live` attribute were set to off.\n *\n * Unfortunately, `aria-relevant` doesn't behave as expected across all device/screen reader\n * combinations. It's important to test its implementation before relying on it to work for your\n * users. The attribute is omitted by default.\n *\n * @see WAI-ARIA https://www.w3.org/TR/wai-aria-1.2/#aria-relevant\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-relevant_attribute\n * @see Opinion https://medium.com/dev-channel/why-authors-should-avoid-aria-relevant-5d3164fab1e3\n * @see Demo http://pauljadam.com/demos/aria-atomic-relevant.html\n */\n 'aria-relevant'?: PrimitiveDivProps['aria-relevant'];\n /**\n * React children of your component. Children can be mirrored directly or modified to optimize for\n * screen reader user experience.\n */\n children: React.ReactNode;\n /**\n * An optional unique identifier for the live region.\n *\n * By default, `Announce` components create, at most, two unique `aria-live` regions in the\n * document (one for all `polite` notifications, one for all `assertive` notifications). In some\n * cases you may wish to append additional `aria-live` regions for distinct purposes (for example,\n * simple status updates may need to be separated from a stack of toast-style notifications). By\n * passing an id, you indicate that any content rendered by components with the same identifier\n * should be mirrored in a separate `aria-live` region.\n */\n regionIdentifier?: string;\n /**\n * Mirrors the `role` DOM attribute. This is optional and may be useful as an override in some\n * cases. By default, the role is determined by the `type` prop.\n *\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles\n */\n role?: RegionRole;\n /**\n * Mirrors the `aria-live` DOM attribute. The `aria-live=POLITENESS_SETTING` is used to set the\n * priority with which screen reader should treat updates to live regions. Its possible settings\n * are: off, polite or assertive. Defaults to `polite`.\n *\n * @see MDN https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions\n */\n type?: RegionType;\n}\n\nconst Announce = React.forwardRef<AnnounceElement, AnnounceProps>((props, forwardedRef) => {\n const {\n 'aria-relevant': ariaRelevant,\n children,\n type = 'polite',\n role = ROLES[type],\n regionIdentifier,\n ...regionProps\n } = props;\n\n const ariaAtomic = ['true', true].includes(regionProps['aria-atomic'] as any);\n\n // The region is appended to the root document node, which is usually the global `document` but in\n // some contexts may be another node. After the Announce element ref is attached, we set the\n // ownerDocumentRef to make sure we have the right root node. We should only need to do this once.\n const ownerDocumentRef = React.useRef(document);\n const setOwnerDocumentFromRef = React.useCallback((node: HTMLDivElement) => {\n if (node) {\n ownerDocumentRef.current = node.ownerDocument;\n }\n }, []);\n const ownRef = React.useRef<HTMLDivElement | null>(null);\n const ref = useComposedRefs(forwardedRef, ownRef, setOwnerDocumentFromRef);\n\n const [region, setRegion] = React.useState<HTMLElement>();\n const relevant = ariaRelevant\n ? Array.isArray(ariaRelevant)\n ? ariaRelevant.join(' ')\n : ariaRelevant\n : undefined;\n\n const getLiveRegionElement = React.useCallback(() => {\n const ownerDocument = ownerDocumentRef.current;\n const regionConfig = { type, role, relevant, id: regionIdentifier, atomic: ariaAtomic };\n const regionSelector = buildSelector(regionConfig);\n const element = ownerDocument.querySelector(regionSelector);\n\n return element || buildLiveRegionElement(ownerDocument, regionConfig);\n }, [ariaAtomic, relevant, role, type, regionIdentifier]);\n\n useLayoutEffect(() => {\n setRegion(getLiveRegionElement() as HTMLElement);\n }, [getLiveRegionElement]);\n\n // In some screen reader/browser combinations, alerts coming from an inactive browser tab may be\n // announced, which is a confusing experience for a user interacting with a completely different\n // page. When the page visibility changes we'll update the `role` and `aria-live` attributes of\n // our region element to prevent that.\n // https://inclusive-components.design/notifications/#restrictingmessagestocontexts\n React.useEffect(() => {\n const ownerDocument = ownerDocumentRef.current;\n function updateAttributesOnVisibilityChange() {\n regionElement.setAttribute('role', ownerDocument.hidden ? 'none' : role);\n regionElement.setAttribute('aria-live', ownerDocument.hidden ? 'off' : type);\n }\n\n // Ok, so this might look a little weird and confusing, but here's what's going on:\n // - We need to hide `aria-live` regions via a global event listener, as noted in the comment\n // above.\n // - We only need one listener per region. Keep in mind that each `Announce` does not\n // necessarily generate a unique live region element.\n // - We track whether or not a listener has already been attached for a given region in a map\n // so we can skip these effects after `Announce` is used again with a shared live region.\n const regionElement = getLiveRegionElement();\n\n if (!listenerMap.get(regionElement)) {\n ownerDocument.addEventListener('visibilitychange', updateAttributesOnVisibilityChange);\n listenerMap.set(regionElement, 1);\n } else {\n const announceCount = listenerMap.get(regionElement)!;\n listenerMap.set(regionElement, announceCount + 1);\n }\n\n return function () {\n const announceCount = listenerMap.get(regionElement)!;\n listenerMap.set(regionElement, announceCount - 1);\n if (announceCount === 1) {\n ownerDocument.removeEventListener('visibilitychange', updateAttributesOnVisibilityChange);\n }\n };\n }, [getLiveRegionElement, role, type]);\n\n return (\n <React.Fragment>\n <Primitive.div {...regionProps} ref={ref}>\n {children}\n </Primitive.div>\n\n {/* portal into live region for screen reader announcements */}\n {region && ReactDOM.createPortal(<div>{children}</div>, region)}\n </React.Fragment>\n );\n});\n\nAnnounce.displayName = NAME;\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype LiveRegionOptions = {\n type: string;\n relevant?: string;\n role: string;\n atomic?: boolean;\n id?: string;\n};\n\nfunction buildLiveRegionElement(\n ownerDocument: Document,\n { type, relevant, role, atomic, id }: LiveRegionOptions\n) {\n const element = ownerDocument.createElement('div');\n element.setAttribute(getLiveRegionPartDataAttr(id), '');\n element.setAttribute(\n 'style',\n 'position: absolute; top: -1px; width: 1px; height: 1px; overflow: hidden;'\n );\n ownerDocument.body.appendChild(element);\n\n element.setAttribute('aria-live', type);\n element.setAttribute('aria-atomic', String(atomic || false));\n element.setAttribute('role', role);\n if (relevant) {\n element.setAttribute('aria-relevant', relevant);\n }\n\n return element;\n}\n\nfunction buildSelector({ type, relevant, role, atomic, id }: LiveRegionOptions) {\n return `[${getLiveRegionPartDataAttr(id)}]${[\n ['aria-live', type],\n ['aria-atomic', atomic],\n ['aria-relevant', relevant],\n ['role', role],\n ]\n .filter(([, val]) => !!val)\n .map(([attr, val]) => `[${attr}=${val}]`)\n .join('')}`;\n}\n\nfunction getLiveRegionPartDataAttr(id?: string) {\n return 'data-huin-core-announce-region' + (id ? `-${id}` : '');\n}\n\nconst Root = Announce;\n\nexport {\n Announce,\n //\n Root,\n};\nexport type { AnnounceProps };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huin-core/react-announce",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": {