@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d
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 +165 -0
- package/README.md +12 -12
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +2 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +0 -1
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +0 -1
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts +8 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +0 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +9 -5
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +51 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +167 -99
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +32 -6
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +16 -6
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +3 -3
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +33 -1
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -9
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +16 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +18 -7
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +27 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +141 -42
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +15 -1
- package/dist/Popover/Popover.d.ts +18 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -2
- package/dist/Popover/usePopover.d.ts +38 -3
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +24 -9
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +24 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +122 -43
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +2 -0
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +36 -9
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +87 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +11 -8
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +10 -1
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +66 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +147 -76
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +131 -3
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +26 -4
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +56 -9
- package/dist/TopNav/TopNavHeading.d.ts +7 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +8 -0
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +69 -6
- package/dist/Typeahead/Typeahead.d.ts +26 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +65 -29
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +18 -0
- package/dist/astryx.umd.js +55 -55
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -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/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/docs.mjs +2 -2
- package/package.json +12 -8
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.tsx +3 -16
- package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
- package/src/ButtonGroup/ButtonGroup.tsx +0 -1
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposerInput.test.tsx +26 -7
- package/src/Chat/ChatComposerInput.tsx +0 -1
- package/src/Chat/ChatDictationButton.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +22 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +192 -26
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/CheckboxList/CheckboxListItem.tsx +0 -3
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +121 -0
- package/src/Citation/Citation.tsx +15 -3
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +63 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +286 -56
- package/src/DateInput/DateInput.test.tsx +248 -2
- package/src/DateInput/DateInput.tsx +196 -100
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/Field/Field.doc.mjs +59 -18
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +17 -4
- package/src/Grid/Grid.test.tsx +43 -30
- package/src/Grid/Grid.tsx +38 -3
- package/src/Icon/Icon.doc.mjs +3 -3
- package/src/InputGroup/InputGroup.doc.mjs +111 -23
- package/src/InputGroup/InputGroup.test.tsx +257 -60
- package/src/InputGroup/InputGroup.tsx +23 -5
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/groupStyles.ts +7 -1
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +35 -3
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +5 -0
- package/src/Layer/useLayer.test.tsx +111 -0
- package/src/Layer/useLayer.tsx +90 -9
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -0
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +50 -0
- package/src/Link/Link.tsx +39 -4
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +7 -0
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +194 -48
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +117 -5
- package/src/Pagination/Pagination.tsx +21 -1
- package/src/Popover/Popover.doc.mjs +26 -0
- package/src/Popover/Popover.test.tsx +121 -0
- package/src/Popover/Popover.tsx +23 -2
- package/src/Popover/usePopover.doc.mjs +9 -3
- package/src/Popover/usePopover.tsx +70 -12
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +34 -26
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +26 -0
- package/src/Selector/Selector.test.tsx +387 -15
- package/src/Selector/Selector.tsx +175 -67
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +48 -0
- package/src/SideNav/SideNavHeading.tsx +8 -2
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +15 -0
- package/src/Slider/Slider.test.tsx +155 -2
- package/src/Slider/Slider.tsx +53 -5
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +6 -0
- package/src/TabList/TabList.test.tsx +251 -0
- package/src/TabList/TabList.tsx +103 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +21 -17
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +10 -0
- package/src/Table/Table.tsx +8 -0
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +3 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- package/src/Table/useTableStickyColumns.doc.mjs +2 -2
- package/src/Text/Text.doc.mjs +18 -18
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
- package/src/TimeInput/TimeInput.doc.mjs +340 -60
- package/src/TimeInput/TimeInput.test.tsx +255 -7
- package/src/TimeInput/TimeInput.tsx +176 -70
- package/src/Timestamp/Timestamp.doc.mjs +19 -19
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +214 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +37 -1
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +68 -0
- package/src/Tooltip/useTooltip.tsx +55 -8
- package/src/TopNav/TopNav.test.tsx +50 -0
- package/src/TopNav/TopNavHeading.tsx +17 -1
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +93 -9
- package/src/Typeahead/Typeahead.doc.mjs +141 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +105 -33
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/docs-script.test.mjs +50 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +10 -5
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useLayer.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, useLayer hook
|
|
6
|
+
* @output Unit tests for useLayer show/hide behavior and feature-detection guards
|
|
7
|
+
* @position Testing; validates useLayer.tsx implementation
|
|
8
|
+
*
|
|
9
|
+
* SYNC: When useLayer.tsx changes, update tests to match new behavior
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
|
+
import {render, act} from '@testing-library/react';
|
|
14
|
+
import {useLayer} from './useLayer';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Minimal harness that exposes the imperative show/hide callbacks and renders
|
|
18
|
+
* the layer element so tests can assert on visibility.
|
|
19
|
+
*/
|
|
20
|
+
function LayerHarness({
|
|
21
|
+
onReady,
|
|
22
|
+
}: {
|
|
23
|
+
onReady: (api: {show: () => void; hide: () => void}) => void;
|
|
24
|
+
}) {
|
|
25
|
+
const layer = useLayer({mode: 'fixed'});
|
|
26
|
+
onReady({show: layer.show, hide: layer.hide});
|
|
27
|
+
return <>{layer.render(<span>Layer content</span>, {x: 0, y: 0})}</>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('useLayer', () => {
|
|
31
|
+
const originalShowPopover = HTMLElement.prototype.showPopover;
|
|
32
|
+
const originalHidePopover = HTMLElement.prototype.hidePopover;
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
// Restore whatever the environment originally provided.
|
|
36
|
+
if (originalShowPopover === undefined) {
|
|
37
|
+
// @ts-expect-error - deleting to simulate original absence
|
|
38
|
+
delete HTMLElement.prototype.showPopover;
|
|
39
|
+
} else {
|
|
40
|
+
HTMLElement.prototype.showPopover = originalShowPopover;
|
|
41
|
+
}
|
|
42
|
+
if (originalHidePopover === undefined) {
|
|
43
|
+
// @ts-expect-error - deleting to simulate original absence
|
|
44
|
+
delete HTMLElement.prototype.hidePopover;
|
|
45
|
+
} else {
|
|
46
|
+
HTMLElement.prototype.hidePopover = originalHidePopover;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('when the Popover API is supported', () => {
|
|
51
|
+
it('calls showPopover/hidePopover on show/hide', () => {
|
|
52
|
+
const showSpy = vi.fn();
|
|
53
|
+
const hideSpy = vi.fn();
|
|
54
|
+
HTMLElement.prototype.showPopover = showSpy;
|
|
55
|
+
HTMLElement.prototype.hidePopover = hideSpy;
|
|
56
|
+
|
|
57
|
+
let api: {show: () => void; hide: () => void} = {
|
|
58
|
+
show: () => {},
|
|
59
|
+
hide: () => {},
|
|
60
|
+
};
|
|
61
|
+
render(<LayerHarness onReady={a => (api = a)} />);
|
|
62
|
+
|
|
63
|
+
act(() => api.show());
|
|
64
|
+
expect(showSpy).toHaveBeenCalledTimes(1);
|
|
65
|
+
|
|
66
|
+
act(() => api.hide());
|
|
67
|
+
expect(hideSpy).toHaveBeenCalledTimes(1);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('when the Popover API is unsupported (Safari <17 / Firefox <125)', () => {
|
|
72
|
+
it('show() does not throw when showPopover is undefined and the layer becomes visible', () => {
|
|
73
|
+
// Simulate a browser without the Popover API (finding infra-4).
|
|
74
|
+
// @ts-expect-error - simulate missing API
|
|
75
|
+
delete HTMLElement.prototype.showPopover;
|
|
76
|
+
// @ts-expect-error - simulate missing API
|
|
77
|
+
delete HTMLElement.prototype.hidePopover;
|
|
78
|
+
|
|
79
|
+
let api: {show: () => void; hide: () => void} = {
|
|
80
|
+
show: () => {},
|
|
81
|
+
hide: () => {},
|
|
82
|
+
};
|
|
83
|
+
const {container} = render(<LayerHarness onReady={a => (api = a)} />);
|
|
84
|
+
|
|
85
|
+
const layerEl = container.querySelector('[popover]') as HTMLElement;
|
|
86
|
+
expect(layerEl).not.toBeNull();
|
|
87
|
+
|
|
88
|
+
expect(() => act(() => api.show())).not.toThrow();
|
|
89
|
+
// Falls back to plain visibility so the layer is still usable.
|
|
90
|
+
expect(layerEl.style.display).toBe('block');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('hide() does not throw when hidePopover is undefined and the layer is hidden', () => {
|
|
94
|
+
// @ts-expect-error - simulate missing API
|
|
95
|
+
delete HTMLElement.prototype.showPopover;
|
|
96
|
+
// @ts-expect-error - simulate missing API
|
|
97
|
+
delete HTMLElement.prototype.hidePopover;
|
|
98
|
+
|
|
99
|
+
let api: {show: () => void; hide: () => void} = {
|
|
100
|
+
show: () => {},
|
|
101
|
+
hide: () => {},
|
|
102
|
+
};
|
|
103
|
+
const {container} = render(<LayerHarness onReady={a => (api = a)} />);
|
|
104
|
+
const layerEl = container.querySelector('[popover]') as HTMLElement;
|
|
105
|
+
|
|
106
|
+
act(() => api.show());
|
|
107
|
+
expect(() => act(() => api.hide())).not.toThrow();
|
|
108
|
+
expect(layerEl.style.display).toBe('none');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import React, {
|
|
17
17
|
useCallback,
|
|
18
|
+
useEffect,
|
|
18
19
|
useId,
|
|
19
20
|
useRef,
|
|
20
21
|
useState,
|
|
@@ -99,6 +100,16 @@ export interface ContextRenderProps {
|
|
|
99
100
|
* @default 'div'
|
|
100
101
|
*/
|
|
101
102
|
as?: 'div' | 'span';
|
|
103
|
+
/**
|
|
104
|
+
* Pointer-enter handler attached to the popover container itself. Lets a
|
|
105
|
+
* consumer keep a hover-driven layer open while the pointer is over the
|
|
106
|
+
* surface (e.g. Tooltip/HoverCard "hoverable" behavior — WCAG 1.4.13).
|
|
107
|
+
*/
|
|
108
|
+
onMouseEnter?: React.MouseEventHandler<HTMLElement>;
|
|
109
|
+
/**
|
|
110
|
+
* Pointer-leave handler attached to the popover container itself.
|
|
111
|
+
*/
|
|
112
|
+
onMouseLeave?: React.MouseEventHandler<HTMLElement>;
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
/**
|
|
@@ -310,8 +321,19 @@ export function useLayer(
|
|
|
310
321
|
const isOpenRef = useRef(false);
|
|
311
322
|
|
|
312
323
|
const show = useCallback(() => {
|
|
313
|
-
|
|
314
|
-
|
|
324
|
+
const el = popoverRef.current;
|
|
325
|
+
if (el && !isOpenRef.current) {
|
|
326
|
+
// Finding infra-4: the Popover API is unsupported on Safari <17 and
|
|
327
|
+
// Firefox <125. On those browsers `showPopover` does not exist, so
|
|
328
|
+
// calling it unconditionally throws a TypeError and the layer never
|
|
329
|
+
// opens. Guard behind a feature check; when the API is missing, fall
|
|
330
|
+
// back to plain visibility (the [popover] attribute is inert there, so
|
|
331
|
+
// the element sits in normal flow) so the layer still becomes visible.
|
|
332
|
+
if (typeof el.showPopover === 'function') {
|
|
333
|
+
el.showPopover();
|
|
334
|
+
} else {
|
|
335
|
+
el.style.display = 'block';
|
|
336
|
+
}
|
|
315
337
|
isOpenRef.current = true;
|
|
316
338
|
setIsOpen(true);
|
|
317
339
|
onShow?.();
|
|
@@ -320,7 +342,16 @@ export function useLayer(
|
|
|
320
342
|
|
|
321
343
|
const hide = useCallback(() => {
|
|
322
344
|
if (isOpenRef.current) {
|
|
323
|
-
popoverRef.current
|
|
345
|
+
const el = popoverRef.current;
|
|
346
|
+
// See finding infra-4 note in `show`: mirror the same guard on hide so
|
|
347
|
+
// unsupported browsers degrade gracefully instead of throwing.
|
|
348
|
+
if (el) {
|
|
349
|
+
if (typeof el.hidePopover === 'function') {
|
|
350
|
+
el.hidePopover();
|
|
351
|
+
} else {
|
|
352
|
+
el.style.display = 'none';
|
|
353
|
+
}
|
|
354
|
+
}
|
|
324
355
|
isOpenRef.current = false;
|
|
325
356
|
setIsOpen(false);
|
|
326
357
|
onHide?.();
|
|
@@ -367,17 +398,63 @@ export function useLayer(
|
|
|
367
398
|
[onHide],
|
|
368
399
|
);
|
|
369
400
|
|
|
370
|
-
// Ref callback for popover element — sets up toggle listener
|
|
401
|
+
// Ref callback for popover element — sets up the `toggle` listener.
|
|
402
|
+
// Tracks the element + handler currently bound so the listener is removed
|
|
403
|
+
// when the element detaches or when `handleToggle`'s identity changes (a new
|
|
404
|
+
// `onHide` prop), preventing stale-closure listeners from accumulating on the
|
|
405
|
+
// same element (infra-10).
|
|
406
|
+
const listenedElRef = useRef<HTMLElement | null>(null);
|
|
407
|
+
const listenedHandlerRef = useRef<((e: Event) => void) | null>(null);
|
|
408
|
+
|
|
409
|
+
const bindToggleListener = useCallback(
|
|
410
|
+
(el: HTMLElement | null, handler: (e: Event) => void) => {
|
|
411
|
+
if (
|
|
412
|
+
listenedElRef.current &&
|
|
413
|
+
listenedHandlerRef.current &&
|
|
414
|
+
(listenedElRef.current !== el || listenedHandlerRef.current !== handler)
|
|
415
|
+
) {
|
|
416
|
+
listenedElRef.current.removeEventListener(
|
|
417
|
+
'toggle',
|
|
418
|
+
listenedHandlerRef.current,
|
|
419
|
+
);
|
|
420
|
+
listenedElRef.current = null;
|
|
421
|
+
listenedHandlerRef.current = null;
|
|
422
|
+
}
|
|
423
|
+
if (el && listenedElRef.current !== el) {
|
|
424
|
+
el.addEventListener('toggle', handler);
|
|
425
|
+
listenedElRef.current = el;
|
|
426
|
+
listenedHandlerRef.current = handler;
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
[],
|
|
430
|
+
);
|
|
431
|
+
|
|
371
432
|
const popoverRefCallback = useCallback(
|
|
372
433
|
(el: HTMLElement | null) => {
|
|
373
434
|
popoverRef.current = el;
|
|
374
|
-
|
|
375
|
-
el.addEventListener('toggle', handleToggle);
|
|
376
|
-
}
|
|
435
|
+
bindToggleListener(el, handleToggle);
|
|
377
436
|
},
|
|
378
|
-
[handleToggle],
|
|
437
|
+
[handleToggle, bindToggleListener],
|
|
379
438
|
);
|
|
380
439
|
|
|
440
|
+
// Re-bind when the handler identity changes while the element stays mounted,
|
|
441
|
+
// and detach on unmount.
|
|
442
|
+
useEffect(() => {
|
|
443
|
+
if (popoverRef.current) {
|
|
444
|
+
bindToggleListener(popoverRef.current, handleToggle);
|
|
445
|
+
}
|
|
446
|
+
return () => {
|
|
447
|
+
if (listenedElRef.current && listenedHandlerRef.current) {
|
|
448
|
+
listenedElRef.current.removeEventListener(
|
|
449
|
+
'toggle',
|
|
450
|
+
listenedHandlerRef.current,
|
|
451
|
+
);
|
|
452
|
+
listenedElRef.current = null;
|
|
453
|
+
listenedHandlerRef.current = null;
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
}, [handleToggle, bindToggleListener]);
|
|
457
|
+
|
|
381
458
|
// Render function for context mode
|
|
382
459
|
const renderContext = useCallback(
|
|
383
460
|
(children: ReactNode, props?: ContextRenderProps) => {
|
|
@@ -389,6 +466,8 @@ export function useLayer(
|
|
|
389
466
|
className: extraClassName,
|
|
390
467
|
style: extraStyle,
|
|
391
468
|
as: Container = 'div',
|
|
469
|
+
onMouseEnter,
|
|
470
|
+
onMouseLeave,
|
|
392
471
|
} = props || {};
|
|
393
472
|
|
|
394
473
|
// CSS anchor positioning (dynamic, not in StyleX)
|
|
@@ -413,7 +492,9 @@ export function useLayer(
|
|
|
413
492
|
role={role}
|
|
414
493
|
popover={lightDismiss ? 'auto' : 'manual'}
|
|
415
494
|
className={combinedClassName}
|
|
416
|
-
style={{...stylexResult.style, ...anchorStyle, ...extraStyle}}
|
|
495
|
+
style={{...stylexResult.style, ...anchorStyle, ...extraStyle}}
|
|
496
|
+
onMouseEnter={onMouseEnter}
|
|
497
|
+
onMouseLeave={onMouseLeave}>
|
|
417
498
|
{children}
|
|
418
499
|
</Container>
|
|
419
500
|
);
|
package/src/Layout/Layout.tsx
CHANGED
|
@@ -26,7 +26,7 @@ import {stack} from '../Stack/stack.stylex';
|
|
|
26
26
|
import {stackItem} from '../Stack/stackItem.stylex';
|
|
27
27
|
import {mergeProps} from '../utils';
|
|
28
28
|
import type {BaseProps} from '../BaseProps';
|
|
29
|
-
import type {SpacingStep} from '../utils/types';
|
|
29
|
+
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
30
30
|
import {themeProps} from '../utils/themeProps';
|
|
31
31
|
import {
|
|
32
32
|
layoutPaddingOuterXVarStyles,
|
|
@@ -76,12 +76,12 @@ const styles = stylex.create({
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
const dynamicStyles = stylex.create({
|
|
79
|
-
contentWidthVar: (width:
|
|
80
|
-
'--layout-content-width': `${width}px
|
|
79
|
+
contentWidthVar: (width: SizeValue) => ({
|
|
80
|
+
'--layout-content-width': typeof width === 'number' ? `${width}px` : width,
|
|
81
81
|
}),
|
|
82
|
-
contentWidth: (width:
|
|
82
|
+
contentWidth: (width: SizeValue) => ({
|
|
83
83
|
width: '100%',
|
|
84
|
-
maxWidth: width,
|
|
84
|
+
maxWidth: typeof width === 'number' ? `${width}px` : width,
|
|
85
85
|
marginInline: 'auto',
|
|
86
86
|
}),
|
|
87
87
|
});
|
|
@@ -102,11 +102,12 @@ export interface LayoutProps extends Omit<BaseProps, 'content'> {
|
|
|
102
102
|
* panels). Dividers remain full-bleed. Content is centered with
|
|
103
103
|
* `margin-inline: auto` when narrower than the available space.
|
|
104
104
|
*
|
|
105
|
-
*
|
|
105
|
+
* Numbers are treated as pixels, strings are used as-is (e.g., '60ch').
|
|
106
|
+
* Common page widths:
|
|
106
107
|
* - `640` — forms, settings, text-focused pages
|
|
107
108
|
* - `960` — content pages, component demos, wider layouts
|
|
108
109
|
*/
|
|
109
|
-
contentWidth?:
|
|
110
|
+
contentWidth?: SizeValue;
|
|
110
111
|
|
|
111
112
|
/**
|
|
112
113
|
* End panel slot (right in LTR, left in RTL).
|
|
@@ -149,15 +150,6 @@ export interface LayoutProps extends Omit<BaseProps, 'content'> {
|
|
|
149
150
|
*/
|
|
150
151
|
defaultHasDividers?: boolean;
|
|
151
152
|
|
|
152
|
-
/**
|
|
153
|
-
* CSS class name(s) appended to the root element.
|
|
154
|
-
*/
|
|
155
|
-
className?: string;
|
|
156
|
-
/**
|
|
157
|
-
* Inline styles to apply to the root element.
|
|
158
|
-
*/
|
|
159
|
-
style?: React.CSSProperties;
|
|
160
|
-
|
|
161
153
|
/**
|
|
162
154
|
* Children are a shorthand for the `content` slot:
|
|
163
155
|
* `<Layout>{main}</Layout>` is equivalent to `<Layout content={main} />`.
|
|
@@ -22,8 +22,8 @@ export const docs = {
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
name: 'height',
|
|
25
|
-
type: '
|
|
26
|
-
description: 'Footer height.',
|
|
25
|
+
type: 'SizeValue',
|
|
26
|
+
description: 'Footer height. Numbers are treated as pixels, strings are used as-is.',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
name: 'label',
|
|
@@ -57,8 +57,8 @@ export const docsZh = {
|
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
name: 'height',
|
|
60
|
-
type: '
|
|
61
|
-
description: '
|
|
60
|
+
type: 'SizeValue',
|
|
61
|
+
description: '页脚高度。数字类型会被解释为像素值,字符串类型按原样使用。',
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
name: 'label',
|
|
@@ -22,7 +22,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
22
22
|
import {LayoutDividerContext} from './LayoutDividerContext';
|
|
23
23
|
import {colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
24
24
|
import {mergeProps} from '../utils';
|
|
25
|
-
import type {SpacingStep} from '../utils/types';
|
|
25
|
+
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
26
26
|
import {themeProps} from '../utils/themeProps';
|
|
27
27
|
import {
|
|
28
28
|
paddingStyles,
|
|
@@ -71,7 +71,7 @@ const styles = stylex.create({
|
|
|
71
71
|
|
|
72
72
|
// Dynamic styles for sizing props
|
|
73
73
|
const dynamicStyles = stylex.create({
|
|
74
|
-
sizing: (height:
|
|
74
|
+
sizing: (height: SizeValue | null) => ({
|
|
75
75
|
height,
|
|
76
76
|
}),
|
|
77
77
|
});
|
|
@@ -95,7 +95,7 @@ export interface LayoutFooterProps extends BaseProps<HTMLDivElement> {
|
|
|
95
95
|
* Height of the footer.
|
|
96
96
|
* Numbers are treated as pixels, strings are used as-is.
|
|
97
97
|
*/
|
|
98
|
-
height?:
|
|
98
|
+
height?: SizeValue;
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
101
|
* Internal padding of the footer using the spacing scale.
|
|
@@ -22,8 +22,8 @@ export const docs = {
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
name: 'height',
|
|
25
|
-
type: '
|
|
26
|
-
description: 'Header height.',
|
|
25
|
+
type: 'SizeValue',
|
|
26
|
+
description: 'Header height. Numbers are treated as pixels, strings are used as-is.',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
name: 'label',
|
|
@@ -57,8 +57,8 @@ export const docsZh = {
|
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
name: 'height',
|
|
60
|
-
type: '
|
|
61
|
-
description: '
|
|
60
|
+
type: 'SizeValue',
|
|
61
|
+
description: '页眉高度。数字类型会被解释为像素值,字符串类型按原样使用。',
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
name: 'label',
|
|
@@ -22,7 +22,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
22
22
|
import {LayoutDividerContext} from './LayoutDividerContext';
|
|
23
23
|
import {colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
24
24
|
import {mergeProps} from '../utils';
|
|
25
|
-
import type {SpacingStep} from '../utils/types';
|
|
25
|
+
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
26
26
|
import {themeProps} from '../utils/themeProps';
|
|
27
27
|
import {
|
|
28
28
|
paddingStyles,
|
|
@@ -71,7 +71,7 @@ const styles = stylex.create({
|
|
|
71
71
|
|
|
72
72
|
// Dynamic styles for sizing props
|
|
73
73
|
const dynamicStyles = stylex.create({
|
|
74
|
-
sizing: (height:
|
|
74
|
+
sizing: (height: SizeValue | null) => ({
|
|
75
75
|
height,
|
|
76
76
|
}),
|
|
77
77
|
});
|
|
@@ -95,7 +95,7 @@ export interface LayoutHeaderProps extends BaseProps<HTMLDivElement> {
|
|
|
95
95
|
* Height of the header.
|
|
96
96
|
* Numbers are treated as pixels, strings are used as-is.
|
|
97
97
|
*/
|
|
98
|
-
height?:
|
|
98
|
+
height?: SizeValue;
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
101
|
* Internal padding of the header using the spacing scale.
|
|
@@ -23,7 +23,7 @@ import {colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
|
23
23
|
import {LayoutAreaContext} from './LayoutAreaContext';
|
|
24
24
|
import {LayoutSlotsContext} from './LayoutSlotsContext';
|
|
25
25
|
import {mergeProps} from '../utils';
|
|
26
|
-
import type {SpacingStep} from '../utils/types';
|
|
26
|
+
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
27
27
|
import type {ResizableProps} from '../Resizable/useResizable';
|
|
28
28
|
import {themeProps} from '../utils/themeProps';
|
|
29
29
|
import {
|
|
@@ -102,7 +102,7 @@ const styles = stylex.create({
|
|
|
102
102
|
|
|
103
103
|
// Dynamic styles for sizing props
|
|
104
104
|
const dynamicStyles = stylex.create({
|
|
105
|
-
sizing: (width:
|
|
105
|
+
sizing: (width: SizeValue | null) => ({
|
|
106
106
|
width,
|
|
107
107
|
}),
|
|
108
108
|
});
|
|
@@ -158,7 +158,7 @@ export interface LayoutPanelProps extends BaseProps<HTMLDivElement> {
|
|
|
158
158
|
* Numbers are treated as pixels, strings are used as-is.
|
|
159
159
|
* When `resizable` is provided, this is ignored — the hook controls width.
|
|
160
160
|
*/
|
|
161
|
-
width?:
|
|
161
|
+
width?: SizeValue;
|
|
162
162
|
|
|
163
163
|
/**
|
|
164
164
|
* Resize props from `useResizable()`. When provided, the panel width
|
|
@@ -220,6 +220,58 @@ export const layoutPaddingOuterYVarStyles = stylex.create({
|
|
|
220
220
|
10: {'--layout-padding-outer-y': spacingVars['--spacing-10']},
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Inline-only padding styles.
|
|
225
|
+
* Use when a component needs to set inline (horizontal) padding independently
|
|
226
|
+
* of block padding — e.g. the `paddingX` prop on Stack.
|
|
227
|
+
*/
|
|
228
|
+
export const paddingInlineStyles = stylex.create({
|
|
229
|
+
0: {
|
|
230
|
+
paddingInlineStart: spacingVars['--spacing-0'],
|
|
231
|
+
paddingInlineEnd: spacingVars['--spacing-0'],
|
|
232
|
+
},
|
|
233
|
+
0.5: {
|
|
234
|
+
paddingInlineStart: spacingVars['--spacing-0-5'],
|
|
235
|
+
paddingInlineEnd: spacingVars['--spacing-0-5'],
|
|
236
|
+
},
|
|
237
|
+
1: {
|
|
238
|
+
paddingInlineStart: spacingVars['--spacing-1'],
|
|
239
|
+
paddingInlineEnd: spacingVars['--spacing-1'],
|
|
240
|
+
},
|
|
241
|
+
1.5: {
|
|
242
|
+
paddingInlineStart: spacingVars['--spacing-1-5'],
|
|
243
|
+
paddingInlineEnd: spacingVars['--spacing-1-5'],
|
|
244
|
+
},
|
|
245
|
+
2: {
|
|
246
|
+
paddingInlineStart: spacingVars['--spacing-2'],
|
|
247
|
+
paddingInlineEnd: spacingVars['--spacing-2'],
|
|
248
|
+
},
|
|
249
|
+
3: {
|
|
250
|
+
paddingInlineStart: spacingVars['--spacing-3'],
|
|
251
|
+
paddingInlineEnd: spacingVars['--spacing-3'],
|
|
252
|
+
},
|
|
253
|
+
4: {
|
|
254
|
+
paddingInlineStart: spacingVars['--spacing-4'],
|
|
255
|
+
paddingInlineEnd: spacingVars['--spacing-4'],
|
|
256
|
+
},
|
|
257
|
+
5: {
|
|
258
|
+
paddingInlineStart: spacingVars['--spacing-5'],
|
|
259
|
+
paddingInlineEnd: spacingVars['--spacing-5'],
|
|
260
|
+
},
|
|
261
|
+
6: {
|
|
262
|
+
paddingInlineStart: spacingVars['--spacing-6'],
|
|
263
|
+
paddingInlineEnd: spacingVars['--spacing-6'],
|
|
264
|
+
},
|
|
265
|
+
8: {
|
|
266
|
+
paddingInlineStart: spacingVars['--spacing-8'],
|
|
267
|
+
paddingInlineEnd: spacingVars['--spacing-8'],
|
|
268
|
+
},
|
|
269
|
+
10: {
|
|
270
|
+
paddingInlineStart: spacingVars['--spacing-10'],
|
|
271
|
+
paddingInlineEnd: spacingVars['--spacing-10'],
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
|
|
223
275
|
/**
|
|
224
276
|
* Block-only padding override styles.
|
|
225
277
|
* Use when a component needs to override block padding independently
|
|
@@ -64,6 +64,15 @@ export const docs = {
|
|
|
64
64
|
{ guidance: false, description: 'Nest interactive content inside captions; keep them plain text.' },
|
|
65
65
|
],
|
|
66
66
|
},
|
|
67
|
+
playground: {
|
|
68
|
+
defaults: {
|
|
69
|
+
media: {
|
|
70
|
+
src: 'https://lookaside.facebook.com/assets/astryx/light-scene-horizontal-1.png',
|
|
71
|
+
alt: 'Coastal shoreline with ocean waves',
|
|
72
|
+
caption: 'A scenic coastline with waves rolling onto a sandy beach beneath a clear sky.',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
67
76
|
};
|
|
68
77
|
|
|
69
78
|
/** @type {import('../docs-types').ComponentDoc} */
|
|
@@ -177,7 +177,7 @@ describe('Lightbox', () => {
|
|
|
177
177
|
expect(screen.getByLabelText('Next')).toBeInTheDocument();
|
|
178
178
|
});
|
|
179
179
|
|
|
180
|
-
it('
|
|
180
|
+
it('keeps prev mounted and disabled on first item', () => {
|
|
181
181
|
render(
|
|
182
182
|
<Lightbox
|
|
183
183
|
isOpen={true}
|
|
@@ -186,11 +186,16 @@ describe('Lightbox', () => {
|
|
|
186
186
|
index={0}
|
|
187
187
|
/>,
|
|
188
188
|
);
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
// The Prev button stays mounted at the range boundary (disabled) rather
|
|
190
|
+
// than unmounting, so navigating to the first item never removes the
|
|
191
|
+
// focused control and drops focus to <body>.
|
|
192
|
+
const prev = screen.getByLabelText('Previous');
|
|
193
|
+
expect(prev).toBeInTheDocument();
|
|
194
|
+
expect(prev).toBeDisabled();
|
|
195
|
+
expect(screen.getByLabelText('Next')).not.toBeDisabled();
|
|
191
196
|
});
|
|
192
197
|
|
|
193
|
-
it('
|
|
198
|
+
it('keeps next mounted and disabled on last item', () => {
|
|
194
199
|
render(
|
|
195
200
|
<Lightbox
|
|
196
201
|
isOpen={true}
|
|
@@ -199,8 +204,51 @@ describe('Lightbox', () => {
|
|
|
199
204
|
index={2}
|
|
200
205
|
/>,
|
|
201
206
|
);
|
|
207
|
+
const next = screen.getByLabelText('Next');
|
|
208
|
+
expect(next).toBeInTheDocument();
|
|
209
|
+
expect(next).toBeDisabled();
|
|
210
|
+
expect(screen.getByLabelText('Previous')).not.toBeDisabled();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('does not drop focus to <body> when navigating to the last item', () => {
|
|
214
|
+
const {rerender} = render(
|
|
215
|
+
<Lightbox
|
|
216
|
+
isOpen={true}
|
|
217
|
+
onOpenChange={() => {}}
|
|
218
|
+
media={media}
|
|
219
|
+
index={1}
|
|
220
|
+
/>,
|
|
221
|
+
);
|
|
222
|
+
// Simulate arriving at the final item (Next becomes disabled).
|
|
223
|
+
rerender(
|
|
224
|
+
<Lightbox
|
|
225
|
+
isOpen={true}
|
|
226
|
+
onOpenChange={() => {}}
|
|
227
|
+
media={media}
|
|
228
|
+
index={2}
|
|
229
|
+
/>,
|
|
230
|
+
);
|
|
231
|
+
// Both nav buttons remain in the DOM; the dialog stays available so
|
|
232
|
+
// keyboard gallery navigation isn't dead-ended.
|
|
202
233
|
expect(screen.getByLabelText('Previous')).toBeInTheDocument();
|
|
203
|
-
expect(screen.
|
|
234
|
+
expect(screen.getByLabelText('Next')).toBeInTheDocument();
|
|
235
|
+
const dialog = document.querySelector('dialog');
|
|
236
|
+
expect(dialog).toBeInTheDocument();
|
|
237
|
+
// Arrow handling is on the dialog, so navigation still works at the edge.
|
|
238
|
+
const onIndexChange = vi.fn();
|
|
239
|
+
rerender(
|
|
240
|
+
<Lightbox
|
|
241
|
+
isOpen={true}
|
|
242
|
+
onOpenChange={() => {}}
|
|
243
|
+
media={media}
|
|
244
|
+
index={2}
|
|
245
|
+
onIndexChange={onIndexChange}
|
|
246
|
+
/>,
|
|
247
|
+
);
|
|
248
|
+
if (dialog instanceof HTMLElement) {
|
|
249
|
+
fireEvent.keyDown(dialog, {key: 'ArrowLeft'});
|
|
250
|
+
}
|
|
251
|
+
expect(onIndexChange).toHaveBeenCalledWith(1);
|
|
204
252
|
});
|
|
205
253
|
|
|
206
254
|
it('calls onIndexChange when next is clicked', () => {
|
|
@@ -496,13 +496,16 @@ export function Lightbox({
|
|
|
496
496
|
/>
|
|
497
497
|
</div>
|
|
498
498
|
|
|
499
|
-
{/* Gallery nav: prev
|
|
500
|
-
|
|
499
|
+
{/* Gallery nav: prev — stays mounted and is disabled at the start of
|
|
500
|
+
the range so pressing/arrowing to the boundary doesn't unmount the
|
|
501
|
+
focused control and drop focus to <body>. */}
|
|
502
|
+
{isGallery && (
|
|
501
503
|
<div {...stylex.props(styles.navButton, styles.navPrev)}>
|
|
502
504
|
<IconButton
|
|
503
505
|
icon={<Icon icon="chevronLeft" size="sm" color="inherit" />}
|
|
504
506
|
label="Previous"
|
|
505
507
|
variant="ghost"
|
|
508
|
+
isDisabled={!canPrev}
|
|
506
509
|
onClick={goToPrev}
|
|
507
510
|
xstyle={styles.controlButton}
|
|
508
511
|
/>
|
|
@@ -549,13 +552,15 @@ export function Lightbox({
|
|
|
549
552
|
)}
|
|
550
553
|
</div>
|
|
551
554
|
|
|
552
|
-
{/* Gallery nav: next
|
|
553
|
-
|
|
555
|
+
{/* Gallery nav: next — see "prev" above; stays mounted and disabled at
|
|
556
|
+
the end of the range instead of unmounting. */}
|
|
557
|
+
{isGallery && (
|
|
554
558
|
<div {...stylex.props(styles.navButton, styles.navNext)}>
|
|
555
559
|
<IconButton
|
|
556
560
|
icon={<Icon icon="chevronRight" size="sm" color="inherit" />}
|
|
557
561
|
label="Next"
|
|
558
562
|
variant="ghost"
|
|
563
|
+
isDisabled={!canNext}
|
|
559
564
|
onClick={goToNext}
|
|
560
565
|
xstyle={styles.controlButton}
|
|
561
566
|
/>
|
package/src/Link/Link.doc.mjs
CHANGED
|
@@ -59,6 +59,13 @@ export const docs = {
|
|
|
59
59
|
'Opens in new tab with external icon and safe rel tokens',
|
|
60
60
|
default: 'false',
|
|
61
61
|
},
|
|
62
|
+
{
|
|
63
|
+
name: 'newTabLabel',
|
|
64
|
+
type: 'string',
|
|
65
|
+
description:
|
|
66
|
+
'Screen-reader text announcing that an external link opens in a new tab. Override for localization.',
|
|
67
|
+
default: "'(opens in new tab)'",
|
|
68
|
+
},
|
|
62
69
|
{
|
|
63
70
|
name: 'target',
|
|
64
71
|
type: 'string',
|
|
@@ -185,6 +192,12 @@ export const docsZh = {
|
|
|
185
192
|
description: '在新标签页中打开,带外部图标和安全 rel 标记',
|
|
186
193
|
default: 'false',
|
|
187
194
|
},
|
|
195
|
+
{
|
|
196
|
+
name: 'newTabLabel',
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: '向屏幕阅读器announce外部链接将在新标签页打开的文本。可覆盖以本地化。',
|
|
199
|
+
default: "'(opens in new tab)'",
|
|
200
|
+
},
|
|
188
201
|
{
|
|
189
202
|
name: 'target',
|
|
190
203
|
type: 'string',
|
|
@@ -296,6 +309,7 @@ export const docsDense = {
|
|
|
296
309
|
hasUnderline: 'Always show underline',
|
|
297
310
|
isDisabled: 'Disables link',
|
|
298
311
|
isExternalLink: 'Opens new tab w/ external icon and safe rel tokens',
|
|
312
|
+
newTabLabel: 'SR text announcing an external link opens in a new tab',
|
|
299
313
|
target:
|
|
300
314
|
'Where to open linked document. target="_blank" auto-adds noopener noreferrer.',
|
|
301
315
|
rel: 'Link relationship tokens. noopener noreferrer are merged for target="_blank".',
|