@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
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Detects trigger characters (@ / etc.) typed inside a contentEditable,
|
|
12
12
|
* opens a popover at the cursor position with filtered items, handles
|
|
13
|
-
* keyboard navigation, and inserts tokens or text on selection.
|
|
13
|
+
* keyboard navigation, and inserts tokens or text on selection. Triggers
|
|
14
|
+
* opt into multi-word queries with hasMultiWordQuery; results apply only
|
|
15
|
+
* while their query is current (component:ChatComposerInput FR10–FR16).
|
|
14
16
|
*
|
|
15
17
|
* Reuses SearchSource from Typeahead for async/sync search with
|
|
16
18
|
* cancel() support and debounce.
|
|
@@ -38,7 +40,7 @@ import {
|
|
|
38
40
|
typeScaleVars,
|
|
39
41
|
typographyVars,
|
|
40
42
|
} from '../theme/tokens.stylex';
|
|
41
|
-
import {mergeProps, groupItems} from '../utils';
|
|
43
|
+
import {mergeProps, groupItems, isImeKeyEvent} from '../utils';
|
|
42
44
|
import type {SearchableItem} from '../Typeahead/types';
|
|
43
45
|
import {themeProps} from '../utils/themeProps';
|
|
44
46
|
import {useTranslator} from '../i18n';
|
|
@@ -55,6 +57,11 @@ export interface TriggerMenuState {
|
|
|
55
57
|
items: SearchableItem[];
|
|
56
58
|
highlightedIndex: number;
|
|
57
59
|
isLoading: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The last settled results were an unmatched multi-word query, so the menu
|
|
62
|
+
* is closed. It stays closed while a newer search for the same query runs.
|
|
63
|
+
*/
|
|
64
|
+
isHidden: boolean;
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
export interface UseTriggerMenuOptions {
|
|
@@ -74,7 +81,7 @@ export interface UseTriggerMenuReturn {
|
|
|
74
81
|
state: TriggerMenuState;
|
|
75
82
|
/** Call on every input event to check for trigger activation */
|
|
76
83
|
handleInput: () => void;
|
|
77
|
-
/** Call on keydown
|
|
84
|
+
/** Call on keydown — returns true if the event was consumed */
|
|
78
85
|
handleKeyDown: (e: React.KeyboardEvent) => boolean;
|
|
79
86
|
/** Render the trigger menu popover */
|
|
80
87
|
renderMenu: () => ReactNode;
|
|
@@ -169,6 +176,18 @@ const styles = stylex.create({
|
|
|
169
176
|
// Helpers
|
|
170
177
|
// =============================================================================
|
|
171
178
|
|
|
179
|
+
/** The text node holding a collapsed caret inside `editable`, if any. */
|
|
180
|
+
function getCaretTextNode(editable: HTMLDivElement): Node | null {
|
|
181
|
+
const selection = window.getSelection();
|
|
182
|
+
if (!selection || selection.rangeCount === 0) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const node = selection.getRangeAt(0).startContainer;
|
|
186
|
+
return node.nodeType === Node.TEXT_NODE && editable.contains(node)
|
|
187
|
+
? node
|
|
188
|
+
: null;
|
|
189
|
+
}
|
|
190
|
+
|
|
172
191
|
function getTextBeforeCursor(editable: HTMLDivElement): string | null {
|
|
173
192
|
const selection = window.getSelection();
|
|
174
193
|
if (!selection || selection.rangeCount === 0) {
|
|
@@ -191,6 +210,38 @@ function getTextBeforeCursor(editable: HTMLDivElement): string | null {
|
|
|
191
210
|
return null;
|
|
192
211
|
}
|
|
193
212
|
|
|
213
|
+
const MAX_MULTI_WORD_QUERY_LENGTH = 64;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* An unmatched multi-word query hides the menu instead of covering prose with
|
|
217
|
+
* an empty panel, unless the trigger supplies its own empty message.
|
|
218
|
+
*/
|
|
219
|
+
function isUnmatchedMultiWordQuery(
|
|
220
|
+
trigger: ChatComposerTrigger | null,
|
|
221
|
+
items: SearchableItem[],
|
|
222
|
+
isLoading: boolean,
|
|
223
|
+
): boolean {
|
|
224
|
+
return (
|
|
225
|
+
trigger?.hasMultiWordQuery === true &&
|
|
226
|
+
// `null` means "not given", exactly as `undefined` does.
|
|
227
|
+
trigger.emptySearchText == null &&
|
|
228
|
+
items.length === 0 &&
|
|
229
|
+
!isLoading
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function isTriggerBoundary(char: string | null): boolean {
|
|
234
|
+
return char === null || char === ' ' || char === '\t' || char === '\n';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Finds the trigger query the caret is in (component:ChatComposerInput FR10,
|
|
239
|
+
* FR11). A trigger character activates at the start of the text or after a
|
|
240
|
+
* space, tab, or line break. A single-token query ends at whitespace. A
|
|
241
|
+
* multi-word query ends at a line break, past the length bound, or where the
|
|
242
|
+
* same trigger's character starts a new query; another trigger's character
|
|
243
|
+
* inside it is ordinary text.
|
|
244
|
+
*/
|
|
194
245
|
function findActiveTrigger(
|
|
195
246
|
textBeforeCursor: string,
|
|
196
247
|
triggers: ChatComposerTrigger[],
|
|
@@ -199,25 +250,50 @@ function findActiveTrigger(
|
|
|
199
250
|
query: string;
|
|
200
251
|
triggerStart: number;
|
|
201
252
|
} | null {
|
|
202
|
-
|
|
253
|
+
let active: {trigger: ChatComposerTrigger; triggerStart: number} | null =
|
|
254
|
+
null;
|
|
255
|
+
|
|
256
|
+
for (let i = 0; i < textBeforeCursor.length; i++) {
|
|
203
257
|
const char = textBeforeCursor[i];
|
|
204
258
|
|
|
205
|
-
if (char === '
|
|
206
|
-
|
|
259
|
+
if (char === '\n') {
|
|
260
|
+
active = null;
|
|
261
|
+
continue;
|
|
207
262
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const prevChar = i > 0 ? textBeforeCursor[i - 1] : null;
|
|
212
|
-
if (prevChar === null || prevChar === ' ' || prevChar === '\n') {
|
|
213
|
-
const query = textBeforeCursor.slice(i + 1);
|
|
214
|
-
return {trigger, query, triggerStart: i};
|
|
215
|
-
}
|
|
263
|
+
if (active && !active.trigger.hasMultiWordQuery) {
|
|
264
|
+
if (char === ' ' || char === '\t') {
|
|
265
|
+
active = null;
|
|
216
266
|
}
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (active && i - active.triggerStart > MAX_MULTI_WORD_QUERY_LENGTH) {
|
|
270
|
+
active = null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!isTriggerBoundary(i > 0 ? textBeforeCursor[i - 1] : null)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const trigger = triggers.find(t => t.character === char);
|
|
277
|
+
if (!trigger) {
|
|
278
|
+
continue;
|
|
217
279
|
}
|
|
280
|
+
if (active && trigger.character !== active.trigger.character) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
active = {trigger, triggerStart: i};
|
|
218
284
|
}
|
|
219
285
|
|
|
220
|
-
|
|
286
|
+
if (!active) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
const query = textBeforeCursor.slice(active.triggerStart + 1);
|
|
290
|
+
if (
|
|
291
|
+
active.trigger.hasMultiWordQuery &&
|
|
292
|
+
query.length > MAX_MULTI_WORD_QUERY_LENGTH
|
|
293
|
+
) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
return {trigger: active.trigger, query, triggerStart: active.triggerStart};
|
|
221
297
|
}
|
|
222
298
|
|
|
223
299
|
function deleteTriggerText(
|
|
@@ -274,11 +350,25 @@ export function useTriggerMenu(
|
|
|
274
350
|
items: [],
|
|
275
351
|
highlightedIndex: 0,
|
|
276
352
|
isLoading: false,
|
|
353
|
+
isHidden: false,
|
|
277
354
|
});
|
|
278
355
|
|
|
279
356
|
const triggerStartRef = useRef<number>(-1);
|
|
280
357
|
const searchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
358
|
+
const searchRequestIdRef = useRef<number>(0);
|
|
359
|
+
const dismissedRef = useRef<{
|
|
360
|
+
character: string;
|
|
361
|
+
triggerStart: number;
|
|
362
|
+
dismissedQuery: string;
|
|
363
|
+
// The text the Escape dismissed. Replacing the draft from outside typing
|
|
364
|
+
// (a send button, a cleared value) replaces this node, which ends the
|
|
365
|
+
// dismissal without any extra bookkeeping.
|
|
366
|
+
textNode: Node | null;
|
|
367
|
+
} | null>(null);
|
|
281
368
|
const anchorSpanRef = useRef<HTMLSpanElement | null>(null);
|
|
369
|
+
// True while the popover is closed only because the query is unmatched; the
|
|
370
|
+
// trigger query itself is still active.
|
|
371
|
+
const isMenuSuppressedRef = useRef(false);
|
|
282
372
|
|
|
283
373
|
const removeAnchorSpan = useCallback(() => {
|
|
284
374
|
if (anchorSpanRef.current) {
|
|
@@ -289,6 +379,10 @@ export function useTriggerMenu(
|
|
|
289
379
|
|
|
290
380
|
const popover = usePopover({
|
|
291
381
|
onHide: useCallback(() => {
|
|
382
|
+
if (isMenuSuppressedRef.current) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
searchRequestIdRef.current++;
|
|
292
386
|
removeAnchorSpan();
|
|
293
387
|
setState(prev => ({
|
|
294
388
|
...prev,
|
|
@@ -298,6 +392,7 @@ export function useTriggerMenu(
|
|
|
298
392
|
items: [],
|
|
299
393
|
highlightedIndex: 0,
|
|
300
394
|
isLoading: false,
|
|
395
|
+
isHidden: false,
|
|
301
396
|
}));
|
|
302
397
|
}, [removeAnchorSpan]),
|
|
303
398
|
hasLightDismiss: true,
|
|
@@ -307,6 +402,7 @@ export function useTriggerMenu(
|
|
|
307
402
|
// the contenteditable composer, so a modal dialog wrapper is incorrect.
|
|
308
403
|
role: 'none',
|
|
309
404
|
});
|
|
405
|
+
const {show: showPopover, hide: hidePopover} = popover;
|
|
310
406
|
|
|
311
407
|
// Cleanup on unmount
|
|
312
408
|
useEffect(() => {
|
|
@@ -323,14 +419,29 @@ export function useTriggerMenu(
|
|
|
323
419
|
clearTimeout(searchTimeoutRef.current);
|
|
324
420
|
searchTimeoutRef.current = null;
|
|
325
421
|
}
|
|
422
|
+
searchRequestIdRef.current++;
|
|
326
423
|
// Cancel any in-flight search on the active trigger's searchSource
|
|
327
424
|
const trigger = state.activeTrigger;
|
|
328
425
|
if (trigger?.searchSource) {
|
|
329
426
|
trigger.searchSource.cancel?.();
|
|
330
427
|
}
|
|
331
428
|
removeAnchorSpan();
|
|
429
|
+
isMenuSuppressedRef.current = false;
|
|
430
|
+
// Ending the query also forgets an Escape on it; a send or clear must not
|
|
431
|
+
// leave the next message's mention at the same offset suppressed.
|
|
432
|
+
dismissedRef.current = null;
|
|
332
433
|
popover.hide();
|
|
333
434
|
triggerStartRef.current = -1;
|
|
435
|
+
setState(prev => ({
|
|
436
|
+
...prev,
|
|
437
|
+
isActive: false,
|
|
438
|
+
activeTrigger: null,
|
|
439
|
+
query: '',
|
|
440
|
+
items: [],
|
|
441
|
+
highlightedIndex: 0,
|
|
442
|
+
isLoading: false,
|
|
443
|
+
isHidden: false,
|
|
444
|
+
}));
|
|
334
445
|
}, [popover, state.activeTrigger, removeAnchorSpan]);
|
|
335
446
|
|
|
336
447
|
// Anchor the popover to the cursor position (not the entire input).
|
|
@@ -395,28 +506,69 @@ export function useTriggerMenu(
|
|
|
395
506
|
searchTimeoutRef.current = null;
|
|
396
507
|
}
|
|
397
508
|
|
|
509
|
+
const requestId = ++searchRequestIdRef.current;
|
|
510
|
+
// A result applies only while its request is the latest one and the
|
|
511
|
+
// caret is still inside the same trigger query. Submitting or clearing
|
|
512
|
+
// the editor ends the query without an input event, so check the DOM.
|
|
513
|
+
const isCurrent = () => {
|
|
514
|
+
if (requestId !== searchRequestIdRef.current) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
const editable = editableRef.current;
|
|
518
|
+
const textBefore = editable ? getTextBeforeCursor(editable) : null;
|
|
519
|
+
const found =
|
|
520
|
+
textBefore === null || !triggers
|
|
521
|
+
? null
|
|
522
|
+
: findActiveTrigger(textBefore, triggers);
|
|
523
|
+
if (
|
|
524
|
+
found?.trigger.character !== trigger.character ||
|
|
525
|
+
found.triggerStart !== triggerStartRef.current
|
|
526
|
+
) {
|
|
527
|
+
reset();
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
return true;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const applyResults = (items: SearchableItem[]) => {
|
|
534
|
+
const isHidden = isUnmatchedMultiWordQuery(trigger, items, false);
|
|
535
|
+
setState(prev => ({
|
|
536
|
+
...prev,
|
|
537
|
+
items,
|
|
538
|
+
highlightedIndex: items.length > 0 ? 0 : -1,
|
|
539
|
+
isLoading: false,
|
|
540
|
+
isHidden,
|
|
541
|
+
}));
|
|
542
|
+
// A hidden menu closes its popover, which also releases the popover's
|
|
543
|
+
// Escape and light-dismiss handling; matches reopen it at the caret.
|
|
544
|
+
if (isHidden && !isMenuSuppressedRef.current) {
|
|
545
|
+
isMenuSuppressedRef.current = true;
|
|
546
|
+
hidePopover();
|
|
547
|
+
} else if (!isHidden && isMenuSuppressedRef.current) {
|
|
548
|
+
isMenuSuppressedRef.current = false;
|
|
549
|
+
setAnchor();
|
|
550
|
+
showPopover();
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
|
|
398
554
|
const doSearch = () => {
|
|
399
555
|
if (trigger.searchSource) {
|
|
400
|
-
// Use SearchSource
|
|
556
|
+
// Use SearchSource — cancel previous, then search
|
|
401
557
|
trigger.searchSource.cancel?.();
|
|
402
558
|
setState(prev => ({...prev, isLoading: true}));
|
|
403
559
|
const result = trigger.searchSource.search(query);
|
|
404
560
|
Promise.resolve(result).then(
|
|
405
561
|
items => {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
isLoading: false,
|
|
411
|
-
}));
|
|
562
|
+
if (!isCurrent()) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
applyResults(items);
|
|
412
566
|
},
|
|
413
567
|
() => {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
isLoading: false,
|
|
419
|
-
}));
|
|
568
|
+
if (!isCurrent()) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
applyResults([]);
|
|
420
572
|
},
|
|
421
573
|
);
|
|
422
574
|
}
|
|
@@ -435,7 +587,15 @@ export function useTriggerMenu(
|
|
|
435
587
|
}
|
|
436
588
|
}
|
|
437
589
|
},
|
|
438
|
-
[
|
|
590
|
+
[
|
|
591
|
+
debounceMs,
|
|
592
|
+
editableRef,
|
|
593
|
+
triggers,
|
|
594
|
+
reset,
|
|
595
|
+
setAnchor,
|
|
596
|
+
hidePopover,
|
|
597
|
+
showPopover,
|
|
598
|
+
],
|
|
439
599
|
);
|
|
440
600
|
|
|
441
601
|
const selectItem = useCallback(
|
|
@@ -490,6 +650,7 @@ export function useTriggerMenu(
|
|
|
490
650
|
|
|
491
651
|
const textBefore = getTextBeforeCursor(editable);
|
|
492
652
|
if (textBefore === null) {
|
|
653
|
+
dismissedRef.current = null;
|
|
493
654
|
if (state.isActive) {
|
|
494
655
|
reset();
|
|
495
656
|
}
|
|
@@ -498,6 +659,7 @@ export function useTriggerMenu(
|
|
|
498
659
|
|
|
499
660
|
const found = findActiveTrigger(textBefore, triggers);
|
|
500
661
|
if (!found) {
|
|
662
|
+
dismissedRef.current = null;
|
|
501
663
|
if (state.isActive) {
|
|
502
664
|
reset();
|
|
503
665
|
}
|
|
@@ -506,20 +668,44 @@ export function useTriggerMenu(
|
|
|
506
668
|
|
|
507
669
|
const {trigger, query, triggerStart} = found;
|
|
508
670
|
|
|
509
|
-
|
|
671
|
+
// After Escape, keep the menu hidden while that same query keeps growing
|
|
672
|
+
const dismissed = dismissedRef.current;
|
|
673
|
+
if (
|
|
674
|
+
dismissed &&
|
|
675
|
+
dismissed.character === trigger.character &&
|
|
676
|
+
dismissed.triggerStart === triggerStart &&
|
|
677
|
+
dismissed.textNode !== null &&
|
|
678
|
+
dismissed.textNode.isConnected &&
|
|
679
|
+
dismissed.textNode === getCaretTextNode(editable)
|
|
680
|
+
) {
|
|
681
|
+
if (query.startsWith(dismissed.dismissedQuery)) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
dismissedRef.current = null;
|
|
685
|
+
} else {
|
|
686
|
+
dismissedRef.current = null;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (
|
|
690
|
+
!state.isActive ||
|
|
691
|
+
state.activeTrigger?.character !== trigger.character ||
|
|
692
|
+
triggerStartRef.current !== triggerStart
|
|
693
|
+
) {
|
|
510
694
|
triggerStartRef.current = triggerStart;
|
|
695
|
+
isMenuSuppressedRef.current = false;
|
|
511
696
|
setState(prev => ({
|
|
512
697
|
...prev,
|
|
513
698
|
isActive: true,
|
|
514
699
|
activeTrigger: trigger,
|
|
515
700
|
query,
|
|
516
701
|
highlightedIndex: 0,
|
|
702
|
+
isHidden: false,
|
|
517
703
|
}));
|
|
518
704
|
setAnchor();
|
|
519
705
|
searchItems(trigger, query);
|
|
520
706
|
popover.show();
|
|
521
707
|
} else if (state.query !== query) {
|
|
522
|
-
setState(prev => ({...prev, query}));
|
|
708
|
+
setState(prev => ({...prev, query, activeTrigger: trigger}));
|
|
523
709
|
searchItems(trigger, query);
|
|
524
710
|
}
|
|
525
711
|
}, [
|
|
@@ -534,9 +720,49 @@ export function useTriggerMenu(
|
|
|
534
720
|
popover,
|
|
535
721
|
]);
|
|
536
722
|
|
|
723
|
+
const isMenuVisible = state.isActive && !state.isHidden;
|
|
724
|
+
|
|
537
725
|
const handleKeyDown = useCallback(
|
|
538
726
|
(e: React.KeyboardEvent): boolean => {
|
|
539
|
-
|
|
727
|
+
// Never intercept IME composition keystrokes (e.g. Enter committing candidates)
|
|
728
|
+
if (isImeKeyEvent(e.nativeEvent)) {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// A hidden menu consumes nothing: arrows move the caret, Enter submits,
|
|
733
|
+
// and Escape reaches the surrounding surface.
|
|
734
|
+
if (!isMenuVisible) {
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
if (e.key === 'Escape') {
|
|
739
|
+
e.preventDefault();
|
|
740
|
+
const editable = editableRef.current;
|
|
741
|
+
const dismissed = state.activeTrigger
|
|
742
|
+
? {
|
|
743
|
+
character: state.activeTrigger.character,
|
|
744
|
+
triggerStart: triggerStartRef.current,
|
|
745
|
+
dismissedQuery: state.query,
|
|
746
|
+
textNode: editable ? getCaretTextNode(editable) : null,
|
|
747
|
+
}
|
|
748
|
+
: null;
|
|
749
|
+
reset();
|
|
750
|
+
// Remembered after reset, which clears it: the menu stays hidden while
|
|
751
|
+
// this same query keeps growing.
|
|
752
|
+
dismissedRef.current = dismissed;
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// A visible menu keeps the arrows even when it has nothing to pick (rows
|
|
757
|
+
// still loading, or the empty message), so they never recall history
|
|
758
|
+
// under an open panel. Enter and Tab pick only a settled row; otherwise
|
|
759
|
+
// they keep their editor meaning, so Enter sends the message as typed.
|
|
760
|
+
const hasPickableRows = !state.isLoading && state.items.length > 0;
|
|
761
|
+
if (!hasPickableRows && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
762
|
+
e.preventDefault();
|
|
763
|
+
return true;
|
|
764
|
+
}
|
|
765
|
+
if (!hasPickableRows) {
|
|
540
766
|
return false;
|
|
541
767
|
}
|
|
542
768
|
|
|
@@ -575,20 +801,18 @@ export function useTriggerMenu(
|
|
|
575
801
|
}
|
|
576
802
|
return false;
|
|
577
803
|
}
|
|
578
|
-
case 'Escape': {
|
|
579
|
-
e.preventDefault();
|
|
580
|
-
reset();
|
|
581
|
-
return true;
|
|
582
|
-
}
|
|
583
804
|
default:
|
|
584
805
|
return false;
|
|
585
806
|
}
|
|
586
807
|
},
|
|
587
808
|
[
|
|
588
|
-
|
|
809
|
+
isMenuVisible,
|
|
810
|
+
editableRef,
|
|
811
|
+
state.activeTrigger,
|
|
812
|
+
state.query,
|
|
813
|
+
state.isLoading,
|
|
589
814
|
state.highlightedIndex,
|
|
590
815
|
state.items,
|
|
591
|
-
popover.isOpen,
|
|
592
816
|
selectItem,
|
|
593
817
|
reset,
|
|
594
818
|
],
|
|
@@ -621,7 +845,7 @@ export function useTriggerMenu(
|
|
|
621
845
|
const hasTriggers = (triggers?.length ?? 0) > 0;
|
|
622
846
|
const ariaProps: UseTriggerMenuReturn['ariaProps'] = !hasTriggers
|
|
623
847
|
? {role: 'textbox', 'aria-multiline': 'true'}
|
|
624
|
-
:
|
|
848
|
+
: isMenuVisible
|
|
625
849
|
? {
|
|
626
850
|
role: 'combobox',
|
|
627
851
|
'aria-expanded': true as const,
|
|
@@ -639,9 +863,17 @@ export function useTriggerMenu(
|
|
|
639
863
|
};
|
|
640
864
|
|
|
641
865
|
const renderMenu = useCallback((): ReactNode => {
|
|
642
|
-
const
|
|
643
|
-
|
|
644
|
-
|
|
866
|
+
const activeTrigger = state.activeTrigger;
|
|
867
|
+
if (!activeTrigger) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
if (state.isHidden) {
|
|
872
|
+
return null;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
const emptyText = activeTrigger.emptySearchText ?? 'No results';
|
|
876
|
+
const loadingText = activeTrigger.loadingText ?? 'Searching\u2026';
|
|
645
877
|
|
|
646
878
|
let listContent: ReactNode;
|
|
647
879
|
if (state.isLoading) {
|
|
@@ -674,8 +906,8 @@ export function useTriggerMenu(
|
|
|
674
906
|
styles.item,
|
|
675
907
|
idx === state.highlightedIndex && styles.itemHighlighted,
|
|
676
908
|
)}>
|
|
677
|
-
{
|
|
678
|
-
|
|
909
|
+
{activeTrigger.renderItem ? (
|
|
910
|
+
activeTrigger.renderItem(item)
|
|
679
911
|
) : (
|
|
680
912
|
<span {...stylex.props(styles.itemLabel)}>{item.label}</span>
|
|
681
913
|
)}
|
|
@@ -704,7 +936,7 @@ export function useTriggerMenu(
|
|
|
704
936
|
id={listboxId}
|
|
705
937
|
role="listbox"
|
|
706
938
|
aria-label={
|
|
707
|
-
|
|
939
|
+
activeTrigger.menuLabel ?? t('@astryx.chatTriggerMenu.suggestions')
|
|
708
940
|
}
|
|
709
941
|
{...mergeProps(
|
|
710
942
|
themeProps('trigger-menu'),
|
|
@@ -56,6 +56,13 @@ export const docs = {
|
|
|
56
56
|
type: 'number[]',
|
|
57
57
|
description: '1-indexed line numbers to highlight.',
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
name: 'isDiff',
|
|
61
|
+
type: 'boolean',
|
|
62
|
+
default: 'false',
|
|
63
|
+
description:
|
|
64
|
+
'Render the code as a unified diff over `language`: lines starting with + are added, - removed, @@ is a hunk header (a `--- `/`+++ ` file-header pair directly before one is a header too), anything else is context. The language label reads `diff` or `<language> diff`. The glyph sits in its own column and the rest of each line keeps syntax highlighting; copy returns the exact source. Markdown ```diff and ```diff-<lang> fences set this.',
|
|
65
|
+
},
|
|
59
66
|
{
|
|
60
67
|
name: 'hasCopyButton',
|
|
61
68
|
type: 'boolean',
|