@radix-ui/react-toast 0.1.2-rc.48 → 0.1.2-rc.50

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.
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/react/toast/src/packages/react/toast/src/Toast.tsx","packages/react/toast/src/packages/react/toast/src/index.ts","packages/react/toast/src/index.ts"],"sourcesContent":[null,null,"export * from './Toast';\n"],"names":[],"version":3,"file":"index.d.ts.map"}
1
+ {"mappings":"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","sources":["packages/react/toast/src/packages/react/toast/src/Toast.tsx","packages/react/toast/src/packages/react/toast/src/index.ts","packages/react/toast/src/index.ts"],"sourcesContent":[null,null,"export * from './Toast';\n"],"names":[],"version":3,"file":"index.d.ts.map"}
package/dist/index.js CHANGED
@@ -3,11 +3,12 @@ var $iTyic$react = require("react");
3
3
  var $iTyic$reactdom = require("react-dom");
4
4
  var $iTyic$radixuiprimitive = require("@radix-ui/primitive");
5
5
  var $iTyic$radixuireactcomposerefs = require("@radix-ui/react-compose-refs");
6
+ var $iTyic$radixuireactcollection = require("@radix-ui/react-collection");
6
7
  var $iTyic$radixuireactcontext = require("@radix-ui/react-context");
7
8
  var $iTyic$radixuireactdismissablelayer = require("@radix-ui/react-dismissable-layer");
8
- var $iTyic$radixuireactportal = require("@radix-ui/react-portal");
9
9
  var $iTyic$radixuireactpresence = require("@radix-ui/react-presence");
10
10
  var $iTyic$radixuireactprimitive = require("@radix-ui/react-primitive");
11
+ var $iTyic$radixuireactslot = require("@radix-ui/react-slot");
11
12
  var $iTyic$radixuireactusecallbackref = require("@radix-ui/react-use-callback-ref");
12
13
  var $iTyic$radixuireactusecontrollablestate = require("@radix-ui/react-use-controllable-state");
13
14
  var $iTyic$radixuireactuselayouteffect = require("@radix-ui/react-use-layout-effect");
@@ -66,10 +67,14 @@ $parcel$export($9208a85b3e79d33f$exports, "Close", () => $9208a85b3e79d33f$expor
66
67
 
67
68
 
68
69
 
70
+
69
71
  /* -------------------------------------------------------------------------------------------------
70
72
  * ToastProvider
71
73
  * -----------------------------------------------------------------------------------------------*/ const $9208a85b3e79d33f$var$PROVIDER_NAME = 'ToastProvider';
72
- const [$9208a85b3e79d33f$var$createToastContext, $9208a85b3e79d33f$export$8a359da18fbc9073] = $iTyic$radixuireactcontext.createContextScope('Toast');
74
+ const [$9208a85b3e79d33f$var$Collection, $9208a85b3e79d33f$var$useCollection, $9208a85b3e79d33f$var$createCollectionScope] = $iTyic$radixuireactcollection.createCollection('Toast');
75
+ const [$9208a85b3e79d33f$var$createToastContext, $9208a85b3e79d33f$export$8a359da18fbc9073] = $iTyic$radixuireactcontext.createContextScope('Toast', [
76
+ $9208a85b3e79d33f$var$createCollectionScope
77
+ ]);
73
78
  const [$9208a85b3e79d33f$var$ToastProviderProvider, $9208a85b3e79d33f$var$useToastProviderContext] = $9208a85b3e79d33f$var$createToastContext($9208a85b3e79d33f$var$PROVIDER_NAME);
74
79
  const $9208a85b3e79d33f$export$f5d03d415824e0e = (props)=>{
75
80
  const { __scopeToast: __scopeToast , label: label = 'Notification' , duration: duration = 5000 , swipeDirection: swipeDirection = 'right' , swipeThreshold: swipeThreshold = 50 , children: children } = props;
@@ -77,7 +82,9 @@ const $9208a85b3e79d33f$export$f5d03d415824e0e = (props)=>{
77
82
  const [toastCount, setToastCount] = $iTyic$react.useState(0);
78
83
  const isFocusedToastEscapeKeyDownRef = $iTyic$react.useRef(false);
79
84
  const isClosePausedRef = $iTyic$react.useRef(false);
80
- return /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$ToastProviderProvider, {
85
+ return /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$Collection.Provider, {
86
+ scope: __scopeToast
87
+ }, /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$ToastProviderProvider, {
81
88
  scope: __scopeToast,
82
89
  label: label,
83
90
  duration: duration,
@@ -94,7 +101,16 @@ const $9208a85b3e79d33f$export$f5d03d415824e0e = (props)=>{
94
101
  , []),
95
102
  isFocusedToastEscapeKeyDownRef: isFocusedToastEscapeKeyDownRef,
96
103
  isClosePausedRef: isClosePausedRef
97
- }, children);
104
+ }, children));
105
+ };
106
+ $9208a85b3e79d33f$export$f5d03d415824e0e.propTypes = {
107
+ label (props) {
108
+ if (props.label && typeof props.label === 'string' && !props.label.trim()) {
109
+ const error = `Invalid prop \`label\` supplied to \`${$9208a85b3e79d33f$var$PROVIDER_NAME}\`. Expected non-empty \`string\`.`;
110
+ return new Error(error);
111
+ }
112
+ return null;
113
+ }
98
114
  };
