@dnd-kit/accessibility 1.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,75 @@
1
1
  # @dnd-kit/accessibility
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`a9d92cf`](https://github.com/clauderic/dnd-kit/commit/a9d92cf1fa35dd957e6c5915a13dfd2af134c103) [#174](https://github.com/clauderic/dnd-kit/pull/174) Thanks [@clauderic](https://github.com/clauderic)! - Distributed assets now only target modern browsers. [Browserlist](https://github.com/browserslist/browserslist) config:
8
+
9
+ ```
10
+ defaults
11
+ last 2 version
12
+ not IE 11
13
+ not dead
14
+ ```
15
+
16
+ If you need to support older browsers, include the appropriate polyfills in your project's build process.
17
+
18
+ ### Patch Changes
19
+
20
+ - [`b406cb9`](https://github.com/clauderic/dnd-kit/commit/b406cb9251beef8677d05c45ec42bab7581a86dc) [#187](https://github.com/clauderic/dnd-kit/pull/187) Thanks [@clauderic](https://github.com/clauderic)! - Introduced the `useDndMonitor` hook. The `useDndMonitor` hook can be used within components wrapped in a `DndContext` provider to monitor the different drag and drop events that happen for that `DndContext`.
21
+
22
+ Example usage:
23
+
24
+ ```tsx
25
+ import {DndContext, useDndMonitor} from '@dnd-kit/core';
26
+
27
+ function App() {
28
+ return (
29
+ <DndContext>
30
+ <Component />
31
+ </DndContext>
32
+ );
33
+ }
34
+
35
+ function Component() {
36
+ useDndMonitor({
37
+ onDragStart(event) {},
38
+ onDragMove(event) {},
39
+ onDragOver(event) {},
40
+ onDragEnd(event) {},
41
+ onDragCancel(event) {},
42
+ });
43
+ }
44
+ ```
45
+
46
+ ## 2.0.0
47
+
48
+ ### Major Changes
49
+
50
+ - [`2833337`](https://github.com/clauderic/dnd-kit/commit/2833337043719853902c3989dfcd5b55ae9ddc73) [#186](https://github.com/clauderic/dnd-kit/pull/186) Thanks [@clauderic](https://github.com/clauderic)! - Simplify `useAnnouncement` hook to only return a single `announcement` rather than `entries`. Similarly, the `LiveRegion` component now only accepts a single `announcement` rather than `entries.
51
+
52
+ - The current strategy used in the useAnnouncement hook is needlessly complex. It's not actually necessary to render multiple announcements at once within the LiveRegion component. It's sufficient to render a single announcement at a time. It's also un-necessary to clean up the announcements after they have been announced, especially now that the role="status" attribute has been added to LiveRegion, keeping the last announcement rendered means users can refer to the last status.
53
+
54
+ ### Patch Changes
55
+
56
+ - [`c24bdb3`](https://github.com/clauderic/dnd-kit/commit/c24bdb3723f1e3e4c474439f837a19c6d48059fb) [#184](https://github.com/clauderic/dnd-kit/pull/184) Thanks [@clauderic](https://github.com/clauderic)! - Tweaked LiveRegion component:
57
+ - Entries are now rendered without wrapper `span` elements. Having wrapper `span` elements causes VoiceOver on macOS to try to move the VoiceOver cursor to the live region, which interferes with scrolling. This issue is not exhibited when rendering announcement entries as plain text without wrapper spans.
58
+ - Added the `role="status"` attribute to the LiveRegion wrapper element.
59
+ - Added the `white-space: no-wrap;` property to ensure that text does not wrap.
60
+
61
+ ## 1.0.2
62
+
63
+ ### Patch Changes
64
+
65
+ - [`423610c`](https://github.com/clauderic/dnd-kit/commit/423610ca48c5e5ca95545fdb5c5cfcfbd3d233ba) [#56](https://github.com/clauderic/dnd-kit/pull/56) Thanks [@clauderic](https://github.com/clauderic)! - Add MIT license to package.json and distributed files
66
+
67
+ ## 1.0.1
68
+
69
+ ### Patch Changes
70
+
71
+ - [`310bbd6`](https://github.com/clauderic/dnd-kit/commit/310bbd6370e85f8fb16cad149e6254600a5beb3a) [#37](https://github.com/clauderic/dnd-kit/pull/37) Thanks [@nickpresta](https://github.com/nickpresta)! - Fix typo in package.json repository URL
72
+
3
73
  ## 1.0.0
4
74
 
5
75
  ### Major Changes
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021, Claudéric Demers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -7,19 +7,20 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
7
7
  var React = require('react');
8
8
  var React__default = _interopDefault(React);
9
9
 
10
- var hiddenStyles = {
10
+ const hiddenStyles = {
11
11
  display: 'none'
12
12
  };
13
- function HiddenText(_ref) {
14
- var id = _ref.id,
15
- value = _ref.value;
13
+ function HiddenText({
14
+ id,
15
+ value
16
+ }) {
16
17
  return React__default.createElement("div", {
17
18
  id: id,
18
19
  style: hiddenStyles
19
20
  }, value);
20
21
  }
21
22
 
22
- var visuallyHidden = {
23
+ const visuallyHidden = {
23
24
  position: 'absolute',
24
25
  width: 1,
25
26
  height: 1,
@@ -28,64 +29,32 @@ var visuallyHidden = {
28
29
  padding: 0,
29
30
  overflow: 'hidden',
30
31
  clip: 'rect(0 0 0 0)',
31
- clipPath: 'inset(100%)'
32
+ clipPath: 'inset(100%)',
33
+ whiteSpace: 'nowrap'
32
34
  };
33
- function LiveRegion(_ref) {
34
- var id = _ref.id,
35
- entries = _ref.entries;
35
+ function LiveRegion({
36
+ id,
37
+ announcement
38
+ }) {
36
39
  return React__default.createElement("div", {
37
40
  id: id,
38
41
  style: visuallyHidden,
42
+ role: "status",
39
43
  "aria-live": "assertive",
40
- "aria-relevant": "additions",
41
44
  "aria-atomic": true
42
- }, entries.map(function (_ref2) {
43
- var id = _ref2[0],
44
- entry = _ref2[1];
45
- return React__default.createElement("span", {
46
- key: id.toString()
47
- }, entry);
48
- }));
45
+ }, announcement);
49
46
  }
50
47
 
51
- var timeout = 1e3; // 1 second
52
-
53
48
  function useAnnouncement() {
54
- var _useState = React.useState(new Map()),
55
- announcementMap = _useState[0],
56
- setAnnouncements = _useState[1];
57
-
58
- var announce = React.useCallback(function (announcement) {
59
- setAnnouncements(function (announcements) {
60
- var timeoutId = setTimeout(function () {
61
- setAnnouncements(function (announcements) {
62
- announcements["delete"](timeoutId);
63
- return new Map(announcements);
64
- });
65
- }, timeout);
66
- announcements.set(timeoutId, announcement);
67
- return new Map(announcements);
68
- });
69
- }, []);
70
- var announcementMapRef = React.useRef(announcementMap);
71
- var entries = React.useMemo(function () {
72
- return Array.from(announcementMap.entries());
73
- }, [announcementMap]);
74
- React.useEffect(function () {
75
- announcementMapRef.current = announcementMap;
76
- }, [announcementMap]);
77
- React.useEffect(function () {
78
- return function () {
79
- // Clean up any queued `setTimeout` calls on unmount
80
- // eslint-disable-next-line react-hooks/exhaustive-deps
81
- announcementMapRef.current.forEach(function (_, key) {
82
- clearTimeout(key);
83
- });
84
- };
49
+ const [announcement, setAnnouncement] = React.useState('');
50
+ const announce = React.useCallback(value => {
51
+ if (value != null) {
52
+ setAnnouncement(value);
53
+ }
85
54
  }, []);
86
55
  return {
87
- announce: announce,
88
- entries: entries
56
+ announce,
57
+ announcement
89
58
  };
90
59
  }
91
60
 
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility.cjs.development.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n entries: [NodeJS.Timeout, string][];\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n};\n\nexport function LiveRegion({id, entries}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n aria-live=\"assertive\"\n aria-relevant=\"additions\"\n aria-atomic\n >\n {entries.map(([id, entry]) => (\n <span key={id.toString()}>{entry}</span>\n ))}\n </div>\n );\n}\n","import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nconst timeout = 1e3; // 1 second\n\nexport function useAnnouncement() {\n const [announcementMap, setAnnouncements] = useState(\n new Map<NodeJS.Timeout, string>()\n );\n const announce = useCallback((announcement: string) => {\n setAnnouncements((announcements) => {\n const timeoutId = setTimeout(() => {\n setAnnouncements((announcements) => {\n announcements.delete(timeoutId);\n\n return new Map(announcements);\n });\n }, timeout);\n\n announcements.set(timeoutId, announcement);\n\n return new Map(announcements);\n });\n }, []);\n const announcementMapRef = useRef(announcementMap);\n const entries = useMemo(() => Array.from(announcementMap.entries()), [\n announcementMap,\n ]);\n\n useEffect(() => {\n announcementMapRef.current = announcementMap;\n }, [announcementMap]);\n\n useEffect(() => {\n return () => {\n // Clean up any queued `setTimeout` calls on unmount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n announcementMapRef.current.forEach((_, key) => {\n clearTimeout(key);\n });\n };\n }, []);\n\n return {announce, entries} as const;\n}\n"],"names":["hiddenStyles","display","HiddenText","id","value","React","style","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","LiveRegion","entries","map","entry","key","toString","timeout","useAnnouncement","useState","Map","announcementMap","setAnnouncements","announce","useCallback","announcement","announcements","timeoutId","setTimeout","set","announcementMapRef","useRef","useMemo","Array","from","useEffect","current","forEach","_","clearTimeout"],"mappings":";;;;;;;;;AAOA,IAAMA,YAAY,GAAwB;AACxCC,EAAAA,OAAO,EAAE;AAD+B,CAA1C;SAIgBC;MAAYC,UAAAA;MAAIC,aAAAA;AAC9B,SACEC,4BAAA,MAAA;AAAKF,IAAAA,EAAE,EAAEA;AAAIG,IAAAA,KAAK,EAAEN;GAApB,EACGI,KADH,CADF;AAKD;;ACTD,IAAMG,cAAc,GAAwB;AAC1CC,EAAAA,QAAQ,EAAE,UADgC;AAE1CC,EAAAA,KAAK,EAAE,CAFmC;AAG1CC,EAAAA,MAAM,EAAE,CAHkC;AAI1CC,EAAAA,MAAM,EAAE,CAAC,CAJiC;AAK1CC,EAAAA,MAAM,EAAE,CALkC;AAM1CC,EAAAA,OAAO,EAAE,CANiC;AAO1CC,EAAAA,QAAQ,EAAE,QAPgC;AAQ1CC,EAAAA,IAAI,EAAE,eARoC;AAS1CC,EAAAA,QAAQ,EAAE;AATgC,CAA5C;AAYA,SAAgBC;MAAYd,UAAAA;MAAIe,eAAAA;AAC9B,SACEb,4BAAA,MAAA;AACEF,IAAAA,EAAE,EAAEA;AACJG,IAAAA,KAAK,EAAEC;iBACG;qBACI;;GAJhB,EAOGW,OAAO,CAACC,GAAR,CAAY;AAAA,QAAEhB,EAAF;AAAA,QAAMiB,KAAN;AAAA,WACXf,4BAAA,OAAA;AAAMgB,MAAAA,GAAG,EAAElB,EAAE,CAACmB,QAAH;KAAX,EAA2BF,KAA3B,CADW;AAAA,GAAZ,CAPH,CADF;AAaD;;AChCD,IAAMG,OAAO,GAAG,GAAhB;;AAEA,SAAgBC;kBAC8BC,cAAQ,CAClD,IAAIC,GAAJ,EADkD;MAA7CC;MAAiBC;;AAGxB,MAAMC,QAAQ,GAAGC,iBAAW,CAAC,UAACC,YAAD;AAC3BH,IAAAA,gBAAgB,CAAC,UAACI,aAAD;AACf,UAAMC,SAAS,GAAGC,UAAU,CAAC;AAC3BN,QAAAA,gBAAgB,CAAC,UAACI,aAAD;AACfA,UAAAA,aAAa,UAAb,CAAqBC,SAArB;AAEA,iBAAO,IAAIP,GAAJ,CAAQM,aAAR,CAAP;AACD,SAJe,CAAhB;AAKD,OAN2B,EAMzBT,OANyB,CAA5B;AAQAS,MAAAA,aAAa,CAACG,GAAd,CAAkBF,SAAlB,EAA6BF,YAA7B;AAEA,aAAO,IAAIL,GAAJ,CAAQM,aAAR,CAAP;AACD,KAZe,CAAhB;AAaD,GAd2B,EAczB,EAdyB,CAA5B;AAeA,MAAMI,kBAAkB,GAAGC,YAAM,CAACV,eAAD,CAAjC;AACA,MAAMT,OAAO,GAAGoB,aAAO,CAAC;AAAA,WAAMC,KAAK,CAACC,IAAN,CAAWb,eAAe,CAACT,OAAhB,EAAX,CAAN;AAAA,GAAD,EAA8C,CACnES,eADmE,CAA9C,CAAvB;AAIAc,EAAAA,eAAS,CAAC;AACRL,IAAAA,kBAAkB,CAACM,OAAnB,GAA6Bf,eAA7B;AACD,GAFQ,EAEN,CAACA,eAAD,CAFM,CAAT;AAIAc,EAAAA,eAAS,CAAC;AACR,WAAO;AACL;AACA;AACAL,MAAAA,kBAAkB,CAACM,OAAnB,CAA2BC,OAA3B,CAAmC,UAACC,CAAD,EAAIvB,GAAJ;AACjCwB,QAAAA,YAAY,CAACxB,GAAD,CAAZ;AACD,OAFD;AAGD,KAND;AAOD,GARQ,EAQN,EARM,CAAT;AAUA,SAAO;AAACQ,IAAAA,QAAQ,EAARA,QAAD;AAAWX,IAAAA,OAAO,EAAPA;AAAX,GAAP;AACD;;;;;;"}
1
+ {"version":3,"file":"accessibility.cjs.development.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n announcement: string;\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n whiteSpace: 'nowrap',\n};\n\nexport function LiveRegion({id, announcement}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n role=\"status\"\n aria-live=\"assertive\"\n aria-atomic\n >\n {announcement}\n </div>\n );\n}\n","import {useCallback, useState} from 'react';\n\nexport function useAnnouncement() {\n const [announcement, setAnnouncement] = useState('');\n const announce = useCallback((value: string | undefined) => {\n if (value != null) {\n setAnnouncement(value);\n }\n }, []);\n\n return {announce, announcement} as const;\n}\n"],"names":["hiddenStyles","display","HiddenText","id","value","React","style","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","whiteSpace","LiveRegion","announcement","role","useAnnouncement","setAnnouncement","useState","announce","useCallback"],"mappings":";;;;;;;;;AAOA,MAAMA,YAAY,GAAwB;AACxCC,EAAAA,OAAO,EAAE;AAD+B,CAA1C;SAIgBC,WAAW;AAACC,EAAAA,EAAD;AAAKC,EAAAA;AAAL;AACzB,SACEC,4BAAA,MAAA;AAAKF,IAAAA,EAAE,EAAEA;AAAIG,IAAAA,KAAK,EAAEN;GAApB,EACGI,KADH,CADF;AAKD;;ACTD,MAAMG,cAAc,GAAwB;AAC1CC,EAAAA,QAAQ,EAAE,UADgC;AAE1CC,EAAAA,KAAK,EAAE,CAFmC;AAG1CC,EAAAA,MAAM,EAAE,CAHkC;AAI1CC,EAAAA,MAAM,EAAE,CAAC,CAJiC;AAK1CC,EAAAA,MAAM,EAAE,CALkC;AAM1CC,EAAAA,OAAO,EAAE,CANiC;AAO1CC,EAAAA,QAAQ,EAAE,QAPgC;AAQ1CC,EAAAA,IAAI,EAAE,eARoC;AAS1CC,EAAAA,QAAQ,EAAE,aATgC;AAU1CC,EAAAA,UAAU,EAAE;AAV8B,CAA5C;AAaA,SAAgBC,WAAW;AAACf,EAAAA,EAAD;AAAKgB,EAAAA;AAAL;AACzB,SACEd,4BAAA,MAAA;AACEF,IAAAA,EAAE,EAAEA;AACJG,IAAAA,KAAK,EAAEC;AACPa,IAAAA,IAAI,EAAC;iBACK;;GAJZ,EAOGD,YAPH,CADF;AAWD;;SC/BeE;AACd,QAAM,CAACF,YAAD,EAAeG,eAAf,IAAkCC,cAAQ,CAAC,EAAD,CAAhD;AACA,QAAMC,QAAQ,GAAGC,iBAAW,CAAErB,KAAD;AAC3B,QAAIA,KAAK,IAAI,IAAb,EAAmB;AACjBkB,MAAAA,eAAe,CAAClB,KAAD,CAAf;AACD;AACF,GAJ2B,EAIzB,EAJyB,CAA5B;AAMA,SAAO;AAACoB,IAAAA,QAAD;AAAWL,IAAAA;AAAX,GAAP;AACD;;;;;;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,r={display:"none"},i={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)"};exports.HiddenText=function(e){return n.createElement("div",{id:e.id,style:r},e.value)},exports.LiveRegion=function(e){return n.createElement("div",{id:e.id,style:i,"aria-live":"assertive","aria-relevant":"additions","aria-atomic":!0},e.entries.map((function(e){var t=e[1];return n.createElement("span",{key:e[0].toString()},t)})))},exports.useAnnouncement=function(){var e=t.useState(new Map),n=e[0],r=e[1],i=t.useCallback((function(e){r((function(t){var n=setTimeout((function(){r((function(e){return e.delete(n),new Map(e)}))}),1e3);return t.set(n,e),new Map(t)}))}),[]),u=t.useRef(n),a=t.useMemo((function(){return Array.from(n.entries())}),[n]);return t.useEffect((function(){u.current=n}),[n]),t.useEffect((function(){return function(){u.current.forEach((function(e,t){clearTimeout(t)}))}}),[]),{announce:i,entries:a}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e;const i={display:"none"},r={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};exports.HiddenText=function({id:e,value:t}){return n.createElement("div",{id:e,style:i},t)},exports.LiveRegion=function({id:e,announcement:t}){return n.createElement("div",{id:e,style:r,role:"status","aria-live":"assertive","aria-atomic":!0},t)},exports.useAnnouncement=function(){const[e,n]=t.useState("");return{announce:t.useCallback(e=>{null!=e&&n(e)},[]),announcement:e}};
2
2
  //# sourceMappingURL=accessibility.cjs.production.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility.cjs.production.min.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n entries: [NodeJS.Timeout, string][];\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n};\n\nexport function LiveRegion({id, entries}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n aria-live=\"assertive\"\n aria-relevant=\"additions\"\n aria-atomic\n >\n {entries.map(([id, entry]) => (\n <span key={id.toString()}>{entry}</span>\n ))}\n </div>\n );\n}\n","import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nconst timeout = 1e3; // 1 second\n\nexport function useAnnouncement() {\n const [announcementMap, setAnnouncements] = useState(\n new Map<NodeJS.Timeout, string>()\n );\n const announce = useCallback((announcement: string) => {\n setAnnouncements((announcements) => {\n const timeoutId = setTimeout(() => {\n setAnnouncements((announcements) => {\n announcements.delete(timeoutId);\n\n return new Map(announcements);\n });\n }, timeout);\n\n announcements.set(timeoutId, announcement);\n\n return new Map(announcements);\n });\n }, []);\n const announcementMapRef = useRef(announcementMap);\n const entries = useMemo(() => Array.from(announcementMap.entries()), [\n announcementMap,\n ]);\n\n useEffect(() => {\n announcementMapRef.current = announcementMap;\n }, [announcementMap]);\n\n useEffect(() => {\n return () => {\n // Clean up any queued `setTimeout` calls on unmount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n announcementMapRef.current.forEach((_, key) => {\n clearTimeout(key);\n });\n };\n }, []);\n\n return {announce, entries} as const;\n}\n"],"names":["hiddenStyles","display","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","React","id","style","value","entries","map","entry","key","toString","useState","Map","announcementMap","setAnnouncements","announce","useCallback","announcement","announcements","timeoutId","setTimeout","set","announcementMapRef","useRef","useMemo","Array","from","useEffect","current","forEach","_","clearTimeout"],"mappings":"oJAOMA,EAAoC,CACxCC,QAAS,QCALC,EAAsC,CAC1CC,SAAU,WACVC,MAAO,EACPC,OAAQ,EACRC,QAAS,EACTC,OAAQ,EACRC,QAAS,EACTC,SAAU,SACVC,KAAM,gBACNC,SAAU,qDDJRC,uBAAKC,KAFmBA,GAEXC,MAAOd,KAFQe,8CCW5BH,uBACEC,KAHsBA,GAItBC,MAAOZ,cACG,4BACI,gCANYc,QASjBC,KAAI,gBAAMC,cACjBN,wBAAMO,SAAQC,YAAaF,gCC1BnC,iBAC8CG,WAC1C,IAAIC,KADCC,OAAiBC,OAGlBC,EAAWC,eAAY,SAACC,GAC5BH,GAAiB,SAACI,OACVC,EAAYC,YAAW,WAC3BN,GAAiB,SAACI,UAChBA,SAAqBC,GAEd,IAAIP,IAAIM,QAZT,YAgBVA,EAAcG,IAAIF,EAAWF,GAEtB,IAAIL,IAAIM,QAEhB,IACGI,EAAqBC,SAAOV,GAC5BP,EAAUkB,WAAQ,kBAAMC,MAAMC,KAAKb,EAAgBP,aAAY,CACnEO,WAGFc,aAAU,WACRL,EAAmBM,QAAUf,IAC5B,CAACA,IAEJc,aAAU,kBACD,WAGLL,EAAmBM,QAAQC,SAAQ,SAACC,EAAGrB,GACrCsB,aAAatB,SAGhB,IAEI,CAACM,SAAAA,EAAUT,QAAAA"}
1
+ {"version":3,"file":"accessibility.cjs.production.min.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n announcement: string;\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n whiteSpace: 'nowrap',\n};\n\nexport function LiveRegion({id, announcement}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n role=\"status\"\n aria-live=\"assertive\"\n aria-atomic\n >\n {announcement}\n </div>\n );\n}\n","import {useCallback, useState} from 'react';\n\nexport function useAnnouncement() {\n const [announcement, setAnnouncement] = useState('');\n const announce = useCallback((value: string | undefined) => {\n if (value != null) {\n setAnnouncement(value);\n }\n }, []);\n\n return {announce, announcement} as const;\n}\n"],"names":["hiddenStyles","display","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","whiteSpace","id","value","React","style","announcement","role","setAnnouncement","useState","announce","useCallback"],"mappings":"oJAOA,MAAMA,EAAoC,CACxCC,QAAS,QCALC,EAAsC,CAC1CC,SAAU,WACVC,MAAO,EACPC,OAAQ,EACRC,QAAS,EACTC,OAAQ,EACRC,QAAS,EACTC,SAAU,SACVC,KAAM,gBACNC,SAAU,cACVC,WAAY,uCDPaC,GAACA,EAADC,MAAKA,WAE5BC,uBAAKF,GAAIA,EAAIG,MAAOhB,GACjBc,uBCOP,UAA2BD,GAACA,EAADI,aAAKA,WAE5BF,uBACEF,GAAIA,EACJG,MAAOd,EACPgB,KAAK,qBACK,8BAGTD,6CC3BEA,EAAcE,GAAmBC,WAAS,UAO1C,CAACC,SANSC,cAAaR,IACf,MAATA,GACFK,EAAgBL,IAEjB,IAEeG,aAAAA"}
@@ -1,18 +1,19 @@
1
- import React, { useState, useCallback, useRef, useMemo, useEffect } from 'react';
1
+ import React, { useState, useCallback } from 'react';
2
2
 
3
- var hiddenStyles = {
3
+ const hiddenStyles = {
4
4
  display: 'none'
5
5
  };
6
- function HiddenText(_ref) {
7
- var id = _ref.id,
8
- value = _ref.value;
6
+ function HiddenText({
7
+ id,
8
+ value
9
+ }) {
9
10
  return React.createElement("div", {
10
11
  id: id,
11
12
  style: hiddenStyles
12
13
  }, value);
13
14
  }
14
15
 
15
- var visuallyHidden = {
16
+ const visuallyHidden = {
16
17
  position: 'absolute',
17
18
  width: 1,
18
19
  height: 1,
@@ -21,64 +22,32 @@ var visuallyHidden = {
21
22
  padding: 0,
22
23
  overflow: 'hidden',
23
24
  clip: 'rect(0 0 0 0)',
24
- clipPath: 'inset(100%)'
25
+ clipPath: 'inset(100%)',
26
+ whiteSpace: 'nowrap'
25
27
  };
26
- function LiveRegion(_ref) {
27
- var id = _ref.id,
28
- entries = _ref.entries;
28
+ function LiveRegion({
29
+ id,
30
+ announcement
31
+ }) {
29
32
  return React.createElement("div", {
30
33
  id: id,
31
34
  style: visuallyHidden,
35
+ role: "status",
32
36
  "aria-live": "assertive",
33
- "aria-relevant": "additions",
34
37
  "aria-atomic": true
35
- }, entries.map(function (_ref2) {
36
- var id = _ref2[0],
37
- entry = _ref2[1];
38
- return React.createElement("span", {
39
- key: id.toString()
40
- }, entry);
41
- }));
38
+ }, announcement);
42
39
  }
43
40
 
44
- var timeout = 1e3; // 1 second
45
-
46
41
  function useAnnouncement() {
47
- var _useState = useState(new Map()),
48
- announcementMap = _useState[0],
49
- setAnnouncements = _useState[1];
50
-
51
- var announce = useCallback(function (announcement) {
52
- setAnnouncements(function (announcements) {
53
- var timeoutId = setTimeout(function () {
54
- setAnnouncements(function (announcements) {
55
- announcements["delete"](timeoutId);
56
- return new Map(announcements);
57
- });
58
- }, timeout);
59
- announcements.set(timeoutId, announcement);
60
- return new Map(announcements);
61
- });
62
- }, []);
63
- var announcementMapRef = useRef(announcementMap);
64
- var entries = useMemo(function () {
65
- return Array.from(announcementMap.entries());
66
- }, [announcementMap]);
67
- useEffect(function () {
68
- announcementMapRef.current = announcementMap;
69
- }, [announcementMap]);
70
- useEffect(function () {
71
- return function () {
72
- // Clean up any queued `setTimeout` calls on unmount
73
- // eslint-disable-next-line react-hooks/exhaustive-deps
74
- announcementMapRef.current.forEach(function (_, key) {
75
- clearTimeout(key);
76
- });
77
- };
42
+ const [announcement, setAnnouncement] = useState('');
43
+ const announce = useCallback(value => {
44
+ if (value != null) {
45
+ setAnnouncement(value);
46
+ }
78
47
  }, []);
79
48
  return {
80
- announce: announce,
81
- entries: entries
49
+ announce,
50
+ announcement
82
51
  };
83
52
  }
84
53
 
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility.esm.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n entries: [NodeJS.Timeout, string][];\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n};\n\nexport function LiveRegion({id, entries}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n aria-live=\"assertive\"\n aria-relevant=\"additions\"\n aria-atomic\n >\n {entries.map(([id, entry]) => (\n <span key={id.toString()}>{entry}</span>\n ))}\n </div>\n );\n}\n","import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nconst timeout = 1e3; // 1 second\n\nexport function useAnnouncement() {\n const [announcementMap, setAnnouncements] = useState(\n new Map<NodeJS.Timeout, string>()\n );\n const announce = useCallback((announcement: string) => {\n setAnnouncements((announcements) => {\n const timeoutId = setTimeout(() => {\n setAnnouncements((announcements) => {\n announcements.delete(timeoutId);\n\n return new Map(announcements);\n });\n }, timeout);\n\n announcements.set(timeoutId, announcement);\n\n return new Map(announcements);\n });\n }, []);\n const announcementMapRef = useRef(announcementMap);\n const entries = useMemo(() => Array.from(announcementMap.entries()), [\n announcementMap,\n ]);\n\n useEffect(() => {\n announcementMapRef.current = announcementMap;\n }, [announcementMap]);\n\n useEffect(() => {\n return () => {\n // Clean up any queued `setTimeout` calls on unmount\n // eslint-disable-next-line react-hooks/exhaustive-deps\n announcementMapRef.current.forEach((_, key) => {\n clearTimeout(key);\n });\n };\n }, []);\n\n return {announce, entries} as const;\n}\n"],"names":["hiddenStyles","display","HiddenText","id","value","React","style","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","LiveRegion","entries","map","entry","key","toString","timeout","useAnnouncement","useState","Map","announcementMap","setAnnouncements","announce","useCallback","announcement","announcements","timeoutId","setTimeout","set","announcementMapRef","useRef","useMemo","Array","from","useEffect","current","forEach","_","clearTimeout"],"mappings":";;AAOA,IAAMA,YAAY,GAAwB;AACxCC,EAAAA,OAAO,EAAE;AAD+B,CAA1C;SAIgBC;MAAYC,UAAAA;MAAIC,aAAAA;AAC9B,SACEC,mBAAA,MAAA;AAAKF,IAAAA,EAAE,EAAEA;AAAIG,IAAAA,KAAK,EAAEN;GAApB,EACGI,KADH,CADF;AAKD;;ACTD,IAAMG,cAAc,GAAwB;AAC1CC,EAAAA,QAAQ,EAAE,UADgC;AAE1CC,EAAAA,KAAK,EAAE,CAFmC;AAG1CC,EAAAA,MAAM,EAAE,CAHkC;AAI1CC,EAAAA,MAAM,EAAE,CAAC,CAJiC;AAK1CC,EAAAA,MAAM,EAAE,CALkC;AAM1CC,EAAAA,OAAO,EAAE,CANiC;AAO1CC,EAAAA,QAAQ,EAAE,QAPgC;AAQ1CC,EAAAA,IAAI,EAAE,eARoC;AAS1CC,EAAAA,QAAQ,EAAE;AATgC,CAA5C;AAYA,SAAgBC;MAAYd,UAAAA;MAAIe,eAAAA;AAC9B,SACEb,mBAAA,MAAA;AACEF,IAAAA,EAAE,EAAEA;AACJG,IAAAA,KAAK,EAAEC;iBACG;qBACI;;GAJhB,EAOGW,OAAO,CAACC,GAAR,CAAY;AAAA,QAAEhB,EAAF;AAAA,QAAMiB,KAAN;AAAA,WACXf,mBAAA,OAAA;AAAMgB,MAAAA,GAAG,EAAElB,EAAE,CAACmB,QAAH;KAAX,EAA2BF,KAA3B,CADW;AAAA,GAAZ,CAPH,CADF;AAaD;;AChCD,IAAMG,OAAO,GAAG,GAAhB;;AAEA,SAAgBC;kBAC8BC,QAAQ,CAClD,IAAIC,GAAJ,EADkD;MAA7CC;MAAiBC;;AAGxB,MAAMC,QAAQ,GAAGC,WAAW,CAAC,UAACC,YAAD;AAC3BH,IAAAA,gBAAgB,CAAC,UAACI,aAAD;AACf,UAAMC,SAAS,GAAGC,UAAU,CAAC;AAC3BN,QAAAA,gBAAgB,CAAC,UAACI,aAAD;AACfA,UAAAA,aAAa,UAAb,CAAqBC,SAArB;AAEA,iBAAO,IAAIP,GAAJ,CAAQM,aAAR,CAAP;AACD,SAJe,CAAhB;AAKD,OAN2B,EAMzBT,OANyB,CAA5B;AAQAS,MAAAA,aAAa,CAACG,GAAd,CAAkBF,SAAlB,EAA6BF,YAA7B;AAEA,aAAO,IAAIL,GAAJ,CAAQM,aAAR,CAAP;AACD,KAZe,CAAhB;AAaD,GAd2B,EAczB,EAdyB,CAA5B;AAeA,MAAMI,kBAAkB,GAAGC,MAAM,CAACV,eAAD,CAAjC;AACA,MAAMT,OAAO,GAAGoB,OAAO,CAAC;AAAA,WAAMC,KAAK,CAACC,IAAN,CAAWb,eAAe,CAACT,OAAhB,EAAX,CAAN;AAAA,GAAD,EAA8C,CACnES,eADmE,CAA9C,CAAvB;AAIAc,EAAAA,SAAS,CAAC;AACRL,IAAAA,kBAAkB,CAACM,OAAnB,GAA6Bf,eAA7B;AACD,GAFQ,EAEN,CAACA,eAAD,CAFM,CAAT;AAIAc,EAAAA,SAAS,CAAC;AACR,WAAO;AACL;AACA;AACAL,MAAAA,kBAAkB,CAACM,OAAnB,CAA2BC,OAA3B,CAAmC,UAACC,CAAD,EAAIvB,GAAJ;AACjCwB,QAAAA,YAAY,CAACxB,GAAD,CAAZ;AACD,OAFD;AAGD,KAND;AAOD,GARQ,EAQN,EARM,CAAT;AAUA,SAAO;AAACQ,IAAAA,QAAQ,EAARA,QAAD;AAAWX,IAAAA,OAAO,EAAPA;AAAX,GAAP;AACD;;;;"}
1
+ {"version":3,"file":"accessibility.esm.js","sources":["../src/components/HiddenText/HiddenText.tsx","../src/components/LiveRegion/LiveRegion.tsx","../src/hooks/useAnnouncement.ts"],"sourcesContent":["import React from 'react';\n\ninterface Props {\n id: string;\n value: string;\n}\n\nconst hiddenStyles: React.CSSProperties = {\n display: 'none',\n};\n\nexport function HiddenText({id, value}: Props) {\n return (\n <div id={id} style={hiddenStyles}>\n {value}\n </div>\n );\n}\n","import React from 'react';\n\nexport interface Props {\n id: string;\n announcement: string;\n}\n\n// Hide element visually but keep it readable by screen readers\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(100%)',\n whiteSpace: 'nowrap',\n};\n\nexport function LiveRegion({id, announcement}: Props) {\n return (\n <div\n id={id}\n style={visuallyHidden}\n role=\"status\"\n aria-live=\"assertive\"\n aria-atomic\n >\n {announcement}\n </div>\n );\n}\n","import {useCallback, useState} from 'react';\n\nexport function useAnnouncement() {\n const [announcement, setAnnouncement] = useState('');\n const announce = useCallback((value: string | undefined) => {\n if (value != null) {\n setAnnouncement(value);\n }\n }, []);\n\n return {announce, announcement} as const;\n}\n"],"names":["hiddenStyles","display","HiddenText","id","value","React","style","visuallyHidden","position","width","height","margin","border","padding","overflow","clip","clipPath","whiteSpace","LiveRegion","announcement","role","useAnnouncement","setAnnouncement","useState","announce","useCallback"],"mappings":";;AAOA,MAAMA,YAAY,GAAwB;AACxCC,EAAAA,OAAO,EAAE;AAD+B,CAA1C;SAIgBC,WAAW;AAACC,EAAAA,EAAD;AAAKC,EAAAA;AAAL;AACzB,SACEC,mBAAA,MAAA;AAAKF,IAAAA,EAAE,EAAEA;AAAIG,IAAAA,KAAK,EAAEN;GAApB,EACGI,KADH,CADF;AAKD;;ACTD,MAAMG,cAAc,GAAwB;AAC1CC,EAAAA,QAAQ,EAAE,UADgC;AAE1CC,EAAAA,KAAK,EAAE,CAFmC;AAG1CC,EAAAA,MAAM,EAAE,CAHkC;AAI1CC,EAAAA,MAAM,EAAE,CAAC,CAJiC;AAK1CC,EAAAA,MAAM,EAAE,CALkC;AAM1CC,EAAAA,OAAO,EAAE,CANiC;AAO1CC,EAAAA,QAAQ,EAAE,QAPgC;AAQ1CC,EAAAA,IAAI,EAAE,eARoC;AAS1CC,EAAAA,QAAQ,EAAE,aATgC;AAU1CC,EAAAA,UAAU,EAAE;AAV8B,CAA5C;AAaA,SAAgBC,WAAW;AAACf,EAAAA,EAAD;AAAKgB,EAAAA;AAAL;AACzB,SACEd,mBAAA,MAAA;AACEF,IAAAA,EAAE,EAAEA;AACJG,IAAAA,KAAK,EAAEC;AACPa,IAAAA,IAAI,EAAC;iBACK;;GAJZ,EAOGD,YAPH,CADF;AAWD;;SC/BeE;AACd,QAAM,CAACF,YAAD,EAAeG,eAAf,IAAkCC,QAAQ,CAAC,EAAD,CAAhD;AACA,QAAMC,QAAQ,GAAGC,WAAW,CAAErB,KAAD;AAC3B,QAAIA,KAAK,IAAI,IAAb,EAAmB;AACjBkB,MAAAA,eAAe,CAAClB,KAAD,CAAf;AACD;AACF,GAJ2B,EAIzB,EAJyB,CAA5B;AAMA,SAAO;AAACoB,IAAAA,QAAD;AAAWL,IAAAA;AAAX,GAAP;AACD;;;;"}
@@ -1,7 +1,6 @@
1
- /// <reference types="node" />
2
1
  /// <reference types="react" />
3
2
  export interface Props {
4
3
  id: string;
5
- entries: [NodeJS.Timeout, string][];
4
+ announcement: string;
6
5
  }
7
- export declare function LiveRegion({ id, entries }: Props): JSX.Element;
6
+ export declare function LiveRegion({ id, announcement }: Props): JSX.Element;
@@ -1,5 +1,4 @@
1
- /// <reference types="node" />
2
1
  export declare function useAnnouncement(): {
3
- readonly announce: (announcement: string) => void;
4
- readonly entries: [NodeJS.Timeout, string][];
2
+ readonly announce: (value: string | undefined) => void;
3
+ readonly announcement: string;
5
4
  };
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@dnd-kit/accessibility",
3
- "version": "1.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "A generic toolkit to help with accessibility",
5
5
  "author": "Claudéric Demers",
6
+ "license": "MIT",
6
7
  "repository": {
7
8
  "type": "git",
8
- "url": "git+https://github.com/claudric/dnd-kit.git",
9
+ "url": "git+https://github.com/clauderic/dnd-kit.git",
9
10
  "directory": "packages/accessibility"
10
11
  },
11
12
  "scripts": {