@astryxdesign/core 0.1.6 → 0.1.7-canary.04cd8f7
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 +68 -0
- package/README.md +25 -14
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +4 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +4 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +8 -6
- package/dist/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.js +4 -1
- package/dist/Button/Button.d.ts +10 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +49 -6
- package/dist/ButtonGroup/ButtonGroup.d.ts +20 -5
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +27 -11
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +29 -7
- package/dist/Carousel/Carousel.d.ts +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +8 -5
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +4 -1
- package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +9 -2
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +6 -2
- package/dist/Chat/ChatLayout.d.ts +1 -11
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +6 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -2
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +8 -2
- package/dist/Chat/ChatMessageBubble.d.ts +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +3 -1
- package/dist/Chat/ChatMessageList.d.ts +1 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +3 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +13 -8
- package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
- package/dist/Chat/ChatPastedTextToken.js +3 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +3 -1
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +12 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +43 -6
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -2
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +4 -2
- package/dist/CheckboxList/CheckboxList.d.ts +1 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +3 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +3 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +71 -53
- package/dist/Collapsible/Collapsible.d.ts +11 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +36 -4
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +8 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +4 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteList.js +4 -1
- package/dist/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +8 -4
- package/dist/ContextMenu/index.d.ts +3 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +7 -1
- package/dist/DateInput/DateInput.d.ts +1 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +10 -5
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +11 -6
- package/dist/DateTimeInput/DateTimeInput.d.ts +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +15 -7
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +15 -12
- package/dist/Dialog/DialogHeader.d.ts +1 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +7 -3
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +19 -9
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +89 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +170 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +70 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +10 -1
- package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemRoles.js +15 -0
- package/dist/EmptyState/EmptyState.d.ts +4 -1
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +11 -1
- package/dist/Icon/Icon.d.ts +17 -12
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +28 -20
- package/dist/Kbd/Kbd.js +1 -1
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +23 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +6 -4
- package/dist/Link/Link.d.ts +5 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +32 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +10 -8
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +4 -2
- package/dist/MobileNav/MobileNavToggle.d.ts +1 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -1
- package/dist/MoreMenu/MoreMenu.d.ts +1 -1
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +13 -6
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +5 -1
- package/dist/Outline/Outline.d.ts +1 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +4 -1
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +38 -11
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +4 -1
- package/dist/PowerSearch/PowerSearch.d.ts +1 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +22 -12
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +26 -20
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +7 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +34 -21
- package/dist/PowerSearch/formatFilterValue.d.ts +2 -1
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +19 -9
- package/dist/PowerSearch/index.d.ts +2 -1
- package/dist/PowerSearch/index.d.ts.map +1 -1
- package/dist/PowerSearch/index.js +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts +23 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts.map +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.js +28 -0
- package/dist/PowerSearch/types.d.ts +28 -2
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.js +27 -27
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +15 -8
- package/dist/Resizable/ResizeHandle.d.ts +1 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +4 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +52 -14
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -2
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +3 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -3
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +7 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +4 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +6 -1
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +5 -3
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +56 -19
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +12 -5
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -3
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +8 -6
- package/dist/Table/plugins/rowIndex/useTableRowIndex.d.ts +1 -1
- package/dist/Table/plugins/rowIndex/useTableRowIndex.js +1 -1
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +5 -2
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +6 -4
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +2 -2
- package/dist/Table/plugins/tree/index.d.ts +5 -0
- package/dist/Table/plugins/tree/index.d.ts.map +1 -0
- package/dist/Table/plugins/tree/index.js +4 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +38 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeData.js +358 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +51 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeState.js +175 -0
- package/dist/Table/types.d.ts +17 -10
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +6 -3
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +5 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +8 -2
- package/dist/TimeInput/TimeInput.d.ts +1 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +7 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +18 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +3 -1
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +3 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +8 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +3 -1
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +8 -1
- package/dist/TopNav/TopNav.d.ts +2 -1
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +4 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +5 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +7 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +8 -4
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +1 -0
- package/dist/astryx.css +38 -4
- package/dist/astryx.umd.js +62 -60
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts +145 -0
- package/dist/authoring/doc.d.ts.map +1 -0
- package/dist/authoring/doc.js +100 -0
- package/dist/authoring/index.d.ts +29 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/index.js +28 -0
- package/dist/authoring/integration.d.ts +35 -0
- package/dist/authoring/integration.d.ts.map +1 -0
- package/dist/authoring/integration.js +30 -0
- package/dist/authoring/template.d.ts +66 -0
- package/dist/authoring/template.d.ts.map +1 -0
- package/dist/authoring/template.js +55 -0
- package/dist/config.d.ts +80 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/docs-types.d.ts +13 -4
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.d.ts +12 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -0
- package/dist/i18n/InternationalizationContext.js +29 -0
- package/dist/i18n/InternationalizationProvider.d.ts +61 -0
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -0
- package/dist/i18n/InternationalizationProvider.js +44 -0
- package/dist/i18n/index.d.ts +24 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +21 -0
- package/dist/i18n/resolve.d.ts +22 -0
- package/dist/i18n/resolve.d.ts.map +1 -0
- package/dist/i18n/resolve.js +141 -0
- package/dist/i18n/translator.d.ts +25 -0
- package/dist/i18n/translator.d.ts.map +1 -0
- package/dist/i18n/translator.js +1 -0
- package/dist/i18n/types.d.ts +47 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +1 -0
- package/dist/i18n/useTranslator.d.ts +15 -0
- package/dist/i18n/useTranslator.d.ts.map +1 -0
- package/dist/i18n/useTranslator.js +39 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/theme/Theme.js +1 -1
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +0 -3
- package/dist/utils/color.d.ts +13 -1
- package/dist/utils/color.d.ts.map +1 -1
- package/dist/utils/color.js +23 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/locales/en.json +754 -0
- package/locales/pseudo.json +566 -0
- package/package.json +23 -2
- package/src/AlertDialog/AlertDialog.doc.mjs +5 -0
- package/src/AlertDialog/AlertDialog.tsx +4 -1
- package/src/AppShell/AppShell.doc.mjs +8 -2
- package/src/AppShell/AppShell.tsx +3 -1
- package/src/AvatarGroup/AvatarGroup.tsx +4 -1
- package/src/Banner/Banner.tsx +10 -5
- package/src/Breadcrumbs/Breadcrumbs.tsx +4 -1
- package/src/Button/Button.doc.mjs +8 -0
- package/src/Button/Button.test.tsx +27 -0
- package/src/Button/Button.tsx +51 -5
- package/src/ButtonGroup/ButtonGroup.test.tsx +386 -2
- package/src/ButtonGroup/ButtonGroup.tsx +27 -11
- package/src/Calendar/Calendar.test.tsx +103 -2
- package/src/Calendar/Calendar.tsx +29 -6
- package/src/Card/Card.doc.mjs +3 -3
- package/src/Carousel/Carousel.tsx +10 -7
- package/src/Chat/ChatComposer.tsx +5 -1
- package/src/Chat/ChatComposerDrawer.tsx +9 -2
- package/src/Chat/ChatComposerInput.tsx +10 -4
- package/src/Chat/ChatLayout.test.tsx +127 -2
- package/src/Chat/ChatLayout.tsx +5 -12
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -2
- package/src/Chat/ChatMessage.tsx +5 -1
- package/src/Chat/ChatMessageBubble.tsx +2 -0
- package/src/Chat/ChatMessageList.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.tsx +2 -0
- package/src/Chat/ChatMessageMetadata.tsx +15 -9
- package/src/Chat/ChatPastedTextToken.tsx +3 -1
- package/src/Chat/ChatSendButton.tsx +3 -1
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/index.ts +1 -0
- package/src/Chat/useChatStreamScroll.test.tsx +168 -0
- package/src/Chat/useChatStreamScroll.ts +67 -11
- package/src/Chat/useSpeechRecognition.ts +11 -2
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +16 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -2
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -1
- package/src/CheckboxList/CheckboxList.tsx +2 -0
- package/src/CheckboxList/CheckboxListItem.tsx +7 -1
- package/src/Citation/Citation.tsx +4 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +1 -1
- package/src/CodeBlock/CodeBlock.tsx +91 -40
- package/src/Collapsible/Collapsible.doc.mjs +7 -0
- package/src/Collapsible/Collapsible.test.tsx +80 -0
- package/src/Collapsible/Collapsible.tsx +58 -5
- package/src/CommandPalette/CommandPalette.tsx +10 -3
- package/src/CommandPalette/CommandPaletteInput.test.tsx +1 -1
- package/src/CommandPalette/CommandPaletteInput.tsx +5 -1
- package/src/CommandPalette/CommandPaletteList.tsx +4 -1
- package/src/ContextMenu/ContextMenu.test.tsx +75 -1
- package/src/ContextMenu/ContextMenu.tsx +14 -6
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateInput/DateInput.doc.mjs +2 -2
- package/src/DateInput/DateInput.test.tsx +17 -5
- package/src/DateInput/DateInput.tsx +13 -5
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.tsx +14 -6
- package/src/DateTimeInput/DateTimeInput.doc.mjs +2 -2
- package/src/DateTimeInput/DateTimeInput.tsx +17 -7
- package/src/Dialog/Dialog.tsx +11 -15
- package/src/Dialog/DialogHeader.tsx +7 -3
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +23 -14
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +237 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +7 -1
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +119 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
- package/src/DropdownMenu/index.ts +23 -3
- package/src/DropdownMenu/menuItemRoles.ts +22 -0
- package/src/EmptyState/EmptyState.doc.mjs +3 -3
- package/src/EmptyState/EmptyState.tsx +4 -1
- package/src/Field/Field.doc.mjs +3 -3
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/FileInput/FileInput.test.tsx +40 -1
- package/src/FileInput/FileInput.tsx +12 -1
- package/src/Grid/Grid.doc.mjs +5 -5
- package/src/Icon/Icon.test.tsx +46 -0
- package/src/Icon/Icon.tsx +37 -24
- package/src/InputGroup/InputGroup.doc.mjs +1 -1
- package/src/Kbd/Kbd.test.tsx +26 -0
- package/src/Kbd/Kbd.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +8 -5
- package/src/Layer/useLayer.test.tsx +136 -1
- package/src/Layer/useLayer.tsx +34 -2
- package/src/Lightbox/Lightbox.doc.mjs +7 -2
- package/src/Lightbox/Lightbox.tsx +6 -4
- package/src/Link/Link.test.tsx +74 -2
- package/src/Link/Link.tsx +48 -1
- package/src/Markdown/Markdown.tsx +12 -4
- package/src/MobileNav/MobileNav.tsx +4 -2
- package/src/MobileNav/MobileNavToggle.tsx +5 -3
- package/src/MoreMenu/MoreMenu.tsx +4 -1
- package/src/MultiSelector/MultiSelector.tsx +14 -5
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/NumberInput/NumberInput.tsx +3 -1
- package/src/Outline/Outline.tsx +4 -1
- package/src/OverflowList/OverflowList.doc.mjs +2 -2
- package/src/Pagination/Pagination.tsx +35 -12
- package/src/Popover/usePopover.tsx +6 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +9 -4
- package/src/PowerSearch/PowerSearch.tsx +22 -10
- package/src/PowerSearch/PowerSearchEditPopover.tsx +27 -20
- package/src/PowerSearch/PowerSearchToken.tsx +17 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +34 -21
- package/src/PowerSearch/formatFilterValue.test.ts +282 -0
- package/src/PowerSearch/formatFilterValue.ts +21 -8
- package/src/PowerSearch/index.ts +5 -0
- package/src/PowerSearch/resolveOperatorLabel.ts +34 -0
- package/src/PowerSearch/types.ts +33 -9
- package/src/PowerSearch/usePowerSearchConfig.ts +59 -27
- package/src/PowerSearch/usePowerSearchSource.ts +17 -8
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/Resizable/ResizeHandle.tsx +4 -1
- package/src/Section/Section.doc.mjs +4 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +6 -3
- package/src/Selector/Selector.test.tsx +114 -6
- package/src/Selector/Selector.tsx +68 -17
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavCollapseButton.tsx +3 -1
- package/src/SideNav/SideNavHeading.tsx +5 -3
- package/src/SideNav/SideNavItem.doc.mjs +2 -2
- package/src/SideNav/SideNavItem.tsx +3 -1
- package/src/Slider/Slider.doc.mjs +2 -2
- package/src/Stack/Stack.doc.mjs +10 -10
- package/src/Switch/Switch.doc.mjs +3 -3
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +4 -2
- package/src/TabList/Tab.tsx +5 -1
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/TabList.tsx +12 -1
- package/src/TabList/TabMenu.tsx +4 -1
- package/src/Table/BaseTable.tsx +36 -19
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +132 -1
- package/src/Table/Table.tsx +6 -4
- package/src/Table/index.ts +7 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.tsx +31 -30
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +7 -5
- package/src/Table/plugins/pagination/useTablePagination.tsx +4 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -8
- package/src/Table/plugins/rowIndex/useTableRowIndex.tsx +1 -1
- package/src/Table/plugins/selection/useTableSelection.tsx +6 -7
- package/src/Table/plugins/sortable/useTableSortable.tsx +8 -5
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +4 -4
- package/src/Table/plugins/tree/index.ts +12 -0
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +163 -0
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +594 -0
- package/src/Table/plugins/tree/useTableTreeData.tsx +495 -0
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +636 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +253 -0
- package/src/Table/types.ts +18 -12
- package/src/Table/useBaseTablePlugins.ts +6 -2
- package/src/Table/useTableFiltering.doc.mjs +2 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTableSortable.doc.mjs +11 -11
- package/src/Table/useTableTreeData.doc.mjs +75 -0
- package/src/Table/useTableTreeState.doc.mjs +98 -0
- package/src/Text/Text.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.doc.mjs +2 -2
- package/src/TimeInput/TimeInput.tsx +6 -2
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +120 -7
- package/src/Timestamp/Timestamp.tsx +21 -1
- package/src/Toast/Toast.tsx +3 -1
- package/src/Toast/ToastViewport.tsx +3 -1
- package/src/Token/Token.tsx +4 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.tsx +4 -4
- package/src/Toolbar/Toolbar.doc.mjs +1 -1
- package/src/Toolbar/Toolbar.tsx +10 -3
- package/src/TopNav/TopNav.doc.mjs +1 -0
- package/src/TopNav/TopNav.test.tsx +30 -0
- package/src/TopNav/TopNav.tsx +6 -4
- package/src/TopNav/TopNavHeading.tsx +5 -3
- package/src/TreeList/TreeList.tsx +5 -1
- package/src/TreeList/TreeListItem.tsx +6 -1
- package/src/Typeahead/BaseTypeahead.tsx +11 -4
- package/src/Typeahead/Typeahead.doc.mjs +1 -1
- package/src/Typeahead/Typeahead.tsx +3 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
- package/src/authoring/doc.ts +166 -0
- package/src/authoring/index.test.ts +52 -0
- package/src/authoring/index.ts +50 -0
- package/src/authoring/integration.ts +42 -0
- package/src/authoring/template.ts +74 -0
- package/src/config.test.ts +16 -0
- package/src/config.ts +92 -0
- package/src/docPropLiterals.test.ts +938 -0
- package/src/docs-types.ts +15 -10
- package/src/i18n/InternationalizationContext.ts +39 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +72 -0
- package/src/i18n/InternationalizationProvider.tsx +82 -0
- package/src/i18n/__tests__/e2e-pagination.test.tsx +172 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +130 -0
- package/src/i18n/__tests__/resolve.test.ts +284 -0
- package/src/i18n/index.ts +32 -0
- package/src/i18n/resolve.ts +165 -0
- package/src/i18n/translator.ts +31 -0
- package/src/i18n/types.ts +53 -0
- package/src/i18n/useTranslator.doc.mjs +46 -0
- package/src/i18n/useTranslator.ts +50 -0
- package/src/index.ts +3 -0
- package/src/theme/Theme.doc.mjs +4 -4
- package/src/theme/Theme.tsx +1 -1
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/hct.ts +0 -4
- package/src/utils/color.test.ts +101 -1
- package/src/utils/color.ts +23 -1
- package/src/utils/index.ts +8 -1
- package/dist/NavItem/index.d.ts +0 -9
- package/dist/NavItem/index.d.ts.map +0 -1
- package/dist/NavItem/index.js +0 -10
- package/src/NavItem/index.ts +0 -11
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file ButtonGroup.test.tsx
|
|
5
|
-
* @input Uses vitest, @testing-library/react,
|
|
6
|
-
*
|
|
5
|
+
* @input Uses vitest, @testing-library/react, @babel/core + @stylexjs/babel-plugin,
|
|
6
|
+
* ButtonGroup and Button components
|
|
7
|
+
* @output Unit tests for ButtonGroup, incl. the compiled-CSS contract for the
|
|
8
|
+
* trailing radius (#2508)
|
|
7
9
|
* @position Testing; validates ButtonGroup component implementation
|
|
8
10
|
*
|
|
9
11
|
* SYNC: When ButtonGroup component changes, update tests to match new behavior
|
|
@@ -11,9 +13,16 @@
|
|
|
11
13
|
|
|
12
14
|
import {describe, it, expect} from 'vitest';
|
|
13
15
|
import {render, screen} from '@testing-library/react';
|
|
16
|
+
import {transformSync} from '@babel/core';
|
|
17
|
+
import stylexBabelPlugin from '@stylexjs/babel-plugin';
|
|
18
|
+
import {readFileSync} from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
14
20
|
import {ButtonGroup} from './ButtonGroup';
|
|
15
21
|
import {Button} from '../Button';
|
|
16
22
|
import {IconButton} from '../IconButton';
|
|
23
|
+
import {DropdownMenu} from '../DropdownMenu';
|
|
24
|
+
import {Tooltip} from '../Tooltip';
|
|
25
|
+
import {HoverCard} from '../HoverCard';
|
|
17
26
|
|
|
18
27
|
describe('ButtonGroup', () => {
|
|
19
28
|
it('renders a group with aria-label', () => {
|
|
@@ -188,4 +197,379 @@ describe('ButtonGroup', () => {
|
|
|
188
197
|
screen.getByRole('button', {name: 'More options'}),
|
|
189
198
|
).toBeInTheDocument();
|
|
190
199
|
});
|
|
200
|
+
|
|
201
|
+
// ===========================================================================
|
|
202
|
+
// Trailing radius (issue #2508)
|
|
203
|
+
//
|
|
204
|
+
// The trailing end cap cannot be keyed off `:last-child`: members render an
|
|
205
|
+
// invisible layer AFTER their button (tooltip'd Button, DropdownMenu), and
|
|
206
|
+
// useLayer renders it inline rather than portaling it, so the layer steals the
|
|
207
|
+
// slot. See IS_LAST_ITEM in Button.tsx.
|
|
208
|
+
//
|
|
209
|
+
// HOW THESE TESTS CATCH THE BUG
|
|
210
|
+
// jsdom applies no StyleX CSS, so a DOM-only test cannot prove which rule
|
|
211
|
+
// wins — and a test that hand-copies the selector is a tautology (revert
|
|
212
|
+
// groupStyles to `:last-child` and it still passes). So the predicate is NOT
|
|
213
|
+
// hand-copied here: `compileButtonRules()` runs the REAL StyleX babel plugin
|
|
214
|
+
// over Button.tsx (same config as scripts/build-css.mjs) and reads the
|
|
215
|
+
// trailing-radius rule's selector straight out of the emitted CSS, then
|
|
216
|
+
// matches it against the real rendered DOM. Revert groupStyles to
|
|
217
|
+
// `:last-child` and these go red.
|
|
218
|
+
// ===========================================================================
|
|
219
|
+
describe('trailing radius (#2508)', () => {
|
|
220
|
+
/** The group members, in DOM order (excludes invisible layer siblings). */
|
|
221
|
+
const items = (group: HTMLElement): Element[] =>
|
|
222
|
+
Array.from(group.querySelectorAll(':scope > *:not([popover])'));
|
|
223
|
+
|
|
224
|
+
// -- Compiled CSS, read from the source -----------------------------------
|
|
225
|
+
|
|
226
|
+
/** One atomic StyleX rule, parsed out of the plugin's emitted CSS. */
|
|
227
|
+
type CompiledRule = {
|
|
228
|
+
/** Atomic class name, e.g. `xp0wexf`. */
|
|
229
|
+
className: string;
|
|
230
|
+
/** Selector text after the class, e.g. `:first-child`. '' if unconditional. */
|
|
231
|
+
condition: string;
|
|
232
|
+
/** CSS property, e.g. `border-start-end-radius`. */
|
|
233
|
+
property: string;
|
|
234
|
+
/** CSS value, e.g. `var(--radius-element)`. */
|
|
235
|
+
value: string;
|
|
236
|
+
/** The full compiled selector, e.g. `.xp0wexf:not(:has(~ [data-...]))`. */
|
|
237
|
+
selector: string;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Compiles Button.tsx with the real StyleX babel plugin and returns its
|
|
242
|
+
* atomic rules. This is the CSS the browser actually gets — the whole point
|
|
243
|
+
* is that the trailing-radius predicate comes from the SOURCE, never from a
|
|
244
|
+
* string retyped in this file.
|
|
245
|
+
*/
|
|
246
|
+
function compileButtonRules(): CompiledRule[] {
|
|
247
|
+
const repoRoot = path.resolve(__dirname, '../../../..');
|
|
248
|
+
const buttonSrc = path.resolve(__dirname, '../Button/Button.tsx');
|
|
249
|
+
|
|
250
|
+
const result = transformSync(readFileSync(buttonSrc, 'utf8'), {
|
|
251
|
+
babelrc: false,
|
|
252
|
+
configFile: false,
|
|
253
|
+
filename: buttonSrc,
|
|
254
|
+
presets: [
|
|
255
|
+
['@babel/preset-typescript', {isTSX: true, allExtensions: true}],
|
|
256
|
+
['@babel/preset-react', {runtime: 'automatic'}],
|
|
257
|
+
],
|
|
258
|
+
plugins: [
|
|
259
|
+
[
|
|
260
|
+
stylexBabelPlugin,
|
|
261
|
+
{
|
|
262
|
+
dev: false,
|
|
263
|
+
runtimeInjection: false,
|
|
264
|
+
genConditionalClasses: true,
|
|
265
|
+
treeshakeCompensation: true,
|
|
266
|
+
unstable_moduleResolution: {type: 'commonJS', rootDir: repoRoot},
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const rules =
|
|
273
|
+
(result?.metadata as {stylex?: [string, {ltr: string}, number][]})
|
|
274
|
+
?.stylex ?? [];
|
|
275
|
+
|
|
276
|
+
return rules.flatMap(([, {ltr}]) => {
|
|
277
|
+
// Plain atomic rules only: `.cls<condition>{prop:value}`. @media-wrapped
|
|
278
|
+
// rules are irrelevant to the radius contract.
|
|
279
|
+
const parsed = /^\.([\w-]+)([^{]*)\{([\w-]+):(.+)\}$/.exec(ltr);
|
|
280
|
+
if (!parsed) {
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
283
|
+
const [, className, condition, property, value] = parsed;
|
|
284
|
+
return [
|
|
285
|
+
{
|
|
286
|
+
className,
|
|
287
|
+
condition,
|
|
288
|
+
property,
|
|
289
|
+
value,
|
|
290
|
+
selector: `.${className}${condition}`,
|
|
291
|
+
},
|
|
292
|
+
];
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const COMPILED = compileButtonRules();
|
|
297
|
+
|
|
298
|
+
/** A rounded (non-zero) corner is exactly this value in the compiled CSS. */
|
|
299
|
+
const ROUNDED = 'var(--radius-element)';
|
|
300
|
+
|
|
301
|
+
/** The two corners on the group's trailing edge — pure geometry. */
|
|
302
|
+
const TRAILING_CORNERS = {
|
|
303
|
+
horizontal: ['border-end-end-radius', 'border-start-end-radius'],
|
|
304
|
+
vertical: ['border-end-end-radius', 'border-end-start-radius'],
|
|
305
|
+
} as const;
|
|
306
|
+
|
|
307
|
+
/** The two corners on the group's leading edge — pure geometry. */
|
|
308
|
+
const LEADING_CORNERS = {
|
|
309
|
+
horizontal: ['border-end-start-radius', 'border-start-start-radius'],
|
|
310
|
+
vertical: ['border-start-end-radius', 'border-start-start-radius'],
|
|
311
|
+
} as const;
|
|
312
|
+
|
|
313
|
+
type Orientation = keyof typeof TRAILING_CORNERS;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* The compiled rules that ROUND `corners` and are actually applied to `el`
|
|
317
|
+
* (its class list carries them). StyleX emits the `default: 0` class and the
|
|
318
|
+
* conditional class on every member, so this returns the same rules for any
|
|
319
|
+
* member of the group — which rule *wins* is decided by the selector, and
|
|
320
|
+
* that is what the tests below assert against the DOM.
|
|
321
|
+
*/
|
|
322
|
+
const roundingRules = (
|
|
323
|
+
el: Element,
|
|
324
|
+
corners: ReadonlyArray<string>,
|
|
325
|
+
): CompiledRule[] =>
|
|
326
|
+
COMPILED.filter(
|
|
327
|
+
rule =>
|
|
328
|
+
corners.includes(rule.property) &&
|
|
329
|
+
rule.value === ROUNDED &&
|
|
330
|
+
el.classList.contains(rule.className),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
/** The compiled selectors that round `el`'s trailing corners. */
|
|
334
|
+
const trailingRoundingSelectors = (
|
|
335
|
+
el: Element,
|
|
336
|
+
orientation: Orientation,
|
|
337
|
+
): string[] => {
|
|
338
|
+
const rules = roundingRules(el, TRAILING_CORNERS[orientation]);
|
|
339
|
+
// Guard against a vacuous pass: both trailing corners must be accounted
|
|
340
|
+
// for, or the assertions below would be quantifying over an empty set.
|
|
341
|
+
expect(rules.map(rule => rule.property).sort()).toEqual([
|
|
342
|
+
...TRAILING_CORNERS[orientation],
|
|
343
|
+
]);
|
|
344
|
+
return rules.map(rule => rule.selector);
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
/** Does the compiled CSS actually round `el`'s trailing corners? */
|
|
348
|
+
const hasRoundedTrailingCorners = (
|
|
349
|
+
el: Element,
|
|
350
|
+
orientation: Orientation = 'horizontal',
|
|
351
|
+
): boolean =>
|
|
352
|
+
trailingRoundingSelectors(el, orientation).every(selector =>
|
|
353
|
+
el.matches(selector),
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// -- The compiled CSS contract --------------------------------------------
|
|
357
|
+
|
|
358
|
+
it.each(['horizontal', 'vertical'] as const)(
|
|
359
|
+
'keys the trailing radius off layer-skipping, not :last-child (%s)',
|
|
360
|
+
orientation => {
|
|
361
|
+
render(
|
|
362
|
+
<ButtonGroup label="Actions" orientation={orientation}>
|
|
363
|
+
<Button label="Save" />
|
|
364
|
+
</ButtonGroup>,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
368
|
+
const selectors = trailingRoundingSelectors(save, orientation);
|
|
369
|
+
|
|
370
|
+
for (const selector of selectors) {
|
|
371
|
+
// `:last-child` is the bug: an inline layer element steals the slot.
|
|
372
|
+
expect(selector).not.toContain(':last-child');
|
|
373
|
+
// `[popover]` must survive compilation *verbatim*. StyleX only
|
|
374
|
+
// statically evaluates a selector key from a same-file const; from a
|
|
375
|
+
// .stylex.ts file it compiles to a mangled selector like `[x13pbwiz]`
|
|
376
|
+
// that matches nothing in the DOM.
|
|
377
|
+
expect(selector).toContain('[popover]');
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
it.each(['horizontal', 'vertical'] as const)(
|
|
383
|
+
'still rounds the leading corners off :first-child (%s)',
|
|
384
|
+
orientation => {
|
|
385
|
+
render(
|
|
386
|
+
<ButtonGroup label="Actions" orientation={orientation}>
|
|
387
|
+
<Button label="Save" />
|
|
388
|
+
<Button label="More" tooltip="More options" />
|
|
389
|
+
</ButtonGroup>,
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
393
|
+
const more = screen.getByRole('button', {name: 'More'});
|
|
394
|
+
const rules = roundingRules(save, LEADING_CORNERS[orientation]);
|
|
395
|
+
|
|
396
|
+
expect(rules.map(rule => rule.property).sort()).toEqual([
|
|
397
|
+
...LEADING_CORNERS[orientation],
|
|
398
|
+
]);
|
|
399
|
+
for (const {condition, selector} of rules) {
|
|
400
|
+
// The leading edge is genuinely safe on :first-child — a member's
|
|
401
|
+
// button always precedes its own layer.
|
|
402
|
+
expect(condition).toBe(':first-child');
|
|
403
|
+
expect(save.matches(selector)).toBe(true);
|
|
404
|
+
expect(more.matches(selector)).toBe(false);
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
// -- The compiled CSS, matched against the real DOM ------------------------
|
|
410
|
+
|
|
411
|
+
it.each(['horizontal', 'vertical'] as const)(
|
|
412
|
+
'rounds a tooltip’d trailing Button, whose layer follows it in the DOM (%s)',
|
|
413
|
+
orientation => {
|
|
414
|
+
render(
|
|
415
|
+
<ButtonGroup label="Actions" orientation={orientation}>
|
|
416
|
+
<Button label="Save" />
|
|
417
|
+
<Button label="More" tooltip="More options" />
|
|
418
|
+
</ButtonGroup>,
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
const group = screen.getByRole('group');
|
|
422
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
423
|
+
const more = screen.getByRole('button', {name: 'More'});
|
|
424
|
+
|
|
425
|
+
// Precondition: the tooltip layer really is an inline DOM sibling that
|
|
426
|
+
// follows the button — this is exactly what broke `:last-child`.
|
|
427
|
+
expect(more).not.toBe(group.lastElementChild);
|
|
428
|
+
expect(items(group).at(-1)).toBe(more);
|
|
429
|
+
|
|
430
|
+
expect(hasRoundedTrailingCorners(more, orientation)).toBe(true);
|
|
431
|
+
expect(hasRoundedTrailingCorners(save, orientation)).toBe(false);
|
|
432
|
+
},
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
it.each(['horizontal', 'vertical'] as const)(
|
|
436
|
+
'rounds a trailing DropdownMenu trigger, whose popover follows it (%s)',
|
|
437
|
+
orientation => {
|
|
438
|
+
render(
|
|
439
|
+
<ButtonGroup label="Approve action" orientation={orientation}>
|
|
440
|
+
<Button label="Allow once" variant="primary" />
|
|
441
|
+
<DropdownMenu
|
|
442
|
+
button={{label: 'Allow options', variant: 'primary'}}
|
|
443
|
+
items={[{label: 'Always allow'}]}
|
|
444
|
+
/>
|
|
445
|
+
</ButtonGroup>,
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
const group = screen.getByRole('group');
|
|
449
|
+
const allow = screen.getByRole('button', {name: 'Allow once'});
|
|
450
|
+
const trigger = screen.getByRole('button', {name: 'Allow options'});
|
|
451
|
+
|
|
452
|
+
// The popover surface is an inline sibling after the trigger.
|
|
453
|
+
expect(trigger).not.toBe(group.lastElementChild);
|
|
454
|
+
expect(items(group).at(-1)).toBe(trigger);
|
|
455
|
+
|
|
456
|
+
expect(hasRoundedTrailingCorners(trigger, orientation)).toBe(true);
|
|
457
|
+
expect(hasRoundedTrailingCorners(allow, orientation)).toBe(false);
|
|
458
|
+
},
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
it('rounds a trailing link (<a>) member with a tooltip', () => {
|
|
462
|
+
render(
|
|
463
|
+
<ButtonGroup label="Actions">
|
|
464
|
+
<Button label="Save" />
|
|
465
|
+
<Button label="Docs" href="https://example.com" tooltip="Open docs" />
|
|
466
|
+
</ButtonGroup>,
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const group = screen.getByRole('group');
|
|
470
|
+
const link = screen.getByRole('link', {name: 'Docs'});
|
|
471
|
+
|
|
472
|
+
expect(link.tagName).toBe('A');
|
|
473
|
+
expect(link).not.toBe(group.lastElementChild);
|
|
474
|
+
expect(items(group).at(-1)).toBe(link);
|
|
475
|
+
|
|
476
|
+
expect(hasRoundedTrailingCorners(link)).toBe(true);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('rounds only the last member (first/middle/last)', () => {
|
|
480
|
+
render(
|
|
481
|
+
<ButtonGroup label="Actions">
|
|
482
|
+
<Button label="First" />
|
|
483
|
+
<Button label="Middle" tooltip="Middle tip" />
|
|
484
|
+
<DropdownMenu
|
|
485
|
+
button={{label: 'Last'}}
|
|
486
|
+
items={[{label: 'An option'}]}
|
|
487
|
+
/>
|
|
488
|
+
</ButtonGroup>,
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
const group = screen.getByRole('group');
|
|
492
|
+
const [first, middle, last] = items(group);
|
|
493
|
+
|
|
494
|
+
expect([first, middle, last].map(el => el.textContent)).toEqual([
|
|
495
|
+
'First',
|
|
496
|
+
'Middle',
|
|
497
|
+
'Last',
|
|
498
|
+
]);
|
|
499
|
+
|
|
500
|
+
// Middle has a tooltip layer after it, but a *marked* sibling follows too,
|
|
501
|
+
// so it must NOT take the trailing radius.
|
|
502
|
+
expect(hasRoundedTrailingCorners(first)).toBe(false);
|
|
503
|
+
expect(hasRoundedTrailingCorners(middle)).toBe(false);
|
|
504
|
+
expect(hasRoundedTrailingCorners(last)).toBe(true);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('rounds both edges of a lone tooltip’d member', () => {
|
|
508
|
+
render(
|
|
509
|
+
<ButtonGroup label="Actions">
|
|
510
|
+
<Button label="Only" tooltip="The only one" />
|
|
511
|
+
</ButtonGroup>,
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
const only = screen.getByRole('button', {name: 'Only'});
|
|
515
|
+
|
|
516
|
+
// Leading edge is unaffected: a member's button always precedes its layer.
|
|
517
|
+
expect(only.matches(':first-child')).toBe(true);
|
|
518
|
+
expect(hasRoundedTrailingCorners(only)).toBe(true);
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// -- Members the group does not recognise ---------------------------------
|
|
522
|
+
//
|
|
523
|
+
// The trailing predicate must stay CONSERVATIVE: a sibling the group does
|
|
524
|
+
// not understand is still a member. Otherwise the button BEFORE it wrongly
|
|
525
|
+
// takes the trailing radius and renders as a rounded notch mid-group —
|
|
526
|
+
// worse than the bug being fixed, because it is silent and visual.
|
|
527
|
+
|
|
528
|
+
it('does not round the preceding button when a Tooltip-wrapped member follows', () => {
|
|
529
|
+
render(
|
|
530
|
+
<ButtonGroup label="Actions">
|
|
531
|
+
<Button label="Save" />
|
|
532
|
+
<Tooltip content="Rich tip">
|
|
533
|
+
<Button label="More" />
|
|
534
|
+
</Tooltip>
|
|
535
|
+
</ButtonGroup>,
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
539
|
+
|
|
540
|
+
// Tooltip wraps element children in a `display: contents` <div>, so the
|
|
541
|
+
// inner Button is a DESCENDANT of the wrapper, not a DOM sibling of Save.
|
|
542
|
+
expect(hasRoundedTrailingCorners(save)).toBe(false);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
it('does not round the preceding button when a HoverCard-wrapped member follows', () => {
|
|
546
|
+
render(
|
|
547
|
+
<ButtonGroup label="Actions">
|
|
548
|
+
<Button label="Save" />
|
|
549
|
+
<HoverCard content="Preview">
|
|
550
|
+
<Button label="More" />
|
|
551
|
+
</HoverCard>
|
|
552
|
+
</ButtonGroup>,
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
556
|
+
|
|
557
|
+
// Button has no `hoverCard` prop, so wrapping is the ONLY way to put a
|
|
558
|
+
// HoverCard on a group button — this composition has no alternative.
|
|
559
|
+
expect(hasRoundedTrailingCorners(save)).toBe(false);
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it('does not round the preceding button when a raw <button> follows', () => {
|
|
563
|
+
render(
|
|
564
|
+
<ButtonGroup label="Actions">
|
|
565
|
+
<Button label="Save" />
|
|
566
|
+
<button type="button">Custom</button>
|
|
567
|
+
</ButtonGroup>,
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
const save = screen.getByRole('button', {name: 'Save'});
|
|
571
|
+
|
|
572
|
+
expect(hasRoundedTrailingCorners(save)).toBe(false);
|
|
573
|
+
});
|
|
574
|
+
});
|
|
191
575
|
});
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* @output Exports ButtonGroup component, context, and types
|
|
9
9
|
* @position Groups buttons with connected styling; consumed by index.ts
|
|
10
10
|
*
|
|
11
|
-
* Children (Button, IconButton) consume the ButtonGroup context to
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Children (Button, IconButton) consume the ButtonGroup context to apply
|
|
12
|
+
* position-aware styles in pure CSS — no cloneElement or wrapper divs needed.
|
|
13
|
+
* The end-cap radius rules live in Button.tsx; see IS_LAST_ITEM there for why
|
|
14
|
+
* the trailing edge cannot use :last-child (#2508).
|
|
14
15
|
*
|
|
15
16
|
* SYNC: When modified, update these files to stay in sync:
|
|
16
17
|
* - /packages/core/src/ButtonGroup/ButtonGroup.doc.mjs (props table, features)
|
|
@@ -25,7 +26,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
25
26
|
import type {ButtonSize} from '../Button';
|
|
26
27
|
import {SizeProvider, useSize} from '../SizeContext/SizeContext';
|
|
27
28
|
import {useListFocus} from '../hooks/useListFocus';
|
|
28
|
-
import {mergeProps, mergeRefs} from '../utils';
|
|
29
|
+
import {mergeProps, mergeRefs, composeEventHandlers} from '../utils';
|
|
29
30
|
import type {BaseProps} from '../BaseProps';
|
|
30
31
|
import {ButtonGroupContext} from './ButtonGroupContext';
|
|
31
32
|
import type {ButtonGroupOrientation} from './ButtonGroupContext';
|
|
@@ -97,7 +98,10 @@ const styles = stylex.create({
|
|
|
97
98
|
* handling (only on outer edges), and horizontal or vertical orientation.
|
|
98
99
|
*
|
|
99
100
|
* Children automatically detect the group via context and apply position-aware
|
|
100
|
-
* styles
|
|
101
|
+
* styles in pure CSS.
|
|
102
|
+
*
|
|
103
|
+
* Members that render their own layer — a Button with a `tooltip`, or a
|
|
104
|
+
* DropdownMenu — compose correctly, including as the trailing member.
|
|
101
105
|
*
|
|
102
106
|
* @example
|
|
103
107
|
* ```
|
|
@@ -107,6 +111,17 @@ const styles = stylex.create({
|
|
|
107
111
|
* <Button label="Paste" />
|
|
108
112
|
* </ButtonGroup>
|
|
109
113
|
* ```
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```
|
|
117
|
+
* <ButtonGroup label="Approve action">
|
|
118
|
+
* <Button label="Allow once" variant="primary" />
|
|
119
|
+
* <DropdownMenu
|
|
120
|
+
* button={{label: 'Allow options', variant: 'primary', isIconOnly: true, icon: <Icon icon="chevronDown" />}}
|
|
121
|
+
* items={[{label: 'Allow for 30 minutes'}, {label: 'Always allow'}]}
|
|
122
|
+
* />
|
|
123
|
+
* </ButtonGroup>
|
|
124
|
+
* ```
|
|
110
125
|
*/
|
|
111
126
|
export function ButtonGroup({
|
|
112
127
|
children,
|
|
@@ -119,6 +134,7 @@ export function ButtonGroup({
|
|
|
119
134
|
style,
|
|
120
135
|
ref,
|
|
121
136
|
'data-testid': testId,
|
|
137
|
+
onKeyDown,
|
|
122
138
|
...props
|
|
123
139
|
}: ButtonGroupProps): ReactNode {
|
|
124
140
|
const size = useSize(sizeProp, 'md');
|
|
@@ -138,11 +154,7 @@ export function ButtonGroup({
|
|
|
138
154
|
<SizeProvider value={size}>
|
|
139
155
|
<div
|
|
140
156
|
ref={mergeRefs(ref, listRef)}
|
|
141
|
-
|
|
142
|
-
aria-label={label}
|
|
143
|
-
onKeyDown={handleKeyDown}
|
|
144
|
-
aria-disabled={isDisabled || undefined}
|
|
145
|
-
data-testid={testId}
|
|
157
|
+
{...props}
|
|
146
158
|
{...mergeProps(
|
|
147
159
|
themeProps('button-group', {size, orientation}),
|
|
148
160
|
stylex.props(
|
|
@@ -153,7 +165,11 @@ export function ButtonGroup({
|
|
|
153
165
|
className,
|
|
154
166
|
style,
|
|
155
167
|
)}
|
|
156
|
-
|
|
168
|
+
role="group"
|
|
169
|
+
aria-label={label}
|
|
170
|
+
onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}
|
|
171
|
+
aria-disabled={isDisabled || undefined}
|
|
172
|
+
data-testid={testId}>
|
|
157
173
|
{children}
|
|
158
174
|
</div>
|
|
159
175
|
</SizeProvider>
|
|
@@ -9,14 +9,23 @@
|
|
|
9
9
|
* SYNC: When Calendar.tsx changes, update tests accordingly
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {act, render, screen, within} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
|
+
import {act, render, screen, within, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {getButton} from '../__tests__/fastRoleQueries';
|
|
16
16
|
import * as stylex from '@stylexjs/stylex';
|
|
17
17
|
import {Calendar} from './Calendar';
|
|
18
18
|
import type {CalendarHandle} from './Calendar';
|
|
19
19
|
import {calendarStyles} from './styles';
|
|
20
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
__resetLiveRegionsForTest();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function politeRegion(): HTMLElement | null {
|
|
27
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
28
|
+
}
|
|
20
29
|
|
|
21
30
|
/**
|
|
22
31
|
* Helper to find a day button by its day number.
|
|
@@ -545,6 +554,98 @@ describe('Calendar', () => {
|
|
|
545
554
|
expect(getButton('Next month')).toBeInTheDocument();
|
|
546
555
|
});
|
|
547
556
|
|
|
557
|
+
// ─── Month Change Announcements ──────────────────────────────
|
|
558
|
+
|
|
559
|
+
describe('month change announcements', () => {
|
|
560
|
+
it('does not announce on initial render', () => {
|
|
561
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
562
|
+
// The live region is only created lazily on first announce; mounting the
|
|
563
|
+
// calendar must not speak the initial month.
|
|
564
|
+
expect(politeRegion()).toBeNull();
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
it('announces the new month politely when clicking next', async () => {
|
|
568
|
+
const user = userEvent.setup();
|
|
569
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
570
|
+
|
|
571
|
+
await user.click(screen.getByRole('button', {name: 'Next month'}));
|
|
572
|
+
|
|
573
|
+
await waitFor(() => {
|
|
574
|
+
expect(politeRegion()).toHaveTextContent('February 2026');
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
it('announces the new month politely when clicking previous', async () => {
|
|
579
|
+
const user = userEvent.setup();
|
|
580
|
+
render(<Calendar focusDate="2026-02-01" />);
|
|
581
|
+
|
|
582
|
+
await user.click(screen.getByRole('button', {name: 'Previous month'}));
|
|
583
|
+
|
|
584
|
+
await waitFor(() => {
|
|
585
|
+
expect(politeRegion()).toHaveTextContent('January 2026');
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('announces the next month when paging the grid with PageDown', async () => {
|
|
590
|
+
const user = userEvent.setup();
|
|
591
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
592
|
+
|
|
593
|
+
// PageDown from a focused day pages the visible grid to the next month.
|
|
594
|
+
getDayButton(15).focus();
|
|
595
|
+
await user.keyboard('{PageDown}');
|
|
596
|
+
|
|
597
|
+
await waitFor(() => {
|
|
598
|
+
expect(politeRegion()).toHaveTextContent('February 2026');
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it('announces the newly visible month when navigated via the handle', async () => {
|
|
603
|
+
let handle: CalendarHandle | null = null;
|
|
604
|
+
render(
|
|
605
|
+
<Calendar
|
|
606
|
+
focusDate="2026-01-01"
|
|
607
|
+
handleRef={h => {
|
|
608
|
+
handle = h;
|
|
609
|
+
}}
|
|
610
|
+
/>,
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
act(() => {
|
|
614
|
+
handle?.navigateTo('2026-03-01');
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
await waitFor(() => {
|
|
618
|
+
expect(politeRegion()).toHaveTextContent('March 2026');
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('announces both months in a two-month view', async () => {
|
|
623
|
+
const user = userEvent.setup();
|
|
624
|
+
render(<Calendar numberOfMonths={2} focusDate="2026-01-01" />);
|
|
625
|
+
|
|
626
|
+
await user.click(screen.getByRole('button', {name: 'Next month'}));
|
|
627
|
+
|
|
628
|
+
await waitFor(() => {
|
|
629
|
+
expect(politeRegion()).toHaveTextContent('February 2026 – March 2026');
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it('does not announce when selecting a date leaves the visible month unchanged', async () => {
|
|
634
|
+
const user = userEvent.setup();
|
|
635
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
636
|
+
|
|
637
|
+
// Selecting an in-month day does not move the grid, so nothing should be
|
|
638
|
+
// announced (the live region stays uncreated).
|
|
639
|
+
await user.click(getDayButton(15));
|
|
640
|
+
|
|
641
|
+
// Allow the announce rAF a chance to run before asserting silence.
|
|
642
|
+
await act(async () => {
|
|
643
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
644
|
+
});
|
|
645
|
+
expect(politeRegion()).toBeNull();
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
|
|
548
649
|
// ─── Bug Regression Tests ───────────────────────────────────
|
|
549
650
|
|
|
550
651
|
it('day buttons have data-date attribute with ISO string', () => {
|