@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
|
@@ -29,7 +29,6 @@ import {mergeProps} from '../utils';
|
|
|
29
29
|
import {useLinkComponent} from '../Link/useLinkComponent';
|
|
30
30
|
import {TreeListBranches} from './TreeListBranches';
|
|
31
31
|
import type {TreeListDensity} from './TreeListTypes';
|
|
32
|
-
import {treeItemScope} from './treeListItem.markers.stylex';
|
|
33
32
|
import {themeProps} from '../utils/themeProps';
|
|
34
33
|
import {useTranslator} from '../i18n';
|
|
35
34
|
|
|
@@ -47,6 +46,19 @@ const styles = stylex.create({
|
|
|
47
46
|
// The treeitem row is the roving-tabindex focus owner; suppress the
|
|
48
47
|
// native focus ring in favor of the row's :focus-visible outline below.
|
|
49
48
|
outline: 'none',
|
|
49
|
+
// Publish this row's own focus state as an inheritable CSS variable
|
|
50
|
+
// instead of matching it via an ancestor selector. Every nested <li>
|
|
51
|
+
// redeclares these vars (default: 'none' / '0'), so a descendant row's
|
|
52
|
+
// default shadows an ancestor's active value — the ring can never leak
|
|
53
|
+
// past the nearest containing treeitem, however deep the tree nests.
|
|
54
|
+
'--_tree-focus-outline': {
|
|
55
|
+
default: 'none',
|
|
56
|
+
':focus-visible': `2px solid ${colorVars['--color-accent']}`,
|
|
57
|
+
},
|
|
58
|
+
'--_tree-focus-outline-offset': {
|
|
59
|
+
default: '0',
|
|
60
|
+
':focus-visible': '2px',
|
|
61
|
+
},
|
|
50
62
|
},
|
|
51
63
|
childGroup: {
|
|
52
64
|
margin: 0,
|
|
@@ -86,17 +98,14 @@ const styles = stylex.create({
|
|
|
86
98
|
},
|
|
87
99
|
focusVisibleOutline: {
|
|
88
100
|
outline: {
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
[stylex.when.ancestor(':focus-visible', treeItemScope)]:
|
|
94
|
-
`2px solid ${colorVars['--color-accent']}`,
|
|
101
|
+
// Reads the row's own --_tree-focus-outline (published on the <li> in
|
|
102
|
+
// `wrapper`), which resolves to the nearest containing treeitem only.
|
|
103
|
+
default: 'var(--_tree-focus-outline, none)',
|
|
104
|
+
// Also support inner focusable actions.
|
|
95
105
|
':has(:focus-visible)': `2px solid ${colorVars['--color-accent']}`,
|
|
96
106
|
},
|
|
97
107
|
outlineOffset: {
|
|
98
|
-
default: '0',
|
|
99
|
-
[stylex.when.ancestor(':focus-visible', treeItemScope)]: '2px',
|
|
108
|
+
default: 'var(--_tree-focus-outline-offset, 0)',
|
|
100
109
|
':has(:focus-visible)': '2px',
|
|
101
110
|
},
|
|
102
111
|
},
|
|
@@ -451,7 +460,7 @@ export function TreeListItem({
|
|
|
451
460
|
data-tree-id={id}
|
|
452
461
|
data-tree-level={nestedLevel + 1}
|
|
453
462
|
data-tree-disabled={isDisabled || undefined}
|
|
454
|
-
{...stylex.props(styles.wrapper
|
|
463
|
+
{...stylex.props(styles.wrapper)}>
|
|
455
464
|
<div {...stylex.props(styles.treeBranches)}>
|
|
456
465
|
<TreeListBranches
|
|
457
466
|
ancestorsIsLast={ancestorsIsLast}
|
package/src/authoring/doc.ts
CHANGED
|
@@ -130,9 +130,7 @@ export type AstryxGenericDocInput = AstryxBaseDocInput;
|
|
|
130
130
|
* any code referring to the old name.
|
|
131
131
|
*/
|
|
132
132
|
export type AstryxComponentDoc =
|
|
133
|
-
|
|
|
134
|
-
| AstryxFunctionDocInput
|
|
135
|
-
| AstryxGenericDocInput;
|
|
133
|
+
AstryxComponentDocInput | AstryxFunctionDocInput | AstryxGenericDocInput;
|
|
136
134
|
|
|
137
135
|
/**
|
|
138
136
|
* Author a component doc. Stamp-only: returns the def with `type: 'component'`
|
package/src/docs-script.test.mjs
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file Subprocess smoke tests for the zero-dependency docs script.
|
|
5
5
|
*
|
|
6
|
-
* `docs.mjs`
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* `docs.mjs` no longer prints component docs itself — it intentionally
|
|
7
|
+
* redirects to the Astryx CLI (`npx @astryxdesign/cli init`) so agents and
|
|
8
|
+
* humans converge on the CLI + `init` rather than a stale bundled snapshot.
|
|
9
|
+
* These tests spawn the script as a real subprocess from a neutral cwd and
|
|
10
|
+
* assert that, regardless of the arguments passed, it prints the redirect
|
|
11
|
+
* banner and exits 0 instead of rendering a component catalog or per-component
|
|
12
|
+
* docs.
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import {describe, it, expect} from 'vitest';
|
|
@@ -29,22 +30,26 @@ function runDocs(args) {
|
|
|
29
30
|
});
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
describe('docs.mjs
|
|
33
|
-
it('
|
|
33
|
+
describe('docs.mjs redirects to the Astryx CLI', () => {
|
|
34
|
+
it('redirects to the CLI instead of printing a component catalog for --list', () => {
|
|
34
35
|
const r = runDocs(['--list']);
|
|
35
36
|
expect(r.error).toBeUndefined();
|
|
36
37
|
expect(r.signal).toBeNull();
|
|
37
38
|
expect(r.status).toBe(0);
|
|
38
|
-
|
|
39
|
-
expect(r.stdout).toMatch(
|
|
39
|
+
// Prints the redirect banner, not a component list.
|
|
40
|
+
expect(r.stdout).toMatch(/docs are served by the Astryx CLI/);
|
|
41
|
+
expect(r.stdout).toMatch(/npx @astryxdesign\/cli init/);
|
|
42
|
+
expect(r.stdout).toMatch(/npx @astryxdesign\/cli component --list/);
|
|
40
43
|
});
|
|
41
44
|
|
|
42
|
-
it('
|
|
45
|
+
it('redirects to the CLI instead of rendering docs for a single component', () => {
|
|
43
46
|
const r = runDocs(['Button']);
|
|
44
47
|
expect(r.error).toBeUndefined();
|
|
45
48
|
expect(r.signal).toBeNull();
|
|
46
49
|
expect(r.status).toBe(0);
|
|
47
|
-
|
|
48
|
-
expect(r.stdout).toMatch(
|
|
50
|
+
// A pure redirect: it must not render the component's docs.
|
|
51
|
+
expect(r.stdout).not.toMatch(/^# Button$/m);
|
|
52
|
+
expect(r.stdout).not.toMatch(/## Props/);
|
|
53
|
+
expect(r.stdout).toMatch(/npx @astryxdesign\/cli component <Name>/);
|
|
49
54
|
});
|
|
50
55
|
});
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, it, expect} from 'vitest';
|
|
4
|
+
import {computeOverflow, type ComputeOverflowInput} from './computeOverflow';
|
|
5
|
+
|
|
6
|
+
// Convenience wrapper with sensible defaults so each test states only what it
|
|
7
|
+
// exercises. All widths/gaps are plain numbers — no DOM involved.
|
|
8
|
+
function compute(overrides: Partial<ComputeOverflowInput>) {
|
|
9
|
+
return computeOverflow({
|
|
10
|
+
widths: [],
|
|
11
|
+
gap: 0,
|
|
12
|
+
availableWidth: 0,
|
|
13
|
+
indicatorWidth: 0,
|
|
14
|
+
minVisibleItems: 0,
|
|
15
|
+
collapseFrom: 'end',
|
|
16
|
+
...overrides,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('computeOverflow — single line, no limits (parity with legacy loop)', () => {
|
|
21
|
+
it('shows all items when they fit', () => {
|
|
22
|
+
// 3×50, gap 10 → 170 ≤ 200
|
|
23
|
+
expect(
|
|
24
|
+
compute({widths: [50, 50, 50], gap: 10, availableWidth: 200}),
|
|
25
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('hides items that do not fit and reserves indicator space', () => {
|
|
29
|
+
// 4×50, gap 10, indicator 30, container 150 → 2 fit
|
|
30
|
+
expect(
|
|
31
|
+
compute({
|
|
32
|
+
widths: [50, 50, 50, 50],
|
|
33
|
+
gap: 10,
|
|
34
|
+
indicatorWidth: 30,
|
|
35
|
+
availableWidth: 150,
|
|
36
|
+
}),
|
|
37
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('shows zero when nothing fits and floor is 0', () => {
|
|
41
|
+
expect(
|
|
42
|
+
compute({
|
|
43
|
+
widths: [100, 100, 100],
|
|
44
|
+
indicatorWidth: 30,
|
|
45
|
+
availableWidth: 50,
|
|
46
|
+
}),
|
|
47
|
+
).toEqual({visibleCount: 0, rows: 0});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('exact fit with indicator not needed shows all', () => {
|
|
51
|
+
// 3×50, gap 10 → 170 == 170
|
|
52
|
+
expect(
|
|
53
|
+
compute({
|
|
54
|
+
widths: [50, 50, 50],
|
|
55
|
+
gap: 10,
|
|
56
|
+
indicatorWidth: 30,
|
|
57
|
+
availableWidth: 170,
|
|
58
|
+
}),
|
|
59
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('off-by-one: one pixel short drops the last item', () => {
|
|
63
|
+
expect(
|
|
64
|
+
compute({
|
|
65
|
+
widths: [50, 50, 50],
|
|
66
|
+
gap: 10,
|
|
67
|
+
indicatorWidth: 30,
|
|
68
|
+
availableWidth: 169,
|
|
69
|
+
}),
|
|
70
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('works without an indicator', () => {
|
|
74
|
+
// 3×50, gap 10, container 130 → 2 fit
|
|
75
|
+
expect(
|
|
76
|
+
compute({widths: [50, 50, 50], gap: 10, availableWidth: 130}),
|
|
77
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('varied widths', () => {
|
|
81
|
+
expect(
|
|
82
|
+
compute({
|
|
83
|
+
widths: [30, 80, 40, 60],
|
|
84
|
+
gap: 10,
|
|
85
|
+
indicatorWidth: 25,
|
|
86
|
+
availableWidth: 200,
|
|
87
|
+
}),
|
|
88
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('computeOverflow — floor (minVisibleItems)', () => {
|
|
93
|
+
it('respects the floor even when items do not fit', () => {
|
|
94
|
+
expect(
|
|
95
|
+
compute({
|
|
96
|
+
widths: [100, 100, 100],
|
|
97
|
+
indicatorWidth: 30,
|
|
98
|
+
availableWidth: 50,
|
|
99
|
+
minVisibleItems: 2,
|
|
100
|
+
}),
|
|
101
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('floor larger than itemCount is clamped to itemCount', () => {
|
|
105
|
+
expect(
|
|
106
|
+
compute({
|
|
107
|
+
widths: [100, 100],
|
|
108
|
+
availableWidth: 10,
|
|
109
|
+
minVisibleItems: 5,
|
|
110
|
+
}),
|
|
111
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('computeOverflow — cap (maxVisibleItems)', () => {
|
|
116
|
+
it('caps below fit even when everything fits', () => {
|
|
117
|
+
// all 5 fit in a wide container, cap at 2
|
|
118
|
+
expect(
|
|
119
|
+
compute({
|
|
120
|
+
widths: [40, 40, 40, 40, 40],
|
|
121
|
+
gap: 8,
|
|
122
|
+
availableWidth: 10000,
|
|
123
|
+
maxVisibleItems: 2,
|
|
124
|
+
}),
|
|
125
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('cap of 0 shows nothing', () => {
|
|
129
|
+
expect(
|
|
130
|
+
compute({
|
|
131
|
+
widths: [40, 40, 40],
|
|
132
|
+
availableWidth: 10000,
|
|
133
|
+
maxVisibleItems: 0,
|
|
134
|
+
}),
|
|
135
|
+
).toEqual({visibleCount: 0, rows: 0});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('cap greater than itemCount is a no-op', () => {
|
|
139
|
+
expect(
|
|
140
|
+
compute({
|
|
141
|
+
widths: [40, 40, 40],
|
|
142
|
+
gap: 8,
|
|
143
|
+
availableWidth: 10000,
|
|
144
|
+
maxVisibleItems: 99,
|
|
145
|
+
}),
|
|
146
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('cap does not raise a fit-limited count', () => {
|
|
150
|
+
// container only fits 2, cap is 4 → still 2
|
|
151
|
+
expect(
|
|
152
|
+
compute({
|
|
153
|
+
widths: [50, 50, 50, 50],
|
|
154
|
+
gap: 10,
|
|
155
|
+
indicatorWidth: 30,
|
|
156
|
+
availableWidth: 150,
|
|
157
|
+
maxVisibleItems: 4,
|
|
158
|
+
}),
|
|
159
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('computeOverflow — cap + floor composition', () => {
|
|
164
|
+
it('both honored when min <= max', () => {
|
|
165
|
+
// fit would be 2; floor 1, cap 3 → 2
|
|
166
|
+
expect(
|
|
167
|
+
compute({
|
|
168
|
+
widths: [50, 50, 50, 50],
|
|
169
|
+
gap: 10,
|
|
170
|
+
indicatorWidth: 30,
|
|
171
|
+
availableWidth: 150,
|
|
172
|
+
minVisibleItems: 1,
|
|
173
|
+
maxVisibleItems: 3,
|
|
174
|
+
}),
|
|
175
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('D1: when max < min, min wins', () => {
|
|
179
|
+
// wide container fits all 5; floor 3, cap 1 → floor wins → 3
|
|
180
|
+
expect(
|
|
181
|
+
compute({
|
|
182
|
+
widths: [40, 40, 40, 40, 40],
|
|
183
|
+
gap: 8,
|
|
184
|
+
availableWidth: 10000,
|
|
185
|
+
minVisibleItems: 3,
|
|
186
|
+
maxVisibleItems: 1,
|
|
187
|
+
}),
|
|
188
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('computeOverflow — collapseFrom start vs end + cap', () => {
|
|
193
|
+
it('single-line collapseFrom start keeps the tail', () => {
|
|
194
|
+
// Items: 30, 80, 40. gap 10, indicator 25, container 100.
|
|
195
|
+
// reversed: [40, 80, 30] → only 40 fits → visibleCount 1
|
|
196
|
+
expect(
|
|
197
|
+
compute({
|
|
198
|
+
widths: [30, 80, 40],
|
|
199
|
+
gap: 10,
|
|
200
|
+
indicatorWidth: 25,
|
|
201
|
+
availableWidth: 100,
|
|
202
|
+
collapseFrom: 'start',
|
|
203
|
+
}),
|
|
204
|
+
).toEqual({visibleCount: 1, rows: 1});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('collapseFrom start + cap trims from the correct end', () => {
|
|
208
|
+
expect(
|
|
209
|
+
compute({
|
|
210
|
+
widths: [40, 40, 40, 40],
|
|
211
|
+
gap: 8,
|
|
212
|
+
availableWidth: 10000,
|
|
213
|
+
collapseFrom: 'start',
|
|
214
|
+
maxVisibleItems: 2,
|
|
215
|
+
}),
|
|
216
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe('computeOverflow — multi-row (maxRows)', () => {
|
|
221
|
+
it('maxRows 1 is equivalent to single line', () => {
|
|
222
|
+
const single = compute({
|
|
223
|
+
widths: [50, 50, 50, 50],
|
|
224
|
+
gap: 10,
|
|
225
|
+
indicatorWidth: 30,
|
|
226
|
+
availableWidth: 150,
|
|
227
|
+
});
|
|
228
|
+
const withMaxRows1 = compute({
|
|
229
|
+
widths: [50, 50, 50, 50],
|
|
230
|
+
gap: 10,
|
|
231
|
+
indicatorWidth: 30,
|
|
232
|
+
availableWidth: 150,
|
|
233
|
+
maxRows: 1,
|
|
234
|
+
});
|
|
235
|
+
expect(withMaxRows1).toEqual(single);
|
|
236
|
+
expect(withMaxRows1).toEqual({visibleCount: 2, rows: 1});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('packs items onto exactly maxRows rows when all fit', () => {
|
|
240
|
+
// 6×50, gap 10 → each row of width 170 holds 3 (50+10+50+10+50=170).
|
|
241
|
+
// availableWidth 170, maxRows 2 → all 6 fit on 2 rows.
|
|
242
|
+
expect(
|
|
243
|
+
compute({
|
|
244
|
+
widths: [50, 50, 50, 50, 50, 50],
|
|
245
|
+
gap: 10,
|
|
246
|
+
availableWidth: 170,
|
|
247
|
+
maxRows: 2,
|
|
248
|
+
}),
|
|
249
|
+
).toEqual({visibleCount: 6, rows: 2});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('collapses overflow past maxRows into the indicator (reserved on last row)', () => {
|
|
253
|
+
// 8×50, gap 10, width 170 → 3 per row. maxRows 2.
|
|
254
|
+
// Row 1: 3 items (170). Row 2 (last): reserve indicator 40 + gap 10 = 50.
|
|
255
|
+
// available for items on row 2 = 170; place 50 (ok, rowWidth 50),
|
|
256
|
+
// next 50 → 50+10+50=110 + reserve 50 = 160 ≤ 170 ok (2 items),
|
|
257
|
+
// next 50 → 110+10+50=170 + 50 = 220 > 170 stop. Row 2 holds 2.
|
|
258
|
+
// → 3 + 2 = 5 visible, 2 rows.
|
|
259
|
+
expect(
|
|
260
|
+
compute({
|
|
261
|
+
widths: [50, 50, 50, 50, 50, 50, 50, 50],
|
|
262
|
+
gap: 10,
|
|
263
|
+
indicatorWidth: 40,
|
|
264
|
+
availableWidth: 170,
|
|
265
|
+
maxRows: 2,
|
|
266
|
+
}),
|
|
267
|
+
).toEqual({visibleCount: 5, rows: 2});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('all items on a single row still reports rows: 1 under maxRows 2', () => {
|
|
271
|
+
expect(
|
|
272
|
+
compute({
|
|
273
|
+
widths: [30, 30, 30],
|
|
274
|
+
gap: 5,
|
|
275
|
+
availableWidth: 500,
|
|
276
|
+
maxRows: 2,
|
|
277
|
+
}),
|
|
278
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('cap wins when it is stricter than the rows allow', () => {
|
|
282
|
+
// 6 items fit on 2 rows, but cap at 4 → 4 visible.
|
|
283
|
+
expect(
|
|
284
|
+
compute({
|
|
285
|
+
widths: [50, 50, 50, 50, 50, 50],
|
|
286
|
+
gap: 10,
|
|
287
|
+
indicatorWidth: 40,
|
|
288
|
+
availableWidth: 170,
|
|
289
|
+
maxRows: 2,
|
|
290
|
+
maxVisibleItems: 4,
|
|
291
|
+
}),
|
|
292
|
+
).toEqual({visibleCount: 4, rows: 2});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('rows win when they are stricter than the cap', () => {
|
|
296
|
+
// maxRows 2 admits 5 (see above); cap 8 is looser → rows win → 5.
|
|
297
|
+
expect(
|
|
298
|
+
compute({
|
|
299
|
+
widths: [50, 50, 50, 50, 50, 50, 50, 50],
|
|
300
|
+
gap: 10,
|
|
301
|
+
indicatorWidth: 40,
|
|
302
|
+
availableWidth: 170,
|
|
303
|
+
maxRows: 2,
|
|
304
|
+
maxVisibleItems: 8,
|
|
305
|
+
}),
|
|
306
|
+
).toEqual({visibleCount: 5, rows: 2});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('multi-row collapseFrom start keeps the tail items', () => {
|
|
310
|
+
// 8 items, reversed packing; same geometry as the end case → 5 visible.
|
|
311
|
+
const res = compute({
|
|
312
|
+
widths: [50, 50, 50, 50, 50, 50, 50, 50],
|
|
313
|
+
gap: 10,
|
|
314
|
+
indicatorWidth: 40,
|
|
315
|
+
availableWidth: 170,
|
|
316
|
+
maxRows: 2,
|
|
317
|
+
collapseFrom: 'start',
|
|
318
|
+
});
|
|
319
|
+
expect(res).toEqual({visibleCount: 5, rows: 2});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('maxRows taller than content does not add phantom rows', () => {
|
|
323
|
+
// 3 items fit on one row; maxRows 5 → rows 1, all visible.
|
|
324
|
+
expect(
|
|
325
|
+
compute({
|
|
326
|
+
widths: [40, 40, 40],
|
|
327
|
+
gap: 10,
|
|
328
|
+
availableWidth: 500,
|
|
329
|
+
maxRows: 5,
|
|
330
|
+
}),
|
|
331
|
+
).toEqual({visibleCount: 3, rows: 1});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('floor is honored in multi-row even when nothing fits', () => {
|
|
335
|
+
// Very narrow container, floor 2.
|
|
336
|
+
expect(
|
|
337
|
+
compute({
|
|
338
|
+
widths: [500, 500, 500],
|
|
339
|
+
gap: 10,
|
|
340
|
+
indicatorWidth: 40,
|
|
341
|
+
availableWidth: 100,
|
|
342
|
+
maxRows: 2,
|
|
343
|
+
minVisibleItems: 2,
|
|
344
|
+
}),
|
|
345
|
+
).toEqual({visibleCount: 2, rows: 2});
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
describe('computeOverflow — resize behavior (shrink/grow re-clamps, never exceeds cap)', () => {
|
|
350
|
+
const base: Partial<ComputeOverflowInput> = {
|
|
351
|
+
widths: [50, 50, 50, 50, 50],
|
|
352
|
+
gap: 10,
|
|
353
|
+
indicatorWidth: 30,
|
|
354
|
+
maxVisibleItems: 3,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
it('grows back only up to the cap', () => {
|
|
358
|
+
// Huge container would fit all 5, cap holds at 3.
|
|
359
|
+
expect(compute({...base, availableWidth: 10000})).toEqual({
|
|
360
|
+
visibleCount: 3,
|
|
361
|
+
rows: 1,
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('shrinks below the cap when space is tight', () => {
|
|
366
|
+
// Narrow container fits fewer than the cap.
|
|
367
|
+
expect(compute({...base, availableWidth: 150})).toEqual({
|
|
368
|
+
visibleCount: 2,
|
|
369
|
+
rows: 1,
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('never exceeds the cap across a shrink→grow cycle', () => {
|
|
374
|
+
const shrunk = compute({...base, availableWidth: 120});
|
|
375
|
+
const grown = compute({...base, availableWidth: 10000});
|
|
376
|
+
expect(grown.visibleCount).toBeLessThanOrEqual(3);
|
|
377
|
+
expect(shrunk.visibleCount).toBeLessThanOrEqual(grown.visibleCount);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('computeOverflow — degenerate inputs', () => {
|
|
382
|
+
it('empty list', () => {
|
|
383
|
+
expect(compute({widths: []})).toEqual({visibleCount: 0, rows: 0});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it('single item that fits', () => {
|
|
387
|
+
expect(compute({widths: [50], gap: 10, availableWidth: 100})).toEqual({
|
|
388
|
+
visibleCount: 1,
|
|
389
|
+
rows: 1,
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('single item that does not fit, no floor', () => {
|
|
394
|
+
expect(
|
|
395
|
+
compute({widths: [200], indicatorWidth: 30, availableWidth: 100}),
|
|
396
|
+
).toEqual({visibleCount: 0, rows: 0});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('maxRows 0 falls back to single-line semantics', () => {
|
|
400
|
+
// maxRows 0 is degenerate; treated as single line (not multi-row).
|
|
401
|
+
expect(
|
|
402
|
+
compute({
|
|
403
|
+
widths: [50, 50, 50],
|
|
404
|
+
gap: 10,
|
|
405
|
+
availableWidth: 130,
|
|
406
|
+
maxRows: 0,
|
|
407
|
+
}),
|
|
408
|
+
).toEqual({visibleCount: 2, rows: 1});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('cap 0 with floor 0 and multi-row shows nothing', () => {
|
|
412
|
+
expect(
|
|
413
|
+
compute({
|
|
414
|
+
widths: [50, 50],
|
|
415
|
+
gap: 10,
|
|
416
|
+
availableWidth: 500,
|
|
417
|
+
maxRows: 2,
|
|
418
|
+
maxVisibleItems: 0,
|
|
419
|
+
}),
|
|
420
|
+
).toEqual({visibleCount: 0, rows: 0});
|
|
421
|
+
});
|
|
422
|
+
});
|