@astryxdesign/core 0.4.6 → 0.4.7-canary.019ae5a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -2
- package/dist/AspectRatio/AspectRatio.d.ts +24 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +23 -4
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +15 -10
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +3 -2
- package/dist/Banner/Banner.d.ts +40 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +51 -18
- package/dist/BottomSheet/BottomSheet.d.ts +1 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +54 -15
- package/dist/BottomSheet/BottomSheetEdgeTint.d.ts +6 -0
- package/dist/BottomSheet/BottomSheetEdgeTint.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetEdgeTint.js +62 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +1 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts +1 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +13 -6
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +23 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +5 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +26 -7
- package/dist/Calendar/Calendar.d.ts +3 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +13 -14
- package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
- package/dist/Calendar/getInitialFocusDate.js +62 -0
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +3 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +3 -3
- package/dist/Chat/ChatMessageList.d.ts +22 -3
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +6 -3
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/Chat/useChatComposerTokens.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +3 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +3 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +3 -2
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +38 -4
- package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +406 -12
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts +7 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +89 -58
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +3 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +6 -2
- package/dist/HoverCard/HoverCard.d.ts +6 -0
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.d.ts +5 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +67 -25
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +10 -3
- package/dist/Layer/LayerDepthContext.d.ts +52 -0
- package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
- package/dist/Layer/LayerDepthContext.js +66 -0
- package/dist/Layer/index.d.ts +3 -0
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +4 -0
- package/dist/Layer/layerStack.d.ts +98 -0
- package/dist/Layer/layerStack.d.ts.map +1 -0
- package/dist/Layer/layerStack.js +306 -0
- package/dist/Layer/useLayerDismissal.d.ts +93 -0
- package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
- package/dist/Layer/useLayerDismissal.js +91 -0
- package/dist/Lightbox/Lightbox.d.ts +1 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +103 -81
- package/dist/Markdown/index.d.ts +1 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/parser.d.ts +38 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +177 -29
- package/dist/MobileNav/MobileNav.d.ts +6 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +61 -36
- package/dist/MultiSelector/MultiSelector.d.ts +15 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +17 -6
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +3 -2
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -2
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +3 -2
- package/dist/Overlay/Overlay.d.ts.map +1 -1
- package/dist/Overlay/Overlay.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +20 -17
- package/dist/PowerSearch/PowerSearch.d.ts +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +19 -6
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
- package/dist/PowerSearch/types.d.ts +2 -0
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +14 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -3
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +5 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -3
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +6 -5
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +4 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -3
- package/dist/Spinner/Spinner.d.ts +3 -3
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +130 -78
- package/dist/Stepper/Step.d.ts +140 -0
- package/dist/Stepper/Step.d.ts.map +1 -0
- package/dist/Stepper/Step.js +1045 -0
- package/dist/Stepper/StepStatus.d.ts +24 -0
- package/dist/Stepper/StepStatus.d.ts.map +1 -0
- package/dist/Stepper/StepStatus.js +1 -0
- package/dist/Stepper/Stepper.d.ts +93 -0
- package/dist/Stepper/Stepper.d.ts.map +1 -0
- package/dist/Stepper/Stepper.js +184 -0
- package/dist/Stepper/StepperContext.d.ts +41 -0
- package/dist/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/Stepper/StepperContext.js +34 -0
- package/dist/Stepper/index.d.ts +8 -0
- package/dist/Stepper/index.d.ts.map +1 -0
- package/dist/Stepper/index.js +7 -0
- package/dist/Stepper/stepper.stylex.d.ts +15 -0
- package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
- package/dist/Stepper/stepper.stylex.js +20 -0
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +3 -2
- package/dist/TabList/Tab.d.ts +15 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +32 -3
- package/dist/TabList/TabList.d.ts +46 -7
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +353 -23
- package/dist/TabList/TabListContext.d.ts +11 -1
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +11 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -2
- package/dist/TabList/index.d.ts +2 -2
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +4 -1
- package/dist/Table/TableRow.d.ts +16 -5
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +16 -5
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
- package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +19 -5
- package/dist/Table/types.d.ts +22 -4
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -0
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +6 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +3 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +5 -3
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +2 -2
- package/dist/Tokenizer/Tokenizer.d.ts +3 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -0
- package/dist/Tooltip/Tooltip.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +5 -0
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +39 -24
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +3 -2
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -3
- package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +68 -29
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -2
- package/dist/astryx.css +72 -2
- 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/useFocusTrap.d.ts +7 -4
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +60 -95
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +10 -3
- package/dist/hooks/useListFocus.d.ts +5 -2
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +12 -6
- package/dist/hooks/useMergedRefs.d.ts +18 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/utils/groupItems.d.ts +5 -1
- package/dist/utils/groupItems.d.ts.map +1 -1
- package/dist/utils/groupItems.js +9 -9
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/dist/utils/timeParser.d.ts +1 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +26 -12
- package/locales/en.json +31 -7
- package/locales/pseudo.json +18 -0
- package/package.json +8 -3
- package/src/AppShell/AppShell.tsx +3 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
- package/src/AspectRatio/AspectRatio.test.tsx +57 -10
- package/src/AspectRatio/AspectRatio.tsx +40 -1
- package/src/Avatar/Avatar.doc.mjs +2 -1
- package/src/Avatar/Avatar.test.tsx +17 -0
- package/src/Avatar/Avatar.tsx +61 -38
- package/src/AvatarGroup/AvatarGroup.tsx +3 -2
- package/src/Banner/Banner.doc.mjs +13 -11
- package/src/Banner/Banner.test.tsx +102 -15
- package/src/Banner/Banner.tsx +72 -25
- package/src/BottomSheet/BottomSheet.test.tsx +123 -0
- package/src/BottomSheet/BottomSheet.tsx +36 -4
- package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +225 -0
- package/src/BottomSheet/BottomSheetEdgeTint.tsx +82 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +66 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +19 -0
- package/src/BottomSheet/BottomSheetSwitcher.tsx +16 -2
- package/src/BottomSheet/useSheetGestures.test.ts +27 -0
- package/src/BottomSheet/useSheetGestures.ts +25 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
- package/src/Button/Button.doc.mjs +22 -0
- package/src/Button/Button.test.tsx +13 -0
- package/src/Button/Button.tsx +5 -4
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +4 -3
- package/src/Calendar/Calendar.test.tsx +52 -0
- package/src/Calendar/Calendar.tsx +18 -15
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- package/src/Carousel/Carousel.tsx +3 -2
- package/src/Chat/ChatComposerInput.tsx +5 -1
- package/src/Chat/ChatLayout.tsx +3 -2
- package/src/Chat/ChatMessageList.doc.mjs +9 -1
- package/src/Chat/ChatMessageList.test.tsx +46 -0
- package/src/Chat/ChatMessageList.tsx +28 -4
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Chat/useChatComposerTokens.ts +1 -1
- package/src/CheckboxInput/CheckboxInput.tsx +3 -2
- package/src/ClickableCard/ClickableCard.tsx +3 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
- package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -3
- package/src/DateInput/DateInput.tsx +3 -2
- package/src/DateInput/DateInputTouch.test.tsx +36 -0
- package/src/DateInput/TouchDateField.tsx +38 -4
- package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
- package/src/DateTimeInput/DateTimeInput.tsx +556 -24
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +8 -3
- package/src/Dialog/Dialog.test.tsx +261 -1
- package/src/Dialog/Dialog.tsx +109 -58
- package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
- package/src/Field/Field.doc.mjs +13 -2
- package/src/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -2
- package/src/HoverCard/HoverCard.doc.mjs +5 -0
- package/src/HoverCard/HoverCard.tsx +6 -0
- package/src/HoverCard/useHoverCard.tsx +81 -30
- package/src/Item/Item.tsx +5 -4
- package/src/Kbd/Kbd.test.tsx +17 -0
- package/src/Kbd/Kbd.tsx +10 -3
- package/src/Layer/LayerDepthContext.tsx +62 -0
- package/src/Layer/index.ts +9 -0
- package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
- package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
- package/src/Layer/layerStack.ts +362 -0
- package/src/Layer/useLayerDismissal.test.tsx +469 -0
- package/src/Layer/useLayerDismissal.ts +173 -0
- package/src/Layout/Layout.doc.mjs +2 -2
- package/src/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/incremental.test.ts +16 -2
- package/src/Markdown/index.ts +1 -0
- package/src/Markdown/parser.perf.test.ts +96 -1
- package/src/Markdown/parser.test.ts +145 -2
- package/src/Markdown/parser.ts +244 -29
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
- package/src/MultiSelector/MultiSelector.test.tsx +106 -0
- package/src/MultiSelector/MultiSelector.tsx +50 -6
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavMenu/NavHeadingMenu.tsx +3 -2
- package/src/NumberInput/NumberInput.doc.mjs +5 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.tsx +3 -2
- package/src/Popover/Popover.test.tsx +27 -1
- package/src/Popover/usePopover.tsx +31 -28
- package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
- package/src/PowerSearch/PowerSearch.test.tsx +240 -1
- package/src/PowerSearch/PowerSearch.tsx +34 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
- package/src/PowerSearch/types.ts +2 -0
- package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
- package/src/PowerSearch/usePowerSearchSource.ts +13 -3
- package/src/Resizable/ResizeHandle.tsx +3 -2
- package/src/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/SelectableCard/SelectableCard.tsx +3 -2
- package/src/Selector/Selector.doc.mjs +12 -1
- package/src/Selector/Selector.test.tsx +45 -1
- package/src/Selector/Selector.tsx +11 -1
- package/src/SideNav/SideNav.doc.mjs +6 -6
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavHeading.tsx +10 -10
- package/src/SideNav/SideNavItem.tsx +4 -2
- package/src/Slider/Slider.tsx +3 -2
- package/src/Spinner/Spinner.test.tsx +147 -1
- package/src/Spinner/Spinner.tsx +120 -101
- package/src/Stepper/Step.doc.mjs +98 -0
- package/src/Stepper/Step.tsx +1638 -0
- package/src/Stepper/StepStatus.ts +26 -0
- package/src/Stepper/Stepper.doc.mjs +370 -0
- package/src/Stepper/Stepper.test.tsx +1024 -0
- package/src/Stepper/Stepper.tsx +258 -0
- package/src/Stepper/StepperContext.ts +71 -0
- package/src/Stepper/index.ts +18 -0
- package/src/Stepper/stepper.stylex.ts +19 -0
- package/src/Switch/Switch.tsx +3 -2
- package/src/TabList/Tab.doc.mjs +13 -1
- package/src/TabList/Tab.tsx +67 -3
- package/src/TabList/TabList.doc.mjs +22 -6
- package/src/TabList/TabList.test.tsx +580 -4
- package/src/TabList/TabList.tsx +490 -22
- package/src/TabList/TabListContext.ts +13 -2
- package/src/TabList/TabMenu.tsx +3 -2
- package/src/TabList/index.ts +6 -2
- package/src/Table/BaseTable.tsx +6 -3
- package/src/Table/Table.doc.mjs +6 -1
- package/src/Table/Table.test.tsx +132 -14
- package/src/Table/TableBody.doc.mjs +40 -0
- package/src/Table/TableFooter.doc.mjs +40 -0
- package/src/Table/TableHeader.doc.mjs +40 -0
- package/src/Table/TableRow.tsx +16 -5
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
- package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
- package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
- package/src/Table/types.ts +22 -4
- package/src/Table/useBaseTablePlugins.ts +5 -0
- package/src/Table/useTableGroupedRows.doc.mjs +5 -4
- package/src/Table/useTablePagination.doc.mjs +7 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +31 -0
- package/src/Text/Text.test.tsx +23 -1
- package/src/Text/Text.tsx +6 -2
- package/src/TextArea/TextArea.tsx +3 -2
- package/src/TextInput/TextInput.doc.mjs +10 -0
- package/src/TextInput/TextInput.tsx +3 -2
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timestamp/Timestamp.tsx +4 -2
- package/src/Toast/Toast.doc.mjs +6 -0
- package/src/Token/TokenLink.tsx +2 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
- package/src/Tokenizer/Tokenizer.tsx +4 -0
- package/src/Toolbar/Toolbar.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.test.tsx +32 -0
- package/src/Tooltip/Tooltip.tsx +5 -0
- package/src/Tooltip/useTooltip.tsx +47 -24
- package/src/TopNav/TopNavHeading.tsx +3 -2
- package/src/TopNav/TopNavMegaMenu.tsx +3 -2
- package/src/TopNav/TopNavMenu.tsx +4 -3
- package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
- package/src/Typeahead/BaseTypeahead.tsx +85 -33
- package/src/Typeahead/Typeahead.doc.mjs +5 -0
- package/src/Typeahead/Typeahead.test.tsx +49 -0
- package/src/Typeahead/Typeahead.tsx +3 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- package/src/hooks/useFocusTrap.test.tsx +14 -0
- package/src/hooks/useFocusTrap.ts +62 -111
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
- package/src/hooks/useHotkeys.test.ts +18 -0
- package/src/hooks/useHotkeys.ts +10 -3
- package/src/hooks/useListFocus.doc.mjs +2 -2
- package/src/hooks/useListFocus.test.tsx +65 -3
- package/src/hooks/useListFocus.ts +15 -7
- package/src/hooks/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -0
- package/src/index.ts +1 -0
- package/src/theme/MediaTheme.doc.mjs +5 -5
- package/src/utils/groupItems.ts +12 -6
- package/src/utils/index.ts +1 -1
- package/src/utils/sharedResizeObserver.ts +10 -2
- package/src/utils/timeParser.test.ts +6 -1
- package/src/utils/timeParser.ts +35 -13
- package/src/__tests__/inputWidthContract.test.tsx +0 -69
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file layerStack.ts
|
|
7
|
+
* @input Uses the isImeKeyEvent predicate from utils/ime
|
|
8
|
+
* @output Exports the shared layer dismissal stack: registration, top-most
|
|
9
|
+
* ordering, and the single document-level Escape listener
|
|
10
|
+
* @position Internal to the Layer system; consumed by useLayerDismissal, which
|
|
11
|
+
* is what overlays actually call. Not exported from the package root.
|
|
12
|
+
*
|
|
13
|
+
* SYNC: When modified, update:
|
|
14
|
+
* - /packages/core/src/Layer/useLayerDismissal.ts
|
|
15
|
+
* - /packages/core/src/Layer/useLayerDismissal.test.tsx
|
|
16
|
+
*
|
|
17
|
+
* ## Why one stack
|
|
18
|
+
*
|
|
19
|
+
* Every overlay used to own its own Escape listener, so one press dismissed
|
|
20
|
+
* every open layer (a popover inside a Dialog closed both; a Modal opened from
|
|
21
|
+
* inside another Modal closed both). Patching this per primitive produced
|
|
22
|
+
* parallel registries — the focus-trap Escape stack, Drawer's LIFO registry,
|
|
23
|
+
* useScrollLock's counter. This module is the single registry those collapse
|
|
24
|
+
* into. One press dismisses exactly one layer.
|
|
25
|
+
*
|
|
26
|
+
* ## Only the top layer acts
|
|
27
|
+
*
|
|
28
|
+
* The stack owns ONE `keydown` listener on `document` and routes the press to
|
|
29
|
+
* the top-most layer itself. Overlays do not listen; they register and say what
|
|
30
|
+
* they want done. The alternative — every layer listens and filters itself out
|
|
31
|
+
* — is what forces `stopPropagation()` choreography between element-level and
|
|
32
|
+
* document-level listeners, and it silently breaks whenever a layer forgets.
|
|
33
|
+
*
|
|
34
|
+
* ## Bubble phase, not capture
|
|
35
|
+
*
|
|
36
|
+
* The listener is on the BUBBLE phase so content inside a layer can claim the
|
|
37
|
+
* press first, either by `stopPropagation()` (the press never reaches us) or by
|
|
38
|
+
* `preventDefault()` (we see it and stand down). Editors are the motivating
|
|
39
|
+
* case: Monaco and the rich-text editor use Escape to close their own find
|
|
40
|
+
* widget or autocomplete, and that must win over dismissing the Dialog they sit
|
|
41
|
+
* in. A capture-phase listener would take the press away from them.
|
|
42
|
+
*
|
|
43
|
+
* ## The stack, not the browser, decides
|
|
44
|
+
*
|
|
45
|
+
* When the stack handles a press it calls `preventDefault()`, which suppresses
|
|
46
|
+
* the browser's own close-watcher behavior — both `<dialog>`'s `cancel` event
|
|
47
|
+
* and `popover="auto"` light-dismiss (verified in Chromium; the default action
|
|
48
|
+
* runs after propagation, so a bubble-phase `preventDefault` still beats it).
|
|
49
|
+
* That is deliberate: the native top layer only covers `showModal()` and
|
|
50
|
+
* `popover="auto"`, so relying on it would leave non-modal `show()` drawers,
|
|
51
|
+
* `popover="manual"` layers, and older browsers on a second, differently-behaved
|
|
52
|
+
* code path. One code path, one ordering, everywhere.
|
|
53
|
+
*
|
|
54
|
+
* ## An Escape that cancels an IME composition
|
|
55
|
+
*
|
|
56
|
+
* That press is not a dismissal, so no layer acts on it — but the stack still
|
|
57
|
+
* claims it, because an unclaimed Escape is exactly what makes the browser
|
|
58
|
+
* raise a close request, and that request dismisses the layer through its
|
|
59
|
+
* `cancel` handler on the same keypress. Claiming is the whole fix; the guard
|
|
60
|
+
* that only returns measures identically to no guard at all.
|
|
61
|
+
*
|
|
62
|
+
* Close requests that arrive with no keydown to read — the Android back
|
|
63
|
+
* gesture, the platform close watcher — are answered by the hosts, which ask
|
|
64
|
+
* `isTextComposing()` through `useLayerDismissal`.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
import {isImeKeyEvent} from '../utils/ime';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* What a layer does with an Escape press that reaches it.
|
|
71
|
+
*
|
|
72
|
+
* - `'close'` — dismiss this layer and consume the press. One Escape closes
|
|
73
|
+
* exactly this layer. The default, and correct for every dismissible layer:
|
|
74
|
+
* modals, popovers, menus, comboboxes, and hover layers alike.
|
|
75
|
+
* - `'block'` — consume the press WITHOUT dismissing. For a layer that requires
|
|
76
|
+
* an explicit choice (`Dialog purpose="required"`): Escape must not dismiss
|
|
77
|
+
* it, and must not fall through and dismiss something behind it either.
|
|
78
|
+
*
|
|
79
|
+
* There is deliberately no "dismiss but let the press continue" variant. Escape
|
|
80
|
+
* affects exactly one layer, always — a rule with no per-component exceptions
|
|
81
|
+
* is one users can predict. Hover layers were the tempting exception (the user
|
|
82
|
+
* never opened the tip, so why should it eat their press?), but guessing wrong
|
|
83
|
+
* that way is destructive: someone dismissing a stray tooltip over a form would
|
|
84
|
+
* lose the whole dialog. Guessing wrong the other way costs one keystroke.
|
|
85
|
+
*/
|
|
86
|
+
export type LayerEscapeBehavior = 'close' | 'block';
|
|
87
|
+
|
|
88
|
+
export interface LayerStackEntry {
|
|
89
|
+
/**
|
|
90
|
+
* Identity for removal; also the equality check for top-most, and the key
|
|
91
|
+
* `seq` is assigned against so a layer keeps its place across re-registration.
|
|
92
|
+
*/
|
|
93
|
+
token: object;
|
|
94
|
+
/**
|
|
95
|
+
* Nesting depth from the React tree (see LayerDepthContext), NOT the DOM.
|
|
96
|
+
* Context flows through portals and is known during render, so it is correct
|
|
97
|
+
* for layers that portal out and for an inner + outer layer that open in the
|
|
98
|
+
* same commit — the case where effect order lies, because React runs child
|
|
99
|
+
* effects before parent effects.
|
|
100
|
+
*/
|
|
101
|
+
depth: number;
|
|
102
|
+
/**
|
|
103
|
+
* Monotonic registration order; breaks ties between unrelated layers. For a
|
|
104
|
+
* layer that registers when it opens this is open order; a hover layer
|
|
105
|
+
* registers at mount and answers `isPresent` instead, so for two of those it
|
|
106
|
+
* is mount order rather than which one appeared first.
|
|
107
|
+
*
|
|
108
|
+
* Keyed to `token`, not to the registration, because a layer re-registers
|
|
109
|
+
* whenever its behavior or depth changes and must not overtake the layers
|
|
110
|
+
* above it.
|
|
111
|
+
*/
|
|
112
|
+
seq: number;
|
|
113
|
+
behavior: LayerEscapeBehavior;
|
|
114
|
+
/**
|
|
115
|
+
* The layer's container element, read lazily at press time. Used only to
|
|
116
|
+
* break ties between layers the React tree reports at the same depth — a raw
|
|
117
|
+
* `useFocusTrap` cannot wrap its content in a depth provider (it renders
|
|
118
|
+
* nothing), so DOM containment is the only nesting signal those have.
|
|
119
|
+
*/
|
|
120
|
+
getContainer?: () => HTMLElement | null;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the layer is really on screen right now, asked at press time.
|
|
123
|
+
*
|
|
124
|
+
* Registration alone is not proof: a layer whose open state lives in React
|
|
125
|
+
* state can lag a frame behind the DOM, so gating registration on that state
|
|
126
|
+
* drops presses that arrive in the gap. Such layers register for their whole
|
|
127
|
+
* lifetime and answer this from the DOM instead. Omit it to mean "registered
|
|
128
|
+
* means present", which is true for layers that register on open.
|
|
129
|
+
*/
|
|
130
|
+
isPresent?: () => boolean;
|
|
131
|
+
dismiss: () => void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const entries: LayerStackEntry[] = [];
|
|
135
|
+
// Registration order per layer identity. A layer re-registers whenever its
|
|
136
|
+
// depth or behavior changes — a Dialog whose `purpose` flips while open, a focus trap
|
|
137
|
+
// that moves — and StrictMode remounts every effect once more on top of that.
|
|
138
|
+
// Counting registrations instead would hand the layer a fresh, higher seq each
|
|
139
|
+
// time and promote it above the layers opened over it.
|
|
140
|
+
let seqByToken = new WeakMap<object, number>();
|
|
141
|
+
let nextSeq = 0;
|
|
142
|
+
let isListening = false;
|
|
143
|
+
|
|
144
|
+
function seqFor(token: object): number {
|
|
145
|
+
const existing = seqByToken.get(token);
|
|
146
|
+
if (existing !== undefined) {
|
|
147
|
+
return existing;
|
|
148
|
+
}
|
|
149
|
+
const seq = nextSeq++;
|
|
150
|
+
seqByToken.set(token, seq);
|
|
151
|
+
return seq;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Order two entries: positive when `a` is above `b`, negative when below.
|
|
156
|
+
* Three keys, each earning its place:
|
|
157
|
+
*
|
|
158
|
+
* 1. **Depth.** The layer nested inside the other is on top. This is what makes
|
|
159
|
+
* an inner-and-outer pair that mount in the SAME commit come out right;
|
|
160
|
+
* registration order alone gets it backwards, because React runs child
|
|
161
|
+
* effects before parent effects.
|
|
162
|
+
* 2. **DOM containment.** Depth only moves when a layer wraps its content in a
|
|
163
|
+
* `LayerDepthProvider`, which a bare `useFocusTrap` cannot do — it renders
|
|
164
|
+
* nothing. For those, containment recovers the nesting the tree did not
|
|
165
|
+
* report.
|
|
166
|
+
* 3. **Registration order.** For unrelated layers, the one that registered
|
|
167
|
+
* later is on top, matching how the browser's own top layer stacks. A layer
|
|
168
|
+
* keeps its first place for as long as its identity lives, so one that
|
|
169
|
+
* closes and reopens does not move to the top — see the known edge in the
|
|
170
|
+
* pull request.
|
|
171
|
+
*
|
|
172
|
+
* Modality is deliberately NOT a key. Ranking modals above everything sounds
|
|
173
|
+
* right and is not: a hover tip shown inside a modal renders on top of it, so
|
|
174
|
+
* a modal-first rule would hand the press to the dialog and strand the tip.
|
|
175
|
+
* Nesting already covers the case modality was meant to catch — a layer opened
|
|
176
|
+
* from inside another is deeper, modal or not.
|
|
177
|
+
*
|
|
178
|
+
* Note this is a PARTIAL order: containment relates only nested pairs. Callers
|
|
179
|
+
* must resolve the top with a pairwise max scan, never `Array.sort`, whose
|
|
180
|
+
* result is undefined for a non-transitive comparator.
|
|
181
|
+
*/
|
|
182
|
+
function compareEntries(a: LayerStackEntry, b: LayerStackEntry): number {
|
|
183
|
+
if (a.depth !== b.depth) {
|
|
184
|
+
return a.depth - b.depth;
|
|
185
|
+
}
|
|
186
|
+
const aEl = a.getContainer?.() ?? null;
|
|
187
|
+
const bEl = b.getContainer?.() ?? null;
|
|
188
|
+
if (aEl != null && bEl != null && aEl !== bEl) {
|
|
189
|
+
if (bEl.contains(aEl)) {
|
|
190
|
+
return 1;
|
|
191
|
+
}
|
|
192
|
+
if (aEl.contains(bEl)) {
|
|
193
|
+
return -1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return a.seq - b.seq;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function isPresentEntry(entry: LayerStackEntry): boolean {
|
|
200
|
+
return entry.isPresent?.() ?? true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Whether a text composition is running anywhere on the page. Tracked from
|
|
204
|
+
// composition events because the DOM offers no way to ask.
|
|
205
|
+
let isComposing = false;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Whether the user is part-way through composing text with an IME.
|
|
209
|
+
*
|
|
210
|
+
* The stack reads this to decide what an Escape means, and layers read it
|
|
211
|
+
* through `useLayerDismissal`'s `shouldDismissOnCloseRequest` for the close
|
|
212
|
+
* requests that arrive without a keydown to inspect — the Android back
|
|
213
|
+
* gesture, the platform close watcher, or a composing Escape whose keydown
|
|
214
|
+
* never reached this listener because content stopped it. Mid-composition,
|
|
215
|
+
* those are far more likely to be the user backing out of a half-formed
|
|
216
|
+
* character than a request to dismiss a layer, and guessing wrong that way
|
|
217
|
+
* costs them everything they have typed into it.
|
|
218
|
+
*
|
|
219
|
+
* Scope, deliberately page-wide: a composition in a field behind a non-modal
|
|
220
|
+
* layer also suppresses that layer's close requests. It is one keypress to
|
|
221
|
+
* recover from, and the alternative — matching the composing element against
|
|
222
|
+
* a layer's container — cannot work for the layers that do not have one.
|
|
223
|
+
*
|
|
224
|
+
* A composition already running when the first layer registers is invisible
|
|
225
|
+
* here: the listeners go on with the stack's own.
|
|
226
|
+
*/
|
|
227
|
+
export function isTextComposing(): boolean {
|
|
228
|
+
return isComposing;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function handleCompositionStart(): void {
|
|
232
|
+
isComposing = true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Focus leaving the field ends the composition too. Clearing on blur as well
|
|
236
|
+
// means a compositionend this listener never sees cannot leave the flag stuck
|
|
237
|
+
// on, swallowing every later close request.
|
|
238
|
+
function handleCompositionEnd(): void {
|
|
239
|
+
isComposing = false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The top-most present layer, or null when nothing is on screen. */
|
|
243
|
+
function topPresentEntry(): LayerStackEntry | null {
|
|
244
|
+
let top: LayerStackEntry | null = null;
|
|
245
|
+
for (const entry of entries) {
|
|
246
|
+
if (!isPresentEntry(entry)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (top == null || compareEntries(entry, top) > 0) {
|
|
250
|
+
top = entry;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return top;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Whether `token` identifies the top-most layer. Overlays that still own a
|
|
258
|
+
* dismissal channel the stack does not model yet (outside-press, swipe) can
|
|
259
|
+
* gate on this so every channel agrees on who is on top.
|
|
260
|
+
*/
|
|
261
|
+
export function isTopmostLayer(token: object): boolean {
|
|
262
|
+
return topPresentEntry()?.token === token;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Resolve an Escape press against the stack. Returns whether it was handled. */
|
|
266
|
+
function dispatchEscape(): boolean {
|
|
267
|
+
const top = topPresentEntry();
|
|
268
|
+
if (top == null) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
if (top.behavior === 'block') {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
top.dismiss();
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function handleKeyDown(event: KeyboardEvent): void {
|
|
279
|
+
if (event.key !== 'Escape') {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// An IME user pressing Escape is cancelling a composition, not dismissing a
|
|
283
|
+
// layer. Claim the press anyway, then stand down: left unclaimed, the browser
|
|
284
|
+
// raises its own close request, which arrives at a layer's `cancel` handler
|
|
285
|
+
// and dismisses it on this very keypress — measured in Chromium, where a
|
|
286
|
+
// guard that only returns behaves exactly like no guard at all. Claim it only
|
|
287
|
+
// while a layer is on screen; with nothing to protect, the press is not ours.
|
|
288
|
+
if (isImeKeyEvent(event)) {
|
|
289
|
+
if (topPresentEntry() != null) {
|
|
290
|
+
event.preventDefault();
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// Content inside a layer already claimed this press (see the bubble-phase
|
|
295
|
+
// note in the file header). Honor it and leave the default action alone.
|
|
296
|
+
if (event.defaultPrevented) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (dispatchEscape()) {
|
|
300
|
+
// Suppress the browser's own close-watcher so it cannot dismiss a second
|
|
301
|
+
// layer behind our back. Propagation is left alone: consumers may
|
|
302
|
+
// legitimately listen for Escape on window, and the stack's decision is
|
|
303
|
+
// already recorded in defaultPrevented.
|
|
304
|
+
event.preventDefault();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function startListening(): void {
|
|
309
|
+
if (isListening || typeof document === 'undefined') {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
313
|
+
document.addEventListener('compositionstart', handleCompositionStart, true);
|
|
314
|
+
document.addEventListener('compositionend', handleCompositionEnd, true);
|
|
315
|
+
document.addEventListener('blur', handleCompositionEnd, true);
|
|
316
|
+
isListening = true;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function stopListening(): void {
|
|
320
|
+
if (!isListening || typeof document === 'undefined') {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
324
|
+
document.removeEventListener(
|
|
325
|
+
'compositionstart',
|
|
326
|
+
handleCompositionStart,
|
|
327
|
+
true,
|
|
328
|
+
);
|
|
329
|
+
document.removeEventListener('compositionend', handleCompositionEnd, true);
|
|
330
|
+
document.removeEventListener('blur', handleCompositionEnd, true);
|
|
331
|
+
isComposing = false;
|
|
332
|
+
isListening = false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Add a layer to the stack for as long as it is active. Returns the unregister
|
|
337
|
+
* function; callers own calling it.
|
|
338
|
+
*/
|
|
339
|
+
export function registerLayer(entry: Omit<LayerStackEntry, 'seq'>): () => void {
|
|
340
|
+
const full: LayerStackEntry = {...entry, seq: seqFor(entry.token)};
|
|
341
|
+
entries.push(full);
|
|
342
|
+
startListening();
|
|
343
|
+
|
|
344
|
+
return () => {
|
|
345
|
+
const index = entries.indexOf(full);
|
|
346
|
+
if (index !== -1) {
|
|
347
|
+
entries.splice(index, 1);
|
|
348
|
+
}
|
|
349
|
+
if (entries.length === 0) {
|
|
350
|
+
stopListening();
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** Test-only: drop all entries and detach the listener. */
|
|
356
|
+
export function resetLayerStackForTests(): void {
|
|
357
|
+
entries.length = 0;
|
|
358
|
+
seqByToken = new WeakMap();
|
|
359
|
+
nextSeq = 0;
|
|
360
|
+
isComposing = false;
|
|
361
|
+
stopListening();
|
|
362
|
+
}
|