@fluentui/react-aria 9.10.5 → 9.11.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.
Files changed (29) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/dist/index.d.ts +12 -0
  3. package/lib/AriaLiveAnnouncer/useAriaLiveAnnouncer.js +12 -114
  4. package/lib/AriaLiveAnnouncer/useAriaLiveAnnouncer.js.map +1 -1
  5. package/lib/AriaLiveAnnouncer/useAriaNotifyAnnounce.js +26 -0
  6. package/lib/AriaLiveAnnouncer/useAriaNotifyAnnounce.js.map +1 -0
  7. package/lib/AriaLiveAnnouncer/useDomAnnounce.js +121 -0
  8. package/lib/AriaLiveAnnouncer/useDomAnnounce.js.map +1 -0
  9. package/lib/activedescendant/ActiveDescendantContext.js +1 -0
  10. package/lib/activedescendant/ActiveDescendantContext.js.map +1 -1
  11. package/lib/activedescendant/scrollIntoView.js +44 -9
  12. package/lib/activedescendant/scrollIntoView.js.map +1 -1
  13. package/lib/activedescendant/types.js.map +1 -1
  14. package/lib/activedescendant/useActiveDescendant.js +27 -3
  15. package/lib/activedescendant/useActiveDescendant.js.map +1 -1
  16. package/lib/index.js.map +1 -1
  17. package/lib-commonjs/AriaLiveAnnouncer/useAriaLiveAnnouncer.js +12 -114
  18. package/lib-commonjs/AriaLiveAnnouncer/useAriaLiveAnnouncer.js.map +1 -1
  19. package/lib-commonjs/AriaLiveAnnouncer/useAriaNotifyAnnounce.js +37 -0
  20. package/lib-commonjs/AriaLiveAnnouncer/useAriaNotifyAnnounce.js.map +1 -0
  21. package/lib-commonjs/AriaLiveAnnouncer/useDomAnnounce.js +132 -0
  22. package/lib-commonjs/AriaLiveAnnouncer/useDomAnnounce.js.map +1 -0
  23. package/lib-commonjs/activedescendant/ActiveDescendantContext.js +1 -0
  24. package/lib-commonjs/activedescendant/ActiveDescendantContext.js.map +1 -1
  25. package/lib-commonjs/activedescendant/scrollIntoView.js +44 -9
  26. package/lib-commonjs/activedescendant/scrollIntoView.js.map +1 -1
  27. package/lib-commonjs/activedescendant/useActiveDescendant.js +38 -6
  28. package/lib-commonjs/activedescendant/useActiveDescendant.js.map +1 -1
  29. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["useActiveDescendant.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport { useOnKeyboardNavigationChange } from '@fluentui/react-tabster';\nimport { useOptionWalker } from './useOptionWalker';\nimport type { ActiveDescendantImperativeRef, ActiveDescendantOptions, UseActiveDescendantReturn } from './types';\nimport { ACTIVEDESCENDANT_ATTRIBUTE, ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE } from './constants';\nimport { scrollIntoView } from './scrollIntoView';\n\nexport function useActiveDescendant<TActiveParentElement extends HTMLElement, TListboxElement extends HTMLElement>(\n options: ActiveDescendantOptions,\n): UseActiveDescendantReturn<TActiveParentElement, TListboxElement> {\n const { imperativeRef, matchOption: matchOptionUnstable } = options;\n const focusVisibleRef = React.useRef(false);\n const activeIdRef = React.useRef<string | null>(null);\n const activeParentRef = React.useRef<TActiveParentElement>(null);\n const attributeVisibilityRef = React.useRef(true);\n\n const removeAttribute = React.useCallback(() => {\n activeParentRef.current?.removeAttribute('aria-activedescendant');\n }, []);\n const setAttribute = React.useCallback((id?: string) => {\n if (id) {\n activeIdRef.current = id;\n }\n if (attributeVisibilityRef.current && activeIdRef.current) {\n activeParentRef.current?.setAttribute('aria-activedescendant', activeIdRef.current);\n }\n }, []);\n\n useOnKeyboardNavigationChange(isNavigatingWithKeyboard => {\n focusVisibleRef.current = isNavigatingWithKeyboard;\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n if (isNavigatingWithKeyboard) {\n active.setAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE, '');\n } else {\n active.removeAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE);\n }\n });\n\n const matchOption = useEventCallback(matchOptionUnstable);\n const listboxRef = React.useRef<TListboxElement>(null);\n const { optionWalker, listboxCallbackRef } = useOptionWalker<TListboxElement>({ matchOption });\n const getActiveDescendant = React.useCallback(() => {\n return listboxRef.current?.querySelector<HTMLElement>(`#${activeIdRef.current}`);\n }, [listboxRef]);\n\n const blurActiveDescendant = React.useCallback(() => {\n const active = getActiveDescendant();\n if (active) {\n active.removeAttribute(ACTIVEDESCENDANT_ATTRIBUTE);\n active.removeAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE);\n }\n\n removeAttribute();\n activeIdRef.current = null;\n }, [getActiveDescendant, removeAttribute]);\n\n const focusActiveDescendant = React.useCallback(\n (nextActive: HTMLElement | null) => {\n if (!nextActive) {\n return;\n }\n\n blurActiveDescendant();\n\n scrollIntoView(nextActive, listboxRef.current);\n setAttribute(nextActive.id);\n nextActive.setAttribute(ACTIVEDESCENDANT_ATTRIBUTE, '');\n\n if (focusVisibleRef.current) {\n nextActive.setAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE, '');\n }\n },\n [listboxRef, blurActiveDescendant, setAttribute],\n );\n\n const controller: ActiveDescendantImperativeRef = React.useMemo(\n () => ({\n first: ({ passive } = {}) => {\n const first = optionWalker.first();\n if (!passive) {\n focusActiveDescendant(first);\n }\n\n return first?.id;\n },\n last: ({ passive } = {}) => {\n const last = optionWalker.last();\n if (!passive) {\n focusActiveDescendant(last);\n }\n\n return last?.id;\n },\n next: ({ passive } = {}) => {\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n optionWalker.setCurrent(active);\n const next = optionWalker.next();\n if (!passive) {\n focusActiveDescendant(next);\n }\n\n return next?.id;\n },\n prev: ({ passive } = {}) => {\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n optionWalker.setCurrent(active);\n const next = optionWalker.prev();\n\n if (!passive) {\n focusActiveDescendant(next);\n }\n\n return next?.id;\n },\n blur: () => {\n blurActiveDescendant();\n },\n active: () => {\n return getActiveDescendant()?.id;\n },\n\n focus: (id: string) => {\n if (!listboxRef.current) {\n return;\n }\n\n const target = listboxRef.current.querySelector<HTMLElement>(`#${id}`);\n if (target) {\n focusActiveDescendant(target);\n }\n },\n\n find(predicate, { passive, startFrom } = {}) {\n const target = optionWalker.find(predicate, startFrom);\n if (!passive) {\n focusActiveDescendant(target);\n }\n\n return target?.id;\n },\n showAttributes() {\n attributeVisibilityRef.current = true;\n setAttribute();\n },\n hideAttributes() {\n attributeVisibilityRef.current = false;\n removeAttribute();\n },\n }),\n [\n optionWalker,\n listboxRef,\n setAttribute,\n removeAttribute,\n focusActiveDescendant,\n blurActiveDescendant,\n getActiveDescendant,\n ],\n );\n\n React.useImperativeHandle(imperativeRef, () => controller);\n\n return { listboxRef: useMergedRefs(listboxRef, listboxCallbackRef), activeParentRef, controller };\n}\n"],"names":["React","useEventCallback","useMergedRefs","useOnKeyboardNavigationChange","useOptionWalker","ACTIVEDESCENDANT_ATTRIBUTE","ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE","scrollIntoView","useActiveDescendant","options","imperativeRef","matchOption","matchOptionUnstable","focusVisibleRef","useRef","activeIdRef","activeParentRef","attributeVisibilityRef","removeAttribute","useCallback","current","setAttribute","id","isNavigatingWithKeyboard","active","getActiveDescendant","listboxRef","optionWalker","listboxCallbackRef","querySelector","blurActiveDescendant","focusActiveDescendant","nextActive","controller","useMemo","first","passive","last","next","setCurrent","prev","blur","focus","target","find","predicate","startFrom","showAttributes","hideAttributes","useImperativeHandle"],"mappings":"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"}