99
115
  /*#__PURE__*/ Object.assign($9208a85b3e79d33f$export$f5d03d415824e0e, {
100
116
  displayName: $9208a85b3e79d33f$var$PROVIDER_NAME
@@ -110,10 +126,14 @@ const $9208a85b3e79d33f$var$VIEWPORT_RESUME = 'toast.viewportResume';
110
126
  const $9208a85b3e79d33f$export$6192c2425ecfd989 = /*#__PURE__*/ $iTyic$react.forwardRef((props, forwardedRef)=>{
111
127
  const { __scopeToast: __scopeToast , hotkey: hotkey = $9208a85b3e79d33f$var$VIEWPORT_DEFAULT_HOTKEY , label: label = 'Notifications ({hotkey})' , ...viewportProps } = props;
112
128
  const context = $9208a85b3e79d33f$var$useToastProviderContext($9208a85b3e79d33f$var$VIEWPORT_NAME, __scopeToast);
129
+ const getItems = $9208a85b3e79d33f$var$useCollection(__scopeToast);
113
130
  const wrapperRef = $iTyic$react.useRef(null);
131
+ const headFocusProxyRef = $iTyic$react.useRef(null);
132
+ const tailFocusProxyRef = $iTyic$react.useRef(null);
114
133
  const ref = $iTyic$react.useRef(null);
115
134
  const composedRefs = $iTyic$radixuireactcomposerefs.useComposedRefs(forwardedRef, ref, context.onViewportChange);
116
135
  const hotkeyLabel = hotkey.join('+').replace(/Key/g, '').replace(/Digit/g, '');
136
+ const hasToasts = context.toastCount > 0;
117
137
  $iTyic$react.useEffect(()=>{
118
138
  const handleKeyDown = (event)=>{
119
139
  var _ref$current;
@@ -161,33 +181,62 @@ const $9208a85b3e79d33f$export$6192c2425ecfd989 = /*#__PURE__*/ $iTyic$react.for
161
181
  }, [
162
182
  context.isClosePausedRef
163
183
  ]);
184
+ const getSortedTabbableCandidates = $iTyic$react.useCallback(({ tabbingDirection: tabbingDirection })=>{
185
+ const toastItems = getItems();
186
+ const tabbableCandidates = toastItems.map((toastItem)=>{
187
+ const toastNode = toastItem.ref.current;
188
+ const toastTabbableCandidates = [
189
+ toastNode,
190
+ ...$9208a85b3e79d33f$var$getTabbableCandidates(toastNode)
191
+ ];
192
+ return tabbingDirection === 'forwards' ? toastTabbableCandidates : toastTabbableCandidates.reverse();
193
+ });
194
+ return (tabbingDirection === 'forwards' ? tabbableCandidates.reverse() : tabbableCandidates).flat();
195
+ }, [
196
+ getItems
197
+ ]);
164
198
  $iTyic$react.useEffect(()=>{
165
- const viewport = ref.current; // Re-order DOM so most recent toasts are at top of DOM structure to improve tab order
199
+ const viewport = ref.current; // We programmatically manage tabbing as we are unable to influence
200
+ // the source order with portals, this allows us to reverse the
201
+ // tab order so that it runs from most recent toast to least
166
202
  if (viewport) {
167
- const prepended = new Set();
168
- const observer = new MutationObserver((mutations)=>{
169
- const addedNodes = mutations.map((mutation)=>Array.from(mutation.addedNodes)
170
- ).reduce((a, b)=>a.concat(b)
171
- );
172
- addedNodes.forEach((node)=>{
173
- // mutation will immediately fire again when we prepend so we only prepend if
174
- // it hasn't just prepended.
175
- if (!prepended.has(node)) {
176
- viewport.prepend(node);
177
- prepended.add(node);
178
- } else // this else catches the case where the mutation fires immediately after prepend.
179
- // we remove from cache after it prepends to allow observer to catch future updates
180
- // to DOM order, e.g. if `key` changes for a toast and is reportalled to bottom.
181
- prepended.delete(node);
182
- });
183
- });
184
- observer.observe(viewport, {
185
- childList: true
186
- });
187
- return ()=>observer.disconnect()
203
+ const handleKeyDown = (event)=>{
204
+ const isMetaKey = event.altKey || event.ctrlKey || event.metaKey;
205
+ const isTabKey = event.key === 'Tab' && !isMetaKey;
206
+ if (isTabKey) {
207
+ const focusedElement = document.activeElement;
208
+ const isTabbingBackwards = event.shiftKey;
209
+ const targetIsViewport = event.target === viewport; // If we're back tabbing after jumping to the viewport then we simply
210
+ // proxy focus out to the preceding document
211
+ if (targetIsViewport && isTabbingBackwards) {
212
+ var _headFocusProxyRef$cu;
213
+ (_headFocusProxyRef$cu = headFocusProxyRef.current) === null || _headFocusProxyRef$cu === void 0 || _headFocusProxyRef$cu.focus();
214
+ return;
215
+ }
216
+ const tabbingDirection = isTabbingBackwards ? 'backwards' : 'forwards';
217
+ const sortedCandidates = getSortedTabbableCandidates({
218
+ tabbingDirection: tabbingDirection
219
+ });
220
+ const index = sortedCandidates.findIndex((candidate)=>candidate === focusedElement
221
+ );
222
+ if ($9208a85b3e79d33f$var$focusFirst(sortedCandidates.slice(index + 1))) event.preventDefault();
223
+ else {
224
+ var _headFocusProxyRef$cu2, _tailFocusProxyRef$cu;
225
+ // If we can't focus that means we're at the edges so we
226
+ // proxy to the corresponding exit point and let the browser handle
227
+ // tab/shift+tab keypress and implicitly pass focus to the next valid element in the document
228
+ isTabbingBackwards ? (_headFocusProxyRef$cu2 = headFocusProxyRef.current) === null || _headFocusProxyRef$cu2 === void 0 || _headFocusProxyRef$cu2.focus() : (_tailFocusProxyRef$cu = tailFocusProxyRef.current) === null || _tailFocusProxyRef$cu === void 0 || _tailFocusProxyRef$cu.focus();
229
+ }
230
+ }
231
+ }; // Toasts are not in the viewport React tree so we need to bind DOM events
232
+ viewport.addEventListener('keydown', handleKeyDown);
233
+ return ()=>viewport.removeEventListener('keydown', handleKeyDown)
188
234
  ;
189
235
  }
190
- }, []);
236
+ }, [
237
+ getItems,
238
+ getSortedTabbableCandidates
239
+ ]);
191
240
  return /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactdismissablelayer.Branch, {
192
241
  ref: wrapperRef,
193
242
  role: "region",
@@ -196,17 +245,59 @@ const $9208a85b3e79d33f$export$6192c2425ecfd989 = /*#__PURE__*/ $iTyic$react.for
196
245
  tabIndex: -1 // incase list has size when empty (e.g. padding), we remove pointer events so
197
246
  ,
198
247
  style: {
199
- pointerEvents: context.toastCount > 0 ? undefined : 'none'
248
+ pointerEvents: hasToasts ? undefined : 'none'
249
+ }
250
+ }, hasToasts && /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$FocusProxy, {
251
+ ref: headFocusProxyRef,
252
+ onFocusFromOutsideViewport: ()=>{
253
+ const tabbableCandidates = getSortedTabbableCandidates({
254
+ tabbingDirection: 'forwards'
255
+ });
256
+ $9208a85b3e79d33f$var$focusFirst(tabbableCandidates);
200
257
  }
258
+ }), /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$Collection.Slot, {
259
+ scope: __scopeToast
201
260
  }, /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactprimitive.Primitive.ol, ($parcel$interopDefault($iTyic$babelruntimehelpersextends))({
202
261
  tabIndex: -1
203
262
  }, viewportProps, {
204
263
  ref: composedRefs
205
- })));
264
+ }))), hasToasts && /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$FocusProxy, {
265
+ ref: tailFocusProxyRef,
266
+ onFocusFromOutsideViewport: ()=>{
267
+ const tabbableCandidates = getSortedTabbableCandidates({
268
+ tabbingDirection: 'backwards'
269
+ });
270
+ $9208a85b3e79d33f$var$focusFirst(tabbableCandidates);
271
+ }
272
+ }));
206
273
  });
