@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,121 @@
|
|
|
1
1
|
# @xds/core
|
|
2
2
|
|
|
3
|
+
# 0.7.1
|
|
4
|
+
|
|
5
|
+
#### New Features
|
|
6
|
+
|
|
7
|
+
- Chat: mention people and topics by multi-word names with opt-in `hasMultiWordQuery` on `ChatComposerTrigger` (#6128)
|
|
8
|
+
Set `hasMultiWordQuery: true` on a trigger whose suggestions contain spaces, and typing `@Jordan Le` keeps narrowing the menu instead of closing it at the first space. The query runs until a line break or about 64 characters, typed text is never changed unless a row is picked, and an unmatched multi-word phrase hides the menu unless the trigger sets `emptySearchText`. Triggers that don't opt in still end their query at a space.
|
|
9
|
+
|
|
10
|
+
For every trigger: while results for the current query are still loading, Enter sends the message as typed and never picks a row from an earlier query. Results that arrive after a send or after the editor clears are dropped, so the menu never reopens over an empty composer. Escape and the arrow keys pass through while the menu is hidden, and IME keystrokes never pick a row.
|
|
11
|
+
|
|
12
|
+
- `CodeBlock` gains `isDiff`, a diff layer over any `language`, and Markdown renders a ```diff fence as tinted diff rows instead of plain text. (#7389)
|
|
13
|
+
With `isDiff`, lines starting with `+` sit on a success-tinted row, `-` on an error-tinted row, `@@` hunk headers (and a `--- `/`+++ ` file-header pair directly before one) on a quiet muted row, and the rest of every line keeps the language's syntax highlighting. The glyph renders in its own column so the code's indentation lines up on every row and stays in the copied text. A changed row's margin reads the change: the tint runs under the line-number gutter too and spans the full scroll width of a long line, and the line number and the glyph take the row's marker colour, while the code keeps the syntax theme's colours. These are five new syntax-theme slots — `--color-syntax-added`, `--color-syntax-removed`, `--color-syntax-diff-header` (row paints, defaulting to `--color-success-muted` and `--color-error-muted` at 25% strength and to `--color-background-muted`; a defined syntax theme that leaves the header paint unset gets none, its header rows sitting on its own background in its punctuation colour) and `--color-syntax-added-marker`, `--color-syntax-removed-marker` (defaulting to `--color-text-green` and `--color-text-red` in the default syntax theme; a defined syntax theme that leaves them unset keeps its own line-number colour) — so existing and custom syntax themes need no change and may override them.
|
|
14
|
+
|
|
15
|
+
Markdown maps a ```diff-<lang> fence to the layer over `<lang>` (labelled `<lang> diff`) and a ```diff fence to the layer over plaintext (labelled `diff`), so a diff keeps its header, copy button, disclosure, and a viewport name that still says `diff`.
|
|
16
|
+
|
|
17
|
+
A ```diff fence that should stay plain text can use ```text. A custom `components.code` renderer is unchanged: it keeps receiving the fence's leading word characters in `language` (`diff` for both ```diff and ```diff-tsx, as today), so an existing `language === 'diff'` check still matches, and receives nothing new.
|
|
18
|
+
|
|
19
|
+
- Clearable inputs: the clear button's tooltip now reads just "Clear" (localized) instead of repeating the field's label, so a long label no longer turns into awkward tooltip copy such as "Clear Assigned engineering partner". The button's accessible name is unchanged and still names the field, such as "Clear Search". Applies to every input that renders the shared clear button, including `TextInput`, `NumberInput`, the date and time inputs, `FileInput`, `Selector`, `MultiSelector`, `Typeahead`, and `Tokenizer`. Override the new `@astryx.inputClearButton.tooltip` catalog key to change the wording. (#7476)
|
|
20
|
+
- `Markdown` fenced code blocks wrap long lines instead of scrolling them sideways. A reader on a narrow screen sees the whole line without a horizontal scroll, and where `Markdown` and RichText give a code block the same width, a long line takes the same number of lines in both. Only the appearance changes: the code's text, line numbers, syntax colours and what Copy returns are unchanged, and a code block whose lines no longer overflow also no longer takes the scroll region's Tab stop, as a code block that fits never has. To keep the old sideways-scrolling look, render code yourself through the `components.code` prop with a `CodeBlock` that leaves `isWrapped` off. (#7564)
|
|
21
|
+
- Selector, MultiSelector, and ComplexSelector gain a `secondary` variant: a borderless, neutral-filled trigger matching secondary buttons in navigation and toolbar compositions. Inside an `InputGroup`, a secondary Selector or MultiSelector keeps its fill and takes the group's row height and connected edges. Existing `input` (default) and `ghost` behavior is unchanged. (#7252)
|
|
22
|
+
|
|
23
|
+
#### Fixes
|
|
24
|
+
|
|
25
|
+
- `Typeahead`, `Tokenizer`, and `PowerSearch`: focusing an empty field with `hasEntriesOnFocus` after its search source changed now bootstraps entries from the new source. Previously the results cached from the old source were already invalidated but still blocked the bootstrap, so focusing or clicking into the field opened nothing until the user typed. Cached results that are still current are re-shown without a new bootstrap, as before. (#7157)
|
|
26
|
+
- `BottomSheet` returns focus without a focus ring after a pointer close (a tap in WebKit, or a pointer close of a sheet opened from the keyboard) and keeps the ring after a keyboard close, including on a `DropdownMenu` bottom-sheet trigger the caller renders (`renderTrigger`). The sheet now asks the browser not to treat that focus as keyboard focus, the way Dialog's focus moves do. (#7388)
|
|
27
|
+
- Keep DateInput's calendar selection empty after clearing the field. (#6935)
|
|
28
|
+
- `Calendar`: PageUp and PageDown move the focused day by a month — into the month the grid shows, on the same day of the month where it exists — instead of by a week; a page from a borrowed adjacent-month day lands on that day of the month now shown rather than on the month's first day. With two months, a page or an arrow crossing a month edge from the first month now lands on the correct day (the second grid no longer overrides the first grid's target). An arrow or page past `min`/`max` changes nothing, and a page into a month with no enabled day keeps focus in the grid. (#7467)
|
|
29
|
+
- `Calendar`: the arrow keys, Home and End no longer land on a borrowed adjacent-month day (shown dimmed, exposed as disabled, and inert to Enter, Space and clicks). An arrow crosses into that month and focuses the real day there, including across the two grids of a two-month view; Home and End stop at the first or last enabled day of the week in the month shown. A month with no enabled day holds no Tab stop. (#7511)
|
|
30
|
+
- `Calendar` with `hasWeekNumbers`: the blank cell above the week-number column is now a `columnheader` named with the locale's own word for the week field (from CLDR, visually hidden), so every cell in the header row has a grid role and assistive technology reads the weekday header row without a stray unnamed cell. (#7509)
|
|
31
|
+
- `ChatMessage` no longer leaves empty space for an avatar, name, or metadata that renders nothing. Booleans and empty strings create no slot, and any other slot content that renders nothing, such as an empty Fragment or a component that returns `null`, collapses its wrapper. A name that renders no text falls back to the translated sender label, while numeric values such as `0` still render. (#6597)
|
|
32
|
+
- `CodeBlock`'s code viewport is a keyboard Tab stop only while its content actually overflows, through the shared scroll capability: a short snippet no longer adds an unexplained stop to the page's Tab order, a wide or capped block still does, and a viewport that stops overflowing keeps focus where it is. Role and accessible name are unchanged. (#7424)
|
|
33
|
+
- `CommandPaletteInput` now exposes the semantics and name that its visible state promises. (#7321)
|
|
34
|
+
- A standalone field with no popup attributes was `role="combobox"` with `aria-expanded="true"` and `aria-autocomplete="list"`; it is now `role="searchbox"` with no popup state. Pass `role="combobox"`, or your popup's own ARIA attributes, to keep the old semantics. A field that already passes popup attributes (`aria-expanded`, `aria-controls`, `aria-owns`, `aria-haspopup`, and the like) stays a `combobox` and keeps them, and a field inside `CommandPalette` is unchanged.
|
|
35
|
+
|
|
36
|
+
- The field's default accessible name was its placeholder (`Search…`, or the caller's `placeholder`); it is now `Search commands`, translated. Pass `label` to keep a specific name, for example `label="Search…"` for the old default. A caller whose custom `placeholder` served as the name keeps working code and hears the generic name until it passes `label`.
|
|
37
|
+
|
|
38
|
+
- The CLI's async-search CommandPalette block names its field `Search files`.
|
|
39
|
+
|
|
40
|
+
- `endContent={true}` no longer renders an empty trailing slot, and `endContent={0}` renders inside the trailing slot instead of after it.
|
|
41
|
+
- A standalone `CommandPaletteItem` now keeps a caller-supplied id on its rendered option and ignores click callbacks while disabled, so labels and test hooks keep pointing at the option and a disabled command cannot run. (#7324)
|
|
42
|
+
- `CommandPalette` now keeps dismissal, text entry, result focus, and empty-state announcements aligned with what the reader sees. (#6950)
|
|
43
|
+
- While no selectable result exists, the results container no longer exposes an empty `listbox`, and the query field reports `aria-expanded="false"` with no `aria-controls` or `aria-activedescendant`. It was an expanded combobox controlling an empty listbox.
|
|
44
|
+
|
|
45
|
+
- Home and End move the caret in the query field, as in any text field; they used to jump to the first and last result. Page Up and Page Down still jump to the first and last result.
|
|
46
|
+
|
|
47
|
+
- A search with no results announces the empty message the palette renders (`No results` by default, or the caller's `emptySearchText`), once the search settles. It used to announce `No results for <query>`, whatever the palette showed. An override of the `@astryx.commandPalette.noResultsFor` catalog entry no longer has any effect; use `emptySearchText` to customize the message.
|
|
48
|
+
- `ContextMenu` paints in Safari when its trigger sits inside a scroll container. The menu is anchored to a box at the pointer, and that box was empty: WebKit counts an empty anchor box inside a scroller as clipped, so the default `position-visibility: anchors-visible` hid the open menu. The anchor is now 1px, kept inside the trigger, so the menu still hides while a scroller clips the pointer position and paints again when it scrolls back. A pointer-opened menu now starts 1px lower, below the pixel under the pointer. (#7369)
|
|
49
|
+
- `ContextMenu` now lets Escape dismiss the topmost nested overlay before the menu itself, and preserves consumer trigger handlers while adding its own, so an overlay opened from a menu stays usable and product event logic still runs. (#7167)
|
|
50
|
+
- The touch month scroller shared by `DateInput` and `DateTimeInput`: under RTL the horizontal arrows follow the reading direction (ArrowLeft moves to the next day, ArrowRight to the previous), and every keyboard move — arrows and Home/End — now lands on the real day in its own month pane rather than on the dimmed, disabled copy a neighbouring pane shows at its edge. Touch scrolling is unchanged. (#7466)
|
|
51
|
+
- `DateRangeInput`: activating the clear button with the keyboard now returns focus to the range trigger. Previously the button unmounted once the range was cleared and focus fell to `<body>`, so a keyboard user had to Tab back in from the top of the page. Pointer clears are unchanged. (#7507)
|
|
52
|
+
- `Dialog` now preserves consumer `onClick` handlers while retaining its controlled backdrop-dismissal behavior. (#7452)
|
|
53
|
+
- `DialogHeader` now keeps valid numeric zero content inside its `startContent` and `endContent` wrappers and theme targets. (#7454)
|
|
54
|
+
- `Divider` now keeps numeric zero labels inside the labelled separator and omits boolean or empty-string labels without leaving empty label spacing. (#7572)
|
|
55
|
+
- `DropdownMenuCheckboxItem` now preserves consumer click and pointer-move handlers while keeping its checked-state, disabled, hover-focus, and close-menu behavior. (#7573)
|
|
56
|
+
- A `DropdownMenu` with `header` or `footer` is now exposed as a modal dialog around its menu, as the APG Dialog pattern requires. The popover is a named `role="dialog"` with `aria-modal` and the `role="menu"` inside it; the trigger says `aria-haspopup="dialog"` and its `aria-controls` names the popover holding the dialog. Tab and Shift+Tab wrap through the header, the menu and the footer instead of closing the menu at either end. Escape still closes and returns focus to the trigger. A menu without either prop is unchanged. (#7515)
|
|
57
|
+
- A `DropdownMenu` whose trigger the caller renders (`renderTrigger`) returns focus to it without a focus ring after a pointer pick (a mouse click in Chromium, a click or a tap in WebKit), as the built-in trigger already did: the menu now asks the browser not to treat that focus as keyboard focus, the way Dialog's focus moves do. (#7382)
|
|
58
|
+
- `DropdownMenu` and `MoreMenu`: a disabled trigger no longer opens the menu. A disabled trigger with a tooltip stays focusable (`aria-disabled`), and Button swallowed only Enter and Space, so ArrowDown, ArrowUp, a press, or a click could still open the anchored menu; the anchored open path and the bottom-sheet trigger's click now check the trigger's availability first, for the default Button and for a natively or `aria-disabled` custom trigger. (#7475)
|
|
59
|
+
- `FormLayout`: below the 480px collapse, `direction="horizontal-labels"` controls now fill the column the way they do in a vertical `FormLayout`. Previously each control shrank to its content, so a `Selector` was only as wide as its current value. The two-column layout above 480px is unchanged. (#7501)
|
|
60
|
+
- Buttons used as InputGroup addons now share the group's outer shape, with square inner corners where they meet the adjacent input. (#7233)
|
|
61
|
+
Standalone buttons and buttons rendered inside an input keep their existing shape and behavior.
|
|
62
|
+
- Keep `useHoverCard()` trigger refs stable across unchanged rerenders. The hook returned a fresh `ref`/`interactionRef` on every render because its callbacks depended on the whole `layer` and `touch` objects, which are rebuilt each render — React detached and re-attached every trigger listener and rewrote the trigger's inline `anchor-name` on each rerender. Hooks now depend on the stable layer and touch members instead, mirroring the Tooltip fix in #5951. (#6472) (#6606)
|
|
63
|
+
- MobileNav: return focus to the element that opened the drawer when it closes. The drawer relied entirely on the browser's implicit `<dialog>` focus restore, which was reported failing in Safari 26.5.2: `document.activeElement` became `<body>` after close, stranding keyboard and screen-reader users at the top of the document. MobileNav now captures the opener before `showModal()` moves focus into the top layer and hands it back as soon as the native dialog has closed, matching what `Dialog` already does. The close is deferred until the slide-out has played, so the restore waits for it too; until then the rest of the document is inert and an earlier `focus()` would be silently dropped. The restore also covers the AppShell path, where the drawer is torn down by an `<Activity>` switching to `mode="hidden"` rather than by the close branch re-running. No API change. Focus is left untouched when there was no real opener (`activeElement` was `<body>`), when the opener has since left the DOM, or when the drawer is reopened before its pending close runs. (#3343) (#4410)
|
|
64
|
+
- `MultiSelector`: activating the clear button with the keyboard now returns focus to the trigger, as `hasClear` documents. Previously the button unmounted once the selection was empty and focus fell to `<body>`, so a keyboard user had to Tab back in from the top of the page. Pointer clears are unchanged. (#7506)
|
|
65
|
+
- `NumberInput`: the screen-reader "Invalid number" alert now goes through the i18n translator, so an `InternationalizationProvider` locale or override can replace it. Adds `@astryx.numberInput.invalidNumber` to the `en` catalog. Locales without a translation yet still fall back to English. (#7482)
|
|
66
|
+
- `astryx.css`, `reset.css`, and every other package stylesheet (`richtext.css`, `lab.css`, `charts.css`) now open with `@layer reset, astryx-base, astryx-theme;`, the same line theme stylesheets carry. The Astryx layer order holds whichever Astryx stylesheet loads first: loading `reset.css` after `astryx.css` no longer lets the reset override component styles, and theme overrides keep winning. Setups that already declare the order on their own first line are unchanged. (#7585)
|
|
67
|
+
- `plainDateToInstant` now resolves skipped and repeated wall times the way Temporal's default `"compatible"` disambiguation does. (#7081)
|
|
68
|
+
- A skipped wall time moves forward by the length of the gap. In a zone that springs forward from a negative offset at local midnight, such as America/Santiago on September 6, 2026 or America/Havana on March 8, 2026, the start of that day came back as 11:00 PM the day before, so a week or day range landed on the wrong date; it is now the day's first instant (1:00 AM).
|
|
69
|
+
|
|
70
|
+
- A repeated wall time resolves to its earlier occurrence in every zone. In zones with a positive offset, such as Europe/Berlin on October 25, 2026, it resolved to the later one.
|
|
71
|
+
- `Calendar`: dates in years 1-99 now show their own year instead of 1900-1999. A value of `0001-01-15` was captioned "January 1901" with 1901's weekday layout and day labels, while `onChange` still emitted the year-1 ISO date. The shared date helpers behind the caption, day grid, week numbers, day counts, and timezone instants now keep years 1-99 as given. One limitation remains: in a timezone west of UTC, the instant for January 1 of year 1 still comes out a year early, because its timezone offset is read from a 1 BC wall clock without the era. (#7465)
|
|
72
|
+
- `PowerSearch`: pressing Enter on a focused button in the filter editor now activates that button. Enter on Cancel closes the editor without applying the draft, and Enter on Delete removes the filter; before, both applied the draft instead. Enter in a text or number value field still applies the filter; Enter on the date picker's calendar button now opens the calendar. (#7500)
|
|
73
|
+
- `CommandPaletteList` now preserves a caller-supplied id when used standalone, while a managed `CommandPalette` still assigns the ARIA id its search field controls. External labels and test hooks stay attached without breaking the palette's combobox relationship. (#6988)
|
|
74
|
+
- `reset.css` no longer hides `hidden="until-found"` content with `display: none`. The browser's own rendering, `content-visibility: hidden`, now applies, so find in page and text fragment links can find the content and reveal it, as the HTML Standard specifies. Plain `hidden` elements are still `display: none`, and a browser without until-found support still hides the content with its own `[hidden]` rule. (#7520)
|
|
75
|
+
- `ResizeHandle`: on a collapsed pane, the arrow that grows it opens it one step above its minimum, or at its `collapsedSize` when that is larger (a single step below the collapse threshold used to leave it collapsed); the arrow that shrinks it stays a no-op. Enter and double-click still restore the previous size. (#7512)
|
|
76
|
+
- `ResizeHandle`: Enter and double-click on a collapsed pane restore it to the size it had before it collapsed, not to its minimum, and reopen it even when `minSize` is below `collapsedSize`. The handle uses `useResizable`'s own collapse and expand transitions; `ResizableProps` is unchanged, and a hand-built props object keeps the previous resize-to-minimum behavior. (#7479)
|
|
77
|
+
- `ResizeHandle`: with snap points set, an arrow key moves the pane to the adjacent snap point in its direction (Shift moves two), a point beyond the bounds counting as that bound — a 10px step used to snap straight back to the point it started on. With snap points, a shrink arrow at the lowest point no longer collapses a collapsible pane; Enter, double-click and dragging still do. (#7514)
|
|
78
|
+
- `ResizeHandle`: a separator whose region sets no `maxSize` now reports an `aria-valuemax` — a measured extent standing in for the missing maximum (the window's extent on the region's axis, or the container's content box while a percentage bound observes it), never below the current size or, while collapsed, the minimum. Pixel-only regions inside a container still report no maximum (measuring one would add an observer). `ResizableProps` is unchanged; End still moves only to a configured maximum. (#7481)
|
|
79
|
+
- `useScrollOverflow` (the strip of `TabList`, the scroller of `Carousel`) measures a resize, and its container at registration, only while the container is rendered. Inside a `display: none` ancestor or a `content-visibility: hidden` subtree the hook keeps its last state instead of reading layout, since a layout read there made the browser render the whole hidden subtree for the answer; the resize observation that comes with the reveal measures again, one frame after the reveal paints. A scroll is measured hidden or not, so a container script scrolled while hidden (a selected tab's reveal) is right at a reveal that brings no resize. Before, a hidden container reported no overflow. (#7518)
|
|
80
|
+
- A `secondary` Selector, MultiSelector, or ComplexSelector now matches the theme's secondary Button: under butter, chocolate, gothic, stone, and y2k it takes that Button's border, fill, text color, and hover instead of the default borderless neutral fill, so a toolbar mixing secondary buttons and selectors reads as one set of controls. Disabled and read-only triggers keep a still fill on hover, as a disabled Button does, and a Selector or MultiSelector inside an InputGroup keeps the group's neutral fill and edges. The default theme is unchanged, the selector docs now say `secondary` follows the theme's secondary Button, and themes added with the CLI get the same parity. (#7548)
|
|
81
|
+
- `Selector`: activating the clear button with the keyboard now returns focus to the trigger, as `hasClear` documents. Previously the button unmounted once the value was cleared and focus fell to `<body>`, so a keyboard user had to Tab back in from the top of the page. Pointer clears are unchanged. (#7455)
|
|
82
|
+
- `SideNav`: the resize handle now names the navigation pane it resizes with `aria-controls` (the nav gets a generated id when the consumer gives none), as the APG window splitter pattern requires, so assistive technology can relate the separator to the pane. (#7473)
|
|
83
|
+
- `Slider`: End now reaches `max` even when the step grid does not land on it (for `max={100}` with `step={3}`, End stopped at 99). Arrow and Page key results still snap to the nearest step and then clamp. (#7484)
|
|
84
|
+
- `Slider`: on a horizontal track under RTL the arrow keys now follow the mirrored track — ArrowLeft increases the value and ArrowRight decreases it, matching where the thumb moves on screen. ArrowUp/ArrowDown, PageUp/PageDown, Home/End, and vertical sliders are unchanged. (#7461)
|
|
85
|
+
- Stop Tokenizer's `hasCreate` "Create X" entry from offering a label that is already tokenized under a different id. The duplicate check compared the typed text against selected ids, but real selections usually carry an opaque id (`u1` under the label "Alice"), and the search results could not catch the match because they are pre-filtered to remove already-selected items — so typing an existing token's label offered "Create", which committed a second, duplicate token with a new id. The check now also compares against selected labels (case-insensitive), in both the Create entry and the stale-entry commit guard. (#6367)
|
|
86
|
+
- Keep Toolbar keyboard navigation and roving tab stops outside nested popover menus, without disabling toolbar navigation inside an outer popover. (#7446)
|
|
87
|
+
- `TreeList`: each row is now named by its label alone and described by its description (`aria-labelledby`/`aria-describedby` on the `treeitem`), so screen readers no longer read the chevron toggle's label or the description as part of a row's name, and link and action rows are named as rows, not only through their inner control. Typeahead matches the label rather than the row's whole text. (#7472)
|
|
88
|
+
|
|
89
|
+
#### Documentation
|
|
90
|
+
|
|
91
|
+
- `AlertDialog`'s anatomy lists the dialog surface — the modal panel that holds the title, description, and buttons — and `Calendar`'s anatomy lists the calendar root and the day button, so every part that carries a theming target (`alert-dialog`, `calendar`, `calendar-day`) is named in the component docs. (#7464)
|
|
92
|
+
- List `DateInput`'s `containerClassName`, `containerStyle`, `controlClassName`, and `controlStyle` props in its API reference, alongside `containerXstyle` and `controlXstyle`. (#7372)
|
|
93
|
+
- Grid's `columns` docs now lead with the shape that reflows: a numeric `columns` is exactly N columns at every width and never reflows, and `columns={{minWidth, max}}` is the form for columns that must survive a phone. The `astryx docs layout/responsive` topic gains a "Columns that reflow" section with a reflowing stat row beside a fixed week row. No behavior changes. (#7340)
|
|
94
|
+
|
|
95
|
+
#### Other Changes
|
|
96
|
+
|
|
97
|
+
- The core build now fails when StyleX rejects a declaration such as a `border`, `background`, or `all` shorthand, instead of silently dropping it from the shipped CSS. The emitted `dist/` is unchanged. No API change. (#6830)
|
|
98
|
+
|
|
99
|
+
#### Contributors
|
|
100
|
+
|
|
101
|
+
Thanks to everyone who contributed to this release:
|
|
102
|
+
|
|
103
|
+
- @AKnassa
|
|
104
|
+
- @athz
|
|
105
|
+
- @barm
|
|
106
|
+
- @cixzhang
|
|
107
|
+
- @ernestt
|
|
108
|
+
- @Geervan
|
|
109
|
+
- @harjothkhara
|
|
110
|
+
- @imdreamrunner
|
|
111
|
+
- @korkt-kim
|
|
112
|
+
- @kyu-rong
|
|
113
|
+
- @ManoharPaturi
|
|
114
|
+
- @rubyycheung
|
|
115
|
+
- @vjeux
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
3
119
|
# 0.7.0
|
|
4
120
|
|
|
5
121
|
#### Breaking Changes
|
package/dist/Button/Button.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Button.tsx
|
|
3
|
-
* @input Uses React, ButtonHTMLAttributes, ReactNode, i18n (useTranslator)
|
|
3
|
+
* @input Uses React, ButtonHTMLAttributes, ReactNode, i18n (useTranslator), group contexts
|
|
4
4
|
* @output Exports Button component, ButtonProps, ButtonVariant types
|
|
5
5
|
* @position Core implementation; consumed by index.ts, tested by Button.test.tsx
|
|
6
6
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAwB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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"}
|
package/dist/Button/Button.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Button.tsx
|
|
7
|
-
* @input Uses React, ButtonHTMLAttributes, ReactNode, i18n (useTranslator)
|
|
7
|
+
* @input Uses React, ButtonHTMLAttributes, ReactNode, i18n (useTranslator), group contexts
|
|
8
8
|
* @output Exports Button component, ButtonProps, ButtonVariant types
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by Button.test.tsx
|
|
10
10
|
*
|
|
@@ -29,6 +29,8 @@ import { iconBoxSizeStyles } from "../Icon/IconSize.stylex.js";
|
|
|
29
29
|
import { EDGE_COMP_ATTR } from "../Layout/edgeCompensation.stylex.js";
|
|
30
30
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
31
31
|
import { useButtonGroup } from "../ButtonGroup/ButtonGroupContext.js";
|
|
32
|
+
import { useInputGroup } from "../InputGroup/InputGroupContext.js";
|
|
33
|
+
import { groupStyles as inputGroupStyles } from "../InputGroup/groupStyles.js";
|
|
32
34
|
import { mergeProps } from "../utils/index.js";
|
|
33
35
|
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
34
36
|
import { useLinkComponent } from "../Link/useLinkComponent.js";
|
|
@@ -347,6 +349,7 @@ export function Button({
|
|
|
347
349
|
const t = useTranslator();
|
|
348
350
|
const size = useSize(sizeProp, 'md');
|
|
349
351
|
const buttonGroup = useButtonGroup();
|
|
352
|
+
const inputGroup = useInputGroup();
|
|
350
353
|
const [isPending, startTransition] = useTransition();
|
|
351
354
|
// clickAction is normally fire-once (submit/save/pay), so a same-tick
|
|
352
355
|
// double-click must dedupe — which neither isPending nor useOptimistic do.
|
|
@@ -428,7 +431,7 @@ export function Button({
|
|
|
428
431
|
} : null;
|
|
429
432
|
|
|
430
433
|
// Shared StyleX props for both button and link rendering
|
|
431
|
-
const sharedStylexProps = focusOutlineProps.focusVisible(styles.base, sizeStyles[size], isIconOnly && styles.iconOnly, interactionOverlayStyles.backgroundImage, buttonDisabled && styles.inactive, visuallyDisabled && styles.disabled, useAriaDisabled && styles.ariaDisabled, renderAsLink && styles.link, !buttonGroup && styles.pressable, buttonGroup && (buttonGroup.orientation === 'horizontal' ? groupStyles.horizontal : groupStyles.vertical), buttonGroup && (variant === 'primary' || variant === 'destructive') && (buttonGroup.orientation === 'horizontal' ? groupStyles.onSolidHorizontal : groupStyles.onSolidVertical),
|
|
434
|
+
const sharedStylexProps = focusOutlineProps.focusVisible(styles.base, sizeStyles[size], isIconOnly && styles.iconOnly, interactionOverlayStyles.backgroundImage, buttonDisabled && styles.inactive, visuallyDisabled && styles.disabled, useAriaDisabled && styles.ariaDisabled, renderAsLink && styles.link, !buttonGroup && styles.pressable, buttonGroup && (buttonGroup.orientation === 'horizontal' ? groupStyles.horizontal : groupStyles.vertical), inputGroup != null && buttonGroup == null && inputGroupStyles.buttonAddon, buttonGroup && (variant === 'primary' || variant === 'destructive') && (buttonGroup.orientation === 'horizontal' ? groupStyles.onSolidHorizontal : groupStyles.onSolidVertical),
|
|
432
435
|
// Standalone floating buttons only — a grouped button's elevation is owned
|
|
433
436
|
// by the ButtonGroup so the shared surface lifts as one unit.
|
|
434
437
|
!buttonGroup && elevationStyles[elevation], width != null && dynamicStyles.width(width),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../../src/Calendar/Calendar.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../../src/Calendar/Calendar.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsD5C,YAAY,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACV,MAAM,oBAAoB,CAAC;AAS5B,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAID,UAAU,iBAAkB,SAAQ,IAAI,CACtC,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,cAAc,CAC5B;IACC,kDAAkD;IAClD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qDAAqD;IACrD,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEvB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAEzD;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAC;IAEvD;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;CAC1C;AAID,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,qBAAqB;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,mFAAmF;IACnF,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAE7B,0CAA0C;IAC1C,YAAY,CAAC,EAAE,aAAa,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,KAAK,IAAI,CAAC;CAC9D;AAED,UAAU,kBAAmB,SAAQ,iBAAiB;IACpD,qBAAqB;IACrB,IAAI,EAAE,OAAO,CAAC;IAEd,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEzB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,SAAS,CAAC;IAEzB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAqBrE;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,aAAa,+BAghBtD;yBAhhBe,QAAQ"}
|
|
@@ -24,7 +24,7 @@ import { Icon } from "../Icon/index.js";
|
|
|
24
24
|
import { useAnnounce, useGridFocus } from "../hooks/index.js";
|
|
25
25
|
import { useCalendarDays, useCalendarConstraints } from "./hooks/index.js";
|
|
26
26
|
import { calendarStyles, monthGridStyles, dayCellStyles, dayCellTheme } from "./styles.js";
|
|
27
|
-
import { plainDateFromISO, plainDateToISO, plainDateToDate, plainDateToday, plainDateSetFirstOfMonth, plainDateAddMonths, plainDateAddDays, plainDateIsBefore, plainDateIsEqual, plainDateGetWeekNumber, plainDateFormat, DATE_FORMAT_WITH_WEEKDAY, DATE_FORMAT_MONTH_YEAR } from "../utils/plainDate.js";
|
|
27
|
+
import { plainDateFromISO, plainDateToISO, plainDateToDate, plainDateToday, plainDateSetFirstOfMonth, plainDateAddMonths, plainDateAddDays, plainDateDiffDays, getDaysInMonth, plainDateIsAfter, plainDateIsBefore, plainDateIsEqual, plainDateGetWeekNumber, plainDateFormat, plainDateWeekFieldName, DATE_FORMAT_WITH_WEEKDAY, DATE_FORMAT_MONTH_YEAR } from "../utils/plainDate.js";
|
|
28
28
|
import { mergeProps, composeEventHandlers, rtlStyles } from "../utils/index.js";
|
|
29
29
|
import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
|
|
30
30
|
import { interactionOverlayStyles } from "../utils/interactionOverlay.stylex.js";
|
|
@@ -39,6 +39,9 @@ import { computeDayCellState, computeRangeRounding, computePreviewRounding, comp
|
|
|
39
39
|
import { normalizeDayOfWeek } from "../utils/dateTypes.js";
|
|
40
40
|
import { themeProps } from "../utils/themeProps.js";
|
|
41
41
|
import { useLocale, useTranslator } from "../i18n/index.js";
|
|
42
|
+
import { VisuallyHidden } from "../VisuallyHidden/index.js";
|
|
43
|
+
|
|
44
|
+
/** How a month navigation moves the focused day: by its row offset in days, or by whole months. */
|
|
42
45
|
|
|
43
46
|
/** Imperative handle for Calendar handleRef */
|
|
44
47
|
|
|
@@ -46,6 +49,22 @@ import { useLocale, useTranslator } from "../i18n/index.js";
|
|
|
46
49
|
|
|
47
50
|
// ─── Mode-specific Props (discriminated union) ────────────────
|
|
48
51
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
52
|
+
/** The first day of `month`'s month that `isDisabled` allows, or null. */
|
|
53
|
+
function firstEnabledDayOfMonth(month, isDisabled) {
|
|
54
|
+
const days = getDaysInMonth(month.year, month.month);
|
|
55
|
+
for (let day = 1; day <= days; day += 1) {
|
|
56
|
+
const pd = {
|
|
57
|
+
year: month.year,
|
|
58
|
+
month: month.month,
|
|
59
|
+
day
|
|
60
|
+
};
|
|
61
|
+
if (!isDisabled(pd)) {
|
|
62
|
+
return pd;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
49
68
|
// =============================================================================
|
|
50
69
|
// Main Component
|
|
51
70
|
// =============================================================================
|
|
@@ -157,6 +176,30 @@ export function Calendar({
|
|
|
157
176
|
});
|
|
158
177
|
}, [baseMonth, numberOfMonths]);
|
|
159
178
|
|
|
179
|
+
// A pending target is claimed by the grid that shows its month, or dropped
|
|
180
|
+
// by the next focus move that is not onto the target day: when a controlled
|
|
181
|
+
// owner refuses the month change, no grid shows the target's month, and a
|
|
182
|
+
// stale target would later steal focus (and Enter) when that month does
|
|
183
|
+
// appear. Only a grid showing the target's month receives it; any other
|
|
184
|
+
// focus change (an arrow to another day, the month header's buttons, or out
|
|
185
|
+
// of the calendar) drops it (see onBlur below).
|
|
186
|
+
const claimablePendingFocus = useMemo(() => {
|
|
187
|
+
if (pendingFocus == null) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const target = plainDateFromISO(pendingFocus);
|
|
191
|
+
return visibleMonths.some(pd => pd.year === target.year && pd.month === target.month) ? pendingFocus : null;
|
|
192
|
+
}, [pendingFocus, visibleMonths]);
|
|
193
|
+
const handleRootBlur = useCallback(e => {
|
|
194
|
+
// Only the move onto the target day itself keeps the target: an arrow
|
|
195
|
+
// to any other day, a move to the header buttons, or focus leaving the
|
|
196
|
+
// calendar all drop it.
|
|
197
|
+
const movesToTarget = e.relatedTarget instanceof Element && e.relatedTarget.getAttribute('data-date') === pendingFocus;
|
|
198
|
+
if (pendingFocus != null && !movesToTarget) {
|
|
199
|
+
setPendingFocus(null);
|
|
200
|
+
}
|
|
201
|
+
}, [pendingFocus]);
|
|
202
|
+
|
|
160
203
|
// Format month header
|
|
161
204
|
const monthYearLabel = useMemo(() => {
|
|
162
205
|
if (numberOfMonths === 1) {
|
|
@@ -185,6 +228,8 @@ export function Calendar({
|
|
|
185
228
|
}, [monthYearLabel, announce]);
|
|
186
229
|
|
|
187
230
|
// Determine if prev/next navigation is possible based on min/max
|
|
231
|
+
const minDateForKeys = useMemo(() => min ? plainDateFromISO(min) : null, [min]);
|
|
232
|
+
const maxDateForKeys = useMemo(() => max ? plainDateFromISO(max) : null, [max]);
|
|
188
233
|
const canNavigatePrevious = useMemo(() => {
|
|
189
234
|
if (!min) {
|
|
190
235
|
return true;
|
|
@@ -204,23 +249,109 @@ export function Calendar({
|
|
|
204
249
|
}, [max, baseMonth, numberOfMonths]);
|
|
205
250
|
|
|
206
251
|
// Navigation handlers
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
252
|
+
// The same constraint view the grids use, so a key can resolve its target
|
|
253
|
+
// before the month changes.
|
|
254
|
+
const rootRangeAnchor = useMemo(() => mode === 'range' && rangeSelectionStart ? plainDateFromISO(rangeSelectionStart) : null, [mode, rangeSelectionStart]);
|
|
255
|
+
const {
|
|
256
|
+
isDateDisabled: isRootDateDisabled
|
|
257
|
+
} = useCalendarConstraints({
|
|
258
|
+
min,
|
|
259
|
+
max,
|
|
260
|
+
dateConstraints,
|
|
261
|
+
maxRangeSpan,
|
|
262
|
+
minRangeSpan,
|
|
263
|
+
rangeAnchor: rootRangeAnchor
|
|
264
|
+
});
|
|
265
|
+
const navigateMonth = useCallback((delta, focusedDate, offset, unit = 'days') => {
|
|
266
|
+
const monthIndex = pd => pd.year * 12 + pd.month;
|
|
267
|
+
const firstShown = monthIndex(baseMonth);
|
|
268
|
+
const lastShown = firstShown + numberOfMonths - 1;
|
|
269
|
+
|
|
270
|
+
// The Previous/Next buttons move the month with no focused day.
|
|
271
|
+
if (!focusedDate) {
|
|
272
|
+
if (delta < 0 && !canNavigatePrevious || delta > 0 && !canNavigateNext) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const newPd = plainDateAddMonths(baseMonth, delta);
|
|
276
|
+
if (onFocusDateChange) {
|
|
277
|
+
onFocusDateChange(plainDateToISO(newPd));
|
|
278
|
+
} else {
|
|
279
|
+
setInternalFocusDate(newPd);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
210
283
|
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
284
|
+
// A key resolves its TARGET day first and decides by that, so a
|
|
285
|
+
// boundary blocks only out-of-range targets, never the month movement
|
|
286
|
+
// itself (ArrowUp from February 3 reaches January 27 at a January
|
|
287
|
+
// minimum), and a direction with no enabled day left changes nothing
|
|
288
|
+
// rather than dropping focus.
|
|
289
|
+
const currentPd = plainDateFromISO(focusedDate);
|
|
290
|
+
const inRange = pd => !(minDateForKeys && plainDateIsBefore(pd, minDateForKeys)) && !(maxDateForKeys && plainDateIsAfter(pd, maxDateForKeys));
|
|
291
|
+
let targetPd;
|
|
292
|
+
if (unit === 'months') {
|
|
293
|
+
// A page targets the same day of the month a month away (clamped to
|
|
294
|
+
// that month's length). Past `min`/`max` nothing moves; a month with
|
|
295
|
+
// no enabled day is no destination either, the same as an arrow with
|
|
296
|
+
// no enabled day in its direction; a target disabled by a constraint
|
|
297
|
+
// lands on that month's first enabled day instead.
|
|
298
|
+
const candidate = plainDateAddMonths(currentPd, delta);
|
|
299
|
+
if (!inRange(candidate)) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (isRootDateDisabled(candidate)) {
|
|
303
|
+
const firstEnabled = firstEnabledDayOfMonth(candidate, isRootDateDisabled);
|
|
304
|
+
if (firstEnabled == null) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
targetPd = firstEnabled;
|
|
308
|
+
} else {
|
|
309
|
+
targetPd = candidate;
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
// Walk the arrow's direction to the first enabled day, up to a year
|
|
313
|
+
// away; past `min`/`max` or with every day disabled, nothing moves.
|
|
314
|
+
const step = delta * (offset ?? 7);
|
|
315
|
+
let candidate = plainDateAddDays(currentPd, step);
|
|
316
|
+
let found = null;
|
|
317
|
+
while (Math.abs(plainDateDiffDays(currentPd, candidate)) <= 366) {
|
|
318
|
+
if (!inRange(candidate)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (!isRootDateDisabled(candidate)) {
|
|
322
|
+
found = candidate;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
candidate = plainDateAddDays(candidate, step);
|
|
326
|
+
}
|
|
327
|
+
if (found == null) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
targetPd = found;
|
|
217
331
|
}
|
|
332
|
+
|
|
333
|
+
// Focus moves to the target; the months change only when the target's
|
|
334
|
+
// month is not already shown. The view shifts the least it can in the
|
|
335
|
+
// key's direction, so the target month becomes the first (backwards)
|
|
336
|
+
// or last (forwards) month shown.
|
|
337
|
+
const resolved = targetPd;
|
|
338
|
+
const targetMonth = monthIndex(resolved);
|
|
339
|
+
setPendingFocus(plainDateToISO(resolved));
|
|
340
|
+
if (targetMonth >= firstShown && targetMonth <= lastShown) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const targetFirst = {
|
|
344
|
+
year: resolved.year,
|
|
345
|
+
month: resolved.month,
|
|
346
|
+
day: 1
|
|
347
|
+
};
|
|
348
|
+
const newPd = targetMonth < firstShown ? targetFirst : plainDateAddMonths(targetFirst, -(numberOfMonths - 1));
|
|
218
349
|
if (onFocusDateChange) {
|
|
219
|
-
onFocusDateChange(
|
|
350
|
+
onFocusDateChange(plainDateToISO(newPd));
|
|
220
351
|
} else {
|
|
221
352
|
setInternalFocusDate(newPd);
|
|
222
353
|
}
|
|
223
|
-
}, [baseMonth, onFocusDateChange]);
|
|
354
|
+
}, [baseMonth, canNavigateNext, canNavigatePrevious, isRootDateDisabled, maxDateForKeys, minDateForKeys, numberOfMonths, onFocusDateChange]);
|
|
224
355
|
|
|
225
356
|
// Escape key handler to cancel range selection
|
|
226
357
|
const handleCalendarKeyDown = useCallback(e => {
|
|
@@ -294,6 +425,7 @@ export function Calendar({
|
|
|
294
425
|
return /*#__PURE__*/_jsxs("div", {
|
|
295
426
|
ref: ref,
|
|
296
427
|
...rest,
|
|
428
|
+
onBlur: composeEventHandlers(rest.onBlur, handleRootBlur),
|
|
297
429
|
...mergeProps(themeProps('calendar', {
|
|
298
430
|
mode
|
|
299
431
|
}), stylex.props(calendarStyles.calendar, xstyle), className, style),
|
|
@@ -365,9 +497,9 @@ export function Calendar({
|
|
|
365
497
|
onDayClick: handleDayClick,
|
|
366
498
|
onDayHover: date => setHoveredDate(date ? plainDateToISO(date) : null),
|
|
367
499
|
today: today,
|
|
368
|
-
onNavigatePrevious: (focusedDate, offset) => navigateMonth(-1, focusedDate, offset),
|
|
369
|
-
onNavigateNext: (focusedDate, offset) => navigateMonth(1, focusedDate, offset),
|
|
370
|
-
pendingFocus:
|
|
500
|
+
onNavigatePrevious: (focusedDate, offset, unit) => navigateMonth(-1, focusedDate, offset, unit),
|
|
501
|
+
onNavigateNext: (focusedDate, offset, unit) => navigateMonth(1, focusedDate, offset, unit),
|
|
502
|
+
pendingFocus: claimablePendingFocus,
|
|
371
503
|
onPendingFocusHandled: () => setPendingFocus(null)
|
|
372
504
|
}, `${month.year}-${month.month}`))
|
|
373
505
|
})]
|
|
@@ -501,13 +633,13 @@ function MonthGrid({
|
|
|
501
633
|
const handlePageUp = useCallback(() => {
|
|
502
634
|
const focusedDate = getFocusedDate();
|
|
503
635
|
if (focusedDate) {
|
|
504
|
-
onNavigatePrevious?.(focusedDate,
|
|
636
|
+
onNavigatePrevious?.(focusedDate, 1, 'months');
|
|
505
637
|
}
|
|
506
638
|
}, [getFocusedDate, onNavigatePrevious]);
|
|
507
639
|
const handlePageDown = useCallback(() => {
|
|
508
640
|
const focusedDate = getFocusedDate();
|
|
509
641
|
if (focusedDate) {
|
|
510
|
-
onNavigateNext?.(focusedDate,
|
|
642
|
+
onNavigateNext?.(focusedDate, 1, 'months');
|
|
511
643
|
}
|
|
512
644
|
}, [getFocusedDate, onNavigateNext]);
|
|
513
645
|
|
|
@@ -527,7 +659,12 @@ function MonthGrid({
|
|
|
527
659
|
} = useGridFocus({
|
|
528
660
|
columns: 7,
|
|
529
661
|
cellSelector: '[role="gridcell"]',
|
|
530
|
-
|
|
662
|
+
// A borrowed adjacent-month day is exposed aria-disabled (its click does
|
|
663
|
+
// nothing, but it can still take pointer focus) and may also be natively
|
|
664
|
+
// disabled by bounds or a constraint; the keyboard skips it either way
|
|
665
|
+
// and crosses into that month through the grid edge instead, so focus
|
|
666
|
+
// lands on the real day in the month now shown (FR5).
|
|
667
|
+
isCellFocusable: cell => cell.querySelector('button:not([disabled]):not([aria-disabled="true"])') !== null,
|
|
531
668
|
getFocusTarget: cell => cell.querySelector('button'),
|
|
532
669
|
hasRovingTabIndex: true,
|
|
533
670
|
onNavigateBefore: handleNavigatePrevious,
|
|
@@ -536,27 +673,38 @@ function MonthGrid({
|
|
|
536
673
|
onPageDown: handlePageDown
|
|
537
674
|
});
|
|
538
675
|
|
|
539
|
-
// Handle pending focus after month navigation
|
|
676
|
+
// Handle pending focus after month navigation. Every mounted month grid
|
|
677
|
+
// sees the same pending date; only the grid showing that date's month acts,
|
|
678
|
+
// so a neighbouring grid's fallback never overrides the right target. The
|
|
679
|
+
// target is the real day in this month, never an outside-day copy; when it
|
|
680
|
+
// is disabled, the month's first enabled day takes focus instead.
|
|
540
681
|
useEffect(() => {
|
|
541
682
|
if (!pendingFocus || !gridRef.current) {
|
|
542
683
|
return;
|
|
543
684
|
}
|
|
544
|
-
const buttons = gridRef.current.querySelectorAll('button:not([disabled])');
|
|
545
685
|
const targetPd = plainDateFromISO(pendingFocus);
|
|
686
|
+
if (targetPd.year !== year || targetPd.month !== month.month) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
546
689
|
const targetIso = plainDateToISO(targetPd);
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
690
|
+
const buttons = Array.from(gridRef.current.querySelectorAll('button[data-date]:not([disabled]):not([aria-disabled="true"])'));
|
|
691
|
+
|
|
692
|
+
// The real target day, else the month's first enabled day, else — in a
|
|
693
|
+
// month with no enabled day — the first day button that can still take
|
|
694
|
+
// focus (a borrowed adjacent-month day), so focus stays in the grid
|
|
695
|
+
// rather than dropping to the page.
|
|
696
|
+
const targetButton = buttons.find(button => button.getAttribute('data-date') === targetIso) ?? buttons[0] ?? gridRef.current.querySelector('button[data-date]:not([disabled])') ?? null;
|
|
697
|
+
if (targetButton != null) {
|
|
698
|
+
// The target becomes this grid's one Tab stop before it takes focus,
|
|
699
|
+
// the way the hook's own arrow moves do (FR2): a programmatic focus
|
|
700
|
+
// alone would leave the stop on the day the grid mounted with.
|
|
701
|
+
for (const button of gridRef.current.querySelectorAll('button[data-date]')) {
|
|
702
|
+
button.tabIndex = button === targetButton ? 0 : -1;
|
|
552
703
|
}
|
|
704
|
+
targetButton.focus();
|
|
553
705
|
}
|
|
554
|
-
if (!targetButton && buttons.length > 0) {
|
|
555
|
-
targetButton = buttons[0];
|
|
556
|
-
}
|
|
557
|
-
targetButton?.focus();
|
|
558
706
|
onPendingFocusHandled?.();
|
|
559
|
-
}, [pendingFocus, gridRef, onPendingFocusHandled]);
|
|
707
|
+
}, [pendingFocus, gridRef, month.month, onPendingFocusHandled, year]);
|
|
560
708
|
|
|
561
709
|
// Parse selection
|
|
562
710
|
let selectedDate = null;
|
|
@@ -613,8 +761,19 @@ function MonthGrid({
|
|
|
613
761
|
children: [/*#__PURE__*/_jsxs("div", {
|
|
614
762
|
role: "row",
|
|
615
763
|
...stylex.props(monthGridStyles.weekRow),
|
|
616
|
-
children: [hasWeekNumbers &&
|
|
617
|
-
|
|
764
|
+
children: [hasWeekNumbers &&
|
|
765
|
+
/*#__PURE__*/
|
|
766
|
+
// The corner above the week-number column is a header cell like
|
|
767
|
+
// the weekday names beside it (APG grid: every cell in a row is a
|
|
768
|
+
// gridcell, columnheader or rowheader). Its name is the locale's
|
|
769
|
+
// own word for the week field, as visually hidden text so the
|
|
770
|
+
// column stays blank and the header is not empty to axe.
|
|
771
|
+
_jsx("div", {
|
|
772
|
+
role: "columnheader",
|
|
773
|
+
...stylex.props(monthGridStyles.dayName, monthGridStyles.weekNumberHeader),
|
|
774
|
+
children: /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
775
|
+
children: plainDateWeekFieldName(locale)
|
|
776
|
+
})
|
|
618
777
|
}), dayNameHeaders.map(({
|
|
619
778
|
dayOfWeek,
|
|
620
779
|
name
|
|
@@ -116,6 +116,15 @@ export type ChatComposerTrigger = {
|
|
|
116
116
|
loadingText?: string;
|
|
117
117
|
/** Accessible label for the menu. @default 'Suggestions' */
|
|
118
118
|
menuLabel?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Whether the query continues past spaces, for suggestions whose names have
|
|
121
|
+
* spaces (e.g. "@María José García", "@Design Review: Q4"). The query then
|
|
122
|
+
* runs until a line break or about 64 characters, and when nothing matches
|
|
123
|
+
* the menu hides unless `emptySearchText` is set. When false, the query ends
|
|
124
|
+
* at the first space.
|
|
125
|
+
* @default false
|
|
126
|
+
*/
|
|
127
|
+
hasMultiWordQuery?: boolean;
|
|
119
128
|
};
|
|
120
129
|
export interface ChatComposerInputProps extends Omit<BaseProps<HTMLDivElement>, 'onChange' | 'onPaste' | 'onSubmit'> {
|
|
121
130
|
/** Ref forwarded to the root element. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAqBrE,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAQ,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAShD,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;IAC9D,6EAA6E;IAC7E,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uDAAuD;IACvD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,sBAAsB;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB;AAED,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAAG;IACnC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC;AAE/D,mFAAmF;AACnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,EAAE,MAAM,SAAS,CAAC;CACzB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAC3B,sBAAsB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,WAAW,6BAA8B,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC/E,0CAA0C;IAC1C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,kEAAkE;IAClE,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG;IAChC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,SAAS,CAAC;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,GAAG,iBAAiB,CAAC;IAC/D;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAC;IAC1D;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -437,6 +437,11 @@ export function ChatComposerInput(props) {
|
|
|
437
437
|
historyIndexRef.current = -1;
|
|
438
438
|
currentDraftRef.current = '';
|
|
439
439
|
}
|
|
440
|
+
|
|
441
|
+
// Submitting ends any trigger query, including one dismissed with
|
|
442
|
+
// Escape: no menu stays open, and no dismissal carries into the next
|
|
443
|
+
// message.
|
|
444
|
+
triggerMenu.reset();
|
|
440
445
|
onSubmit?.(text);
|
|
441
446
|
editableRef.current.textContent = '';
|
|
442
447
|
setIsEmpty(true);
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* SYNC: When modified, update these files to stay in sync:
|
|
13
13
|
* - /packages/core/src/Chat/index.ts (exports)
|
|
14
14
|
* - /apps/storybook/stories/Chat.stories.tsx
|
|
15
|
+
* - /apps/storybook/stories/ChatMessage.stories.tsx
|
|
15
16
|
* - /packages/cli/assets/templates/blocks/components/ChatMessage/ (block examples)
|
|
16
17
|
*/
|
|
17
18
|
import { type ReactNode } from 'react';
|
|
@@ -28,9 +29,17 @@ export interface ChatMessageProps extends BaseProps<HTMLElement> {
|
|
|
28
29
|
* should span the full message column.
|
|
29
30
|
*/
|
|
30
31
|
children: ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Avatar content rendered beside a non-system message.
|
|
34
|
+
* `null`, booleans, and empty strings create no slot; any other content that
|
|
35
|
+
* renders nothing collapses its slot.
|
|
36
|
+
*/
|
|
31
37
|
avatar?: ReactNode;
|
|
32
38
|
/**
|
|
33
39
|
* Sender name rendered above the message body.
|
|
40
|
+
* `null`, booleans, and empty strings create no slot, and the message is
|
|
41
|
+
* labelled by the translated sender fallback; any other content that renders
|
|
42
|
+
* nothing collapses its slot and falls back to the same label.
|
|
34
43
|
* Use when the first child is raw content (not a bubble).
|
|
35
44
|
* If the first child is a ChatMessageBubble, put the name on the
|
|
36
45
|
* bubble's `name` prop instead — it aligns with the bubble's padding.
|
|
@@ -38,6 +47,8 @@ export interface ChatMessageProps extends BaseProps<HTMLElement> {
|
|
|
38
47
|
name?: ReactNode;
|
|
39
48
|
/**
|
|
40
49
|
* Metadata rendered below the message body.
|
|
50
|
+
* `null`, booleans, and empty strings create no slot; any other content that
|
|
51
|
+
* renders nothing collapses its slot.
|
|
41
52
|
* Use when the last child is raw content (not a bubble).
|
|
42
53
|
* If the last child is a ChatMessageBubble, put metadata on the
|
|
43
54
|
* bubble's `metadata` prop instead — it aligns with the bubble's padding.
|