1
+ {"version":3,"sources":["useActiveDescendant.ts"],"sourcesContent":["import * as React from 'react';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport { useOnKeyboardNavigationChange } from '@fluentui/react-tabster';\nimport { useOptionWalker } from './useOptionWalker';\nimport type { ActiveDescendantImperativeRef, ActiveDescendantOptions, UseActiveDescendantReturn } from './types';\nimport { ACTIVEDESCENDANT_ATTRIBUTE, ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE } from './constants';\nimport { scrollIntoView } from './scrollIntoView';\n\ninterface ActiveDescendantChangeEventDetail {\n id: string;\n previousId: string | null;\n}\n\nexport type ActiveDescendantChangeEvent = CustomEvent<ActiveDescendantChangeEventDetail>;\n\nexport const createActiveDescendantChangeEvent = (\n detail: ActiveDescendantChangeEventDetail,\n): ActiveDescendantChangeEvent =>\n new CustomEvent<ActiveDescendantChangeEventDetail>('activedescendantchange', {\n bubbles: true,\n cancelable: false,\n composed: true,\n detail,\n });\n\nexport function useActiveDescendant<TActiveParentElement extends HTMLElement, TListboxElement extends HTMLElement>(\n options: ActiveDescendantOptions,\n): UseActiveDescendantReturn<TActiveParentElement, TListboxElement> {\n const { imperativeRef, matchOption: matchOptionUnstable } = options;\n const focusVisibleRef = React.useRef(false);\n const activeIdRef = React.useRef<string | null>(null);\n const lastActiveIdRef = React.useRef<string | null>(null);\n const activeParentRef = React.useRef<TActiveParentElement>(null);\n const attributeVisibilityRef = React.useRef(true);\n\n const removeAttribute = React.useCallback(() => {\n activeParentRef.current?.removeAttribute('aria-activedescendant');\n }, []);\n const setAttribute = React.useCallback((id?: string) => {\n if (id) {\n activeIdRef.current = id;\n }\n if (attributeVisibilityRef.current && activeIdRef.current) {\n activeParentRef.current?.setAttribute('aria-activedescendant', activeIdRef.current);\n }\n }, []);\n\n useOnKeyboardNavigationChange(isNavigatingWithKeyboard => {\n focusVisibleRef.current = isNavigatingWithKeyboard;\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n if (isNavigatingWithKeyboard) {\n active.setAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE, '');\n } else {\n active.removeAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE);\n }\n });\n\n const matchOption = useEventCallback(matchOptionUnstable);\n const listboxRef = React.useRef<TListboxElement>(null);\n const { optionWalker, listboxCallbackRef } = useOptionWalker<TListboxElement>({ matchOption });\n const getActiveDescendant = React.useCallback(() => {\n return listboxRef.current?.querySelector<HTMLElement>(`#${activeIdRef.current}`);\n }, [listboxRef]);\n\n const blurActiveDescendant = React.useCallback(() => {\n const active = getActiveDescendant();\n if (active) {\n active.removeAttribute(ACTIVEDESCENDANT_ATTRIBUTE);\n active.removeAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE);\n }\n\n removeAttribute();\n lastActiveIdRef.current = activeIdRef.current;\n activeIdRef.current = null;\n return active?.id ?? null;\n }, [getActiveDescendant, removeAttribute]);\n\n const focusActiveDescendant = React.useCallback(\n (nextActive: HTMLElement | null) => {\n if (!nextActive) {\n return;\n }\n\n const previousActiveId = blurActiveDescendant();\n\n scrollIntoView(nextActive);\n setAttribute(nextActive.id);\n nextActive.setAttribute(ACTIVEDESCENDANT_ATTRIBUTE, '');\n\n if (focusVisibleRef.current) {\n nextActive.setAttribute(ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE, '');\n }\n\n const event = createActiveDescendantChangeEvent({ id: nextActive.id, previousId: previousActiveId });\n nextActive.dispatchEvent(event);\n },\n [blurActiveDescendant, setAttribute],\n );\n\n const controller: ActiveDescendantImperativeRef = React.useMemo(\n () => ({\n first: ({ passive } = {}) => {\n const first = optionWalker.first();\n if (!passive) {\n focusActiveDescendant(first);\n }\n\n return first?.id;\n },\n last: ({ passive } = {}) => {\n const last = optionWalker.last();\n if (!passive) {\n focusActiveDescendant(last);\n }\n\n return last?.id;\n },\n next: ({ passive } = {}) => {\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n optionWalker.setCurrent(active);\n const next = optionWalker.next();\n if (!passive) {\n focusActiveDescendant(next);\n }\n\n return next?.id;\n },\n prev: ({ passive } = {}) => {\n const active = getActiveDescendant();\n if (!active) {\n return;\n }\n\n optionWalker.setCurrent(active);\n const next = optionWalker.prev();\n\n if (!passive) {\n focusActiveDescendant(next);\n }\n\n return next?.id;\n },\n blur: () => {\n blurActiveDescendant();\n },\n active: () => {\n return getActiveDescendant()?.id;\n },\n focus: (id: string) => {\n if (!listboxRef.current) {\n return;\n }\n\n const target = listboxRef.current.querySelector<HTMLElement>(`#${id}`);\n if (target) {\n focusActiveDescendant(target);\n }\n },\n focusLastActive: () => {\n if (!listboxRef.current || !lastActiveIdRef.current) {\n return;\n }\n\n const target = listboxRef.current.querySelector<HTMLElement>(`#${lastActiveIdRef.current}`);\n if (target) {\n focusActiveDescendant(target);\n return true;\n }\n },\n find(predicate, { passive, startFrom } = {}) {\n const target = optionWalker.find(predicate, startFrom);\n if (!passive) {\n focusActiveDescendant(target);\n }\n\n return target?.id;\n },\n showAttributes() {\n attributeVisibilityRef.current = true;\n setAttribute();\n },\n hideAttributes() {\n attributeVisibilityRef.current = false;\n removeAttribute();\n },\n }),\n [\n optionWalker,\n listboxRef,\n setAttribute,\n removeAttribute,\n focusActiveDescendant,\n blurActiveDescendant,\n getActiveDescendant,\n ],\n );\n\n React.useImperativeHandle(imperativeRef, () => controller);\n\n return { listboxRef: useMergedRefs(listboxRef, listboxCallbackRef), activeParentRef, controller };\n}\n"],"names":["React","useEventCallback","useMergedRefs","useOnKeyboardNavigationChange","useOptionWalker","ACTIVEDESCENDANT_ATTRIBUTE","ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE","scrollIntoView","createActiveDescendantChangeEvent","detail","CustomEvent","bubbles","cancelable","composed","useActiveDescendant","options","imperativeRef","matchOption","matchOptionUnstable","focusVisibleRef","useRef","activeIdRef","lastActiveIdRef","activeParentRef","attributeVisibilityRef","removeAttribute","useCallback","current","setAttribute","id","isNavigatingWithKeyboard","active","getActiveDescendant","listboxRef","optionWalker","listboxCallbackRef","querySelector","blurActiveDescendant","focusActiveDescendant","nextActive","previousActiveId","event","previousId","dispatchEvent","controller","useMemo","first","passive","last","next","setCurrent","prev","blur","focus","target","focusLastActive","find","predicate","startFrom","showAttributes","hideAttributes","useImperativeHandle"],"mappings":"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"}
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["index.ts"],"sourcesContent":["export {\n // eslint-disable-next-line deprecation/deprecation\n useARIAButtonShorthand,\n useARIAButtonProps,\n} from './button/index';\nexport {\n useActiveDescendant,\n ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE,\n ActiveDescendantContextProvider,\n useActiveDescendantContext,\n useHasParentActiveDescendantContext,\n} from './activedescendant';\nexport type {\n ActiveDescendantImperativeRef,\n ActiveDescendantOptions,\n ActiveDescendantContextValue,\n} from './activedescendant';\nexport type {\n ARIAButtonSlotProps,\n ARIAButtonProps,\n ARIAButtonResultProps,\n ARIAButtonType,\n ARIAButtonElement,\n ARIAButtonElementIntersection,\n ARIAButtonAlteredProps,\n} from './button/index';\n\nexport {\n AriaLiveAnnouncer,\n renderAriaLiveAnnouncer_unstable,\n useAriaLiveAnnouncer_unstable,\n useAriaLiveAnnouncerContextValues_unstable,\n} from './AriaLiveAnnouncer/index';\nexport type { AriaLiveAnnouncerProps, AriaLiveAnnouncerState } from './AriaLiveAnnouncer/index';\n"],"names":["useARIAButtonShorthand","useARIAButtonProps","useActiveDescendant","ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE","ActiveDescendantContextProvider","useActiveDescendantContext","useHasParentActiveDescendantContext","AriaLiveAnnouncer","renderAriaLiveAnnouncer_unstable","useAriaLiveAnnouncer_unstable","useAriaLiveAnnouncerContextValues_unstable"],"mappings":"AAAA,SACE,mDAAmD;AACnDA,sBAAsB,EACtBC,kBAAkB,QACb,iBAAiB;AACxB,SACEC,mBAAmB,EACnBC,uCAAuC,EACvCC,+BAA+B,EAC/BC,0BAA0B,EAC1BC,mCAAmC,QAC9B,qBAAqB;AAgB5B,SACEC,iBAAiB,EACjBC,gCAAgC,EAChCC,6BAA6B,EAC7BC,0CAA0C,QACrC,4BAA4B"}
1
+ {"version":3,"sources":["index.ts"],"sourcesContent":["export {\n // eslint-disable-next-line deprecation/deprecation\n useARIAButtonShorthand,\n useARIAButtonProps,\n} from './button/index';\nexport {\n useActiveDescendant,\n ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE,\n ActiveDescendantContextProvider,\n useActiveDescendantContext,\n useHasParentActiveDescendantContext,\n} from './activedescendant';\nexport type {\n ActiveDescendantImperativeRef,\n ActiveDescendantOptions,\n ActiveDescendantContextValue,\n ActiveDescendantChangeEvent,\n} from './activedescendant';\nexport type {\n ARIAButtonSlotProps,\n ARIAButtonProps,\n ARIAButtonResultProps,\n ARIAButtonType,\n ARIAButtonElement,\n ARIAButtonElementIntersection,\n ARIAButtonAlteredProps,\n} from './button/index';\n\nexport {\n AriaLiveAnnouncer,\n renderAriaLiveAnnouncer_unstable,\n useAriaLiveAnnouncer_unstable,\n useAriaLiveAnnouncerContextValues_unstable,\n} from './AriaLiveAnnouncer/index';\nexport type { AriaLiveAnnouncerProps, AriaLiveAnnouncerState } from './AriaLiveAnnouncer/index';\n"],"names":["useARIAButtonShorthand","useARIAButtonProps","useActiveDescendant","ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE","ActiveDescendantContextProvider","useActiveDescendantContext","useHasParentActiveDescendantContext","AriaLiveAnnouncer","renderAriaLiveAnnouncer_unstable","useAriaLiveAnnouncer_unstable","useAriaLiveAnnouncerContextValues_unstable"],"mappings":"AAAA,SACE,mDAAmD;AACnDA,sBAAsB,EACtBC,kBAAkB,QACb,iBAAiB;AACxB,SACEC,mBAAmB,EACnBC,uCAAuC,EACvCC,+BAA+B,EAC/BC,0BAA0B,EAC1BC,mCAAmC,QAC9B,qBAAqB;AAiB5B,SACEC,iBAAiB,EACjBC,gCAAgC,EAChCC,6BAA6B,EAC7BC,0CAA0C,QACrC,4BAA4B"}
@@ -9,124 +9,22 @@ Object.defineProperty(exports, "useAriaLiveAnnouncer_unstable", {
9
9
  }
10
10
  });
