@astryxdesign/core 0.1.9-canary.d2d84f8 → 0.1.9-canary.e00a241
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/Avatar/Avatar.d.ts +6 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +46 -12
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
- package/dist/Breadcrumbs/index.d.ts +1 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +2 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +50 -9
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +2 -2
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.js +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +22 -12
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +8 -8
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +10 -3
- package/dist/CheckboxInput/CheckboxInput.js +4 -4
- package/dist/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +13 -7
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +42 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +1 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +31 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +20 -19
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -18
- package/dist/Divider/Divider.d.ts +2 -2
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +13 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -1
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +4 -1
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/FileInput/FileInput.d.ts +1 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +91 -65
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +10 -4
- package/dist/Icon/Icon.d.ts +15 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +15 -9
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +65 -40
- package/dist/NumberInput/NumberInput.d.ts +1 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +20 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +49 -19
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +58 -16
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +87 -34
- package/dist/Spinner/Spinner.d.ts +3 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +11 -2
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/TabList.d.ts +2 -11
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +5 -9
- package/dist/TabList/TabListContext.d.ts +0 -5
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +0 -5
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +14 -6
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +1 -0
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -19
- package/dist/TextInput/TextInput.d.ts +1 -0
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +18 -17
- package/dist/TimeInput/TimeInput.d.ts +1 -0
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -17
- package/dist/Timestamp/Timestamp.d.ts +31 -3
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +47 -76
- package/dist/Timestamp/formatInstant.d.ts +41 -0
- package/dist/Timestamp/formatInstant.d.ts.map +1 -0
- package/dist/Timestamp/formatInstant.js +177 -0
- package/dist/Timestamp/index.d.ts +1 -0
- package/dist/Timestamp/index.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.d.ts +56 -0
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
- package/dist/Timestamp/tooltipEntries.js +163 -0
- package/dist/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavItem.d.ts +3 -1
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +30 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +1 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +8 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +32 -14
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +19 -10
- package/dist/Typeahead/Typeahead.js +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +38 -14
- package/dist/astryx.umd.js +52 -52
- package/dist/astryx.umd.js.map +4 -4
- 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/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useAnnounce.d.ts +3 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +39 -1
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +52 -11
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useHotkeys.d.ts +9 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +9 -0
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/plainDate.d.ts +17 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +23 -4
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/locales/en.json +76 -0
- package/locales/pseudo.json +57 -0
- package/package.json +6 -1
- package/src/Avatar/Avatar.doc.mjs +18 -4
- package/src/Avatar/Avatar.test.tsx +106 -0
- package/src/Avatar/Avatar.tsx +62 -10
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.test.tsx +16 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +51 -0
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Calendar/Calendar.test.tsx +170 -20
- package/src/Calendar/Calendar.tsx +73 -16
- package/src/Calendar/dayCellUtils.test.ts +18 -18
- package/src/Calendar/dayCellUtils.ts +2 -2
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.tsx +1 -1
- package/src/Carousel/Carousel.tsx +25 -6
- package/src/Chat/ChatComposer.doc.mjs +2 -2
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -4
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- package/src/CodeBlock/CodeBlock.tsx +35 -8
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +41 -2
- package/src/ContextMenu/ContextMenu.test.tsx +42 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +15 -5
- package/src/DateInput/DateInput.test.tsx +210 -3
- package/src/DateInput/DateInput.tsx +41 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +11 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +120 -3
- package/src/DateRangeInput/DateRangeInput.tsx +29 -27
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
- package/src/DateTimeInput/DateTimeInput.tsx +44 -39
- package/src/Divider/Divider.test.tsx +32 -8
- package/src/Divider/Divider.tsx +14 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.tsx +14 -9
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.tsx +10 -4
- package/src/FileInput/FileInput.doc.mjs +13 -7
- package/src/FileInput/FileInput.test.tsx +84 -16
- package/src/FileInput/FileInput.tsx +96 -79
- package/src/HoverCard/useHoverCard.tsx +15 -3
- package/src/Icon/Icon.doc.mjs +13 -0
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +51 -3
- package/src/Lightbox/Lightbox.tsx +11 -3
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +11 -0
- package/src/MultiSelector/MultiSelector.test.tsx +306 -3
- package/src/MultiSelector/MultiSelector.tsx +88 -57
- package/src/NumberInput/NumberInput.doc.mjs +11 -5
- package/src/NumberInput/NumberInput.test.tsx +48 -0
- package/src/NumberInput/NumberInput.tsx +25 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/Selector/Selector.doc.mjs +8 -0
- package/src/Selector/Selector.test.tsx +328 -3
- package/src/Selector/Selector.tsx +70 -19
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +240 -12
- package/src/Slider/Slider.tsx +96 -23
- package/src/Spinner/Spinner.test.tsx +10 -8
- package/src/Spinner/Spinner.tsx +15 -5
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +22 -0
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/TabList.doc.mjs +0 -6
- package/src/TabList/TabList.test.tsx +3 -15
- package/src/TabList/TabList.tsx +6 -17
- package/src/TabList/TabListContext.ts +0 -6
- package/src/Table/BaseTable.tsx +34 -2
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +37 -8
- package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
- package/src/Table/types.ts +33 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/TextArea/TextArea.doc.mjs +11 -5
- package/src/TextArea/TextArea.tsx +17 -26
- package/src/TextInput/TextInput.doc.mjs +11 -5
- package/src/TextInput/TextInput.test.tsx +130 -3
- package/src/TextInput/TextInput.tsx +18 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +11 -5
- package/src/TimeInput/TimeInput.tsx +14 -25
- package/src/Timestamp/Timestamp.doc.mjs +32 -6
- package/src/Timestamp/Timestamp.test.tsx +371 -0
- package/src/Timestamp/Timestamp.tsx +96 -93
- package/src/Timestamp/formatInstant.ts +218 -0
- package/src/Timestamp/index.ts +4 -0
- package/src/Timestamp/tooltipEntries.test.ts +552 -0
- package/src/Timestamp/tooltipEntries.ts +210 -0
- package/src/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +8 -1
- package/src/Tokenizer/Tokenizer.tsx +4 -2
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +93 -2
- package/src/TopNav/TopNavItem.doc.mjs +3 -3
- package/src/TopNav/TopNavItem.tsx +35 -6
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
- package/src/TreeList/TreeList.doc.mjs +6 -0
- package/src/TreeList/TreeList.test.tsx +50 -10
- package/src/TreeList/TreeList.tsx +5 -0
- package/src/TreeList/TreeListBranches.tsx +8 -6
- package/src/TreeList/TreeListItem.tsx +33 -11
- package/src/Typeahead/BaseTypeahead.tsx +29 -14
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.test.tsx +27 -0
- package/src/Typeahead/Typeahead.tsx +1 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/doc-mjs.d.ts +19 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useAnnounce.test.tsx +75 -2
- package/src/hooks/useAnnounce.ts +47 -1
- package/src/hooks/useFocusTrap.test.tsx +104 -0
- package/src/hooks/useFocusTrap.ts +61 -12
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useHotkeys.ts +9 -0
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +42 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +24 -6
- package/src/utils/plainDate.ts +18 -4
- package/src/utils/rtlStyles.ts +27 -0
|
@@ -15,16 +15,17 @@
|
|
|
15
15
|
* - /apps/storybook/stories/Timestamp.stories.tsx
|
|
16
16
|
* - /packages/cli/templates/blocks/components/Timestamp/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
|
-
import { useEffect, useRef, useState, lazy, Suspense } from 'react';
|
|
18
|
+
import { useEffect, useRef, useState, lazy, Suspense, Fragment } from 'react';
|
|
19
19
|
import * as stylex from '@stylexjs/stylex';
|
|
20
20
|
import { Text } from "../Text/index.js";
|
|
21
21
|
import { mergeProps, mergeRefs } from "../utils/index.js";
|
|
22
22
|
import { useDevWarning } from "../hooks/useDevWarning.js";
|
|
23
23
|
import { themeProps } from "../utils/themeProps.js";
|
|
24
24
|
import "../theme/tokens.stylex.js";
|
|
25
|
-
import { colorVars } from "../theme/tokens.stylex.js";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
25
|
+
import { colorVars, spacingVars } from "../theme/tokens.stylex.js";
|
|
26
|
+
import { formatInstant } from "./formatInstant.js";
|
|
27
|
+
import { formatTooltipLines } from "./tooltipEntries.js";
|
|
28
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
28
29
|
const LazyXDSTooltip = /*#__PURE__*/lazy(async () => import('../Tooltip/Tooltip').then(mod => ({
|
|
29
30
|
default: mod.Tooltip
|
|
30
31
|
})));
|
|
@@ -137,73 +138,6 @@ function getRelativeTimeString(date, now) {
|
|
|
137
138
|
const years = Math.floor(diffSeconds / YEAR);
|
|
138
139
|
return `${years} ${years === 1 ? 'year' : 'years'} ago`;
|
|
139
140
|
}
|
|
140
|
-
function pad(n) {
|
|
141
|
-
return String(n).padStart(2, '0');
|
|
142
|
-
}
|
|
143
|
-
function formatTimestamp(date, format, isTimezoneShown) {
|
|
144
|
-
switch (format) {
|
|
145
|
-
case 'date':
|
|
146
|
-
return new Intl.DateTimeFormat(undefined, SHARED_DATE_FORMAT_OPTIONS.date).format(date);
|
|
147
|
-
case 'date_long':
|
|
148
|
-
return new Intl.DateTimeFormat(undefined, SHARED_DATE_FORMAT_OPTIONS.date_long).format(date);
|
|
149
|
-
case 'date_weekday':
|
|
150
|
-
return new Intl.DateTimeFormat(undefined, SHARED_DATE_FORMAT_OPTIONS.date_weekday).format(date);
|
|
151
|
-
case 'date_time':
|
|
152
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
153
|
-
year: 'numeric',
|
|
154
|
-
month: 'short',
|
|
155
|
-
day: 'numeric',
|
|
156
|
-
hour: 'numeric',
|
|
157
|
-
minute: '2-digit',
|
|
158
|
-
...(isTimezoneShown ? {
|
|
159
|
-
timeZoneName: 'short'
|
|
160
|
-
} : {})
|
|
161
|
-
}).format(date);
|
|
162
|
-
case 'time':
|
|
163
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
164
|
-
hour: 'numeric',
|
|
165
|
-
minute: '2-digit',
|
|
166
|
-
...(isTimezoneShown ? {
|
|
167
|
-
timeZoneName: 'short'
|
|
168
|
-
} : {})
|
|
169
|
-
}).format(date);
|
|
170
|
-
case 'system_date':
|
|
171
|
-
{
|
|
172
|
-
const y = date.getFullYear();
|
|
173
|
-
const m = pad(date.getMonth() + 1);
|
|
174
|
-
const d = pad(date.getDate());
|
|
175
|
-
return `${y}-${m}-${d}`;
|
|
176
|
-
}
|
|
177
|
-
case 'system_date_time':
|
|
178
|
-
{
|
|
179
|
-
const y = date.getFullYear();
|
|
180
|
-
const m = pad(date.getMonth() + 1);
|
|
181
|
-
const d = pad(date.getDate());
|
|
182
|
-
const h = pad(date.getHours());
|
|
183
|
-
const min = pad(date.getMinutes());
|
|
184
|
-
const s = pad(date.getSeconds());
|
|
185
|
-
return `${y}-${m}-${d} ${h}:${min}:${s}`;
|
|
186
|
-
}
|
|
187
|
-
case 'system_time':
|
|
188
|
-
{
|
|
189
|
-
const h = pad(date.getHours());
|
|
190
|
-
const min = pad(date.getMinutes());
|
|
191
|
-
const s = pad(date.getSeconds());
|
|
192
|
-
return `${h}:${min}:${s}`;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function getFullAbsoluteString(date) {
|
|
197
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
198
|
-
year: 'numeric',
|
|
199
|
-
month: 'long',
|
|
200
|
-
day: 'numeric',
|
|
201
|
-
hour: 'numeric',
|
|
202
|
-
minute: '2-digit',
|
|
203
|
-
second: '2-digit',
|
|
204
|
-
timeZoneName: 'short'
|
|
205
|
-
}).format(date);
|
|
206
|
-
}
|
|
207
141
|
|
|
208
142
|
/** Returns the interval (in ms) at which a relative timestamp should update. */
|
|
209
143
|
function getLiveInterval(diffSeconds) {
|
|
@@ -250,6 +184,7 @@ export function Timestamp({
|
|
|
250
184
|
format = 'auto',
|
|
251
185
|
autoThreshold = DEFAULT_AUTO_THRESHOLD,
|
|
252
186
|
hasTooltip = true,
|
|
187
|
+
tooltipEntries,
|
|
253
188
|
isTimezoneShown = false,
|
|
254
189
|
isLive = false,
|
|
255
190
|
type = 'supporting',
|
|
@@ -276,11 +211,14 @@ export function Timestamp({
|
|
|
276
211
|
const diffSeconds = Math.round((now.getTime() - date.getTime()) / 1000);
|
|
277
212
|
const effectiveFormat = format === 'auto' ? Math.abs(diffSeconds) <= autoThreshold ? 'relative' : 'date_time' : format;
|
|
278
213
|
|
|
279
|
-
// Format the display text
|
|
280
|
-
|
|
214
|
+
// Format the display text. No time zone is passed: the visible text always
|
|
215
|
+
// reads in the viewer's own zone, and only the tooltip names others.
|
|
216
|
+
const displayText = !isValidDate ? '' : effectiveFormat === 'relative' ? getRelativeTimeString(date, now) : isAbsoluteFormat(effectiveFormat) ? formatInstant(date, effectiveFormat, {
|
|
217
|
+
isTimezoneShown
|
|
218
|
+
}) : '';
|
|
281
219
|
|
|
282
220
|
// Full absolute text for tooltip and aria-label
|
|
283
|
-
const fullAbsoluteText = isValidDate ?
|
|
221
|
+
const fullAbsoluteText = isValidDate ? formatInstant(date, 'full') : '';
|
|
284
222
|
|
|
285
223
|
// Live updates
|
|
286
224
|
useEffect(() => {
|
|
@@ -299,7 +237,16 @@ export function Timestamp({
|
|
|
299
237
|
if (!isValidDate) {
|
|
300
238
|
return null;
|
|
301
239
|
}
|
|
302
|
-
|
|
240
|
+
|
|
241
|
+
// An empty array is not a second way to spell "off" — `hasTooltip` stays the
|
|
242
|
+
// only on/off axis — so normalize it away before anything reads it.
|
|
243
|
+
const entries = tooltipEntries !== undefined && tooltipEntries.length > 0 ? tooltipEntries : undefined;
|
|
244
|
+
|
|
245
|
+
// Absolute formats have never carried a tooltip. Leaving that gate closed
|
|
246
|
+
// when a consumer has explicitly configured tooltip lines would let `format`
|
|
247
|
+
// silently suppress another prop's output, so entry presence opens it too.
|
|
248
|
+
// With no entries this reduces to the original condition exactly.
|
|
249
|
+
const showTooltip = hasTooltip && (effectiveFormat === 'relative' || entries !== undefined);
|
|
303
250
|
const timestampProps = mergeProps(themeProps('timestamp', {
|
|
304
251
|
format: effectiveFormat
|
|
305
252
|
}), {
|
|
@@ -338,12 +285,36 @@ export function Timestamp({
|
|
|
338
285
|
})
|
|
339
286
|
});
|
|
340
287
|
if (showTooltip) {
|
|
288
|
+
// Built inside the branch so a timestamp without a tooltip allocates none
|
|
289
|
+
// of it. With no entries the content stays the bare string it has always
|
|
290
|
+
// been — no wrapper element is introduced around the default line.
|
|
291
|
+
const tooltipContent = entries === undefined ? fullAbsoluteText : /*#__PURE__*/_jsx("dl", {
|
|
292
|
+
...{
|
|
293
|
+
className: "xrvj5dj x1pmbctz x1tw44j4 x10im51j xrxpjvj"
|
|
294
|
+
},
|
|
295
|
+
children: formatTooltipLines(date, entries).map((line, index) =>
|
|
296
|
+
/*#__PURE__*/
|
|
297
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key -- tooltip lines are fixed positional slots and two entries may legitimately be identical
|
|
298
|
+
_jsxs(Fragment, {
|
|
299
|
+
children: [/*#__PURE__*/_jsx("dt", {
|
|
300
|
+
...{
|
|
301
|
+
className: "x10im51j xrxpjvj xyri2b xepvkrk"
|
|
302
|
+
},
|
|
303
|
+
children: line.label ?? ''
|
|
304
|
+
}), /*#__PURE__*/_jsx("dd", {
|
|
305
|
+
...{
|
|
306
|
+
className: "x10im51j xrxpjvj"
|
|
307
|
+
},
|
|
308
|
+
children: line.value
|
|
309
|
+
})]
|
|
310
|
+
}, index))
|
|
311
|
+
});
|
|
341
312
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
342
313
|
children: [timeElement, /*#__PURE__*/_jsx(Suspense, {
|
|
343
314
|
fallback: null,
|
|
344
315
|
children: /*#__PURE__*/_jsx(LazyXDSTooltip, {
|
|
345
316
|
anchorRef: timeRef,
|
|
346
|
-
content:
|
|
317
|
+
content: tooltipContent,
|
|
347
318
|
placement: "above"
|
|
348
319
|
})
|
|
349
320
|
})]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { TimestampFormat } from './Timestamp';
|
|
2
|
+
/**
|
|
3
|
+
* Every format that names a fixed instant, plus `'full'` — the long absolute
|
|
4
|
+
* style ("February 19, 2026 at 5:00:00 PM UTC") that backs a relative
|
|
5
|
+
* timestamp's accessible name and the tooltip's default line.
|
|
6
|
+
*
|
|
7
|
+
* `'relative'` and `'auto'` are excluded: a relative phrase names no instant,
|
|
8
|
+
* so a zone could not change what it says.
|
|
9
|
+
*/
|
|
10
|
+
export type InstantFormat = Exclude<TimestampFormat, 'relative' | 'auto'> | 'full';
|
|
11
|
+
export interface FormatInstantOptions {
|
|
12
|
+
/**
|
|
13
|
+
* IANA time zone identifier. Omit for the viewer's own zone — which is what
|
|
14
|
+
* `Intl` already does with no `timeZone`, so the omitted path never
|
|
15
|
+
* constructs an explicit-zone formatter and cannot drift from the host
|
|
16
|
+
* default.
|
|
17
|
+
*
|
|
18
|
+
* Must already be one the platform accepts. An identifier `Intl` does not
|
|
19
|
+
* recognize throws a `RangeError` from its constructor, before any
|
|
20
|
+
* formatting happens; deciding what to do about that belongs to whoever
|
|
21
|
+
* took the identifier from a consumer, not here (tooltipEntries resolves
|
|
22
|
+
* and warns in `resolveTimezoneID`, then passes only what survived).
|
|
23
|
+
*/
|
|
24
|
+
timeZone?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to append the zone abbreviation. Honoured by `date_time` and
|
|
27
|
+
* `time` only: `'full'` always carries one because that is the style, and
|
|
28
|
+
* the `system_*` shapes never do — a trailing "PST" would break anything
|
|
29
|
+
* parsing them, which is why `isTimezoneShown` has never applied to them.
|
|
30
|
+
* @default false
|
|
31
|
+
*/
|
|
32
|
+
isTimezoneShown?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Renders one instant in one absolute format.
|
|
36
|
+
*
|
|
37
|
+
* Pure: the same arguments always produce the same string for a given host
|
|
38
|
+
* locale (and, when no `timeZone` is given, host zone).
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatInstant(date: Date, format: InstantFormat, { timeZone, isTimezoneShown }?: FormatInstantOptions): string;
|
|
41
|
+
//# sourceMappingURL=formatInstant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatInstant.d.ts","sourceRoot":"","sources":["../../src/Timestamp/formatInstant.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,aAAa,CAAC;AAMjD;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACrB,OAAO,CAAC,eAAe,EAAE,UAAU,GAAG,MAAM,CAAC,GAC7C,MAAM,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA6ED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,aAAa,EACrB,EAAC,QAAQ,EAAE,eAAuB,EAAC,GAAE,oBAAyB,GAC7D,MAAM,CA0DR"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file formatInstant.ts
|
|
5
|
+
* @input A Date, one absolute format name, and an optional time zone
|
|
6
|
+
* @output That instant rendered as a string
|
|
7
|
+
* @position Leaf shared by Timestamp's visible text and each of its tooltip
|
|
8
|
+
* lines; owns every absolute format Timestamp can produce
|
|
9
|
+
*
|
|
10
|
+
* Timestamp renders the same instant on two surfaces — the visible text and,
|
|
11
|
+
* on hover, one line per configured time zone. They differ only in which zone
|
|
12
|
+
* they name and whether they carry a zone abbreviation, so they are one
|
|
13
|
+
* formatter parameterized by zone rather than two switches that have to be
|
|
14
|
+
* kept in step by hand. Adding a member to `TimestampFormat` now fails to
|
|
15
|
+
* compile in exactly one place.
|
|
16
|
+
*
|
|
17
|
+
* Each caller keeps its own policy for the zone abbreviation: the visible text
|
|
18
|
+
* takes it straight from the `isTimezoneShown` prop, a tooltip line derives it
|
|
19
|
+
* from how many zones are on screen (see tooltipEntries.ts). Only the
|
|
20
|
+
* rendering is shared, not the decision.
|
|
21
|
+
*
|
|
22
|
+
* Omitting `timeZone` means the viewer's own zone. That path hands `Intl` no
|
|
23
|
+
* `timeZone` and keeps `system_*` on plain `Date` getters, so it produces
|
|
24
|
+
* exactly what it produced before this module existed.
|
|
25
|
+
*
|
|
26
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
27
|
+
* - /packages/core/src/Timestamp/Timestamp.tsx
|
|
28
|
+
* - /packages/core/src/Timestamp/tooltipEntries.ts
|
|
29
|
+
* - /packages/core/src/Timestamp/Timestamp.test.tsx
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { SHARED_DATE_FORMAT_OPTIONS, getTimeZoneParts } from "../utils/plainDate.js";
|
|
33
|
+
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Types
|
|
36
|
+
// =============================================================================
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Every format that names a fixed instant, plus `'full'` — the long absolute
|
|
40
|
+
* style ("February 19, 2026 at 5:00:00 PM UTC") that backs a relative
|
|
41
|
+
* timestamp's accessible name and the tooltip's default line.
|
|
42
|
+
*
|
|
43
|
+
* `'relative'` and `'auto'` are excluded: a relative phrase names no instant,
|
|
44
|
+
* so a zone could not change what it says.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
// =============================================================================
|
|
48
|
+
// Option bags
|
|
49
|
+
// =============================================================================
|
|
50
|
+
|
|
51
|
+
/** The long absolute style, with seconds and a zone name. */
|
|
52
|
+
const FULL_OPTIONS = {
|
|
53
|
+
year: 'numeric',
|
|
54
|
+
month: 'long',
|
|
55
|
+
day: 'numeric',
|
|
56
|
+
hour: 'numeric',
|
|
57
|
+
minute: '2-digit',
|
|
58
|
+
second: '2-digit',
|
|
59
|
+
timeZoneName: 'short'
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** The time-of-day part, shared by `time` and `date_time`. */
|
|
63
|
+
const TIME_OPTIONS = {
|
|
64
|
+
hour: 'numeric',
|
|
65
|
+
minute: '2-digit'
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The date part here is spelled out rather than taken from
|
|
70
|
+
* `SHARED_DATE_FORMAT_OPTIONS.date`. That bag is shared with DateInput, and
|
|
71
|
+
* pointing `date_time` at it would mean a change made for date-only fields
|
|
72
|
+
* silently reshaped every date-and-time reading too. The two agree today; they
|
|
73
|
+
* are not the same decision.
|
|
74
|
+
*/
|
|
75
|
+
const DATE_TIME_OPTIONS = {
|
|
76
|
+
year: 'numeric',
|
|
77
|
+
month: 'short',
|
|
78
|
+
day: 'numeric',
|
|
79
|
+
...TIME_OPTIONS
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// =============================================================================
|
|
83
|
+
// Formatting
|
|
84
|
+
// =============================================================================
|
|
85
|
+
|
|
86
|
+
function pad(n) {
|
|
87
|
+
return String(n).padStart(2, '0');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The fields a `system_*` string is assembled from. */
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Wall-clock fields for an instant: in the named zone, or — with no zone —
|
|
94
|
+
* the viewer's own, read straight off the `Date`. The zone-less branch
|
|
95
|
+
* deliberately stays on plain getters so the default rendering never gains a
|
|
96
|
+
* dependency on `Intl` zone data it did not have before.
|
|
97
|
+
*
|
|
98
|
+
* The explicit return type is load-bearing: it is what forces the two branches
|
|
99
|
+
* to keep producing the same shape.
|
|
100
|
+
*/
|
|
101
|
+
function getWallClock(date, timeZone) {
|
|
102
|
+
return timeZone === undefined ? {
|
|
103
|
+
year: date.getFullYear(),
|
|
104
|
+
month: date.getMonth() + 1,
|
|
105
|
+
day: date.getDate(),
|
|
106
|
+
hour: date.getHours(),
|
|
107
|
+
minute: date.getMinutes(),
|
|
108
|
+
second: date.getSeconds()
|
|
109
|
+
} : getTimeZoneParts(date.getTime(), timeZone);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Renders one instant in one absolute format.
|
|
114
|
+
*
|
|
115
|
+
* Pure: the same arguments always produce the same string for a given host
|
|
116
|
+
* locale (and, when no `timeZone` is given, host zone).
|
|
117
|
+
*/
|
|
118
|
+
export function formatInstant(date, format, {
|
|
119
|
+
timeZone,
|
|
120
|
+
isTimezoneShown = false
|
|
121
|
+
} = {}) {
|
|
122
|
+
const zone = timeZone === undefined ? {} : {
|
|
123
|
+
timeZone
|
|
124
|
+
};
|
|
125
|
+
const zoneName = isTimezoneShown ? {
|
|
126
|
+
timeZoneName: 'short'
|
|
127
|
+
} : {};
|
|
128
|
+
switch (format) {
|
|
129
|
+
case 'full':
|
|
130
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
131
|
+
...FULL_OPTIONS,
|
|
132
|
+
...zone
|
|
133
|
+
}).format(date);
|
|
134
|
+
case 'date':
|
|
135
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
136
|
+
...SHARED_DATE_FORMAT_OPTIONS.date,
|
|
137
|
+
...zone
|
|
138
|
+
}).format(date);
|
|
139
|
+
case 'date_long':
|
|
140
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
141
|
+
...SHARED_DATE_FORMAT_OPTIONS.date_long,
|
|
142
|
+
...zone
|
|
143
|
+
}).format(date);
|
|
144
|
+
case 'date_weekday':
|
|
145
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
146
|
+
...SHARED_DATE_FORMAT_OPTIONS.date_weekday,
|
|
147
|
+
...zone
|
|
148
|
+
}).format(date);
|
|
149
|
+
case 'date_time':
|
|
150
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
151
|
+
...DATE_TIME_OPTIONS,
|
|
152
|
+
...zoneName,
|
|
153
|
+
...zone
|
|
154
|
+
}).format(date);
|
|
155
|
+
case 'time':
|
|
156
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
157
|
+
...TIME_OPTIONS,
|
|
158
|
+
...zoneName,
|
|
159
|
+
...zone
|
|
160
|
+
}).format(date);
|
|
161
|
+
case 'system_date':
|
|
162
|
+
{
|
|
163
|
+
const w = getWallClock(date, timeZone);
|
|
164
|
+
return `${w.year}-${pad(w.month)}-${pad(w.day)}`;
|
|
165
|
+
}
|
|
166
|
+
case 'system_date_time':
|
|
167
|
+
{
|
|
168
|
+
const w = getWallClock(date, timeZone);
|
|
169
|
+
return `${w.year}-${pad(w.month)}-${pad(w.day)} ${pad(w.hour)}:${pad(w.minute)}:${pad(w.second)}`;
|
|
170
|
+
}
|
|
171
|
+
case 'system_time':
|
|
172
|
+
{
|
|
173
|
+
const w = getWallClock(date, timeZone);
|
|
174
|
+
return `${pad(w.hour)}:${pad(w.minute)}:${pad(w.second)}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Timestamp/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,YAAY,EAAC,cAAc,EAAE,eAAe,EAAC,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Timestamp/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,YAAY,EAAC,cAAc,EAAE,eAAe,EAAC,MAAM,aAAa,CAAC;AACjE,YAAY,EACV,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { InstantFormat } from './formatInstant';
|
|
2
|
+
/**
|
|
3
|
+
* Formats available to a tooltip line.
|
|
4
|
+
*
|
|
5
|
+
* Every `TimestampFormat` that names a fixed instant, plus `'full'` — the long
|
|
6
|
+
* absolute style the tooltip has always shown ("February 19, 2026 at 5:00:00 PM
|
|
7
|
+
* UTC"). `'relative'` and `'auto'` are excluded: a relative phrase ignores any
|
|
8
|
+
* zone, which would make `timezoneID` silently inert on that line.
|
|
9
|
+
*
|
|
10
|
+
* `'full'` lives only in this vocabulary, never in `TimestampFormat` — nothing
|
|
11
|
+
* asked for it as a visible display format, and keeping it out means new
|
|
12
|
+
* members added to `TimestampFormat` become valid tooltip formats for free.
|
|
13
|
+
*
|
|
14
|
+
* The public spelling of {@link InstantFormat}: consumers reading Timestamp's
|
|
15
|
+
* props should not have to know the name of its internal formatter.
|
|
16
|
+
*/
|
|
17
|
+
export type TimestampTooltipFormat = InstantFormat;
|
|
18
|
+
/** One line of the Timestamp tooltip. */
|
|
19
|
+
export interface TimestampTooltipEntry {
|
|
20
|
+
/**
|
|
21
|
+
* IANA time zone identifier, e.g. `'UTC'`, `'America/Los_Angeles'`.
|
|
22
|
+
* Omit it — or pass `'local'` — for the viewer's own zone.
|
|
23
|
+
*
|
|
24
|
+
* Prefer region identifiers. Fixed-offset abbreviations such as `'EST'` are
|
|
25
|
+
* accepted by the platform but never observe daylight saving, so they read
|
|
26
|
+
* an hour wrong for half the year — `'America/New_York'` is what people
|
|
27
|
+
* usually mean by "Eastern".
|
|
28
|
+
*
|
|
29
|
+
* An identifier the platform does not recognize falls back to the viewer's
|
|
30
|
+
* zone with a console warning rather than throwing.
|
|
31
|
+
*/
|
|
32
|
+
timezoneID?: string;
|
|
33
|
+
/**
|
|
34
|
+
* How this line renders the instant.
|
|
35
|
+
* @default 'full'
|
|
36
|
+
*/
|
|
37
|
+
format?: TimestampTooltipFormat;
|
|
38
|
+
/**
|
|
39
|
+
* Text shown beside the time, e.g. `'Local'`, `'UTC'`, `'Pacific'`.
|
|
40
|
+
* Supplied already translated; Timestamp never invents or localizes labels.
|
|
41
|
+
*/
|
|
42
|
+
label?: string;
|
|
43
|
+
}
|
|
44
|
+
/** A rendered tooltip line. */
|
|
45
|
+
export interface TimestampTooltipLine {
|
|
46
|
+
label?: string;
|
|
47
|
+
value: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Renders one tooltip line per entry, in the order given.
|
|
51
|
+
*
|
|
52
|
+
* Pure: the same `date` and `entries` always produce the same lines for a given
|
|
53
|
+
* host zone and locale.
|
|
54
|
+
*/
|
|
55
|
+
export declare function formatTooltipLines(date: Date, entries: ReadonlyArray<TimestampTooltipEntry>): ReadonlyArray<TimestampTooltipLine>;
|
|
56
|
+
//# sourceMappingURL=tooltipEntries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltipEntries.d.ts","sourceRoot":"","sources":["../../src/Timestamp/tooltipEntries.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAMnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,sBAAsB,GAAG,aAAa,CAAC;AAEnD,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,+BAA+B;AAC/B,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAqGD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,aAAa,CAAC,qBAAqB,CAAC,GAC5C,aAAa,CAAC,oBAAoB,CAAC,CAoBrC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file tooltipEntries.ts
|
|
5
|
+
* @input A Date and the consumer's tooltip entry list
|
|
6
|
+
* @output Pure formatting of one tooltip line per entry, plus the entry types
|
|
7
|
+
* @position Leaf module; owns which zone each tooltip line names and whether
|
|
8
|
+
* it needs a zone abbreviation, then defers to formatInstant to render it
|
|
9
|
+
*
|
|
10
|
+
* This module holds only the decisions a tooltip makes that the visible text
|
|
11
|
+
* does not: resolving `timezoneID` (including the `'local'` alias and the
|
|
12
|
+
* fallback for an unknown identifier), and deciding which lines need a zone
|
|
13
|
+
* abbreviation to be told apart. The formatting itself is formatInstant's,
|
|
14
|
+
* shared with the rendered text, so the two surfaces cannot drift.
|
|
15
|
+
*
|
|
16
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
17
|
+
* - /packages/core/src/Timestamp/Timestamp.tsx
|
|
18
|
+
* - /packages/core/src/Timestamp/formatInstant.ts
|
|
19
|
+
* - /packages/core/src/Timestamp/tooltipEntries.test.ts
|
|
20
|
+
* - /packages/core/src/Timestamp/Timestamp.doc.mjs
|
|
21
|
+
* - /packages/core/src/Timestamp/index.ts
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { devWarn } from "../utils/devWarning.js";
|
|
25
|
+
import { formatInstant } from "./formatInstant.js";
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// Types
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Formats available to a tooltip line.
|
|
33
|
+
*
|
|
34
|
+
* Every `TimestampFormat` that names a fixed instant, plus `'full'` — the long
|
|
35
|
+
* absolute style the tooltip has always shown ("February 19, 2026 at 5:00:00 PM
|
|
36
|
+
* UTC"). `'relative'` and `'auto'` are excluded: a relative phrase ignores any
|
|
37
|
+
* zone, which would make `timezoneID` silently inert on that line.
|
|
38
|
+
*
|
|
39
|
+
* `'full'` lives only in this vocabulary, never in `TimestampFormat` — nothing
|
|
40
|
+
* asked for it as a visible display format, and keeping it out means new
|
|
41
|
+
* members added to `TimestampFormat` become valid tooltip formats for free.
|
|
42
|
+
*
|
|
43
|
+
* The public spelling of {@link InstantFormat}: consumers reading Timestamp's
|
|
44
|
+
* props should not have to know the name of its internal formatter.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/** One line of the Timestamp tooltip. */
|
|
48
|
+
|
|
49
|
+
/** A rendered tooltip line. */
|
|
50
|
+
|
|
51
|
+
// =============================================================================
|
|
52
|
+
// Zone resolution
|
|
53
|
+
// =============================================================================
|
|
54
|
+
|
|
55
|
+
/** Spelling that means "the viewer's own zone" without naming it. */
|
|
56
|
+
const LOCAL_ZONE_ALIAS = 'local';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Zone identifiers already reported as unknown.
|
|
60
|
+
*
|
|
61
|
+
* Resolution runs once per entry on every render, so without this a single
|
|
62
|
+
* typo on a live timestamp would emit the same warning every tick, forever.
|
|
63
|
+
* One report per bad identifier is enough to act on.
|
|
64
|
+
*/
|
|
65
|
+
const warnedTimezoneIDs = new Set();
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Resolves an entry's zone to something safe to hand to `Intl`.
|
|
69
|
+
*
|
|
70
|
+
* Returns `undefined` for the viewer's own zone, which is also what `Intl`
|
|
71
|
+
* treats as "use the host zone" — so the local path never constructs a
|
|
72
|
+
* formatter with an explicit `timeZone` and cannot drift from today's output.
|
|
73
|
+
*/
|
|
74
|
+
function resolveTimezoneID(timezoneID) {
|
|
75
|
+
if (timezoneID === undefined || timezoneID.toLowerCase() === LOCAL_ZONE_ALIAS) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// An unrecognized identifier makes every Intl.DateTimeFormat constructor
|
|
80
|
+
// throw a RangeError. Rendering a timestamp must never take down the tree —
|
|
81
|
+
// degrade to the viewer's zone and say so, mirroring how an unparseable
|
|
82
|
+
// `value` is handled in Timestamp.tsx.
|
|
83
|
+
try {
|
|
84
|
+
new Intl.DateTimeFormat(undefined, {
|
|
85
|
+
timeZone: timezoneID
|
|
86
|
+
});
|
|
87
|
+
} catch {
|
|
88
|
+
if (!warnedTimezoneIDs.has(timezoneID)) {
|
|
89
|
+
warnedTimezoneIDs.add(timezoneID);
|
|
90
|
+
devWarn('Timestamp', `unknown time zone ${JSON.stringify(timezoneID)} in tooltipEntries. Falling back to the viewer's time zone.`);
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
return timezoneID;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* A stable key for "which zone did the consumer ask for", used to decide
|
|
99
|
+
* whether the tooltip needs zone abbreviations to disambiguate its lines.
|
|
100
|
+
*
|
|
101
|
+
* Deliberately keyed on the *requested* zone, not on the resolved offset: a
|
|
102
|
+
* consumer who asks for two zones gets both labelled even when the viewer
|
|
103
|
+
* happens to be sitting in one of them, so the rendering does not change shape
|
|
104
|
+
* depending on where the reader is. That also keeps this testable under any
|
|
105
|
+
* machine timezone.
|
|
106
|
+
*/
|
|
107
|
+
function zoneKey(resolved) {
|
|
108
|
+
return resolved === undefined ? LOCAL_ZONE_ALIAS : resolved.toLowerCase();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// Zone marking
|
|
113
|
+
// =============================================================================
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Whether a format should carry a zone abbreviation.
|
|
117
|
+
*
|
|
118
|
+
* `'full'` always has one (that is the style). `system_*` never does — those
|
|
119
|
+
* are machine shapes and a trailing "PST" would break anything parsing them,
|
|
120
|
+
* which is also why `isTimezoneShown` has never applied to them.
|
|
121
|
+
*
|
|
122
|
+
* The two human formats that can carry one do so when either the reader has
|
|
123
|
+
* to tell several lines apart, or the line shows a zone the consumer named
|
|
124
|
+
* explicitly. That second case matters even for a lone entry: the tooltip is
|
|
125
|
+
* the `<time>` element's `aria-describedby`, and that element's accessible
|
|
126
|
+
* name is the absolute time in the *viewer's* zone — so an unmarked foreign
|
|
127
|
+
* time is announced directly after a local one with nothing to distinguish
|
|
128
|
+
* them. A line the consumer did not steer stays unmarked, matching how the
|
|
129
|
+
* visible text reads with `isTimezoneShown` off.
|
|
130
|
+
*/
|
|
131
|
+
function shouldShowZoneName(format, hasMultipleZones, isNamedZone) {
|
|
132
|
+
if (format === 'full') {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
if (format === 'date_time' || format === 'time') {
|
|
136
|
+
return hasMultipleZones || isNamedZone;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Renders one tooltip line per entry, in the order given.
|
|
143
|
+
*
|
|
144
|
+
* Pure: the same `date` and `entries` always produce the same lines for a given
|
|
145
|
+
* host zone and locale.
|
|
146
|
+
*/
|
|
147
|
+
export function formatTooltipLines(date, entries) {
|
|
148
|
+
const resolved = entries.map(entry => resolveTimezoneID(entry.timezoneID));
|
|
149
|
+
const hasMultipleZones = new Set(resolved.map(zoneKey)).size > 1;
|
|
150
|
+
return entries.map((entry, index) => {
|
|
151
|
+
const format = entry.format ?? 'full';
|
|
152
|
+
const timeZone = resolved[index];
|
|
153
|
+
return {
|
|
154
|
+
...(entry.label === undefined ? {} : {
|
|
155
|
+
label: entry.label
|
|
156
|
+
}),
|
|
157
|
+
value: formatInstant(date, format, {
|
|
158
|
+
timeZone,
|
|
159
|
+
isTimezoneShown: shouldShowZoneName(format, hasMultipleZones, timeZone !== undefined)
|
|
160
|
+
})
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
package/dist/Token/Token.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Token.tsx
|
|
3
3
|
* @input Uses React, ReactNode, StyleXStyles
|
|
4
|
-
* @output Exports Token component, TokenProps, TokenColor types
|
|
4
|
+
* @output Exports Token component, TokenProps, TokenColor, TokenColorMap types
|
|
5
5
|
* @position Core implementation; consumed by index.ts, tested by Token.test.tsx
|
|
6
6
|
*
|
|
7
7
|
* SYNC: When modified, update these files to stay in sync:
|
|
@@ -14,9 +14,36 @@
|
|
|
14
14
|
import type { ReactNode } from 'react';
|
|
15
15
|
import type { BaseProps } from '../BaseProps';
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Extensible color map for Token.
|
|
18
|
+
*
|
|
19
|
+
* Theme packages can add custom colors via TypeScript module augmentation:
|
|
20
|
+
* @example
|
|
21
|
+
* ```
|
|
22
|
+
* declare module '@astryxdesign/core/Token' {
|
|
23
|
+
* interface TokenColorMap {
|
|
24
|
+
* brand: true;
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export interface TokenColorMap {
|
|
30
|
+
default: true;
|
|
31
|
+
red: true;
|
|
32
|
+
orange: true;
|
|
33
|
+
yellow: true;
|
|
34
|
+
green: true;
|
|
35
|
+
teal: true;
|
|
36
|
+
cyan: true;
|
|
37
|
+
blue: true;
|
|
38
|
+
purple: true;
|
|
39
|
+
pink: true;
|
|
40
|
+
gray: true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Token color type derived from TokenColorMap.
|
|
44
|
+
* Extensible via module augmentation of TokenColorMap.
|
|
18
45
|
*/
|
|
19
|
-
export type TokenColor =
|
|
46
|
+
export type TokenColor = keyof TokenColorMap;
|
|
20
47
|
export type TokenSize = 'sm' | 'md' | 'lg';
|
|
21
48
|
export interface TokenProps extends BaseProps<HTMLElement> {
|
|
22
49
|
/** Ref forwarded to the root element */
|