@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
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
useMemo,
|
|
22
22
|
useRef,
|
|
23
23
|
useState,
|
|
24
|
-
useSyncExternalStore,
|
|
25
24
|
} from 'react';
|
|
26
25
|
import type {ReactNode} from 'react';
|
|
27
26
|
import {createPortal} from 'react-dom';
|
|
@@ -29,11 +28,6 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
29
28
|
import {spacingVars, durationVars, easeVars} from '../theme/tokens.stylex';
|
|
30
29
|
import {mergeProps} from '../utils';
|
|
31
30
|
import {getNodeText} from '../utils/getNodeText';
|
|
32
|
-
import {
|
|
33
|
-
moveFocusLeftBehind,
|
|
34
|
-
noteFocusWithin,
|
|
35
|
-
type FocusWithin,
|
|
36
|
-
} from '../utils/focusReturn';
|
|
37
31
|
import {INTERACTIVE_SELECTORS} from '../hooks/useClickableContainer';
|
|
38
32
|
import {useAnnounce} from '../hooks/useAnnounce';
|
|
39
33
|
import {layerTextReset} from '../Layer/layerTextReset.stylex';
|
|
@@ -230,8 +224,6 @@ interface ToastRowProps {
|
|
|
230
224
|
isReversed: boolean;
|
|
231
225
|
onExited: (id: string) => void;
|
|
232
226
|
onDismiss: (id: string, reason: ToastDismissReason) => void;
|
|
233
|
-
/** Whether the card carries its own live region (see ToastViewport). */
|
|
234
|
-
isLiveRegion: boolean;
|
|
235
227
|
}
|
|
236
228
|
|
|
237
229
|
/**
|
|
@@ -254,7 +246,6 @@ function ToastRow({
|
|
|
254
246
|
isReversed,
|
|
255
247
|
onExited,
|
|
256
248
|
onDismiss,
|
|
257
|
-
isLiveRegion,
|
|
258
249
|
}: ToastRowProps) {
|
|
259
250
|
const o = entry.options;
|
|
260
251
|
const type = o.type ?? 'info';
|
|
@@ -305,8 +296,6 @@ function ToastRow({
|
|
|
305
296
|
gestureDirection={isReversed ? -1 : 1}
|
|
306
297
|
onDismiss={reason => onDismiss(entry.id, reason)}
|
|
307
298
|
renderContent={o.renderContent}
|
|
308
|
-
timerKey={entry.id}
|
|
309
|
-
isLiveRegion={isLiveRegion}
|
|
310
299
|
/>
|
|
311
300
|
</div>
|
|
312
301
|
</div>
|
|
@@ -314,9 +303,6 @@ function ToastRow({
|
|
|
314
303
|
}
|
|
315
304
|
ToastRow.displayName = 'ToastRow';
|
|
316
305
|
|
|
317
|
-
const hasActiveModalOutlet = (): boolean => getActiveModalOutlet() != null;
|
|
318
|
-
const hasNoModalOutlet = (): boolean => false;
|
|
319
|
-
|
|
320
306
|
/**
|
|
321
307
|
* Container that renders and manages toast notifications. Place at the root
|
|
322
308
|
* of your app to enable useToast(). Toasts stack with enter/exit
|
|
@@ -377,13 +363,6 @@ export function ToastViewport({
|
|
|
377
363
|
// The next toast id that should receive focus once the dismissed toast has
|
|
378
364
|
// unmounted, or 'restore' to fall back to the previously-focused element.
|
|
379
365
|
const pendingFocusRef = useRef<string | 'restore' | null>(null);
|
|
380
|
-
// The id of a toast whose overwrite updated a row that held focus. If the
|
|
381
|
-
// update removed the focused control, the commit hands focus off.
|
|
382
|
-
const overwriteFocusRef = useRef<{id: string; note: FocusWithin} | null>(
|
|
383
|
-
null,
|
|
384
|
-
);
|
|
385
|
-
// Where focus was inside a toast whose dismissal hands focus off.
|
|
386
|
-
const dismissFocusNoteRef = useRef<FocusWithin | null>(null);
|
|
387
366
|
|
|
388
367
|
// Collect a focusable control within a toast node, if any.
|
|
389
368
|
// Reuses the canonical INTERACTIVE_SELECTORS list (native controls plus
|
|
@@ -413,9 +392,13 @@ export function ToastViewport({
|
|
|
413
392
|
[],
|
|
414
393
|
);
|
|
415
394
|
|
|
416
|
-
// Announce toasts through the persistent singleton live regions.
|
|
417
|
-
//
|
|
418
|
-
//
|
|
395
|
+
// Announce toasts through the persistent singleton live regions. Each
|
|
396
|
+
// <Toast> also renders its own role="status"/"alert" region, but that region
|
|
397
|
+
// is "born with content" — mounted together with its text — which many
|
|
398
|
+
// screen readers do not announce (see useAnnounce.ts); the singleton regions
|
|
399
|
+
// are mounted empty and only mutated afterwards, so they are what actually
|
|
400
|
+
// guarantees the announcement (the per-toast markup is kept for browse-mode
|
|
401
|
+
// discoverability). The announcement happens in addToast — the imperative
|
|
419
402
|
// dispatch path invoked once per useToast() call from an event handler,
|
|
420
403
|
// never from render — so each toast is announced exactly once by
|
|
421
404
|
// construction, independent of the React render lifecycle (StrictMode
|
|
@@ -423,16 +406,6 @@ export function ToastViewport({
|
|
|
423
406
|
// re-renders never re-announce). It is client-only (addToast never runs
|
|
424
407
|
// during SSR), so it is SSR-safe.
|
|
425
408
|
const announce = useAnnounce();
|
|
426
|
-
// An open native modal hides the body-level channel above from assistive
|
|
427
|
-
// technology, so while the viewport is hosted in one, each card announces
|
|
428
|
-
// itself through its own live region instead. Outside a modal the cards
|
|
429
|
-
// carry none, so a card updated in place is announced once.
|
|
430
|
-
const hasModalOutlet = useSyncExternalStore(
|
|
431
|
-
subscribeModalOutlets,
|
|
432
|
-
hasActiveModalOutlet,
|
|
433
|
-
hasNoModalOutlet,
|
|
434
|
-
);
|
|
435
|
-
const isModalHosted = isTopLayer && hasModalOutlet;
|
|
436
409
|
|
|
437
410
|
const addToast = useCallback(
|
|
438
411
|
(entry: ToastEntry) => {
|
|
@@ -468,29 +441,9 @@ export function ToastViewport({
|
|
|
468
441
|
if (overwritten && renderedToastsRef.current.includes(overwritten)) {
|
|
469
442
|
replacedRef.current.set(overwritten.id, overwritten);
|
|
470
443
|
}
|
|
471
|
-
// An overwrite of a toast that is not leaving keeps its row, so the card
|
|
472
|
-
// updates in place and focus inside it stays. A leaving namesake
|
|
473
|
-
// is replaced by a new row, which enters again.
|
|
474
|
-
const keepsRow =
|
|
475
|
-
overwritten != null && !exitingIdsRef.current.has(overwritten.id);
|
|
476
|
-
const placed: ToastEntry = keepsRow
|
|
477
|
-
? {...entry, rowKey: overwritten.rowKey ?? overwritten.id}
|
|
478
|
-
: entry;
|
|
479
|
-
if (keepsRow) {
|
|
480
|
-
// If the update removes the focused control, the commit hands focus
|
|
481
|
-
// off as a dismissal does.
|
|
482
|
-
const note = noteFocusWithin(
|
|
483
|
-
viewportRef.current?.querySelector<HTMLElement>(
|
|
484
|
-
`[data-toast-id="${overwritten.id}"]`,
|
|
485
|
-
),
|
|
486
|
-
);
|
|
487
|
-
if (note != null) {
|
|
488
|
-
overwriteFocusRef.current = {id: placed.id, note};
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
444
|
const projected = overwritten
|
|
492
|
-
? committed.map(t => (t === overwritten ?
|
|
493
|
-
: [...committed,
|
|
445
|
+
? committed.map(t => (t === overwritten ? entry : t))
|
|
446
|
+
: [...committed, entry];
|
|
494
447
|
// `maxVisible={0}` shows every toast (FR7): nothing leaves the window.
|
|
495
448
|
const firstVisible = maxVisible > 0 ? projected.length - maxVisible : 0;
|
|
496
449
|
const cutIds = new Set(
|
|
@@ -517,7 +470,7 @@ export function ToastViewport({
|
|
|
517
470
|
}
|
|
518
471
|
}
|
|
519
472
|
}
|
|
520
|
-
pending.set(entry.id,
|
|
473
|
+
pending.set(entry.id, entry);
|
|
521
474
|
// An overwrite swaps a new entry, with a new id, into the replaced
|
|
522
475
|
// toast's place, so the old row leaves the DOM without ever being
|
|
523
476
|
// dismissed. Its settled id is dropped by the prune below, which covers
|
|
@@ -529,8 +482,8 @@ export function ToastViewport({
|
|
|
529
482
|
// overwrite into an append. An ignored collision already returned.
|
|
530
483
|
const kept = prev.filter(t => !cutIds.has(t.id));
|
|
531
484
|
return overwritten && kept.includes(overwritten)
|
|
532
|
-
? kept.map(t => (t === overwritten ?
|
|
533
|
-
: [...kept,
|
|
485
|
+
? kept.map(t => (t === overwritten ? entry : t))
|
|
486
|
+
: [...kept, entry];
|
|
534
487
|
});
|
|
535
488
|
},
|
|
536
489
|
[announce, maxVisible],
|
|
@@ -559,23 +512,14 @@ export function ToastViewport({
|
|
|
559
512
|
// focused before the user entered the viewport) rather than <body>.
|
|
560
513
|
const el = viewportRef.current;
|
|
561
514
|
const active = document.activeElement;
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
// focus in it, to the replacement.
|
|
565
|
-
const rowKey = entry.rowKey ?? entry.id;
|
|
566
|
-
const isReplacedInPlace =
|
|
567
|
-
!toastsRef.current.some(t => t.id === id) &&
|
|
568
|
-
toastsRef.current.some(t => t.rowKey === rowKey);
|
|
569
|
-
const dismissedNode = isReplacedInPlace
|
|
570
|
-
? null
|
|
571
|
-
: (el?.querySelector<HTMLElement>(`[data-toast-id="${id}"]`) ?? null);
|
|
515
|
+
const dismissedNode =
|
|
516
|
+
el?.querySelector<HTMLElement>(`[data-toast-id="${id}"]`) ?? null;
|
|
572
517
|
if (
|
|
573
518
|
dismissedNode &&
|
|
574
519
|
active instanceof Node &&
|
|
575
520
|
dismissedNode.contains(active)
|
|
576
521
|
) {
|
|
577
522
|
focusHandoffIdRef.current = id;
|
|
578
|
-
dismissFocusNoteRef.current = noteFocusWithin(dismissedNode);
|
|
579
523
|
// Pick the toast to receive focus while the DOM is still intact: the
|
|
580
524
|
// nearest one after it, then before it, that shows once it is gone
|
|
581
525
|
// (FR10), else restore. The list may already run ahead of the render
|
|
@@ -643,41 +587,6 @@ export function ToastViewport({
|
|
|
643
587
|
setToasts(prev => prev.filter(t => t.id !== id));
|
|
644
588
|
}, []);
|
|
645
589
|
|
|
646
|
-
// Moves focus to a control in the target toast, else in another toast that
|
|
647
|
-
// shows (newest first), else back to the element focused before focus
|
|
648
|
-
// entered the viewport, so a handoff never drops focus to <body>.
|
|
649
|
-
const handOffFocus = useCallback(
|
|
650
|
-
(note: FocusWithin | null, targetId: string | null) => {
|
|
651
|
-
const el = viewportRef.current;
|
|
652
|
-
const rowFor = (id: string) =>
|
|
653
|
-
el?.querySelector<HTMLElement>(`[data-toast-id="${id}"]`) ?? null;
|
|
654
|
-
const shownIds = toastsRef.current
|
|
655
|
-
.slice(maxVisibleRef.current > 0 ? -maxVisibleRef.current : 0)
|
|
656
|
-
.map(t => t.id)
|
|
657
|
-
.reverse();
|
|
658
|
-
const candidates =
|
|
659
|
-
targetId == null
|
|
660
|
-
? []
|
|
661
|
-
: [targetId, ...shownIds.filter(id => id !== targetId)];
|
|
662
|
-
let target: HTMLElement | null = null;
|
|
663
|
-
for (const id of candidates) {
|
|
664
|
-
target = getFocusable(rowFor(id));
|
|
665
|
-
if (target != null) {
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
const prev = prevFocusRef.current;
|
|
670
|
-
const isReturning = target == null && prev != null && prev.isConnected;
|
|
671
|
-
if (target == null) {
|
|
672
|
-
target = isReturning ? prev : el;
|
|
673
|
-
}
|
|
674
|
-
if (moveFocusLeftBehind(note, target) && isReturning) {
|
|
675
|
-
prevFocusRef.current = null;
|
|
676
|
-
}
|
|
677
|
-
},
|
|
678
|
-
[getFocusable],
|
|
679
|
-
);
|
|
680
|
-
|
|
681
590
|
// After a dismissed toast unmounts, hand focus off so it never falls to
|
|
682
591
|
// <body>. Runs in a layout effect once the toast list no longer contains
|
|
683
592
|
// the dismissed toast.
|
|
@@ -693,21 +602,27 @@ export function ToastViewport({
|
|
|
693
602
|
}
|
|
694
603
|
focusHandoffIdRef.current = null;
|
|
695
604
|
pendingFocusRef.current = null;
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
605
|
+
const el = viewportRef.current;
|
|
606
|
+
if (target !== 'restore' && el) {
|
|
607
|
+
const nextNode = el.querySelector<HTMLElement>(
|
|
608
|
+
`[data-toast-id="${target}"]`,
|
|
609
|
+
);
|
|
610
|
+
const focusable = getFocusable(nextNode) ?? nextNode;
|
|
611
|
+
if (focusable) {
|
|
612
|
+
focusable.focus();
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
// No remaining toast to receive focus — restore the previously-focused
|
|
617
|
+
// element if it's still connected, else fall back to the container.
|
|
618
|
+
const prev = prevFocusRef.current;
|
|
619
|
+
prevFocusRef.current = null;
|
|
620
|
+
if (prev && prev.isConnected) {
|
|
621
|
+
prev.focus();
|
|
622
|
+
} else if (el) {
|
|
623
|
+
el.focus();
|
|
707
624
|
}
|
|
708
|
-
|
|
709
|
-
handOffFocus(overwrite.note, overwrite.id);
|
|
710
|
-
}, [toasts, handOffFocus]);
|
|
625
|
+
}, [toasts, getFocusable]);
|
|
711
626
|
|
|
712
627
|
const findByUniqueID = useCallback((uid: string) => {
|
|
713
628
|
return toastsRef.current.find(t => t.options.uniqueID === uid);
|
|
@@ -915,13 +830,12 @@ export function ToastViewport({
|
|
|
915
830
|
<LayerContentBoundary>
|
|
916
831
|
{visibleToasts.map(entry => (
|
|
917
832
|
<ToastRow
|
|
918
|
-
key={entry.
|
|
833
|
+
key={entry.id}
|
|
919
834
|
entry={entry}
|
|
920
835
|
isExiting={exitingIds.has(entry.id)}
|
|
921
836
|
isReversed={isReversed}
|
|
922
837
|
onExited={handleExited}
|
|
923
838
|
onDismiss={removeToast}
|
|
924
|
-
isLiveRegion={isModalHosted}
|
|
925
839
|
/>
|
|
926
840
|
))}
|
|
927
841
|
</LayerContentBoundary>
|
package/src/Toast/types.ts
CHANGED
|
@@ -38,10 +38,9 @@ export interface ToastOptions {
|
|
|
38
38
|
/**
|
|
39
39
|
* Replaces the content of this toast's card with your own layout.
|
|
40
40
|
*
|
|
41
|
-
* Astryx keeps the card and
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* renderer this toast's content, resolved settings and `dismiss` callback. The renderer owns every control inside its layout; call
|
|
41
|
+
* Astryx keeps the card, live-region role and auto-hide behavior, then hands
|
|
42
|
+
* the renderer this toast's content, resolved settings and `dismiss`
|
|
43
|
+
* callback. The renderer owns every control inside its layout; call
|
|
45
44
|
* `dismiss` from the control that should close the toast. Astryx does not
|
|
46
45
|
* inject a fallback control into custom content.
|
|
47
46
|
*
|
|
@@ -101,9 +100,4 @@ export interface ToastEntry {
|
|
|
101
100
|
id: string;
|
|
102
101
|
options: ToastOptions;
|
|
103
102
|
createdAt: number;
|
|
104
|
-
/**
|
|
105
|
-
* The row's identity in the stack. A uniqueID overwrite keeps the replaced
|
|
106
|
-
* toast's, so the card updates in place and focus inside it stays.
|
|
107
|
-
*/
|
|
108
|
-
rowKey?: string;
|
|
109
103
|
}
|
|
@@ -110,18 +110,6 @@ export const docs = {
|
|
|
110
110
|
description:
|
|
111
111
|
'Render function for the anchor-positioned tooltip content. The positioning opt-out is excluded: the tooltip always derives its position from placement/alignment.',
|
|
112
112
|
},
|
|
113
|
-
{
|
|
114
|
-
name: 'show',
|
|
115
|
-
type: '() => void',
|
|
116
|
-
description:
|
|
117
|
-
'Opens the tooltip now and keeps it open until hide(), Escape, a press outside, or focus leaving its trigger. Its text is announced once, and onShow fires. Under a controlled isOpen it only calls onShow. Does nothing while isEnabled is false.',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: 'hide',
|
|
121
|
-
type: '() => void',
|
|
122
|
-
description:
|
|
123
|
-
'Closes the tooltip now, and onHide fires. Under a controlled isOpen it only calls onHide.',
|
|
124
|
-
},
|
|
125
113
|
],
|
|
126
114
|
usage: {
|
|
127
115
|
description:
|
|
@@ -137,11 +125,6 @@ export const docs = {
|
|
|
137
125
|
description:
|
|
138
126
|
'Prefer the Tooltip component for standard wrapping; use the hook when the trigger is not a simple child.',
|
|
139
127
|
},
|
|
140
|
-
{
|
|
141
|
-
guidance: true,
|
|
142
|
-
description:
|
|
143
|
-
'For a toggle-style trigger, have your own button call show() and hide() on each press. Give it aria-describedby and aria-controls set to describedBy, and aria-expanded (true while show() holds the tooltip, false after hide() or onHide), and keep its own accessible name. For an info icon, use InfoTip instead.',
|
|
144
|
-
},
|
|
145
128
|
{
|
|
146
129
|
guidance: false,
|
|
147
130
|
description:
|
|
@@ -184,8 +167,6 @@ export const docsDense = {
|
|
|
184
167
|
anchorId: 'CSS anchor name.',
|
|
185
168
|
describedBy: 'ID for aria-describedby.',
|
|
186
169
|
renderTooltip: 'renders anchor-positioned tooltip content.',
|
|
187
|
-
show: 'opens + holds until hide()/Escape/outside press/focus leave; announces once; onShow. Controlled: onShow only. No-op when disabled.',
|
|
188
|
-
hide: 'closes; onHide. Controlled: onHide only.',
|
|
189
170
|
},
|
|
190
171
|
usage: {
|
|
191
172
|
description:
|
|
@@ -201,11 +182,6 @@ export const docsDense = {
|
|
|
201
182
|
description:
|
|
202
183
|
'Prefer Tooltip for standard wrapping; use hook when trigger is not simple child.',
|
|
203
184
|
},
|
|
204
|
-
{
|
|
205
|
-
guidance: true,
|
|
206
|
-
description:
|
|
207
|
-
'Toggle-style trigger: own button calls show()/hide() per press, sets aria-describedby + aria-controls={describedBy}, aria-expanded (true while held), keeps its own name. Info icon: use InfoTip.',
|
|
208
|
-
},
|
|
209
185
|
{
|
|
210
186
|
guidance: false,
|
|
211
187
|
description:
|
|
@@ -5,8 +5,7 @@
|
|
|
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
|
*
|
|
@@ -18,11 +17,9 @@ import {
|
|
|
18
17
|
useCallback,
|
|
19
18
|
useEffect,
|
|
20
19
|
useRef,
|
|
21
|
-
useState,
|
|
22
20
|
type ReactNode,
|
|
23
21
|
type RefCallback,
|
|
24
22
|
} from 'react';
|
|
25
|
-
import {createTriggerFocusGate} from '../utils/triggerFocus';
|
|
26
23
|
import * as stylex from '@stylexjs/stylex';
|
|
27
24
|
import {
|
|
28
25
|
useLayerInternal,
|
|
@@ -219,25 +216,29 @@ export interface TooltipReturn {
|
|
|
219
216
|
children: ReactNode,
|
|
220
217
|
props?: Omit<ContextRenderProps, 'positioning'>,
|
|
221
218
|
) => ReactNode;
|
|
219
|
+
}
|
|
222
220
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Check if an element is naturally focusable
|
|
223
|
+
*/
|
|
224
|
+
function isFocusable(element: HTMLElement): boolean {
|
|
225
|
+
// Elements with explicit tabindex
|
|
226
|
+
if (element.hasAttribute('tabindex')) {
|
|
227
|
+
return element.tabIndex >= 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Naturally focusable elements
|
|
231
|
+
const focusableTags = ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'];
|
|
232
|
+
if (focusableTags.includes(element.tagName)) {
|
|
233
|
+
return !(element as HTMLButtonElement).disabled;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Elements with contenteditable
|
|
237
|
+
if (element.isContentEditable) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return false;
|
|
241
242
|
}
|
|
242
243
|
|
|
243
244
|
/**
|
|
@@ -374,9 +375,6 @@ export function useTooltipWithTriggerBehavior(
|
|
|
374
375
|
isHeldOpen: isPressHeldOpen,
|
|
375
376
|
attach: attachPressPin,
|
|
376
377
|
unpin: unpinPress,
|
|
377
|
-
hold: holdPress,
|
|
378
|
-
release: releasePress,
|
|
379
|
-
isAppHeld,
|
|
380
378
|
isPinShown,
|
|
381
379
|
touch: {
|
|
382
380
|
isTouchPointerRef,
|
|
@@ -487,13 +485,32 @@ export function useTooltipWithTriggerBehavior(
|
|
|
487
485
|
[isTouchPointerRef, layerId, scheduleHide],
|
|
488
486
|
);
|
|
489
487
|
|
|
490
|
-
// Under `auto`, whether focus counts is decided when it arrives,
|
|
491
|
-
//
|
|
492
|
-
|
|
488
|
+
// Under `auto`, whether focus counts is decided when it arrives, not when
|
|
489
|
+
// the listeners attach: a roving-tabindex member that was `tabindex="-1"`
|
|
490
|
+
// then can be the tab stop now. A trigger that receives focus is focusable
|
|
491
|
+
// by definition; focus inside it counts only while the trigger is
|
|
492
|
+
// focusable too, so a plain wrapper still ignores its children's focus.
|
|
493
|
+
const isFocusForTrigger = useCallback(
|
|
494
|
+
(e: Event): boolean => {
|
|
495
|
+
if (focusTrigger === 'always') {
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
const triggerEl = e.currentTarget as HTMLElement | null;
|
|
499
|
+
return (
|
|
500
|
+
triggerEl != null && (e.target === triggerEl || isFocusable(triggerEl))
|
|
501
|
+
);
|
|
502
|
+
},
|
|
503
|
+
[focusTrigger],
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
// Whether the trigger's current focus counted when it arrived, so its blur
|
|
507
|
+
// hides the tooltip even if the trigger has since left the tab order.
|
|
508
|
+
const focusCountedRef = useRef(false);
|
|
493
509
|
|
|
494
510
|
const handleFocusIn = useCallback(
|
|
495
511
|
(e: Event) => {
|
|
496
|
-
|
|
512
|
+
focusCountedRef.current = isFocusForTrigger(e);
|
|
513
|
+
if (!isEnabled || !focusCountedRef.current) {
|
|
497
514
|
return;
|
|
498
515
|
}
|
|
499
516
|
// A tap focuses the trigger it activates, and `:focus-visible` does not
|
|
@@ -514,9 +531,8 @@ export function useTooltipWithTriggerBehavior(
|
|
|
514
531
|
showLayer();
|
|
515
532
|
},
|
|
516
533
|
[
|
|
517
|
-
focusGate,
|
|
518
|
-
focusTrigger,
|
|
519
534
|
isEnabled,
|
|
535
|
+
isFocusForTrigger,
|
|
520
536
|
isTouchInteraction,
|
|
521
537
|
clearTimeouts,
|
|
522
538
|
showLayer,
|
|
@@ -528,12 +544,13 @@ export function useTooltipWithTriggerBehavior(
|
|
|
528
544
|
// which a held tooltip skips.
|
|
529
545
|
const handleFocusOut = useCallback(
|
|
530
546
|
(e: Event) => {
|
|
531
|
-
if (!
|
|
547
|
+
if (!focusCountedRef.current && !isFocusForTrigger(e)) {
|
|
532
548
|
return;
|
|
533
549
|
}
|
|
550
|
+
focusCountedRef.current = false;
|
|
534
551
|
scheduleHide();
|
|
535
552
|
},
|
|
536
|
-
[
|
|
553
|
+
[isFocusForTrigger, scheduleHide],
|
|
537
554
|
);
|
|
538
555
|
|
|
539
556
|
// Pressing the trigger hides its own tooltip: once the control is activated
|
|
@@ -545,10 +562,9 @@ export function useTooltipWithTriggerBehavior(
|
|
|
545
562
|
// tooltip at all), so the touch path answers it first.
|
|
546
563
|
const handlePointerDown = useCallback(
|
|
547
564
|
(event: PointerEvent) => {
|
|
548
|
-
// A toggle trigger
|
|
549
|
-
//
|
|
550
|
-
|
|
551
|
-
if (isToggleTrigger(triggerRef.current) || isAppHeld()) {
|
|
565
|
+
// A press on a toggle trigger pins or closes through its click. It
|
|
566
|
+
// neither hides the preview here nor waits for a tap verdict.
|
|
567
|
+
if (isToggleTrigger(triggerRef.current)) {
|
|
552
568
|
return;
|
|
553
569
|
}
|
|
554
570
|
if (handleTouchPointerDown(event)) {
|
|
@@ -560,14 +576,7 @@ export function useTooltipWithTriggerBehavior(
|
|
|
560
576
|
clearTimeouts();
|
|
561
577
|
hideLayer();
|
|
562
578
|
},
|
|
563
|
-
[
|
|
564
|
-
isToggleTrigger,
|
|
565
|
-
isAppHeld,
|
|
566
|
-
handleTouchPointerDown,
|
|
567
|
-
isOpen,
|
|
568
|
-
clearTimeouts,
|
|
569
|
-
hideLayer,
|
|
570
|
-
],
|
|
579
|
+
[isToggleTrigger, handleTouchPointerDown, isOpen, clearTimeouts, hideLayer],
|
|
571
580
|
);
|
|
572
581
|
|
|
573
582
|
// Interaction ref that handles event listeners only
|
|
@@ -600,7 +609,7 @@ export function useTooltipWithTriggerBehavior(
|
|
|
600
609
|
el.addEventListener('pointerdown', handlePointerDown);
|
|
601
610
|
|
|
602
611
|
// Focus listeners unless focus never opens the tooltip; `auto` decides
|
|
603
|
-
// per event (
|
|
612
|
+
// per event (isFocusForTrigger).
|
|
604
613
|
if (focusTrigger !== 'never') {
|
|
605
614
|
el.addEventListener('focusin', handleFocusIn);
|
|
606
615
|
el.addEventListener('focusout', handleFocusOut);
|
|
@@ -656,11 +665,9 @@ export function useTooltipWithTriggerBehavior(
|
|
|
656
665
|
showLayer();
|
|
657
666
|
} else {
|
|
658
667
|
clearTimeouts();
|
|
659
|
-
// A pin or app hold ends when the consumer closes the tooltip.
|
|
660
|
-
unpinPress();
|
|
661
668
|
hideLayer();
|
|
662
669
|
}
|
|
663
|
-
}, [isOpen, clearTimeouts, showLayer, hideLayer
|
|
670
|
+
}, [isOpen, clearTimeouts, showLayer, hideLayer]);
|
|
664
671
|
|
|
665
672
|
// Dismiss on Escape (WCAG 1.4.13 — dismissible) through the shared layer
|
|
666
673
|
// stack. A visible tip is the top-most layer, so it takes the press and
|
|
@@ -756,16 +763,6 @@ export function useTooltipWithTriggerBehavior(
|
|
|
756
763
|
],
|
|
757
764
|
);
|
|
758
765
|
|
|
759
|
-
const show = useCallback(() => {
|
|
760
|
-
clearTimeouts();
|
|
761
|
-
holdPress();
|
|
762
|
-
}, [clearTimeouts, holdPress]);
|
|
763
|
-
|
|
764
|
-
const hide = useCallback(() => {
|
|
765
|
-
clearTimeouts();
|
|
766
|
-
releasePress();
|
|
767
|
-
}, [clearTimeouts, releasePress]);
|
|
768
|
-
|
|
769
766
|
return {
|
|
770
767
|
ref,
|
|
771
768
|
positionRef: layerRef,
|
|
@@ -773,7 +770,5 @@ export function useTooltipWithTriggerBehavior(
|
|
|
773
770
|
anchorId: layerAnchorId,
|
|
774
771
|
describedBy: layerId,
|
|
775
772
|
renderTooltip,
|
|
776
|
-
show,
|
|
777
|
-
hide,
|
|
778
773
|
};
|
|
779
774
|
}
|
|
@@ -43,8 +43,7 @@ export const docs = {
|
|
|
43
43
|
{
|
|
44
44
|
name: 'group',
|
|
45
45
|
type: 'string',
|
|
46
|
-
description:
|
|
47
|
-
'This prop has no effect. Set `item.auxiliaryData.group` on search-source items to group results in Typeahead or BaseTypeahead.',
|
|
46
|
+
description: 'Group label for grouping items visually.',
|
|
48
47
|
},
|
|
49
48
|
],
|
|
50
49
|
};
|
|
@@ -80,8 +79,7 @@ export const docsZh = {
|
|
|
80
79
|
{
|
|
81
80
|
name: 'group',
|
|
82
81
|
type: 'string',
|
|
83
|
-
description:
|
|
84
|
-
'此属性不影响渲染。要在 Typeahead 或 BaseTypeahead 中分组,请在搜索源返回的结果项上设置 `item.auxiliaryData.group`。',
|
|
82
|
+
description: '用于视觉分组的分组标签。',
|
|
85
83
|
},
|
|
86
84
|
],
|
|
87
85
|
};
|
|
@@ -96,7 +94,6 @@ export const docsDense = {
|
|
|
96
94
|
icon: 'Icon/avatar before label.',
|
|
97
95
|
description: 'Text below label.',
|
|
98
96
|
isDisabled: 'Visually disabled.',
|
|
99
|
-
group:
|
|
100
|
-
'No effect. Group results via `item.auxiliaryData.group` in the search source.',
|
|
97
|
+
group: 'Group label for visual grouping.',
|
|
101
98
|
},
|
|
102
99
|
};
|
|
@@ -54,8 +54,7 @@ export interface TypeaheadItemProps<
|
|
|
54
54
|
isDisabled?: boolean;
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
58
|
-
* items to group results in Typeahead or BaseTypeahead.
|
|
57
|
+
* Group label for grouping items visually.
|
|
59
58
|
*/
|
|
60
59
|
group?: string;
|
|
61
60
|
}
|
|
@@ -47,8 +47,7 @@
|
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
import {UIKIT_CONTROL, UIKIT_PAN, UIKIT_PRESS} from '../motion/uikit/gestures';
|
|
50
|
-
|
|
51
|
-
import {press as pressClocks} from '../motion/uikit/timing';
|
|
50
|
+
import {timing} from '../motion/uikit/timing';
|
|
52
51
|
import {travel} from './geometry';
|
|
53
52
|
import type {GestureRecognizer, SelectionLock} from './GestureRecognizer';
|
|
54
53
|
import type {TapGestureRecognizer} from './TapGestureRecognizer';
|
|
@@ -155,7 +154,7 @@ export const PRESS_PROFILES = {
|
|
|
155
154
|
// The shared press styles release every surface on the deselect clock
|
|
156
155
|
// until a control runs its own release (UIButton's 250 ms), so a
|
|
157
156
|
// painter's `fading` never outlasts the fade it shows.
|
|
158
|
-
releaseMs:
|
|
157
|
+
releaseMs: timing.press.highlightOutMs,
|
|
159
158
|
},
|
|
160
159
|
/**
|
|
161
160
|
* A table or collection cell: inside a scroll view it highlights after the
|
|
@@ -166,7 +165,7 @@ export const PRESS_PROFILES = {
|
|
|
166
165
|
highlightDelay: 'inScrollers',
|
|
167
166
|
cancelTravel: UIKIT_PAN.hysteresis.value,
|
|
168
167
|
quickTapFlash: 0,
|
|
169
|
-
releaseMs:
|
|
168
|
+
releaseMs: timing.press.highlightOutMs,
|
|
170
169
|
},
|
|
171
170
|
} as const satisfies Record<string, PressProfile>;
|
|
172
171
|
|
package/src/gestures/README.md
CHANGED
|
@@ -96,10 +96,6 @@ Once a drag has claimed its finger, a second finger never breaks it.
|
|
|
96
96
|
| `PinchGestureRecognizer` | `UIPinchGestureRecognizer` | continuous | `scale` (settable, to re-base it), `velocity` in scale per second, `focalPoint()` |
|
|
97
97
|
| `ScreenEdgePanGestureRecognizer` | `UIScreenEdgePanGestureRecognizer` | continuous | `edges`: `leading` / `trailing`, resolved against the view's writing direction; attached to an edge zone the view lies within; fails as soon as the touch lands outside every requested edge band; a finger's only |
|
|
98
98
|
|
|
99
|
-
Each recognizer reports what it is in `kind` (`'tap'`, `'longPress'`,
|
|
100
|
-
`'pan'`, `'screenEdgePan'`, `'swipe'`, `'pinch'`): code tells the family apart by it, never by `instanceof`
|
|
101
|
-
(`architecture:react-component-runtime` INV13).
|
|
102
|
-
|
|
103
99
|
A recognizer created with `claimsTouches: false` is a watcher (a tab bar
|
|
104
100
|
that minimizes while the page scrolls): it never claims, so its element gets
|
|
105
101
|
only passive listeners and a scroll never waits for it; it prevents no other
|
|
@@ -178,9 +174,7 @@ innerPan.requireToFail(edgePan);
|
|
|
178
174
|
## Touches in the view: `createPressTracker`
|
|
179
175
|
|
|
180
176
|
A pressable control's view-level touch handling, with `UIControl`
|
|
181
|
-
semantics
|
|
182
|
-
`architecture:react-component-runtime` INV13 asks of the touch modules outside
|
|
183
|
-
the recognizer family (`VelocityTracker` is still a class, its one listed gap):
|
|
177
|
+
semantics:
|
|
184
178
|
|
|
185
179
|
- `touchDown`, `touchDragInside` / `touchDragOutside`, `touchDragEnter` /
|
|
186
180
|
`touchDragExit`, `touchUpInside` / `touchUpOutside`, `touchCancel`.
|