@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
|
@@ -4,43 +4,57 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file PowerSearch.tsx
|
|
7
|
-
* @input PowerSearchConfig, filters, onChange
|
|
7
|
+
* @input PowerSearchConfig, filters, onChange; Tokenizer, Field parts, Token,
|
|
8
|
+
* useAdaptivePresentation, and PowerSearchBottomSheet (lazy)
|
|
8
9
|
* @output Structured filter bar with token-based filter management
|
|
9
10
|
* @position Main component; forwards DOM ref and exposes tokenizer control via
|
|
10
|
-
* handleRef
|
|
11
|
+
* handleRef. The experimental `presentation` option swaps the tokenizer
|
|
12
|
+
* field and editor popover for one trigger that opens PowerSearchBottomSheet.
|
|
11
13
|
*
|
|
12
14
|
* SYNC: When modified, update:
|
|
13
15
|
* - /packages/core/src/PowerSearch/index.ts
|
|
16
|
+
* - /packages/core/src/PowerSearch/PowerSearchBottomSheet.tsx (sheet presentation)
|
|
14
17
|
* - /packages/cli/assets/templates/blocks/components/PowerSearch/ (showcase blocks)
|
|
15
18
|
*/
|
|
16
|
-
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
19
|
+
import React, { lazy, Suspense, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
17
20
|
import * as stylex from '@stylexjs/stylex';
|
|
18
21
|
import { Tokenizer } from "../Tokenizer/index.js";
|
|
19
22
|
import { TokenizerClearAllMessageContext } from "../Tokenizer/TokenizerClearAllMessageContext.js";
|
|
23
|
+
import { TokenizerItemRemovableContext } from "../Tokenizer/TokenizerItemRemovableContext.js";
|
|
20
24
|
import { TypeaheadItem } from "../Typeahead/TypeaheadItem.js";
|
|
21
25
|
import { Token } from "../Token/index.js";
|
|
26
|
+
import { TokenNamingContext } from "../Token/TokenNamingContext.js";
|
|
22
27
|
import { Avatar } from "../Avatar/index.js";
|
|
23
28
|
import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
|
|
24
|
-
import { Icon } from "../Icon/index.js";
|
|
29
|
+
import { Icon, renderIconSlot } from "../Icon/index.js";
|
|
30
|
+
import { Field } from "../Field/Field.js";
|
|
31
|
+
import { inputStatusBorderStyles, inputStatusFocusWithinStyles, inputStatusHoverShadowStyles, inputWrapperStyles } from "../Field/inputStyles.stylex.js";
|
|
25
32
|
import { usePopover } from "../Popover/usePopover.js";
|
|
33
|
+
import { useTooltip } from "../Tooltip/useTooltip.js";
|
|
26
34
|
import "../Layer/layerViewportInset.stylex.js";
|
|
27
35
|
import { layerViewportInset } from "../Layer/layerViewportInset.stylex.js";
|
|
28
36
|
import { useAnnounce } from "../hooks/useAnnounce.js";
|
|
37
|
+
import { useAdaptivePresentation } from "../hooks/useAdaptivePresentation.js";
|
|
38
|
+
import { useDevWarning } from "../hooks/useDevWarning.js";
|
|
39
|
+
import { useIsHydrating } from "../hooks/useIsHydrating.js";
|
|
29
40
|
import "../theme/tokens.stylex.js";
|
|
30
|
-
import { spacingVars, colorVars, typeScaleVars, fontWeightVars } from "../theme/tokens.stylex.js";
|
|
41
|
+
import { spacingVars, colorVars, sizeVars, typeScaleVars, typographyVars, fontWeightVars } from "../theme/tokens.stylex.js";
|
|
31
42
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
43
|
+
import { isFocusDetached } from "../utils/focusReturn.js";
|
|
44
|
+
import { isRenderable } from "../utils/isRenderable.js";
|
|
32
45
|
import { useInternalConfig } from "./useInternalConfig.js";
|
|
33
46
|
import { usePowerSearchSource } from "./usePowerSearchSource.js";
|
|
34
|
-
import { formatFilterValue
|
|
35
|
-
import { PowerSearchEditPopover } from "./PowerSearchEditPopover.js";
|
|
47
|
+
import { formatFilterValue } from "./formatFilterValue.js";
|
|
48
|
+
import { NestedEditor, PowerSearchEditPopover } from "./PowerSearchEditPopover.js";
|
|
49
|
+
import { buildRelativeDateOptions, PowerSearchValueEditor } from "./PowerSearchValueEditor.js";
|
|
36
50
|
import { resolveOperatorLabel } from "./resolveOperatorLabel.js";
|
|
37
51
|
import { themeProps } from "../utils/themeProps.js";
|
|
38
|
-
import { truncateCharacters } from "../utils/characters.js";
|
|
39
52
|
import { useLocale } from "../i18n/useLocale.js";
|
|
53
|
+
import { formatTokenValueText } from "./formatTokenValue.js";
|
|
40
54
|
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
41
55
|
import { registerEnglishFallback, useComponentTranslator } from "../i18n/useComponentTranslator.js";
|
|
42
56
|
import english from "../i18n/generated-english/PowerSearch/PowerSearch.generated.js";
|
|
43
|
-
import { jsx as _jsx,
|
|
57
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
44
58
|
registerEnglishFallback(english);
|
|
45
59
|
// =============================================================================
|
|
46
60
|
// Icon mapping for typeahead entries
|
|
@@ -81,219 +95,86 @@ const popoverLayerStyles = {
|
|
|
81
95
|
$$css: true
|
|
82
96
|
}
|
|
83
97
|
};
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
// The sheet presentation's trigger field: the same control box as the
|
|
99
|
+
// tokenizer field, with display-only tokens and one button as its only tab
|
|
100
|
+
// stop.
|
|
101
|
+
const sheetTriggerSizeStyles = {
|
|
102
|
+
sm: {
|
|
103
|
+
kAzted: "x1gdqauq",
|
|
104
|
+
$$css: true
|
|
105
|
+
},
|
|
106
|
+
md: {
|
|
107
|
+
kAzted: "x1uogy3y",
|
|
108
|
+
$$css: true
|
|
109
|
+
},
|
|
110
|
+
lg: {
|
|
111
|
+
kAzted: "x1xf4nls",
|
|
112
|
+
$$css: true
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const sheetTriggerStyles = {
|
|
116
|
+
wrapper: {
|
|
117
|
+
kVAEAm: "x1n2onr6",
|
|
118
|
+
kwnvtZ: "xozqiw3",
|
|
119
|
+
kOIVth: "xzye2dw",
|
|
120
|
+
kZKoxP: "xt7dq6l",
|
|
121
|
+
kkrTdU: "x1ypdohk xvivl9a",
|
|
122
|
+
$$css: true
|
|
123
|
+
},
|
|
124
|
+
wrapperWithTokens: {
|
|
125
|
+
k8WAf4: "x1x7cmac",
|
|
126
|
+
kg3NbH: "xx2oswg",
|
|
127
|
+
$$css: true
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// The sheet flow (three standalone sheets, the sheet editors) only
|
|
132
|
+
// renders for the bottom-sheet presentation. Loading it on demand keeps it out
|
|
133
|
+
// of pages whose PowerSearch stays a tokenizer field.
|
|
134
|
+
// One import promise, shared by the preload and the lazy element: the sheet
|
|
135
|
+
// presentation loads the flow's chunk as soon as it is active, so the first
|
|
136
|
+
// press does not wait for the network, while nothing of the flow is rendered
|
|
137
|
+
// until a press.
|
|
138
|
+
const loadPowerSearchBottomSheet = async () => import("./PowerSearchBottomSheet.js");
|
|
139
|
+
const LazyPowerSearchBottomSheet = /*#__PURE__*/lazy(async () => loadPowerSearchBottomSheet().then(module => ({
|
|
140
|
+
default: module.PowerSearchBottomSheet
|
|
141
|
+
})));
|
|
142
|
+
// The value step reuses the popover presentation's editors, which this
|
|
143
|
+
// module already loads; see PowerSearchSheetEditors.
|
|
144
|
+
const SHEET_EDITORS = {
|
|
145
|
+
NestedEditor,
|
|
146
|
+
PowerSearchValueEditor,
|
|
147
|
+
buildRelativeDateOptions
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Hosts the lazily loaded sheet flow. Renders nothing on the server or in the
|
|
152
|
+
* render that hydrates server HTML: a lazy component that has not loaded yet
|
|
153
|
+
* would leave server markup incomplete and abort hydration. The closed flow
|
|
154
|
+
* has no visible markup, so it first renders right after hydration.
|
|
155
|
+
*/
|
|
156
|
+
function PowerSearchSheetHost(props) {
|
|
157
|
+
const isHydrating = useIsHydrating();
|
|
158
|
+
if (isHydrating) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return /*#__PURE__*/_jsx(Suspense, {
|
|
162
|
+
fallback: null,
|
|
163
|
+
children: /*#__PURE__*/_jsx(LazyPowerSearchBottomSheet, {
|
|
164
|
+
...props,
|
|
165
|
+
editors: SHEET_EDITORS
|
|
166
|
+
})
|
|
167
|
+
});
|
|
91
168
|
}
|
|
92
169
|
function PowerSearchTokenValue({
|
|
93
|
-
|
|
94
|
-
filterValue,
|
|
95
|
-
maxLength,
|
|
96
|
-
locale
|
|
170
|
+
text
|
|
97
171
|
}) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
className: "x1lvx875"
|
|
105
|
-
},
|
|
106
|
-
children: truncateString(filterValue.value, maxLength)
|
|
107
|
-
});
|
|
108
|
-
case 'integer':
|
|
109
|
-
case 'float':
|
|
110
|
-
return /*#__PURE__*/_jsx("span", {
|
|
111
|
-
...{
|
|
112
|
-
className: "x1lvx875"
|
|
113
|
-
},
|
|
114
|
-
children: filterValue.value
|
|
115
|
-
});
|
|
116
|
-
case 'enum':
|
|
117
|
-
if (operatorValue.type === 'enum') {
|
|
118
|
-
return /*#__PURE__*/_jsx("span", {
|
|
119
|
-
...{
|
|
120
|
-
className: "x1lvx875"
|
|
121
|
-
},
|
|
122
|
-
children: truncateString(getEnumLabel(operatorValue.values, filterValue.value), maxLength)
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
return /*#__PURE__*/_jsx("span", {
|
|
126
|
-
...{
|
|
127
|
-
className: "x1lvx875"
|
|
128
|
-
},
|
|
129
|
-
children: truncateString(filterValue.value, maxLength)
|
|
130
|
-
});
|
|
131
|
-
case 'string_list':
|
|
132
|
-
{
|
|
133
|
-
const items = filterValue.value;
|
|
134
|
-
if (items.length === 0) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
if (items.length === 1) {
|
|
138
|
-
return /*#__PURE__*/_jsx("span", {
|
|
139
|
-
...{
|
|
140
|
-
className: "x1lvx875"
|
|
141
|
-
},
|
|
142
|
-
children: truncateString(items[0], maxLength)
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
const totalLength = items.reduce((sum, s) => sum + s.length, 0);
|
|
146
|
-
if (totalLength > maxLength) {
|
|
147
|
-
return /*#__PURE__*/_jsxs("span", {
|
|
148
|
-
...{
|
|
149
|
-
className: "x1lvx875"
|
|
150
|
-
},
|
|
151
|
-
children: [items.length, " items"]
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
return /*#__PURE__*/_jsx("span", {
|
|
155
|
-
...{
|
|
156
|
-
className: "x1lvx875"
|
|
157
|
-
},
|
|
158
|
-
children: items.join(', ')
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
case 'enum_list':
|
|
162
|
-
{
|
|
163
|
-
const items = filterValue.value;
|
|
164
|
-
if (items.length === 0) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
if (operatorValue.type === 'enum_list') {
|
|
168
|
-
const labels = items.map(v => getEnumLabel(operatorValue.values, v));
|
|
169
|
-
if (labels.length === 1) {
|
|
170
|
-
return /*#__PURE__*/_jsx("span", {
|
|
171
|
-
...{
|
|
172
|
-
className: "x1lvx875"
|
|
173
|
-
},
|
|
174
|
-
children: truncateString(labels[0], maxLength)
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
const totalLength = labels.reduce((sum, s) => sum + s.length, 0);
|
|
178
|
-
if (totalLength > maxLength) {
|
|
179
|
-
return /*#__PURE__*/_jsxs("span", {
|
|
180
|
-
...{
|
|
181
|
-
className: "x1lvx875"
|
|
182
|
-
},
|
|
183
|
-
children: [labels.length, " items"]
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
return /*#__PURE__*/_jsx("span", {
|
|
187
|
-
...{
|
|
188
|
-
className: "x1lvx875"
|
|
189
|
-
},
|
|
190
|
-
children: labels.join(', ')
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
if (items.length === 1) {
|
|
194
|
-
return /*#__PURE__*/_jsx("span", {
|
|
195
|
-
...{
|
|
196
|
-
className: "x1lvx875"
|
|
197
|
-
},
|
|
198
|
-
children: truncateString(items[0], maxLength)
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
return /*#__PURE__*/_jsxs("span", {
|
|
202
|
-
...{
|
|
203
|
-
className: "x1lvx875"
|
|
204
|
-
},
|
|
205
|
-
children: [items.length, " items"]
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
case 'entity_list':
|
|
209
|
-
{
|
|
210
|
-
const entities = filterValue.value;
|
|
211
|
-
if (entities.length === 0) {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
if (entities.length === 1) {
|
|
215
|
-
return /*#__PURE__*/_jsx("span", {
|
|
216
|
-
...{
|
|
217
|
-
className: "x1lvx875"
|
|
218
|
-
},
|
|
219
|
-
children: truncateString(entities[0].label, maxLength)
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
const totalLength = entities.reduce((sum, e) => sum + e.label.length, 0);
|
|
223
|
-
if (totalLength > maxLength) {
|
|
224
|
-
return /*#__PURE__*/_jsxs("span", {
|
|
225
|
-
...{
|
|
226
|
-
className: "x1lvx875"
|
|
227
|
-
},
|
|
228
|
-
children: [entities.length, " items"]
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
return /*#__PURE__*/_jsx("span", {
|
|
232
|
-
...{
|
|
233
|
-
className: "x1lvx875"
|
|
234
|
-
},
|
|
235
|
-
children: entities.map(e => e.label).join(', ')
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
case 'time':
|
|
239
|
-
return /*#__PURE__*/_jsx("span", {
|
|
240
|
-
...{
|
|
241
|
-
className: "x1lvx875"
|
|
242
|
-
},
|
|
243
|
-
children: filterValue.value
|
|
244
|
-
});
|
|
245
|
-
case 'date_absolute':
|
|
246
|
-
{
|
|
247
|
-
const formatted = formatDateAbsoluteCompact(filterValue.unixSeconds, locale);
|
|
248
|
-
return /*#__PURE__*/_jsx("span", {
|
|
249
|
-
...{
|
|
250
|
-
className: "x1lvx875"
|
|
251
|
-
},
|
|
252
|
-
children: truncateString(formatted, maxLength)
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
case 'date_relative':
|
|
256
|
-
return /*#__PURE__*/_jsx("span", {
|
|
257
|
-
...{
|
|
258
|
-
className: "x1lvx875"
|
|
259
|
-
},
|
|
260
|
-
children: truncateString(filterValue.value, maxLength)
|
|
261
|
-
});
|
|
262
|
-
case 'date_range':
|
|
263
|
-
return /*#__PURE__*/_jsx("span", {
|
|
264
|
-
...{
|
|
265
|
-
className: "x1lvx875"
|
|
266
|
-
},
|
|
267
|
-
children: "date range"
|
|
268
|
-
});
|
|
269
|
-
case 'custom':
|
|
270
|
-
if (operatorValue.type === 'custom') {
|
|
271
|
-
return /*#__PURE__*/_jsx("span", {
|
|
272
|
-
...{
|
|
273
|
-
className: "x1lvx875"
|
|
274
|
-
},
|
|
275
|
-
children: truncateString(operatorValue.getString(filterValue.value), maxLength)
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
return /*#__PURE__*/_jsx("span", {
|
|
279
|
-
...{
|
|
280
|
-
className: "x1lvx875"
|
|
281
|
-
},
|
|
282
|
-
children: filterValue.value
|
|
283
|
-
});
|
|
284
|
-
case 'nested':
|
|
285
|
-
{
|
|
286
|
-
const count = filterValue.value.length;
|
|
287
|
-
return /*#__PURE__*/_jsx("span", {
|
|
288
|
-
...{
|
|
289
|
-
className: "x1lvx875"
|
|
290
|
-
},
|
|
291
|
-
children: count === 1 ? '1 filter' : `${count} filters`
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
default:
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
172
|
+
return /*#__PURE__*/_jsx("span", {
|
|
173
|
+
...{
|
|
174
|
+
className: "x1lvx875"
|
|
175
|
+
},
|
|
176
|
+
children: text
|
|
177
|
+
});
|
|
297
178
|
}
|
|
298
179
|
|
|
299
180
|
// =============================================================================
|
|
@@ -308,6 +189,14 @@ function PowerSearchTokenValue({
|
|
|
308
189
|
// Component
|
|
309
190
|
// =============================================================================
|
|
310
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Whether a press on a token with this operator commits the filter instead of
|
|
194
|
+
* opening its editor: an `empty` operator with no `empty` Editor override.
|
|
195
|
+
*/
|
|
196
|
+
function commitsWithoutEditor(operator, componentOverrides) {
|
|
197
|
+
return operator?.value.type === 'empty' && componentOverrides?.empty?.Editor == null;
|
|
198
|
+
}
|
|
199
|
+
|
|
311
200
|
/**
|
|
312
201
|
* Structured filter bar where each token represents a filter (field + operator + value).
|
|
313
202
|
*
|
|
@@ -407,7 +296,8 @@ export function PowerSearch({
|
|
|
407
296
|
xstyle,
|
|
408
297
|
className,
|
|
409
298
|
style,
|
|
410
|
-
components: componentOverrides
|
|
299
|
+
components: componentOverrides,
|
|
300
|
+
experimental
|
|
411
301
|
}) {
|
|
412
302
|
const size = useSize(sizeProp, 'md');
|
|
413
303
|
const config = useInternalConfig(configProp);
|
|
@@ -418,12 +308,129 @@ export function PowerSearch({
|
|
|
418
308
|
const placeholder = placeholderFromProps ?? t('@astryx.powersearch.placeholder');
|
|
419
309
|
const popoverSaveButtonLabel = popoverSaveButtonLabelFromProps ?? t('@astryx.powersearch.editor.apply');
|
|
420
310
|
const tokenizerRef = useRef(null);
|
|
311
|
+
|
|
312
|
+
// Experimental presentation. `adaptive`
|
|
313
|
+
// resolves through the policy the selection controls share; an open flow
|
|
314
|
+
// keeps its presentation until it closes, so a resolution change mid-task
|
|
315
|
+
// cannot pull the surface out from under the person.
|
|
316
|
+
const presentation = experimental?.presentation ?? 'popover';
|
|
317
|
+
const resolvedPresentation = useAdaptivePresentation(presentation);
|
|
318
|
+
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
319
|
+
// Latched for the flow's lifetime: the flow stays presented after it closes
|
|
320
|
+
// until the sheets have run their exit and handed focus back to the trigger.
|
|
321
|
+
// Without the latch, `adaptive` resolving to `popover` mid-session (a phone
|
|
322
|
+
// turned to landscape) would unmount the sheets and the trigger they return
|
|
323
|
+
// focus to in the same render, dropping focus to the page body.
|
|
324
|
+
const [isSheetPresented, setIsSheetPresented] = useState(false);
|
|
325
|
+
const isSheetPresentation = isSheetOpen || isSheetPresented || resolvedPresentation === 'bottom-sheet';
|
|
326
|
+
const triggerRef = useRef(null);
|
|
327
|
+
// `hasAutoFocus` applies only to the control the field first mounts. A
|
|
328
|
+
// presentation swap remounts the control (combobox input or trigger), and
|
|
329
|
+
// React's `autoFocus` on the new one would pull focus from wherever on the
|
|
330
|
+
// page it was; the roots' callback refs hand over the focus the field held
|
|
331
|
+
// instead. A field that never swaps keeps `autoFocus` on every render, so a
|
|
332
|
+
// Dialog that keeps it mounted still finds its `data-autofocus` on open.
|
|
333
|
+
const [autoFocusState, setAutoFocusState] = useState({
|
|
334
|
+
presentation: isSheetPresentation,
|
|
335
|
+
isFirstControl: true
|
|
336
|
+
});
|
|
337
|
+
if (autoFocusState.presentation !== isSheetPresentation) {
|
|
338
|
+
setAutoFocusState({
|
|
339
|
+
presentation: isSheetPresentation,
|
|
340
|
+
isFirstControl: false
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
const autoFocusOnMount = hasAutoFocus && autoFocusState.isFirstControl && autoFocusState.presentation === isSheetPresentation;
|
|
344
|
+
// A focus the swap moves continues the same visit to the field: the
|
|
345
|
+
// control that held focus is gone (no blur fires for a removed element), so
|
|
346
|
+
// the caller is told of neither a blur nor a new focus.
|
|
347
|
+
const isSwapFocusRef = useRef(false);
|
|
348
|
+
const focusAfterSwap = useCallback(control => {
|
|
349
|
+
if (control == null) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
isSwapFocusRef.current = true;
|
|
353
|
+
try {
|
|
354
|
+
control.focus();
|
|
355
|
+
} finally {
|
|
356
|
+
isSwapFocusRef.current = false;
|
|
357
|
+
}
|
|
358
|
+
}, []);
|
|
359
|
+
const handleFieldFocus = useCallback(event => {
|
|
360
|
+
if (!isSwapFocusRef.current) {
|
|
361
|
+
onFocus?.(event);
|
|
362
|
+
}
|
|
363
|
+
}, [onFocus]);
|
|
364
|
+
const handleFieldBlur = useCallback(event => {
|
|
365
|
+
onBlur?.(event);
|
|
366
|
+
}, [onBlur]);
|
|
367
|
+
// While the flow is open, the sheet announces its own content from inside
|
|
368
|
+
// its dialog; this component announces only with the flow closed, and
|
|
369
|
+
// `useAnnounce` routes those messages by where the field is — into a Dialog
|
|
370
|
+
// or modal Drawer that holds it, or the shared channel when no modal does.
|
|
371
|
+
// A result count that changed during the flow's exit is spoken once the
|
|
372
|
+
// flow has fully closed and focus is back on the trigger: the closing
|
|
373
|
+
// dialog stays modal through its exit, so neither its region nor the
|
|
374
|
+
// page-body channel is heard before.
|
|
375
|
+
const afterCloseResultCountRef = useRef(null);
|
|
376
|
+
const triggerId = useId();
|
|
377
|
+
const triggerLabelId = useId();
|
|
378
|
+
const triggerContentId = useId();
|
|
379
|
+
const statusMessageId = useId();
|
|
380
|
+
// A field that becomes disabled cannot keep its flow open, and must not
|
|
381
|
+
// reopen it when re-enabled. Adjusted in the
|
|
382
|
+
// render that sees the change, not an effect, so no frame shows both.
|
|
383
|
+
const [wasDisabled, setWasDisabled] = useState(isDisabled);
|
|
384
|
+
if (isDisabled !== wasDisabled) {
|
|
385
|
+
setWasDisabled(isDisabled);
|
|
386
|
+
if (isDisabled && isSheetOpen) {
|
|
387
|
+
setIsSheetOpen(false);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
useDevWarning('PowerSearch', '`menuWidth` has no surface in the bottom-sheet presentation: the sheet flow has no typeahead popover to size. Scope it to the popover presentation or leave it out.', isSheetPresentation && menuWidth != null);
|
|
391
|
+
useDevWarning('PowerSearch', '`tokenOverflowBehavior` has no surface in the bottom-sheet presentation: the trigger wraps its display-only tokens. Scope it to the popover presentation or leave it out.', isSheetPresentation && tokenOverflowBehavior != null);
|
|
421
392
|
const [popoverState, setPopoverStateRaw] = useState({
|
|
422
393
|
type: 'idle'
|
|
423
394
|
});
|
|
424
395
|
|
|
396
|
+
// A default filter token's visible text: its label (field and operator)
|
|
397
|
+
// and its value. The token's remove button and editor dialog are named by
|
|
398
|
+
// the same text.
|
|
399
|
+
const tokenText = useCallback(filter => {
|
|
400
|
+
const field = config.getField(filter.field);
|
|
401
|
+
const operator = config.getOperator(filter.field, filter.operator);
|
|
402
|
+
const fieldLabel = field?.label ?? '';
|
|
403
|
+
const operatorLabel = operator ? resolveOperatorLabel(operator, t) : '';
|
|
404
|
+
const label = `${fieldLabel}: ${operatorLabel}`.trim();
|
|
405
|
+
const value = operator ? formatTokenValueText(operator.value, filter.value, Math.max(maxTokenLength - fieldLabel.length - operatorLabel.length, 10), locale) : null;
|
|
406
|
+
return {
|
|
407
|
+
label,
|
|
408
|
+
value,
|
|
409
|
+
full: value != null ? `${label} ${value}` : label
|
|
410
|
+
};
|
|
411
|
+
}, [config, maxTokenLength, t, locale]);
|
|
412
|
+
// The built-in token being edited. A token from a `components` override
|
|
413
|
+
// names itself, so its editor keeps the plain popover.
|
|
414
|
+
const editedFilter = popoverState.type === 'editing' ? filters[popoverState.filterIndex] : undefined;
|
|
415
|
+
const editedOperator = editedFilter != null ? config.getOperator(editedFilter.field, editedFilter.operator) : undefined;
|
|
416
|
+
const editedBuiltInFilter = editedOperator == null || componentOverrides?.[editedOperator.value.type]?.Token == null ? editedFilter : undefined;
|
|
417
|
+
// Whether the editor popover is open, for the hand-off below, which runs
|
|
418
|
+
// in the commit that swaps presentations.
|
|
419
|
+
const isPopoverOpenRef = useRef(false);
|
|
420
|
+
// When `adaptive` flips to the sheet while the editor popover is open (a
|
|
421
|
+
// phone rotated), the editing ends with the popover: its state returns to
|
|
422
|
+
// idle (through the raw setter, since the tokenizer input is gone), in the
|
|
423
|
+
// render that sees the swap, so a later switch back does not reopen a stale
|
|
424
|
+
// editor.
|
|
425
|
+
if (isSheetPresentation && popoverState.type !== 'idle') {
|
|
426
|
+
setPopoverStateRaw({
|
|
427
|
+
type: 'idle'
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
425
431
|
// Layer for positioning the edit popover anchored to the tokenizer
|
|
426
432
|
const handleLayerHide = useCallback(() => {
|
|
433
|
+
isPopoverOpenRef.current = false;
|
|
427
434
|
setPopoverStateRaw({
|
|
428
435
|
type: 'idle'
|
|
429
436
|
});
|
|
@@ -433,13 +440,56 @@ export function PowerSearch({
|
|
|
433
440
|
hasLightDismiss: true,
|
|
434
441
|
hasCloseButton: false,
|
|
435
442
|
hasAutoFocus: false,
|
|
436
|
-
//
|
|
437
|
-
// stays on the tokenizer input, so a
|
|
438
|
-
|
|
443
|
+
// Adding: the popup's own listbox/menu content is the exposed semantics,
|
|
444
|
+
// and focus stays on the tokenizer input, so a dialog wrapper is
|
|
445
|
+
// incorrect. Editing a token: focus moves into the editor's controls, so
|
|
446
|
+
// the editor is a non-modal dialog named by the token's visible text.
|
|
447
|
+
role: editedBuiltInFilter != null ? 'dialog' : 'none',
|
|
448
|
+
isModal: false,
|
|
449
|
+
dialogLabel: editedBuiltInFilter != null ? tokenText(editedBuiltInFilter).full : undefined
|
|
439
450
|
});
|
|
440
451
|
|
|
452
|
+
// A presentation swap removes the focused control, so the other
|
|
453
|
+
// presentation's primary control (the combobox input or the trigger) takes
|
|
454
|
+
// focus and focus never falls to the page body. Each presentation keys its
|
|
455
|
+
// root, so a swap mounts a new root. The detaching root notes that it held
|
|
456
|
+
// focus, which also covers an input focused by server-rendered `autofocus`
|
|
457
|
+
// before hydration. The editor popover is portaled outside the root, so an
|
|
458
|
+
// open editor counts as held focus. The attaching root gives focus to its
|
|
459
|
+
// primary control when focus has fallen to the page body; the sheet root
|
|
460
|
+
// also hides a popover layer left open.
|
|
461
|
+
const isFocusPendingHandOffRef = useRef(false);
|
|
462
|
+
const hidePopover = popover.hide;
|
|
463
|
+
const handOffFocusRef = useCallback(node => {
|
|
464
|
+
if (node == null) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
const trigger = triggerRef.current;
|
|
468
|
+
const isSheetRoot = trigger != null && node.contains(trigger);
|
|
469
|
+
// The sheet presentation preloads the flow's chunk, so the first press
|
|
470
|
+
// opens without waiting for the network; nothing renders.
|
|
471
|
+
if (isSheetRoot) {
|
|
472
|
+
void loadPowerSearchBottomSheet();
|
|
473
|
+
}
|
|
474
|
+
if (isSheetRoot && isPopoverOpenRef.current) {
|
|
475
|
+
isPopoverOpenRef.current = false;
|
|
476
|
+
hidePopover();
|
|
477
|
+
}
|
|
478
|
+
const takesFocus = isFocusPendingHandOffRef.current;
|
|
479
|
+
isFocusPendingHandOffRef.current = false;
|
|
480
|
+
if (takesFocus && isFocusDetached(node.ownerDocument)) {
|
|
481
|
+
focusAfterSwap(isSheetRoot ? trigger : tokenizerRef.current);
|
|
482
|
+
}
|
|
483
|
+
return () => {
|
|
484
|
+
if (node.contains(node.ownerDocument.activeElement) || isPopoverOpenRef.current) {
|
|
485
|
+
isFocusPendingHandOffRef.current = true;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
}, [focusAfterSwap, hidePopover]);
|
|
489
|
+
|
|
441
490
|
// Wrapper that manages layer visibility and tokenizer focus alongside state
|
|
442
491
|
const setPopoverState = useCallback(state => {
|
|
492
|
+
isPopoverOpenRef.current = state.type !== 'idle';
|
|
443
493
|
setPopoverStateRaw(state);
|
|
444
494
|
if (state.type !== 'idle') {
|
|
445
495
|
// Schedule after the current frame so React can render the popover
|
|
@@ -454,13 +504,22 @@ export function PowerSearch({
|
|
|
454
504
|
}
|
|
455
505
|
}, [popover]);
|
|
456
506
|
|
|
457
|
-
// Expose imperative handle
|
|
507
|
+
// Expose imperative handle; in the sheet presentation the trigger is the
|
|
508
|
+
// field's focusable control.
|
|
458
509
|
useImperativeHandle(handleRef, () => ({
|
|
459
510
|
focusTypeahead() {
|
|
460
|
-
|
|
511
|
+
if (isSheetPresentation) {
|
|
512
|
+
triggerRef.current?.focus();
|
|
513
|
+
} else {
|
|
514
|
+
tokenizerRef.current?.focus();
|
|
515
|
+
}
|
|
461
516
|
},
|
|
462
517
|
blurTypeahead() {
|
|
463
|
-
|
|
518
|
+
if (isSheetPresentation) {
|
|
519
|
+
triggerRef.current?.blur();
|
|
520
|
+
} else {
|
|
521
|
+
tokenizerRef.current?.blur();
|
|
522
|
+
}
|
|
464
523
|
}
|
|
465
524
|
}));
|
|
466
525
|
|
|
@@ -532,15 +591,26 @@ export function PowerSearch({
|
|
|
532
591
|
value: undefined
|
|
533
592
|
}
|
|
534
593
|
});
|
|
535
|
-
} else if (change.type === 'remove'
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
onChange(
|
|
594
|
+
} else if (change.type === 'remove') {
|
|
595
|
+
const keptIndices = new Set(_items.map(item => item.auxiliaryData?.filterIndex));
|
|
596
|
+
const firstRemovedIndex = filters.findIndex((_, i) => !keptIndices.has(i));
|
|
597
|
+
if (firstRemovedIndex >= 0) {
|
|
598
|
+
onChange(filters.filter((_, i) => keptIndices.has(i)), 'remove', firstRemovedIndex);
|
|
540
599
|
}
|
|
541
600
|
}
|
|
542
601
|
}, [config, filters, onChange, setPopoverState]);
|
|
543
602
|
|
|
603
|
+
// Tokenizer's Backspace and Clear all do not go through renderToken. This
|
|
604
|
+
// predicate locks each read-only filter, and every token of a read-only
|
|
605
|
+
// field.
|
|
606
|
+
const isItemRemovable = useCallback(item => {
|
|
607
|
+
if (isReadOnly) {
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
const filterIndex = item.auxiliaryData?.filterIndex;
|
|
611
|
+
return filterIndex == null || !filters[filterIndex]?.isReadOnly;
|
|
612
|
+
}, [filters, isReadOnly]);
|
|
613
|
+
|
|
544
614
|
// Handle clicking a token to edit
|
|
545
615
|
const handleTokenClick = useCallback(index => {
|
|
546
616
|
if (isReadOnly || isDisabled) {
|
|
@@ -555,7 +625,7 @@ export function PowerSearch({
|
|
|
555
625
|
// edit: commit it as that editor's save would, the way adding one does,
|
|
556
626
|
// instead of opening it. A consumer's `empty` Editor override still opens.
|
|
557
627
|
const operator = config.getOperator(filter.field, filter.operator);
|
|
558
|
-
if (operator
|
|
628
|
+
if (commitsWithoutEditor(operator, componentOverrides)) {
|
|
559
629
|
const newFilters = [...filters];
|
|
560
630
|
newFilters[index] = {
|
|
561
631
|
field: filter.field,
|
|
@@ -610,15 +680,17 @@ export function PowerSearch({
|
|
|
610
680
|
});
|
|
611
681
|
}, [setPopoverState]);
|
|
612
682
|
|
|
613
|
-
//
|
|
614
|
-
//
|
|
615
|
-
|
|
683
|
+
// Token renderer for both presentations. Given `onRemove`, the token is
|
|
684
|
+
// the tokenizer field's: click edits, × removes. Without it (the sheet
|
|
685
|
+
// presentation's trigger) the token is display-only; the field as a whole
|
|
686
|
+
// opens the flow.
|
|
687
|
+
const renderFilterToken = useCallback((item, onRemove) => {
|
|
616
688
|
const auxData = item.auxiliaryData;
|
|
617
689
|
const filterIndex = auxData?.filterIndex ?? -1;
|
|
618
690
|
const filter = filterIndex >= 0 ? filters[filterIndex] : undefined;
|
|
619
691
|
const field = auxData ? config.getField(auxData.fieldKey) : undefined;
|
|
620
692
|
const operator = auxData?.operatorKey ? config.getOperator(auxData.fieldKey, auxData.operatorKey) : undefined;
|
|
621
|
-
const canInteract = !isReadOnly && !isDisabled && !filter?.isReadOnly;
|
|
693
|
+
const canInteract = onRemove != null && !isReadOnly && !isDisabled && !filter?.isReadOnly;
|
|
622
694
|
const handleClick = canInteract ? () => handleTokenClick(filterIndex) : undefined;
|
|
623
695
|
const handleRemove = canInteract ? onRemove : undefined;
|
|
624
696
|
|
|
@@ -640,13 +712,14 @@ export function PowerSearch({
|
|
|
640
712
|
// Default token rendering
|
|
641
713
|
const fieldLabel = field?.label ?? '';
|
|
642
714
|
const operatorLabel = operator ? resolveOperatorLabel(operator, t) : '';
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
715
|
+
const text = filter != null ? tokenText(filter) : {
|
|
716
|
+
label: `${fieldLabel}: ${operatorLabel}`.trim(),
|
|
717
|
+
value: null
|
|
718
|
+
};
|
|
719
|
+
const tokenLabel = text.label;
|
|
720
|
+
const fullText = text.value != null ? `${text.label} ${text.value}` : text.label;
|
|
721
|
+
const valueContent = text.value != null ? /*#__PURE__*/_jsx(PowerSearchTokenValue, {
|
|
722
|
+
text: text.value
|
|
650
723
|
}) : undefined;
|
|
651
724
|
|
|
652
725
|
// Show entity photo as token icon for single-entity filters
|
|
@@ -659,24 +732,39 @@ export function PowerSearch({
|
|
|
659
732
|
size: 16
|
|
660
733
|
});
|
|
661
734
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
735
|
+
|
|
736
|
+
// A token that opens its editor says that it opens a dialog, and the
|
|
737
|
+
// naming context names it by all its visible text.
|
|
738
|
+
const editorProps = handleClick != null && !commitsWithoutEditor(operator, componentOverrides) ? {
|
|
739
|
+
'aria-haspopup': 'dialog',
|
|
740
|
+
'aria-expanded': popoverState.type === 'editing' && popoverState.filterIndex === filterIndex
|
|
741
|
+
} : null;
|
|
742
|
+
return /*#__PURE__*/_jsx(TokenNamingContext, {
|
|
743
|
+
value: {
|
|
744
|
+
actionName: fullText,
|
|
745
|
+
removeName: fullText
|
|
746
|
+
},
|
|
747
|
+
children: /*#__PURE__*/_jsx(Token, {
|
|
748
|
+
label: tokenLabel,
|
|
749
|
+
size: size,
|
|
750
|
+
icon: tokenIcon,
|
|
751
|
+
...editorProps,
|
|
752
|
+
endContent: valueContent,
|
|
753
|
+
onMouseDown: handleClick ? e => {
|
|
754
|
+
// Keep a token press from entering Tokenizer's input-focus
|
|
755
|
+
// redirect. Click still edits/removes; Tab entry is unchanged.
|
|
756
|
+
e.preventDefault();
|
|
757
|
+
} : undefined,
|
|
758
|
+
onClick: handleClick ? e => {
|
|
759
|
+
e.stopPropagation();
|
|
760
|
+
handleClick();
|
|
761
|
+
} : undefined,
|
|
762
|
+
onRemove: handleRemove,
|
|
763
|
+
isDisabled: isDisabled
|
|
764
|
+
})
|
|
678
765
|
});
|
|
679
|
-
}, [filters, config, configProp, maxTokenLength,
|
|
766
|
+
}, [filters, config, configProp, maxTokenLength, size, isReadOnly, isDisabled, handleTokenClick, componentOverrides, t, popoverState, tokenText]);
|
|
767
|
+
const renderToken = useCallback((item, onRemove) => renderFilterToken(item, onRemove), [renderFilterToken]);
|
|
680
768
|
|
|
681
769
|
// Custom typeahead item renderer — adds field icon and description
|
|
682
770
|
const renderItem = useCallback(item => {
|
|
@@ -764,27 +852,38 @@ export function PowerSearch({
|
|
|
764
852
|
return resultCount;
|
|
765
853
|
}, [resultCount, t]);
|
|
766
854
|
|
|
767
|
-
//
|
|
768
|
-
//
|
|
769
|
-
//
|
|
770
|
-
//
|
|
771
|
-
//
|
|
772
|
-
//
|
|
773
|
-
//
|
|
855
|
+
// This Effect synchronizes a polite live region with the result count,
|
|
856
|
+
// mirroring the way Typeahead announces its dropdown result count: the count
|
|
857
|
+
// is otherwise only shown visually and stays silent to assistive tech. The
|
|
858
|
+
// region follows where the field is: the modal that holds the field (a
|
|
859
|
+
// Dialog, a modal Drawer), else the shared channel. While a sheet of the flow is open the sheet itself announces the
|
|
860
|
+
// count from inside its dialog, and this Effect stays quiet. Only a
|
|
861
|
+
// change after mount is spoken — the count present on mount is not
|
|
862
|
+
// announced unprompted — and the guard compares against the last announced
|
|
863
|
+
// text rather than a mounted flag, so StrictMode's effect replay announces
|
|
864
|
+
// nothing either. A change that lands while the flow is closing waits for
|
|
865
|
+
// the trigger focus, since the dialog is still modal through its exit. The
|
|
866
|
+
// announcement acquires no resource, so there is no cleanup.
|
|
774
867
|
const announce = useAnnounce();
|
|
775
868
|
// PowerSearch words its Clear all as its record does; the field announces
|
|
776
869
|
// these words instead of Tokenizer's (component:Tokenizer AR7).
|
|
777
|
-
const
|
|
870
|
+
const hasReadOnlyFilter = filters.some(filter => filter.isReadOnly);
|
|
871
|
+
const clearAllMessage = useMemo(() => hasReadOnlyFilter ? t('@astryx.powersearch.editableFiltersRemoved') : t('@astryx.powersearch.allFiltersRemoved'), [hasReadOnlyFilter, t]);
|
|
778
872
|
const announcedResultCountRef = useRef(resultCountText);
|
|
873
|
+
const isSheetExiting = isSheetPresented && !isSheetOpen;
|
|
779
874
|
useEffect(() => {
|
|
780
875
|
if (resultCountText === announcedResultCountRef.current) {
|
|
781
876
|
return;
|
|
782
877
|
}
|
|
783
878
|
announcedResultCountRef.current = resultCountText;
|
|
784
879
|
if (resultCountText != null) {
|
|
785
|
-
|
|
880
|
+
if (isSheetExiting) {
|
|
881
|
+
afterCloseResultCountRef.current = resultCountText;
|
|
882
|
+
} else if (!isSheetOpen) {
|
|
883
|
+
announce(resultCountText);
|
|
884
|
+
}
|
|
786
885
|
}
|
|
787
|
-
}, [resultCountText, announce]);
|
|
886
|
+
}, [resultCountText, announce, isSheetExiting, isSheetOpen]);
|
|
788
887
|
|
|
789
888
|
// Build combined endContent from resultCount + endContent props
|
|
790
889
|
const combinedEndContent = useMemo(() => {
|
|
@@ -803,45 +902,215 @@ export function PowerSearch({
|
|
|
803
902
|
}
|
|
804
903
|
return resultCountNode || endContent || undefined;
|
|
805
904
|
}, [resultCountText, endContent]);
|
|
905
|
+
|
|
906
|
+
// ------------------------------------------------------- sheet trigger --
|
|
907
|
+
|
|
908
|
+
// Disabled-reason tooltip for the sheet trigger. Disabled controls swallow
|
|
909
|
+
// pointer events, so the listeners attach to the field's control box; the
|
|
910
|
+
// trigger stays perceivable through aria-disabled.
|
|
911
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
912
|
+
const disabledMessageTooltip = useTooltip({
|
|
913
|
+
placement: 'above',
|
|
914
|
+
focusTrigger: 'always',
|
|
915
|
+
isEnabled: isSheetPresentation && showsDisabledMessage
|
|
916
|
+
});
|
|
917
|
+
const rootRef = useMergedRefs(ref, popover.triggerRef, handOffFocusRef);
|
|
918
|
+
const openSheet = useCallback(() => {
|
|
919
|
+
if (isDisabled) {
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
// The flow restores focus to the element that was active when it opened;
|
|
923
|
+
// make sure that is the trigger even for a tap on a token.
|
|
924
|
+
triggerRef.current?.focus({
|
|
925
|
+
preventScroll: true
|
|
926
|
+
});
|
|
927
|
+
setIsSheetPresented(true);
|
|
928
|
+
setIsSheetOpen(true);
|
|
929
|
+
}, [isDisabled]);
|
|
930
|
+
|
|
931
|
+
// The field's end lane — the result count and `endContent` — sits outside
|
|
932
|
+
// the trigger button: a caller's action button there keeps its own tab stop
|
|
933
|
+
// and taps, and an interactive control must not nest in a component
|
|
934
|
+
// button, so a tap on it must not open the flow.
|
|
935
|
+
const endLaneRef = useRef(null);
|
|
936
|
+
const handleTriggerWrapperClick = useCallback(event => {
|
|
937
|
+
// Tokens are display-only; a tap on them or the empty space around them
|
|
938
|
+
// opens the flow. The trigger button handles its own click, and the end
|
|
939
|
+
// lane handles its own.
|
|
940
|
+
if (event.target instanceof Node && (triggerRef.current?.contains(event.target) || endLaneRef.current?.contains(event.target))) {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
openSheet();
|
|
944
|
+
}, [openSheet]);
|
|
945
|
+
const handleTriggerFocusWithin = useCallback(event => {
|
|
946
|
+
// The flow focuses the trigger only after its exit completes; that focus
|
|
947
|
+
// is the signal that the retained sheets can leave. If the resolution
|
|
948
|
+
// moved to the popover meanwhile, the tokenizer input takes over the
|
|
949
|
+
// focus once it mounts (the hand-off above).
|
|
950
|
+
if (!isSheetOpen && isSheetPresented) {
|
|
951
|
+
setIsSheetPresented(false);
|
|
952
|
+
// The dialogs have closed: the page-body channel is exposed again.
|
|
953
|
+
const resultCount = afterCloseResultCountRef.current;
|
|
954
|
+
afterCloseResultCountRef.current = null;
|
|
955
|
+
if (resultCount != null) {
|
|
956
|
+
announce(resultCount);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
if (!(event.relatedTarget instanceof Node) || !event.currentTarget.contains(event.relatedTarget)) {
|
|
960
|
+
handleFieldFocus(event);
|
|
961
|
+
}
|
|
962
|
+
}, [announce, handleFieldFocus, isSheetOpen, isSheetPresented]);
|
|
963
|
+
const handleTriggerBlurWithin = useCallback(event => {
|
|
964
|
+
if (!(event.relatedTarget instanceof Node) || !event.currentTarget.contains(event.relatedTarget)) {
|
|
965
|
+
handleFieldBlur(event);
|
|
966
|
+
}
|
|
967
|
+
}, [handleFieldBlur]);
|
|
968
|
+
if (isSheetPresentation) {
|
|
969
|
+
const triggerDescribedBy = [status?.message ? statusMessageId : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null].filter(Boolean).join(' ') || undefined;
|
|
970
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
971
|
+
ref: rootRef,
|
|
972
|
+
...themeProps('power-search'),
|
|
973
|
+
children: [/*#__PURE__*/_jsxs(Field, {
|
|
974
|
+
label: label,
|
|
975
|
+
isLabelHidden: isLabelHidden,
|
|
976
|
+
inputID: triggerId,
|
|
977
|
+
labelID: triggerLabelId,
|
|
978
|
+
isDisabled: isDisabled,
|
|
979
|
+
status: status ? {
|
|
980
|
+
type: status.type,
|
|
981
|
+
message: status.message,
|
|
982
|
+
messageID: status.message ? statusMessageId : undefined
|
|
983
|
+
} : undefined,
|
|
984
|
+
statusVariant: statusVariant,
|
|
985
|
+
xstyle: xstyle,
|
|
986
|
+
className: className,
|
|
987
|
+
style: style,
|
|
988
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
989
|
+
ref: disabledMessageTooltip.ref,
|
|
990
|
+
onClick: handleTriggerWrapperClick,
|
|
991
|
+
onFocus: handleTriggerFocusWithin,
|
|
992
|
+
onBlur: handleTriggerBlurWithin,
|
|
993
|
+
"aria-disabled": isDisabled ? true : undefined,
|
|
994
|
+
...stylex.props(inputWrapperStyles.base, sheetTriggerStyles.wrapper, filters.length > 0 && sheetTriggerStyles.wrapperWithTokens, sheetTriggerSizeStyles[size], isDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type]),
|
|
995
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
996
|
+
id: triggerContentId,
|
|
997
|
+
...{
|
|
998
|
+
className: "x1n2onr6 xeuugli x1iyjqo2 x78zum5 x6s0dn4 x1a02dak x1lfs0n9 xajebq8"
|
|
999
|
+
},
|
|
1000
|
+
children: [isRenderable(startIcon) && /*#__PURE__*/_jsx("span", {
|
|
1001
|
+
...{
|
|
1002
|
+
0: {},
|
|
1003
|
+
1: {
|
|
1004
|
+
className: "x1xrm450"
|
|
1005
|
+
}
|
|
1006
|
+
}[!!(filters.length > 0) << 0],
|
|
1007
|
+
children: renderIconSlot(startIcon, {
|
|
1008
|
+
size: 'sm',
|
|
1009
|
+
color: 'secondary'
|
|
1010
|
+
})
|
|
1011
|
+
}), tokenizerValue.map(item => /*#__PURE__*/_jsx(React.Fragment, {
|
|
1012
|
+
children: renderFilterToken(item, undefined)
|
|
1013
|
+
}, item.id)), /*#__PURE__*/_jsx("button", {
|
|
1014
|
+
type: "button",
|
|
1015
|
+
id: triggerId,
|
|
1016
|
+
ref: triggerRef
|
|
1017
|
+
// The field's primary control: `data-testid` lands here, as it
|
|
1018
|
+
// lands on the combobox input in the popover presentation.
|
|
1019
|
+
,
|
|
1020
|
+
"data-testid": testId,
|
|
1021
|
+
autoFocus: autoFocusOnMount,
|
|
1022
|
+
onClick: openSheet,
|
|
1023
|
+
"aria-disabled": isDisabled ? true : undefined,
|
|
1024
|
+
"aria-haspopup": "dialog",
|
|
1025
|
+
"aria-expanded": isSheetOpen,
|
|
1026
|
+
"aria-labelledby": `${triggerLabelId} ${triggerContentId}`,
|
|
1027
|
+
"aria-describedby": triggerDescribedBy,
|
|
1028
|
+
...{
|
|
1029
|
+
0: {
|
|
1030
|
+
className: "xjyslct xfoc8du x1fns5xo xkh2ocl x78zum5 x6s0dn4 xt970qd x7a5moj x1ghz6dp xc342km xng3xce xjbqb8w xv1l7n4 x9ynric xjm74w1 xw6l6zx x1yc453h xuxw1ft x1ypdohk xvivl9a x1a2a7pz"
|
|
1031
|
+
},
|
|
1032
|
+
1: {
|
|
1033
|
+
className: "xjyslct xfoc8du xkh2ocl x78zum5 x6s0dn4 xt970qd x7a5moj x1ghz6dp xc342km xng3xce xjbqb8w xv1l7n4 x9ynric xjm74w1 xw6l6zx x1yc453h xuxw1ft x1ypdohk xvivl9a x1a2a7pz x10l6tqk x10a8y8t xeuugli x1717udv"
|
|
1034
|
+
}
|
|
1035
|
+
}[!!(filters.length > 0) << 0],
|
|
1036
|
+
children: filters.length === 0 ? placeholder : null
|
|
1037
|
+
})]
|
|
1038
|
+
}), (endContent || isRenderable(resultCountText)) && /*#__PURE__*/_jsxs("div", {
|
|
1039
|
+
ref: endLaneRef,
|
|
1040
|
+
...{
|
|
1041
|
+
className: "x78zum5 x6s0dn4 x1txdalj x2lah0s x1nryj5t"
|
|
1042
|
+
},
|
|
1043
|
+
children: [isRenderable(resultCountText) && /*#__PURE__*/_jsx("span", {
|
|
1044
|
+
...{
|
|
1045
|
+
className: "x141an7d x1ltkj2j xv1l7n4 xuxw1ft"
|
|
1046
|
+
},
|
|
1047
|
+
children: resultCountText
|
|
1048
|
+
}), endContent]
|
|
1049
|
+
})]
|
|
1050
|
+
}), showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
1051
|
+
}), (isSheetOpen || isSheetPresented) && /*#__PURE__*/_jsx(PowerSearchSheetHost, {
|
|
1052
|
+
isOpen: isSheetOpen,
|
|
1053
|
+
onOpenChange: setIsSheetOpen,
|
|
1054
|
+
finalFocusRef: triggerRef,
|
|
1055
|
+
resultCountText: resultCountText,
|
|
1056
|
+
config: config,
|
|
1057
|
+
configProp: configProp,
|
|
1058
|
+
filters: filters,
|
|
1059
|
+
onChange: onChange,
|
|
1060
|
+
searchSource: searchSource,
|
|
1061
|
+
placeholder: placeholder,
|
|
1062
|
+
isReadOnly: isReadOnly,
|
|
1063
|
+
isDisabled: isDisabled,
|
|
1064
|
+
hasClear: hasClear,
|
|
1065
|
+
maxOperatorMenuItems: maxOperatorMenuItems,
|
|
1066
|
+
maxSearchResults: maxSearchResults,
|
|
1067
|
+
saveButtonLabel: popoverSaveButtonLabelFromProps,
|
|
1068
|
+
components: componentOverrides
|
|
1069
|
+
})]
|
|
1070
|
+
}, "sheet");
|
|
1071
|
+
}
|
|
806
1072
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
807
1073
|
children: [/*#__PURE__*/_jsx("div", {
|
|
808
|
-
ref:
|
|
1074
|
+
ref: rootRef,
|
|
809
1075
|
...themeProps('power-search'),
|
|
810
1076
|
children: /*#__PURE__*/_jsx(TokenizerClearAllMessageContext, {
|
|
811
1077
|
value: clearAllMessage,
|
|
812
|
-
children: /*#__PURE__*/_jsx(
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1078
|
+
children: /*#__PURE__*/_jsx(TokenizerItemRemovableContext, {
|
|
1079
|
+
value: isItemRemovable,
|
|
1080
|
+
children: /*#__PURE__*/_jsx(Tokenizer, {
|
|
1081
|
+
handleRef: tokenizerRef,
|
|
1082
|
+
label: label,
|
|
1083
|
+
isLabelHidden: isLabelHidden,
|
|
1084
|
+
searchSource: searchSource,
|
|
1085
|
+
value: tokenizerValue,
|
|
1086
|
+
onChange: handleTokenizerChange,
|
|
1087
|
+
renderToken: renderToken,
|
|
1088
|
+
renderItem: renderItem,
|
|
1089
|
+
maxMenuItems: MAX_BROWSE_MENU_ITEMS,
|
|
1090
|
+
menuWidth: menuWidth,
|
|
1091
|
+
placeholder: filters.length === 0 ? placeholder : '',
|
|
1092
|
+
hasAutoFocus: autoFocusOnMount,
|
|
1093
|
+
hasClear: hasClear && !isReadOnly,
|
|
1094
|
+
startIcon: startIcon,
|
|
1095
|
+
endContent: combinedEndContent,
|
|
1096
|
+
isDisabled: isDisabled,
|
|
1097
|
+
disabledMessage: disabledMessage,
|
|
1098
|
+
size: size,
|
|
1099
|
+
tokenOverflowBehavior: tokenOverflowBehavior,
|
|
1100
|
+
hasEntriesOnFocus: true,
|
|
1101
|
+
debounceMs: 0,
|
|
1102
|
+
status: status,
|
|
1103
|
+
statusVariant: statusVariant,
|
|
1104
|
+
onFocus: handleFieldFocus,
|
|
1105
|
+
onBlur: handleFieldBlur,
|
|
1106
|
+
containerXstyle: xstyle,
|
|
1107
|
+
containerClassName: className,
|
|
1108
|
+
containerStyle: style,
|
|
1109
|
+
"data-testid": testId
|
|
1110
|
+
})
|
|
842
1111
|
})
|
|
843
1112
|
})
|
|
844
|
-
}), popover.render(popoverContent, {
|
|
1113
|
+
}, "popover"), popover.render(popoverContent, {
|
|
845
1114
|
placement: 'below',
|
|
846
1115
|
alignment: 'start',
|
|
847
1116
|
offset: spacingVars['--spacing-1'],
|