@astryxdesign/core 0.1.4-canary.ff77e1c → 0.1.4
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/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +18 -20
- package/dist/AlertDialog/useImperativeAlertDialog.js +3 -3
- package/dist/AppShell/AppShell.d.ts +1 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +53 -55
- package/dist/AspectRatio/AspectRatio.d.ts +10 -48
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +12 -33
- 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 +25 -27
- package/dist/Avatar/AvatarStatusDot.js +5 -5
- package/dist/AvatarGroup/AvatarGroup.js +5 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.js +5 -5
- package/dist/Badge/Badge.js +3 -3
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +25 -32
- 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 +48 -68
- 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 +2 -4
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +10 -18
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +21 -24
- package/dist/Carousel/carousel.markers.stylex.d.ts +7 -0
- package/dist/Carousel/carousel.markers.stylex.d.ts.map +1 -0
- package/dist/Carousel/carousel.markers.stylex.js +12 -0
- 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 +15 -27
- package/dist/Chat/ChatDictationButton.d.ts +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +11 -13
- 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 +10 -12
- 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 +12 -14
- 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 +15 -24
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +74 -81
- 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 +23 -25
- 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 +6 -8
- package/dist/Citation/Citation.js +10 -10
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +9 -32
- package/dist/Code/Code.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts +1 -10
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +52 -88
- package/dist/Collapsible/Collapsible.d.ts +3 -9
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +22 -110
- package/dist/Collapsible/CollapsibleGroup.d.ts +7 -39
- package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +12 -73
- package/dist/Collapsible/CollapsibleGroupContext.d.ts +0 -31
- package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +3 -33
- package/dist/Collapsible/index.d.ts +0 -1
- package/dist/Collapsible/index.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.d.ts +1 -4
- package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.js +6 -20
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +34 -36
- 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 +2 -7
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +43 -76
- package/dist/DateInput/DateInput.js +18 -18
- package/dist/DateRangeInput/DateRangeInput.js +21 -21
- package/dist/DateTimeInput/DateTimeInput.d.ts +2 -5
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +26 -30
- 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 +17 -2
- 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 +3 -4
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +12 -29
- 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 +1 -5
- 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 +12 -16
- 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 +2 -29
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +31 -44
- 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 +31 -55
- package/dist/Lightbox/useLightbox.js +3 -3
- package/dist/Link/Link.js +15 -15
- 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 +23 -26
- 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 +32 -48
- 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.js +3 -3
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +72 -125
- 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 +92 -110
- 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 +18 -25
- 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 +21 -24
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +10 -28
- 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 +10 -32
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +12 -18
- 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 +34 -38
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +6 -8
- 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 +16 -18
- 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 +4 -8
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +29 -34
- 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 +30 -57
- package/dist/TabList/tab.markers.stylex.d.ts +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +39 -50
- 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 +5 -9
- 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 +5 -9
- package/dist/Table/TableHeader.d.ts +1 -1
- package/dist/Table/TableHeader.d.ts.map +1 -1
- package/dist/Table/TableHeader.js +5 -9
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/TableRow.js +5 -5
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +11 -14
- package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +1 -5
- package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +22 -22
- 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 +1 -11
- 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 +4 -8
- 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 +2 -3
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +29 -30
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +21 -26
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +26 -37
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +17 -25
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +11 -23
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +4 -44
- 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 +34 -36
- package/dist/Toolbar/Toolbar.js +18 -18
- package/dist/Tooltip/Tooltip.js +11 -11
- package/dist/Tooltip/useTooltip.d.ts +1 -5
- 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 +14 -25
- 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 +20 -23
- package/dist/Typeahead/Typeahead.js +12 -12
- package/dist/Typeahead/TypeaheadItem.js +10 -10
- package/dist/VStack/VStack.js +3 -3
- package/dist/astryx.css +0 -7
- package/dist/astryx.umd.js +59 -59
- package/dist/astryx.umd.js.map +4 -4
- package/dist/docs-types.d.ts +2 -8
- 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 +0 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/hooks/useFocusTrap.d.ts +0 -3
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +1 -38
- package/dist/hooks/useInteractiveRole.d.ts +2 -6
- package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
- package/dist/hooks/useInteractiveRole.js +2 -6
- package/dist/hooks/useKeyboardHint.js +9 -9
- package/dist/hooks/useStreamingText.d.ts +1 -3
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +5 -14
- 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 +3 -10
- package/dist/theme/hct.d.ts +15 -0
- 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 +2 -10
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +4 -220
- package/dist/theme/useTheme.d.ts +2 -3
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +6 -73
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -3
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -8
- package/package.json +3 -3
- package/src/AlertDialog/AlertDialog.doc.mjs +0 -4
- package/src/AlertDialog/AlertDialog.tsx +0 -2
- package/src/AppShell/AppShell.tsx +0 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +1 -28
- package/src/AspectRatio/AspectRatio.test.tsx +1 -142
- package/src/AspectRatio/AspectRatio.tsx +10 -70
- package/src/AspectRatio/index.ts +1 -5
- package/src/Avatar/Avatar.doc.mjs +0 -11
- package/src/Avatar/Avatar.test.tsx +1 -32
- package/src/Avatar/Avatar.tsx +20 -12
- package/src/AvatarGroup/AvatarGroup.doc.mjs +0 -1
- package/src/Banner/Banner.doc.mjs +0 -8
- package/src/Banner/Banner.test.tsx +0 -38
- package/src/Banner/Banner.tsx +1 -8
- package/src/Calendar/Calendar.doc.mjs +1 -1
- package/src/Calendar/Calendar.test.tsx +17 -122
- package/src/Calendar/Calendar.tsx +5 -26
- package/src/Calendar/dayCellUtils.ts +1 -3
- package/src/Calendar/styles.ts +2 -12
- package/src/Card/Card.doc.mjs +1 -1
- package/src/Card/Card.tsx +6 -16
- package/src/Carousel/Carousel.doc.mjs +12 -12
- package/src/Carousel/Carousel.test.tsx +0 -13
- package/src/Carousel/Carousel.tsx +2 -4
- package/src/Carousel/carousel.markers.stylex.ts +10 -0
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.test.tsx +1 -27
- package/src/Chat/ChatComposerInput.tsx +15 -20
- package/src/Chat/ChatDictationButton.tsx +4 -4
- package/src/Chat/ChatLayoutScrollButton.tsx +1 -3
- package/src/Chat/ChatMessageMetadata.tsx +6 -4
- package/src/Chat/ChatSystemMessage.test.tsx +11 -26
- package/src/Chat/ChatSystemMessage.tsx +7 -7
- package/src/Chat/ChatTokenizedText.test.tsx +16 -29
- package/src/Chat/ChatTokenizedText.tsx +8 -15
- package/src/Chat/ChatToolCalls.test.tsx +0 -55
- package/src/Chat/ChatToolCalls.tsx +12 -10
- package/src/Chat/index.ts +4 -1
- package/src/Chat/useTriggerMenu.tsx +4 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -3
- package/src/CheckboxInput/CheckboxInput.test.tsx +4 -71
- package/src/CheckboxInput/CheckboxInput.tsx +0 -2
- package/src/CheckboxList/CheckboxList.test.tsx +0 -19
- package/src/CheckboxList/CheckboxListItem.tsx +2 -11
- package/src/Citation/Citation.doc.mjs +0 -5
- package/src/ClickableCard/ClickableCard.tsx +2 -45
- package/src/CodeBlock/CodeBlock.doc.mjs +2 -7
- package/src/CodeBlock/CodeBlock.test.tsx +3 -122
- package/src/CodeBlock/CodeBlock.tsx +4 -62
- package/src/Collapsible/Collapsible.doc.mjs +4 -8
- package/src/Collapsible/Collapsible.tsx +10 -86
- package/src/Collapsible/CollapsibleGroup.doc.mjs +3 -27
- package/src/Collapsible/CollapsibleGroup.test.tsx +0 -318
- package/src/Collapsible/CollapsibleGroup.tsx +9 -107
- package/src/Collapsible/CollapsibleGroupContext.tsx +2 -42
- package/src/Collapsible/index.ts +0 -4
- package/src/Collapsible/useCollapsible.ts +6 -20
- package/src/CommandPalette/CommandPalette.doc.mjs +0 -5
- package/src/CommandPalette/CommandPalette.tsx +3 -5
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +0 -5
- package/src/CommandPalette/CommandPaletteGroup.doc.mjs +0 -10
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +0 -6
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +0 -6
- package/src/CommandPalette/CommandPaletteList.doc.mjs +0 -9
- package/src/ContextMenu/ContextMenu.doc.mjs +0 -15
- package/src/ContextMenu/ContextMenu.test.tsx +0 -87
- package/src/ContextMenu/ContextMenu.tsx +28 -87
- package/src/ContextMenu/ContextMenuItem.doc.mjs +0 -6
- package/src/DateInput/DateInput.test.tsx +20 -11
- package/src/DateRangeInput/DateRangeInput.test.tsx +44 -31
- package/src/DateTimeInput/DateTimeInput.doc.mjs +2 -3
- package/src/DateTimeInput/DateTimeInput.test.tsx +16 -118
- package/src/DateTimeInput/DateTimeInput.tsx +2 -8
- package/src/DateTimeInput/index.ts +0 -1
- package/src/Dialog/Dialog.doc.mjs +0 -4
- package/src/Dialog/DialogHeader.doc.mjs +0 -45
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +2 -22
- package/src/DropdownMenu/DropdownMenuItem.tsx +17 -5
- package/src/EmptyState/EmptyState.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +4 -1
- package/src/Field/FieldLabel.test.tsx +2 -2
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +3 -0
- package/src/Grid/Grid.test.tsx +18 -43
- package/src/Grid/Grid.tsx +9 -26
- package/src/HoverCard/HoverCard.doc.mjs +6 -6
- package/src/HoverCard/useHoverCard.doc.mjs +5 -5
- package/src/HoverCard/useHoverCard.tsx +2 -9
- package/src/Icon/Icon.test.tsx +29 -41
- package/src/Icon/Icon.tsx +2 -6
- package/src/InputGroup/InputGroup.doc.mjs +0 -1
- package/src/InputGroup/InputGroup.tsx +2 -2
- package/src/Item/Item.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layer/useLayer.test.tsx +2 -221
- package/src/Layer/useLayer.tsx +30 -69
- package/src/Layout/LayoutContent.doc.mjs +0 -12
- package/src/Layout/LayoutPanel.doc.mjs +0 -40
- package/src/Lightbox/Lightbox.doc.mjs +0 -5
- package/src/Lightbox/Lightbox.test.tsx +2 -123
- package/src/Lightbox/Lightbox.tsx +1 -29
- package/src/Markdown/Markdown.tsx +7 -9
- package/src/Markdown/parser.perf.test.ts +12 -34
- package/src/MobileNav/MobileNav.test.tsx +0 -56
- package/src/MobileNav/MobileNav.tsx +8 -13
- package/src/NavMenu/NavMenu.doc.mjs +0 -15
- package/src/NumberInput/NumberInput.test.tsx +3 -48
- package/src/NumberInput/NumberInput.tsx +15 -32
- package/src/Outline/Outline.doc.mjs +0 -2
- package/src/Overlay/Overlay.doc.mjs +0 -6
- package/src/Pagination/Pagination.test.tsx +0 -162
- package/src/Pagination/Pagination.tsx +26 -80
- package/src/Popover/Popover.doc.mjs +6 -6
- package/src/Popover/Popover.test.tsx +0 -65
- package/src/Popover/usePopover.doc.mjs +1 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
- package/src/PowerSearch/PowerSearch.test.tsx +1 -109
- package/src/PowerSearch/PowerSearch.tsx +16 -37
- package/src/ProgressBar/ProgressBar.doc.mjs +0 -2
- package/src/ProgressBar/ProgressBar.test.tsx +0 -30
- package/src/ProgressBar/ProgressBar.tsx +5 -12
- package/src/RadioList/RadioList.test.tsx +0 -19
- package/src/RadioList/RadioListItem.tsx +4 -9
- package/src/Resizable/ResizeHandle.tsx +4 -22
- package/src/SegmentedControl/SegmentedControl.doc.mjs +1 -1
- package/src/SegmentedControl/SegmentedControl.test.tsx +0 -192
- package/src/SegmentedControl/SegmentedControl.tsx +5 -27
- package/src/SegmentedControl/SegmentedControlItem.tsx +4 -9
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.test.tsx +1 -27
- package/src/SideNav/SideNav.doc.mjs +1 -7
- package/src/SideNav/SideNav.test.tsx +0 -66
- package/src/SideNav/SideNav.tsx +2 -6
- package/src/SideNav/SideNavCollapseButton.tsx +3 -4
- package/src/SideNav/SideNavSection.tsx +4 -6
- package/src/Switch/Switch.doc.mjs +7 -7
- package/src/Switch/Switch.test.tsx +3 -102
- package/src/Switch/Switch.tsx +7 -20
- package/src/TabList/TabList.test.tsx +1 -185
- package/src/TabList/TabMenu.tsx +9 -45
- package/src/Table/BaseTable.tsx +2 -13
- package/src/Table/Table.doc.mjs +0 -5
- package/src/Table/Table.test.tsx +0 -87
- package/src/Table/TableBody.tsx +2 -15
- package/src/Table/TableFooter.tsx +2 -15
- package/src/Table/TableHeader.tsx +2 -15
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +0 -13
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +1 -3
- package/src/Table/plugins/pagination/paginateData.ts +1 -5
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +0 -13
- package/src/Table/plugins/selection/useTableSelectionState.test.tsx +0 -23
- package/src/Table/plugins/selection/useTableSelectionState.tsx +6 -11
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +1 -35
- package/src/Table/plugins/sortable/useTableSortableState.tsx +4 -8
- package/src/TextArea/TextArea.test.tsx +3 -3
- package/src/TextInput/TextInput.test.tsx +3 -3
- package/src/Thumbnail/Thumbnail.test.tsx +2 -36
- package/src/Thumbnail/Thumbnail.tsx +2 -4
- package/src/TimeInput/TimeInput.test.tsx +0 -37
- package/src/TimeInput/TimeInput.tsx +1 -11
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +0 -52
- package/src/Timestamp/Timestamp.tsx +16 -30
- package/src/Toast/Toast.tsx +3 -11
- package/src/Toast/ToastViewport.test.tsx +0 -64
- package/src/Toast/ToastViewport.tsx +0 -12
- package/src/Toast/useToast.tsx +0 -41
- package/src/ToggleButton/ToggleButton.doc.mjs +0 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.test.tsx +0 -54
- package/src/Tokenizer/Tokenizer.tsx +4 -5
- package/src/Tooltip/Tooltip.doc.mjs +6 -6
- package/src/Tooltip/useTooltip.doc.mjs +5 -5
- package/src/Tooltip/useTooltip.tsx +2 -12
- package/src/TopNav/TopNav.doc.mjs +1 -1
- package/src/TopNav/TopNav.test.tsx +7 -23
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +2 -9
- package/src/TreeList/TreeList.doc.mjs +2 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +0 -19
- package/src/Typeahead/BaseTypeahead.tsx +2 -5
- package/src/Typeahead/Typeahead.doc.mjs +1 -1
- package/src/Typeahead/Typeahead.test.tsx +1 -45
- package/src/docs-types.ts +1 -9
- package/src/hooks/focusableSelector.ts +1 -1
- package/src/hooks/index.ts +0 -3
- package/src/hooks/useFocusTrap.doc.mjs +2 -4
- package/src/hooks/useFocusTrap.test.tsx +1 -149
- package/src/hooks/useFocusTrap.ts +1 -50
- package/src/hooks/useInteractiveRole.ts +4 -12
- package/src/hooks/useStreamingText.test.ts +19 -54
- package/src/hooks/useStreamingText.ts +5 -16
- package/src/hooks/useTreeFocus.test.tsx +3 -1
- package/src/reset.css +0 -29
- package/src/theme/SyntaxTheme.doc.mjs +4 -4
- package/src/theme/defineTheme.ts +13 -4
- package/src/theme/derivedVarRegistry.test.ts +2 -2
- package/src/theme/expandColorScale.test.ts +0 -29
- package/src/theme/expandColorScale.ts +6 -11
- package/src/theme/hct.ts +17 -9
- package/src/theme/tokens.test.ts +9 -182
- package/src/theme/tokens.ts +4 -239
- package/src/theme/useTheme.test.tsx +2 -126
- package/src/theme/useTheme.ts +6 -87
- package/src/utils/index.ts +0 -4
- package/src/utils/sharedResizeObserver.test.ts +2 -2
- package/src/utils/timeParser.test.ts +0 -13
- package/src/utils/timeParser.ts +5 -8
- package/dist/hooks/useHotkeys.d.ts +0 -51
- package/dist/hooks/useHotkeys.d.ts.map +0 -1
- package/dist/hooks/useHotkeys.js +0 -160
- package/dist/utils/color.d.ts +0 -42
- package/dist/utils/color.d.ts.map +0 -1
- package/dist/utils/color.js +0 -150
- package/dist/utils/composeEventHandlers.d.ts +0 -30
- package/dist/utils/composeEventHandlers.d.ts.map +0 -1
- package/dist/utils/composeEventHandlers.js +0 -40
- package/src/Chat/ChatDictationButton.test.tsx +0 -43
- package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -33
- package/src/Chat/ChatMessageMetadata.test.tsx +0 -32
- package/src/Collapsible/Collapsible.test.tsx +0 -405
- package/src/FieldStatus/FieldStatus.test.tsx +0 -282
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +0 -185
- package/src/Layout/Layout.test.tsx +0 -285
- package/src/Layout/LayoutSlots.test.tsx +0 -364
- package/src/Outline/parseOutlineFromMarkdown.test.ts +0 -80
- package/src/OverflowList/OverflowList.test.tsx +0 -416
- package/src/Overlay/Overlay.test.tsx +0 -356
- package/src/Resizable/ResizeHandle.test.tsx +0 -218
- package/src/SizeContext/SizeContext.test.tsx +0 -226
- package/src/Toast/useToast.test.tsx +0 -258
- package/src/__tests__/TestIcon.tsx +0 -26
- package/src/__tests__/fastRoleQueries.ts +0 -66
- package/src/docPropReferences.test.ts +0 -178
- package/src/hooks/useHotkeys.doc.mjs +0 -52
- package/src/hooks/useHotkeys.test.ts +0 -245
- package/src/hooks/useHotkeys.ts +0 -203
- package/src/theme/themingTargets.test.ts +0 -353
- package/src/utils/color.test.ts +0 -133
- package/src/utils/color.ts +0 -148
- package/src/utils/composeEventHandlers.test.ts +0 -71
- package/src/utils/composeEventHandlers.ts +0 -44
- package/src/utils/mergeProps.test.ts +0 -166
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
4
|
-
/**
|
|
5
|
-
* @file Guards `theming.targets` against the real `themeProps()` call sites (#3741).
|
|
6
|
-
* @input Component sources (*.tsx/*.ts) and their `{Name}.doc.mjs` files.
|
|
7
|
-
* @output Vitest failures naming each undocumented class / visual prop.
|
|
8
|
-
* @position Sibling of derivedVarRegistry.test.ts, which already validates the
|
|
9
|
-
* OTHER fields of the same `theming` block (`vars`, `derived`). `targets` was
|
|
10
|
-
* the one field with no machine check, so it drifted — twice (#3652, #3680).
|
|
11
|
-
*
|
|
12
|
-
* `theming.targets` is the documented CSS surface of a component: the stable
|
|
13
|
-
* `astryx-*` classes it renders and the visual props it reflects as data
|
|
14
|
-
* attributes. It is hand-authored, while the truth lives in `themeProps()`
|
|
15
|
-
* calls in the source. Nothing kept the two in agreement.
|
|
16
|
-
*
|
|
17
|
-
* Drift is not cosmetic. `targets` is what theme authors and codegen read to
|
|
18
|
-
* learn which selectors exist; an undocumented class is an unthemeable element.
|
|
19
|
-
*
|
|
20
|
-
* Policy is SUBSET, not equality: every class rendered by `themeProps()` must be
|
|
21
|
-
* documented, and every prop key passed to it must appear in that target's
|
|
22
|
-
* `visualProps` or `states`. Docs may list MORE than the source passes —
|
|
23
|
-
* components forward props they don't themselves reflect (Timestamp passes
|
|
24
|
-
* `{format}` but documents `type`/`color`/`format`), and that is intentional.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import {describe, it, expect} from 'vitest';
|
|
28
|
-
import {readdirSync, readFileSync} from 'node:fs';
|
|
29
|
-
import {join} from 'node:path';
|
|
30
|
-
import ts from 'typescript';
|
|
31
|
-
import {stableClassName} from '../naming';
|
|
32
|
-
|
|
33
|
-
const SRC_DIR = join(__dirname, '..');
|
|
34
|
-
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
// Source scanning: find themeProps() call sites via the TypeScript AST
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
|
|
39
|
-
interface ThemeTargetSite {
|
|
40
|
-
/** Full stable class, e.g. 'astryx-progressbar-fill'. */
|
|
41
|
-
className: string;
|
|
42
|
-
/** Keys of the object literal passed as the 2nd arg (may be empty). */
|
|
43
|
-
propKeys: string[];
|
|
44
|
-
/** True when the 2nd arg exists but its keys can't be read statically. */
|
|
45
|
-
isOpaque: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Extract every `themeProps('name', {...})` call from a source file.
|
|
50
|
-
*
|
|
51
|
-
* Uses the AST rather than a regex because the call sites use every object
|
|
52
|
-
* form: shorthand (`{variant}`), renamed (`{variant: fillVariant}` — the KEY is
|
|
53
|
-
* the prop, not the value), and multi-line. A regex reading identifiers after
|
|
54
|
-
* `:` would record `fillVariant`, a prop that does not exist.
|
|
55
|
-
*/
|
|
56
|
-
function extractThemeTargets(
|
|
57
|
-
sourceText: string,
|
|
58
|
-
fileName = 'source.tsx',
|
|
59
|
-
): ThemeTargetSite[] {
|
|
60
|
-
const sourceFile = ts.createSourceFile(
|
|
61
|
-
fileName,
|
|
62
|
-
sourceText,
|
|
63
|
-
ts.ScriptTarget.Latest,
|
|
64
|
-
/* setParentNodes */ true,
|
|
65
|
-
fileName.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
const sites: ThemeTargetSite[] = [];
|
|
69
|
-
|
|
70
|
-
const visit = (node: ts.Node): void => {
|
|
71
|
-
if (
|
|
72
|
-
ts.isCallExpression(node) &&
|
|
73
|
-
ts.isIdentifier(node.expression) &&
|
|
74
|
-
node.expression.text === 'themeProps'
|
|
75
|
-
) {
|
|
76
|
-
const [nameArg, propsArg] = node.arguments;
|
|
77
|
-
|
|
78
|
-
// Only string-literal component names are resolvable. A dynamic name
|
|
79
|
-
// can't be checked statically; skip rather than guess.
|
|
80
|
-
if (nameArg != null && ts.isStringLiteralLike(nameArg)) {
|
|
81
|
-
const site: ThemeTargetSite = {
|
|
82
|
-
className: stableClassName(nameArg.text),
|
|
83
|
-
propKeys: [],
|
|
84
|
-
isOpaque: false,
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
if (propsArg != null) {
|
|
88
|
-
if (ts.isObjectLiteralExpression(propsArg)) {
|
|
89
|
-
for (const prop of propsArg.properties) {
|
|
90
|
-
if (ts.isSpreadAssignment(prop)) {
|
|
91
|
-
// {...rest} — keys unknown at parse time.
|
|
92
|
-
site.isOpaque = true;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
const name = prop.name;
|
|
96
|
-
if (name == null) {
|
|
97
|
-
site.isOpaque = true;
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) {
|
|
101
|
-
site.propKeys.push(name.text);
|
|
102
|
-
} else {
|
|
103
|
-
// Computed key: themeProps('x', {[k]: v})
|
|
104
|
-
site.isOpaque = true;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
// A variable or call passed as the props bag.
|
|
109
|
-
site.isOpaque = true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
sites.push(site);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
ts.forEachChild(node, visit);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
visit(sourceFile);
|
|
121
|
-
return sites;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ---------------------------------------------------------------------------
|
|
125
|
-
// The extractor must be right before its verdicts mean anything.
|
|
126
|
-
// ---------------------------------------------------------------------------
|
|
127
|
-
|
|
128
|
-
describe('extractThemeTargets', () => {
|
|
129
|
-
it('reads a bare call with no props', () => {
|
|
130
|
-
expect(extractThemeTargets(`themeProps('progressbar-track')`)).toEqual([
|
|
131
|
-
{className: 'astryx-progressbar-track', propKeys: [], isOpaque: false},
|
|
132
|
-
]);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('reads shorthand props', () => {
|
|
136
|
-
expect(extractThemeTargets(`themeProps('progressbar', {variant})`)).toEqual(
|
|
137
|
-
[
|
|
138
|
-
{
|
|
139
|
-
className: 'astryx-progressbar',
|
|
140
|
-
propKeys: ['variant'],
|
|
141
|
-
isOpaque: false,
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('records the KEY, not the value, when a prop is renamed', () => {
|
|
148
|
-
// The trap a regex falls into: `fillVariant` is a local, not a prop.
|
|
149
|
-
expect(
|
|
150
|
-
extractThemeTargets(
|
|
151
|
-
`themeProps('progressbar-fill', {variant: fillVariant})`,
|
|
152
|
-
),
|
|
153
|
-
).toEqual([
|
|
154
|
-
{
|
|
155
|
-
className: 'astryx-progressbar-fill',
|
|
156
|
-
propKeys: ['variant'],
|
|
157
|
-
isOpaque: false,
|
|
158
|
-
},
|
|
159
|
-
]);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('reads multi-line object literals', () => {
|
|
163
|
-
const src = `
|
|
164
|
-
const p = themeProps('outline', {
|
|
165
|
-
variant,
|
|
166
|
-
size: resolvedSize,
|
|
167
|
-
});
|
|
168
|
-
`;
|
|
169
|
-
expect(extractThemeTargets(src)).toEqual([
|
|
170
|
-
{
|
|
171
|
-
className: 'astryx-outline',
|
|
172
|
-
propKeys: ['variant', 'size'],
|
|
173
|
-
isOpaque: false,
|
|
174
|
-
},
|
|
175
|
-
]);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('reads a call whose result is immediately accessed', () => {
|
|
179
|
-
// Table does `themeProps('table').className` — still a rendered class.
|
|
180
|
-
expect(extractThemeTargets(`themeProps('table').className`)).toEqual([
|
|
181
|
-
{className: 'astryx-table', propKeys: [], isOpaque: false},
|
|
182
|
-
]);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('finds every call in a file', () => {
|
|
186
|
-
const src = `
|
|
187
|
-
<div {...themeProps('card', {variant})}>
|
|
188
|
-
<span {...themeProps('card-header')} />
|
|
189
|
-
</div>
|
|
190
|
-
`;
|
|
191
|
-
expect(extractThemeTargets(src).map(s => s.className)).toEqual([
|
|
192
|
-
'astryx-card',
|
|
193
|
-
'astryx-card-header',
|
|
194
|
-
]);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('marks a spread props bag opaque rather than guessing its keys', () => {
|
|
198
|
-
const [site] = extractThemeTargets(`themeProps('card', {...rest})`);
|
|
199
|
-
expect(site.isOpaque).toBe(true);
|
|
200
|
-
expect(site.propKeys).toEqual([]);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('marks a non-literal props bag opaque', () => {
|
|
204
|
-
const [site] = extractThemeTargets(`themeProps('card', visualProps)`);
|
|
205
|
-
expect(site.isOpaque).toBe(true);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('ignores a dynamic component name it cannot resolve', () => {
|
|
209
|
-
expect(extractThemeTargets(`themeProps(name, {variant})`)).toEqual([]);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('ignores an unrelated function of a similar shape', () => {
|
|
213
|
-
expect(extractThemeTargets(`stylex.props('card', {variant})`)).toEqual([]);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
|
-
// Discovery: every component dir's rendered classes vs its documented targets
|
|
219
|
-
// ---------------------------------------------------------------------------
|
|
220
|
-
|
|
221
|
-
interface DocTarget {
|
|
222
|
-
className: string;
|
|
223
|
-
visualProps?: string[];
|
|
224
|
-
states?: string[];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
type DocBlock = {theming?: {targets?: DocTarget[]}};
|
|
228
|
-
type ComponentDocModule = {docs?: DocBlock; docsZh?: DocBlock};
|
|
229
|
-
|
|
230
|
-
interface ComponentInfo {
|
|
231
|
-
dir: string;
|
|
232
|
-
sites: ThemeTargetSite[];
|
|
233
|
-
/** The doc blocks that carry theming.targets, by the key they live under. */
|
|
234
|
-
docBlocks: {key: 'docs' | 'docsZh'; targets: DocTarget[]}[];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function discoverComponents(): ComponentInfo[] {
|
|
238
|
-
const results: ComponentInfo[] = [];
|
|
239
|
-
const dirs = readdirSync(SRC_DIR, {withFileTypes: true})
|
|
240
|
-
.filter(d => d.isDirectory())
|
|
241
|
-
.map(d => d.name);
|
|
242
|
-
|
|
243
|
-
for (const dir of dirs) {
|
|
244
|
-
const dirPath = join(SRC_DIR, dir);
|
|
245
|
-
const dirEntries = readdirSync(dirPath);
|
|
246
|
-
|
|
247
|
-
const sourceFiles = dirEntries.filter(
|
|
248
|
-
f =>
|
|
249
|
-
(f.endsWith('.tsx') || f.endsWith('.ts')) &&
|
|
250
|
-
!f.includes('.test.') &&
|
|
251
|
-
!f.endsWith('.d.ts'),
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
const sites: ThemeTargetSite[] = [];
|
|
255
|
-
for (const f of sourceFiles) {
|
|
256
|
-
const filePath = join(dirPath, f);
|
|
257
|
-
sites.push(
|
|
258
|
-
...extractThemeTargets(readFileSync(filePath, 'utf-8'), filePath),
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
if (sites.length === 0) {
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Match the on-disk listing rather than existsSync: on case-insensitive
|
|
266
|
-
// filesystems existsSync would match a differently-cased doc file that CI
|
|
267
|
-
// never checks. (Same guard as derivedVarRegistry.test.ts.)
|
|
268
|
-
if (!dirEntries.includes(`${dir}.doc.mjs`)) {
|
|
269
|
-
continue;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
let mod: ComponentDocModule;
|
|
273
|
-
try {
|
|
274
|
-
mod = require(join(dirPath, `${dir}.doc.mjs`)) as ComponentDocModule;
|
|
275
|
-
} catch {
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const docBlocks: ComponentInfo['docBlocks'] = [];
|
|
280
|
-
for (const key of ['docs', 'docsZh'] as const) {
|
|
281
|
-
const targets = mod[key]?.theming?.targets;
|
|
282
|
-
// Only blocks that already document a theming surface are held to it —
|
|
283
|
-
// a doc with no theming block at all is a separate (documentation) gap.
|
|
284
|
-
if (targets != null) {
|
|
285
|
-
docBlocks.push({key, targets});
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (docBlocks.length === 0) {
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
results.push({dir, sites, docBlocks});
|
|
293
|
-
}
|
|
294
|
-
return results;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// ---------------------------------------------------------------------------
|
|
298
|
-
// The guard
|
|
299
|
-
// ---------------------------------------------------------------------------
|
|
300
|
-
|
|
301
|
-
describe('theming.targets matches the themeProps() call sites', () => {
|
|
302
|
-
const components = discoverComponents();
|
|
303
|
-
|
|
304
|
-
it('finds components to check', () => {
|
|
305
|
-
// A refactor that renames themeProps must not silently disable this file.
|
|
306
|
-
expect(components.length).toBeGreaterThan(0);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
for (const {dir, sites, docBlocks} of components) {
|
|
310
|
-
const renderedClasses = [...new Set(sites.map(s => s.className))].sort();
|
|
311
|
-
|
|
312
|
-
for (const {key, targets} of docBlocks) {
|
|
313
|
-
const documented = new Set(targets.map(t => t.className));
|
|
314
|
-
|
|
315
|
-
it(`${dir} (${key}): every rendered class is documented`, () => {
|
|
316
|
-
const undocumented = renderedClasses.filter(c => !documented.has(c));
|
|
317
|
-
expect(
|
|
318
|
-
undocumented,
|
|
319
|
-
`${dir} renders ${undocumented.length} astryx-* class(es) that ` +
|
|
320
|
-
`${dir}.doc.mjs ${key}.theming.targets does not document: ` +
|
|
321
|
-
`${undocumented.join(', ')}. An undocumented class is an ` +
|
|
322
|
-
`unthemeable element — theme authors and codegen read targets[] ` +
|
|
323
|
-
`to learn which selectors exist. Add {className: '...'} entries.`,
|
|
324
|
-
).toEqual([]);
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
it(`${dir} (${key}): every visual prop passed to themeProps is documented`, () => {
|
|
328
|
-
const missing: string[] = [];
|
|
329
|
-
for (const site of sites) {
|
|
330
|
-
const target = targets.find(t => t.className === site.className);
|
|
331
|
-
if (target == null) {
|
|
332
|
-
continue; // Reported by the class test above.
|
|
333
|
-
}
|
|
334
|
-
const known = new Set([
|
|
335
|
-
...(target.visualProps || []),
|
|
336
|
-
...(target.states || []),
|
|
337
|
-
]);
|
|
338
|
-
for (const propKey of site.propKeys) {
|
|
339
|
-
if (!known.has(propKey)) {
|
|
340
|
-
missing.push(`${site.className}: ${propKey}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
expect(
|
|
345
|
-
[...new Set(missing)],
|
|
346
|
-
`${dir} passes prop keys to themeProps() that ${dir}.doc.mjs ` +
|
|
347
|
-
`${key}.theming.targets does not list under visualProps/states. ` +
|
|
348
|
-
`Each one is a [data-*] selector consumers cannot discover.`,
|
|
349
|
-
).toEqual([]);
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
});
|
package/src/utils/color.test.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
import {describe, expect, it} from 'vitest';
|
|
4
|
-
import {parseHex, parseRgb, parseColor, formatHex, formatColor} from './color';
|
|
5
|
-
|
|
6
|
-
describe('parseHex', () => {
|
|
7
|
-
it('parses #rrggbb', () => {
|
|
8
|
-
expect(parseHex('#0064E0')).toEqual({r: 0, g: 100, b: 224, a: 1});
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('parses without a leading #', () => {
|
|
12
|
-
expect(parseHex('0064E0')).toEqual({r: 0, g: 100, b: 224, a: 1});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('expands #rgb shorthand', () => {
|
|
16
|
-
expect(parseHex('#abc')).toEqual({r: 0xaa, g: 0xbb, b: 0xcc, a: 1});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('parses #rrggbbaa alpha', () => {
|
|
20
|
-
expect(parseHex('#00000080')).toEqual({r: 0, g: 0, b: 0, a: 128 / 255});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('expands #rgba shorthand alpha', () => {
|
|
24
|
-
expect(parseHex('#f008')).toEqual({
|
|
25
|
-
r: 0xff,
|
|
26
|
-
g: 0,
|
|
27
|
-
b: 0,
|
|
28
|
-
a: 0x88 / 255,
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('returns null for non-hex input', () => {
|
|
33
|
-
expect(parseHex('rgb(0,0,0)')).toBeNull();
|
|
34
|
-
expect(parseHex('#12')).toBeNull();
|
|
35
|
-
expect(parseHex('#zzzzzz')).toBeNull();
|
|
36
|
-
// @ts-expect-error runtime guard for non-string input
|
|
37
|
-
expect(parseHex(null)).toBeNull();
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('parseRgb', () => {
|
|
42
|
-
it('parses comma-separated rgb()', () => {
|
|
43
|
-
expect(parseRgb('rgb(0, 100, 224)')).toEqual({
|
|
44
|
-
r: 0,
|
|
45
|
-
g: 100,
|
|
46
|
-
b: 224,
|
|
47
|
-
a: 1,
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('parses rgba() with alpha', () => {
|
|
52
|
-
expect(parseRgb('rgba(0, 0, 0, 0.5)')).toEqual({r: 0, g: 0, b: 0, a: 0.5});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('parses space-separated with slash alpha', () => {
|
|
56
|
-
expect(parseRgb('rgb(0 100 224 / 0.25)')).toEqual({
|
|
57
|
-
r: 0,
|
|
58
|
-
g: 100,
|
|
59
|
-
b: 224,
|
|
60
|
-
a: 0.25,
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('parses percentage channels', () => {
|
|
65
|
-
expect(parseRgb('rgb(100%, 0%, 0%)')).toEqual({
|
|
66
|
-
r: 255,
|
|
67
|
-
g: 0,
|
|
68
|
-
b: 0,
|
|
69
|
-
a: 1,
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('clamps alpha and channels into range', () => {
|
|
74
|
-
expect(parseRgb('rgba(300, -20, 10, 2)')).toEqual({
|
|
75
|
-
r: 255,
|
|
76
|
-
g: 0,
|
|
77
|
-
b: 10,
|
|
78
|
-
a: 1,
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('returns null when it cannot parse', () => {
|
|
83
|
-
expect(parseRgb('rgb(0, 0)')).toBeNull();
|
|
84
|
-
expect(parseRgb('#000000')).toBeNull();
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('parseColor', () => {
|
|
89
|
-
it('routes hex and rgb strings to the right parser', () => {
|
|
90
|
-
expect(parseColor('#FFFFFF')).toEqual({r: 255, g: 255, b: 255, a: 1});
|
|
91
|
-
expect(parseColor('rgb(1, 2, 3)')).toEqual({r: 1, g: 2, b: 3, a: 1});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('resolves the named colors used in token expressions', () => {
|
|
95
|
-
expect(parseColor('transparent')).toEqual({r: 0, g: 0, b: 0, a: 0});
|
|
96
|
-
expect(parseColor('BLACK')).toEqual({r: 0, g: 0, b: 0, a: 1});
|
|
97
|
-
expect(parseColor('white')).toEqual({r: 255, g: 255, b: 255, a: 1});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('returns null for unsupported colors so callers can preserve them', () => {
|
|
101
|
-
expect(parseColor('var(--color-accent)')).toBeNull();
|
|
102
|
-
expect(parseColor('oklch(0.5 0.1 200)')).toBeNull();
|
|
103
|
-
expect(parseColor('rebeccapurple')).toBeNull();
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe('formatHex', () => {
|
|
108
|
-
it('formats channels as uppercase #RRGGBB', () => {
|
|
109
|
-
expect(formatHex(0, 100, 224)).toBe('#0064E0');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('rounds and clamps out-of-range channels', () => {
|
|
113
|
-
expect(formatHex(-5, 300, 127.6)).toBe('#00FF80');
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('formatColor', () => {
|
|
118
|
-
it('formats opaque colors as hex', () => {
|
|
119
|
-
expect(formatColor({r: 0, g: 100, b: 224, a: 1})).toBe('#0064E0');
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('formats translucent colors as rgba()', () => {
|
|
123
|
-
expect(formatColor({r: 0, g: 100, b: 224, a: 0.2})).toBe(
|
|
124
|
-
'rgba(0, 100, 224, 0.2)',
|
|
125
|
-
);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('round-trips through parseColor', () => {
|
|
129
|
-
const parsed = parseColor('rgba(10, 20, 30, 0.5)');
|
|
130
|
-
expect(parsed).not.toBeNull();
|
|
131
|
-
expect(formatColor(parsed!)).toBe('rgba(10, 20, 30, 0.5)');
|
|
132
|
-
});
|
|
133
|
-
});
|
package/src/utils/color.ts
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file color.ts
|
|
5
|
-
* @input CSS color strings (hex, rgb()/rgba(), a small set of named colors)
|
|
6
|
-
* @output Shared color parsing/formatting primitives used across the design system
|
|
7
|
-
* @position Package utility; backs theme token resolution, HCT color math, and chart rendering
|
|
8
|
-
*
|
|
9
|
-
* A single home for the color parsers that were previously duplicated across
|
|
10
|
-
* the theme layer, charts, and lab. Consumers get one well-tested definition of
|
|
11
|
-
* "parse this color" rather than several subtly different regexes.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/** A color decomposed into 0-255 RGB channels and a 0-1 alpha. */
|
|
15
|
-
export interface RGBA {
|
|
16
|
-
r: number;
|
|
17
|
-
g: number;
|
|
18
|
-
b: number;
|
|
19
|
-
a: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** The named colors the design system relies on in token expressions. */
|
|
23
|
-
const NAMED_COLORS: Record<string, RGBA> = {
|
|
24
|
-
transparent: {r: 0, g: 0, b: 0, a: 0},
|
|
25
|
-
black: {r: 0, g: 0, b: 0, a: 1},
|
|
26
|
-
white: {r: 255, g: 255, b: 255, a: 1},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const clamp = (value: number, min: number, max: number): number =>
|
|
30
|
-
Math.max(min, Math.min(max, value));
|
|
31
|
-
|
|
32
|
-
/** Expand a shorthand hex body (`rgb`/`rgba`) to its full form (`rrggbb`/`rrggbbaa`). */
|
|
33
|
-
function expandShorthand(body: string): string {
|
|
34
|
-
return body
|
|
35
|
-
.split('')
|
|
36
|
-
.map(c => c + c)
|
|
37
|
-
.join('');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Parse a hex color into {@link RGBA}. Accepts `#rgb`, `#rgba`, `#rrggbb`, and
|
|
42
|
-
* `#rrggbbaa`, with or without the leading `#`. Returns null for anything else.
|
|
43
|
-
*/
|
|
44
|
-
export function parseHex(hex: string): RGBA | null {
|
|
45
|
-
if (typeof hex !== 'string') {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
const body = hex.trim().replace(/^#/, '');
|
|
49
|
-
const normalized =
|
|
50
|
-
body.length === 3 || body.length === 4 ? expandShorthand(body) : body;
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
(normalized.length !== 6 && normalized.length !== 8) ||
|
|
54
|
-
!/^[0-9a-fA-F]+$/.test(normalized)
|
|
55
|
-
) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
r: parseInt(normalized.slice(0, 2), 16),
|
|
61
|
-
g: parseInt(normalized.slice(2, 4), 16),
|
|
62
|
-
b: parseInt(normalized.slice(4, 6), 16),
|
|
63
|
-
a: normalized.length === 8 ? parseInt(normalized.slice(6, 8), 16) / 255 : 1,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Parse an `rgb()`/`rgba()` color into {@link RGBA}. Accepts comma- or
|
|
69
|
-
* space-separated channels, an optional `/ alpha`, and percentage channels.
|
|
70
|
-
*/
|
|
71
|
-
export function parseRgb(value: string): RGBA | null {
|
|
72
|
-
const open = value.indexOf('(');
|
|
73
|
-
if (open === -1 || !value.trim().endsWith(')')) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
const body = value
|
|
77
|
-
.slice(open + 1, value.lastIndexOf(')'))
|
|
78
|
-
.replace(/\//g, ' ');
|
|
79
|
-
const parts = body
|
|
80
|
-
.split(/[\s,]+/)
|
|
81
|
-
.map(p => p.trim())
|
|
82
|
-
.filter(Boolean);
|
|
83
|
-
if (parts.length < 3) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const channel = (p: string): number => {
|
|
88
|
-
const n = p.endsWith('%') ? (parseFloat(p) / 100) * 255 : parseFloat(p);
|
|
89
|
-
return clamp(n, 0, 255);
|
|
90
|
-
};
|
|
91
|
-
const r = channel(parts[0]);
|
|
92
|
-
const g = channel(parts[1]);
|
|
93
|
-
const b = channel(parts[2]);
|
|
94
|
-
if ([r, g, b].some(Number.isNaN)) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
let a = 1;
|
|
99
|
-
if (parts.length >= 4) {
|
|
100
|
-
const raw = parts[3];
|
|
101
|
-
a = raw.endsWith('%') ? parseFloat(raw) / 100 : parseFloat(raw);
|
|
102
|
-
if (Number.isNaN(a)) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
a = clamp(a, 0, 1);
|
|
106
|
-
}
|
|
107
|
-
return {r, g, b, a};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Parse a concrete CSS color string into {@link RGBA}. Supports hex,
|
|
112
|
-
* `rgb()`/`rgba()`, and the named colors used in token expressions. Returns
|
|
113
|
-
* null for anything it can't evaluate (e.g. `var()`, `oklch()`, unknown names)
|
|
114
|
-
* so callers can preserve the original expression rather than guessing.
|
|
115
|
-
*/
|
|
116
|
-
export function parseColor(value: string): RGBA | null {
|
|
117
|
-
const trimmed = value.trim();
|
|
118
|
-
const named = NAMED_COLORS[trimmed.toLowerCase()];
|
|
119
|
-
if (named) {
|
|
120
|
-
return {...named};
|
|
121
|
-
}
|
|
122
|
-
if (trimmed.startsWith('#')) {
|
|
123
|
-
return parseHex(trimmed);
|
|
124
|
-
}
|
|
125
|
-
if (/^rgba?\(/i.test(trimmed)) {
|
|
126
|
-
return parseRgb(trimmed);
|
|
127
|
-
}
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** Format RGB channels (0-255) as an uppercase `#RRGGBB` string. */
|
|
132
|
-
export function formatHex(r: number, g: number, b: number): string {
|
|
133
|
-
const channel = (c: number): string =>
|
|
134
|
-
clamp(Math.round(c), 0, 255).toString(16).padStart(2, '0').toUpperCase();
|
|
135
|
-
return `#${channel(r)}${channel(g)}${channel(b)}`;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Serialize {@link RGBA} to a compact, JS-usable CSS color: `#RRGGBB` when
|
|
140
|
-
* fully opaque, otherwise `rgba(r, g, b, a)`.
|
|
141
|
-
*/
|
|
142
|
-
export function formatColor({r, g, b, a}: RGBA): string {
|
|
143
|
-
if (a >= 1) {
|
|
144
|
-
return formatHex(r, g, b);
|
|
145
|
-
}
|
|
146
|
-
const round = (n: number): number => clamp(Math.round(n), 0, 255);
|
|
147
|
-
return `rgba(${round(r)}, ${round(g)}, ${round(b)}, ${parseFloat(a.toFixed(4))})`;
|
|
148
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
import {describe, expect, it, vi} from 'vitest';
|
|
4
|
-
import type {SyntheticEvent} from 'react';
|
|
5
|
-
import {composeEventHandlers} from './composeEventHandlers';
|
|
6
|
-
|
|
7
|
-
function fakeEvent(): SyntheticEvent {
|
|
8
|
-
const event = {
|
|
9
|
-
defaultPrevented: false,
|
|
10
|
-
preventDefault() {
|
|
11
|
-
event.defaultPrevented = true;
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
return event as unknown as SyntheticEvent;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
describe('composeEventHandlers', () => {
|
|
18
|
-
it('calls every handler in argument order', () => {
|
|
19
|
-
const calls: string[] = [];
|
|
20
|
-
const composed = composeEventHandlers(
|
|
21
|
-
() => calls.push('first'),
|
|
22
|
-
() => calls.push('second'),
|
|
23
|
-
);
|
|
24
|
-
composed(fakeEvent());
|
|
25
|
-
expect(calls).toEqual(['first', 'second']);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('skips undefined handlers', () => {
|
|
29
|
-
const handler = vi.fn();
|
|
30
|
-
const composed = composeEventHandlers(undefined, handler, undefined);
|
|
31
|
-
composed(fakeEvent());
|
|
32
|
-
expect(handler).toHaveBeenCalledTimes(1);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('passes the same event to each handler', () => {
|
|
36
|
-
const event = fakeEvent();
|
|
37
|
-
const a = vi.fn();
|
|
38
|
-
const b = vi.fn();
|
|
39
|
-
composeEventHandlers(a, b)(event);
|
|
40
|
-
expect(a).toHaveBeenCalledWith(event);
|
|
41
|
-
expect(b).toHaveBeenCalledWith(event);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('stops after a handler prevents default', () => {
|
|
45
|
-
const first = vi.fn((e: SyntheticEvent) => e.preventDefault());
|
|
46
|
-
const second = vi.fn();
|
|
47
|
-
composeEventHandlers(first, second)(fakeEvent());
|
|
48
|
-
expect(first).toHaveBeenCalledTimes(1);
|
|
49
|
-
expect(second).not.toHaveBeenCalled();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('lets a consumer handler opt out of later behavior (consumer-first order)', () => {
|
|
53
|
-
const consumer = vi.fn((e: SyntheticEvent) => e.preventDefault());
|
|
54
|
-
const ownBehavior = vi.fn();
|
|
55
|
-
composeEventHandlers(consumer, ownBehavior)(fakeEvent());
|
|
56
|
-
expect(ownBehavior).not.toHaveBeenCalled();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('runs later handlers when default is not prevented', () => {
|
|
60
|
-
const consumer = vi.fn();
|
|
61
|
-
const ownBehavior = vi.fn();
|
|
62
|
-
composeEventHandlers(consumer, ownBehavior)(fakeEvent());
|
|
63
|
-
expect(ownBehavior).toHaveBeenCalledTimes(1);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('returns a no-op-safe function when all handlers are undefined', () => {
|
|
67
|
-
expect(() =>
|
|
68
|
-
composeEventHandlers(undefined, undefined)(fakeEvent()),
|
|
69
|
-
).not.toThrow();
|
|
70
|
-
});
|
|
71
|
-
});
|