@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
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useHoverCard.ts
|
|
7
7
|
* @input Uses useLayer, useTouchTrigger, React hooks
|
|
8
|
-
* @output Exports useHoverCard hook for hover/focus/tap
|
|
8
|
+
* @output Exports useHoverCard hook with stable trigger refs for hover/focus/tap layers
|
|
9
9
|
* @position Layer hook; builds on useLayer for hover card behavior
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update:
|
|
@@ -99,6 +99,21 @@ export function useHoverCard(options = {}) {
|
|
|
99
99
|
onShow,
|
|
100
100
|
onHide
|
|
101
101
|
});
|
|
102
|
+
// Destructure the layer and touch objects once: both are rebuilt every
|
|
103
|
+
// render, but their members are stable. Depending on the members instead of
|
|
104
|
+
// the enclosing objects keeps the refs below identity-stable across
|
|
105
|
+
// unchanged rerenders, so React never detaches and re-attaches the trigger
|
|
106
|
+
// (and never rewrites the trigger's `anchor-name`) while the card streams
|
|
107
|
+
// alongside it.
|
|
108
|
+
const {
|
|
109
|
+
ref: layerRef,
|
|
110
|
+
anchorId: layerAnchorId,
|
|
111
|
+
show: showLayer,
|
|
112
|
+
hide: hideLayer,
|
|
113
|
+
isOpen: isLayerOpen,
|
|
114
|
+
id: layerId,
|
|
115
|
+
render: renderLayer
|
|
116
|
+
} = layer;
|
|
102
117
|
const popoverXstyle = styles.container;
|
|
103
118
|
const showTimeoutRef = useRef(null);
|
|
104
119
|
const hideTimeoutRef = useRef(null);
|
|
@@ -123,19 +138,25 @@ export function useHoverCard(options = {}) {
|
|
|
123
138
|
// passing across the trigger, and a tap is never that.
|
|
124
139
|
const showNow = useCallback(() => {
|
|
125
140
|
clearTimeouts();
|
|
126
|
-
|
|
127
|
-
}, [clearTimeouts,
|
|
141
|
+
showLayer();
|
|
142
|
+
}, [clearTimeouts, showLayer]);
|
|
128
143
|
const hideNow = useCallback(() => {
|
|
129
144
|
clearTimeouts();
|
|
130
145
|
isHoveringContentRef.current = false;
|
|
131
|
-
|
|
132
|
-
}, [clearTimeouts,
|
|
133
|
-
const
|
|
146
|
+
hideLayer();
|
|
147
|
+
}, [clearTimeouts, hideLayer]);
|
|
148
|
+
const {
|
|
149
|
+
isTouchPointerRef,
|
|
150
|
+
isTouchInteraction,
|
|
151
|
+
handlePointerEnter,
|
|
152
|
+
handlePointerDown: handleTouchPointerDown,
|
|
153
|
+
clearTapOpen
|
|
154
|
+
} = useTouchTrigger({
|
|
134
155
|
touchTrigger,
|
|
135
156
|
isEnabled,
|
|
136
157
|
isControlled: isOpen !== undefined,
|
|
137
|
-
isOpen:
|
|
138
|
-
layerId:
|
|
158
|
+
isOpen: isLayerOpen,
|
|
159
|
+
layerId: layerId,
|
|
139
160
|
triggerRef,
|
|
140
161
|
show: showNow,
|
|
141
162
|
hide: hideNow
|
|
@@ -148,9 +169,9 @@ export function useHoverCard(options = {}) {
|
|
|
148
169
|
}
|
|
149
170
|
clearTimeouts();
|
|
150
171
|
showTimeoutRef.current = setTimeout(() => {
|
|
151
|
-
|
|
172
|
+
showLayer();
|
|
152
173
|
}, delay);
|
|
153
|
-
}, [isEnabled, isOpen, clearTimeouts,
|
|
174
|
+
}, [isEnabled, isOpen, clearTimeouts, showLayer, delay]);
|
|
154
175
|
|
|
155
176
|
// Schedule hide with delay (suppressed when isOpen is true)
|
|
156
177
|
const scheduleHide = useCallback(() => {
|
|
@@ -161,34 +182,34 @@ export function useHoverCard(options = {}) {
|
|
|
161
182
|
hideTimeoutRef.current = setTimeout(() => {
|
|
162
183
|
// Don't hide if hovering content
|
|
163
184
|
if (!isHoveringContentRef.current) {
|
|
164
|
-
|
|
185
|
+
hideLayer();
|
|
165
186
|
}
|
|
166
187
|
}, hideDelay);
|
|
167
|
-
}, [isOpen, clearTimeouts,
|
|
188
|
+
}, [isOpen, clearTimeouts, hideLayer, hideDelay]);
|
|
168
189
|
|
|
169
190
|
// Event handlers
|
|
170
191
|
const handleMouseEnter = useCallback(() => {
|
|
171
192
|
// A tap synthesizes mouseenter. On touch the tap path owns the decision,
|
|
172
193
|
// so hover must not also fire — without this a hover card opens on every
|
|
173
194
|
// tap of its trigger and has nothing to close it.
|
|
174
|
-
if (
|
|
195
|
+
if (isTouchPointerRef.current) {
|
|
175
196
|
return;
|
|
176
197
|
}
|
|
177
198
|
scheduleShow();
|
|
178
|
-
}, [
|
|
199
|
+
}, [isTouchPointerRef, scheduleShow]);
|
|
179
200
|
const handleMouseLeave = useCallback(() => {
|
|
180
201
|
// On touch the synthesized mouseleave arrives with the next tap elsewhere,
|
|
181
202
|
// which the outside-tap dismissal already handles.
|
|
182
|
-
if (
|
|
203
|
+
if (isTouchPointerRef.current) {
|
|
183
204
|
return;
|
|
184
205
|
}
|
|
185
206
|
scheduleHide();
|
|
186
|
-
}, [
|
|
207
|
+
}, [isTouchPointerRef, scheduleHide]);
|
|
187
208
|
|
|
188
209
|
// Tap-to-open on touch; on a mouse this does nothing and hover still rules.
|
|
189
210
|
const handlePointerDown = useCallback(event => {
|
|
190
|
-
|
|
191
|
-
}, [
|
|
211
|
+
handleTouchPointerDown(event);
|
|
212
|
+
}, [handleTouchPointerDown]);
|
|
192
213
|
const handleFocusIn = useCallback(() => {
|
|
193
214
|
if (!isEnabled) {
|
|
194
215
|
return;
|
|
@@ -196,7 +217,7 @@ export function useHoverCard(options = {}) {
|
|
|
196
217
|
// A tap focuses the trigger it activates. Opening on that focus would
|
|
197
218
|
// reinstate exactly the behavior the touch path just decided against —
|
|
198
219
|
// and on an action trigger it covers the thing the user tapped.
|
|
199
|
-
if (
|
|
220
|
+
if (isTouchInteraction()) {
|
|
200
221
|
return;
|
|
201
222
|
}
|
|
202
223
|
// Skip showing if we're in the middle of an Escape dismiss
|
|
@@ -205,18 +226,18 @@ export function useHoverCard(options = {}) {
|
|
|
205
226
|
return;
|
|
206
227
|
}
|
|
207
228
|
clearTimeouts();
|
|
208
|
-
|
|
209
|
-
}, [isEnabled,
|
|
229
|
+
showLayer();
|
|
230
|
+
}, [isEnabled, isTouchInteraction, clearTimeouts, showLayer]);
|
|
210
231
|
const handleFocusOut = useCallback(e => {
|
|
211
232
|
// Check if focus is moving to the hover card content
|
|
212
233
|
const relatedTarget = e.relatedTarget;
|
|
213
|
-
const popoverElement = document.getElementById(
|
|
234
|
+
const popoverElement = document.getElementById(layerId);
|
|
214
235
|
if (popoverElement?.contains(relatedTarget)) {
|
|
215
236
|
// Focus moving into hover card, keep it open
|
|
216
237
|
return;
|
|
217
238
|
}
|
|
218
239
|
scheduleHide();
|
|
219
|
-
}, [
|
|
240
|
+
}, [layerId, scheduleHide]);
|
|
220
241
|
|
|
221
242
|
// Escape dismissal (WCAG 1.4.13) goes through the shared layer stack: a
|
|
222
243
|
// visible card is the top-most layer, so it takes the press and consumes it.
|
|
@@ -239,7 +260,7 @@ export function useHoverCard(options = {}) {
|
|
|
239
260
|
// presence is answered from the DOM at press time instead of from state.
|
|
240
261
|
isActive: true,
|
|
241
262
|
isPresent: () => {
|
|
242
|
-
const el = typeof document === 'undefined' ? null : document.getElementById(
|
|
263
|
+
const el = typeof document === 'undefined' ? null : document.getElementById(layerId);
|
|
243
264
|
if (el == null) {
|
|
244
265
|
return false;
|
|
245
266
|
}
|
|
@@ -248,12 +269,12 @@ export function useHoverCard(options = {}) {
|
|
|
248
269
|
} catch {
|
|
249
270
|
// Browsers without the Popover API (and some test environments) cannot
|
|
250
271
|
// answer the selector; fall back to the hook's own state.
|
|
251
|
-
return
|
|
272
|
+
return isLayerOpen;
|
|
252
273
|
}
|
|
253
274
|
},
|
|
254
275
|
onDismiss: () => {
|
|
255
276
|
clearTimeouts();
|
|
256
|
-
|
|
277
|
+
clearTapOpen();
|
|
257
278
|
// Controlled: report and stop. The close — and the focus restore that
|
|
258
279
|
// goes with it — happens in the controlled effect if and when the
|
|
259
280
|
// consumer flips `isOpen`.
|
|
@@ -268,9 +289,9 @@ export function useHoverCard(options = {}) {
|
|
|
268
289
|
// guard unconditionally would swallow their next focus on the trigger,
|
|
269
290
|
// because a focus() on the already-focused trigger fires no focusin to
|
|
270
291
|
// clear it.
|
|
271
|
-
const card = typeof document === 'undefined' ? null : document.getElementById(
|
|
292
|
+
const card = typeof document === 'undefined' ? null : document.getElementById(layerId);
|
|
272
293
|
const hadFocus = card?.contains(document.activeElement) ?? false;
|
|
273
|
-
|
|
294
|
+
hideLayer();
|
|
274
295
|
if (hadFocus) {
|
|
275
296
|
isEscapeDismissingRef.current = true;
|
|
276
297
|
triggerRef.current?.focus();
|
|
@@ -279,9 +300,6 @@ export function useHoverCard(options = {}) {
|
|
|
279
300
|
});
|
|
280
301
|
|
|
281
302
|
// Interaction ref that handles event listeners only
|
|
282
|
-
const {
|
|
283
|
-
handlePointerEnter
|
|
284
|
-
} = touch;
|
|
285
303
|
const interactionRef = useCallback(el => {
|
|
286
304
|
// Cleanup previous element
|
|
287
305
|
if (triggerRef.current) {
|
|
@@ -313,9 +331,9 @@ export function useHoverCard(options = {}) {
|
|
|
313
331
|
|
|
314
332
|
// Combined ref - shorthand for calling both positionRef and interactionRef
|
|
315
333
|
const ref = useCallback(el => {
|
|
316
|
-
|
|
334
|
+
layerRef(el);
|
|
317
335
|
interactionRef(el);
|
|
318
|
-
}, [
|
|
336
|
+
}, [layerRef, interactionRef]);
|
|
319
337
|
|
|
320
338
|
// Cleanup on unmount
|
|
321
339
|
useEffect(() => {
|
|
@@ -327,7 +345,7 @@ export function useHoverCard(options = {}) {
|
|
|
327
345
|
// Show on mount when isDefaultOpen is true
|
|
328
346
|
useEffect(() => {
|
|
329
347
|
if (isDefaultOpen) {
|
|
330
|
-
|
|
348
|
+
showLayer();
|
|
331
349
|
}
|
|
332
350
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- intentionally only on mount
|
|
333
351
|
}, []);
|
|
@@ -339,21 +357,21 @@ export function useHoverCard(options = {}) {
|
|
|
339
357
|
}
|
|
340
358
|
if (isOpen) {
|
|
341
359
|
clearTimeouts();
|
|
342
|
-
|
|
360
|
+
showLayer();
|
|
343
361
|
} else {
|
|
344
362
|
clearTimeouts();
|
|
345
363
|
// A consumer closing the card while it holds focus would strand focus on
|
|
346
364
|
// <body>. Arming the re-show guard is what keeps the refocus from
|
|
347
365
|
// reopening the card through `handleFocusIn`, which shows on any focusin.
|
|
348
|
-
const card = typeof document === 'undefined' ? null : document.getElementById(
|
|
366
|
+
const card = typeof document === 'undefined' ? null : document.getElementById(layerId);
|
|
349
367
|
const hadFocus = card?.contains(document.activeElement) ?? false;
|
|
350
|
-
|
|
368
|
+
hideLayer();
|
|
351
369
|
if (hadFocus) {
|
|
352
370
|
isEscapeDismissingRef.current = true;
|
|
353
371
|
triggerRef.current?.focus();
|
|
354
372
|
}
|
|
355
373
|
}
|
|
356
|
-
}, [isOpen, clearTimeouts,
|
|
374
|
+
}, [isOpen, clearTimeouts, showLayer, hideLayer, layerId]);
|
|
357
375
|
|
|
358
376
|
// Render function that wraps layer.render with hover card behavior
|
|
359
377
|
const renderHoverCard = useCallback((children, props) => {
|
|
@@ -379,21 +397,21 @@ export function useHoverCard(options = {}) {
|
|
|
379
397
|
// so rich HoverCard content can use block-safe markup.
|
|
380
398
|
as: 'div'
|
|
381
399
|
};
|
|
382
|
-
return
|
|
400
|
+
return renderLayer(/*#__PURE__*/_jsx("div", {
|
|
383
401
|
...{
|
|
384
402
|
className: "x1lliihq x1vlblms xvmdzux x126nfab x1t818jl"
|
|
385
403
|
},
|
|
386
404
|
onMouseEnter: () => {
|
|
387
405
|
// Touch synthesizes these over the card too; letting a tap inside
|
|
388
406
|
// register as "hovering content" would block every later hide.
|
|
389
|
-
if (
|
|
407
|
+
if (isTouchPointerRef.current) {
|
|
390
408
|
return;
|
|
391
409
|
}
|
|
392
410
|
isHoveringContentRef.current = true;
|
|
393
411
|
clearTimeouts();
|
|
394
412
|
},
|
|
395
413
|
onMouseLeave: () => {
|
|
396
|
-
if (
|
|
414
|
+
if (isTouchPointerRef.current) {
|
|
397
415
|
return;
|
|
398
416
|
}
|
|
399
417
|
isHoveringContentRef.current = false;
|
|
@@ -419,17 +437,17 @@ export function useHoverCard(options = {}) {
|
|
|
419
437
|
},
|
|
420
438
|
children: children
|
|
421
439
|
}), renderProps);
|
|
422
|
-
}, [
|
|
440
|
+
}, [renderLayer, placement, alignment, label, clearTimeouts, scheduleHide, popoverXstyle, isTouchPointerRef]);
|
|
423
441
|
return {
|
|
424
442
|
ref,
|
|
425
|
-
positionRef:
|
|
443
|
+
positionRef: layerRef,
|
|
426
444
|
interactionRef,
|
|
427
|
-
anchorId:
|
|
428
|
-
id:
|
|
429
|
-
describedBy:
|
|
430
|
-
isOpen:
|
|
445
|
+
anchorId: layerAnchorId,
|
|
446
|
+
id: layerId,
|
|
447
|
+
describedBy: layerId,
|
|
448
|
+
isOpen: isLayerOpen,
|
|
431
449
|
renderHoverCard,
|
|
432
|
-
show:
|
|
433
|
-
hide:
|
|
450
|
+
show: showLayer,
|
|
451
|
+
hide: hideLayer
|
|
434
452
|
};
|
|
435
453
|
}
|
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
* @output Exports InputGroup component with group label/description ARIA wiring
|
|
5
5
|
* @position Groups input with prefix/suffix addons; consumed by index.ts
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* to remove their own border/radius so the group container provides
|
|
10
|
-
* the unified border treatment.
|
|
7
|
+
* Compatible input children consume InputGroup context to remove competing
|
|
8
|
+
* border/radius geometry. Button addons consume it to join the same outer shape.
|
|
11
9
|
*
|
|
12
10
|
* SYNC: When modified, update these files to stay in sync:
|
|
13
11
|
* - /packages/core/src/InputGroup/InputGroup.doc.mjs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputGroup.d.ts","sourceRoot":"","sources":["../../src/InputGroup/InputGroup.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"InputGroup.d.ts","sourceRoot":"","sources":["../../src/InputGroup/InputGroup.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAiB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGrD,OAAO,EAAQ,KAAK,WAAW,EAAC,MAAM,UAAU,CAAC;AAGjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAI5C,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AA0BhD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,CACX;IACC,mDAAmD;IACnD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IAEtB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,YAAY,EACZ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,eAAe,+BAwEjB;yBAzFe,UAAU"}
|
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
* @output Exports InputGroup component with group label/description ARIA wiring
|
|
9
9
|
* @position Groups input with prefix/suffix addons; consumed by index.ts
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* to remove their own border/radius so the group container provides
|
|
14
|
-
* the unified border treatment.
|
|
11
|
+
* Compatible input children consume InputGroup context to remove competing
|
|
12
|
+
* border/radius geometry. Button addons consume it to join the same outer shape.
|
|
15
13
|
*
|
|
16
14
|
* SYNC: When modified, update these files to stay in sync:
|
|
17
15
|
* - /packages/core/src/InputGroup/InputGroup.doc.mjs
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file groupStyles.ts
|
|
3
3
|
* @input Uses StyleX, theme tokens, and layer-aware group end-cap selectors
|
|
4
|
-
* @output Exports shared group-aware styles for
|
|
5
|
-
* @position Shared styles consumed by InputGroup-compatible controls
|
|
4
|
+
* @output Exports shared group-aware styles for InputGroup children
|
|
5
|
+
* @position Shared styles consumed by InputGroup-compatible controls and addons
|
|
6
6
|
*/
|
|
7
7
|
import * as stylex from '@stylexjs/stylex';
|
|
8
8
|
export declare const groupStyles: Readonly<{
|
|
9
|
+
readonly buttonAddon: Readonly<{
|
|
10
|
+
readonly borderStartStartRadius: stylex.StyleXClassNameFor<"borderStartStartRadius", 0 | null>;
|
|
11
|
+
readonly borderEndStartRadius: stylex.StyleXClassNameFor<"borderEndStartRadius", 0 | null>;
|
|
12
|
+
readonly borderStartEndRadius: stylex.StyleXClassNameFor<"borderStartEndRadius", 0 | null>;
|
|
13
|
+
readonly borderEndEndRadius: stylex.StyleXClassNameFor<"borderEndEndRadius", 0 | null>;
|
|
14
|
+
readonly height: stylex.StyleXClassNameFor<"height", "100%" | null>;
|
|
15
|
+
readonly zIndex: stylex.StyleXClassNameFor<"zIndex", 2 | null>;
|
|
16
|
+
}>;
|
|
9
17
|
readonly inGroup: Readonly<{
|
|
10
18
|
readonly flex: stylex.StyleXClassNameFor<"flex", 1>;
|
|
11
19
|
readonly minWidth: stylex.StyleXClassNameFor<"minWidth", 0>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupStyles.d.ts","sourceRoot":"","sources":["../../src/InputGroup/groupStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"groupStyles.d.ts","sourceRoot":"","sources":["../../src/InputGroup/groupStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAmB3C,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;EAwDtB,CAAC"}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file groupStyles.ts
|
|
5
5
|
* @input Uses StyleX, theme tokens, and layer-aware group end-cap selectors
|
|
6
|
-
* @output Exports shared group-aware styles for
|
|
7
|
-
* @position Shared styles consumed by InputGroup-compatible controls
|
|
6
|
+
* @output Exports shared group-aware styles for InputGroup children
|
|
7
|
+
* @position Shared styles consumed by InputGroup-compatible controls and addons
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import * as stylex from '@stylexjs/stylex';
|
|
@@ -15,7 +15,24 @@ import { radiusVars, borderVars } from "../theme/tokens.stylex.js";
|
|
|
15
15
|
// than another control. Popovers, inert markers, and native dialog surfaces
|
|
16
16
|
// are not visual group members; skip them when finding the trailing edge.
|
|
17
17
|
const IS_LAST_ITEM = ':not(:has(~ *:not([popover]):not(template):not(dialog)))';
|
|
18
|
+
|
|
19
|
+
// Button consumes InputGroup context anywhere below the group, including buttons
|
|
20
|
+
// inside an input's own implementation. Keep the visual adaptation on direct
|
|
21
|
+
// children so internal clear, calendar, and disclosure actions stay unchanged.
|
|
22
|
+
const DIRECT_INPUT_GROUP_ADDON = ':where(.astryx-input-group > *)';
|
|
23
|
+
const DIRECT_INPUT_GROUP_ADDON_FOCUS_VISIBLE = ':where(.astryx-input-group > *):focus-visible';
|
|
24
|
+
const DIRECT_INPUT_GROUP_ADDON_NOT_FIRST = ':where(.astryx-input-group > *):not(:first-child)';
|
|
25
|
+
const DIRECT_INPUT_GROUP_ADDON_WITH_MEMBER_AFTER = ':where(.astryx-input-group > *):has(~ *:not([popover]):not(template):not(dialog))';
|
|
18
26
|
export const groupStyles = {
|
|
27
|
+
buttonAddon: {
|
|
28
|
+
krdFHd: "x1epqg88",
|
|
29
|
+
kVL7Gh: "xf2wquc",
|
|
30
|
+
kfmiAY: "x2dar1b",
|
|
31
|
+
kT0f0o: "x1tgb0ru",
|
|
32
|
+
kZKoxP: "x1vonza8",
|
|
33
|
+
kY2c9j: "x1qf1n5z",
|
|
34
|
+
$$css: true
|
|
35
|
+
},
|
|
19
36
|
inGroup: {
|
|
20
37
|
kUk6DE: "x98rzlu",
|
|
21
38
|
k7Eaqz: "xeuugli",
|
|
@@ -66,16 +66,16 @@ export interface UseLayerDismissalReturn {
|
|
|
66
66
|
*
|
|
67
67
|
* The layer does NOT attach a key listener — the stack owns one listener and
|
|
68
68
|
* routes each Escape press to the top-most REGISTERED layer, so one press
|
|
69
|
-
* dismisses exactly one of them. Dialog (and what is built on it
|
|
70
|
-
* the menus built on it,
|
|
71
|
-
* BottomSheetSwitcher and lab's
|
|
69
|
+
* dismisses exactly one of them. Dialog (and what is built on it, including
|
|
70
|
+
* CommandPalette), Popover and the menus built on it, ContextMenu, Tooltip,
|
|
71
|
+
* HoverCard, Lightbox, MobileNav, BottomSheet, BottomSheetSwitcher and lab's
|
|
72
|
+
* `Drawer` register today.
|
|
72
73
|
*
|
|
73
|
-
* `
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* fix.
|
|
74
|
+
* `DropdownMenuSubMenu` and `PowerSearchEditPopover` still run their own Escape
|
|
75
|
+
* listeners. They stay safe next to the stack only because each claims the press
|
|
76
|
+
* at element level, and the stack stands down on an already-`defaultPrevented`
|
|
77
|
+
* press — but a registered layer opened inside one of them does not get the
|
|
78
|
+
* press. Migrating them is the fix.
|
|
79
79
|
*
|
|
80
80
|
* Wrap the layer's own content in `LayerDepthProvider` so anything opened from
|
|
81
81
|
* inside it registers as nested.
|
|
@@ -23,16 +23,16 @@ import { isTextComposing, isTopmostLayer, registerLayer } from "./layerStack.js"
|
|
|
23
23
|
*
|
|
24
24
|
* The layer does NOT attach a key listener — the stack owns one listener and
|
|
25
25
|
* routes each Escape press to the top-most REGISTERED layer, so one press
|
|
26
|
-
* dismisses exactly one of them. Dialog (and what is built on it
|
|
27
|
-
* the menus built on it,
|
|
28
|
-
* BottomSheetSwitcher and lab's
|
|
26
|
+
* dismisses exactly one of them. Dialog (and what is built on it, including
|
|
27
|
+
* CommandPalette), Popover and the menus built on it, ContextMenu, Tooltip,
|
|
28
|
+
* HoverCard, Lightbox, MobileNav, BottomSheet, BottomSheetSwitcher and lab's
|
|
29
|
+
* `Drawer` register today.
|
|
29
30
|
*
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* fix.
|
|
31
|
+
* `DropdownMenuSubMenu` and `PowerSearchEditPopover` still run their own Escape
|
|
32
|
+
* listeners. They stay safe next to the stack only because each claims the press
|
|
33
|
+
* at element level, and the stack stands down on an already-`defaultPrevented`
|
|
34
|
+
* press — but a registered layer opened inside one of them does not get the
|
|
35
|
+
* press. Migrating them is the fix.
|
|
36
36
|
*
|
|
37
37
|
* Wrap the layer's own content in `LayerDepthProvider` so anything opened from
|
|
38
38
|
* inside it registers as nested.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
14
14
|
import "../theme/tokens.stylex.js";
|
|
15
15
|
import { colorVars, spacingVars, radiusVars, typeScaleVars, typographyVars, fontWeightVars, borderVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
|
|
16
16
|
import { CodeBlock, Code } from "../CodeBlock/index.js";
|
|
17
|
+
import { parseFenceLanguage } from "../CodeBlock/tokenizer.js";
|
|
17
18
|
import { CheckboxList } from "../CheckboxList/CheckboxList.js";
|
|
18
19
|
import { CheckboxListItem } from "../CheckboxList/CheckboxListItem.js";
|
|
19
20
|
import { Blockquote } from "../Blockquote/Blockquote.js";
|
|
@@ -1009,15 +1010,29 @@ listDepth = 0) {
|
|
|
1009
1010
|
{
|
|
1010
1011
|
// Track codeblock content in cursor for accurate character counting
|
|
1011
1012
|
cursor.offset += node.value.length;
|
|
1012
|
-
|
|
1013
|
+
// `diff-<lang>` fences are the diff layer over <lang>; `diff` is the
|
|
1014
|
+
// layer over plaintext. The legacy language is the info
|
|
1015
|
+
// string's leading word characters, which stops at the hyphen, so the
|
|
1016
|
+
// diff mapping reads the whole first word and then applies the same
|
|
1017
|
+
// word rule to the language it names.
|
|
1018
|
+
const legacyLanguage = getMarkdownAstLegacyCodeLanguage(node) ?? 'plaintext';
|
|
1019
|
+
const fence = parseFenceLanguage(node.lang ?? legacyLanguage);
|
|
1020
|
+
const isDiff = fence.isDiff;
|
|
1021
|
+
// The language under the diff layer; the default CodeBlock renders it.
|
|
1022
|
+
const diffLanguage = isDiff ? fence.language.match(/^\w*/)?.[0] || 'plaintext' : undefined;
|
|
1023
|
+
const language = diffLanguage ?? legacyLanguage;
|
|
1013
1024
|
// A semantic-fence proposal claims its fence before the host's code
|
|
1014
1025
|
// renderer (spec:AST-036 FR17). The host renderer, or the default Code
|
|
1015
1026
|
// block without one, draws every unclaimed fence and is the fallback
|
|
1016
1027
|
// when the claiming renderer is absent, declines, throws, or suspends.
|
|
1017
1028
|
const CodeBlockComp = components?.code;
|
|
1018
1029
|
const fallback = CodeBlockComp ? /*#__PURE__*/_jsx(CodeBlockComp, {
|
|
1019
|
-
code: node.value
|
|
1020
|
-
|
|
1030
|
+
code: node.value
|
|
1031
|
+
// A supplied renderer's contract is unchanged: it keeps receiving
|
|
1032
|
+
// the leading word characters (`diff` for a `diff-tsx` fence, as
|
|
1033
|
+
// today) and nothing new; only the default path maps the layer.
|
|
1034
|
+
,
|
|
1035
|
+
language: legacyLanguage,
|
|
1021
1036
|
...lineProp
|
|
1022
1037
|
}, index) : /*#__PURE__*/_jsx("div", {
|
|
1023
1038
|
...mergeProps(themeProps('markdown-codeblock', {
|
|
@@ -1027,7 +1042,13 @@ listDepth = 0) {
|
|
|
1027
1042
|
children: /*#__PURE__*/_jsx(CodeBlock, {
|
|
1028
1043
|
code: node.value,
|
|
1029
1044
|
language: language,
|
|
1030
|
-
|
|
1045
|
+
isDiff: isDiff,
|
|
1046
|
+
isCollapsible: true
|
|
1047
|
+
// Long lines wrap rather than scroll sideways, as they do in
|
|
1048
|
+
// RichText, so a reader sees whole lines and the read/edit switch
|
|
1049
|
+
// moves no block (spec:AST-061 FR5, DEC-9).
|
|
1050
|
+
,
|
|
1051
|
+
isWrapped: true,
|
|
1031
1052
|
xstyle: [contentWidthValue != null ? dynamicStyles.blockWidth(contentWidthValue) : undefined, blockAlignStyle]
|
|
1032
1053
|
})
|
|
1033
1054
|
}, index);
|
|
@@ -21,6 +21,13 @@
|
|
|
21
21
|
* closes. The native `cancel` event still handles the dismissals the browser
|
|
22
22
|
* starts itself, such as the Android back gesture.
|
|
23
23
|
*
|
|
24
|
+
* Focus RESTORATION is not delegated to the browser. The drawer captures the
|
|
25
|
+
* element that opened it and refocuses it once the native dialog has closed,
|
|
26
|
+
* mirroring Dialog: the implicit `<dialog>` restore has been observed dropping
|
|
27
|
+
* focus to `<body>`. The close itself is deferred past the slide-out, and the
|
|
28
|
+
* restore has to follow it. Until close() runs the rest of the document is
|
|
29
|
+
* inert and focus() on the opener is silently dropped.
|
|
30
|
+
*
|
|
24
31
|
* SYNC: When modified, update these files to stay in sync:
|
|
25
32
|
* - /packages/core/src/MobileNav/index.ts (exports if types change)
|
|
26
33
|
* - /packages/core/src/Layer/useLayerDismissal.ts (dismissal stack)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileNav.d.ts","sourceRoot":"","sources":["../../src/MobileNav/MobileNav.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"MobileNav.d.ts","sourceRoot":"","sources":["../../src/MobileNav/MobileNav.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAOL,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAwBf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiM5C;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBpE;AA+DD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,EACxB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EACR,MAAM,EACN,KAAW,EACX,IAAa,EACb,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,+BAmPhB;yBAlQe,SAAS"}
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
* closes. The native `cancel` event still handles the dismissals the browser
|
|
26
26
|
* starts itself, such as the Android back gesture.
|
|
27
27
|
*
|
|
28
|
+
* Focus RESTORATION is not delegated to the browser. The drawer captures the
|
|
29
|
+
* element that opened it and refocuses it once the native dialog has closed,
|
|
30
|
+
* mirroring Dialog: the implicit `<dialog>` restore has been observed dropping
|
|
31
|
+
* focus to `<body>`. The close itself is deferred past the slide-out, and the
|
|
32
|
+
* restore has to follow it. Until close() runs the rest of the document is
|
|
33
|
+
* inert and focus() on the opener is silently dropped.
|
|
34
|
+
*
|
|
28
35
|
* SYNC: When modified, update these files to stay in sync:
|
|
29
36
|
* - /packages/core/src/MobileNav/index.ts (exports if types change)
|
|
30
37
|
* - /packages/core/src/Layer/useLayerDismissal.ts (dismissal stack)
|
|
@@ -206,6 +213,31 @@ function resolveCloseDelay(dialog) {
|
|
|
206
213
|
return hold <= 0 ? 0 : Math.min(cap, hold * CLOSE_WITHIN_HOLD);
|
|
207
214
|
}
|
|
208
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Close the native dialog, then return focus to the element that opened it.
|
|
218
|
+
*
|
|
219
|
+
* Browsers are supposed to restore focus themselves when a modal <dialog>
|
|
220
|
+
* closes, but that has been observed to fail (focus lands on <body>), so the
|
|
221
|
+
* drawer does it explicitly, as Dialog does. The order is load-bearing: while
|
|
222
|
+
* the modal dialog holds the top layer the rest of the document is inert and
|
|
223
|
+
* focus() on the opener is silently dropped. So the restore rides on the close
|
|
224
|
+
* itself, wherever that happens (the delayed timer, or the unmount teardown),
|
|
225
|
+
* not on the `isOpen` flip that only schedules it.
|
|
226
|
+
*
|
|
227
|
+
* Focus is left alone when there was no real opener (activeElement was <body>)
|
|
228
|
+
* or the opener has since left the DOM: focusing <body> would blur whatever a
|
|
229
|
+
* router moved focus to, and a detached node cannot take focus.
|
|
230
|
+
*/
|
|
231
|
+
function closeAndRestoreFocus(dialog, openerRef) {
|
|
232
|
+
dialog.close();
|
|
233
|
+
const opener = openerRef.current;
|
|
234
|
+
openerRef.current = null;
|
|
235
|
+
if (!opener || opener === document.body || !opener.isConnected) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
opener.focus();
|
|
239
|
+
}
|
|
240
|
+
|
|
209
241
|
// =============================================================================
|
|
210
242
|
// Types
|
|
211
243
|
// =============================================================================
|
|
@@ -273,6 +305,9 @@ export function MobileNav({
|
|
|
273
305
|
}), [onOpenChangeProp, appShellMobile]);
|
|
274
306
|
const dialogRef = useRef(null);
|
|
275
307
|
const closeTimeoutRef = useRef(null);
|
|
308
|
+
// Element that was focused when the drawer opened; focus goes back to it
|
|
309
|
+
// once the native dialog has closed (see closeAndRestoreFocus).
|
|
310
|
+
const triggerElementRef = useRef(null);
|
|
276
311
|
const gutterRef = useRef(null);
|
|
277
312
|
|
|
278
313
|
// Gives back the gutter held open in place of the hidden scrollbar.
|
|
@@ -322,6 +357,11 @@ export function MobileNav({
|
|
|
322
357
|
// and the gutter has to be measured while it is still there.
|
|
323
358
|
gutterRef.current ??= holdScrollbarGutter(document.documentElement);
|
|
324
359
|
if (!dialog.open) {
|
|
360
|
+
// Capture the opener before showModal() pulls focus into the top
|
|
361
|
+
// layer. Only on the transition into open: a reopen while the delayed
|
|
362
|
+
// close is still pending finds the dialog open, and must keep the
|
|
363
|
+
// original opener rather than whatever is focused inside the drawer.
|
|
364
|
+
triggerElementRef.current = document.activeElement;
|
|
325
365
|
dialog.showModal();
|
|
326
366
|
}
|
|
327
367
|
// Prevent background scrolling and iOS pull-to-refresh.
|
|
@@ -333,7 +373,7 @@ export function MobileNav({
|
|
|
333
373
|
document.documentElement.style.overflow = '';
|
|
334
374
|
releaseGutter();
|
|
335
375
|
closeTimeoutRef.current = setTimeout(() => {
|
|
336
|
-
dialog
|
|
376
|
+
closeAndRestoreFocus(dialog, triggerElementRef);
|
|
337
377
|
}, resolveCloseDelay(dialog));
|
|
338
378
|
}
|
|
339
379
|
return () => {
|
|
@@ -356,11 +396,14 @@ export function MobileNav({
|
|
|
356
396
|
// This must be a separate unmount-only effect: putting it in the open/close
|
|
357
397
|
// effect above would close the dialog on every isOpen flip and cut off the
|
|
358
398
|
// delayed slide-out close.
|
|
399
|
+
//
|
|
400
|
+
// Inside AppShell this teardown is the only close the drawer ever gets, so
|
|
401
|
+
// it is also where focus goes back to the toggle.
|
|
359
402
|
useEffect(() => {
|
|
360
403
|
const dialog = dialogRef.current;
|
|
361
404
|
return () => {
|
|
362
405
|
if (dialog?.open) {
|
|
363
|
-
dialog
|
|
406
|
+
closeAndRestoreFocus(dialog, triggerElementRef);
|
|
364
407
|
}
|
|
365
408
|
};
|
|
366
409
|
}, []);
|