@astryxdesign/core 0.7.1-canary.bffff80 → 0.7.1-canary.c187a4a
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/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/useTriggerMenu.d.ts +9 -2
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +222 -50
- 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/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +6 -1
- package/package.json +3 -3
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.spec.md +21 -21
- package/src/Chat/ChatComposerInput.test.tsx +198 -1
- package/src/Chat/ChatComposerInput.tsx +13 -0
- 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/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/Markdown/Markdown.doc.mjs +1 -1
- package/src/Markdown/Markdown.spec.md +15 -7
- package/src/Markdown/Markdown.tsx +4 -0
|
@@ -116,6 +116,15 @@ export type ChatComposerTrigger = {
|
|
|
116
116
|
loadingText?: string;
|
|
117
117
|
/** Accessible label for the menu. @default 'Suggestions' */
|
|
118
118
|
menuLabel?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Whether the query continues past spaces, for suggestions whose names have
|
|
121
|
+
* spaces (e.g. "@María José García", "@Design Review: Q4"). The query then
|
|
122
|
+
* runs until a line break or about 64 characters, and when nothing matches
|
|
123
|
+
* the menu hides unless `emptySearchText` is set. When false, the query ends
|
|
124
|
+
* at the first space.
|
|
125
|
+
* @default false
|
|
126
|
+
*/
|
|
127
|
+
hasMultiWordQuery?: boolean;
|
|
119
128
|
};
|
|
120
129
|
export interface ChatComposerInputProps extends Omit<BaseProps<HTMLDivElement>, 'onChange' | 'onPaste' | 'onSubmit'> {
|
|
121
130
|
/** Ref forwarded to the root element. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAqBrE,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAQ,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAShD,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;IAC9D,6EAA6E;IAC7E,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uDAAuD;IACvD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,sBAAsB;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB;AAED,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAAG;IACnC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC;AAE/D,mFAAmF;AACnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,EAAE,MAAM,SAAS,CAAC;CACzB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAC3B,sBAAsB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,WAAW,6BAA8B,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC/E,0CAA0C;IAC1C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,kEAAkE;IAClE,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG;IAChC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,SAAS,CAAC;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,GAAG,iBAAiB,CAAC;IAC/D;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAC;IAC1D;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -437,6 +437,11 @@ export function ChatComposerInput(props) {
|
|
|
437
437
|
historyIndexRef.current = -1;
|
|
438
438
|
currentDraftRef.current = '';
|
|
439
439
|
}
|
|
440
|
+
|
|
441
|
+
// Submitting ends any trigger query, including one dismissed with
|
|
442
|
+
// Escape: no menu stays open, and no dismissal carries into the next
|
|
443
|
+
// message.
|
|
444
|
+
triggerMenu.reset();
|
|
440
445
|
onSubmit?.(text);
|
|
441
446
|
editableRef.current.textContent = '';
|
|
442
447
|
setIsEmpty(true);
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Detects trigger characters (@ / etc.) typed inside a contentEditable,
|
|
8
8
|
* opens a popover at the cursor position with filtered items, handles
|
|
9
|
-
* keyboard navigation, and inserts tokens or text on selection.
|
|
9
|
+
* keyboard navigation, and inserts tokens or text on selection. Triggers
|
|
10
|
+
* opt into multi-word queries with hasMultiWordQuery; results apply only
|
|
11
|
+
* while their query is current (component:ChatComposerInput FR10–FR16).
|
|
10
12
|
*
|
|
11
13
|
* Reuses SearchSource from Typeahead for async/sync search with
|
|
12
14
|
* cancel() support and debounce.
|
|
@@ -25,6 +27,11 @@ export interface TriggerMenuState {
|
|
|
25
27
|
items: SearchableItem[];
|
|
26
28
|
highlightedIndex: number;
|
|
27
29
|
isLoading: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The last settled results were an unmatched multi-word query, so the menu
|
|
32
|
+
* is closed. It stays closed while a newer search for the same query runs.
|
|
33
|
+
*/
|
|
34
|
+
isHidden: boolean;
|
|
28
35
|
}
|
|
29
36
|
export interface UseTriggerMenuOptions {
|
|
30
37
|
triggers?: ChatComposerTrigger[];
|
|
@@ -42,7 +49,7 @@ export interface UseTriggerMenuReturn {
|
|
|
42
49
|
state: TriggerMenuState;
|
|
43
50
|
/** Call on every input event to check for trigger activation */
|
|
44
51
|
handleInput: () => void;
|
|
45
|
-
/** Call on keydown
|
|
52
|
+
/** Call on keydown — returns true if the event was consumed */
|
|
46
53
|
handleKeyDown: (e: React.KeyboardEvent) => boolean;
|
|
47
54
|
/** Render the trigger menu popover */
|
|
48
55
|
renderMenu: () => ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTriggerMenu.d.ts","sourceRoot":"","sources":["../../src/Chat/useTriggerMenu.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useTriggerMenu.d.ts","sourceRoot":"","sources":["../../src/Chat/useTriggerMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAYf,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAGvD,OAAO,KAAK,EAAC,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAMhF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,CAAC;IACxB,gEAAgE;IAChE,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,+DAA+D;IAC/D,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,OAAO,CAAC;IACnD,sCAAsC;IACtC,UAAU,EAAE,MAAM,SAAS,CAAC;IAC5B,mCAAmC;IACnC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;;;;OAKG;IACH,SAAS,EAAE;QACT,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;QAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,uBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,eAAe,CAAC,EAAE,SAAS,CAAC;KAC7B,CAAC;CACH;AAoOD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,qBAAqB,GAC7B,oBAAoB,CAsnBtB"}
|
|
@@ -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.
|
|
@@ -25,7 +27,7 @@ import { usePopover } from "../Popover/usePopover.js";
|
|
|
25
27
|
import { useHighlightedOptionScroll } from "../hooks/useHighlightedOptionScroll.js";
|
|
26
28
|
import "../theme/tokens.stylex.js";
|
|
27
29
|
import { colorVars, spacingVars, radiusVars, typeScaleVars, typographyVars } from "../theme/tokens.stylex.js";
|
|
28
|
-
import { mergeProps, groupItems } from "../utils/index.js";
|
|
30
|
+
import { mergeProps, groupItems, isImeKeyEvent } from "../utils/index.js";
|
|
29
31
|
import { themeProps } from "../utils/themeProps.js";
|
|
30
32
|
import { useTranslator } from "../i18n/index.js";
|
|
31
33
|
|
|
@@ -48,6 +50,15 @@ const styles = {
|
|
|
48
50
|
// Helpers
|
|
49
51
|
// =============================================================================
|
|
50
52
|
|
|
53
|
+
/** The text node holding a collapsed caret inside `editable`, if any. */
|
|
54
|
+
function getCaretTextNode(editable) {
|
|
55
|
+
const selection = window.getSelection();
|
|
56
|
+
if (!selection || selection.rangeCount === 0) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const node = selection.getRangeAt(0).startContainer;
|
|
60
|
+
return node.nodeType === Node.TEXT_NODE && editable.contains(node) ? node : null;
|
|
61
|
+
}
|
|
51
62
|
function getTextBeforeCursor(editable) {
|
|
52
63
|
const selection = window.getSelection();
|
|
53
64
|
if (!selection || selection.rangeCount === 0) {
|
|
@@ -66,27 +77,73 @@ function getTextBeforeCursor(editable) {
|
|
|
66
77
|
}
|
|
67
78
|
return null;
|
|
68
79
|
}
|
|
80
|
+
const MAX_MULTI_WORD_QUERY_LENGTH = 64;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* An unmatched multi-word query hides the menu instead of covering prose with
|
|
84
|
+
* an empty panel, unless the trigger supplies its own empty message.
|
|
85
|
+
*/
|
|
86
|
+
function isUnmatchedMultiWordQuery(trigger, items, isLoading) {
|
|
87
|
+
return trigger?.hasMultiWordQuery === true &&
|
|
88
|
+
// `null` means "not given", exactly as `undefined` does.
|
|
89
|
+
trigger.emptySearchText == null && items.length === 0 && !isLoading;
|
|
90
|
+
}
|
|
91
|
+
function isTriggerBoundary(char) {
|
|
92
|
+
return char === null || char === ' ' || char === '\t' || char === '\n';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Finds the trigger query the caret is in (component:ChatComposerInput FR10,
|
|
97
|
+
* FR11). A trigger character activates at the start of the text or after a
|
|
98
|
+
* space, tab, or line break. A single-token query ends at whitespace. A
|
|
99
|
+
* multi-word query ends at a line break, past the length bound, or where the
|
|
100
|
+
* same trigger's character starts a new query; another trigger's character
|
|
101
|
+
* inside it is ordinary text.
|
|
102
|
+
*/
|
|
69
103
|
function findActiveTrigger(textBeforeCursor, triggers) {
|
|
70
|
-
|
|
104
|
+
let active = null;
|
|
105
|
+
for (let i = 0; i < textBeforeCursor.length; i++) {
|
|
71
106
|
const char = textBeforeCursor[i];
|
|
72
|
-
if (char === '
|
|
73
|
-
|
|
107
|
+
if (char === '\n') {
|
|
108
|
+
active = null;
|
|
109
|
+
continue;
|
|
74
110
|
}
|
|
75
|
-
|
|
76
|
-
if (char ===
|
|
77
|
-
|
|
78
|
-
if (prevChar === null || prevChar === ' ' || prevChar === '\n') {
|
|
79
|
-
const query = textBeforeCursor.slice(i + 1);
|
|
80
|
-
return {
|
|
81
|
-
trigger,
|
|
82
|
-
query,
|
|
83
|
-
triggerStart: i
|
|
84
|
-
};
|
|
85
|
-
}
|
|
111
|
+
if (active && !active.trigger.hasMultiWordQuery) {
|
|
112
|
+
if (char === ' ' || char === '\t') {
|
|
113
|
+
active = null;
|
|
86
114
|
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (active && i - active.triggerStart > MAX_MULTI_WORD_QUERY_LENGTH) {
|
|
118
|
+
active = null;
|
|
119
|
+
}
|
|
120
|
+
if (!isTriggerBoundary(i > 0 ? textBeforeCursor[i - 1] : null)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const trigger = triggers.find(t => t.character === char);
|
|
124
|
+
if (!trigger) {
|
|
125
|
+
continue;
|
|
87
126
|
}
|
|
127
|
+
if (active && trigger.character !== active.trigger.character) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
active = {
|
|
131
|
+
trigger,
|
|
132
|
+
triggerStart: i
|
|
133
|
+
};
|
|
88
134
|
}
|
|
89
|
-
|
|
135
|
+
if (!active) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const query = textBeforeCursor.slice(active.triggerStart + 1);
|
|
139
|
+
if (active.trigger.hasMultiWordQuery && query.length > MAX_MULTI_WORD_QUERY_LENGTH) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
trigger: active.trigger,
|
|
144
|
+
query,
|
|
145
|
+
triggerStart: active.triggerStart
|
|
146
|
+
};
|
|
90
147
|
}
|
|
91
148
|
function deleteTriggerText(editable, triggerStart) {
|
|
92
149
|
const selection = window.getSelection();
|
|
@@ -131,11 +188,17 @@ export function useTriggerMenu(options) {
|
|
|
131
188
|
query: '',
|
|
132
189
|
items: [],
|
|
133
190
|
highlightedIndex: 0,
|
|
134
|
-
isLoading: false
|
|
191
|
+
isLoading: false,
|
|
192
|
+
isHidden: false
|
|
135
193
|
});
|
|
136
194
|
const triggerStartRef = useRef(-1);
|
|
137
195
|
const searchTimeoutRef = useRef(null);
|
|
196
|
+
const searchRequestIdRef = useRef(0);
|
|
197
|
+
const dismissedRef = useRef(null);
|
|
138
198
|
const anchorSpanRef = useRef(null);
|
|
199
|
+
// True while the popover is closed only because the query is unmatched; the
|
|
200
|
+
// trigger query itself is still active.
|
|
201
|
+
const isMenuSuppressedRef = useRef(false);
|
|
139
202
|
const removeAnchorSpan = useCallback(() => {
|
|
140
203
|
if (anchorSpanRef.current) {
|
|
141
204
|
anchorSpanRef.current.remove();
|
|
@@ -144,6 +207,10 @@ export function useTriggerMenu(options) {
|
|
|
144
207
|
}, []);
|
|
145
208
|
const popover = usePopover({
|
|
146
209
|
onHide: useCallback(() => {
|
|
210
|
+
if (isMenuSuppressedRef.current) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
searchRequestIdRef.current++;
|
|
147
214
|
removeAnchorSpan();
|
|
148
215
|
setState(prev => ({
|
|
149
216
|
...prev,
|
|
@@ -152,7 +219,8 @@ export function useTriggerMenu(options) {
|
|
|
152
219
|
query: '',
|
|
153
220
|
items: [],
|
|
154
221
|
highlightedIndex: 0,
|
|
155
|
-
isLoading: false
|
|
222
|
+
isLoading: false,
|
|
223
|
+
isHidden: false
|
|
156
224
|
}));
|
|
157
225
|
}, [removeAnchorSpan]),
|
|
158
226
|
hasLightDismiss: true,
|
|
@@ -162,6 +230,10 @@ export function useTriggerMenu(options) {
|
|
|
162
230
|
// the contenteditable composer, so a modal dialog wrapper is incorrect.
|
|
163
231
|
role: 'none'
|
|
164
232
|
});
|
|
233
|
+
const {
|
|
234
|
+
show: showPopover,
|
|
235
|
+
hide: hidePopover
|
|
236
|
+
} = popover;
|
|
165
237
|
|
|
166
238
|
// Cleanup on unmount
|
|
167
239
|
useEffect(() => {
|
|
@@ -177,14 +249,29 @@ export function useTriggerMenu(options) {
|
|
|
177
249
|
clearTimeout(searchTimeoutRef.current);
|
|
178
250
|
searchTimeoutRef.current = null;
|
|
179
251
|
}
|
|
252
|
+
searchRequestIdRef.current++;
|
|
180
253
|
// Cancel any in-flight search on the active trigger's searchSource
|
|
181
254
|
const trigger = state.activeTrigger;
|
|
182
255
|
if (trigger?.searchSource) {
|
|
183
256
|
trigger.searchSource.cancel?.();
|
|
184
257
|
}
|
|
185
258
|
removeAnchorSpan();
|
|
259
|
+
isMenuSuppressedRef.current = false;
|
|
260
|
+
// Ending the query also forgets an Escape on it; a send or clear must not
|
|
261
|
+
// leave the next message's mention at the same offset suppressed.
|
|
262
|
+
dismissedRef.current = null;
|
|
186
263
|
popover.hide();
|
|
187
264
|
triggerStartRef.current = -1;
|
|
265
|
+
setState(prev => ({
|
|
266
|
+
...prev,
|
|
267
|
+
isActive: false,
|
|
268
|
+
activeTrigger: null,
|
|
269
|
+
query: '',
|
|
270
|
+
items: [],
|
|
271
|
+
highlightedIndex: 0,
|
|
272
|
+
isLoading: false,
|
|
273
|
+
isHidden: false
|
|
274
|
+
}));
|
|
188
275
|
}, [popover, state.activeTrigger, removeAnchorSpan]);
|
|
189
276
|
|
|
190
277
|
// Anchor the popover to the cursor position (not the entire input).
|
|
@@ -232,9 +319,46 @@ export function useTriggerMenu(options) {
|
|
|
232
319
|
clearTimeout(searchTimeoutRef.current);
|
|
233
320
|
searchTimeoutRef.current = null;
|
|
234
321
|
}
|
|
322
|
+
const requestId = ++searchRequestIdRef.current;
|
|
323
|
+
// A result applies only while its request is the latest one and the
|
|
324
|
+
// caret is still inside the same trigger query. Submitting or clearing
|
|
325
|
+
// the editor ends the query without an input event, so check the DOM.
|
|
326
|
+
const isCurrent = () => {
|
|
327
|
+
if (requestId !== searchRequestIdRef.current) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const editable = editableRef.current;
|
|
331
|
+
const textBefore = editable ? getTextBeforeCursor(editable) : null;
|
|
332
|
+
const found = textBefore === null || !triggers ? null : findActiveTrigger(textBefore, triggers);
|
|
333
|
+
if (found?.trigger.character !== trigger.character || found.triggerStart !== triggerStartRef.current) {
|
|
334
|
+
reset();
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
return true;
|
|
338
|
+
};
|
|
339
|
+
const applyResults = items => {
|
|
340
|
+
const isHidden = isUnmatchedMultiWordQuery(trigger, items, false);
|
|
341
|
+
setState(prev => ({
|
|
342
|
+
...prev,
|
|
343
|
+
items,
|
|
344
|
+
highlightedIndex: items.length > 0 ? 0 : -1,
|
|
345
|
+
isLoading: false,
|
|
346
|
+
isHidden
|
|
347
|
+
}));
|
|
348
|
+
// A hidden menu closes its popover, which also releases the popover's
|
|
349
|
+
// Escape and light-dismiss handling; matches reopen it at the caret.
|
|
350
|
+
if (isHidden && !isMenuSuppressedRef.current) {
|
|
351
|
+
isMenuSuppressedRef.current = true;
|
|
352
|
+
hidePopover();
|
|
353
|
+
} else if (!isHidden && isMenuSuppressedRef.current) {
|
|
354
|
+
isMenuSuppressedRef.current = false;
|
|
355
|
+
setAnchor();
|
|
356
|
+
showPopover();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
235
359
|
const doSearch = () => {
|
|
236
360
|
if (trigger.searchSource) {
|
|
237
|
-
// Use SearchSource
|
|
361
|
+
// Use SearchSource — cancel previous, then search
|
|
238
362
|
trigger.searchSource.cancel?.();
|
|
239
363
|
setState(prev => ({
|
|
240
364
|
...prev,
|
|
@@ -242,19 +366,15 @@ export function useTriggerMenu(options) {
|
|
|
242
366
|
}));
|
|
243
367
|
const result = trigger.searchSource.search(query);
|
|
244
368
|
Promise.resolve(result).then(items => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
isLoading: false
|
|
250
|
-
}));
|
|
369
|
+
if (!isCurrent()) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
applyResults(items);
|
|
251
373
|
}, () => {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
isLoading: false
|
|
257
|
-
}));
|
|
374
|
+
if (!isCurrent()) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
applyResults([]);
|
|
258
378
|
});
|
|
259
379
|
}
|
|
260
380
|
};
|
|
@@ -274,7 +394,7 @@ export function useTriggerMenu(options) {
|
|
|
274
394
|
doSearch();
|
|
275
395
|
}
|
|
276
396
|
}
|
|
277
|
-
}, [debounceMs]);
|
|
397
|
+
}, [debounceMs, editableRef, triggers, reset, setAnchor, hidePopover, showPopover]);
|
|
278
398
|
const selectItem = useCallback(item => {
|
|
279
399
|
const trigger = state.activeTrigger;
|
|
280
400
|
if (!trigger) {
|
|
@@ -309,6 +429,7 @@ export function useTriggerMenu(options) {
|
|
|
309
429
|
}
|
|
310
430
|
const textBefore = getTextBeforeCursor(editable);
|
|
311
431
|
if (textBefore === null) {
|
|
432
|
+
dismissedRef.current = null;
|
|
312
433
|
if (state.isActive) {
|
|
313
434
|
reset();
|
|
314
435
|
}
|
|
@@ -316,6 +437,7 @@ export function useTriggerMenu(options) {
|
|
|
316
437
|
}
|
|
317
438
|
const found = findActiveTrigger(textBefore, triggers);
|
|
318
439
|
if (!found) {
|
|
440
|
+
dismissedRef.current = null;
|
|
319
441
|
if (state.isActive) {
|
|
320
442
|
reset();
|
|
321
443
|
}
|
|
@@ -326,14 +448,27 @@ export function useTriggerMenu(options) {
|
|
|
326
448
|
query,
|
|
327
449
|
triggerStart
|
|
328
450
|
} = found;
|
|
329
|
-
|
|
451
|
+
|
|
452
|
+
// After Escape, keep the menu hidden while that same query keeps growing
|
|
453
|
+
const dismissed = dismissedRef.current;
|
|
454
|
+
if (dismissed && dismissed.character === trigger.character && dismissed.triggerStart === triggerStart && dismissed.textNode !== null && dismissed.textNode.isConnected && dismissed.textNode === getCaretTextNode(editable)) {
|
|
455
|
+
if (query.startsWith(dismissed.dismissedQuery)) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
dismissedRef.current = null;
|
|
459
|
+
} else {
|
|
460
|
+
dismissedRef.current = null;
|
|
461
|
+
}
|
|
462
|
+
if (!state.isActive || state.activeTrigger?.character !== trigger.character || triggerStartRef.current !== triggerStart) {
|
|
330
463
|
triggerStartRef.current = triggerStart;
|
|
464
|
+
isMenuSuppressedRef.current = false;
|
|
331
465
|
setState(prev => ({
|
|
332
466
|
...prev,
|
|
333
467
|
isActive: true,
|
|
334
468
|
activeTrigger: trigger,
|
|
335
469
|
query,
|
|
336
|
-
highlightedIndex: 0
|
|
470
|
+
highlightedIndex: 0,
|
|
471
|
+
isHidden: false
|
|
337
472
|
}));
|
|
338
473
|
setAnchor();
|
|
339
474
|
searchItems(trigger, query);
|
|
@@ -341,13 +476,50 @@ export function useTriggerMenu(options) {
|
|
|
341
476
|
} else if (state.query !== query) {
|
|
342
477
|
setState(prev => ({
|
|
343
478
|
...prev,
|
|
344
|
-
query
|
|
479
|
+
query,
|
|
480
|
+
activeTrigger: trigger
|
|
345
481
|
}));
|
|
346
482
|
searchItems(trigger, query);
|
|
347
483
|
}
|
|
348
484
|
}, [triggers, editableRef, state.isActive, state.activeTrigger, state.query, reset, setAnchor, searchItems, popover]);
|
|
485
|
+
const isMenuVisible = state.isActive && !state.isHidden;
|
|
349
486
|
const handleKeyDown = useCallback(e => {
|
|
350
|
-
|
|
487
|
+
// Never intercept IME composition keystrokes (e.g. Enter committing candidates)
|
|
488
|
+
if (isImeKeyEvent(e.nativeEvent)) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// A hidden menu consumes nothing: arrows move the caret, Enter submits,
|
|
493
|
+
// and Escape reaches the surrounding surface.
|
|
494
|
+
if (!isMenuVisible) {
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
if (e.key === 'Escape') {
|
|
498
|
+
e.preventDefault();
|
|
499
|
+
const editable = editableRef.current;
|
|
500
|
+
const dismissed = state.activeTrigger ? {
|
|
501
|
+
character: state.activeTrigger.character,
|
|
502
|
+
triggerStart: triggerStartRef.current,
|
|
503
|
+
dismissedQuery: state.query,
|
|
504
|
+
textNode: editable ? getCaretTextNode(editable) : null
|
|
505
|
+
} : null;
|
|
506
|
+
reset();
|
|
507
|
+
// Remembered after reset, which clears it: the menu stays hidden while
|
|
508
|
+
// this same query keeps growing.
|
|
509
|
+
dismissedRef.current = dismissed;
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// A visible menu keeps the arrows even when it has nothing to pick (rows
|
|
514
|
+
// still loading, or the empty message), so they never recall history
|
|
515
|
+
// under an open panel. Enter and Tab pick only a settled row; otherwise
|
|
516
|
+
// they keep their editor meaning, so Enter sends the message as typed.
|
|
517
|
+
const hasPickableRows = !state.isLoading && state.items.length > 0;
|
|
518
|
+
if (!hasPickableRows && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
519
|
+
e.preventDefault();
|
|
520
|
+
return true;
|
|
521
|
+
}
|
|
522
|
+
if (!hasPickableRows) {
|
|
351
523
|
return false;
|
|
352
524
|
}
|
|
353
525
|
switch (e.key) {
|
|
@@ -379,16 +551,10 @@ export function useTriggerMenu(options) {
|
|
|
379
551
|
}
|
|
380
552
|
return false;
|
|
381
553
|
}
|
|
382
|
-
case 'Escape':
|
|
383
|
-
{
|
|
384
|
-
e.preventDefault();
|
|
385
|
-
reset();
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
554
|
default:
|
|
389
555
|
return false;
|
|
390
556
|
}
|
|
391
|
-
}, [state.
|
|
557
|
+
}, [isMenuVisible, editableRef, state.activeTrigger, state.query, state.isLoading, state.highlightedIndex, state.items, selectItem, reset]);
|
|
392
558
|
const getItemId = useCallback(index => `${listboxId}-option-${index}`, [listboxId]);
|
|
393
559
|
|
|
394
560
|
// Keep the highlighted option visible during keyboard navigation; hover
|
|
@@ -416,7 +582,7 @@ export function useTriggerMenu(options) {
|
|
|
416
582
|
const ariaProps = !hasTriggers ? {
|
|
417
583
|
role: 'textbox',
|
|
418
584
|
'aria-multiline': 'true'
|
|
419
|
-
} :
|
|
585
|
+
} : isMenuVisible ? {
|
|
420
586
|
role: 'combobox',
|
|
421
587
|
'aria-expanded': true,
|
|
422
588
|
'aria-controls': listboxId,
|
|
@@ -428,9 +594,15 @@ export function useTriggerMenu(options) {
|
|
|
428
594
|
'aria-haspopup': 'listbox'
|
|
429
595
|
};
|
|
430
596
|
const renderMenu = useCallback(() => {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
597
|
+
const activeTrigger = state.activeTrigger;
|
|
598
|
+
if (!activeTrigger) {
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
if (state.isHidden) {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
const emptyText = activeTrigger.emptySearchText ?? 'No results';
|
|
605
|
+
const loadingText = activeTrigger.loadingText ?? 'Searching\u2026';
|
|
434
606
|
let listContent;
|
|
435
607
|
if (state.isLoading) {
|
|
436
608
|
listContent = /*#__PURE__*/_jsx("div", {
|
|
@@ -471,7 +643,7 @@ export function useTriggerMenu(options) {
|
|
|
471
643
|
className: "x9f619 x78zum5 x6s0dn4 xh8yej3 xlsj2fj xh6dtrn x1ypdohk x16khyan x1a2a7pz xc342km xng3xce x1yc453h x9ynric xjm74w1 xw6l6zx x1tgivj0 x1lmrjuc"
|
|
472
644
|
}
|
|
473
645
|
}[!!(idx === state.highlightedIndex) << 0],
|
|
474
|
-
children:
|
|
646
|
+
children: activeTrigger.renderItem ? activeTrigger.renderItem(item) : /*#__PURE__*/_jsx("span", {
|
|
475
647
|
...{
|
|
476
648
|
className: "x98rzlu xeuugli xb3r6kr xlyipyv xuxw1ft"
|
|
477
649
|
},
|
|
@@ -498,7 +670,7 @@ export function useTriggerMenu(options) {
|
|
|
498
670
|
return popover.render(/*#__PURE__*/_jsx("div", {
|
|
499
671
|
id: listboxId,
|
|
500
672
|
role: "listbox",
|
|
501
|
-
"aria-label":
|
|
673
|
+
"aria-label": activeTrigger.menuLabel ?? t('@astryx.chatTriggerMenu.suggestions'),
|
|
502
674
|
...mergeProps(themeProps('trigger-menu'), {
|
|
503
675
|
className: "x9f619 x1xiyphd x1odjw0f x9epnlk xfb3i0g"
|
|
504
676
|
}),
|
|
@@ -27,6 +27,7 @@ export interface DividerProps extends BaseProps<HTMLDivElement> {
|
|
|
27
27
|
orientation?: 'horizontal' | 'vertical';
|
|
28
28
|
/**
|
|
29
29
|
* Optional label to display centered on the divider.
|
|
30
|
+
* Numeric zero is preserved; null, booleans, and empty strings render no label.
|
|
30
31
|
* Rendered with small, secondary text styling.
|
|
31
32
|
*/
|
|
32
33
|
label?: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Divider.d.ts","sourceRoot":"","sources":["../../src/Divider/Divider.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC7D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IAExC
|
|
1
|
+
{"version":3,"file":"Divider.d.ts","sourceRoot":"","sources":["../../src/Divider/Divider.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC7D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IAExC;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IAEzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAiED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,EACtB,WAA0B,EAC1B,KAAK,EACL,OAAkB,EAClB,WAAmB,EACnB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,GAAG,KAAK,EACT,EAAE,YAAY,+BA2Dd;yBAvEe,OAAO"}
|
package/dist/Divider/Divider.js
CHANGED
|
@@ -18,7 +18,7 @@ import { useId } from 'react';
|
|
|
18
18
|
import * as stylex from '@stylexjs/stylex';
|
|
19
19
|
import "../theme/tokens.stylex.js";
|
|
20
20
|
import { colorVars, spacingVars, typeScaleVars, borderVars } from "../theme/tokens.stylex.js";
|
|
21
|
-
import { mergeProps } from "../utils/index.js";
|
|
21
|
+
import { isRenderable, mergeProps } from "../utils/index.js";
|
|
22
22
|
import { themeProps } from "../utils/themeProps.js";
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -102,13 +102,14 @@ export function Divider({
|
|
|
102
102
|
...props
|
|
103
103
|
}) {
|
|
104
104
|
const isHorizontal = orientation === 'horizontal';
|
|
105
|
+
const hasLabel = isRenderable(label);
|
|
105
106
|
const labelId = useId();
|
|
106
107
|
|
|
107
108
|
// A separator does not derive its accessible name from its content, so the
|
|
108
109
|
// rendered label must be referenced explicitly via aria-labelledby to be
|
|
109
110
|
// exposed as the separator's name (WCAG 1.3.1). An explicit aria-label or
|
|
110
111
|
// aria-labelledby from the consumer takes precedence.
|
|
111
|
-
const resolvedLabelledBy = ariaLabelledBy ?? (
|
|
112
|
+
const resolvedLabelledBy = ariaLabelledBy ?? (hasLabel && ariaLabel == null ? labelId : undefined);
|
|
112
113
|
return /*#__PURE__*/_jsxs("div", {
|
|
113
114
|
ref: ref,
|
|
114
115
|
...props,
|
|
@@ -122,7 +123,7 @@ export function Divider({
|
|
|
122
123
|
}), stylex.props(isHorizontal ? baseStyles.horizontal : baseStyles.vertical, isFullBleed && (isHorizontal ? fullBleedStyles.horizontal : fullBleedStyles.vertical), xstyle), className, style),
|
|
123
124
|
children: [/*#__PURE__*/_jsx("div", {
|
|
124
125
|
...stylex.props(isHorizontal ? lineStyles.horizontalLine : lineStyles.verticalLine, lineStyles[variant])
|
|
125
|
-
}),
|
|
126
|
+
}), hasLabel && /*#__PURE__*/_jsx("div", {
|
|
126
127
|
id: labelId,
|
|
127
128
|
...{
|
|
128
129
|
0: {
|
|
@@ -133,7 +134,7 @@ export function Divider({
|
|
|
133
134
|
}
|
|
134
135
|
}[!!!isHorizontal << 0],
|
|
135
136
|
children: label
|
|
136
|
-
}),
|
|
137
|
+
}), hasLabel && /*#__PURE__*/_jsx("div", {
|
|
137
138
|
...stylex.props(isHorizontal ? lineStyles.horizontalLine : lineStyles.verticalLine, lineStyles[variant])
|
|
138
139
|
})]
|
|
139
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown/Markdown.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1043,7 +1043,12 @@ listDepth = 0) {
|
|
|
1043
1043
|
code: node.value,
|
|
1044
1044
|
language: language,
|
|
1045
1045
|
isDiff: isDiff,
|
|
1046
|
-
isCollapsible: true
|
|
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,
|
|
1047
1052
|
xstyle: [contentWidthValue != null ? dynamicStyles.blockWidth(contentWidthValue) : undefined, blockAlignStyle]
|
|
1048
1053
|
})
|
|
1049
1054
|
}, index);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.7.1-canary.
|
|
3
|
+
"version": "0.7.1-canary.c187a4a",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -787,8 +787,8 @@
|
|
|
787
787
|
"react-dom": ">=19.0.0"
|
|
788
788
|
},
|
|
789
789
|
"devDependencies": {
|
|
790
|
-
"@astryxdesign/a11y-spec": "0.7.1-canary.
|
|
791
|
-
"@astryxdesign/cli": "0.7.1-canary.
|
|
790
|
+
"@astryxdesign/a11y-spec": "0.7.1-canary.c187a4a",
|
|
791
|
+
"@astryxdesign/cli": "0.7.1-canary.c187a4a",
|
|
792
792
|
"@babel/cli": "^7.29.7",
|
|
793
793
|
"@babel/core": "^7.29.7",
|
|
794
794
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -98,7 +98,7 @@ export const docs = {
|
|
|
98
98
|
name: 'triggers',
|
|
99
99
|
type: 'ChatComposerTrigger[]',
|
|
100
100
|
description:
|
|
101
|
-
'Trigger definitions for typeahead menus. Each trigger specifies a character (@ or /), a search source, and an onSelect handler that returns the token to insert. Per-trigger emptySearchText (ReactNode) is the message when the query matched nothing.',
|
|
101
|
+
'Trigger definitions for typeahead menus. Each trigger specifies a character (@ or /), a search source, and an onSelect handler that returns the token to insert. Set hasMultiWordQuery: true when suggestions contain spaces (people, topics): the query then runs to a line break or about 64 characters instead of ending at the first space. Per-trigger emptySearchText (ReactNode) is the message when the query matched nothing.',
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
name: 'debounceMs',
|