@djangocfg/ui-tools 2.1.389 → 2.1.393

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.
Files changed (183) hide show
  1. package/README.md +7 -10
  2. package/dist/chunk-PAWJFY3S.mjs +6 -0
  3. package/dist/{chunk-N2XQF2OL.mjs.map → chunk-PAWJFY3S.mjs.map} +1 -1
  4. package/dist/chunk-PK6SKIKE.cjs +8 -0
  5. package/dist/{chunk-OLISEQHS.cjs.map → chunk-PK6SKIKE.cjs.map} +1 -1
  6. package/dist/file-icon/index.cjs +6 -6
  7. package/dist/file-icon/index.d.cts +1 -1
  8. package/dist/file-icon/index.d.ts +1 -1
  9. package/dist/file-icon/index.mjs +1 -1
  10. package/dist/tree/index.cjs +1372 -143
  11. package/dist/tree/index.cjs.map +1 -1
  12. package/dist/tree/index.d.cts +2 -2
  13. package/dist/tree/index.d.ts +2 -2
  14. package/dist/tree/index.mjs +1322 -3
  15. package/dist/tree/index.mjs.map +1 -1
  16. package/dist/{types-CevSbyfD.d.cts → types-B_zhyAqR.d.cts} +1 -1
  17. package/dist/{types-CevSbyfD.d.ts → types-B_zhyAqR.d.ts} +1 -1
  18. package/package.json +9 -17
  19. package/src/tools/AudioPlayer/README.md +4 -4
  20. package/src/tools/Chat/README.md +6 -6
  21. package/src/tools/CronScheduler/index.tsx +1 -1
  22. package/src/tools/CronScheduler/lazy.tsx +1 -1
  23. package/src/tools/ImageViewer/README.md +1 -1
  24. package/src/tools/JsonForm/README.md +2 -2
  25. package/src/tools/MarkdownEditor/README.md +3 -3
  26. package/src/tools/MarkdownMessage/README.md +2 -2
  27. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +5 -1
  28. package/src/tools/SpeechRecognition/README.md +1 -1
  29. package/dist/ChatRoot-EFNXQXXN.cjs +0 -15
  30. package/dist/ChatRoot-EFNXQXXN.cjs.map +0 -1
  31. package/dist/ChatRoot-FITF5RVP.mjs +0 -6
  32. package/dist/ChatRoot-FITF5RVP.mjs.map +0 -1
  33. package/dist/ChatRoot-PNNGQCYF.css +0 -7
  34. package/dist/ChatRoot-PNNGQCYF.css.map +0 -1
  35. package/dist/CronScheduler.client-DLMXCPAJ.mjs +0 -67
  36. package/dist/CronScheduler.client-DLMXCPAJ.mjs.map +0 -1
  37. package/dist/CronScheduler.client-WEJF4PWQ.cjs +0 -72
  38. package/dist/CronScheduler.client-WEJF4PWQ.cjs.map +0 -1
  39. package/dist/DictationField-AS2F33WI.cjs +0 -13
  40. package/dist/DictationField-AS2F33WI.cjs.map +0 -1
  41. package/dist/DictationField-WPONUCYE.mjs +0 -4
  42. package/dist/DictationField-WPONUCYE.mjs.map +0 -1
  43. package/dist/DocsLayout-EKASBSP7.mjs +0 -3448
  44. package/dist/DocsLayout-EKASBSP7.mjs.map +0 -1
  45. package/dist/DocsLayout-MBFIB4NO.css +0 -7
  46. package/dist/DocsLayout-MBFIB4NO.css.map +0 -1
  47. package/dist/DocsLayout-OURFYWQE.cjs +0 -3455
  48. package/dist/DocsLayout-OURFYWQE.cjs.map +0 -1
  49. package/dist/JsonSchemaForm-DD7CLRIG.cjs +0 -13
  50. package/dist/JsonSchemaForm-DD7CLRIG.cjs.map +0 -1
  51. package/dist/JsonSchemaForm-XKUIVELK.mjs +0 -4
  52. package/dist/JsonSchemaForm-XKUIVELK.mjs.map +0 -1
  53. package/dist/JsonTree-43PQAJKY.mjs +0 -5
  54. package/dist/JsonTree-43PQAJKY.mjs.map +0 -1
  55. package/dist/JsonTree-MLET23ZA.css +0 -7
  56. package/dist/JsonTree-MLET23ZA.css.map +0 -1
  57. package/dist/JsonTree-X6W5YEVY.cjs +0 -11
  58. package/dist/JsonTree-X6W5YEVY.cjs.map +0 -1
  59. package/dist/LottiePlayer.client-2S7ISJ2S.cjs +0 -168
  60. package/dist/LottiePlayer.client-2S7ISJ2S.cjs.map +0 -1
  61. package/dist/LottiePlayer.client-5LDSSJWS.mjs +0 -161
  62. package/dist/LottiePlayer.client-5LDSSJWS.mjs.map +0 -1
  63. package/dist/MapContainer-AKIPABJK.mjs +0 -4
  64. package/dist/MapContainer-AKIPABJK.mjs.map +0 -1
  65. package/dist/MapContainer-STVDMC36.cjs +0 -17
  66. package/dist/MapContainer-STVDMC36.cjs.map +0 -1
  67. package/dist/Mermaid.client-DDXWXZXY.css +0 -7
  68. package/dist/Mermaid.client-DDXWXZXY.css.map +0 -1
  69. package/dist/Mermaid.client-NL4SVR7F.mjs +0 -481
  70. package/dist/Mermaid.client-NL4SVR7F.mjs.map +0 -1
  71. package/dist/Mermaid.client-NNTI6DFX.cjs +0 -487
  72. package/dist/Mermaid.client-NNTI6DFX.cjs.map +0 -1
  73. package/dist/Player-BRV7XTWR.mjs +0 -4
  74. package/dist/Player-BRV7XTWR.mjs.map +0 -1
  75. package/dist/Player-PM7F7DD7.cjs +0 -13
  76. package/dist/Player-PM7F7DD7.cjs.map +0 -1
  77. package/dist/Player-ZGQKKOWI.css +0 -66
  78. package/dist/Player-ZGQKKOWI.css.map +0 -1
  79. package/dist/PrettyCode.client-GWFAIVFN.css +0 -7
  80. package/dist/PrettyCode.client-GWFAIVFN.css.map +0 -1
  81. package/dist/PrettyCode.client-KOHDVPPN.cjs +0 -285
  82. package/dist/PrettyCode.client-KOHDVPPN.cjs.map +0 -1
  83. package/dist/PrettyCode.client-ZGYGKE7G.mjs +0 -283
  84. package/dist/PrettyCode.client-ZGYGKE7G.mjs.map +0 -1
  85. package/dist/TreeRoot-5COOOSWG.mjs +0 -4
  86. package/dist/TreeRoot-5COOOSWG.mjs.map +0 -1
  87. package/dist/TreeRoot-AABP2J6Y.cjs +0 -19
  88. package/dist/TreeRoot-AABP2J6Y.cjs.map +0 -1
  89. package/dist/chunk-2NG4SXEP.mjs +0 -743
  90. package/dist/chunk-2NG4SXEP.mjs.map +0 -1
  91. package/dist/chunk-4LFB7I5K.cjs +0 -1387
  92. package/dist/chunk-4LFB7I5K.cjs.map +0 -1
  93. package/dist/chunk-5D2OCOPQ.cjs +0 -222
  94. package/dist/chunk-5D2OCOPQ.cjs.map +0 -1
  95. package/dist/chunk-5I5QNGUG.cjs +0 -611
  96. package/dist/chunk-5I5QNGUG.cjs.map +0 -1
  97. package/dist/chunk-6ZX2G25W.mjs +0 -1361
  98. package/dist/chunk-6ZX2G25W.mjs.map +0 -1
  99. package/dist/chunk-76NNDZH6.cjs +0 -1061
  100. package/dist/chunk-76NNDZH6.cjs.map +0 -1
  101. package/dist/chunk-7CWGZPO3.mjs +0 -214
  102. package/dist/chunk-7CWGZPO3.mjs.map +0 -1
  103. package/dist/chunk-7EYHNP3E.cjs +0 -965
  104. package/dist/chunk-7EYHNP3E.cjs.map +0 -1
  105. package/dist/chunk-7IYXZUJO.cjs +0 -769
  106. package/dist/chunk-7IYXZUJO.cjs.map +0 -1
  107. package/dist/chunk-ADEN3UA4.cjs +0 -892
  108. package/dist/chunk-ADEN3UA4.cjs.map +0 -1
  109. package/dist/chunk-B6IR5KSC.mjs +0 -59
  110. package/dist/chunk-B6IR5KSC.mjs.map +0 -1
  111. package/dist/chunk-C6GXVH5J.mjs +0 -338
  112. package/dist/chunk-C6GXVH5J.mjs.map +0 -1
  113. package/dist/chunk-DMX7W4XZ.mjs +0 -1113
  114. package/dist/chunk-DMX7W4XZ.mjs.map +0 -1
  115. package/dist/chunk-ECONRHIG.mjs +0 -212
  116. package/dist/chunk-ECONRHIG.mjs.map +0 -1
  117. package/dist/chunk-FEN5S772.cjs +0 -1227
  118. package/dist/chunk-FEN5S772.cjs.map +0 -1
  119. package/dist/chunk-FP2RLYQZ.cjs +0 -187
  120. package/dist/chunk-FP2RLYQZ.cjs.map +0 -1
  121. package/dist/chunk-FVVF7VCD.cjs +0 -1325
  122. package/dist/chunk-FVVF7VCD.cjs.map +0 -1
  123. package/dist/chunk-GYIO7W7M.mjs +0 -1197
  124. package/dist/chunk-GYIO7W7M.mjs.map +0 -1
  125. package/dist/chunk-KNDLV4PI.cjs +0 -1356
  126. package/dist/chunk-KNDLV4PI.cjs.map +0 -1
  127. package/dist/chunk-KNEQRUBA.mjs +0 -181
  128. package/dist/chunk-KNEQRUBA.mjs.map +0 -1
  129. package/dist/chunk-N2XQF2OL.mjs +0 -14
  130. package/dist/chunk-N4MZYNR4.mjs +0 -1342
  131. package/dist/chunk-N4MZYNR4.mjs.map +0 -1
  132. package/dist/chunk-NTVBIIUD.mjs +0 -1439
  133. package/dist/chunk-NTVBIIUD.mjs.map +0 -1
  134. package/dist/chunk-OBRSGM64.mjs +0 -607
  135. package/dist/chunk-OBRSGM64.mjs.map +0 -1
  136. package/dist/chunk-ODO4GMW7.mjs +0 -79
  137. package/dist/chunk-ODO4GMW7.mjs.map +0 -1
  138. package/dist/chunk-OLISEQHS.cjs +0 -18
  139. package/dist/chunk-PVAX67JG.mjs +0 -1041
  140. package/dist/chunk-PVAX67JG.mjs.map +0 -1
  141. package/dist/chunk-QJ6GTUCO.cjs +0 -81
  142. package/dist/chunk-QJ6GTUCO.cjs.map +0 -1
  143. package/dist/chunk-T3MWM23F.cjs +0 -214
  144. package/dist/chunk-T3MWM23F.cjs.map +0 -1
  145. package/dist/chunk-TBSHZO5R.cjs +0 -1134
  146. package/dist/chunk-TBSHZO5R.cjs.map +0 -1
  147. package/dist/chunk-UNCS5V5F.mjs +0 -887
  148. package/dist/chunk-UNCS5V5F.mjs.map +0 -1
  149. package/dist/chunk-VWQ5WOIL.mjs +0 -2059
  150. package/dist/chunk-VWQ5WOIL.mjs.map +0 -1
  151. package/dist/chunk-W75B7Y6C.cjs +0 -1478
  152. package/dist/chunk-W75B7Y6C.cjs.map +0 -1
  153. package/dist/chunk-Y6UTOBF6.mjs +0 -938
  154. package/dist/chunk-Y6UTOBF6.mjs.map +0 -1
  155. package/dist/chunk-YDPDTOSP.cjs +0 -2061
  156. package/dist/chunk-YDPDTOSP.cjs.map +0 -1
  157. package/dist/chunk-YW5IVWHQ.cjs +0 -346
  158. package/dist/chunk-YW5IVWHQ.cjs.map +0 -1
  159. package/dist/chunk-YXZ6GU7H.cjs +0 -63
  160. package/dist/chunk-YXZ6GU7H.cjs.map +0 -1
  161. package/dist/chunk-ZL7FH4NW.mjs +0 -1274
  162. package/dist/chunk-ZL7FH4NW.mjs.map +0 -1
  163. package/dist/components-EHOGXATG.cjs +0 -22
  164. package/dist/components-EHOGXATG.cjs.map +0 -1
  165. package/dist/components-MQ6DR7TX.cjs +0 -26
  166. package/dist/components-MQ6DR7TX.cjs.map +0 -1
  167. package/dist/components-XRX7QGLB.mjs +0 -5
  168. package/dist/components-XRX7QGLB.mjs.map +0 -1
  169. package/dist/components-YATKRWLH.mjs +0 -5
  170. package/dist/components-YATKRWLH.mjs.map +0 -1
  171. package/dist/index.cjs +0 -3674
  172. package/dist/index.cjs.map +0 -1
  173. package/dist/index.css +0 -234
  174. package/dist/index.css.map +0 -1
  175. package/dist/index.d.cts +0 -4929
  176. package/dist/index.d.ts +0 -4929
  177. package/dist/index.mjs +0 -2912
  178. package/dist/index.mjs.map +0 -1
  179. package/dist/launcher-5Y42OBSN.mjs +0 -6
  180. package/dist/launcher-5Y42OBSN.mjs.map +0 -1
  181. package/dist/launcher-PMW2YB24.cjs +0 -59
  182. package/dist/launcher-PMW2YB24.cjs.map +0 -1
  183. package/src/index.ts +0 -157
