@dnd-kit/accessibility
Advanced tools
Comparing version 1.0.2 to 2.0.0
# @dnd-kit/accessibility | ||
## 2.0.0 | ||
### Major Changes | ||
- [`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. | ||
- 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. | ||
### Patch Changes | ||
- [`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: | ||
- 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. | ||
- Added the `role="status"` attribute to the LiveRegion wrapper element. | ||
- Added the `white-space: no-wrap;` property to ensure that text does not wrap. | ||
## 1.0.2 | ||
@@ -4,0 +19,0 @@ |
@@ -31,60 +31,25 @@ 'use strict'; | ||
clip: 'rect(0 0 0 0)', | ||
clipPath: 'inset(100%)' | ||
clipPath: 'inset(100%)', | ||
whiteSpace: 'nowrap' | ||
}; | ||
function LiveRegion(_ref) { | ||
var id = _ref.id, | ||
entries = _ref.entries; | ||
announcement = _ref.announcement; | ||
return React__default.createElement("div", { | ||
id: id, | ||
style: visuallyHidden, | ||
role: "status", | ||
"aria-live": "assertive", | ||
"aria-relevant": "additions", | ||
"aria-atomic": true | ||
}, entries.map(function (_ref2) { | ||
var id = _ref2[0], | ||
entry = _ref2[1]; | ||
return React__default.createElement("span", { | ||
key: id.toString() | ||
}, entry); | ||
})); | ||
}, announcement); | ||
} | ||
var timeout = 1e3; // 1 second | ||
function useAnnouncement() { | ||
var _useState = React.useState(new Map()), | ||
announcementMap = _useState[0], | ||
setAnnouncements = _useState[1]; | ||
var _useState = React.useState(''), | ||
announcement = _useState[0], | ||
setAnnouncement = _useState[1]; | ||
var announce = React.useCallback(function (announcement) { | ||
setAnnouncements(function (announcements) { | ||
var timeoutId = setTimeout(function () { | ||
setAnnouncements(function (announcements) { | ||
announcements["delete"](timeoutId); | ||
return new Map(announcements); | ||
}); | ||
}, timeout); | ||
announcements.set(timeoutId, announcement); | ||
return new Map(announcements); | ||
}); | ||
}, []); | ||
var announcementMapRef = React.useRef(announcementMap); | ||
var entries = React.useMemo(function () { | ||
return Array.from(announcementMap.entries()); | ||
}, [announcementMap]); | ||
React.useEffect(function () { | ||
announcementMapRef.current = announcementMap; | ||
}, [announcementMap]); | ||
React.useEffect(function () { | ||
return function () { | ||
// Clean up any queued `setTimeout` calls on unmount | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
announcementMapRef.current.forEach(function (_, key) { | ||
clearTimeout(key); | ||
}); | ||
}; | ||
}, []); | ||
return { | ||
announce: announce, | ||
entries: entries | ||
announce: setAnnouncement, | ||
announcement: announcement | ||
}; | ||
@@ -91,0 +56,0 @@ } |
@@ -1,2 +0,2 @@ | ||
"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}}; | ||
"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,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(e){return n.createElement("div",{id:e.id,style:i},e.value)},exports.LiveRegion=function(e){return n.createElement("div",{id:e.id,style:r,role:"status","aria-live":"assertive","aria-atomic":!0},e.announcement)},exports.useAnnouncement=function(){var e=t.useState("");return{announce:e[1],announcement:e[0]}}; | ||
//# sourceMappingURL=accessibility.cjs.production.min.js.map |
@@ -1,2 +0,2 @@ | ||
import React, { useState, useCallback, useRef, useMemo, useEffect } from 'react'; | ||
import React, { useState } from 'react'; | ||
@@ -24,60 +24,25 @@ var hiddenStyles = { | ||
clip: 'rect(0 0 0 0)', | ||
clipPath: 'inset(100%)' | ||
clipPath: 'inset(100%)', | ||
whiteSpace: 'nowrap' | ||
}; | ||
function LiveRegion(_ref) { | ||
var id = _ref.id, | ||
entries = _ref.entries; | ||
announcement = _ref.announcement; | ||
return React.createElement("div", { | ||
id: id, | ||
style: visuallyHidden, | ||
role: "status", | ||
"aria-live": "assertive", | ||
"aria-relevant": "additions", | ||
"aria-atomic": true | ||
}, entries.map(function (_ref2) { | ||
var id = _ref2[0], | ||
entry = _ref2[1]; | ||
return React.createElement("span", { | ||
key: id.toString() | ||
}, entry); | ||
})); | ||
}, announcement); | ||
} | ||
var timeout = 1e3; // 1 second | ||
function useAnnouncement() { | ||
var _useState = useState(new Map()), | ||
announcementMap = _useState[0], | ||
setAnnouncements = _useState[1]; | ||
var _useState = useState(''), | ||
announcement = _useState[0], | ||
setAnnouncement = _useState[1]; | ||
var announce = useCallback(function (announcement) { | ||
setAnnouncements(function (announcements) { | ||
var timeoutId = setTimeout(function () { | ||
setAnnouncements(function (announcements) { | ||
announcements["delete"](timeoutId); | ||
return new Map(announcements); | ||
}); | ||
}, timeout); | ||
announcements.set(timeoutId, announcement); | ||
return new Map(announcements); | ||
}); | ||
}, []); | ||
var announcementMapRef = useRef(announcementMap); | ||
var entries = useMemo(function () { | ||
return Array.from(announcementMap.entries()); | ||
}, [announcementMap]); | ||
useEffect(function () { | ||
announcementMapRef.current = announcementMap; | ||
}, [announcementMap]); | ||
useEffect(function () { | ||
return function () { | ||
// Clean up any queued `setTimeout` calls on unmount | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
announcementMapRef.current.forEach(function (_, key) { | ||
clearTimeout(key); | ||
}); | ||
}; | ||
}, []); | ||
return { | ||
announce: announce, | ||
entries: entries | ||
announce: setAnnouncement, | ||
announcement: announcement | ||
}; | ||
@@ -84,0 +49,0 @@ } |
@@ -1,7 +0,6 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="react" /> | ||
export interface Props { | ||
id: string; | ||
entries: [NodeJS.Timeout, string][]; | ||
announcement: string; | ||
} | ||
export declare function LiveRegion({ id, entries }: Props): JSX.Element; | ||
export declare function LiveRegion({ id, announcement }: Props): JSX.Element; |
@@ -1,5 +0,5 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="react" /> | ||
export declare function useAnnouncement(): { | ||
readonly announce: (announcement: string) => void; | ||
readonly entries: [NodeJS.Timeout, string][]; | ||
readonly announce: import("react").Dispatch<import("react").SetStateAction<string>>; | ||
readonly announcement: string; | ||
}; |
{ | ||
"name": "@dnd-kit/accessibility", | ||
"version": "1.0.2", | ||
"version": "2.0.0", | ||
"description": "A generic toolkit to help with accessibility", | ||
@@ -5,0 +5,0 @@ "author": "Claudéric Demers", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
16018
133