@astryxdesign/core 0.1.9-canary.d2d84f8 → 0.1.9-canary.e00a241
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Avatar/Avatar.d.ts +6 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +46 -12
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
- package/dist/Breadcrumbs/index.d.ts +1 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +2 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +50 -9
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +2 -2
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.js +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +22 -12
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +8 -8
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +10 -3
- package/dist/CheckboxInput/CheckboxInput.js +4 -4
- package/dist/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +13 -7
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +42 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +1 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +31 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +20 -19
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -18
- package/dist/Divider/Divider.d.ts +2 -2
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +13 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -1
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +4 -1
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/FileInput/FileInput.d.ts +1 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +91 -65
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +10 -4
- package/dist/Icon/Icon.d.ts +15 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +15 -9
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +65 -40
- package/dist/NumberInput/NumberInput.d.ts +1 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +20 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +49 -19
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +58 -16
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +87 -34
- package/dist/Spinner/Spinner.d.ts +3 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +11 -2
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/TabList.d.ts +2 -11
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +5 -9
- package/dist/TabList/TabListContext.d.ts +0 -5
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +0 -5
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +14 -6
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +1 -0
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -19
- package/dist/TextInput/TextInput.d.ts +1 -0
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +18 -17
- package/dist/TimeInput/TimeInput.d.ts +1 -0
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -17
- package/dist/Timestamp/Timestamp.d.ts +31 -3
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +47 -76
- package/dist/Timestamp/formatInstant.d.ts +41 -0
- package/dist/Timestamp/formatInstant.d.ts.map +1 -0
- package/dist/Timestamp/formatInstant.js +177 -0
- package/dist/Timestamp/index.d.ts +1 -0
- package/dist/Timestamp/index.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.d.ts +56 -0
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
- package/dist/Timestamp/tooltipEntries.js +163 -0
- package/dist/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavItem.d.ts +3 -1
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +30 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +1 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +8 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +32 -14
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +19 -10
- package/dist/Typeahead/Typeahead.js +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +38 -14
- package/dist/astryx.umd.js +52 -52
- package/dist/astryx.umd.js.map +4 -4
- 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/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useAnnounce.d.ts +3 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +39 -1
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +52 -11
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useHotkeys.d.ts +9 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +9 -0
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/plainDate.d.ts +17 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +23 -4
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/locales/en.json +76 -0
- package/locales/pseudo.json +57 -0
- package/package.json +6 -1
- package/src/Avatar/Avatar.doc.mjs +18 -4
- package/src/Avatar/Avatar.test.tsx +106 -0
- package/src/Avatar/Avatar.tsx +62 -10
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.test.tsx +16 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +51 -0
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Calendar/Calendar.test.tsx +170 -20
- package/src/Calendar/Calendar.tsx +73 -16
- package/src/Calendar/dayCellUtils.test.ts +18 -18
- package/src/Calendar/dayCellUtils.ts +2 -2
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.tsx +1 -1
- package/src/Carousel/Carousel.tsx +25 -6
- package/src/Chat/ChatComposer.doc.mjs +2 -2
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -4
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- package/src/CodeBlock/CodeBlock.tsx +35 -8
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +41 -2
- package/src/ContextMenu/ContextMenu.test.tsx +42 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +15 -5
- package/src/DateInput/DateInput.test.tsx +210 -3
- package/src/DateInput/DateInput.tsx +41 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +11 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +120 -3
- package/src/DateRangeInput/DateRangeInput.tsx +29 -27
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
- package/src/DateTimeInput/DateTimeInput.tsx +44 -39
- package/src/Divider/Divider.test.tsx +32 -8
- package/src/Divider/Divider.tsx +14 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.tsx +14 -9
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.tsx +10 -4
- package/src/FileInput/FileInput.doc.mjs +13 -7
- package/src/FileInput/FileInput.test.tsx +84 -16
- package/src/FileInput/FileInput.tsx +96 -79
- package/src/HoverCard/useHoverCard.tsx +15 -3
- package/src/Icon/Icon.doc.mjs +13 -0
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +51 -3
- package/src/Lightbox/Lightbox.tsx +11 -3
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +11 -0
- package/src/MultiSelector/MultiSelector.test.tsx +306 -3
- package/src/MultiSelector/MultiSelector.tsx +88 -57
- package/src/NumberInput/NumberInput.doc.mjs +11 -5
- package/src/NumberInput/NumberInput.test.tsx +48 -0
- package/src/NumberInput/NumberInput.tsx +25 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/Selector/Selector.doc.mjs +8 -0
- package/src/Selector/Selector.test.tsx +328 -3
- package/src/Selector/Selector.tsx +70 -19
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +240 -12
- package/src/Slider/Slider.tsx +96 -23
- package/src/Spinner/Spinner.test.tsx +10 -8
- package/src/Spinner/Spinner.tsx +15 -5
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +22 -0
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/TabList.doc.mjs +0 -6
- package/src/TabList/TabList.test.tsx +3 -15
- package/src/TabList/TabList.tsx +6 -17
- package/src/TabList/TabListContext.ts +0 -6
- package/src/Table/BaseTable.tsx +34 -2
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +37 -8
- package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
- package/src/Table/types.ts +33 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/TextArea/TextArea.doc.mjs +11 -5
- package/src/TextArea/TextArea.tsx +17 -26
- package/src/TextInput/TextInput.doc.mjs +11 -5
- package/src/TextInput/TextInput.test.tsx +130 -3
- package/src/TextInput/TextInput.tsx +18 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +11 -5
- package/src/TimeInput/TimeInput.tsx +14 -25
- package/src/Timestamp/Timestamp.doc.mjs +32 -6
- package/src/Timestamp/Timestamp.test.tsx +371 -0
- package/src/Timestamp/Timestamp.tsx +96 -93
- package/src/Timestamp/formatInstant.ts +218 -0
- package/src/Timestamp/index.ts +4 -0
- package/src/Timestamp/tooltipEntries.test.ts +552 -0
- package/src/Timestamp/tooltipEntries.ts +210 -0
- package/src/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +8 -1
- package/src/Tokenizer/Tokenizer.tsx +4 -2
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +93 -2
- package/src/TopNav/TopNavItem.doc.mjs +3 -3
- package/src/TopNav/TopNavItem.tsx +35 -6
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
- package/src/TreeList/TreeList.doc.mjs +6 -0
- package/src/TreeList/TreeList.test.tsx +50 -10
- package/src/TreeList/TreeList.tsx +5 -0
- package/src/TreeList/TreeListBranches.tsx +8 -6
- package/src/TreeList/TreeListItem.tsx +33 -11
- package/src/Typeahead/BaseTypeahead.tsx +29 -14
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.test.tsx +27 -0
- package/src/Typeahead/Typeahead.tsx +1 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/doc-mjs.d.ts +19 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useAnnounce.test.tsx +75 -2
- package/src/hooks/useAnnounce.ts +47 -1
- package/src/hooks/useFocusTrap.test.tsx +104 -0
- package/src/hooks/useFocusTrap.ts +61 -12
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useHotkeys.ts +9 -0
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +42 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +24 -6
- package/src/utils/plainDate.ts +18 -4
- package/src/utils/rtlStyles.ts +27 -0
|
@@ -570,6 +570,21 @@ export interface MultiSelectorProps<
|
|
|
570
570
|
'data-testid'?: string;
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
+
// Case-insensitive substring match for a single option. The one predicate used
|
|
574
|
+
// by both the flat filter (count + keyboard nav) and the grouped renderer, so
|
|
575
|
+
// what is shown while searching stays in lockstep with the announced count.
|
|
576
|
+
function optionMatchesQuery(
|
|
577
|
+
option: MultiSelectorOptionData,
|
|
578
|
+
query: string,
|
|
579
|
+
): boolean {
|
|
580
|
+
if (!query) {
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
return (option.label ?? option.value)
|
|
584
|
+
.toLowerCase()
|
|
585
|
+
.includes(query.toLowerCase());
|
|
586
|
+
}
|
|
587
|
+
|
|
573
588
|
// Case-insensitive substring filter over the selectable options. Shared by the
|
|
574
589
|
// `filteredItems` memo (rendering) and the search-change handler, which needs
|
|
575
590
|
// the count for the *next* query synchronously to announce it exactly once per
|
|
@@ -581,10 +596,7 @@ function filterOptionsByQuery(
|
|
|
581
596
|
if (!query) {
|
|
582
597
|
return items;
|
|
583
598
|
}
|
|
584
|
-
|
|
585
|
-
return items.filter(item =>
|
|
586
|
-
(item.label ?? item.value).toLowerCase().includes(q),
|
|
587
|
-
);
|
|
599
|
+
return items.filter(item => optionMatchesQuery(item, query));
|
|
588
600
|
}
|
|
589
601
|
|
|
590
602
|
/**
|
|
@@ -725,35 +737,25 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
725
737
|
|
|
726
738
|
// Single source of truth for item order. Both the hook (keyboard navigation)
|
|
727
739
|
// and renderOptions (DOM rendering) consume this list — no independent sorting.
|
|
728
|
-
// Selected-at-open items are placed first within each group/section
|
|
740
|
+
// Selected-at-open items are placed first within each group/section, and the
|
|
741
|
+
// same walk applies while searching so group structure survives filtering
|
|
742
|
+
// (only matching items are kept; the query is empty in non-search mode).
|
|
729
743
|
const sortedItems = useMemo(() => {
|
|
730
744
|
const selectedSet = selectedAtOpen ?? new Set<string>();
|
|
731
|
-
if (searchQuery) {
|
|
732
|
-
const selected = filteredItems.filter(item =>
|
|
733
|
-
selectedSet.has(item.value),
|
|
734
|
-
);
|
|
735
|
-
const unselected = filteredItems.filter(
|
|
736
|
-
item => !selectedSet.has(item.value),
|
|
737
|
-
);
|
|
738
|
-
const items = [...selected, ...unselected];
|
|
739
|
-
if (hasSelectAll) {
|
|
740
|
-
return [{value: SELECT_ALL_VALUE, label: selectAllLabel}, ...items];
|
|
741
|
-
}
|
|
742
|
-
return items;
|
|
743
|
-
}
|
|
744
|
-
// For non-search mode, flatten options in the same order as renderOptions
|
|
745
745
|
const result: MultiSelectorOptionData[] = [];
|
|
746
746
|
let pendingFlat: MultiSelectorOptionData[] = [];
|
|
747
747
|
|
|
748
|
+
const orderSelectedFirst = (items: MultiSelectorOptionData[]) => {
|
|
749
|
+
const selected = items.filter(item => selectedSet.has(item.value));
|
|
750
|
+
const unselected = items.filter(item => !selectedSet.has(item.value));
|
|
751
|
+
return [...selected, ...unselected];
|
|
752
|
+
};
|
|
753
|
+
|
|
748
754
|
const flushFlat = () => {
|
|
749
755
|
if (pendingFlat.length === 0) {
|
|
750
756
|
return;
|
|
751
757
|
}
|
|
752
|
-
|
|
753
|
-
const unselected = pendingFlat.filter(
|
|
754
|
-
item => !selectedSet.has(item.value),
|
|
755
|
-
);
|
|
756
|
-
result.push(...selected, ...unselected);
|
|
758
|
+
result.push(...orderSelectedFirst(pendingFlat));
|
|
757
759
|
pendingFlat = [];
|
|
758
760
|
};
|
|
759
761
|
|
|
@@ -762,16 +764,15 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
762
764
|
flushFlat();
|
|
763
765
|
} else if (isSection(option)) {
|
|
764
766
|
flushFlat();
|
|
765
|
-
const sectionOptions = option.options
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
);
|
|
769
|
-
const unselected = sectionOptions.filter(
|
|
770
|
-
item => !selectedSet.has(item.value),
|
|
771
|
-
);
|
|
772
|
-
result.push(...selected, ...unselected);
|
|
767
|
+
const sectionOptions = option.options
|
|
768
|
+
.map(opt => normalizeOption(opt))
|
|
769
|
+
.filter(opt => optionMatchesQuery(opt, searchQuery));
|
|
770
|
+
result.push(...orderSelectedFirst(sectionOptions));
|
|
773
771
|
} else if (isOptionData(option)) {
|
|
774
|
-
|
|
772
|
+
const normalized = normalizeOption(option);
|
|
773
|
+
if (optionMatchesQuery(normalized, searchQuery)) {
|
|
774
|
+
pendingFlat.push(normalized);
|
|
775
|
+
}
|
|
775
776
|
}
|
|
776
777
|
}
|
|
777
778
|
flushFlat();
|
|
@@ -780,14 +781,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
780
781
|
return [{value: SELECT_ALL_VALUE, label: selectAllLabel}, ...result];
|
|
781
782
|
}
|
|
782
783
|
return result;
|
|
783
|
-
}, [
|
|
784
|
-
filteredItems,
|
|
785
|
-
searchQuery,
|
|
786
|
-
options,
|
|
787
|
-
selectedAtOpen,
|
|
788
|
-
hasSelectAll,
|
|
789
|
-
selectAllLabel,
|
|
790
|
-
]);
|
|
784
|
+
}, [searchQuery, options, selectedAtOpen, hasSelectAll, selectAllLabel]);
|
|
791
785
|
|
|
792
786
|
// Layer for dropdown positioning
|
|
793
787
|
const handleLayerHide = useCallback(() => {
|
|
@@ -1227,15 +1221,12 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1227
1221
|
return elements;
|
|
1228
1222
|
}
|
|
1229
1223
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
// Non-search: consume items from sortedItems in order, interleaving
|
|
1238
|
-
// structural elements (dividers, section headers) from the options prop.
|
|
1224
|
+
// Consume items from sortedItems in order, interleaving structural elements
|
|
1225
|
+
// (dividers, section headers) from the options prop. While searching, only
|
|
1226
|
+
// matching items are present in sortedItems, so a section consumes just its
|
|
1227
|
+
// matches and is skipped entirely when none match — no header left standing
|
|
1228
|
+
// over nothing, and the cursor stays aligned with the combobox indices.
|
|
1229
|
+
const isSearching = Boolean(searchQuery);
|
|
1239
1230
|
let pendingCount = 0;
|
|
1240
1231
|
|
|
1241
1232
|
const flushPending = () => {
|
|
@@ -1251,12 +1242,25 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1251
1242
|
|
|
1252
1243
|
if (isDivider(option)) {
|
|
1253
1244
|
flushPending();
|
|
1254
|
-
|
|
1245
|
+
// A standalone divider between groups would orphan itself once its
|
|
1246
|
+
// neighbors are filtered out, so skip it while searching.
|
|
1247
|
+
if (!isSearching) {
|
|
1248
|
+
elements.push(
|
|
1249
|
+
<Divider key={`divider-${i}`} xstyle={styles.divider} />,
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1255
1252
|
} else if (isSection(option)) {
|
|
1256
1253
|
flushPending();
|
|
1257
|
-
const
|
|
1254
|
+
const matchCount = isSearching
|
|
1255
|
+
? option.options.filter(opt =>
|
|
1256
|
+
optionMatchesQuery(normalizeOption(opt), searchQuery),
|
|
1257
|
+
).length
|
|
1258
|
+
: option.options.length;
|
|
1259
|
+
if (matchCount === 0) {
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1258
1262
|
const sectionItems: ReactNode[] = [];
|
|
1259
|
-
for (let j = 0; j <
|
|
1263
|
+
for (let j = 0; j < matchCount; j++) {
|
|
1260
1264
|
sectionItems.push(renderItem(sortedItems[cursor], cursor));
|
|
1261
1265
|
cursor++;
|
|
1262
1266
|
}
|
|
@@ -1275,7 +1279,12 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1275
1279
|
</div>,
|
|
1276
1280
|
);
|
|
1277
1281
|
} else if (isOptionData(option)) {
|
|
1278
|
-
|
|
1282
|
+
if (
|
|
1283
|
+
!isSearching ||
|
|
1284
|
+
optionMatchesQuery(normalizeOption(option), searchQuery)
|
|
1285
|
+
) {
|
|
1286
|
+
pendingCount++;
|
|
1287
|
+
}
|
|
1279
1288
|
}
|
|
1280
1289
|
}
|
|
1281
1290
|
flushPending();
|
|
@@ -1304,7 +1313,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1304
1313
|
isDisabled && inputWrapperStyles.disabled,
|
|
1305
1314
|
optimisticValue.length === 0 && styles.triggerPlaceholder,
|
|
1306
1315
|
status && inputStatusBorderStyles[status.type],
|
|
1307
|
-
status && inputStatusHoverShadowStyles[status.type],
|
|
1316
|
+
status && !isDisabled && inputStatusHoverShadowStyles[status.type],
|
|
1308
1317
|
inputGroup && groupStyles.inGroup,
|
|
1309
1318
|
xstyle,
|
|
1310
1319
|
),
|
|
@@ -1368,7 +1377,17 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1368
1377
|
onClick={handleClear}
|
|
1369
1378
|
aria-label={t('@astryx.multiSelector.clearAll', {label})}
|
|
1370
1379
|
{...stylex.props(styles.clearButton)}>
|
|
1371
|
-
<Icon
|
|
1380
|
+
<Icon
|
|
1381
|
+
icon="close"
|
|
1382
|
+
size="sm"
|
|
1383
|
+
color="secondary"
|
|
1384
|
+
// Stable theme target on the clear glyph itself, so a theme can
|
|
1385
|
+
// restyle just this icon (color, size, hover) via `defineTheme`.
|
|
1386
|
+
// Same-element rules in @layer astryx-theme win over the icon's
|
|
1387
|
+
// own base color/size, which a button-level target could not
|
|
1388
|
+
// reach.
|
|
1389
|
+
{...themeProps('multi-selector-clear-icon')}
|
|
1390
|
+
/>
|
|
1372
1391
|
</button>
|
|
1373
1392
|
)}
|
|
1374
1393
|
<span
|
|
@@ -1384,7 +1403,19 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1384
1403
|
color={STATUS_ICON_COLOR_MAP[status.type]}
|
|
1385
1404
|
/>
|
|
1386
1405
|
) : (
|
|
1387
|
-
<Icon
|
|
1406
|
+
<Icon
|
|
1407
|
+
icon="chevronDown"
|
|
1408
|
+
size="sm"
|
|
1409
|
+
color="inherit"
|
|
1410
|
+
// Stable theme target on the chevron glyph itself, so a theme can
|
|
1411
|
+
// restyle just this icon (color, size, hover) — and its
|
|
1412
|
+
// open/closed state — via `defineTheme`. Same-element rules in
|
|
1413
|
+
// @layer astryx-theme win over the icon's own base color/size,
|
|
1414
|
+
// which a button-level target could not reach.
|
|
1415
|
+
{...themeProps('multi-selector-indicator-icon', {
|
|
1416
|
+
state: popover.isOpen ? 'expanded' : 'collapsed',
|
|
1417
|
+
})}
|
|
1418
|
+
/>
|
|
1388
1419
|
)}
|
|
1389
1420
|
</span>
|
|
1390
1421
|
</div>
|
|
@@ -96,9 +96,9 @@ export const docs = {
|
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
name: 'statusVariant',
|
|
99
|
-
type: "'attached' | 'detached'",
|
|
99
|
+
type: "'attached' | 'detached' | 'tooltip'",
|
|
100
100
|
description:
|
|
101
|
-
'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing.',
|
|
101
|
+
'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing; tooltip hides the message box and surfaces it in a tooltip on the status icon.',
|
|
102
102
|
default: "'attached'",
|
|
103
103
|
},
|
|
104
104
|
{
|
|
@@ -145,6 +145,12 @@ export const docs = {
|
|
|
145
145
|
type: 'string',
|
|
146
146
|
description: 'HTML autocomplete attribute.',
|
|
147
147
|
},
|
|
148
|
+
{
|
|
149
|
+
name: 'width',
|
|
150
|
+
type: 'SizeValue',
|
|
151
|
+
description:
|
|
152
|
+
'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
|
|
153
|
+
},
|
|
148
154
|
{
|
|
149
155
|
name: 'hasAutoFocus',
|
|
150
156
|
type: 'boolean',
|
|
@@ -284,9 +290,9 @@ export const docsZh = {
|
|
|
284
290
|
},
|
|
285
291
|
{
|
|
286
292
|
name: 'statusVariant',
|
|
287
|
-
type: "'attached' | 'detached'",
|
|
293
|
+
type: "'attached' | 'detached' | 'tooltip'",
|
|
288
294
|
description:
|
|
289
|
-
'状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached
|
|
295
|
+
'状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached 作为独立元素浮于下方并留有间距;tooltip 隐藏消息框,并在状态图标上以提示气泡形式显示。',
|
|
290
296
|
default: "'attached'",
|
|
291
297
|
},
|
|
292
298
|
{
|
|
@@ -416,7 +422,7 @@ export const docsDense = {
|
|
|
416
422
|
startIcon: 'Icon at input start.',
|
|
417
423
|
labelIcon: 'Icon before label text.',
|
|
418
424
|
status: 'Validation status w/ optional message.',
|
|
419
|
-
statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing.',
|
|
425
|
+
statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing; tooltip hides the box and shows it on the status icon.',
|
|
420
426
|
min: 'Minimum value allowed.',
|
|
421
427
|
max: 'Maximum value allowed.',
|
|
422
428
|
step: 'Step increment.',
|
|
@@ -13,6 +13,7 @@ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
|
13
13
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {TestIcon} from '../__tests__/TestIcon';
|
|
16
|
+
import {InputGroup} from '../InputGroup';
|
|
16
17
|
import {NumberInput} from './NumberInput';
|
|
17
18
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
18
19
|
|
|
@@ -336,6 +337,33 @@ describe('NumberInput', () => {
|
|
|
336
337
|
expect(screen.queryByText('%')).not.toBeInTheDocument();
|
|
337
338
|
expect(screen.queryByText('GB')).not.toBeInTheDocument();
|
|
338
339
|
});
|
|
340
|
+
|
|
341
|
+
it('includes the units text in the accessible description (WCAG 1.3.1)', () => {
|
|
342
|
+
render(
|
|
343
|
+
<NumberInput
|
|
344
|
+
label="Storage"
|
|
345
|
+
value={50}
|
|
346
|
+
onChange={() => {}}
|
|
347
|
+
units="GB"
|
|
348
|
+
/>,
|
|
349
|
+
);
|
|
350
|
+
expect(screen.getByRole('spinbutton')).toHaveAccessibleDescription(/GB/);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('combines units with the description in the accessible description', () => {
|
|
354
|
+
render(
|
|
355
|
+
<NumberInput
|
|
356
|
+
label="Discount"
|
|
357
|
+
value={10}
|
|
358
|
+
onChange={() => {}}
|
|
359
|
+
description="Applied at checkout"
|
|
360
|
+
units="%"
|
|
361
|
+
/>,
|
|
362
|
+
);
|
|
363
|
+
const input = screen.getByRole('spinbutton');
|
|
364
|
+
expect(input).toHaveAccessibleDescription(/Applied at checkout/);
|
|
365
|
+
expect(input).toHaveAccessibleDescription(/%/);
|
|
366
|
+
});
|
|
339
367
|
});
|
|
340
368
|
|
|
341
369
|
describe('event callbacks', () => {
|
|
@@ -463,6 +491,26 @@ describe('NumberInput', () => {
|
|
|
463
491
|
expect(screen.getByText('Value must be positive')).toBeInTheDocument();
|
|
464
492
|
});
|
|
465
493
|
|
|
494
|
+
it('has no dangling aria-describedby ids inside InputGroup (WCAG 1.3.1)', () => {
|
|
495
|
+
// Inside an InputGroup no Field renders, so the status message element
|
|
496
|
+
// does not exist; aria-describedby must not reference its id.
|
|
497
|
+
render(
|
|
498
|
+
<InputGroup label="Price">
|
|
499
|
+
<NumberInput
|
|
500
|
+
label="Amount"
|
|
501
|
+
value={null}
|
|
502
|
+
onChange={() => {}}
|
|
503
|
+
status={{type: 'error', message: 'Value must be positive'}}
|
|
504
|
+
/>
|
|
505
|
+
</InputGroup>,
|
|
506
|
+
);
|
|
507
|
+
const input = screen.getByRole('spinbutton');
|
|
508
|
+
const describedBy = input.getAttribute('aria-describedby') ?? '';
|
|
509
|
+
for (const idToken of describedBy.split(/\s+/).filter(Boolean)) {
|
|
510
|
+
expect(document.getElementById(idToken)).not.toBeNull();
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
466
514
|
it('does not render status message when not provided', () => {
|
|
467
515
|
render(
|
|
468
516
|
<NumberInput
|
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
type ReactNode,
|
|
28
28
|
} from 'react';
|
|
29
29
|
import * as stylex from '@stylexjs/stylex';
|
|
30
|
-
import type {IconName} from '../Icon';
|
|
31
30
|
import {
|
|
32
31
|
colorVars,
|
|
33
32
|
sizeVars,
|
|
@@ -39,7 +38,6 @@ import {
|
|
|
39
38
|
import {
|
|
40
39
|
Field,
|
|
41
40
|
type InputStatus,
|
|
42
|
-
type InputStatusType,
|
|
43
41
|
inputWrapperStyles,
|
|
44
42
|
inputStatusBorderStyles,
|
|
45
43
|
inputStatusHoverShadowStyles,
|
|
@@ -52,6 +50,7 @@ import {useTooltip} from '../Tooltip';
|
|
|
52
50
|
import {getInputARIA} from '../utils';
|
|
53
51
|
import {useSize} from '../SizeContext/SizeContext';
|
|
54
52
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
53
|
+
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
55
54
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
56
55
|
|
|
57
56
|
const styles = stylex.create({
|
|
@@ -212,6 +211,7 @@ interface NumberInputPropsBase extends Omit<
|
|
|
212
211
|
* How the status message is placed relative to the input.
|
|
213
212
|
* - 'attached': message overlaps directly below the input (bordered treatment)
|
|
214
213
|
* - 'detached': message floats below as a separate element with spacing
|
|
214
|
+
* - 'tooltip': no message box; the status icon becomes a focusable info-tip button that reveals the message on hover, keyboard focus, or tap
|
|
215
215
|
* @default 'attached'
|
|
216
216
|
*/
|
|
217
217
|
statusVariant?: FieldStatusVariant;
|
|
@@ -414,6 +414,7 @@ export function NumberInput({
|
|
|
414
414
|
const inputLabelID = useId();
|
|
415
415
|
const descriptionID = useId();
|
|
416
416
|
const statusMessageID = useId();
|
|
417
|
+
const unitsID = useId();
|
|
417
418
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
418
419
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
419
420
|
const inputGroup = useInputGroup();
|
|
@@ -435,26 +436,26 @@ export function NumberInput({
|
|
|
435
436
|
isEnabled: showsDisabledMessage,
|
|
436
437
|
});
|
|
437
438
|
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const statusIconColorMap: Record<
|
|
445
|
-
InputStatusType,
|
|
446
|
-
'warning' | 'error' | 'success'
|
|
447
|
-
> = {
|
|
448
|
-
warning: 'warning',
|
|
449
|
-
error: 'error',
|
|
450
|
-
success: 'success',
|
|
451
|
-
};
|
|
439
|
+
const {statusIcon, describedBy: statusTooltipDescribedBy} =
|
|
440
|
+
useInputStatusIcon({
|
|
441
|
+
status,
|
|
442
|
+
statusVariant,
|
|
443
|
+
isInGroup: !!inputGroup,
|
|
444
|
+
});
|
|
452
445
|
|
|
453
446
|
const {ariaLabelledBy, ariaDescribedBy} = getInputARIA(
|
|
454
447
|
inputLabelID,
|
|
455
448
|
[
|
|
456
449
|
description ? descriptionID : null,
|
|
457
|
-
status
|
|
450
|
+
// The status message element is rendered by Field, which is skipped
|
|
451
|
+
// inside an InputGroup — only reference it when it actually exists.
|
|
452
|
+
!inputGroup && statusVariant !== 'tooltip' && status?.message
|
|
453
|
+
? statusMessageID
|
|
454
|
+
: null,
|
|
455
|
+
// The tooltip variant renders no message box; describe the input by the
|
|
456
|
+
// tooltip's content instead so the status is still announced.
|
|
457
|
+
statusTooltipDescribedBy,
|
|
458
|
+
units ? unitsID : null,
|
|
458
459
|
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
459
460
|
],
|
|
460
461
|
inputGroup,
|
|
@@ -614,7 +615,7 @@ export function NumberInput({
|
|
|
614
615
|
sizeStyles[size],
|
|
615
616
|
isDisabled && inputWrapperStyles.disabled,
|
|
616
617
|
status && inputStatusBorderStyles[status.type],
|
|
617
|
-
status && inputStatusHoverShadowStyles[status.type],
|
|
618
|
+
status && !isDisabled && inputStatusHoverShadowStyles[status.type],
|
|
618
619
|
status && inputStatusFocusWithinStyles[status.type],
|
|
619
620
|
inputGroup && groupStyles.inGroup,
|
|
620
621
|
xstyle,
|
|
@@ -660,7 +661,11 @@ export function NumberInput({
|
|
|
660
661
|
!isInputValid && styles.inputInvalid,
|
|
661
662
|
)}
|
|
662
663
|
/>
|
|
663
|
-
{units &&
|
|
664
|
+
{units && (
|
|
665
|
+
<span id={unitsID} {...stylex.props(styles.units)}>
|
|
666
|
+
{units}
|
|
667
|
+
</span>
|
|
668
|
+
)}
|
|
664
669
|
{/*
|
|
665
670
|
Live region announcing invalid typed input to assistive technology.
|
|
666
671
|
The value silently reverts on blur, so without this a screen-reader
|
|
@@ -678,13 +683,7 @@ export function NumberInput({
|
|
|
678
683
|
<Icon icon="close" size="sm" color="secondary" />
|
|
679
684
|
</button>
|
|
680
685
|
)}
|
|
681
|
-
{
|
|
682
|
-
<Icon
|
|
683
|
-
icon={statusIconMap[status.type]}
|
|
684
|
-
size="md"
|
|
685
|
-
color={statusIconColorMap[status.type]}
|
|
686
|
-
/>
|
|
687
|
-
)}
|
|
686
|
+
{statusIcon}
|
|
688
687
|
</div>
|
|
689
688
|
);
|
|
690
689
|
|
|
@@ -86,7 +86,7 @@ describe('Outline', () => {
|
|
|
86
86
|
render(<Outline items={items} activeId="install" />);
|
|
87
87
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
88
88
|
'aria-current',
|
|
89
|
-
'
|
|
89
|
+
'location',
|
|
90
90
|
);
|
|
91
91
|
expect(
|
|
92
92
|
screen.getByRole('link', {name: 'Introduction'}),
|
|
@@ -111,7 +111,7 @@ describe('Outline', () => {
|
|
|
111
111
|
// so it has not moved to the clicked item yet.
|
|
112
112
|
expect(
|
|
113
113
|
screen.getByRole('link', {name: 'Installation'}),
|
|
114
|
-
).not.toHaveAttribute('aria-current', '
|
|
114
|
+
).not.toHaveAttribute('aria-current', 'location');
|
|
115
115
|
|
|
116
116
|
// When the scroll settles, the indicator lands on the clicked item.
|
|
117
117
|
act(() => {
|
|
@@ -120,7 +120,7 @@ describe('Outline', () => {
|
|
|
120
120
|
expect(onActiveIdChange).toHaveBeenCalledWith('install');
|
|
121
121
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
122
122
|
'aria-current',
|
|
123
|
-
'
|
|
123
|
+
'location',
|
|
124
124
|
);
|
|
125
125
|
|
|
126
126
|
document.body.removeChild(target);
|
|
@@ -224,7 +224,7 @@ describe('Outline', () => {
|
|
|
224
224
|
|
|
225
225
|
expect(screen.getByRole('link', {name: 'Introduction'})).toHaveAttribute(
|
|
226
226
|
'aria-current',
|
|
227
|
-
'
|
|
227
|
+
'location',
|
|
228
228
|
);
|
|
229
229
|
|
|
230
230
|
// Controlled active id is driven entirely by the prop.
|
|
@@ -237,7 +237,7 @@ describe('Outline', () => {
|
|
|
237
237
|
);
|
|
238
238
|
expect(screen.getByRole('link', {name: 'API'})).toHaveAttribute(
|
|
239
239
|
'aria-current',
|
|
240
|
-
'
|
|
240
|
+
'location',
|
|
241
241
|
);
|
|
242
242
|
expect(
|
|
243
243
|
screen.getByRole('link', {name: 'Introduction'}),
|
|
@@ -277,7 +277,7 @@ describe('Outline', () => {
|
|
|
277
277
|
|
|
278
278
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
279
279
|
'aria-current',
|
|
280
|
-
'
|
|
280
|
+
'location',
|
|
281
281
|
);
|
|
282
282
|
expect(onActiveIdChange).toHaveBeenCalledWith('install');
|
|
283
283
|
|
|
@@ -493,7 +493,7 @@ describe('Outline keyboard navigation', () => {
|
|
|
493
493
|
expect(onNavigateEnd).toHaveBeenCalledTimes(1);
|
|
494
494
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
495
495
|
'aria-current',
|
|
496
|
-
'
|
|
496
|
+
'location',
|
|
497
497
|
);
|
|
498
498
|
|
|
499
499
|
cleanup();
|
|
@@ -764,7 +764,7 @@ describe('Outline scroll scoping', () => {
|
|
|
764
764
|
expect(onNavigateEnd).toHaveBeenCalledWith('install');
|
|
765
765
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
766
766
|
'aria-current',
|
|
767
|
-
'
|
|
767
|
+
'location',
|
|
768
768
|
);
|
|
769
769
|
|
|
770
770
|
cleanup();
|
|
@@ -797,7 +797,7 @@ describe('Outline scroll scoping', () => {
|
|
|
797
797
|
// has not reached it, so `intro` stays active.
|
|
798
798
|
expect(screen.getByRole('link', {name: 'Introduction'})).toHaveAttribute(
|
|
799
799
|
'aria-current',
|
|
800
|
-
'
|
|
800
|
+
'location',
|
|
801
801
|
);
|
|
802
802
|
|
|
803
803
|
rerender(<Outline items={items} offset={64} />);
|
|
@@ -806,7 +806,7 @@ describe('Outline scroll scoping', () => {
|
|
|
806
806
|
});
|
|
807
807
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
808
808
|
'aria-current',
|
|
809
|
-
'
|
|
809
|
+
'location',
|
|
810
810
|
);
|
|
811
811
|
|
|
812
812
|
cleanup();
|
|
@@ -930,7 +930,7 @@ describe('Outline scroll scoping', () => {
|
|
|
930
930
|
|
|
931
931
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
932
932
|
'aria-current',
|
|
933
|
-
'
|
|
933
|
+
'location',
|
|
934
934
|
);
|
|
935
935
|
expect(screen.getByRole('link', {name: 'API'})).not.toHaveAttribute(
|
|
936
936
|
'aria-current',
|
|
@@ -981,7 +981,7 @@ describe('Outline scroll scoping', () => {
|
|
|
981
981
|
|
|
982
982
|
expect(screen.getByRole('link', {name: 'Installation'})).toHaveAttribute(
|
|
983
983
|
'aria-current',
|
|
984
|
-
'
|
|
984
|
+
'location',
|
|
985
985
|
);
|
|
986
986
|
|
|
987
987
|
pane.remove();
|
package/src/Outline/Outline.tsx
CHANGED
|
@@ -372,7 +372,7 @@ export function Outline({
|
|
|
372
372
|
}
|
|
373
373
|
const links = Array.from(list.querySelectorAll<HTMLElement>('a[href]'));
|
|
374
374
|
const active = links.find(
|
|
375
|
-
link => link.getAttribute('aria-current') === '
|
|
375
|
+
link => link.getAttribute('aria-current') === 'location',
|
|
376
376
|
);
|
|
377
377
|
if (active == null) {
|
|
378
378
|
return;
|
|
@@ -465,7 +465,7 @@ export function Outline({
|
|
|
465
465
|
<li key={item.id} {...stylex.props(styles.item)} role="listitem">
|
|
466
466
|
<LinkComponent
|
|
467
467
|
href={`#${item.id}`}
|
|
468
|
-
aria-current={isActive ? '
|
|
468
|
+
aria-current={isActive ? 'location' : undefined}
|
|
469
469
|
onClick={handleClick(item.id)}
|
|
470
470
|
onKeyDown={handleKeyDown(item.id)}
|
|
471
471
|
{...mergeProps(
|
|
@@ -114,6 +114,12 @@ export const docs = {
|
|
|
114
114
|
type: 'string',
|
|
115
115
|
description: 'Tooltip text for an info icon next to the label.',
|
|
116
116
|
},
|
|
117
|
+
{
|
|
118
|
+
name: 'width',
|
|
119
|
+
type: 'SizeValue',
|
|
120
|
+
description:
|
|
121
|
+
'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
|
|
122
|
+
},
|
|
117
123
|
{
|
|
118
124
|
name: 'xstyle',
|
|
119
125
|
type: 'StyleXStyles',
|
|
@@ -146,8 +146,8 @@ export interface RadioListProps extends Omit<
|
|
|
146
146
|
status?: InputStatus;
|
|
147
147
|
/**
|
|
148
148
|
* The size of the radio controls.
|
|
149
|
-
* - 'sm': Compact size (
|
|
150
|
-
* - 'md': Default size (
|
|
149
|
+
* - 'sm': Compact size (20px radio)
|
|
150
|
+
* - 'md': Default size (24px radio)
|
|
151
151
|
* @default 'md'
|
|
152
152
|
*/
|
|
153
153
|
size?: RadioListSize;
|
|
@@ -140,12 +140,12 @@ const wrapperSizeStyles = stylex.create({
|
|
|
140
140
|
|
|
141
141
|
const radioSizeStyles = stylex.create({
|
|
142
142
|
sm: {
|
|
143
|
-
width:
|
|
144
|
-
height:
|
|
143
|
+
width: 20,
|
|
144
|
+
height: 20,
|
|
145
145
|
},
|
|
146
146
|
md: {
|
|
147
|
-
width:
|
|
148
|
-
height:
|
|
147
|
+
width: 24,
|
|
148
|
+
height: 24,
|
|
149
149
|
},
|
|
150
150
|
});
|
|
151
151
|
|