207
274
  /*#__PURE__*/ Object.assign($9208a85b3e79d33f$export$6192c2425ecfd989, {
208
275
  displayName: $9208a85b3e79d33f$var$VIEWPORT_NAME
209
276
  });
277
+ /* -----------------------------------------------------------------------------------------------*/ const $9208a85b3e79d33f$var$FOCUS_PROXY_NAME = 'ToastFocusProxy';
278
+ const $9208a85b3e79d33f$var$FocusProxy = /*#__PURE__*/ $iTyic$react.forwardRef((props, forwardedRef)=>{
279
+ const { __scopeToast: __scopeToast , onFocusFromOutsideViewport: onFocusFromOutsideViewport , ...proxyProps } = props;
280
+ const context = $9208a85b3e79d33f$var$useToastProviderContext($9208a85b3e79d33f$var$FOCUS_PROXY_NAME, __scopeToast);
281
+ return /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactvisuallyhidden.VisuallyHidden, ($parcel$interopDefault($iTyic$babelruntimehelpersextends))({
282
+ "aria-hidden": true,
283
+ tabIndex: 0
284
+ }, proxyProps, {
285
+ ref: forwardedRef // Avoid page scrolling when focus is on the focus proxy
286
+ ,
287
+ style: {
288
+ position: 'fixed'
289
+ },
290
+ onFocus: (event)=>{
291
+ var _context$viewport;
292
+ const prevFocusedElement = event.relatedTarget;
293
+ const isFocusFromOutsideViewport = !((_context$viewport = context.viewport) !== null && _context$viewport !== void 0 && _context$viewport.contains(prevFocusedElement));
294
+ if (isFocusFromOutsideViewport) onFocusFromOutsideViewport();
295
+ }
296
+ }));
297
+ });
298
+ /*#__PURE__*/ Object.assign($9208a85b3e79d33f$var$FocusProxy, {
299
+ displayName: $9208a85b3e79d33f$var$FOCUS_PROXY_NAME
300
+ });
210
301
  /* -------------------------------------------------------------------------------------------------
211
302
  * Toast
212
303
  * -----------------------------------------------------------------------------------------------*/ const $9208a85b3e79d33f$var$TOAST_NAME = 'Toast';
