@astryxdesign/core 0.1.9 → 0.2.0-canary.136a00f
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 +107 -0
- package/dist/Avatar/Avatar.d.ts +42 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +190 -59
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
- package/dist/Banner/Banner.js +2 -2
- 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/Button/Button.d.ts +1 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +6 -4
- 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/ChatComposerInput.js +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatLayout.js +4 -4
- 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/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -6
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +19 -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 +16 -10
- 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/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +23 -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 +10 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +33 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- 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 +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
- 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/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -5
- 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 +10 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +39 -3
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +93 -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/Item/Item.d.ts +16 -3
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +31 -6
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +10 -2
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/List/ListItem.d.ts +11 -1
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +2 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MetadataList/MetadataList.d.ts +1 -1
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +4 -2
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +80 -42
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +6 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -5
- 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 +5 -3
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +66 -17
- 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/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +2 -2
- 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 +171 -91
- package/dist/TabList/Tab.js +2 -2
- 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/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- 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 +37 -27
- 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 +15 -7
- 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 +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.js +2 -2
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +17 -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/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +61 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +3 -1
- package/dist/Token/Token.d.ts +34 -4
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +85 -45
- package/dist/Token/TokenLink.d.ts +62 -0
- package/dist/Token/TokenLink.d.ts.map +1 -0
- package/dist/Token/TokenLink.js +76 -0
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +9 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +4 -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 +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +22 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +11 -2
- 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 +70 -30
- package/dist/astryx.umd.js +51 -51
- 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/useKeyboardHint.d.ts +1 -1
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
- package/dist/hooks/useKeyboardHint.js +4 -2
- 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/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- 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 +112 -0
- package/locales/pseudo.json +84 -0
- package/package.json +6 -1
- package/src/Avatar/Avatar.doc.mjs +50 -3
- package/src/Avatar/Avatar.test.tsx +218 -0
- package/src/Avatar/Avatar.tsx +285 -79
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
- package/src/Banner/Banner.tsx +6 -6
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Button/Button.test.tsx +16 -0
- package/src/Button/Button.tsx +6 -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/ChatComposerInput.tsx +2 -2
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatLayout.tsx +4 -4
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/Chat/useTriggerMenu.tsx +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +94 -3
- package/src/CheckboxList/CheckboxListItem.tsx +17 -10
- 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.test.tsx +17 -0
- package/src/CodeBlock/CodeBlock.tsx +38 -11
- 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/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +59 -2
- package/src/ContextMenu/ContextMenu.tsx +22 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +25 -0
- package/src/DateInput/DateInput.test.tsx +230 -0
- package/src/DateInput/DateInput.tsx +51 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- 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 +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -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/FieldLabel.test.tsx +25 -0
- package/src/Field/FieldLabel.tsx +12 -3
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.test.tsx +72 -0
- package/src/FieldStatus/FieldStatus.tsx +48 -2
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +104 -13
- package/src/FileInput/FileInput.tsx +106 -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/Item/Item.doc.mjs +5 -0
- package/src/Item/Item.test.tsx +88 -0
- package/src/Item/Item.tsx +57 -11
- package/src/Layer/layerAnimations.stylex.ts +23 -0
- package/src/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/List/ListItem.doc.mjs +12 -0
- package/src/List/ListItem.tsx +13 -0
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MetadataList/MetadataList.test.tsx +24 -0
- package/src/MetadataList/MetadataList.tsx +6 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
- package/src/MultiSelector/MultiSelector.test.tsx +402 -0
- package/src/MultiSelector/MultiSelector.tsx +120 -59
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +71 -0
- package/src/NumberInput/NumberInput.tsx +35 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -2
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +23 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/ProgressBar/ProgressBar.test.tsx +34 -0
- package/src/ProgressBar/ProgressBar.tsx +16 -1
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.test.tsx +26 -4
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +12 -5
- package/src/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +370 -0
- package/src/Selector/Selector.tsx +88 -20
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Skeleton/Skeleton.test.tsx +16 -0
- package/src/Skeleton/Skeleton.tsx +13 -1
- 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 +111 -0
- package/src/Switch/Switch.tsx +149 -32
- package/src/TabList/Tab.tsx +2 -2
- 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/TabList/TabMenu.tsx +2 -2
- 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/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
- 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 +38 -9
- 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 +21 -0
- package/src/TextArea/TextArea.test.tsx +23 -0
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.tsx +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +23 -0
- package/src/TimeInput/TimeInput.tsx +24 -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/Toast/ToastViewport.test.tsx +218 -8
- package/src/Toast/ToastViewport.tsx +71 -12
- package/src/ToggleButton/ToggleButton.test.tsx +24 -0
- package/src/ToggleButton/ToggleButton.tsx +19 -1
- package/src/Token/Token.test.tsx +166 -15
- package/src/Token/Token.tsx +104 -47
- package/src/Token/TokenLink.tsx +107 -0
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
- package/src/Tokenizer/Tokenizer.test.tsx +23 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -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 +42 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +112 -0
- package/src/Typeahead/Typeahead.tsx +17 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/forcedColors.ts +60 -0
- 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/useKeyboardHint.test.tsx +22 -0
- package/src/hooks/useKeyboardHint.tsx +6 -2
- 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/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/useDirection.ts +29 -0
- 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
package/src/Slider/Slider.tsx
CHANGED
|
@@ -41,6 +41,7 @@ import {useTooltip} from '../Tooltip';
|
|
|
41
41
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
42
42
|
import type {InputStatus} from '../Field/types';
|
|
43
43
|
import {mergeProps, mergeRefs} from '../utils';
|
|
44
|
+
import {isRtlElement} from '../hooks/isRtlElement';
|
|
44
45
|
import type {BaseProps} from '../BaseProps';
|
|
45
46
|
import type {SizeValue} from '../utils/types';
|
|
46
47
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -192,8 +193,8 @@ const styles = stylex.create({
|
|
|
192
193
|
borderRadius: radiusVars['--radius-full'],
|
|
193
194
|
},
|
|
194
195
|
trackHorizontal: {
|
|
195
|
-
|
|
196
|
-
|
|
196
|
+
insetInlineStart: 0,
|
|
197
|
+
insetInlineEnd: 0,
|
|
197
198
|
height: TRACK_SIZE,
|
|
198
199
|
top: '50%',
|
|
199
200
|
transform: 'translateY(-50%)',
|
|
@@ -202,7 +203,7 @@ const styles = stylex.create({
|
|
|
202
203
|
top: 0,
|
|
203
204
|
bottom: 0,
|
|
204
205
|
width: TRACK_SIZE,
|
|
205
|
-
|
|
206
|
+
insetInlineStart: '50%',
|
|
206
207
|
transform: 'translateX(-50%)',
|
|
207
208
|
},
|
|
208
209
|
filledTrack: {
|
|
@@ -217,7 +218,7 @@ const styles = stylex.create({
|
|
|
217
218
|
},
|
|
218
219
|
filledTrackVertical: {
|
|
219
220
|
width: TRACK_SIZE,
|
|
220
|
-
|
|
221
|
+
insetInlineStart: '50%',
|
|
221
222
|
transform: 'translateX(-50%)',
|
|
222
223
|
},
|
|
223
224
|
thumb: {
|
|
@@ -239,9 +240,17 @@ const styles = stylex.create({
|
|
|
239
240
|
},
|
|
240
241
|
thumbHorizontal: {
|
|
241
242
|
top: '50%',
|
|
243
|
+
// The thumb is positioned via logical `insetInlineStart`, which resolves
|
|
244
|
+
// from the right edge under RTL. The centering translate is a physical
|
|
245
|
+
// (screen-space) transform, so it must flip its X direction under RTL to
|
|
246
|
+
// keep the thumb centered on the value point.
|
|
247
|
+
transform: {
|
|
248
|
+
default: 'translate(-50%, -50%)',
|
|
249
|
+
':is([dir="rtl"] *)': 'translate(50%, -50%)',
|
|
250
|
+
},
|
|
242
251
|
},
|
|
243
252
|
thumbVertical: {
|
|
244
|
-
|
|
253
|
+
insetInlineStart: '50%',
|
|
245
254
|
transform: 'translate(-50%, 50%)',
|
|
246
255
|
},
|
|
247
256
|
thumbHover: {
|
|
@@ -277,14 +286,14 @@ const styles = stylex.create({
|
|
|
277
286
|
position: 'absolute',
|
|
278
287
|
},
|
|
279
288
|
marksContainerHorizontal: {
|
|
280
|
-
|
|
281
|
-
|
|
289
|
+
insetInlineStart: 0,
|
|
290
|
+
insetInlineEnd: 0,
|
|
282
291
|
top: '50%',
|
|
283
292
|
},
|
|
284
293
|
marksContainerVertical: {
|
|
285
294
|
top: 0,
|
|
286
295
|
bottom: 0,
|
|
287
|
-
|
|
296
|
+
insetInlineStart: '50%',
|
|
288
297
|
},
|
|
289
298
|
mark: {
|
|
290
299
|
position: 'absolute',
|
|
@@ -294,7 +303,10 @@ const styles = stylex.create({
|
|
|
294
303
|
markHorizontal: {
|
|
295
304
|
width: 2,
|
|
296
305
|
height: 8,
|
|
297
|
-
transform:
|
|
306
|
+
transform: {
|
|
307
|
+
default: 'translate(-50%, -50%)',
|
|
308
|
+
':is([dir="rtl"] *)': 'translate(50%, -50%)',
|
|
309
|
+
},
|
|
298
310
|
},
|
|
299
311
|
markVertical: {
|
|
300
312
|
height: 2,
|
|
@@ -309,12 +321,15 @@ const styles = stylex.create({
|
|
|
309
321
|
whiteSpace: 'nowrap',
|
|
310
322
|
},
|
|
311
323
|
markLabelHorizontal: {
|
|
312
|
-
transform:
|
|
324
|
+
transform: {
|
|
325
|
+
default: 'translateX(-50%)',
|
|
326
|
+
':is([dir="rtl"] *)': 'translateX(50%)',
|
|
327
|
+
},
|
|
313
328
|
top: THUMB_SIZE / 2 + 4,
|
|
314
329
|
},
|
|
315
330
|
markLabelVertical: {
|
|
316
331
|
transform: 'translateY(50%)',
|
|
317
|
-
|
|
332
|
+
insetInlineStart: THUMB_SIZE / 2 + 4,
|
|
318
333
|
},
|
|
319
334
|
});
|
|
320
335
|
|
|
@@ -326,12 +341,39 @@ function clamp(val: number, min: number, max: number): number {
|
|
|
326
341
|
return Math.min(Math.max(val, min), max);
|
|
327
342
|
}
|
|
328
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Number of decimal places a value carries, including values in exponent
|
|
346
|
+
* notation (e.g. 1e-7 → 7). Used to round away binary floating-point error
|
|
347
|
+
* after step arithmetic.
|
|
348
|
+
*/
|
|
349
|
+
function getDecimalPrecision(num: number): number {
|
|
350
|
+
if (Math.abs(num) < 1) {
|
|
351
|
+
const parts = num.toExponential().split('e-');
|
|
352
|
+
if (parts.length === 2) {
|
|
353
|
+
const mantissaDecimals = parts[0].split('.')[1]?.length ?? 0;
|
|
354
|
+
return mantissaDecimals + parseInt(parts[1], 10);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const decimalPart = String(num).split('.')[1];
|
|
358
|
+
return decimalPart ? decimalPart.length : 0;
|
|
359
|
+
}
|
|
360
|
+
|
|
329
361
|
function snapToStep(val: number, min: number, step: number): number {
|
|
330
362
|
if (step <= 0) {
|
|
331
363
|
return val;
|
|
332
364
|
}
|
|
333
365
|
const steps = Math.round((val - min) / step);
|
|
334
|
-
|
|
366
|
+
const snapped = min + steps * step;
|
|
367
|
+
// `min + steps * step` accumulates binary floating-point error with
|
|
368
|
+
// fractional steps (0 + 3 * 0.1 → 0.30000000000000004), which leaks into
|
|
369
|
+
// onChange/onChangeEnd payloads, aria-valuenow, and the value tooltip.
|
|
370
|
+
// Snapped values can never carry more decimals than min/step combined, so
|
|
371
|
+
// rounding to that precision removes only the error.
|
|
372
|
+
const precision = Math.min(
|
|
373
|
+
Math.max(getDecimalPrecision(min), getDecimalPrecision(step)),
|
|
374
|
+
20, // toFixed() throws past 20 digits
|
|
375
|
+
);
|
|
376
|
+
return Number(snapped.toFixed(precision));
|
|
335
377
|
}
|
|
336
378
|
|
|
337
379
|
function getPercent(val: number, min: number, max: number): number {
|
|
@@ -392,6 +434,7 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
392
434
|
const isHorizontal = orientation === 'horizontal';
|
|
393
435
|
|
|
394
436
|
const id = useId();
|
|
437
|
+
const labelID = useId();
|
|
395
438
|
const descriptionID = useId();
|
|
396
439
|
const statusMessageID = useId();
|
|
397
440
|
const requiredID = useId();
|
|
@@ -459,7 +502,12 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
459
502
|
|
|
460
503
|
let percent: number;
|
|
461
504
|
if (isHorizontal) {
|
|
462
|
-
|
|
505
|
+
// In RTL the inline-start (value = min) is the right edge, so measure
|
|
506
|
+
// the pointer fraction from the right instead of the left. Detected
|
|
507
|
+
// from the track's computed direction (lazy, only on pointer move).
|
|
508
|
+
percent = isRtlElement(track)
|
|
509
|
+
? (rect.right - clientX) / rect.width
|
|
510
|
+
: (clientX - rect.left) / rect.width;
|
|
463
511
|
} else {
|
|
464
512
|
// Vertical: bottom = min, top = max
|
|
465
513
|
percent = 1 - (clientY - rect.top) / rect.height;
|
|
@@ -692,14 +740,28 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
692
740
|
const percent = getPercent(val, min, max);
|
|
693
741
|
|
|
694
742
|
const positionStyle = isHorizontal
|
|
695
|
-
? {
|
|
743
|
+
? {insetInlineStart: `${percent}%`}
|
|
696
744
|
: {bottom: `${percent}%`, left: '50%'};
|
|
697
745
|
|
|
746
|
+
// In range mode each thumb keeps a short individual name that composes
|
|
747
|
+
// with the group label (announced via the group's aria-labelledby), per
|
|
748
|
+
// the APG multi-thumb slider pattern. In single mode the thumb takes its
|
|
749
|
+
// name from the visible label element via aria-labelledby.
|
|
698
750
|
const thumbLabel = isRange
|
|
699
751
|
? thumbIndex === 0
|
|
700
|
-
?
|
|
701
|
-
:
|
|
702
|
-
:
|
|
752
|
+
? 'Minimum value'
|
|
753
|
+
: 'Maximum value'
|
|
754
|
+
: undefined;
|
|
755
|
+
|
|
756
|
+
// ARIA bounds must agree with the movement clamping in updateValue: in
|
|
757
|
+
// range mode a thumb can't cross its sibling (minus the
|
|
758
|
+
// minStepsBetweenThumbs gap), and the result is always clamped to
|
|
759
|
+
// [min, max].
|
|
760
|
+
const minGap = minStepsBetweenThumbs * step;
|
|
761
|
+
const ariaValueMin =
|
|
762
|
+
isRange && thumbIndex === 1 ? clamp(values[0] + minGap, min, max) : min;
|
|
763
|
+
const ariaValueMax =
|
|
764
|
+
isRange && thumbIndex === 0 ? clamp(values[1] - minGap, min, max) : max;
|
|
703
765
|
|
|
704
766
|
// Suppress the per-thumb value bubble while the disabled-message tooltip is
|
|
705
767
|
// showing, so a disabled slider surfaces the *reason* on hover/focus rather
|
|
@@ -716,14 +778,15 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
716
778
|
// focus-discoverable; value changes stay blocked by the isDisabled
|
|
717
779
|
// guards in the pointer/keyboard handlers.
|
|
718
780
|
tabIndex={isDisabled && !showsDisabledMessage ? -1 : 0}
|
|
719
|
-
aria-valuemin={
|
|
720
|
-
aria-valuemax={
|
|
781
|
+
aria-valuemin={ariaValueMin}
|
|
782
|
+
aria-valuemax={ariaValueMax}
|
|
721
783
|
aria-valuenow={val}
|
|
722
784
|
aria-valuetext={formatValue ? formatValue(val) : undefined}
|
|
723
785
|
aria-orientation={orientation}
|
|
724
786
|
aria-disabled={isDisabled || undefined}
|
|
725
787
|
aria-invalid={status?.type === 'error' ? true : undefined}
|
|
726
788
|
aria-label={thumbLabel}
|
|
789
|
+
aria-labelledby={!isRange ? labelID : undefined}
|
|
727
790
|
aria-describedby={ariaDescribedBy}
|
|
728
791
|
onKeyDown={e => handleKeyDown(thumbIndex, e)}
|
|
729
792
|
{...mergeProps(
|
|
@@ -768,13 +831,13 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
768
831
|
const p0 = getPercent(v0, min, max);
|
|
769
832
|
const p1 = getPercent(v1, min, max);
|
|
770
833
|
if (isHorizontal) {
|
|
771
|
-
return {
|
|
834
|
+
return {insetInlineStart: `${p0}%`, width: `${p1 - p0}%`};
|
|
772
835
|
}
|
|
773
836
|
return {bottom: `${p0}%`, height: `${p1 - p0}%`};
|
|
774
837
|
}
|
|
775
838
|
const p = getPercent(values[0], min, max);
|
|
776
839
|
if (isHorizontal) {
|
|
777
|
-
return {
|
|
840
|
+
return {insetInlineStart: '0%', width: `${p}%`};
|
|
778
841
|
}
|
|
779
842
|
return {bottom: '0%', height: `${p}%`};
|
|
780
843
|
})();
|
|
@@ -796,6 +859,14 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
796
859
|
isLabelHidden={isLabelHidden}
|
|
797
860
|
description={description}
|
|
798
861
|
inputID={id}
|
|
862
|
+
labelID={labelID}
|
|
863
|
+
// The thumb is a div[role="slider"], which a <label htmlFor> can't
|
|
864
|
+
// name (only form-associated elements are labelable). Render the label
|
|
865
|
+
// as a group label and associate it via aria-labelledby instead: the
|
|
866
|
+
// single thumb references it directly, and in range mode the
|
|
867
|
+
// role="group" container references it while each thumb keeps its own
|
|
868
|
+
// "Minimum value"/"Maximum value" name.
|
|
869
|
+
isGroupLabel
|
|
799
870
|
descriptionID={description ? descriptionID : undefined}
|
|
800
871
|
isOptional={isOptional}
|
|
801
872
|
isRequired={isRequired}
|
|
@@ -838,7 +909,9 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
838
909
|
))}
|
|
839
910
|
<div
|
|
840
911
|
ref={mergeRefs(ref, trackRef, disabledMessageTooltip.ref)}
|
|
841
|
-
{...(isRange
|
|
912
|
+
{...(isRange
|
|
913
|
+
? {role: 'group', 'aria-labelledby': labelID}
|
|
914
|
+
: undefined)}
|
|
842
915
|
onPointerDown={handlePointerDown}
|
|
843
916
|
onPointerMove={handlePointerMove}
|
|
844
917
|
onPointerUp={handlePointerUp}
|
|
@@ -889,7 +962,7 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
889
962
|
{marks.map(mark => {
|
|
890
963
|
const percent = getPercent(mark.value, min, max);
|
|
891
964
|
const markPos = isHorizontal
|
|
892
|
-
? {
|
|
965
|
+
? {insetInlineStart: `${percent}%`}
|
|
893
966
|
: {bottom: `${percent}%`};
|
|
894
967
|
return (
|
|
895
968
|
<div key={mark.value}>
|
|
@@ -64,12 +64,16 @@ describe('Spinner', () => {
|
|
|
64
64
|
);
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
it('
|
|
67
|
+
it('names the status element from the visible string label', () => {
|
|
68
68
|
render(<Spinner label="Fetching data" data-testid="spinner" />);
|
|
69
|
-
expect(screen.getByRole('status')).
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
expect(screen.getByRole('status')).toHaveAccessibleName('Fetching data');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('does not duplicate a visible string label as aria-label', () => {
|
|
73
|
+
render(<Spinner label="Fetching data" data-testid="spinner" />);
|
|
74
|
+
const status = screen.getByRole('status');
|
|
75
|
+
expect(status).not.toHaveAttribute('aria-label');
|
|
76
|
+
expect(status).toHaveAttribute('aria-labelledby');
|
|
73
77
|
});
|
|
74
78
|
|
|
75
79
|
it('uses explicit aria-label over string label', () => {
|
|
@@ -103,9 +107,7 @@ describe('Spinner', () => {
|
|
|
103
107
|
});
|
|
104
108
|
|
|
105
109
|
it('defaults aria-label to "Loading" for ReactNode label without explicit aria-label', () => {
|
|
106
|
-
render(
|
|
107
|
-
<Spinner label={<span>Rich content</span>} data-testid="spinner" />,
|
|
108
|
-
);
|
|
110
|
+
render(<Spinner label={<span>Rich content</span>} data-testid="spinner" />);
|
|
109
111
|
expect(screen.getByRole('status')).toHaveAttribute('aria-label', 'Loading');
|
|
110
112
|
});
|
|
111
113
|
|
package/src/Spinner/Spinner.tsx
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* - /packages/cli/templates/blocks/components/Spinner/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {useEffect, useRef, type ReactNode} from 'react';
|
|
19
|
+
import {useEffect, useId, useRef, type ReactNode} from 'react';
|
|
20
20
|
import * as stylex from '@stylexjs/stylex';
|
|
21
21
|
import {durationVars, spacingVars} from '../theme/tokens.stylex';
|
|
22
22
|
import {useTheme} from '../theme/useTheme';
|
|
@@ -119,8 +119,9 @@ export interface SpinnerProps extends BaseProps<HTMLSpanElement> {
|
|
|
119
119
|
* Visible content displayed below the spinner.
|
|
120
120
|
* Accepts a string or ReactNode for rich content.
|
|
121
121
|
*
|
|
122
|
-
* When `label` is a string,
|
|
123
|
-
* (
|
|
122
|
+
* When `label` is a string, the visible text also provides the accessible
|
|
123
|
+
* name of the status element (via aria-labelledby, avoiding a duplicate
|
|
124
|
+
* announcement) unless `aria-label` is explicitly set.
|
|
124
125
|
*
|
|
125
126
|
* @example
|
|
126
127
|
* ```
|
|
@@ -255,6 +256,14 @@ export function Spinner({
|
|
|
255
256
|
const {border, diameter} = SIZES[size];
|
|
256
257
|
const frameSize = diameter + border * 2;
|
|
257
258
|
const hasLabel = label != null;
|
|
259
|
+
const labelId = useId();
|
|
260
|
+
|
|
261
|
+
// When a visible string label renders (and no explicit aria-label is set),
|
|
262
|
+
// name the status element from the visible Text via aria-labelledby instead
|
|
263
|
+
// of duplicating the same string as aria-label — the duplicate would be
|
|
264
|
+
// announced twice by screen readers (WCAG 4.1.2).
|
|
265
|
+
const namedByVisibleLabel =
|
|
266
|
+
hasLabel && typeof label === 'string' && ariaLabel == null;
|
|
258
267
|
|
|
259
268
|
// Resolve accessible name: explicit aria-label > string label > "Loading"
|
|
260
269
|
const resolvedAriaLabel =
|
|
@@ -264,7 +273,8 @@ export function Spinner({
|
|
|
264
273
|
<span
|
|
265
274
|
ref={hasLabel ? undefined : ref}
|
|
266
275
|
role="status"
|
|
267
|
-
aria-label={resolvedAriaLabel}
|
|
276
|
+
aria-label={namedByVisibleLabel ? undefined : resolvedAriaLabel}
|
|
277
|
+
aria-labelledby={namedByVisibleLabel ? labelId : undefined}
|
|
268
278
|
data-testid={hasLabel ? undefined : testId}
|
|
269
279
|
{...(hasLabel ? {} : restProps)}
|
|
270
280
|
{...mergeProps(
|
|
@@ -294,7 +304,7 @@ export function Spinner({
|
|
|
294
304
|
)}>
|
|
295
305
|
{spinner}
|
|
296
306
|
{typeof label === 'string' ? (
|
|
297
|
-
<Text type="body" weight="bold">
|
|
307
|
+
<Text id={labelId} type="body" weight="bold">
|
|
298
308
|
{label}
|
|
299
309
|
</Text>
|
|
300
310
|
) : (
|
|
@@ -6,7 +6,14 @@ export const docs = {
|
|
|
6
6
|
name: 'Switch',
|
|
7
7
|
displayName: 'Switch',
|
|
8
8
|
category: 'Data Input',
|
|
9
|
-
keywords: [
|
|
9
|
+
keywords: [
|
|
10
|
+
'switch',
|
|
11
|
+
'toggle',
|
|
12
|
+
'onoff',
|
|
13
|
+
'flipswitch',
|
|
14
|
+
'boolean',
|
|
15
|
+
'toggleswitch',
|
|
16
|
+
],
|
|
10
17
|
props: [
|
|
11
18
|
{
|
|
12
19
|
name: 'ref',
|
|
@@ -62,6 +69,13 @@ export const docs = {
|
|
|
62
69
|
description: 'Whether the switch is disabled.',
|
|
63
70
|
default: 'false',
|
|
64
71
|
},
|
|
72
|
+
{
|
|
73
|
+
name: 'size',
|
|
74
|
+
type: "'sm' | 'md'",
|
|
75
|
+
description:
|
|
76
|
+
'Size variant controlling track and thumb dimensions. sm (32x20px) matches sm checkbox/radio vertical rhythm; md (40x24px, default) matches md checkbox/radio vertical rhythm.',
|
|
77
|
+
default: "'md'",
|
|
78
|
+
},
|
|
65
79
|
{
|
|
66
80
|
name: 'htmlName',
|
|
67
81
|
type: 'string',
|
|
@@ -107,7 +121,8 @@ export const docs = {
|
|
|
107
121
|
{
|
|
108
122
|
name: 'labelIcon',
|
|
109
123
|
type: 'IconType',
|
|
110
|
-
description:
|
|
124
|
+
description:
|
|
125
|
+
'Icon displayed before the label text. See `astryx docs icons` for valid semantic names.',
|
|
111
126
|
},
|
|
112
127
|
{
|
|
113
128
|
name: 'labelTooltip',
|
|
@@ -129,23 +144,60 @@ export const docs = {
|
|
|
129
144
|
'Spacing behavior between label and switch. "hug" places them next to each other; "spread" pushes them to opposite ends of the container (full width). "default" is a deprecated alias for "hug".',
|
|
130
145
|
default: "'hug'",
|
|
131
146
|
},
|
|
147
|
+
{
|
|
148
|
+
name: 'width',
|
|
149
|
+
type: 'SizeValue',
|
|
150
|
+
description:
|
|
151
|
+
'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.',
|
|
152
|
+
},
|
|
132
153
|
],
|
|
133
154
|
theming: {
|
|
134
155
|
targets: [
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
{
|
|
157
|
+
className: 'astryx-switch',
|
|
158
|
+
visualProps: ['size'],
|
|
159
|
+
states: ['checked', 'disabled'],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
className: 'astryx-switch-thumb',
|
|
163
|
+
visualProps: ['size'],
|
|
164
|
+
states: ['checked'],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
className: 'astryx-switch-field',
|
|
168
|
+
visualProps: ['labelPosition', 'labelSpacing'],
|
|
169
|
+
},
|
|
138
170
|
],
|
|
139
171
|
},
|
|
140
172
|
usage: {
|
|
141
173
|
description:
|
|
142
174
|
'A toggle control for on/off states that take effect immediately. Supports labels, descriptions, loading states, and validation. Use it for settings or preferences that apply instantly. For changes requiring a form submission, use a checkbox instead.',
|
|
143
175
|
bestPractices: [
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
176
|
+
{
|
|
177
|
+
guidance: true,
|
|
178
|
+
description:
|
|
179
|
+
'Use for settings that apply immediately; the toggle should take effect without a separate save action.',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
guidance: true,
|
|
183
|
+
description:
|
|
184
|
+
'Pair with a clear, concise label that describes the setting being controlled.',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
guidance: false,
|
|
188
|
+
description:
|
|
189
|
+
'Use for options that require a form submission to take effect; use a checkbox instead.',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
guidance: false,
|
|
193
|
+
description:
|
|
194
|
+
"Use a switch for multi-state values; it's strictly on/off.",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
guidance: false,
|
|
198
|
+
description:
|
|
199
|
+
'Wrap a disabled switch in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.',
|
|
200
|
+
},
|
|
149
201
|
],
|
|
150
202
|
},
|
|
151
203
|
};
|
|
@@ -163,8 +215,7 @@ export const docsZh = {
|
|
|
163
215
|
{
|
|
164
216
|
name: 'label',
|
|
165
217
|
type: 'string',
|
|
166
|
-
description:
|
|
167
|
-
'开关的标签文本(始终渲染以确保无障碍性)。',
|
|
218
|
+
description: '开关的标签文本(始终渲染以确保无障碍性)。',
|
|
168
219
|
required: true,
|
|
169
220
|
},
|
|
170
221
|
{
|
|
@@ -187,15 +238,13 @@ export const docsZh = {
|
|
|
187
238
|
{
|
|
188
239
|
name: 'isLoading',
|
|
189
240
|
type: 'boolean',
|
|
190
|
-
description:
|
|
191
|
-
'开关是否处于加载状态,在滑块内显示旋转器。',
|
|
241
|
+
description: '开关是否处于加载状态,在滑块内显示旋转器。',
|
|
192
242
|
default: 'false',
|
|
193
243
|
},
|
|
194
244
|
{
|
|
195
245
|
name: 'isLabelHidden',
|
|
196
246
|
type: 'boolean',
|
|
197
|
-
description:
|
|
198
|
-
'视觉上隐藏标签,同时保持屏幕阅读器的无障碍性。',
|
|
247
|
+
description: '视觉上隐藏标签,同时保持屏幕阅读器的无障碍性。',
|
|
199
248
|
default: 'false',
|
|
200
249
|
},
|
|
201
250
|
{
|
|
@@ -212,7 +261,8 @@ export const docsZh = {
|
|
|
212
261
|
{
|
|
213
262
|
name: 'htmlName',
|
|
214
263
|
type: 'string',
|
|
215
|
-
description:
|
|
264
|
+
description:
|
|
265
|
+
'底层复选框输入的 HTML name 属性,用于表单提交(开启时提交 "on")。',
|
|
216
266
|
},
|
|
217
267
|
{
|
|
218
268
|
name: 'disabledMessage',
|
|
@@ -223,15 +273,13 @@ export const docsZh = {
|
|
|
223
273
|
{
|
|
224
274
|
name: 'isOptional',
|
|
225
275
|
type: 'boolean',
|
|
226
|
-
description:
|
|
227
|
-
'字段是否为可选。与 isRequired 互斥。',
|
|
276
|
+
description: '字段是否为可选。与 isRequired 互斥。',
|
|
228
277
|
default: 'false',
|
|
229
278
|
},
|
|
230
279
|
{
|
|
231
280
|
name: 'isRequired',
|
|
232
281
|
type: 'boolean',
|
|
233
|
-
description:
|
|
234
|
-
'开关是否为必填。与 isOptional 互斥。',
|
|
282
|
+
description: '开关是否为必填。与 isOptional 互斥。',
|
|
235
283
|
default: 'false',
|
|
236
284
|
},
|
|
237
285
|
{
|
|
@@ -258,14 +306,12 @@ export const docsZh = {
|
|
|
258
306
|
{
|
|
259
307
|
name: 'labelTooltip',
|
|
260
308
|
type: 'string',
|
|
261
|
-
description:
|
|
262
|
-
'在标签末尾的信息图标中显示的工具提示文本。',
|
|
309
|
+
description: '在标签末尾的信息图标中显示的工具提示文本。',
|
|
263
310
|
},
|
|
264
311
|
{
|
|
265
312
|
name: 'labelPosition',
|
|
266
313
|
type: "'start' | 'end'",
|
|
267
|
-
description:
|
|
268
|
-
'标签出现在开关的哪一侧。"start" 将标签放在开关前面。',
|
|
314
|
+
description: '标签出现在开关的哪一侧。"start" 将标签放在开关前面。',
|
|
269
315
|
default: "'end'",
|
|
270
316
|
},
|
|
271
317
|
{
|
|
@@ -278,20 +324,51 @@ export const docsZh = {
|
|
|
278
324
|
],
|
|
279
325
|
theming: {
|
|
280
326
|
targets: [
|
|
281
|
-
{
|
|
282
|
-
|
|
283
|
-
|
|
327
|
+
{
|
|
328
|
+
className: 'astryx-switch',
|
|
329
|
+
visualProps: ['size'],
|
|
330
|
+
states: ['checked', 'disabled'],
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
className: 'astryx-switch-thumb',
|
|
334
|
+
visualProps: ['size'],
|
|
335
|
+
states: ['checked'],
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
className: 'astryx-switch-field',
|
|
339
|
+
visualProps: ['labelPosition', 'labelSpacing'],
|
|
340
|
+
},
|
|
284
341
|
],
|
|
285
342
|
},
|
|
286
343
|
usage: {
|
|
287
344
|
description:
|
|
288
345
|
'A toggle control for on/off states that take effect immediately. Supports labels, descriptions, loading states, and validation. Use it for settings or preferences that apply instantly. For changes requiring a form submission, use a checkbox instead.',
|
|
289
346
|
bestPractices: [
|
|
290
|
-
{
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
347
|
+
{
|
|
348
|
+
guidance: true,
|
|
349
|
+
description:
|
|
350
|
+
'Use for settings that apply immediately; the toggle should take effect without a separate save action.',
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
guidance: true,
|
|
354
|
+
description:
|
|
355
|
+
'Pair with a clear, concise label that describes the setting being controlled.',
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
guidance: false,
|
|
359
|
+
description:
|
|
360
|
+
'Use for options that require a form submission to take effect; use a checkbox instead.',
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
guidance: false,
|
|
364
|
+
description:
|
|
365
|
+
"Use a switch for multi-state values; it's strictly on/off.",
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
guidance: false,
|
|
369
|
+
description:
|
|
370
|
+
'Wrap a disabled switch in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.',
|
|
371
|
+
},
|
|
295
372
|
],
|
|
296
373
|
},
|
|
297
374
|
};
|
|
@@ -303,11 +380,31 @@ export const docsDense = {
|
|
|
303
380
|
description:
|
|
304
381
|
'A toggle control for on/off states that take effect immediately. Supports labels, descriptions, loading states, and validation. Use it for settings or preferences that apply instantly. For changes requiring a form submission, use a checkbox instead.',
|
|
305
382
|
bestPractices: [
|
|
306
|
-
{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
383
|
+
{
|
|
384
|
+
guidance: true,
|
|
385
|
+
description:
|
|
386
|
+
'Use for settings that apply immediately; the toggle should take effect without a separate save action.',
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
guidance: true,
|
|
390
|
+
description:
|
|
391
|
+
'Pair with a clear, concise label that describes the setting being controlled.',
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
guidance: false,
|
|
395
|
+
description:
|
|
396
|
+
'Use for options that require a form submission to take effect; use a checkbox instead.',
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
guidance: false,
|
|
400
|
+
description:
|
|
401
|
+
"Use a switch for multi-state values; it's strictly on/off.",
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
guidance: false,
|
|
405
|
+
description:
|
|
406
|
+
'Wrap a disabled switch in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.',
|
|
407
|
+
},
|
|
311
408
|
],
|
|
312
409
|
},
|
|
313
410
|
propDescriptions: {
|
|
@@ -315,7 +412,8 @@ export const docsDense = {
|
|
|
315
412
|
label: 'Label text (always rendered for a11y).',
|
|
316
413
|
value: 'Whether switch is on or off.',
|
|
317
414
|
onChange: 'Fired when switch state changes.',
|
|
318
|
-
changeAction:
|
|
415
|
+
changeAction:
|
|
416
|
+
'Async action after onChange; triggers optimistic UI + loading spinner until resolved.',
|
|
319
417
|
isLoading: 'Loading state; shows spinner in thumb.',
|
|
320
418
|
isLabelHidden: 'Visually hides label; still accessible to screen readers.',
|
|
321
419
|
description: 'Description text below label.',
|
|
@@ -323,12 +421,14 @@ export const docsDense = {
|
|
|
323
421
|
htmlName: 'HTML name attr for the checkbox; submits "on" when on.',
|
|
324
422
|
isOptional: 'Whether field is optional; mutually exclusive w/ isRequired.',
|
|
325
423
|
isRequired: 'Whether switch is required; mutually exclusive w/ isOptional.',
|
|
326
|
-
status:
|
|
424
|
+
status:
|
|
425
|
+
'Status indicator w/ type + message; colored message box, sets aria-invalid on error.',
|
|
327
426
|
onFocus: 'Fired when switch receives focus.',
|
|
328
427
|
onBlur: 'Fired when switch loses focus.',
|
|
329
428
|
labelIcon: 'Icon before label text.',
|
|
330
429
|
labelTooltip: 'Tooltip text in info icon at label end.',
|
|
331
430
|
labelPosition: 'Which side label appears; "start" places before switch.',
|
|
332
|
-
labelSpacing:
|
|
431
|
+
labelSpacing:
|
|
432
|
+
'Spacing behavior; "hug" places next to each other, "spread" pushes to opposite ends (full width). "default" is deprecated alias for "hug".',
|
|
333
433
|
},
|
|
334
|
-
};
|
|
434
|
+
};
|