@astryxdesign/core 0.7.7-canary.fc68123 → 0.7.7
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.
- package/CHANGELOG.md +104 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -4
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +6 -36
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +4 -23
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +1 -3
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +1 -17
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +2 -13
- package/dist/ComplexSelector/ComplexSelector.d.ts +1 -4
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +4 -14
- package/dist/ContextMenu/ContextMenu.js +2 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +31 -7
- package/dist/Field/Field.js +2 -2
- package/dist/HoverCard/HoverCard.d.ts +3 -4
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -27
- package/dist/HoverCard/useHoverCard.d.ts +4 -5
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +31 -17
- package/dist/Icon/Icon.d.ts +1 -5
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +2 -5
- package/dist/Layer/usePressPin.d.ts +5 -17
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +12 -62
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +0 -18
- package/dist/PowerSearch/PowerSearch.d.ts +3 -36
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +127 -433
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -32
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +6 -17
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -38
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +61 -170
- package/dist/PowerSearch/formatFilterValue.d.ts +0 -7
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +1 -11
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +2 -3
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +3 -5
- package/dist/Resizable/ResizeHandle.d.ts +1 -2
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +77 -99
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -1
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
- package/dist/Slider/sliderTouchController.js +2 -2
- package/dist/Spinner/Spinner.d.ts +1 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +58 -60
- package/dist/Switch/useSwitchTouch.js +4 -4
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +8 -29
- package/dist/TextInput/TextInput.d.ts +2 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +7 -10
- package/dist/Toast/Toast.d.ts +1 -11
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +15 -25
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +34 -94
- package/dist/Toast/types.d.ts +3 -9
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +1 -19
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +53 -34
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -2
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/astryx.css +6 -35
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +3 -4
- package/dist/hooks/actionGroupTracker.d.ts +1 -4
- package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
- package/dist/hooks/actionGroupTracker.js +3 -13
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/useAttachment.d.ts +1 -1
- package/dist/hooks/useAttachment.js +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +2 -2
- package/dist/hooks/useLongPress.d.ts +2 -6
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +15 -95
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +0 -6
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +0 -30
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +0 -30
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/motion/animatedLayout.d.ts.map +1 -1
- package/dist/motion/animatedLayout.js +6 -5
- package/dist/motion/animator.d.ts +14 -14
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +18 -41
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +0 -12
- package/dist/utils/focusReturn.d.ts +0 -15
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +0 -28
- package/dist/utils/interactionOverlay.stylex.d.ts +2 -3
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +2 -3
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +6 -19
- package/locales/en.json +0 -120
- package/locales/pseudo.json +0 -90
- package/package.json +5 -10
- package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
- package/src/AlertDialog/AlertDialog.tsx +5 -37
- package/src/BottomSheet/BottomSheetPanel.tsx +3 -37
- package/src/BottomSheet/useSheetGestures.ts +1 -3
- package/src/Button/Button.tsx +4 -26
- package/src/CheckboxInput/CheckboxInput.doc.mjs +0 -18
- package/src/CheckboxInput/CheckboxInput.tsx +9 -36
- package/src/ComplexSelector/ComplexSelector.tsx +5 -20
- package/src/ContextMenu/ContextMenu.tsx +2 -2
- package/src/Dialog/Dialog.tsx +31 -10
- package/src/Field/Field.tsx +2 -2
- package/src/HoverCard/HoverCard.doc.mjs +2 -4
- package/src/HoverCard/HoverCard.tsx +4 -35
- package/src/HoverCard/useHoverCard.doc.mjs +36 -178
- package/src/HoverCard/useHoverCard.tsx +52 -46
- package/src/Icon/Icon.doc.mjs +8 -49
- package/src/Icon/Icon.tsx +7 -15
- package/src/Layer/usePressPin.ts +15 -81
- package/src/Lightbox/Lightbox.tsx +0 -18
- package/src/PowerSearch/PowerSearch.doc.mjs +5 -54
- package/src/PowerSearch/PowerSearch.tsx +155 -609
- package/src/PowerSearch/PowerSearchEditPopover.tsx +6 -28
- package/src/PowerSearch/PowerSearchValueEditor.tsx +38 -203
- package/src/PowerSearch/formatFilterValue.ts +1 -18
- package/src/RadioList/RadioList.tsx +2 -3
- package/src/RadioList/RadioListItem.tsx +3 -5
- package/src/Resizable/Resizable.doc.mjs +4 -5
- package/src/Resizable/ResizeHandle.tsx +109 -167
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +3 -6
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +63 -77
- package/src/Switch/useSwitchTouch.ts +4 -4
- package/src/Table/BaseTable.tsx +12 -46
- package/src/TextInput/TextInput.tsx +10 -11
- package/src/Toast/Toast.doc.mjs +3 -4
- package/src/Toast/Toast.tsx +32 -52
- package/src/Toast/ToastViewport.tsx +35 -121
- package/src/Toast/types.ts +3 -9
- package/src/Tooltip/useTooltip.doc.mjs +0 -24
- package/src/Tooltip/useTooltip.tsx +56 -61
- package/src/Typeahead/TypeaheadItem.doc.mjs +3 -6
- package/src/Typeahead/TypeaheadItem.tsx +1 -2
- package/src/gestures/PressTracker.ts +3 -4
- package/src/gestures/README.md +1 -7
- package/src/hooks/actionGroupTracker.ts +5 -20
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useAttachment.ts +1 -1
- package/src/hooks/useInputStatusIcon.tsx +2 -3
- package/src/hooks/useLongPress.doc.mjs +2 -2
- package/src/hooks/useLongPress.ts +15 -136
- package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +0 -6
- package/src/i18n/generated-locales/en.generated.ts +0 -41
- package/src/i18n/generated-locales/pseudo.generated.ts +0 -42
- package/src/index.ts +0 -13
- package/src/motion/README.md +5 -9
- package/src/motion/animatedLayout.ts +4 -5
- package/src/motion/animator.ts +29 -61
- package/src/utils/dateParser.ts +0 -16
- package/src/utils/focusReturn.ts +0 -30
- package/src/utils/interactionOverlay.stylex.ts +2 -3
- package/src/utils/pressFeedback.ts +6 -19
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +0 -100
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +0 -1
- package/dist/PowerSearch/PowerSearchBottomSheet.js +0 -1913
- package/dist/PowerSearch/formatTokenValue.d.ts +0 -28
- package/dist/PowerSearch/formatTokenValue.d.ts.map +0 -1
- package/dist/PowerSearch/formatTokenValue.js +0 -160
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts +0 -65
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +0 -1
- package/dist/PowerSearch/powerSearchSheetUtils.js +0 -168
- package/dist/animator/createAnimator.d.ts +0 -98
- package/dist/animator/createAnimator.d.ts.map +0 -1
- package/dist/animator/createAnimator.js +0 -259
- package/dist/hooks/pressGroupContext.d.ts +0 -6
- package/dist/hooks/pressGroupContext.d.ts.map +0 -1
- package/dist/hooks/pressGroupContext.js +0 -20
- package/dist/hooks/useActionGroupTracking.d.ts +0 -53
- package/dist/hooks/useActionGroupTracking.d.ts.map +0 -1
- package/dist/hooks/useActionGroupTracking.js +0 -174
- package/dist/hooks/useAnimator.d.ts +0 -41
- package/dist/hooks/useAnimator.d.ts.map +0 -1
- package/dist/hooks/useAnimator.js +0 -70
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +0 -8
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +0 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +0 -42
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +0 -8
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +0 -1
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +0 -14
- package/dist/internal/indicatorPress.stylex.d.ts +0 -20
- package/dist/internal/indicatorPress.stylex.d.ts.map +0 -1
- package/dist/internal/indicatorPress.stylex.js +0 -26
- package/dist/motion/progress.d.ts +0 -88
- package/dist/motion/progress.d.ts.map +0 -1
- package/dist/motion/progress.js +0 -128
- package/dist/motion/uikit/alert.d.ts +0 -41
- package/dist/motion/uikit/alert.d.ts.map +0 -1
- package/dist/motion/uikit/alert.js +0 -43
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts +0 -15
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +0 -1
- package/dist/privateAttributes/pressGroupItem.stylex.js +0 -23
- package/dist/utils/triggerFocus.d.ts +0 -36
- package/dist/utils/triggerFocus.d.ts.map +0 -1
- package/dist/utils/triggerFocus.js +0 -65
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +0 -2515
- package/src/PowerSearch/formatTokenValue.ts +0 -215
- package/src/PowerSearch/powerSearchSheetUtils.ts +0 -224
- package/src/animator/createAnimator.doc.mjs +0 -153
- package/src/animator/createAnimator.ts +0 -324
- package/src/hooks/pressGroupContext.ts +0 -21
- package/src/hooks/useActionGroupTracking.ts +0 -224
- package/src/hooks/useAnimator.doc.mjs +0 -109
- package/src/hooks/useAnimator.ts +0 -67
- package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +0 -43
- package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +0 -15
- package/src/internal/indicatorPress.stylex.ts +0 -24
- package/src/motion/progress.ts +0 -155
- package/src/motion/uikit/alert.ts +0 -43
- package/src/privateAttributes/pressGroupItem.stylex.ts +0 -23
- package/src/utils/triggerFocus.ts +0 -80
|
@@ -13,14 +13,13 @@
|
|
|
13
13
|
* SYNC: When placement, stacking, hosting, focus, announcement, or safe-area
|
|
14
14
|
* behavior changes, update ToastViewport.test.tsx, Toast.doc.mjs, and Toast.stories.tsx.
|
|
15
15
|
*/
|
|
16
|
-
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState
|
|
16
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
17
17
|
import { createPortal } from 'react-dom';
|
|
18
18
|
import * as stylex from '@stylexjs/stylex';
|
|
19
19
|
import "../theme/tokens.stylex.js";
|
|
20
20
|
import { spacingVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
|
|
21
21
|
import { mergeProps } from "../utils/index.js";
|
|
22
22
|
import { getNodeText } from "../utils/getNodeText.js";
|
|
23
|
-
import { moveFocusLeftBehind, noteFocusWithin } from "../utils/focusReturn.js";
|
|
24
23
|
import { INTERACTIVE_SELECTORS } from "../hooks/useClickableContainer.js";
|
|
25
24
|
import { useAnnounce } from "../hooks/useAnnounce.js";
|
|
26
25
|
import { layerTextReset } from "../Layer/layerTextReset.stylex.js";
|
|
@@ -123,8 +122,7 @@ function ToastRow({
|
|
|
123
122
|
isExiting,
|
|
124
123
|
isReversed,
|
|
125
124
|
onExited,
|
|
126
|
-
onDismiss
|
|
127
|
-
isLiveRegion
|
|
125
|
+
onDismiss
|
|
128
126
|
}) {
|
|
129
127
|
const o = entry.options;
|
|
130
128
|
const type = o.type ?? 'info';
|
|
@@ -196,16 +194,12 @@ function ToastRow({
|
|
|
196
194
|
isExiting: isExiting,
|
|
197
195
|
gestureDirection: isReversed ? -1 : 1,
|
|
198
196
|
onDismiss: reason => onDismiss(entry.id, reason),
|
|
199
|
-
renderContent: o.renderContent
|
|
200
|
-
timerKey: entry.id,
|
|
201
|
-
isLiveRegion: isLiveRegion
|
|
197
|
+
renderContent: o.renderContent
|
|
202
198
|
})
|
|
203
199
|
})
|
|
204
200
|
});
|
|
205
201
|
}
|
|
206
202
|
ToastRow.displayName = 'ToastRow';
|
|
207
|
-
const hasActiveModalOutlet = () => getActiveModalOutlet() != null;
|
|
208
|
-
const hasNoModalOutlet = () => false;
|
|
209
203
|
|
|
210
204
|
/**
|
|
211
205
|
* Container that renders and manages toast notifications. Place at the root
|
|
@@ -266,11 +260,6 @@ export function ToastViewport({
|
|
|
266
260
|
// The next toast id that should receive focus once the dismissed toast has
|
|
267
261
|
// unmounted, or 'restore' to fall back to the previously-focused element.
|
|
268
262
|
const pendingFocusRef = useRef(null);
|
|
269
|
-
// The id of a toast whose overwrite updated a row that held focus. If the
|
|
270
|
-
// update removed the focused control, the commit hands focus off.
|
|
271
|
-
const overwriteFocusRef = useRef(null);
|
|
272
|
-
// Where focus was inside a toast whose dismissal hands focus off.
|
|
273
|
-
const dismissFocusNoteRef = useRef(null);
|
|
274
263
|
|
|
275
264
|
// Collect a focusable control within a toast node, if any.
|
|
276
265
|
// Reuses the canonical INTERACTIVE_SELECTORS list (native controls plus
|
|
@@ -291,9 +280,13 @@ export function ToastViewport({
|
|
|
291
280
|
return null;
|
|
292
281
|
}, []);
|
|
293
282
|
|
|
294
|
-
// Announce toasts through the persistent singleton live regions.
|
|
295
|
-
//
|
|
296
|
-
//
|
|
283
|
+
// Announce toasts through the persistent singleton live regions. Each
|
|
284
|
+
// <Toast> also renders its own role="status"/"alert" region, but that region
|
|
285
|
+
// is "born with content" — mounted together with its text — which many
|
|
286
|
+
// screen readers do not announce (see useAnnounce.ts); the singleton regions
|
|
287
|
+
// are mounted empty and only mutated afterwards, so they are what actually
|
|
288
|
+
// guarantees the announcement (the per-toast markup is kept for browse-mode
|
|
289
|
+
// discoverability). The announcement happens in addToast — the imperative
|
|
297
290
|
// dispatch path invoked once per useToast() call from an event handler,
|
|
298
291
|
// never from render — so each toast is announced exactly once by
|
|
299
292
|
// construction, independent of the React render lifecycle (StrictMode
|
|
@@ -301,12 +294,6 @@ export function ToastViewport({
|
|
|
301
294
|
// re-renders never re-announce). It is client-only (addToast never runs
|
|
302
295
|
// during SSR), so it is SSR-safe.
|
|
303
296
|
const announce = useAnnounce();
|
|
304
|
-
// An open native modal hides the body-level channel above from assistive
|
|
305
|
-
// technology, so while the viewport is hosted in one, each card announces
|
|
306
|
-
// itself through its own live region instead. Outside a modal the cards
|
|
307
|
-
// carry none, so a card updated in place is announced once.
|
|
308
|
-
const hasModalOutlet = useSyncExternalStore(subscribeModalOutlets, hasActiveModalOutlet, hasNoModalOutlet);
|
|
309
|
-
const isModalHosted = isTopLayer && hasModalOutlet;
|
|
310
297
|
const addToast = useCallback(entry => {
|
|
311
298
|
const {
|
|
312
299
|
uniqueID,
|
|
@@ -339,26 +326,7 @@ export function ToastViewport({
|
|
|
339
326
|
if (overwritten && renderedToastsRef.current.includes(overwritten)) {
|
|
340
327
|
replacedRef.current.set(overwritten.id, overwritten);
|
|
341
328
|
}
|
|
342
|
-
|
|
343
|
-
// updates in place and focus inside it stays. A leaving namesake
|
|
344
|
-
// is replaced by a new row, which enters again.
|
|
345
|
-
const keepsRow = overwritten != null && !exitingIdsRef.current.has(overwritten.id);
|
|
346
|
-
const placed = keepsRow ? {
|
|
347
|
-
...entry,
|
|
348
|
-
rowKey: overwritten.rowKey ?? overwritten.id
|
|
349
|
-
} : entry;
|
|
350
|
-
if (keepsRow) {
|
|
351
|
-
// If the update removes the focused control, the commit hands focus
|
|
352
|
-
// off as a dismissal does.
|
|
353
|
-
const note = noteFocusWithin(viewportRef.current?.querySelector(`[data-toast-id="${overwritten.id}"]`));
|
|
354
|
-
if (note != null) {
|
|
355
|
-
overwriteFocusRef.current = {
|
|
356
|
-
id: placed.id,
|
|
357
|
-
note
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const projected = overwritten ? committed.map(t => t === overwritten ? placed : t) : [...committed, placed];
|
|
329
|
+
const projected = overwritten ? committed.map(t => t === overwritten ? entry : t) : [...committed, entry];
|
|
362
330
|
// `maxVisible={0}` shows every toast (FR7): nothing leaves the window.
|
|
363
331
|
const firstVisible = maxVisible > 0 ? projected.length - maxVisible : 0;
|
|
364
332
|
const cutIds = new Set(projected.filter((t, i) => i < firstVisible && exitingIdsRef.current.has(t.id)).map(t => t.id));
|
|
@@ -381,7 +349,7 @@ export function ToastViewport({
|
|
|
381
349
|
}
|
|
382
350
|
}
|
|
383
351
|
}
|
|
384
|
-
pending.set(entry.id,
|
|
352
|
+
pending.set(entry.id, entry);
|
|
385
353
|
// An overwrite swaps a new entry, with a new id, into the replaced
|
|
386
354
|
// toast's place, so the old row leaves the DOM without ever being
|
|
387
355
|
// dismissed. Its settled id is dropped by the prune below, which covers
|
|
@@ -392,7 +360,7 @@ export function ToastViewport({
|
|
|
392
360
|
// replaced namesake as leaving since, which must not turn the
|
|
393
361
|
// overwrite into an append. An ignored collision already returned.
|
|
394
362
|
const kept = prev.filter(t => !cutIds.has(t.id));
|
|
395
|
-
return overwritten && kept.includes(overwritten) ? kept.map(t => t === overwritten ?
|
|
363
|
+
return overwritten && kept.includes(overwritten) ? kept.map(t => t === overwritten ? entry : t) : [...kept, entry];
|
|
396
364
|
});
|
|
397
365
|
}, [announce, maxVisible]);
|
|
398
366
|
const removeToast = useCallback((id, reason) => {
|
|
@@ -415,15 +383,9 @@ export function ToastViewport({
|
|
|
415
383
|
// focused before the user entered the viewport) rather than <body>.
|
|
416
384
|
const el = viewportRef.current;
|
|
417
385
|
const active = document.activeElement;
|
|
418
|
-
|
|
419
|
-
// replacement does, so dismissing the replaced toast leaves the row, and
|
|
420
|
-
// focus in it, to the replacement.
|
|
421
|
-
const rowKey = entry.rowKey ?? entry.id;
|
|
422
|
-
const isReplacedInPlace = !toastsRef.current.some(t => t.id === id) && toastsRef.current.some(t => t.rowKey === rowKey);
|
|
423
|
-
const dismissedNode = isReplacedInPlace ? null : el?.querySelector(`[data-toast-id="${id}"]`) ?? null;
|
|
386
|
+
const dismissedNode = el?.querySelector(`[data-toast-id="${id}"]`) ?? null;
|
|
424
387
|
if (dismissedNode && active instanceof Node && dismissedNode.contains(active)) {
|
|
425
388
|
focusHandoffIdRef.current = id;
|
|
426
|
-
dismissFocusNoteRef.current = noteFocusWithin(dismissedNode);
|
|
427
389
|
// Pick the toast to receive focus while the DOM is still intact: the
|
|
428
390
|
// nearest one after it, then before it, that shows once it is gone
|
|
429
391
|
// (FR10), else restore. The list may already run ahead of the render
|
|
@@ -479,31 +441,6 @@ export function ToastViewport({
|
|
|
479
441
|
setToasts(prev => prev.filter(t => t.id !== id));
|
|
480
442
|
}, []);
|
|
481
443
|
|
|
482
|
-
// Moves focus to a control in the target toast, else in another toast that
|
|
483
|
-
// shows (newest first), else back to the element focused before focus
|
|
484
|
-
// entered the viewport, so a handoff never drops focus to <body>.
|
|
485
|
-
const handOffFocus = useCallback((note, targetId) => {
|
|
486
|
-
const el = viewportRef.current;
|
|
487
|
-
const rowFor = id => el?.querySelector(`[data-toast-id="${id}"]`) ?? null;
|
|
488
|
-
const shownIds = toastsRef.current.slice(maxVisibleRef.current > 0 ? -maxVisibleRef.current : 0).map(t => t.id).reverse();
|
|
489
|
-
const candidates = targetId == null ? [] : [targetId, ...shownIds.filter(id => id !== targetId)];
|
|
490
|
-
let target = null;
|
|
491
|
-
for (const id of candidates) {
|
|
492
|
-
target = getFocusable(rowFor(id));
|
|
493
|
-
if (target != null) {
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
const prev = prevFocusRef.current;
|
|
498
|
-
const isReturning = target == null && prev != null && prev.isConnected;
|
|
499
|
-
if (target == null) {
|
|
500
|
-
target = isReturning ? prev : el;
|
|
501
|
-
}
|
|
502
|
-
if (moveFocusLeftBehind(note, target) && isReturning) {
|
|
503
|
-
prevFocusRef.current = null;
|
|
504
|
-
}
|
|
505
|
-
}, [getFocusable]);
|
|
506
|
-
|
|
507
444
|
// After a dismissed toast unmounts, hand focus off so it never falls to
|
|
508
445
|
// <body>. Runs in a layout effect once the toast list no longer contains
|
|
509
446
|
// the dismissed toast.
|
|
@@ -519,21 +456,25 @@ export function ToastViewport({
|
|
|
519
456
|
}
|
|
520
457
|
focusHandoffIdRef.current = null;
|
|
521
458
|
pendingFocusRef.current = null;
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
459
|
+
const el = viewportRef.current;
|
|
460
|
+
if (target !== 'restore' && el) {
|
|
461
|
+
const nextNode = el.querySelector(`[data-toast-id="${target}"]`);
|
|
462
|
+
const focusable = getFocusable(nextNode) ?? nextNode;
|
|
463
|
+
if (focusable) {
|
|
464
|
+
focusable.focus();
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// No remaining toast to receive focus — restore the previously-focused
|
|
469
|
+
// element if it's still connected, else fall back to the container.
|
|
470
|
+
const prev = prevFocusRef.current;
|
|
471
|
+
prevFocusRef.current = null;
|
|
472
|
+
if (prev && prev.isConnected) {
|
|
473
|
+
prev.focus();
|
|
474
|
+
} else if (el) {
|
|
475
|
+
el.focus();
|
|
533
476
|
}
|
|
534
|
-
|
|
535
|
-
handOffFocus(overwrite.note, overwrite.id);
|
|
536
|
-
}, [toasts, handOffFocus]);
|
|
477
|
+
}, [toasts, getFocusable]);
|
|
537
478
|
const findByUniqueID = useCallback(uid => {
|
|
538
479
|
return toastsRef.current.find(t => t.options.uniqueID === uid);
|
|
539
480
|
}, []);
|
|
@@ -722,9 +663,8 @@ export function ToastViewport({
|
|
|
722
663
|
isExiting: exitingIds.has(entry.id),
|
|
723
664
|
isReversed: isReversed,
|
|
724
665
|
onExited: handleExited,
|
|
725
|
-
onDismiss: removeToast
|
|
726
|
-
|
|
727
|
-
}, entry.rowKey ?? entry.id))
|
|
666
|
+
onDismiss: removeToast
|
|
667
|
+
}, entry.id))
|
|
728
668
|
})
|
|
729
669
|
});
|
|
730
670
|
return /*#__PURE__*/_jsxs(ToastContext, {
|
package/dist/Toast/types.d.ts
CHANGED
|
@@ -31,10 +31,9 @@ export interface ToastOptions {
|
|
|
31
31
|
/**
|
|
32
32
|
* Replaces the content of this toast's card with your own layout.
|
|
33
33
|
*
|
|
34
|
-
* Astryx keeps the card and
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* renderer this toast's content, resolved settings and `dismiss` callback. The renderer owns every control inside its layout; call
|
|
34
|
+
* Astryx keeps the card, live-region role and auto-hide behavior, then hands
|
|
35
|
+
* the renderer this toast's content, resolved settings and `dismiss`
|
|
36
|
+
* callback. The renderer owns every control inside its layout; call
|
|
38
37
|
* `dismiss` from the control that should close the toast. Astryx does not
|
|
39
38
|
* inject a fallback control into custom content.
|
|
40
39
|
*
|
|
@@ -86,10 +85,5 @@ export interface ToastEntry {
|
|
|
86
85
|
id: string;
|
|
87
86
|
options: ToastOptions;
|
|
88
87
|
createdAt: number;
|
|
89
|
-
/**
|
|
90
|
-
* The row's identity in the stack. A uniqueID overwrite keeps the replaced
|
|
91
|
-
* toast's, so the card updates in place and focus inside it stays.
|
|
92
|
-
*/
|
|
93
|
-
rowKey?: string;
|
|
94
88
|
}
|
|
95
89
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/Toast/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,gDAAgD;AAChD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzC,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;AAEhF,mEAAmE;AACnE,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D,wCAAwC;AACxC,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnD,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/Toast/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,gDAAgD;AAChD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzC,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;AAEhF,mEAAmE;AACnE,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D,wCAAwC;AACxC,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnD,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAErC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C,gDAAgD;IAChD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AAED,oDAAoD;AACpD,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC;AAExC,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,IAAI,EAAE,SAAS,CAAC;IAChB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,4EAA4E;IAC5E,IAAI,EAAE,SAAS,CAAC;IAChB,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAC;IACpB,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,KAAK,EAAE,uBAAuB,KAC3B,SAAS,CAAC;AAEf,oDAAoD;AACpD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,cAAc,CAAC;AAEpE,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file useTooltip.tsx
|
|
3
3
|
* @input Uses useLayer, usePressPin, React hooks
|
|
4
|
-
* @output Exports useTooltip hook with stable trigger refs for hover/focus/tap tooltips
|
|
5
|
-
* and imperative show() and hide() for an app-built toggle trigger,
|
|
4
|
+
* @output Exports useTooltip hook with stable trigger refs for hover/focus/tap tooltips,
|
|
6
5
|
* and the module-only useTooltipWithTriggerBehavior that InfoTip's press-to-pin uses
|
|
7
6
|
* @position Layer hook; builds on useLayer for tooltip behavior
|
|
8
7
|
*
|
|
@@ -134,23 +133,6 @@ export interface TooltipReturn {
|
|
|
134
133
|
* silent no-op.
|
|
135
134
|
*/
|
|
136
135
|
renderTooltip: (children: ReactNode, props?: Omit<ContextRenderProps, 'positioning'>) => ReactNode;
|
|
137
|
-
/**
|
|
138
|
-
* Opens the tooltip now and keeps it open until `hide()`, Escape, a press
|
|
139
|
-
* outside, or focus leaving its trigger, as a pinned tooltip does. Its text
|
|
140
|
-
* is announced once. Reports through `onShow`. Under a controlled `isOpen`,
|
|
141
|
-
* it calls `onShow` and does not change `isOpen`. Does nothing while
|
|
142
|
-
* `isEnabled` is false.
|
|
143
|
-
*
|
|
144
|
-
* Use `show()` and `hide()` to build a toggle-style trigger: your own button
|
|
145
|
-
* calls them, sets `aria-describedby` and `aria-controls` to `describedBy`
|
|
146
|
-
* and `aria-expanded` (true while shown), and keeps its own accessible name.
|
|
147
|
-
*/
|
|
148
|
-
show: () => void;
|
|
149
|
-
/**
|
|
150
|
-
* Closes the tooltip now. Reports through `onHide`. Under a controlled
|
|
151
|
-
* `isOpen`, it calls `onHide` and does not change `isOpen`.
|
|
152
|
-
*/
|
|
153
|
-
hide: () => void;
|
|
154
136
|
}
|
|
155
137
|
/**
|
|
156
138
|
* Hook for tooltip behavior with hover/focus triggers.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTooltip.d.ts","sourceRoot":"","sources":["../../src/Tooltip/useTooltip.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useTooltip.d.ts","sourceRoot":"","sources":["../../src/Tooltip/useTooltip.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,WAAW,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAKhE,OAAO,EAAc,KAAK,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AA0C5E;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAEnC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAE9B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEtC;;;;OAIG;IACH,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IAEzC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;;;OAOG;IACH,aAAa,EAAE,CACb,QAAQ,EAAE,SAAS,EACnB,KAAK,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,KAC5C,SAAS,CAAC;CAChB;AAyBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAOtE;AAED;;;GAGG;AACH,MAAM,WAAW,iCAAkC,SAAQ,cAAc;IACvE;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,oBAAoB,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,iCAAsC,GAC9C,aAAa,CAqdf"}
|
|
@@ -5,16 +5,14 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useTooltip.tsx
|
|
7
7
|
* @input Uses useLayer, usePressPin, React hooks
|
|
8
|
-
* @output Exports useTooltip hook with stable trigger refs for hover/focus/tap tooltips
|
|
9
|
-
* and imperative show() and hide() for an app-built toggle trigger,
|
|
8
|
+
* @output Exports useTooltip hook with stable trigger refs for hover/focus/tap tooltips,
|
|
10
9
|
* and the module-only useTooltipWithTriggerBehavior that InfoTip's press-to-pin uses
|
|
11
10
|
* @position Layer hook; builds on useLayer for tooltip behavior
|
|
12
11
|
*
|
|
13
12
|
* SYNC: When modified, update:
|
|
14
13
|
* - /packages/core/src/Tooltip/index.ts
|
|
15
14
|
*/
|
|
16
|
-
import { useCallback, useEffect, useRef
|
|
17
|
-
import { createTriggerFocusGate } from "../utils/triggerFocus.js";
|
|
15
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
18
16
|
import * as stylex from '@stylexjs/stylex';
|
|
19
17
|
import { useLayerInternal } from "../Layer/useLayer.js";
|
|
20
18
|
import { useAnnounceRenderedText } from "../hooks/useAnnounceRenderedText.js";
|
|
@@ -54,6 +52,28 @@ const styles = {
|
|
|
54
52
|
* Touch trigger behavior for tooltips
|
|
55
53
|
*/
|
|
56
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Check if an element is naturally focusable
|
|
57
|
+
*/
|
|
58
|
+
function isFocusable(element) {
|
|
59
|
+
// Elements with explicit tabindex
|
|
60
|
+
if (element.hasAttribute('tabindex')) {
|
|
61
|
+
return element.tabIndex >= 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Naturally focusable elements
|
|
65
|
+
const focusableTags = ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'];
|
|
66
|
+
if (focusableTags.includes(element.tagName)) {
|
|
67
|
+
return !element.disabled;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Elements with contenteditable
|
|
71
|
+
if (element.isContentEditable) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
57
77
|
/**
|
|
58
78
|
* Hook for tooltip behavior with hover/focus triggers.
|
|
59
79
|
*
|
|
@@ -167,9 +187,6 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
167
187
|
isHeldOpen: isPressHeldOpen,
|
|
168
188
|
attach: attachPressPin,
|
|
169
189
|
unpin: unpinPress,
|
|
170
|
-
hold: holdPress,
|
|
171
|
-
release: releasePress,
|
|
172
|
-
isAppHeld,
|
|
173
190
|
isPinShown,
|
|
174
191
|
touch: {
|
|
175
192
|
isTouchPointerRef,
|
|
@@ -272,11 +289,25 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
272
289
|
scheduleHide();
|
|
273
290
|
}, [isTouchPointerRef, layerId, scheduleHide]);
|
|
274
291
|
|
|
275
|
-
// Under `auto`, whether focus counts is decided when it arrives,
|
|
276
|
-
//
|
|
277
|
-
|
|
292
|
+
// Under `auto`, whether focus counts is decided when it arrives, not when
|
|
293
|
+
// the listeners attach: a roving-tabindex member that was `tabindex="-1"`
|
|
294
|
+
// then can be the tab stop now. A trigger that receives focus is focusable
|
|
295
|
+
// by definition; focus inside it counts only while the trigger is
|
|
296
|
+
// focusable too, so a plain wrapper still ignores its children's focus.
|
|
297
|
+
const isFocusForTrigger = useCallback(e => {
|
|
298
|
+
if (focusTrigger === 'always') {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
const triggerEl = e.currentTarget;
|
|
302
|
+
return triggerEl != null && (e.target === triggerEl || isFocusable(triggerEl));
|
|
303
|
+
}, [focusTrigger]);
|
|
304
|
+
|
|
305
|
+
// Whether the trigger's current focus counted when it arrived, so its blur
|
|
306
|
+
// hides the tooltip even if the trigger has since left the tab order.
|
|
307
|
+
const focusCountedRef = useRef(false);
|
|
278
308
|
const handleFocusIn = useCallback(e => {
|
|
279
|
-
|
|
309
|
+
focusCountedRef.current = isFocusForTrigger(e);
|
|
310
|
+
if (!isEnabled || !focusCountedRef.current) {
|
|
280
311
|
return;
|
|
281
312
|
}
|
|
282
313
|
// A tap focuses the trigger it activates, and `:focus-visible` does not
|
|
@@ -295,17 +326,18 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
295
326
|
}
|
|
296
327
|
clearTimeouts();
|
|
297
328
|
showLayer();
|
|
298
|
-
}, [
|
|
329
|
+
}, [isEnabled, isFocusForTrigger, isTouchInteraction, clearTimeouts, showLayer]);
|
|
299
330
|
|
|
300
331
|
// A pinned tooltip's focus-leave close is the pin's own: it listens on the
|
|
301
332
|
// trigger whatever `focusTrigger` is. This schedules the unpinned hide,
|
|
302
333
|
// which a held tooltip skips.
|
|
303
334
|
const handleFocusOut = useCallback(e => {
|
|
304
|
-
if (!
|
|
335
|
+
if (!focusCountedRef.current && !isFocusForTrigger(e)) {
|
|
305
336
|
return;
|
|
306
337
|
}
|
|
338
|
+
focusCountedRef.current = false;
|
|
307
339
|
scheduleHide();
|
|
308
|
-
}, [
|
|
340
|
+
}, [isFocusForTrigger, scheduleHide]);
|
|
309
341
|
|
|
310
342
|
// Pressing the trigger hides its own tooltip: once the control is activated
|
|
311
343
|
// the hint has served its purpose, and a tooltip lingering over a
|
|
@@ -315,10 +347,9 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
315
347
|
// A touch press is a different gesture (it may be the only way to open the
|
|
316
348
|
// tooltip at all), so the touch path answers it first.
|
|
317
349
|
const handlePointerDown = useCallback(event => {
|
|
318
|
-
// A toggle trigger
|
|
319
|
-
//
|
|
320
|
-
|
|
321
|
-
if (isToggleTrigger(triggerRef.current) || isAppHeld()) {
|
|
350
|
+
// A press on a toggle trigger pins or closes through its click. It
|
|
351
|
+
// neither hides the preview here nor waits for a tap verdict.
|
|
352
|
+
if (isToggleTrigger(triggerRef.current)) {
|
|
322
353
|
return;
|
|
323
354
|
}
|
|
324
355
|
if (handleTouchPointerDown(event)) {
|
|
@@ -329,7 +360,7 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
329
360
|
}
|
|
330
361
|
clearTimeouts();
|
|
331
362
|
hideLayer();
|
|
332
|
-
}, [isToggleTrigger,
|
|
363
|
+
}, [isToggleTrigger, handleTouchPointerDown, isOpen, clearTimeouts, hideLayer]);
|
|
333
364
|
|
|
334
365
|
// Interaction ref that handles event listeners only
|
|
335
366
|
const interactionRef = useCallback(el => {
|
|
@@ -353,7 +384,7 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
353
384
|
el.addEventListener('pointerdown', handlePointerDown);
|
|
354
385
|
|
|
355
386
|
// Focus listeners unless focus never opens the tooltip; `auto` decides
|
|
356
|
-
// per event (
|
|
387
|
+
// per event (isFocusForTrigger).
|
|
357
388
|
if (focusTrigger !== 'never') {
|
|
358
389
|
el.addEventListener('focusin', handleFocusIn);
|
|
359
390
|
el.addEventListener('focusout', handleFocusOut);
|
|
@@ -394,11 +425,9 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
394
425
|
showLayer();
|
|
395
426
|
} else {
|
|
396
427
|
clearTimeouts();
|
|
397
|
-
// A pin or app hold ends when the consumer closes the tooltip.
|
|
398
|
-
unpinPress();
|
|
399
428
|
hideLayer();
|
|
400
429
|
}
|
|
401
|
-
}, [isOpen, clearTimeouts, showLayer, hideLayer
|
|
430
|
+
}, [isOpen, clearTimeouts, showLayer, hideLayer]);
|
|
402
431
|
|
|
403
432
|
// Dismiss on Escape (WCAG 1.4.13 — dismissible) through the shared layer
|
|
404
433
|
// stack. A visible tip is the top-most layer, so it takes the press and
|
|
@@ -478,22 +507,12 @@ export function useTooltipWithTriggerBehavior(options = {}) {
|
|
|
478
507
|
children: children
|
|
479
508
|
}), renderProps);
|
|
480
509
|
}, [renderLayer, placement, alignment, popoverXstyle, cancelHide, scheduleHide, contentRefs]);
|
|
481
|
-
const show = useCallback(() => {
|
|
482
|
-
clearTimeouts();
|
|
483
|
-
holdPress();
|
|
484
|
-
}, [clearTimeouts, holdPress]);
|
|
485
|
-
const hide = useCallback(() => {
|
|
486
|
-
clearTimeouts();
|
|
487
|
-
releasePress();
|
|
488
|
-
}, [clearTimeouts, releasePress]);
|
|
489
510
|
return {
|
|
490
511
|
ref,
|
|
491
512
|
positionRef: layerRef,
|
|
492
513
|
interactionRef,
|
|
493
514
|
anchorId: layerAnchorId,
|
|
494
515
|
describedBy: layerId,
|
|
495
|
-
renderTooltip
|
|
496
|
-
show,
|
|
497
|
-
hide
|
|
516
|
+
renderTooltip
|
|
498
517
|
};
|
|
499
518
|
}
|
|
@@ -31,8 +31,7 @@ export interface TypeaheadItemProps<T extends SearchableItem = SearchableItem> e
|
|
|
31
31
|
*/
|
|
32
32
|
isDisabled?: boolean;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
* items to group results in Typeahead or BaseTypeahead.
|
|
34
|
+
* Group label for grouping items visually.
|
|
36
35
|
*/
|
|
37
36
|
group?: string;
|
|
38
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeaheadItem.d.ts","sourceRoot":"","sources":["../../src/Typeahead/TypeaheadItem.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,EAAC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAQ5C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,MAAM,WAAW,kBAAkB,CACjC,CAAC,SAAS,cAAc,GAAG,cAAc,CACzC,SAAQ,SAAS,CAAC,cAAc,CAAC;IACjC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB
|
|
1
|
+
{"version":3,"file":"TypeaheadItem.d.ts","sourceRoot":"","sources":["../../src/Typeahead/TypeaheadItem.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,EAAC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAQ5C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,MAAM,WAAW,kBAAkB,CACjC,CAAC,SAAS,cAAc,GAAG,cAAc,CACzC,SAAQ,SAAS,CAAC,cAAc,CAAC;IACjC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6CD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,cAAc,EAAE,EACtD,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,UAAkB,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,kBAAkB,CAAC,CAAC,CAAC,qBAyBvB;yBApCe,aAAa"}
|