@@ -264,7 +355,7 @@ const $9208a85b3e79d33f$export$8d8dc7d5f743331b = /*#__PURE__*/ $iTyic$react.for
264
355
  onClose () {}
265
356
  });
266
357
  const $9208a85b3e79d33f$var$ToastImpl = /*#__PURE__*/ $iTyic$react.forwardRef((props, forwardedRef)=>{
267
- const { __scopeToast: __scopeToast , type: type = 'foreground' , duration: durationProp , open: open , onClose: onClose , onEscapeKeyDown: onEscapeKeyDown , onSwipeStart: onSwipeStart , onSwipeMove: onSwipeMove , onSwipeCancel: onSwipeCancel , onSwipeEnd: onSwipeEnd , ...toastProps } = props;
358
+ const { __scopeToast: __scopeToast , children: children , type: type = 'foreground' , duration: durationProp , open: open , onClose: onClose , onEscapeKeyDown: onEscapeKeyDown , onSwipeStart: onSwipeStart , onSwipeMove: onSwipeMove , onSwipeCancel: onSwipeCancel , onSwipeEnd: onSwipeEnd , ...toastProps } = props;
268
359
  const context = $9208a85b3e79d33f$var$useToastProviderContext($9208a85b3e79d33f$var$TOAST_NAME, __scopeToast);
269
360
  const ref = $iTyic$react.useRef(null);
270
361
  const composedRefs = $iTyic$radixuireactcomposerefs.useComposedRefs(forwardedRef, ref);
@@ -274,13 +365,14 @@ const $9208a85b3e79d33f$var$ToastImpl = /*#__PURE__*/ $iTyic$react.forwardRef((p
274
365
  const closeTimerStartTimeRef = $iTyic$react.useRef(0);
275
366
  const closeTimerRemainingTimeRef = $iTyic$react.useRef(duration1);
276
367
  const closeTimerRef = $iTyic$react.useRef(0);
368
+ const [renderLabel, setRenderLabel] = $iTyic$react.useState(false);
277
369
  const { onToastAdd: onToastAdd , onToastRemove: onToastRemove } = context;
278
370
  const handleClose = $iTyic$radixuireactusecallbackref.useCallbackRef(()=>{
279
- var _ref$current2, _context$viewport;
371
+ var _ref$current2, _context$viewport2;
280
372
  // focus viewport if focus is within toast to read the remaining toast
281
373
  // count to SR users and ensure focus isn't lost
282
374
  const isFocusInToast = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.contains(document.activeElement);
283
- if (isFocusInToast) (_context$viewport = context.viewport) === null || _context$viewport === void 0 || _context$viewport.focus();
375
+ if (isFocusInToast) (_context$viewport2 = context.viewport) === null || _context$viewport2 === void 0 || _context$viewport2.focus();
284
376
  onClose();
285
377
  });
286
378
  const startTimer = $iTyic$react.useCallback((duration)=>{
@@ -331,19 +423,17 @@ const $9208a85b3e79d33f$var$ToastImpl = /*#__PURE__*/ $iTyic$react.forwardRef((p
331
423
  }, [
332
424
  onToastAdd,
333
425
  onToastRemove
334
- ]);
426
+ ]); // render label in the next frame to trigger toast announcement in NVDA
427
+ $9208a85b3e79d33f$var$useNextFrame(()=>setRenderLabel(true)
428
+ );
335
429
  if (!context.viewport) return null;
336
- return /*#__PURE__*/ $iTyic$react.createElement($iTyic$react.Fragment, null, /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$ToastAnnounce, {
337
- __scopeToast: __scopeToast // Toasts are always role=status to avoid stuttering issues with role=alert in SRs.
338
- ,
339
- role: "status",
340
- "aria-live": type === 'foreground' ? 'assertive' : 'polite',
341
- "aria-atomic": true
342
- }, props.children), /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$ToastInteractiveProvider, {
430
+ return /*#__PURE__*/ $iTyic$react.createElement($iTyic$react.Fragment, null, /*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$ToastInteractiveProvider, {
343
431
  scope: __scopeToast,
344
432
  isInteractive: true,
345
433
  onClose: handleClose
346
- }, /*#__PURE__*/ $iTyic$reactdom.createPortal(/*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactdismissablelayer.Root, {
434
+ }, /*#__PURE__*/ $iTyic$reactdom.createPortal(/*#__PURE__*/ $iTyic$react.createElement($9208a85b3e79d33f$var$Collection.ItemSlot, {
435
+ scope: __scopeToast
436
+ }, /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactdismissablelayer.Root, {
347
437
  asChild: true,
348
438
  onEscapeKeyDown: $iTyic$radixuiprimitive.composeEventHandlers(onEscapeKeyDown, ()=>{
349
439
  if (!context.isFocusedToastEscapeKeyDownRef.current) handleClose();
@@ -351,8 +441,10 @@ const $9208a85b3e79d33f$var$ToastImpl = /*#__PURE__*/ $iTyic$react.forwardRef((p
351
441
  })
352
442
  }, /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactprimitive.Primitive.li, ($parcel$interopDefault($iTyic$babelruntimehelpersextends))({
353
443
  role: "status",
354
- "aria-live": "off",
355
- "aria-atomic": true,
444
+ "aria-live": type === 'foreground' ? 'assertive' : 'polite',
445
+ "aria-atomic": true // Prevent voice over from announcing before the label is rendered
446
+ ,
447
+ "aria-hidden": !renderLabel || undefined,
356
448
  tabIndex: 0,
357
449
  "data-state": open ? 'open' : 'closed',
358
450
  "data-swipe-direction": context.swipeDirection
@@ -442,7 +534,7 @@ const $9208a85b3e79d33f$var$ToastImpl = /*#__PURE__*/ $iTyic$react.forwardRef((p
442
534
  });
443
535
  }
444
536
  })
445
- }))), context.viewport)));
537
+ }), /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactvisuallyhidden.VisuallyHidden, null, renderLabel && context.label), /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactslot.Slottable, null, children)))), context.viewport)));
446
538
  });