@@ -1,1387 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkTBSHZO5R_cjs = require('./chunk-TBSHZO5R.cjs');
4
- var chunk7IYXZUJO_cjs = require('./chunk-7IYXZUJO.cjs');
5
- var chunkOLISEQHS_cjs = require('./chunk-OLISEQHS.cjs');
6
- var react = require('react');
7
- var lib = require('@djangocfg/ui-core/lib');
8
- var lucideReact = require('lucide-react');
9
- var components = require('@djangocfg/ui-core/components');
10
- var jsxRuntime = require('react/jsx-runtime');
11
- var reactVirtuoso = require('react-virtuoso');
12
- var hooks = require('@djangocfg/ui-core/hooks');
13
-
14
- function useAutoFocusOnStreamEnd(options = {}) {
15
- const { isStreaming: isStreamingProp, targetRef, enabled = true, delayMs = 0 } = options;
16
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
17
- const isStreaming = isStreamingProp ?? ctx?.isStreaming ?? false;
18
- const composerHandleRef = react.useRef(null);
19
- composerHandleRef.current = ctx?.composer ?? null;
20
- const prevStreamingRef = react.useRef(isStreaming);
21
- react.useEffect(() => {
22
- const wasStreaming = prevStreamingRef.current;
23
- prevStreamingRef.current = isStreaming;
24
- if (!enabled) return;
25
- if (!(wasStreaming && !isStreaming)) return;
26
- const focusNow = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
27
- const explicit = targetRef?.current;
28
- const target = explicit ?? composerHandleRef.current;
29
- target?.focus();
30
- }, "focusNow");
31
- if (delayMs > 0) {
32
- const id = window.setTimeout(focusNow, delayMs);
33
- return () => window.clearTimeout(id);
34
- }
35
- const raf = requestAnimationFrame(focusNow);
36
- return () => cancelAnimationFrame(raf);
37
- }, [isStreaming, enabled, delayMs, targetRef]);
38
- }
39
- chunkOLISEQHS_cjs.__name(useAutoFocusOnStreamEnd, "useAutoFocusOnStreamEnd");
40
- function useRegisterComposer(handle) {
41
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
42
- const register = ctx?.registerComposer;
43
- const focus = handle.focus;
44
- const moveCursorToEnd = handle.moveCursorToEnd;
45
- react.useEffect(() => {
46
- if (!register) return;
47
- register({ focus, moveCursorToEnd });
48
- return () => register(null);
49
- }, [register, focus, moveCursorToEnd]);
50
- }
51
- chunkOLISEQHS_cjs.__name(useRegisterComposer, "useRegisterComposer");
52
-
53
- // src/tools/Chat/utils/sanitizeDraft.ts
54
- function sanitizeDraft(input) {
55
- if (!input) return "";
56
- let s = input.replace(/[​‌‍]/g, "");
57
- s = s.replace(/\r\n?/g, "\n");
58
- s = s.trim();
59
- return s;
60
- }
61
- chunkOLISEQHS_cjs.__name(sanitizeDraft, "sanitizeDraft");
62
- function isSubmittableDraft(input) {
63
- return sanitizeDraft(input).length > 0;
64
- }
65
- chunkOLISEQHS_cjs.__name(isSubmittableDraft, "isSubmittableDraft");
66
-
67
- // src/tools/Chat/hooks/useChatComposer.ts
68
- var MAX_TEXTAREA_HEIGHT = 240;
69
- function useChatComposer(options) {
70
- const {
71
- onSubmit,
72
- initialValue = "",
73
- maxLength = chunkTBSHZO5R_cjs.LIMITS.messageMaxLength,
74
- maxAttachments = chunkTBSHZO5R_cjs.LIMITS.attachmentsMax,
75
- disabled = false,
76
- submitOn = "enter",
77
- history = { enabled: true, size: chunkTBSHZO5R_cjs.LIMITS.composerHistorySize },
78
- onPasteFiles,
79
- persistKey,
80
- preserveExactValue = false
81
- } = options;
82
- const initialFromStorage = (() => {
83
- if (!persistKey || typeof window === "undefined") return initialValue;
84
- try {
85
- const stored = window.sessionStorage.getItem(`chat:draft:${persistKey}`);
86
- return stored && stored.length > 0 ? stored : initialValue;
87
- } catch {
88
- return initialValue;
89
- }
90
- })();
91
- const [value, setValueState] = react.useState(initialFromStorage);
92
- react.useEffect(() => {
93
- if (!persistKey || typeof window === "undefined") return;
94
- try {
95
- const k = `chat:draft:${persistKey}`;
96
- if (value.length > 0) window.sessionStorage.setItem(k, value);
97
- else window.sessionStorage.removeItem(k);
98
- } catch {
99
- }
100
- }, [value, persistKey]);
101
- const [attachments, setAttachments] = react.useState([]);
102
- const [isSubmitting, setIsSubmitting] = react.useState(false);
103
- const textareaRef = react.useRef(null);
104
- const historyRef = react.useRef({ items: [], index: -1 });
105
- const setValue = react.useCallback(
106
- (next) => {
107
- setValueState(next.length > maxLength ? next.slice(0, maxLength) : next);
108
- },
109
- [maxLength]
110
- );
111
- react.useEffect(() => {
112
- const el = textareaRef.current;
113
- if (!el) return;
114
- el.style.height = "auto";
115
- el.style.height = `${Math.min(el.scrollHeight, MAX_TEXTAREA_HEIGHT)}px`;
116
- }, [value]);
117
- const reset = react.useCallback(() => {
118
- setValueState("");
119
- setAttachments([]);
120
- historyRef.current.index = -1;
121
- }, []);
122
- const focus = react.useCallback(() => {
123
- requestAnimationFrame(() => textareaRef.current?.focus());
124
- }, []);
125
- const submit = react.useCallback(async () => {
126
- const cleaned = preserveExactValue ? value : sanitizeDraft(value);
127
- if (!cleaned && attachments.length === 0 || isSubmitting || disabled) return;
128
- setIsSubmitting(true);
129
- try {
130
- if (history.enabled !== false && cleaned) {
131
- const buf = historyRef.current.items;
132
- if (buf[buf.length - 1] !== cleaned) {
133
- buf.push(cleaned);
134
- if (buf.length > (history.size ?? chunkTBSHZO5R_cjs.LIMITS.composerHistorySize)) buf.shift();
135
- }
136
- historyRef.current.index = -1;
137
- }
138
- const snapshot = [...attachments];
139
- reset();
140
- await onSubmit(cleaned, snapshot);
141
- } finally {
142
- setIsSubmitting(false);
143
- }
144
- }, [value, attachments, isSubmitting, disabled, history, onSubmit, reset, preserveExactValue]);
145
- const addAttachment = react.useCallback(
146
- (a) => {
147
- setAttachments((prev) => {
148
- if (prev.some((p) => p.id === a.id)) {
149
- return prev.map((p) => p.id === a.id ? a : p);
150
- }
151
- if (prev.length >= maxAttachments) return prev;
152
- return [...prev, a];
153
- });
154
- },
155
- [maxAttachments]
156
- );
157
- const removeAttachment = react.useCallback((id) => {
158
- setAttachments((prev) => prev.filter((a) => a.id !== id));
159
- }, []);
160
- const recallPrevious = react.useCallback(() => {
161
- const { items } = historyRef.current;
162
- if (!items.length) return;
163
- const next = historyRef.current.index < 0 ? items.length - 1 : Math.max(0, historyRef.current.index - 1);
164
- historyRef.current.index = next;
165
- setValueState(items[next]);
166
- }, []);
167
- const recallNext = react.useCallback(() => {
168
- const { items } = historyRef.current;
169
- if (!items.length || historyRef.current.index < 0) return;
170
- const next = historyRef.current.index + 1;
171
- if (next >= items.length) {
172
- historyRef.current.index = -1;
173
- setValueState("");
174
- return;
175
- }
176
- historyRef.current.index = next;
177
- setValueState(items[next]);
178
- }, []);
179
- const onChange = react.useCallback(
180
- (e) => {
181
- setValue(e.target.value);
182
- },
183
- [setValue]
184
- );
185
- const onKeyDown = react.useCallback(
186
- (e) => {
187
- if (e.key === "Enter") {
188
- const isCmd = e.metaKey || e.ctrlKey;
189
- const shouldSend = submitOn === "cmd+enter" ? isCmd : !e.shiftKey;
190
- if (shouldSend) {
191
- e.preventDefault();
192
- void submit();
193
- }
194
- return;
195
- }
196
- if (history.enabled !== false && value === "" && attachments.length === 0) {
197
- if (e.key === "ArrowUp") {
198
- e.preventDefault();
199
- recallPrevious();
200
- } else if (e.key === "ArrowDown" && historyRef.current.index >= 0) {
201
- e.preventDefault();
202
- recallNext();
203
- }
204
- }
205
- },
206
- [submitOn, submit, history, value, attachments.length, recallPrevious, recallNext]
207
- );
208
- const onPaste = react.useCallback(
209
- (e) => {
210
- const files = Array.from(e.clipboardData?.files ?? []);
211
- if (files.length && onPasteFiles) {
212
- e.preventDefault();
213
- onPasteFiles(files);
214
- }
215
- },
216
- [onPasteFiles]
217
- );
218
- const canSubmit = !disabled && !isSubmitting && ((preserveExactValue ? value.trim().length : sanitizeDraft(value).length) > 0 || attachments.length > 0);
219
- return {
220
- value,
221
- setValue,
222
- attachments,
223
- addAttachment,
224
- removeAttachment,
225
- isSubmitting,
226
- canSubmit,
227
- submit,
228
- reset,
229
- focus,
230
- textareaRef,
231
- textareaProps: {
232
- ref: textareaRef,
233
- value,
234
- disabled,
235
- onChange,
236
- onKeyDown,
237
- onPaste
238
- },
239
- recallPrevious,
240
- recallNext
241
- };
242
- }
243
- chunkOLISEQHS_cjs.__name(useChatComposer, "useChatComposer");
244
- function useFocusOnEmptyClick(options = {}) {
245
- const { targetRef, enabled = true, skipWhileStreaming = true } = options;
246
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
247
- const composerHandleRef = react.useRef(null);
248
- composerHandleRef.current = ctx?.composer ?? null;
249
- const isStreamingRef = react.useRef(false);
250
- isStreamingRef.current = ctx?.isStreaming ?? false;
251
- return react.useCallback(
252
- (event) => {
253
- if (!enabled) return;
254
- if (skipWhileStreaming && isStreamingRef.current) return;
255
- const pointerType = event.nativeEvent.pointerType;
256
- if (pointerType && pointerType !== "mouse") return;
257
- const selection = typeof window !== "undefined" ? window.getSelection?.() : null;
258
- if (selection && !selection.isCollapsed && selection.toString().length > 0) {
259
- return;
260
- }
261
- const target = event.target;
262
- if (!target) return;
263
- if (isInteractive(target)) return;
264
- const explicit = targetRef?.current;
265
- if (explicit) {
266
- explicit.focus?.();
267
- return;
268
- }
269
- composerHandleRef.current?.focus?.();
270
- },
271
- [enabled, skipWhileStreaming, targetRef]
272
- );
273
- }
274
- chunkOLISEQHS_cjs.__name(useFocusOnEmptyClick, "useFocusOnEmptyClick");
275
- var INTERACTIVE_SELECTORS = [
276
- "a[href]",
277
- "button",
278
- "input",
279
- "textarea",
280
- "select",
281
- "label",
282
- "summary",
283
- '[role="button"]',
284
- '[role="link"]',
285
- '[role="menuitem"]',
286
- '[role="tab"]',
287
- '[contenteditable]:not([contenteditable="false"])',
288
- "[data-no-autofocus]"
289
- ].join(",");
290
- function isInteractive(el) {
291
- if (!el) return false;
292
- return !!el.closest(INTERACTIVE_SELECTORS);
293
- }
294
- chunkOLISEQHS_cjs.__name(isInteractive, "isInteractive");
295
- function useChatBubbleStyles(role, isError) {
296
- return react.useMemo(() => {
297
- const isUser = role === "user";
298
- const variant = isUser ? "user" : isError ? "error" : "assistant";
299
- return {
300
- surface: chunk7IYXZUJO_cjs.BUBBLE_SURFACE[variant],
301
- anchor: isUser ? chunk7IYXZUJO_cjs.ANCHOR.user : chunk7IYXZUJO_cjs.ANCHOR.assistant,
302
- toggle: isUser ? chunk7IYXZUJO_cjs.TOGGLE.user : chunk7IYXZUJO_cjs.TOGGLE.assistant
303
- };
304
- }, [role, isError]);
305
- }
306
- chunkOLISEQHS_cjs.__name(useChatBubbleStyles, "useChatBubbleStyles");
307
- function useChatRoleStyles(isUser) {
308
- return react.useMemo(
309
- () => ({
310
- anchor: isUser ? chunk7IYXZUJO_cjs.ANCHOR.user : chunk7IYXZUJO_cjs.ANCHOR.assistant,
311
- toggle: isUser ? chunk7IYXZUJO_cjs.TOGGLE.user : chunk7IYXZUJO_cjs.TOGGLE.assistant
312
- }),
313
- [isUser]
314
- );
315
- }
316
- chunkOLISEQHS_cjs.__name(useChatRoleStyles, "useChatRoleStyles");
317
- function useChatDestructiveStyles() {
318
- return DESTRUCTIVE_STYLES;
319
- }
320
- chunkOLISEQHS_cjs.__name(useChatDestructiveStyles, "useChatDestructiveStyles");
321
- var DESTRUCTIVE_STYLES = {
322
- banner: chunk7IYXZUJO_cjs.DESTRUCTIVE_SURFACE.banner,
323
- hover: chunk7IYXZUJO_cjs.DESTRUCTIVE_SURFACE.hover,
324
- hoverStrong: chunk7IYXZUJO_cjs.DESTRUCTIVE_SURFACE.hoverStrong,
325
- text: chunk7IYXZUJO_cjs.DESTRUCTIVE_SURFACE.text,
326
- menuItem: chunk7IYXZUJO_cjs.DESTRUCTIVE_SURFACE.menuItem,
327
- toolErrorText: chunk7IYXZUJO_cjs.TOOL_CALL.errorText
328
- };
329
- function AttachmentsGrid({
330
- attachments,
331
- maxVisible,
332
- onClick,
333
- onRemove,
334
- isInComposer = false,
335
- layout = "wrap",
336
- className
337
- }) {
338
- if (!attachments?.length) return null;
339
- const visible = maxVisible ? attachments.slice(0, maxVisible) : attachments;
340
- return /* @__PURE__ */ jsxRuntime.jsx(
341
- "div",
342
- {
343
- className: lib.cn(
344
- layout === "grid" ? "grid grid-cols-3 gap-2" : "flex flex-wrap gap-2",
345
- className
346
- ),
347
- children: visible.map((a) => /* @__PURE__ */ jsxRuntime.jsx(
348
- AttachmentTile,
349
- {
350
- attachment: a,
351
- isInComposer,
352
- onClick: onClick ? () => onClick(a) : void 0,
353
- onRemove: onRemove ? () => onRemove(a) : void 0
354
- },
355
- a.id
356
- ))
357
- }
358
- );
359
- }
360
- chunkOLISEQHS_cjs.__name(AttachmentsGrid, "AttachmentsGrid");
361
- function AttachmentsList({
362
- attachments,
363
- maxVisible,
364
- onClick,
365
- onRemove,
366
- renderers,
367
- isInComposer = false,
368
- className
369
- }) {
370
- if (!attachments?.length) return null;
371
- const visible = maxVisible ? attachments.slice(0, maxVisible) : attachments;
372
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: lib.cn("flex w-full flex-col gap-2", className), children: visible.map((a) => {
373
- const renderer = renderers?.[a.type] ?? renderers?.default;
374
- const args = {
375
- attachment: a,
376
- isInComposer,
377
- onClick: onClick ? () => onClick(a) : void 0,
378
- onRemove: onRemove ? () => onRemove(a) : void 0
379
- };
380
- if (renderer) {
381
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full min-w-0", children: [
382
- renderer(args),
383
- args.onRemove ? /* @__PURE__ */ jsxRuntime.jsx(RemoveBtn, { onRemove: args.onRemove }) : null
384
- ] }, a.id);
385
- }
386
- return /* @__PURE__ */ jsxRuntime.jsx(AttachmentTile, { ...args }, a.id);
387
- }) });
388
- }
389
- chunkOLISEQHS_cjs.__name(AttachmentsList, "AttachmentsList");
390
- function Attachments(props) {
391
- const { renderers, layout, ...rest } = props;
392
- if (renderers) {
393
- return /* @__PURE__ */ jsxRuntime.jsx(AttachmentsList, { ...rest, renderers });
394
- }
395
- return /* @__PURE__ */ jsxRuntime.jsx(AttachmentsGrid, { ...rest, layout: layout === "grid" ? "grid" : "wrap" });
396
- }
397
- chunkOLISEQHS_cjs.__name(Attachments, "Attachments");
398
- function AttachmentTile({ attachment, onClick, onRemove }) {
399
- const isImage = attachment.type === "image";
400
- const isUploading = attachment.status === "uploading";
401
- const inner = isImage ? /* @__PURE__ */ jsxRuntime.jsx(
402
- "img",
403
- {
404
- src: attachment.thumbnailUrl ?? attachment.url,
405
- alt: attachment.name ?? "attachment",
406
- className: "h-16 w-16 rounded-md object-cover",
407
- loading: "lazy"
408
- }
409
- ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-w-44 items-center gap-2 rounded-md border border-border bg-background/60 px-2 py-1.5 text-xs", children: [
410
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.File, { "aria-hidden": true, className: "size-4 shrink-0 text-muted-foreground" }),
411
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: attachment.name ?? "file" })
412
- ] });
413
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
414
- onClick ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick, className: "block", children: inner }) : inner,
415
- isUploading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center rounded-md bg-background/70 text-[10px] font-medium", children: attachment.progress != null ? `${Math.round(attachment.progress * 100)}%` : "\u2026" }) : null,
416
- onRemove ? /* @__PURE__ */ jsxRuntime.jsx(RemoveBtn, { onRemove }) : null
417
- ] });
418
- }
419
- chunkOLISEQHS_cjs.__name(AttachmentTile, "AttachmentTile");
420
- function RemoveBtn({ onRemove }) {
421
- const styles = useChatDestructiveStyles();
422
- return /* @__PURE__ */ jsxRuntime.jsx(
423
- "button",
424
- {
425
- type: "button",
426
- "aria-label": "Remove attachment",
427
- onClick: onRemove,
428
- className: lib.cn(
429
- "absolute -right-1.5 -top-1.5 grid h-4 w-4 place-items-center rounded-full border border-border bg-background text-muted-foreground",
430
- styles.hoverStrong
431
- ),
432
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": true, className: "size-2.5" })
433
- }
434
- );
435
- }
436
- chunkOLISEQHS_cjs.__name(RemoveBtn, "RemoveBtn");
437
- var SIZE_CLASSES = {
438
- sm: {
439
- slot: "[&>:not(textarea)]:h-8",
440
- button: "h-8 w-8",
441
- iconButton: "size-3.5",
442
- textarea: "min-h-8 max-h-48 px-3 py-1.5",
443
- text: "text-sm",
444
- padding: "gap-1.5",
445
- containerPadding: "px-2 pt-1.5 pb-[max(0.375rem,env(safe-area-inset-bottom))]"
446
- },
447
- md: {
448
- slot: "[&>:not(textarea)]:h-9",
449
- button: "h-9 w-9",
450
- iconButton: "size-4",
451
- textarea: "min-h-9 max-h-60 px-3.5 py-2",
452
- text: "text-base sm:text-sm",
453
- padding: "gap-1.5",
454
- containerPadding: "px-2.5 pt-2 pb-[max(0.5rem,env(safe-area-inset-bottom))]"
455
- },
456
- lg: {
457
- slot: "[&>:not(textarea)]:h-12",
458
- button: "h-12 w-12",
459
- iconButton: "size-5",
460
- textarea: "min-h-12 max-h-72 px-4 py-3",
461
- text: "text-base",
462
- padding: "gap-2",
463
- containerPadding: "px-3.5 pt-3 pb-[max(0.875rem,env(safe-area-inset-bottom))]"
464
- }
465
- };
466
- var Composer = react.forwardRef(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(function Composer2({
467
- composer,
468
- placeholder = "Type a message...",
469
- disabled,
470
- showAttachmentButton = false,
471
- onPickFiles,
472
- toolbarStart,
473
- toolbarEnd,
474
- attachmentTray,
475
- className,
476
- textareaClassName,
477
- size = "md",
478
- isStreaming: isStreamingProp,
479
- onCancel: onCancelProp
480
- }, ref) {
481
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
482
- const isStreaming = isStreamingProp ?? ctx?.isStreaming ?? false;
483
- const onCancel = onCancelProp ?? ctx?.cancelStream;
484
- const isDisabled = disabled ?? isStreaming;
485
- const sz = SIZE_CLASSES[size];
486
- const register = ctx?.registerComposer;
487
- const composerFocus = composer.focus;
488
- const composerSetValue = composer.setValue;
489
- const textareaRef = composer.textareaRef;
490
- const getValueRef = react.useRef(() => composer.value);
491
- getValueRef.current = () => composer.value;
492
- react.useEffect(() => {
493
- if (!register) return;
494
- register({
495
- focus: composerFocus,
496
- moveCursorToEnd: /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
497
- const el = textareaRef.current;
498
- if (!el) return;
499
- const end = el.value.length;
500
- el.setSelectionRange(end, end);
501
- }, "moveCursorToEnd"),
502
- getValue: /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => getValueRef.current(), "getValue"),
503
- setValue: composerSetValue
504
- });
505
- return () => register(null);
506
- }, [register, composerFocus, composerSetValue, textareaRef]);
507
- return /* @__PURE__ */ jsxRuntime.jsxs(
508
- "div",
509
- {
510
- ref,
511
- className: lib.cn(
512
- "border-t border-border bg-background/95",
513
- sz.containerPadding,
514
- className
515
- ),
516
- children: [
517
- composer.attachments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1.5", children: attachmentTray ?? /* @__PURE__ */ jsxRuntime.jsx(
518
- Attachments,
519
- {
520
- attachments: composer.attachments,
521
- onRemove: (a) => composer.removeAttachment(a.id)
522
- }
523
- ) }) : null,
524
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex items-end [&>:not(textarea)]:shrink-0", sz.padding, sz.slot), children: [
525
- showAttachmentButton ? /* @__PURE__ */ jsxRuntime.jsx(
526
- components.Button,
527
- {
528
- type: "button",
529
- variant: "ghost",
530
- size: "icon",
531
- onClick: onPickFiles,
532
- "aria-label": "Attach files",
533
- disabled: isDisabled,
534
- className: sz.button,
535
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { "aria-hidden": true, className: sz.iconButton })
536
- }
537
- ) : null,
538
- toolbarStart,
539
- /* @__PURE__ */ jsxRuntime.jsx(
540
- components.Textarea,
541
- {
542
- ...composer.textareaProps,
543
- rows: 1,
544
- placeholder,
545
- "aria-label": placeholder,
546
- "aria-multiline": "true",
547
- disabled: isDisabled,
548
- className: lib.cn(
549
- "flex-1 resize-none rounded-2xl",
550
- sz.textarea,
551
- sz.text,
552
- textareaClassName
553
- )
554
- }
555
- ),
556
- toolbarEnd,
557
- isStreaming ? /* @__PURE__ */ jsxRuntime.jsx(
558
- components.Button,
559
- {
560
- type: "button",
561
- variant: "secondary",
562
- size: "icon",
563
- onClick: onCancel,
564
- "aria-label": "Stop",
565
- "aria-keyshortcuts": "Escape",
566
- className: sz.button,
567
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { "aria-hidden": true, className: sz.iconButton })
568
- }
569
- ) : /* @__PURE__ */ jsxRuntime.jsx(
570
- components.Button,
571
- {
572
- type: "button",
573
- size: "icon",
574
- onClick: () => void composer.submit(),
575
- disabled: !composer.canSubmit,
576
- "aria-label": "Send",
577
- "aria-keyshortcuts": "Enter",
578
- className: sz.button,
579
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { "aria-hidden": true, className: sz.iconButton })
580
- }
581
- )
582
- ] })
583
- ]
584
- }
585
- );
586
- }, "Composer"));
587
- function EmptyState({
588
- greeting,
589
- description,
590
- suggestions,
591
- onPickSuggestion,
592
- className
593
- }) {
594
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex flex-col items-center gap-3 px-4 py-12 text-center", className), children: [
595
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid size-10 place-items-center rounded-full bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { "aria-hidden": true, className: "size-5 text-muted-foreground" }) }),
596
- greeting ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold", children: greeting }) : null,
597
- description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-sm text-muted-foreground", children: description }) : null,
598
- suggestions?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 grid w-full max-w-md grid-cols-1 gap-2 sm:grid-cols-2", children: suggestions.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
599
- "button",
600
- {
601
- type: "button",
602
- onClick: () => onPickSuggestion?.(s.prompt),
603
- className: "rounded-lg border border-border bg-background/60 px-3 py-2 text-left text-xs hover:bg-accent",
604
- children: s.label
605
- },
606
- s.prompt
607
- )) }) : null
608
- ] });
609
- }
610
- chunkOLISEQHS_cjs.__name(EmptyState, "EmptyState");
611
- function ErrorBanner({ error, onDismiss, onRetry, className }) {
612
- const styles = useChatDestructiveStyles();
613
- if (!error) return null;
614
- return /* @__PURE__ */ jsxRuntime.jsxs(
615
- "div",
616
- {
617
- role: "alert",
618
- className: lib.cn(
619
- "mx-2.5 my-2 flex items-start gap-2 rounded-md px-3 py-2 text-xs",
620
- styles.banner,
621
- className
622
- ),
623
- children: [
624
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0" }),
625
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 break-words", children: error }),
626
- onRetry ? /* @__PURE__ */ jsxRuntime.jsxs(
627
- "button",
628
- {
629
- type: "button",
630
- onClick: onRetry,
631
- className: lib.cn("inline-flex items-center gap-1 rounded px-1.5 py-0.5", styles.hover),
632
- children: [
633
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { "aria-hidden": true, className: "size-3" }),
634
- " Retry"
635
- ]
636
- }
637
- ) : null,
638
- onDismiss ? /* @__PURE__ */ jsxRuntime.jsx(
639
- "button",
640
- {
641
- type: "button",
642
- "aria-label": "Dismiss",
643
- onClick: onDismiss,
644
- className: lib.cn("rounded p-0.5", styles.hover),
645
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": true, className: "size-3" })
646
- }
647
- ) : null
648
- ]
649
- }
650
- );
651
- }
652
- chunkOLISEQHS_cjs.__name(ErrorBanner, "ErrorBanner");
653
- function JumpToLatest({ visible, unreadCount = 0, onClick, className }) {
654
- if (!visible) return null;
655
- return /* @__PURE__ */ jsxRuntime.jsxs(
656
- "button",
657
- {
658
- type: "button",
659
- onClick,
660
- "aria-live": "polite",
661
- className: lib.cn(
662
- "pointer-events-auto inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-3 py-1 text-xs shadow-md hover:bg-accent",
663
- className
664
- ),
665
- children: [
666
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { "aria-hidden": true, className: "size-3.5" }),
667
- unreadCount > 0 ? `${unreadCount} new` : "Jump to latest"
668
- ]
669
- }
670
- );
671
- }
672
- chunkOLISEQHS_cjs.__name(JumpToLatest, "JumpToLatest");
673
-
674
- // src/tools/Chat/core/persona.ts
675
- var FALLBACK_USER = { name: "You", initials: "You" };
676
- var FALLBACK_ASSISTANT = { name: "AI", initials: "AI" };
677
- function resolvePersona(message, user, assistant) {
678
- if (message.sender) return message.sender;
679
- if (message.role === "user") return user ?? FALLBACK_USER;
680
- if (message.role === "assistant") return assistant ?? FALLBACK_ASSISTANT;
681
- return { name: message.role };
682
- }
683
- chunkOLISEQHS_cjs.__name(resolvePersona, "resolvePersona");
684
- function deriveInitials(persona, role) {
685
- if (persona.initials) return persona.initials;
686
- if (persona.name) {
687
- const parts = persona.name.trim().split(/\s+/);
688
- if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
689
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
690
- }
691
- if (role === "user") return "You";
692
- if (role === "assistant") return "AI";
693
- return "?";
694
- }
695
- chunkOLISEQHS_cjs.__name(deriveInitials, "deriveInitials");
696
- function StreamingIndicatorRaw({ variant = "dots", label, className }) {
697
- return /* @__PURE__ */ jsxRuntime.jsxs(
698
- "span",
699
- {
700
- className: lib.cn("inline-flex items-center gap-1.5 text-xs text-muted-foreground", className),
701
- "aria-live": "off",
702
- children: [
703
- variant === "dots" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex gap-0.5", "aria-hidden": true, children: [
704
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1 animate-bounce rounded-full bg-current [animation-delay:-0.2s]" }),
705
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1 animate-bounce rounded-full bg-current [animation-delay:-0.1s]" }),
706
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1 animate-bounce rounded-full bg-current" })
707
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block size-1.5 animate-pulse rounded-full bg-current", "aria-hidden": true }),
708
- label ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic", children: label }) : null
709
- ]
710
- }
711
- );
712
- }
713
- chunkOLISEQHS_cjs.__name(StreamingIndicatorRaw, "StreamingIndicatorRaw");
714
- var StreamingIndicator = react.memo(StreamingIndicatorRaw);
715
- function Sources({ sources, layout = "inline", maxVisible, onClick, className }) {
716
- if (!sources?.length) return null;
717
- const visible = maxVisible ? sources.slice(0, maxVisible) : sources;
718
- const remaining = maxVisible ? Math.max(0, sources.length - maxVisible) : 0;
719
- return /* @__PURE__ */ jsxRuntime.jsxs(
720
- "div",
721
- {
722
- className: lib.cn(
723
- "mt-2 flex flex-wrap gap-1.5",
724
- layout === "grid" && "grid grid-cols-2",
725
- className
726
- ),
727
- children: [
728
- visible.map((s, i) => {
729
- const handle = onClick ? () => onClick(s) : void 0;
730
- const Tag = handle ? "button" : "a";
731
- const props = handle ? { type: "button", onClick: handle } : { href: s.url, target: "_blank", rel: "noopener noreferrer" };
732
- return /* @__PURE__ */ jsxRuntime.jsxs(
733
- Tag,
734
- {
735
- ...props,
736
- className: "inline-flex max-w-full items-center gap-1 rounded-md border border-border bg-background/60 px-2 py-1 text-xs text-foreground/80 hover:bg-accent hover:text-foreground",
737
- title: s.snippet ?? s.title,
738
- children: [
739
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: s.title || s.url }),
740
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { "aria-hidden": true, className: "size-3 shrink-0 opacity-60" })
741
- ]
742
- },
743
- `${s.url}-${i}`
744
- );
745
- }),
746
- remaining > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center rounded-md border border-dashed border-border px-2 py-1 text-xs text-muted-foreground", children: [
747
- "+",
748
- remaining
749
- ] }) : null
750
- ]
751
- }
752
- );
753
- }
754
- chunkOLISEQHS_cjs.__name(Sources, "Sources");
755
- function ToolCalls({
756
- calls,
757
- defaultExpanded = false,
758
- expandWhileStreaming = true,
759
- renderInput,
760
- renderOutput,
761
- renderStreaming,
762
- renderPayload,
763
- renderAfterCalls,
764
- renderToolCall,
765
- hideToolCalls = false,
766
- className
767
- }) {
768
- if (!calls?.length) return null;
769
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("mt-2 space-y-1.5", className), children: [
770
- !hideToolCalls && calls.map(
771
- (call) => renderToolCall ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderToolCall(call) }, call.id) : /* @__PURE__ */ jsxRuntime.jsx(
772
- ToolCallItem,
773
- {
774
- call,
775
- defaultExpanded,
776
- expandWhileStreaming,
777
- renderInput,
778
- renderOutput,
779
- renderStreaming,
780
- renderPayload
781
- },
782
- call.id
783
- )
784
- ),
785
- renderAfterCalls ? renderAfterCalls(calls) : null
786
- ] });
787
- }
788
- chunkOLISEQHS_cjs.__name(ToolCalls, "ToolCalls");
789
- var ToolCallItem = react.memo(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(function ToolCallItem2({
790
- call,
791
- defaultExpanded,
792
- expandWhileStreaming,
793
- renderInput,
794
- renderOutput,
795
- renderStreaming,
796
- renderPayload
797
- }) {
798
- const isRunning = call.status === "running";
799
- const initialOpen = defaultExpanded || expandWhileStreaming && isRunning;
800
- const [open, setOpen] = react.useState(initialOpen);
801
- const userToggledRef = react.useRef(false);
802
- const wasRunningRef = react.useRef(isRunning);
803
- react.useEffect(() => {
804
- if (wasRunningRef.current && !isRunning) {
805
- if (!userToggledRef.current && !defaultExpanded) {
806
- setOpen(false);
807
- }
808
- }
809
- wasRunningRef.current = isRunning;
810
- }, [isRunning, defaultExpanded]);
811
- const handleToggle = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
812
- userToggledRef.current = true;
813
- setOpen((v) => !v);
814
- }, "handleToggle");
815
- const Icon = open ? lucideReact.ChevronDown : lucideReact.ChevronRight;
816
- const statusColor = call.status === "success" ? "text-emerald-500" : call.status === "error" ? "text-destructive" : call.status === "cancelled" ? "text-muted-foreground" : "text-amber-500";
817
- const renderValue = /* @__PURE__ */ chunkOLISEQHS_cjs.__name((value, kind) => {
818
- if (kind === "input" && renderInput) return renderInput(value, call);
819
- if (kind === "output" && renderOutput) return renderOutput(value, call);
820
- if (kind === "streaming" && renderStreaming)
821
- return renderStreaming(typeof value === "string" ? value : String(value), call);
822
- if (renderPayload) return renderPayload(value, kind, call);
823
- return /* @__PURE__ */ jsxRuntime.jsx(DefaultPayload, { value, kind });
824
- }, "renderValue");
825
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-md border border-border bg-muted/30", children: [
826
- /* @__PURE__ */ jsxRuntime.jsxs(
827
- "button",
828
- {
829
- type: "button",
830
- onClick: handleToggle,
831
- "aria-expanded": open,
832
- className: "flex w-full items-center gap-2 px-2 py-1.5 text-left text-xs hover:bg-muted/60",
833
- children: [
834
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: "size-3 shrink-0 text-muted-foreground" }),
835
- isRunning ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { "aria-hidden": true, className: "size-3 shrink-0 animate-spin text-amber-500" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn("size-2 shrink-0 rounded-full", statusColor.replace("text-", "bg-")) }),
836
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-foreground", children: call.name }),
837
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn("ml-auto", statusColor), children: call.status })
838
- ]
839
- }
840
- ),
841
- open ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-t border-border px-2 py-1.5 text-[11px]", children: [
842
- call.input != null ? renderValue(call.input, "input") : null,
843
- call.streamingText != null ? renderValue(call.streamingText, "streaming") : call.output !== void 0 ? renderValue(call.output, "output") : null
844
- ] }) : null
845
- ] });
846
- }, "ToolCallItem"), (prev, next) => {
847
- const a = prev.call;
848
- const b = next.call;
849
- return a.id === b.id && a.status === b.status && a.output === b.output && a.streamingText === b.streamingText && prev.defaultExpanded === next.defaultExpanded && prev.expandWhileStreaming === next.expandWhileStreaming && prev.renderInput === next.renderInput && prev.renderOutput === next.renderOutput && prev.renderStreaming === next.renderStreaming && prev.renderPayload === next.renderPayload;
850
- });
851
- function DefaultPayload({ value, kind }) {
852
- const isStreamingOrString = kind === "streaming" || typeof value === "string";
853
- const muted = kind === "input";
854
- return /* @__PURE__ */ jsxRuntime.jsx(
855
- "pre",
856
- {
857
- className: lib.cn(
858
- "overflow-auto rounded bg-background/60 p-1.5 font-mono",
859
- kind === "input" ? "max-h-32" : "max-h-48",
860
- muted ? "text-muted-foreground" : "text-foreground/90"
861
- ),
862
- children: isStreamingOrString ? String(value) : safeStringify(value)
863
- }
864
- );
865
- }
866
- chunkOLISEQHS_cjs.__name(DefaultPayload, "DefaultPayload");
867
- function safeStringify(value) {
868
- try {
869
- return JSON.stringify(value, null, 2);
870
- } catch {
871
- return String(value);
872
- }
873
- }
874
- chunkOLISEQHS_cjs.__name(safeStringify, "safeStringify");
875
- function MessageActionsRaw({
876
- role,
877
- onCopy,
878
- onRegenerate,
879
- onEdit,
880
- onDelete,
881
- hideOn,
882
- className
883
- }) {
884
- if (hideOn?.includes(role)) return null;
885
- return /* @__PURE__ */ jsxRuntime.jsxs(
886
- "div",
887
- {
888
- className: lib.cn(
889
- "mt-1 flex items-center gap-0.5 opacity-0 transition-opacity group-hover/msg:opacity-100 focus-within:opacity-100",
890
- className
891
- ),
892
- children: [
893
- onCopy ? /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { onClick: onCopy, label: "Copy", icon: lucideReact.Copy }) : null,
894
- onRegenerate && role === "assistant" ? /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { onClick: onRegenerate, label: "Regenerate", icon: lucideReact.RefreshCw }) : null,
895
- onEdit && role === "user" ? /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { onClick: onEdit, label: "Edit", icon: lucideReact.Pencil }) : null,
896
- onDelete ? /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { onClick: onDelete, label: "Delete", icon: lucideReact.Trash, destructive: true }) : null
897
- ]
898
- }
899
- );
900
- }
901
- chunkOLISEQHS_cjs.__name(MessageActionsRaw, "MessageActionsRaw");
902
- var ActionButton = react.memo(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(function ActionButton2({
903
- onClick,
904
- label,
905
- icon: Icon,
906
- destructive
907
- }) {
908
- const styles = useChatDestructiveStyles();
909
- return /* @__PURE__ */ jsxRuntime.jsx(
910
- "button",
911
- {
912
- type: "button",
913
- onClick,
914
- "aria-label": label,
915
- className: lib.cn(
916
- "rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
917
- destructive && lib.cn(styles.hover, "hover:text-destructive")
918
- ),
919
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: "size-3" })
920
- }
921
- );
922
- }, "ActionButton"));
923
- var MessageActions = react.memo(MessageActionsRaw);
924
- var MessageBubbleInner = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(({
925
- message,
926
- isUser: isUserProp,
927
- showAvatar = true,
928
- avatarSrc,
929
- avatarFallback,
930
- user,
931
- assistant,
932
- showTimestamp = false,
933
- showActions = true,
934
- isCompact = false,
935
- className,
936
- beforeContent,
937
- afterContent,
938
- toolCallsRenderer,
939
- toolCallsProps,
940
- sourcesRenderer,
941
- attachmentsRenderer,
942
- attachmentRenderers,
943
- onAttachmentOpen,
944
- onCopy,
945
- onRegenerate,
946
- onEdit,
947
- onDelete,
948
- messageActionsExtra,
949
- streamingIndicator
950
- }) => {
951
- const isUser = isUserProp ?? message.role === "user";
952
- const isStreaming = !!message.isStreaming;
953
- const isErr = !!message.isError;
954
- const { surface: bubbleSurface } = useChatBubbleStyles(
955
- isUser ? "user" : "assistant",
956
- isErr
957
- );
958
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
959
- const persona = resolvePersona(
960
- message,
961
- user ?? ctx?.config.user,
962
- assistant ?? ctx?.config.assistant
963
- );
964
- const initials = deriveInitials(persona, message.role);
965
- const personaName = persona.name ?? (isUser ? "You" : "Assistant");
966
- return /* @__PURE__ */ jsxRuntime.jsxs(
967
- "div",
968
- {
969
- role: "article",
970
- "aria-label": `${personaName} said: ${message.content.slice(0, 80)}`,
971
- "aria-busy": isStreaming || void 0,
972
- "data-role": message.role,
973
- className: lib.cn(
974
- "group/msg flex gap-2.5 px-2.5 py-2",
975
- isUser ? "flex-row-reverse" : "flex-row",
976
- className
977
- ),
978
- children: [
979
- showAvatar ? /* @__PURE__ */ jsxRuntime.jsxs(
980
- components.Avatar,
981
- {
982
- className: "size-7 shrink-0",
983
- title: persona.description ?? personaName,
984
- children: [
985
- avatarSrc || persona.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(components.AvatarImage, { src: avatarSrc ?? persona.avatarUrl, alt: personaName }) : null,
986
- /* @__PURE__ */ jsxRuntime.jsx(components.AvatarFallback, { className: "text-[10px]", children: avatarFallback ?? initials })
987
- ]
988
- }
989
- ) : null,
990
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("min-w-0 flex-1", isUser && "flex flex-col items-end"), children: [
991
- beforeContent,
992
- message.attachments?.length ? attachmentsRenderer ? attachmentsRenderer(message.attachments) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1.5 w-full", children: attachmentRenderers ? /* @__PURE__ */ jsxRuntime.jsx(
993
- AttachmentsList,
994
- {
995
- attachments: message.attachments,
996
- renderers: attachmentRenderers,
997
- onClick: onAttachmentOpen,
998
- className: isUser ? "items-end" : void 0
999
- }
1000
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1001
- AttachmentsGrid,
1002
- {
1003
- attachments: message.attachments,
1004
- onClick: onAttachmentOpen,
1005
- className: isUser ? "justify-end" : void 0
1006
- }
1007
- ) }) : null,
1008
- /* @__PURE__ */ jsxRuntime.jsxs(
1009
- "div",
1010
- {
1011
- className: lib.cn(
1012
- "inline-block max-w-full rounded-2xl px-3.5 py-2 text-sm",
1013
- bubbleSurface
1014
- ),
1015
- children: [
1016
- isStreaming && message.toolActivity ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1.5", children: streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, { label: message.toolActivity }) }) : null,
1017
- message.content || !isStreaming ? /* @__PURE__ */ jsxRuntime.jsx(
1018
- chunk7IYXZUJO_cjs.MarkdownMessage,
1019
- {
1020
- content: message.content || (isErr ? "*Failed to generate a response.*" : ""),
1021
- isUser,
1022
- isCompact,
1023
- plainText: isStreaming
1024
- }
1025
- ) : streamingIndicator ? streamingIndicator(message) : /* @__PURE__ */ jsxRuntime.jsx(StreamingIndicator, {})
1026
- ]
1027
- }
1028
- ),
1029
- message.toolCalls?.length ? toolCallsRenderer ? toolCallsRenderer(message.toolCalls) : /* @__PURE__ */ jsxRuntime.jsx(ToolCalls, { calls: message.toolCalls, ...toolCallsProps }) : null,
1030
- message.sources?.length && !isStreaming ? sourcesRenderer ? sourcesRenderer(message.sources) : /* @__PURE__ */ jsxRuntime.jsx(Sources, { sources: message.sources }) : null,
1031
- showActions && !isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
1032
- /* @__PURE__ */ jsxRuntime.jsx(
1033
- MessageActions,
1034
- {
1035
- role: message.role,
1036
- onCopy,
1037
- onRegenerate,
1038
- onEdit,
1039
- onDelete
1040
- }
1041
- ),
1042
- messageActionsExtra ? messageActionsExtra(message) : null
1043
- ] }) : null,
1044
- showTimestamp ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-[10px] text-muted-foreground", children: new Date(message.createdAt).toLocaleTimeString() }) : null,
1045
- afterContent
1046
- ] })
1047
- ]
1048
- }
1049
- );
1050
- }, "MessageBubbleInner");
1051
- var MessageBubble = react.memo(MessageBubbleInner, (prev, next) => {
1052
- const a = prev.message;
1053
- const b = next.message;
1054
- return a.id === b.id && a.content === b.content && a.isStreaming === b.isStreaming && a.isError === b.isError && (a.version ?? 0) === (b.version ?? 0) && a.toolActivity === b.toolActivity && a.toolCalls === b.toolCalls && a.sources === b.sources && a.attachments === b.attachments;
1055
- });
1056
- MessageBubble.displayName = "MessageBubble";
1057
- var MessageList = react.forwardRef(/* @__PURE__ */ chunkOLISEQHS_cjs.__name(function MessageList2({
1058
- messages: messagesProp,
1059
- renderItem,
1060
- renderEmpty,
1061
- isLoadingMore: isLoadingMoreProp,
1062
- onStartReached,
1063
- className,
1064
- itemClassName,
1065
- noVirtualize = false,
1066
- defaultItemHeight: _deprecatedDefaultItemHeight,
1067
- onAtBottomChange,
1068
- atBottomThreshold = 120,
1069
- scrollAnchorId
1070
- }, ref) {
1071
- const ctx = chunkTBSHZO5R_cjs.useChatContextOptional();
1072
- const messages = messagesProp ?? ctx?.messages ?? [];
1073
- const isLoadingMore = isLoadingMoreProp ?? ctx?.isLoadingMore ?? false;
1074
- const { copyToClipboard } = hooks.useCopy();
1075
- const virtuosoRef = react.useRef(null);
1076
- const scrollerRef = react.useRef(null);
1077
- const [isScrollable, setIsScrollable] = react.useState(false);
1078
- const lastReportedAtBottomRef = react.useRef(null);
1079
- const reportAtBottom = react.useCallback(
1080
- (value) => {
1081
- if (lastReportedAtBottomRef.current === value) return;
1082
- lastReportedAtBottomRef.current = value;
1083
- onAtBottomChange?.(value);
1084
- },
1085
- [onAtBottomChange]
1086
- );
1087
- const didInitialScrollRef = react.useRef(false);
1088
- react.useImperativeHandle(
1089
- ref,
1090
- () => ({
1091
- scrollToBottom: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((smooth = false) => {
1092
- virtuosoRef.current?.scrollToIndex({
1093
- index: "LAST",
1094
- behavior: smooth ? "smooth" : "auto",
1095
- align: "end"
1096
- });
1097
- }, "scrollToBottom"),
1098
- scrollToIndex: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((index, smooth = false) => {
1099
- virtuosoRef.current?.scrollToIndex({
1100
- index,
1101
- behavior: smooth ? "smooth" : "auto"
1102
- });
1103
- }, "scrollToIndex")
1104
- }),
1105
- []
1106
- );
1107
- const defaultRenderItem = react.useCallback(
1108
- (m) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: itemClassName, children: /* @__PURE__ */ jsxRuntime.jsx(
1109
- MessageBubble,
1110
- {
1111
- message: m,
1112
- onCopy: () => void copyToClipboard(m.content),
1113
- onRegenerate: ctx ? () => void ctx.regenerate(m.id) : void 0,
1114
- onDelete: ctx ? () => ctx.deleteMessage(m.id) : void 0
1115
- }
1116
- ) }),
1117
- [itemClassName, ctx, copyToClipboard]
1118
- );
1119
- const itemRenderer = renderItem ?? defaultRenderItem;
1120
- react.useEffect(() => {
1121
- if (didInitialScrollRef.current) return;
1122
- if (messages.length === 0) return;
1123
- didInitialScrollRef.current = true;
1124
- const id = requestAnimationFrame(() => {
1125
- virtuosoRef.current?.scrollToIndex({
1126
- index: "LAST",
1127
- align: "end",
1128
- behavior: "auto"
1129
- });
1130
- });
1131
- return () => cancelAnimationFrame(id);
1132
- }, [messages.length]);
1133
- react.useEffect(() => {
1134
- if (scrollAnchorId == null) return;
1135
- if (!didInitialScrollRef.current) return;
1136
- let raf1 = 0;
1137
- let raf2 = 0;
1138
- raf1 = requestAnimationFrame(() => {
1139
- raf2 = requestAnimationFrame(() => {
1140
- virtuosoRef.current?.scrollToIndex({
1141
- index: "LAST",
1142
- align: "end",
1143
- behavior: "smooth"
1144
- });
1145
- });
1146
- });
1147
- return () => {
1148
- cancelAnimationFrame(raf1);
1149
- cancelAnimationFrame(raf2);
1150
- };
1151
- }, [scrollAnchorId]);
1152
- react.useEffect(() => {
1153
- const el = scrollerRef.current;
1154
- if (!el || el === window || !(el instanceof HTMLElement)) return;
1155
- const probe = /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => {
1156
- const scrollable = el.scrollHeight > el.clientHeight + 1;
1157
- setIsScrollable(scrollable);
1158
- if (!scrollable) reportAtBottom(true);
1159
- }, "probe");
1160
- probe();
1161
- const ro = new ResizeObserver(probe);
1162
- ro.observe(el);
1163
- return () => ro.disconnect();
1164
- }, [reportAtBottom, messages.length]);
1165
- const computeItemKey = react.useCallback(
1166
- (index, m) => m?.id ?? index,
1167
- []
1168
- );
1169
- const startReachedHandler = react.useMemo(() => {
1170
- if (!onStartReached) return void 0;
1171
- let inFlight = false;
1172
- return () => {
1173
- if (inFlight || isLoadingMore) return;
1174
- inFlight = true;
1175
- try {
1176
- onStartReached();
1177
- } finally {
1178
- queueMicrotask(() => {
1179
- inFlight = false;
1180
- });
1181
- }
1182
- };
1183
- }, [onStartReached, isLoadingMore]);
1184
- if (messages.length === 0) {
1185
- return /* @__PURE__ */ jsxRuntime.jsx(
1186
- "div",
1187
- {
1188
- role: "log",
1189
- "aria-live": "polite",
1190
- "aria-atomic": "false",
1191
- className: lib.cn("flex-1 overflow-y-auto", className),
1192
- children: renderEmpty?.() ?? null
1193
- }
1194
- );
1195
- }
1196
- if (noVirtualize) {
1197
- return /* @__PURE__ */ jsxRuntime.jsxs(
1198
- "div",
1199
- {
1200
- role: "log",
1201
- "aria-live": "polite",
1202
- "aria-atomic": "false",
1203
- className: lib.cn("flex-1 overflow-y-auto", className),
1204
- children: [
1205
- isLoadingMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(components.Spinner, { className: "size-4 text-muted-foreground" }) }) : null,
1206
- messages.map((m, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: itemRenderer(m, i) }, m.id ?? i))
1207
- ]
1208
- }
1209
- );
1210
- }
1211
- return /* @__PURE__ */ jsxRuntime.jsx(
1212
- reactVirtuoso.Virtuoso,
1213
- {
1214
- ref: virtuosoRef,
1215
- role: "log",
1216
- "aria-live": "polite",
1217
- "aria-atomic": "false",
1218
- className: lib.cn("flex-1", className),
1219
- data: messages,
1220
- computeItemKey,
1221
- itemContent: (index, m) => m ? itemRenderer(m, index) : null,
1222
- initialTopMostItemIndex: messages.length > 0 ? messages.length - 1 : 0,
1223
- atBottomThreshold,
1224
- followOutput: (isAtBottom) => isAtBottom ? "auto" : false,
1225
- scrollerRef: (el) => {
1226
- scrollerRef.current = el;
1227
- },
1228
- atBottomStateChange: (atBottom) => {
1229
- reportAtBottom(!isScrollable ? true : atBottom);
1230
- },
1231
- startReached: startReachedHandler,
1232
- components: isLoadingMore ? {
1233
- Header: /* @__PURE__ */ chunkOLISEQHS_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntime.jsx(components.Spinner, { className: "size-4 text-muted-foreground" }) }), "Header")
1234
- } : EMPTY_COMPONENTS
1235
- }
1236
- );
1237
- }, "MessageList"));
1238
- var EMPTY_COMPONENTS = {};
1239
- function ChatRoot(props) {
1240
- const { transport, config, initialSessionId, autoCreateSession, streaming, audio, debug, className, listClassName, ...slots } = props;
1241
- return /* @__PURE__ */ jsxRuntime.jsx(
1242
- chunkTBSHZO5R_cjs.ChatProvider,
1243
- {
1244
- transport,
1245
- config,
1246
- initialSessionId,
1247
- autoCreateSession,
1248
- streaming,
1249
- audio,
1250
- debug,
1251
- children: /* @__PURE__ */ jsxRuntime.jsx(ChatRootShell, { className, listClassName, slots })
1252
- }
1253
- );
1254
- }
1255
- chunkOLISEQHS_cjs.__name(ChatRoot, "ChatRoot");
1256
- function ChatRootShell({ className, listClassName, slots }) {
1257
- const chat = chunkTBSHZO5R_cjs.useChatContext();
1258
- const composer = useChatComposer({
1259
- onSubmit: /* @__PURE__ */ chunkOLISEQHS_cjs.__name((content, attachments) => chat.sendMessage(content, attachments), "onSubmit"),
1260
- disabled: chat.isStreaming
1261
- });
1262
- const onMessagesMouseUp = useFocusOnEmptyClick({
1263
- enabled: slots.focusOnEmptyClick !== false
1264
- });
1265
- useAutoFocusOnStreamEnd();
1266
- const listRef = react.useRef(null);
1267
- const [isAtBottom, setIsAtBottom] = react.useState(true);
1268
- const lastUserMessageId = react.useMemo(() => {
1269
- const msgs = chat.messages;
1270
- for (let i = msgs.length - 1; i >= 0; i -= 1) {
1271
- if (msgs[i].role === "user") return msgs[i].id;
1272
- }
1273
- return null;
1274
- }, [chat.messages]);
1275
- const handleStartReached = chat.hasMore && !chat.isLoadingMore ? () => void chat.loadMore() : void 0;
1276
- const greeting = chat.config.greeting ?? "How can I help?";
1277
- const description = chat.config.description;
1278
- const suggestions = chat.config.suggestions;
1279
- const headerNode = slots.renderHeader ? slots.renderHeader(chat) : slots.header;
1280
- const emptyNode = slots.empty ?? (slots.renderEmpty ? slots.renderEmpty({ setValue: composer.setValue, focus: composer.focus }) : /* @__PURE__ */ jsxRuntime.jsx(
1281
- EmptyState,
1282
- {
1283
- greeting,
1284
- description,
1285
- suggestions,
1286
- onPickSuggestion: (prompt) => {
1287
- composer.setValue(prompt);
1288
- composer.focus();
1289
- }
1290
- }
1291
- ));
1292
- const renderItem = slots.renderMessage ?? ((m) => /* @__PURE__ */ jsxRuntime.jsx(
1293
- MessageBubble,
1294
- {
1295
- message: m,
1296
- toolCallsProps: slots.toolCallsProps,
1297
- attachmentRenderers: slots.attachmentRenderers,
1298
- onAttachmentOpen: slots.onAttachmentOpen,
1299
- onCopy: () => copy(m.content),
1300
- onRegenerate: () => void chat.regenerate(m.id),
1301
- onDelete: () => chat.deleteMessage(m.id)
1302
- },
1303
- m.id
1304
- ));
1305
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("relative flex h-full min-h-0 flex-col overflow-hidden", className), children: [
1306
- slots.banner ?? null,
1307
- headerNode ?? null,
1308
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col", onMouseUp: onMessagesMouseUp, children: [
1309
- /* @__PURE__ */ jsxRuntime.jsx(
1310
- ErrorBanner,
1311
- {
1312
- error: chat.error,
1313
- onDismiss: chat.error ? () => chat.clearMessages() : void 0,
1314
- onRetry: chat.error ? () => void chat.regenerate() : void 0
1315
- }
1316
- ),
1317
- /* @__PURE__ */ jsxRuntime.jsx(
1318
- MessageList,
1319
- {
1320
- ref: listRef,
1321
- renderItem,
1322
- renderEmpty: () => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyNode }),
1323
- className: listClassName,
1324
- onStartReached: handleStartReached,
1325
- onAtBottomChange: setIsAtBottom,
1326
- scrollAnchorId: lastUserMessageId
1327
- }
1328
- ),
1329
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 flex justify-center", children: slots.jumpToLatest ?? /* @__PURE__ */ jsxRuntime.jsx(
1330
- JumpToLatest,
1331
- {
1332
- visible: !isAtBottom,
1333
- onClick: () => listRef.current?.scrollToBottom(true)
1334
- }
1335
- ) })
1336
- ] }),
1337
- !slots.hideComposer && /* @__PURE__ */ jsxRuntime.jsx(
1338
- Composer,
1339
- {
1340
- composer,
1341
- placeholder: chat.config.placeholder,
1342
- showAttachmentButton: slots.showAttachmentButton,
1343
- onPickFiles: slots.onPickFiles,
1344
- toolbarStart: slots.composerToolbarStart,
1345
- toolbarEnd: slots.composerToolbarEnd,
1346
- attachmentTray: slots.composerAttachmentTray,
1347
- size: slots.composerSize
1348
- }
1349
- ),
1350
- slots.footer ?? null
1351
- ] });
1352
- }
1353
- chunkOLISEQHS_cjs.__name(ChatRootShell, "ChatRootShell");
1354
- function copy(text) {
1355
- if (typeof navigator !== "undefined" && navigator.clipboard) {
1356
- void navigator.clipboard.writeText(text);
1357
- }
1358
- }
1359
- chunkOLISEQHS_cjs.__name(copy, "copy");
1360
-
1361
- exports.Attachments = Attachments;
1362
- exports.AttachmentsGrid = AttachmentsGrid;
1363
- exports.AttachmentsList = AttachmentsList;
1364
- exports.ChatRoot = ChatRoot;
1365
- exports.Composer = Composer;
1366
- exports.EmptyState = EmptyState;
1367
- exports.ErrorBanner = ErrorBanner;
1368
- exports.JumpToLatest = JumpToLatest;
1369
- exports.MessageActions = MessageActions;
1370
- exports.MessageBubble = MessageBubble;
1371
- exports.MessageList = MessageList;
1372
- exports.Sources = Sources;
1373
- exports.StreamingIndicator = StreamingIndicator;
1374
- exports.ToolCalls = ToolCalls;
1375
- exports.deriveInitials = deriveInitials;
1376
- exports.isSubmittableDraft = isSubmittableDraft;
1377
- exports.resolvePersona = resolvePersona;
1378
- exports.sanitizeDraft = sanitizeDraft;
1379
- exports.useAutoFocusOnStreamEnd = useAutoFocusOnStreamEnd;
1380
- exports.useChatBubbleStyles = useChatBubbleStyles;
1381
- exports.useChatComposer = useChatComposer;
1382
- exports.useChatDestructiveStyles = useChatDestructiveStyles;
1383
- exports.useChatRoleStyles = useChatRoleStyles;
1384
- exports.useFocusOnEmptyClick = useFocusOnEmptyClick;
1385
- exports.useRegisterComposer = useRegisterComposer;
1386
- //# sourceMappingURL=chunk-4LFB7I5K.cjs.map
1387
- //# sourceMappingURL=chunk-4LFB7I5K.cjs.map