@astryxdesign/core 0.6.2 → 0.6.3-canary.0899f21
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.js +1 -1
- 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 +716 -167
- 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/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.test.tsx +1 -4
- package/src/Chat/ChatSendButton.tsx +1 -1
- 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/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 +203 -45
- package/src/Markdown/Markdown.test.tsx +63 -0
- 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 +12 -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 +20 -0
- package/src/Markdown/parser.ts +1180 -235
- 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 +31 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
- package/src/Selector/Selector.doc.mjs +2 -2
- 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,413 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file ChatMessageMetadata.a11y.chromium.spec.ts
|
|
5
|
+
* @input Exact-head Storybook build and component-owned metadata fixtures
|
|
6
|
+
* @output Chromium PNGs, semantic/paint sensor receipts, and a fail-closed manifest
|
|
7
|
+
* @position Browser evidence for the ChatMessageMetadata component audit
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {createHash} from 'node:crypto';
|
|
11
|
+
import {execFileSync} from 'node:child_process';
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import {expect, test, type Page} from '@playwright/test';
|
|
15
|
+
import {holdMotionStill} from '@astryxdesign/a11y-spec/chromium';
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_STORYBOOK_DIR,
|
|
18
|
+
serveStorybook,
|
|
19
|
+
type StaticServer,
|
|
20
|
+
} from '@astryxdesign/a11y-spec/storybook';
|
|
21
|
+
|
|
22
|
+
const OUTPUT = path.resolve(
|
|
23
|
+
'test-results/chat-message-metadata-audit-evidence',
|
|
24
|
+
);
|
|
25
|
+
const STATES = 'core-chatmessagemetadata--states';
|
|
26
|
+
const NARROW = 'core-chatmessagemetadata--narrow-overflow';
|
|
27
|
+
const LABELS = {
|
|
28
|
+
sending: 'Sending',
|
|
29
|
+
sent: 'Sent',
|
|
30
|
+
delivered: 'Delivered',
|
|
31
|
+
read: 'Read',
|
|
32
|
+
error: 'Failed',
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
interface Case {
|
|
36
|
+
name: string;
|
|
37
|
+
storyId: string;
|
|
38
|
+
rootCount: number;
|
|
39
|
+
text: string;
|
|
40
|
+
status?: keyof typeof LABELS;
|
|
41
|
+
button?: boolean;
|
|
42
|
+
sender?: 'user' | 'assistant';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// These expectations are fixture/source facts, never values copied from a page.
|
|
46
|
+
const CASES: Case[] = [
|
|
47
|
+
...Object.entries(LABELS).map(([status, label]) => ({
|
|
48
|
+
name: `status-${status}`,
|
|
49
|
+
storyId: STATES,
|
|
50
|
+
rootCount: 1,
|
|
51
|
+
text: `10:30·${label}`,
|
|
52
|
+
status: status as keyof typeof LABELS,
|
|
53
|
+
sender: 'user' as const,
|
|
54
|
+
})),
|
|
55
|
+
{
|
|
56
|
+
name: 'assistant-footer',
|
|
57
|
+
storyId: STATES,
|
|
58
|
+
rootCount: 1,
|
|
59
|
+
text: '10:31·Copy reply',
|
|
60
|
+
button: true,
|
|
61
|
+
sender: 'assistant',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'empty-footer',
|
|
65
|
+
storyId: STATES,
|
|
66
|
+
rootCount: 1,
|
|
67
|
+
text: '10:32',
|
|
68
|
+
sender: 'assistant',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'empty-timestamp',
|
|
72
|
+
storyId: STATES,
|
|
73
|
+
rootCount: 1,
|
|
74
|
+
text: 'Model info',
|
|
75
|
+
sender: 'assistant',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'empty-row',
|
|
79
|
+
storyId: STATES,
|
|
80
|
+
rootCount: 0,
|
|
81
|
+
text: '',
|
|
82
|
+
sender: 'assistant',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'numeric-slots',
|
|
86
|
+
storyId: STATES,
|
|
87
|
+
rootCount: 1,
|
|
88
|
+
text: '0·0',
|
|
89
|
+
sender: 'user',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'standalone',
|
|
93
|
+
storyId: STATES,
|
|
94
|
+
rootCount: 1,
|
|
95
|
+
text: '11:00·Read',
|
|
96
|
+
status: 'read',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'narrow-overflow',
|
|
100
|
+
storyId: NARROW,
|
|
101
|
+
rootCount: 1,
|
|
102
|
+
text: '10:32·A longer metadata description that can grow when translated into a different language·Delivered',
|
|
103
|
+
status: 'delivered',
|
|
104
|
+
sender: 'assistant',
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
let server: StaticServer;
|
|
109
|
+
let head: string;
|
|
110
|
+
let build: string;
|
|
111
|
+
const frames: Record<string, unknown>[] = [];
|
|
112
|
+
|
|
113
|
+
test.beforeAll(async () => {
|
|
114
|
+
head = execFileSync('git', ['rev-parse', 'HEAD'], {encoding: 'utf8'}).trim();
|
|
115
|
+
if (process.env.ASTRYX_HEAD_SHA && process.env.ASTRYX_HEAD_SHA !== head) {
|
|
116
|
+
throw new Error('PR head differs from the checked out source');
|
|
117
|
+
}
|
|
118
|
+
server = await serveStorybook(
|
|
119
|
+
process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
|
|
120
|
+
);
|
|
121
|
+
const stamp = await fetch(`${server.origin}/astryx-build-sha.txt`);
|
|
122
|
+
if (!stamp.ok) {
|
|
123
|
+
throw new Error('Storybook build is missing its source stamp');
|
|
124
|
+
}
|
|
125
|
+
build = (await stamp.text()).trim();
|
|
126
|
+
if (build !== head) {
|
|
127
|
+
throw new Error('Storybook bytes differ from the PR head');
|
|
128
|
+
}
|
|
129
|
+
fs.mkdirSync(OUTPUT, {recursive: true});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test.afterAll(async () => {
|
|
133
|
+
const previous = fs.existsSync(path.join(OUTPUT, 'manifest.json'))
|
|
134
|
+
? (JSON.parse(fs.readFileSync(path.join(OUTPUT, 'manifest.json'), 'utf8'))
|
|
135
|
+
.frames ?? [])
|
|
136
|
+
: [];
|
|
137
|
+
if (head && build) {
|
|
138
|
+
fs.writeFileSync(
|
|
139
|
+
path.join(OUTPUT, 'manifest.json'),
|
|
140
|
+
`${JSON.stringify(
|
|
141
|
+
{
|
|
142
|
+
version: 1,
|
|
143
|
+
component: 'core/ChatMessageMetadata',
|
|
144
|
+
headSha: head,
|
|
145
|
+
storybookSha: build,
|
|
146
|
+
frames: [...previous, ...frames].filter(
|
|
147
|
+
(frame, index, all) =>
|
|
148
|
+
all.findIndex(
|
|
149
|
+
other =>
|
|
150
|
+
other.state === frame.state &&
|
|
151
|
+
other.mode === frame.mode &&
|
|
152
|
+
other.direction === frame.direction,
|
|
153
|
+
) === index,
|
|
154
|
+
),
|
|
155
|
+
},
|
|
156
|
+
null,
|
|
157
|
+
2,
|
|
158
|
+
)}\n`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
await server?.close();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
async function capture(
|
|
165
|
+
page: Page,
|
|
166
|
+
scenario: Case,
|
|
167
|
+
mode: 'light' | 'dark',
|
|
168
|
+
direction: 'ltr' | 'rtl',
|
|
169
|
+
options: {
|
|
170
|
+
viewport?: {width: number; height: number};
|
|
171
|
+
coarsePointer?: boolean;
|
|
172
|
+
state?: string;
|
|
173
|
+
} = {},
|
|
174
|
+
) {
|
|
175
|
+
const viewport = options.viewport ?? {width: 1024, height: 768};
|
|
176
|
+
const state = options.state ?? scenario.name;
|
|
177
|
+
const errors: string[] = [];
|
|
178
|
+
const onError = (error: Error) => errors.push(String(error));
|
|
179
|
+
page.on('pageerror', onError);
|
|
180
|
+
await page.setViewportSize(viewport);
|
|
181
|
+
await page.goto(
|
|
182
|
+
`${server.origin}/iframe.html?id=${scenario.storyId}&viewMode=story&globals=colorMode:${mode};astryxTheme:neutral;direction:${direction}`,
|
|
183
|
+
);
|
|
184
|
+
const panel = page.locator(`[data-metadata-case="${scenario.name}"]`);
|
|
185
|
+
await panel.waitFor();
|
|
186
|
+
await page.waitForFunction(
|
|
187
|
+
expected =>
|
|
188
|
+
document.documentElement.getAttribute('data-theme') === expected,
|
|
189
|
+
mode,
|
|
190
|
+
);
|
|
191
|
+
await holdMotionStill(page);
|
|
192
|
+
await page.evaluate(async () => document.fonts.ready);
|
|
193
|
+
const roots = panel.locator('.astryx-chat-message-metadata');
|
|
194
|
+
const actual = await panel.evaluate((element, expected) => {
|
|
195
|
+
const root = element.querySelector('.astryx-chat-message-metadata');
|
|
196
|
+
const status = root?.querySelector('[title]');
|
|
197
|
+
const rect = element.getBoundingClientRect();
|
|
198
|
+
const rootStyle = root ? getComputedStyle(root) : null;
|
|
199
|
+
return {
|
|
200
|
+
rootCount: element.querySelectorAll('.astryx-chat-message-metadata')
|
|
201
|
+
.length,
|
|
202
|
+
text: (root?.textContent ?? '').replace(/\s+/g, ' ').trim(),
|
|
203
|
+
direction: rootStyle?.direction ?? getComputedStyle(element).direction,
|
|
204
|
+
color: rootStyle?.color ?? null,
|
|
205
|
+
fontSize: rootStyle?.fontSize ?? null,
|
|
206
|
+
statusColor: status ? getComputedStyle(status).color : null,
|
|
207
|
+
statusTitle: status?.getAttribute('title') ?? null,
|
|
208
|
+
statusLabel: status?.getAttribute('aria-label') ?? null,
|
|
209
|
+
buttonCount: element.querySelectorAll('button').length,
|
|
210
|
+
sender:
|
|
211
|
+
element.querySelector('article')?.getAttribute('data-sender') ?? null,
|
|
212
|
+
overflowFree: element.scrollWidth <= element.clientWidth + 1,
|
|
213
|
+
rootWidth: root?.getBoundingClientRect().width ?? null,
|
|
214
|
+
childX: root
|
|
215
|
+
? [...root.children].map(child => child.getBoundingClientRect().x)
|
|
216
|
+
: [],
|
|
217
|
+
geometry: {x: rect.x, y: rect.y, width: rect.width, height: rect.height},
|
|
218
|
+
rootVisible: root
|
|
219
|
+
? root.getBoundingClientRect().width > 0 &&
|
|
220
|
+
root.getBoundingClientRect().height > 0
|
|
221
|
+
: false,
|
|
222
|
+
storyError: [
|
|
223
|
+
...document.querySelectorAll(
|
|
224
|
+
'.sb-errordisplay, [data-testid="story-error"]',
|
|
225
|
+
),
|
|
226
|
+
].some(node => {
|
|
227
|
+
const box = node.getBoundingClientRect();
|
|
228
|
+
const style = getComputedStyle(node);
|
|
229
|
+
return (
|
|
230
|
+
box.width > 0 &&
|
|
231
|
+
box.height > 0 &&
|
|
232
|
+
box.bottom > 0 &&
|
|
233
|
+
box.right > 0 &&
|
|
234
|
+
box.top < innerHeight &&
|
|
235
|
+
box.left < innerWidth &&
|
|
236
|
+
style.display !== 'none' &&
|
|
237
|
+
style.visibility !== 'hidden' &&
|
|
238
|
+
style.opacity !== '0'
|
|
239
|
+
);
|
|
240
|
+
}),
|
|
241
|
+
mode: document.documentElement.getAttribute('data-theme'),
|
|
242
|
+
theme: document
|
|
243
|
+
.querySelector('[data-astryx-theme]')
|
|
244
|
+
?.getAttribute('data-astryx-theme'),
|
|
245
|
+
colorScheme: getComputedStyle(document.documentElement).colorScheme,
|
|
246
|
+
fonts: document.fonts.status,
|
|
247
|
+
viewport: {width: innerWidth, height: innerHeight},
|
|
248
|
+
dpr: devicePixelRatio,
|
|
249
|
+
reducedMotion: matchMedia('(prefers-reduced-motion: reduce)').matches,
|
|
250
|
+
coarsePointer: matchMedia('(pointer: coarse)').matches,
|
|
251
|
+
horizontalOverflow: document.documentElement.scrollWidth > innerWidth + 1,
|
|
252
|
+
expectedSubject: expected,
|
|
253
|
+
};
|
|
254
|
+
}, scenario.name);
|
|
255
|
+
const expected = {
|
|
256
|
+
build: head,
|
|
257
|
+
storyId: scenario.storyId,
|
|
258
|
+
theme: 'neutral',
|
|
259
|
+
mode,
|
|
260
|
+
direction,
|
|
261
|
+
viewport,
|
|
262
|
+
coarsePointer: options.coarsePointer ?? false,
|
|
263
|
+
reducedMotion: true,
|
|
264
|
+
rootCount: scenario.rootCount,
|
|
265
|
+
text: scenario.text,
|
|
266
|
+
statusTitle: scenario.status ? LABELS[scenario.status] : null,
|
|
267
|
+
buttonCount: scenario.button ? 1 : 0,
|
|
268
|
+
sender: scenario.sender ?? null,
|
|
269
|
+
};
|
|
270
|
+
const failures: string[] = [];
|
|
271
|
+
const check = (ok: boolean, detail: string) => {
|
|
272
|
+
if (!ok) {
|
|
273
|
+
failures.push(detail);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
check(actual.rootCount === expected.rootCount, 'metadata root count');
|
|
277
|
+
check(actual.text === expected.text, 'visible content and separators');
|
|
278
|
+
check(actual.direction === direction, 'computed direction');
|
|
279
|
+
if (scenario.name === 'status-read' || scenario.name === 'assistant-footer') {
|
|
280
|
+
const first = actual.childX[0];
|
|
281
|
+
const last = actual.childX[actual.childX.length - 1];
|
|
282
|
+
const goesRight =
|
|
283
|
+
scenario.sender === 'user' ? direction === 'rtl' : direction === 'ltr';
|
|
284
|
+
check(
|
|
285
|
+
first != null &&
|
|
286
|
+
last != null &&
|
|
287
|
+
(goesRight ? first < last : first > last),
|
|
288
|
+
'sender-relative visual order',
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
check(actual.statusTitle === expected.statusTitle, 'translated status title');
|
|
292
|
+
check(actual.buttonCount === expected.buttonCount, 'footer button');
|
|
293
|
+
check(actual.sender === expected.sender, 'message sender');
|
|
294
|
+
check(
|
|
295
|
+
actual.theme === 'neutral' &&
|
|
296
|
+
actual.mode === mode &&
|
|
297
|
+
actual.colorScheme === mode,
|
|
298
|
+
'resolved theme',
|
|
299
|
+
);
|
|
300
|
+
check(
|
|
301
|
+
actual.fonts === 'loaded' && actual.reducedMotion,
|
|
302
|
+
'settled fonts and reduced motion',
|
|
303
|
+
);
|
|
304
|
+
check(
|
|
305
|
+
actual.viewport.width === viewport.width &&
|
|
306
|
+
actual.viewport.height === viewport.height &&
|
|
307
|
+
actual.coarsePointer === expected.coarsePointer,
|
|
308
|
+
'viewport and pointer',
|
|
309
|
+
);
|
|
310
|
+
check(
|
|
311
|
+
actual.geometry.width > 0 &&
|
|
312
|
+
actual.geometry.height > 0 &&
|
|
313
|
+
!actual.storyError,
|
|
314
|
+
'visible fixture with no Storybook error',
|
|
315
|
+
);
|
|
316
|
+
check(
|
|
317
|
+
actual.rootCount === 0 || actual.rootVisible,
|
|
318
|
+
'visible metadata subject',
|
|
319
|
+
);
|
|
320
|
+
check(
|
|
321
|
+
actual.overflowFree && !actual.horizontalOverflow,
|
|
322
|
+
'no horizontal overflow',
|
|
323
|
+
);
|
|
324
|
+
check(errors.length === 0, 'no page errors');
|
|
325
|
+
const file = `ChatMessageMetadata__${state}__neutral-${mode}__${direction}.png`;
|
|
326
|
+
const png = await panel.screenshot({animations: 'disabled'});
|
|
327
|
+
const image = {
|
|
328
|
+
file,
|
|
329
|
+
sha256: createHash('sha256').update(png).digest('hex'),
|
|
330
|
+
width: png.readUInt32BE(16),
|
|
331
|
+
height: png.readUInt32BE(20),
|
|
332
|
+
};
|
|
333
|
+
fs.writeFileSync(path.join(OUTPUT, file), png);
|
|
334
|
+
const receipt = {
|
|
335
|
+
expected,
|
|
336
|
+
observed: {...actual, build, storyId: scenario.storyId, pageErrors: errors},
|
|
337
|
+
browser: page.context().browser()?.version() ?? 'unknown',
|
|
338
|
+
image,
|
|
339
|
+
passed: failures.length === 0,
|
|
340
|
+
failures,
|
|
341
|
+
};
|
|
342
|
+
fs.writeFileSync(
|
|
343
|
+
path.join(OUTPUT, `${file}.sensors.json`),
|
|
344
|
+
`${JSON.stringify(receipt, null, 2)}\n`,
|
|
345
|
+
);
|
|
346
|
+
frames.push({
|
|
347
|
+
state,
|
|
348
|
+
mode,
|
|
349
|
+
direction,
|
|
350
|
+
receipt: `${file}.sensors.json`,
|
|
351
|
+
image,
|
|
352
|
+
passed: receipt.passed,
|
|
353
|
+
failures,
|
|
354
|
+
});
|
|
355
|
+
expect(await roots.count()).toBe(actual.rootCount);
|
|
356
|
+
page.off('pageerror', onError);
|
|
357
|
+
return failures.map(detail => `${state}/${mode}/${direction}: ${detail}`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
test('captures light and dark status, composition, empty, and overflow states', async ({
|
|
361
|
+
page,
|
|
362
|
+
}) => {
|
|
363
|
+
const failures: string[] = [];
|
|
364
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
365
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
366
|
+
for (const scenario of CASES) {
|
|
367
|
+
failures.push(...(await capture(page, scenario, mode, 'ltr')));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
expect(failures).toEqual([]);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('captures sender ordering in RTL', async ({page}) => {
|
|
374
|
+
const failures: string[] = [];
|
|
375
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
376
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
377
|
+
for (const scenario of CASES.filter(
|
|
378
|
+
item => item.name === 'status-read' || item.name === 'assistant-footer',
|
|
379
|
+
)) {
|
|
380
|
+
failures.push(...(await capture(page, scenario, mode, 'rtl')));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
expect(failures).toEqual([]);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
test('captures narrow touch reflow in both modes', async ({browser}) => {
|
|
387
|
+
const viewport = {width: 320, height: 640};
|
|
388
|
+
const context = await browser.newContext({
|
|
389
|
+
viewport,
|
|
390
|
+
deviceScaleFactor: 1,
|
|
391
|
+
hasTouch: true,
|
|
392
|
+
isMobile: true,
|
|
393
|
+
reducedMotion: 'reduce',
|
|
394
|
+
});
|
|
395
|
+
try {
|
|
396
|
+
const page = await context.newPage();
|
|
397
|
+
const scenario = CASES.find(item => item.name === 'narrow-overflow');
|
|
398
|
+
if (!scenario) {throw new Error('Narrow metadata fixture is missing');}
|
|
399
|
+
const failures: string[] = [];
|
|
400
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
401
|
+
failures.push(
|
|
402
|
+
...(await capture(page, scenario, mode, 'ltr', {
|
|
403
|
+
viewport,
|
|
404
|
+
coarsePointer: true,
|
|
405
|
+
state: 'narrow-touch',
|
|
406
|
+
})),
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
expect(failures).toEqual([]);
|
|
410
|
+
} finally {
|
|
411
|
+
await context.close();
|
|
412
|
+
}
|
|
413
|
+
});
|
package/src/Chat/index.ts
CHANGED
|
@@ -137,6 +137,17 @@ export const docs = {
|
|
|
137
137
|
],
|
|
138
138
|
},
|
|
139
139
|
usage: {
|
|
140
|
+
accessibility: [
|
|
141
|
+
{
|
|
142
|
+
name: 'Checkbox box',
|
|
143
|
+
category: 'Color contrast',
|
|
144
|
+
criterion: '1.4.11 Non-text Contrast',
|
|
145
|
+
requirement: '3:1',
|
|
146
|
+
states: ['Rest', 'Hover', 'Pointer down', 'Checked'],
|
|
147
|
+
description:
|
|
148
|
+
'The box edge (unchecked) and fill (checked) must have at least 3:1 contrast with the surface behind them. For Hover and Pointer down, measure the final colors after the tint and the pressed overlay are applied.',
|
|
149
|
+
},
|
|
150
|
+
],
|
|
140
151
|
description: 'CheckboxInput toggles a single on/off value. Use it for settings like "Enable notifications", terms acceptance, or opt-in choices. For multiple checkboxes in a group, use CheckboxList instead.',
|
|
141
152
|
bestPractices: [
|
|
142
153
|
{ guidance: true, description: 'Always provide a visible label so the user knows what they are toggling. Use isLabelHidden only when surrounding context makes it obvious.' },
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
16
16
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
17
17
|
import userEvent from '@testing-library/user-event';
|
|
18
|
+
import {hasPressedArm} from '../__tests__/pressState';
|
|
18
19
|
import {CheckboxInput} from './CheckboxInput';
|
|
19
20
|
import {Theme} from '../theme/Theme';
|
|
20
21
|
import {defineTheme} from '../theme/defineTheme';
|
|
@@ -763,3 +764,36 @@ describe('label theme target', () => {
|
|
|
763
764
|
expect(label).toHaveClass('astryx-checkbox-label');
|
|
764
765
|
});
|
|
765
766
|
});
|
|
767
|
+
|
|
768
|
+
describe('pressed state', () => {
|
|
769
|
+
it('paints the pressed overlay over the indicator while the row is pressed', () => {
|
|
770
|
+
const {container} = render(
|
|
771
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
772
|
+
);
|
|
773
|
+
const box = container.querySelector('.astryx-checkbox-indicator');
|
|
774
|
+
const wrapper = box?.parentElement?.parentElement;
|
|
775
|
+
if (wrapper == null) {
|
|
776
|
+
throw new Error('the checkbox has no indicator wrapper to press');
|
|
777
|
+
}
|
|
778
|
+
// The owner paints over the resolved indicator, so the treatment survives a
|
|
779
|
+
// theme replacement that does not forward style props.
|
|
780
|
+
expect(hasPressedArm(wrapper)).toBe(true);
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
it('does not expose a pressed arm on a disabled checkbox', () => {
|
|
784
|
+
const {container} = render(
|
|
785
|
+
<CheckboxInput
|
|
786
|
+
label="Unavailable"
|
|
787
|
+
value={false}
|
|
788
|
+
onChange={() => {}}
|
|
789
|
+
isDisabled
|
|
790
|
+
/>,
|
|
791
|
+
);
|
|
792
|
+
const box = container.querySelector('.astryx-checkbox-indicator');
|
|
793
|
+
const wrapper = box?.parentElement?.parentElement;
|
|
794
|
+
if (wrapper == null) {
|
|
795
|
+
throw new Error('the checkbox has no indicator wrapper');
|
|
796
|
+
}
|
|
797
|
+
expect(hasPressedArm(wrapper)).toBe(false);
|
|
798
|
+
});
|
|
799
|
+
});
|
|
@@ -70,6 +70,22 @@ const styles = stylex.create({
|
|
|
70
70
|
flexShrink: 0,
|
|
71
71
|
isolation: 'isolate',
|
|
72
72
|
},
|
|
73
|
+
// The owner paints this layer over the resolved indicator, so a theme
|
|
74
|
+
// replacement cannot accidentally drop the component's pressed contract.
|
|
75
|
+
indicatorPressOverlay: {
|
|
76
|
+
'::after': {
|
|
77
|
+
content: '""',
|
|
78
|
+
position: 'absolute',
|
|
79
|
+
inset: 0,
|
|
80
|
+
borderRadius: radiusVars['--radius-inner'],
|
|
81
|
+
pointerEvents: 'none',
|
|
82
|
+
backgroundColor: {
|
|
83
|
+
default: 'transparent',
|
|
84
|
+
[stylex.when.ancestor(':active', indicatorScope)]:
|
|
85
|
+
colorVars['--color-overlay-pressed'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
73
89
|
// Holds only the indicator, so the focus ring has one unambiguous target.
|
|
74
90
|
// `display: contents` adds no box of its own — the indicator keeps whatever
|
|
75
91
|
// layout relationship it already had with the wrapper.
|
|
@@ -399,7 +415,11 @@ export function CheckboxInput({
|
|
|
399
415
|
!isDisabled && indicatorScope,
|
|
400
416
|
)}>
|
|
401
417
|
<div
|
|
402
|
-
{...stylex.props(
|
|
418
|
+
{...stylex.props(
|
|
419
|
+
styles.checkboxWrapper,
|
|
420
|
+
wrapperSizeStyles[size],
|
|
421
|
+
!isDisabled && styles.indicatorPressOverlay,
|
|
422
|
+
)}
|
|
403
423
|
{...focusProps}>
|
|
404
424
|
<input
|
|
405
425
|
{...rest}
|
|
@@ -71,7 +71,7 @@ export const docs = {
|
|
|
71
71
|
name: 'source',
|
|
72
72
|
type: 'CitationSource',
|
|
73
73
|
description:
|
|
74
|
-
'The citation source object containing title, url, an optional image src, and an optional icon node.',
|
|
74
|
+
'The citation source object containing title, url, an optional image src, and an optional icon node. The url follows the shared navigation rule described on the Link `href` prop; rejected destinations leave the citation visible without navigation. Image src uses separate resource handling.',
|
|
75
75
|
required: true,
|
|
76
76
|
},
|
|
77
77
|
{
|
|
@@ -122,7 +122,7 @@ export const docsDense = {
|
|
|
122
122
|
},
|
|
123
123
|
propDescriptions: {
|
|
124
124
|
source:
|
|
125
|
-
'citation source
|
|
125
|
+
'citation source with title, url, optional image src, and optional icon. url follows the Link href navigation rule; rejected destinations stay visible without navigation. Image src handling is separate.',
|
|
126
126
|
number: 'display index for this citation.',
|
|
127
127
|
variant: 'display style: label chip with source title or compact numbered badge.',
|
|
128
128
|
},
|
|
@@ -36,6 +36,23 @@ function atomicClasses(style: (typeof probe)[keyof typeof probe]): string[] {
|
|
|
36
36
|
describe('Citation', () => {
|
|
37
37
|
const source = {title: 'Example Source', url: 'https://example.com'};
|
|
38
38
|
|
|
39
|
+
it.each([
|
|
40
|
+
'javascript:alert(1)',
|
|
41
|
+
'vbscript:MsgBox(1)',
|
|
42
|
+
'data:text/html,<b>x</b>',
|
|
43
|
+
'java\nscript:alert(1)',
|
|
44
|
+
])('renders rejected citation URL %s without navigation', url => {
|
|
45
|
+
const {container} = render(
|
|
46
|
+
<>
|
|
47
|
+
<Citation source={{title: 'Source', url}} number={1} />
|
|
48
|
+
<Citation source={{title: 'Source', url}} number={1} variant="number" />
|
|
49
|
+
</>,
|
|
50
|
+
);
|
|
51
|
+
expect(container.querySelector('a')).toBeNull();
|
|
52
|
+
expect(container.querySelector('[href]')).toBeNull();
|
|
53
|
+
expect(container.textContent).toBe('Source1');
|
|
54
|
+
});
|
|
55
|
+
|
|
39
56
|
it('renders the source title as a link in the label variant', () => {
|
|
40
57
|
render(<Citation source={source} number={1} data-testid="citation" />);
|
|
41
58
|
const el = screen.getByTestId('citation');
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Citation.tsx
|
|
7
|
-
* @input Uses React, StyleX, theme tokens
|
|
7
|
+
* @input Uses React, StyleX, theme tokens, and the shared navigation policy
|
|
8
8
|
* @output Exports Citation component for inline citation references
|
|
9
9
|
* @position Core implementation; consumed by index.ts
|
|
10
10
|
*
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
easeVars,
|
|
31
31
|
} from '../theme/tokens.stylex';
|
|
32
32
|
import {mergeProps} from '../utils';
|
|
33
|
+
import {isSafeUrl} from '../utils/safeUrl';
|
|
33
34
|
import type {BaseProps} from '../BaseProps';
|
|
34
35
|
import {themeProps} from '../utils/themeProps';
|
|
35
36
|
import {useTranslator} from '../i18n';
|
|
@@ -189,7 +190,8 @@ export function Citation({
|
|
|
189
190
|
}: CitationProps): React.ReactElement {
|
|
190
191
|
const t = useTranslator();
|
|
191
192
|
const title = source.title ?? String(number);
|
|
192
|
-
const href =
|
|
193
|
+
const href =
|
|
194
|
+
source.url != null && isSafeUrl(source.url) ? source.url : undefined;
|
|
193
195
|
|
|
194
196
|
// Resolve the source icon. A non-string `icon` node renders as-is (an Astryx
|
|
195
197
|
// <Icon>, SVG, avatar, etc.). Otherwise fall back to an image URL: `src`, or
|
|
@@ -22,7 +22,7 @@ export const docs = {
|
|
|
22
22
|
props: [
|
|
23
23
|
{name: 'label', type: 'string', description: 'Accessibility label.', required: true},
|
|
24
24
|
{name: 'onClick', type: '(event: MouseEvent) => void', description: 'Click handler: fires on card surface only.'},
|
|
25
|
-
{name: 'href', type: 'string', description: 'Navigation URL.'},
|
|
25
|
+
{name: 'href', type: 'string', description: 'Navigation URL. Plain, new-tab, Cmd/Ctrl-click, and middle-click activation all follow the shared navigation rule described on the Link `href` prop.'},
|
|
26
26
|
{name: 'target', type: 'string', description: 'Link target.', default: "'_self'"},
|
|
27
27
|
{name: 'isDisabled', type: 'boolean', description: 'Disables the card.', default: 'false'},
|
|
28
28
|
{name: 'children', type: 'ReactNode', description: 'Card content.'},
|
|
@@ -69,7 +69,7 @@ export const docsDense = {
|
|
|
69
69
|
propDescriptions: {
|
|
70
70
|
label: 'accessibility label',
|
|
71
71
|
onClick: 'click handler: fires on card surface only',
|
|
72
|
-
href: 'navigation URL',
|
|
72
|
+
href: 'navigation URL; every activation follows the shared navigation rule (see Link href)',
|
|
73
73
|
target: 'link target',
|
|
74
74
|
isDisabled: 'disables card',
|
|
75
75
|
padding: 'inner padding',
|