447
539
  $9208a85b3e79d33f$var$ToastImpl.propTypes = {
448
540
  type (props) {
@@ -451,30 +543,11 @@ $9208a85b3e79d33f$var$ToastImpl.propTypes = {
451
543
  'background'
452
544
  ].includes(props.type)) {
453
545
  const error = `Invalid prop \`type\` supplied to \`${$9208a85b3e79d33f$var$TOAST_NAME}\`. Expected \`foreground | background\`.`;
454
- throw new Error(error);
546
+ return new Error(error);
455
547
  }
456
548
  return null;
457
549
  }
458
550
  };
459
- /* -----------------------------------------------------------------------------------------------*/ const $9208a85b3e79d33f$var$ToastAnnounce = (props)=>{
460
- const { __scopeToast: __scopeToast , ...announceProps } = props;
461
- const context = $9208a85b3e79d33f$var$useToastProviderContext($9208a85b3e79d33f$var$TOAST_NAME, __scopeToast);
462
- const [renderChildren, setRenderChildren] = $iTyic$react.useState(false);
463
- const [isAnnounced, setIsAnnounced] = $iTyic$react.useState(false); // render children in the next frame to ensure toast is announced in NVDA
464
- $9208a85b3e79d33f$var$useNextFrame(()=>setRenderChildren(true)
465
- );
466
- $iTyic$react.useEffect(()=>{
467
- const timer = window.setTimeout(()=>setIsAnnounced(true)
468
- , 1000);
469
- return ()=>window.clearTimeout(timer)
470
- ;
471
- }, []);
472
- return isAnnounced ? null : /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactportal.Portal, {
473
- asChild: true
474
- }, /*#__PURE__*/ $iTyic$react.createElement($iTyic$radixuireactvisuallyhidden.VisuallyHidden, {
475
- asChild: true
476
- }, /*#__PURE__*/ $iTyic$react.createElement("div", announceProps, renderChildren && /*#__PURE__*/ $iTyic$react.createElement($iTyic$react.Fragment, null, context.label, " ", props.children))));
477
- };
478
551
  /* -------------------------------------------------------------------------------------------------
479
552
  * ToastTitle
480
553
  * -----------------------------------------------------------------------------------------------*/ const $9208a85b3e79d33f$var$TITLE_NAME = 'ToastTitle';
