@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
|
@@ -326,21 +326,201 @@ export const paddingBlockStyles = stylex.create({
|
|
|
326
326
|
});
|
|
327
327
|
|
|
328
328
|
/**
|
|
329
|
-
*
|
|
329
|
+
* Inline-start-only padding override styles.
|
|
330
|
+
* Use when a component needs to override the inline-start edge independently
|
|
331
|
+
* of inline-end. Logical, so it follows the writing direction (left in LTR,
|
|
332
|
+
* right in RTL).
|
|
333
|
+
*/
|
|
334
|
+
export const paddingInlineStartStyles = stylex.create({
|
|
335
|
+
0: {paddingInlineStart: spacingVars['--spacing-0']},
|
|
336
|
+
0.5: {paddingInlineStart: spacingVars['--spacing-0-5']},
|
|
337
|
+
1: {paddingInlineStart: spacingVars['--spacing-1']},
|
|
338
|
+
1.5: {paddingInlineStart: spacingVars['--spacing-1-5']},
|
|
339
|
+
2: {paddingInlineStart: spacingVars['--spacing-2']},
|
|
340
|
+
3: {paddingInlineStart: spacingVars['--spacing-3']},
|
|
341
|
+
4: {paddingInlineStart: spacingVars['--spacing-4']},
|
|
342
|
+
5: {paddingInlineStart: spacingVars['--spacing-5']},
|
|
343
|
+
6: {paddingInlineStart: spacingVars['--spacing-6']},
|
|
344
|
+
8: {paddingInlineStart: spacingVars['--spacing-8']},
|
|
345
|
+
10: {paddingInlineStart: spacingVars['--spacing-10']},
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Inline-end-only padding override styles.
|
|
350
|
+
* The inline-end counterpart of paddingInlineStartStyles.
|
|
351
|
+
*/
|
|
352
|
+
export const paddingInlineEndStyles = stylex.create({
|
|
353
|
+
0: {paddingInlineEnd: spacingVars['--spacing-0']},
|
|
354
|
+
0.5: {paddingInlineEnd: spacingVars['--spacing-0-5']},
|
|
355
|
+
1: {paddingInlineEnd: spacingVars['--spacing-1']},
|
|
356
|
+
1.5: {paddingInlineEnd: spacingVars['--spacing-1-5']},
|
|
357
|
+
2: {paddingInlineEnd: spacingVars['--spacing-2']},
|
|
358
|
+
3: {paddingInlineEnd: spacingVars['--spacing-3']},
|
|
359
|
+
4: {paddingInlineEnd: spacingVars['--spacing-4']},
|
|
360
|
+
5: {paddingInlineEnd: spacingVars['--spacing-5']},
|
|
361
|
+
6: {paddingInlineEnd: spacingVars['--spacing-6']},
|
|
362
|
+
8: {paddingInlineEnd: spacingVars['--spacing-8']},
|
|
363
|
+
10: {paddingInlineEnd: spacingVars['--spacing-10']},
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Container padding inline-start CSS variable style, set independently of
|
|
368
|
+
* inline-end so a per-edge override keeps edge-compensating children (Card,
|
|
369
|
+
* Divider, a nested Section) compensating against the padding actually
|
|
370
|
+
* applied on that edge.
|
|
371
|
+
*/
|
|
372
|
+
export const containerPaddingInlineStartVarStyles = stylex.create({
|
|
373
|
+
0: {'--container-padding-inline-start': spacingVars['--spacing-0']},
|
|
374
|
+
0.5: {'--container-padding-inline-start': spacingVars['--spacing-0-5']},
|
|
375
|
+
1: {'--container-padding-inline-start': spacingVars['--spacing-1']},
|
|
376
|
+
1.5: {'--container-padding-inline-start': spacingVars['--spacing-1-5']},
|
|
377
|
+
2: {'--container-padding-inline-start': spacingVars['--spacing-2']},
|
|
378
|
+
3: {'--container-padding-inline-start': spacingVars['--spacing-3']},
|
|
379
|
+
4: {'--container-padding-inline-start': spacingVars['--spacing-4']},
|
|
380
|
+
5: {'--container-padding-inline-start': spacingVars['--spacing-5']},
|
|
381
|
+
6: {'--container-padding-inline-start': spacingVars['--spacing-6']},
|
|
382
|
+
8: {'--container-padding-inline-start': spacingVars['--spacing-8']},
|
|
383
|
+
10: {'--container-padding-inline-start': spacingVars['--spacing-10']},
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Container padding inline-end CSS variable style, the counterpart of
|
|
388
|
+
* containerPaddingInlineStartVarStyles.
|
|
389
|
+
*/
|
|
390
|
+
export const containerPaddingInlineEndVarStyles = stylex.create({
|
|
391
|
+
0: {'--container-padding-inline-end': spacingVars['--spacing-0']},
|
|
392
|
+
0.5: {'--container-padding-inline-end': spacingVars['--spacing-0-5']},
|
|
393
|
+
1: {'--container-padding-inline-end': spacingVars['--spacing-1']},
|
|
394
|
+
1.5: {'--container-padding-inline-end': spacingVars['--spacing-1-5']},
|
|
395
|
+
2: {'--container-padding-inline-end': spacingVars['--spacing-2']},
|
|
396
|
+
3: {'--container-padding-inline-end': spacingVars['--spacing-3']},
|
|
397
|
+
4: {'--container-padding-inline-end': spacingVars['--spacing-4']},
|
|
398
|
+
5: {'--container-padding-inline-end': spacingVars['--spacing-5']},
|
|
399
|
+
6: {'--container-padding-inline-end': spacingVars['--spacing-6']},
|
|
400
|
+
8: {'--container-padding-inline-end': spacingVars['--spacing-8']},
|
|
401
|
+
10: {'--container-padding-inline-end': spacingVars['--spacing-10']},
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Block-start-only padding override styles.
|
|
406
|
+
* Use when a component needs to override the block-start (top) edge
|
|
407
|
+
* independently of block-end — e.g. a section that sits under a sticky
|
|
408
|
+
* header and needs less padding above than below.
|
|
409
|
+
*/
|
|
410
|
+
export const paddingBlockStartStyles = stylex.create({
|
|
411
|
+
0: {paddingBlockStart: spacingVars['--spacing-0']},
|
|
412
|
+
0.5: {paddingBlockStart: spacingVars['--spacing-0-5']},
|
|
413
|
+
1: {paddingBlockStart: spacingVars['--spacing-1']},
|
|
414
|
+
1.5: {paddingBlockStart: spacingVars['--spacing-1-5']},
|
|
415
|
+
2: {paddingBlockStart: spacingVars['--spacing-2']},
|
|
416
|
+
3: {paddingBlockStart: spacingVars['--spacing-3']},
|
|
417
|
+
4: {paddingBlockStart: spacingVars['--spacing-4']},
|
|
418
|
+
5: {paddingBlockStart: spacingVars['--spacing-5']},
|
|
419
|
+
6: {paddingBlockStart: spacingVars['--spacing-6']},
|
|
420
|
+
8: {paddingBlockStart: spacingVars['--spacing-8']},
|
|
421
|
+
10: {paddingBlockStart: spacingVars['--spacing-10']},
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Block-end-only padding override styles.
|
|
426
|
+
* The block-end counterpart of paddingBlockStartStyles.
|
|
427
|
+
*/
|
|
428
|
+
export const paddingBlockEndStyles = stylex.create({
|
|
429
|
+
0: {paddingBlockEnd: spacingVars['--spacing-0']},
|
|
430
|
+
0.5: {paddingBlockEnd: spacingVars['--spacing-0-5']},
|
|
431
|
+
1: {paddingBlockEnd: spacingVars['--spacing-1']},
|
|
432
|
+
1.5: {paddingBlockEnd: spacingVars['--spacing-1-5']},
|
|
433
|
+
2: {paddingBlockEnd: spacingVars['--spacing-2']},
|
|
434
|
+
3: {paddingBlockEnd: spacingVars['--spacing-3']},
|
|
435
|
+
4: {paddingBlockEnd: spacingVars['--spacing-4']},
|
|
436
|
+
5: {paddingBlockEnd: spacingVars['--spacing-5']},
|
|
437
|
+
6: {paddingBlockEnd: spacingVars['--spacing-6']},
|
|
438
|
+
8: {paddingBlockEnd: spacingVars['--spacing-8']},
|
|
439
|
+
10: {paddingBlockEnd: spacingVars['--spacing-10']},
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Propagation styles for `--_section-padding-propagated`.
|
|
330
444
|
* When a parent section sets explicit padding, this propagates the value
|
|
331
445
|
* through the CSS custom property cascade so nested sections that use
|
|
332
446
|
* useThemeDefault inherit the parent's padding instead of the theme default.
|
|
447
|
+
*
|
|
448
|
+
* This is deliberately NOT the public `--astryx-section-padding` token. The
|
|
449
|
+
* two carry different authority: the public token is the THEME's section
|
|
450
|
+
* padding, set once at the theme root, while this one is one ancestor
|
|
451
|
+
* Section's padding, propagated down the tree. An overlay has to drop the
|
|
452
|
+
* inherited value at its boundary (see {@link overlayPaddingReset}) without
|
|
453
|
+
* dropping the theme's — impossible while both live under one name.
|
|
454
|
+
* `container.stylex.ts` reads this ahead of the public token, so a propagated
|
|
455
|
+
* value still wins over the theme for nested sections, as before.
|
|
333
456
|
*/
|
|
334
457
|
export const sectionPaddingPropagationStyles = stylex.create({
|
|
335
|
-
0: {'--
|
|
336
|
-
0.5: {'--
|
|
337
|
-
1: {'--
|
|
338
|
-
1.5: {'--
|
|
339
|
-
2: {'--
|
|
340
|
-
3: {'--
|
|
341
|
-
4: {'--
|
|
342
|
-
5: {'--
|
|
343
|
-
6: {'--
|
|
344
|
-
8: {'--
|
|
345
|
-
10: {'--
|
|
458
|
+
0: {'--_section-padding-propagated': spacingVars['--spacing-0']},
|
|
459
|
+
0.5: {'--_section-padding-propagated': spacingVars['--spacing-0-5']},
|
|
460
|
+
1: {'--_section-padding-propagated': spacingVars['--spacing-1']},
|
|
461
|
+
1.5: {'--_section-padding-propagated': spacingVars['--spacing-1-5']},
|
|
462
|
+
2: {'--_section-padding-propagated': spacingVars['--spacing-2']},
|
|
463
|
+
3: {'--_section-padding-propagated': spacingVars['--spacing-3']},
|
|
464
|
+
4: {'--_section-padding-propagated': spacingVars['--spacing-4']},
|
|
465
|
+
5: {'--_section-padding-propagated': spacingVars['--spacing-5']},
|
|
466
|
+
6: {'--_section-padding-propagated': spacingVars['--spacing-6']},
|
|
467
|
+
8: {'--_section-padding-propagated': spacingVars['--spacing-8']},
|
|
468
|
+
10: {'--_section-padding-propagated': spacingVars['--spacing-10']},
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Padding-variable reset for overlay roots (Dialog, BottomSheet, Drawer,
|
|
473
|
+
* MobileNav, Lightbox, and every layer surface).
|
|
474
|
+
*
|
|
475
|
+
* ## Why an overlay needs this
|
|
476
|
+
*
|
|
477
|
+
* The container padding system talks to descendants through inherited custom
|
|
478
|
+
* properties: a padded container announces its padding, and children read the
|
|
479
|
+
* value either to apply it or to cancel it with a negative margin
|
|
480
|
+
* (`Section`, `Divider`, `Layout`, `Table`).
|
|
481
|
+
*
|
|
482
|
+
* Inheritance follows the DOM, but an overlay leaves its parent's visual box —
|
|
483
|
+
* a fixed/top-layer `<dialog>` is a DOM descendant of the padded page while
|
|
484
|
+
* being nowhere near it on screen. It inherits values describing padding that
|
|
485
|
+
* is not there, and its content compensates against phantom space: a `Section`
|
|
486
|
+
* inside a 640px sheet rendered 672px wide and hung off both edges (#5208).
|
|
487
|
+
*
|
|
488
|
+
* Two families leak, and they need opposite treatments:
|
|
489
|
+
*
|
|
490
|
+
* - `--container-padding-*` -> `0px`. Descendants SUBTRACT these (bleed
|
|
491
|
+
* margins). The overlay root has no padding of its own to escape, so the
|
|
492
|
+
* honest answer is zero. Nested containers that do set padding (a Dialog's
|
|
493
|
+
* content wrapper) re-announce their own values below this point, so
|
|
494
|
+
* legitimate edge-to-edge bleed inside the overlay is unaffected.
|
|
495
|
+
* - `--layout-padding-*` and `--_section-padding-propagated` -> `initial`.
|
|
496
|
+
* Descendants ADD these, so zeroing them would strip padding rather than
|
|
497
|
+
* restore it. `initial` makes each guaranteed-invalid, so readers fall
|
|
498
|
+
* through their own `var(…, fallback)` chain and land on the theme default —
|
|
499
|
+
* which is what an overlay at the top of the tree should show.
|
|
500
|
+
*
|
|
501
|
+
* `initial` is also why propagation moved off `--astryx-section-padding`: that
|
|
502
|
+
* name is public theme surface, set at the theme root, and making it invalid
|
|
503
|
+
* here would blank the theme's own section padding inside every overlay.
|
|
504
|
+
*
|
|
505
|
+
* Apply on the overlay's outermost styled element.
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```
|
|
509
|
+
* <dialog {...stylex.props(styles.dialog, overlayPaddingReset.reset)} />
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
export const overlayPaddingReset = stylex.create({
|
|
513
|
+
reset: {
|
|
514
|
+
// Subtracted by descendants — the overlay root has no padding to escape.
|
|
515
|
+
'--container-padding-inline-start': '0px',
|
|
516
|
+
'--container-padding-inline-end': '0px',
|
|
517
|
+
'--container-padding-block-start': '0px',
|
|
518
|
+
'--container-padding-block-end': '0px',
|
|
519
|
+
// Added by descendants — fall through to each reader's own default.
|
|
520
|
+
'--layout-padding-outer-x': 'initial',
|
|
521
|
+
'--layout-padding-outer-y': 'initial',
|
|
522
|
+
'--layout-padding-inner-x': 'initial',
|
|
523
|
+
'--layout-padding-inner-y': 'initial',
|
|
524
|
+
'--_section-padding-propagated': 'initial',
|
|
525
|
+
},
|
|
346
526
|
});
|
|
@@ -36,6 +36,7 @@ import {mergeProps, mergeRefs, rtlStyles} from '../utils';
|
|
|
36
36
|
import type {BaseProps} from '../BaseProps';
|
|
37
37
|
import {themeProps} from '../utils/themeProps';
|
|
38
38
|
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
39
|
+
import {overlayPaddingReset} from '../Layout/padding.stylex';
|
|
39
40
|
import {useTranslator} from '../i18n';
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -588,7 +589,7 @@ export function Lightbox({
|
|
|
588
589
|
aria-label={currentItem.alt || t('@astryx.lightbox.mediaViewer')}
|
|
589
590
|
{...mergeProps(
|
|
590
591
|
themeProps('lightbox'),
|
|
591
|
-
stylex.props(styles.dialog, xstyle),
|
|
592
|
+
stylex.props(styles.dialog, overlayPaddingReset.reset, xstyle),
|
|
592
593
|
className,
|
|
593
594
|
style,
|
|
594
595
|
)}
|
package/src/Link/Link.tsx
CHANGED
|
@@ -61,7 +61,7 @@ const styles = stylex.create({
|
|
|
61
61
|
fontWeight: 'inherit',
|
|
62
62
|
textDecoration: {
|
|
63
63
|
default: 'none',
|
|
64
|
-
':hover': {
|
|
64
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
65
65
|
'@media (hover: hover)': 'underline',
|
|
66
66
|
},
|
|
67
67
|
},
|
|
@@ -103,7 +103,7 @@ const linkColorStyles = stylex.create({
|
|
|
103
103
|
primary: {
|
|
104
104
|
color: {
|
|
105
105
|
default: colorVars['--color-text-primary'],
|
|
106
|
-
':hover': {
|
|
106
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
107
107
|
'@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-primary']}, ${colorVars['--color-tint-hover']} 15%)`,
|
|
108
108
|
},
|
|
109
109
|
},
|
|
@@ -111,7 +111,7 @@ const linkColorStyles = stylex.create({
|
|
|
111
111
|
secondary: {
|
|
112
112
|
color: {
|
|
113
113
|
default: colorVars['--color-text-secondary'],
|
|
114
|
-
':hover': {
|
|
114
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
115
115
|
'@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-secondary']}, ${colorVars['--color-tint-hover']} 15%)`,
|
|
116
116
|
},
|
|
117
117
|
},
|
|
@@ -125,7 +125,7 @@ const linkColorStyles = stylex.create({
|
|
|
125
125
|
accent: {
|
|
126
126
|
color: {
|
|
127
127
|
default: colorVars['--color-text-accent'],
|
|
128
|
-
':hover': {
|
|
128
|
+
':hover:where(:not(:disabled,[aria-disabled="true"]))': {
|
|
129
129
|
'@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-text-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
|
|
130
130
|
},
|
|
131
131
|
},
|
|
@@ -169,6 +169,7 @@ export const docs = {
|
|
|
169
169
|
{ guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
|
|
170
170
|
{ guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
|
|
171
171
|
{ guidance: true, description: 'Use inlinePlugins for custom shorthand patterns like issue refs, diff refs, and mentions instead of preprocessing the markdown string.' },
|
|
172
|
+
{ guidance: true, description: 'Pair with Outline and useOutlineFromMarkdown for section navigation: headings render generated id attributes that match the outline item ids, so hash links scroll to their target.' },
|
|
172
173
|
{ guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
|
|
173
174
|
],
|
|
174
175
|
},
|
|
@@ -381,6 +382,7 @@ export const docsZh = {
|
|
|
381
382
|
{ guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
|
|
382
383
|
{ guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
|
|
383
384
|
{ guidance: true, description: 'Use inlinePlugins for custom shorthand patterns like issue refs, diff refs, and mentions instead of preprocessing the markdown string.' },
|
|
385
|
+
{ guidance: true, description: 'Pair with Outline and useOutlineFromMarkdown for section navigation: headings render generated id attributes that match the outline item ids, so hash links scroll to their target.' },
|
|
384
386
|
{ guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
|
|
385
387
|
],
|
|
386
388
|
},
|
|
@@ -396,6 +398,7 @@ export const docsDense = {
|
|
|
396
398
|
{ guidance: true, description: 'Set headingLevelStart to match the page hierarchy, e.g. start at 3 if the markdown sits inside an h2 section.' },
|
|
397
399
|
{ guidance: true, description: 'Use contentWidth to keep prose at a readable line length in wide layouts.' },
|
|
398
400
|
{ guidance: true, description: 'Use inlinePlugins for custom shorthand patterns (issue refs, diff refs, mentions) instead of preprocessing the markdown string.' },
|
|
401
|
+
{ guidance: true, description: 'Headings render id attributes matching useOutlineFromMarkdown ids; pair with Outline for hash navigation.' },
|
|
399
402
|
{ guidance: false, description: 'Use Markdown for hand-authored layouts; use Text and Heading directly when you control the content.' },
|
|
400
403
|
],
|
|
401
404
|
},
|
|
@@ -5,6 +5,7 @@ import {render, screen, fireEvent} from '@testing-library/react';
|
|
|
5
5
|
import type {ReactNode} from 'react';
|
|
6
6
|
import {Markdown} from './Markdown';
|
|
7
7
|
import type {MarkdownInlinePlugin} from './Markdown';
|
|
8
|
+
import {parseOutlineFromMarkdown} from '../Outline/parseOutlineFromMarkdown';
|
|
8
9
|
|
|
9
10
|
describe('Markdown', () => {
|
|
10
11
|
it('renders with role="document"', () => {
|
|
@@ -23,6 +24,83 @@ describe('Markdown', () => {
|
|
|
23
24
|
expect(screen.getByText('Heading 2').tagName).toBe('H2');
|
|
24
25
|
});
|
|
25
26
|
|
|
27
|
+
describe('heading ids', () => {
|
|
28
|
+
// Outline's documented contract: an outline item id "should match the
|
|
29
|
+
// target heading element id". Markdown renders the ids that
|
|
30
|
+
// useOutlineFromMarkdown derives, so hash navigation resolves.
|
|
31
|
+
it('renders generated id attributes on headings', () => {
|
|
32
|
+
render(<Markdown>{'# Overview\n\ncontent\n\n# Installation'}</Markdown>);
|
|
33
|
+
expect(screen.getByText('Overview')).toHaveAttribute('id', 'overview');
|
|
34
|
+
expect(screen.getByText('Installation')).toHaveAttribute(
|
|
35
|
+
'id',
|
|
36
|
+
'installation',
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('disambiguates duplicate headings with numeric suffixes', () => {
|
|
41
|
+
render(<Markdown>{'# Setup\n\n# Setup\n\n# Setup'}</Markdown>);
|
|
42
|
+
const ids = screen.getAllByText('Setup').map(el => el.id);
|
|
43
|
+
expect(ids).toEqual(['setup', 'setup-1', 'setup-2']);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('renders ids matching parseOutlineFromMarkdown for the same source', () => {
|
|
47
|
+
// Parity invariant: every id the outline derives must resolve to a
|
|
48
|
+
// rendered heading with that exact id — including slugified formatting,
|
|
49
|
+
// duplicate numbering, the empty-slug fallback, and code-fence decoys.
|
|
50
|
+
const source = [
|
|
51
|
+
'# **Bold** and _italic_ text',
|
|
52
|
+
'## Setup',
|
|
53
|
+
'## Setup',
|
|
54
|
+
'### !!!',
|
|
55
|
+
'```',
|
|
56
|
+
'# not a heading',
|
|
57
|
+
'```',
|
|
58
|
+
'## The `useState` hook',
|
|
59
|
+
].join('\n\n');
|
|
60
|
+
const {container} = render(<Markdown>{source}</Markdown>);
|
|
61
|
+
const outline = parseOutlineFromMarkdown(source);
|
|
62
|
+
expect(outline.length).toBe(5);
|
|
63
|
+
for (const item of outline) {
|
|
64
|
+
const target = container.querySelector(`[id="${item.id}"]`);
|
|
65
|
+
expect(target, `no rendered heading with id "${item.id}"`).not.toBe(
|
|
66
|
+
null,
|
|
67
|
+
);
|
|
68
|
+
expect(target!.tagName).toMatch(/^H[1-6]$/);
|
|
69
|
+
expect(target!.textContent?.trim()).toBe(item.label);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('passes the generated id to a custom heading component', () => {
|
|
74
|
+
const received: (string | undefined)[] = [];
|
|
75
|
+
render(
|
|
76
|
+
<Markdown
|
|
77
|
+
components={{
|
|
78
|
+
heading: ({children, id}: {children: ReactNode; id?: string}) => {
|
|
79
|
+
received.push(id);
|
|
80
|
+
return <h2 id={id}>{children}</h2>;
|
|
81
|
+
},
|
|
82
|
+
}}>
|
|
83
|
+
{'# Overview\n\n# Overview'}
|
|
84
|
+
</Markdown>,
|
|
85
|
+
);
|
|
86
|
+
expect(received).toEqual(['overview', 'overview-1']);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not assign ids to headings nested inside blockquotes', () => {
|
|
90
|
+
// parseOutlineFromMarkdown only lists top-level headings. If nested
|
|
91
|
+
// headings consumed slugs too, duplicate numbering would drift and
|
|
92
|
+
// outline links would land on the wrong heading.
|
|
93
|
+
const source = '> # Quoted\n\n# Quoted';
|
|
94
|
+
const {container} = render(<Markdown>{source}</Markdown>);
|
|
95
|
+
const outline = parseOutlineFromMarkdown(source);
|
|
96
|
+
expect(outline.map(i => i.id)).toEqual(['quoted']);
|
|
97
|
+
const [nested, topLevel] = screen.getAllByText('Quoted');
|
|
98
|
+
expect(container.querySelector('blockquote')).toContainElement(nested);
|
|
99
|
+
expect(nested).not.toHaveAttribute('id');
|
|
100
|
+
expect(topLevel).toHaveAttribute('id', 'quoted');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
26
104
|
it('renders paragraphs as block <div> (never <p>) for composition safety', () => {
|
|
27
105
|
render(<Markdown>{'Hello world'}</Markdown>);
|
|
28
106
|
// Markdown paragraphs render as <div> so block-level inline content
|
|
@@ -53,6 +53,9 @@ import {
|
|
|
53
53
|
parseMarkdownIncremental,
|
|
54
54
|
createIncrementalState,
|
|
55
55
|
trimStreamingArtifacts,
|
|
56
|
+
inlineText,
|
|
57
|
+
slugify,
|
|
58
|
+
uniqueSlug,
|
|
56
59
|
} from './parser';
|
|
57
60
|
import type {BlockNode, InlineNode, IncrementalState} from './parser';
|
|
58
61
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -108,6 +111,14 @@ export interface MarkdownComponents {
|
|
|
108
111
|
heading?: React.ComponentType<{
|
|
109
112
|
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
110
113
|
children: React.ReactNode;
|
|
114
|
+
/**
|
|
115
|
+
* Generated slug for this heading, matching the ids produced by
|
|
116
|
+
* useOutlineFromMarkdown / parseOutlineFromMarkdown. Render it as the
|
|
117
|
+
* element's `id` to keep Outline hash navigation working. Undefined for
|
|
118
|
+
* headings nested inside blockquotes or list items (the outline only
|
|
119
|
+
* lists top-level headings).
|
|
120
|
+
*/
|
|
121
|
+
id?: string;
|
|
111
122
|
}>;
|
|
112
123
|
paragraph?: React.ComponentType<{children: React.ReactNode}>;
|
|
113
124
|
image?: React.ComponentType<{src: string; alt: string}>;
|
|
@@ -1045,6 +1056,7 @@ function renderBlock(
|
|
|
1045
1056
|
inlinePlugins: MarkdownInlinePlugin[] | undefined,
|
|
1046
1057
|
components: Partial<MarkdownComponents> | undefined,
|
|
1047
1058
|
t: TranslatorFn,
|
|
1059
|
+
headingIdMap?: ReadonlyMap<BlockNode, string>,
|
|
1048
1060
|
): SyncReactNode {
|
|
1049
1061
|
const blockAlignMargin = BLOCK_ALIGN_MARGIN[contentAlign];
|
|
1050
1062
|
const blockAlignStyle =
|
|
@@ -1071,10 +1083,15 @@ function renderBlock(
|
|
|
1071
1083
|
components,
|
|
1072
1084
|
),
|
|
1073
1085
|
);
|
|
1086
|
+
// Only top-level headings get an id: the map is built from the same
|
|
1087
|
+
// traversal parseOutlineFromMarkdown uses (which skips headings nested
|
|
1088
|
+
// in blockquotes / list items), so rendered ids and outline ids stay
|
|
1089
|
+
// identical — including duplicate-slug numbering.
|
|
1090
|
+
const headingId = headingIdMap?.get(node);
|
|
1074
1091
|
const HeadingComp = components?.heading;
|
|
1075
1092
|
if (HeadingComp) {
|
|
1076
1093
|
return (
|
|
1077
|
-
<HeadingComp key={index} level={level}>
|
|
1094
|
+
<HeadingComp key={index} level={level} id={headingId}>
|
|
1078
1095
|
{headingChildren}
|
|
1079
1096
|
</HeadingComp>
|
|
1080
1097
|
);
|
|
@@ -1083,6 +1100,7 @@ function renderBlock(
|
|
|
1083
1100
|
return (
|
|
1084
1101
|
<Tag
|
|
1085
1102
|
key={index}
|
|
1103
|
+
id={headingId}
|
|
1086
1104
|
{...mergeProps(
|
|
1087
1105
|
themeProps('markdown-heading', {density, level}),
|
|
1088
1106
|
stylex.props(
|
|
@@ -1652,6 +1670,27 @@ export function Markdown({
|
|
|
1652
1670
|
return parseMarkdown(children, parseOptions);
|
|
1653
1671
|
}, [display, smoothedText, children, isStreaming, parseOptions]);
|
|
1654
1672
|
|
|
1673
|
+
// Assign each top-level heading the slug that parseOutlineFromMarkdown
|
|
1674
|
+
// would derive for it, so Outline hash links built from the same source
|
|
1675
|
+
// always find a matching DOM id. Mirrors that function's traversal exactly:
|
|
1676
|
+
// top-level blocks only, one shared duplicate-numbering sequence.
|
|
1677
|
+
// NOTE: must stay above the `display === 'inline'` early return below —
|
|
1678
|
+
// hooks cannot be conditional.
|
|
1679
|
+
const headingIdMap = useMemo(() => {
|
|
1680
|
+
if (display === 'inline' || blocks.length === 0) {
|
|
1681
|
+
return undefined;
|
|
1682
|
+
}
|
|
1683
|
+
const map = new Map<BlockNode, string>();
|
|
1684
|
+
const counts = new Map<string, number>();
|
|
1685
|
+
for (const block of blocks) {
|
|
1686
|
+
if (block.type === 'heading') {
|
|
1687
|
+
const label = inlineText(block.children).trim();
|
|
1688
|
+
map.set(block, uniqueSlug(slugify(label), counts));
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
return map;
|
|
1692
|
+
}, [display, blocks]);
|
|
1693
|
+
|
|
1655
1694
|
const inlineNodes = useMemo(() => {
|
|
1656
1695
|
if (display !== 'inline') {
|
|
1657
1696
|
return [];
|
|
@@ -1765,6 +1804,7 @@ export function Markdown({
|
|
|
1765
1804
|
inlinePlugins,
|
|
1766
1805
|
components,
|
|
1767
1806
|
t,
|
|
1807
|
+
headingIdMap,
|
|
1768
1808
|
),
|
|
1769
1809
|
)}
|
|
1770
1810
|
</div>
|
package/src/Markdown/parser.ts
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file parser.ts
|
|
5
5
|
* @input Markdown string
|
|
6
|
-
* @output Array of MarkdownNode AST nodes
|
|
7
|
-
*
|
|
6
|
+
* @output Array of MarkdownNode AST nodes; heading slug helpers
|
|
7
|
+
* (inlineText, slugify, uniqueSlug) shared by Markdown rendering and
|
|
8
|
+
* Outline's parseOutlineFromMarkdown
|
|
9
|
+
* @position Core parser; consumed by Markdown.tsx and Outline
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
// ---------------------------------------------------------------------------
|
|
@@ -1815,3 +1817,59 @@ export function parseMarkdownIncremental(
|
|
|
1815
1817
|
|
|
1816
1818
|
return mergeSettledBlocks(settledBlocks, unsettledBlocks);
|
|
1817
1819
|
}
|
|
1820
|
+
|
|
1821
|
+
// ---------------------------------------------------------------------------
|
|
1822
|
+
// Heading slugs
|
|
1823
|
+
// ---------------------------------------------------------------------------
|
|
1824
|
+
// Single source of truth for the heading id contract: Markdown renders these
|
|
1825
|
+
// slugs as `id` attributes on h1–h6, and Outline's parseOutlineFromMarkdown
|
|
1826
|
+
// derives its item ids from the same functions, so outline hash links always
|
|
1827
|
+
// resolve to a rendered heading by construction.
|
|
1828
|
+
|
|
1829
|
+
/** Flatten inline nodes into their plain text content. */
|
|
1830
|
+
export function inlineText(nodes: InlineNode[]): string {
|
|
1831
|
+
return nodes
|
|
1832
|
+
.map(node => {
|
|
1833
|
+
switch (node.type) {
|
|
1834
|
+
case 'text':
|
|
1835
|
+
case 'code':
|
|
1836
|
+
return node.content;
|
|
1837
|
+
case 'bold':
|
|
1838
|
+
case 'italic':
|
|
1839
|
+
case 'strikethrough':
|
|
1840
|
+
case 'link':
|
|
1841
|
+
return inlineText(node.children);
|
|
1842
|
+
case 'image':
|
|
1843
|
+
return node.alt;
|
|
1844
|
+
case 'citation':
|
|
1845
|
+
case 'break':
|
|
1846
|
+
return '';
|
|
1847
|
+
}
|
|
1848
|
+
})
|
|
1849
|
+
.join('');
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
/** Turn heading text into a URL-safe slug (lowercase, hyphen-separated). */
|
|
1853
|
+
export function slugify(value: string): string {
|
|
1854
|
+
return value
|
|
1855
|
+
.trim()
|
|
1856
|
+
.toLowerCase()
|
|
1857
|
+
.replace(/['"]/g, '')
|
|
1858
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
1859
|
+
.replace(/^-+|-+$/g, '');
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
/**
|
|
1863
|
+
* Disambiguate repeated slugs with a numeric suffix (`setup`, `setup-1`, …).
|
|
1864
|
+
* Empty slugs fall back to `section`. The caller owns the counts map so one
|
|
1865
|
+
* document shares a single numbering sequence.
|
|
1866
|
+
*/
|
|
1867
|
+
export function uniqueSlug(
|
|
1868
|
+
baseSlug: string,
|
|
1869
|
+
counts: Map<string, number>,
|
|
1870
|
+
): string {
|
|
1871
|
+
const fallbackSlug = baseSlug || 'section';
|
|
1872
|
+
const count = counts.get(fallbackSlug) ?? 0;
|
|
1873
|
+
counts.set(fallbackSlug, count + 1);
|
|
1874
|
+
return count === 0 ? fallbackSlug : `${fallbackSlug}-${count}`;
|
|
1875
|
+
}
|