@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
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
import {devWarn} from '../utils/devWarning';
|
|
25
25
|
import {formatInstant} from './formatInstant';
|
|
26
26
|
import type {InstantFormat} from './formatInstant';
|
|
27
|
+
import type {Locale} from '../i18n/types';
|
|
27
28
|
|
|
28
29
|
// =============================================================================
|
|
29
30
|
// Types
|
|
@@ -130,7 +131,9 @@ function resolveTimezoneID(timezoneID: string | undefined): string | undefined {
|
|
|
130
131
|
// degrade to the viewer's zone and say so, mirroring how an unparseable
|
|
131
132
|
// `value` is handled in Timestamp.tsx.
|
|
132
133
|
try {
|
|
133
|
-
|
|
134
|
+
// Locale does not affect time-zone identifier validity; pin one so this
|
|
135
|
+
// validation path stays explicit and deterministic.
|
|
136
|
+
new Intl.DateTimeFormat('en-US', {timeZone: timezoneID});
|
|
134
137
|
} catch {
|
|
135
138
|
if (!warnedTimezoneIDs.has(timezoneID)) {
|
|
136
139
|
warnedTimezoneIDs.add(timezoneID);
|
|
@@ -202,6 +205,7 @@ function shouldShowZoneName(
|
|
|
202
205
|
export function formatTooltipLines(
|
|
203
206
|
date: Date,
|
|
204
207
|
entries: ReadonlyArray<TimestampTooltipEntry>,
|
|
208
|
+
locale: Locale,
|
|
205
209
|
): ReadonlyArray<TimestampTooltipLine> {
|
|
206
210
|
const resolved = entries.map(entry => resolveTimezoneID(entry.timezoneID));
|
|
207
211
|
const hasMultipleZones = new Set(resolved.map(zoneKey)).size > 1;
|
|
@@ -213,7 +217,7 @@ export function formatTooltipLines(
|
|
|
213
217
|
return {
|
|
214
218
|
...(entry.label === undefined ? {} : {label: entry.label}),
|
|
215
219
|
isCopyable: entry.isCopyable ?? false,
|
|
216
|
-
value: formatInstant(date, format, {
|
|
220
|
+
value: formatInstant(date, format, locale, {
|
|
217
221
|
timeZone,
|
|
218
222
|
isTimezoneShown: shouldShowZoneName(
|
|
219
223
|
format,
|
package/src/Token/Token.tsx
CHANGED
|
@@ -142,7 +142,7 @@ const styles = stylex.create({
|
|
|
142
142
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
143
143
|
backgroundImage: {
|
|
144
144
|
default: null,
|
|
145
|
-
':hover': {
|
|
145
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
146
146
|
'@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
|
|
147
147
|
},
|
|
148
148
|
':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
|
|
@@ -66,6 +66,13 @@ export const docs = {
|
|
|
66
66
|
description: 'Controls when focus events trigger the tooltip.',
|
|
67
67
|
default: "'auto'",
|
|
68
68
|
},
|
|
69
|
+
{
|
|
70
|
+
name: 'touchTrigger',
|
|
71
|
+
type: "'auto' | 'tap' | 'none'",
|
|
72
|
+
description:
|
|
73
|
+
'What a tap does where there is no hover. auto opens on tap unless the trigger performs an action of its own (a button, link, or form control), whose tap belongs to the control. tap always opens; use it for an info icon rendered as a button, whose only job is to reveal the tooltip. none never opens on touch.',
|
|
74
|
+
default: "'auto'",
|
|
75
|
+
},
|
|
69
76
|
{
|
|
70
77
|
name: 'isEnabled',
|
|
71
78
|
type: 'boolean',
|
|
@@ -103,6 +110,7 @@ export const docs = {
|
|
|
103
110
|
bestPractices: [
|
|
104
111
|
{guidance: true, description: 'Keep tooltip content concise: aim for under 140 characters of plain text.'},
|
|
105
112
|
{guidance: true, description: 'Add a tooltip to icon-only buttons and controls that lack a visible label.'},
|
|
113
|
+
{guidance: true, description: 'Set touchTrigger to tap when the trigger is a button whose only job is revealing the tooltip, such as an info icon: touch has no hover, and auto keeps the tap for triggers that perform an action.'},
|
|
106
114
|
{guidance: false, description: 'Place interactive elements like links or buttons inside a tooltip; use HoverCard or Popover instead.'},
|
|
107
115
|
{guidance: false, description: 'Use tooltips for essential information that users must see to complete a task.'},
|
|
108
116
|
],
|
|
@@ -165,6 +173,13 @@ export const docsZh = {
|
|
|
165
173
|
description: '控制聚焦事件何时触发工具提示。',
|
|
166
174
|
default: "'auto'",
|
|
167
175
|
},
|
|
176
|
+
{
|
|
177
|
+
name: 'touchTrigger',
|
|
178
|
+
type: "'auto' | 'tap' | 'none'",
|
|
179
|
+
description:
|
|
180
|
+
'在没有悬停的触摸设备上,轻点的行为。auto:轻点即打开,除非触发元素本身会执行操作(按钮、链接、表单控件),此时轻点归该控件所有。tap:始终轻点打开——适用于以按钮形式呈现、唯一作用就是显示工具提示的信息图标。none:触摸永不打开。',
|
|
181
|
+
default: "'auto'",
|
|
182
|
+
},
|
|
168
183
|
{
|
|
169
184
|
name: 'isEnabled',
|
|
170
185
|
type: 'boolean',
|
|
@@ -202,6 +217,7 @@ export const docsZh = {
|
|
|
202
217
|
bestPractices: [
|
|
203
218
|
{guidance: true, description: 'Keep tooltip content concise: aim for under 140 characters of plain text.'},
|
|
204
219
|
{guidance: true, description: 'Add a tooltip to icon-only buttons and controls that lack a visible label.'},
|
|
220
|
+
{guidance: true, description: 'Set touchTrigger to tap when the trigger is a button whose only job is revealing the tooltip, such as an info icon: touch has no hover, and auto keeps the tap for triggers that perform an action.'},
|
|
205
221
|
{guidance: false, description: 'Place interactive elements like links or buttons inside a tooltip; use HoverCard or Popover instead.'},
|
|
206
222
|
{guidance: false, description: 'Use tooltips for essential information that users must see to complete a task.'},
|
|
207
223
|
],
|
|
@@ -217,6 +233,7 @@ export const docsDense = {
|
|
|
217
233
|
bestPractices: [
|
|
218
234
|
{guidance: true, description: 'Keep tooltip content concise: aim for under 140 characters of plain text.'},
|
|
219
235
|
{guidance: true, description: 'Add a tooltip to icon-only buttons and controls that lack a visible label.'},
|
|
236
|
+
{guidance: true, description: 'Set touchTrigger to tap when the trigger is a button whose only job is revealing the tooltip, such as an info icon: touch has no hover, and auto keeps the tap for triggers that perform an action.'},
|
|
220
237
|
{guidance: false, description: 'Place interactive elements like links or buttons inside a tooltip; use HoverCard or Popover instead.'},
|
|
221
238
|
{guidance: false, description: 'Use tooltips for essential information that users must see to complete a task.'},
|
|
222
239
|
],
|
|
@@ -235,6 +252,7 @@ export const docsDense = {
|
|
|
235
252
|
delay: 'Show delay in ms.',
|
|
236
253
|
hideDelay: 'Hide delay in ms.',
|
|
237
254
|
focusTrigger: 'Controls when focus events trigger tooltip.',
|
|
255
|
+
touchTrigger: 'Tap behavior where there is no hover. auto = tap opens unless the trigger acts (button/link/control); tap = always opens (info icon rendered as a button); none = never on touch.',
|
|
238
256
|
isEnabled: 'Enables/disables tooltip triggers.',
|
|
239
257
|
onOpenChange: 'Callback when visibility changes; true=shown, false=hidden.',
|
|
240
258
|
hasHoverIndication: 'Dashed underline on trigger element.',
|
|
@@ -9,9 +9,18 @@
|
|
|
9
9
|
* SYNC: When Tooltip.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
describe,
|
|
14
|
+
it,
|
|
15
|
+
expect,
|
|
16
|
+
vi,
|
|
17
|
+
beforeAll,
|
|
18
|
+
beforeEach,
|
|
19
|
+
afterAll,
|
|
20
|
+
} from 'vitest';
|
|
13
21
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
22
|
import {Tooltip} from './Tooltip';
|
|
23
|
+
import {__resetInteractionModalityForTest} from '../utils/interactionModality';
|
|
15
24
|
|
|
16
25
|
// Store original matches to restore later
|
|
17
26
|
const originalMatches = HTMLElement.prototype.matches;
|
|
@@ -267,4 +276,248 @@ describe('Tooltip', () => {
|
|
|
267
276
|
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
268
277
|
});
|
|
269
278
|
});
|
|
279
|
+
describe('touch', () => {
|
|
280
|
+
// The modality is document-global; a tap in one case must not decide the
|
|
281
|
+
// next one's answer.
|
|
282
|
+
beforeEach(() => {
|
|
283
|
+
__resetInteractionModalityForTest();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
/** A tap: the pointer sequence a finger produces before hover is faked. */
|
|
287
|
+
const tap = (element: HTMLElement) => {
|
|
288
|
+
// A finger's arrival fires pointerenter too, and that is the path a pen
|
|
289
|
+
// must not take — cover it here rather than starting at pointerdown.
|
|
290
|
+
fireEvent.pointerEnter(element, {pointerType: 'touch'});
|
|
291
|
+
fireEvent.pointerDown(element, {pointerType: 'touch'});
|
|
292
|
+
fireEvent.pointerUp(element, {pointerType: 'touch'});
|
|
293
|
+
// Touch synthesizes hover after the press; the tooltip must not act on it.
|
|
294
|
+
fireEvent.mouseEnter(element);
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
it('opens on a tap when the trigger performs no action', async () => {
|
|
298
|
+
const onOpenChange = vi.fn();
|
|
299
|
+
render(
|
|
300
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={200}>
|
|
301
|
+
Abbreviation
|
|
302
|
+
</Tooltip>,
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
tap(screen.getByText('Abbreviation'));
|
|
306
|
+
|
|
307
|
+
// Immediately: a tap is a decision, not hover intent, so no delay applies.
|
|
308
|
+
await waitFor(() => {
|
|
309
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('stays shut on a tap when the trigger performs an action', async () => {
|
|
314
|
+
const onOpenChange = vi.fn();
|
|
315
|
+
render(
|
|
316
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
317
|
+
<button type="button">Save</button>
|
|
318
|
+
</Tooltip>,
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
tap(screen.getByRole('button', {name: 'Save'}));
|
|
322
|
+
|
|
323
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
324
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(true);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('opens on a tap of an action trigger when touchTrigger is "tap"', async () => {
|
|
328
|
+
const onOpenChange = vi.fn();
|
|
329
|
+
render(
|
|
330
|
+
<Tooltip
|
|
331
|
+
content="What this metric means"
|
|
332
|
+
onOpenChange={onOpenChange}
|
|
333
|
+
touchTrigger="tap"
|
|
334
|
+
delay={0}>
|
|
335
|
+
<button type="button">Info</button>
|
|
336
|
+
</Tooltip>,
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
tap(screen.getByRole('button', {name: 'Info'}));
|
|
340
|
+
|
|
341
|
+
await waitFor(() => {
|
|
342
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('never opens on a tap when touchTrigger is "none"', async () => {
|
|
347
|
+
const onOpenChange = vi.fn();
|
|
348
|
+
render(
|
|
349
|
+
<Tooltip
|
|
350
|
+
content="Tooltip text"
|
|
351
|
+
onOpenChange={onOpenChange}
|
|
352
|
+
touchTrigger="none"
|
|
353
|
+
delay={0}>
|
|
354
|
+
Abbreviation
|
|
355
|
+
</Tooltip>,
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
tap(screen.getByText('Abbreviation'));
|
|
359
|
+
|
|
360
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
361
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(true);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('closes on a second tap of the trigger', async () => {
|
|
365
|
+
const onOpenChange = vi.fn();
|
|
366
|
+
render(
|
|
367
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
368
|
+
Abbreviation
|
|
369
|
+
</Tooltip>,
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const trigger = screen.getByText('Abbreviation');
|
|
373
|
+
tap(trigger);
|
|
374
|
+
await waitFor(() => {
|
|
375
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
tap(trigger);
|
|
379
|
+
await waitFor(() => {
|
|
380
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('closes on a tap outside — the dismissal a tap-open owes the user', async () => {
|
|
385
|
+
const onOpenChange = vi.fn();
|
|
386
|
+
render(
|
|
387
|
+
<>
|
|
388
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
389
|
+
Abbreviation
|
|
390
|
+
</Tooltip>
|
|
391
|
+
<button type="button">Elsewhere</button>
|
|
392
|
+
</>,
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
tap(screen.getByText('Abbreviation'));
|
|
396
|
+
await waitFor(() => {
|
|
397
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
fireEvent.pointerDown(screen.getByRole('button', {name: 'Elsewhere'}), {
|
|
401
|
+
pointerType: 'touch',
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
await waitFor(() => {
|
|
405
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('still opens on a real mouse hover after a tap', async () => {
|
|
410
|
+
const onOpenChange = vi.fn();
|
|
411
|
+
render(
|
|
412
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
413
|
+
<button type="button">Save</button>
|
|
414
|
+
</Tooltip>,
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
const trigger = screen.getByRole('button', {name: 'Save'});
|
|
418
|
+
tap(trigger);
|
|
419
|
+
await new Promise(resolve => setTimeout(resolve, 20));
|
|
420
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(true);
|
|
421
|
+
|
|
422
|
+
// A hybrid device: the same trigger, now under a mouse.
|
|
423
|
+
fireEvent.pointerEnter(trigger, {pointerType: 'mouse'});
|
|
424
|
+
fireEvent.mouseEnter(trigger);
|
|
425
|
+
|
|
426
|
+
await waitFor(() => {
|
|
427
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('opens on a hovering pen, which is a hover and not a tap', async () => {
|
|
432
|
+
const onOpenChange = vi.fn();
|
|
433
|
+
render(
|
|
434
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
435
|
+
<button type="button">Save</button>
|
|
436
|
+
</Tooltip>,
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
const trigger = screen.getByRole('button', {name: 'Save'});
|
|
440
|
+
// A stylus in detection range: pointerenter with nothing in contact, on
|
|
441
|
+
// a device where `(hover: hover)` matches. Reading that as touch would
|
|
442
|
+
// bail out of the hover path and leave the user no tooltip at all.
|
|
443
|
+
fireEvent.pointerEnter(trigger, {pointerType: 'pen', buttons: 0});
|
|
444
|
+
fireEvent.mouseEnter(trigger);
|
|
445
|
+
|
|
446
|
+
await waitFor(() => {
|
|
447
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('tap-opens when a pen lands on an inert trigger', async () => {
|
|
452
|
+
const onOpenChange = vi.fn();
|
|
453
|
+
render(
|
|
454
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={200}>
|
|
455
|
+
Abbreviation
|
|
456
|
+
</Tooltip>,
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
const trigger = screen.getByText('Abbreviation');
|
|
460
|
+
// Hovering first, as a real pen does — then contact, which is a tap.
|
|
461
|
+
fireEvent.pointerEnter(trigger, {pointerType: 'pen', buttons: 0});
|
|
462
|
+
fireEvent.pointerDown(trigger, {pointerType: 'pen'});
|
|
463
|
+
fireEvent.pointerUp(trigger, {pointerType: 'pen'});
|
|
464
|
+
|
|
465
|
+
await waitFor(() => {
|
|
466
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('does not reopen from the focus a tapped text field takes', async () => {
|
|
471
|
+
const onOpenChange = vi.fn();
|
|
472
|
+
render(
|
|
473
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
474
|
+
<input type="text" aria-label="Amount" />
|
|
475
|
+
</Tooltip>,
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
const trigger = screen.getByLabelText('Amount');
|
|
479
|
+
// A tapped text field matches `:focus-visible` in a real browser —
|
|
480
|
+
// deliberately, per Selectors 4, so typing has a visible home. jsdom
|
|
481
|
+
// does not model that, so stand it up here; without it this case cannot
|
|
482
|
+
// fail, whatever the focus path does.
|
|
483
|
+
const realMatches = trigger.matches.bind(trigger);
|
|
484
|
+
vi.spyOn(trigger, 'matches').mockImplementation((selector: string) =>
|
|
485
|
+
selector === ':focus-visible' ? true : realMatches(selector),
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
// An `<input>` is an action trigger, so `auto` gives it the tap — and
|
|
489
|
+
// the focus it takes must not put the tooltip back over the field the
|
|
490
|
+
// user is about to type into.
|
|
491
|
+
tap(trigger);
|
|
492
|
+
fireEvent.focusIn(trigger);
|
|
493
|
+
|
|
494
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
495
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(true);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it('still opens on keyboard focus of a trigger a finger touched', async () => {
|
|
499
|
+
const onOpenChange = vi.fn();
|
|
500
|
+
render(
|
|
501
|
+
<Tooltip content="Tooltip text" onOpenChange={onOpenChange} delay={0}>
|
|
502
|
+
<input type="text" aria-label="Amount" />
|
|
503
|
+
</Tooltip>,
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
const trigger = screen.getByLabelText('Amount');
|
|
507
|
+
const realMatches = trigger.matches.bind(trigger);
|
|
508
|
+
vi.spyOn(trigger, 'matches').mockImplementation((selector: string) =>
|
|
509
|
+
selector === ':focus-visible' ? true : realMatches(selector),
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
tap(trigger);
|
|
513
|
+
// Reaching for the keyboard ends the touch interaction; the guard is on
|
|
514
|
+
// the gesture in flight, not on the device the trigger last saw.
|
|
515
|
+
fireEvent.keyDown(document, {key: 'Tab'});
|
|
516
|
+
fireEvent.focusIn(trigger);
|
|
517
|
+
|
|
518
|
+
await waitFor(() => {
|
|
519
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
});
|
|
270
523
|
});
|
package/src/Tooltip/Tooltip.tsx
CHANGED
|
@@ -22,11 +22,15 @@ import React, {
|
|
|
22
22
|
} from 'react';
|
|
23
23
|
import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
24
24
|
import * as stylex from '@stylexjs/stylex';
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
useTooltip,
|
|
27
|
+
type TooltipFocusTrigger,
|
|
28
|
+
type TooltipTouchTrigger,
|
|
29
|
+
} from './useTooltip';
|
|
26
30
|
import type {LayerAlignment, LayerPlacement} from '../Layer/useLayer';
|
|
27
31
|
import {colorVars} from '../theme/tokens.stylex';
|
|
28
32
|
|
|
29
|
-
export type {TooltipFocusTrigger} from './useTooltip';
|
|
33
|
+
export type {TooltipFocusTrigger, TooltipTouchTrigger} from './useTooltip';
|
|
30
34
|
|
|
31
35
|
const styles = stylex.create({
|
|
32
36
|
wrapperContents: {
|
|
@@ -99,6 +103,20 @@ export interface TooltipProps {
|
|
|
99
103
|
*/
|
|
100
104
|
focusTrigger?: TooltipFocusTrigger;
|
|
101
105
|
|
|
106
|
+
/**
|
|
107
|
+
* What a tap does on a touch pointer, where there is no hover:
|
|
108
|
+
* - `auto`: tap opens the tooltip, unless the trigger performs an action of
|
|
109
|
+
* its own (a button, a link, a form control) — that tap belongs to the
|
|
110
|
+
* control, and a hint about a control the user just operated is noise
|
|
111
|
+
* - `tap`: tap always opens the tooltip. This is what an info icon rendered
|
|
112
|
+
* as a button wants: it looks like an action to the DOM, but revealing the
|
|
113
|
+
* tooltip is the only thing it does
|
|
114
|
+
* - `none`: touch never opens the tooltip
|
|
115
|
+
*
|
|
116
|
+
* @default 'auto'
|
|
117
|
+
*/
|
|
118
|
+
touchTrigger?: TooltipTouchTrigger;
|
|
119
|
+
|
|
102
120
|
/**
|
|
103
121
|
* Whether the tooltip is enabled.
|
|
104
122
|
* When false, hover/focus triggers are disabled.
|
|
@@ -176,6 +194,7 @@ export function Tooltip({
|
|
|
176
194
|
delay = 200,
|
|
177
195
|
hideDelay = 0,
|
|
178
196
|
focusTrigger = 'auto',
|
|
197
|
+
touchTrigger = 'auto',
|
|
179
198
|
isEnabled = true,
|
|
180
199
|
onOpenChange,
|
|
181
200
|
hasHoverIndication = 'auto',
|
|
@@ -204,6 +223,7 @@ export function Tooltip({
|
|
|
204
223
|
delay,
|
|
205
224
|
hideDelay,
|
|
206
225
|
focusTrigger,
|
|
226
|
+
touchTrigger,
|
|
207
227
|
isEnabled,
|
|
208
228
|
isOpen,
|
|
209
229
|
isDefaultOpen,
|
package/src/Tooltip/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export const docs = {
|
|
|
12
12
|
{name: 'delay', type: 'number', description: 'Delay before showing on hover, in milliseconds.', default: '200'},
|
|
13
13
|
{name: 'hideDelay', type: 'number', description: 'Delay before hiding after mouse or focus leaves, in milliseconds.', default: '0'},
|
|
14
14
|
{name: 'focusTrigger', type: "'auto' | 'always' | 'never'", description: 'When focus should open the tooltip. auto only attaches focus listeners to naturally focusable elements.', default: "'auto'"},
|
|
15
|
+
{name: 'touchTrigger', type: "'auto' | 'tap' | 'none'", description: 'What a tap does where there is no hover. auto opens on tap unless the trigger performs an action of its own; tap always opens (an info icon rendered as a button); none never opens on touch.', default: "'auto'"},
|
|
15
16
|
{name: 'isEnabled', type: 'boolean', description: 'Whether hover and focus triggers are enabled.', default: 'true'},
|
|
16
17
|
{name: 'isOpen', type: 'boolean', description: 'Controlled open state. true force-shows, false force-hides, undefined lets hover/focus manage visibility.'},
|
|
17
18
|
{name: 'isDefaultOpen', type: 'boolean', description: 'Whether the tooltip should be shown on mount.', default: 'false'},
|
|
@@ -49,6 +50,7 @@ export const docsDense = {
|
|
|
49
50
|
delay: 'show delay in ms.',
|
|
50
51
|
hideDelay: 'hide delay after mouse/focus leave in ms.',
|
|
51
52
|
focusTrigger: 'when focus opens tooltip; auto = naturally focusable elements only.',
|
|
53
|
+
touchTrigger: 'tap behavior with no hover; auto = tap unless trigger acts, tap = always, none = never.',
|
|
52
54
|
isEnabled: 'whether hover/focus triggers are enabled.',
|
|
53
55
|
isOpen: 'controlled open state: true force-show, false force-hide, undefined unmanaged.',
|
|
54
56
|
isDefaultOpen: 'show on mount.',
|