@epicbagel/saas-kit 1.2.2 → 1.3.0
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/README.md +84 -0
- package/dist/chunk-2TKLS73N.js +121 -0
- package/dist/chunk-4UUTKR3V.cjs +53 -0
- package/dist/chunk-BTHYGHOH.cjs +143 -0
- package/dist/chunk-GRY77463.cjs +121 -0
- package/dist/chunk-HHV4G77I.js +55 -0
- package/dist/chunk-JTI4244T.js +143 -0
- package/dist/chunk-QEJ2STIV.js +53 -0
- package/dist/chunk-VLXPLKFR.cjs +55 -0
- package/dist/primitives/chat.cjs +46 -19
- package/dist/primitives/chat.d.cts +24 -5
- package/dist/primitives/chat.d.ts +24 -5
- package/dist/primitives/chat.js +42 -15
- package/dist/primitives/code-block.cjs +4 -49
- package/dist/primitives/code-block.js +4 -49
- package/dist/primitives/document-preview.cjs +54 -0
- package/dist/primitives/document-preview.d.cts +30 -0
- package/dist/primitives/document-preview.d.ts +30 -0
- package/dist/primitives/document-preview.js +54 -0
- package/dist/primitives/file-preview-internals.cjs +20 -0
- package/dist/primitives/file-preview-internals.d.cts +44 -0
- package/dist/primitives/file-preview-internals.d.ts +44 -0
- package/dist/primitives/file-preview-internals.js +20 -0
- package/dist/primitives/file-preview.cjs +327 -0
- package/dist/primitives/file-preview.d.cts +92 -0
- package/dist/primitives/file-preview.d.ts +92 -0
- package/dist/primitives/file-preview.js +327 -0
- package/dist/primitives/image.cjs +4 -48
- package/dist/primitives/image.js +3 -47
- package/dist/primitives/responsive-dialog.cjs +26 -142
- package/dist/primitives/responsive-dialog.js +13 -129
- package/package.json +21 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Drawer,
|
|
4
|
+
DrawerClose,
|
|
5
|
+
DrawerContent,
|
|
6
|
+
DrawerDescription,
|
|
7
|
+
DrawerFooter,
|
|
8
|
+
DrawerHeader,
|
|
9
|
+
DrawerTitle,
|
|
10
|
+
DrawerTrigger
|
|
11
|
+
} from "./chunk-4HWCNRK4.js";
|
|
12
|
+
import {
|
|
13
|
+
Dialog,
|
|
14
|
+
DialogClose,
|
|
15
|
+
DialogContent,
|
|
16
|
+
DialogDescription,
|
|
17
|
+
DialogFooter,
|
|
18
|
+
DialogHeader,
|
|
19
|
+
DialogTitle,
|
|
20
|
+
DialogTrigger
|
|
21
|
+
} from "./chunk-3QT5VYZ3.js";
|
|
22
|
+
import {
|
|
23
|
+
cn
|
|
24
|
+
} from "./chunk-G6SRSWXB.js";
|
|
25
|
+
|
|
26
|
+
// src/primitives/responsive-dialog.tsx
|
|
27
|
+
import * as React from "react";
|
|
28
|
+
import { useMediaQuery } from "react-responsive";
|
|
29
|
+
import { jsx } from "react/jsx-runtime";
|
|
30
|
+
var DesktopContext = React.createContext(false);
|
|
31
|
+
var useIsDesktop = () => React.useContext(DesktopContext);
|
|
32
|
+
var DESKTOP_QUERY = { minWidth: 1024 };
|
|
33
|
+
var ResponsiveDialog = ({ children, ...props }) => {
|
|
34
|
+
const isDesktop = useMediaQuery(DESKTOP_QUERY);
|
|
35
|
+
const Root = isDesktop ? Dialog : Drawer;
|
|
36
|
+
return /* @__PURE__ */ jsx(DesktopContext.Provider, { value: isDesktop, children: /* @__PURE__ */ jsx(Root, { ...props, children }) });
|
|
37
|
+
};
|
|
38
|
+
ResponsiveDialog.displayName = "ResponsiveDialog";
|
|
39
|
+
var ResponsiveDialogTrigger = ({
|
|
40
|
+
children,
|
|
41
|
+
...props
|
|
42
|
+
}) => {
|
|
43
|
+
const Trigger = useIsDesktop() ? DialogTrigger : DrawerTrigger;
|
|
44
|
+
return /* @__PURE__ */ jsx(Trigger, { ...props, children });
|
|
45
|
+
};
|
|
46
|
+
ResponsiveDialogTrigger.displayName = "ResponsiveDialogTrigger";
|
|
47
|
+
var ResponsiveDialogClose = ({
|
|
48
|
+
children,
|
|
49
|
+
...props
|
|
50
|
+
}) => {
|
|
51
|
+
const Close = useIsDesktop() ? DialogClose : DrawerClose;
|
|
52
|
+
return /* @__PURE__ */ jsx(Close, { ...props, children });
|
|
53
|
+
};
|
|
54
|
+
ResponsiveDialogClose.displayName = "ResponsiveDialogClose";
|
|
55
|
+
var ResponsiveDialogContent = React.forwardRef(({ className, children, presentation = "default", ...props }, ref) => {
|
|
56
|
+
if (useIsDesktop()) {
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
DialogContent,
|
|
59
|
+
{
|
|
60
|
+
ref,
|
|
61
|
+
className: cn(
|
|
62
|
+
"flex max-h-[85vh] max-w-md flex-col gap-0 overflow-hidden p-0",
|
|
63
|
+
presentation === "preview" && "max-w-2xl sm:h-[85vh] [&>button:last-child]:hidden",
|
|
64
|
+
className
|
|
65
|
+
),
|
|
66
|
+
...props,
|
|
67
|
+
children
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
DrawerContent,
|
|
73
|
+
{
|
|
74
|
+
ref,
|
|
75
|
+
className: cn("max-h-[92vh]", className),
|
|
76
|
+
...props,
|
|
77
|
+
children
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
ResponsiveDialogContent.displayName = "ResponsiveDialogContent";
|
|
82
|
+
var ResponsiveDialogHeader = ({
|
|
83
|
+
className,
|
|
84
|
+
visibility = "visible",
|
|
85
|
+
...props
|
|
86
|
+
}) => {
|
|
87
|
+
const Header = useIsDesktop() ? DialogHeader : DrawerHeader;
|
|
88
|
+
return /* @__PURE__ */ jsx(
|
|
89
|
+
Header,
|
|
90
|
+
{
|
|
91
|
+
className: cn(useIsDesktop() && "p-4", visibility === "screen-reader" && "sr-only", className),
|
|
92
|
+
...props
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
ResponsiveDialogHeader.displayName = "ResponsiveDialogHeader";
|
|
97
|
+
var ResponsiveDialogBody = ({
|
|
98
|
+
className,
|
|
99
|
+
...props
|
|
100
|
+
}) => /* @__PURE__ */ jsx("div", { className: cn("min-h-0 flex-1 overflow-y-auto px-4 pb-6", className), ...props });
|
|
101
|
+
ResponsiveDialogBody.displayName = "ResponsiveDialogBody";
|
|
102
|
+
var ResponsiveDialogFooter = ({
|
|
103
|
+
className,
|
|
104
|
+
layout = "auto",
|
|
105
|
+
...props
|
|
106
|
+
}) => {
|
|
107
|
+
const isDesktop = useIsDesktop();
|
|
108
|
+
const Footer = isDesktop ? DialogFooter : DrawerFooter;
|
|
109
|
+
return /* @__PURE__ */ jsx(
|
|
110
|
+
Footer,
|
|
111
|
+
{
|
|
112
|
+
className: cn(
|
|
113
|
+
"mt-0 shrink-0 gap-2 border-t bg-background p-4",
|
|
114
|
+
layout === "fill" ? "flex-row space-x-0 [&>*]:min-w-0 [&>*]:flex-1" : isDesktop ? "flex-row justify-end space-x-0 [&>*]:flex-none" : "grid grid-cols-2 [&>*]:w-full",
|
|
115
|
+
className
|
|
116
|
+
),
|
|
117
|
+
...props
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
ResponsiveDialogFooter.displayName = "ResponsiveDialogFooter";
|
|
122
|
+
var ResponsiveDialogTitle = React.forwardRef(({ className, visuallyHidden = false, ...props }, ref) => {
|
|
123
|
+
const Title = useIsDesktop() ? DialogTitle : DrawerTitle;
|
|
124
|
+
return /* @__PURE__ */ jsx(Title, { ref, className: cn(visuallyHidden && "sr-only", className), ...props });
|
|
125
|
+
});
|
|
126
|
+
ResponsiveDialogTitle.displayName = "ResponsiveDialogTitle";
|
|
127
|
+
var ResponsiveDialogDescription = React.forwardRef(({ className, visuallyHidden = false, ...props }, ref) => {
|
|
128
|
+
const Description = useIsDesktop() ? DialogDescription : DrawerDescription;
|
|
129
|
+
return /* @__PURE__ */ jsx(Description, { ref, className: cn(visuallyHidden && "sr-only", className), ...props });
|
|
130
|
+
});
|
|
131
|
+
ResponsiveDialogDescription.displayName = "ResponsiveDialogDescription";
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
ResponsiveDialog,
|
|
135
|
+
ResponsiveDialogTrigger,
|
|
136
|
+
ResponsiveDialogClose,
|
|
137
|
+
ResponsiveDialogContent,
|
|
138
|
+
ResponsiveDialogHeader,
|
|
139
|
+
ResponsiveDialogBody,
|
|
140
|
+
ResponsiveDialogFooter,
|
|
141
|
+
ResponsiveDialogTitle,
|
|
142
|
+
ResponsiveDialogDescription
|
|
143
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
cn
|
|
4
|
+
} from "./chunk-G6SRSWXB.js";
|
|
5
|
+
|
|
6
|
+
// src/primitives/image.tsx
|
|
7
|
+
import { forwardRef, useEffect, useState } from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var fitStyles = { cover: "object-cover", contain: "object-contain" };
|
|
10
|
+
var radiusStyles = { none: "", sm: "rounded-sm", md: "rounded-md", xl: "rounded-xl", full: "rounded-full" };
|
|
11
|
+
var Image = forwardRef(function Image2({ fit = "cover", frameHeight, radius = "none", width = "auto", align = "start", border = false, shadow = "none", emphasis = "full", loadingIndicator = "none", className, onLoad, onError, src, ...props }, ref) {
|
|
12
|
+
const [loaded, setLoaded] = useState(loadingIndicator === "none" || !src);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setLoaded(loadingIndicator === "none" || !src);
|
|
15
|
+
}, [loadingIndicator, src]);
|
|
16
|
+
const loading = loadingIndicator === "pulse" && !loaded;
|
|
17
|
+
return /* @__PURE__ */ jsx(
|
|
18
|
+
"img",
|
|
19
|
+
{
|
|
20
|
+
ref,
|
|
21
|
+
className: cn(
|
|
22
|
+
fitStyles[fit],
|
|
23
|
+
radiusStyles[radius],
|
|
24
|
+
frameHeight === "sm" && "h-16",
|
|
25
|
+
frameHeight === "md" && "h-28",
|
|
26
|
+
width === "full" && "w-full",
|
|
27
|
+
width === "preview" && "w-full max-w-[380px]",
|
|
28
|
+
width === "preview-lg" && "w-full max-w-[440px]",
|
|
29
|
+
align === "center" && "mx-auto",
|
|
30
|
+
border && "border",
|
|
31
|
+
shadow === "subtle" && "shadow-xs",
|
|
32
|
+
loading && "animate-pulse bg-muted",
|
|
33
|
+
emphasis === "soft-until-parent-hover" && "transition-opacity duration-200 md:opacity-70 md:group-hover:opacity-100",
|
|
34
|
+
className
|
|
35
|
+
),
|
|
36
|
+
src,
|
|
37
|
+
...props,
|
|
38
|
+
"aria-busy": loading || void 0,
|
|
39
|
+
onLoad: (event) => {
|
|
40
|
+
setLoaded(true);
|
|
41
|
+
onLoad?.(event);
|
|
42
|
+
},
|
|
43
|
+
onError: (event) => {
|
|
44
|
+
setLoaded(true);
|
|
45
|
+
onError?.(event);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
Image
|
|
53
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkVKIGJNJRcjs = require('./chunk-VKIGJNJR.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
8
|
+
|
|
9
|
+
// src/primitives/code-block.tsx
|
|
10
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
11
|
+
var HEIGHTS = {
|
|
12
|
+
none: "",
|
|
13
|
+
sm: "max-h-40 overflow-y-auto",
|
|
14
|
+
md: "max-h-64 overflow-y-auto",
|
|
15
|
+
lg: "max-h-96 overflow-y-auto",
|
|
16
|
+
viewport: "min-h-[55vh] max-h-[65vh] overflow-y-auto"
|
|
17
|
+
};
|
|
18
|
+
function CodeBlock({
|
|
19
|
+
children,
|
|
20
|
+
copy,
|
|
21
|
+
copyLabel,
|
|
22
|
+
wrap = false,
|
|
23
|
+
maxHeight = "none",
|
|
24
|
+
className
|
|
25
|
+
}) {
|
|
26
|
+
const copyText = typeof copy === "string" ? copy : children;
|
|
27
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkKWLSBTB2cjs.cn.call(void 0, "relative", className), children: [
|
|
28
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
29
|
+
"pre",
|
|
30
|
+
{
|
|
31
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
32
|
+
"rounded-md border border-border bg-muted/40 p-3 font-mono text-xs leading-relaxed",
|
|
33
|
+
wrap ? "whitespace-pre-wrap break-words" : "overflow-x-auto",
|
|
34
|
+
HEIGHTS[maxHeight],
|
|
35
|
+
copy ? "pr-12" : void 0
|
|
36
|
+
),
|
|
37
|
+
children
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
copy ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
41
|
+
_chunkVKIGJNJRcjs.CopyButton,
|
|
42
|
+
{
|
|
43
|
+
text: copyText,
|
|
44
|
+
label: copyLabel,
|
|
45
|
+
size: "sm",
|
|
46
|
+
variant: "ghost",
|
|
47
|
+
className: "absolute right-1.5 top-1.5"
|
|
48
|
+
}
|
|
49
|
+
) : null
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
exports.CodeBlock = CodeBlock;
|
package/dist/primitives/chat.cjs
CHANGED
|
@@ -15,19 +15,19 @@ var _chunkSUB4BAYEcjs = require('../chunk-SUB4BAYE.cjs');
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
|
|
22
|
+
var _chunkXABXUP6Lcjs = require('../chunk-XABXUP6L.cjs');
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
var
|
|
26
|
+
var _chunk2AU7ZRGXcjs = require('../chunk-2AU7ZRGX.cjs');
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
@@ -36,12 +36,12 @@ var _chunkRIWLAMMEcjs = require('../chunk-RIWLAMME.cjs');
|
|
|
36
36
|
require('../chunk-2HV2KKOE.cjs');
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
var _chunkKENBU3NVcjs = require('../chunk-KENBU3NV.cjs');
|
|
40
|
-
require('../chunk-ELPV44S6.cjs');
|
|
41
39
|
|
|
40
|
+
var _chunkKADJ56AHcjs = require('../chunk-KADJ56AH.cjs');
|
|
42
41
|
|
|
43
42
|
|
|
44
|
-
var
|
|
43
|
+
var _chunkKENBU3NVcjs = require('../chunk-KENBU3NV.cjs');
|
|
44
|
+
require('../chunk-ELPV44S6.cjs');
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
|
|
@@ -114,13 +114,32 @@ function useArrivingUserTurnId(messages) {
|
|
|
114
114
|
}, [messages]);
|
|
115
115
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
116
116
|
const message = messages[i];
|
|
117
|
-
if (message.role === "user"
|
|
117
|
+
if (message.role === "user" && message.status !== "running") {
|
|
118
|
+
return seen.current.has(message.id) ? void 0 : message.id;
|
|
119
|
+
}
|
|
118
120
|
}
|
|
119
121
|
return void 0;
|
|
120
122
|
}
|
|
123
|
+
function timelineMarkers(messages, now) {
|
|
124
|
+
let previous = null;
|
|
125
|
+
return messages.map((message) => {
|
|
126
|
+
if (message.status === "running") return null;
|
|
127
|
+
const relativeTime = _chunkH2UFRLLNcjs.formatRelativeLong.call(void 0, message.createdAt, now);
|
|
128
|
+
const opens = relativeTime && relativeTime !== previous ? relativeTime : null;
|
|
129
|
+
previous = relativeTime;
|
|
130
|
+
return opens;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
121
133
|
function TimelineMarker({ label }) {
|
|
122
134
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkB765DSRGcjs.Marker, { variant: "separator", role: "separator", "aria-label": label, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkB765DSRGcjs.MarkerContent, { children: label }) });
|
|
123
135
|
}
|
|
136
|
+
function ChatRunningLine({
|
|
137
|
+
label,
|
|
138
|
+
align = "start",
|
|
139
|
+
workspace
|
|
140
|
+
}) {
|
|
141
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.Message, { align, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.MessageContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.Trace, { className: workspace ? void 0 : "px-3.5 py-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceLine, { status: "running", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceTitle, { children: label }) }) }) }) });
|
|
142
|
+
}
|
|
124
143
|
var ChatThread = _react.forwardRef.call(void 0,
|
|
125
144
|
function ChatThread2({
|
|
126
145
|
messages,
|
|
@@ -136,7 +155,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
136
155
|
attachmentAction = "open",
|
|
137
156
|
className
|
|
138
157
|
}, ref) {
|
|
139
|
-
const
|
|
158
|
+
const markers = timelineMarkers(messages, /* @__PURE__ */ new Date());
|
|
140
159
|
const anchorId = useArrivingUserTurnId(messages);
|
|
141
160
|
const workspace = appearance === "workspace";
|
|
142
161
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerProvider, { autoScroll: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
@@ -155,10 +174,18 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
155
174
|
children: [
|
|
156
175
|
messages.map((m, index) => {
|
|
157
176
|
const isUser = m.role === "user";
|
|
177
|
+
if (m.status === "running") {
|
|
178
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
179
|
+
ChatRunningLine,
|
|
180
|
+
{
|
|
181
|
+
label: m.text || pendingLabel,
|
|
182
|
+
align: isUser ? "end" : "start",
|
|
183
|
+
workspace
|
|
184
|
+
}
|
|
185
|
+
) }, m.id);
|
|
186
|
+
}
|
|
158
187
|
const isFullWidth = m.width === "full";
|
|
159
|
-
const
|
|
160
|
-
const previousRelativeTime = _chunkH2UFRLLNcjs.formatRelativeLong.call(void 0, _optionalChain([messages, 'access', _ => _[index - 1], 'optionalAccess', _2 => _2.createdAt]), timelineNow);
|
|
161
|
-
const startsTimelineSection = relativeTime && relativeTime !== previousRelativeTime;
|
|
188
|
+
const marker = markers[index];
|
|
162
189
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
163
190
|
_chunkXABXUP6Lcjs.MessageScrollerItem,
|
|
164
191
|
{
|
|
@@ -166,7 +193,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
166
193
|
scrollAnchor: m.id === anchorId,
|
|
167
194
|
className: _chunkKWLSBTB2cjs.cn.call(void 0, "flex flex-col", workspace ? "gap-5" : "gap-3"),
|
|
168
195
|
children: [
|
|
169
|
-
|
|
196
|
+
marker ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TimelineMarker, { label: marker }) : null,
|
|
170
197
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk2AU7ZRGXcjs.MessageContent, { children: [
|
|
171
198
|
(m.content || m.text) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
172
199
|
_chunkV4YWTRLDcjs.Bubble,
|
|
@@ -202,7 +229,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
202
229
|
m.id
|
|
203
230
|
);
|
|
204
231
|
}),
|
|
205
|
-
pending && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
232
|
+
pending && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatRunningLine, { label: pendingLabel, workspace }) }),
|
|
206
233
|
footer && // Always painted: content-visibility:auto would contain the
|
|
207
234
|
// footer's paint and layout, clipping a ring or shadow at its
|
|
208
235
|
// edge and re-parenting anything fixed inside it.
|
|
@@ -258,7 +285,7 @@ function ChatAttachmentList({
|
|
|
258
285
|
{
|
|
259
286
|
"aria-label": `${verb} ${attachment.name}`,
|
|
260
287
|
title: `${verb} ${attachment.name}`,
|
|
261
|
-
onClick: () => _optionalChain([onOpen, 'optionalCall',
|
|
288
|
+
onClick: () => _optionalChain([onOpen, 'optionalCall', _ => _(attachment)]),
|
|
262
289
|
className: "rounded-xl focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
263
290
|
}
|
|
264
291
|
),
|
|
@@ -403,7 +430,7 @@ function ChatInput({
|
|
|
403
430
|
"data-slot": "chat-input-actions",
|
|
404
431
|
onClick: (event) => {
|
|
405
432
|
if (!event.currentTarget.contains(event.target)) return;
|
|
406
|
-
if (!event.target.closest("button")) _optionalChain([ref, 'access',
|
|
433
|
+
if (!event.target.closest("button")) _optionalChain([ref, 'access', _2 => _2.current, 'optionalAccess', _3 => _3.focus, 'call', _4 => _4()]);
|
|
407
434
|
},
|
|
408
435
|
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
409
436
|
"gap-2",
|
|
@@ -421,7 +448,7 @@ function ChatInput({
|
|
|
421
448
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Plus, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
|
|
422
449
|
}
|
|
423
450
|
) }),
|
|
424
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuContent, { align: "start", side: "top", className: "min-w-52", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenuItem, { onSelect: () => _optionalChain([fileInputRef, 'access',
|
|
451
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuContent, { align: "start", side: "top", className: "min-w-52", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenuItem, { onSelect: () => _optionalChain([fileInputRef, 'access', _5 => _5.current, 'optionalAccess', _6 => _6.click, 'call', _7 => _7()]), children: [
|
|
425
452
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Paperclip, { className: "h-4 w-4" }),
|
|
426
453
|
addFilesLabel
|
|
427
454
|
] }) })
|
|
@@ -652,14 +679,14 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
652
679
|
else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
|
|
653
680
|
else console.error(cause);
|
|
654
681
|
}
|
|
655
|
-
window.setTimeout(() => _optionalChain([inputRef, 'access',
|
|
682
|
+
window.setTimeout(() => _optionalChain([inputRef, 'access', _8 => _8.current, 'optionalAccess', _9 => _9.focus, 'call', _10 => _10()]), 0);
|
|
656
683
|
},
|
|
657
684
|
[attachments, mode, onSend, onSendError, pending]
|
|
658
685
|
);
|
|
659
686
|
_react.useImperativeHandle.call(void 0,
|
|
660
687
|
ref,
|
|
661
688
|
() => ({
|
|
662
|
-
focusInput: () => _optionalChain([inputRef, 'access',
|
|
689
|
+
focusInput: () => _optionalChain([inputRef, 'access', _11 => _11.current, 'optionalAccess', _12 => _12.focus, 'call', _13 => _13()]),
|
|
663
690
|
clearInput: () => setInput("")
|
|
664
691
|
}),
|
|
665
692
|
[]
|
|
@@ -667,7 +694,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
667
694
|
const dropFiles = _react.useCallback.call(void 0,
|
|
668
695
|
(files) => {
|
|
669
696
|
if (!conversationStarted && mode === "voice") setUserMode("text");
|
|
670
|
-
return _optionalChain([onFilesSelected, 'optionalCall',
|
|
697
|
+
return _optionalChain([onFilesSelected, 'optionalCall', _14 => _14(files)]);
|
|
671
698
|
},
|
|
672
699
|
[conversationStarted, mode, onFilesSelected]
|
|
673
700
|
);
|
|
@@ -34,12 +34,26 @@ type ChatMessage = {
|
|
|
34
34
|
content?: ReactNode;
|
|
35
35
|
/** Files that belong to this turn. */
|
|
36
36
|
attachments?: ReadonlyArray<ChatAttachment>;
|
|
37
|
+
/**
|
|
38
|
+
* `"running"`: a reply still being worked on. The thread draws the turn as
|
|
39
|
+
* its running line, the one `pending` adds at the end, labelled with `text`
|
|
40
|
+
* (else the thread's `pendingLabel`), where the turn sits in `messages`.
|
|
41
|
+
* Unlike `pending`, it leaves the composer free, so use it for a reply
|
|
42
|
+
* worked on in the background while the user can keep writing; replace it
|
|
43
|
+
* with the reply when that lands. The line is not a message: it has no time
|
|
44
|
+
* marker, files or rich `content`, and the scroller neither anchors nor
|
|
45
|
+
* tracks it.
|
|
46
|
+
*/
|
|
47
|
+
status?: "running";
|
|
37
48
|
};
|
|
38
49
|
interface ChatThreadProps {
|
|
39
50
|
messages: ChatMessage[];
|
|
40
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Show a running line (`pendingLabel`) at the end of the thread. A turn with
|
|
53
|
+
* `status: "running"` draws the same line where it sits in `messages`.
|
|
54
|
+
*/
|
|
41
55
|
pending?: boolean;
|
|
42
|
-
/** The running line while a reply is pending
|
|
56
|
+
/** The running line while a reply is pending, and a running turn's without `text`. Defaults to "Thinking…". */
|
|
43
57
|
pendingLabel?: string;
|
|
44
58
|
/** Accessible name of the scroll-to-latest button. Defaults to "Scroll to latest message". */
|
|
45
59
|
scrollButtonLabel?: string;
|
|
@@ -80,7 +94,7 @@ interface ChatThreadProps {
|
|
|
80
94
|
* button appears whenever the reader is away from the end. Turns with a
|
|
81
95
|
* `createdAt` are grouped under relative-time markers ("2 days ago"), and a
|
|
82
96
|
* pending reply shows as a running trace line, which the log announces as it
|
|
83
|
-
* appears.
|
|
97
|
+
* appears. A turn with `status: "running"` draws the same line in its place.
|
|
84
98
|
*/
|
|
85
99
|
declare const ChatThread: React$1.ForwardRefExoticComponent<ChatThreadProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
86
100
|
interface ChatInputProps {
|
|
@@ -170,9 +184,14 @@ interface ChatProps {
|
|
|
170
184
|
* failure itself, with `error`.
|
|
171
185
|
*/
|
|
172
186
|
onSendError?: (error: unknown) => void;
|
|
173
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Whether an in-flight request is pending. Disables input and shows a
|
|
189
|
+
* running line (`pendingLabel`) at the end of the thread. To show that line
|
|
190
|
+
* and leave the composer free, as for a reply worked on in the background,
|
|
191
|
+
* put a turn with `status: "running"` in `messages` instead.
|
|
192
|
+
*/
|
|
174
193
|
pending?: boolean;
|
|
175
|
-
/** The running line while a reply is pending
|
|
194
|
+
/** The running line while a reply is pending, and a running turn's without `text`. Defaults to "Thinking…". */
|
|
176
195
|
pendingLabel?: string;
|
|
177
196
|
/**
|
|
178
197
|
* Replaces the empty composer while its first message is in flight. Use for
|
|
@@ -34,12 +34,26 @@ type ChatMessage = {
|
|
|
34
34
|
content?: ReactNode;
|
|
35
35
|
/** Files that belong to this turn. */
|
|
36
36
|
attachments?: ReadonlyArray<ChatAttachment>;
|
|
37
|
+
/**
|
|
38
|
+
* `"running"`: a reply still being worked on. The thread draws the turn as
|
|
39
|
+
* its running line, the one `pending` adds at the end, labelled with `text`
|
|
40
|
+
* (else the thread's `pendingLabel`), where the turn sits in `messages`.
|
|
41
|
+
* Unlike `pending`, it leaves the composer free, so use it for a reply
|
|
42
|
+
* worked on in the background while the user can keep writing; replace it
|
|
43
|
+
* with the reply when that lands. The line is not a message: it has no time
|
|
44
|
+
* marker, files or rich `content`, and the scroller neither anchors nor
|
|
45
|
+
* tracks it.
|
|
46
|
+
*/
|
|
47
|
+
status?: "running";
|
|
37
48
|
};
|
|
38
49
|
interface ChatThreadProps {
|
|
39
50
|
messages: ChatMessage[];
|
|
40
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Show a running line (`pendingLabel`) at the end of the thread. A turn with
|
|
53
|
+
* `status: "running"` draws the same line where it sits in `messages`.
|
|
54
|
+
*/
|
|
41
55
|
pending?: boolean;
|
|
42
|
-
/** The running line while a reply is pending
|
|
56
|
+
/** The running line while a reply is pending, and a running turn's without `text`. Defaults to "Thinking…". */
|
|
43
57
|
pendingLabel?: string;
|
|
44
58
|
/** Accessible name of the scroll-to-latest button. Defaults to "Scroll to latest message". */
|
|
45
59
|
scrollButtonLabel?: string;
|
|
@@ -80,7 +94,7 @@ interface ChatThreadProps {
|
|
|
80
94
|
* button appears whenever the reader is away from the end. Turns with a
|
|
81
95
|
* `createdAt` are grouped under relative-time markers ("2 days ago"), and a
|
|
82
96
|
* pending reply shows as a running trace line, which the log announces as it
|
|
83
|
-
* appears.
|
|
97
|
+
* appears. A turn with `status: "running"` draws the same line in its place.
|
|
84
98
|
*/
|
|
85
99
|
declare const ChatThread: React$1.ForwardRefExoticComponent<ChatThreadProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
86
100
|
interface ChatInputProps {
|
|
@@ -170,9 +184,14 @@ interface ChatProps {
|
|
|
170
184
|
* failure itself, with `error`.
|
|
171
185
|
*/
|
|
172
186
|
onSendError?: (error: unknown) => void;
|
|
173
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Whether an in-flight request is pending. Disables input and shows a
|
|
189
|
+
* running line (`pendingLabel`) at the end of the thread. To show that line
|
|
190
|
+
* and leave the composer free, as for a reply worked on in the background,
|
|
191
|
+
* put a turn with `status: "running"` in `messages` instead.
|
|
192
|
+
*/
|
|
174
193
|
pending?: boolean;
|
|
175
|
-
/** The running line while a reply is pending
|
|
194
|
+
/** The running line while a reply is pending, and a running turn's without `text`. Defaults to "Thinking…". */
|
|
176
195
|
pendingLabel?: string;
|
|
177
196
|
/**
|
|
178
197
|
* Replaces the empty composer while its first message is in flight. Use for
|
package/dist/primitives/chat.js
CHANGED
|
@@ -12,10 +12,6 @@ import {
|
|
|
12
12
|
Suggestion,
|
|
13
13
|
Suggestions
|
|
14
14
|
} from "../chunk-THWIJG5C.js";
|
|
15
|
-
import {
|
|
16
|
-
Marker,
|
|
17
|
-
MarkerContent
|
|
18
|
-
} from "../chunk-IW4ZIXXG.js";
|
|
19
15
|
import {
|
|
20
16
|
MessageScroller,
|
|
21
17
|
MessageScrollerButton,
|
|
@@ -28,20 +24,24 @@ import {
|
|
|
28
24
|
Message,
|
|
29
25
|
MessageContent
|
|
30
26
|
} from "../chunk-JZOBIPFC.js";
|
|
27
|
+
import {
|
|
28
|
+
Marker,
|
|
29
|
+
MarkerContent
|
|
30
|
+
} from "../chunk-IW4ZIXXG.js";
|
|
31
31
|
import {
|
|
32
32
|
InputGroup,
|
|
33
33
|
InputGroupAddon,
|
|
34
34
|
InputGroupTextarea
|
|
35
35
|
} from "../chunk-MHYAVXOE.js";
|
|
36
36
|
import "../chunk-6FC65AZQ.js";
|
|
37
|
-
import {
|
|
38
|
-
LazyMarkdown
|
|
39
|
-
} from "../chunk-VY5U4VGV.js";
|
|
40
|
-
import "../chunk-INNGGLMZ.js";
|
|
41
37
|
import {
|
|
42
38
|
FileDropArea,
|
|
43
39
|
FileDropzone
|
|
44
40
|
} from "../chunk-M7FYGAGO.js";
|
|
41
|
+
import {
|
|
42
|
+
LazyMarkdown
|
|
43
|
+
} from "../chunk-VY5U4VGV.js";
|
|
44
|
+
import "../chunk-INNGGLMZ.js";
|
|
45
45
|
import {
|
|
46
46
|
DropdownMenu,
|
|
47
47
|
DropdownMenuContent,
|
|
@@ -114,13 +114,32 @@ function useArrivingUserTurnId(messages) {
|
|
|
114
114
|
}, [messages]);
|
|
115
115
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
116
116
|
const message = messages[i];
|
|
117
|
-
if (message.role === "user"
|
|
117
|
+
if (message.role === "user" && message.status !== "running") {
|
|
118
|
+
return seen.current.has(message.id) ? void 0 : message.id;
|
|
119
|
+
}
|
|
118
120
|
}
|
|
119
121
|
return void 0;
|
|
120
122
|
}
|
|
123
|
+
function timelineMarkers(messages, now) {
|
|
124
|
+
let previous = null;
|
|
125
|
+
return messages.map((message) => {
|
|
126
|
+
if (message.status === "running") return null;
|
|
127
|
+
const relativeTime = formatRelativeLong(message.createdAt, now);
|
|
128
|
+
const opens = relativeTime && relativeTime !== previous ? relativeTime : null;
|
|
129
|
+
previous = relativeTime;
|
|
130
|
+
return opens;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
121
133
|
function TimelineMarker({ label }) {
|
|
122
134
|
return /* @__PURE__ */ jsx(Marker, { variant: "separator", role: "separator", "aria-label": label, children: /* @__PURE__ */ jsx(MarkerContent, { children: label }) });
|
|
123
135
|
}
|
|
136
|
+
function ChatRunningLine({
|
|
137
|
+
label,
|
|
138
|
+
align = "start",
|
|
139
|
+
workspace
|
|
140
|
+
}) {
|
|
141
|
+
return /* @__PURE__ */ jsx(Message, { align, children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Trace, { className: workspace ? void 0 : "px-3.5 py-2", children: /* @__PURE__ */ jsx(TraceLine, { status: "running", children: /* @__PURE__ */ jsx(TraceTitle, { children: label }) }) }) }) });
|
|
142
|
+
}
|
|
124
143
|
var ChatThread = forwardRef(
|
|
125
144
|
function ChatThread2({
|
|
126
145
|
messages,
|
|
@@ -136,7 +155,7 @@ var ChatThread = forwardRef(
|
|
|
136
155
|
attachmentAction = "open",
|
|
137
156
|
className
|
|
138
157
|
}, ref) {
|
|
139
|
-
const
|
|
158
|
+
const markers = timelineMarkers(messages, /* @__PURE__ */ new Date());
|
|
140
159
|
const anchorId = useArrivingUserTurnId(messages);
|
|
141
160
|
const workspace = appearance === "workspace";
|
|
142
161
|
return /* @__PURE__ */ jsx(MessageScrollerProvider, { autoScroll: true, children: /* @__PURE__ */ jsxs(
|
|
@@ -155,10 +174,18 @@ var ChatThread = forwardRef(
|
|
|
155
174
|
children: [
|
|
156
175
|
messages.map((m, index) => {
|
|
157
176
|
const isUser = m.role === "user";
|
|
177
|
+
if (m.status === "running") {
|
|
178
|
+
return /* @__PURE__ */ jsx(MessageScrollerItem, { children: /* @__PURE__ */ jsx(
|
|
179
|
+
ChatRunningLine,
|
|
180
|
+
{
|
|
181
|
+
label: m.text || pendingLabel,
|
|
182
|
+
align: isUser ? "end" : "start",
|
|
183
|
+
workspace
|
|
184
|
+
}
|
|
185
|
+
) }, m.id);
|
|
186
|
+
}
|
|
158
187
|
const isFullWidth = m.width === "full";
|
|
159
|
-
const
|
|
160
|
-
const previousRelativeTime = formatRelativeLong(messages[index - 1]?.createdAt, timelineNow);
|
|
161
|
-
const startsTimelineSection = relativeTime && relativeTime !== previousRelativeTime;
|
|
188
|
+
const marker = markers[index];
|
|
162
189
|
return /* @__PURE__ */ jsxs(
|
|
163
190
|
MessageScrollerItem,
|
|
164
191
|
{
|
|
@@ -166,7 +193,7 @@ var ChatThread = forwardRef(
|
|
|
166
193
|
scrollAnchor: m.id === anchorId,
|
|
167
194
|
className: cn("flex flex-col", workspace ? "gap-5" : "gap-3"),
|
|
168
195
|
children: [
|
|
169
|
-
|
|
196
|
+
marker ? /* @__PURE__ */ jsx(TimelineMarker, { label: marker }) : null,
|
|
170
197
|
/* @__PURE__ */ jsx(Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ jsxs(MessageContent, { children: [
|
|
171
198
|
(m.content || m.text) && /* @__PURE__ */ jsx(
|
|
172
199
|
Bubble,
|
|
@@ -202,7 +229,7 @@ var ChatThread = forwardRef(
|
|
|
202
229
|
m.id
|
|
203
230
|
);
|
|
204
231
|
}),
|
|
205
|
-
pending && /* @__PURE__ */ jsx(MessageScrollerItem, { children: /* @__PURE__ */ jsx(
|
|
232
|
+
pending && /* @__PURE__ */ jsx(MessageScrollerItem, { children: /* @__PURE__ */ jsx(ChatRunningLine, { label: pendingLabel, workspace }) }),
|
|
206
233
|
footer && // Always painted: content-visibility:auto would contain the
|
|
207
234
|
// footer's paint and layout, clipping a ring or shadow at its
|
|
208
235
|
// edge and re-parenting anything fixed inside it.
|