11
11
  const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
12
- const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
13
- const _reactutilities = require("@fluentui/react-utilities");
14
12
  const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
15
- /** The duration the message needs to be in present in DOM for screen readers to register a change and announce */ const MESSAGE_DURATION = 500;
16
- const VISUALLY_HIDDEN_STYLES = {
17
- clip: 'rect(0px, 0px, 0px, 0px)',
18
- height: '1px',
19
- margin: '-1px',
20
- width: '1px',
21
- position: 'absolute',
22
- overflow: 'hidden',
23
- textWrap: 'nowrap'
24
- };
13
+ const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
14
+ const _useDomAnnounce = require("./useDomAnnounce");
15
+ const _useAriaNotifyAnnounce = require("./useAriaNotifyAnnounce");
25
16
  const useAriaLiveAnnouncer_unstable = (props)=>{
26
17
  const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
27
- const timeoutRef = _react.useRef(undefined);
28
- const [setAnnounceTimeout, clearAnnounceTimeout] = (0, _reactutilities.useTimeout)();
29
- const elementRef = _react.useRef(null);
30
- const order = _react.useRef(0);
31
- // investigate alert implementation later
32
- // const [alertList, setAlertList] = React.useState<string[]>([]);
33
- const batchMessages = _react.useRef([]);
34
- const [messageQueue] = _react.useState(()=>(0, _reactutilities.createPriorityQueue)((a, b)=>{
35
- if (a.priority !== b.priority) {
36
- return b.priority - a.priority;
37
- }
38
- return a.createdAt - b.createdAt;
39
- }));
40
- const queueMessage = _react.useCallback(()=>{
41
- if (timeoutRef.current || !elementRef.current) {
42
- return;
43
- }
44
- const runCycle = ()=>{
45
- if (!elementRef.current) {
46
- return;
47
- }
48
- if (targetDocument && messageQueue.peek()) {
49
- // need a wrapping element for Narrator/Edge, which currently does not pick up text-only live region changes
50
- // consistently
51
- // if this is fixed, we can set textContent to the string directly
52
- const wrappingEl = targetDocument.createElement('span');
53
- wrappingEl.innerText = messageQueue.all().filter((msg)=>msg.message.trim().length > 0).reduce((prevText, currMsg)=>prevText + currMsg.message + '. ', '');
54
- elementRef.current.innerText = '';
55
- elementRef.current.appendChild(wrappingEl);
56
- messageQueue.clear();
57
- batchMessages.current = [];
58
- // begin new cycle to clear (or update) messages
59
- timeoutRef.current = setAnnounceTimeout(()=>{
60
- runCycle();
61
- }, MESSAGE_DURATION);
62
- } else {
63
- elementRef.current.textContent = '';
64
- clearAnnounceTimeout();
65
- timeoutRef.current = undefined;
66
- }
67
- };
68
- runCycle();
69
- }, [
70
- clearAnnounceTimeout,
71
- messageQueue,
72
- setAnnounceTimeout,
73
- targetDocument
74
- ]);
75
- const announce = _react.useMemo(()=>(message, options = {})=>{
76
- const { alert = false, priority = 0, batchId } = options;
77
- // check if message is an alert
78
- if (alert) {
79
- // TODO: alert implementation
80
- // setAlertList([...alertList, message]);
81
- }
82
- const liveMessage = {
83
- message,
84
- createdAt: order.current++,
85
- priority,
86
- batchId
87
- };
88
- // check if batchId exists
89
- if (batchId) {
90
- // update associated msg if it does
91
- const batchMessage = batchMessages.current.find((msg)=>msg.batchId === batchId);
92
- if (batchMessage) {
93
- // replace existing message in queue
94
- messageQueue.remove(batchMessage.message);
95
- // update list of existing batchIds w/ most recent message
96
- batchMessage.message = liveMessage;
97
- } else {
98
- // update list of existing batchIds, add new if doesn't already exist
99
- batchMessages.current = [
100
- ...batchMessages.current,
101
- {
102
- batchId,
103
- message: liveMessage
104
- }
105
- ];
106
- }
107
- }
108
- // add new message
109
- messageQueue.enqueue(liveMessage);
110
- queueMessage();
111
- }, [
112
- messageQueue,
113
- queueMessage
114
- ]);
115
- _react.useEffect(()=>{
116
- if (!targetDocument) {
117
- return;
118
- }
119
- const element = targetDocument.createElement('div');
120
- element.setAttribute('aria-live', 'assertive');
121
- Object.assign(element.style, VISUALLY_HIDDEN_STYLES);
122
- targetDocument.body.append(element);
123
- elementRef.current = element;
124
- return ()=>{
125
- element.remove();
126
- elementRef.current = null;
127
- };
18
+ const domAnnounce = (0, _useDomAnnounce.useDomAnnounce_unstable)();
19
+ const ariaNotifyAnnounce = (0, _useAriaNotifyAnnounce.useAriaNotifyAnnounce_unstable)();
20
+ const announce = _react.useMemo(()=>{
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const supportsAriaNotify = typeof (targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.ariaNotify) === 'function';
23
+ return supportsAriaNotify ? ariaNotifyAnnounce : domAnnounce;
128
24
  }, [
129
- targetDocument
25
+ targetDocument,
26
+ ariaNotifyAnnounce,
27
+ domAnnounce
130
28
  ]);
131
29
  return {
132
30
  announce,
@@ -1 +1 @@
1
- {"version":3,"sources":["useAriaLiveAnnouncer.js"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { createPriorityQueue, useTimeout } from '@fluentui/react-utilities';\nimport * as React from 'react';\n/** The duration the message needs to be in present in DOM for screen readers to register a change and announce */ const MESSAGE_DURATION = 500;\nconst VISUALLY_HIDDEN_STYLES = {\n clip: 'rect(0px, 0px, 0px, 0px)',\n height: '1px',\n margin: '-1px',\n width: '1px',\n position: 'absolute',\n overflow: 'hidden',\n textWrap: 'nowrap'\n};\nexport const useAriaLiveAnnouncer_unstable = (props)=>{\n const { targetDocument } = useFluent();\n const timeoutRef = React.useRef(undefined);\n const [setAnnounceTimeout, clearAnnounceTimeout] = useTimeout();\n const elementRef = React.useRef(null);\n const order = React.useRef(0);\n // investigate alert implementation later\n // const [alertList, setAlertList] = React.useState<string[]>([]);\n const batchMessages = React.useRef([]);\n const [messageQueue] = React.useState(()=>createPriorityQueue((a, b)=>{\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n return a.createdAt - b.createdAt;\n }));\n const queueMessage = React.useCallback(()=>{\n if (timeoutRef.current || !elementRef.current) {\n return;\n }\n const runCycle = ()=>{\n if (!elementRef.current) {\n return;\n }\n if (targetDocument && messageQueue.peek()) {\n // need a wrapping element for Narrator/Edge, which currently does not pick up text-only live region changes\n // consistently\n // if this is fixed, we can set textContent to the string directly\n const wrappingEl = targetDocument.createElement('span');\n wrappingEl.innerText = messageQueue.all().filter((msg)=>msg.message.trim().length > 0).reduce((prevText, currMsg)=>prevText + currMsg.message + '. ', '');\n elementRef.current.innerText = '';\n elementRef.current.appendChild(wrappingEl);\n messageQueue.clear();\n batchMessages.current = [];\n // begin new cycle to clear (or update) messages\n timeoutRef.current = setAnnounceTimeout(()=>{\n runCycle();\n }, MESSAGE_DURATION);\n } else {\n elementRef.current.textContent = '';\n clearAnnounceTimeout();\n timeoutRef.current = undefined;\n }\n };\n runCycle();\n }, [\n clearAnnounceTimeout,\n messageQueue,\n setAnnounceTimeout,\n targetDocument\n ]);\n const announce = React.useMemo(()=>(message, options = {})=>{\n const { alert = false, priority = 0, batchId } = options;\n // check if message is an alert\n if (alert) {\n // TODO: alert implementation\n // setAlertList([...alertList, message]);\n }\n const liveMessage = {\n message,\n createdAt: order.current++,\n priority,\n batchId\n };\n // check if batchId exists\n if (batchId) {\n // update associated msg if it does\n const batchMessage = batchMessages.current.find((msg)=>msg.batchId === batchId);\n if (batchMessage) {\n // replace existing message in queue\n messageQueue.remove(batchMessage.message);\n // update list of existing batchIds w/ most recent message\n batchMessage.message = liveMessage;\n } else {\n // update list of existing batchIds, add new if doesn't already exist\n batchMessages.current = [\n ...batchMessages.current,\n {\n batchId,\n message: liveMessage\n }\n ];\n }\n }\n // add new message\n messageQueue.enqueue(liveMessage);\n queueMessage();\n }, [\n messageQueue,\n queueMessage\n ]);\n React.useEffect(()=>{\n if (!targetDocument) {\n return;\n }\n const element = targetDocument.createElement('div');\n element.setAttribute('aria-live', 'assertive');\n Object.assign(element.style, VISUALLY_HIDDEN_STYLES);\n targetDocument.body.append(element);\n elementRef.current = element;\n return ()=>{\n element.remove();\n elementRef.current = null;\n };\n }, [\n targetDocument\n ]);\n return {\n announce,\n children: props.children\n };\n};\n"],"names":["useAriaLiveAnnouncer_unstable","MESSAGE_DURATION","VISUALLY_HIDDEN_STYLES","clip","height","margin","width","position","overflow","textWrap","props","targetDocument","useFluent","timeoutRef","React","useRef","undefined","setAnnounceTimeout","clearAnnounceTimeout","useTimeout","elementRef","order","batchMessages","messageQueue","useState","createPriorityQueue","a","b","priority","createdAt","queueMessage","useCallback","current","runCycle","peek","wrappingEl","createElement","innerText","all","filter","msg","message","trim","length","reduce","prevText","currMsg","appendChild","clear","textContent","announce","useMemo","options","alert","batchId","liveMessage","batchMessage","find","remove","enqueue","useEffect","element","setAttribute","Object","assign","style","body","append","children"],"mappings":"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"}
1
+ {"version":3,"sources":["useAriaLiveAnnouncer.js"],"sourcesContent":["import * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useDomAnnounce_unstable } from './useDomAnnounce';\nimport { useAriaNotifyAnnounce_unstable } from './useAriaNotifyAnnounce';\nexport const useAriaLiveAnnouncer_unstable = (props)=>{\n const { targetDocument } = useFluent();\n const domAnnounce = useDomAnnounce_unstable();\n const ariaNotifyAnnounce = useAriaNotifyAnnounce_unstable();\n const announce = React.useMemo(()=>{\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const supportsAriaNotify = typeof (targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.ariaNotify) === 'function';\n return supportsAriaNotify ? ariaNotifyAnnounce : domAnnounce;\n }, [\n targetDocument,\n ariaNotifyAnnounce,\n domAnnounce\n ]);\n return {\n announce,\n children: props.children\n };\n};\n"],"names":["useAriaLiveAnnouncer_unstable","props","targetDocument","useFluent","domAnnounce","useDomAnnounce_unstable","ariaNotifyAnnounce","useAriaNotifyAnnounce_unstable","announce","React","useMemo","supportsAriaNotify","ariaNotify","children"],"mappings":";;;;+BAIaA;;;eAAAA;;;;iEAJU;qCACyB;gCACR;uCACO;AACxC,MAAMA,gCAAgC,CAACC;IAC1C,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,cAAcC,IAAAA,uCAAuB;IAC3C,MAAMC,qBAAqBC,IAAAA,qDAA8B;IACzD,MAAMC,WAAWC,OAAMC,OAAO,CAAC;QAC3B,8DAA8D;QAC9D,MAAMC,qBAAqB,OAAQT,CAAAA,mBAAmB,QAAQA,mBAAmB,KAAK,IAAI,KAAK,IAAIA,eAAeU,UAAU,AAAD,MAAO;QAClI,OAAOD,qBAAqBL,qBAAqBF;IACrD,GAAG;QACCF;QACAI;QACAF;KACH;IACD,OAAO;QACHI;QACAK,UAAUZ,MAAMY,QAAQ;IAC5B;AACJ"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "useAriaNotifyAnnounce_unstable", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return useAriaNotifyAnnounce_unstable;
9
+ }
10
+ });
11
+ const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
12
+ const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
13
+ const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
14
+ const useAriaNotifyAnnounce_unstable = ()=>{
15
+ const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
16
+ const announce = _react.useCallback((message, options = {})=>{
17
+ if (!targetDocument) {
18
+ return;
19
+ }
20
+ const { alert = false, polite, batchId } = options;
21
+ // default priority to 0 if polite, 2 if alert, and 1 by default
22
+ // used to set both ariaNotify's priority and interrupt
23
+ const defaultPriority = polite ? 0 : alert ? 2 : 1;
24
+ var _options_priority;
25
+ const priority = (_options_priority = options.priority) !== null && _options_priority !== void 0 ? _options_priority : defaultPriority;
26
+ // map fluent announce options to ariaNotify options
27
+ const ariaNotifyOptions = {
28
+ notificationID: batchId,
29
+ priority: priority > 1 ? 'important' : 'none',
30
+ interrupt: batchId ? priority > 0 ? 'all' : 'pending' : 'none'
31
+ };
32
+ targetDocument.ariaNotify(message, ariaNotifyOptions);
33
+ }, [
34
+ targetDocument
35
+ ]);
36
+ return announce;
37
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["useAriaNotifyAnnounce.js"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport * as React from 'react';\n/* INTERNAL: implementation of the announcer using the ariaNotify API */ export const useAriaNotifyAnnounce_unstable = ()=>{\n const { targetDocument } = useFluent();\n const announce = React.useCallback((message, options = {})=>{\n if (!targetDocument) {\n return;\n }\n const { alert = false, polite, batchId } = options;\n // default priority to 0 if polite, 2 if alert, and 1 by default\n // used to set both ariaNotify's priority and interrupt\n const defaultPriority = polite ? 0 : alert ? 2 : 1;\n var _options_priority;\n const priority = (_options_priority = options.priority) !== null && _options_priority !== void 0 ? _options_priority : defaultPriority;\n // map fluent announce options to ariaNotify options\n const ariaNotifyOptions = {\n notificationID: batchId,\n priority: priority > 1 ? 'important' : 'none',\n interrupt: batchId ? priority > 0 ? 'all' : 'pending' : 'none'\n };\n targetDocument.ariaNotify(message, ariaNotifyOptions);\n }, [\n targetDocument\n ]);\n return announce;\n};\n"],"names":["useAriaNotifyAnnounce_unstable","targetDocument","useFluent","announce","React","useCallback","message","options","alert","polite","batchId","defaultPriority","_options_priority","priority","ariaNotifyOptions","notificationID","interrupt","ariaNotify"],"mappings":";;;;+BAEsFA;;;eAAAA;;;;qCAFtC;iEACzB;AACyD,MAAMA,iCAAiC;IACnH,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,WAAWC,OAAMC,WAAW,CAAC,CAACC,SAASC,UAAU,CAAC,CAAC;QACrD,IAAI,CAACN,gBAAgB;YACjB;QACJ;QACA,MAAM,EAAEO,QAAQ,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAE,GAAGH;QAC3C,gEAAgE;QAChE,uDAAuD;QACvD,MAAMI,kBAAkBF,SAAS,IAAID,QAAQ,IAAI;QACjD,IAAII;QACJ,MAAMC,WAAW,AAACD,CAAAA,oBAAoBL,QAAQM,QAAQ,AAAD,MAAO,QAAQD,sBAAsB,KAAK,IAAIA,oBAAoBD;QACvH,oDAAoD;QACpD,MAAMG,oBAAoB;YACtBC,gBAAgBL;YAChBG,UAAUA,WAAW,IAAI,cAAc;YACvCG,WAAWN,UAAUG,WAAW,IAAI,QAAQ,YAAY;QAC5D;QACAZ,eAAegB,UAAU,CAACX,SAASQ;IACvC,GAAG;QACCb;KACH;IACD,OAAOE;AACX"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "useDomAnnounce_unstable", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return useDomAnnounce_unstable;
9
+ }
10
+ });
11
+ const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
12
+ const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
13
+ const _reactutilities = require("@fluentui/react-utilities");
14
+ const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
15
+ /** The duration the message needs to be in present in DOM for screen readers to register a change and announce */ const MESSAGE_DURATION = 500;
16
+ const VISUALLY_HIDDEN_STYLES = {
17
+ clip: 'rect(0px, 0px, 0px, 0px)',
18
+ height: '1px',
19
+ margin: '-1px',
20
+ width: '1px',
21
+ position: 'absolute',
22
+ overflow: 'hidden',
23
+ textWrap: 'nowrap'
24
+ };
25
+ const useDomAnnounce_unstable = ()=>{
26
+ const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
27
+ const timeoutRef = _react.useRef(undefined);
28
+ const [setAnnounceTimeout, clearAnnounceTimeout] = (0, _reactutilities.useTimeout)();
29
+ const elementRef = _react.useRef(null);
30
+ const order = _react.useRef(0);
31
+ // investigate alert implementation later
32
+ // const [alertList, setAlertList] = React.useState<string[]>([]);
33
+ const batchMessages = _react.useRef([]);
34
+ const [messageQueue] = _react.useState(()=>(0, _reactutilities.createPriorityQueue)((a, b)=>{
35
+ if (a.priority !== b.priority) {
36
+ return b.priority - a.priority;
37
+ }
38
+ return a.createdAt - b.createdAt;
39
+ }));
40
+ const queueMessage = _react.useCallback(()=>{
41
+ if (timeoutRef.current || !elementRef.current) {
42
+ return;
43
+ }
44
+ const runCycle = ()=>{
45
+ if (!elementRef.current) {
46
+ return;
47
+ }
48
+ if (targetDocument && messageQueue.peek()) {
49
+ // need a wrapping element for Narrator/Edge, which currently does not pick up text-only live region changes
50
+ // consistently
51
+ // if this is fixed, we can set textContent to the string directly
52
+ const wrappingEl = targetDocument.createElement('span');
53
+ wrappingEl.innerText = messageQueue.all().filter((msg)=>msg.message.trim().length > 0).reduce((prevText, currMsg)=>prevText + currMsg.message + '. ', '');
54
+ elementRef.current.innerText = '';
55
+ elementRef.current.appendChild(wrappingEl);
56
+ messageQueue.clear();
57
+ batchMessages.current = [];
58
+ // begin new cycle to clear (or update) messages
59
+ timeoutRef.current = setAnnounceTimeout(()=>{
60
+ runCycle();
61
+ }, MESSAGE_DURATION);
62
+ } else {
63
+ elementRef.current.textContent = '';
64
+ clearAnnounceTimeout();
65
+ timeoutRef.current = undefined;
66
+ }
67
+ };
68
+ runCycle();
69
+ }, [
70
+ clearAnnounceTimeout,
71
+ messageQueue,
72
+ setAnnounceTimeout,
73
+ targetDocument
74
+ ]);
75
+ const announce = _react.useCallback((message, options = {})=>{
76
+ const { alert = false, priority = 0, batchId } = options;
77
+ // check if message is an alert
78
+ if (alert) {
79
+ // TODO: alert implementation
80
+ // setAlertList([...alertList, message]);
81
+ }
82
+ const liveMessage = {
83
+ message,
84
+ createdAt: order.current++,
85
+ priority,
86
+ batchId
87
+ };
88
+ // check if batchId exists
89
+ if (batchId) {
90
+ // update associated msg if it does
91
+ const batchMessage = batchMessages.current.find((msg)=>msg.batchId === batchId);
92
+ if (batchMessage) {
93
+ // replace existing message in queue
94
+ messageQueue.remove(batchMessage.message);
95
+ // update list of existing batchIds w/ most recent message
96
+ batchMessage.message = liveMessage;
97
+ } else {
98
+ // update list of existing batchIds, add new if doesn't already exist
99
+ batchMessages.current = [
100
+ ...batchMessages.current,
101
+ {
102
+ batchId,
103
+ message: liveMessage
104
+ }
105
+ ];
106
+ }
107
+ }
108
+ // add new message
109
+ messageQueue.enqueue(liveMessage);
110
+ queueMessage();
111
+ }, [
112
+ messageQueue,
113
+ queueMessage
114
+ ]);
115
+ _react.useEffect(()=>{
116
+ if (!targetDocument) {
117
+ return;
118
+ }
119
+ const element = targetDocument.createElement('div');
120
+ element.setAttribute('aria-live', 'assertive');
121
+ Object.assign(element.style, VISUALLY_HIDDEN_STYLES);
122
+ targetDocument.body.append(element);
123
+ elementRef.current = element;
124
+ return ()=>{
125
+ element.remove();
126
+ elementRef.current = null;
127
+ };
128
+ }, [
129
+ targetDocument
130
+ ]);
131
+ return announce;
132
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["useDomAnnounce.js"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { createPriorityQueue, useTimeout } from '@fluentui/react-utilities';\nimport * as React from 'react';\n/** The duration the message needs to be in present in DOM for screen readers to register a change and announce */ const MESSAGE_DURATION = 500;\nconst VISUALLY_HIDDEN_STYLES = {\n clip: 'rect(0px, 0px, 0px, 0px)',\n height: '1px',\n margin: '-1px',\n width: '1px',\n position: 'absolute',\n overflow: 'hidden',\n textWrap: 'nowrap'\n};\n/* INTERNAL: implementation of the announcer using a live region element */ export const useDomAnnounce_unstable = ()=>{\n const { targetDocument } = useFluent();\n const timeoutRef = React.useRef(undefined);\n const [setAnnounceTimeout, clearAnnounceTimeout] = useTimeout();\n const elementRef = React.useRef(null);\n const order = React.useRef(0);\n // investigate alert implementation later\n // const [alertList, setAlertList] = React.useState<string[]>([]);\n const batchMessages = React.useRef([]);\n const [messageQueue] = React.useState(()=>createPriorityQueue((a, b)=>{\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n return a.createdAt - b.createdAt;\n }));\n const queueMessage = React.useCallback(()=>{\n if (timeoutRef.current || !elementRef.current) {\n return;\n }\n const runCycle = ()=>{\n if (!elementRef.current) {\n return;\n }\n if (targetDocument && messageQueue.peek()) {\n // need a wrapping element for Narrator/Edge, which currently does not pick up text-only live region changes\n // consistently\n // if this is fixed, we can set textContent to the string directly\n const wrappingEl = targetDocument.createElement('span');\n wrappingEl.innerText = messageQueue.all().filter((msg)=>msg.message.trim().length > 0).reduce((prevText, currMsg)=>prevText + currMsg.message + '. ', '');\n elementRef.current.innerText = '';\n elementRef.current.appendChild(wrappingEl);\n messageQueue.clear();\n batchMessages.current = [];\n // begin new cycle to clear (or update) messages\n timeoutRef.current = setAnnounceTimeout(()=>{\n runCycle();\n }, MESSAGE_DURATION);\n } else {\n elementRef.current.textContent = '';\n clearAnnounceTimeout();\n timeoutRef.current = undefined;\n }\n };\n runCycle();\n }, [\n clearAnnounceTimeout,\n messageQueue,\n setAnnounceTimeout,\n targetDocument\n ]);\n const announce = React.useCallback((message, options = {})=>{\n const { alert = false, priority = 0, batchId } = options;\n // check if message is an alert\n if (alert) {\n // TODO: alert implementation\n // setAlertList([...alertList, message]);\n }\n const liveMessage = {\n message,\n createdAt: order.current++,\n priority,\n batchId\n };\n // check if batchId exists\n if (batchId) {\n // update associated msg if it does\n const batchMessage = batchMessages.current.find((msg)=>msg.batchId === batchId);\n if (batchMessage) {\n // replace existing message in queue\n messageQueue.remove(batchMessage.message);\n // update list of existing batchIds w/ most recent message\n batchMessage.message = liveMessage;\n } else {\n // update list of existing batchIds, add new if doesn't already exist\n batchMessages.current = [\n ...batchMessages.current,\n {\n batchId,\n message: liveMessage\n }\n ];\n }\n }\n // add new message\n messageQueue.enqueue(liveMessage);\n queueMessage();\n }, [\n messageQueue,\n queueMessage\n ]);\n React.useEffect(()=>{\n if (!targetDocument) {\n return;\n }\n const element = targetDocument.createElement('div');\n element.setAttribute('aria-live', 'assertive');\n Object.assign(element.style, VISUALLY_HIDDEN_STYLES);\n targetDocument.body.append(element);\n elementRef.current = element;\n return ()=>{\n element.remove();\n elementRef.current = null;\n };\n }, [\n targetDocument\n ]);\n return announce;\n};\n"],"names":["useDomAnnounce_unstable","MESSAGE_DURATION","VISUALLY_HIDDEN_STYLES","clip","height","margin","width","position","overflow","textWrap","targetDocument","useFluent","timeoutRef","React","useRef","undefined","setAnnounceTimeout","clearAnnounceTimeout","useTimeout","elementRef","order","batchMessages","messageQueue","useState","createPriorityQueue","a","b","priority","createdAt","queueMessage","useCallback","current","runCycle","peek","wrappingEl","createElement","innerText","all","filter","msg","message","trim","length","reduce","prevText","currMsg","appendChild","clear","textContent","announce","options","alert","batchId","liveMessage","batchMessage","find","remove","enqueue","useEffect","element","setAttribute","Object","assign","style","body","append"],"mappings":"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"}
@@ -29,6 +29,7 @@ const activeDescendantContextDefaultValue = {
29
29
  find: noop,
30
30
  first: noop,
31
31
  focus: noop,
32
+ focusLastActive: noop,
32
33
  last: noop,
33
34
  next: noop,
34
35
  prev: noop,
@@ -1 +1 @@
1
- {"version":3,"sources":["ActiveDescendantContext.js"],"sourcesContent":["import * as React from 'react';\nconst noop = ()=>undefined;\nconst activeDescendantContextDefaultValue = {\n controller: {\n active: noop,\n blur: noop,\n find: noop,\n first: noop,\n focus: noop,\n last: noop,\n next: noop,\n prev: noop,\n showAttributes: noop,\n hideAttributes: noop\n }\n};\nconst ActiveDescendantContext = React.createContext(undefined);\nexport const ActiveDescendantContextProvider = ActiveDescendantContext.Provider;\nexport const useActiveDescendantContext = ()=>{\n var _React_useContext;\n return (_React_useContext = React.useContext(ActiveDescendantContext)) !== null && _React_useContext !== void 0 ? _React_useContext : activeDescendantContextDefaultValue;\n};\nexport const useHasParentActiveDescendantContext = ()=>!!React.useContext(ActiveDescendantContext);\n"],"names":["ActiveDescendantContextProvider","useActiveDescendantContext","useHasParentActiveDescendantContext","noop","undefined","activeDescendantContextDefaultValue","controller","active","blur","find","first","focus","last","next","prev","showAttributes","hideAttributes","ActiveDescendantContext","React","createContext","Provider","_React_useContext","useContext"],"mappings":";;;;;;;;;;;IAiBaA,+BAA+B;eAA/BA;;IACAC,0BAA0B;eAA1BA;;IAIAC,mCAAmC;eAAnCA;;;;iEAtBU;AACvB,MAAMC,OAAO,IAAIC;AACjB,MAAMC,sCAAsC;IACxCC,YAAY;QACRC,QAAQJ;QACRK,MAAML;QACNM,MAAMN;QACNO,OAAOP;QACPQ,OAAOR;QACPS,MAAMT;QACNU,MAAMV;QACNW,MAAMX;QACNY,gBAAgBZ;QAChBa,gBAAgBb;IACpB;AACJ;AACA,MAAMc,wCAA0BC,OAAMC,aAAa,CAACf;AAC7C,MAAMJ,kCAAkCiB,wBAAwBG,QAAQ;AACxE,MAAMnB,6BAA6B;IACtC,IAAIoB;IACJ,OAAO,AAACA,CAAAA,oBAAoBH,OAAMI,UAAU,CAACL,wBAAuB,MAAO,QAAQI,sBAAsB,KAAK,IAAIA,oBAAoBhB;AAC1I;AACO,MAAMH,sCAAsC,IAAI,CAAC,CAACgB,OAAMI,UAAU,CAACL"}
1
+ {"version":3,"sources":["ActiveDescendantContext.js"],"sourcesContent":["import * as React from 'react';\nconst noop = ()=>undefined;\nconst activeDescendantContextDefaultValue = {\n controller: {\n active: noop,\n blur: noop,\n find: noop,\n first: noop,\n focus: noop,\n focusLastActive: noop,\n last: noop,\n next: noop,\n prev: noop,\n showAttributes: noop,\n hideAttributes: noop\n }\n};\nconst ActiveDescendantContext = React.createContext(undefined);\nexport const ActiveDescendantContextProvider = ActiveDescendantContext.Provider;\nexport const useActiveDescendantContext = ()=>{\n var _React_useContext;\n return (_React_useContext = React.useContext(ActiveDescendantContext)) !== null && _React_useContext !== void 0 ? _React_useContext : activeDescendantContextDefaultValue;\n};\nexport const useHasParentActiveDescendantContext = ()=>!!React.useContext(ActiveDescendantContext);\n"],"names":["ActiveDescendantContextProvider","useActiveDescendantContext","useHasParentActiveDescendantContext","noop","undefined","activeDescendantContextDefaultValue","controller","active","blur","find","first","focus","focusLastActive","last","next","prev","showAttributes","hideAttributes","ActiveDescendantContext","React","createContext","Provider","_React_useContext","useContext"],"mappings":";;;;;;;;;;;IAkBaA,+BAA+B;eAA/BA;;IACAC,0BAA0B;eAA1BA;;IAIAC,mCAAmC;eAAnCA;;;;iEAvBU;AACvB,MAAMC,OAAO,IAAIC;AACjB,MAAMC,sCAAsC;IACxCC,YAAY;QACRC,QAAQJ;QACRK,MAAML;QACNM,MAAMN;QACNO,OAAOP;QACPQ,OAAOR;QACPS,iBAAiBT;QACjBU,MAAMV;QACNW,MAAMX;QACNY,MAAMZ;QACNa,gBAAgBb;QAChBc,gBAAgBd;IACpB;AACJ;AACA,MAAMe,wCAA0BC,OAAMC,aAAa,CAAChB;AAC7C,MAAMJ,kCAAkCkB,wBAAwBG,QAAQ;AACxE,MAAMpB,6BAA6B;IACtC,IAAIqB;IACJ,OAAO,AAACA,CAAAA,oBAAoBH,OAAMI,UAAU,CAACL,wBAAuB,MAAO,QAAQI,sBAAsB,KAAK,IAAIA,oBAAoBjB;AAC1I;AACO,MAAMH,sCAAsC,IAAI,CAAC,CAACiB,OAAMI,UAAU,CAACL"}
@@ -8,22 +8,57 @@ Object.defineProperty(exports, "scrollIntoView", {
8
8
  return scrollIntoView;
9
9
  }
10
10
  });
11
- const scrollIntoView = (target, scrollParent)=>{
12
- if (!target || !scrollParent) {
11
+ const scrollIntoView = (target)=>{
12
+ if (!target) {
13
13
  return;
14
14
  }
15
- if (scrollParent.offsetHeight >= scrollParent.scrollHeight) {
15
+ const scrollParent = findScrollableParent(target.parentElement);
16
+ if (!scrollParent) {
16
17
  return;
17
18
  }
18
- const { offsetHeight, offsetTop } = target;
19
+ const { offsetHeight } = target;
20
+ const offsetTop = getTotalOffsetTop(target, scrollParent);
21
+ const { scrollMarginTop, scrollMarginBottom } = getScrollMargins(target);
19
22
  const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent;
20
- const isAbove = offsetTop < scrollTop;
21
- const isBelow = offsetTop + offsetHeight > scrollTop + parentOffsetHeight;
23
+ const isAbove = offsetTop - scrollMarginTop < scrollTop;
24
+ const isBelow = offsetTop + offsetHeight + scrollMarginBottom > scrollTop + parentOffsetHeight;
22
25
  const buffer = 2;
23
26
  if (isAbove) {
24
- scrollParent.scrollTo(0, offsetTop - buffer);
27
+ scrollParent.scrollTo(0, offsetTop - scrollMarginTop - buffer);
28
+ } else if (isBelow) {
29
+ scrollParent.scrollTo(0, offsetTop + offsetHeight + scrollMarginBottom - parentOffsetHeight + buffer);
25
30
  }
26
- if (isBelow) {
27
- scrollParent.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight + buffer);
31
+ };
32
+ const findScrollableParent = (element)=>{
33
+ if (!element) {
34
+ return null;
35
+ }
36
+ if (element.scrollHeight > element.offsetHeight) {
37
+ return element;
38
+ }
39
+ return findScrollableParent(element.parentElement);
40
+ };
41
+ const getTotalOffsetTop = (element, scrollParent)=>{
42
+ if (!element || element === scrollParent) {
43
+ return 0;
28
44
  }
45
+ if (element.contains(scrollParent)) {
46
+ // subtract the scroll parent's offset top from the running total if the offsetParent is above it
47
+ return scrollParent.offsetTop * -1;
48
+ }
49
+ return element.offsetTop + getTotalOffsetTop(element.offsetParent, scrollParent);
50
+ };
51
+ const getScrollMargins = (element)=>{
52
+ const computedStyles = getComputedStyle(element);
53
+ var _getIntValueOfComputedStyle;
54
+ const scrollMarginTop = (_getIntValueOfComputedStyle = getIntValueOfComputedStyle(computedStyles.scrollMarginTop)) !== null && _getIntValueOfComputedStyle !== void 0 ? _getIntValueOfComputedStyle : getIntValueOfComputedStyle(computedStyles.scrollMarginBlockStart);
55
+ var _getIntValueOfComputedStyle1;
56
+ const scrollMarginBottom = (_getIntValueOfComputedStyle1 = getIntValueOfComputedStyle(computedStyles.scrollMarginBottom)) !== null && _getIntValueOfComputedStyle1 !== void 0 ? _getIntValueOfComputedStyle1 : getIntValueOfComputedStyle(computedStyles.scrollMarginBlockEnd);
57
+ return {
58
+ scrollMarginTop,
59
+ scrollMarginBottom
60
+ };
61
+ };
62
+ const getIntValueOfComputedStyle = (computedStyle)=>{
63
+ return computedStyle ? parseInt(computedStyle, 10) : 0;
29
64
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["scrollIntoView.js"],"sourcesContent":["export const scrollIntoView = (target, scrollParent)=>{\n if (!target || !scrollParent) {\n return;\n }\n if (scrollParent.offsetHeight >= scrollParent.scrollHeight) {\n return;\n }\n const { offsetHeight, offsetTop } = target;\n const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent;\n const isAbove = offsetTop < scrollTop;\n const isBelow = offsetTop + offsetHeight > scrollTop + parentOffsetHeight;\n const buffer = 2;\n if (isAbove) {\n scrollParent.scrollTo(0, offsetTop - buffer);\n }\n if (isBelow) {\n scrollParent.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight + buffer);\n }\n};\n"],"names":["scrollIntoView","target","scrollParent","offsetHeight","scrollHeight","offsetTop","parentOffsetHeight","scrollTop","isAbove","isBelow","buffer","scrollTo"],"mappings":";;;;+BAAaA;;;eAAAA;;;AAAN,MAAMA,iBAAiB,CAACC,QAAQC;IACnC,IAAI,CAACD,UAAU,CAACC,cAAc;QAC1B;IACJ;IACA,IAAIA,aAAaC,YAAY,IAAID,aAAaE,YAAY,EAAE;QACxD;IACJ;IACA,MAAM,EAAED,YAAY,EAAEE,SAAS,EAAE,GAAGJ;IACpC,MAAM,EAAEE,cAAcG,kBAAkB,EAAEC,SAAS,EAAE,GAAGL;IACxD,MAAMM,UAAUH,YAAYE;IAC5B,MAAME,UAAUJ,YAAYF,eAAeI,YAAYD;IACvD,MAAMI,SAAS;IACf,IAAIF,SAAS;QACTN,aAAaS,QAAQ,CAAC,GAAGN,YAAYK;IACzC;IACA,IAAID,SAAS;QACTP,aAAaS,QAAQ,CAAC,GAAGN,YAAYC,qBAAqBH,eAAeO;IAC7E;AACJ"}
1
+ {"version":3,"sources":["scrollIntoView.js"],"sourcesContent":["export const scrollIntoView = (target)=>{\n if (!target) {\n return;\n }\n const scrollParent = findScrollableParent(target.parentElement);\n if (!scrollParent) {\n return;\n }\n const { offsetHeight } = target;\n const offsetTop = getTotalOffsetTop(target, scrollParent);\n const { scrollMarginTop, scrollMarginBottom } = getScrollMargins(target);\n const { offsetHeight: parentOffsetHeight, scrollTop } = scrollParent;\n const isAbove = offsetTop - scrollMarginTop < scrollTop;\n const isBelow = offsetTop + offsetHeight + scrollMarginBottom > scrollTop + parentOffsetHeight;\n const buffer = 2;\n if (isAbove) {\n scrollParent.scrollTo(0, offsetTop - scrollMarginTop - buffer);\n } else if (isBelow) {\n scrollParent.scrollTo(0, offsetTop + offsetHeight + scrollMarginBottom - parentOffsetHeight + buffer);\n }\n};\nconst findScrollableParent = (element)=>{\n if (!element) {\n return null;\n }\n if (element.scrollHeight > element.offsetHeight) {\n return element;\n }\n return findScrollableParent(element.parentElement);\n};\nconst getTotalOffsetTop = (element, scrollParent)=>{\n if (!element || element === scrollParent) {\n return 0;\n }\n if (element.contains(scrollParent)) {\n // subtract the scroll parent's offset top from the running total if the offsetParent is above it\n return scrollParent.offsetTop * -1;\n }\n return element.offsetTop + getTotalOffsetTop(element.offsetParent, scrollParent);\n};\nconst getScrollMargins = (element)=>{\n const computedStyles = getComputedStyle(element);\n var _getIntValueOfComputedStyle;\n const scrollMarginTop = (_getIntValueOfComputedStyle = getIntValueOfComputedStyle(computedStyles.scrollMarginTop)) !== null && _getIntValueOfComputedStyle !== void 0 ? _getIntValueOfComputedStyle : getIntValueOfComputedStyle(computedStyles.scrollMarginBlockStart);\n var _getIntValueOfComputedStyle1;\n const scrollMarginBottom = (_getIntValueOfComputedStyle1 = getIntValueOfComputedStyle(computedStyles.scrollMarginBottom)) !== null && _getIntValueOfComputedStyle1 !== void 0 ? _getIntValueOfComputedStyle1 : getIntValueOfComputedStyle(computedStyles.scrollMarginBlockEnd);\n return {\n scrollMarginTop,\n scrollMarginBottom\n };\n};\nconst getIntValueOfComputedStyle = (computedStyle)=>{\n return computedStyle ? parseInt(computedStyle, 10) : 0;\n};\n"],"names":["scrollIntoView","target","scrollParent","findScrollableParent","parentElement","offsetHeight","offsetTop","getTotalOffsetTop","scrollMarginTop","scrollMarginBottom","getScrollMargins","parentOffsetHeight","scrollTop","isAbove","isBelow","buffer","scrollTo","element","scrollHeight","contains","offsetParent","computedStyles","getComputedStyle","_getIntValueOfComputedStyle","getIntValueOfComputedStyle","scrollMarginBlockStart","_getIntValueOfComputedStyle1","scrollMarginBlockEnd","computedStyle","parseInt"],"mappings":";;;;+BAAaA;;;eAAAA;;;AAAN,MAAMA,iBAAiB,CAACC;IAC3B,IAAI,CAACA,QAAQ;QACT;IACJ;IACA,MAAMC,eAAeC,qBAAqBF,OAAOG,aAAa;IAC9D,IAAI,CAACF,cAAc;QACf;IACJ;IACA,MAAM,EAAEG,YAAY,EAAE,GAAGJ;IACzB,MAAMK,YAAYC,kBAAkBN,QAAQC;IAC5C,MAAM,EAAEM,eAAe,EAAEC,kBAAkB,EAAE,GAAGC,iBAAiBT;IACjE,MAAM,EAAEI,cAAcM,kBAAkB,EAAEC,SAAS,EAAE,GAAGV;IACxD,MAAMW,UAAUP,YAAYE,kBAAkBI;IAC9C,MAAME,UAAUR,YAAYD,eAAeI,qBAAqBG,YAAYD;IAC5E,MAAMI,SAAS;IACf,IAAIF,SAAS;QACTX,aAAac,QAAQ,CAAC,GAAGV,YAAYE,kBAAkBO;IAC3D,OAAO,IAAID,SAAS;QAChBZ,aAAac,QAAQ,CAAC,GAAGV,YAAYD,eAAeI,qBAAqBE,qBAAqBI;IAClG;AACJ;AACA,MAAMZ,uBAAuB,CAACc;IAC1B,IAAI,CAACA,SAAS;QACV,OAAO;IACX;IACA,IAAIA,QAAQC,YAAY,GAAGD,QAAQZ,YAAY,EAAE;QAC7C,OAAOY;IACX;IACA,OAAOd,qBAAqBc,QAAQb,aAAa;AACrD;AACA,MAAMG,oBAAoB,CAACU,SAASf;IAChC,IAAI,CAACe,WAAWA,YAAYf,cAAc;QACtC,OAAO;IACX;IACA,IAAIe,QAAQE,QAAQ,CAACjB,eAAe;QAChC,iGAAiG;QACjG,OAAOA,aAAaI,SAAS,GAAG,CAAC;IACrC;IACA,OAAOW,QAAQX,SAAS,GAAGC,kBAAkBU,QAAQG,YAAY,EAAElB;AACvE;AACA,MAAMQ,mBAAmB,CAACO;IACtB,MAAMI,iBAAiBC,iBAAiBL;IACxC,IAAIM;IACJ,MAAMf,kBAAkB,AAACe,CAAAA,8BAA8BC,2BAA2BH,eAAeb,eAAe,CAAA,MAAO,QAAQe,gCAAgC,KAAK,IAAIA,8BAA8BC,2BAA2BH,eAAeI,sBAAsB;IACtQ,IAAIC;IACJ,MAAMjB,qBAAqB,AAACiB,CAAAA,+BAA+BF,2BAA2BH,eAAeZ,kBAAkB,CAAA,MAAO,QAAQiB,iCAAiC,KAAK,IAAIA,+BAA+BF,2BAA2BH,eAAeM,oBAAoB;IAC7Q,OAAO;QACHnB;QACAC;IACJ;AACJ;AACA,MAAMe,6BAA6B,CAACI;IAChC,OAAOA,gBAAgBC,SAASD,eAAe,MAAM;AACzD"}
@@ -2,9 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "useActiveDescendant", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ createActiveDescendantChangeEvent: function() {
13
+ return createActiveDescendantChangeEvent;
14
+ },
15
+ useActiveDescendant: function() {
8
16
  return useActiveDescendant;
9
17
  }
10
18
  });
@@ -15,10 +23,17 @@ const _reacttabster = require("@fluentui/react-tabster");
15
23
  const _useOptionWalker = require("./useOptionWalker");
16
24
  const _constants = require("./constants");
17
25
  const _scrollIntoView = require("./scrollIntoView");
26
+ const createActiveDescendantChangeEvent = (detail)=>new CustomEvent('activedescendantchange', {
27
+ bubbles: true,
28
+ cancelable: false,
29
+ composed: true,
30
+ detail
31
+ });
18
32
  function useActiveDescendant(options) {
19
33
  const { imperativeRef, matchOption: matchOptionUnstable } = options;
20
34
  const focusVisibleRef = _react.useRef(false);
21
35
  const activeIdRef = _react.useRef(null);
36
+ const lastActiveIdRef = _react.useRef(null);
22
37
  const activeParentRef = _react.useRef(null);
23
38
  const attributeVisibilityRef = _react.useRef(true);
24
39
  const removeAttribute = _react.useCallback(()=>{
@@ -64,7 +79,10 @@ function useActiveDescendant(options) {
64
79
  active.removeAttribute(_constants.ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE);
65
80
  }
66
81
  removeAttribute();
82
+ lastActiveIdRef.current = activeIdRef.current;
67
83
  activeIdRef.current = null;
84
+ var _active_id;
85
+ return (_active_id = active === null || active === void 0 ? void 0 : active.id) !== null && _active_id !== void 0 ? _active_id : null;
68
86
  }, [
69
87
  getActiveDescendant,
70
88
  removeAttribute
@@ -73,15 +91,19 @@ function useActiveDescendant(options) {
73
91
  if (!nextActive) {
74
92
  return;
75
93
  }
76
- blurActiveDescendant();
77
- (0, _scrollIntoView.scrollIntoView)(nextActive, listboxRef.current);
94
+ const previousActiveId = blurActiveDescendant();
95
+ (0, _scrollIntoView.scrollIntoView)(nextActive);
78
96
  setAttribute(nextActive.id);
79
97
  nextActive.setAttribute(_constants.ACTIVEDESCENDANT_ATTRIBUTE, '');
80
98
  if (focusVisibleRef.current) {
81
99
  nextActive.setAttribute(_constants.ACTIVEDESCENDANT_FOCUSVISIBLE_ATTRIBUTE, '');
82
100
  }
101
+ const event = createActiveDescendantChangeEvent({
102
+ id: nextActive.id,
103
+ previousId: previousActiveId
104
+ });
105
+ nextActive.dispatchEvent(event);
83
106
  }, [
84
- listboxRef,
85
107
  blurActiveDescendant,
86
108
  setAttribute
87
109
  ]);
@@ -140,6 +162,16 @@ function useActiveDescendant(options) {
140
162
  focusActiveDescendant(target);
141
163
  }
142
164
  },
165
+ focusLastActive: ()=>{
166
+ if (!listboxRef.current || !lastActiveIdRef.current) {
167
+ return;
168
+ }
169
+ const target = listboxRef.current.querySelector(`#${lastActiveIdRef.current}`);
170
+ if (target) {
171
+ focusActiveDescendant(target);
172
+ return true;
173
+ }
174
+ },
143
175
  find (predicate, { passive, startFrom } = {}) {
144
176
  const target = optionWalker.find(predicate, startFrom);
145
177
  if (!passive) {