@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
|
@@ -167,6 +167,59 @@ describe('CheckboxInput', () => {
|
|
|
167
167
|
expect(handleChange).not.toHaveBeenCalled();
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
+
it('forwards data-testid to the input', () => {
|
|
171
|
+
render(
|
|
172
|
+
<CheckboxInput
|
|
173
|
+
label="Accept terms"
|
|
174
|
+
value={false}
|
|
175
|
+
onChange={() => {}}
|
|
176
|
+
data-testid="accept-terms-checkbox"
|
|
177
|
+
/>,
|
|
178
|
+
);
|
|
179
|
+
expect(screen.getByTestId('accept-terms-checkbox')).toBe(
|
|
180
|
+
screen.getByRole('checkbox'),
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('forwards arbitrary data-* attributes to the input', () => {
|
|
185
|
+
render(
|
|
186
|
+
<CheckboxInput
|
|
187
|
+
label="Accept terms"
|
|
188
|
+
value={false}
|
|
189
|
+
onChange={() => {}}
|
|
190
|
+
data-tracking-id="checkbox-42"
|
|
191
|
+
/>,
|
|
192
|
+
);
|
|
193
|
+
expect(screen.getByRole('checkbox')).toHaveAttribute(
|
|
194
|
+
'data-tracking-id',
|
|
195
|
+
'checkbox-42',
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('does not let rest props override checked, disabled, or type', () => {
|
|
200
|
+
// Not part of CheckboxInputProps; spread (rather than named attributes)
|
|
201
|
+
// to sidestep JSX excess-property checks the same way a real caller's
|
|
202
|
+
// spread rest-props object would arrive untyped at runtime.
|
|
203
|
+
const foreignAttrs: Record<string, unknown> = {
|
|
204
|
+
checked: false,
|
|
205
|
+
disabled: false,
|
|
206
|
+
type: 'text',
|
|
207
|
+
};
|
|
208
|
+
render(
|
|
209
|
+
<CheckboxInput
|
|
210
|
+
{...foreignAttrs}
|
|
211
|
+
label="Accept terms"
|
|
212
|
+
value={true}
|
|
213
|
+
onChange={() => {}}
|
|
214
|
+
isDisabled
|
|
215
|
+
/>,
|
|
216
|
+
);
|
|
217
|
+
const checkbox = screen.getByRole('checkbox');
|
|
218
|
+
expect(checkbox).toBeChecked();
|
|
219
|
+
expect(checkbox).toBeDisabled();
|
|
220
|
+
expect(checkbox).toHaveAttribute('type', 'checkbox');
|
|
221
|
+
});
|
|
222
|
+
|
|
170
223
|
it('forwards ref correctly', () => {
|
|
171
224
|
const ref = vi.fn();
|
|
172
225
|
render(
|
|
@@ -396,7 +449,12 @@ describe('CheckboxInput', () => {
|
|
|
396
449
|
it('submits under htmlName when checked', () => {
|
|
397
450
|
const {container} = render(
|
|
398
451
|
<form>
|
|
399
|
-
<CheckboxInput
|
|
452
|
+
<CheckboxInput
|
|
453
|
+
label="Terms"
|
|
454
|
+
htmlName="terms"
|
|
455
|
+
value={true}
|
|
456
|
+
onChange={() => {}}
|
|
457
|
+
/>
|
|
400
458
|
</form>,
|
|
401
459
|
);
|
|
402
460
|
const data = new FormData(container.querySelector('form')!);
|
|
@@ -416,16 +474,25 @@ describe('CheckboxInput', () => {
|
|
|
416
474
|
/>
|
|
417
475
|
</form>,
|
|
418
476
|
);
|
|
419
|
-
expect([
|
|
477
|
+
expect([
|
|
478
|
+
...new FormData(container.querySelector('form')!).keys(),
|
|
479
|
+
]).toEqual([]);
|
|
420
480
|
});
|
|
421
481
|
|
|
422
482
|
it('submits nothing when unchecked', () => {
|
|
423
483
|
const {container} = render(
|
|
424
484
|
<form>
|
|
425
|
-
<CheckboxInput
|
|
485
|
+
<CheckboxInput
|
|
486
|
+
label="Terms"
|
|
487
|
+
htmlName="terms"
|
|
488
|
+
value={false}
|
|
489
|
+
onChange={() => {}}
|
|
490
|
+
/>
|
|
426
491
|
</form>,
|
|
427
492
|
);
|
|
428
|
-
expect([
|
|
493
|
+
expect([
|
|
494
|
+
...new FormData(container.querySelector('form')!).keys(),
|
|
495
|
+
]).toEqual([]);
|
|
429
496
|
});
|
|
430
497
|
});
|
|
431
498
|
});
|
|
@@ -395,6 +395,7 @@ export function CheckboxInput({
|
|
|
395
395
|
className,
|
|
396
396
|
style,
|
|
397
397
|
ref,
|
|
398
|
+
...rest
|
|
398
399
|
}: CheckboxInputProps) {
|
|
399
400
|
const id = useId();
|
|
400
401
|
const descriptionID = useId();
|
|
@@ -484,6 +485,7 @@ export function CheckboxInput({
|
|
|
484
485
|
)}>
|
|
485
486
|
<div {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}>
|
|
486
487
|
<input
|
|
488
|
+
{...rest}
|
|
487
489
|
ref={mergeRefs(
|
|
488
490
|
ref,
|
|
489
491
|
indeterminateRef,
|
|
@@ -135,6 +135,25 @@ describe('CheckboxList', () => {
|
|
|
135
135
|
expect(handleChange).toHaveBeenCalledWith(['b']);
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
+
it('fires a consumer onClick on an item in addition to toggling', async () => {
|
|
139
|
+
const user = userEvent.setup();
|
|
140
|
+
const handleChange = vi.fn();
|
|
141
|
+
const handleClick = vi.fn();
|
|
142
|
+
render(
|
|
143
|
+
<CheckboxList label="Preferences" value={['a']} onChange={handleChange}>
|
|
144
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
145
|
+
<CheckboxListItem label="Option B" value="b" onClick={handleClick} />
|
|
146
|
+
</CheckboxList>,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Click the interactive row (invisible-button pattern), which is where the
|
|
150
|
+
// composed onClick lives — not the inner checkbox.
|
|
151
|
+
await user.click(screen.getByRole('button', {name: 'Option B'}));
|
|
152
|
+
|
|
153
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
154
|
+
expect(handleChange).toHaveBeenCalledWith(['a', 'b']);
|
|
155
|
+
});
|
|
156
|
+
|
|
138
157
|
it('disables all checkboxes when group isDisabled is true', () => {
|
|
139
158
|
render(
|
|
140
159
|
<CheckboxList
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
* - /packages/cli/templates/blocks/components/CheckboxList/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {use, type ReactNode} from 'react';
|
|
19
|
+
import {use, type MouseEvent, type ReactNode} from 'react';
|
|
20
20
|
import * as stylex from '@stylexjs/stylex';
|
|
21
21
|
import type {StyleXStyles} from '@stylexjs/stylex';
|
|
22
22
|
import {colorVars} from '../theme/tokens.stylex';
|
|
23
23
|
import type {BaseProps} from '../BaseProps';
|
|
24
|
+
import {composeEventHandlers} from '../utils';
|
|
24
25
|
import {CheckboxInput} from '../CheckboxInput/CheckboxInput';
|
|
25
26
|
import {ListItem} from '../List/ListItem';
|
|
26
27
|
import {ListContext} from '../List/ListContext';
|
|
@@ -128,6 +129,7 @@ export function CheckboxListItem({
|
|
|
128
129
|
xstyle,
|
|
129
130
|
className,
|
|
130
131
|
style,
|
|
132
|
+
onClick: onClickProp,
|
|
131
133
|
...restProps
|
|
132
134
|
}: CheckboxListItemProps) {
|
|
133
135
|
const ctx = use(CheckboxListContext);
|
|
@@ -200,7 +202,14 @@ export function CheckboxListItem({
|
|
|
200
202
|
description={description}
|
|
201
203
|
endContent={endContent}
|
|
202
204
|
isDisabled={effectiveDisabled}
|
|
203
|
-
onClick={
|
|
205
|
+
onClick={
|
|
206
|
+
isInteractive || onClickProp
|
|
207
|
+
? composeEventHandlers<MouseEvent>(
|
|
208
|
+
onClickProp as ((event: MouseEvent) => void) | undefined,
|
|
209
|
+
isInteractive ? handleToggle : undefined,
|
|
210
|
+
)
|
|
211
|
+
: undefined
|
|
212
|
+
}
|
|
204
213
|
aria-busy={isBusy || undefined}
|
|
205
214
|
xstyle={
|
|
206
215
|
[
|
|
@@ -31,7 +31,12 @@
|
|
|
31
31
|
import {type ReactNode, type MouseEvent, useRef, type Ref} from 'react';
|
|
32
32
|
import * as stylex from '@stylexjs/stylex';
|
|
33
33
|
import type {StyleXStyles} from '@stylexjs/stylex';
|
|
34
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
borderVars,
|
|
36
|
+
colorVars,
|
|
37
|
+
durationVars,
|
|
38
|
+
easeVars,
|
|
39
|
+
} from '../theme/tokens.stylex';
|
|
35
40
|
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
36
41
|
import {mergeProps, mergeRefs} from '../utils';
|
|
37
42
|
import {Card} from '../Card/Card';
|
|
@@ -66,7 +71,6 @@ const styles = stylex.create({
|
|
|
66
71
|
content: '""',
|
|
67
72
|
position: 'absolute',
|
|
68
73
|
inset: 0,
|
|
69
|
-
borderRadius: 'inherit',
|
|
70
74
|
pointerEvents: 'none',
|
|
71
75
|
transitionProperty: 'background-color',
|
|
72
76
|
transitionDuration: durationVars['--duration-fast'],
|
|
@@ -84,6 +88,38 @@ const styles = stylex.create({
|
|
|
84
88
|
},
|
|
85
89
|
},
|
|
86
90
|
},
|
|
91
|
+
// Borderless variants (everything except `default`): drop the transparent
|
|
92
|
+
// 1px border Card applies. The overlay is inset to the padding box — inside
|
|
93
|
+
// that border — so a transparent border strip stays untinted on hover and
|
|
94
|
+
// reads as a faint ring. With no border, the overlay covers the full box
|
|
95
|
+
// edge-to-edge and the ring disappears.
|
|
96
|
+
borderless: {
|
|
97
|
+
borderWidth: 0,
|
|
98
|
+
},
|
|
99
|
+
// Bordered variant (`default`): draw the 1px border *within* the padding by
|
|
100
|
+
// subtracting the border width from every side. Total inset (border +
|
|
101
|
+
// padding) then equals the borderless variants' padding, so content geometry
|
|
102
|
+
// and outer dimensions stay identical across all variants. The border rests
|
|
103
|
+
// at the subtle token and emphasizes on hover.
|
|
104
|
+
bordered: {
|
|
105
|
+
borderColor: colorVars['--color-border'],
|
|
106
|
+
paddingInlineStart: `calc(var(--container-padding-inline-start) - ${borderVars['--border-width']})`,
|
|
107
|
+
paddingInlineEnd: `calc(var(--container-padding-inline-end) - ${borderVars['--border-width']})`,
|
|
108
|
+
paddingBlockStart: `calc(var(--container-padding-block-start) - ${borderVars['--border-width']})`,
|
|
109
|
+
paddingBlockEnd: `calc(var(--container-padding-block-end) - ${borderVars['--border-width']})`,
|
|
110
|
+
transitionProperty: 'border-color',
|
|
111
|
+
transitionDuration: durationVars['--duration-fast'],
|
|
112
|
+
transitionTimingFunction: easeVars['--ease-standard'],
|
|
113
|
+
},
|
|
114
|
+
// Emphasize the bordered variant's border on hover. Guarded by
|
|
115
|
+
// @media (hover: hover) so touch devices don't get a stuck hover state.
|
|
116
|
+
borderedHoverOnPointer: {
|
|
117
|
+
'@media (hover: hover)': {
|
|
118
|
+
':hover': {
|
|
119
|
+
borderColor: colorVars['--color-border-emphasized'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
87
123
|
disabled: {
|
|
88
124
|
cursor: 'not-allowed',
|
|
89
125
|
opacity: 0.5,
|
|
@@ -248,6 +284,11 @@ export function ClickableCard({
|
|
|
248
284
|
|
|
249
285
|
const isLink = href != null;
|
|
250
286
|
|
|
287
|
+
// Only the `default` variant has a visible border. Card draws a transparent
|
|
288
|
+
// 1px border on every other variant purely to avoid layout jitter; we drop
|
|
289
|
+
// it here so the hover overlay covers the full box with no untinted ring.
|
|
290
|
+
const hasBorder = variant === 'default';
|
|
291
|
+
|
|
251
292
|
return (
|
|
252
293
|
<Card
|
|
253
294
|
ref={mergeRefs(ref, containerRef)}
|
|
@@ -264,8 +305,10 @@ export function ClickableCard({
|
|
|
264
305
|
[
|
|
265
306
|
styles.interactive,
|
|
266
307
|
styles.focusWithin,
|
|
308
|
+
hasBorder ? styles.bordered : styles.borderless,
|
|
267
309
|
!isDisabled && styles.overlay,
|
|
268
310
|
!isDisabled && styles.hoverOnPointer,
|
|
311
|
+
!isDisabled && hasBorder && styles.borderedHoverOnPointer,
|
|
269
312
|
isDisabled && styles.disabled,
|
|
270
313
|
xstyleProp,
|
|
271
314
|
] as unknown as StyleXStyles
|
|
@@ -90,6 +90,11 @@ export const docs = {
|
|
|
90
90
|
type: '(code: string, language: string) => Array<{type: string; start: number; end: number}>',
|
|
91
91
|
description: 'Custom tokenizer override for unsupported languages.',
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
name: 'syntaxTheme',
|
|
95
|
+
type: 'SyntaxThemeDefinition',
|
|
96
|
+
description: 'Per-instance syntax theme override. Shorthand for wrapping the block in <SyntaxTheme theme={...}>. Accepts a preset from @astryxdesign/core/theme/syntax or a theme created with defineSyntaxTheme(). Defaults to the nearest SyntaxTheme ancestor or the theme-level syntax colors.',
|
|
97
|
+
},
|
|
93
98
|
{
|
|
94
99
|
name: 'isCollapsible',
|
|
95
100
|
type: 'boolean',
|
|
@@ -135,8 +140,8 @@ export const docs = {
|
|
|
135
140
|
},
|
|
136
141
|
theming: {
|
|
137
142
|
targets: [
|
|
138
|
-
{className: 'astryx-code'},
|
|
139
|
-
{className: 'astryx-codeblock', visualProps: ['size', 'language']},
|
|
143
|
+
{className: 'astryx-code', visualProps: ['color']},
|
|
144
|
+
{className: 'astryx-codeblock', visualProps: ['size', 'language', 'container']},
|
|
140
145
|
],
|
|
141
146
|
},
|
|
142
147
|
usage: {
|
|
@@ -3,15 +3,21 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file CodeBlock.test.tsx
|
|
5
5
|
* @input Uses vitest, @testing-library/react, CodeBlock component
|
|
6
|
-
* @output Unit tests for CodeBlock (copy button, collapse, scroll region a11y)
|
|
6
|
+
* @output Unit tests for CodeBlock (copy button, collapse, scroll region a11y, syntaxTheme)
|
|
7
7
|
* @position Testing; validates CodeBlock implementation
|
|
8
8
|
*
|
|
9
9
|
* SYNC: When CodeBlock.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
-
import {render, screen, fireEvent} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
|
+
import {act, render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import {CodeBlock} from './CodeBlock';
|
|
15
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
16
|
+
import {dracula} from '../theme/syntax';
|
|
17
|
+
|
|
18
|
+
function politeRegion(): HTMLElement | null {
|
|
19
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
20
|
+
}
|
|
15
21
|
|
|
16
22
|
// A code sample long enough to exceed the default collapsible threshold (10).
|
|
17
23
|
const LONG_CODE = Array.from(
|
|
@@ -27,6 +33,10 @@ describe('CodeBlock', () => {
|
|
|
27
33
|
});
|
|
28
34
|
});
|
|
29
35
|
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
__resetLiveRegionsForTest();
|
|
38
|
+
});
|
|
39
|
+
|
|
30
40
|
it('renders the code', () => {
|
|
31
41
|
render(<CodeBlock code="const x = 1;" language="javascript" />);
|
|
32
42
|
expect(screen.getByText(/const/)).toBeInTheDocument();
|
|
@@ -53,6 +63,50 @@ describe('CodeBlock', () => {
|
|
|
53
63
|
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('const x = 1;');
|
|
54
64
|
});
|
|
55
65
|
|
|
66
|
+
it('announces "Copied" to a polite live region after copying', async () => {
|
|
67
|
+
render(<CodeBlock code="const x = 1;" language="javascript" />);
|
|
68
|
+
const copyButton = screen.getByRole('button', {name: 'Copy code'});
|
|
69
|
+
fireEvent.click(copyButton);
|
|
70
|
+
await waitFor(() => {
|
|
71
|
+
expect(politeRegion()).toHaveTextContent('Copied');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('keeps the copied indicator a full 2s after a rapid re-copy', async () => {
|
|
76
|
+
vi.useFakeTimers();
|
|
77
|
+
try {
|
|
78
|
+
render(<CodeBlock code="const x = 1;" language="javascript" />);
|
|
79
|
+
fireEvent.click(screen.getByRole('button', {name: 'Copy code'}));
|
|
80
|
+
// Flush the async clipboard write.
|
|
81
|
+
await act(async () => {});
|
|
82
|
+
expect(screen.getByRole('button', {name: 'Copied'})).toBeInTheDocument();
|
|
83
|
+
|
|
84
|
+
// 1.5s later the user copies again.
|
|
85
|
+
act(() => {
|
|
86
|
+
vi.advanceTimersByTime(1500);
|
|
87
|
+
});
|
|
88
|
+
fireEvent.click(screen.getByRole('button', {name: 'Copied'}));
|
|
89
|
+
await act(async () => {});
|
|
90
|
+
|
|
91
|
+
// 600ms after the second copy (2.1s after the first): the first
|
|
92
|
+
// click's timer must not have reverted the indicator early.
|
|
93
|
+
act(() => {
|
|
94
|
+
vi.advanceTimersByTime(600);
|
|
95
|
+
});
|
|
96
|
+
expect(screen.getByRole('button', {name: 'Copied'})).toBeInTheDocument();
|
|
97
|
+
|
|
98
|
+
// It resets 2s after the most recent copy.
|
|
99
|
+
act(() => {
|
|
100
|
+
vi.advanceTimersByTime(1400);
|
|
101
|
+
});
|
|
102
|
+
expect(
|
|
103
|
+
screen.getByRole('button', {name: 'Copy code'}),
|
|
104
|
+
).toBeInTheDocument();
|
|
105
|
+
} finally {
|
|
106
|
+
vi.useRealTimers();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
56
110
|
it('does NOT collapse the block when the copy button is clicked', () => {
|
|
57
111
|
render(
|
|
58
112
|
<CodeBlock
|
|
@@ -112,4 +166,69 @@ describe('CodeBlock', () => {
|
|
|
112
166
|
fireEvent.click(header);
|
|
113
167
|
expect(header).toHaveAttribute('aria-expanded', 'false');
|
|
114
168
|
});
|
|
169
|
+
|
|
170
|
+
it('links the collapsible header to its code region via aria-controls', () => {
|
|
171
|
+
render(
|
|
172
|
+
<CodeBlock
|
|
173
|
+
code={LONG_CODE}
|
|
174
|
+
language="javascript"
|
|
175
|
+
title="example"
|
|
176
|
+
isCollapsible
|
|
177
|
+
/>,
|
|
178
|
+
);
|
|
179
|
+
const header = screen
|
|
180
|
+
.getAllByRole('button')
|
|
181
|
+
.find(el => el.hasAttribute('aria-expanded'))!;
|
|
182
|
+
const controlsId = header.getAttribute('aria-controls');
|
|
183
|
+
// aria-controls must be present and point at the real code region.
|
|
184
|
+
expect(controlsId).toBeTruthy();
|
|
185
|
+
const region = document.getElementById(controlsId as string);
|
|
186
|
+
expect(region).not.toBeNull();
|
|
187
|
+
// The region contains the scrollable code body (role="group").
|
|
188
|
+
expect(region).toContainElement(screen.getByRole('group'));
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('keeps aria-controls resolvable when collapsed (region stays mounted)', () => {
|
|
192
|
+
render(
|
|
193
|
+
<CodeBlock
|
|
194
|
+
code={LONG_CODE}
|
|
195
|
+
language="javascript"
|
|
196
|
+
title="example"
|
|
197
|
+
isCollapsible
|
|
198
|
+
/>,
|
|
199
|
+
);
|
|
200
|
+
const header = screen
|
|
201
|
+
.getAllByRole('button')
|
|
202
|
+
.find(el => el.hasAttribute('aria-expanded'))!;
|
|
203
|
+
fireEvent.click(header);
|
|
204
|
+
expect(header).toHaveAttribute('aria-expanded', 'false');
|
|
205
|
+
// The code region uses a CSS grid animation to collapse, so it stays in
|
|
206
|
+
// the DOM — aria-controls stays a valid, resolvable reference (unlike a
|
|
207
|
+
// conditionally-mounted region, which would need a conditional attribute).
|
|
208
|
+
const controlsId = header.getAttribute('aria-controls');
|
|
209
|
+
expect(controlsId).toBeTruthy();
|
|
210
|
+
expect(document.getElementById(controlsId as string)).not.toBeNull();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('applies a per-instance syntax theme via the syntaxTheme prop', () => {
|
|
214
|
+
const {container} = render(
|
|
215
|
+
<CodeBlock
|
|
216
|
+
code="const x = 1;"
|
|
217
|
+
language="javascript"
|
|
218
|
+
syntaxTheme={dracula}
|
|
219
|
+
/>,
|
|
220
|
+
);
|
|
221
|
+
const wrapper = container.querySelector('[data-astryx-syntax-theme]');
|
|
222
|
+
expect(wrapper).not.toBeNull();
|
|
223
|
+
expect(wrapper).toHaveAttribute('data-astryx-syntax-theme', 'dracula');
|
|
224
|
+
expect(wrapper!.querySelector('pre')).not.toBeNull();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('renders no syntax theme wrapper when syntaxTheme is not set', () => {
|
|
228
|
+
const {container} = render(
|
|
229
|
+
<CodeBlock code="const x = 1;" language="javascript" />,
|
|
230
|
+
);
|
|
231
|
+
expect(container.querySelector('[data-astryx-syntax-theme]')).toBeNull();
|
|
232
|
+
expect(container.firstElementChild?.tagName).toBe('PRE');
|
|
233
|
+
});
|
|
115
234
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
'use client';
|
|
4
4
|
/**
|
|
5
5
|
* @file CodeBlock.tsx
|
|
6
|
-
* @input Uses React, StyleX, theme tokens, CSS Custom Highlight API
|
|
6
|
+
* @input Uses React, StyleX, theme tokens, CSS Custom Highlight API, SyntaxTheme provider
|
|
7
7
|
* @output Exports CodeBlock component and CodeBlockProps
|
|
8
8
|
* @position Core implementation; read-only syntax-highlighted code display
|
|
9
9
|
*/
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import {
|
|
12
12
|
useInsertionEffect,
|
|
13
13
|
useEffect,
|
|
14
|
+
useId,
|
|
14
15
|
useRef,
|
|
15
16
|
useState,
|
|
16
17
|
useCallback,
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
easeVars,
|
|
33
34
|
} from '../theme/tokens.stylex';
|
|
34
35
|
import {mergeProps} from '../utils';
|
|
36
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
35
37
|
import {Icon} from '../Icon';
|
|
36
38
|
import {
|
|
37
39
|
tokenize,
|
|
@@ -43,6 +45,7 @@ import type {SyntaxToken, TokenLine} from './tokenizer';
|
|
|
43
45
|
import {ensureHighlightStyles} from './highlightStyles';
|
|
44
46
|
import {applyHighlightRangesChunked} from './highlightRanges';
|
|
45
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
|
+
import {SyntaxTheme, type SyntaxThemeDefinition} from '../theme/syntax';
|
|
46
49
|
|
|
47
50
|
// ---------------------------------------------------------------------------
|
|
48
51
|
// Styles
|
|
@@ -173,6 +176,17 @@ const styles = stylex.create({
|
|
|
173
176
|
headerCollapsible: {
|
|
174
177
|
cursor: 'pointer',
|
|
175
178
|
userSelect: 'none',
|
|
179
|
+
// Restore a keyboard-only focus ring with the standard token/offset so this
|
|
180
|
+
// disclosure control matches the rest of the system (Collapsible, TabMenu);
|
|
181
|
+
// otherwise it falls back to the inconsistent UA default outline.
|
|
182
|
+
outline: {
|
|
183
|
+
default: null,
|
|
184
|
+
':focus-visible': `2px solid ${colorVars['--color-accent']}`,
|
|
185
|
+
},
|
|
186
|
+
outlineOffset: {
|
|
187
|
+
default: '0',
|
|
188
|
+
':focus-visible': '2px',
|
|
189
|
+
},
|
|
176
190
|
},
|
|
177
191
|
gutter: {
|
|
178
192
|
flexShrink: 0,
|
|
@@ -382,6 +396,14 @@ export interface CodeBlockProps extends BaseProps<HTMLPreElement> {
|
|
|
382
396
|
language: string,
|
|
383
397
|
) => {type: string; start: number; end: number}[];
|
|
384
398
|
highlightMode?: 'auto' | 'ranges' | 'spans';
|
|
399
|
+
/**
|
|
400
|
+
* Per-instance syntax theme override. Shorthand for wrapping this block in
|
|
401
|
+
* `<SyntaxTheme theme={...}>` — accepts a preset from
|
|
402
|
+
* `@astryxdesign/core/theme/syntax` or a theme created with
|
|
403
|
+
* `defineSyntaxTheme()`. Without it, the block uses the theme-level syntax
|
|
404
|
+
* colors from the nearest SyntaxTheme ancestor or `defineTheme({ syntax })`.
|
|
405
|
+
*/
|
|
406
|
+
syntaxTheme?: SyntaxThemeDefinition;
|
|
385
407
|
}
|
|
386
408
|
|
|
387
409
|
// ---------------------------------------------------------------------------
|
|
@@ -633,6 +655,7 @@ export function CodeBlock({
|
|
|
633
655
|
container = 'card',
|
|
634
656
|
tokenizer: customTokenizer,
|
|
635
657
|
highlightMode = 'auto',
|
|
658
|
+
syntaxTheme,
|
|
636
659
|
xstyle,
|
|
637
660
|
className,
|
|
638
661
|
style,
|
|
@@ -640,6 +663,17 @@ export function CodeBlock({
|
|
|
640
663
|
...props
|
|
641
664
|
}: CodeBlockProps) {
|
|
642
665
|
const [copied, setCopied] = useState(false);
|
|
666
|
+
const copyResetTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
667
|
+
const announce = useAnnounce();
|
|
668
|
+
|
|
669
|
+
// Clear a pending "copied" reset when the block unmounts.
|
|
670
|
+
useEffect(() => {
|
|
671
|
+
return () => {
|
|
672
|
+
if (copyResetTimerRef.current != null) {
|
|
673
|
+
clearTimeout(copyResetTimerRef.current);
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
}, []);
|
|
643
677
|
|
|
644
678
|
const useSpans =
|
|
645
679
|
highlightMode === 'spans' ||
|
|
@@ -665,12 +699,23 @@ export function CodeBlock({
|
|
|
665
699
|
try {
|
|
666
700
|
await navigator.clipboard.writeText(code);
|
|
667
701
|
setCopied(true);
|
|
702
|
+
// Swapping the button's aria-label alone isn't reliably announced by
|
|
703
|
+
// screen readers, so confirm the copy via a polite live region.
|
|
704
|
+
announce('Copied');
|
|
668
705
|
onCopy?.();
|
|
669
|
-
|
|
706
|
+
// Restart the reset timer on every copy — otherwise a rapid re-copy
|
|
707
|
+
// is reverted early by the previous click's timer.
|
|
708
|
+
if (copyResetTimerRef.current != null) {
|
|
709
|
+
clearTimeout(copyResetTimerRef.current);
|
|
710
|
+
}
|
|
711
|
+
copyResetTimerRef.current = setTimeout(() => {
|
|
712
|
+
copyResetTimerRef.current = null;
|
|
713
|
+
setCopied(false);
|
|
714
|
+
}, 2000);
|
|
670
715
|
} catch {
|
|
671
716
|
// Clipboard failures leave the copied state unchanged.
|
|
672
717
|
}
|
|
673
|
-
}, [code, onCopy]);
|
|
718
|
+
}, [code, onCopy, announce]);
|
|
674
719
|
|
|
675
720
|
const sizeStyle = size === 'sm' ? styles.sizeSm : styles.sizeMd;
|
|
676
721
|
const gutterSizeStyle = size === 'sm' ? styles.gutterSm : styles.gutterMd;
|
|
@@ -680,6 +725,11 @@ export function CodeBlock({
|
|
|
680
725
|
|
|
681
726
|
const canCollapse = isCollapsible && lines.length >= collapsibleThreshold;
|
|
682
727
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
728
|
+
// Links the collapsible header to the code region it shows/hides so assistive
|
|
729
|
+
// tech can move from the button to its controlled content (disclosure
|
|
730
|
+
// pattern). The region stays mounted when collapsed (CSS grid animation), so
|
|
731
|
+
// this is always a resolvable reference — aria-controls can be unconditional.
|
|
732
|
+
const regionId = useId();
|
|
683
733
|
|
|
684
734
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
685
735
|
const scrollStyle: CSSProperties | undefined = maxHeight
|
|
@@ -717,6 +767,7 @@ export function CodeBlock({
|
|
|
717
767
|
role={canCollapse ? 'button' : undefined}
|
|
718
768
|
tabIndex={canCollapse ? 0 : undefined}
|
|
719
769
|
aria-expanded={canCollapse ? !isCollapsed : undefined}
|
|
770
|
+
aria-controls={canCollapse ? regionId : undefined}
|
|
720
771
|
onClick={canCollapse ? () => setIsCollapsed(prev => !prev) : undefined}
|
|
721
772
|
onKeyDown={
|
|
722
773
|
canCollapse
|
|
@@ -802,7 +853,7 @@ export function CodeBlock({
|
|
|
802
853
|
</div>
|
|
803
854
|
);
|
|
804
855
|
|
|
805
|
-
|
|
856
|
+
const block = (
|
|
806
857
|
<pre
|
|
807
858
|
ref={ref}
|
|
808
859
|
{...mergeProps(
|
|
@@ -820,6 +871,7 @@ export function CodeBlock({
|
|
|
820
871
|
{headerEl}
|
|
821
872
|
{canCollapse ? (
|
|
822
873
|
<div
|
|
874
|
+
id={regionId}
|
|
823
875
|
{...stylex.props(
|
|
824
876
|
styles.collapseGrid,
|
|
825
877
|
isCollapsed && styles.collapseGridCollapsed,
|
|
@@ -832,6 +884,12 @@ export function CodeBlock({
|
|
|
832
884
|
{!showHeader && copyButtonEl}
|
|
833
885
|
</pre>
|
|
834
886
|
);
|
|
887
|
+
|
|
888
|
+
return syntaxTheme ? (
|
|
889
|
+
<SyntaxTheme theme={syntaxTheme}>{block}</SyntaxTheme>
|
|
890
|
+
) : (
|
|
891
|
+
block
|
|
892
|
+
);
|
|
835
893
|
}
|
|
836
894
|
|
|
837
895
|
CodeBlock.displayName = 'CodeBlock';
|
|
@@ -16,7 +16,8 @@ export const docs = {
|
|
|
16
16
|
},
|
|
17
17
|
theming: {
|
|
18
18
|
targets: [
|
|
19
|
-
{className: 'astryx-collapsible'},
|
|
19
|
+
{className: 'astryx-collapsible', visualProps: ['density']},
|
|
20
|
+
{className: 'astryx-collapsible-group', visualProps: ['density']},
|
|
20
21
|
],
|
|
21
22
|
},
|
|
22
23
|
description: 'A primitive that makes any content collapsible: a trigger button toggles visibility of the content area, managing its own state or deferring to a parent CollapsibleGroup.',
|
|
@@ -69,7 +70,8 @@ export const docs = {
|
|
|
69
70
|
usage: {
|
|
70
71
|
description: 'Collapsible hides and reveals content behind a trigger button. Use it in settings panels, FAQ pages, or detail views to keep the page scannable while letting users drill into sections they care about. Wrap multiple collapsibles in CollapsibleGroup for accordion behavior. For custom collapsible components, use the `useCollapsible` hook directly (`astryx hook useCollapsible`).',
|
|
71
72
|
bestPractices: [
|
|
72
|
-
{ guidance: true, description: '
|
|
73
|
+
{ guidance: true, description: 'Use hasDividers on CollapsibleGroup for FAQ-style lists — built-in row hairlines with themed border tokens, no hand-rolled borders.' },
|
|
74
|
+
{ guidance: true, description: 'Wrap each Collapsible in an Card for visual separation in accordion layouts, or use CollapsibleGroup\'s hasDividers for flat lists; don\'t combine both.' },
|
|
73
75
|
{ guidance: true, description: 'Use CollapsibleGroup with type="single" for settings or FAQ pages where only one section should be open at a time.' },
|
|
74
76
|
{ guidance: true, description: 'Use type="multiple" when users need to compare content across sections, like feature lists or pricing tiers.' },
|
|
75
77
|
{ guidance: true, description: 'Start sections open (defaultIsOpen) when the content is likely needed on first view; don\'t make users click to see essential info.' },
|
|
@@ -90,7 +92,8 @@ export const docsZh = {
|
|
|
90
92
|
usage: {
|
|
91
93
|
description: 'Collapsible hides and reveals content behind a trigger button. Use it in settings panels, FAQ pages, or detail views to keep the page scannable while letting users drill into sections they care about. Wrap multiple collapsibles in CollapsibleGroup for accordion behavior.',
|
|
92
94
|
bestPractices: [
|
|
93
|
-
{ guidance: true, description: '
|
|
95
|
+
{ guidance: true, description: 'Use hasDividers on CollapsibleGroup for FAQ-style lists — built-in row hairlines with themed border tokens, no hand-rolled borders.' },
|
|
96
|
+
{ guidance: true, description: 'Wrap each Collapsible in an Card for visual separation in accordion layouts, or use CollapsibleGroup\'s hasDividers for flat lists; don\'t combine both.' },
|
|
94
97
|
{ guidance: true, description: 'Use CollapsibleGroup with type="single" for settings or FAQ pages where only one section should be open at a time.' },
|
|
95
98
|
{ guidance: true, description: 'Use type="multiple" when users need to compare content across sections, like feature lists or pricing tiers.' },
|
|
96
99
|
{ guidance: true, description: 'Start sections open (defaultIsOpen) when the content is likely needed on first view; don\'t make users click to see essential info.' },
|
|
@@ -107,7 +110,8 @@ export const docsDense = {
|
|
|
107
110
|
usage: {
|
|
108
111
|
description: 'Collapsible hides and reveals content behind a trigger button. Use in settings, FAQs, or detail views. Wrap in CollapsibleGroup for accordion behavior.',
|
|
109
112
|
bestPractices: [
|
|
110
|
-
{ guidance: true, description: '
|
|
113
|
+
{ guidance: true, description: 'Use hasDividers on CollapsibleGroup for FAQ-style lists — built-in row hairlines, no hand-rolled borders.' },
|
|
114
|
+
{ guidance: true, description: 'Wrap each Collapsible in an Card for visual separation, or use CollapsibleGroup\'s hasDividers for flat lists; not both.' },
|
|
111
115
|
{ guidance: true, description: 'Use CollapsibleGroup with type="single" for settings or FAQ pages where only one section should be open at a time.' },
|
|
112
116
|
{ guidance: true, description: 'Use type="multiple" when users need to compare across sections.' },
|
|
113
117
|
{ guidance: true, description: 'Start sections open (defaultIsOpen) when content is needed on first view.' },
|