@astryxdesign/core 0.1.6 → 0.1.7-canary.0a6de96
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 +2 -0
- 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.map +1 -1
- package/dist/Collapsible/Collapsible.js +8 -1
- 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/TabList.d.ts +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +4 -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/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/types.d.ts +17 -10
- package/dist/Table/types.d.ts.map +1 -1
- 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/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 +35 -3
- 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/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 +746 -0
- package/locales/pseudo.json +560 -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.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 +1 -0
- package/src/Collapsible/Collapsible.test.tsx +6 -0
- package/src/Collapsible/Collapsible.tsx +19 -4
- 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 +6 -0
- 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 +2 -2
- 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.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/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavCollapseButton.tsx +3 -1
- package/src/SideNav/SideNavHeading.tsx +5 -3
- 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 +2 -2
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +4 -2
- package/src/TabList/TabList.tsx +4 -1
- package/src/Table/BaseTable.tsx +36 -19
- package/src/Table/Table.test.tsx +132 -1
- package/src/Table/Table.tsx +6 -4
- 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/types.ts +18 -12
- 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/Text/Text.doc.mjs +2 -2
- 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/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/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
package/src/Icon/Icon.tsx
CHANGED
|
@@ -111,51 +111,64 @@ const colorStyles = stylex.create({
|
|
|
111
111
|
/**
|
|
112
112
|
* Size styles for direct SVG icon components.
|
|
113
113
|
* Uses width/height only — SVG components handle their own viewBox scaling.
|
|
114
|
+
*
|
|
115
|
+
* Sizes are expressed in `rem` (relative to the root font-size) so icons scale
|
|
116
|
+
* in step with text when the document font-size changes, matching the rest of
|
|
117
|
+
* the design system's rem-based type scale. Values are the px-equivalents at a
|
|
118
|
+
* 16px root: 12px → 0.75rem, 16px → 1rem, 20px → 1.25rem, 24px → 1.5rem.
|
|
114
119
|
*/
|
|
115
120
|
const sizeStyles = stylex.create({
|
|
116
121
|
xsm: {
|
|
117
|
-
width:
|
|
118
|
-
height:
|
|
122
|
+
width: '0.75rem',
|
|
123
|
+
height: '0.75rem',
|
|
119
124
|
},
|
|
120
125
|
sm: {
|
|
121
|
-
width:
|
|
122
|
-
height:
|
|
126
|
+
width: '1rem',
|
|
127
|
+
height: '1rem',
|
|
123
128
|
},
|
|
124
129
|
md: {
|
|
125
|
-
width:
|
|
126
|
-
height:
|
|
130
|
+
width: '1.25rem',
|
|
131
|
+
height: '1.25rem',
|
|
127
132
|
},
|
|
128
133
|
lg: {
|
|
129
|
-
width:
|
|
130
|
-
height:
|
|
134
|
+
width: '1.5rem',
|
|
135
|
+
height: '1.5rem',
|
|
131
136
|
},
|
|
132
137
|
});
|
|
133
138
|
|
|
134
139
|
/**
|
|
135
140
|
* Size styles for string-based (registry) icons.
|
|
136
141
|
* Includes fontSize so that 1em-based icons from the registry scale correctly.
|
|
142
|
+
*
|
|
143
|
+
* Expressed in `rem` for the same reason as {@link sizeStyles} — icons track the
|
|
144
|
+
* root font-size instead of being locked to absolute pixels.
|
|
137
145
|
*/
|
|
138
146
|
const spanSizeStyles = stylex.create({
|
|
147
|
+
/* eslint-disable @astryx/no-hardcoded-styles -- fontSize here sizes 1em-based
|
|
148
|
+
registry SVGs to the icon box; icons use their own 12/16/20/24 scale, not
|
|
149
|
+
the 14px-anchored textSizeVars type scale. Values are rem so icons track
|
|
150
|
+
the root font-size. */
|
|
139
151
|
xsm: {
|
|
140
|
-
width:
|
|
141
|
-
height:
|
|
142
|
-
fontSize:
|
|
152
|
+
width: '0.75rem',
|
|
153
|
+
height: '0.75rem',
|
|
154
|
+
fontSize: '0.75rem',
|
|
143
155
|
},
|
|
144
156
|
sm: {
|
|
145
|
-
width:
|
|
146
|
-
height:
|
|
147
|
-
fontSize:
|
|
157
|
+
width: '1rem',
|
|
158
|
+
height: '1rem',
|
|
159
|
+
fontSize: '1rem',
|
|
148
160
|
},
|
|
149
161
|
md: {
|
|
150
|
-
width:
|
|
151
|
-
height:
|
|
152
|
-
fontSize:
|
|
162
|
+
width: '1.25rem',
|
|
163
|
+
height: '1.25rem',
|
|
164
|
+
fontSize: '1.25rem',
|
|
153
165
|
},
|
|
154
166
|
lg: {
|
|
155
|
-
width:
|
|
156
|
-
height:
|
|
157
|
-
fontSize:
|
|
167
|
+
width: '1.5rem',
|
|
168
|
+
height: '1.5rem',
|
|
169
|
+
fontSize: '1.5rem',
|
|
158
170
|
},
|
|
171
|
+
/* eslint-enable @astryx/no-hardcoded-styles */
|
|
159
172
|
});
|
|
160
173
|
|
|
161
174
|
// =============================================================================
|
|
@@ -194,10 +207,10 @@ export interface IconProps extends Omit<
|
|
|
194
207
|
color?: IconColor;
|
|
195
208
|
/**
|
|
196
209
|
* The size of the icon.
|
|
197
|
-
* - 'xsm': 12px
|
|
198
|
-
* - 'sm': 16px
|
|
199
|
-
* - 'md': 20px
|
|
200
|
-
* - 'lg': 24px
|
|
210
|
+
* - 'xsm': 0.75rem (12px at a 16px root)
|
|
211
|
+
* - 'sm': 1rem (16px at a 16px root)
|
|
212
|
+
* - 'md': 1.25rem (20px at a 16px root)
|
|
213
|
+
* - 'lg': 1.5rem (24px at a 16px root)
|
|
201
214
|
* @default 'md'
|
|
202
215
|
*/
|
|
203
216
|
size?: IconSize;
|
package/src/Kbd/Kbd.test.tsx
CHANGED
|
@@ -119,4 +119,30 @@ describe('Kbd', () => {
|
|
|
119
119
|
expect(screen.getByText('⇧')).toBeInTheDocument();
|
|
120
120
|
expect(screen.getByText('+')).toBeInTheDocument();
|
|
121
121
|
});
|
|
122
|
+
|
|
123
|
+
it('keeps the computed role and aria-label when unrelated rest props are spread', () => {
|
|
124
|
+
render(<Kbd keys="mod+k" data-testid="kbd" id="shortcut" />);
|
|
125
|
+
const el = screen.getByTestId('kbd');
|
|
126
|
+
// Pass-through attributes land on the wrapper...
|
|
127
|
+
expect(el).toHaveAttribute('id', 'shortcut');
|
|
128
|
+
// ...without disturbing the computed accessibility contract.
|
|
129
|
+
expect(el).toHaveAttribute('role', 'img');
|
|
130
|
+
expect(el).toHaveAttribute('aria-label', 'Control + K');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('computed role and aria-label win over consumer-passed overrides', () => {
|
|
134
|
+
// Contract props the component computes must not be clobbered by
|
|
135
|
+
// pass-through attributes: {...rest} is spread before role/aria-label.
|
|
136
|
+
render(
|
|
137
|
+
<Kbd
|
|
138
|
+
keys="mod+k"
|
|
139
|
+
role="presentation"
|
|
140
|
+
aria-label="custom"
|
|
141
|
+
data-testid="kbd"
|
|
142
|
+
/>,
|
|
143
|
+
);
|
|
144
|
+
const el = screen.getByTestId('kbd');
|
|
145
|
+
expect(el).toHaveAttribute('role', 'img');
|
|
146
|
+
expect(el).toHaveAttribute('aria-label', 'Control + K');
|
|
147
|
+
});
|
|
122
148
|
});
|
package/src/Kbd/Kbd.tsx
CHANGED
|
@@ -188,10 +188,10 @@ export function Kbd({keys, ref, xstyle, className, style, ...rest}: KbdProps) {
|
|
|
188
188
|
|
|
189
189
|
return (
|
|
190
190
|
<span
|
|
191
|
+
{...rest}
|
|
191
192
|
ref={ref}
|
|
192
193
|
role="img"
|
|
193
194
|
aria-label={accessibleName}
|
|
194
|
-
{...rest}
|
|
195
195
|
{...mergeProps(
|
|
196
196
|
themeProps('kbd'),
|
|
197
197
|
stylex.props(styles.wrapper, xstyle),
|
|
@@ -72,13 +72,14 @@ export const docs = {
|
|
|
72
72
|
{
|
|
73
73
|
name: 'id',
|
|
74
74
|
type: 'string',
|
|
75
|
-
description:
|
|
75
|
+
description:
|
|
76
|
+
'Unique ID for aria-describedby or other ARIA relationships.',
|
|
76
77
|
},
|
|
77
78
|
{
|
|
78
79
|
name: 'render',
|
|
79
80
|
type: '(children: ReactNode, props: ContextRenderProps | FixedRenderProps) => ReactNode',
|
|
80
81
|
description:
|
|
81
|
-
'Render function for the popover element. Pass placement/alignment in context mode or x/y in fixed mode. Placement/alignment are logical: they map to the self-* position-area keyword family, which resolves against the popover\'s own inherited direction, so RTL contexts mirror automatically in pure CSS. Pass `positioning: "custom"` in context mode to author position styles yourself via `style` (e.g. explicit anchor() insets or an anchor-size() cover): the hook keeps the popover behavior and position-anchor wiring but derives no position styles
|
|
82
|
+
'Render function for the popover element. Pass placement/alignment in context mode or x/y in fixed mode. Placement/alignment are logical: they map to the self-* position-area keyword family, which resolves against the popover\'s own inherited direction, so RTL contexts mirror automatically in pure CSS. Pass `positioning: "custom"` in context mode to author position styles yourself via `style` (e.g. explicit anchor() insets or an anchor-size() cover): the hook keeps the popover behavior and position-anchor wiring but derives no position styles, including the automatic RTL mirroring, which becomes your responsibility. In context mode, pass `as: "span"` to render an inline-safe layer (e.g. inside a paragraph). The layer renders inline in the React tree; the Popover API promotes it to the top layer when shown, so it escapes ancestor clipping and stacking without a portal. When the layer would overflow the viewport, position-try fallbacks flip it to the opposite side; centered layers additionally slide along the alignment axis (span fallbacks) so they stay on-screen near viewport edges.',
|
|
82
83
|
},
|
|
83
84
|
],
|
|
84
85
|
usage: {
|
|
@@ -130,7 +131,7 @@ export const docsDense = {
|
|
|
130
131
|
hide: 'hide layer.',
|
|
131
132
|
isOpen: 'whether layer is open.',
|
|
132
133
|
id: 'unique ARIA id.',
|
|
133
|
-
render: 'renders popover element; pass placement/alignment or x/y. Placement/alignment logical: mapped to self-* position-area keywords resolved against the popover\'s inherited direction (RTL mirrors in pure CSS). `positioning: "custom"` (context mode) = author position styles yourself via `style`; keeps popover behavior + position-anchor wiring, derives nothing (incl. RTL mirroring
|
|
134
|
+
render: 'renders popover element; pass placement/alignment or x/y. Placement/alignment logical: mapped to self-* position-area keywords resolved against the popover\'s inherited direction (RTL mirrors in pure CSS). `positioning: "custom"` (context mode) = author position styles yourself via `style`; keeps popover behavior + position-anchor wiring, derives nothing (incl. RTL mirroring, which becomes yours). Context mode accepts `as: "span"` for inline-safe layers. Renders inline; the Popover API top layer escapes clipping/stacking without a portal. Viewport overflow: flips to opposite side; centered layers also slide along the alignment axis (span fallbacks).',
|
|
134
135
|
},
|
|
135
136
|
usage: {
|
|
136
137
|
description:
|
|
@@ -138,11 +139,13 @@ export const docsDense = {
|
|
|
138
139
|
bestPractices: [
|
|
139
140
|
{
|
|
140
141
|
guidance: true,
|
|
141
|
-
description:
|
|
142
|
+
description:
|
|
143
|
+
'Use context mode for trigger-anchored overlays; fixed mode for explicit coordinates.',
|
|
142
144
|
},
|
|
143
145
|
{
|
|
144
146
|
guidance: true,
|
|
145
|
-
description:
|
|
147
|
+
description:
|
|
148
|
+
'Build on Popover/HoverCard/Tooltip for common overlay patterns.',
|
|
146
149
|
},
|
|
147
150
|
{
|
|
148
151
|
guidance: true,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
13
|
import {render, act} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
|
-
import {useLayer} from './useLayer';
|
|
15
|
+
import {useLayer, getPositionTryFallbacks} from './useLayer';
|
|
16
16
|
import type {
|
|
17
17
|
LayerPlacement,
|
|
18
18
|
LayerAlignment,
|
|
@@ -33,6 +33,141 @@ function LayerHarness({
|
|
|
33
33
|
return <>{layer.render(<span>Layer content</span>, {x: 0, y: 0})}</>;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Context-mode harness: renders a trigger plus the layer so tests can assert
|
|
38
|
+
* on the anchor-positioning styles applied to the popover element.
|
|
39
|
+
*/
|
|
40
|
+
function ContextLayerHarness({
|
|
41
|
+
placement,
|
|
42
|
+
alignment,
|
|
43
|
+
}: {
|
|
44
|
+
placement?: LayerPlacement;
|
|
45
|
+
alignment?: LayerAlignment;
|
|
46
|
+
}) {
|
|
47
|
+
const layer = useLayer({mode: 'context'});
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<button type="button" ref={layer.ref}>
|
|
51
|
+
Trigger
|
|
52
|
+
</button>
|
|
53
|
+
{layer.render(<span>Layer content</span>, {placement, alignment})}
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('getPositionTryFallbacks (issue #3671)', () => {
|
|
59
|
+
const FLIPS = 'flip-block, flip-inline, flip-block flip-inline';
|
|
60
|
+
|
|
61
|
+
it('appends inline span fallbacks for centered above/below layers so inline overflow can resolve (flip-inline is a no-op on center)', () => {
|
|
62
|
+
expect(getPositionTryFallbacks('above', 'center')).toBe(
|
|
63
|
+
`${FLIPS}, top span-left, top span-right, bottom span-left, bottom span-right`,
|
|
64
|
+
);
|
|
65
|
+
expect(getPositionTryFallbacks('below', 'center')).toBe(
|
|
66
|
+
`${FLIPS}, bottom span-left, bottom span-right, top span-left, top span-right`,
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('appends block span fallbacks for centered start/end layers so block overflow can resolve (flip-block is a no-op on center)', () => {
|
|
71
|
+
expect(getPositionTryFallbacks('start', 'center')).toBe(
|
|
72
|
+
`${FLIPS}, left span-top, left span-bottom, right span-top, right span-bottom`,
|
|
73
|
+
);
|
|
74
|
+
expect(getPositionTryFallbacks('end', 'center')).toBe(
|
|
75
|
+
`${FLIPS}, right span-top, right span-bottom, left span-top, left span-bottom`,
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('keeps flip-only fallbacks for non-centered alignments (flips already resolve overflow there)', () => {
|
|
80
|
+
const nonCentered: [LayerPlacement, LayerAlignment][] = [
|
|
81
|
+
['above', 'start'],
|
|
82
|
+
['above', 'end'],
|
|
83
|
+
['below', 'start'],
|
|
84
|
+
['below', 'end'],
|
|
85
|
+
['start', 'start'],
|
|
86
|
+
['start', 'end'],
|
|
87
|
+
['end', 'start'],
|
|
88
|
+
['end', 'end'],
|
|
89
|
+
];
|
|
90
|
+
for (const [placement, alignment] of nonCentered) {
|
|
91
|
+
expect(getPositionTryFallbacks(placement, alignment)).toBe(FLIPS);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('defaults to above/center when called without arguments (matches renderContext defaults)', () => {
|
|
96
|
+
expect(getPositionTryFallbacks()).toBe(
|
|
97
|
+
getPositionTryFallbacks('above', 'center'),
|
|
98
|
+
);
|
|
99
|
+
expect(getPositionTryFallbacks(undefined, undefined)).toBe(
|
|
100
|
+
`${FLIPS}, top span-left, top span-right, bottom span-left, bottom span-right`,
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('produces well-formed, duplicate-free lists with flips first and axis-correct spans for every placement/alignment combo', () => {
|
|
105
|
+
const placements: LayerPlacement[] = ['above', 'below', 'start', 'end'];
|
|
106
|
+
const alignments: LayerAlignment[] = ['start', 'center', 'end'];
|
|
107
|
+
const spanPattern: Record<LayerPlacement, RegExp> = {
|
|
108
|
+
above: /^(top|bottom) span-(left|right)$/,
|
|
109
|
+
below: /^(top|bottom) span-(left|right)$/,
|
|
110
|
+
start: /^(left|right) span-(top|bottom)$/,
|
|
111
|
+
end: /^(left|right) span-(top|bottom)$/,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
for (const placement of placements) {
|
|
115
|
+
for (const alignment of alignments) {
|
|
116
|
+
const list = getPositionTryFallbacks(placement, alignment);
|
|
117
|
+
const items = list.split(', ');
|
|
118
|
+
|
|
119
|
+
expect(items.slice(0, 3)).toEqual([
|
|
120
|
+
'flip-block',
|
|
121
|
+
'flip-inline',
|
|
122
|
+
'flip-block flip-inline',
|
|
123
|
+
]);
|
|
124
|
+
expect(new Set(items).size).toBe(items.length);
|
|
125
|
+
for (const item of items.slice(3)) {
|
|
126
|
+
expect(item).toMatch(spanPattern[placement]);
|
|
127
|
+
}
|
|
128
|
+
expect(items.length).toBe(alignment === 'center' ? 7 : 3);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('updates the fallback list when placement/alignment props change on re-render', () => {
|
|
134
|
+
const {container, rerender} = render(
|
|
135
|
+
<ContextLayerHarness placement="above" alignment="center" />,
|
|
136
|
+
);
|
|
137
|
+
const layerEl = container.querySelector('[popover]') as HTMLElement;
|
|
138
|
+
expect(layerEl.style.positionTryFallbacks).toContain('top span-left');
|
|
139
|
+
|
|
140
|
+
rerender(<ContextLayerHarness placement="above" alignment="start" />);
|
|
141
|
+
expect(layerEl.style.positionTryFallbacks).toBe(FLIPS);
|
|
142
|
+
|
|
143
|
+
rerender(<ContextLayerHarness placement="start" alignment="center" />);
|
|
144
|
+
expect(layerEl.style.positionTryFallbacks).toBe(
|
|
145
|
+
`${FLIPS}, left span-top, left span-bottom, right span-top, right span-bottom`,
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('does not apply anchor fallbacks in fixed mode (manual coordinates)', () => {
|
|
150
|
+
function FixedHarness() {
|
|
151
|
+
const layer = useLayer({mode: 'fixed'});
|
|
152
|
+
return <>{layer.render(<span>Fixed content</span>, {x: 10, y: 20})}</>;
|
|
153
|
+
}
|
|
154
|
+
const {container} = render(<FixedHarness />);
|
|
155
|
+
const layerEl = container.querySelector('[popover]') as HTMLElement;
|
|
156
|
+
expect(layerEl.style.positionTryFallbacks ?? '').toBeFalsy();
|
|
157
|
+
expect(layerEl.style.left).toBe('10px');
|
|
158
|
+
expect(layerEl.style.top).toBe('20px');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('applies span fallbacks to the rendered popover for the default (above/center) layer', () => {
|
|
162
|
+
const {container} = render(<ContextLayerHarness />);
|
|
163
|
+
const layerEl = container.querySelector('[popover]') as HTMLElement;
|
|
164
|
+
expect(layerEl).not.toBeNull();
|
|
165
|
+
expect(layerEl.style.positionTryFallbacks).toBe(
|
|
166
|
+
`${FLIPS}, top span-left, top span-right, bottom span-left, bottom span-right`,
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
36
171
|
describe('useLayer', () => {
|
|
37
172
|
const originalShowPopover = HTMLElement.prototype.showPopover;
|
|
38
173
|
const originalHidePopover = HTMLElement.prototype.hidePopover;
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -320,6 +320,36 @@ function getPositionArea(
|
|
|
320
320
|
return inline; // center
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Compute the `position-try-fallbacks` list for a placement/alignment pair.
|
|
325
|
+
*
|
|
326
|
+
* Flips alone cannot rescue a centered layer — flipping along the alignment
|
|
327
|
+
* axis maps center → center, so overflow on that axis renders clipped
|
|
328
|
+
* (#3671). Centered alignments therefore append span-based fallbacks letting
|
|
329
|
+
* the browser slide the layer along the alignment axis as a last resort
|
|
330
|
+
* (same-side spans first). Flips already resolve non-centered alignments.
|
|
331
|
+
*/
|
|
332
|
+
export function getPositionTryFallbacks(
|
|
333
|
+
placement: LayerPlacement = 'above',
|
|
334
|
+
alignment: LayerAlignment = 'center',
|
|
335
|
+
): string {
|
|
336
|
+
const flips = 'flip-block, flip-inline, flip-block flip-inline';
|
|
337
|
+
|
|
338
|
+
if (alignment !== 'center') {
|
|
339
|
+
return flips;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (placement === 'above' || placement === 'below') {
|
|
343
|
+
const [same, opposite] =
|
|
344
|
+
placement === 'above' ? ['top', 'bottom'] : ['bottom', 'top'];
|
|
345
|
+
return `${flips}, ${same} span-left, ${same} span-right, ${opposite} span-left, ${opposite} span-right`;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const [same, opposite] =
|
|
349
|
+
placement === 'start' ? ['left', 'right'] : ['right', 'left'];
|
|
350
|
+
return `${flips}, ${same} span-top, ${same} span-bottom, ${opposite} span-top, ${opposite} span-bottom`;
|
|
351
|
+
}
|
|
352
|
+
|
|
323
353
|
/**
|
|
324
354
|
* Core layer hook that handles popover behavior and positioning.
|
|
325
355
|
*
|
|
@@ -512,8 +542,10 @@ export function useLayer(
|
|
|
512
542
|
: {
|
|
513
543
|
positionAnchor: anchorId,
|
|
514
544
|
positionArea: getPositionArea(placement, alignment),
|
|
515
|
-
positionTryFallbacks:
|
|
516
|
-
|
|
545
|
+
positionTryFallbacks: getPositionTryFallbacks(
|
|
546
|
+
placement,
|
|
547
|
+
alignment,
|
|
548
|
+
),
|
|
517
549
|
};
|
|
518
550
|
|
|
519
551
|
const stylexResult = stylex.props(styles.base, xstyle);
|
|
@@ -22,8 +22,13 @@ export const docs = {
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
name: 'media',
|
|
25
|
+
// Left as the named type on purpose: the shape carries `caption?:
|
|
26
|
+
// ReactNode`, so spelling it out makes the docsite playground parse the
|
|
27
|
+
// whole prop as an editable *string*, which would feed the preview text
|
|
28
|
+
// where a media object belongs. The shape and its legal values live in
|
|
29
|
+
// the description instead (#1645).
|
|
25
30
|
type: 'LightboxMedia | LightboxMedia[]',
|
|
26
|
-
description:
|
|
31
|
+
description: "Media to display. Pass a single object for one item, or an array for gallery mode with prev/next navigation. Each item is {src: string, alt: string, caption?: ReactNode, type?: 'image' | 'video'}; type defaults to 'image', and zoom/pan is disabled for 'video'.",
|
|
27
32
|
required: true,
|
|
28
33
|
},
|
|
29
34
|
{
|
|
@@ -100,7 +105,7 @@ export const docsZh = {
|
|
|
100
105
|
{
|
|
101
106
|
name: 'media',
|
|
102
107
|
type: 'LightboxMedia | LightboxMedia[]',
|
|
103
|
-
description: '
|
|
108
|
+
description: "要显示的媒体。传入单个对象或数组(用于画廊模式的上一张/下一张导航)。每项为 {src, alt, caption?, type?: 'image' | 'video'};type 默认为 'image','video' 禁用缩放/平移。",
|
|
104
109
|
required: true,
|
|
105
110
|
},
|
|
106
111
|
{
|
|
@@ -35,6 +35,7 @@ import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
|
35
35
|
import {mergeProps, mergeRefs} from '../utils';
|
|
36
36
|
import type {BaseProps} from '../BaseProps';
|
|
37
37
|
import {themeProps} from '../utils/themeProps';
|
|
38
|
+
import {useTranslator} from '../i18n';
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* Media type for lightbox items.
|
|
@@ -282,6 +283,7 @@ export function Lightbox({
|
|
|
282
283
|
onKeyDown: onKeyDownProp,
|
|
283
284
|
...props
|
|
284
285
|
}: LightboxProps) {
|
|
286
|
+
const t = useTranslator();
|
|
285
287
|
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
286
288
|
const imageWrapperRef = useRef<HTMLDivElement>(null);
|
|
287
289
|
const triggerElementRef = useRef<Element | null>(null);
|
|
@@ -504,7 +506,7 @@ export function Lightbox({
|
|
|
504
506
|
handleKeyDown(e);
|
|
505
507
|
onKeyDownProp?.(e);
|
|
506
508
|
}}
|
|
507
|
-
aria-label={currentItem.alt || '
|
|
509
|
+
aria-label={currentItem.alt || t('@astryx.lightbox.mediaViewer')}
|
|
508
510
|
{...mergeProps(
|
|
509
511
|
themeProps('lightbox'),
|
|
510
512
|
stylex.props(styles.dialog, xstyle),
|
|
@@ -517,7 +519,7 @@ export function Lightbox({
|
|
|
517
519
|
<div {...stylex.props(styles.closeButton)}>
|
|
518
520
|
<IconButton
|
|
519
521
|
icon={<Icon icon="close" size="sm" color="inherit" />}
|
|
520
|
-
label=
|
|
522
|
+
label={t('@astryx.lightbox.close')}
|
|
521
523
|
variant="ghost"
|
|
522
524
|
onClick={handleClose}
|
|
523
525
|
xstyle={styles.controlButton}
|
|
@@ -531,7 +533,7 @@ export function Lightbox({
|
|
|
531
533
|
<div {...stylex.props(styles.navButton, styles.navPrev)}>
|
|
532
534
|
<IconButton
|
|
533
535
|
icon={<Icon icon="chevronLeft" size="sm" color="inherit" />}
|
|
534
|
-
label=
|
|
536
|
+
label={t('@astryx.lightbox.previous')}
|
|
535
537
|
variant="ghost"
|
|
536
538
|
isDisabled={!canPrev}
|
|
537
539
|
onClick={goToPrev}
|
|
@@ -586,7 +588,7 @@ export function Lightbox({
|
|
|
586
588
|
<div {...stylex.props(styles.navButton, styles.navNext)}>
|
|
587
589
|
<IconButton
|
|
588
590
|
icon={<Icon icon="chevronRight" size="sm" color="inherit" />}
|
|
589
|
-
label=
|
|
591
|
+
label={t('@astryx.lightbox.next')}
|
|
590
592
|
variant="ghost"
|
|
591
593
|
isDisabled={!canNext}
|
|
592
594
|
onClick={goToNext}
|
package/src/Link/Link.test.tsx
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
13
|
+
import {fireEvent, render, screen} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {Link} from './Link';
|
|
16
16
|
import {LinkProvider} from './LinkProvider';
|
|
@@ -153,9 +153,81 @@ describe('Link', () => {
|
|
|
153
153
|
Disabled Link
|
|
154
154
|
</Link>,
|
|
155
155
|
);
|
|
156
|
-
|
|
156
|
+
// An href-less anchor has no implicit `link` role, so query by text.
|
|
157
|
+
const link = screen.getByText('Disabled Link').closest('a');
|
|
158
|
+
expect(link).not.toBeNull();
|
|
157
159
|
expect(link).toHaveAttribute('aria-disabled', 'true');
|
|
158
160
|
expect(link).toHaveAttribute('tabIndex', '-1');
|
|
161
|
+
// Visual classes are preserved in the disabled state.
|
|
162
|
+
expect(link?.className).toContain('astryx-link');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('disabled link has no href attribute', () => {
|
|
166
|
+
render(
|
|
167
|
+
<Link href="/test" isDisabled>
|
|
168
|
+
Disabled Link
|
|
169
|
+
</Link>,
|
|
170
|
+
);
|
|
171
|
+
const link = screen.getByText('Disabled Link').closest('a');
|
|
172
|
+
expect(link).not.toBeNull();
|
|
173
|
+
expect(link).not.toHaveAttribute('href');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('clicking a disabled link cancels default navigation', () => {
|
|
177
|
+
render(
|
|
178
|
+
<Link href="/test" isDisabled>
|
|
179
|
+
Disabled Link
|
|
180
|
+
</Link>,
|
|
181
|
+
);
|
|
182
|
+
const link = screen.getByText('Disabled Link').closest('a');
|
|
183
|
+
expect(link).not.toBeNull();
|
|
184
|
+
// fireEvent bypasses pointer-events, simulating programmatic/AT
|
|
185
|
+
// activation. It returns false when preventDefault was called, i.e.
|
|
186
|
+
// any default navigation behavior is cancelled.
|
|
187
|
+
const notCancelled = fireEvent.click(link as HTMLAnchorElement);
|
|
188
|
+
expect(notCancelled).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('disabled link with onClick fires neither navigation nor the consumer onClick', () => {
|
|
192
|
+
const handleClick = vi.fn();
|
|
193
|
+
const {container} = render(
|
|
194
|
+
<Link href="/test" isDisabled onClick={handleClick}>
|
|
195
|
+
Disabled Link
|
|
196
|
+
</Link>,
|
|
197
|
+
);
|
|
198
|
+
// With onClick present, a disabled Link renders as a disabled <button>
|
|
199
|
+
// (useInteractiveRole excludes a disabled href). Either way the rendered
|
|
200
|
+
// root must carry no live href and never invoke the consumer handler.
|
|
201
|
+
const el = container.firstElementChild as HTMLElement;
|
|
202
|
+
expect(el).not.toHaveAttribute('href');
|
|
203
|
+
fireEvent.click(el);
|
|
204
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('disabled link omits target and rel', () => {
|
|
208
|
+
render(
|
|
209
|
+
<Link href="https://example.com" isDisabled isExternalLink>
|
|
210
|
+
Disabled External
|
|
211
|
+
</Link>,
|
|
212
|
+
);
|
|
213
|
+
const link = screen.getByText('Disabled External').closest('a');
|
|
214
|
+
expect(link).not.toBeNull();
|
|
215
|
+
expect(link).not.toHaveAttribute('target');
|
|
216
|
+
expect(link).not.toHaveAttribute('rel');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('disabled link renders a plain anchor, not the custom LinkComponent', () => {
|
|
220
|
+
render(
|
|
221
|
+
<LinkProvider component={CustomLink}>
|
|
222
|
+
<Link href="/custom" as={CustomLink} isDisabled>
|
|
223
|
+
Disabled Custom
|
|
224
|
+
</Link>
|
|
225
|
+
</LinkProvider>,
|
|
226
|
+
);
|
|
227
|
+
const link = screen.getByText('Disabled Custom').closest('a');
|
|
228
|
+
expect(link).not.toBeNull();
|
|
229
|
+
expect(link).not.toHaveAttribute('data-custom-link');
|
|
230
|
+
expect(link).not.toHaveAttribute('href');
|
|
159
231
|
});
|
|
160
232
|
|
|
161
233
|
it('renders external link with icon and target="_blank"', () => {
|
package/src/Link/Link.tsx
CHANGED
|
@@ -44,6 +44,7 @@ import {mergeProps} from '../utils';
|
|
|
44
44
|
import {computeTargetAndRel} from './computeTargetAndRel';
|
|
45
45
|
import {useInteractiveRole} from '../hooks/useInteractiveRole';
|
|
46
46
|
import {themeProps} from '../utils/themeProps';
|
|
47
|
+
import {useTranslator} from '../i18n';
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Base link styles
|
|
@@ -174,6 +175,10 @@ export interface LinkProps extends BaseProps<
|
|
|
174
175
|
hasUnderline?: boolean;
|
|
175
176
|
/**
|
|
176
177
|
* Whether the link is disabled.
|
|
178
|
+
* A disabled link renders as a plain anchor without an href (and without
|
|
179
|
+
* target/rel/onClick), so it cannot be focused or activated — no
|
|
180
|
+
* navigation and no onClick, even via programmatic focus or assistive
|
|
181
|
+
* technology activation.
|
|
177
182
|
* @default false
|
|
178
183
|
*/
|
|
179
184
|
isDisabled?: boolean;
|
|
@@ -261,6 +266,15 @@ export interface LinkProps extends BaseProps<
|
|
|
261
266
|
children: ReactNode;
|
|
262
267
|
}
|
|
263
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Click handler for disabled links. The disabled anchor renders without an
|
|
271
|
+
* href, so there is no navigation to block in practice; preventDefault is a
|
|
272
|
+
* defensive guard against synthetic/programmatic clicks.
|
|
273
|
+
*/
|
|
274
|
+
function preventDefaultClick(event: React.MouseEvent<HTMLAnchorElement>): void {
|
|
275
|
+
event.preventDefault();
|
|
276
|
+
}
|
|
277
|
+
|
|
264
278
|
/**
|
|
265
279
|
* A styled anchor link component.
|
|
266
280
|
*
|
|
@@ -286,7 +300,7 @@ export function Link({
|
|
|
286
300
|
hasUnderline = false,
|
|
287
301
|
isDisabled = false,
|
|
288
302
|
isExternalLink = false,
|
|
289
|
-
newTabLabel
|
|
303
|
+
newTabLabel: newTabLabelFromProps,
|
|
290
304
|
target: targetFromProps,
|
|
291
305
|
onClick,
|
|
292
306
|
tooltip,
|
|
@@ -305,6 +319,8 @@ export function Link({
|
|
|
305
319
|
ref,
|
|
306
320
|
...props
|
|
307
321
|
}: LinkProps) {
|
|
322
|
+
const t = useTranslator();
|
|
323
|
+
const newTabLabel = newTabLabelFromProps ?? t('@astryx.link.newTab');
|
|
308
324
|
const LinkComponent = useLinkComponent(as);
|
|
309
325
|
const role = useInteractiveRole({href, onClick, isDisabled});
|
|
310
326
|
// Determine target and rel based on isExternalLink
|
|
@@ -368,6 +384,37 @@ export function Link({
|
|
|
368
384
|
{sharedContent}
|
|
369
385
|
</button>
|
|
370
386
|
);
|
|
387
|
+
} else if (isDisabled) {
|
|
388
|
+
// A disabled link renders as a plain <a> with no href: an href-less
|
|
389
|
+
// anchor is not focusable and exposes no link affordance, so programmatic
|
|
390
|
+
// focus + Enter, AT activation commands, and middle-click cannot navigate
|
|
391
|
+
// or fire the consumer onClick. The router LinkComponent is deliberately
|
|
392
|
+
// skipped — a disabled link performs no navigation, and custom router
|
|
393
|
+
// links may require a live href. target/rel are omitted with the href.
|
|
394
|
+
linkElement = (
|
|
395
|
+
<a
|
|
396
|
+
ref={ref as React.Ref<HTMLAnchorElement>}
|
|
397
|
+
onClick={preventDefaultClick}
|
|
398
|
+
aria-label={label || undefined}
|
|
399
|
+
aria-disabled={true}
|
|
400
|
+
tabIndex={-1}
|
|
401
|
+
{...mergeProps(
|
|
402
|
+
themeProps('link', {color}),
|
|
403
|
+
stylex.props(
|
|
404
|
+
styles.base,
|
|
405
|
+
linkColorStyles[color],
|
|
406
|
+
hasUnderline && styles.hasUnderline,
|
|
407
|
+
isStandalone && styles.standalone,
|
|
408
|
+
styles.disabled,
|
|
409
|
+
xstyle,
|
|
410
|
+
),
|
|
411
|
+
className,
|
|
412
|
+
style,
|
|
413
|
+
)}
|
|
414
|
+
{...props}>
|
|
415
|
+
{sharedContent}
|
|
416
|
+
</a>
|
|
417
|
+
);
|
|
371
418
|
} else {
|
|
372
419
|
linkElement = (
|
|
373
420
|
<LinkComponent
|