@astryxdesign/core 0.7.1-canary.ff40b78 → 0.7.1
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 +116 -0
- package/dist/Button/Button.d.ts +1 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +5 -2
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +191 -32
- package/dist/Chat/ChatComposerInput.d.ts +9 -0
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +5 -0
- package/dist/Chat/ChatMessage.d.ts +11 -0
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +18 -9
- package/dist/Chat/useTriggerMenu.d.ts +9 -2
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +222 -50
- package/dist/CodeBlock/CodeBlock.d.ts +10 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +158 -38
- package/dist/CodeBlock/tokenizer.d.ts +39 -0
- package/dist/CodeBlock/tokenizer.d.ts.map +1 -1
- package/dist/CodeBlock/tokenizer.js +108 -0
- package/dist/CommandPalette/CommandPalette.d.ts +9 -5
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +38 -20
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts +4 -3
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.js +4 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts +5 -4
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +35 -18
- package/dist/CommandPalette/CommandPaletteItem.d.ts +11 -6
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +8 -9
- package/dist/CommandPalette/CommandPaletteList.d.ts +4 -2
- package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteList.js +10 -5
- package/dist/ComplexSelector/ComplexSelector.d.ts +8 -5
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +12 -3
- package/dist/ContextMenu/ContextMenu.d.ts +3 -3
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +62 -48
- package/dist/DateInput/DateInput.js +1 -1
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +12 -4
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +12 -2
- package/dist/Dialog/Dialog.d.ts +1 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +16 -5
- package/dist/Dialog/DialogHeader.d.ts +1 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +7 -7
- package/dist/Divider/Divider.d.ts +1 -0
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +5 -4
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +161 -65
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +7 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +12 -5
- package/dist/Field/InputClearButton.d.ts +8 -4
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +23 -7
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +1 -0
- package/dist/Grid/Grid.d.ts +13 -4
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +7 -1
- package/dist/HoverCard/useHoverCard.d.ts +1 -1
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +67 -49
- package/dist/InputGroup/InputGroup.d.ts +2 -4
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +2 -4
- package/dist/InputGroup/groupStyles.d.ts +10 -2
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +19 -2
- package/dist/Layer/useLayerDismissal.d.ts +9 -9
- package/dist/Layer/useLayerDismissal.js +9 -9
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +25 -4
- package/dist/MobileNav/MobileNav.d.ts +7 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +45 -2
- package/dist/MultiSelector/MultiSelector.d.ts +7 -4
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +24 -3
- package/dist/NumberInput/NumberInput.js +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +6 -0
- package/dist/Resizable/ResizeHandle.d.ts +1 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +83 -15
- package/dist/Resizable/useResizable.d.ts +23 -0
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +78 -0
- package/dist/Selector/Selector.d.ts +6 -3
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +28 -6
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +10 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +18 -7
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +16 -4
- package/dist/Toolbar/Toolbar.d.ts +2 -1
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +3 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +6 -3
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +7 -1
- package/dist/astryx.css +22 -0
- package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
- package/dist/hooks/useScrollOverflow.js +55 -12
- package/dist/hooks/useTreeFocus.d.ts +21 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -1
- package/dist/hooks/useTreeFocus.js +40 -2
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +3 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +3 -0
- package/dist/reset.a11y.chromium.spec.js +6 -1
- package/dist/reset.until-found.a11y.browser.spec.d.ts +2 -0
- package/dist/reset.until-found.a11y.browser.spec.d.ts.map +1 -0
- package/dist/reset.until-found.a11y.browser.spec.js +71 -0
- package/dist/theme/syntax/SyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +43 -2
- package/dist/theme/syntax/defineSyntaxTheme.d.ts +18 -5
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +38 -9
- package/dist/theme/syntax/index.d.ts +1 -1
- package/dist/theme/syntax/index.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.d.ts +12 -2
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +25 -4
- package/dist/utils/plainDate.d.ts +12 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +63 -10
- package/locales/en.json +13 -1
- package/locales/pseudo.json +9 -0
- package/package.json +4 -4
- package/src/AlertDialog/AlertDialog.doc.mjs +6 -0
- package/src/AlertDialog/AlertDialog.spec.md +205 -0
- package/src/AlertDialog/AlertDialog.test.tsx +3 -14
- package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +115 -0
- package/src/AlertDialog/__tests__/AlertDialog.a11y.renders.tsx +52 -0
- package/src/AlertDialog/__tests__/AlertDialog.a11y.states.ts +68 -0
- package/src/AlertDialog/__tests__/AlertDialog.a11y.test.tsx +144 -0
- package/src/Button/Button.test.tsx +37 -0
- package/src/Button/Button.tsx +5 -1
- package/src/Calendar/Calendar.doc.mjs +234 -60
- package/src/Calendar/Calendar.spec.md +209 -0
- package/src/Calendar/Calendar.test.tsx +559 -20
- package/src/Calendar/Calendar.tsx +258 -41
- package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +126 -0
- package/src/Calendar/__tests__/Calendar.a11y.known-failures.ts +12 -0
- package/src/Calendar/__tests__/Calendar.a11y.renders.tsx +57 -0
- package/src/Calendar/__tests__/Calendar.a11y.states.ts +139 -0
- package/src/Calendar/__tests__/Calendar.a11y.test.tsx +137 -0
- package/src/Carousel/Carousel.test.tsx +54 -71
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +192 -0
- package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +27 -0
- package/src/Carousel/__tests__/Carousel.a11y.renders.tsx +39 -0
- package/src/Carousel/__tests__/Carousel.a11y.states.ts +139 -0
- package/src/Carousel/__tests__/Carousel.a11y.test.tsx +127 -0
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.spec.md +94 -55
- package/src/Chat/ChatComposerInput.test.tsx +202 -1
- package/src/Chat/ChatComposerInput.tsx +13 -0
- package/src/Chat/ChatMessage.doc.mjs +31 -16
- package/src/Chat/ChatMessage.spec.md +265 -0
- package/src/Chat/ChatMessage.test.tsx +246 -0
- package/src/Chat/ChatMessage.tsx +30 -7
- package/src/Chat/ChatSystemMessage.spec.md +36 -37
- package/src/Chat/ChatSystemMessage.test.tsx +4 -4
- package/src/Chat/useTriggerMenu.test.tsx +994 -0
- package/src/Chat/useTriggerMenu.tsx +278 -46
- package/src/CodeBlock/CodeBlock.doc.mjs +7 -0
- package/src/CodeBlock/CodeBlock.spec.md +40 -41
- package/src/CodeBlock/CodeBlock.test.tsx +89 -9
- package/src/CodeBlock/CodeBlock.tsx +205 -25
- package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +125 -0
- package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +93 -0
- package/src/CodeBlock/tokenizer.test.ts +112 -0
- package/src/CodeBlock/tokenizer.ts +106 -0
- package/src/Collapsible/CollapsibleGroup.spec.md +17 -8
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.renders.tsx +45 -0
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.states.ts +139 -0
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.test.tsx +135 -0
- package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +128 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +126 -23
- package/src/CommandPalette/CommandPalette.spec.md +100 -49
- package/src/CommandPalette/CommandPalette.test.tsx +241 -2
- package/src/CommandPalette/CommandPalette.tsx +47 -21
- package/src/CommandPalette/CommandPaletteEmpty.tsx +4 -3
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +61 -4
- package/src/CommandPalette/CommandPaletteInput.spec.md +215 -0
- package/src/CommandPalette/CommandPaletteInput.test.tsx +375 -51
- package/src/CommandPalette/CommandPaletteInput.tsx +74 -21
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +73 -22
- package/src/CommandPalette/CommandPaletteItem.spec.md +223 -0
- package/src/CommandPalette/CommandPaletteItem.test.tsx +200 -5
- package/src/CommandPalette/CommandPaletteItem.tsx +16 -11
- package/src/CommandPalette/CommandPaletteList.doc.mjs +3 -3
- package/src/CommandPalette/CommandPaletteList.spec.md +41 -36
- package/src/CommandPalette/CommandPaletteList.test.tsx +80 -0
- package/src/CommandPalette/CommandPaletteList.tsx +10 -5
- package/src/CommandPalette/__tests__/CommandPalette.a11y.chromium.spec.ts +599 -0
- package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -8
- package/src/ComplexSelector/ComplexSelector.spec.md +14 -9
- package/src/ComplexSelector/ComplexSelector.test.tsx +64 -16
- package/src/ComplexSelector/ComplexSelector.tsx +37 -8
- package/src/ContextMenu/ContextMenu.doc.mjs +6 -0
- package/src/ContextMenu/ContextMenu.spec.md +51 -53
- package/src/ContextMenu/ContextMenu.test.tsx +132 -1
- package/src/ContextMenu/ContextMenu.tsx +78 -48
- package/src/DateInput/DateInput.doc.mjs +52 -0
- package/src/DateInput/DateInput.spec.md +27 -15
- package/src/DateInput/DateInput.test.tsx +38 -0
- package/src/DateInput/DateInput.tsx +1 -1
- package/src/DateInput/DateInputTouch.test.tsx +22 -0
- package/src/DateInput/MonthScroller.tsx +12 -4
- package/src/DateRangeInput/DateRangeInput.test.tsx +49 -0
- package/src/DateRangeInput/DateRangeInput.tsx +20 -2
- package/src/Dialog/Dialog.test.tsx +27 -1
- package/src/Dialog/Dialog.tsx +16 -5
- package/src/Dialog/DialogHeader.test.tsx +27 -2
- package/src/Dialog/DialogHeader.tsx +7 -8
- package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +21 -14
- package/src/Divider/Divider.doc.mjs +5 -3
- package/src/Divider/Divider.spec.md +140 -54
- package/src/Divider/Divider.test.tsx +15 -0
- package/src/Divider/Divider.tsx +6 -4
- package/src/DropdownMenu/DropdownMenu.doc.mjs +2 -2
- package/src/DropdownMenu/DropdownMenu.spec.md +121 -45
- package/src/DropdownMenu/DropdownMenu.test.tsx +288 -23
- package/src/DropdownMenu/DropdownMenu.tsx +212 -81
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +38 -2
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +32 -18
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +146 -1
- package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +136 -0
- package/src/DropdownMenu/__tests__/MenuButton.a11y.known-failures.ts +12 -0
- package/src/DropdownMenu/__tests__/MenuButton.a11y.renders.tsx +67 -0
- package/src/DropdownMenu/__tests__/MenuButton.a11y.states.ts +141 -0
- package/src/DropdownMenu/__tests__/MenuButton.a11y.test.tsx +138 -0
- package/src/DropdownMenu/__tests__/MenuHeaderFooter.a11y.chromium.spec.ts +40 -5
- package/src/Field/InputClearButton.test.tsx +29 -4
- package/src/Field/InputClearButton.tsx +26 -8
- package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +21 -14
- package/src/FormLayout/FormLayout.tsx +1 -0
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +1 -1
- package/src/Grid/Grid.doc.mjs +14 -11
- package/src/Grid/Grid.spec.md +50 -32
- package/src/Grid/Grid.tsx +13 -4
- package/src/HoverCard/HoverCard.test.tsx +46 -1
- package/src/HoverCard/useHoverCard.tsx +68 -48
- package/src/InputGroup/InputGroup.doc.mjs +11 -1
- package/src/InputGroup/InputGroup.tsx +2 -4
- package/src/InputGroup/groupStyles.ts +40 -2
- package/src/Layer/useLayerDismissal.ts +9 -9
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +142 -0
- package/src/Link/__tests__/Link.a11y.renders.tsx +97 -0
- package/src/Link/__tests__/Link.a11y.states.ts +104 -0
- package/src/Link/__tests__/Link.a11y.test.tsx +127 -0
- package/src/Markdown/Markdown.doc.mjs +1 -1
- package/src/Markdown/Markdown.fr23.perf.test.ts +161 -40
- package/src/Markdown/Markdown.spec.md +45 -23
- package/src/Markdown/Markdown.test.tsx +38 -0
- package/src/Markdown/Markdown.tsx +24 -2
- package/src/Markdown/plugins/semanticFence.test.tsx +3 -2
- package/src/MobileNav/MobileNav.tsx +50 -2
- package/src/MobileNav/MobileNavFocus.test.tsx +553 -0
- package/src/MoreMenu/MoreMenu.spec.md +18 -7
- package/src/MoreMenu/MoreMenu.test.tsx +38 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +8 -8
- package/src/MultiSelector/MultiSelector.spec.md +1 -1
- package/src/MultiSelector/MultiSelector.test.tsx +188 -21
- package/src/MultiSelector/MultiSelector.tsx +50 -11
- package/src/NumberInput/NumberInput.test.tsx +24 -0
- package/src/NumberInput/NumberInput.tsx +1 -1
- package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +22 -15
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +78 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +6 -0
- package/src/Resizable/Resizable.spec.md +41 -9
- package/src/Resizable/ResizeHandle.test.tsx +565 -2
- package/src/Resizable/ResizeHandle.tsx +126 -21
- package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +119 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.known-failures.ts +39 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.renders.tsx +80 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.states.ts +197 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.test.tsx +123 -0
- package/src/Resizable/useResizable.ts +95 -0
- package/src/Selector/Selector.doc.mjs +7 -6
- package/src/Selector/Selector.spec.md +37 -24
- package/src/Selector/Selector.test.tsx +176 -10
- package/src/Selector/Selector.tsx +59 -14
- package/src/Selector/__tests__/Combobox.a11y.known-failures.ts +27 -0
- package/src/Selector/__tests__/Combobox.a11y.states.ts +145 -0
- package/src/Selector/__tests__/Selector.combobox.a11y.chromium.spec.ts +108 -0
- package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +126 -0
- package/src/SideNav/SideNav.test.tsx +35 -0
- package/src/SideNav/SideNav.tsx +16 -2
- package/src/Slider/Slider.spec.md +43 -17
- package/src/Slider/Slider.test.tsx +134 -0
- package/src/Slider/Slider.tsx +29 -6
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +112 -0
- package/src/Slider/__tests__/Slider.a11y.known-failures.ts +12 -0
- package/src/Slider/__tests__/Slider.a11y.renders.tsx +42 -0
- package/src/Slider/__tests__/Slider.a11y.states.ts +106 -0
- package/src/Slider/__tests__/Slider.a11y.test.tsx +105 -0
- package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +25 -18
- package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +19 -12
- package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +21 -14
- package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +18 -11
- package/src/Tokenizer/Tokenizer.test.tsx +87 -0
- package/src/Tokenizer/Tokenizer.tsx +31 -3
- package/src/Toolbar/Toolbar.test.tsx +131 -4
- package/src/Toolbar/Toolbar.tsx +3 -1
- package/src/TreeList/TreeList.spec.md +33 -8
- package/src/TreeList/TreeList.test.tsx +72 -0
- package/src/TreeList/TreeList.tsx +10 -6
- package/src/TreeList/TreeListItem.tsx +5 -0
- package/src/TreeList/__tests__/TreeList.a11y.chromium.spec.ts +125 -0
- package/src/TreeList/__tests__/TreeList.a11y.renders.tsx +44 -0
- package/src/TreeList/__tests__/TreeList.a11y.states.ts +164 -0
- package/src/TreeList/__tests__/TreeList.a11y.test.tsx +138 -0
- package/src/TreeList/__tests__/TreeListRowNames.a11y.chromium.spec.ts +82 -0
- package/src/hooks/useScrollOverflow.test.tsx +222 -0
- package/src/hooks/useScrollOverflow.ts +55 -13
- package/src/hooks/useTreeFocus.test.tsx +37 -0
- package/src/hooks/useTreeFocus.ts +55 -2
- package/src/i18n/generated-locales/en.generated.ts +3 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +3 -0
- package/src/reset.a11y.chromium.spec.ts +9 -1
- package/src/reset.css +8 -3
- package/src/reset.until-found.a11y.browser.spec.ts +75 -0
- package/src/reset.until-found.test.ts +32 -0
- package/src/stylexValidation.source-build.test.mjs +42 -0
- package/src/theme/syntax/SyntaxTheme.tsx +46 -5
- package/src/theme/syntax/defineSyntaxTheme.diff.test.ts +91 -0
- package/src/theme/syntax/defineSyntaxTheme.ts +75 -15
- package/src/theme/syntax/index.ts +5 -1
- package/src/theme/syntax/tokens.ts +32 -2
- package/src/theme/syntax/useSyntaxTheme.diff.test.tsx +40 -0
- package/src/utils/plainDate.test.ts +147 -0
- package/src/utils/plainDate.ts +75 -10
|
@@ -15,8 +15,11 @@
|
|
|
15
15
|
* which is bound to the region's `_size`.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import {useRef} from 'react';
|
|
18
19
|
import {describe, it, expect, vi} from 'vitest';
|
|
19
|
-
import {render, screen, fireEvent, act} from '@testing-library/react';
|
|
20
|
+
import {render, screen, fireEvent, act, waitFor} from '@testing-library/react';
|
|
21
|
+
import {hydrateRoot} from 'react-dom/client';
|
|
22
|
+
import {renderToString} from 'react-dom/server';
|
|
20
23
|
import {ResizeHandle} from './ResizeHandle';
|
|
21
24
|
import type {ResizeHandleProps} from './ResizeHandle';
|
|
22
25
|
import {useResizable} from './useResizable';
|
|
@@ -130,6 +133,192 @@ describe('ResizeHandle', () => {
|
|
|
130
133
|
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
131
134
|
});
|
|
132
135
|
|
|
136
|
+
it('reports the window basis as aria-valuemax when no maximum is configured; End leaves an unbounded region alone', () => {
|
|
137
|
+
const previous = window.innerWidth;
|
|
138
|
+
window.innerWidth = 1000;
|
|
139
|
+
try {
|
|
140
|
+
render(<Harness config={{defaultSize: 200, minSize: 100}} />);
|
|
141
|
+
const separator = getSeparator();
|
|
142
|
+
// ARIA needs a maximum on a separator with a value: the basis the hook
|
|
143
|
+
// resolves against stands in for an unbounded one.
|
|
144
|
+
expect(separator).toHaveAttribute('aria-valuemax', '1000');
|
|
145
|
+
// End still moves only to a configured maximum: the stand-in says how
|
|
146
|
+
// far the pane could reach, not where the handle may safely go
|
|
147
|
+
// (component:Resizable records the End gap).
|
|
148
|
+
act(() => separator.focus());
|
|
149
|
+
fireEvent.keyDown(separator, {key: 'End'});
|
|
150
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
151
|
+
} finally {
|
|
152
|
+
window.innerWidth = previous;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('server-renders an unbounded handle with no maximum and reports the window extent after hydration, with no hydration error', async () => {
|
|
157
|
+
const previous = window.innerWidth;
|
|
158
|
+
window.innerWidth = 1000;
|
|
159
|
+
const probe = <Harness config={{defaultSize: 200, minSize: 100}} />;
|
|
160
|
+
const serverHTML = renderToString(probe);
|
|
161
|
+
// The server has no window: no aria-valuemax in the markup.
|
|
162
|
+
expect(serverHTML).not.toContain('aria-valuemax');
|
|
163
|
+
const container = document.createElement('div');
|
|
164
|
+
container.innerHTML = serverHTML;
|
|
165
|
+
document.body.appendChild(container);
|
|
166
|
+
const consoleError = vi
|
|
167
|
+
.spyOn(console, 'error')
|
|
168
|
+
.mockImplementation(() => {});
|
|
169
|
+
const recoverableErrors: unknown[] = [];
|
|
170
|
+
let root: ReturnType<typeof hydrateRoot>;
|
|
171
|
+
try {
|
|
172
|
+
await act(async () => {
|
|
173
|
+
root = hydrateRoot(container, probe, {
|
|
174
|
+
onRecoverableError: error => recoverableErrors.push(error),
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
// The first client render reads the window through the store and
|
|
178
|
+
// reports it; a render-time window read would mismatch the server
|
|
179
|
+
// markup (or, read only once, leave the attribute missing).
|
|
180
|
+
await waitFor(() =>
|
|
181
|
+
expect(container.querySelector('[role="separator"]')).toHaveAttribute(
|
|
182
|
+
'aria-valuemax',
|
|
183
|
+
'1000',
|
|
184
|
+
),
|
|
185
|
+
);
|
|
186
|
+
expect(recoverableErrors).toEqual([]);
|
|
187
|
+
expect(
|
|
188
|
+
consoleError.mock.calls.filter(call =>
|
|
189
|
+
String(call[0] ?? '')
|
|
190
|
+
.toLowerCase()
|
|
191
|
+
.includes('hydrat'),
|
|
192
|
+
),
|
|
193
|
+
).toEqual([]);
|
|
194
|
+
} finally {
|
|
195
|
+
await act(async () => root!.unmount());
|
|
196
|
+
consoleError.mockRestore();
|
|
197
|
+
container.remove();
|
|
198
|
+
window.innerWidth = previous;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('never reports a maximum below the current size, and End does not shrink the region', () => {
|
|
203
|
+
const previous = window.innerWidth;
|
|
204
|
+
window.innerWidth = 500;
|
|
205
|
+
try {
|
|
206
|
+
// A default (or saved, or pre-resize) size larger than the window.
|
|
207
|
+
render(<Harness config={{defaultSize: 800, minSize: 100}} />);
|
|
208
|
+
const separator = getSeparator();
|
|
209
|
+
expect(separator).toHaveAttribute('aria-valuenow', '800');
|
|
210
|
+
expect(separator).toHaveAttribute('aria-valuemax', '800');
|
|
211
|
+
act(() => separator.focus());
|
|
212
|
+
fireEvent.keyDown(separator, {key: 'End'});
|
|
213
|
+
expect(separator).toHaveAttribute('aria-valuenow', '800');
|
|
214
|
+
} finally {
|
|
215
|
+
window.innerWidth = previous;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('never reports aria-valuemax below aria-valuemin while collapsed in a small window', () => {
|
|
220
|
+
const previous = window.innerWidth;
|
|
221
|
+
window.innerWidth = 375;
|
|
222
|
+
try {
|
|
223
|
+
render(
|
|
224
|
+
<Harness
|
|
225
|
+
config={{defaultSize: 500, minSize: 400, collapsible: true}}
|
|
226
|
+
/>,
|
|
227
|
+
);
|
|
228
|
+
const separator = getSeparator();
|
|
229
|
+
act(() => separator.focus());
|
|
230
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
231
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
232
|
+
expect(separator).toHaveAttribute('aria-valuemin', '400');
|
|
233
|
+
expect(
|
|
234
|
+
Number(separator.getAttribute('aria-valuemax')),
|
|
235
|
+
).toBeGreaterThanOrEqual(400);
|
|
236
|
+
} finally {
|
|
237
|
+
window.innerWidth = previous;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('reports the window height, not the width, for an unbounded vertical region', () => {
|
|
242
|
+
const previousWidth = window.innerWidth;
|
|
243
|
+
const previousHeight = window.innerHeight;
|
|
244
|
+
window.innerWidth = 1000;
|
|
245
|
+
window.innerHeight = 700;
|
|
246
|
+
try {
|
|
247
|
+
render(
|
|
248
|
+
<Harness
|
|
249
|
+
config={{defaultSize: 200, minSize: 100, direction: 'vertical'}}
|
|
250
|
+
handleProps={{direction: 'vertical'}}
|
|
251
|
+
/>,
|
|
252
|
+
);
|
|
253
|
+
const separator = getSeparator();
|
|
254
|
+
expect(separator).toHaveAttribute('aria-valuemax', '700');
|
|
255
|
+
} finally {
|
|
256
|
+
window.innerWidth = previousWidth;
|
|
257
|
+
window.innerHeight = previousHeight;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('reports the container basis as aria-valuemax while a percentage bound already observes it', () => {
|
|
262
|
+
function ContainerHarness() {
|
|
263
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
264
|
+
const region = useResizable({
|
|
265
|
+
defaultSize: 200,
|
|
266
|
+
minSize: '10%',
|
|
267
|
+
containerRef,
|
|
268
|
+
});
|
|
269
|
+
return (
|
|
270
|
+
<div ref={containerRef}>
|
|
271
|
+
<ResizeHandle resizable={region.props} label="Resize" />
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
// jsdom has no ResizeObserver; a stub lets the hook subscribe, and the
|
|
276
|
+
// content box is measured through clientWidth minus padding.
|
|
277
|
+
class StubResizeObserver {
|
|
278
|
+
observe() {}
|
|
279
|
+
unobserve() {}
|
|
280
|
+
disconnect() {}
|
|
281
|
+
}
|
|
282
|
+
vi.stubGlobal('ResizeObserver', StubResizeObserver);
|
|
283
|
+
const clientWidth = vi
|
|
284
|
+
.spyOn(HTMLElement.prototype, 'clientWidth', 'get')
|
|
285
|
+
.mockReturnValue(640);
|
|
286
|
+
const computedStyle = vi.spyOn(window, 'getComputedStyle').mockReturnValue({
|
|
287
|
+
paddingTop: '0px',
|
|
288
|
+
paddingBottom: '0px',
|
|
289
|
+
paddingLeft: '0px',
|
|
290
|
+
paddingRight: '0px',
|
|
291
|
+
} as unknown as CSSStyleDeclaration);
|
|
292
|
+
try {
|
|
293
|
+
render(<ContainerHarness />);
|
|
294
|
+
expect(getSeparator()).toHaveAttribute('aria-valuemax', '640');
|
|
295
|
+
} finally {
|
|
296
|
+
clientWidth.mockRestore();
|
|
297
|
+
computedStyle.mockRestore();
|
|
298
|
+
vi.unstubAllGlobals();
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('reports no aria-valuemax for an unbounded pixel-only region in a container, which stays unobserved', () => {
|
|
303
|
+
function ContainerHarness() {
|
|
304
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
305
|
+
const region = useResizable({
|
|
306
|
+
defaultSize: 200,
|
|
307
|
+
minSize: 100,
|
|
308
|
+
containerRef,
|
|
309
|
+
});
|
|
310
|
+
return (
|
|
311
|
+
<div ref={containerRef}>
|
|
312
|
+
<ResizeHandle resizable={region.props} label="Resize" />
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
render(<ContainerHarness />);
|
|
317
|
+
// component:Resizable Performance: atomic pixel paths add no observer, so
|
|
318
|
+
// the hook never measures this container and reports no stand-in.
|
|
319
|
+
expect(getSeparator()).not.toHaveAttribute('aria-valuemax');
|
|
320
|
+
});
|
|
321
|
+
|
|
133
322
|
it('jumps to the maximum on End', () => {
|
|
134
323
|
render(<Harness />);
|
|
135
324
|
const separator = getSeparator();
|
|
@@ -202,6 +391,379 @@ describe('ResizeHandle', () => {
|
|
|
202
391
|
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
203
392
|
});
|
|
204
393
|
|
|
394
|
+
it('restores the previous size, not the minimum, when Enter reopens a collapsed pane', () => {
|
|
395
|
+
render(
|
|
396
|
+
<Harness
|
|
397
|
+
config={{
|
|
398
|
+
defaultSize: 300,
|
|
399
|
+
minSize: 100,
|
|
400
|
+
maxSize: 400,
|
|
401
|
+
collapsible: true,
|
|
402
|
+
}}
|
|
403
|
+
/>,
|
|
404
|
+
);
|
|
405
|
+
const separator = getSeparator();
|
|
406
|
+
act(() => separator.focus());
|
|
407
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
408
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
409
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
410
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
411
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
412
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('restores the previous size, not the minimum, when a double-click reopens a collapsed pane', () => {
|
|
416
|
+
render(
|
|
417
|
+
<Harness
|
|
418
|
+
config={{
|
|
419
|
+
defaultSize: 300,
|
|
420
|
+
minSize: 100,
|
|
421
|
+
maxSize: 400,
|
|
422
|
+
collapsible: true,
|
|
423
|
+
}}
|
|
424
|
+
/>,
|
|
425
|
+
);
|
|
426
|
+
const separator = getSeparator();
|
|
427
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
428
|
+
fireEvent.doubleClick(separator);
|
|
429
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
430
|
+
fireEvent.doubleClick(separator);
|
|
431
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
432
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it('reopens on a double-click even when the minimum size sits below the collapse threshold', () => {
|
|
436
|
+
render(
|
|
437
|
+
<Harness
|
|
438
|
+
config={{
|
|
439
|
+
defaultSize: 200,
|
|
440
|
+
minSize: 20,
|
|
441
|
+
maxSize: 400,
|
|
442
|
+
collapsible: true,
|
|
443
|
+
collapsedSize: 50,
|
|
444
|
+
}}
|
|
445
|
+
/>,
|
|
446
|
+
);
|
|
447
|
+
const separator = getSeparator();
|
|
448
|
+
fireEvent.doubleClick(separator);
|
|
449
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
450
|
+
fireEvent.doubleClick(separator);
|
|
451
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
452
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it('a grow arrow opens a collapsed pane one step above its minimum; the shrink arrow leaves it collapsed', () => {
|
|
456
|
+
render(
|
|
457
|
+
<Harness
|
|
458
|
+
config={{
|
|
459
|
+
defaultSize: 200,
|
|
460
|
+
minSize: 100,
|
|
461
|
+
maxSize: 400,
|
|
462
|
+
collapsible: true,
|
|
463
|
+
}}
|
|
464
|
+
/>,
|
|
465
|
+
);
|
|
466
|
+
const separator = getSeparator();
|
|
467
|
+
act(() => separator.focus());
|
|
468
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
469
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
470
|
+
// Shrinking a collapsed pane changes nothing.
|
|
471
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
472
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
473
|
+
// One bare grow step would stay below the collapse threshold (40px) and
|
|
474
|
+
// leave the pane collapsed; instead the arrow opens it one step above the
|
|
475
|
+
// minimum it announced (100 → 110).
|
|
476
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
477
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
478
|
+
expect(separator).toHaveAttribute('aria-valuenow', '110');
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it('a grow arrow opens a collapsed pane at its collapsedSize when the minimum sits below it', () => {
|
|
482
|
+
render(
|
|
483
|
+
<Harness
|
|
484
|
+
config={{
|
|
485
|
+
defaultSize: 200,
|
|
486
|
+
minSize: 20,
|
|
487
|
+
maxSize: 400,
|
|
488
|
+
collapsible: true,
|
|
489
|
+
collapsedSize: 50,
|
|
490
|
+
}}
|
|
491
|
+
/>,
|
|
492
|
+
);
|
|
493
|
+
const separator = getSeparator();
|
|
494
|
+
act(() => separator.focus());
|
|
495
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
496
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
497
|
+
// min + step (30) would still be below the 50px threshold, so the pane
|
|
498
|
+
// opens at the threshold instead.
|
|
499
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
500
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
501
|
+
expect(separator).toHaveAttribute('aria-valuenow', '50');
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('a grow arrow opens a collapsed pane in the reversed layout and under RTL too', () => {
|
|
505
|
+
const rtl = vi
|
|
506
|
+
.spyOn(window, 'getComputedStyle')
|
|
507
|
+
.mockImplementation(
|
|
508
|
+
() => ({direction: 'rtl'}) as unknown as CSSStyleDeclaration,
|
|
509
|
+
);
|
|
510
|
+
try {
|
|
511
|
+
// Reversed + RTL: the pane sits on the right and grows to the left on
|
|
512
|
+
// screen, which under RTL is ArrowRight again.
|
|
513
|
+
render(
|
|
514
|
+
<Harness
|
|
515
|
+
config={{
|
|
516
|
+
defaultSize: 200,
|
|
517
|
+
minSize: 100,
|
|
518
|
+
maxSize: 400,
|
|
519
|
+
collapsible: true,
|
|
520
|
+
}}
|
|
521
|
+
handleProps={{isReversed: true}}
|
|
522
|
+
/>,
|
|
523
|
+
);
|
|
524
|
+
const separator = getSeparator();
|
|
525
|
+
act(() => separator.focus());
|
|
526
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
527
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
528
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
529
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
530
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
531
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
532
|
+
expect(separator).toHaveAttribute('aria-valuenow', '110');
|
|
533
|
+
} finally {
|
|
534
|
+
rtl.mockRestore();
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
it('in a reversed layout, ArrowLeft opens a collapsed pane and ArrowRight leaves it collapsed', () => {
|
|
539
|
+
// Reversed: the pane sits on the right and grows to the left.
|
|
540
|
+
render(
|
|
541
|
+
<Harness
|
|
542
|
+
config={{
|
|
543
|
+
defaultSize: 200,
|
|
544
|
+
minSize: 100,
|
|
545
|
+
maxSize: 400,
|
|
546
|
+
collapsible: true,
|
|
547
|
+
}}
|
|
548
|
+
handleProps={{isReversed: true}}
|
|
549
|
+
/>,
|
|
550
|
+
);
|
|
551
|
+
const separator = getSeparator();
|
|
552
|
+
act(() => separator.focus());
|
|
553
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
554
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
555
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
556
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
557
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
558
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
559
|
+
expect(separator).toHaveAttribute('aria-valuenow', '110');
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it('under RTL, ArrowLeft opens a collapsed pane and ArrowRight leaves it collapsed', () => {
|
|
563
|
+
const rtl = vi
|
|
564
|
+
.spyOn(window, 'getComputedStyle')
|
|
565
|
+
.mockImplementation(
|
|
566
|
+
() => ({direction: 'rtl'}) as unknown as CSSStyleDeclaration,
|
|
567
|
+
);
|
|
568
|
+
try {
|
|
569
|
+
// Not reversed, right-to-left: the pane sits on the right and grows
|
|
570
|
+
// toward the left edge of the screen.
|
|
571
|
+
render(
|
|
572
|
+
<Harness
|
|
573
|
+
config={{
|
|
574
|
+
defaultSize: 200,
|
|
575
|
+
minSize: 100,
|
|
576
|
+
maxSize: 400,
|
|
577
|
+
collapsible: true,
|
|
578
|
+
}}
|
|
579
|
+
/>,
|
|
580
|
+
);
|
|
581
|
+
const separator = getSeparator();
|
|
582
|
+
act(() => separator.focus());
|
|
583
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
584
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
585
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
586
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
587
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
588
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
589
|
+
expect(separator).toHaveAttribute('aria-valuenow', '110');
|
|
590
|
+
} finally {
|
|
591
|
+
rtl.mockRestore();
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
it('with snap points, an arrow moves to the adjacent point in its direction and Shift moves two, clamped to the ends', () => {
|
|
596
|
+
render(
|
|
597
|
+
<Harness
|
|
598
|
+
config={{
|
|
599
|
+
defaultSize: 200,
|
|
600
|
+
minSize: 100,
|
|
601
|
+
maxSize: 400,
|
|
602
|
+
snaps: [100, 200, 300, 400],
|
|
603
|
+
}}
|
|
604
|
+
/>,
|
|
605
|
+
);
|
|
606
|
+
const separator = getSeparator();
|
|
607
|
+
act(() => separator.focus());
|
|
608
|
+
// A 10px step would snap straight back to 200; the arrow reaches the
|
|
609
|
+
// next point instead.
|
|
610
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
611
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
612
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
613
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
614
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight', shiftKey: true});
|
|
615
|
+
expect(separator).toHaveAttribute('aria-valuenow', '400');
|
|
616
|
+
// Already at the last point: the grow arrow changes nothing.
|
|
617
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
618
|
+
expect(separator).toHaveAttribute('aria-valuenow', '400');
|
|
619
|
+
// Shift past the first point clamps to it.
|
|
620
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft', shiftKey: true});
|
|
621
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
622
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft', shiftKey: true});
|
|
623
|
+
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
624
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
625
|
+
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
it('with snap points past the bounds, a point beyond maxSize or minSize counts as that bound', () => {
|
|
629
|
+
render(
|
|
630
|
+
<Harness
|
|
631
|
+
config={{
|
|
632
|
+
defaultSize: 200,
|
|
633
|
+
minSize: 100,
|
|
634
|
+
maxSize: 400,
|
|
635
|
+
snaps: [50, 100, 200, 300, 450],
|
|
636
|
+
}}
|
|
637
|
+
/>,
|
|
638
|
+
);
|
|
639
|
+
const separator = getSeparator();
|
|
640
|
+
act(() => separator.focus());
|
|
641
|
+
fireEvent.keyDown(separator, {key: 'End'});
|
|
642
|
+
expect(separator).toHaveAttribute('aria-valuenow', '400');
|
|
643
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
644
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
645
|
+
// The 450 point counts as the 400 bound.
|
|
646
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
647
|
+
expect(separator).toHaveAttribute('aria-valuenow', '400');
|
|
648
|
+
fireEvent.keyDown(separator, {key: 'Home'});
|
|
649
|
+
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
650
|
+
// The 50 point counts as the 100 bound: nothing below it.
|
|
651
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
652
|
+
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('with snap points, the arrows follow the reversed layout and the reading direction', () => {
|
|
656
|
+
const rtl = vi
|
|
657
|
+
.spyOn(window, 'getComputedStyle')
|
|
658
|
+
.mockImplementation(
|
|
659
|
+
() => ({direction: 'rtl'}) as unknown as CSSStyleDeclaration,
|
|
660
|
+
);
|
|
661
|
+
try {
|
|
662
|
+
// Reversed under RTL: the two inversions cancel, so ArrowRight grows.
|
|
663
|
+
render(
|
|
664
|
+
<Harness
|
|
665
|
+
config={{
|
|
666
|
+
defaultSize: 200,
|
|
667
|
+
minSize: 100,
|
|
668
|
+
maxSize: 400,
|
|
669
|
+
snaps: [100, 200, 300, 400],
|
|
670
|
+
}}
|
|
671
|
+
handleProps={{isReversed: true}}
|
|
672
|
+
/>,
|
|
673
|
+
);
|
|
674
|
+
const separator = getSeparator();
|
|
675
|
+
act(() => separator.focus());
|
|
676
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
677
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
678
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
679
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
680
|
+
} finally {
|
|
681
|
+
rtl.mockRestore();
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
it('with snap points in a reversed layout, ArrowLeft moves to the next point and ArrowRight to the previous', () => {
|
|
686
|
+
render(
|
|
687
|
+
<Harness
|
|
688
|
+
config={{
|
|
689
|
+
defaultSize: 200,
|
|
690
|
+
minSize: 100,
|
|
691
|
+
maxSize: 400,
|
|
692
|
+
snaps: [100, 200, 300, 400],
|
|
693
|
+
}}
|
|
694
|
+
handleProps={{isReversed: true}}
|
|
695
|
+
/>,
|
|
696
|
+
);
|
|
697
|
+
const separator = getSeparator();
|
|
698
|
+
act(() => separator.focus());
|
|
699
|
+
fireEvent.keyDown(separator, {key: 'ArrowLeft'});
|
|
700
|
+
expect(separator).toHaveAttribute('aria-valuenow', '300');
|
|
701
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
702
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
it('with snap points, the grow arrow opens a collapsed pane at the snap point nearest one step above its minimum', () => {
|
|
706
|
+
render(
|
|
707
|
+
<Harness
|
|
708
|
+
config={{
|
|
709
|
+
defaultSize: 200,
|
|
710
|
+
minSize: 100,
|
|
711
|
+
maxSize: 400,
|
|
712
|
+
collapsible: true,
|
|
713
|
+
snaps: [100, 200, 300, 400],
|
|
714
|
+
}}
|
|
715
|
+
/>,
|
|
716
|
+
);
|
|
717
|
+
const separator = getSeparator();
|
|
718
|
+
act(() => separator.focus());
|
|
719
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
720
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
721
|
+
// min + step is 110; the region can rest only on a point, so it opens
|
|
722
|
+
// on the nearest one (100).
|
|
723
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
724
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
725
|
+
expect(separator).toHaveAttribute('aria-valuenow', '100');
|
|
726
|
+
// From there the arrows move between points.
|
|
727
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
728
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
it('a grow arrow opens a hand-built collapsed region one step above its minimum', () => {
|
|
732
|
+
const props: ResizableProps = {
|
|
733
|
+
...makeResizable(),
|
|
734
|
+
_isCollapsed: true,
|
|
735
|
+
_size: 0,
|
|
736
|
+
_collapsible: true,
|
|
737
|
+
};
|
|
738
|
+
render(<ResizeHandle resizable={props} label="Resize" />);
|
|
739
|
+
const separator = getSeparator();
|
|
740
|
+
act(() => separator.focus());
|
|
741
|
+
fireEvent.keyDown(separator, {key: 'ArrowRight'});
|
|
742
|
+
// The same move as the hook's own region: minimum plus one step.
|
|
743
|
+
expect(props._onResizeMove).toHaveBeenCalledWith(props._minSizePx + 10);
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
it('reopens on Enter even when the minimum size sits below the collapse threshold', () => {
|
|
747
|
+
render(
|
|
748
|
+
<Harness
|
|
749
|
+
config={{
|
|
750
|
+
defaultSize: 200,
|
|
751
|
+
minSize: 20,
|
|
752
|
+
maxSize: 400,
|
|
753
|
+
collapsible: true,
|
|
754
|
+
collapsedSize: 50,
|
|
755
|
+
}}
|
|
756
|
+
/>,
|
|
757
|
+
);
|
|
758
|
+
const separator = getSeparator();
|
|
759
|
+
act(() => separator.focus());
|
|
760
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
761
|
+
expect(separator).toHaveAttribute('aria-valuetext', 'Collapsed');
|
|
762
|
+
fireEvent.keyDown(separator, {key: 'Enter'});
|
|
763
|
+
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
764
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
765
|
+
});
|
|
766
|
+
|
|
205
767
|
it('keeps aria-valuenow >= aria-valuemin and announces "Collapsed" while collapsed', () => {
|
|
206
768
|
render(
|
|
207
769
|
<Harness
|
|
@@ -243,7 +805,8 @@ describe('ResizeHandle', () => {
|
|
|
243
805
|
|
|
244
806
|
fireEvent.keyDown(separator, {key: 'Enter'}); // expand again
|
|
245
807
|
expect(separator).not.toHaveAttribute('aria-valuetext');
|
|
246
|
-
|
|
808
|
+
// Back to the size it had before collapsing, not the minimum.
|
|
809
|
+
expect(separator).toHaveAttribute('aria-valuenow', '200');
|
|
247
810
|
});
|
|
248
811
|
|
|
249
812
|
// --- Disabled guard ---
|