@astryxdesign/core 0.1.3 → 0.1.4-canary.01e5b29
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 +51 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +20 -18
- package/dist/AlertDialog/useImperativeAlertDialog.js +3 -3
- package/dist/AppShell/AppShell.d.ts +1 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +55 -53
- package/dist/AspectRatio/AspectRatio.js +5 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +27 -25
- package/dist/Avatar/AvatarStatusDot.js +5 -5
- package/dist/AvatarGroup/AvatarGroup.js +5 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.js +5 -5
- package/dist/Badge/Badge.js +3 -3
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +32 -25
- package/dist/Blockquote/Blockquote.js +7 -7
- package/dist/Breadcrumbs/BreadcrumbItem.js +17 -17
- package/dist/Breadcrumbs/Breadcrumbs.js +7 -7
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +47 -26
- package/dist/ButtonGroup/ButtonGroup.js +7 -7
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +108 -64
- package/dist/Calendar/dayCellUtils.d.ts +67 -5
- package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
- package/dist/Calendar/dayCellUtils.js +139 -18
- package/dist/Calendar/styles.d.ts +2 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +2 -2
- package/dist/Card/Card.d.ts +4 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +18 -10
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +20 -19
- package/dist/Center/Center.js +3 -3
- package/dist/Chat/ChatComposer.js +23 -23
- package/dist/Chat/ChatComposerDrawer.js +14 -14
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +27 -15
- package/dist/Chat/ChatDictationButton.d.ts +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +13 -11
- package/dist/Chat/ChatLayout.js +17 -17
- package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +12 -10
- package/dist/Chat/ChatMessage.js +12 -12
- package/dist/Chat/ChatMessageBubble.js +7 -7
- package/dist/Chat/ChatMessageList.js +14 -14
- package/dist/Chat/ChatMessageMetadata.d.ts +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +14 -12
- package/dist/Chat/ChatPastedTextToken.js +13 -13
- package/dist/Chat/ChatSendButton.js +3 -3
- package/dist/Chat/ChatSystemMessage.d.ts +1 -1
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +17 -17
- package/dist/Chat/ChatTokenizedText.d.ts +1 -1
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +24 -15
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +81 -74
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -15
- package/dist/CheckboxInput/CheckboxInput.d.ts +6 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +32 -24
- package/dist/CheckboxList/CheckboxList.js +9 -9
- package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +8 -6
- package/dist/Citation/Citation.js +10 -10
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +32 -9
- package/dist/Code/Code.d.ts +15 -1
- package/dist/Code/Code.d.ts.map +1 -1
- package/dist/Code/Code.js +35 -5
- package/dist/Code/index.d.ts +1 -1
- package/dist/Code/index.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.d.ts +10 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +88 -52
- package/dist/CodeBlock/index.d.ts +1 -1
- package/dist/CodeBlock/index.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.d.ts +9 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +110 -22
- package/dist/Collapsible/CollapsibleGroup.d.ts +39 -7
- package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +73 -12
- package/dist/Collapsible/CollapsibleGroupContext.d.ts +31 -0
- package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +33 -3
- package/dist/Collapsible/index.d.ts +1 -0
- package/dist/Collapsible/index.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.d.ts +4 -1
- package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.js +20 -6
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +36 -34
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.js +27 -7
- package/dist/CommandPalette/CommandPaletteFooter.js +16 -16
- package/dist/CommandPalette/CommandPaletteGroup.js +5 -5
- package/dist/CommandPalette/CommandPaletteInput.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.js +3 -3
- package/dist/CommandPalette/CommandPaletteList.js +3 -3
- package/dist/ContextMenu/ContextMenu.d.ts +9 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +16 -11
- package/dist/DateInput/DateInput.js +18 -18
- package/dist/DateRangeInput/DateRangeInput.js +23 -23
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -7
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +30 -26
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +9 -9
- package/dist/Dialog/DialogHeader.js +16 -16
- package/dist/Dialog/useImperativeDialog.js +3 -3
- package/dist/Divider/Divider.d.ts +0 -22
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +7 -7
- package/dist/DropdownMenu/DropdownMenu.js +10 -10
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +2 -17
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
- package/dist/DropdownMenu/renderDropdownItems.js +10 -10
- package/dist/EmptyState/EmptyState.js +9 -9
- package/dist/Field/Field.js +17 -17
- package/dist/Field/FieldLabel.js +15 -15
- package/dist/Field/InputClearButton.js +5 -5
- package/dist/FieldStatus/FieldStatus.js +3 -3
- package/dist/FileInput/FileInput.js +29 -29
- package/dist/FormLayout/FormLayout.js +5 -5
- package/dist/Grid/Grid.d.ts +4 -3
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +29 -12
- package/dist/Grid/GridSpan.js +3 -3
- package/dist/HStack/HStack.js +3 -3
- package/dist/Heading/Heading.js +10 -10
- package/dist/HoverCard/HoverCard.js +9 -9
- package/dist/HoverCard/useHoverCard.js +3 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +16 -12
- package/dist/Icon/defaultIcons.js +116 -116
- package/dist/IconButton/IconButton.js +3 -3
- package/dist/InputGroup/InputGroup.js +11 -11
- package/dist/InputGroup/InputGroupText.js +3 -3
- package/dist/Item/Item.js +18 -18
- package/dist/Kbd/Kbd.js +5 -5
- package/dist/Layer/LayerProvider.js +7 -7
- package/dist/Layer/useLayer.js +5 -5
- package/dist/Layout/Layout.js +21 -21
- package/dist/Layout/LayoutContent.js +3 -3
- package/dist/Layout/LayoutFooter.js +5 -5
- package/dist/Layout/LayoutHeader.js +5 -5
- package/dist/Layout/LayoutPanel.js +3 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +55 -31
- package/dist/Lightbox/useLightbox.js +3 -3
- package/dist/Link/Link.js +15 -15
- package/dist/Link/LinkProvider.js +3 -3
- package/dist/Link/useLinkify.js +3 -3
- package/dist/List/List.js +11 -11
- package/dist/List/ListItem.js +11 -11
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +102 -102
- package/dist/Markdown/parser.d.ts +7 -0
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +300 -6
- package/dist/MetadataList/MetadataList.js +10 -10
- package/dist/MetadataList/MetadataListItem.js +15 -15
- package/dist/MobileNav/MobileNav.js +15 -15
- package/dist/MobileNav/MobileNavToggle.js +5 -5
- package/dist/MoreMenu/MoreMenu.js +3 -3
- package/dist/MultiSelector/MultiSelector.d.ts +7 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +64 -55
- package/dist/NavIcon/NavIcon.js +3 -3
- package/dist/NavMenu/NavHeadingMenu.js +5 -5
- package/dist/NavMenu/NavHeadingMenuItem.js +8 -8
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +48 -32
- package/dist/Outline/Outline.js +15 -15
- package/dist/OverflowList/OverflowList.js +8 -8
- package/dist/Overlay/Overlay.js +3 -3
- package/dist/Overlay/OverlayScrim.js +5 -5
- package/dist/Overlay/useOverlay.js +3 -3
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +125 -72
- package/dist/Popover/Popover.js +16 -16
- package/dist/Popover/usePopover.js +7 -7
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +110 -92
- package/dist/PowerSearch/PowerSearchEditPopover.js +84 -84
- package/dist/PowerSearch/PowerSearchFilterEditor.js +3 -3
- package/dist/PowerSearch/PowerSearchToken.js +5 -5
- package/dist/PowerSearch/PowerSearchValueEditor.js +54 -54
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +25 -18
- package/dist/RadioList/RadioList.d.ts +7 -1
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +10 -8
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +30 -22
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +28 -10
- package/dist/Section/Section.js +5 -5
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +32 -10
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +18 -12
- package/dist/SelectableCard/SelectableCard.js +5 -5
- package/dist/Selector/Selector.d.ts +6 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +54 -45
- package/dist/Selector/SelectorOption.js +3 -3
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +38 -34
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +8 -6
- package/dist/SideNav/SideNavHeading.js +87 -87
- package/dist/SideNav/SideNavItem.js +42 -42
- package/dist/SideNav/SideNavSection.d.ts +1 -1
- package/dist/SideNav/SideNavSection.d.ts.map +1 -1
- package/dist/SideNav/SideNavSection.js +18 -16
- package/dist/Skeleton/Skeleton.js +3 -3
- package/dist/Slider/Slider.d.ts +6 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +31 -22
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +10 -10
- package/dist/StatusDot/StatusDot.js +5 -5
- package/dist/Switch/Switch.d.ts +13 -4
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -30
- package/dist/TabList/Tab.js +18 -18
- package/dist/TabList/TabList.js +5 -5
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +57 -30
- package/dist/TabList/tab.markers.stylex.d.ts +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +51 -39
- package/dist/Table/Table.js +7 -7
- package/dist/Table/TableBody.d.ts +1 -1
- package/dist/Table/TableBody.d.ts.map +1 -1
- package/dist/Table/TableBody.js +9 -5
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +76 -7
- package/dist/Table/TableFooter.d.ts +1 -1
- package/dist/Table/TableFooter.d.ts.map +1 -1
- package/dist/Table/TableFooter.js +9 -5
- package/dist/Table/TableHeader.d.ts +1 -1
- package/dist/Table/TableHeader.d.ts.map +1 -1
- package/dist/Table/TableHeader.js +9 -5
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/TableRow.js +5 -5
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +14 -11
- package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +5 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
- package/dist/Table/plugins/rowExpansion/index.d.ts +3 -0
- package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/index.js +3 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +90 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +398 -0
- package/dist/Table/plugins/selection/useTableSelection.js +18 -18
- package/dist/Table/plugins/selection/useTableSelectionState.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelectionState.js +11 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +17 -17
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +8 -4
- package/dist/Table/tableContextMenu.d.ts +5 -1
- package/dist/Table/tableContextMenu.d.ts.map +1 -1
- package/dist/Table/tableContextMenu.js +19 -12
- package/dist/Text/Text.d.ts +1 -1
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +14 -13
- package/dist/Text/text.stylex.d.ts +35 -0
- package/dist/Text/text.stylex.d.ts.map +1 -1
- package/dist/Text/text.stylex.js +52 -1
- package/dist/TextArea/TextArea.js +14 -14
- package/dist/TextInput/TextInput.js +15 -15
- package/dist/Thumbnail/Thumbnail.d.ts +3 -2
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +30 -29
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +26 -21
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +37 -26
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +25 -17
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +23 -11
- package/dist/Toast/useToast.js +4 -4
- package/dist/ToggleButton/ToggleButton.js +12 -12
- package/dist/ToggleButton/ToggleButtonGroup.js +5 -5
- package/dist/Token/Token.js +21 -21
- package/dist/Tokenizer/Tokenizer.d.ts +6 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +38 -29
- package/dist/Toolbar/Toolbar.js +18 -18
- package/dist/Tooltip/Tooltip.js +11 -11
- package/dist/Tooltip/useTooltip.js +3 -3
- package/dist/TopNav/TopNav.js +32 -32
- package/dist/TopNav/TopNavHeading.js +67 -67
- package/dist/TopNav/TopNavItem.js +5 -5
- package/dist/TopNav/TopNavMegaMenu.js +30 -30
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +25 -14
- package/dist/TopNav/TopNavMegaMenuItem.js +16 -16
- package/dist/TopNav/TopNavMenu.js +32 -32
- package/dist/TreeList/TreeList.js +8 -8
- package/dist/TreeList/TreeListBranches.js +11 -11
- package/dist/TreeList/TreeListItem.js +30 -30
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +23 -20
- package/dist/Typeahead/Typeahead.js +12 -12
- package/dist/Typeahead/TypeaheadItem.js +10 -10
- package/dist/VStack/VStack.js +3 -3
- package/dist/astryx.css +23 -0
- package/dist/astryx.umd.js +60 -58
- package/dist/astryx.umd.js.map +4 -4
- package/dist/docs-types.d.ts +13 -1
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.d.ts +1 -1
- package/dist/hooks/focusableSelector.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.js +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +3 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +38 -1
- package/dist/hooks/useHotkeys.d.ts +51 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -0
- package/dist/hooks/useHotkeys.js +160 -0
- package/dist/hooks/useInteractiveRole.d.ts +6 -2
- package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
- package/dist/hooks/useInteractiveRole.js +6 -2
- package/dist/hooks/useKeyboardHint.js +9 -9
- package/dist/hooks/useStreamingText.d.ts +3 -1
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +14 -5
- package/dist/theme/MediaTheme.js +3 -3
- package/dist/theme/Theme.js +7 -7
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +10 -3
- package/dist/theme/hct.d.ts +0 -15
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +9 -9
- package/dist/theme/syntax/SyntaxTheme.js +5 -5
- package/dist/theme/tokens.d.ts +10 -2
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +220 -4
- package/dist/utils/color.d.ts +42 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/color.js +150 -0
- package/dist/utils/composeEventHandlers.d.ts +30 -0
- package/dist/utils/composeEventHandlers.d.ts.map +1 -0
- package/dist/utils/composeEventHandlers.js +40 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +8 -5
- package/package.json +3 -3
- package/src/AlertDialog/AlertDialog.tsx +2 -0
- package/src/AppShell/AppShell.tsx +2 -0
- package/src/AspectRatio/AspectRatio.doc.mjs +1 -1
- package/src/Avatar/Avatar.doc.mjs +13 -2
- package/src/Avatar/Avatar.test.tsx +32 -1
- package/src/Avatar/Avatar.tsx +12 -20
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +38 -0
- package/src/Banner/Banner.tsx +8 -1
- package/src/Button/Button.tsx +39 -6
- package/src/ButtonGroup/ButtonGroup.doc.mjs +1 -1
- package/src/Calendar/Calendar.doc.mjs +1 -1
- package/src/Calendar/Calendar.test.tsx +201 -17
- package/src/Calendar/Calendar.tsx +79 -26
- package/src/Calendar/dayCellUtils.test.ts +306 -1
- package/src/Calendar/dayCellUtils.ts +206 -13
- package/src/Calendar/styles.ts +12 -2
- package/src/Card/Card.doc.mjs +1 -1
- package/src/Card/Card.tsx +16 -6
- package/src/Carousel/Carousel.doc.mjs +12 -12
- package/src/Carousel/Carousel.test.tsx +13 -0
- package/src/Carousel/Carousel.tsx +1 -0
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.test.tsx +24 -0
- package/src/Chat/ChatComposerInput.tsx +17 -1
- package/src/Chat/ChatDictationButton.test.tsx +43 -0
- package/src/Chat/ChatDictationButton.tsx +4 -4
- package/src/Chat/ChatLayoutScrollButton.test.tsx +33 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessageMetadata.test.tsx +32 -0
- package/src/Chat/ChatMessageMetadata.tsx +4 -6
- package/src/Chat/ChatSystemMessage.test.tsx +26 -11
- package/src/Chat/ChatSystemMessage.tsx +7 -7
- package/src/Chat/ChatTokenizedText.test.tsx +29 -16
- package/src/Chat/ChatTokenizedText.tsx +15 -8
- package/src/Chat/ChatToolCalls.test.tsx +55 -0
- package/src/Chat/ChatToolCalls.tsx +10 -12
- package/src/Chat/index.ts +1 -4
- package/src/Chat/useChatNewMessages.test.tsx +4 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +12 -4
- package/src/CheckboxInput/CheckboxInput.test.tsx +103 -0
- package/src/CheckboxInput/CheckboxInput.tsx +13 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +19 -0
- package/src/CheckboxList/CheckboxListItem.tsx +11 -2
- package/src/Citation/Citation.doc.mjs +5 -0
- package/src/ClickableCard/ClickableCard.tsx +45 -2
- package/src/Code/Code.test.tsx +54 -0
- package/src/Code/Code.tsx +48 -4
- package/src/Code/index.ts +1 -1
- package/src/CodeBlock/CodeBlock.doc.mjs +7 -2
- package/src/CodeBlock/CodeBlock.test.tsx +122 -3
- package/src/CodeBlock/CodeBlock.tsx +62 -4
- package/src/CodeBlock/index.ts +1 -1
- package/src/Collapsible/Collapsible.doc.mjs +8 -4
- package/src/Collapsible/Collapsible.test.tsx +405 -0
- package/src/Collapsible/Collapsible.tsx +86 -10
- package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
- package/src/Collapsible/CollapsibleGroup.test.tsx +318 -0
- package/src/Collapsible/CollapsibleGroup.tsx +107 -9
- package/src/Collapsible/CollapsibleGroupContext.tsx +42 -2
- package/src/Collapsible/index.ts +4 -0
- package/src/Collapsible/useCollapsible.ts +20 -6
- package/src/CommandPalette/CommandPalette.tsx +5 -3
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
- package/src/CommandPalette/CommandPaletteEmpty.tsx +15 -1
- package/src/CommandPalette/CommandPaletteGroup.doc.mjs +10 -0
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteList.doc.mjs +9 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +15 -0
- package/src/ContextMenu/ContextMenu.test.tsx +15 -0
- package/src/ContextMenu/ContextMenu.tsx +19 -1
- package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
- package/src/DateInput/DateInput.doc.mjs +6 -1
- package/src/DateInput/DateInput.test.tsx +11 -20
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
- package/src/DateRangeInput/DateRangeInput.tsx +2 -2
- package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -3
- package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
- package/src/DateTimeInput/DateTimeInput.tsx +9 -8
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/DialogHeader.doc.mjs +45 -0
- package/src/Divider/Divider.tsx +1 -23
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +5 -3
- package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
- package/src/EmptyState/EmptyState.doc.mjs +1 -1
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/FieldLabel.test.tsx +2 -2
- package/src/FieldStatus/FieldStatus.test.tsx +282 -0
- package/src/FileInput/FileInput.doc.mjs +1 -1
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
- package/src/Grid/Grid.doc.mjs +3 -3
- package/src/Grid/Grid.test.tsx +43 -18
- package/src/Grid/Grid.tsx +26 -9
- package/src/Icon/Icon.test.tsx +41 -29
- package/src/Icon/Icon.tsx +6 -2
- package/src/InputGroup/InputGroup.tsx +2 -2
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
- package/src/Item/Item.tsx +1 -1
- package/src/Layout/Layout.test.tsx +285 -0
- package/src/Layout/LayoutContent.doc.mjs +12 -0
- package/src/Layout/LayoutPanel.doc.mjs +40 -0
- package/src/Layout/LayoutSlots.test.tsx +364 -0
- package/src/Layout/__tests__/edgeCompensation.test.tsx +72 -0
- package/src/Lightbox/Lightbox.doc.mjs +5 -0
- package/src/Lightbox/Lightbox.test.tsx +123 -2
- package/src/Lightbox/Lightbox.tsx +29 -1
- package/src/Markdown/Markdown.test.tsx +23 -0
- package/src/Markdown/Markdown.tsx +9 -7
- package/src/Markdown/incremental.test.ts +36 -0
- package/src/Markdown/parser.perf.test.ts +34 -12
- package/src/Markdown/parser.test.ts +210 -0
- package/src/Markdown/parser.ts +301 -6
- package/src/MobileNav/MobileNav.doc.mjs +20 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +14 -1
- package/src/MultiSelector/MultiSelector.test.tsx +33 -0
- package/src/MultiSelector/MultiSelector.tsx +20 -0
- package/src/NavMenu/NavMenu.doc.mjs +15 -0
- package/src/NumberInput/NumberInput.test.tsx +48 -3
- package/src/NumberInput/NumberInput.tsx +32 -15
- package/src/Outline/parseOutlineFromMarkdown.test.ts +80 -0
- package/src/OverflowList/OverflowList.test.tsx +416 -0
- package/src/Overlay/Overlay.doc.mjs +6 -0
- package/src/Overlay/Overlay.test.tsx +356 -0
- package/src/Pagination/Pagination.test.tsx +162 -0
- package/src/Pagination/Pagination.tsx +80 -26
- package/src/Popover/Popover.test.tsx +65 -0
- package/src/PowerSearch/PowerSearch.doc.mjs +4 -4
- package/src/PowerSearch/PowerSearch.test.tsx +109 -1
- package/src/PowerSearch/PowerSearch.tsx +37 -16
- package/src/ProgressBar/ProgressBar.test.tsx +30 -0
- package/src/ProgressBar/ProgressBar.tsx +12 -5
- package/src/RadioList/RadioList.doc.mjs +7 -1
- package/src/RadioList/RadioList.test.tsx +65 -0
- package/src/RadioList/RadioList.tsx +10 -1
- package/src/RadioList/RadioListItem.tsx +13 -4
- package/src/Resizable/ResizeHandle.test.tsx +218 -0
- package/src/Resizable/ResizeHandle.tsx +22 -4
- package/src/Section/Section.test.tsx +4 -10
- package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
- package/src/SegmentedControl/SegmentedControl.test.tsx +192 -0
- package/src/SegmentedControl/SegmentedControl.tsx +27 -5
- package/src/SegmentedControl/SegmentedControlItem.tsx +9 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +12 -1
- package/src/Selector/Selector.test.tsx +30 -0
- package/src/Selector/Selector.tsx +18 -0
- package/src/SideNav/SideNav.doc.mjs +7 -1
- package/src/SideNav/SideNav.test.tsx +66 -0
- package/src/SideNav/SideNav.tsx +6 -2
- package/src/SideNav/SideNavCollapseButton.tsx +4 -3
- package/src/SideNav/SideNavSection.tsx +6 -4
- package/src/SizeContext/SizeContext.test.tsx +226 -0
- package/src/Slider/Slider.doc.mjs +14 -2
- package/src/Slider/Slider.test.tsx +30 -0
- package/src/Slider/Slider.tsx +20 -0
- package/src/Spinner/Spinner.tsx +1 -0
- package/src/Switch/Switch.doc.mjs +21 -9
- package/src/Switch/Switch.test.tsx +137 -0
- package/src/Switch/Switch.tsx +32 -7
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +185 -1
- package/src/TabList/TabMenu.tsx +45 -9
- package/src/Table/BaseTable.tsx +16 -3
- package/src/Table/Table.test.tsx +87 -0
- package/src/Table/TableBody.tsx +15 -2
- package/src/Table/TableCell.tsx +87 -8
- package/src/Table/TableFooter.tsx +15 -2
- package/src/Table/TableHeader.tsx +15 -2
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +13 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +3 -1
- package/src/Table/plugins/pagination/paginateData.ts +5 -1
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
- package/src/Table/plugins/rowExpansion/index.ts +7 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +155 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +590 -0
- package/src/Table/plugins/selection/useTableSelectionState.test.tsx +23 -0
- package/src/Table/plugins/selection/useTableSelectionState.tsx +11 -6
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +35 -1
- package/src/Table/plugins/sortable/useTableSortableState.tsx +8 -4
- package/src/Table/tableContextMenu.test.tsx +27 -3
- package/src/Table/tableContextMenu.tsx +20 -2
- package/src/Table/useTablePagination.doc.mjs +4 -1
- package/src/Table/useTableRowExpansion.doc.mjs +80 -0
- package/src/Table/useTableSortable.doc.mjs +4 -1
- package/src/Text/Text.doc.mjs +2 -2
- package/src/Text/Text.test.tsx +11 -0
- package/src/Text/Text.tsx +4 -2
- package/src/Text/text.stylex.ts +41 -0
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.test.tsx +3 -3
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TextInput/TextInput.test.tsx +3 -3
- package/src/Thumbnail/Thumbnail.test.tsx +36 -2
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.doc.mjs +11 -6
- package/src/TimeInput/TimeInput.test.tsx +37 -0
- package/src/TimeInput/TimeInput.tsx +11 -1
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +52 -0
- package/src/Timestamp/Timestamp.tsx +30 -16
- package/src/Toast/Toast.tsx +11 -3
- package/src/Toast/ToastViewport.test.tsx +64 -0
- package/src/Toast/ToastViewport.tsx +12 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -4
- package/src/Tokenizer/Tokenizer.test.tsx +33 -0
- package/src/Tokenizer/Tokenizer.tsx +19 -0
- package/src/Toolbar/Toolbar.test.tsx +1 -1
- package/src/TopNav/TopNav.doc.mjs +1 -1
- package/src/TopNav/TopNav.test.tsx +18 -0
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +9 -2
- package/src/TreeList/TreeList.doc.mjs +2 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +19 -0
- package/src/Typeahead/BaseTypeahead.tsx +5 -2
- package/src/Typeahead/Typeahead.doc.mjs +7 -2
- package/src/Typeahead/Typeahead.test.tsx +45 -1
- package/src/__tests__/TestIcon.tsx +26 -0
- package/src/__tests__/fastRoleQueries.ts +66 -0
- package/src/docPropReferences.test.ts +178 -0
- package/src/docs-types.ts +14 -0
- package/src/hooks/focusableSelector.ts +1 -1
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useFocusTrap.doc.mjs +4 -2
- package/src/hooks/useFocusTrap.test.tsx +149 -1
- package/src/hooks/useFocusTrap.ts +50 -1
- package/src/hooks/useHotkeys.doc.mjs +52 -0
- package/src/hooks/useHotkeys.test.ts +245 -0
- package/src/hooks/useHotkeys.ts +203 -0
- package/src/hooks/useInteractiveRole.ts +12 -4
- package/src/hooks/useKeyboardHint.doc.mjs +6 -6
- package/src/hooks/useStreamingText.test.ts +54 -19
- package/src/hooks/useStreamingText.ts +16 -5
- package/src/theme/SyntaxTheme.doc.mjs +4 -4
- package/src/theme/defineTheme.ts +4 -13
- package/src/theme/derivedVarRegistry.test.ts +2 -2
- package/src/theme/expandColorScale.test.ts +29 -0
- package/src/theme/expandColorScale.ts +11 -6
- package/src/theme/hct.ts +9 -17
- package/src/theme/tokens.test.ts +182 -9
- package/src/theme/tokens.ts +239 -4
- package/src/theme/useTheme.test.tsx +20 -0
- package/src/utils/color.test.ts +133 -0
- package/src/utils/color.ts +148 -0
- package/src/utils/composeEventHandlers.test.ts +71 -0
- package/src/utils/composeEventHandlers.ts +44 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/mergeProps.test.ts +166 -0
- package/src/utils/sharedResizeObserver.test.ts +2 -2
- package/src/utils/timeParser.test.ts +13 -0
- package/src/utils/timeParser.ts +8 -5
|
@@ -34,7 +34,7 @@ export const docs = {
|
|
|
34
34
|
],
|
|
35
35
|
theming: {
|
|
36
36
|
container: true,
|
|
37
|
-
targets: [{className: 'astryx-selectable-card', visualProps: ['selected']}],
|
|
37
|
+
targets: [{className: 'astryx-selectable-card', visualProps: ['selected', 'variant']}],
|
|
38
38
|
},
|
|
39
39
|
playground: {
|
|
40
40
|
defaults: {
|
|
@@ -86,11 +86,17 @@ export const docs = {
|
|
|
86
86
|
description: 'Disables the selector.',
|
|
87
87
|
default: 'false',
|
|
88
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: 'htmlName',
|
|
91
|
+
type: 'string',
|
|
92
|
+
description:
|
|
93
|
+
'The HTML name attribute for form submissions. Renders a hidden input carrying the selected value, like a native select.',
|
|
94
|
+
},
|
|
89
95
|
{
|
|
90
96
|
name: 'disabledMessage',
|
|
91
97
|
type: 'string',
|
|
92
98
|
description:
|
|
93
|
-
'Explains why the selector is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the trigger focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled Selector in Tooltip
|
|
99
|
+
'Explains why the selector is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the trigger focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled Selector in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
94
100
|
},
|
|
95
101
|
{
|
|
96
102
|
name: 'isLabelHidden',
|
|
@@ -346,6 +352,11 @@ export const docsDense = {
|
|
|
346
352
|
description:
|
|
347
353
|
'Set a meaningful placeholder that hints at the expected selection (e.g. "Choose a country" not "Select...").',
|
|
348
354
|
},
|
|
355
|
+
{
|
|
356
|
+
guidance: true,
|
|
357
|
+
description:
|
|
358
|
+
'Use inside InputGroup only when the selector needs a short prefix or suffix addon.',
|
|
359
|
+
},
|
|
349
360
|
{
|
|
350
361
|
guidance: false,
|
|
351
362
|
description:
|
|
@@ -839,4 +839,34 @@ describe('Selector', () => {
|
|
|
839
839
|
expect(trigger).toHaveAttribute('tabIndex', '-1');
|
|
840
840
|
});
|
|
841
841
|
});
|
|
842
|
+
describe('form participation', () => {
|
|
843
|
+
it('submits the selected value under htmlName', () => {
|
|
844
|
+
const {container} = render(
|
|
845
|
+
<form>
|
|
846
|
+
<Selector label="Fruit" htmlName="fruit" options={OPTIONS} value="Banana" />
|
|
847
|
+
</form>,
|
|
848
|
+
);
|
|
849
|
+
const data = new FormData(container.querySelector('form')!);
|
|
850
|
+
expect(data.get('fruit')).toBe('Banana');
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
it('submits an empty string when nothing is selected', () => {
|
|
854
|
+
const {container} = render(
|
|
855
|
+
<form>
|
|
856
|
+
<Selector label="Fruit" htmlName="fruit" options={OPTIONS} />
|
|
857
|
+
</form>,
|
|
858
|
+
);
|
|
859
|
+
const data = new FormData(container.querySelector('form')!);
|
|
860
|
+
expect(data.get('fruit')).toBe('');
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
it('is excluded from form data when disabled', () => {
|
|
864
|
+
const {container} = render(
|
|
865
|
+
<form>
|
|
866
|
+
<Selector label="Fruit" htmlName="fruit" options={OPTIONS} value="Banana" isDisabled />
|
|
867
|
+
</form>,
|
|
868
|
+
);
|
|
869
|
+
expect([...new FormData(container.querySelector('form')!).keys()]).toEqual([]);
|
|
870
|
+
});
|
|
871
|
+
});
|
|
842
872
|
});
|
|
@@ -483,6 +483,13 @@ interface SelectorPropsBase<
|
|
|
483
483
|
*/
|
|
484
484
|
isDefaultOpen?: boolean;
|
|
485
485
|
|
|
486
|
+
/**
|
|
487
|
+
* The HTML name attribute for form submissions. When set, a hidden input
|
|
488
|
+
* carries the selected value under this name, matching how a native
|
|
489
|
+
* select serializes.
|
|
490
|
+
*/
|
|
491
|
+
htmlName?: string;
|
|
492
|
+
|
|
486
493
|
/**
|
|
487
494
|
* Test ID for testing frameworks.
|
|
488
495
|
*/
|
|
@@ -564,6 +571,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
564
571
|
status,
|
|
565
572
|
labelTooltip,
|
|
566
573
|
startIcon,
|
|
574
|
+
htmlName,
|
|
567
575
|
renderOption,
|
|
568
576
|
hasSearch = false,
|
|
569
577
|
searchPlaceholder = 'Search...',
|
|
@@ -991,6 +999,16 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
991
999
|
{selectedItem?.label ?? placeholder}
|
|
992
1000
|
</span>
|
|
993
1001
|
</button>
|
|
1002
|
+
{htmlName != null && (
|
|
1003
|
+
<input
|
|
1004
|
+
type="hidden"
|
|
1005
|
+
name={htmlName}
|
|
1006
|
+
value={value ?? ''}
|
|
1007
|
+
// Disabled native controls are excluded from form submission;
|
|
1008
|
+
// mirror that for the hidden carrier.
|
|
1009
|
+
disabled={isDisabled}
|
|
1010
|
+
/>
|
|
1011
|
+
)}
|
|
994
1012
|
{isBusy && <Spinner size="sm" />}
|
|
995
1013
|
{hasClear && value != null && !isDisabled && (
|
|
996
1014
|
<button
|
|
@@ -21,7 +21,7 @@ export const docs = {
|
|
|
21
21
|
targets: [
|
|
22
22
|
{className: 'astryx-side-nav', visualProps: ['mode']},
|
|
23
23
|
{className: 'astryx-side-nav-heading'},
|
|
24
|
-
{className: 'astryx-side-nav-item'},
|
|
24
|
+
{className: 'astryx-side-nav-item', visualProps: ['size'], states: ['selected']},
|
|
25
25
|
{className: 'astryx-side-nav-section'},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
@@ -102,6 +102,12 @@ export const docs = {
|
|
|
102
102
|
description: 'Enables collapse behavior. true for uncontrolled with default toggle button, or an object for controlled mode and advanced config (defaultIsCollapsed, isCollapsed + onCollapsedChange, hasButton, buttonLabel).',
|
|
103
103
|
default: 'false',
|
|
104
104
|
},
|
|
105
|
+
{
|
|
106
|
+
name: 'resizable',
|
|
107
|
+
type: 'boolean | { defaultWidth?: number; minWidth?: number; maxWidth?: number; autoSaveId?: string; onWidthChange?: (width: number) => void }',
|
|
108
|
+
description: 'Enables a resize handle at the inline-end edge. true for defaults (260px initial, 180-480px range), or a ResizableConfig object (defaultWidth, minWidth, maxWidth, autoSaveId for localStorage persistence, onWidthChange). The handle is hidden while collapsed.',
|
|
109
|
+
default: 'false',
|
|
110
|
+
},
|
|
105
111
|
{
|
|
106
112
|
name: 'handleRef',
|
|
107
113
|
type: 'Ref<SideNavImperativeCollapseHandle>',
|
|
@@ -162,6 +162,61 @@ describe('SideNav', () => {
|
|
|
162
162
|
screen.getByRole('button', {name: 'Expand sidebar'}),
|
|
163
163
|
).toBeInTheDocument();
|
|
164
164
|
});
|
|
165
|
+
|
|
166
|
+
it('does not render an empty footer container when collapsible.hasButton is false', () => {
|
|
167
|
+
render(
|
|
168
|
+
<SideNav data-testid="nav" collapsible={{hasButton: false}}>
|
|
169
|
+
Content
|
|
170
|
+
</SideNav>,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// The built-in collapse button is opted out (consumers render their own
|
|
174
|
+
// SideNavCollapseButton in the header), so it must not appear...
|
|
175
|
+
expect(
|
|
176
|
+
screen.queryByRole('button', {name: 'Collapse sidebar'}),
|
|
177
|
+
).not.toBeInTheDocument();
|
|
178
|
+
|
|
179
|
+
// ...and no empty sticky-bottom container should be left behind. With no
|
|
180
|
+
// footer/footerIcons and no built-in button, the scrollable content region
|
|
181
|
+
// is the nav's only child.
|
|
182
|
+
const nav = screen.getByTestId('nav');
|
|
183
|
+
expect(nav.children).toHaveLength(1);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('fires a consumer onClick on the collapse button in addition to toggling', async () => {
|
|
187
|
+
const user = userEvent.setup();
|
|
188
|
+
const onClick = vi.fn();
|
|
189
|
+
|
|
190
|
+
function Example() {
|
|
191
|
+
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
192
|
+
const handleRef = useRef<SideNavImperativeCollapseHandle>(null);
|
|
193
|
+
return (
|
|
194
|
+
<>
|
|
195
|
+
<SideNavCollapseButton handleRef={handleRef} onClick={onClick} />
|
|
196
|
+
<SideNav
|
|
197
|
+
handleRef={handleRef}
|
|
198
|
+
collapsible={{
|
|
199
|
+
isCollapsed,
|
|
200
|
+
onCollapsedChange: setIsCollapsed,
|
|
201
|
+
hasButton: false,
|
|
202
|
+
}}>
|
|
203
|
+
<SideNavSection title="Main">
|
|
204
|
+
<SideNavItem label="Dashboard" icon={StubIcon} />
|
|
205
|
+
</SideNavSection>
|
|
206
|
+
</SideNav>
|
|
207
|
+
</>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
render(<Example />);
|
|
212
|
+
await user.click(screen.getByRole('button', {name: 'Collapse sidebar'}));
|
|
213
|
+
|
|
214
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
215
|
+
// Toggle still ran: the label flipped to "Expand sidebar".
|
|
216
|
+
expect(
|
|
217
|
+
screen.getByRole('button', {name: 'Expand sidebar'}),
|
|
218
|
+
).toBeInTheDocument();
|
|
219
|
+
});
|
|
165
220
|
});
|
|
166
221
|
|
|
167
222
|
// =============================================================================
|
|
@@ -734,6 +789,17 @@ describe('SideNavSection', () => {
|
|
|
734
789
|
const group = screen.getByRole('group');
|
|
735
790
|
expect(group.style.marginTop).toBe('16px');
|
|
736
791
|
});
|
|
792
|
+
|
|
793
|
+
it('forwards arbitrary pass-through attributes (id, aria-*) to root element', () => {
|
|
794
|
+
render(
|
|
795
|
+
<SideNavSection title="Main" id="section-1" aria-describedby="hint">
|
|
796
|
+
<SideNavItem label="Dashboard" />
|
|
797
|
+
</SideNavSection>,
|
|
798
|
+
);
|
|
799
|
+
const group = screen.getByRole('group');
|
|
800
|
+
expect(group).toHaveAttribute('id', 'section-1');
|
|
801
|
+
expect(group).toHaveAttribute('aria-describedby', 'hint');
|
|
802
|
+
});
|
|
737
803
|
});
|
|
738
804
|
|
|
739
805
|
// =============================================================================
|
package/src/SideNav/SideNav.tsx
CHANGED
|
@@ -490,6 +490,10 @@ export function SideNav({
|
|
|
490
490
|
// =========================================================================
|
|
491
491
|
const hasStickyTop = !!(header || topContent);
|
|
492
492
|
const hasStickyBottom = !!(footer || footerIcons);
|
|
493
|
+
// The built-in collapse button only renders when collapse is enabled and it
|
|
494
|
+
// hasn't been opted out via `collapsible.hasButton: false` (e.g. when the
|
|
495
|
+
// consumer places a SideNavCollapseButton in the header instead).
|
|
496
|
+
const showCollapseButton = isCollapsible && hasCollapseButton;
|
|
493
497
|
|
|
494
498
|
// When resizable, override the nav width via inline style
|
|
495
499
|
const resizableNavStyle: React.CSSProperties | undefined = isResizable
|
|
@@ -532,7 +536,7 @@ export function SideNav({
|
|
|
532
536
|
)}>
|
|
533
537
|
{children}
|
|
534
538
|
</div>
|
|
535
|
-
{(hasStickyBottom ||
|
|
539
|
+
{(hasStickyBottom || showCollapseButton) && (
|
|
536
540
|
<div
|
|
537
541
|
{...stylex.props(
|
|
538
542
|
styles.stickyBottom,
|
|
@@ -544,7 +548,7 @@ export function SideNav({
|
|
|
544
548
|
styles.footerRow,
|
|
545
549
|
collapsed && styles.footerRowCollapsed,
|
|
546
550
|
)}>
|
|
547
|
-
{
|
|
551
|
+
{showCollapseButton && <SideNavCollapseButton />}
|
|
548
552
|
{footerIcons}
|
|
549
553
|
</div>
|
|
550
554
|
</div>
|
|
@@ -23,6 +23,7 @@ import {durationVars, easeVars} from '../theme/tokens.stylex';
|
|
|
23
23
|
import {getIcon} from '../Icon/globalIconRegistry';
|
|
24
24
|
import {Button} from '../Button';
|
|
25
25
|
import type {BaseProps} from '../BaseProps';
|
|
26
|
+
import {composeEventHandlers} from '../utils';
|
|
26
27
|
import {
|
|
27
28
|
useSideNavCollapse,
|
|
28
29
|
type SideNavCollapseState,
|
|
@@ -101,6 +102,7 @@ export function SideNavCollapseButton({
|
|
|
101
102
|
handleRef,
|
|
102
103
|
label,
|
|
103
104
|
children,
|
|
105
|
+
onClick: onClickProp,
|
|
104
106
|
...props
|
|
105
107
|
}: SideNavCollapseButtonProps) {
|
|
106
108
|
const {isCollapsed, toggle, isCollapsible} =
|
|
@@ -119,7 +121,7 @@ export function SideNavCollapseButton({
|
|
|
119
121
|
label={label ?? (isCollapsed ? 'Expand sidebar' : 'Collapse sidebar')}
|
|
120
122
|
variant="ghost"
|
|
121
123
|
{...props}
|
|
122
|
-
onClick={toggle}
|
|
124
|
+
onClick={composeEventHandlers(onClickProp, toggle)}
|
|
123
125
|
icon={
|
|
124
126
|
children ?? (
|
|
125
127
|
<span
|
|
@@ -140,8 +142,7 @@ SideNavCollapseButton.displayName = 'SideNavCollapseButton';
|
|
|
140
142
|
|
|
141
143
|
function useSideNavCollapseState(
|
|
142
144
|
handleRef:
|
|
143
|
-
|
|
144
|
-
| undefined,
|
|
145
|
+
React.RefObject<SideNavImperativeCollapseHandle | null> | undefined,
|
|
145
146
|
): SideNavCollapseState {
|
|
146
147
|
const contextCollapseState = useSideNavCollapse();
|
|
147
148
|
|
|
@@ -145,6 +145,7 @@ export function SideNavSection({
|
|
|
145
145
|
className,
|
|
146
146
|
style,
|
|
147
147
|
'data-testid': testId,
|
|
148
|
+
...rest
|
|
148
149
|
}: SideNavSectionProps) {
|
|
149
150
|
const {isCollapsed} = useSideNavCollapse();
|
|
150
151
|
const id = useId();
|
|
@@ -183,15 +184,16 @@ export function SideNavSection({
|
|
|
183
184
|
return (
|
|
184
185
|
<div
|
|
185
186
|
ref={ref}
|
|
186
|
-
role="group"
|
|
187
|
-
aria-labelledby={titleId}
|
|
188
|
-
data-testid={testId}
|
|
189
187
|
{...mergeProps(
|
|
190
188
|
themeProps('side-nav-section'),
|
|
191
189
|
stylex.props(styles.root, xstyle),
|
|
192
190
|
className,
|
|
193
191
|
style,
|
|
194
|
-
)}
|
|
192
|
+
)}
|
|
193
|
+
{...rest}
|
|
194
|
+
role="group"
|
|
195
|
+
aria-labelledby={titleId}
|
|
196
|
+
data-testid={testId}>
|
|
195
197
|
<div
|
|
196
198
|
{...mergeProps(stylex.props(styles.header), {
|
|
197
199
|
style: shouldHideHeader ? visuallyHiddenStyle : undefined,
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file SizeContext.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, SizeContext module
|
|
6
|
+
* @output Characterization tests for SizeContext / useSize / SizeProvider
|
|
7
|
+
* @position Testing; validates the size-cascade resolution contract
|
|
8
|
+
*
|
|
9
|
+
* SYNC: When SizeContext.ts changes, update tests to match new behavior
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {describe, it, expect} from 'vitest';
|
|
13
|
+
import {renderHook, render, screen} from '@testing-library/react';
|
|
14
|
+
import {createElement, type ReactNode} from 'react';
|
|
15
|
+
import {
|
|
16
|
+
SizeContext,
|
|
17
|
+
SizeProvider,
|
|
18
|
+
useSize,
|
|
19
|
+
type ElementSize,
|
|
20
|
+
} from './SizeContext';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Wrap children in a SizeProvider set to `size`. Passing `null` mimics
|
|
24
|
+
* "no container is providing a size".
|
|
25
|
+
*/
|
|
26
|
+
function withProvider(size: ElementSize | null) {
|
|
27
|
+
return function Wrapper({children}: {children: ReactNode}) {
|
|
28
|
+
return <SizeProvider value={size}>{children}</SizeProvider>;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('SizeContext', () => {
|
|
33
|
+
describe('context identity', () => {
|
|
34
|
+
it('defaults to null when read outside any provider', () => {
|
|
35
|
+
const {result} = renderHook(() => useSize());
|
|
36
|
+
// No provider + no prop + no explicit default → the 'md' fallback.
|
|
37
|
+
expect(result.current).toBe('md');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('exposes a displayName for devtools', () => {
|
|
41
|
+
expect(SizeContext.displayName).toBe('SizeContext');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('SizeProvider is the context Provider itself', () => {
|
|
45
|
+
expect(SizeProvider).toBe(SizeContext.Provider);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('useSize — resolution priority', () => {
|
|
50
|
+
it('returns the default "md" with no prop and no provider', () => {
|
|
51
|
+
const {result} = renderHook(() => useSize());
|
|
52
|
+
expect(result.current).toBe('md');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('honors an explicit defaultSize when neither prop nor context is set', () => {
|
|
56
|
+
const {result} = renderHook(() => useSize(undefined, 'lg'));
|
|
57
|
+
expect(result.current).toBe('lg');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('returns the explicit size prop when provided', () => {
|
|
61
|
+
const {result} = renderHook(() => useSize('sm'));
|
|
62
|
+
expect(result.current).toBe('sm');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('prop wins over the explicit default', () => {
|
|
66
|
+
const {result} = renderHook(() => useSize('sm', 'lg'));
|
|
67
|
+
expect(result.current).toBe('sm');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('inherits the size from an enclosing provider when no prop is passed', () => {
|
|
71
|
+
const {result} = renderHook(() => useSize(), {
|
|
72
|
+
wrapper: withProvider('lg'),
|
|
73
|
+
});
|
|
74
|
+
expect(result.current).toBe('lg');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('prop wins over the inherited provider size', () => {
|
|
78
|
+
const {result} = renderHook(() => useSize('sm'), {
|
|
79
|
+
wrapper: withProvider('lg'),
|
|
80
|
+
});
|
|
81
|
+
expect(result.current).toBe('sm');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('inherited context wins over the explicit default fallback', () => {
|
|
85
|
+
const {result} = renderHook(() => useSize(undefined, 'sm'), {
|
|
86
|
+
wrapper: withProvider('lg'),
|
|
87
|
+
});
|
|
88
|
+
expect(result.current).toBe('lg');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('falls back to default when the provider value is explicitly null', () => {
|
|
92
|
+
const {result} = renderHook(() => useSize(undefined, 'sm'), {
|
|
93
|
+
wrapper: withProvider(null),
|
|
94
|
+
});
|
|
95
|
+
expect(result.current).toBe('sm');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('falls back to "md" when provider is null and no default is given', () => {
|
|
99
|
+
const {result} = renderHook(() => useSize(), {
|
|
100
|
+
wrapper: withProvider(null),
|
|
101
|
+
});
|
|
102
|
+
expect(result.current).toBe('md');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('useSize — every standard ElementSize resolves', () => {
|
|
107
|
+
const sizes: ElementSize[] = ['sm', 'md', 'lg'];
|
|
108
|
+
|
|
109
|
+
it.each(sizes)('resolves explicit prop "%s"', size => {
|
|
110
|
+
const {result} = renderHook(() => useSize(size));
|
|
111
|
+
expect(result.current).toBe(size);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it.each(sizes)('resolves inherited provider "%s"', size => {
|
|
115
|
+
const {result} = renderHook(() => useSize(), {
|
|
116
|
+
wrapper: withProvider(size),
|
|
117
|
+
});
|
|
118
|
+
expect(result.current).toBe(size);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('useSize — nested providers', () => {
|
|
123
|
+
it('resolves to the nearest provider', () => {
|
|
124
|
+
function Nested({children}: {children: ReactNode}) {
|
|
125
|
+
return (
|
|
126
|
+
<SizeProvider value="sm">
|
|
127
|
+
<SizeProvider value="lg">{children}</SizeProvider>
|
|
128
|
+
</SizeProvider>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
const {result} = renderHook(() => useSize(), {wrapper: Nested});
|
|
132
|
+
expect(result.current).toBe('lg');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('a prop still overrides the nearest provider', () => {
|
|
136
|
+
function Nested({children}: {children: ReactNode}) {
|
|
137
|
+
return (
|
|
138
|
+
<SizeProvider value="sm">
|
|
139
|
+
<SizeProvider value="lg">{children}</SizeProvider>
|
|
140
|
+
</SizeProvider>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const {result} = renderHook(() => useSize('md'), {wrapper: Nested});
|
|
144
|
+
expect(result.current).toBe('md');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('useSize — generic (non-ElementSize) values', () => {
|
|
149
|
+
it('supports a custom string union via the type parameter', () => {
|
|
150
|
+
type Custom = 'compact' | 'comfortable';
|
|
151
|
+
const {result} = renderHook(() =>
|
|
152
|
+
useSize<Custom>('compact', 'comfortable'),
|
|
153
|
+
);
|
|
154
|
+
expect(result.current).toBe('compact');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('returns the custom default when no prop is given', () => {
|
|
158
|
+
type Custom = 'compact' | 'comfortable';
|
|
159
|
+
const {result} = renderHook(() =>
|
|
160
|
+
useSize<Custom>(undefined, 'comfortable'),
|
|
161
|
+
);
|
|
162
|
+
expect(result.current).toBe('comfortable');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('empty-string prop is a real value and does NOT fall through to default', () => {
|
|
166
|
+
// '' ?? x === '' because nullish coalescing only catches null/undefined.
|
|
167
|
+
const {result} = renderHook(() => useSize('' as ElementSize, 'lg'));
|
|
168
|
+
expect(result.current).toBe('');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('integration — components consuming the cascade', () => {
|
|
173
|
+
function SizedProbe({size}: {size?: ElementSize}) {
|
|
174
|
+
const resolved = useSize(size);
|
|
175
|
+
return <span data-testid="probe">{resolved}</span>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
it('a child with no size prop reads the container size', () => {
|
|
179
|
+
render(
|
|
180
|
+
<SizeProvider value="lg">
|
|
181
|
+
<SizedProbe />
|
|
182
|
+
</SizeProvider>,
|
|
183
|
+
);
|
|
184
|
+
expect(screen.getByTestId('probe')).toHaveTextContent('lg');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('sibling children resolve independently against the same provider', () => {
|
|
188
|
+
render(
|
|
189
|
+
<SizeProvider value="lg">
|
|
190
|
+
<span data-testid="a">
|
|
191
|
+
<SizedProbe />
|
|
192
|
+
</span>
|
|
193
|
+
<span data-testid="b">
|
|
194
|
+
<SizedProbe size="sm" />
|
|
195
|
+
</span>
|
|
196
|
+
</SizeProvider>,
|
|
197
|
+
);
|
|
198
|
+
expect(screen.getByTestId('a')).toHaveTextContent('lg');
|
|
199
|
+
expect(screen.getByTestId('b')).toHaveTextContent('sm');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('re-renders with the new size when the provider value changes', () => {
|
|
203
|
+
const {rerender} = render(
|
|
204
|
+
<SizeProvider value="sm">
|
|
205
|
+
<SizedProbe />
|
|
206
|
+
</SizeProvider>,
|
|
207
|
+
);
|
|
208
|
+
expect(screen.getByTestId('probe')).toHaveTextContent('sm');
|
|
209
|
+
|
|
210
|
+
rerender(
|
|
211
|
+
<SizeProvider value="lg">
|
|
212
|
+
<SizedProbe />
|
|
213
|
+
</SizeProvider>,
|
|
214
|
+
);
|
|
215
|
+
expect(screen.getByTestId('probe')).toHaveTextContent('lg');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('works with createElement (no JSX) call form', () => {
|
|
219
|
+
const {result} = renderHook(() => useSize(), {
|
|
220
|
+
wrapper: ({children}: {children: ReactNode}) =>
|
|
221
|
+
createElement(SizeProvider, {value: 'sm'}, children),
|
|
222
|
+
});
|
|
223
|
+
expect(result.current).toBe('sm');
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
});
|
|
@@ -95,11 +95,17 @@ export const docs = {
|
|
|
95
95
|
description: 'Whether the slider is disabled.',
|
|
96
96
|
default: 'false',
|
|
97
97
|
},
|
|
98
|
+
{
|
|
99
|
+
name: 'htmlName',
|
|
100
|
+
type: 'string',
|
|
101
|
+
description:
|
|
102
|
+
'The HTML name attribute for form submissions. Renders hidden inputs carrying the current value (two entries in range mode).',
|
|
103
|
+
},
|
|
98
104
|
{
|
|
99
105
|
name: 'disabledMessage',
|
|
100
106
|
type: 'string',
|
|
101
107
|
description:
|
|
102
|
-
'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip
|
|
108
|
+
'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
103
109
|
},
|
|
104
110
|
{
|
|
105
111
|
name: 'isOptional',
|
|
@@ -244,11 +250,16 @@ export const docsZh = {
|
|
|
244
250
|
description: '是否禁用滑块。',
|
|
245
251
|
default: 'false',
|
|
246
252
|
},
|
|
253
|
+
{
|
|
254
|
+
name: 'htmlName',
|
|
255
|
+
type: 'string',
|
|
256
|
+
description: '用于表单提交的 HTML name 属性。渲染携带当前值的隐藏输入(范围模式下为两个条目)。',
|
|
257
|
+
},
|
|
247
258
|
{
|
|
248
259
|
name: 'disabledMessage',
|
|
249
260
|
type: 'string',
|
|
250
261
|
description:
|
|
251
|
-
'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip
|
|
262
|
+
'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
252
263
|
},
|
|
253
264
|
{
|
|
254
265
|
name: 'isOptional',
|
|
@@ -338,6 +349,7 @@ export const docsDense = {
|
|
|
338
349
|
marks: 'Tick marks at specified positions w/ optional labels.',
|
|
339
350
|
minStepsBetweenThumbs: 'Min steps between thumbs in range mode; prevents overlap.',
|
|
340
351
|
isDisabled: 'Whether slider is disabled.',
|
|
352
|
+
htmlName: 'HTML name attr; hidden inputs carry the value (two in range mode).',
|
|
341
353
|
isOptional: 'Whether field is optional.',
|
|
342
354
|
isRequired: 'Whether field is required.',
|
|
343
355
|
isLabelHidden: 'Visually hide label.',
|
|
@@ -535,4 +535,34 @@ describe('Slider', () => {
|
|
|
535
535
|
expect(screen.getByRole('slider')).toHaveAttribute('tabindex', '-1');
|
|
536
536
|
});
|
|
537
537
|
});
|
|
538
|
+
describe('form participation', () => {
|
|
539
|
+
it('submits the value under htmlName', () => {
|
|
540
|
+
const {container} = render(
|
|
541
|
+
<form>
|
|
542
|
+
<Slider label="Volume" htmlName="volume" value={50} />
|
|
543
|
+
</form>,
|
|
544
|
+
);
|
|
545
|
+
const data = new FormData(container.querySelector('form')!);
|
|
546
|
+
expect(data.get('volume')).toBe('50');
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('submits both range values under the same name', () => {
|
|
550
|
+
const {container} = render(
|
|
551
|
+
<form>
|
|
552
|
+
<Slider label="Price" htmlName="price" value={[20, 80] as [number, number]} />
|
|
553
|
+
</form>,
|
|
554
|
+
);
|
|
555
|
+
const data = new FormData(container.querySelector('form')!);
|
|
556
|
+
expect(data.getAll('price')).toEqual(['20', '80']);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('is excluded from form data when disabled', () => {
|
|
560
|
+
const {container} = render(
|
|
561
|
+
<form>
|
|
562
|
+
<Slider label="Volume" htmlName="volume" value={50} isDisabled />
|
|
563
|
+
</form>,
|
|
564
|
+
);
|
|
565
|
+
expect([...new FormData(container.querySelector('form')!).keys()]).toEqual([]);
|
|
566
|
+
});
|
|
567
|
+
});
|
|
538
568
|
});
|
package/src/Slider/Slider.tsx
CHANGED
|
@@ -111,6 +111,12 @@ export interface SliderBaseProps extends Omit<
|
|
|
111
111
|
valueDisplay?: 'tooltip' | 'text' | 'none';
|
|
112
112
|
/** Tick marks at specified positions with optional labels. */
|
|
113
113
|
marks?: {value: number; label?: string}[];
|
|
114
|
+
/**
|
|
115
|
+
* The HTML name attribute for form submissions. When set, the slider
|
|
116
|
+
* renders hidden inputs carrying the current value (two in range mode,
|
|
117
|
+
* matching how paired native range inputs submit).
|
|
118
|
+
*/
|
|
119
|
+
htmlName?: string;
|
|
114
120
|
/** Test ID for the root element. */
|
|
115
121
|
'data-testid'?: string;
|
|
116
122
|
}
|
|
@@ -363,6 +369,7 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
363
369
|
step = 1,
|
|
364
370
|
orientation = 'horizontal',
|
|
365
371
|
formatValue,
|
|
372
|
+
htmlName,
|
|
366
373
|
valueDisplay = 'tooltip',
|
|
367
374
|
marks,
|
|
368
375
|
width,
|
|
@@ -803,6 +810,19 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
803
810
|
}),
|
|
804
811
|
stylex.props(styles.sliderRow),
|
|
805
812
|
)}>
|
|
813
|
+
{htmlName != null &&
|
|
814
|
+
values.map((v, i) => (
|
|
815
|
+
<input
|
|
816
|
+
// Positional identity: index 0 is the start thumb, 1 the end.
|
|
817
|
+
key={i === 0 ? 'start' : 'end'}
|
|
818
|
+
type="hidden"
|
|
819
|
+
name={htmlName}
|
|
820
|
+
value={String(v)}
|
|
821
|
+
// Disabled native controls are excluded from form submission;
|
|
822
|
+
// mirror that for the hidden carrier.
|
|
823
|
+
disabled={isDisabled}
|
|
824
|
+
/>
|
|
825
|
+
))}
|
|
806
826
|
<div
|
|
807
827
|
ref={mergeRefs(ref, trackRef, disabledMessageTooltip.ref)}
|
|
808
828
|
{...(isRange ? {role: 'group', 'aria-label': label} : undefined)}
|
package/src/Spinner/Spinner.tsx
CHANGED
|
@@ -70,6 +70,7 @@ const styles = stylex.create({
|
|
|
70
70
|
canvas: {
|
|
71
71
|
backfaceVisibility: 'hidden',
|
|
72
72
|
display: 'block',
|
|
73
|
+
willChange: 'transform',
|
|
73
74
|
// Slow the rotation dramatically under reduced-motion rather than freezing
|
|
74
75
|
// it (a frozen spinner reads as broken), matching ProgressBar's approach.
|
|
75
76
|
// The role="status" + "Loading" label still convey busy state (obs-6).
|