@astryxdesign/core 0.6.2 → 0.6.3-canary.01fa439
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/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/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/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 +10 -1
- 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/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/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 +16 -0
- package/dist/Markdown/plugins/index.d.ts.map +1 -0
- package/dist/Markdown/plugins/index.js +13 -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/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 +4 -0
- package/dist/Markdown/url.d.ts.map +1 -0
- package/dist/Markdown/url.js +25 -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/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/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/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 +7 -5
- 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/ToggleButton/ToggleButton.d.ts +9 -6
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +15 -27
- 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 +18 -7
- 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/useScrollableArea.d.ts +6 -2
- package/dist/hooks/useScrollableArea.d.ts.map +1 -1
- package/dist/hooks/useScrollableArea.js +17 -5
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +10 -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/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 +19 -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/__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/ChatSendButton.test.tsx +1 -4
- package/src/Chat/ChatSendButton.tsx +1 -1
- 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/ClickableCard/ClickableCard.test.tsx +102 -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/DialogHeader.doc.mjs +12 -0
- package/src/Dialog/DialogHeader.test.tsx +97 -0
- package/src/Dialog/DialogHeader.tsx +25 -3
- package/src/Dialog/modules/DialogHeader.spec.md +75 -38
- 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/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 +11 -0
- package/src/Link/Link.test.tsx +24 -0
- package/src/Link/Link.tsx +5 -0
- package/src/List/List.spec.md +200 -0
- package/src/Markdown/Markdown.doc.mjs +272 -0
- 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 +126 -3
- package/src/Markdown/Markdown.spec.md +197 -44
- package/src/Markdown/Markdown.test.tsx +11 -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/parser/index.ts +64 -0
- package/src/Markdown/parser.public.test.ts +103 -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 +53 -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/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 +30 -0
- package/src/Markdown/utils.ts +13 -1
- 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/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/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 +23 -14
- 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.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/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/Tokenizer/Tokenizer.spec.md +142 -75
- 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/useScrollableArea.doc.mjs +15 -3
- package/src/hooks/useScrollableArea.test.tsx +59 -1
- package/src/hooks/useScrollableArea.ts +34 -10
- package/src/inputFontFloor.test.ts +106 -0
- package/src/tailwind-theme.css +0 -6
- package/src/theme/generateThemeRules.test.ts +30 -0
- package/src/theme/generateThemeRules.ts +10 -0
- package/src/utils/interactionOverlay.stylex.ts +20 -0
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Selector.tsx
|
|
7
|
-
* @input Uses React, StyleX,
|
|
8
|
-
* and
|
|
9
|
-
* @output Exports Selector
|
|
7
|
+
* @input Uses React, StyleX, adaptive selection surfaces, theme-resolved
|
|
8
|
+
* indicators, Field, and InputGroup context
|
|
9
|
+
* @output Exports Selector with content-derived option-mark layout
|
|
10
10
|
* @position Core implementation; consumed by index.ts
|
|
11
11
|
*
|
|
12
12
|
* SYNC: When modified, update:
|
|
13
|
+
* - /packages/core/src/Selector/Selector.spec.md
|
|
13
14
|
* - /packages/core/src/Selector/Selector.doc.mjs
|
|
14
15
|
* - /packages/core/src/Selector/Selector.test.tsx
|
|
15
16
|
* - /packages/core/src/Selector/index.ts
|
|
17
|
+
* - /apps/storybook/stories/Selector.stories.tsx
|
|
16
18
|
* - /apps/storybook/stories/InputGroup.stories.tsx
|
|
17
19
|
* - /packages/cli/assets/templates/blocks/components/Selector/ (showcase blocks)
|
|
18
20
|
*/
|
|
@@ -102,9 +104,14 @@ const styles = stylex.create({
|
|
|
102
104
|
paddingBlock: spacingVars['--spacing-2'],
|
|
103
105
|
paddingInline: spacingVars['--spacing-3'],
|
|
104
106
|
fontFamily: typographyVars['--font-family-body'],
|
|
107
|
+
// The 16px floor is iOS-only: iOS Safari zooms the page when a focused
|
|
108
|
+
// control sits under 16px, and only iOS WebKit implements
|
|
109
|
+
// -webkit-touch-callout to key the coarse-pointer floor to it.
|
|
105
110
|
fontSize: {
|
|
106
111
|
default: typeScaleVars['--text-label-size'],
|
|
107
|
-
'@media (pointer: coarse)':
|
|
112
|
+
'@media (pointer: coarse)': {
|
|
113
|
+
'@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-label-size']})`,
|
|
114
|
+
},
|
|
108
115
|
},
|
|
109
116
|
// A FIXED line box, not the ratio: the trigger's padding is derived from
|
|
110
117
|
// one line being `--spacing-5` tall, and a ratio makes the line box track
|
|
@@ -362,18 +369,20 @@ const styles = stylex.create({
|
|
|
362
369
|
flex: 1,
|
|
363
370
|
minWidth: 0,
|
|
364
371
|
},
|
|
365
|
-
// The
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
// indicator (a radio is 20px at `sm`), and the column has to grow with it.
|
|
372
|
+
// The wrapper keeps a visible mark at either logical position and lets a
|
|
373
|
+
// replacement indicator grow beyond the default 1rem minimum. When the
|
|
374
|
+
// resolved indicator draws nothing, `:empty` removes the wrapper from layout
|
|
375
|
+
// instead of reserving blank space. Selected and unselected labels may
|
|
376
|
+
// therefore shift or have different available width by design (AST-004).
|
|
371
377
|
itemMarkColumn: {
|
|
372
378
|
display: 'inline-flex',
|
|
373
379
|
alignItems: 'center',
|
|
374
380
|
justifyContent: 'center',
|
|
375
381
|
flexShrink: 0,
|
|
376
382
|
minWidth: '1rem',
|
|
383
|
+
':empty': {
|
|
384
|
+
display: 'none',
|
|
385
|
+
},
|
|
377
386
|
},
|
|
378
387
|
itemCheckmark: {
|
|
379
388
|
flexShrink: 0,
|
|
@@ -649,10 +658,10 @@ interface SelectorPropsBase<
|
|
|
649
658
|
renderValue?: (option: SelectorOptionData) => ReactNode;
|
|
650
659
|
|
|
651
660
|
/**
|
|
652
|
-
* Which edge of the option row carries
|
|
653
|
-
* mark
|
|
654
|
-
*
|
|
655
|
-
* CommandPalette.
|
|
661
|
+
* Which logical edge of the option row carries a rendered selection mark. An
|
|
662
|
+
* empty mark consumes no space, so selected and unselected labels may shift or
|
|
663
|
+
* have different available width. `end` is the house convention shared with
|
|
664
|
+
* Typeahead and CommandPalette.
|
|
656
665
|
*
|
|
657
666
|
* @default 'end'
|
|
658
667
|
*/
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Listbox.a11y.chromium.spec.ts
|
|
5
|
+
* @input Uses the Listbox contract, browser harness, state inventory, and checked-in stories
|
|
6
|
+
* @output DOM/accessibility-tree evidence for each real Listbox binding part
|
|
7
|
+
* @position Browser binding; keyboard policy, pixels, and real AT remain separate owners.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {expect, test} from '@playwright/test';
|
|
11
|
+
import {
|
|
12
|
+
LISTBOX_PATTERN,
|
|
13
|
+
checkAccessibilitySpec,
|
|
14
|
+
blockingResults,
|
|
15
|
+
formatFailures,
|
|
16
|
+
formatReport,
|
|
17
|
+
summarize,
|
|
18
|
+
neverExercised,
|
|
19
|
+
unmatchedKnownFailures,
|
|
20
|
+
type BindingResult,
|
|
21
|
+
} from '@astryxdesign/a11y-spec';
|
|
22
|
+
import {
|
|
23
|
+
createChromiumHarness,
|
|
24
|
+
holdMotionStill,
|
|
25
|
+
} from '@astryxdesign/a11y-spec/chromium';
|
|
26
|
+
import {
|
|
27
|
+
serveStorybook,
|
|
28
|
+
DEFAULT_STORYBOOK_DIR,
|
|
29
|
+
type StaticServer,
|
|
30
|
+
} from '@astryxdesign/a11y-spec/storybook';
|
|
31
|
+
import {LISTBOX_KNOWN_FAILURES} from './Listbox.a11y.known-failures';
|
|
32
|
+
import {LISTBOX_SCENARIOS, listboxParts} from './Listbox.a11y.states';
|
|
33
|
+
|
|
34
|
+
let storybook: StaticServer;
|
|
35
|
+
const observedResults: BindingResult[] = [];
|
|
36
|
+
test.beforeAll(async () => {
|
|
37
|
+
storybook = await serveStorybook(
|
|
38
|
+
process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
test.afterAll(async () => {
|
|
42
|
+
await storybook?.close();
|
|
43
|
+
expect(
|
|
44
|
+
unmatchedKnownFailures(LISTBOX_KNOWN_FAILURES, observedResults),
|
|
45
|
+
).toEqual([]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
for (const scenario of LISTBOX_SCENARIOS) {
|
|
49
|
+
test(`${scenario.component} — ${scenario.id}`, async ({page}) => {
|
|
50
|
+
test.setTimeout(2 * 60 * 1000);
|
|
51
|
+
const cdp = await page.context().newCDPSession(page);
|
|
52
|
+
const results: BindingResult[] = [];
|
|
53
|
+
const mount = async () => {
|
|
54
|
+
await page.goto(
|
|
55
|
+
`${storybook.origin}/iframe.html?id=a11y-listbox-pattern--${scenario.id}&viewMode=story&globals=direction:${scenario.direction ?? 'ltr'}`,
|
|
56
|
+
{waitUntil: 'load'},
|
|
57
|
+
);
|
|
58
|
+
await holdMotionStill(page);
|
|
59
|
+
await expect(
|
|
60
|
+
page.locator(`[data-listbox-scenario="${scenario.id}"]`),
|
|
61
|
+
).toBeAttached();
|
|
62
|
+
await page.getByRole('listbox').waitFor({state: 'visible'});
|
|
63
|
+
if (scenario.query != null) {
|
|
64
|
+
await page.getByRole('combobox').fill(scenario.query);
|
|
65
|
+
}
|
|
66
|
+
await expect(page.getByRole('listbox').getByRole('option')).toHaveCount(
|
|
67
|
+
scenario.expectedOptions.length,
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
for (const part of listboxParts(scenario)) {
|
|
72
|
+
results.push(
|
|
73
|
+
await checkAccessibilitySpec({
|
|
74
|
+
spec: LISTBOX_PATTERN,
|
|
75
|
+
binding: `${scenario.component}.${part.role}`,
|
|
76
|
+
state: part.state,
|
|
77
|
+
facts: part.facts,
|
|
78
|
+
knownFailures: LISTBOX_KNOWN_FAILURES,
|
|
79
|
+
mount: async () => {
|
|
80
|
+
await mount();
|
|
81
|
+
const listbox = page.getByRole('listbox');
|
|
82
|
+
const subject =
|
|
83
|
+
part.role === 'listbox'
|
|
84
|
+
? listbox
|
|
85
|
+
: part.role === 'group'
|
|
86
|
+
? listbox
|
|
87
|
+
.getByRole('group')
|
|
88
|
+
.nth(scenario.groups.indexOf(part.name ?? ''))
|
|
89
|
+
: listbox.getByRole('option', {
|
|
90
|
+
name: part.name,
|
|
91
|
+
exact: true,
|
|
92
|
+
});
|
|
93
|
+
return createChromiumHarness({
|
|
94
|
+
page,
|
|
95
|
+
cdp,
|
|
96
|
+
subject,
|
|
97
|
+
related: {
|
|
98
|
+
listbox,
|
|
99
|
+
...Object.fromEntries(
|
|
100
|
+
scenario.expectedOptions.map(option => [
|
|
101
|
+
`option:${option.value}`,
|
|
102
|
+
listbox.getByRole('option', {
|
|
103
|
+
name: option.name,
|
|
104
|
+
exact: true,
|
|
105
|
+
}),
|
|
106
|
+
]),
|
|
107
|
+
),
|
|
108
|
+
...Object.fromEntries(
|
|
109
|
+
scenario.groups.map((name, index) => [
|
|
110
|
+
`group:${name}`,
|
|
111
|
+
listbox.getByRole('group').nth(index),
|
|
112
|
+
]),
|
|
113
|
+
),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
observedResults.push(...results);
|
|
122
|
+
const report = summarize(LISTBOX_PATTERN, results);
|
|
123
|
+
console.log(formatReport(report));
|
|
124
|
+
expect(formatFailures(blockingResults(results))).toBe('');
|
|
125
|
+
expect(report.counts.unrun).toBe(0);
|
|
126
|
+
if (scenario.component === 'Selector' && scenario.groups.length > 0) {
|
|
127
|
+
expect(neverExercised(results)).toEqual([]);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Listbox.a11y.dom.ts
|
|
5
|
+
* @input Uses Vitest lifecycle hooks and the DOM Dialog prototype
|
|
6
|
+
* @output Scoped stubs for Dialog methods missing from jsdom
|
|
7
|
+
* @position DOM-only binding setup; these stubs prove no native modal behavior.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {afterAll, beforeAll} from 'vitest';
|
|
11
|
+
|
|
12
|
+
export function installListboxDialogStubs(): void {
|
|
13
|
+
const originals = new Map<string, PropertyDescriptor | undefined>();
|
|
14
|
+
beforeAll(() => {
|
|
15
|
+
for (const name of ['show', 'showModal', 'close']) {
|
|
16
|
+
originals.set(
|
|
17
|
+
name,
|
|
18
|
+
Object.getOwnPropertyDescriptor(HTMLDialogElement.prototype, name),
|
|
19
|
+
);
|
|
20
|
+
Object.defineProperty(HTMLDialogElement.prototype, name, {
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: function (this: HTMLDialogElement) {
|
|
24
|
+
this.open = name !== 'close';
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
afterAll(() => {
|
|
30
|
+
for (const [name, descriptor] of originals) {
|
|
31
|
+
if (descriptor == null) {
|
|
32
|
+
Reflect.deleteProperty(HTMLDialogElement.prototype, name);
|
|
33
|
+
} else {
|
|
34
|
+
Object.defineProperty(HTMLDialogElement.prototype, name, descriptor);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Listbox.a11y.inventory.test.ts
|
|
5
|
+
* @input Uses the locked Listbox migration matrix and checklist
|
|
6
|
+
* @output Coverage-boundary and part-inventory regression checks
|
|
7
|
+
* @position Binding metadata proof, separate from runtime conformance results.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {describe, expect, it} from 'vitest';
|
|
11
|
+
import {LISTBOX_PATTERN, unansweredDimensions} from '@astryxdesign/a11y-spec';
|
|
12
|
+
import {LISTBOX_KNOWN_FAILURES} from './Listbox.a11y.known-failures';
|
|
13
|
+
import {
|
|
14
|
+
LISTBOX_SCENARIOS,
|
|
15
|
+
LISTBOX_EXCLUSIONS,
|
|
16
|
+
listboxParts,
|
|
17
|
+
} from './Listbox.a11y.states';
|
|
18
|
+
|
|
19
|
+
describe('Listbox migration inventory', () => {
|
|
20
|
+
it('accounts for every checklist dimension without claiming other evidence layers', () => {
|
|
21
|
+
expect(unansweredDimensions(LISTBOX_PATTERN)).toEqual([]);
|
|
22
|
+
expect(LISTBOX_EXCLUSIONS).toHaveLength(5);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('binds 21 scenarios and all six real semantic parts', () => {
|
|
26
|
+
expect(LISTBOX_SCENARIOS).toHaveLength(21);
|
|
27
|
+
const parts = LISTBOX_SCENARIOS.flatMap(scenario =>
|
|
28
|
+
listboxParts(scenario).map(part => ({
|
|
29
|
+
binding: `${scenario.component}.${part.role}`,
|
|
30
|
+
state: part.state,
|
|
31
|
+
})),
|
|
32
|
+
);
|
|
33
|
+
expect(parts).toHaveLength(89);
|
|
34
|
+
expect(new Set(parts.map(part => part.state)).size).toBe(89);
|
|
35
|
+
expect([...new Set(parts.map(part => part.binding))].sort()).toEqual([
|
|
36
|
+
'MultiSelector.group',
|
|
37
|
+
'MultiSelector.listbox',
|
|
38
|
+
'MultiSelector.option',
|
|
39
|
+
'Selector.group',
|
|
40
|
+
'Selector.listbox',
|
|
41
|
+
'Selector.option',
|
|
42
|
+
]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('pins each known failure to one exact inventory part', () => {
|
|
46
|
+
const parts = LISTBOX_SCENARIOS.flatMap(scenario =>
|
|
47
|
+
listboxParts(scenario).map(part => ({
|
|
48
|
+
binding: `${scenario.component}.${part.role}`,
|
|
49
|
+
state: part.state,
|
|
50
|
+
})),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(LISTBOX_KNOWN_FAILURES).toHaveLength(2);
|
|
54
|
+
for (const record of LISTBOX_KNOWN_FAILURES) {
|
|
55
|
+
expect(
|
|
56
|
+
parts.filter(
|
|
57
|
+
part =>
|
|
58
|
+
part.binding === record.binding && part.state === record.state,
|
|
59
|
+
),
|
|
60
|
+
).toHaveLength(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Listbox.a11y.known-failures.ts
|
|
5
|
+
* @input Uses KnownFailure from @astryxdesign/a11y-spec
|
|
6
|
+
* @output Exact public-safe Selector and MultiSelector listbox migration failures
|
|
7
|
+
* @position AST-021 debt records; operational ownership remains outside public source.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {KnownFailure} from '@astryxdesign/a11y-spec';
|
|
11
|
+
|
|
12
|
+
export const LISTBOX_KNOWN_FAILURES: ReadonlyArray<KnownFailure> = [
|
|
13
|
+
{
|
|
14
|
+
expectation: 'listbox.exposure.identity',
|
|
15
|
+
binding: 'Selector.listbox',
|
|
16
|
+
state: 'single-sheet:listbox',
|
|
17
|
+
evidenceLayer: 'accessibility-tree',
|
|
18
|
+
failureEquals: 'the browser exposes the listbox without an accessible name',
|
|
19
|
+
standardsReference: 'WCAG 2.2 4.1.2 Name, Role, Value (Level A)',
|
|
20
|
+
userImpact:
|
|
21
|
+
'An accessibility consumer encounters an unnamed listbox in the bottom-sheet presentation and cannot identify what set of choices it contains.',
|
|
22
|
+
reason:
|
|
23
|
+
'The no-search bottom-sheet presentation renders a visible sheet heading without assigning that heading, or another label, as the listbox accessible name. This migration records the existing behavior without changing the component.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
expectation: 'listbox.exposure.identity',
|
|
27
|
+
binding: 'MultiSelector.listbox',
|
|
28
|
+
state: 'multiple-sheet:listbox',
|
|
29
|
+
evidenceLayer: 'accessibility-tree',
|
|
30
|
+
failureEquals: 'the browser exposes the listbox without an accessible name',
|
|
31
|
+
standardsReference: 'WCAG 2.2 4.1.2 Name, Role, Value (Level A)',
|
|
32
|
+
userImpact:
|
|
33
|
+
'An accessibility consumer encounters an unnamed multi-select listbox in the bottom-sheet presentation and cannot identify what set of choices it contains.',
|
|
34
|
+
reason:
|
|
35
|
+
'The no-search bottom-sheet presentation renders a visible sheet heading without assigning that heading, or another label, as the listbox accessible name. This migration records the existing behavior without changing the component.',
|
|
36
|
+
},
|
|
37
|
+
];
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Listbox.a11y.states.ts
|
|
5
|
+
* @input Uses public Selector option types and the shared Listbox facts
|
|
6
|
+
* @output A bounded, explicit inventory of existing listbox/group/option states
|
|
7
|
+
* @position Test-only migration ledger shared by component tests and browser stories.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {ListboxStateFacts} from '@astryxdesign/a11y-spec';
|
|
11
|
+
import type {SelectorOptionType} from '../types';
|
|
12
|
+
|
|
13
|
+
export interface ListboxScenario {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly component: 'Selector' | 'MultiSelector';
|
|
16
|
+
readonly options: SelectorOptionType[];
|
|
17
|
+
readonly values: string[];
|
|
18
|
+
readonly expectedOptions: ReadonlyArray<{
|
|
19
|
+
value: string;
|
|
20
|
+
name: string;
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
selected?: boolean;
|
|
23
|
+
group?: string;
|
|
24
|
+
}>;
|
|
25
|
+
readonly groups: ReadonlyArray<string>;
|
|
26
|
+
readonly hasSearch?: boolean;
|
|
27
|
+
readonly query?: string;
|
|
28
|
+
readonly presentation?: 'popover' | 'bottom-sheet';
|
|
29
|
+
readonly customContent?: boolean;
|
|
30
|
+
readonly hiddenLabel?: boolean;
|
|
31
|
+
readonly direction?: 'ltr' | 'rtl';
|
|
32
|
+
readonly isLoading?: boolean;
|
|
33
|
+
readonly hasSelectAll?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const flatOptions: SelectorOptionType[] = [
|
|
37
|
+
{value: 'apple', label: 'Apple'},
|
|
38
|
+
{value: 'banana', label: 'Banana'},
|
|
39
|
+
{value: 'cherry', label: 'Cherry', disabled: true},
|
|
40
|
+
];
|
|
41
|
+
const flatExpected = [
|
|
42
|
+
{value: 'apple', name: 'Apple', disabled: false},
|
|
43
|
+
{value: 'banana', name: 'Banana', disabled: false},
|
|
44
|
+
{value: 'cherry', name: 'Cherry', disabled: true},
|
|
45
|
+
];
|
|
46
|
+
const groupedOptions: SelectorOptionType[] = [
|
|
47
|
+
{
|
|
48
|
+
type: 'section',
|
|
49
|
+
title: 'Citrus',
|
|
50
|
+
options: [
|
|
51
|
+
{value: 'orange', label: 'Orange'},
|
|
52
|
+
{value: 'lemon', label: 'Lemon'},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{type: 'divider'},
|
|
56
|
+
{
|
|
57
|
+
type: 'section',
|
|
58
|
+
title: 'Berries',
|
|
59
|
+
options: [{value: 'blueberry', label: 'Blueberry', disabled: true}],
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
const groupedExpected = [
|
|
63
|
+
{value: 'orange', name: 'Orange', disabled: false, group: 'Citrus'},
|
|
64
|
+
{value: 'lemon', name: 'Lemon', disabled: false, group: 'Citrus'},
|
|
65
|
+
{value: 'blueberry', name: 'Blueberry', disabled: true, group: 'Berries'},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
function scenarios(component: ListboxScenario['component']): ListboxScenario[] {
|
|
69
|
+
const prefix = component === 'Selector' ? 'single' : 'multiple';
|
|
70
|
+
const base = {
|
|
71
|
+
component,
|
|
72
|
+
options: flatOptions,
|
|
73
|
+
expectedOptions: flatExpected,
|
|
74
|
+
groups: [],
|
|
75
|
+
};
|
|
76
|
+
return [
|
|
77
|
+
{...base, id: `${prefix}-unset`, values: []},
|
|
78
|
+
{
|
|
79
|
+
...base,
|
|
80
|
+
id: `${prefix}-selected`,
|
|
81
|
+
values: component === 'Selector' ? ['apple'] : ['apple', 'banana'],
|
|
82
|
+
},
|
|
83
|
+
{...base, id: `${prefix}-disabled-selected`, values: ['cherry']},
|
|
84
|
+
{
|
|
85
|
+
...base,
|
|
86
|
+
id: `${prefix}-grouped`,
|
|
87
|
+
options: groupedOptions,
|
|
88
|
+
values: ['orange'],
|
|
89
|
+
expectedOptions: groupedExpected,
|
|
90
|
+
groups: ['Citrus', 'Berries'],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
...base,
|
|
94
|
+
id: `${prefix}-filtered`,
|
|
95
|
+
options: groupedOptions,
|
|
96
|
+
values: ['orange'],
|
|
97
|
+
expectedOptions: [
|
|
98
|
+
{value: 'lemon', name: 'Lemon', disabled: false, group: 'Citrus'},
|
|
99
|
+
],
|
|
100
|
+
groups: ['Citrus'],
|
|
101
|
+
hasSearch: true,
|
|
102
|
+
query: 'lem',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
...base,
|
|
106
|
+
id: `${prefix}-custom-rtl`,
|
|
107
|
+
values: ['banana'],
|
|
108
|
+
customContent: true,
|
|
109
|
+
hiddenLabel: true,
|
|
110
|
+
direction: 'rtl',
|
|
111
|
+
expectedOptions: [
|
|
112
|
+
{value: 'apple', name: 'Apple details', disabled: false},
|
|
113
|
+
{value: 'banana', name: 'Banana details', disabled: false},
|
|
114
|
+
{value: 'cherry', name: 'Cherry details', disabled: true},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
...base,
|
|
119
|
+
id: `${prefix}-sheet`,
|
|
120
|
+
values: ['apple'],
|
|
121
|
+
presentation: 'bottom-sheet',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
...base,
|
|
125
|
+
id: `${prefix}-sheet-search`,
|
|
126
|
+
values: ['banana'],
|
|
127
|
+
presentation: 'bottom-sheet',
|
|
128
|
+
hasSearch: true,
|
|
129
|
+
},
|
|
130
|
+
{...base, id: `${prefix}-loading`, values: ['apple'], isLoading: true},
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const LISTBOX_SCENARIOS: ReadonlyArray<ListboxScenario> = [
|
|
135
|
+
...scenarios('Selector'),
|
|
136
|
+
...scenarios('MultiSelector'),
|
|
137
|
+
...(['none', 'partial', 'all'] as const).map(state => ({
|
|
138
|
+
id: `multiple-select-all-${state}`,
|
|
139
|
+
component: 'MultiSelector' as const,
|
|
140
|
+
options: flatOptions,
|
|
141
|
+
values:
|
|
142
|
+
state === 'none'
|
|
143
|
+
? []
|
|
144
|
+
: state === 'partial'
|
|
145
|
+
? ['apple']
|
|
146
|
+
: ['apple', 'banana'],
|
|
147
|
+
groups: [],
|
|
148
|
+
hasSelectAll: true,
|
|
149
|
+
expectedOptions: [
|
|
150
|
+
{
|
|
151
|
+
value: 'select-all',
|
|
152
|
+
name:
|
|
153
|
+
state === 'partial' ? 'Select all, partially selected' : 'Select all',
|
|
154
|
+
disabled: false,
|
|
155
|
+
selected: state === 'all',
|
|
156
|
+
},
|
|
157
|
+
...flatExpected,
|
|
158
|
+
],
|
|
159
|
+
})),
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
export interface ListboxBindingPart {
|
|
163
|
+
readonly role: 'listbox' | 'group' | 'option';
|
|
164
|
+
readonly name?: string;
|
|
165
|
+
readonly state: string;
|
|
166
|
+
readonly facts: ListboxStateFacts;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function listboxParts(
|
|
170
|
+
scenario: ListboxScenario,
|
|
171
|
+
): ReadonlyArray<ListboxBindingPart> {
|
|
172
|
+
const multiple = scenario.component === 'MultiSelector';
|
|
173
|
+
return [
|
|
174
|
+
{
|
|
175
|
+
role: 'listbox',
|
|
176
|
+
state: `${scenario.id}:listbox`,
|
|
177
|
+
facts: {
|
|
178
|
+
part: 'listbox',
|
|
179
|
+
multiple,
|
|
180
|
+
optionRelations: scenario.expectedOptions.map(
|
|
181
|
+
option => `option:${option.value}`,
|
|
182
|
+
),
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
...scenario.groups.map(name => ({
|
|
186
|
+
role: 'group' as const,
|
|
187
|
+
name,
|
|
188
|
+
state: `${scenario.id}:group:${name}`,
|
|
189
|
+
facts: {part: 'group' as const, multiple},
|
|
190
|
+
})),
|
|
191
|
+
...scenario.expectedOptions.map(option => ({
|
|
192
|
+
role: 'option' as const,
|
|
193
|
+
name: option.name,
|
|
194
|
+
state: `${scenario.id}:option:${option.value}`,
|
|
195
|
+
facts: {
|
|
196
|
+
part: 'option' as const,
|
|
197
|
+
multiple,
|
|
198
|
+
selected: option.selected ?? scenario.values.includes(option.value),
|
|
199
|
+
disabled: option.disabled,
|
|
200
|
+
ownerGroup: option.group == null ? undefined : `group:${option.group}`,
|
|
201
|
+
},
|
|
202
|
+
})),
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export const LISTBOX_EXCLUSIONS = [
|
|
207
|
+
{
|
|
208
|
+
owner: 'Selector/MultiSelector trigger and search input',
|
|
209
|
+
reason:
|
|
210
|
+
'Combobox, field validation, required/read-only/disabled trigger state, and opening/closing are separate contracts. This slice observes active popup parts.',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
owner: 'Selector/MultiSelector existing interaction suites',
|
|
214
|
+
reason:
|
|
215
|
+
'Keyboard selection, selection-follows-focus, disabled-option discovery, Home/End, typeahead, and callback policy are not newly adopted here.',
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
owner: 'Selector/MultiSelector empty-state and live-region owners',
|
|
219
|
+
reason:
|
|
220
|
+
'Zero-result representation and announcement timing require their own authority/evidence. No required option is invented for an empty listbox.',
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
owner: 'Typeahead, Tokenizer, PowerSearch, ComplexSelector, CommandPalette',
|
|
224
|
+
reason:
|
|
225
|
+
'Later bounded adopters; this first migration is limited to Selector and MultiSelector.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
owner: 'Component-specific suites',
|
|
229
|
+
reason:
|
|
230
|
+
'Public ID forwarding, callback payloads, forms, value formatting, sorting, required/error status, and styling stay local. Selector has no independent uncontrolled selected-value owner; an omitted value is the unset state.',
|
|
231
|
+
},
|
|
232
|
+
] as const;
|