@astryxdesign/core 0.4.4 → 0.4.5-canary.013e728
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
- package/dist/BottomSheet/BottomSheet.d.ts +11 -2
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +4 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +65 -15
- package/dist/BottomSheet/index.d.ts +1 -1
- package/dist/BottomSheet/index.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.d.ts +57 -20
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.js +106 -30
- package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +160 -64
- package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
- package/dist/Button/Button.js +5 -5
- package/dist/Calendar/Calendar.d.ts +17 -0
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +55 -15
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
- package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarDays.js +14 -10
- package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
- package/dist/Calendar/styles.js +3 -3
- package/dist/Center/Center.d.ts +23 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +12 -6
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +2 -2
- package/dist/Chat/ChatToolCalls.js +1 -1
- package/dist/Chat/useChatDictation.d.ts +1 -1
- package/dist/Chat/useChatDictation.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts +1 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +9 -0
- package/dist/Citation/Citation.js +3 -3
- package/dist/ClickableCard/ClickableCard.js +2 -2
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +8 -3
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +17 -9
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +47 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +18 -10
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +3 -3
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +21 -3
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +12 -1
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +4 -4
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +2 -2
- package/dist/FormLayout/FormLayout.d.ts +24 -2
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +7 -2
- package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
- package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
- package/dist/FormLayout/FormLayoutContext.js +19 -4
- package/dist/FormLayout/index.d.ts +1 -1
- package/dist/FormLayout/index.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.d.ts +13 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/index.d.ts +1 -1
- package/dist/HoverCard/index.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.d.ts +17 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +78 -9
- package/dist/Item/Item.d.ts +9 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +46 -8
- package/dist/Layer/index.d.ts +4 -2
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +2 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +3 -2
- package/dist/Layer/useTouchTrigger.d.ts +113 -0
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
- package/dist/Layer/useTouchTrigger.js +241 -0
- package/dist/Layout/container.stylex.d.ts +4 -2
- package/dist/Layout/container.stylex.d.ts.map +1 -1
- package/dist/Layout/container.stylex.js +19 -11
- package/dist/Layout/index.d.ts +1 -0
- package/dist/Layout/index.d.ts.map +1 -1
- package/dist/Layout/index.js +4 -0
- package/dist/Layout/padding.stylex.d.ts +315 -12
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +389 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +2 -1
- package/dist/Link/Link.js +4 -4
- package/dist/Markdown/Markdown.d.ts +8 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +31 -3
- package/dist/Markdown/parser.d.ts +14 -2
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +50 -2
- package/dist/MobileNav/MobileNav.d.ts +1 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +24 -6
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +8 -3
- package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
- package/dist/NavItem/navItemStyles.stylex.js +2 -2
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +38 -5
- package/dist/Outline/Outline.js +2 -2
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +11 -12
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +3 -1
- package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +23 -8
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +12 -1
- package/dist/RadioList/RadioListItem.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +68 -38
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -3
- package/dist/Section/Section.d.ts +36 -1
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +12 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
- package/dist/SelectableCard/SelectableCard.js +1 -1
- package/dist/Selector/Selector.d.ts +26 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +95 -17
- package/dist/Selector/SelectorOption.d.ts +14 -1
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +6 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
- package/dist/Selector/SelectorRowLayoutContext.js +27 -0
- package/dist/Selector/types.d.ts +1 -0
- package/dist/Selector/types.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -3
- package/dist/Stack/Stack.d.ts +23 -1
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +12 -6
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +9 -0
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/TableRow.js +4 -4
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
- package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +6 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/Thumbnail/Thumbnail.js +1 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +6 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +6 -4
- package/dist/Timestamp/formatInstant.d.ts +3 -2
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +8 -8
- package/dist/Timestamp/tooltipEntries.d.ts +2 -1
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.js +5 -3
- package/dist/Token/Token.js +1 -1
- package/dist/Tooltip/Tooltip.d.ts +16 -3
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +2 -0
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +21 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +71 -13
- package/dist/TopNav/TopNavHeading.js +2 -2
- package/dist/TopNav/TopNavItem.js +2 -2
- package/dist/TopNav/TopNavMegaMenu.js +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
- package/dist/TopNav/TopNavMenu.js +2 -2
- package/dist/TreeList/TreeListItem.js +1 -1
- package/dist/astryx.css +85 -60
- package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
- package/dist/hooks/containerReveal.stylex.js +18 -18
- package/dist/hooks/scrollbarGutter.d.ts +28 -0
- package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
- package/dist/hooks/scrollbarGutter.js +103 -0
- package/dist/hooks/useResolvedRequired.d.ts +19 -0
- package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
- package/dist/hooks/useResolvedRequired.js +40 -0
- package/dist/hooks/useScrollLock.d.ts +4 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +13 -1
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +2 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/useCollator.d.ts +12 -0
- package/dist/i18n/useCollator.d.ts.map +1 -0
- package/dist/i18n/useCollator.js +40 -0
- package/dist/i18n/useLocale.d.ts +3 -0
- package/dist/i18n/useLocale.d.ts.map +1 -0
- package/dist/i18n/useLocale.js +31 -0
- package/dist/theme/defineTheme.d.ts +5 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +5 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +66 -5
- package/dist/utils/dateParser.d.ts +4 -3
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +8 -8
- package/dist/utils/plainDate.d.ts +9 -2
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +16 -4
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +8 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +6 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +3 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
- package/src/Banner/Banner.doc.mjs +2 -0
- package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
- package/src/BottomSheet/BottomSheet.test.tsx +177 -2
- package/src/BottomSheet/BottomSheet.tsx +16 -2
- package/src/BottomSheet/BottomSheetPanel.test.tsx +41 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +95 -15
- package/src/BottomSheet/index.ts +5 -1
- package/src/BottomSheet/snapOffsets.test.ts +114 -47
- package/src/BottomSheet/snapOffsets.ts +119 -33
- package/src/BottomSheet/useSheetGestures.test.ts +113 -15
- package/src/BottomSheet/useSheetGestures.ts +196 -100
- package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
- package/src/Button/Button.tsx +7 -7
- package/src/Calendar/Calendar.doc.mjs +16 -0
- package/src/Calendar/Calendar.test.tsx +137 -0
- package/src/Calendar/Calendar.tsx +80 -11
- package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
- package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
- package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
- package/src/Calendar/hooks/useCalendarDays.ts +13 -10
- package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
- package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
- package/src/Calendar/styles.ts +3 -3
- package/src/Center/Center.doc.mjs +48 -0
- package/src/Center/Center.test.tsx +158 -0
- package/src/Center/Center.tsx +50 -9
- package/src/Chat/ChatComposer.tsx +7 -4
- package/src/Chat/ChatToolCalls.tsx +1 -1
- package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
- package/src/Chat/useChatDictation.ts +1 -1
- package/src/Chat/useSpeechRecognition.ts +5 -3
- package/src/CheckboxInput/CheckboxInput.tsx +6 -0
- package/src/Citation/Citation.tsx +3 -3
- package/src/ClickableCard/ClickableCard.tsx +2 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
- package/src/ComplexSelector/ComplexSelector.tsx +8 -5
- package/src/DateInput/DateInput.test.tsx +17 -1
- package/src/DateInput/DateInput.tsx +13 -9
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
- package/src/DateRangeInput/DateRangeInput.tsx +88 -8
- package/src/DateTimeInput/DateTimeInput.tsx +23 -8
- package/src/Dialog/Dialog.test.tsx +24 -0
- package/src/Dialog/Dialog.tsx +3 -0
- package/src/Field/Field.doc.mjs +3 -0
- package/src/Field/FieldLabel.tsx +20 -4
- package/src/Field/InputClearButton.test.tsx +134 -2
- package/src/Field/InputClearButton.tsx +42 -1
- package/src/Field/inputStyles.stylex.ts +16 -12
- package/src/FileInput/FileInput.tsx +5 -4
- package/src/FormLayout/FormLayout.doc.mjs +13 -0
- package/src/FormLayout/FormLayout.test.tsx +181 -4
- package/src/FormLayout/FormLayout.tsx +33 -2
- package/src/FormLayout/FormLayoutContext.ts +22 -7
- package/src/FormLayout/index.ts +1 -1
- package/src/HoverCard/HoverCard.doc.mjs +18 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -0
- package/src/HoverCard/HoverCard.tsx +22 -2
- package/src/HoverCard/index.ts +1 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +103 -7
- package/src/Item/Item.doc.mjs +1 -0
- package/src/Item/Item.test.tsx +50 -0
- package/src/Item/Item.tsx +41 -2
- package/src/Layer/index.ts +10 -0
- package/src/Layer/useLayer.tsx +13 -2
- package/src/Layer/useTouchTrigger.test.ts +70 -0
- package/src/Layer/useTouchTrigger.ts +366 -0
- package/src/Layout/Layout.doc.mjs +18 -0
- package/src/Layout/container.stylex.ts +11 -3
- package/src/Layout/index.ts +4 -0
- package/src/Layout/overlayPaddingReset.test.tsx +222 -0
- package/src/Layout/padding.stylex.ts +192 -12
- package/src/Lightbox/Lightbox.tsx +2 -1
- package/src/Link/Link.tsx +4 -4
- package/src/Markdown/Markdown.doc.mjs +3 -0
- package/src/Markdown/Markdown.test.tsx +78 -0
- package/src/Markdown/Markdown.tsx +41 -1
- package/src/Markdown/parser.ts +60 -2
- package/src/MobileNav/MobileNav.tsx +61 -5
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
- package/src/MultiSelector/MultiSelector.test.tsx +1 -1
- package/src/MultiSelector/MultiSelector.tsx +8 -5
- package/src/NavItem/navItemStyles.stylex.ts +2 -2
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +24 -0
- package/src/NumberInput/NumberInput.test.tsx +138 -0
- package/src/NumberInput/NumberInput.tsx +44 -6
- package/src/Outline/Outline.doc.mjs +2 -0
- package/src/Outline/Outline.tsx +1 -1
- package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
- package/src/PowerSearch/PowerSearch.tsx +17 -8
- package/src/PowerSearch/PowerSearchToken.tsx +3 -0
- package/src/PowerSearch/formatFilterValue.test.ts +22 -2
- package/src/PowerSearch/formatFilterValue.ts +31 -6
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/RadioList/RadioList.test.tsx +170 -2
- package/src/RadioList/RadioList.tsx +9 -1
- package/src/RadioList/RadioListItem.tsx +83 -51
- package/src/Resizable/ResizeHandle.test.tsx +22 -0
- package/src/Resizable/ResizeHandle.tsx +9 -3
- package/src/Section/Section.doc.mjs +55 -0
- package/src/Section/Section.test.tsx +201 -4
- package/src/Section/Section.tsx +69 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
- package/src/SelectableCard/SelectableCard.tsx +1 -1
- package/src/Selector/Selector.doc.mjs +16 -2
- package/src/Selector/Selector.test.tsx +525 -1
- package/src/Selector/Selector.tsx +166 -21
- package/src/Selector/SelectorOption.doc.mjs +7 -0
- package/src/Selector/SelectorOption.tsx +21 -0
- package/src/Selector/SelectorRowLayoutContext.ts +32 -0
- package/src/Selector/types.ts +4 -4
- package/src/SideNav/SideNavHeading.tsx +2 -2
- package/src/SideNav/SideNavItem.tsx +1 -1
- package/src/Slider/Slider.tsx +11 -1
- package/src/Stack/Stack.doc.mjs +72 -0
- package/src/Stack/Stack.test.tsx +156 -0
- package/src/Stack/Stack.tsx +50 -8
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.tsx +6 -0
- package/src/TabList/TabMenu.tsx +1 -1
- package/src/Table/TableRow.tsx +4 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
- package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
- package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.tsx +3 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/Thumbnail/Thumbnail.tsx +1 -1
- package/src/TimeInput/TimeInput.tsx +3 -1
- package/src/Timestamp/Timestamp.test.tsx +27 -7
- package/src/Timestamp/Timestamp.tsx +8 -4
- package/src/Timestamp/formatInstant.ts +9 -7
- package/src/Timestamp/tooltipEntries.test.ts +11 -6
- package/src/Timestamp/tooltipEntries.ts +6 -2
- package/src/Token/Token.tsx +1 -1
- package/src/Tooltip/Tooltip.doc.mjs +18 -0
- package/src/Tooltip/Tooltip.test.tsx +254 -1
- package/src/Tooltip/Tooltip.tsx +22 -2
- package/src/Tooltip/index.ts +1 -0
- package/src/Tooltip/useTooltip.doc.mjs +2 -0
- package/src/Tooltip/useTooltip.tsx +99 -21
- package/src/TopNav/TopNavHeading.tsx +1 -1
- package/src/TopNav/TopNavItem.tsx +2 -2
- package/src/TopNav/TopNavMegaMenu.tsx +1 -1
- package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
- package/src/TopNav/TopNavMenu.tsx +2 -2
- package/src/TreeList/TreeListItem.tsx +1 -1
- package/src/hooks/containerReveal.stylex.ts +54 -18
- package/src/hooks/scrollbarGutter.test.ts +167 -0
- package/src/hooks/scrollbarGutter.ts +121 -0
- package/src/hooks/useResolvedRequired.ts +42 -0
- package/src/hooks/useScrollLock.doc.mjs +4 -4
- package/src/hooks/useScrollLock.test.ts +73 -0
- package/src/hooks/useScrollLock.ts +14 -0
- package/src/i18n/InternationalizationContext.ts +2 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
- package/src/i18n/__tests__/useCollator.test.tsx +115 -0
- package/src/i18n/__tests__/useLocale.test.tsx +52 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/useCollator.doc.mjs +84 -0
- package/src/i18n/useCollator.ts +44 -0
- package/src/i18n/useLocale.doc.mjs +70 -0
- package/src/i18n/useLocale.ts +34 -0
- package/src/i18n/useTranslator.doc.mjs +1 -1
- package/src/theme/defineTheme.test.ts +9 -3
- package/src/theme/defineTheme.ts +5 -0
- package/src/theme/derivedVarRegistry.test.ts +19 -5
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +118 -0
- package/src/theme/generateThemeRules.ts +83 -5
- package/src/utils/dateParser.test.ts +20 -0
- package/src/utils/dateParser.ts +14 -7
- package/src/utils/plainDate.test.ts +56 -0
- package/src/utils/plainDate.ts +17 -4
package/src/Table/TableRow.tsx
CHANGED
|
@@ -61,13 +61,13 @@ const hoverRowStyles = stylex.create({
|
|
|
61
61
|
row: {
|
|
62
62
|
backgroundColor: {
|
|
63
63
|
default: null,
|
|
64
|
-
':hover': {
|
|
64
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
65
65
|
'@media (hover: hover)': colorVars['--color-overlay-hover'],
|
|
66
66
|
},
|
|
67
67
|
},
|
|
68
68
|
'--table-row-overlay': {
|
|
69
69
|
default: null,
|
|
70
|
-
':hover': {
|
|
70
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
71
71
|
'@media (hover: hover)': colorVars['--color-overlay-hover'],
|
|
72
72
|
},
|
|
73
73
|
},
|
|
@@ -82,14 +82,14 @@ const stripedHoverRowStyles = stylex.create({
|
|
|
82
82
|
backgroundColor: {
|
|
83
83
|
default: null,
|
|
84
84
|
':nth-child(even)': colorVars['--color-background-muted'],
|
|
85
|
-
':hover': {
|
|
85
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
86
86
|
'@media (hover: hover)': colorVars['--color-overlay-hover'],
|
|
87
87
|
},
|
|
88
88
|
},
|
|
89
89
|
'--table-row-overlay': {
|
|
90
90
|
default: null,
|
|
91
91
|
':nth-child(even)': colorVars['--color-background-muted'],
|
|
92
|
-
':hover': {
|
|
92
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
93
93
|
'@media (hover: hover)': colorVars['--color-overlay-hover'],
|
|
94
94
|
},
|
|
95
95
|
},
|
|
@@ -216,7 +216,8 @@ const handleStyles = stylex.create({
|
|
|
216
216
|
// can't receive :hover directly.
|
|
217
217
|
'--indicator-color': {
|
|
218
218
|
default: 'transparent',
|
|
219
|
-
':hover
|
|
219
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))':
|
|
220
|
+
colorVars['--color-accent'],
|
|
220
221
|
':focus-visible': colorVars['--color-accent'],
|
|
221
222
|
},
|
|
222
223
|
'@media (pointer: coarse)': {
|
|
@@ -148,7 +148,8 @@ const styles = stylex.create({
|
|
|
148
148
|
cursor: 'pointer',
|
|
149
149
|
color: {
|
|
150
150
|
default: colorVars['--color-icon-secondary'],
|
|
151
|
-
':hover
|
|
151
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))':
|
|
152
|
+
colorVars['--color-icon-primary'],
|
|
152
153
|
},
|
|
153
154
|
},
|
|
154
155
|
chevronIcon: {
|
|
@@ -23,6 +23,7 @@ import {spacingVars, colorVars, radiusVars} from '../../../theme/tokens.stylex';
|
|
|
23
23
|
import {Icon} from '../../../Icon';
|
|
24
24
|
import {resolveContextActions} from '../../tableContextMenu';
|
|
25
25
|
import {useTranslator} from '../../../i18n';
|
|
26
|
+
import {rtlStyles} from '../../../utils';
|
|
26
27
|
import type {
|
|
27
28
|
TablePlugin,
|
|
28
29
|
TableColumn,
|
|
@@ -84,16 +85,28 @@ const expansionStyles = stylex.create({
|
|
|
84
85
|
// Match IconButton ghost hover: subtle overlay background.
|
|
85
86
|
backgroundImage: {
|
|
86
87
|
default: null,
|
|
87
|
-
':hover': {
|
|
88
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
88
89
|
'@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
|
|
89
90
|
},
|
|
90
91
|
},
|
|
91
|
-
':hover': {
|
|
92
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
92
93
|
color: colorVars['--color-icon-primary'],
|
|
93
94
|
},
|
|
94
95
|
},
|
|
96
|
+
// The RTL mirror is folded into each state's transform rather than living
|
|
97
|
+
// on a parent span, matching TreeListItem's chevron (both are `transform`,
|
|
98
|
+
// so on one element the later value would win).
|
|
95
99
|
chevronExpanded: {
|
|
96
|
-
transform:
|
|
100
|
+
transform: {
|
|
101
|
+
default: 'rotate(90deg)',
|
|
102
|
+
':is([dir="rtl"] *)': 'scaleX(-1) rotate(90deg)',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
chevronCollapsed: {
|
|
106
|
+
transform: {
|
|
107
|
+
default: 'rotate(0deg)',
|
|
108
|
+
':is([dir="rtl"] *)': 'scaleX(-1) rotate(0deg)',
|
|
109
|
+
},
|
|
97
110
|
},
|
|
98
111
|
expandedRow: {
|
|
99
112
|
backgroundColor: colorVars['--color-background-muted'],
|
|
@@ -121,7 +134,9 @@ function ExpansionChevron({
|
|
|
121
134
|
type="button"
|
|
122
135
|
{...stylex.props(
|
|
123
136
|
expansionStyles.chevronButton,
|
|
124
|
-
isExpanded
|
|
137
|
+
isExpanded
|
|
138
|
+
? expansionStyles.chevronExpanded
|
|
139
|
+
: expansionStyles.chevronCollapsed,
|
|
125
140
|
)}
|
|
126
141
|
onClick={e => {
|
|
127
142
|
e.stopPropagation();
|
|
@@ -249,6 +264,9 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
|
|
|
249
264
|
icon={isExpanded ? 'chevronDown' : 'chevronRight'}
|
|
250
265
|
size="xsm"
|
|
251
266
|
aria-hidden
|
|
267
|
+
// chevronDown needs no mirroring; chevronRight (collapsed,
|
|
268
|
+
// pointing toward the reveal direction) does.
|
|
269
|
+
xstyle={!isExpanded && rtlStyles.mirror}
|
|
252
270
|
/>
|
|
253
271
|
),
|
|
254
272
|
onSelect: () => onToggle(key),
|
|
@@ -17,6 +17,7 @@ import {useTableSortable} from './useTableSortable';
|
|
|
17
17
|
import type {TableSortState} from './useTableSortable';
|
|
18
18
|
import {useTableSortableState} from './useTableSortableState';
|
|
19
19
|
import type {UseTableSortableStateConfig} from './useTableSortableState';
|
|
20
|
+
import {InternationalizationProvider} from '../../../i18n';
|
|
20
21
|
|
|
21
22
|
// =============================================================================
|
|
22
23
|
// Test Data
|
|
@@ -119,6 +120,39 @@ describe('useTableSortableState', () => {
|
|
|
119
120
|
]);
|
|
120
121
|
});
|
|
121
122
|
|
|
123
|
+
it('re-sorts strings when the provider locale changes', () => {
|
|
124
|
+
const localeData: Employee[] = [
|
|
125
|
+
{
|
|
126
|
+
id: '1',
|
|
127
|
+
name: 'z',
|
|
128
|
+
age: 1,
|
|
129
|
+
department: 'Test',
|
|
130
|
+
salary: 1,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: '2',
|
|
134
|
+
name: 'ä',
|
|
135
|
+
age: 2,
|
|
136
|
+
department: 'Test',
|
|
137
|
+
salary: 2,
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
const table = (locale: string) => (
|
|
141
|
+
<InternationalizationProvider locale={locale}>
|
|
142
|
+
<SortableStateTable
|
|
143
|
+
data={localeData}
|
|
144
|
+
defaultSort={[{sortKey: 'name', direction: 'ascending'}]}
|
|
145
|
+
/>
|
|
146
|
+
</InternationalizationProvider>
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const {rerender} = render(table('sv-SE'));
|
|
150
|
+
expect(getNameColumnValues()).toEqual(['z', 'ä']);
|
|
151
|
+
|
|
152
|
+
rerender(table('de-DE'));
|
|
153
|
+
expect(getNameColumnValues()).toEqual(['ä', 'z']);
|
|
154
|
+
});
|
|
155
|
+
|
|
122
156
|
it('renders unsorted when no defaultSort', () => {
|
|
123
157
|
render(<SortableStateTable />);
|
|
124
158
|
|
|
@@ -18,10 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import {useState, useMemo, useCallback, useRef} from 'react';
|
|
21
|
-
import type {
|
|
22
|
-
|
|
23
|
-
UseTableSortableConfig,
|
|
24
|
-
} from './useTableSortable';
|
|
21
|
+
import type {TableSortState, UseTableSortableConfig} from './useTableSortable';
|
|
22
|
+
import {useCollator} from '../../../i18n/useCollator';
|
|
25
23
|
|
|
26
24
|
// =============================================================================
|
|
27
25
|
// Comparator Types
|
|
@@ -104,14 +102,16 @@ export interface UseTableSortableStateConfig<
|
|
|
104
102
|
* two row items. Comparators should sort ascending — the hook flips the
|
|
105
103
|
* sign for descending.
|
|
106
104
|
*
|
|
107
|
-
* For keys not in this map, the hook falls back to `
|
|
108
|
-
* `{
|
|
105
|
+
* For keys not in this map, the hook falls back to an `Intl.Collator`
|
|
106
|
+
* comparison (`{numeric: true}`) on the stringified values, bound to the
|
|
107
|
+
* active `InternationalizationProvider` locale.
|
|
109
108
|
*
|
|
110
109
|
* @example
|
|
111
110
|
* ```
|
|
111
|
+
* const collator = useCollator({numeric: true});
|
|
112
112
|
* comparators: {
|
|
113
113
|
* age: (a, b) => a.age - b.age,
|
|
114
|
-
* name: (a, b) => a.name
|
|
114
|
+
* name: (a, b) => collator.compare(a.name, b.name),
|
|
115
115
|
* }
|
|
116
116
|
* ```
|
|
117
117
|
*/
|
|
@@ -164,6 +164,7 @@ function defaultCompare<T extends Record<string, unknown>>(
|
|
|
164
164
|
a: T,
|
|
165
165
|
b: T,
|
|
166
166
|
sortKey: string,
|
|
167
|
+
collator: Intl.Collator,
|
|
167
168
|
): number {
|
|
168
169
|
const aVal = a[sortKey];
|
|
169
170
|
const bVal = b[sortKey];
|
|
@@ -171,8 +172,10 @@ function defaultCompare<T extends Record<string, unknown>>(
|
|
|
171
172
|
// null/undefined/NaN sort to the end. NaN must not reach the numeric fast
|
|
172
173
|
// path: a NaN comparator result reads as "equal" to Array.sort, which makes
|
|
173
174
|
// the comparator inconsistent and corrupts the order of the other rows.
|
|
174
|
-
const aMissing =
|
|
175
|
-
|
|
175
|
+
const aMissing =
|
|
176
|
+
aVal == null || (typeof aVal === 'number' && Number.isNaN(aVal));
|
|
177
|
+
const bMissing =
|
|
178
|
+
bVal == null || (typeof bVal === 'number' && Number.isNaN(bVal));
|
|
176
179
|
if (aMissing && bMissing) {
|
|
177
180
|
return 0;
|
|
178
181
|
}
|
|
@@ -188,14 +191,9 @@ function defaultCompare<T extends Record<string, unknown>>(
|
|
|
188
191
|
return aVal - bVal;
|
|
189
192
|
}
|
|
190
193
|
|
|
191
|
-
// string comparison with numeric collation
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
undefined,
|
|
195
|
-
{
|
|
196
|
-
numeric: true,
|
|
197
|
-
},
|
|
198
|
-
);
|
|
194
|
+
// string comparison with numeric collation, bound to the provider locale
|
|
195
|
+
// via useCollator() rather than a raw localeCompare(value, locale) call.
|
|
196
|
+
return collator.compare(toSortableString(aVal), toSortableString(bVal));
|
|
199
197
|
}
|
|
200
198
|
|
|
201
199
|
// =============================================================================
|
|
@@ -208,7 +206,8 @@ function sortData<
|
|
|
208
206
|
>(
|
|
209
207
|
data: T[],
|
|
210
208
|
sortState: TableSortState<TSortKey>,
|
|
211
|
-
comparators
|
|
209
|
+
comparators: Partial<Record<TSortKey, TableSortComparator<T>>> | undefined,
|
|
210
|
+
collator: Intl.Collator,
|
|
212
211
|
): T[] {
|
|
213
212
|
if (sortState.length === 0) {
|
|
214
213
|
return data;
|
|
@@ -218,7 +217,9 @@ function sortData<
|
|
|
218
217
|
for (const entry of sortState) {
|
|
219
218
|
const {sortKey, direction} = entry;
|
|
220
219
|
const customCmp = comparators?.[sortKey];
|
|
221
|
-
const cmp = customCmp
|
|
220
|
+
const cmp = customCmp
|
|
221
|
+
? customCmp(a, b)
|
|
222
|
+
: defaultCompare(a, b, sortKey, collator);
|
|
222
223
|
|
|
223
224
|
if (cmp !== 0) {
|
|
224
225
|
return direction === 'ascending' ? cmp : -cmp;
|
|
@@ -265,6 +266,7 @@ export function useTableSortableState<
|
|
|
265
266
|
allowUnsortedState,
|
|
266
267
|
isMultiSortEnabled,
|
|
267
268
|
} = config;
|
|
269
|
+
const collator = useCollator({numeric: true});
|
|
268
270
|
|
|
269
271
|
// Internal state (used in uncontrolled mode)
|
|
270
272
|
const [internalSort, setInternalSort] =
|
|
@@ -287,14 +289,15 @@ export function useTableSortableState<
|
|
|
287
289
|
|
|
288
290
|
// Sorted data — memoized on sort state + data identity
|
|
289
291
|
const sortedData = useMemo(
|
|
290
|
-
() => sortData(data, sort, comparatorsRef.current),
|
|
291
|
-
[data, sort],
|
|
292
|
+
() => sortData(data, sort, comparatorsRef.current, collator),
|
|
293
|
+
[data, sort, collator],
|
|
292
294
|
);
|
|
293
295
|
|
|
294
296
|
// applySort — lets consumers sort arbitrary data with the current state
|
|
295
297
|
const applySort = useCallback(
|
|
296
|
-
(inputData: T[]): T[] =>
|
|
297
|
-
|
|
298
|
+
(inputData: T[]): T[] =>
|
|
299
|
+
sortData(inputData, sort, comparatorsRef.current, collator),
|
|
300
|
+
[sort, collator],
|
|
298
301
|
);
|
|
299
302
|
|
|
300
303
|
// Config ready for useTableSortable
|
|
@@ -251,11 +251,11 @@ const treeStyles = stylex.create({
|
|
|
251
251
|
// Match IconButton ghost hover: subtle overlay background
|
|
252
252
|
backgroundImage: {
|
|
253
253
|
default: null,
|
|
254
|
-
':hover': {
|
|
254
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
255
255
|
'@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
|
|
256
256
|
},
|
|
257
257
|
},
|
|
258
|
-
':hover': {
|
|
258
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
259
259
|
color: colorVars['--color-icon-primary'],
|
|
260
260
|
},
|
|
261
261
|
},
|
|
@@ -105,7 +105,7 @@ export const docs = {
|
|
|
105
105
|
name: 'maxLength',
|
|
106
106
|
type: 'number',
|
|
107
107
|
description:
|
|
108
|
-
'Maximum number of characters allowed, counted as user-perceived characters
|
|
108
|
+
'Maximum number of characters allowed, counted as user-perceived characters: an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.',
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
111
|
name: 'status',
|
|
@@ -52,6 +52,7 @@ import type {SizeValue} from '../utils/types';
|
|
|
52
52
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
53
53
|
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
54
54
|
import {useAnnounce} from '../hooks/useAnnounce';
|
|
55
|
+
import {useResolvedRequired} from '../hooks/useResolvedRequired';
|
|
55
56
|
import {useSize} from '../SizeContext/SizeContext';
|
|
56
57
|
import {themeProps} from '../utils/themeProps';
|
|
57
58
|
import {characterCount} from '../utils/characters';
|
|
@@ -394,6 +395,7 @@ export function TextArea({
|
|
|
394
395
|
}: TextAreaProps) {
|
|
395
396
|
const size = useSize(sizeProp, 'md');
|
|
396
397
|
const t = useTranslator();
|
|
398
|
+
const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
|
|
397
399
|
const announce = useAnnounce();
|
|
398
400
|
const id = useId();
|
|
399
401
|
const descriptionID = useId();
|
|
@@ -598,7 +600,7 @@ export function TextArea({
|
|
|
598
600
|
autoFocus={hasAutoFocus}
|
|
599
601
|
data-autofocus={hasAutoFocus || undefined}
|
|
600
602
|
aria-describedby={ariaDescribedBy}
|
|
601
|
-
aria-required={
|
|
603
|
+
aria-required={isEffectivelyRequired ? 'true' : undefined}
|
|
602
604
|
aria-invalid={
|
|
603
605
|
status?.type === 'error' ||
|
|
604
606
|
(maxLength != null && valueLength > maxLength)
|
|
@@ -101,6 +101,7 @@ import {mergeProps, mergeRefs} from '../utils';
|
|
|
101
101
|
import {useSize} from '../SizeContext/SizeContext';
|
|
102
102
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
103
103
|
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
104
|
+
import {useResolvedRequired} from '../hooks/useResolvedRequired';
|
|
104
105
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
105
106
|
import type {BaseProps} from '../BaseProps';
|
|
106
107
|
import type {SizeValue} from '../utils/types';
|
|
@@ -301,6 +302,7 @@ export function TextInput({
|
|
|
301
302
|
...rest
|
|
302
303
|
}: TextInputProps) {
|
|
303
304
|
const t = useTranslator();
|
|
305
|
+
const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
|
|
304
306
|
const size = useSize(sizeProp, 'md');
|
|
305
307
|
|
|
306
308
|
const id = useId();
|
|
@@ -445,7 +447,7 @@ export function TextInput({
|
|
|
445
447
|
autoFocus={hasAutoFocus}
|
|
446
448
|
data-autofocus={hasAutoFocus || undefined}
|
|
447
449
|
aria-describedby={ariaDescribedBy}
|
|
448
|
-
aria-required={
|
|
450
|
+
aria-required={isEffectivelyRequired ? 'true' : undefined}
|
|
449
451
|
aria-invalid={status?.type === 'error' ? 'true' : undefined}
|
|
450
452
|
aria-busy={isBusy || undefined}
|
|
451
453
|
aria-labelledby={ariaLabelledBy}
|
|
@@ -183,7 +183,7 @@ const styles = stylex.create({
|
|
|
183
183
|
},
|
|
184
184
|
hoverOnPointer: {
|
|
185
185
|
'@media (hover: hover)': {
|
|
186
|
-
':hover::after': {
|
|
186
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))::after': {
|
|
187
187
|
backgroundColor: colorVars['--color-overlay-hover'],
|
|
188
188
|
},
|
|
189
189
|
},
|
|
@@ -67,6 +67,7 @@ import {useSize} from '../SizeContext/SizeContext';
|
|
|
67
67
|
import {useAnnounce} from '../hooks/useAnnounce';
|
|
68
68
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
69
69
|
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
70
|
+
import {useResolvedRequired} from '../hooks/useResolvedRequired';
|
|
70
71
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
71
72
|
import {groupStyles} from '../InputGroup/groupStyles';
|
|
72
73
|
import {useTooltip} from '../Tooltip';
|
|
@@ -347,6 +348,7 @@ export function TimeInput({
|
|
|
347
348
|
ref,
|
|
348
349
|
}: TimeInputProps) {
|
|
349
350
|
const t = useTranslator();
|
|
351
|
+
const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
|
|
350
352
|
const placeholder =
|
|
351
353
|
placeholderFromProps ?? t('@astryx.timeInput.placeholder');
|
|
352
354
|
const size = useSize(sizeProp, 'md');
|
|
@@ -664,7 +666,7 @@ export function TimeInput({
|
|
|
664
666
|
autoFocus={hasAutoFocus}
|
|
665
667
|
data-autofocus={hasAutoFocus || undefined}
|
|
666
668
|
aria-describedby={ariaDescribedBy}
|
|
667
|
-
aria-required={
|
|
669
|
+
aria-required={isEffectivelyRequired ? 'true' : undefined}
|
|
668
670
|
aria-invalid={
|
|
669
671
|
status?.type === 'error' || !isInputValid ? 'true' : undefined
|
|
670
672
|
}
|
|
@@ -257,6 +257,26 @@ describe('Timestamp', () => {
|
|
|
257
257
|
|
|
258
258
|
// --- Standard display formats ---
|
|
259
259
|
|
|
260
|
+
it('updates absolute output when the provider locale changes', () => {
|
|
261
|
+
const value = '2026-01-25T12:00:00Z';
|
|
262
|
+
const timestamp = (locale: string) => (
|
|
263
|
+
<InternationalizationProvider locale={locale}>
|
|
264
|
+
<Timestamp
|
|
265
|
+
value={value}
|
|
266
|
+
format="date_long"
|
|
267
|
+
hasTooltip={false}
|
|
268
|
+
data-testid="ts"
|
|
269
|
+
/>
|
|
270
|
+
</InternationalizationProvider>
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const {rerender} = render(timestamp('en-US'));
|
|
274
|
+
expect(screen.getByTestId('ts')).toHaveTextContent('January 25, 2026');
|
|
275
|
+
|
|
276
|
+
rerender(timestamp('de-DE'));
|
|
277
|
+
expect(screen.getByTestId('ts')).toHaveTextContent('25. Januar 2026');
|
|
278
|
+
});
|
|
279
|
+
|
|
260
280
|
it('renders date format', () => {
|
|
261
281
|
render(
|
|
262
282
|
<Timestamp value="2026-02-19T17:00:00Z" format="date" data-testid="ts" />,
|
|
@@ -441,7 +461,7 @@ describe('Timestamp', () => {
|
|
|
441
461
|
);
|
|
442
462
|
|
|
443
463
|
const longTz =
|
|
444
|
-
new Intl.DateTimeFormat(
|
|
464
|
+
new Intl.DateTimeFormat('en', {timeZoneName: 'long'})
|
|
445
465
|
.formatToParts(oneHourAgo)
|
|
446
466
|
.find(p => p.type === 'timeZoneName')?.value ?? '';
|
|
447
467
|
expect(longTz).not.toBe('');
|
|
@@ -462,7 +482,7 @@ describe('Timestamp', () => {
|
|
|
462
482
|
);
|
|
463
483
|
|
|
464
484
|
const tzPart = (form: 'short' | 'long') =>
|
|
465
|
-
new Intl.DateTimeFormat(
|
|
485
|
+
new Intl.DateTimeFormat('en', {timeZoneName: form})
|
|
466
486
|
.formatToParts(date)
|
|
467
487
|
.find(p => p.type === 'timeZoneName')?.value ?? '';
|
|
468
488
|
const text = screen.getByTestId('ts').textContent ?? '';
|
|
@@ -673,7 +693,7 @@ describe('Timestamp', () => {
|
|
|
673
693
|
// no-break spaces that jest-dom's matcher normalization would break on.
|
|
674
694
|
const normalize = (s: string) => s.replace(/\s+/g, ' ');
|
|
675
695
|
const datetime = new Date(el.getAttribute('datetime') ?? '');
|
|
676
|
-
const expected = new Intl.DateTimeFormat(
|
|
696
|
+
const expected = new Intl.DateTimeFormat('en', {
|
|
677
697
|
year: 'numeric',
|
|
678
698
|
month: 'long',
|
|
679
699
|
day: 'numeric',
|
|
@@ -789,7 +809,7 @@ describe('Timestamp', () => {
|
|
|
789
809
|
const datetime = new Date(
|
|
790
810
|
screen.getByTestId('ts').getAttribute('datetime') ?? '',
|
|
791
811
|
);
|
|
792
|
-
const expected = new Intl.DateTimeFormat(
|
|
812
|
+
const expected = new Intl.DateTimeFormat('en', {
|
|
793
813
|
year: 'numeric',
|
|
794
814
|
month: 'long',
|
|
795
815
|
day: 'numeric',
|
|
@@ -1252,7 +1272,7 @@ describe('Timestamp', () => {
|
|
|
1252
1272
|
data-testid="ts"
|
|
1253
1273
|
/>,
|
|
1254
1274
|
);
|
|
1255
|
-
const [line] = formatTooltipLines(new Date(VALUE), [{format}]);
|
|
1275
|
+
const [line] = formatTooltipLines(new Date(VALUE), [{format}], 'en');
|
|
1256
1276
|
expect(line.value).toBe(screen.getByTestId('ts').textContent);
|
|
1257
1277
|
},
|
|
1258
1278
|
);
|
|
@@ -1275,10 +1295,10 @@ describe('Timestamp', () => {
|
|
|
1275
1295
|
);
|
|
1276
1296
|
const date = new Date(VALUE);
|
|
1277
1297
|
const tzPart = (form: 'short' | 'long') =>
|
|
1278
|
-
new Intl.DateTimeFormat(
|
|
1298
|
+
new Intl.DateTimeFormat('en', {timeZoneName: form})
|
|
1279
1299
|
.formatToParts(date)
|
|
1280
1300
|
.find(p => p.type === 'timeZoneName')?.value ?? '';
|
|
1281
|
-
const [line] = formatTooltipLines(date, [{format: 'full'}]);
|
|
1301
|
+
const [line] = formatTooltipLines(date, [{format: 'full'}], 'en');
|
|
1282
1302
|
expect(screen.getByTestId('ts').getAttribute('aria-label')).toBe(
|
|
1283
1303
|
line.value.replace(tzPart('short'), tzPart('long')),
|
|
1284
1304
|
);
|
|
@@ -23,6 +23,7 @@ import type {TextType, TextSize, TextColor, TextWeight} from '../theme/types';
|
|
|
23
23
|
import {mergeProps, mergeRefs} from '../utils';
|
|
24
24
|
import {useDevWarning} from '../hooks/useDevWarning';
|
|
25
25
|
import {useTranslator} from '../i18n';
|
|
26
|
+
import {useLocale} from '../i18n/useLocale';
|
|
26
27
|
import type {BaseProps} from '../BaseProps';
|
|
27
28
|
import {themeProps} from '../utils/themeProps';
|
|
28
29
|
import {formatInstant} from './formatInstant';
|
|
@@ -419,6 +420,7 @@ export function Timestamp({
|
|
|
419
420
|
'data-testid': testId,
|
|
420
421
|
}: TimestampProps) {
|
|
421
422
|
const t = useTranslator();
|
|
423
|
+
const locale = useLocale();
|
|
422
424
|
const timeRef = useRef<HTMLTimeElement>(null);
|
|
423
425
|
const [now, setNow] = useState(() => new Date());
|
|
424
426
|
|
|
@@ -448,16 +450,18 @@ export function Timestamp({
|
|
|
448
450
|
: effectiveFormat === 'relative_short'
|
|
449
451
|
? getRelativeTimeShortString(date, now)
|
|
450
452
|
: isAbsoluteFormat(effectiveFormat)
|
|
451
|
-
? formatInstant(date, effectiveFormat, {isTimezoneShown})
|
|
453
|
+
? formatInstant(date, effectiveFormat, locale, {isTimezoneShown})
|
|
452
454
|
: '';
|
|
453
455
|
|
|
454
456
|
// Full absolute text for the tooltip (visible — keeps the compact timezone
|
|
455
457
|
// abbreviation) and for the AT-facing aria-label, which spells the timezone
|
|
456
458
|
// out in full: abbreviations like "PST" or "GMT+2" are unexpanded
|
|
457
459
|
// abbreviations to a screen-reader user (WCAG 3.1.4).
|
|
458
|
-
const fullAbsoluteText = isValidDate
|
|
460
|
+
const fullAbsoluteText = isValidDate
|
|
461
|
+
? formatInstant(date, 'full', locale)
|
|
462
|
+
: '';
|
|
459
463
|
const ariaLabelText = isValidDate
|
|
460
|
-
? formatInstant(date, 'full', {timeZoneNameStyle: 'long'})
|
|
464
|
+
? formatInstant(date, 'full', locale, {timeZoneNameStyle: 'long'})
|
|
461
465
|
: '';
|
|
462
466
|
|
|
463
467
|
// Live updates
|
|
@@ -506,7 +510,7 @@ export function Timestamp({
|
|
|
506
510
|
const lines: ReadonlyArray<TimestampTooltipLine> =
|
|
507
511
|
entries === undefined
|
|
508
512
|
? [{value: fullAbsoluteText, isCopyable: true}]
|
|
509
|
-
: formatTooltipLines(date, entries);
|
|
513
|
+
: formatTooltipLines(date, entries, locale);
|
|
510
514
|
|
|
511
515
|
const timestampProps = mergeProps(
|
|
512
516
|
themeProps('timestamp', {format: effectiveFormat}),
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
import {SHARED_DATE_FORMAT_OPTIONS, getTimeZoneParts} from '../utils/plainDate';
|
|
33
|
+
import type {Locale} from '../i18n/types';
|
|
33
34
|
import type {TimestampFormat} from './Timestamp';
|
|
34
35
|
|
|
35
36
|
// =============================================================================
|
|
@@ -159,12 +160,13 @@ function getWallClock(date: Date, timeZone: string | undefined): WallClock {
|
|
|
159
160
|
/**
|
|
160
161
|
* Renders one instant in one absolute format.
|
|
161
162
|
*
|
|
162
|
-
* Pure: the same arguments always produce the same string for
|
|
163
|
+
* Pure: the same arguments always produce the same string for the requested
|
|
163
164
|
* locale (and, when no `timeZone` is given, host zone).
|
|
164
165
|
*/
|
|
165
166
|
export function formatInstant(
|
|
166
167
|
date: Date,
|
|
167
168
|
format: InstantFormat,
|
|
169
|
+
locale: Locale,
|
|
168
170
|
{
|
|
169
171
|
timeZone,
|
|
170
172
|
isTimezoneShown = false,
|
|
@@ -176,39 +178,39 @@ export function formatInstant(
|
|
|
176
178
|
|
|
177
179
|
switch (format) {
|
|
178
180
|
case 'full':
|
|
179
|
-
return new Intl.DateTimeFormat(
|
|
181
|
+
return new Intl.DateTimeFormat(locale, {
|
|
180
182
|
...FULL_OPTIONS,
|
|
181
183
|
timeZoneName: timeZoneNameStyle,
|
|
182
184
|
...zone,
|
|
183
185
|
}).format(date);
|
|
184
186
|
|
|
185
187
|
case 'date':
|
|
186
|
-
return new Intl.DateTimeFormat(
|
|
188
|
+
return new Intl.DateTimeFormat(locale, {
|
|
187
189
|
...SHARED_DATE_FORMAT_OPTIONS.date,
|
|
188
190
|
...zone,
|
|
189
191
|
}).format(date);
|
|
190
192
|
|
|
191
193
|
case 'date_long':
|
|
192
|
-
return new Intl.DateTimeFormat(
|
|
194
|
+
return new Intl.DateTimeFormat(locale, {
|
|
193
195
|
...SHARED_DATE_FORMAT_OPTIONS.date_long,
|
|
194
196
|
...zone,
|
|
195
197
|
}).format(date);
|
|
196
198
|
|
|
197
199
|
case 'date_weekday':
|
|
198
|
-
return new Intl.DateTimeFormat(
|
|
200
|
+
return new Intl.DateTimeFormat(locale, {
|
|
199
201
|
...SHARED_DATE_FORMAT_OPTIONS.date_weekday,
|
|
200
202
|
...zone,
|
|
201
203
|
}).format(date);
|
|
202
204
|
|
|
203
205
|
case 'date_time':
|
|
204
|
-
return new Intl.DateTimeFormat(
|
|
206
|
+
return new Intl.DateTimeFormat(locale, {
|
|
205
207
|
...DATE_TIME_OPTIONS,
|
|
206
208
|
...zoneName,
|
|
207
209
|
...zone,
|
|
208
210
|
}).format(date);
|
|
209
211
|
|
|
210
212
|
case 'time':
|
|
211
|
-
return new Intl.DateTimeFormat(
|
|
213
|
+
return new Intl.DateTimeFormat(locale, {
|
|
212
214
|
...TIME_OPTIONS,
|
|
213
215
|
...zoneName,
|
|
214
216
|
...zone,
|
|
@@ -16,12 +16,17 @@
|
|
|
16
16
|
|
|
17
17
|
import {describe, it, expect, vi} from 'vitest';
|
|
18
18
|
import {SHARED_DATE_FORMAT_OPTIONS} from '../utils/plainDate';
|
|
19
|
-
import {formatTooltipLines} from './tooltipEntries';
|
|
19
|
+
import {formatTooltipLines as formatTooltipLinesForLocale} from './tooltipEntries';
|
|
20
|
+
|
|
21
|
+
const formatTooltipLines = (
|
|
22
|
+
date: Parameters<typeof formatTooltipLinesForLocale>[0],
|
|
23
|
+
entries: Parameters<typeof formatTooltipLinesForLocale>[1],
|
|
24
|
+
) => formatTooltipLinesForLocale(date, entries, 'en-US');
|
|
20
25
|
|
|
21
26
|
/** 2026-02-19T17:00:00Z — chosen so several zones land on different dates. */
|
|
22
27
|
const INSTANT = new Date('2026-02-19T17:00:00Z');
|
|
23
28
|
|
|
24
|
-
const LOCAL_ZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
29
|
+
const LOCAL_ZONE = Intl.DateTimeFormat('en-US').resolvedOptions().timeZone;
|
|
25
30
|
|
|
26
31
|
describe('formatTooltipLines', () => {
|
|
27
32
|
// --- Explicit zones: exact, locale-free, TZ-agnostic ---
|
|
@@ -86,7 +91,7 @@ describe('formatTooltipLines', () => {
|
|
|
86
91
|
for (const timezoneID of ['UTC', 'Asia/Tokyo']) {
|
|
87
92
|
const [line] = formatTooltipLines(INSTANT, [{timezoneID, format}]);
|
|
88
93
|
expect(line.value).toBe(
|
|
89
|
-
new Intl.DateTimeFormat(
|
|
94
|
+
new Intl.DateTimeFormat('en-US', {
|
|
90
95
|
...SHARED_DATE_FORMAT_OPTIONS[format],
|
|
91
96
|
timeZone: timezoneID,
|
|
92
97
|
}).format(INSTANT),
|
|
@@ -208,7 +213,7 @@ describe('formatTooltipLines', () => {
|
|
|
208
213
|
{format: 'date_time'},
|
|
209
214
|
{format: 'system_date_time'},
|
|
210
215
|
]);
|
|
211
|
-
const localName = new Intl.DateTimeFormat(
|
|
216
|
+
const localName = new Intl.DateTimeFormat('en-US', {
|
|
212
217
|
timeZoneName: 'short',
|
|
213
218
|
})
|
|
214
219
|
.formatToParts(INSTANT)
|
|
@@ -230,7 +235,7 @@ describe('formatTooltipLines', () => {
|
|
|
230
235
|
// aria-describedby, and that element's accessible name is the LOCAL
|
|
231
236
|
// absolute time. A lone foreign-zone line with no marker is therefore
|
|
232
237
|
// announced right after a local time, with nothing to say it is not one.
|
|
233
|
-
const zoneName = new Intl.DateTimeFormat(
|
|
238
|
+
const zoneName = new Intl.DateTimeFormat('en-US', {
|
|
234
239
|
timeZone: 'Asia/Tokyo',
|
|
235
240
|
timeZoneName: 'short',
|
|
236
241
|
})
|
|
@@ -248,7 +253,7 @@ describe('formatTooltipLines', () => {
|
|
|
248
253
|
// The consumer never named a zone, so there is nothing to disambiguate
|
|
249
254
|
// against — this must stay as bare as the visible text is by default.
|
|
250
255
|
const [line] = formatTooltipLines(INSTANT, [{format: 'date_time'}]);
|
|
251
|
-
const localName = new Intl.DateTimeFormat(
|
|
256
|
+
const localName = new Intl.DateTimeFormat('en-US', {
|
|
252
257
|
timeZoneName: 'short',
|
|
253
258
|
})
|
|
254
259
|
.formatToParts(INSTANT)
|