@astryxdesign/core 0.7.7-canary.c0929c8 → 0.7.7-canary.c19ca12
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/dist/AlertDialog/AlertDialog.d.ts +4 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +36 -6
- package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts +13 -0
- package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts.map +1 -0
- package/dist/AppShell/useCloseMobileDrawerOnActivate.js +45 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +79 -9
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +23 -4
- package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
- package/dist/BottomSheet/bottomSheetStack.js +5 -4
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +3 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +2 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +7 -3
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +47 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +13 -2
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +7 -1
- package/dist/CheckboxList/CheckboxListContext.d.ts +6 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +10 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -4
- package/dist/ContextMenu/ContextMenu.js +2 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +5 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +13 -27
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +22 -41
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +5 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +23 -45
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +15 -11
- package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
- package/dist/Drawer/useDrawerDialogPresence.js +5 -1
- package/dist/Field/Field.js +2 -2
- package/dist/Field/PanelSearchInput.d.ts +9 -1
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +3 -1
- package/dist/HoverCard/HoverCard.d.ts +4 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +27 -2
- package/dist/HoverCard/useHoverCard.d.ts +5 -4
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -31
- package/dist/Icon/Icon.d.ts +5 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +5 -2
- package/dist/InfoTip/InfoTip.d.ts +63 -0
- package/dist/InfoTip/InfoTip.d.ts.map +1 -0
- package/dist/InfoTip/InfoTip.js +126 -0
- package/dist/InfoTip/index.d.ts +10 -0
- package/dist/InfoTip/index.d.ts.map +1 -0
- package/dist/InfoTip/index.js +12 -0
- package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +25 -20
- package/dist/Layer/useBackdropPress.d.ts +27 -0
- package/dist/Layer/useBackdropPress.d.ts.map +1 -0
- package/dist/Layer/useBackdropPress.js +53 -0
- package/dist/Layer/usePressPin.d.ts +20 -10
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +66 -18
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +18 -0
- package/dist/MobileNav/MobileNav.js +0 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +2 -4
- package/dist/Outline/Outline.d.ts +2 -4
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +4 -52
- package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/useOutlineFromMarkdown.js +1 -0
- package/dist/Outline/useScrollSpy.js +3 -3
- package/dist/PowerSearch/PowerSearch.d.ts +36 -3
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +571 -302
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +100 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.js +1913 -0
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +32 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +17 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +170 -61
- package/dist/PowerSearch/formatFilterValue.d.ts +7 -0
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +11 -1
- package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
- package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
- package/dist/PowerSearch/formatTokenValue.js +160 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
- package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +8 -2
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -3
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +118 -260
- package/dist/Resizable/resizeGesture.d.ts +91 -0
- package/dist/Resizable/resizeGesture.d.ts.map +1 -0
- package/dist/Resizable/resizeGesture.js +251 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +3 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +115 -8
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +6 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -0
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +8 -1
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts +357 -0
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -0
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +1349 -0
- package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts +70 -0
- package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts.map +1 -0
- package/dist/SegmentedControl/useSegmentedTouchTracking.js +264 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +96 -67
- package/dist/Selector/optionShape.d.ts +24 -0
- package/dist/Selector/optionShape.d.ts.map +1 -0
- package/dist/Selector/optionShape.js +48 -0
- package/dist/Selector/selectableOptionEntries.d.ts +20 -0
- package/dist/Selector/selectableOptionEntries.d.ts.map +1 -0
- package/dist/Selector/selectableOptionEntries.js +38 -0
- package/dist/Selector/utils.d.ts +2 -17
- package/dist/Selector/utils.d.ts.map +1 -1
- package/dist/Selector/utils.js +3 -51
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +3 -9
- 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 +60 -58
- package/dist/Switch/switchTouch.d.ts +0 -7
- package/dist/Switch/switchTouch.d.ts.map +1 -1
- package/dist/Switch/switchTouch.js +2 -10
- package/dist/Switch/useSwitchTouch.d.ts +2 -11
- package/dist/Switch/useSwitchTouch.d.ts.map +1 -1
- package/dist/Switch/useSwitchTouch.js +35 -93
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -8
- package/dist/TextInput/TextInput.d.ts +2 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +10 -7
- package/dist/Toast/Toast.d.ts +11 -1
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +30 -15
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +94 -34
- package/dist/Toast/types.d.ts +9 -3
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Token/Token.d.ts +2 -2
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +13 -4
- package/dist/Token/TokenNamingContext.d.ts +14 -0
- package/dist/Token/TokenNamingContext.d.ts.map +1 -0
- package/dist/Token/TokenNamingContext.js +23 -0
- package/dist/Tokenizer/Tokenizer.d.ts +46 -59
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +40 -57
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts +25 -28
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
- package/dist/Tokenizer/TokenizerBottomSheet.js +157 -54
- package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts +3 -0
- package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -0
- package/dist/Tokenizer/TokenizerItemRemovableContext.js +19 -0
- package/dist/Tooltip/Tooltip.d.ts +25 -30
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +24 -5
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +45 -28
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +52 -59
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +4 -7
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +4 -7
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -7
- package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/animator/createAnimator.d.ts +98 -0
- package/dist/animator/createAnimator.d.ts.map +1 -0
- package/dist/animator/createAnimator.js +259 -0
- package/dist/astryx.css +96 -7
- package/dist/gestures/GestureHost.d.ts +27 -1
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +157 -21
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +4 -3
- package/dist/hooks/actionGroupTracker.d.ts +7 -4
- package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
- package/dist/hooks/actionGroupTracker.js +19 -56
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/pressGroupContext.d.ts +6 -0
- package/dist/hooks/pressGroupContext.d.ts.map +1 -0
- package/dist/hooks/pressGroupContext.js +20 -0
- package/dist/hooks/useActionGroupTracking.d.ts +53 -0
- package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
- package/dist/hooks/useActionGroupTracking.js +174 -0
- package/dist/hooks/useAnimator.d.ts +41 -0
- package/dist/hooks/useAnimator.d.ts.map +1 -0
- package/dist/hooks/useAnimator.js +70 -0
- package/dist/hooks/useAttachment.d.ts +1 -1
- package/dist/hooks/useAttachment.js +1 -1
- package/dist/hooks/useHighlightedOptionScroll.d.ts +11 -1
- package/dist/hooks/useHighlightedOptionScroll.d.ts.map +1 -1
- package/dist/hooks/useHighlightedOptionScroll.js +112 -11
- 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 +6 -2
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +95 -15
- package/dist/hooks/useMediaQuery.d.ts +2 -1
- package/dist/hooks/useMediaQuery.d.ts.map +1 -1
- package/dist/hooks/useMediaQuery.js +7 -4
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +4 -2
- package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts +8 -0
- package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/InfoTip/InfoTip.generated.js +12 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.js +1 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
- package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.js +7 -1
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +33 -1
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +33 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/internal/SheetConfirmation.d.ts +11 -0
- package/dist/internal/SheetConfirmation.d.ts.map +1 -0
- package/dist/internal/SheetConfirmation.js +92 -0
- package/dist/internal/indicatorPress.stylex.d.ts +20 -0
- package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
- package/dist/internal/indicatorPress.stylex.js +26 -0
- package/dist/internal/sheetDraft.d.ts +35 -0
- package/dist/internal/sheetDraft.d.ts.map +1 -0
- package/dist/internal/sheetDraft.js +65 -0
- package/dist/internal/touch-sheet.d.ts +21 -0
- package/dist/internal/touch-sheet.d.ts.map +1 -0
- package/dist/internal/touch-sheet.js +19 -0
- package/dist/internal/useDismissSearchOnTouchDrag.d.ts +24 -0
- package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +1 -0
- package/dist/internal/useDismissSearchOnTouchDrag.js +56 -0
- package/dist/motion/animator.d.ts +14 -14
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +41 -18
- package/dist/motion/reducedMotion.d.ts +24 -0
- package/dist/motion/reducedMotion.d.ts.map +1 -1
- package/dist/motion/reducedMotion.js +78 -1
- package/dist/motion/roles.d.ts +7 -1
- package/dist/motion/roles.d.ts.map +1 -1
- package/dist/motion/roles.js +20 -1
- package/dist/motion/uikit/alert.d.ts +41 -0
- package/dist/motion/uikit/alert.d.ts.map +1 -0
- package/dist/motion/uikit/alert.js +43 -0
- package/dist/motion/uikit/index.d.ts +6 -5
- package/dist/motion/uikit/index.d.ts.map +1 -1
- package/dist/motion/uikit/index.js +6 -5
- package/dist/motion/uikit/segmented.d.ts +55 -0
- package/dist/motion/uikit/segmented.d.ts.map +1 -0
- package/dist/motion/uikit/segmented.js +77 -0
- package/dist/motion/uikit/springs.d.ts +0 -18
- package/dist/motion/uikit/springs.d.ts.map +1 -1
- package/dist/motion/uikit/springs.js +5 -21
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts +15 -0
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/pressGroupItem.stylex.js +23 -0
- package/dist/privateAttributes/segmentTitle.stylex.d.ts +5 -0
- package/dist/privateAttributes/segmentTitle.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/segmentTitle.stylex.js +22 -0
- package/dist/utils/browserClickWait.d.ts +35 -0
- package/dist/utils/browserClickWait.d.ts.map +1 -0
- package/dist/utils/browserClickWait.js +123 -0
- package/dist/utils/clickGuard.d.ts +14 -1
- package/dist/utils/clickGuard.d.ts.map +1 -1
- package/dist/utils/clickGuard.js +46 -1
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +12 -0
- package/dist/utils/focusReturn.d.ts +15 -0
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +28 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +3 -2
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +19 -6
- package/dist/utils/triggerFocus.d.ts +36 -0
- package/dist/utils/triggerFocus.d.ts.map +1 -0
- package/dist/utils/triggerFocus.js +65 -0
- package/locales/en.json +128 -0
- package/locales/pseudo.json +96 -0
- package/package.json +18 -8
- package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
- package/src/AlertDialog/AlertDialog.tsx +37 -5
- package/src/AppShell/useCloseMobileDrawerOnActivate.ts +52 -0
- package/src/BottomSheet/BottomSheet.tsx +95 -10
- package/src/BottomSheet/BottomSheetPanel.tsx +40 -5
- package/src/BottomSheet/bottomSheetStack.ts +8 -4
- package/src/BottomSheet/useSheetGestures.ts +3 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +13 -3
- package/src/Button/Button.tsx +63 -5
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.tsx +36 -9
- package/src/CheckboxList/CheckboxList.doc.mjs +4 -2
- package/src/CheckboxList/CheckboxList.tsx +6 -0
- package/src/CheckboxList/CheckboxListContext.tsx +6 -0
- package/src/CheckboxList/CheckboxListItem.tsx +11 -2
- package/src/ComplexSelector/ComplexSelector.tsx +20 -5
- package/src/ContextMenu/ContextMenu.tsx +2 -2
- package/src/DateInput/DateInput.tsx +8 -2
- package/src/DateInput/MonthScroller.tsx +18 -22
- package/src/DateInput/Wheel.tsx +30 -32
- package/src/DateTimeInput/DateTimeInput.tsx +8 -2
- package/src/Dialog/Dialog.tsx +54 -45
- package/src/Drawer/Drawer.tsx +28 -11
- package/src/Drawer/useDrawerDialogPresence.ts +5 -1
- package/src/Field/Field.tsx +2 -2
- package/src/Field/PanelSearchInput.tsx +11 -0
- package/src/HoverCard/HoverCard.doc.mjs +4 -2
- package/src/HoverCard/HoverCard.tsx +35 -4
- package/src/HoverCard/useHoverCard.doc.mjs +178 -36
- package/src/HoverCard/useHoverCard.tsx +46 -52
- package/src/Icon/Icon.doc.mjs +49 -8
- package/src/Icon/Icon.tsx +15 -7
- package/src/InfoTip/InfoTip.doc.mjs +192 -0
- package/src/InfoTip/InfoTip.tsx +186 -0
- package/src/InfoTip/index.ts +14 -0
- package/src/Layer/layerAnimations.stylex.ts +24 -16
- package/src/Layer/useBackdropPress.ts +81 -0
- package/src/Layer/usePressPin.ts +86 -26
- package/src/Lightbox/Lightbox.tsx +18 -0
- package/src/MobileNav/MobileNav.tsx +1 -1
- package/src/MultiSelector/hooks.ts +2 -4
- package/src/Outline/Outline.doc.mjs +177 -51
- package/src/Outline/Outline.tsx +5 -57
- package/src/Outline/useOutlineFromMarkdown.doc.mjs +157 -0
- package/src/Outline/useOutlineFromMarkdown.ts +1 -0
- package/src/Outline/useScrollSpy.ts +3 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +55 -6
- package/src/PowerSearch/PowerSearch.tsx +798 -324
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +2515 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +28 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +203 -38
- package/src/PowerSearch/formatFilterValue.ts +18 -1
- package/src/PowerSearch/formatTokenValue.ts +215 -0
- package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
- package/src/RadioList/RadioList.doc.mjs +4 -2
- package/src/RadioList/RadioList.tsx +7 -2
- package/src/RadioList/RadioListItem.tsx +5 -3
- package/src/Resizable/ResizeHandle.tsx +133 -328
- package/src/Resizable/resizeGesture.ts +368 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +3 -3
- package/src/SegmentedControl/SegmentedControl.tsx +179 -5
- package/src/SegmentedControl/SegmentedControlContext.ts +6 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +12 -1
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +1640 -0
- package/src/SegmentedControl/useSegmentedTouchTracking.ts +308 -0
- package/src/Selector/Selector.tsx +136 -89
- package/src/Selector/optionShape.ts +64 -0
- package/src/Selector/selectableOptionEntries.ts +39 -0
- package/src/Selector/utils.ts +9 -68
- package/src/SideNav/SideNavItem.tsx +3 -7
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +77 -63
- package/src/Switch/switchTouch.ts +2 -10
- package/src/Switch/useSwitchTouch.ts +38 -104
- package/src/Table/BaseTable.tsx +46 -12
- package/src/TextInput/TextInput.tsx +11 -10
- package/src/Toast/Toast.doc.mjs +4 -3
- package/src/Toast/Toast.tsx +57 -32
- package/src/Toast/ToastViewport.tsx +121 -35
- package/src/Toast/types.ts +9 -3
- package/src/Token/Token.tsx +15 -4
- package/src/Token/TokenNamingContext.ts +28 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
- package/src/Tokenizer/Tokenizer.tsx +89 -85
- package/src/Tokenizer/TokenizerBottomSheet.tsx +219 -93
- package/src/Tokenizer/TokenizerItemRemovableContext.ts +24 -0
- package/src/Tooltip/Tooltip.doc.mjs +123 -54
- package/src/Tooltip/Tooltip.tsx +36 -39
- package/src/Tooltip/index.ts +0 -1
- package/src/Tooltip/useTooltip.doc.mjs +171 -33
- package/src/Tooltip/useTooltip.tsx +98 -86
- package/src/TopNav/TopNavItem.tsx +6 -5
- package/src/TopNav/TopNavMegaMenuItem.tsx +6 -5
- package/src/TopNav/TopNavMenu.tsx +6 -5
- package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/animator/createAnimator.doc.mjs +153 -0
- package/src/animator/createAnimator.ts +324 -0
- package/src/gestures/GestureHost.ts +198 -20
- package/src/gestures/PressTracker.ts +4 -3
- package/src/gestures/README.md +7 -1
- package/src/hooks/actionGroupTracker.ts +32 -61
- package/src/hooks/index.ts +2 -0
- package/src/hooks/pressGroupContext.ts +21 -0
- package/src/hooks/useActionGroupTracking.ts +224 -0
- package/src/hooks/useAnimator.doc.mjs +109 -0
- package/src/hooks/useAnimator.ts +67 -0
- package/src/hooks/useAttachment.ts +1 -1
- package/src/hooks/useHighlightedOptionScroll.ts +123 -15
- package/src/hooks/useInputStatusIcon.tsx +3 -2
- package/src/hooks/useLongPress.doc.mjs +2 -2
- package/src/hooks/useLongPress.ts +136 -15
- package/src/hooks/useMediaQuery.doc.mjs +2 -2
- package/src/hooks/useMediaQuery.ts +13 -4
- package/src/hooks/useMenuPress.ts +8 -2
- package/src/i18n/generated-english/InfoTip/InfoTip.generated.ts +13 -0
- package/src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts +1 -0
- package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
- package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
- package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
- package/src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts +7 -1
- package/src/i18n/generated-locales/en.generated.ts +43 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +44 -0
- package/src/index.ts +14 -0
- package/src/internal/SheetConfirmation.tsx +101 -0
- package/src/internal/indicatorPress.stylex.ts +24 -0
- package/src/internal/sheetDraft.ts +80 -0
- package/src/internal/touch-sheet.ts +21 -0
- package/src/internal/useDismissSearchOnTouchDrag.ts +69 -0
- package/src/motion/MEASUREMENTS.md +7 -0
- package/src/motion/README.md +9 -5
- package/src/motion/animator.ts +61 -29
- package/src/motion/reducedMotion.ts +79 -1
- package/src/motion/roles.ts +20 -1
- package/src/motion/uikit/alert.ts +43 -0
- package/src/motion/uikit/index.ts +5 -5
- package/src/motion/uikit/segmented.ts +74 -0
- package/src/motion/uikit/springs.ts +5 -21
- package/src/privateAttributes/pressGroupItem.stylex.ts +23 -0
- package/src/privateAttributes/segmentTitle.stylex.ts +22 -0
- package/src/utils/browserClickWait.ts +133 -0
- package/src/utils/clickGuard.ts +64 -1
- package/src/utils/dateParser.ts +16 -0
- package/src/utils/focusReturn.ts +30 -0
- package/src/utils/interactionOverlay.stylex.ts +3 -2
- package/src/utils/pressFeedback.ts +19 -6
- package/src/utils/triggerFocus.ts +80 -0
- package/dist/internal/tokenizer-presentation.d.ts +0 -21
- package/dist/internal/tokenizer-presentation.d.ts.map +0 -1
- package/dist/internal/tokenizer-presentation.js +0 -21
- package/src/internal/tokenizer-presentation.ts +0 -25
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useSegmentedTouchTracking.ts
|
|
7
|
+
* @input The radiogroup element, the selection motion controller and whether
|
|
8
|
+
* the control is enabled
|
|
9
|
+
* @output useSegmentedTouchTracking (a press of any pointer, landing to
|
|
10
|
+
* lift, and its ClickWait), and segmentTargetAt, measureSegments and
|
|
11
|
+
* liftTargetAt, the segment a pointer counts for
|
|
12
|
+
* @position Internal to SegmentedControl; drives useSegmentedSelectionMotion.ts
|
|
13
|
+
*
|
|
14
|
+
* SYNC: When modified, update:
|
|
15
|
+
* - /packages/core/src/SegmentedControl/useSegmentedSelectionMotion.ts
|
|
16
|
+
* - /packages/core/src/SegmentedControl/__tests__/SegmentedControl.interaction.browser.spec.ts
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {useRef, useState, type RefObject} from 'react';
|
|
20
|
+
import {PanGestureRecognizer} from '../gestures/PanGestureRecognizer';
|
|
21
|
+
import {useGestureRecognizer} from '../gestures/useGestureRecognizer';
|
|
22
|
+
import {usePressTracker} from '../gestures/usePressTracker';
|
|
23
|
+
import {
|
|
24
|
+
createActionGroupTracker,
|
|
25
|
+
type ActionGroupTarget,
|
|
26
|
+
type ActionGroupTracker,
|
|
27
|
+
} from '../hooks/actionGroupTracker';
|
|
28
|
+
import {lockSelection} from '../gestures/selectionLock';
|
|
29
|
+
import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
30
|
+
import {awaitBrowserClick, clickForLift} from '../utils/browserClickWait';
|
|
31
|
+
import {
|
|
32
|
+
SEGMENT_SELECTOR,
|
|
33
|
+
type SegmentedSelectionMotion,
|
|
34
|
+
} from './useSegmentedSelectionMotion';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A tap's click still to come. Until it runs, a focus move the tap causes
|
|
38
|
+
* selects nothing. A key press, the next press or a cancel ends the wait.
|
|
39
|
+
*/
|
|
40
|
+
export interface ClickWait {
|
|
41
|
+
readonly isAwaiting: () => boolean;
|
|
42
|
+
readonly end: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A ref to nothing: hooks given it attach nothing. */
|
|
46
|
+
const DETACHED: RefObject<HTMLElement | null> = {current: null};
|
|
47
|
+
|
|
48
|
+
/** The control's box as measured when the finger landed: viewport px. */
|
|
49
|
+
export interface ControlBounds {
|
|
50
|
+
readonly left: number;
|
|
51
|
+
readonly top: number;
|
|
52
|
+
readonly right: number;
|
|
53
|
+
readonly bottom: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** A segment as measured when the finger landed: its viewport span, px. */
|
|
57
|
+
export interface SegmentSpan {
|
|
58
|
+
readonly element: HTMLElement;
|
|
59
|
+
readonly left: number;
|
|
60
|
+
readonly right: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Every segment of `track`, disabled ones included, measured once. */
|
|
64
|
+
export function measureSegments(track: HTMLElement): SegmentSpan[] {
|
|
65
|
+
return Array.from(
|
|
66
|
+
track.querySelectorAll<HTMLElement>(SEGMENT_SELECTOR),
|
|
67
|
+
element => {
|
|
68
|
+
const rect = element.getBoundingClientRect();
|
|
69
|
+
return {element, left: rect.left, right: rect.right};
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isDisabled(element: HTMLElement): boolean {
|
|
75
|
+
return (
|
|
76
|
+
element.hasAttribute('disabled') ||
|
|
77
|
+
element.getAttribute('aria-disabled') === 'true'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The segment a finger at viewport `x` counts for: the one under it, else the
|
|
83
|
+
* nearest. A gap between two segments splits at its middle, as UIKit's
|
|
84
|
+
* segments share an edge. Past the ends, the end segment counts. The result is
|
|
85
|
+
* null when that segment is disabled.
|
|
86
|
+
*/
|
|
87
|
+
export function segmentTargetAt(
|
|
88
|
+
x: number,
|
|
89
|
+
segments: ReadonlyArray<SegmentSpan>,
|
|
90
|
+
): HTMLElement | null {
|
|
91
|
+
let best: SegmentSpan | null = null;
|
|
92
|
+
let distance = Infinity;
|
|
93
|
+
for (const segment of segments) {
|
|
94
|
+
const d = Math.max(segment.left - x, 0, x - segment.right);
|
|
95
|
+
if (d < distance) {
|
|
96
|
+
distance = d;
|
|
97
|
+
best = segment;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return best != null && !isDisabled(best.element) ? best.element : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The segment a lift at viewport (`x`, `y`) commits: inside the control's
|
|
105
|
+
* `bounds`, the one `segmentTargetAt` counts it for; outside them, none. A
|
|
106
|
+
* press that slides off cancels, because the control selects rather than
|
|
107
|
+
* toggles: a second press would not undo it.
|
|
108
|
+
*/
|
|
109
|
+
export function liftTargetAt(
|
|
110
|
+
x: number,
|
|
111
|
+
y: number,
|
|
112
|
+
bounds: ControlBounds,
|
|
113
|
+
segments: ReadonlyArray<SegmentSpan>,
|
|
114
|
+
): HTMLElement | null {
|
|
115
|
+
if (
|
|
116
|
+
x < bounds.left ||
|
|
117
|
+
x > bounds.right ||
|
|
118
|
+
y < bounds.top ||
|
|
119
|
+
y > bounds.bottom
|
|
120
|
+
) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return segmentTargetAt(x, segments);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const NO_BOUNDS: ControlBounds = {left: 0, top: 0, right: -1, bottom: -1};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Tracks a press on the control as UIKit's segmented control does. The press
|
|
130
|
+
* tracker reports the press from landing to lift. It never claims the
|
|
131
|
+
* pointer, so a vertical drag still scrolls the page. A horizontal pan
|
|
132
|
+
* carries the lens. It claims the pointer only past its slop, and the lift
|
|
133
|
+
* still ends the press.
|
|
134
|
+
*
|
|
135
|
+
* The lift decides the segment, wherever the press began. Inside the control,
|
|
136
|
+
* the segment under the pointer counts, else the nearest one. Outside the
|
|
137
|
+
* control, nothing counts.
|
|
138
|
+
*
|
|
139
|
+
* A tap gets the browser's own click. A drag gets no click from the browser,
|
|
140
|
+
* so the tracker clicks the segment at the lift. Either way the item's
|
|
141
|
+
* `onClick` runs once and can cancel the selection. A mouse and a pen are
|
|
142
|
+
* tracked as a finger is. Keyboard and assistive technology keep the click.
|
|
143
|
+
*/
|
|
144
|
+
export function useSegmentedTouchTracking(
|
|
145
|
+
trackRef: RefObject<HTMLElement | null>,
|
|
146
|
+
motion: SegmentedSelectionMotion,
|
|
147
|
+
isEnabled: boolean,
|
|
148
|
+
): ClickWait {
|
|
149
|
+
/** The horizontal pan began for this touch: it is a drag, not a tap. */
|
|
150
|
+
const isDraggingRef = useRef(false);
|
|
151
|
+
/** The segments as the finger found them (disabled ones too). */
|
|
152
|
+
const segmentsRef = useRef<SegmentSpan[]>([]);
|
|
153
|
+
/** The control's box as the finger found it: a lift outside it cancels. */
|
|
154
|
+
const boundsRef = useRef<ControlBounds>(NO_BOUNDS);
|
|
155
|
+
const trackerRef = useRef<ActionGroupTracker | null>(null);
|
|
156
|
+
const tracker = (trackerRef.current ??= createActionGroupTracker(() => ({
|
|
157
|
+
roots: () => [trackRef.current],
|
|
158
|
+
itemSelector: SEGMENT_SELECTOR,
|
|
159
|
+
highlightExpansion: 0,
|
|
160
|
+
// The press controller writes the shared press paint on the touched
|
|
161
|
+
// segment, as everywhere under a finger. The tracker paints nothing of its
|
|
162
|
+
// own. A held lens shows the selected face.
|
|
163
|
+
paintsHighlight: false,
|
|
164
|
+
resolveTarget: (
|
|
165
|
+
x: number,
|
|
166
|
+
y: number,
|
|
167
|
+
_targets: ReadonlyArray<ActionGroupTarget>,
|
|
168
|
+
) => liftTargetAt(x, y, boundsRef.current, segmentsRef.current),
|
|
169
|
+
onActivated: (item, cancelled) => {
|
|
170
|
+
const track = trackRef.current;
|
|
171
|
+
const value = item.dataset.value;
|
|
172
|
+
if (track != null && value != null) {
|
|
173
|
+
motion.clicked(track, value, cancelled);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
swallowsNativeClick: true,
|
|
177
|
+
})));
|
|
178
|
+
/** Click waits still running: an unmount ends them. */
|
|
179
|
+
const pendingClicksRef = useRef<Set<() => void>>(new Set());
|
|
180
|
+
/**
|
|
181
|
+
* A tap lifted and its click has not run. After a direct click, the
|
|
182
|
+
* browser's late copy can still move focus, so the wait then lasts until the
|
|
183
|
+
* next key or press.
|
|
184
|
+
*/
|
|
185
|
+
const clickToComeRef = useRef(false);
|
|
186
|
+
const [clickWait] = useState<ClickWait>(() => ({
|
|
187
|
+
isAwaiting: () => clickToComeRef.current,
|
|
188
|
+
end: () => {
|
|
189
|
+
clickToComeRef.current = false;
|
|
190
|
+
},
|
|
191
|
+
}));
|
|
192
|
+
// Ends the tracker's window listeners and any click wait on unmount.
|
|
193
|
+
useIsomorphicLayoutEffect(() => {
|
|
194
|
+
const pendingClicks = pendingClicksRef.current;
|
|
195
|
+
return () => {
|
|
196
|
+
tracker.dispose();
|
|
197
|
+
clickWait.end();
|
|
198
|
+
for (const end of [...pendingClicks]) {
|
|
199
|
+
end();
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}, [tracker, clickWait]);
|
|
203
|
+
|
|
204
|
+
// Every pointer type is tracked. A disabled control attaches nothing.
|
|
205
|
+
const attachRef = isEnabled ? trackRef : DETACHED;
|
|
206
|
+
usePressTracker(attachRef, {
|
|
207
|
+
isEnabled: () => isEnabled,
|
|
208
|
+
onControlEvent: (event, touch) => {
|
|
209
|
+
const track = trackRef.current;
|
|
210
|
+
if (track == null) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
switch (event) {
|
|
214
|
+
case 'touchDown': {
|
|
215
|
+
clickWait.end();
|
|
216
|
+
isDraggingRef.current = false;
|
|
217
|
+
segmentsRef.current = measureSegments(track);
|
|
218
|
+
const rect = track.getBoundingClientRect();
|
|
219
|
+
boundsRef.current = {
|
|
220
|
+
left: rect.left,
|
|
221
|
+
top: rect.top,
|
|
222
|
+
right: rect.right,
|
|
223
|
+
bottom: rect.bottom,
|
|
224
|
+
};
|
|
225
|
+
tracker.begin(touch.x, touch.y);
|
|
226
|
+
motion.begin(track, tracker.beganOn, touch.pointerType === 'touch');
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case 'touchUpInside':
|
|
230
|
+
case 'touchUpOutside': {
|
|
231
|
+
// The lift decides, wherever the press began. A lift outside the
|
|
232
|
+
// control commits nothing.
|
|
233
|
+
tracker.move(touch.x, touch.y);
|
|
234
|
+
const lifted = tracker.highlighted;
|
|
235
|
+
const isTap =
|
|
236
|
+
event === 'touchUpInside' &&
|
|
237
|
+
!isDraggingRef.current &&
|
|
238
|
+
lifted != null &&
|
|
239
|
+
lifted === tracker.beganOn;
|
|
240
|
+
const value = motion.release(lifted);
|
|
241
|
+
if (value != null && isTap && lifted != null) {
|
|
242
|
+
// A tap: the browser's own click commits it.
|
|
243
|
+
tracker.cancel();
|
|
244
|
+
clickToComeRef.current = true;
|
|
245
|
+
const pending = pendingClicksRef.current;
|
|
246
|
+
const endWait = awaitBrowserClick(lifted, {
|
|
247
|
+
onClicked: isCancelled => {
|
|
248
|
+
pending.delete(endWait);
|
|
249
|
+
clickWait.end();
|
|
250
|
+
motion.clicked(track, value, isCancelled);
|
|
251
|
+
},
|
|
252
|
+
onNoClick: () => {
|
|
253
|
+
pending.delete(endWait);
|
|
254
|
+
motion.clicked(track, value, clickForLift(lifted));
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
pending.add(endWait);
|
|
258
|
+
} else if (value != null) {
|
|
259
|
+
// No click comes from the browser for a drag: the segment's own
|
|
260
|
+
// click, inside the lift's event; its onClick may veto it.
|
|
261
|
+
tracker.end();
|
|
262
|
+
} else {
|
|
263
|
+
tracker.cancel();
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case 'touchCancel':
|
|
268
|
+
clickWait.end();
|
|
269
|
+
tracker.cancel();
|
|
270
|
+
motion.cancel();
|
|
271
|
+
break;
|
|
272
|
+
case 'touchDragInside':
|
|
273
|
+
case 'touchDragOutside':
|
|
274
|
+
case 'touchDragEnter':
|
|
275
|
+
case 'touchDragExit':
|
|
276
|
+
// The horizontal pan carries the lens.
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
useGestureRecognizer(
|
|
282
|
+
attachRef,
|
|
283
|
+
() =>
|
|
284
|
+
new PanGestureRecognizer({
|
|
285
|
+
name: 'segmented-control-drag',
|
|
286
|
+
direction: 'horizontal',
|
|
287
|
+
cancelsTouchesInView: false,
|
|
288
|
+
// No title is selectable under a held finger, as in UIKit. A hold on
|
|
289
|
+
// the track does something: a drag carries the lens and commits where
|
|
290
|
+
// it lifts. So this recognizer brings the lock, and the host turns off
|
|
291
|
+
// text selection and the callout on the track while a finger is down.
|
|
292
|
+
selectionLock: lockSelection,
|
|
293
|
+
}),
|
|
294
|
+
recognizer => {
|
|
295
|
+
if (recognizer.state === 'began') {
|
|
296
|
+
isDraggingRef.current = true;
|
|
297
|
+
}
|
|
298
|
+
if (recognizer.state === 'began' || recognizer.state === 'changed') {
|
|
299
|
+
const {x, y} = recognizer.location();
|
|
300
|
+
// The lens chases the finger, then the tracker moves the highlight.
|
|
301
|
+
motion.drag(x);
|
|
302
|
+
tracker.move(x, y);
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{isEnabled},
|
|
306
|
+
);
|
|
307
|
+
return clickWait;
|
|
308
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import React, {
|
|
23
|
+
memo,
|
|
23
24
|
use,
|
|
24
25
|
useCallback,
|
|
25
26
|
useEffect,
|
|
@@ -37,6 +38,7 @@ import {useTooltip} from '../Tooltip';
|
|
|
37
38
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
38
39
|
import {useIndicator} from '../Indicator';
|
|
39
40
|
import type {IndicatorPosition} from '../Indicator';
|
|
41
|
+
import type {IndicatorComponent, IndicatorMap} from '../Indicator/types';
|
|
40
42
|
import type {IconName} from '../Icon';
|
|
41
43
|
import {
|
|
42
44
|
Field,
|
|
@@ -66,13 +68,8 @@ import {
|
|
|
66
68
|
borderVars,
|
|
67
69
|
} from '../theme/tokens.stylex';
|
|
68
70
|
import type {SelectorOptionType, SelectorOptionData} from './types';
|
|
69
|
-
import {
|
|
70
|
-
|
|
71
|
-
isDivider,
|
|
72
|
-
isSection,
|
|
73
|
-
normalizeOption,
|
|
74
|
-
getSelectableOptions,
|
|
75
|
-
} from './utils';
|
|
71
|
+
import {isOptionData, isDivider, isSection, normalizeOption} from './utils';
|
|
72
|
+
import {getSelectableOptionEntries} from './selectableOptionEntries';
|
|
76
73
|
import {useCombobox, useSelectedItemOffset} from './hooks';
|
|
77
74
|
import {useMenuPress} from '../hooks/useMenuPress';
|
|
78
75
|
import {useMenuOverflow} from '../DropdownMenu/useMenuOverflow';
|
|
@@ -917,6 +914,108 @@ function DefaultOption({option}: {option: SelectorOptionData}) {
|
|
|
917
914
|
);
|
|
918
915
|
}
|
|
919
916
|
|
|
917
|
+
interface SelectorOptionRowProps {
|
|
918
|
+
item: SelectorOptionData;
|
|
919
|
+
flatIndex: number;
|
|
920
|
+
id: string;
|
|
921
|
+
isHighlighted: boolean;
|
|
922
|
+
isSelected: boolean;
|
|
923
|
+
size: SelectorSize;
|
|
924
|
+
indicatorPosition: IndicatorPosition;
|
|
925
|
+
renderOption: ((option: SelectorOptionData) => ReactNode) | undefined;
|
|
926
|
+
SelectionMark: IndicatorComponent<IndicatorMap['check']>;
|
|
927
|
+
onSelect: (item: SelectorOptionData) => void;
|
|
928
|
+
onHover: (item: SelectorOptionData, flatIndex: number) => void;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Keep each prop stable across renders that do not change this row. A new
|
|
933
|
+
* `onSelect` or `renderOption` re-renders every row.
|
|
934
|
+
*/
|
|
935
|
+
const SelectorOptionRow = memo(function SelectorOptionRow({
|
|
936
|
+
item,
|
|
937
|
+
flatIndex,
|
|
938
|
+
id,
|
|
939
|
+
isHighlighted,
|
|
940
|
+
isSelected,
|
|
941
|
+
size,
|
|
942
|
+
indicatorPosition,
|
|
943
|
+
renderOption,
|
|
944
|
+
SelectionMark,
|
|
945
|
+
onSelect,
|
|
946
|
+
onHover,
|
|
947
|
+
}: SelectorOptionRowProps) {
|
|
948
|
+
/*
|
|
949
|
+
* Rendered UNCONDITIONALLY, with the state passed down: the default
|
|
950
|
+
* check draws nothing when unchecked, but a theme that replaces the
|
|
951
|
+
* `check` indicator with a radio needs the unselected state to draw
|
|
952
|
+
* its empty circle. `{isSelected && …}` would make that impossible.
|
|
953
|
+
*
|
|
954
|
+
* `selector-check` stays the stable target for the mark's position
|
|
955
|
+
* in the row; the indicator owns what the mark looks like.
|
|
956
|
+
*/
|
|
957
|
+
const mark = (
|
|
958
|
+
<span {...stylex.props(styles.itemMarkColumn)}>
|
|
959
|
+
<SelectionMark
|
|
960
|
+
state={isSelected ? 'checked' : 'unchecked'}
|
|
961
|
+
size="sm"
|
|
962
|
+
isDisabled={item.disabled ?? false}
|
|
963
|
+
{...themeProps('selector-check')}
|
|
964
|
+
/>
|
|
965
|
+
</span>
|
|
966
|
+
);
|
|
967
|
+
|
|
968
|
+
const optionContent = (
|
|
969
|
+
<span {...stylex.props(styles.itemContent)}>
|
|
970
|
+
{renderOption ? renderOption(item) : <DefaultOption option={item} />}
|
|
971
|
+
</span>
|
|
972
|
+
);
|
|
973
|
+
|
|
974
|
+
return (
|
|
975
|
+
<div
|
|
976
|
+
id={id}
|
|
977
|
+
role="option"
|
|
978
|
+
aria-selected={isSelected}
|
|
979
|
+
aria-disabled={item.disabled}
|
|
980
|
+
onClick={() => onSelect(item)}
|
|
981
|
+
onMouseEnter={() => onHover(item, flatIndex)}
|
|
982
|
+
{...mergeProps(
|
|
983
|
+
// Stable theme target on the option row itself, mirroring
|
|
984
|
+
// `multi-selector-option`: it carries the row's size and runtime
|
|
985
|
+
// state so a theme can express "selected option at large" or
|
|
986
|
+
// restyle a given row density without structural selectors. The
|
|
987
|
+
// row's padding is split across a base and a per-size override (the
|
|
988
|
+
// default `md` trims the block axis), so `size` is what a theme
|
|
989
|
+
// needs to reach it. Named `-option-row` because `selector-option`
|
|
990
|
+
// is the public SelectorOption content primitive, not this row.
|
|
991
|
+
themeProps('selector-option-row', {
|
|
992
|
+
size,
|
|
993
|
+
selected: isSelected ? 'selected' : null,
|
|
994
|
+
disabled: item.disabled ? 'disabled' : null,
|
|
995
|
+
}),
|
|
996
|
+
stylex.props(
|
|
997
|
+
styles.item,
|
|
998
|
+
itemSizeStyles[size],
|
|
999
|
+
isHighlighted && styles.itemHighlighted,
|
|
1000
|
+
isSelected && styles.itemSelected,
|
|
1001
|
+
item.disabled && styles.itemDisabled,
|
|
1002
|
+
),
|
|
1003
|
+
)}>
|
|
1004
|
+
{indicatorPosition === 'start' ? (
|
|
1005
|
+
<>
|
|
1006
|
+
{mark}
|
|
1007
|
+
{optionContent}
|
|
1008
|
+
</>
|
|
1009
|
+
) : (
|
|
1010
|
+
<>
|
|
1011
|
+
{optionContent}
|
|
1012
|
+
{mark}
|
|
1013
|
+
</>
|
|
1014
|
+
)}
|
|
1015
|
+
</div>
|
|
1016
|
+
);
|
|
1017
|
+
});
|
|
1018
|
+
|
|
920
1019
|
// Case-insensitive substring match for a single option. The one predicate used
|
|
921
1020
|
// by both the flat filter (count + keyboard nav) and the grouped renderer, so
|
|
922
1021
|
// what is shown while searching stays in lockstep with the announced count.
|
|
@@ -1118,10 +1217,19 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1118
1217
|
: ariaLabelledBy;
|
|
1119
1218
|
|
|
1120
1219
|
// Flatten options for keyboard navigation
|
|
1121
|
-
const
|
|
1122
|
-
() =>
|
|
1220
|
+
const selectableEntries = useMemo(
|
|
1221
|
+
() => getSelectableOptionEntries(options),
|
|
1123
1222
|
[options],
|
|
1124
1223
|
);
|
|
1224
|
+
const selectableItems = useMemo(
|
|
1225
|
+
() => selectableEntries.map(entry => entry.item),
|
|
1226
|
+
[selectableEntries],
|
|
1227
|
+
);
|
|
1228
|
+
// Rows need the same item object on every render, or their memo fails.
|
|
1229
|
+
const normalizedOf = useMemo(
|
|
1230
|
+
() => new Map(selectableEntries.map(entry => [entry.source, entry.item])),
|
|
1231
|
+
[selectableEntries],
|
|
1232
|
+
);
|
|
1125
1233
|
|
|
1126
1234
|
// `action` is declared on the shared option type for `MultiSelector`;
|
|
1127
1235
|
// this listbox has not adopted it, so it renders the option without the
|
|
@@ -1613,84 +1721,22 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1613
1721
|
|
|
1614
1722
|
// Render an individual item
|
|
1615
1723
|
const renderItem = useCallback(
|
|
1616
|
-
(item: SelectorOptionData, flatIndex: number) =>
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
state={isSelected ? 'checked' : 'unchecked'}
|
|
1633
|
-
size="sm"
|
|
1634
|
-
isDisabled={item.disabled ?? false}
|
|
1635
|
-
{...themeProps('selector-check')}
|
|
1636
|
-
/>
|
|
1637
|
-
</span>
|
|
1638
|
-
);
|
|
1639
|
-
|
|
1640
|
-
const optionContent = (
|
|
1641
|
-
<span {...stylex.props(styles.itemContent)}>
|
|
1642
|
-
{renderOption ? renderOption(item) : <DefaultOption option={item} />}
|
|
1643
|
-
</span>
|
|
1644
|
-
);
|
|
1645
|
-
|
|
1646
|
-
const content =
|
|
1647
|
-
indicatorPosition === 'start' ? (
|
|
1648
|
-
<>
|
|
1649
|
-
{mark}
|
|
1650
|
-
{optionContent}
|
|
1651
|
-
</>
|
|
1652
|
-
) : (
|
|
1653
|
-
<>
|
|
1654
|
-
{optionContent}
|
|
1655
|
-
{mark}
|
|
1656
|
-
</>
|
|
1657
|
-
);
|
|
1658
|
-
|
|
1659
|
-
return (
|
|
1660
|
-
<div
|
|
1661
|
-
key={item.value}
|
|
1662
|
-
id={getItemId(flatIndex)}
|
|
1663
|
-
role="option"
|
|
1664
|
-
aria-selected={isSelected}
|
|
1665
|
-
aria-disabled={item.disabled}
|
|
1666
|
-
onClick={() => onItemSelect(item)}
|
|
1667
|
-
onMouseEnter={() => onItemMouseEnter(item, flatIndex)}
|
|
1668
|
-
{...mergeProps(
|
|
1669
|
-
// Stable theme target on the option row itself, mirroring
|
|
1670
|
-
// `multi-selector-option`: it carries the row's size and runtime
|
|
1671
|
-
// state so a theme can express "selected option at large" or
|
|
1672
|
-
// restyle a given row density without structural selectors. The
|
|
1673
|
-
// row's padding is split across a base and a per-size override (the
|
|
1674
|
-
// default `md` trims the block axis), so `size` is what a theme
|
|
1675
|
-
// needs to reach it. Named `-option-row` because `selector-option`
|
|
1676
|
-
// is the public SelectorOption content primitive, not this row.
|
|
1677
|
-
themeProps('selector-option-row', {
|
|
1678
|
-
size,
|
|
1679
|
-
selected: isSelected ? 'selected' : null,
|
|
1680
|
-
disabled: item.disabled ? 'disabled' : null,
|
|
1681
|
-
}),
|
|
1682
|
-
stylex.props(
|
|
1683
|
-
styles.item,
|
|
1684
|
-
itemSizeStyles[size],
|
|
1685
|
-
isHighlighted && styles.itemHighlighted,
|
|
1686
|
-
isSelected && styles.itemSelected,
|
|
1687
|
-
item.disabled && styles.itemDisabled,
|
|
1688
|
-
),
|
|
1689
|
-
)}>
|
|
1690
|
-
{content}
|
|
1691
|
-
</div>
|
|
1692
|
-
);
|
|
1693
|
-
},
|
|
1724
|
+
(item: SelectorOptionData, flatIndex: number) => (
|
|
1725
|
+
<SelectorOptionRow
|
|
1726
|
+
key={item.value}
|
|
1727
|
+
item={item}
|
|
1728
|
+
flatIndex={flatIndex}
|
|
1729
|
+
id={getItemId(flatIndex)}
|
|
1730
|
+
isHighlighted={flatIndex === highlightedIndex}
|
|
1731
|
+
isSelected={item.value === normalizedValue}
|
|
1732
|
+
size={size}
|
|
1733
|
+
indicatorPosition={indicatorPosition}
|
|
1734
|
+
renderOption={renderOption}
|
|
1735
|
+
SelectionMark={SelectionMark}
|
|
1736
|
+
onSelect={onItemSelect}
|
|
1737
|
+
onHover={onItemMouseEnter}
|
|
1738
|
+
/>
|
|
1739
|
+
),
|
|
1694
1740
|
[
|
|
1695
1741
|
renderOption,
|
|
1696
1742
|
indicatorPosition,
|
|
@@ -1757,7 +1803,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1757
1803
|
} else if (isSection(option)) {
|
|
1758
1804
|
const sectionItems: ReactNode[] = [];
|
|
1759
1805
|
for (const opt of option.options) {
|
|
1760
|
-
const normalized = normalizeOption(opt);
|
|
1806
|
+
const normalized = normalizedOf.get(opt) ?? normalizeOption(opt);
|
|
1761
1807
|
if (isSearching && !optionMatchesQuery(normalized, searchQuery)) {
|
|
1762
1808
|
continue;
|
|
1763
1809
|
}
|
|
@@ -1790,7 +1836,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1790
1836
|
</div>,
|
|
1791
1837
|
);
|
|
1792
1838
|
} else if (isOptionData(option)) {
|
|
1793
|
-
const normalized = normalizeOption(option);
|
|
1839
|
+
const normalized = normalizedOf.get(option) ?? normalizeOption(option);
|
|
1794
1840
|
if (isSearching && !optionMatchesQuery(normalized, searchQuery)) {
|
|
1795
1841
|
continue;
|
|
1796
1842
|
}
|
|
@@ -1802,6 +1848,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1802
1848
|
return elements;
|
|
1803
1849
|
}, [
|
|
1804
1850
|
options,
|
|
1851
|
+
normalizedOf,
|
|
1805
1852
|
renderItem,
|
|
1806
1853
|
hasSearch,
|
|
1807
1854
|
searchQuery,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file optionShape.ts
|
|
5
|
+
* @input Selector option values
|
|
6
|
+
* @output The option type guards and `normalizeOption`
|
|
7
|
+
* @position Internal; re-exported by utils.ts, the public entry point
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
SelectorOptionType,
|
|
12
|
+
SelectorOptionData,
|
|
13
|
+
SelectorDivider,
|
|
14
|
+
SelectorSection,
|
|
15
|
+
} from './types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Type guard: check if option is a selectable option (string or OptionData)
|
|
19
|
+
*/
|
|
20
|
+
export function isOptionData(
|
|
21
|
+
option: SelectorOptionType,
|
|
22
|
+
): option is SelectorOptionData | string {
|
|
23
|
+
if (typeof option === 'string') {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return !('type' in option);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Type guard: check if option is a divider
|
|
31
|
+
*/
|
|
32
|
+
export function isDivider(
|
|
33
|
+
option: SelectorOptionType,
|
|
34
|
+
): option is SelectorDivider {
|
|
35
|
+
return (
|
|
36
|
+
typeof option === 'object' && 'type' in option && option.type === 'divider'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Type guard: check if option is a section
|
|
42
|
+
*/
|
|
43
|
+
export function isSection(
|
|
44
|
+
option: SelectorOptionType,
|
|
45
|
+
): option is SelectorSection {
|
|
46
|
+
return (
|
|
47
|
+
typeof option === 'object' && 'type' in option && option.type === 'section'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Normalize string or option to consistent shape
|
|
53
|
+
*/
|
|
54
|
+
export function normalizeOption(
|
|
55
|
+
option: string | SelectorOptionData,
|
|
56
|
+
): SelectorOptionData {
|
|
57
|
+
if (typeof option === 'string') {
|
|
58
|
+
return {value: option, label: option};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
...option,
|
|
62
|
+
label: option.label ?? option.value,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file selectableOptionEntries.ts
|
|
5
|
+
* @input Selector options, with sections and dividers
|
|
6
|
+
* @output `getSelectableOptionEntries`: each selectable item with the option
|
|
7
|
+
* it was given as
|
|
8
|
+
* @position Internal; the one walk behind utils.ts's `getSelectableOptions`
|
|
9
|
+
* and Selector's rows
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {SelectorOptionType, SelectorOptionData} from './types';
|
|
13
|
+
import {isOptionData, isSection, normalizeOption} from './optionShape';
|
|
14
|
+
|
|
15
|
+
/** A selectable option as given, and its normalized data. */
|
|
16
|
+
export interface SelectableOptionEntry {
|
|
17
|
+
readonly source: string | SelectorOptionData;
|
|
18
|
+
readonly item: SelectorOptionData;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Every selectable option (sections flattened, dividers skipped), each with
|
|
23
|
+
* the option it was given as.
|
|
24
|
+
*/
|
|
25
|
+
export function getSelectableOptionEntries(
|
|
26
|
+
options: SelectorOptionType[],
|
|
27
|
+
): SelectableOptionEntry[] {
|
|
28
|
+
const result: SelectableOptionEntry[] = [];
|
|
29
|
+
for (const option of options) {
|
|
30
|
+
if (isOptionData(option)) {
|
|
31
|
+
result.push({source: option, item: normalizeOption(option)});
|
|
32
|
+
} else if (isSection(option)) {
|
|
33
|
+
for (const opt of option.options) {
|
|
34
|
+
result.push({source: opt, item: normalizeOption(opt)});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|