@astryxdesign/core 0.6.2 → 0.6.3-canary.0788c49
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 +81 -0
- package/dist/BottomSheet/BottomSheet.d.ts +1 -1
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +3 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +56 -19
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +13 -28
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +10 -5
- package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +48 -23
- package/dist/Chat/ChatComposerInput.d.ts +11 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +63 -16
- package/dist/Chat/ChatDictationButton.d.ts +3 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +6 -4
- package/dist/Chat/ChatLayout.d.ts +19 -0
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +19 -0
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +44 -34
- package/dist/Chat/ChatMessageBubble.d.ts +2 -0
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +5 -3
- package/dist/Chat/ChatMessageList.d.ts +2 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +4 -3
- package/dist/Chat/ChatMessageMetadata.d.ts +5 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +12 -9
- package/dist/Chat/ChatSendButton.d.ts +2 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +6 -4
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +12 -2
- package/dist/Citation/Citation.d.ts +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -2
- package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
- package/dist/CodeBlock/highlightRanges.js +14 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +6 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +1 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +1 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +4 -4
- package/dist/DateInput/NativeDateField.d.ts.map +1 -1
- package/dist/DateInput/NativeDateField.js +16 -16
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +2 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +4 -4
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +8 -8
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
- package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
- package/dist/Dialog/DialogHeader.d.ts +8 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +13 -4
- package/dist/Field/InputClearButton.d.ts +4 -2
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +4 -2
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +7 -7
- package/dist/Icon/Icon.d.ts +6 -31
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +8 -71
- package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
- package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
- package/dist/Icon/IconDefaultSizeContext.js +18 -0
- package/dist/Icon/IconSize.stylex.d.ts +65 -0
- package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
- package/dist/Icon/IconSize.stylex.js +75 -0
- package/dist/Item/Item.d.ts +1 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -3
- package/dist/Kbd/Kbd.d.ts +5 -3
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +36 -42
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +6 -2
- package/dist/Link/useLinkComponent.d.ts +5 -15
- package/dist/Link/useLinkComponent.d.ts.map +1 -1
- package/dist/Link/useLinkComponent.js +34 -51
- package/dist/List/List.d.ts +19 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +9 -2
- package/dist/List/ListContext.d.ts +1 -0
- package/dist/List/ListContext.d.ts.map +1 -1
- package/dist/List/ListContext.js +2 -1
- package/dist/List/ListItem.d.ts +1 -1
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +9 -2
- package/dist/Markdown/Markdown.d.ts +8 -2
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
- package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
- package/dist/Markdown/Markdown.fr23.bench.js +150 -0
- package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
- package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
- package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
- package/dist/Markdown/Markdown.js +262 -109
- package/dist/Markdown/ast.d.ts +162 -0
- package/dist/Markdown/ast.d.ts.map +1 -0
- package/dist/Markdown/ast.js +74 -0
- package/dist/Markdown/index.d.ts +5 -3
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/index.js +3 -2
- package/dist/Markdown/parser/index.d.ts +10 -0
- package/dist/Markdown/parser/index.d.ts.map +1 -0
- package/dist/Markdown/parser/index.js +10 -0
- package/dist/Markdown/parser.d.ts +126 -58
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +726 -177
- package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
- package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
- package/dist/Markdown/plugins/frontmatter.js +132 -0
- package/dist/Markdown/plugins/index.d.ts +17 -0
- package/dist/Markdown/plugins/index.d.ts.map +1 -0
- package/dist/Markdown/plugins/index.js +14 -0
- package/dist/Markdown/plugins/protocol.d.ts +191 -0
- package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
- package/dist/Markdown/plugins/protocol.js +957 -0
- package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
- package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
- package/dist/Markdown/plugins/semanticFence.js +213 -0
- package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
- package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
- package/dist/Markdown/plugins/softBreaks.js +172 -0
- package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
- package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
- package/dist/Markdown/plugins/sourceDecoration.js +393 -0
- package/dist/Markdown/plugins/textTransform.d.ts +30 -0
- package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
- package/dist/Markdown/plugins/textTransform.js +374 -0
- package/dist/Markdown/remark.d.ts +196 -0
- package/dist/Markdown/remark.d.ts.map +1 -0
- package/dist/Markdown/remark.js +1062 -0
- package/dist/Markdown/url.d.ts +6 -0
- package/dist/Markdown/url.d.ts.map +1 -0
- package/dist/Markdown/url.js +31 -0
- package/dist/Markdown/utils.d.ts +4 -2
- package/dist/Markdown/utils.d.ts.map +1 -1
- package/dist/Markdown/utils.js +2 -1
- package/dist/MetadataList/MetadataList.js +3 -3
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +4 -4
- package/dist/Outline/index.d.ts +1 -0
- package/dist/Outline/index.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
- package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
- package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/useOutlineFromMarkdown.js +8 -3
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +36 -31
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -1
- package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
- package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
- package/dist/ScrollableArea/ScrollableArea.js +1 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +1 -0
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
- package/dist/Selector/Selector.d.ts +9 -7
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +16 -7
- package/dist/SideNav/SideNav.d.ts +2 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +9 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +28 -12
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +23 -7
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +11 -0
- package/dist/TabList/Tab.d.ts +1 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +20 -7
- package/dist/Table/Table.d.ts +1 -0
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +29 -13
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +1 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +2 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +4 -4
- package/dist/Timer/Timer.d.ts +49 -0
- package/dist/Timer/Timer.d.ts.map +1 -0
- package/dist/Timer/Timer.js +158 -0
- package/dist/Timer/index.d.ts +9 -0
- package/dist/Timer/index.d.ts.map +1 -0
- package/dist/Timer/index.js +10 -0
- package/dist/ToggleButton/ToggleButton.d.ts +9 -6
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +15 -27
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +3 -2
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +3 -0
- package/dist/TreeList/TreeListItem.d.ts +6 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +12 -2
- package/dist/TreeList/TreeListTypes.d.ts +8 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +16 -7
- package/dist/astryx.css +27 -11
- package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
- package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
- package/dist/hooks/scrollKeyboardDelegation.js +146 -0
- package/dist/hooks/useClickableContainer.d.ts +10 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +15 -4
- package/dist/hooks/useScrollableArea.d.ts +6 -2
- package/dist/hooks/useScrollableArea.d.ts.map +1 -1
- package/dist/hooks/useScrollableArea.js +17 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/theme/declarationBoundary.d.ts +17 -0
- package/dist/theme/declarationBoundary.d.ts.map +1 -0
- package/dist/theme/declarationBoundary.js +343 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +4 -0
- package/dist/theme/generateThemeRules.d.ts +13 -7
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +140 -34
- package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +9 -0
- package/dist/utils/safeUrl.d.ts +11 -0
- package/dist/utils/safeUrl.d.ts.map +1 -0
- package/dist/utils/safeUrl.js +78 -0
- package/locales/af-ZA.json +530 -1
- package/locales/ar-SA.json +490 -1
- package/locales/ca-ES.json +514 -1
- package/locales/cs-CZ.json +498 -1
- package/locales/da-DK.json +522 -1
- package/locales/de-DE.json +522 -1
- package/locales/el-GR.json +498 -1
- package/locales/es-ES.json +510 -1
- package/locales/fi-FI.json +498 -1
- package/locales/fr-FR.json +534 -1
- package/locales/he-IL.json +498 -1
- package/locales/hu-HU.json +498 -1
- package/locales/it-IT.json +510 -1
- package/locales/ja-JP.json +490 -1
- package/locales/ko-KR.json +498 -1
- package/locales/nl-NL.json +534 -1
- package/locales/no-NO.json +510 -1
- package/locales/pl-PL.json +506 -1
- package/locales/pt-BR.json +506 -1
- package/locales/pt-PT.json +506 -1
- package/locales/ro-RO.json +506 -1
- package/locales/ru-RU.json +498 -1
- package/locales/sr-SP.json +498 -1
- package/locales/sv-SE.json +502 -1
- package/locales/tr-TR.json +498 -1
- package/locales/uk-UA.json +498 -1
- package/locales/vi-VN.json +502 -1
- package/locales/zh-CN.json +490 -1
- package/locales/zh-TW.json +490 -1
- package/package.json +24 -4
- package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
- package/src/BottomSheet/BottomSheet.spec.md +46 -20
- package/src/BottomSheet/BottomSheet.test.tsx +6 -3
- package/src/BottomSheet/BottomSheet.tsx +3 -1
- package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
- package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
- package/src/Button/Button.doc.mjs +5 -5
- package/src/Button/Button.tsx +15 -13
- package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
- package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
- package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
- package/src/Button/__tests__/Button.a11y.states.ts +9 -0
- package/src/Chat/ChatComposer.doc.mjs +14 -0
- package/src/Chat/ChatComposer.spec.md +230 -0
- package/src/Chat/ChatComposer.test.tsx +57 -0
- package/src/Chat/ChatComposer.tsx +21 -9
- package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
- package/src/Chat/ChatComposerDrawer.spec.md +267 -0
- package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
- package/src/Chat/ChatComposerDrawer.tsx +38 -9
- package/src/Chat/ChatComposerInput.doc.mjs +114 -26
- package/src/Chat/ChatComposerInput.spec.md +185 -0
- package/src/Chat/ChatComposerInput.test.tsx +113 -3
- package/src/Chat/ChatComposerInput.tsx +78 -13
- package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
- package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
- package/src/Chat/ChatDictationButton.doc.mjs +3 -3
- package/src/Chat/ChatDictationButton.spec.md +160 -0
- package/src/Chat/ChatDictationButton.test.tsx +92 -27
- package/src/Chat/ChatDictationButton.tsx +8 -6
- package/src/Chat/ChatLayout.doc.mjs +12 -4
- package/src/Chat/ChatLayout.spec.md +271 -0
- package/src/Chat/ChatLayout.test.tsx +28 -0
- package/src/Chat/ChatLayout.tsx +19 -0
- package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
- package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
- package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
- package/src/Chat/ChatMessageBubble.spec.md +263 -0
- package/src/Chat/ChatMessageBubble.test.tsx +93 -0
- package/src/Chat/ChatMessageBubble.tsx +8 -3
- package/src/Chat/ChatMessageList.spec.md +222 -0
- package/src/Chat/ChatMessageList.test.tsx +64 -2
- package/src/Chat/ChatMessageList.tsx +4 -3
- package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
- package/src/Chat/ChatMessageMetadata.spec.md +220 -0
- package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
- package/src/Chat/ChatMessageMetadata.tsx +13 -13
- package/src/Chat/ChatSendButton.doc.mjs +32 -0
- package/src/Chat/ChatSendButton.spec.md +227 -0
- package/src/Chat/ChatSendButton.test.tsx +128 -8
- package/src/Chat/ChatSendButton.tsx +6 -4
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
- package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
- package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
- package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
- package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
- package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +1522 -0
- package/src/Chat/index.ts +1 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -1
- package/src/Citation/Citation.doc.mjs +2 -2
- package/src/Citation/Citation.test.tsx +17 -0
- package/src/Citation/Citation.tsx +4 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
- package/src/ClickableCard/ClickableCard.test.tsx +102 -5
- package/src/CodeBlock/highlightRanges.test.ts +143 -1
- package/src/CodeBlock/highlightRanges.ts +15 -5
- package/src/Collapsible/Collapsible.doc.mjs +11 -0
- package/src/Collapsible/Collapsible.test.tsx +21 -0
- package/src/Collapsible/Collapsible.tsx +5 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
- package/src/ComplexSelector/ComplexSelector.tsx +6 -1
- package/src/DateInput/DateInput.tsx +6 -1
- package/src/DateInput/NativeDateField.tsx +24 -8
- package/src/DateInput/TouchDateField.tsx +6 -2
- package/src/DateRangeInput/DateRangeInput.tsx +6 -1
- package/src/DateTimeInput/DateTimeInput.tsx +6 -1
- package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
- package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
- package/src/Dialog/Dialog.doc.mjs +2 -0
- package/src/Dialog/DialogHeader.doc.mjs +22 -0
- package/src/Dialog/DialogHeader.test.tsx +167 -3
- package/src/Dialog/DialogHeader.tsx +37 -6
- package/src/Dialog/modules/DialogHeader.spec.md +101 -42
- package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
- package/src/Field/InputClearButton.test.tsx +17 -3
- package/src/Field/InputClearButton.tsx +5 -2
- package/src/Field/PanelSearchInput.tsx +5 -2
- package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
- package/src/FileInput/FileInput.tsx +11 -2
- package/src/Icon/Icon.doc.mjs +7 -5
- package/src/Icon/Icon.spec.md +81 -40
- package/src/Icon/Icon.test.tsx +6 -3
- package/src/Icon/Icon.tsx +20 -68
- package/src/Icon/IconDefaultSizeContext.ts +23 -0
- package/src/Icon/IconSize.stylex.ts +70 -0
- package/src/IconButton/IconButton.doc.mjs +3 -3
- package/src/IconButton/IconButton.test.tsx +40 -0
- package/src/Item/Item.doc.mjs +6 -2
- package/src/Item/Item.tsx +9 -3
- package/src/Kbd/Kbd.doc.mjs +3 -3
- package/src/Kbd/Kbd.test.tsx +57 -1
- package/src/Kbd/Kbd.tsx +57 -37
- package/src/Layout/LayoutFooter.doc.mjs +17 -0
- package/src/Link/Link.doc.mjs +17 -4
- package/src/Link/Link.test.tsx +24 -0
- package/src/Link/Link.tsx +5 -0
- package/src/Link/LinkProvider.doc.mjs +2 -2
- package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
- package/src/Link/useLinkComponent.test.tsx +333 -0
- package/src/Link/useLinkComponent.ts +29 -57
- package/src/List/List.doc.mjs +6 -0
- package/src/List/List.spec.md +200 -0
- package/src/List/List.test.tsx +117 -1
- package/src/List/List.tsx +22 -2
- package/src/List/ListContext.tsx +3 -1
- package/src/List/ListItem.doc.mjs +2 -2
- package/src/List/ListItem.source-build.test.mjs +41 -0
- package/src/List/ListItem.tsx +26 -2
- package/src/Markdown/Markdown.doc.mjs +300 -2
- package/src/Markdown/Markdown.fr23.bench.ts +174 -0
- package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
- package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
- package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
- package/src/Markdown/Markdown.public.test.ts +130 -3
- package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
- package/src/Markdown/Markdown.spec.md +210 -45
- package/src/Markdown/Markdown.test.tsx +87 -3
- package/src/Markdown/Markdown.tsx +414 -135
- package/src/Markdown/ast.test.ts +307 -0
- package/src/Markdown/ast.ts +337 -0
- package/src/Markdown/incremental.test.ts +43 -0
- package/src/Markdown/index.ts +37 -1
- package/src/Markdown/modules/remark.spec.md +269 -0
- package/src/Markdown/modules/softBreaks.spec.md +137 -0
- package/src/Markdown/parser/index.ts +64 -0
- package/src/Markdown/parser.public.test.ts +103 -0
- package/src/Markdown/parser.test.ts +38 -6
- package/src/Markdown/parser.ts +1221 -242
- package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
- package/src/Markdown/plugins/frontmatter.ts +198 -0
- package/src/Markdown/plugins/index.ts +54 -0
- package/src/Markdown/plugins/protocol.test.tsx +1022 -0
- package/src/Markdown/plugins/protocol.ts +1618 -0
- package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
- package/src/Markdown/plugins/semanticFence.ts +424 -0
- package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
- package/src/Markdown/plugins/softBreaks.ts +169 -0
- package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
- package/src/Markdown/plugins/sourceDecoration.ts +539 -0
- package/src/Markdown/plugins/textTransform.test.ts +467 -0
- package/src/Markdown/plugins/textTransform.ts +554 -0
- package/src/Markdown/remark.test.tsx +1877 -0
- package/src/Markdown/remark.ts +1574 -0
- package/src/Markdown/url.ts +36 -0
- package/src/Markdown/utils.ts +13 -1
- package/src/MetadataList/MetadataList.test.tsx +4 -2
- package/src/MetadataList/MetadataList.tsx +3 -3
- package/src/MultiSelector/MultiSelector.test.tsx +1 -35
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
- package/src/NumberInput/NumberInput.tsx +6 -1
- package/src/Outline/Outline.doc.mjs +7 -5
- package/src/Outline/Outline.spec.md +1 -1
- package/src/Outline/index.ts +1 -0
- package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
- package/src/Outline/useOutlineFromMarkdown.ts +15 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
- package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
- package/src/ProgressBar/ProgressBar.test.tsx +29 -11
- package/src/ProgressBar/ProgressBar.tsx +59 -72
- package/src/RadioList/RadioList.doc.mjs +11 -0
- package/src/RadioList/RadioList.test.tsx +32 -0
- package/src/RadioList/RadioListItem.tsx +25 -1
- package/src/ScrollableArea/ScrollableArea.tsx +1 -0
- package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
- package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
- package/src/SegmentedControl/SegmentedControl.test.tsx +61 -0
- package/src/SegmentedControl/SegmentedControl.tsx +2 -1
- package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
- package/src/Selector/Selector.doc.mjs +3 -3
- package/src/Selector/Selector.spec.md +51 -49
- package/src/Selector/Selector.test.tsx +61 -55
- package/src/Selector/Selector.tsx +34 -15
- package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
- package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
- package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
- package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
- package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
- package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
- package/src/SideNav/SideNav.doc.mjs +1 -1
- package/src/SideNav/SideNav.test.tsx +10 -0
- package/src/SideNav/SideNav.tsx +14 -2
- package/src/Slider/Slider.doc.mjs +17 -3
- package/src/Slider/Slider.test.tsx +221 -0
- package/src/Slider/Slider.tsx +40 -9
- package/src/Spinner/Spinner.test.tsx +4 -0
- package/src/Spinner/Spinner.tsx +31 -18
- package/src/Switch/Switch.doc.mjs +11 -0
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +28 -0
- package/src/TabList/Tab.tsx +35 -7
- package/src/TabList/TabList.doc.mjs +11 -0
- package/src/TabList/TabList.spec.md +204 -0
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
- package/src/Table/Table.doc.mjs +1 -1
- package/src/Table/Table.spec.md +54 -40
- package/src/Table/Table.test.tsx +83 -10
- package/src/Table/Table.tsx +30 -22
- package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
- package/src/TextArea/TextArea.tsx +6 -1
- package/src/TextInput/TextInput.test.tsx +20 -1
- package/src/TextInput/TextInput.tsx +6 -1
- package/src/TimeInput/TimeInput.tsx +6 -1
- package/src/Timer/Timer.doc.mjs +183 -0
- package/src/Timer/Timer.spec.md +215 -0
- package/src/Timer/Timer.test.tsx +302 -0
- package/src/Timer/Timer.tsx +258 -0
- package/src/Timer/index.ts +11 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
- package/src/ToggleButton/ToggleButton.test.tsx +299 -4
- package/src/ToggleButton/ToggleButton.tsx +26 -33
- package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
- package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
- package/src/Token/Token.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.spec.md +142 -75
- package/src/TopNav/TopNavMenu.doc.mjs +2 -2
- package/src/TopNav/TopNavMenu.test.tsx +30 -0
- package/src/TopNav/TopNavMenu.tsx +7 -2
- package/src/TreeList/TreeList.doc.mjs +3 -3
- package/src/TreeList/TreeList.spec.md +123 -75
- package/src/TreeList/TreeList.test.tsx +29 -0
- package/src/TreeList/TreeList.tsx +3 -0
- package/src/TreeList/TreeListItem.tsx +15 -1
- package/src/TreeList/TreeListTypes.ts +11 -1
- package/src/Typeahead/BaseTypeahead.spec.md +4 -3
- package/src/Typeahead/BaseTypeahead.tsx +21 -7
- package/src/Typeahead/Typeahead.test.tsx +53 -0
- package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
- package/src/__tests__/pressState.ts +93 -0
- package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
- package/src/hooks/scrollKeyboardDelegation.ts +233 -0
- package/src/hooks/useClickableContainer.test.tsx +236 -0
- package/src/hooks/useClickableContainer.ts +20 -4
- package/src/hooks/useScrollableArea.doc.mjs +15 -3
- package/src/hooks/useScrollableArea.test.tsx +59 -1
- package/src/hooks/useScrollableArea.ts +34 -10
- package/src/index.ts +3 -0
- package/src/inputFontFloor.test.ts +106 -0
- package/src/tailwind-theme.css +0 -6
- package/src/theme/Theme.test.tsx +32 -0
- package/src/theme/declarationBoundary.test.ts +126 -0
- package/src/theme/declarationBoundary.ts +347 -0
- package/src/theme/derivedVarRegistry.test.ts +7 -0
- package/src/theme/derivedVarRegistry.ts +1 -0
- package/src/theme/generateThemeRules.test.ts +526 -1
- package/src/theme/generateThemeRules.ts +228 -50
- package/src/theme/tokenValueCompat.test.ts +4 -1
- package/src/utils/interactionOverlay.stylex.ts +20 -0
- package/src/utils/safeUrl.test.ts +88 -0
- package/src/utils/safeUrl.ts +85 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file url.ts
|
|
5
|
+
* @input Untrusted Markdown link or image destination
|
|
6
|
+
* @output Parser-compatible acceptance and normalized render-safe destinations
|
|
7
|
+
* @position Shared URL policy for parser, transforms, and renderer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {isSafeUrl, sanitizeUrl} from '../utils/safeUrl';
|
|
11
|
+
|
|
12
|
+
const RENDER_DANGEROUS_URL_PATTERN = /^(?:javascript:|data:|vbscript:)/i;
|
|
13
|
+
|
|
14
|
+
function normalizeMarkdownUrl(url: string): string {
|
|
15
|
+
// Browsers ignore embedded controls in schemes, so normalize before checking.
|
|
16
|
+
// eslint-disable-next-line no-control-regex -- control chars are the bypass
|
|
17
|
+
return url.replace(/[\x00-\x1f\x7f]/g, '').trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Preserve the released parser policy for no-plugin output compatibility. */
|
|
21
|
+
export function isSafeMarkdownParserUrl(url: string): boolean {
|
|
22
|
+
return isSafeUrl(url);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Navigation and image rendering deliberately have different policies. */
|
|
26
|
+
export function sanitizeMarkdownLinkUrl(url: string): string | null {
|
|
27
|
+
const normalized = sanitizeUrl(url);
|
|
28
|
+
return normalized === '' ? null : normalized;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function sanitizeMarkdownUrl(url: string): string | null {
|
|
32
|
+
const normalized = normalizeMarkdownUrl(url);
|
|
33
|
+
return normalized !== '' && !RENDER_DANGEROUS_URL_PATTERN.test(normalized)
|
|
34
|
+
? normalized
|
|
35
|
+
: null;
|
|
36
|
+
}
|
package/src/Markdown/utils.ts
CHANGED
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file utils.ts
|
|
5
|
-
* @output Server-safe
|
|
5
|
+
* @output Server-safe exports for Markdown parsing and AST traversal
|
|
6
6
|
* @position Subpath entry point: `@astryxdesign/core/Markdown/utils`
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
export {visitMarkdownNodes} from './ast';
|
|
10
|
+
export type {
|
|
11
|
+
MarkdownAstExtensionNode,
|
|
12
|
+
MarkdownAstPhrasingContent,
|
|
13
|
+
MarkdownAstBlockContent,
|
|
14
|
+
MarkdownAstRoot,
|
|
15
|
+
MarkdownAstNodeMap,
|
|
16
|
+
MarkdownAstNode,
|
|
17
|
+
} from './ast';
|
|
18
|
+
|
|
9
19
|
export {
|
|
10
20
|
parseMarkdown,
|
|
11
21
|
parseInline,
|
|
@@ -26,5 +36,7 @@ export type {
|
|
|
26
36
|
TableAlignment,
|
|
27
37
|
ParseOptions,
|
|
28
38
|
MathParseOptions,
|
|
39
|
+
IncrementalParseOptions,
|
|
40
|
+
IncrementalMathParseOptions,
|
|
29
41
|
IncrementalState,
|
|
30
42
|
} from './parser';
|
|
@@ -148,7 +148,9 @@ describe('MetadataList', () => {
|
|
|
148
148
|
</MetadataList>,
|
|
149
149
|
);
|
|
150
150
|
|
|
151
|
-
expect(gridTemplateOf(container)).toContain(
|
|
151
|
+
expect(gridTemplateOf(container)).toContain(
|
|
152
|
+
'repeat(3, auto minmax(0, 1fr))',
|
|
153
|
+
);
|
|
152
154
|
});
|
|
153
155
|
|
|
154
156
|
it('leaves the grid to the static rule for columns="multi"', () => {
|
|
@@ -178,7 +180,7 @@ describe('MetadataList', () => {
|
|
|
178
180
|
</MetadataList>,
|
|
179
181
|
);
|
|
180
182
|
|
|
181
|
-
expect(gridTemplateOf(container)).toContain('120px 1fr');
|
|
183
|
+
expect(gridTemplateOf(container)).toContain('120px minmax(0, 1fr)');
|
|
182
184
|
});
|
|
183
185
|
});
|
|
184
186
|
});
|
|
@@ -113,7 +113,7 @@ const styles = stylex.create({
|
|
|
113
113
|
// Vertical orientation — grid layout for label-value pairs
|
|
114
114
|
gridSingle: {
|
|
115
115
|
display: 'grid',
|
|
116
|
-
gridTemplateColumns: 'auto 1fr',
|
|
116
|
+
gridTemplateColumns: 'auto minmax(0, 1fr)',
|
|
117
117
|
gap: `${spacingVars['--spacing-2']} ${spacingVars['--spacing-4']}`,
|
|
118
118
|
alignItems: 'baseline',
|
|
119
119
|
},
|
|
@@ -263,7 +263,7 @@ export function MetadataList({
|
|
|
263
263
|
if (typeof columns === 'number' && columns > 1) {
|
|
264
264
|
return isStacked
|
|
265
265
|
? `repeat(${columns}, 1fr)`
|
|
266
|
-
: `repeat(${columns}, auto 1fr)`;
|
|
266
|
+
: `repeat(${columns}, auto minmax(0, 1fr))`;
|
|
267
267
|
}
|
|
268
268
|
// A custom label width only applies to the label track of side labels.
|
|
269
269
|
if (!isStacked && labelConfig.width != null) {
|
|
@@ -271,7 +271,7 @@ export function MetadataList({
|
|
|
271
271
|
typeof labelConfig.width === 'number'
|
|
272
272
|
? `${labelConfig.width}px`
|
|
273
273
|
: labelConfig.width;
|
|
274
|
-
return `${width} 1fr`;
|
|
274
|
+
return `${width} minmax(0, 1fr)`;
|
|
275
275
|
}
|
|
276
276
|
return null;
|
|
277
277
|
};
|
|
@@ -478,39 +478,6 @@ describe('MultiSelector', () => {
|
|
|
478
478
|
expect(trigger).toHaveAttribute('aria-required', 'true');
|
|
479
479
|
});
|
|
480
480
|
|
|
481
|
-
it('renders listbox with aria-multiselectable', async () => {
|
|
482
|
-
const user = userEvent.setup();
|
|
483
|
-
render(
|
|
484
|
-
<MultiSelector
|
|
485
|
-
label="Fruit"
|
|
486
|
-
options={defaultOptions}
|
|
487
|
-
value={[]}
|
|
488
|
-
onChange={() => {}}
|
|
489
|
-
/>,
|
|
490
|
-
);
|
|
491
|
-
|
|
492
|
-
await user.click(screen.getByRole('combobox'));
|
|
493
|
-
const listbox = screen.getByRole('listbox', h);
|
|
494
|
-
expect(listbox).toHaveAttribute('aria-multiselectable', 'true');
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
it('marks selected options with aria-selected', async () => {
|
|
498
|
-
const user = userEvent.setup();
|
|
499
|
-
render(
|
|
500
|
-
<MultiSelector
|
|
501
|
-
label="Fruit"
|
|
502
|
-
options={defaultOptions}
|
|
503
|
-
value={['Apple']}
|
|
504
|
-
onChange={() => {}}
|
|
505
|
-
/>,
|
|
506
|
-
);
|
|
507
|
-
|
|
508
|
-
await user.click(screen.getByRole('combobox'));
|
|
509
|
-
const options = screen.getAllByRole('option', h);
|
|
510
|
-
expect(options[0]).toHaveAttribute('aria-selected', 'true');
|
|
511
|
-
expect(options[1]).toHaveAttribute('aria-selected', 'false');
|
|
512
|
-
});
|
|
513
|
-
|
|
514
481
|
it('shows error status with aria-invalid', () => {
|
|
515
482
|
render(
|
|
516
483
|
<MultiSelector
|
|
@@ -1393,8 +1360,7 @@ describe('MultiSelector', () => {
|
|
|
1393
1360
|
await user.click(screen.getByRole('combobox'));
|
|
1394
1361
|
const options = screen.getAllByRole('option', h);
|
|
1395
1362
|
expect(options).toHaveLength(3);
|
|
1396
|
-
|
|
1397
|
-
expect(group).toHaveAttribute('aria-label', 'Citrus');
|
|
1363
|
+
expect(screen.getByText('Citrus')).toBeInTheDocument();
|
|
1398
1364
|
});
|
|
1399
1365
|
|
|
1400
1366
|
it('shows loading state with a spinner and aria-busy', () => {
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file MultiSelector.listbox.a11y.test.tsx
|
|
5
|
+
* @input Uses MultiSelector, its part/state inventory, and the shared Listbox contract
|
|
6
|
+
* @output DOM evidence for real multi-select listbox, group, and option parts
|
|
7
|
+
* @position Component-facing binding; API, form, composition, and styling stay local.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {cleanup, render, screen, within} from '@testing-library/react';
|
|
11
|
+
import userEvent from '@testing-library/user-event';
|
|
12
|
+
import {describe, expect, it} from 'vitest';
|
|
13
|
+
import {
|
|
14
|
+
expectAccessibilitySpec,
|
|
15
|
+
LISTBOX_PATTERN,
|
|
16
|
+
} from '@astryxdesign/a11y-spec';
|
|
17
|
+
import {MultiSelector} from '../MultiSelector';
|
|
18
|
+
import {
|
|
19
|
+
LISTBOX_SCENARIOS,
|
|
20
|
+
listboxParts,
|
|
21
|
+
} from '../../Selector/__tests__/Listbox.a11y.states';
|
|
22
|
+
import {installListboxDialogStubs} from '../../Selector/__tests__/Listbox.a11y.dom';
|
|
23
|
+
|
|
24
|
+
installListboxDialogStubs();
|
|
25
|
+
|
|
26
|
+
const scenarios = LISTBOX_SCENARIOS.filter(
|
|
27
|
+
scenario => scenario.component === 'MultiSelector',
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
describe('MultiSelector Listbox semantic binding', () => {
|
|
31
|
+
it.each(scenarios)('$id', async scenario => {
|
|
32
|
+
for (const part of listboxParts(scenario)) {
|
|
33
|
+
await expectAccessibilitySpec({
|
|
34
|
+
spec: LISTBOX_PATTERN,
|
|
35
|
+
binding: `MultiSelector.${part.role}`,
|
|
36
|
+
state: part.state,
|
|
37
|
+
facts: part.facts,
|
|
38
|
+
render: async () => {
|
|
39
|
+
render(
|
|
40
|
+
<div dir={scenario.direction ?? 'ltr'}>
|
|
41
|
+
<MultiSelector
|
|
42
|
+
label="Fruit"
|
|
43
|
+
options={scenario.options}
|
|
44
|
+
value={scenario.values}
|
|
45
|
+
onChange={() => {}}
|
|
46
|
+
hasSearch={scenario.hasSearch}
|
|
47
|
+
hasSelectAll={scenario.hasSelectAll}
|
|
48
|
+
presentation={scenario.presentation}
|
|
49
|
+
isLoading={scenario.isLoading}
|
|
50
|
+
isLabelHidden={scenario.hiddenLabel}
|
|
51
|
+
renderOption={
|
|
52
|
+
scenario.customContent
|
|
53
|
+
? option => <span>{option.label} details</span>
|
|
54
|
+
: undefined
|
|
55
|
+
}
|
|
56
|
+
isDefaultOpen
|
|
57
|
+
/>
|
|
58
|
+
</div>,
|
|
59
|
+
);
|
|
60
|
+
await screen.findByRole('listbox', {hidden: true});
|
|
61
|
+
if (scenario.query != null) {
|
|
62
|
+
await userEvent
|
|
63
|
+
.setup()
|
|
64
|
+
.type(
|
|
65
|
+
screen.getByRole('combobox', {hidden: true}),
|
|
66
|
+
scenario.query,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
subject: () =>
|
|
71
|
+
part.role === 'listbox'
|
|
72
|
+
? screen.getByRole('listbox', {hidden: true})
|
|
73
|
+
: part.role === 'group'
|
|
74
|
+
? within(
|
|
75
|
+
screen.getByRole('listbox', {hidden: true}),
|
|
76
|
+
).getAllByRole('group', {hidden: true})[
|
|
77
|
+
scenario.groups.indexOf(part.name ?? '')
|
|
78
|
+
]
|
|
79
|
+
: within(screen.getByRole('listbox', {hidden: true})).getByRole(
|
|
80
|
+
'option',
|
|
81
|
+
{name: part.name, hidden: true},
|
|
82
|
+
),
|
|
83
|
+
related: () => {
|
|
84
|
+
const listbox = screen.getByRole('listbox', {hidden: true});
|
|
85
|
+
expect(
|
|
86
|
+
within(listbox).getAllByRole('option', {hidden: true}),
|
|
87
|
+
).toHaveLength(scenario.expectedOptions.length);
|
|
88
|
+
return {
|
|
89
|
+
listbox,
|
|
90
|
+
...Object.fromEntries(
|
|
91
|
+
scenario.expectedOptions.map(option => [
|
|
92
|
+
`option:${option.value}`,
|
|
93
|
+
within(listbox).getByRole('option', {
|
|
94
|
+
name: option.name,
|
|
95
|
+
hidden: true,
|
|
96
|
+
}),
|
|
97
|
+
]),
|
|
98
|
+
),
|
|
99
|
+
...Object.fromEntries(
|
|
100
|
+
scenario.groups.map((name, index) => [
|
|
101
|
+
`group:${name}`,
|
|
102
|
+
within(listbox).getAllByRole('group', {hidden: true})[index],
|
|
103
|
+
]),
|
|
104
|
+
),
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
cleanup,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('keeps the bounded state matrix and select-all states explicit', () => {
|
|
113
|
+
expect(scenarios.map(scenario => scenario.id)).toEqual([
|
|
114
|
+
'multiple-unset',
|
|
115
|
+
'multiple-selected',
|
|
116
|
+
'multiple-disabled-selected',
|
|
117
|
+
'multiple-grouped',
|
|
118
|
+
'multiple-filtered',
|
|
119
|
+
'multiple-custom-rtl',
|
|
120
|
+
'multiple-sheet',
|
|
121
|
+
'multiple-sheet-search',
|
|
122
|
+
'multiple-loading',
|
|
123
|
+
'multiple-select-all-none',
|
|
124
|
+
'multiple-select-all-partial',
|
|
125
|
+
'multiple-select-all-all',
|
|
126
|
+
]);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -105,9 +105,14 @@ const styles = stylex.create({
|
|
|
105
105
|
borderStyle: 'none',
|
|
106
106
|
padding: 0,
|
|
107
107
|
fontFamily: typographyVars['--font-family-body'],
|
|
108
|
+
// The 16px floor is iOS-only: iOS Safari zooms the page when a focused
|
|
109
|
+
// control sits under 16px, and only iOS WebKit implements
|
|
110
|
+
// -webkit-touch-callout to key the coarse-pointer floor to it.
|
|
108
111
|
fontSize: {
|
|
109
112
|
default: typeScaleVars['--text-body-size'],
|
|
110
|
-
'@media (pointer: coarse)':
|
|
113
|
+
'@media (pointer: coarse)': {
|
|
114
|
+
'@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
|
|
115
|
+
},
|
|
111
116
|
},
|
|
112
117
|
lineHeight: typeScaleVars['--text-body-leading'],
|
|
113
118
|
color: colorVars['--color-text-primary'],
|
|
@@ -196,11 +196,13 @@ function ControlledOutline() {
|
|
|
196
196
|
code: `
|
|
197
197
|
import {Outline, useOutlineFromMarkdown} from '@astryxdesign/core/Outline';
|
|
198
198
|
|
|
199
|
-
function MarkdownOutline({markdown}) {
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
function MarkdownOutline({markdown, plugins, isStreaming}) {
|
|
200
|
+
// Pass the same plugins and finality to Markdown and Outline so transformed
|
|
201
|
+
// headings share labels and ids while content streams.
|
|
202
|
+
const items = useOutlineFromMarkdown(markdown, {
|
|
203
|
+
plugins,
|
|
204
|
+
isFinal: !isStreaming,
|
|
205
|
+
});
|
|
204
206
|
return <Outline items={items} />;
|
|
205
207
|
}
|
|
206
208
|
`,
|
|
@@ -12,7 +12,7 @@ owners: [cixzhang]
|
|
|
12
12
|
review_triggers: [theming]
|
|
13
13
|
verified_by:
|
|
14
14
|
[packages/core/src/Outline/Outline.test.tsx, scripts/check-knowledge.mjs]
|
|
15
|
-
modules: []
|
|
15
|
+
modules: [module:Outline/parseOutlineFromMarkdown]
|
|
16
16
|
families: []
|
|
17
17
|
design_specs: []
|
|
18
18
|
architecture: [architecture:component-theming-surface]
|
package/src/Outline/index.ts
CHANGED
|
@@ -15,5 +15,6 @@ export {Outline} from './Outline';
|
|
|
15
15
|
export type {OutlineProps} from './Outline';
|
|
16
16
|
export type {OutlineItem} from './types';
|
|
17
17
|
export {parseOutlineFromMarkdown} from './parseOutlineFromMarkdown';
|
|
18
|
+
export type {ParseOutlineFromMarkdownOptions} from './parseOutlineFromMarkdown';
|
|
18
19
|
export {useOutlineFromMarkdown} from './useOutlineFromMarkdown';
|
|
19
20
|
export {useOutlineFromDOM} from './useOutlineFromDOM';
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_version: 3
|
|
3
|
+
template_version: 1
|
|
4
|
+
kind: module
|
|
5
|
+
id: module:Outline/parseOutlineFromMarkdown
|
|
6
|
+
authority: current
|
|
7
|
+
archive_reason: null
|
|
8
|
+
superseded_by: null
|
|
9
|
+
approved_by: cixzhang
|
|
10
|
+
approved_at: 2026-09-15
|
|
11
|
+
owners: [cixzhang]
|
|
12
|
+
review_triggers: [public-api, behavior]
|
|
13
|
+
verified_by: [packages/core/src/Outline/parseOutlineFromMarkdown.test.ts]
|
|
14
|
+
parent_component: component:Outline
|
|
15
|
+
references:
|
|
16
|
+
[architecture:public-component-api, component:Markdown, spec:AST-036]
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# parseOutlineFromMarkdown module contract
|
|
20
|
+
|
|
21
|
+
## Intent
|
|
22
|
+
|
|
23
|
+
`parseOutlineFromMarkdown` and `useOutlineFromMarkdown` derive same-document
|
|
24
|
+
heading navigation from the same Markdown parse configuration, ordered immutable
|
|
25
|
+
transforms, text projection, and collision allocator used by the rendered document.
|
|
26
|
+
This focused module owns that utility behavior without deciding the draft Outline
|
|
27
|
+
component's anatomy or theming.
|
|
28
|
+
|
|
29
|
+
## Compatibility and migration
|
|
30
|
+
|
|
31
|
+
- Released default preserved: `yes`
|
|
32
|
+
- Compatibility class: additive parser options; calls without plugins preserve
|
|
33
|
+
released labels, levels, IDs, and return types
|
|
34
|
+
- Migration decision: `spec:AST-036`
|
|
35
|
+
|
|
36
|
+
## Ownership boundary
|
|
37
|
+
|
|
38
|
+
**Owns**
|
|
39
|
+
|
|
40
|
+
- Deriving ordered `OutlineItem` values from Markdown headings.
|
|
41
|
+
- Accepting the same parser-affecting options and ordered plugin list as Markdown.
|
|
42
|
+
- Applying the same validated immutable transforms before selecting headings.
|
|
43
|
+
- Using the same extension text projection and collision-safe slug allocation as
|
|
44
|
+
Markdown heading rendering.
|
|
45
|
+
|
|
46
|
+
**Does not own / non-goals**
|
|
47
|
+
|
|
48
|
+
- Outline component structure, active state, targets, layout, or theming.
|
|
49
|
+
- Plugin rendering, block-extension navigation entries, or renderer-derived text.
|
|
50
|
+
- A second parser, plugin registry, or independent heading-ID policy.
|
|
51
|
+
|
|
52
|
+
## Public API and concepts
|
|
53
|
+
|
|
54
|
+
`parseOutlineFromMarkdown(source, options?)` performs direct derivation.
|
|
55
|
+
`useOutlineFromMarkdown(source, options?)` memoizes the same derivation for React
|
|
56
|
+
callers. `options.plugins` uses the canonical opaque Markdown plugin entries. The
|
|
57
|
+
same ordered transforms run before heading selection; inline extension-node `toText`
|
|
58
|
+
projections then contribute to heading labels and IDs.
|
|
59
|
+
|
|
60
|
+
## Behavioral contract
|
|
61
|
+
|
|
62
|
+
| ID | Invariant | Basis | Acceptance and implementation state |
|
|
63
|
+
| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ----------------------------------- |
|
|
64
|
+
| FR1 | Both utilities accept the same Markdown parser options and ordered plugin list as the rendered Markdown document. | `spec:AST-036` FR13, FR16 | pending implementation |
|
|
65
|
+
| FR2 | Both utilities apply the same validated immutable transforms before selecting headings, without allowing renderer output to affect identity. | `spec:AST-036` FR13, FR16 | pending implementation |
|
|
66
|
+
| FR3 | Plugin-enabled labels and IDs use the same extension `toText` projection, slugger, and cross-base collision allocator as Markdown, producing unique matching targets. | `spec:AST-036` FR16 | pending implementation |
|
|
67
|
+
| FR4 | An extension node never creates an Outline entry of its own, and extension containers do not change heading traversal: entries come from the same blocks Markdown assigns heading IDs to, so a heading nested in a container is omitted exactly as one nested in a blockquote or list item is. A container never restarts, extends, or re-scopes heading identity or slug allocation. | `spec:AST-036` FR16, FR25 | pending implementation |
|
|
68
|
+
| FR5 | Omitting plugins and passing an empty list preserve released heading selection, labels, levels, IDs, return type, and memoization behavior. | `spec:AST-036` FR2 | pending implementation |
|
|
69
|
+
| FR6 | The hook memoizes against source and every parse-affecting or transform-affecting option so changed configuration cannot return stale headings. | `component:Markdown` FR15–FR16 | pending implementation |
|
|
70
|
+
| FR7 | A transform that removes a heading removes its Outline entry, and a transform that inserts a synthetic heading adds one, in both surfaces identically. Source-backed heading depth cannot change, so an entry's level always matches the rendered heading. | `spec:AST-036` FR26 | pending implementation |
|
|
71
|
+
| FR8 | When a plugin fails, derivation uses the same last valid root the rendered document uses, so labels, levels, and IDs still agree. Failures are reported through the shared diagnostic channel; this module adds no failure mode, fallback, or throw of its own. | `spec:AST-036` FR12, FR29 | pending implementation |
|
|
72
|
+
| FR9 | Derivation runs on the canonical tree through the shared parse path and requires no DOM, renderer, client boundary, or second parser. Because transforms are idempotent under streaming, an outline derived from a growing source prefix converges rather than oscillates. | `spec:AST-036` FR32, FR33, FR36 | pending implementation |
|
|
73
|
+
|
|
74
|
+
### Transformation and precedence order
|
|
75
|
+
|
|
76
|
+
Markdown parse configuration → ordered immutable transforms → heading nodes →
|
|
77
|
+
shared perceivable-text projection → shared slug normalization → document-order
|
|
78
|
+
collision allocation → Outline items.
|
|
79
|
+
|
|
80
|
+
### Performance and resources
|
|
81
|
+
|
|
82
|
+
- The hook recomputes only when source or parser/transform configuration changes.
|
|
83
|
+
- Renderer output does not enter heading identity.
|
|
84
|
+
- No DOM, renderer mount, registry, Remark runtime, or optional plugin resource is
|
|
85
|
+
required.
|
|
86
|
+
|
|
87
|
+
## Accessibility contract
|
|
88
|
+
|
|
89
|
+
Each derived label is the same perceivable heading text used for Markdown identity,
|
|
90
|
+
and each derived ID targets the matching rendered heading. This module adds no
|
|
91
|
+
interaction or ARIA behavior; the Outline component owns navigation presentation.
|
|
92
|
+
|
|
93
|
+
## Design relationships
|
|
94
|
+
|
|
95
|
+
No visual representation is owned by this parser utility.
|
|
96
|
+
|
|
97
|
+
## Parent and system relationships
|
|
98
|
+
|
|
99
|
+
- `component:Markdown` owns aggregate parsing, heading rendering, and the shared
|
|
100
|
+
projection/collision rules.
|
|
101
|
+
- `spec:AST-036` owns the canonical plugin protocol and cross-surface parity.
|
|
102
|
+
- Draft `component:Outline` owns presentation only after its separate anatomy and
|
|
103
|
+
theming decisions become current.
|
|
104
|
+
|
|
105
|
+
## Verification map
|
|
106
|
+
|
|
107
|
+
| Contract | Verification | Representative states | Mutation or failure expectation |
|
|
108
|
+
| -------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| FR1–FR6 | Outline parser tests, plugin transform parity tests, and Core typecheck | transformed, formatted, and extension headings; headings nested in extension containers, blockquotes, and list items; duplicate and cross-base slugs; omitted/empty plugins | A transform is skipped, a label/ID diverges from Markdown, a container changes which headings have identity, or default output changes. |
|
|
110
|
+
| FR7–FR9 | Heading insert/remove parity, failure parity, and streaming derivation | headings removed with/without sections; inserted synthetic headings; failing transform; growing source prefix; server derivation | Outline/document disagreement, divergent fallback, a throw, stale IDs, or streamed oscillation. |
|
|
111
|
+
|
|
112
|
+
## Decision log
|
|
113
|
+
|
|
114
|
+
### DEC-1 — Markdown owns heading identity; Outline projects it
|
|
115
|
+
|
|
116
|
+
**Reference:** `module:Outline/parseOutlineFromMarkdown/DEC-1`
|
|
117
|
+
**Decider:** cixzhang, 2026-09-15
|
|
118
|
+
|
|
119
|
+
Outline utilities consume Markdown's parse configuration, ordered transforms, text
|
|
120
|
+
projection, and collision allocator rather than defining a second heading-identity
|
|
121
|
+
system. This keeps labels and link targets aligned without coupling plugin renderer
|
|
122
|
+
output to navigation identity.
|
|
123
|
+
|
|
124
|
+
### DEC-2 — One traversal survives containers and heading edits
|
|
125
|
+
|
|
126
|
+
**Reference:** `module:Outline/parseOutlineFromMarkdown/DEC-2`
|
|
127
|
+
**Decider:** cixzhang, 2026-09-16
|
|
128
|
+
|
|
129
|
+
Extension containers hold ordinary Markdown but do not change which headings have identity. Markdown assigns IDs by one traversal and this module reads the same one, so Outline never links to a heading Markdown did not identify. A heading inside a container remains omitted like one inside a blockquote or list item, and the extension node is never an Outline entry. Widening traversal is a separate decision.
|
|
130
|
+
|
|
131
|
+
Transforms may remove and insert headings, so Outline follows the rendered document rather than source: a dropped heading disappears, an inserted heading appears, and immutable source-backed depth keeps levels aligned. Both surfaces run the same pipeline rather than independent rules.
|
|
132
|
+
|
|
133
|
+
Rejected: a container-only traversal exception; extension nodes as Outline entries; source-only derivation; module-local plugin failure fallback.
|
|
134
|
+
|
|
135
|
+
## Open questions
|
|
136
|
+
|
|
137
|
+
None.
|
|
138
|
+
|
|
139
|
+
## Content boundary
|
|
140
|
+
|
|
141
|
+
This file does not duplicate plugin protocol details, Markdown parser mechanics,
|
|
142
|
+
consumer examples, or the draft Outline component's anatomy and theming contract.
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file parseOutlineFromMarkdown.ts
|
|
5
|
-
* @input Uses Markdown
|
|
6
|
-
* helpers) and OutlineItem type
|
|
5
|
+
* @input Uses Markdown's canonical AST parser and heading slug helpers
|
|
7
6
|
* @output Exports parseOutlineFromMarkdown for extracting heading outlines from Markdown
|
|
8
|
-
* @position Pure utility; consumed by useOutlineFromMarkdown and public exports
|
|
7
|
+
* @position Pure compatibility utility; consumed by useOutlineFromMarkdown and public exports
|
|
9
8
|
*
|
|
10
9
|
* SYNC: When modified, update these files to stay in sync:
|
|
11
10
|
* - /packages/core/src/Outline/Outline.doc.mjs
|
|
@@ -13,11 +12,19 @@
|
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
import {
|
|
16
|
-
|
|
17
|
-
inlineText,
|
|
15
|
+
parseMarkdownAstInternal,
|
|
18
16
|
slugify,
|
|
19
17
|
uniqueSlug,
|
|
20
18
|
} from '../Markdown/parser';
|
|
19
|
+
import {markdownAstText} from '../Markdown/ast';
|
|
20
|
+
import {
|
|
21
|
+
markdownExtensionText,
|
|
22
|
+
prepareMarkdownPlugins,
|
|
23
|
+
} from '../Markdown/plugins/protocol';
|
|
24
|
+
import type {
|
|
25
|
+
MarkdownExtensionNode,
|
|
26
|
+
MarkdownPluginEntry,
|
|
27
|
+
} from '../Markdown/plugins/protocol';
|
|
21
28
|
import type {OutlineItem} from './types';
|
|
22
29
|
|
|
23
30
|
/**
|
|
@@ -28,16 +35,39 @@ import type {OutlineItem} from './types';
|
|
|
28
35
|
* Ids come from the parser's shared slug helpers, so they always match the
|
|
29
36
|
* `id` attributes Markdown renders on its headings.
|
|
30
37
|
*/
|
|
31
|
-
export
|
|
38
|
+
export interface ParseOutlineFromMarkdownOptions<
|
|
39
|
+
Node extends MarkdownExtensionNode = never,
|
|
40
|
+
> {
|
|
41
|
+
readonly plugins?: ReadonlyArray<MarkdownPluginEntry<Node>>;
|
|
42
|
+
/** Match Markdown's transform finality while content is streaming. */
|
|
43
|
+
readonly isFinal?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function parseOutlineFromMarkdown<
|
|
47
|
+
Node extends MarkdownExtensionNode = never,
|
|
48
|
+
>(
|
|
49
|
+
markdown: string,
|
|
50
|
+
options?: ParseOutlineFromMarkdownOptions<Node>,
|
|
51
|
+
): OutlineItem[] {
|
|
52
|
+
const prepared =
|
|
53
|
+
options?.plugins == null
|
|
54
|
+
? undefined
|
|
55
|
+
: prepareMarkdownPlugins(options.plugins);
|
|
32
56
|
const counts = new Map<string, number>();
|
|
33
|
-
return
|
|
34
|
-
|
|
57
|
+
return parseMarkdownAstInternal(
|
|
58
|
+
markdown,
|
|
59
|
+
{plugins: options?.plugins},
|
|
60
|
+
options?.isFinal ?? true,
|
|
61
|
+
)
|
|
62
|
+
.children.filter(block => block.type === 'heading')
|
|
35
63
|
.map(block => {
|
|
36
|
-
const label =
|
|
64
|
+
const label = markdownAstText(block.children, node =>
|
|
65
|
+
markdownExtensionText(prepared, node),
|
|
66
|
+
).trim();
|
|
37
67
|
return {
|
|
38
68
|
id: uniqueSlug(slugify(label), counts),
|
|
39
69
|
label,
|
|
40
|
-
level: block.
|
|
70
|
+
level: block.depth,
|
|
41
71
|
};
|
|
42
72
|
});
|
|
43
73
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useOutlineFromMarkdown.ts
|
|
7
|
-
* @input Uses React, parseOutlineFromMarkdown
|
|
7
|
+
* @input Uses React, parseOutlineFromMarkdown, and optional Markdown plugins
|
|
8
8
|
* @output Exports useOutlineFromMarkdown hook
|
|
9
9
|
* @position Hook utility; consumed by applications and Outline examples
|
|
10
10
|
*
|
|
@@ -15,9 +15,21 @@
|
|
|
15
15
|
|
|
16
16
|
import {useMemo} from 'react';
|
|
17
17
|
import {parseOutlineFromMarkdown} from './parseOutlineFromMarkdown';
|
|
18
|
+
import type {ParseOutlineFromMarkdownOptions} from './parseOutlineFromMarkdown';
|
|
19
|
+
import type {MarkdownExtensionNode} from '../Markdown/plugins/protocol';
|
|
18
20
|
import type {OutlineItem} from './types';
|
|
19
21
|
|
|
20
22
|
/** Extract a stable outline from a Markdown string. */
|
|
21
|
-
export function useOutlineFromMarkdown
|
|
22
|
-
|
|
23
|
+
export function useOutlineFromMarkdown<
|
|
24
|
+
Node extends MarkdownExtensionNode = never,
|
|
25
|
+
>(
|
|
26
|
+
markdown: string,
|
|
27
|
+
options?: ParseOutlineFromMarkdownOptions<Node>,
|
|
28
|
+
): OutlineItem[] {
|
|
29
|
+
const plugins = options?.plugins;
|
|
30
|
+
const isFinal = options?.isFinal;
|
|
31
|
+
return useMemo(
|
|
32
|
+
() => parseOutlineFromMarkdown(markdown, {plugins, isFinal}),
|
|
33
|
+
[markdown, plugins, isFinal],
|
|
34
|
+
);
|
|
23
35
|
}
|
|
@@ -188,12 +188,12 @@ export const docs = {
|
|
|
188
188
|
},
|
|
189
189
|
{
|
|
190
190
|
name: 'onFocus',
|
|
191
|
-
type: '(e: FocusEvent
|
|
191
|
+
type: '(e: React.FocusEvent) => void',
|
|
192
192
|
description: 'Fires when focus enters the search input.',
|
|
193
193
|
},
|
|
194
194
|
{
|
|
195
195
|
name: 'onBlur',
|
|
196
|
-
type: '(e: FocusEvent
|
|
196
|
+
type: '(e: React.FocusEvent) => void',
|
|
197
197
|
description: 'Fires when focus leaves the search input.',
|
|
198
198
|
},
|
|
199
199
|
{
|