@astryxdesign/core 0.1.4 → 0.1.5-canary.76e6697
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 +141 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +20 -18
- package/dist/AlertDialog/useImperativeAlertDialog.d.ts +0 -2
- package/dist/AlertDialog/useImperativeAlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/useImperativeAlertDialog.js +3 -5
- package/dist/AppShell/AppShell.d.ts +1 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +55 -53
- package/dist/AspectRatio/AspectRatio.d.ts +48 -10
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +33 -12
- package/dist/AspectRatio/index.d.ts +1 -1
- package/dist/AspectRatio/index.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +28 -26
- package/dist/Avatar/AvatarStatusDot.js +6 -6
- package/dist/AvatarGroup/AvatarGroup.js +6 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -7
- package/dist/Badge/Badge.js +3 -3
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +32 -25
- package/dist/Blockquote/Blockquote.js +7 -7
- package/dist/Breadcrumbs/BreadcrumbItem.js +17 -17
- package/dist/Breadcrumbs/Breadcrumbs.js +7 -7
- package/dist/Button/Button.js +19 -19
- package/dist/ButtonGroup/ButtonGroup.js +7 -7
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +68 -48
- package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
- package/dist/Calendar/styles.d.ts +2 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +2 -2
- package/dist/Card/Card.d.ts +4 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +18 -10
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +24 -21
- package/dist/Center/Center.js +3 -3
- package/dist/Chat/ChatComposer.js +23 -23
- package/dist/Chat/ChatComposerDrawer.js +14 -14
- package/dist/Chat/ChatComposerInput.d.ts +1 -1
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +27 -15
- package/dist/Chat/ChatDictationButton.d.ts +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +13 -11
- package/dist/Chat/ChatLayout.js +17 -17
- package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +12 -10
- package/dist/Chat/ChatMessage.js +12 -12
- package/dist/Chat/ChatMessageBubble.js +7 -7
- package/dist/Chat/ChatMessageList.js +14 -14
- package/dist/Chat/ChatMessageMetadata.d.ts +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +14 -12
- package/dist/Chat/ChatPastedTextToken.js +13 -13
- package/dist/Chat/ChatSendButton.js +3 -3
- package/dist/Chat/ChatSystemMessage.d.ts +1 -1
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +17 -17
- package/dist/Chat/ChatTokenizedText.d.ts +1 -1
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +24 -15
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +81 -74
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -15
- package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +25 -23
- package/dist/CheckboxList/CheckboxList.js +9 -9
- package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +8 -6
- package/dist/Citation/Citation.js +10 -10
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +32 -9
- package/dist/Code/Code.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts +10 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +88 -52
- package/dist/Collapsible/Collapsible.d.ts +9 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +109 -22
- package/dist/Collapsible/CollapsibleGroup.d.ts +37 -7
- package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +64 -12
- package/dist/Collapsible/CollapsibleGroupContext.d.ts +24 -0
- package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +26 -3
- package/dist/Collapsible/index.d.ts +1 -0
- package/dist/Collapsible/index.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.d.ts +4 -1
- package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.js +20 -6
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +36 -34
- package/dist/CommandPalette/CommandPaletteEmpty.js +3 -3
- package/dist/CommandPalette/CommandPaletteFooter.js +16 -16
- package/dist/CommandPalette/CommandPaletteGroup.js +5 -5
- package/dist/CommandPalette/CommandPaletteInput.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.js +3 -3
- package/dist/CommandPalette/CommandPaletteList.js +3 -3
- package/dist/ContextMenu/ContextMenu.d.ts +7 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +76 -43
- package/dist/DateInput/DateInput.js +18 -18
- package/dist/DateRangeInput/DateRangeInput.js +21 -21
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +30 -26
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +9 -9
- package/dist/Dialog/DialogHeader.js +16 -16
- package/dist/Dialog/useImperativeDialog.js +3 -3
- package/dist/Divider/Divider.js +7 -7
- package/dist/DropdownMenu/DropdownMenu.js +10 -10
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +2 -17
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
- package/dist/DropdownMenu/renderDropdownItems.js +10 -10
- package/dist/EmptyState/EmptyState.js +9 -9
- package/dist/Field/Field.js +17 -17
- package/dist/Field/FieldLabel.js +15 -15
- package/dist/Field/InputClearButton.js +5 -5
- package/dist/FieldStatus/FieldStatus.js +3 -3
- package/dist/FileInput/FileInput.js +29 -29
- package/dist/FormLayout/FormLayout.js +5 -5
- package/dist/Grid/Grid.d.ts +4 -3
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +29 -12
- package/dist/Grid/GridSpan.js +3 -3
- package/dist/HStack/HStack.js +3 -3
- package/dist/Heading/Heading.js +10 -10
- package/dist/HoverCard/HoverCard.js +9 -9
- package/dist/HoverCard/useHoverCard.d.ts +5 -1
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +3 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +16 -12
- package/dist/Icon/defaultIcons.js +116 -116
- package/dist/IconButton/IconButton.js +3 -3
- package/dist/InputGroup/InputGroup.js +11 -11
- package/dist/InputGroup/InputGroupText.js +3 -3
- package/dist/Item/Item.js +18 -18
- package/dist/Kbd/Kbd.js +5 -5
- package/dist/Layer/LayerProvider.js +7 -7
- package/dist/Layer/useLayer.d.ts +29 -2
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +44 -31
- package/dist/Layout/Layout.js +21 -21
- package/dist/Layout/LayoutContent.js +3 -3
- package/dist/Layout/LayoutFooter.js +5 -5
- package/dist/Layout/LayoutHeader.js +5 -5
- package/dist/Layout/LayoutPanel.js +3 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +55 -31
- package/dist/Lightbox/useLightbox.d.ts +0 -1
- package/dist/Lightbox/useLightbox.d.ts.map +1 -1
- package/dist/Lightbox/useLightbox.js +3 -4
- package/dist/Link/Link.d.ts +0 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +15 -17
- package/dist/Link/LinkProvider.js +3 -3
- package/dist/Link/useLinkify.js +3 -3
- package/dist/List/List.js +11 -11
- package/dist/List/ListItem.js +11 -11
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +102 -102
- package/dist/MetadataList/MetadataList.js +10 -10
- package/dist/MetadataList/MetadataListItem.js +15 -15
- package/dist/MobileNav/MobileNav.d.ts +1 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +26 -23
- package/dist/MobileNav/MobileNavToggle.js +5 -5
- package/dist/MoreMenu/MoreMenu.js +3 -3
- package/dist/MultiSelector/MultiSelector.js +56 -56
- package/dist/NavIcon/NavIcon.js +3 -3
- package/dist/NavMenu/NavHeadingMenu.js +5 -5
- package/dist/NavMenu/NavHeadingMenuItem.js +8 -8
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +48 -32
- package/dist/Outline/Outline.js +15 -15
- package/dist/OverflowList/OverflowList.js +8 -8
- package/dist/Overlay/Overlay.js +3 -3
- package/dist/Overlay/OverlayScrim.js +5 -5
- package/dist/Overlay/useOverlay.d.ts +0 -3
- package/dist/Overlay/useOverlay.d.ts.map +1 -1
- package/dist/Overlay/useOverlay.js +3 -6
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +125 -72
- package/dist/Popover/Popover.js +16 -16
- package/dist/Popover/usePopover.js +7 -7
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +110 -92
- package/dist/PowerSearch/PowerSearchEditPopover.js +84 -84
- package/dist/PowerSearch/PowerSearchFilterEditor.js +3 -3
- package/dist/PowerSearch/PowerSearchToken.js +5 -5
- package/dist/PowerSearch/PowerSearchValueEditor.js +54 -54
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +25 -18
- package/dist/RadioList/RadioList.js +7 -7
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +24 -21
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +28 -10
- package/dist/Section/Section.js +5 -5
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +32 -10
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +18 -12
- package/dist/SelectableCard/SelectableCard.js +5 -5
- package/dist/Selector/Selector.js +46 -46
- package/dist/Selector/SelectorOption.js +3 -3
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +38 -34
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +8 -6
- package/dist/SideNav/SideNavHeading.js +87 -87
- package/dist/SideNav/SideNavItem.js +42 -42
- package/dist/SideNav/SideNavSection.d.ts +1 -1
- package/dist/SideNav/SideNavSection.d.ts.map +1 -1
- package/dist/SideNav/SideNavSection.js +18 -16
- package/dist/Skeleton/Skeleton.js +3 -3
- package/dist/Slider/Slider.js +23 -23
- package/dist/Spinner/Spinner.js +9 -9
- package/dist/StatusDot/StatusDot.js +5 -5
- package/dist/Switch/Switch.d.ts +8 -4
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +34 -29
- package/dist/TabList/Tab.js +18 -18
- package/dist/TabList/TabList.js +5 -5
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +57 -30
- package/dist/TabList/tab.markers.stylex.d.ts +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +50 -39
- package/dist/Table/Table.js +7 -7
- package/dist/Table/TableBody.d.ts +1 -1
- package/dist/Table/TableBody.d.ts.map +1 -1
- package/dist/Table/TableBody.js +9 -5
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableFooter.d.ts +1 -1
- package/dist/Table/TableFooter.d.ts.map +1 -1
- package/dist/Table/TableFooter.js +9 -5
- package/dist/Table/TableHeader.d.ts +1 -1
- package/dist/Table/TableHeader.d.ts.map +1 -1
- package/dist/Table/TableHeader.js +9 -5
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/TableRow.js +5 -5
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +14 -11
- package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
- package/dist/Table/plugins/groupedRows/index.d.ts +3 -0
- package/dist/Table/plugins/groupedRows/index.d.ts.map +1 -0
- package/dist/Table/plugins/groupedRows/index.js +3 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +78 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +250 -0
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +5 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +23 -23
- package/dist/Table/plugins/selection/useTableSelection.js +18 -18
- package/dist/Table/plugins/selection/useTableSelectionState.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelectionState.js +11 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +17 -17
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +8 -4
- package/dist/Table/tableContextMenu.js +9 -9
- package/dist/Text/Text.js +10 -10
- package/dist/TextArea/TextArea.js +14 -14
- package/dist/TextInput/TextInput.js +15 -15
- package/dist/Thumbnail/Thumbnail.d.ts +3 -2
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +30 -29
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +26 -21
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +37 -26
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +25 -17
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +23 -11
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +44 -4
- package/dist/ToggleButton/ToggleButton.js +12 -12
- package/dist/ToggleButton/ToggleButtonGroup.js +5 -5
- package/dist/Token/Token.js +21 -21
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +36 -34
- package/dist/Toolbar/Toolbar.js +18 -18
- package/dist/Tooltip/Tooltip.js +11 -11
- package/dist/Tooltip/useTooltip.d.ts +5 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +3 -3
- package/dist/TopNav/TopNav.js +32 -32
- package/dist/TopNav/TopNavHeading.js +67 -67
- package/dist/TopNav/TopNavItem.js +5 -5
- package/dist/TopNav/TopNavMegaMenu.js +30 -30
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +25 -14
- package/dist/TopNav/TopNavMegaMenuItem.js +16 -16
- package/dist/TopNav/TopNavMenu.js +32 -32
- package/dist/TreeList/TreeList.js +8 -8
- package/dist/TreeList/TreeListBranches.js +11 -11
- package/dist/TreeList/TreeListItem.js +30 -30
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +23 -20
- package/dist/Typeahead/Typeahead.js +12 -12
- package/dist/Typeahead/TypeaheadItem.js +10 -10
- package/dist/VStack/VStack.js +3 -3
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +0 -3
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +0 -3
- package/dist/astryx.css +7 -0
- package/dist/astryx.umd.js +63 -63
- package/dist/astryx.umd.js.map +4 -4
- package/dist/docs-types.d.ts +8 -2
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.d.ts +1 -1
- package/dist/hooks/focusableSelector.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.js +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +3 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +38 -1
- package/dist/hooks/useHotkeys.d.ts +51 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -0
- package/dist/hooks/useHotkeys.js +160 -0
- package/dist/hooks/useInteractiveRole.d.ts +6 -2
- package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
- package/dist/hooks/useInteractiveRole.js +6 -2
- package/dist/hooks/useKeyboardHint.js +9 -9
- package/dist/hooks/useStreamingText.d.ts +3 -1
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +14 -5
- package/dist/theme/MediaTheme.js +3 -3
- package/dist/theme/Theme.js +7 -7
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +10 -3
- package/dist/theme/hct.d.ts +0 -15
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +9 -9
- package/dist/theme/syntax/SyntaxTheme.js +5 -5
- package/dist/theme/tokens.d.ts +10 -2
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +220 -4
- package/dist/theme/useTheme.d.ts +3 -2
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +73 -6
- package/dist/utils/color.d.ts +42 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/color.js +150 -0
- package/dist/utils/composeEventHandlers.d.ts +30 -0
- package/dist/utils/composeEventHandlers.d.ts.map +1 -0
- package/dist/utils/composeEventHandlers.js +40 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +8 -5
- package/package.json +4 -4
- package/src/AlertDialog/AlertDialog.doc.mjs +4 -0
- package/src/AlertDialog/AlertDialog.tsx +2 -0
- package/src/AlertDialog/useImperativeAlertDialog.tsx +0 -2
- package/src/AppShell/AppShell.tsx +2 -0
- package/src/AspectRatio/AspectRatio.doc.mjs +28 -1
- package/src/AspectRatio/AspectRatio.test.tsx +142 -1
- package/src/AspectRatio/AspectRatio.tsx +70 -10
- package/src/AspectRatio/index.ts +5 -1
- package/src/Avatar/Avatar.doc.mjs +11 -0
- package/src/Avatar/Avatar.test.tsx +32 -1
- package/src/Avatar/Avatar.tsx +14 -22
- package/src/Avatar/AvatarStatusDot.tsx +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -0
- package/src/AvatarGroup/AvatarGroup.tsx +2 -2
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -2
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +38 -0
- package/src/Banner/Banner.tsx +8 -1
- package/src/Calendar/Calendar.doc.mjs +1 -1
- package/src/Calendar/Calendar.test.tsx +122 -17
- package/src/Calendar/Calendar.tsx +26 -5
- package/src/Calendar/dayCellUtils.ts +3 -1
- package/src/Calendar/styles.ts +12 -2
- package/src/Card/Card.doc.mjs +1 -1
- package/src/Card/Card.tsx +16 -6
- package/src/Carousel/Carousel.doc.mjs +12 -12
- package/src/Carousel/Carousel.test.tsx +13 -0
- package/src/Carousel/Carousel.tsx +4 -2
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.test.tsx +27 -1
- package/src/Chat/ChatComposerInput.tsx +20 -15
- package/src/Chat/ChatDictationButton.test.tsx +43 -0
- package/src/Chat/ChatDictationButton.tsx +4 -4
- package/src/Chat/ChatLayoutScrollButton.test.tsx +33 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessageMetadata.test.tsx +32 -0
- package/src/Chat/ChatMessageMetadata.tsx +4 -6
- package/src/Chat/ChatSystemMessage.test.tsx +26 -11
- package/src/Chat/ChatSystemMessage.tsx +7 -7
- package/src/Chat/ChatTokenizedText.test.tsx +29 -16
- package/src/Chat/ChatTokenizedText.tsx +15 -8
- package/src/Chat/ChatToolCalls.test.tsx +55 -0
- package/src/Chat/ChatToolCalls.tsx +10 -12
- package/src/Chat/index.ts +1 -4
- package/src/Chat/useTriggerMenu.tsx +1 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -3
- package/src/CheckboxInput/CheckboxInput.test.tsx +71 -4
- package/src/CheckboxInput/CheckboxInput.tsx +2 -0
- package/src/CheckboxList/CheckboxList.test.tsx +19 -0
- package/src/CheckboxList/CheckboxListItem.tsx +11 -2
- package/src/Citation/Citation.doc.mjs +5 -0
- package/src/ClickableCard/ClickableCard.tsx +45 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +7 -2
- package/src/CodeBlock/CodeBlock.test.tsx +122 -3
- package/src/CodeBlock/CodeBlock.tsx +62 -4
- package/src/Collapsible/Collapsible.doc.mjs +8 -4
- package/src/Collapsible/Collapsible.test.tsx +403 -0
- package/src/Collapsible/Collapsible.tsx +85 -10
- package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
- package/src/Collapsible/CollapsibleGroup.test.tsx +314 -0
- package/src/Collapsible/CollapsibleGroup.tsx +97 -9
- package/src/Collapsible/CollapsibleGroupContext.tsx +34 -2
- package/src/Collapsible/index.ts +1 -0
- package/src/Collapsible/useCollapsible.ts +20 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +5 -0
- package/src/CommandPalette/CommandPalette.tsx +5 -3
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
- package/src/CommandPalette/CommandPaletteGroup.doc.mjs +10 -0
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteList.doc.mjs +9 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +15 -0
- package/src/ContextMenu/ContextMenu.test.tsx +87 -0
- package/src/ContextMenu/ContextMenu.tsx +87 -28
- package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
- package/src/DateInput/DateInput.test.tsx +11 -20
- package/src/DateRangeInput/DateRangeInput.doc.mjs +9 -6
- package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
- package/src/DateTimeInput/DateTimeInput.doc.mjs +3 -2
- package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
- package/src/DateTimeInput/DateTimeInput.tsx +8 -2
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +4 -0
- package/src/Dialog/DialogHeader.doc.mjs +45 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +22 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
- package/src/EmptyState/EmptyState.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +1 -4
- package/src/Field/FieldLabel.test.tsx +2 -2
- package/src/FieldStatus/FieldStatus.test.tsx +282 -0
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
- package/src/Grid/Grid.test.tsx +43 -18
- package/src/Grid/Grid.tsx +26 -9
- package/src/HoverCard/HoverCard.doc.mjs +6 -6
- package/src/HoverCard/useHoverCard.doc.mjs +5 -5
- package/src/HoverCard/useHoverCard.tsx +9 -2
- package/src/Icon/Icon.test.tsx +41 -29
- package/src/Icon/Icon.tsx +6 -2
- package/src/InputGroup/InputGroup.doc.mjs +1 -0
- package/src/InputGroup/InputGroup.tsx +2 -2
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
- package/src/Item/Item.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layer/useLayer.test.tsx +221 -2
- package/src/Layer/useLayer.tsx +69 -30
- package/src/Layout/Layout.test.tsx +285 -0
- package/src/Layout/LayoutContent.doc.mjs +12 -0
- package/src/Layout/LayoutPanel.doc.mjs +40 -0
- package/src/Layout/LayoutSlots.test.tsx +364 -0
- package/src/Lightbox/Lightbox.doc.mjs +5 -0
- package/src/Lightbox/Lightbox.test.tsx +123 -2
- package/src/Lightbox/Lightbox.tsx +29 -1
- package/src/Lightbox/useLightbox.tsx +0 -1
- package/src/Link/Link.tsx +0 -2
- package/src/Markdown/Markdown.tsx +9 -7
- package/src/Markdown/parser.perf.test.ts +34 -12
- package/src/MobileNav/MobileNav.test.tsx +56 -0
- package/src/MobileNav/MobileNav.tsx +13 -8
- package/src/NavMenu/NavMenu.doc.mjs +15 -0
- package/src/NumberInput/NumberInput.test.tsx +48 -3
- package/src/NumberInput/NumberInput.tsx +32 -15
- package/src/Outline/Outline.doc.mjs +2 -0
- package/src/Outline/parseOutlineFromMarkdown.test.ts +80 -0
- package/src/OverflowList/OverflowList.test.tsx +416 -0
- package/src/Overlay/Overlay.doc.mjs +6 -0
- package/src/Overlay/Overlay.test.tsx +356 -0
- package/src/Overlay/useOverlay.tsx +0 -3
- package/src/Pagination/Pagination.test.tsx +162 -0
- package/src/Pagination/Pagination.tsx +80 -26
- package/src/Popover/Popover.doc.mjs +6 -6
- package/src/Popover/Popover.test.tsx +65 -0
- package/src/Popover/usePopover.doc.mjs +1 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
- package/src/PowerSearch/PowerSearch.test.tsx +109 -1
- package/src/PowerSearch/PowerSearch.tsx +37 -16
- package/src/ProgressBar/ProgressBar.doc.mjs +2 -0
- package/src/ProgressBar/ProgressBar.test.tsx +30 -0
- package/src/ProgressBar/ProgressBar.tsx +12 -5
- package/src/RadioList/RadioList.test.tsx +19 -0
- package/src/RadioList/RadioListItem.tsx +9 -4
- package/src/Resizable/ResizeHandle.test.tsx +218 -0
- package/src/Resizable/ResizeHandle.tsx +22 -4
- package/src/SegmentedControl/SegmentedControl.doc.mjs +1 -1
- package/src/SegmentedControl/SegmentedControl.test.tsx +192 -0
- package/src/SegmentedControl/SegmentedControl.tsx +27 -5
- package/src/SegmentedControl/SegmentedControlItem.tsx +9 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.test.tsx +27 -1
- package/src/SideNav/SideNav.doc.mjs +7 -1
- package/src/SideNav/SideNav.test.tsx +66 -0
- package/src/SideNav/SideNav.tsx +6 -2
- package/src/SideNav/SideNavCollapseButton.tsx +4 -3
- package/src/SideNav/SideNavSection.tsx +6 -4
- package/src/SizeContext/SizeContext.test.tsx +226 -0
- package/src/Switch/Switch.doc.mjs +7 -7
- package/src/Switch/Switch.test.tsx +102 -3
- package/src/Switch/Switch.tsx +20 -7
- package/src/TabList/TabList.test.tsx +185 -1
- package/src/TabList/TabMenu.tsx +45 -9
- package/src/Table/BaseTable.tsx +13 -2
- package/src/Table/Table.doc.mjs +6 -1
- package/src/Table/Table.test.tsx +87 -0
- package/src/Table/TableBody.tsx +15 -2
- package/src/Table/TableFooter.tsx +15 -2
- package/src/Table/TableHeader.tsx +15 -2
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +13 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +3 -1
- package/src/Table/plugins/groupedRows/index.ts +7 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +231 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +349 -0
- package/src/Table/plugins/pagination/paginateData.ts +5 -1
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +1 -1
- package/src/Table/plugins/selection/useTableSelectionState.test.tsx +23 -0
- package/src/Table/plugins/selection/useTableSelectionState.tsx +11 -6
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +35 -1
- package/src/Table/plugins/sortable/useTableSortableState.tsx +8 -4
- package/src/Table/useTableGroupedRows.doc.mjs +71 -0
- package/src/TextArea/TextArea.test.tsx +3 -3
- package/src/TextInput/TextInput.test.tsx +3 -3
- package/src/Thumbnail/Thumbnail.test.tsx +36 -2
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.test.tsx +37 -0
- package/src/TimeInput/TimeInput.tsx +11 -1
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +52 -0
- package/src/Timestamp/Timestamp.tsx +30 -16
- package/src/Toast/Toast.tsx +11 -3
- package/src/Toast/ToastViewport.test.tsx +64 -0
- package/src/Toast/ToastViewport.tsx +12 -0
- package/src/Toast/useToast.test.tsx +258 -0
- package/src/Toast/useToast.tsx +41 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.test.tsx +54 -0
- package/src/Tokenizer/Tokenizer.tsx +5 -4
- package/src/Tooltip/Tooltip.doc.mjs +6 -6
- package/src/Tooltip/useTooltip.doc.mjs +5 -5
- package/src/Tooltip/useTooltip.tsx +12 -2
- package/src/TopNav/TopNav.doc.mjs +1 -1
- package/src/TopNav/TopNav.test.tsx +23 -7
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +9 -2
- package/src/TreeList/TreeList.doc.mjs +2 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +19 -0
- package/src/Typeahead/BaseTypeahead.tsx +5 -2
- package/src/Typeahead/Typeahead.doc.mjs +1 -1
- package/src/Typeahead/Typeahead.test.tsx +45 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +0 -3
- package/src/__tests__/TestIcon.tsx +26 -0
- package/src/__tests__/fastRoleQueries.ts +66 -0
- package/src/docPropReferences.test.ts +178 -0
- package/src/docs-types.ts +9 -1
- package/src/hooks/focusableSelector.ts +1 -1
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useFocusTrap.doc.mjs +4 -2
- package/src/hooks/useFocusTrap.test.tsx +149 -1
- package/src/hooks/useFocusTrap.ts +50 -1
- package/src/hooks/useHotkeys.doc.mjs +52 -0
- package/src/hooks/useHotkeys.test.ts +245 -0
- package/src/hooks/useHotkeys.ts +203 -0
- package/src/hooks/useInteractiveRole.ts +12 -4
- package/src/hooks/useStreamingText.test.ts +54 -19
- package/src/hooks/useStreamingText.ts +16 -5
- package/src/hooks/useTreeFocus.test.tsx +1 -3
- package/src/reset.css +29 -0
- package/src/theme/SyntaxTheme.doc.mjs +4 -4
- package/src/theme/defineTheme.ts +4 -13
- package/src/theme/derivedVarRegistry.test.ts +2 -2
- package/src/theme/expandColorScale.test.ts +29 -0
- package/src/theme/expandColorScale.ts +11 -6
- package/src/theme/hct.ts +9 -17
- package/src/theme/themingTargets.test.ts +353 -0
- package/src/theme/tokens.test.ts +182 -9
- package/src/theme/tokens.ts +239 -4
- package/src/theme/useTheme.test.tsx +126 -2
- package/src/theme/useTheme.ts +87 -6
- package/src/utils/color.test.ts +133 -0
- package/src/utils/color.ts +148 -0
- package/src/utils/composeEventHandlers.test.ts +71 -0
- package/src/utils/composeEventHandlers.ts +44 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/mergeProps.test.ts +166 -0
- package/src/utils/sharedResizeObserver.test.ts +2 -2
- package/src/utils/timeParser.test.ts +13 -0
- package/src/utils/timeParser.ts +8 -5
- package/dist/Carousel/carousel.markers.stylex.d.ts +0 -7
- package/dist/Carousel/carousel.markers.stylex.d.ts.map +0 -1
- package/dist/Carousel/carousel.markers.stylex.js +0 -12
- package/src/Carousel/carousel.markers.stylex.ts +0 -10
|
@@ -3,15 +3,21 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file useLayer.test.tsx
|
|
5
5
|
* @input Uses vitest, @testing-library/react, useLayer hook
|
|
6
|
-
* @output
|
|
6
|
+
* @output Tests for useLayer show/hide feature-detection guards and context-mode positioning
|
|
7
7
|
* @position Testing; validates useLayer.tsx implementation
|
|
8
8
|
*
|
|
9
|
-
* SYNC: When useLayer.tsx changes, update tests
|
|
9
|
+
* SYNC: When useLayer.tsx changes, update tests accordingly
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
13
|
import {render, act} from '@testing-library/react';
|
|
14
|
+
import userEvent from '@testing-library/user-event';
|
|
14
15
|
import {useLayer} from './useLayer';
|
|
16
|
+
import type {
|
|
17
|
+
LayerPlacement,
|
|
18
|
+
LayerAlignment,
|
|
19
|
+
ContextRenderProps,
|
|
20
|
+
} from './useLayer';
|
|
15
21
|
|
|
16
22
|
/**
|
|
17
23
|
* Minimal harness that exposes the imperative show/hide callbacks and renders
|
|
@@ -109,3 +115,216 @@ describe('useLayer', () => {
|
|
|
109
115
|
});
|
|
110
116
|
});
|
|
111
117
|
});
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Harness that owns the trigger element.
|
|
121
|
+
*/
|
|
122
|
+
function Harness({
|
|
123
|
+
placement,
|
|
124
|
+
alignment,
|
|
125
|
+
triggerStyle,
|
|
126
|
+
triggerDir,
|
|
127
|
+
}: {
|
|
128
|
+
placement: LayerPlacement;
|
|
129
|
+
alignment: LayerAlignment;
|
|
130
|
+
triggerStyle?: React.CSSProperties;
|
|
131
|
+
triggerDir?: string;
|
|
132
|
+
}) {
|
|
133
|
+
const layer = useLayer({mode: 'context'});
|
|
134
|
+
return (
|
|
135
|
+
<>
|
|
136
|
+
<button
|
|
137
|
+
type="button"
|
|
138
|
+
ref={layer.ref}
|
|
139
|
+
dir={triggerDir}
|
|
140
|
+
style={triggerStyle}
|
|
141
|
+
onClick={layer.isOpen ? layer.hide : layer.show}>
|
|
142
|
+
trigger
|
|
143
|
+
</button>
|
|
144
|
+
{layer.render(<span>content</span>, {placement, alignment})}
|
|
145
|
+
</>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function openAndGetStyle(ui: React.ReactElement): Promise<string> {
|
|
150
|
+
const user = userEvent.setup();
|
|
151
|
+
const {container, getByRole} = render(ui);
|
|
152
|
+
await user.click(getByRole('button', {name: 'trigger'}));
|
|
153
|
+
const popover = container.querySelector('[popover]');
|
|
154
|
+
return popover?.getAttribute('style') ?? '';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
describe('useLayer context positioning', () => {
|
|
158
|
+
// The mapping uses the self-* logical keyword family, so the emitted
|
|
159
|
+
// string is direction-independent by construction: the browser resolves
|
|
160
|
+
// the inline axis against the popover's own inherited direction, and RTL
|
|
161
|
+
// mirrors with no JS. jsdom has no layout engine, so these tests can only
|
|
162
|
+
// assert the emitted string — the actual RTL geometry is covered by the
|
|
163
|
+
// RTL Storybook story (and was verified against the full 12-cell matrix
|
|
164
|
+
// in a real browser).
|
|
165
|
+
describe('self-* position-area mapping', () => {
|
|
166
|
+
it.each([
|
|
167
|
+
// [placement, alignment, expected position-area]
|
|
168
|
+
['above', 'start', 'self-block-start span-self-inline-end'],
|
|
169
|
+
['above', 'center', 'self-block-start'],
|
|
170
|
+
['above', 'end', 'self-block-start span-self-inline-start'],
|
|
171
|
+
['below', 'start', 'self-block-end span-self-inline-end'],
|
|
172
|
+
['below', 'center', 'self-block-end'],
|
|
173
|
+
['below', 'end', 'self-block-end span-self-inline-start'],
|
|
174
|
+
['start', 'start', 'self-inline-start span-self-block-end'],
|
|
175
|
+
['start', 'center', 'self-inline-start'],
|
|
176
|
+
['start', 'end', 'self-inline-start span-self-block-start'],
|
|
177
|
+
['end', 'start', 'self-inline-end span-self-block-end'],
|
|
178
|
+
['end', 'center', 'self-inline-end'],
|
|
179
|
+
['end', 'end', 'self-inline-end span-self-block-start'],
|
|
180
|
+
] as const)(
|
|
181
|
+
'placement=%s alignment=%s emits position-area %s',
|
|
182
|
+
async (placement, alignment, expectedArea) => {
|
|
183
|
+
const style = await openAndGetStyle(
|
|
184
|
+
<Harness placement={placement} alignment={alignment} />,
|
|
185
|
+
);
|
|
186
|
+
expect(style).toMatch(
|
|
187
|
+
new RegExp(`position-area: ${expectedArea}(;|$)`),
|
|
188
|
+
);
|
|
189
|
+
expect(style).not.toContain('justify-self');
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
it('emits the same string regardless of trigger direction', async () => {
|
|
194
|
+
const user = userEvent.setup();
|
|
195
|
+
const first = render(<Harness placement="below" alignment="start" />);
|
|
196
|
+
await user.click(first.getByRole('button', {name: 'trigger'}));
|
|
197
|
+
const ltr =
|
|
198
|
+
first.container.querySelector('[popover]')?.getAttribute('style') ?? '';
|
|
199
|
+
first.unmount();
|
|
200
|
+
|
|
201
|
+
const second = render(
|
|
202
|
+
<Harness
|
|
203
|
+
placement="below"
|
|
204
|
+
alignment="start"
|
|
205
|
+
triggerDir="rtl"
|
|
206
|
+
triggerStyle={{direction: 'rtl'}}
|
|
207
|
+
/>,
|
|
208
|
+
);
|
|
209
|
+
await user.click(second.getByRole('button', {name: 'trigger'}));
|
|
210
|
+
const rtl =
|
|
211
|
+
second.container.querySelector('[popover]')?.getAttribute('style') ??
|
|
212
|
+
'';
|
|
213
|
+
// The unique position-anchor id differs per render; the placement
|
|
214
|
+
// mapping must not.
|
|
215
|
+
const positionArea = (s: string) => s.match(/position-area:[^;]*/)?.[0];
|
|
216
|
+
expect(positionArea(rtl)).toBeDefined();
|
|
217
|
+
expect(positionArea(rtl)).toBe(positionArea(ltr));
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('keeps position-try fallbacks intact', async () => {
|
|
221
|
+
const style = await openAndGetStyle(
|
|
222
|
+
<Harness placement="below" alignment="start" />,
|
|
223
|
+
);
|
|
224
|
+
expect(style).toContain(
|
|
225
|
+
'position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline',
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe("positioning='custom' (consumer-authored position styles)", () => {
|
|
231
|
+
// Consumers like Carousel and Tokenizer keep useLayer's popover behavior
|
|
232
|
+
// and anchor wiring but position the layer themselves. The opt-out must
|
|
233
|
+
// suppress every placement-derived style — position-area and the try
|
|
234
|
+
// fallbacks — so those consumers never need to know which properties
|
|
235
|
+
// the hook would have emitted.
|
|
236
|
+
function CustomHarness({
|
|
237
|
+
triggerStyle,
|
|
238
|
+
renderProps,
|
|
239
|
+
}: {
|
|
240
|
+
triggerStyle?: React.CSSProperties;
|
|
241
|
+
renderProps: ContextRenderProps;
|
|
242
|
+
}) {
|
|
243
|
+
const layer = useLayer({mode: 'context'});
|
|
244
|
+
return (
|
|
245
|
+
<>
|
|
246
|
+
<button
|
|
247
|
+
type="button"
|
|
248
|
+
ref={layer.ref}
|
|
249
|
+
style={triggerStyle}
|
|
250
|
+
onClick={layer.isOpen ? layer.hide : layer.show}>
|
|
251
|
+
trigger
|
|
252
|
+
</button>
|
|
253
|
+
{layer.render(<span>content</span>, renderProps)}
|
|
254
|
+
</>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
it('keeps the anchor wiring but derives no placement styles', async () => {
|
|
259
|
+
const style = await openAndGetStyle(
|
|
260
|
+
<CustomHarness
|
|
261
|
+
renderProps={{
|
|
262
|
+
positioning: 'custom',
|
|
263
|
+
style: {positionArea: 'center'},
|
|
264
|
+
}}
|
|
265
|
+
/>,
|
|
266
|
+
);
|
|
267
|
+
expect(style).toContain('position-anchor');
|
|
268
|
+
// The consumer-authored area is the only one present…
|
|
269
|
+
expect(style).toContain('position-area: center');
|
|
270
|
+
// …and no placement-derived styles leak through.
|
|
271
|
+
expect(style).not.toContain('position-try-fallbacks');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('ignores placement and alignment when positioning is custom', async () => {
|
|
275
|
+
// placement/alignment are documented as ignored under custom. Derived
|
|
276
|
+
// output would be position-area "self-block-end span-self-inline-end";
|
|
277
|
+
// none of it may appear.
|
|
278
|
+
const style = await openAndGetStyle(
|
|
279
|
+
<CustomHarness
|
|
280
|
+
renderProps={{
|
|
281
|
+
positioning: 'custom',
|
|
282
|
+
placement: 'below',
|
|
283
|
+
alignment: 'start',
|
|
284
|
+
style: {positionArea: 'center'},
|
|
285
|
+
}}
|
|
286
|
+
/>,
|
|
287
|
+
);
|
|
288
|
+
expect(style).toContain('position-anchor');
|
|
289
|
+
expect(style).toContain('position-area: center');
|
|
290
|
+
expect(style).not.toContain('self-block');
|
|
291
|
+
expect(style).not.toContain('position-try-fallbacks');
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('emits only the anchor wiring when custom positioning passes no style at all', async () => {
|
|
295
|
+
// The strongest suppression probe: with no consumer style in the merge
|
|
296
|
+
// (Tokenizer's insets-only shape reduces to this in jsdom), nothing can
|
|
297
|
+
// clobber a leaked derived value — any position-area or try-fallbacks
|
|
298
|
+
// in the output is a genuine leak.
|
|
299
|
+
const style = await openAndGetStyle(
|
|
300
|
+
<CustomHarness renderProps={{positioning: 'custom'}} />,
|
|
301
|
+
);
|
|
302
|
+
expect(style).toContain('position-anchor');
|
|
303
|
+
expect(style).not.toContain('position-area');
|
|
304
|
+
expect(style).not.toContain('position-try-fallbacks');
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('fixed mode emits no anchor-positioning styles', async () => {
|
|
309
|
+
function FixedHarness() {
|
|
310
|
+
const layer = useLayer({mode: 'fixed'});
|
|
311
|
+
return (
|
|
312
|
+
<>
|
|
313
|
+
<button type="button" onClick={layer.show}>
|
|
314
|
+
opener
|
|
315
|
+
</button>
|
|
316
|
+
{layer.render(<span>content</span>, {x: 10, y: 20})}
|
|
317
|
+
</>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const user = userEvent.setup();
|
|
322
|
+
const {container, getByRole} = render(<FixedHarness />);
|
|
323
|
+
await user.click(getByRole('button', {name: 'opener'}));
|
|
324
|
+
|
|
325
|
+
const style =
|
|
326
|
+
container.querySelector('[popover]')?.getAttribute('style') ?? '';
|
|
327
|
+
expect(style).not.toContain('position-area');
|
|
328
|
+
expect(style).not.toContain('position-anchor');
|
|
329
|
+
});
|
|
330
|
+
});
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* @position Core layer utility; used by useHoverCard, useTooltip, etc.
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update:
|
|
12
|
-
* - /packages/core/src/Layer/
|
|
12
|
+
* - /packages/core/src/Layer/useLayer.doc.mjs
|
|
13
|
+
* - /packages/core/src/Layer/useLayer.test.tsx
|
|
13
14
|
* - /packages/core/src/Layer/index.ts
|
|
14
15
|
*/
|
|
15
16
|
|
|
@@ -52,7 +53,9 @@ const styles = stylex.create({
|
|
|
52
53
|
});
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
|
-
* Position placement relative to anchor
|
|
56
|
+
* Position placement relative to anchor.
|
|
57
|
+
* Logical: start/end resolve against the popover's own inherited direction
|
|
58
|
+
* via CSS (RTL contexts mirror automatically, no JS involved).
|
|
56
59
|
*/
|
|
57
60
|
export type LayerPlacement = 'above' | 'below' | 'start' | 'end';
|
|
58
61
|
|
|
@@ -65,7 +68,31 @@ export type LayerAlignment = 'start' | 'center' | 'end';
|
|
|
65
68
|
* Render props for context mode (anchor positioning)
|
|
66
69
|
*/
|
|
67
70
|
export interface ContextRenderProps {
|
|
71
|
+
/**
|
|
72
|
+
* Who authors the layer's position styles.
|
|
73
|
+
*
|
|
74
|
+
* `'anchor'` (default): the hook derives CSS anchor-positioning styles —
|
|
75
|
+
* `position-area` and `position-try-fallbacks` — from the logical
|
|
76
|
+
* `placement`/`alignment`.
|
|
77
|
+
*
|
|
78
|
+
* `'custom'`: the consumer authors its own position styles via `style`
|
|
79
|
+
* (e.g. explicit `anchor()` insets or an `anchor-size()` cover). The hook
|
|
80
|
+
* keeps the popover behavior and the `position-anchor` wiring but emits no
|
|
81
|
+
* placement-derived styles, so direction handling becomes the consumer's
|
|
82
|
+
* responsibility. `placement`/`alignment` are ignored.
|
|
83
|
+
*
|
|
84
|
+
* @default 'anchor'
|
|
85
|
+
*/
|
|
86
|
+
positioning?: 'anchor' | 'custom';
|
|
87
|
+
/**
|
|
88
|
+
* Logical placement relative to the anchor. Ignored when `positioning`
|
|
89
|
+
* is `'custom'`.
|
|
90
|
+
*/
|
|
68
91
|
placement?: LayerPlacement;
|
|
92
|
+
/**
|
|
93
|
+
* Alignment along the placement axis. Ignored when `positioning`
|
|
94
|
+
* is `'custom'`.
|
|
95
|
+
*/
|
|
69
96
|
alignment?: LayerAlignment;
|
|
70
97
|
/**
|
|
71
98
|
* ARIA role applied to the popover container (e.g. `'tooltip'`). Lets
|
|
@@ -252,40 +279,45 @@ export interface FixedLayerReturn {
|
|
|
252
279
|
}
|
|
253
280
|
|
|
254
281
|
/**
|
|
255
|
-
* Map placement
|
|
282
|
+
* Map logical placement/alignment to a CSS position-area value.
|
|
283
|
+
*
|
|
284
|
+
* Uses the self-* logical keyword family: the inline axis resolves against
|
|
285
|
+
* the popover's own inherited direction (the layer renders inside the
|
|
286
|
+
* trigger's subtree, so it inherits `direction` and mirrors in RTL with no
|
|
287
|
+
* JS). The block axis is direction-neutral but must come from the same
|
|
288
|
+
* keyword family — mixing physical `top` with `self-inline-*` produces an
|
|
289
|
+
* invalid position-area (computes to `none`, which pins the popover to the
|
|
290
|
+
* viewport corner because styles.base zeroes the UA margins).
|
|
291
|
+
*
|
|
292
|
+
* Note the plain logical family (`inline-start`, no `self-`) is NOT a
|
|
293
|
+
* substitute: it resolves against the containing block — the page root for
|
|
294
|
+
* a top-layer popover — so it ignores `direction` set on a subtree, which
|
|
295
|
+
* is exactly #3389's repro.
|
|
256
296
|
*/
|
|
257
297
|
function getPositionArea(
|
|
258
298
|
placement: LayerPlacement = 'above',
|
|
259
299
|
alignment: LayerAlignment = 'center',
|
|
260
300
|
): string {
|
|
261
|
-
const placementMap: Record<LayerPlacement, string> = {
|
|
262
|
-
above: 'top',
|
|
263
|
-
below: 'bottom',
|
|
264
|
-
start: 'left',
|
|
265
|
-
end: 'right',
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const cssPlacement = placementMap[placement];
|
|
269
|
-
|
|
270
|
-
// For above/below, alignment is horizontal
|
|
271
301
|
if (placement === 'above' || placement === 'below') {
|
|
302
|
+
const block = placement === 'above' ? 'self-block-start' : 'self-block-end';
|
|
272
303
|
if (alignment === 'start') {
|
|
273
|
-
return `${
|
|
304
|
+
return `${block} span-self-inline-end`;
|
|
274
305
|
}
|
|
275
306
|
if (alignment === 'end') {
|
|
276
|
-
return `${
|
|
307
|
+
return `${block} span-self-inline-start`;
|
|
277
308
|
}
|
|
278
|
-
return
|
|
309
|
+
return block; // center
|
|
279
310
|
}
|
|
280
311
|
|
|
281
|
-
|
|
312
|
+
const inline =
|
|
313
|
+
placement === 'start' ? 'self-inline-start' : 'self-inline-end';
|
|
282
314
|
if (alignment === 'start') {
|
|
283
|
-
return `${
|
|
315
|
+
return `${inline} span-self-block-end`;
|
|
284
316
|
}
|
|
285
317
|
if (alignment === 'end') {
|
|
286
|
-
return `${
|
|
318
|
+
return `${inline} span-self-block-start`;
|
|
287
319
|
}
|
|
288
|
-
return
|
|
320
|
+
return inline; // center
|
|
289
321
|
}
|
|
290
322
|
|
|
291
323
|
/**
|
|
@@ -321,18 +353,18 @@ export function useLayer(
|
|
|
321
353
|
const isOpenRef = useRef(false);
|
|
322
354
|
|
|
323
355
|
const show = useCallback(() => {
|
|
324
|
-
const
|
|
325
|
-
if (
|
|
356
|
+
const popover = popoverRef.current;
|
|
357
|
+
if (popover && !isOpenRef.current) {
|
|
326
358
|
// Finding infra-4: the Popover API is unsupported on Safari <17 and
|
|
327
359
|
// Firefox <125. On those browsers `showPopover` does not exist, so
|
|
328
360
|
// calling it unconditionally throws a TypeError and the layer never
|
|
329
361
|
// opens. Guard behind a feature check; when the API is missing, fall
|
|
330
362
|
// back to plain visibility (the [popover] attribute is inert there, so
|
|
331
363
|
// the element sits in normal flow) so the layer still becomes visible.
|
|
332
|
-
if (typeof
|
|
333
|
-
|
|
364
|
+
if (typeof popover.showPopover === 'function') {
|
|
365
|
+
popover.showPopover();
|
|
334
366
|
} else {
|
|
335
|
-
|
|
367
|
+
popover.style.display = 'block';
|
|
336
368
|
}
|
|
337
369
|
isOpenRef.current = true;
|
|
338
370
|
setIsOpen(true);
|
|
@@ -461,6 +493,7 @@ export function useLayer(
|
|
|
461
493
|
const {
|
|
462
494
|
placement = 'above',
|
|
463
495
|
alignment = 'center',
|
|
496
|
+
positioning = 'anchor',
|
|
464
497
|
role,
|
|
465
498
|
xstyle,
|
|
466
499
|
className: extraClassName,
|
|
@@ -471,11 +504,17 @@ export function useLayer(
|
|
|
471
504
|
} = props || {};
|
|
472
505
|
|
|
473
506
|
// CSS anchor positioning (dynamic, not in StyleX)
|
|
474
|
-
const anchorStyle: React.CSSProperties =
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
507
|
+
const anchorStyle: React.CSSProperties =
|
|
508
|
+
positioning === 'custom'
|
|
509
|
+
? // Consumer authors its own position styles via `style` — keep
|
|
510
|
+
// only the anchor wiring, derive nothing from placement.
|
|
511
|
+
{positionAnchor: anchorId}
|
|
512
|
+
: {
|
|
513
|
+
positionAnchor: anchorId,
|
|
514
|
+
positionArea: getPositionArea(placement, alignment),
|
|
515
|
+
positionTryFallbacks:
|
|
516
|
+
'flip-block, flip-inline, flip-block flip-inline',
|
|
517
|
+
};
|
|
479
518
|
|
|
480
519
|
const stylexResult = stylex.props(styles.base, xstyle);
|
|
481
520
|
const combinedClassName = extraClassName
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Layout.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, Layout + layout contexts
|
|
6
|
+
* @output Characterization tests for the Layout page-shell component
|
|
7
|
+
* @position Testing; validates slot rendering, context provisioning, and
|
|
8
|
+
* divider/padding/height wiring
|
|
9
|
+
*
|
|
10
|
+
* SYNC: When Layout.tsx changes, update tests to match new behavior
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {describe, it, expect} from 'vitest';
|
|
14
|
+
import {render, screen} from '@testing-library/react';
|
|
15
|
+
import {use, createRef} from 'react';
|
|
16
|
+
import {Layout} from './Layout';
|
|
17
|
+
import {LayoutHeader} from './LayoutHeader';
|
|
18
|
+
import {LayoutFooter} from './LayoutFooter';
|
|
19
|
+
import {LayoutAreaContext} from './LayoutAreaContext';
|
|
20
|
+
import {LayoutSlotsContext} from './LayoutSlotsContext';
|
|
21
|
+
|
|
22
|
+
/** Reports which layout area it is rendered inside. */
|
|
23
|
+
function AreaProbe({testid}: {testid: string}) {
|
|
24
|
+
const area = use(LayoutAreaContext);
|
|
25
|
+
return <span data-testid={testid}>{String(area)}</span>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Reports the current LayoutSlots record as JSON. */
|
|
29
|
+
function SlotsProbe() {
|
|
30
|
+
const slots = use(LayoutSlotsContext);
|
|
31
|
+
return <span data-testid="slots">{JSON.stringify(slots)}</span>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The Layout root is the outermost element rendered by the component. */
|
|
35
|
+
function root(container: HTMLElement): HTMLElement {
|
|
36
|
+
return container.firstElementChild as HTMLElement;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('Layout', () => {
|
|
40
|
+
describe('content / children resolution', () => {
|
|
41
|
+
it('renders the content prop', () => {
|
|
42
|
+
render(<Layout content={<div>main body</div>} />);
|
|
43
|
+
expect(screen.getByText('main body')).toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('renders children as a shorthand for the content slot', () => {
|
|
47
|
+
render(
|
|
48
|
+
<Layout>
|
|
49
|
+
<div>child body</div>
|
|
50
|
+
</Layout>,
|
|
51
|
+
);
|
|
52
|
+
expect(screen.getByText('child body')).toBeInTheDocument();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('content wins when both content and children are provided', () => {
|
|
56
|
+
render(
|
|
57
|
+
<Layout content={<div>from-content</div>}>
|
|
58
|
+
<div>from-children</div>
|
|
59
|
+
</Layout>,
|
|
60
|
+
);
|
|
61
|
+
expect(screen.getByText('from-content')).toBeInTheDocument();
|
|
62
|
+
expect(screen.queryByText('from-children')).not.toBeInTheDocument();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('renders an empty shell without crashing when no slots are given', () => {
|
|
66
|
+
const {container} = render(<Layout />);
|
|
67
|
+
expect(root(container)).toBeInTheDocument();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('slots', () => {
|
|
72
|
+
it('renders all four surrounding slots plus content', () => {
|
|
73
|
+
render(
|
|
74
|
+
<Layout
|
|
75
|
+
header={<div>the-header</div>}
|
|
76
|
+
start={<div>the-start</div>}
|
|
77
|
+
end={<div>the-end</div>}
|
|
78
|
+
footer={<div>the-footer</div>}
|
|
79
|
+
content={<div>the-content</div>}
|
|
80
|
+
/>,
|
|
81
|
+
);
|
|
82
|
+
expect(screen.getByText('the-header')).toBeInTheDocument();
|
|
83
|
+
expect(screen.getByText('the-start')).toBeInTheDocument();
|
|
84
|
+
expect(screen.getByText('the-end')).toBeInTheDocument();
|
|
85
|
+
expect(screen.getByText('the-footer')).toBeInTheDocument();
|
|
86
|
+
expect(screen.getByText('the-content')).toBeInTheDocument();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not render an area wrapper for an omitted slot', () => {
|
|
90
|
+
render(<Layout content={<AreaProbe testid="content" />} />);
|
|
91
|
+
// Only the content probe exists; header/start/end/footer probes absent.
|
|
92
|
+
expect(screen.getByTestId('content')).toHaveTextContent('content');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('LayoutAreaContext provisioning', () => {
|
|
97
|
+
it('tags each slot with its area name', () => {
|
|
98
|
+
render(
|
|
99
|
+
<Layout
|
|
100
|
+
header={<AreaProbe testid="h" />}
|
|
101
|
+
start={<AreaProbe testid="s" />}
|
|
102
|
+
end={<AreaProbe testid="e" />}
|
|
103
|
+
footer={<AreaProbe testid="f" />}
|
|
104
|
+
content={<AreaProbe testid="c" />}
|
|
105
|
+
/>,
|
|
106
|
+
);
|
|
107
|
+
expect(screen.getByTestId('h')).toHaveTextContent('header');
|
|
108
|
+
expect(screen.getByTestId('s')).toHaveTextContent('start');
|
|
109
|
+
expect(screen.getByTestId('e')).toHaveTextContent('end');
|
|
110
|
+
expect(screen.getByTestId('f')).toHaveTextContent('footer');
|
|
111
|
+
expect(screen.getByTestId('c')).toHaveTextContent('content');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('LayoutSlotsContext provisioning', () => {
|
|
116
|
+
it('reports which slots are filled to descendants', () => {
|
|
117
|
+
render(
|
|
118
|
+
<Layout
|
|
119
|
+
header={<div>h</div>}
|
|
120
|
+
start={<div>s</div>}
|
|
121
|
+
content={<SlotsProbe />}
|
|
122
|
+
/>,
|
|
123
|
+
);
|
|
124
|
+
const slots = JSON.parse(screen.getByTestId('slots').textContent ?? '{}');
|
|
125
|
+
expect(slots).toEqual({
|
|
126
|
+
hasHeader: true,
|
|
127
|
+
hasFooter: false,
|
|
128
|
+
hasStart: true,
|
|
129
|
+
hasEnd: false,
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('reports all-false when only content is present', () => {
|
|
134
|
+
render(<Layout content={<SlotsProbe />} />);
|
|
135
|
+
const slots = JSON.parse(screen.getByTestId('slots').textContent ?? '{}');
|
|
136
|
+
expect(slots).toEqual({
|
|
137
|
+
hasHeader: false,
|
|
138
|
+
hasFooter: false,
|
|
139
|
+
hasStart: false,
|
|
140
|
+
hasEnd: false,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('reports every slot filled', () => {
|
|
145
|
+
render(
|
|
146
|
+
<Layout
|
|
147
|
+
header={<div>h</div>}
|
|
148
|
+
footer={<div>f</div>}
|
|
149
|
+
start={<div>s</div>}
|
|
150
|
+
end={<div>e</div>}
|
|
151
|
+
content={<SlotsProbe />}
|
|
152
|
+
/>,
|
|
153
|
+
);
|
|
154
|
+
const slots = JSON.parse(screen.getByTestId('slots').textContent ?? '{}');
|
|
155
|
+
expect(slots).toEqual({
|
|
156
|
+
hasHeader: true,
|
|
157
|
+
hasFooter: true,
|
|
158
|
+
hasStart: true,
|
|
159
|
+
hasEnd: true,
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('theme props (class + data attributes)', () => {
|
|
165
|
+
it('renders the astryx-layout class on the root', () => {
|
|
166
|
+
const {container} = render(<Layout content={<div>x</div>} />);
|
|
167
|
+
expect(root(container).className).toContain('astryx-layout');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('defaults data-height to "fill"', () => {
|
|
171
|
+
const {container} = render(<Layout content={<div>x</div>} />);
|
|
172
|
+
expect(root(container).getAttribute('data-height')).toBe('fill');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('reflects height="auto" as data-height', () => {
|
|
176
|
+
const {container} = render(
|
|
177
|
+
<Layout height="auto" content={<div>x</div>} />,
|
|
178
|
+
);
|
|
179
|
+
expect(root(container).getAttribute('data-height')).toBe('auto');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe('defaultHasDividers → LayoutDividerContext', () => {
|
|
184
|
+
it('makes headers default to having a divider', () => {
|
|
185
|
+
render(
|
|
186
|
+
<Layout
|
|
187
|
+
defaultHasDividers
|
|
188
|
+
header={<LayoutHeader>H</LayoutHeader>}
|
|
189
|
+
content={<div>c</div>}
|
|
190
|
+
/>,
|
|
191
|
+
);
|
|
192
|
+
const header = screen.getByText('H').closest('[data-divider]');
|
|
193
|
+
expect(header).not.toBeNull();
|
|
194
|
+
expect(header?.getAttribute('data-divider')).toBe('true');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('makes footers default to having a divider', () => {
|
|
198
|
+
const {container} = render(
|
|
199
|
+
<Layout
|
|
200
|
+
defaultHasDividers
|
|
201
|
+
footer={<LayoutFooter>F</LayoutFooter>}
|
|
202
|
+
content={<div>c</div>}
|
|
203
|
+
/>,
|
|
204
|
+
);
|
|
205
|
+
expect(
|
|
206
|
+
container.querySelector('.astryx-layout-footer[data-divider]'),
|
|
207
|
+
).not.toBeNull();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('does not force dividers when defaultHasDividers is unset', () => {
|
|
211
|
+
const {container} = render(
|
|
212
|
+
<Layout
|
|
213
|
+
header={<LayoutHeader>H</LayoutHeader>}
|
|
214
|
+
content={<div>c</div>}
|
|
215
|
+
/>,
|
|
216
|
+
);
|
|
217
|
+
expect(
|
|
218
|
+
container.querySelector('.astryx-layout-header[data-divider]'),
|
|
219
|
+
).toBeNull();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('an explicit hasDivider={false} on a header overrides the context default', () => {
|
|
223
|
+
const {container} = render(
|
|
224
|
+
<Layout
|
|
225
|
+
defaultHasDividers
|
|
226
|
+
header={<LayoutHeader hasDivider={false}>H</LayoutHeader>}
|
|
227
|
+
content={<div>c</div>}
|
|
228
|
+
/>,
|
|
229
|
+
);
|
|
230
|
+
expect(
|
|
231
|
+
container.querySelector('.astryx-layout-header[data-divider]'),
|
|
232
|
+
).toBeNull();
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
describe('padding / contentWidth', () => {
|
|
237
|
+
it('accepts a numeric padding step without crashing', () => {
|
|
238
|
+
const {container} = render(<Layout padding={4} content={<div>c</div>} />);
|
|
239
|
+
expect(root(container)).toBeInTheDocument();
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('accepts padding={0} (full bleed) without crashing', () => {
|
|
243
|
+
const {container} = render(<Layout padding={0} content={<div>c</div>} />);
|
|
244
|
+
expect(root(container)).toBeInTheDocument();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('accepts a numeric contentWidth without crashing', () => {
|
|
248
|
+
const {container} = render(
|
|
249
|
+
<Layout contentWidth={640} content={<div>c</div>} />,
|
|
250
|
+
);
|
|
251
|
+
expect(root(container)).toBeInTheDocument();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('accepts a string contentWidth without crashing', () => {
|
|
255
|
+
const {container} = render(
|
|
256
|
+
<Layout contentWidth="60ch" content={<div>c</div>} />,
|
|
257
|
+
);
|
|
258
|
+
expect(root(container)).toBeInTheDocument();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('styling & ref', () => {
|
|
263
|
+
it('forwards ref to the root div', () => {
|
|
264
|
+
const ref = createRef<HTMLDivElement>();
|
|
265
|
+
render(<Layout ref={ref} content={<div>c</div>} />);
|
|
266
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
267
|
+
expect(ref.current?.className).toContain('astryx-layout');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('merges a caller className onto the root', () => {
|
|
271
|
+
const {container} = render(
|
|
272
|
+
<Layout className="my-layout" content={<div>c</div>} />,
|
|
273
|
+
);
|
|
274
|
+
expect(root(container).className).toContain('my-layout');
|
|
275
|
+
expect(root(container).className).toContain('astryx-layout');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('merges a caller inline style onto the root', () => {
|
|
279
|
+
const {container} = render(
|
|
280
|
+
<Layout style={{outline: '1px solid red'}} content={<div>c</div>} />,
|
|
281
|
+
);
|
|
282
|
+
expect(root(container).style.outline).toBe('1px solid red');
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
});
|