@astryxdesign/core 0.6.2 → 0.6.3-canary.039a67e
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/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +33 -12
- 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/ChatSystemMessage.d.ts +3 -3
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +2 -2
- package/dist/Chat/ChatTokenizedText.d.ts +6 -6
- package/dist/Chat/ChatTokenizedText.js +10 -6
- package/dist/Chat/ChatToolCalls.d.ts +7 -9
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +43 -26
- 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 +25 -5
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +29 -17
- 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/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +4 -4
- package/dist/DateTimeInput/DateTimeInput.d.ts +32 -15
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +55 -30
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- 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 +30 -14
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +61 -13
- package/dist/TimeInput/TouchTimeField.d.ts +11 -0
- package/dist/TimeInput/TouchTimeField.d.ts.map +1 -0
- package/dist/TimeInput/TouchTimeField.js +417 -0
- package/dist/TimeInput/index.d.ts +1 -1
- package/dist/TimeInput/index.d.ts.map +1 -1
- 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/defineTheme.d.ts +3 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +4 -1
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +4 -0
- package/dist/theme/generateThemeRules.d.ts +15 -7
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +143 -35
- package/dist/theme/themeAdaptations.d.ts +5 -3
- package/dist/theme/themeAdaptations.d.ts.map +1 -1
- package/dist/theme/themeAdaptations.js +33 -5
- package/dist/utils/inputPresentation.d.ts +55 -0
- package/dist/utils/inputPresentation.d.ts.map +1 -0
- package/dist/utils/inputPresentation.js +108 -0
- 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/Avatar/Avatar.doc.mjs +1 -1
- package/src/Avatar/Avatar.test.tsx +30 -0
- package/src/Avatar/Avatar.tsx +38 -14
- 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/ChatSystemMessage.doc.mjs +115 -12
- package/src/Chat/ChatSystemMessage.spec.md +225 -0
- package/src/Chat/ChatSystemMessage.test.tsx +112 -20
- package/src/Chat/ChatSystemMessage.tsx +4 -6
- package/src/Chat/ChatTokenizedText.doc.mjs +96 -9
- package/src/Chat/ChatTokenizedText.spec.md +190 -0
- package/src/Chat/ChatTokenizedText.test.tsx +60 -1
- package/src/Chat/ChatTokenizedText.tsx +14 -8
- package/src/Chat/ChatToolCalls.doc.mjs +4 -1
- package/src/Chat/ChatToolCalls.spec.md +194 -0
- package/src/Chat/ChatToolCalls.test.tsx +83 -0
- package/src/Chat/ChatToolCalls.tsx +46 -21
- 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/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +1004 -0
- package/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts +573 -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.doc.mjs +38 -9
- package/src/DateInput/DateInput.tsx +59 -17
- package/src/DateInput/NativeDateField.tsx +24 -8
- package/src/DateInput/Presentation.test.tsx +121 -0
- package/src/DateInput/TouchDateField.tsx +6 -2
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.tsx +6 -1
- package/src/DateTimeInput/DateTimeInput.doc.mjs +28 -12
- package/src/DateTimeInput/DateTimeInput.tsx +93 -37
- package/src/DateTimeInput/Presentation.test.tsx +89 -0
- package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
- package/src/DateTimeInput/index.ts +1 -0
- 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/NativeTimeInput.test.tsx +36 -3
- package/src/TimeInput/Presentation.test.tsx +148 -0
- package/src/TimeInput/TimeInput.doc.mjs +21 -5
- package/src/TimeInput/TimeInput.tsx +102 -11
- package/src/TimeInput/TouchTimeField.tsx +572 -0
- package/src/TimeInput/index.ts +1 -0
- 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/defineTheme.ts +4 -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 +231 -50
- package/src/theme/themeAdaptations.test.ts +211 -1
- package/src/theme/themeAdaptations.ts +50 -4
- package/src/theme/tokenValueCompat.test.ts +4 -1
- package/src/utils/inputPresentation.ts +143 -0
- 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,573 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file ChatTokenizedText.a11y.chromium.spec.ts
|
|
5
|
+
* @input Exact-head Storybook build and ChatTokenizedText stories
|
|
6
|
+
* @output Light/dark PNGs, 10-sensor receipts, contact sheet, and fail-closed manifest
|
|
7
|
+
* @position Real-browser evidence for the ChatTokenizedText 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
|
+
// @ts-expect-error -- pngjs ships no declarations; runtime support is pinned.
|
|
16
|
+
import {PNG} from 'pngjs';
|
|
17
|
+
import {holdMotionStill} from '@astryxdesign/a11y-spec/chromium';
|
|
18
|
+
import {
|
|
19
|
+
DEFAULT_STORYBOOK_DIR,
|
|
20
|
+
serveStorybook,
|
|
21
|
+
type StaticServer,
|
|
22
|
+
} from '@astryxdesign/a11y-spec/storybook';
|
|
23
|
+
|
|
24
|
+
const OUTPUT = path.resolve('test-results/chat-tokenized-text-audit-evidence');
|
|
25
|
+
const TARGET = '.astryx-chat-tokenized-text';
|
|
26
|
+
|
|
27
|
+
type Mode = 'light' | 'dark';
|
|
28
|
+
|
|
29
|
+
interface AuditCase {
|
|
30
|
+
key: string;
|
|
31
|
+
storyId: string;
|
|
32
|
+
expectedTokens: number;
|
|
33
|
+
expectedBadges: number;
|
|
34
|
+
expectedText: string[];
|
|
35
|
+
excludedText?: string[];
|
|
36
|
+
narrow?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ImageReceipt {
|
|
40
|
+
file: string;
|
|
41
|
+
sha256: string;
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
distinctColors: number;
|
|
45
|
+
nonBlank: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface FrameReceipt {
|
|
49
|
+
frame: string;
|
|
50
|
+
passed: boolean;
|
|
51
|
+
failures: string[];
|
|
52
|
+
sensors: Record<
|
|
53
|
+
string,
|
|
54
|
+
{expected: unknown; observed: unknown; passed: boolean}
|
|
55
|
+
>;
|
|
56
|
+
image: ImageReceipt;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const CASES: AuditCase[] = [
|
|
60
|
+
{
|
|
61
|
+
key: 'single-token',
|
|
62
|
+
storyId: 'core-chattokenizedtext--single-token',
|
|
63
|
+
expectedTokens: 1,
|
|
64
|
+
expectedBadges: 1,
|
|
65
|
+
expectedText: ['@Cindy Zhang'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
key: 'multiple-tokens',
|
|
69
|
+
storyId: 'core-chattokenizedtext--multiple-tokens',
|
|
70
|
+
expectedTokens: 3,
|
|
71
|
+
expectedBadges: 3,
|
|
72
|
+
expectedText: ['@Cindy Zhang', '@Alex Rivera', '@Navi'],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
key: 'plain-text',
|
|
76
|
+
storyId: 'core-chattokenizedtext--plain-text',
|
|
77
|
+
expectedTokens: 0,
|
|
78
|
+
expectedBadges: 0,
|
|
79
|
+
expectedText: ['Just a regular message with no mentions.'],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
key: 'mixed-variants',
|
|
83
|
+
storyId: 'core-chattokenizedtext--mixed-variants',
|
|
84
|
+
expectedTokens: 3,
|
|
85
|
+
expectedBadges: 3,
|
|
86
|
+
expectedText: ['@Cindy', '#bug', '#feature'],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
key: 'tokens-at-edges',
|
|
90
|
+
storyId: 'core-chattokenizedtext--tokens-at-edges',
|
|
91
|
+
expectedTokens: 2,
|
|
92
|
+
expectedBadges: 2,
|
|
93
|
+
expectedText: ['@Cindy Zhang', '@Navi'],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
key: 'icon-and-custom',
|
|
97
|
+
storyId: 'core-chattokenizedtext--icon-and-custom-tokens',
|
|
98
|
+
expectedTokens: 2,
|
|
99
|
+
expectedBadges: 1,
|
|
100
|
+
expectedText: ['@Cindy Zhang', '@Navi'],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
key: 'empty-value-narrow',
|
|
104
|
+
storyId: 'core-chattokenizedtext--empty-value-narrow',
|
|
105
|
+
expectedTokens: 1,
|
|
106
|
+
expectedBadges: 1,
|
|
107
|
+
expectedText: ['@Alice Rivera', 'remains readable'],
|
|
108
|
+
excludedText: ['Ignored'],
|
|
109
|
+
narrow: true,
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
let server: StaticServer | undefined;
|
|
114
|
+
let head = '';
|
|
115
|
+
let storybookHead = '';
|
|
116
|
+
let browserVersion = 'unknown';
|
|
117
|
+
const receipts: FrameReceipt[] = [];
|
|
118
|
+
|
|
119
|
+
function inspectPng(file: string, bytes: Buffer): ImageReceipt {
|
|
120
|
+
const png = PNG.sync.read(bytes);
|
|
121
|
+
const colors = new Set<string>();
|
|
122
|
+
for (let index = 0; index < png.data.length; index += 4) {
|
|
123
|
+
colors.add(
|
|
124
|
+
`${png.data[index]},${png.data[index + 1]},${png.data[index + 2]},${png.data[index + 3]}`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
file,
|
|
129
|
+
sha256: createHash('sha256').update(bytes).digest('hex'),
|
|
130
|
+
width: png.width,
|
|
131
|
+
height: png.height,
|
|
132
|
+
distinctColors: colors.size,
|
|
133
|
+
nonBlank: colors.size > 1,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function storyUrl(auditCase: AuditCase, mode: Mode): string {
|
|
138
|
+
return (
|
|
139
|
+
`${server?.origin}/iframe.html?id=${auditCase.storyId}&viewMode=story` +
|
|
140
|
+
`&globals=colorMode:${mode};astryxTheme:neutral;direction:ltr`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function capture(
|
|
145
|
+
page: Page,
|
|
146
|
+
auditCase: AuditCase,
|
|
147
|
+
mode: Mode,
|
|
148
|
+
): Promise<string[]> {
|
|
149
|
+
const viewport = auditCase.narrow
|
|
150
|
+
? {width: 320, height: 640}
|
|
151
|
+
: {width: 1024, height: 768};
|
|
152
|
+
await page.setViewportSize(viewport);
|
|
153
|
+
const errors: string[] = [];
|
|
154
|
+
page.removeAllListeners('pageerror');
|
|
155
|
+
page.on('pageerror', error => errors.push(String(error)));
|
|
156
|
+
browserVersion = page.context().browser()?.version() ?? 'unknown';
|
|
157
|
+
await page.goto(storyUrl(auditCase, mode));
|
|
158
|
+
await page.locator(TARGET).waitFor();
|
|
159
|
+
await page.waitForFunction(
|
|
160
|
+
expected =>
|
|
161
|
+
document.documentElement.getAttribute('data-theme') === expected,
|
|
162
|
+
mode,
|
|
163
|
+
);
|
|
164
|
+
await holdMotionStill(page);
|
|
165
|
+
await page.evaluate(async () => document.fonts.ready);
|
|
166
|
+
|
|
167
|
+
const actual = await page.locator(TARGET).evaluate(element => {
|
|
168
|
+
const root = element as HTMLElement;
|
|
169
|
+
const rect = root.getBoundingClientRect();
|
|
170
|
+
const storyRoot = document.getElementById('storybook-root');
|
|
171
|
+
const style = getComputedStyle(root);
|
|
172
|
+
return {
|
|
173
|
+
storyId: new URL(location.href).searchParams.get('id'),
|
|
174
|
+
tagName: root.tagName,
|
|
175
|
+
targetCount: document.querySelectorAll('.astryx-chat-tokenized-text')
|
|
176
|
+
.length,
|
|
177
|
+
tokenCount: root.querySelectorAll(':scope > span').length,
|
|
178
|
+
badgeCount: root.querySelectorAll('[data-variant]').length,
|
|
179
|
+
text: (root.textContent ?? '').replace(/\s+/g, ' ').trim(),
|
|
180
|
+
interactiveCount: root.querySelectorAll(
|
|
181
|
+
'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
|
|
182
|
+
).length,
|
|
183
|
+
direction: style.direction,
|
|
184
|
+
display: style.display,
|
|
185
|
+
geometry: {
|
|
186
|
+
x: rect.x,
|
|
187
|
+
y: rect.y,
|
|
188
|
+
width: rect.width,
|
|
189
|
+
height: rect.height,
|
|
190
|
+
right: rect.right,
|
|
191
|
+
},
|
|
192
|
+
viewport: {width: innerWidth, height: innerHeight},
|
|
193
|
+
storyOverflowFree:
|
|
194
|
+
storyRoot == null || storyRoot.scrollWidth <= storyRoot.clientWidth,
|
|
195
|
+
fontsReady: document.fonts.status === 'loaded',
|
|
196
|
+
storyError:
|
|
197
|
+
document.querySelector('[data-storybook-error]') != null ||
|
|
198
|
+
document.body.textContent?.includes('Error rendering story') === true,
|
|
199
|
+
themeName:
|
|
200
|
+
document
|
|
201
|
+
.querySelector('[data-astryx-theme]')
|
|
202
|
+
?.getAttribute('data-astryx-theme') ?? null,
|
|
203
|
+
theme: document.documentElement.getAttribute('data-theme'),
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const file = `ChatTokenizedText__${auditCase.key}__neutral-${mode}__ltr.png`;
|
|
208
|
+
const bytes = await page
|
|
209
|
+
.locator('#storybook-root')
|
|
210
|
+
.screenshot({animations: 'disabled'});
|
|
211
|
+
fs.writeFileSync(path.join(OUTPUT, file), bytes);
|
|
212
|
+
const image = inspectPng(file, bytes);
|
|
213
|
+
|
|
214
|
+
const failures: string[] = [];
|
|
215
|
+
if (actual.storyId !== auditCase.storyId) {
|
|
216
|
+
failures.push('Storybook served the wrong story');
|
|
217
|
+
}
|
|
218
|
+
if (actual.tagName !== 'SPAN') {
|
|
219
|
+
failures.push('root is not a span');
|
|
220
|
+
}
|
|
221
|
+
if (actual.targetCount !== 1) {
|
|
222
|
+
failures.push('theme target is not unique');
|
|
223
|
+
}
|
|
224
|
+
if (actual.tokenCount !== auditCase.expectedTokens) {
|
|
225
|
+
failures.push(
|
|
226
|
+
`expected ${auditCase.expectedTokens} rendered tokens, observed ${actual.tokenCount}`,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if (actual.badgeCount !== auditCase.expectedBadges) {
|
|
230
|
+
failures.push(
|
|
231
|
+
`expected ${auditCase.expectedBadges} badges, observed ${actual.badgeCount}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
for (const text of auditCase.expectedText) {
|
|
235
|
+
if (!actual.text.includes(text)) {
|
|
236
|
+
failures.push(`missing text: ${text}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
for (const text of auditCase.excludedText ?? []) {
|
|
240
|
+
if (actual.text.includes(text)) {
|
|
241
|
+
failures.push(`unexpected text: ${text}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (actual.interactiveCount !== 0) {
|
|
245
|
+
failures.push('unexpected interactive child');
|
|
246
|
+
}
|
|
247
|
+
if (actual.direction !== 'ltr') {
|
|
248
|
+
failures.push('unexpected direction');
|
|
249
|
+
}
|
|
250
|
+
if (actual.themeName !== 'neutral') {
|
|
251
|
+
failures.push('neutral theme did not settle');
|
|
252
|
+
}
|
|
253
|
+
if (actual.theme !== mode) {
|
|
254
|
+
failures.push('theme mode did not settle');
|
|
255
|
+
}
|
|
256
|
+
if (!actual.storyOverflowFree) {
|
|
257
|
+
failures.push('component story overflow detected');
|
|
258
|
+
}
|
|
259
|
+
if (
|
|
260
|
+
actual.geometry.width <= 0 ||
|
|
261
|
+
actual.geometry.height <= 0 ||
|
|
262
|
+
actual.geometry.x < 0 ||
|
|
263
|
+
actual.geometry.right > actual.viewport.width
|
|
264
|
+
) {
|
|
265
|
+
failures.push('subject geometry escaped the viewport');
|
|
266
|
+
}
|
|
267
|
+
if (!actual.fontsReady) {
|
|
268
|
+
failures.push('fonts did not settle');
|
|
269
|
+
}
|
|
270
|
+
if (actual.storyError) {
|
|
271
|
+
failures.push('Storybook rendered an error');
|
|
272
|
+
}
|
|
273
|
+
if (errors.length > 0) {
|
|
274
|
+
failures.push(`page errors: ${errors.join('; ')}`);
|
|
275
|
+
}
|
|
276
|
+
if (!image.nonBlank) {
|
|
277
|
+
failures.push('blank image');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const sensors: FrameReceipt['sensors'] = {
|
|
281
|
+
Build: {
|
|
282
|
+
expected: head,
|
|
283
|
+
observed: storybookHead,
|
|
284
|
+
passed: head === storybookHead,
|
|
285
|
+
},
|
|
286
|
+
Story: {
|
|
287
|
+
expected: auditCase.storyId,
|
|
288
|
+
observed: actual.storyId,
|
|
289
|
+
passed: actual.storyId === auditCase.storyId,
|
|
290
|
+
},
|
|
291
|
+
Theme: {
|
|
292
|
+
expected: 'neutral',
|
|
293
|
+
observed: actual.themeName,
|
|
294
|
+
passed: actual.themeName === 'neutral',
|
|
295
|
+
},
|
|
296
|
+
'Color mode': {
|
|
297
|
+
expected: mode,
|
|
298
|
+
observed: actual.theme,
|
|
299
|
+
passed: mode === actual.theme,
|
|
300
|
+
},
|
|
301
|
+
Direction: {
|
|
302
|
+
expected: 'ltr',
|
|
303
|
+
observed: actual.direction,
|
|
304
|
+
passed: actual.direction === 'ltr',
|
|
305
|
+
},
|
|
306
|
+
'Viewport/media': {
|
|
307
|
+
expected: viewport,
|
|
308
|
+
observed: actual.viewport,
|
|
309
|
+
passed:
|
|
310
|
+
actual.viewport.width === viewport.width &&
|
|
311
|
+
actual.viewport.height === viewport.height,
|
|
312
|
+
},
|
|
313
|
+
'Rendered state': {
|
|
314
|
+
expected: {
|
|
315
|
+
tokenCount: auditCase.expectedTokens,
|
|
316
|
+
badgeCount: auditCase.expectedBadges,
|
|
317
|
+
expectedText: auditCase.expectedText,
|
|
318
|
+
excludedText: auditCase.excludedText ?? [],
|
|
319
|
+
interactiveCount: 0,
|
|
320
|
+
},
|
|
321
|
+
observed: {
|
|
322
|
+
tokenCount: actual.tokenCount,
|
|
323
|
+
badgeCount: actual.badgeCount,
|
|
324
|
+
text: actual.text,
|
|
325
|
+
interactiveCount: actual.interactiveCount,
|
|
326
|
+
},
|
|
327
|
+
passed: failures.every(
|
|
328
|
+
failure =>
|
|
329
|
+
!failure.includes('token') &&
|
|
330
|
+
!failure.includes('badge') &&
|
|
331
|
+
!failure.includes('text') &&
|
|
332
|
+
!failure.includes('interactive'),
|
|
333
|
+
),
|
|
334
|
+
},
|
|
335
|
+
'Subject geometry': {
|
|
336
|
+
expected: {visible: true, overflowFree: true, insideViewport: true},
|
|
337
|
+
observed: {
|
|
338
|
+
geometry: actual.geometry,
|
|
339
|
+
storyOverflowFree: actual.storyOverflowFree,
|
|
340
|
+
},
|
|
341
|
+
passed:
|
|
342
|
+
actual.geometry.width > 0 &&
|
|
343
|
+
actual.geometry.height > 0 &&
|
|
344
|
+
actual.geometry.x >= 0 &&
|
|
345
|
+
actual.geometry.right <= actual.viewport.width &&
|
|
346
|
+
actual.storyOverflowFree,
|
|
347
|
+
},
|
|
348
|
+
'Settled render': {
|
|
349
|
+
expected: {fontsReady: true, pageErrors: 0, storyError: false},
|
|
350
|
+
observed: {
|
|
351
|
+
fontsReady: actual.fontsReady,
|
|
352
|
+
pageErrors: errors,
|
|
353
|
+
storyError: actual.storyError,
|
|
354
|
+
},
|
|
355
|
+
passed: actual.fontsReady && errors.length === 0 && !actual.storyError,
|
|
356
|
+
},
|
|
357
|
+
Image: {
|
|
358
|
+
expected: {nonBlank: true, nonZeroPixels: true},
|
|
359
|
+
observed: image,
|
|
360
|
+
passed: image.nonBlank && image.width > 0 && image.height > 0,
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const frame = `${auditCase.key}__neutral-${mode}__ltr`;
|
|
365
|
+
const receipt: FrameReceipt = {
|
|
366
|
+
frame,
|
|
367
|
+
passed:
|
|
368
|
+
failures.length === 0 &&
|
|
369
|
+
Object.values(sensors).every(sensor => sensor.passed),
|
|
370
|
+
failures,
|
|
371
|
+
sensors,
|
|
372
|
+
image,
|
|
373
|
+
};
|
|
374
|
+
fs.writeFileSync(
|
|
375
|
+
path.join(OUTPUT, `${frame}.sensors.json`),
|
|
376
|
+
`${JSON.stringify(receipt, null, 2)}\n`,
|
|
377
|
+
);
|
|
378
|
+
receipts.push(receipt);
|
|
379
|
+
return failures.map(failure => `${frame}: ${failure}`);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async function writeContactSheet(page: Page): Promise<ImageReceipt> {
|
|
383
|
+
const figures = receipts
|
|
384
|
+
.map(receipt => {
|
|
385
|
+
const bytes = fs.readFileSync(path.join(OUTPUT, receipt.image.file));
|
|
386
|
+
return `<figure><img src="data:image/png;base64,${bytes.toString('base64')}" alt=""><figcaption>${receipt.frame}</figcaption></figure>`;
|
|
387
|
+
})
|
|
388
|
+
.join('');
|
|
389
|
+
await page.setViewportSize({width: 1200, height: 900});
|
|
390
|
+
await page.setContent(`<!doctype html>
|
|
391
|
+
<style>
|
|
392
|
+
html { color-scheme: light; background: #f3f4f6; }
|
|
393
|
+
body { margin: 20px; font: 12px/1.35 system-ui, sans-serif; color: #111827; }
|
|
394
|
+
h1 { margin: 0 0 16px; font-size: 20px; }
|
|
395
|
+
main { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
|
|
396
|
+
figure { margin: 0; padding: 10px; border: 1px solid #d1d5db; border-radius: 6px; background: white; }
|
|
397
|
+
img { display: block; width: 100%; height: 120px; object-fit: contain; }
|
|
398
|
+
figcaption { margin-top: 8px; overflow-wrap: anywhere; }
|
|
399
|
+
</style>
|
|
400
|
+
<h1>ChatTokenizedText exact-head state evidence</h1>
|
|
401
|
+
<main>${figures}</main>`);
|
|
402
|
+
await page.locator('img').evaluateAll(async images => {
|
|
403
|
+
await Promise.all(
|
|
404
|
+
images.map(async image => {
|
|
405
|
+
const candidate = image as HTMLImageElement;
|
|
406
|
+
if (candidate.complete) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
await new Promise<void>((resolve, reject) => {
|
|
410
|
+
candidate.addEventListener('load', () => resolve(), {once: true});
|
|
411
|
+
candidate.addEventListener(
|
|
412
|
+
'error',
|
|
413
|
+
() => reject(new Error('image failed')),
|
|
414
|
+
{
|
|
415
|
+
once: true,
|
|
416
|
+
},
|
|
417
|
+
);
|
|
418
|
+
});
|
|
419
|
+
}),
|
|
420
|
+
);
|
|
421
|
+
});
|
|
422
|
+
const file = 'ChatTokenizedText__contact-sheet.png';
|
|
423
|
+
const bytes = await page.screenshot({fullPage: true, animations: 'disabled'});
|
|
424
|
+
fs.writeFileSync(path.join(OUTPUT, file), bytes);
|
|
425
|
+
return inspectPng(file, bytes);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
test.describe.configure({mode: 'serial', retries: 0});
|
|
429
|
+
|
|
430
|
+
test.beforeAll(async () => {
|
|
431
|
+
head = execFileSync('git', ['rev-parse', 'HEAD'], {encoding: 'utf8'}).trim();
|
|
432
|
+
const dirty = execFileSync(
|
|
433
|
+
'git',
|
|
434
|
+
[
|
|
435
|
+
'status',
|
|
436
|
+
'--porcelain',
|
|
437
|
+
'--untracked-files=all',
|
|
438
|
+
'--',
|
|
439
|
+
'apps/storybook/stories/ChatTokenizedText.stories.tsx',
|
|
440
|
+
'packages/core/src/Chat/ChatTokenizedText.tsx',
|
|
441
|
+
'packages/core/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts',
|
|
442
|
+
],
|
|
443
|
+
{encoding: 'utf8'},
|
|
444
|
+
).trim();
|
|
445
|
+
if (dirty !== '') {
|
|
446
|
+
throw new Error(
|
|
447
|
+
`browser evidence requires committed source files: ${dirty}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
if (process.env.ASTRYX_HEAD_SHA && process.env.ASTRYX_HEAD_SHA !== head) {
|
|
451
|
+
throw new Error('PR head differs from the checked out source');
|
|
452
|
+
}
|
|
453
|
+
fs.rmSync(OUTPUT, {recursive: true, force: true});
|
|
454
|
+
fs.mkdirSync(OUTPUT, {recursive: true});
|
|
455
|
+
server = await serveStorybook(
|
|
456
|
+
process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
|
|
457
|
+
);
|
|
458
|
+
const stamp = await fetch(`${server.origin}/astryx-build-sha.txt`);
|
|
459
|
+
if (!stamp.ok) {
|
|
460
|
+
throw new Error('Storybook build is missing its source stamp');
|
|
461
|
+
}
|
|
462
|
+
storybookHead = (await stamp.text()).trim();
|
|
463
|
+
if (storybookHead !== head) {
|
|
464
|
+
throw new Error('Storybook bytes differ from the PR head');
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test.afterAll(async () => {
|
|
469
|
+
const expectedFrames = CASES.flatMap(auditCase =>
|
|
470
|
+
(['light', 'dark'] as const).map(
|
|
471
|
+
mode => `${auditCase.key}__neutral-${mode}__ltr`,
|
|
472
|
+
),
|
|
473
|
+
);
|
|
474
|
+
const observed = new Set(receipts.map(receipt => receipt.frame));
|
|
475
|
+
const failures = [
|
|
476
|
+
...expectedFrames
|
|
477
|
+
.filter(frame => !observed.has(frame))
|
|
478
|
+
.map(frame => `missing frame: ${frame}`),
|
|
479
|
+
...receipts
|
|
480
|
+
.filter(receipt => !receipt.passed)
|
|
481
|
+
.map(receipt => `failed frame: ${receipt.frame}`),
|
|
482
|
+
];
|
|
483
|
+
const contactSheetFile = 'ChatTokenizedText__contact-sheet.png';
|
|
484
|
+
const contactSheetPath = path.join(OUTPUT, contactSheetFile);
|
|
485
|
+
const contactSheet = fs.existsSync(contactSheetPath)
|
|
486
|
+
? inspectPng(contactSheetFile, fs.readFileSync(contactSheetPath))
|
|
487
|
+
: null;
|
|
488
|
+
if (contactSheet?.nonBlank !== true) {
|
|
489
|
+
failures.push('missing contact sheet');
|
|
490
|
+
}
|
|
491
|
+
if (head && storybookHead) {
|
|
492
|
+
fs.writeFileSync(
|
|
493
|
+
path.join(OUTPUT, 'manifest.json'),
|
|
494
|
+
`${JSON.stringify(
|
|
495
|
+
{
|
|
496
|
+
version: 1,
|
|
497
|
+
component: 'core/ChatTokenizedText',
|
|
498
|
+
headSha: head,
|
|
499
|
+
storybookSha: storybookHead,
|
|
500
|
+
baselineHeadSha: process.env.ASTRYX_AUDIT_BASELINE_HEAD ?? null,
|
|
501
|
+
browser: browserVersion,
|
|
502
|
+
failClosed: true,
|
|
503
|
+
matrixComplete: failures.length === 0,
|
|
504
|
+
matrixFailures: failures,
|
|
505
|
+
sensorCount: 10,
|
|
506
|
+
requiredSensors: [
|
|
507
|
+
'Build',
|
|
508
|
+
'Story',
|
|
509
|
+
'Theme',
|
|
510
|
+
'Color mode',
|
|
511
|
+
'Direction',
|
|
512
|
+
'Viewport/media',
|
|
513
|
+
'Rendered state',
|
|
514
|
+
'Subject geometry',
|
|
515
|
+
'Settled render',
|
|
516
|
+
'Image',
|
|
517
|
+
],
|
|
518
|
+
visualEvidence: {
|
|
519
|
+
requiredPair: false,
|
|
520
|
+
reason:
|
|
521
|
+
'The repair removes a non-advancing empty match and does not intentionally change settled pixels. The base behavior has no settled before frame because rendering does not terminate; bounded unit evidence proves that failure, and exact-head frames verify the repaired state.',
|
|
522
|
+
subjectiveAcceptanceClaimed: false,
|
|
523
|
+
contactSheet,
|
|
524
|
+
},
|
|
525
|
+
notApplicable: {
|
|
526
|
+
hover: 'ChatTokenizedText owns no interaction.',
|
|
527
|
+
focus: 'ChatTokenizedText introduces no focusable element.',
|
|
528
|
+
pressed: 'ChatTokenizedText has no activation behavior.',
|
|
529
|
+
disabled: 'ChatTokenizedText exposes no disabled state.',
|
|
530
|
+
loading: 'ChatTokenizedText exposes no loading state.',
|
|
531
|
+
selected: 'ChatTokenizedText exposes no selection state.',
|
|
532
|
+
keyboard: 'ChatTokenizedText owns no keyboard interaction.',
|
|
533
|
+
pointerTarget: 'ChatTokenizedText owns no pointer target.',
|
|
534
|
+
rtl: 'A source-hashed verified-N/A record covers its direction-neutral inline flow.',
|
|
535
|
+
},
|
|
536
|
+
unverified: {
|
|
537
|
+
assistiveTechnology:
|
|
538
|
+
'Browser semantics and axe output are measured; spoken output was not tested with assistive technology.',
|
|
539
|
+
customTokenContent:
|
|
540
|
+
'Semantics, interaction, and paint inside custom token renderers remain caller owned.',
|
|
541
|
+
},
|
|
542
|
+
stateVisualConformance: {
|
|
543
|
+
states: CASES.map(auditCase => auditCase.key),
|
|
544
|
+
colorModes: ['light', 'dark'],
|
|
545
|
+
narrow320: ['empty-value-narrow'],
|
|
546
|
+
},
|
|
547
|
+
frames: receipts,
|
|
548
|
+
},
|
|
549
|
+
null,
|
|
550
|
+
2,
|
|
551
|
+
)}\n`,
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
await server?.close();
|
|
555
|
+
expect(failures, 'complete exact-head evidence matrix').toEqual([]);
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
test('captures the complete light, dark, and 320px state matrix', async ({
|
|
559
|
+
page,
|
|
560
|
+
}) => {
|
|
561
|
+
await page.emulateMedia({reducedMotion: 'reduce'});
|
|
562
|
+
const failures: string[] = [];
|
|
563
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
564
|
+
for (const auditCase of CASES) {
|
|
565
|
+
failures.push(...(await capture(page, auditCase, mode)));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const contactSheet = await writeContactSheet(page);
|
|
569
|
+
if (!contactSheet.nonBlank) {
|
|
570
|
+
failures.push('contact sheet is blank');
|
|
571
|
+
}
|
|
572
|
+
expect(failures).toEqual([]);
|
|
573
|
+
});
|
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
|
},
|