@@ -512,7 +585,7 @@ const $9208a85b3e79d33f$export$3019feecfda683d2 = /*#__PURE__*/ $iTyic$react.for
512
585
  });
513
586
  $9208a85b3e79d33f$export$3019feecfda683d2.propTypes = {
514
587
  altText (props) {
515
- if (!props.altText) throw new Error(`Missing prop \`altText\` expected on \`${$9208a85b3e79d33f$var$ACTION_NAME}\``);
588
+ if (!props.altText) return new Error(`Missing prop \`altText\` expected on \`${$9208a85b3e79d33f$var$ACTION_NAME}\``);
516
589
  return null;
517
590
  }
518
591
  };
@@ -570,6 +643,39 @@ function $9208a85b3e79d33f$var$useNextFrame(callback = ()=>{}) {
570
643
  fn
571
644
  ]);
572
645
  }
646
+ /**
647
+ * Returns a list of potential tabbable candidates.
648
+ *
649
+ * NOTE: This is only a close approximation. For example it doesn't take into account cases like when
650
+ * elements are not visible. This cannot be worked out easily by just reading a property, but rather
651
+ * necessitate runtime knowledge (computed styles, etc). We deal with these cases separately.
652
+ *
653
+ * See: https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
654
+ * Credit: https://github.com/discord/focus-layers/blob/master/src/util/wrapFocus.tsx#L1
655
+ */ function $9208a85b3e79d33f$var$getTabbableCandidates(container) {
656
+ const nodes = [];
657
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
658
+ acceptNode: (node)=>{
659
+ const isHiddenInput = node.tagName === 'INPUT' && node.type === 'hidden';
660
+ if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP; // `.tabIndex` is not the same as the `tabindex` attribute. It works on the
661
+ // runtime's understanding of tabbability, so this automatically accounts
662
+ // for any kind of element that could be tabbed to.
663
+ return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
664
+ }
665
+ });
666
+ while(walker.nextNode())nodes.push(walker.currentNode); // we do not take into account the order of nodes with positive `tabIndex` as it
667
+ // hinders accessibility to have tab order different from visual order.
668
+ return nodes;
669
+ }
670
+ function $9208a85b3e79d33f$var$focusFirst(candidates) {
671
+ const previouslyFocusedElement = document.activeElement;
672
+ return candidates.some((candidate)=>{
673
+ // if focus is already where we want to go, we don't want to keep going through the candidates
674
+ if (candidate === previouslyFocusedElement) return true;
675
+ candidate.focus();
676
+ return document.activeElement !== previouslyFocusedElement;
677
+ });
678
+ }
573
679
  const $9208a85b3e79d33f$export$2881499e37b75b9a = $9208a85b3e79d33f$export$f5d03d415824e0e;
574
680
  const $9208a85b3e79d33f$export$d5c6c08dc2d3ca7 = $9208a85b3e79d33f$export$6192c2425ecfd989;
575
681
  const $9208a85b3e79d33f$export$be92b6f5f03c0fe9 = $9208a85b3e79d33f$export$8d8dc7d5f743331b;