@astryxdesign/core 0.4.4 → 0.4.5-canary.0472ec1
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/Blockquote/Blockquote.d.ts +4 -3
- package/dist/Blockquote/Blockquote.d.ts.map +1 -1
- package/dist/Blockquote/Blockquote.js +9 -10
- 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 +77 -18
- 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 +31 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +92 -19
- package/dist/DateInput/MonthScroller.d.ts +35 -0
- package/dist/DateInput/MonthScroller.d.ts.map +1 -0
- package/dist/DateInput/MonthScroller.js +573 -0
- package/dist/DateInput/MonthYearWheels.d.ts +24 -0
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
- package/dist/DateInput/MonthYearWheels.js +114 -0
- package/dist/DateInput/TouchDateField.d.ts +10 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -0
- package/dist/DateInput/TouchDateField.js +810 -0
- package/dist/DateInput/Wheel.d.ts +41 -0
- package/dist/DateInput/Wheel.d.ts.map +1 -0
- package/dist/DateInput/Wheel.js +315 -0
- package/dist/DateInput/monthGeometry.d.ts +65 -0
- package/dist/DateInput/monthGeometry.d.ts.map +1 -0
- package/dist/DateInput/monthGeometry.js +98 -0
- package/dist/DateInput/tokens.stylex.d.ts +63 -0
- package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
- package/dist/DateInput/tokens.stylex.js +74 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
- package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
- package/dist/DateInput/useOwnScrollGesture.js +202 -0
- package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
- package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
- package/dist/DateInput/usePointerDragScroll.js +216 -0
- package/dist/DateInput/useScrollSettle.d.ts +26 -0
- package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
- package/dist/DateInput/useScrollSettle.js +149 -0
- 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 +123 -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/theme/syntax/index.d.ts +6 -0
- package/dist/theme/syntax/index.d.ts.map +1 -1
- package/dist/theme/syntax/index.js +7 -2
- 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/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/plainDate.d.ts +11 -2
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +32 -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 +32 -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 +24 -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/Blockquote/Blockquote.doc.mjs +30 -7
- package/src/Blockquote/Blockquote.test.tsx +34 -3
- package/src/Blockquote/Blockquote.tsx +11 -9
- 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 +91 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +121 -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 +90 -19
- package/src/DateInput/DateInputTouch.test.tsx +2393 -0
- package/src/DateInput/MonthScroller.tsx +784 -0
- package/src/DateInput/MonthYearWheels.tsx +147 -0
- package/src/DateInput/TouchDateField.tsx +1214 -0
- package/src/DateInput/Wheel.tsx +470 -0
- package/src/DateInput/monthGeometry.ts +118 -0
- package/src/DateInput/tokens.stylex.ts +99 -0
- package/src/DateInput/useOwnScrollGesture.ts +227 -0
- package/src/DateInput/usePointerDragScroll.ts +220 -0
- package/src/DateInput/useScrollSettle.ts +164 -0
- 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/theme/syntax/index.ts +6 -2
- package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
- package/src/utils/dateParser.test.ts +20 -0
- package/src/utils/dateParser.ts +14 -7
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +56 -0
- package/src/utils/plainDate.ts +33 -4
package/src/Item/Item.tsx
CHANGED
|
@@ -106,6 +106,15 @@ export interface ItemProps extends BaseProps<HTMLElement> {
|
|
|
106
106
|
*/
|
|
107
107
|
descriptionLines?: number;
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* How the label and description sit together. `stacked` puts the description
|
|
111
|
+
* on its own line below the label; `inline` keeps both on one line, with the
|
|
112
|
+
* description ellipsizing first, so the row fits a fixed-height host.
|
|
113
|
+
*
|
|
114
|
+
* @default 'stacked'
|
|
115
|
+
*/
|
|
116
|
+
layout?: 'stacked' | 'inline';
|
|
117
|
+
|
|
109
118
|
/**
|
|
110
119
|
* Click handler. Makes the item clickable with button semantics.
|
|
111
120
|
*/
|
|
@@ -213,7 +222,7 @@ const styles = stylex.create({
|
|
|
213
222
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
214
223
|
backgroundColor: {
|
|
215
224
|
default: 'transparent',
|
|
216
|
-
':hover': {
|
|
225
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
217
226
|
'@media (hover: hover)': colorVars['--color-overlay-hover'],
|
|
218
227
|
},
|
|
219
228
|
':active': colorVars['--color-overlay-pressed'],
|
|
@@ -264,6 +273,25 @@ const styles = stylex.create({
|
|
|
264
273
|
minWidth: 0,
|
|
265
274
|
textAlign: 'start',
|
|
266
275
|
},
|
|
276
|
+
// `layout="inline"`: label and description share one line, so the row fits a
|
|
277
|
+
// fixed-height host such as a Selector trigger inside an InputGroup.
|
|
278
|
+
inlineContent: {
|
|
279
|
+
flexDirection: 'row',
|
|
280
|
+
// Centered, not baseline-aligned: two different font sizes on a shared
|
|
281
|
+
// baseline make a line box taller than either line, which would push a
|
|
282
|
+
// fixed-height host (a Selector trigger) a pixel off its size token.
|
|
283
|
+
alignItems: 'center',
|
|
284
|
+
columnGap: spacingVars['--spacing-1'],
|
|
285
|
+
},
|
|
286
|
+
inlineLabel: {
|
|
287
|
+
flexShrink: 0,
|
|
288
|
+
},
|
|
289
|
+
// The description yields width first, so the label — the part that identifies
|
|
290
|
+
// the item — is the last thing to ellipsize.
|
|
291
|
+
inlineDescription: {
|
|
292
|
+
flexShrink: 1,
|
|
293
|
+
minWidth: 0,
|
|
294
|
+
},
|
|
267
295
|
label: {
|
|
268
296
|
// Falls back to the primary text token; a parent (e.g. a destructive menu
|
|
269
297
|
// item) can recolor the label by setting --_item-label-color.
|
|
@@ -358,6 +386,7 @@ export function Item({
|
|
|
358
386
|
density = 'balanced',
|
|
359
387
|
labelLines,
|
|
360
388
|
descriptionLines,
|
|
389
|
+
layout = 'stacked',
|
|
361
390
|
onClick,
|
|
362
391
|
interactiveRef,
|
|
363
392
|
href,
|
|
@@ -420,12 +449,16 @@ export function Item({
|
|
|
420
449
|
? styles.labelSingleTruncate
|
|
421
450
|
: null;
|
|
422
451
|
|
|
452
|
+
// Inline rows are one line by definition, so the description always
|
|
453
|
+
// ellipsizes there — a ReactNode description cannot wrap the row open.
|
|
454
|
+
const isInline = layout === 'inline' && description != null;
|
|
455
|
+
|
|
423
456
|
const descriptionTruncateStyle =
|
|
424
457
|
descriptionLines != null
|
|
425
458
|
? descriptionLines === 1
|
|
426
459
|
? styles.descriptionSingleTruncate
|
|
427
460
|
: styles.descriptionMultiTruncate
|
|
428
|
-
: isStringDescription
|
|
461
|
+
: isStringDescription || isInline
|
|
429
462
|
? styles.descriptionSingleTruncate
|
|
430
463
|
: null;
|
|
431
464
|
|
|
@@ -434,6 +467,7 @@ export function Item({
|
|
|
434
467
|
<span
|
|
435
468
|
{...stylex.props(
|
|
436
469
|
styles.label,
|
|
470
|
+
isInline && styles.inlineLabel,
|
|
437
471
|
labelTruncateStyle,
|
|
438
472
|
labelLines != null &&
|
|
439
473
|
labelLines > 1 &&
|
|
@@ -445,6 +479,7 @@ export function Item({
|
|
|
445
479
|
<span
|
|
446
480
|
{...stylex.props(
|
|
447
481
|
styles.description,
|
|
482
|
+
isInline && styles.inlineDescription,
|
|
448
483
|
descriptionTruncateStyle,
|
|
449
484
|
descriptionLines != null &&
|
|
450
485
|
descriptionLines > 1 &&
|
|
@@ -481,6 +516,7 @@ export function Item({
|
|
|
481
516
|
<span
|
|
482
517
|
{...stylex.props(
|
|
483
518
|
styles.content,
|
|
519
|
+
isInline && styles.inlineContent,
|
|
484
520
|
isDisabled && styles.disabledContent,
|
|
485
521
|
)}>
|
|
486
522
|
{labelAndDescription}
|
|
@@ -494,6 +530,7 @@ export function Item({
|
|
|
494
530
|
tabIndex={isDisabled ? -1 : undefined}
|
|
495
531
|
{...stylex.props(
|
|
496
532
|
styles.invisibleAnchor,
|
|
533
|
+
isInline && styles.inlineContent,
|
|
497
534
|
isDisabled && styles.disabledContent,
|
|
498
535
|
)}>
|
|
499
536
|
{labelAndDescription}
|
|
@@ -505,6 +542,7 @@ export function Item({
|
|
|
505
542
|
disabled={isDisabled}
|
|
506
543
|
{...stylex.props(
|
|
507
544
|
styles.invisibleButton,
|
|
545
|
+
isInline && styles.inlineContent,
|
|
508
546
|
isDisabled && styles.disabledContent,
|
|
509
547
|
)}>
|
|
510
548
|
{labelAndDescription}
|
|
@@ -513,6 +551,7 @@ export function Item({
|
|
|
513
551
|
<span
|
|
514
552
|
{...stylex.props(
|
|
515
553
|
styles.content,
|
|
554
|
+
isInline && styles.inlineContent,
|
|
516
555
|
isDisabled && styles.disabledContent,
|
|
517
556
|
)}>
|
|
518
557
|
{labelAndDescription}
|
package/src/Layer/index.ts
CHANGED
|
@@ -29,6 +29,14 @@ export type {
|
|
|
29
29
|
FixedLayerReturn,
|
|
30
30
|
} from './useLayer';
|
|
31
31
|
|
|
32
|
+
// Shared touch behavior for the hover layers
|
|
33
|
+
export {useTouchTrigger, isActionTrigger} from './useTouchTrigger';
|
|
34
|
+
export type {
|
|
35
|
+
LayerTouchTrigger,
|
|
36
|
+
UseTouchTriggerOptions,
|
|
37
|
+
UseTouchTriggerReturn,
|
|
38
|
+
} from './useTouchTrigger';
|
|
39
|
+
|
|
32
40
|
// Layer provider
|
|
33
41
|
export {LayerProvider} from './LayerProvider';
|
|
34
42
|
export type {LayerProviderProps} from './LayerProvider';
|
|
@@ -50,6 +58,7 @@ export type {
|
|
|
50
58
|
export {useHoverCard, HoverCard} from '../HoverCard';
|
|
51
59
|
export type {
|
|
52
60
|
HoverCardFocusTrigger,
|
|
61
|
+
HoverCardTouchTrigger,
|
|
53
62
|
HoverCardOptions,
|
|
54
63
|
HoverCardReturn,
|
|
55
64
|
HoverCardProps,
|
|
@@ -59,6 +68,7 @@ export type {
|
|
|
59
68
|
export {useTooltip, Tooltip} from '../Tooltip';
|
|
60
69
|
export type {
|
|
61
70
|
TooltipFocusTrigger,
|
|
71
|
+
TooltipTouchTrigger,
|
|
62
72
|
TooltipOptions,
|
|
63
73
|
TooltipReturn,
|
|
64
74
|
TooltipProps,
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -29,6 +29,7 @@ import {createPortal} from 'react-dom';
|
|
|
29
29
|
import {addAnchorName, removeAnchorName} from './anchorName';
|
|
30
30
|
import {resolveLayerPortalTarget} from './layerHost';
|
|
31
31
|
import {typeScaleVars, typographyVars} from '../theme/tokens.stylex';
|
|
32
|
+
import {overlayPaddingReset} from '../Layout/padding.stylex';
|
|
32
33
|
|
|
33
34
|
const styles = stylex.create({
|
|
34
35
|
// Base reset for all layers
|
|
@@ -771,7 +772,12 @@ export function useLayer(
|
|
|
771
772
|
: styles.offsetInline(toCssLength(offset))
|
|
772
773
|
: null;
|
|
773
774
|
|
|
774
|
-
const stylexResult = stylex.props(
|
|
775
|
+
const stylexResult = stylex.props(
|
|
776
|
+
styles.base,
|
|
777
|
+
overlayPaddingReset.reset,
|
|
778
|
+
offsetStyle,
|
|
779
|
+
xstyle,
|
|
780
|
+
);
|
|
775
781
|
const combinedClassName = extraClassName
|
|
776
782
|
? `${extraClassName} ${stylexResult.className ?? ''}`
|
|
777
783
|
: stylexResult.className;
|
|
@@ -835,7 +841,12 @@ export function useLayer(
|
|
|
835
841
|
left: x,
|
|
836
842
|
};
|
|
837
843
|
|
|
838
|
-
const stylexResult = stylex.props(
|
|
844
|
+
const stylexResult = stylex.props(
|
|
845
|
+
styles.base,
|
|
846
|
+
overlayPaddingReset.reset,
|
|
847
|
+
styles.fixed,
|
|
848
|
+
xstyle,
|
|
849
|
+
);
|
|
839
850
|
const combinedClassName = extraClassName
|
|
840
851
|
? `${extraClassName} ${stylexResult.className ?? ''}`
|
|
841
852
|
: stylexResult.className;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file useTouchTrigger.test.ts
|
|
5
|
+
* @input Uses vitest, isActionTrigger
|
|
6
|
+
* @output Unit tests for the action-trigger rule behind touchTrigger="auto"
|
|
7
|
+
* @position Testing; validates useTouchTrigger.ts implementation
|
|
8
|
+
*
|
|
9
|
+
* SYNC: When useTouchTrigger.ts changes, update tests to match new behavior
|
|
10
|
+
*
|
|
11
|
+
* The tap-versus-suppress decision rests entirely on this predicate, and it is
|
|
12
|
+
* the part a new element type silently falls through. The per-component tests
|
|
13
|
+
* (Tooltip.test.tsx, HoverCard.test.tsx) cover the gestures it feeds.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {describe, it, expect} from 'vitest';
|
|
17
|
+
import {isActionTrigger} from './useTouchTrigger';
|
|
18
|
+
|
|
19
|
+
function element(html: string): HTMLElement {
|
|
20
|
+
const host = document.createElement('div');
|
|
21
|
+
host.innerHTML = html;
|
|
22
|
+
return host.firstElementChild as HTMLElement;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('isActionTrigger', () => {
|
|
26
|
+
it.each([
|
|
27
|
+
['<button type="button">Save</button>'],
|
|
28
|
+
['<input type="text" />'],
|
|
29
|
+
['<select></select>'],
|
|
30
|
+
['<textarea></textarea>'],
|
|
31
|
+
['<summary>More</summary>'],
|
|
32
|
+
['<label>Name</label>'],
|
|
33
|
+
['<a href="/somewhere">Link</a>'],
|
|
34
|
+
])('treats %s as an action', html => {
|
|
35
|
+
expect(isActionTrigger(element(html))).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it.each([
|
|
39
|
+
['<span>Plain text</span>'],
|
|
40
|
+
['<svg></svg>'],
|
|
41
|
+
['<abbr title="what">WCAG</abbr>'],
|
|
42
|
+
// An anchor without href is a link that goes nowhere.
|
|
43
|
+
['<a>Not a link</a>'],
|
|
44
|
+
])('treats %s as inert', html => {
|
|
45
|
+
expect(isActionTrigger(element(html))).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('reads an explicit role over the tag it sits on', () => {
|
|
49
|
+
expect(isActionTrigger(element('<span role="button">Go</span>'))).toBe(
|
|
50
|
+
true,
|
|
51
|
+
);
|
|
52
|
+
// Scenery: the role says this button is not the control it looks like.
|
|
53
|
+
expect(
|
|
54
|
+
isActionTrigger(element('<button role="presentation">x</button>')),
|
|
55
|
+
).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('does not treat mere focusability as an action', () => {
|
|
59
|
+
// The wrapper a text-only Tooltip renders: reachable by keyboard so the
|
|
60
|
+
// hint is not mouse-only, and it still does nothing when activated.
|
|
61
|
+
expect(isActionTrigger(element('<span tabindex="0">Term</span>'))).toBe(
|
|
62
|
+
false,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('treats a contenteditable surface as an action', () => {
|
|
67
|
+
const editable = element('<div contenteditable="true"></div>');
|
|
68
|
+
expect(isActionTrigger(editable)).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useTouchTrigger.ts
|
|
7
|
+
* @input Touch trigger mode, layer open state, trigger ref, show/hide callbacks
|
|
8
|
+
* @output Exports useTouchTrigger hook, isActionTrigger, LayerTouchTrigger type
|
|
9
|
+
* @position Layer hook; shared touch behavior for useTooltip and useHoverCard
|
|
10
|
+
*
|
|
11
|
+
* SYNC: When modified, update:
|
|
12
|
+
* - /packages/core/src/Layer/index.ts
|
|
13
|
+
*
|
|
14
|
+
* Hover is the one trigger a touch screen cannot express. A tap synthesizes
|
|
15
|
+
* `mouseenter`, so an untreated hover layer either opens on every tap and
|
|
16
|
+
* lingers with nothing to close it, or swallows the tap the user aimed at the
|
|
17
|
+
* control underneath.
|
|
18
|
+
*
|
|
19
|
+
* What the trigger DOES decides which of those the tap deserves. A trigger
|
|
20
|
+
* that performs an action — a button, a link, a form control — keeps its tap:
|
|
21
|
+
* the layer stays shut, because the tap already has somewhere to go and a hint
|
|
22
|
+
* about a control the user just operated is noise. A trigger that performs no
|
|
23
|
+
* action — an info icon, an abbreviation, a truncated label — has nothing to
|
|
24
|
+
* lose, so the tap opens the layer and the next tap outside dismisses it. That
|
|
25
|
+
* is `auto`; `tap` and `none` state the choice outright, which is what an
|
|
26
|
+
* icon-button whose only job is to reveal the layer needs.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import {useCallback, useEffect, useRef, type RefObject} from 'react';
|
|
30
|
+
import {
|
|
31
|
+
getInteractionModality,
|
|
32
|
+
trackInteractionModality,
|
|
33
|
+
} from '../utils/interactionModality';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* How a hover layer behaves on a touch pointer.
|
|
37
|
+
*
|
|
38
|
+
* - `auto`: tap-to-open, unless the trigger performs an action of its own
|
|
39
|
+
* - `tap`: always tap-to-open, even on a trigger that performs an action
|
|
40
|
+
* - `none`: never open on touch
|
|
41
|
+
*/
|
|
42
|
+
export type LayerTouchTrigger = 'auto' | 'tap' | 'none';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Pointer types whose *press* is a tap rather than a click.
|
|
46
|
+
*
|
|
47
|
+
* A pen belongs here but not in the arrival path: in detection range it hovers
|
|
48
|
+
* — firing `pointerenter`/`pointermove` with no contact, exactly as a mouse
|
|
49
|
+
* does, on a device where `(hover: hover)` matches — and only becomes a tap
|
|
50
|
+
* once it lands. See `handlePointerEnter`.
|
|
51
|
+
*/
|
|
52
|
+
const TOUCH_POINTER_TYPES = new Set(['touch', 'pen']);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* ARIA roles that make an element do something when activated. An explicit
|
|
56
|
+
* role wins over the tag: `<button role="presentation">` is scenery, and a
|
|
57
|
+
* `<span role="button">` is a real control.
|
|
58
|
+
*/
|
|
59
|
+
const ACTION_ROLES = new Set([
|
|
60
|
+
'button',
|
|
61
|
+
'checkbox',
|
|
62
|
+
'combobox',
|
|
63
|
+
'link',
|
|
64
|
+
'menuitem',
|
|
65
|
+
'menuitemcheckbox',
|
|
66
|
+
'menuitemradio',
|
|
67
|
+
'option',
|
|
68
|
+
'radio',
|
|
69
|
+
'searchbox',
|
|
70
|
+
'slider',
|
|
71
|
+
'spinbutton',
|
|
72
|
+
'switch',
|
|
73
|
+
'tab',
|
|
74
|
+
'textbox',
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Whether activating this element does something other than reveal the layer.
|
|
79
|
+
*
|
|
80
|
+
* Deliberately narrower than "focusable": the wrapper a text-only Tooltip
|
|
81
|
+
* renders carries `tabindex=0` so keyboard users can reach the hint, and it
|
|
82
|
+
* still performs no action.
|
|
83
|
+
*
|
|
84
|
+
* True only decides that the layer stays shut — the tap itself is never
|
|
85
|
+
* swallowed. Nothing here calls `preventDefault` or `stopPropagation`, so an
|
|
86
|
+
* inert trigger that happens to carry its own `onClick` (a `<div onClick>`
|
|
87
|
+
* with no role) gets both: the layer opens and the handler runs.
|
|
88
|
+
*/
|
|
89
|
+
export function isActionTrigger(element: HTMLElement): boolean {
|
|
90
|
+
const role = element.getAttribute('role');
|
|
91
|
+
if (role != null && role !== '') {
|
|
92
|
+
return ACTION_ROLES.has(role);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
switch (element.tagName) {
|
|
96
|
+
case 'BUTTON':
|
|
97
|
+
case 'INPUT':
|
|
98
|
+
case 'LABEL':
|
|
99
|
+
case 'SELECT':
|
|
100
|
+
case 'SUMMARY':
|
|
101
|
+
case 'TEXTAREA':
|
|
102
|
+
return true;
|
|
103
|
+
case 'A':
|
|
104
|
+
case 'AREA':
|
|
105
|
+
return element.hasAttribute('href');
|
|
106
|
+
default:
|
|
107
|
+
return isEditable(element);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Whether typing into this element edits it. Reads the attribute as well as
|
|
113
|
+
* the property: jsdom does not implement `isContentEditable`, and an editor
|
|
114
|
+
* that is an action in the browser must not be inert under test.
|
|
115
|
+
*/
|
|
116
|
+
function isEditable(element: HTMLElement): boolean {
|
|
117
|
+
if (element.isContentEditable === true) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const attribute = element.getAttribute('contenteditable');
|
|
121
|
+
return attribute != null && attribute !== 'false';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface UseTouchTriggerOptions {
|
|
125
|
+
/** How the layer should behave on a touch pointer. */
|
|
126
|
+
touchTrigger: LayerTouchTrigger;
|
|
127
|
+
|
|
128
|
+
/** Whether the layer's triggers are live at all. */
|
|
129
|
+
isEnabled: boolean;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Whether the consumer controls visibility. A controlled layer is never
|
|
133
|
+
* toggled by a tap — its visibility is the consumer's to own.
|
|
134
|
+
*/
|
|
135
|
+
isControlled: boolean;
|
|
136
|
+
|
|
137
|
+
/** Whether the layer is currently open. */
|
|
138
|
+
isOpen: boolean;
|
|
139
|
+
|
|
140
|
+
/** Element id of the layer surface, so taps inside it count as inside. */
|
|
141
|
+
layerId: string;
|
|
142
|
+
|
|
143
|
+
/** The trigger element the layer is anchored to. */
|
|
144
|
+
triggerRef: RefObject<HTMLElement | null>;
|
|
145
|
+
|
|
146
|
+
/** Open the layer immediately, with no hover delay. */
|
|
147
|
+
show: () => void;
|
|
148
|
+
|
|
149
|
+
/** Close the layer immediately. */
|
|
150
|
+
hide: () => void;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface UseTouchTriggerReturn {
|
|
154
|
+
/**
|
|
155
|
+
* Whether the pointer in play on this trigger has no hover of its own: a
|
|
156
|
+
* finger, or a pen that has landed. A hovering pen reads as false, because
|
|
157
|
+
* it hovers.
|
|
158
|
+
*/
|
|
159
|
+
isTouchPointerRef: RefObject<boolean>;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Whether the interaction in flight is a touch one. Unlike the raw ref this
|
|
163
|
+
* goes false again as soon as the user reaches for the keyboard, so
|
|
164
|
+
* focus-driven triggers stay available after a tap.
|
|
165
|
+
*/
|
|
166
|
+
isTouchInteraction: () => boolean;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Attach to the trigger: records pointer type ahead of synthesized hover.
|
|
170
|
+
* Arrival alone only marks a finger — a pen hovers, so it is left to the
|
|
171
|
+
* hover path until it presses.
|
|
172
|
+
*/
|
|
173
|
+
handlePointerEnter: (event: PointerEvent) => void;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Attach to the trigger. Returns true when the press was a touch one and
|
|
177
|
+
* this hook has dealt with it, meaning the caller's own pointer-down
|
|
178
|
+
* behavior must not also run.
|
|
179
|
+
*/
|
|
180
|
+
handlePointerDown: (event: PointerEvent) => boolean;
|
|
181
|
+
|
|
182
|
+
/** Forget a tap-open. Call from every other close path (Escape, controlled). */
|
|
183
|
+
clearTapOpen: () => void;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Touch behavior shared by the hover layers.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```
|
|
191
|
+
* const touch = useTouchTrigger({
|
|
192
|
+
* touchTrigger,
|
|
193
|
+
* isEnabled,
|
|
194
|
+
* isControlled: isOpen !== undefined,
|
|
195
|
+
* isOpen: layer.isOpen,
|
|
196
|
+
* layerId: layer.id,
|
|
197
|
+
* triggerRef,
|
|
198
|
+
* show: showNow,
|
|
199
|
+
* hide: hideNow,
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function useTouchTrigger(
|
|
204
|
+
options: UseTouchTriggerOptions,
|
|
205
|
+
): UseTouchTriggerReturn {
|
|
206
|
+
const {
|
|
207
|
+
touchTrigger,
|
|
208
|
+
isEnabled,
|
|
209
|
+
isControlled,
|
|
210
|
+
isOpen,
|
|
211
|
+
layerId,
|
|
212
|
+
triggerRef,
|
|
213
|
+
show,
|
|
214
|
+
hide,
|
|
215
|
+
} = options;
|
|
216
|
+
|
|
217
|
+
const isTouchPointerRef = useRef(false);
|
|
218
|
+
// Mirrors `isOpen` for synchronous reads inside the pointer handler, which
|
|
219
|
+
// runs outside React's render and would otherwise close over a stale value.
|
|
220
|
+
const isOpenRef = useRef(isOpen);
|
|
221
|
+
isOpenRef.current = isOpen;
|
|
222
|
+
|
|
223
|
+
// Latest values for the document listener, which outlives the render that
|
|
224
|
+
// armed it.
|
|
225
|
+
const hideRef = useRef(hide);
|
|
226
|
+
hideRef.current = hide;
|
|
227
|
+
const layerIdRef = useRef(layerId);
|
|
228
|
+
layerIdRef.current = layerId;
|
|
229
|
+
|
|
230
|
+
// Whether a tap is what opened the layer. Only a tap-open owes the user an
|
|
231
|
+
// outside-tap dismissal: a hover-opened layer already closes on
|
|
232
|
+
// pointer-leave, and a controlled one is not ours to close.
|
|
233
|
+
const isTapOpenRef = useRef(false);
|
|
234
|
+
const outsideListenerRef = useRef<((event: PointerEvent) => void) | null>(
|
|
235
|
+
null,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
trackInteractionModality();
|
|
240
|
+
}, []);
|
|
241
|
+
|
|
242
|
+
const disarmOutsideDismiss = useCallback(() => {
|
|
243
|
+
isTapOpenRef.current = false;
|
|
244
|
+
const listener = outsideListenerRef.current;
|
|
245
|
+
if (listener == null) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
outsideListenerRef.current = null;
|
|
249
|
+
document.removeEventListener('pointerdown', listener, true);
|
|
250
|
+
}, []);
|
|
251
|
+
|
|
252
|
+
// Capture phase, so a trigger that stops propagation cannot strand an open
|
|
253
|
+
// layer. The opening tap's own capture phase at the document has already
|
|
254
|
+
// passed by the time this runs, so the listener never sees it.
|
|
255
|
+
const armOutsideDismiss = useCallback(() => {
|
|
256
|
+
isTapOpenRef.current = true;
|
|
257
|
+
if (outsideListenerRef.current != null) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const handleOutsidePointerDown = (event: PointerEvent) => {
|
|
262
|
+
const target = event.target as Node | null;
|
|
263
|
+
if (target != null) {
|
|
264
|
+
// The trigger's own handler owns the toggle.
|
|
265
|
+
if (triggerRef.current?.contains(target) === true) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// Hover card content is interactive; a tap inside it is not a dismiss.
|
|
269
|
+
if (
|
|
270
|
+
document.getElementById(layerIdRef.current)?.contains(target) === true
|
|
271
|
+
) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
disarmOutsideDismiss();
|
|
276
|
+
hideRef.current();
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
outsideListenerRef.current = handleOutsidePointerDown;
|
|
280
|
+
document.addEventListener('pointerdown', handleOutsidePointerDown, true);
|
|
281
|
+
}, [triggerRef, disarmOutsideDismiss]);
|
|
282
|
+
|
|
283
|
+
useEffect(() => disarmOutsideDismiss, [disarmOutsideDismiss]);
|
|
284
|
+
|
|
285
|
+
const isTouchInteraction = useCallback(
|
|
286
|
+
() => isTouchPointerRef.current && getInteractionModality() === 'pointer',
|
|
287
|
+
[],
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const handlePointerEnter = useCallback((event: PointerEvent) => {
|
|
291
|
+
// Only a finger is hoverless on arrival. A pen in detection range hovers
|
|
292
|
+
// like a mouse, and treating its arrival as touch would bail out of the
|
|
293
|
+
// hover path and leave a stylus user with no tooltip at all. A pen that
|
|
294
|
+
// presses is a tap, and `handlePointerDown` still reads it as one.
|
|
295
|
+
isTouchPointerRef.current = event.pointerType === 'touch';
|
|
296
|
+
}, []);
|
|
297
|
+
|
|
298
|
+
const handlePointerDown = useCallback(
|
|
299
|
+
(event: PointerEvent): boolean => {
|
|
300
|
+
const isTouch = TOUCH_POINTER_TYPES.has(event.pointerType);
|
|
301
|
+
isTouchPointerRef.current = isTouch;
|
|
302
|
+
|
|
303
|
+
if (!isTouch || isControlled) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const trigger = triggerRef.current;
|
|
308
|
+
const mode =
|
|
309
|
+
touchTrigger === 'auto'
|
|
310
|
+
? trigger != null && isActionTrigger(trigger)
|
|
311
|
+
? 'none'
|
|
312
|
+
: 'tap'
|
|
313
|
+
: touchTrigger;
|
|
314
|
+
|
|
315
|
+
if (mode === 'none' || !isEnabled) {
|
|
316
|
+
// A layer left open by an earlier tap must not survive the next one.
|
|
317
|
+
disarmOutsideDismiss();
|
|
318
|
+
hide();
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// A lazily mounted layer reports `isOpen` a tick after `show()`, so the
|
|
323
|
+
// tap's own bookkeeping is what makes the second tap a close.
|
|
324
|
+
if (isOpenRef.current || isTapOpenRef.current) {
|
|
325
|
+
disarmOutsideDismiss();
|
|
326
|
+
hide();
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
armOutsideDismiss();
|
|
331
|
+
show();
|
|
332
|
+
return true;
|
|
333
|
+
},
|
|
334
|
+
[
|
|
335
|
+
touchTrigger,
|
|
336
|
+
isEnabled,
|
|
337
|
+
isControlled,
|
|
338
|
+
triggerRef,
|
|
339
|
+
show,
|
|
340
|
+
hide,
|
|
341
|
+
armOutsideDismiss,
|
|
342
|
+
disarmOutsideDismiss,
|
|
343
|
+
],
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
// A layer closed by any other path (Escape, a consumer, the browser) leaves
|
|
347
|
+
// no tap-open to dismiss. Only a true open→closed transition counts: a
|
|
348
|
+
// lazily mounted layer still reports `false` for a tick after the tap asked
|
|
349
|
+
// it to open, and reading that as a close would disarm the dismissal the
|
|
350
|
+
// tap-open just armed.
|
|
351
|
+
const wasOpenRef = useRef(isOpen);
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
if (wasOpenRef.current && !isOpen) {
|
|
354
|
+
disarmOutsideDismiss();
|
|
355
|
+
}
|
|
356
|
+
wasOpenRef.current = isOpen;
|
|
357
|
+
}, [isOpen, disarmOutsideDismiss]);
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
isTouchPointerRef,
|
|
361
|
+
isTouchInteraction,
|
|
362
|
+
handlePointerEnter,
|
|
363
|
+
handlePointerDown,
|
|
364
|
+
clearTapOpen: disarmOutsideDismiss,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
@@ -93,6 +93,24 @@ export const docs = {
|
|
|
93
93
|
description: 'Height behavior: fill the container or grow with content.',
|
|
94
94
|
default: "'fill'",
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
name: 'contentWidth',
|
|
98
|
+
type: 'number | string',
|
|
99
|
+
description:
|
|
100
|
+
'Maximum width of the content within each slot (header, content, footer, panels), centered when narrower than the available space. Dividers stay full-bleed. Numbers are pixels, strings are used as-is (e.g. `60ch`). Common page widths: 640 for forms, settings, and text-focused pages; 960 for content pages and wider layouts.',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'padding',
|
|
104
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
105
|
+
description:
|
|
106
|
+
"Padding at the layout's outer edges using the spacing scale.",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'defaultHasDividers',
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description:
|
|
112
|
+
"Default divider visibility for LayoutHeader and LayoutFooter children. Headers and footers that don't pass `hasDivider` use this value; when unset, nested layouts inherit from their parent context.",
|
|
113
|
+
},
|
|
96
114
|
],
|
|
97
115
|
components: [
|
|
98
116
|
{name: 'LayoutHeader'},
|
|
@@ -28,8 +28,10 @@
|
|
|
28
28
|
* }
|
|
29
29
|
* ```
|
|
30
30
|
*
|
|
31
|
-
* Internal variables (`--layout-padding-inner-x`, `--container-padding
|
|
32
|
-
* are implementation details and must not be
|
|
31
|
+
* Internal variables (`--layout-padding-inner-x`, `--container-padding-*`,
|
|
32
|
+
* `--_section-padding-propagated`) are implementation details and must not be
|
|
33
|
+
* referenced by themes. They also do not cross an overlay boundary — see
|
|
34
|
+
* `overlayPaddingReset` in padding.stylex.ts.
|
|
33
35
|
*
|
|
34
36
|
* SYNC: When modified, update /packages/core/src/Layout/Layout.doc.mjs
|
|
35
37
|
*/
|
|
@@ -105,7 +107,13 @@ const cardBlockEnd = `var(--astryx-card-padding-block-end, ${cardShorthand})`;
|
|
|
105
107
|
// Section padding chains: --astryx-* then the next specificity level, terminating
|
|
106
108
|
// at --spacing-4. Built as chained const strings (no function calls) so StyleX
|
|
107
109
|
// can statically analyze them; see naming.ts for the prefix policy.
|
|
108
|
-
|
|
110
|
+
// `--_section-padding-propagated` (set by an ancestor Section with explicit
|
|
111
|
+
// padding) is read AHEAD of the public theme token, so a propagated value
|
|
112
|
+
// still wins over the theme for nested sections. Splitting the two names is
|
|
113
|
+
// what lets an overlay drop the inherited value at its boundary while keeping
|
|
114
|
+
// the theme's — see `overlayPaddingReset` in padding.stylex.ts.
|
|
115
|
+
const sectionThemeShorthand = `var(--astryx-section-padding, ${SP4})`;
|
|
116
|
+
const sectionShorthand = `var(--_section-padding-propagated, ${sectionThemeShorthand})`;
|
|
109
117
|
const sectionInline = `var(--astryx-section-padding-inline, ${sectionShorthand})`;
|
|
110
118
|
const sectionInlineStart = `var(--astryx-section-padding-inline-start, ${sectionInline})`;
|
|
111
119
|
const sectionInlineEnd = `var(--astryx-section-padding-inline-end, ${sectionInline})`;
|
package/src/Layout/index.ts
CHANGED
|
@@ -19,6 +19,10 @@ export type {
|
|
|
19
19
|
SpacingToken,
|
|
20
20
|
} from './container.stylex';
|
|
21
21
|
|
|
22
|
+
// Overlay padding-variable reset (applied on overlay roots so the container
|
|
23
|
+
// padding system does not cross a fixed/top-layer boundary)
|
|
24
|
+
export {overlayPaddingReset} from './padding.stylex';
|
|
25
|
+
|
|
22
26
|
// Edge compensation utility
|
|
23
27
|
export {edgeCompSlot, EDGE_COMP_ATTR} from './edgeCompensation.stylex';
|
|
24
28
|
|