@dbx-tools/ui-mastra 0.6.217 → 0.6.218
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/index.ts +1 -1
- package/package.json +7 -7
- package/src/react/_composer-autosize.ts +41 -0
- package/src/react/chat-composer.tsx +19 -7
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/ui-mastra";
|
|
6
|
-
export const PACKAGE_VERSION = "0.6.
|
|
6
|
+
export const PACKAGE_VERSION = "0.6.218";
|
|
7
7
|
export * as reactBubbles from "./src/react/bubbles.tsx";
|
|
8
8
|
export * as reactChatApprovals from "./src/react/chat-approvals.ts";
|
|
9
9
|
export * as reactChatComposer from "./src/react/chat-composer.tsx";
|
package/package.json
CHANGED
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"react-dom": "~19.2.4"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@dbx-tools/shared-core": "0.6.
|
|
35
|
-
"@dbx-tools/shared-genie": "0.6.
|
|
36
|
-
"@dbx-tools/shared-mastra": "0.6.
|
|
37
|
-
"@dbx-tools/shared-model": "0.6.
|
|
38
|
-
"@dbx-tools/ui-appkit": "0.6.
|
|
39
|
-
"@dbx-tools/ui-branding": "0.6.
|
|
34
|
+
"@dbx-tools/shared-core": "0.6.218",
|
|
35
|
+
"@dbx-tools/shared-genie": "0.6.218",
|
|
36
|
+
"@dbx-tools/shared-mastra": "0.6.218",
|
|
37
|
+
"@dbx-tools/shared-model": "0.6.218",
|
|
38
|
+
"@dbx-tools/ui-appkit": "0.6.218",
|
|
39
|
+
"@dbx-tools/ui-branding": "0.6.218",
|
|
40
40
|
"@mastra/client-js": "1.46.0",
|
|
41
41
|
"@tanstack/react-table": "^8.21.3",
|
|
42
42
|
"ai": "^5.0.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
|
-
"version": "0.6.
|
|
55
|
+
"version": "0.6.218",
|
|
56
56
|
"type": "module",
|
|
57
57
|
"exports": {
|
|
58
58
|
"./react": "./src/react/index.ts",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reset and measure one composer textarea when its container has usable width.
|
|
3
|
+
*
|
|
4
|
+
* Resetting to `auto` before reading `scrollHeight` allows deleted content and
|
|
5
|
+
* wider containers to shrink as well as letting multiline drafts grow.
|
|
6
|
+
*/
|
|
7
|
+
export function autosizeComposerTextarea(
|
|
8
|
+
group: HTMLElement | null,
|
|
9
|
+
textarea: HTMLTextAreaElement | null,
|
|
10
|
+
): void {
|
|
11
|
+
if (!group || !textarea || group.getBoundingClientRect().width <= 0) return;
|
|
12
|
+
textarea.style.height = "auto";
|
|
13
|
+
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Observe width changes without reacting to the group height that the textarea
|
|
18
|
+
* itself controls. A zero-width observation resets the comparison sentinel so
|
|
19
|
+
* reopening at the same prior width still triggers a fresh measurement.
|
|
20
|
+
*/
|
|
21
|
+
export function observeComposerWidth(
|
|
22
|
+
group: HTMLElement,
|
|
23
|
+
resize: () => void,
|
|
24
|
+
Observer: typeof ResizeObserver | undefined = globalThis.ResizeObserver,
|
|
25
|
+
): () => void {
|
|
26
|
+
if (!Observer) return () => {};
|
|
27
|
+
let measuredWidth = 0;
|
|
28
|
+
const observer = new Observer((entries) => {
|
|
29
|
+
const width = entries[0]?.contentRect.width ?? group.getBoundingClientRect().width;
|
|
30
|
+
if (!Number.isFinite(width)) return;
|
|
31
|
+
if (width <= 0) {
|
|
32
|
+
measuredWidth = 0;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (width === measuredWidth) return;
|
|
36
|
+
measuredWidth = width;
|
|
37
|
+
resize();
|
|
38
|
+
});
|
|
39
|
+
observer.observe(group);
|
|
40
|
+
return () => observer.disconnect();
|
|
41
|
+
}
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
XIcon,
|
|
33
33
|
} from "lucide-react";
|
|
34
34
|
import { useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
35
|
+
import { autosizeComposerTextarea, observeComposerWidth } from "./_composer-autosize.ts";
|
|
35
36
|
import { ExportMenu } from "./export-menu.tsx";
|
|
36
37
|
import { SuggestionPills } from "./suggestion-pills.tsx";
|
|
37
38
|
import type { ChatViewProps } from "./types.ts";
|
|
@@ -278,14 +279,22 @@ export const ChatComposer = ({
|
|
|
278
279
|
onResumeFollow,
|
|
279
280
|
}: ChatComposerProps) => {
|
|
280
281
|
const [input, setInput] = useState("");
|
|
282
|
+
const inputGroupRef = useRef<HTMLDivElement>(null);
|
|
281
283
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
282
284
|
|
|
285
|
+
const resizeTextarea = useCallback(() => {
|
|
286
|
+
autosizeComposerTextarea(inputGroupRef.current, textareaRef.current);
|
|
287
|
+
}, []);
|
|
288
|
+
|
|
289
|
+
useLayoutEffect(() => {
|
|
290
|
+
resizeTextarea();
|
|
291
|
+
}, [input, isLoadingHistory, resizeTextarea]);
|
|
292
|
+
|
|
283
293
|
useLayoutEffect(() => {
|
|
284
|
-
const
|
|
285
|
-
if (!
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}, [input]);
|
|
294
|
+
const group = inputGroupRef.current;
|
|
295
|
+
if (!group) return;
|
|
296
|
+
return observeComposerWidth(group, resizeTextarea);
|
|
297
|
+
}, [resizeTextarea]);
|
|
289
298
|
|
|
290
299
|
const isRunning = status === "submitted" || status === "streaming";
|
|
291
300
|
const submit = () => {
|
|
@@ -336,7 +345,10 @@ export const ChatComposer = ({
|
|
|
336
345
|
onRemoveSteer={onRemoveSteer}
|
|
337
346
|
onReorderSteers={onReorderSteers}
|
|
338
347
|
/>
|
|
339
|
-
<InputGroup
|
|
348
|
+
<InputGroup
|
|
349
|
+
ref={inputGroupRef}
|
|
350
|
+
className="rounded-2xl border-border/80 shadow-sm transition-shadow focus-within:shadow-md"
|
|
351
|
+
>
|
|
340
352
|
<InputGroupTextarea
|
|
341
353
|
ref={textareaRef}
|
|
342
354
|
value={input}
|
|
@@ -350,7 +362,7 @@ export const ChatComposer = ({
|
|
|
350
362
|
placeholder={isLoadingHistory ? "Loading history..." : "Send a message..."}
|
|
351
363
|
rows={1}
|
|
352
364
|
disabled={isLoadingHistory}
|
|
353
|
-
className="max-h-48 text-base md:text-sm"
|
|
365
|
+
className="field-sizing-fixed max-h-48 overflow-y-auto text-base md:text-sm"
|
|
354
366
|
/>
|
|
355
367
|
<InputGroupAddon align="inline-end">
|
|
356
368
|
{isRunning && onStop && !input.trim() ? (
|