@astryxdesign/core 0.1.7 → 0.1.8-canary.0c4d8d7
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 +65 -0
- package/README.md +30 -19
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +10 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -8
- package/dist/Avatar/AvatarSizeContext.d.ts +1 -1
- package/dist/Avatar/AvatarSizeContext.js +1 -1
- package/dist/Avatar/AvatarStatusDot.d.ts +2 -2
- package/dist/Avatar/AvatarStatusDot.js +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +2 -2
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +16 -14
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +31 -2
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +31 -2
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +6 -2
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +55 -5
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +31 -6
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +19 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -3
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -4
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -0
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +8 -1
- 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/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- 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/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +10 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +8 -4
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +88 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +169 -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 +68 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +69 -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/FieldStatus/FieldStatus.d.ts +8 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +22 -4
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +10 -2
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -2
- package/dist/Icon/Icon.d.ts +43 -13
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +62 -27
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +39 -12
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/Outline/Outline.d.ts +68 -3
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +128 -26
- package/dist/Outline/useScrollSpy.d.ts +27 -7
- package/dist/Outline/useScrollSpy.d.ts.map +1 -1
- package/dist/Outline/useScrollSpy.js +202 -70
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +14 -11
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +4 -2
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +15 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/Table.d.ts +1 -1
- package/dist/Table/Table.js +1 -1
- package/dist/Table/index.d.ts +4 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +24 -2
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +12 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +4 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +18 -7
- 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/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +6 -3
- package/dist/Thumbnail/Thumbnail.d.ts +8 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +46 -8
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -4
- package/dist/Tokenizer/Tokenizer.d.ts +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +16 -4
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +8 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +5 -14
- package/dist/astryx.css +51 -16
- package/dist/astryx.umd.js +56 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +37 -25
- 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/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -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/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/docs.mjs +32 -461
- package/locales/en.json +212 -172
- package/locales/fr-FR.json +10 -0
- package/locales/pseudo.json +30 -0
- package/package.json +3 -1
- package/scripts/postinstall.mjs +93 -0
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +6 -6
- package/src/Avatar/Avatar.tsx +16 -11
- package/src/Avatar/AvatarSizeContext.ts +1 -1
- package/src/Avatar/AvatarStatusDot.tsx +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroup.test.tsx +17 -3
- package/src/AvatarGroup/AvatarGroup.tsx +3 -3
- package/src/AvatarGroup/AvatarGroupOverflow.doc.mjs +4 -4
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +21 -5
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +47 -3
- package/src/Button/Button.doc.mjs +9 -0
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +25 -1
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +149 -1
- package/src/Carousel/Carousel.tsx +62 -5
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposer.doc.mjs +9 -0
- package/src/Chat/ChatComposer.test.tsx +35 -0
- package/src/Chat/ChatComposer.tsx +58 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +87 -0
- package/src/Chat/ChatComposerInput.tsx +35 -3
- package/src/Chat/ChatLayout.tsx +3 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessage.tsx +4 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +5 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +13 -1
- package/src/Chat/useTriggerMenu.tsx +3 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxList/CheckboxList.test.tsx +9 -1
- package/src/Citation/Citation.test.tsx +51 -0
- package/src/Citation/Citation.tsx +8 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +11 -1
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +9 -1
- 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/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/ContextMenu/ContextMenu.test.tsx +75 -1
- package/src/ContextMenu/ContextMenu.tsx +10 -5
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
- package/src/DateTimeInput/DateTimeInput.tsx +14 -2
- package/src/Dialog/Dialog.tsx +12 -2
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +11 -6
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +236 -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 +118 -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/Field/Field.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +78 -40
- package/src/FieldStatus/FieldStatus.tsx +22 -4
- package/src/FileInput/FileInput.test.tsx +52 -3
- package/src/FileInput/FileInput.tsx +13 -2
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +24 -2
- package/src/Icon/Icon.doc.mjs +12 -0
- package/src/Icon/Icon.test.tsx +142 -0
- package/src/Icon/Icon.tsx +98 -30
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Layer/useLayer.tsx +8 -0
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +4 -2
- package/src/MultiSelector/MultiSelector.test.tsx +162 -1
- package/src/MultiSelector/MultiSelector.tsx +55 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/NumberInput/NumberInput.test.tsx +11 -7
- package/src/NumberInput/NumberInput.tsx +1 -2
- package/src/Outline/Outline.doc.mjs +123 -3
- package/src/Outline/Outline.test.tsx +735 -0
- package/src/Outline/Outline.tsx +183 -33
- package/src/Outline/useScrollSpy.ts +248 -72
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +27 -14
- package/src/Selector/Selector.test.tsx +69 -0
- package/src/Selector/Selector.tsx +5 -1
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNavCollapseButton.tsx +6 -1
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.doc.mjs +2 -2
- package/src/SideNav/SideNavItem.tsx +5 -1
- package/src/Slider/Slider.test.tsx +62 -2
- package/src/Slider/Slider.tsx +15 -1
- package/src/Switch/Switch.doc.mjs +1 -1
- package/src/Switch/Switch.test.tsx +32 -1
- 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 +8 -0
- package/src/TabList/TabMenu.tsx +4 -1
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.tsx +1 -1
- package/src/Table/index.ts +12 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +90 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +37 -5
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +18 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +95 -9
- package/src/Table/plugins/sortable/useTableSortable.tsx +23 -7
- 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/useBaseTablePlugins.ts +6 -2
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +75 -0
- package/src/Table/useTableTreeState.doc.mjs +98 -0
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.test.tsx +9 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +9 -0
- package/src/Thumbnail/Thumbnail.test.tsx +38 -8
- package/src/Thumbnail/Thumbnail.tsx +28 -1
- package/src/TimeInput/TimeInput.test.tsx +76 -1
- package/src/TimeInput/TimeInput.tsx +19 -6
- package/src/Tokenizer/Tokenizer.doc.mjs +1 -1
- package/src/Tokenizer/Tokenizer.test.tsx +137 -2
- package/src/Tokenizer/Tokenizer.tsx +16 -4
- package/src/Toolbar/Toolbar.tsx +10 -3
- package/src/TopNav/TopNav.test.tsx +80 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.test.tsx +32 -1
- package/src/TreeList/TreeListItem.tsx +19 -10
- package/src/authoring/doc.ts +1 -3
- package/src/docs-script.test.mjs +18 -13
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +77 -33
- package/src/postinstall.test.mjs +71 -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/generateThemeRules.test.ts +65 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +0 -4
- package/src/utils/types.ts +14 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +0 -16
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +0 -1
- package/dist/TreeList/treeListItem.markers.stylex.js +0 -22
- package/src/TreeList/treeListItem.markers.stylex.ts +0 -20
|
@@ -185,6 +185,41 @@ describe('DateTimeInput', () => {
|
|
|
185
185
|
);
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
+
it('opens the calendar popover on ArrowDown (keyboard, forms-13)', () => {
|
|
189
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
190
|
+
const input = screen.getByRole('combobox');
|
|
191
|
+
input.focus();
|
|
192
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
193
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
194
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
195
|
+
// skipAutoFocus keeps focus in the input, per the APG date-picker pattern
|
|
196
|
+
expect(input).toHaveFocus();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('opens the calendar popover on Alt+ArrowDown (keyboard, forms-13)', () => {
|
|
200
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
201
|
+
const input = screen.getByRole('combobox');
|
|
202
|
+
fireEvent.keyDown(input, {key: 'ArrowDown', altKey: true});
|
|
203
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('does not open on ArrowDown when disabled', () => {
|
|
207
|
+
render(<DateTimeInput label="Meeting" isDisabled onChange={() => {}} />);
|
|
208
|
+
const input = screen.getByRole('combobox');
|
|
209
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
210
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('does not re-trigger on ArrowDown when the calendar is already open', () => {
|
|
214
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
215
|
+
const input = screen.getByRole('combobox');
|
|
216
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
217
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
218
|
+
// A second ArrowDown is a no-op: the calendar stays open
|
|
219
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
220
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
221
|
+
});
|
|
222
|
+
|
|
188
223
|
it('calendar button is focusable and clickable', () => {
|
|
189
224
|
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
190
225
|
const button = getButton('Open calendar');
|
|
@@ -719,12 +719,22 @@ export function DateTimeInput({
|
|
|
719
719
|
if (e.key === 'Escape' && popover.isOpen) {
|
|
720
720
|
e.preventDefault();
|
|
721
721
|
popover.hide();
|
|
722
|
+
} else if (
|
|
723
|
+
(e.key === 'ArrowDown' || (e.altKey && e.key === 'ArrowDown')) &&
|
|
724
|
+
!popover.isOpen
|
|
725
|
+
) {
|
|
726
|
+
// APG combobox: ArrowDown (and Alt+ArrowDown) opens the calendar
|
|
727
|
+
// popover from the keyboard, keeping focus in the input (forms-13).
|
|
728
|
+
e.preventDefault();
|
|
729
|
+
if (!isEffectivelyDisabled) {
|
|
730
|
+
popover.show({skipAutoFocus: true});
|
|
731
|
+
}
|
|
722
732
|
} else if (e.key === 'Enter') {
|
|
723
733
|
e.preventDefault();
|
|
724
734
|
commitDatePendingInput();
|
|
725
735
|
}
|
|
726
736
|
},
|
|
727
|
-
[popover, commitDatePendingInput],
|
|
737
|
+
[popover, commitDatePendingInput, isEffectivelyDisabled],
|
|
728
738
|
);
|
|
729
739
|
|
|
730
740
|
// --- Time handlers ---
|
|
@@ -1000,7 +1010,9 @@ export function DateTimeInput({
|
|
|
1000
1010
|
disabled={isEffectivelyDisabled && !showsDisabledMessage}
|
|
1001
1011
|
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
1002
1012
|
readOnly={showsDisabledMessage || undefined}
|
|
1003
|
-
aria-label={
|
|
1013
|
+
aria-label={
|
|
1014
|
+
timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label})
|
|
1015
|
+
}
|
|
1004
1016
|
aria-describedby={ariaDescribedBy}
|
|
1005
1017
|
aria-required={isRequired === true ? 'true' : undefined}
|
|
1006
1018
|
aria-invalid={
|
package/src/Dialog/Dialog.tsx
CHANGED
|
@@ -152,7 +152,13 @@ const styles = stylex.create({
|
|
|
152
152
|
open: {
|
|
153
153
|
display: 'flex',
|
|
154
154
|
opacity: 1,
|
|
155
|
-
|
|
155
|
+
// Disable the entry keyframe animation under
|
|
156
|
+
// `prefers-reduced-motion: reduce` so the dialog appears instantly
|
|
157
|
+
// instead of translating/scaling in (same pattern as layerAnimations).
|
|
158
|
+
animationName: {
|
|
159
|
+
default: enterDirectional,
|
|
160
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
161
|
+
},
|
|
156
162
|
},
|
|
157
163
|
// Backdrop using ::backdrop pseudo-element
|
|
158
164
|
backdrop: {
|
|
@@ -531,7 +537,11 @@ export function Dialog({
|
|
|
531
537
|
),
|
|
532
538
|
className,
|
|
533
539
|
style,
|
|
534
|
-
)}
|
|
540
|
+
)}
|
|
541
|
+
data-testid={
|
|
542
|
+
(props as Record<string, unknown>)['data-testid'] as
|
|
543
|
+
string | undefined
|
|
544
|
+
}>
|
|
535
545
|
{innerContent}
|
|
536
546
|
</div>
|
|
537
547
|
);
|
|
@@ -8,10 +8,33 @@ export const docs = {
|
|
|
8
8
|
group: 'DropdownMenu',
|
|
9
9
|
category: 'Action',
|
|
10
10
|
keywords: ["dropdown","menu","popover","select","actions","contextmenu","overflow","kebab","menubutton"],
|
|
11
|
+
playground: {
|
|
12
|
+
// `items` is required; without seeded entries the properties-tab preview
|
|
13
|
+
// renders an empty trigger button. Provide a few actions so the preview
|
|
14
|
+
// is meaningful.
|
|
15
|
+
defaults: {
|
|
16
|
+
button: {label: 'Actions'},
|
|
17
|
+
items: [
|
|
18
|
+
{label: 'Edit'},
|
|
19
|
+
{label: 'Duplicate'},
|
|
20
|
+
{label: 'Delete'},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
11
24
|
theming: {
|
|
12
25
|
targets: [
|
|
13
26
|
{className: 'astryx-dropdown-menu'},
|
|
14
27
|
{className: 'astryx-dropdown-menu-item', visualProps: ['size']},
|
|
28
|
+
{
|
|
29
|
+
className: 'astryx-dropdown-menu-checkbox',
|
|
30
|
+
visualProps: ['size'],
|
|
31
|
+
states: ['checked', 'disabled'],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
className: 'astryx-dropdown-menu-radio',
|
|
35
|
+
visualProps: ['size'],
|
|
36
|
+
states: ['checked', 'disabled'],
|
|
37
|
+
},
|
|
15
38
|
],
|
|
16
39
|
vars: [
|
|
17
40
|
{name: '--_dropdown-menu-radius', description: 'Border radius of the menu popup', default: 'var(--radius-element)', private: true},
|
|
@@ -38,6 +38,7 @@ import {Icon} from '../Icon';
|
|
|
38
38
|
import type {IconType} from '../Icon';
|
|
39
39
|
|
|
40
40
|
import {renderDropdownItems} from './renderDropdownItems';
|
|
41
|
+
import {MENU_ITEM_ROLES, MENU_ITEM_SELECTOR} from './menuItemRoles';
|
|
41
42
|
import {
|
|
42
43
|
DropdownMenuContext,
|
|
43
44
|
type DropdownMenuContextValue,
|
|
@@ -255,14 +256,17 @@ export function DropdownMenu({
|
|
|
255
256
|
popover.hide();
|
|
256
257
|
}, [popover]);
|
|
257
258
|
|
|
258
|
-
// Single keyboard navigation path for both modes
|
|
259
|
+
// Single keyboard navigation path for both modes.
|
|
260
|
+
// The selector matches plain items plus selectable items
|
|
261
|
+
// (menuitemradio/menuitemcheckbox) so lab checkbox/radio rows are reachable
|
|
262
|
+
// and roved to alongside plain items — not just role="menuitem".
|
|
259
263
|
const {
|
|
260
264
|
listRef,
|
|
261
265
|
handleKeyDown: listNavKeyDown,
|
|
262
266
|
focusFirst,
|
|
263
267
|
focusItem,
|
|
264
268
|
} = useListFocus<HTMLDivElement>({
|
|
265
|
-
itemSelector:
|
|
269
|
+
itemSelector: MENU_ITEM_SELECTOR,
|
|
266
270
|
wrap: false,
|
|
267
271
|
onEscape: closeMenu,
|
|
268
272
|
});
|
|
@@ -273,9 +277,7 @@ export function DropdownMenu({
|
|
|
273
277
|
(): HTMLElement[] =>
|
|
274
278
|
listRef.current
|
|
275
279
|
? Array.from(
|
|
276
|
-
listRef.current.querySelectorAll<HTMLElement>(
|
|
277
|
-
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
278
|
-
),
|
|
280
|
+
listRef.current.querySelectorAll<HTMLElement>(MENU_ITEM_SELECTOR),
|
|
279
281
|
)
|
|
280
282
|
: [],
|
|
281
283
|
[listRef],
|
|
@@ -308,7 +310,10 @@ export function DropdownMenu({
|
|
|
308
310
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
309
311
|
e.preventDefault();
|
|
310
312
|
const focused = document.activeElement as HTMLElement | null;
|
|
311
|
-
if (
|
|
313
|
+
if (
|
|
314
|
+
focused &&
|
|
315
|
+
MENU_ITEM_ROLES.has(focused.getAttribute('role') ?? '')
|
|
316
|
+
) {
|
|
312
317
|
focused.click();
|
|
313
318
|
}
|
|
314
319
|
return;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'DropdownMenuCheckboxItem',
|
|
7
|
+
subComponentOf: 'DropdownMenu',
|
|
8
|
+
displayName: 'Dropdown Menu Checkbox Item',
|
|
9
|
+
isHiddenFromOverview: true,
|
|
10
|
+
description:
|
|
11
|
+
'A checkable menu item (role="menuitemcheckbox") that toggles an independent boolean. Use for on/off options inside a DropdownMenu; for a one-of-N choice use DropdownMenuRadioGroup.',
|
|
12
|
+
props: [
|
|
13
|
+
{
|
|
14
|
+
name: 'label',
|
|
15
|
+
type: 'ReactNode',
|
|
16
|
+
description: 'Primary label text identifying the item.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'description',
|
|
20
|
+
type: 'ReactNode',
|
|
21
|
+
description: 'Secondary description text displayed below the label.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'icon',
|
|
25
|
+
type: 'IconType',
|
|
26
|
+
description:
|
|
27
|
+
'Icon to display before the label. See `npx astryx docs icons` for valid semantic names.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'value',
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
description: 'Whether the item is checked. Controlled; pair with onChange.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'onChange',
|
|
36
|
+
type: '(checked: boolean) => void',
|
|
37
|
+
description: 'Callback fired with the next checked state when the item is toggled.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'isDisabled',
|
|
41
|
+
type: 'boolean',
|
|
42
|
+
default: 'false',
|
|
43
|
+
description:
|
|
44
|
+
'Whether the item is disabled. Disabled items stay focusable (via aria-disabled) so they remain discoverable by keyboard and assistive technology, but activation is blocked.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'hasCloseOnSelect',
|
|
48
|
+
type: 'boolean',
|
|
49
|
+
default: 'false',
|
|
50
|
+
description:
|
|
51
|
+
'Whether toggling the item closes the menu. Checkbox items default to staying open so several can be toggled in a single session.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'endContent',
|
|
55
|
+
type: 'ReactNode',
|
|
56
|
+
description:
|
|
57
|
+
'Content to render after the label and description, such as a keyboard shortcut hint or badge.',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const docsZh = {
|
|
63
|
+
name: 'DropdownMenuCheckboxItem',
|
|
64
|
+
isHiddenFromOverview: true,
|
|
65
|
+
displayName: 'Dropdown Menu Checkbox Item',
|
|
66
|
+
description:
|
|
67
|
+
'可勾选的菜单项(role="menuitemcheckbox"),用于切换独立的布尔值。用于 DropdownMenu 中的开关选项;单选请使用 DropdownMenuRadioGroup。',
|
|
68
|
+
propDescriptions: {
|
|
69
|
+
label: '标识该项的主标签文本。',
|
|
70
|
+
description: '显示在标签下方的次要描述文本。',
|
|
71
|
+
icon: '显示在标签前的图标。',
|
|
72
|
+
value: '该项是否被勾选。受控,与 onChange 搭配使用。',
|
|
73
|
+
onChange: '切换该项时以下一个勾选状态触发的回调。',
|
|
74
|
+
isDisabled: '该项是否禁用。',
|
|
75
|
+
hasCloseOnSelect: '切换该项是否关闭菜单。默认保持打开。',
|
|
76
|
+
endContent: '在标签和描述之后渲染的内容。',
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const docsDense = {
|
|
81
|
+
name: 'DropdownMenuCheckboxItem',
|
|
82
|
+
isHiddenFromOverview: true,
|
|
83
|
+
displayName: 'Dropdown Menu Checkbox Item',
|
|
84
|
+
description: 'checkable menu item (menuitemcheckbox); independent boolean toggle',
|
|
85
|
+
propDescriptions: {
|
|
86
|
+
label: 'primary label text',
|
|
87
|
+
description: 'secondary text below label',
|
|
88
|
+
icon: 'icon before label',
|
|
89
|
+
value: 'checked state (controlled, w/ onChange)',
|
|
90
|
+
onChange: 'fired w/ next checked state on toggle',
|
|
91
|
+
isDisabled: 'disabled; stays focusable via aria-disabled',
|
|
92
|
+
hasCloseOnSelect: 'close menu on toggle (default false, stays open)',
|
|
93
|
+
endContent: 'content after label+description',
|
|
94
|
+
},
|
|
95
|
+
};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file DropdownMenuCheckboxItem.tsx
|
|
7
|
+
* @input React, stylex, Item + Icon + DropdownMenu context + tokens from core
|
|
8
|
+
* @output DropdownMenuCheckboxItem — a standalone checkable menu item.
|
|
9
|
+
* @position Sub-component; used inside DropdownMenu.
|
|
10
|
+
*
|
|
11
|
+
* A menu item that toggles an independent boolean (role="menuitemcheckbox").
|
|
12
|
+
* Unlike CheckboxInput, there is no nested native <input>: the row itself owns
|
|
13
|
+
* the role and aria-checked, per the WAI-ARIA menuitemcheckbox pattern.
|
|
14
|
+
* Keyboard navigation (arrows/typeahead) and Enter/Space activation come from
|
|
15
|
+
* the parent DropdownMenu's useListFocus + activation path, which matches
|
|
16
|
+
* menuitemcheckbox alongside plain menuitem rows.
|
|
17
|
+
*
|
|
18
|
+
* The square checkbox visual is decorative (aria-hidden) — the row owns the
|
|
19
|
+
* checked state. Its size is derived from the menu's item size (a `sm` menu
|
|
20
|
+
* gets the compact control; `md`/`lg` get the standard one) and it swaps to the
|
|
21
|
+
* inline-end of the row on coarse-pointer (touch) devices via CSS `order`, so
|
|
22
|
+
* it lands where selection toggles are conventionally placed on mobile. The
|
|
23
|
+
* checkmark uses the `check` icon from the active theme's icon registry.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import {useCallback, type ReactNode} from 'react';
|
|
27
|
+
import * as stylex from '@stylexjs/stylex';
|
|
28
|
+
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
29
|
+
import {Item} from '../Item';
|
|
30
|
+
import {useDropdownMenuContext} from './DropdownMenuContext';
|
|
31
|
+
import {
|
|
32
|
+
colorVars,
|
|
33
|
+
spacingVars,
|
|
34
|
+
radiusVars,
|
|
35
|
+
durationVars,
|
|
36
|
+
easeVars,
|
|
37
|
+
borderVars,
|
|
38
|
+
} from '../theme/tokens.stylex';
|
|
39
|
+
import {mergeProps, themeProps} from '../utils';
|
|
40
|
+
import type {BaseProps} from '../BaseProps';
|
|
41
|
+
|
|
42
|
+
const styles = stylex.create({
|
|
43
|
+
root: {
|
|
44
|
+
width: '100%',
|
|
45
|
+
borderRadius: `max(0px, calc(var(--_dropdown-menu-radius, ${spacingVars['--spacing-2']}) - var(--_dropdown-menu-padding, ${spacingVars['--spacing-1']})))`,
|
|
46
|
+
color: colorVars['--color-text-primary'],
|
|
47
|
+
backgroundColor: {
|
|
48
|
+
default: 'transparent',
|
|
49
|
+
':focus': colorVars['--color-overlay-hover'],
|
|
50
|
+
':hover': colorVars['--color-overlay-hover'],
|
|
51
|
+
},
|
|
52
|
+
cursor: 'pointer',
|
|
53
|
+
outline: 'none',
|
|
54
|
+
},
|
|
55
|
+
disabled: {
|
|
56
|
+
opacity: 0.5,
|
|
57
|
+
cursor: 'not-allowed',
|
|
58
|
+
},
|
|
59
|
+
// Rendered in Item's `marker` slot as a raw flex child, so `order` moves it
|
|
60
|
+
// relative to the label within the row. On touch it moves to the inline-end.
|
|
61
|
+
box: {
|
|
62
|
+
display: 'flex',
|
|
63
|
+
alignItems: 'center',
|
|
64
|
+
justifyContent: 'center',
|
|
65
|
+
flexShrink: 0,
|
|
66
|
+
boxSizing: 'border-box',
|
|
67
|
+
borderWidth: borderVars['--border-width'],
|
|
68
|
+
borderStyle: 'solid',
|
|
69
|
+
borderRadius: radiusVars['--radius-inner'],
|
|
70
|
+
color: colorVars['--color-on-accent'],
|
|
71
|
+
transitionProperty: 'background-color, border-color',
|
|
72
|
+
transitionDuration: {
|
|
73
|
+
default: durationVars['--duration-fast'],
|
|
74
|
+
'@media (prefers-reduced-motion: reduce)': '0s',
|
|
75
|
+
},
|
|
76
|
+
transitionTimingFunction: easeVars['--ease-standard'],
|
|
77
|
+
order: {
|
|
78
|
+
default: 0,
|
|
79
|
+
'@media (pointer: coarse)': 1,
|
|
80
|
+
},
|
|
81
|
+
marginInlineStart: {
|
|
82
|
+
default: 0,
|
|
83
|
+
'@media (pointer: coarse)': 'auto',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
unchecked: {
|
|
87
|
+
borderColor: colorVars['--color-border-emphasized'],
|
|
88
|
+
backgroundColor: colorVars['--color-background-surface'],
|
|
89
|
+
},
|
|
90
|
+
checked: {
|
|
91
|
+
borderColor: colorVars['--color-accent'],
|
|
92
|
+
backgroundColor: colorVars['--color-accent'],
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const boxSizeStyles = stylex.create({
|
|
97
|
+
sm: {width: 18, height: 18},
|
|
98
|
+
md: {width: 22, height: 22},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export interface DropdownMenuCheckboxItemProps extends Omit<
|
|
102
|
+
BaseProps,
|
|
103
|
+
'onChange' | 'role' | 'aria-checked' | 'tabIndex'
|
|
104
|
+
> {
|
|
105
|
+
/**
|
|
106
|
+
* Primary label text identifying the item.
|
|
107
|
+
*/
|
|
108
|
+
label: ReactNode;
|
|
109
|
+
/**
|
|
110
|
+
* Secondary description text displayed below the label.
|
|
111
|
+
*/
|
|
112
|
+
description?: ReactNode;
|
|
113
|
+
/**
|
|
114
|
+
* Icon to display before the label. Accepts a semantic icon name (see
|
|
115
|
+
* `npx astryx docs icons`) or a rendered node.
|
|
116
|
+
*/
|
|
117
|
+
icon?: ReactNode | IconType;
|
|
118
|
+
/**
|
|
119
|
+
* Whether the item is checked. Controlled — pair with `onChange`.
|
|
120
|
+
*/
|
|
121
|
+
value: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Callback fired with the next checked state when the item is toggled.
|
|
124
|
+
*/
|
|
125
|
+
onChange?: (checked: boolean) => void;
|
|
126
|
+
/**
|
|
127
|
+
* Whether the item is disabled. Disabled items stay focusable (via
|
|
128
|
+
* `aria-disabled`) so they remain discoverable by keyboard and assistive
|
|
129
|
+
* technology, but activation is blocked.
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
isDisabled?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Whether toggling the item closes the menu. Checkbox items default to
|
|
135
|
+
* staying open so several can be toggled in a single session, unlike radio
|
|
136
|
+
* items which default to closing on selection.
|
|
137
|
+
* @default false
|
|
138
|
+
*/
|
|
139
|
+
hasCloseOnSelect?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Content to render after the label and description, such as a keyboard
|
|
142
|
+
* shortcut hint or badge.
|
|
143
|
+
*/
|
|
144
|
+
endContent?: ReactNode;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* A checkable dropdown menu item (role="menuitemcheckbox").
|
|
149
|
+
*
|
|
150
|
+
* Must be used inside a DropdownMenu. Toggles an independent boolean; for a
|
|
151
|
+
* one-of-N choice use DropdownMenuRadioGroup + DropdownMenuRadioItem instead.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```
|
|
155
|
+
* import {DropdownMenuCheckboxItem} from '@astryxdesign/core/DropdownMenu';
|
|
156
|
+
* <DropdownMenu button={{label: 'View'}}>
|
|
157
|
+
* <DropdownMenuCheckboxItem
|
|
158
|
+
* label="Show archived"
|
|
159
|
+
* value={showArchived}
|
|
160
|
+
* onChange={setShowArchived}
|
|
161
|
+
* />
|
|
162
|
+
* </DropdownMenu>
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export function DropdownMenuCheckboxItem({
|
|
166
|
+
label,
|
|
167
|
+
description,
|
|
168
|
+
icon,
|
|
169
|
+
value,
|
|
170
|
+
onChange,
|
|
171
|
+
isDisabled = false,
|
|
172
|
+
hasCloseOnSelect = false,
|
|
173
|
+
endContent,
|
|
174
|
+
xstyle,
|
|
175
|
+
className,
|
|
176
|
+
style,
|
|
177
|
+
...rest
|
|
178
|
+
}: DropdownMenuCheckboxItemProps) {
|
|
179
|
+
const ctx = useDropdownMenuContext();
|
|
180
|
+
const menuSize = ctx?.menuSize ?? 'md';
|
|
181
|
+
const controlSize = menuSize === 'sm' ? 'sm' : 'md';
|
|
182
|
+
|
|
183
|
+
const handleClick = useCallback(() => {
|
|
184
|
+
if (isDisabled) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
onChange?.(!value);
|
|
188
|
+
if (hasCloseOnSelect) {
|
|
189
|
+
ctx?.closeMenu();
|
|
190
|
+
}
|
|
191
|
+
}, [isDisabled, onChange, value, hasCloseOnSelect, ctx]);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<Item
|
|
195
|
+
{...rest}
|
|
196
|
+
role="menuitemcheckbox"
|
|
197
|
+
aria-checked={value}
|
|
198
|
+
tabIndex={isDisabled ? undefined : -1}
|
|
199
|
+
marker={
|
|
200
|
+
<span
|
|
201
|
+
aria-hidden="true"
|
|
202
|
+
{...mergeProps(
|
|
203
|
+
themeProps('dropdown-menu-checkbox', {
|
|
204
|
+
size: controlSize,
|
|
205
|
+
checked: value ? 'checked' : null,
|
|
206
|
+
disabled: isDisabled ? 'disabled' : null,
|
|
207
|
+
}),
|
|
208
|
+
stylex.props(
|
|
209
|
+
styles.box,
|
|
210
|
+
boxSizeStyles[controlSize],
|
|
211
|
+
value ? styles.checked : styles.unchecked,
|
|
212
|
+
),
|
|
213
|
+
)}>
|
|
214
|
+
{value && <Icon icon="check" size="sm" color="inherit" />}
|
|
215
|
+
</span>
|
|
216
|
+
}
|
|
217
|
+
startContent={
|
|
218
|
+
icon
|
|
219
|
+
? renderIconSlot(icon, {size: 'sm', color: 'secondary'})
|
|
220
|
+
: undefined
|
|
221
|
+
}
|
|
222
|
+
label={label}
|
|
223
|
+
description={description}
|
|
224
|
+
endContent={endContent}
|
|
225
|
+
onClick={handleClick}
|
|
226
|
+
isDisabled={isDisabled}
|
|
227
|
+
xstyle={[styles.root, isDisabled && styles.disabled, xstyle]}
|
|
228
|
+
{...mergeProps(themeProps('dropdown-menu-item', {size: menuSize}), {
|
|
229
|
+
className,
|
|
230
|
+
style,
|
|
231
|
+
})}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
DropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';
|
|
@@ -14,11 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
import {createContext, use} from 'react';
|
|
16
16
|
|
|
17
|
+
/** Menu size, derived from the trigger button size. */
|
|
18
|
+
export type DropdownMenuSize = 'sm' | 'md' | 'lg';
|
|
19
|
+
|
|
17
20
|
export interface DropdownMenuContextValue {
|
|
18
21
|
/** Close the menu and return focus to trigger */
|
|
19
22
|
closeMenu: () => void;
|
|
20
23
|
/** Menu size derived from button size */
|
|
21
|
-
menuSize:
|
|
24
|
+
menuSize: DropdownMenuSize;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export const DropdownMenuContext =
|
|
@@ -32,3 +35,28 @@ DropdownMenuContext.displayName = 'DropdownMenuContext';
|
|
|
32
35
|
export function useDropdownMenuContext(): DropdownMenuContextValue | null {
|
|
33
36
|
return use(DropdownMenuContext);
|
|
34
37
|
}
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Radio group coordination
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export interface DropdownMenuRadioGroupContextValue {
|
|
44
|
+
/** The currently selected value in the group. */
|
|
45
|
+
value: string | undefined;
|
|
46
|
+
/** Select a value. Called by a DropdownMenuRadioItem on activation. */
|
|
47
|
+
onChange: (value: string) => void;
|
|
48
|
+
/** Whether selecting an item should close the menu. @default true */
|
|
49
|
+
hasCloseOnSelect: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const DropdownMenuRadioGroupContext =
|
|
53
|
+
createContext<DropdownMenuRadioGroupContextValue | null>(null);
|
|
54
|
+
DropdownMenuRadioGroupContext.displayName = 'DropdownMenuRadioGroupContext';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Read the enclosing radio group's selection state.
|
|
58
|
+
* Returns null when used outside a DropdownMenuRadioGroup.
|
|
59
|
+
*/
|
|
60
|
+
export function useDropdownMenuRadioGroupContext(): DropdownMenuRadioGroupContextValue | null {
|
|
61
|
+
return use(DropdownMenuRadioGroupContext);
|
|
62
|
+
}
|
|
@@ -8,11 +8,17 @@ export const docs = {
|
|
|
8
8
|
displayName: 'Dropdown Menu Item',
|
|
9
9
|
isHiddenFromOverview: true,
|
|
10
10
|
description: 'Helper component for custom item rendering with consistent styling.',
|
|
11
|
+
playground: {
|
|
12
|
+
// Standalone DropdownMenuItem has no required props, so the properties-tab
|
|
13
|
+
// preview renders an empty row without seeded content. Seed a label and
|
|
14
|
+
// description so the preview is meaningful.
|
|
15
|
+
defaults: {label: 'Edit', description: 'Modify this item'},
|
|
16
|
+
},
|
|
11
17
|
props: [
|
|
12
18
|
{
|
|
13
19
|
name: 'icon',
|
|
14
20
|
type: 'IconType',
|
|
15
|
-
description: 'Icon to display before the label. See `
|
|
21
|
+
description: 'Icon to display before the label. See `astryx docs icons` for valid semantic names.',
|
|
16
22
|
},
|
|
17
23
|
{
|
|
18
24
|
name: 'label',
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'DropdownMenuRadioGroup',
|
|
7
|
+
subComponentOf: 'DropdownMenu',
|
|
8
|
+
displayName: 'Dropdown Menu Radio Group',
|
|
9
|
+
isHiddenFromOverview: true,
|
|
10
|
+
description:
|
|
11
|
+
'A single-select group of radio menu items (role="group" of menuitemradio). Owns the selected value and lays its items out with the menu\'s inter-item gap.',
|
|
12
|
+
props: [
|
|
13
|
+
{
|
|
14
|
+
name: 'value',
|
|
15
|
+
type: 'string | undefined',
|
|
16
|
+
description:
|
|
17
|
+
'The currently selected value in the group. Pass undefined when nothing is selected yet.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'onChange',
|
|
21
|
+
type: '(value: string) => void',
|
|
22
|
+
description: 'Callback fired when the selected value changes.',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'aria-label',
|
|
26
|
+
type: 'string',
|
|
27
|
+
description:
|
|
28
|
+
'Accessible label for the group. Required (or aria-labelledby) so screen readers announce the radios as a named set, e.g. "Sort by".',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'aria-labelledby',
|
|
32
|
+
type: 'string',
|
|
33
|
+
description:
|
|
34
|
+
'The id of an element that labels the group, as an alternative to aria-label.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'hasCloseOnSelect',
|
|
38
|
+
type: 'boolean',
|
|
39
|
+
default: 'true',
|
|
40
|
+
description:
|
|
41
|
+
'Whether selecting a value closes the menu. Radio items default to closing on selection (a single-choice commit).',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'children',
|
|
45
|
+
type: 'ReactNode',
|
|
46
|
+
description: 'The DropdownMenuRadioItems that make up the group.',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const docsZh = {
|
|
52
|
+
name: 'DropdownMenuRadioGroup',
|
|
53
|
+
isHiddenFromOverview: true,
|
|
54
|
+
displayName: 'Dropdown Menu Radio Group',
|
|
55
|
+
description:
|
|
56
|
+
'单选的单选菜单项组(menuitemradio 的 role="group")。持有所选值,并以菜单的项间距布局其子项。',
|
|
57
|
+
propDescriptions: {
|
|
58
|
+
value: '组中当前选中的值。尚无选中项时传 undefined。',
|
|
59
|
+
onChange: '所选值变化时触发的回调。',
|
|
60
|
+
'aria-label': '组的无障碍标签。必需(或 aria-labelledby),以便屏幕阅读器将单选项作为命名集合朗读。',
|
|
61
|
+
'aria-labelledby': '标记该组的元素 id,作为 aria-label 的替代。',
|
|
62
|
+
hasCloseOnSelect: '选择某值是否关闭菜单。默认关闭。',
|
|
63
|
+
children: '组成该组的 DropdownMenuRadioItem。',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const docsDense = {
|
|
68
|
+
name: 'DropdownMenuRadioGroup',
|
|
69
|
+
isHiddenFromOverview: true,
|
|
70
|
+
displayName: 'Dropdown Menu Radio Group',
|
|
71
|
+
description: 'single-select group of menuitemradio; owns selected value',
|
|
72
|
+
propDescriptions: {
|
|
73
|
+
value: 'selected value (undefined = none)',
|
|
74
|
+
onChange: 'fired when selected value changes',
|
|
75
|
+
'aria-label': 'accessible group name (or aria-labelledby); required',
|
|
76
|
+
'aria-labelledby': 'id of labelling element (alt to aria-label)',
|
|
77
|
+
hasCloseOnSelect: 'close menu on select (default true)',
|
|
78
|
+
children: 'the DropdownMenuRadioItems',
|
|
79
|
+
},
|
|
80
|
+
};
|