@epicbagel/saas-kit 1.4.0 → 1.5.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 +35 -0
- package/dist/{chunk-JZOBIPFC.js → chunk-FGISSYXG.js} +61 -2
- package/dist/{chunk-2AU7ZRGX.cjs → chunk-LAN3K2JI.cjs} +61 -2
- package/dist/primitives/chat.cjs +65 -12
- package/dist/primitives/chat.d.cts +46 -2
- package/dist/primitives/chat.d.ts +46 -2
- package/dist/primitives/chat.js +55 -2
- package/dist/primitives/message.cjs +8 -2
- package/dist/primitives/message.d.cts +35 -1
- package/dist/primitives/message.d.ts +35 -1
- package/dist/primitives/message.js +7 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -160,6 +160,41 @@ public in 1.1.0, and these were the decisions about its props then:
|
|
|
160
160
|
scroller neither anchors it nor tracks it. It has no time marker, files or
|
|
161
161
|
rich `content`, and the turns either side of it keep their time grouping.
|
|
162
162
|
|
|
163
|
+
### A turn's actions (1.5.0)
|
|
164
|
+
|
|
165
|
+
- **Under a reply, a row of actions.** `messageActions(message)` returns the
|
|
166
|
+
actions under a turn, after prompt-kit's "Message with Actions": small
|
|
167
|
+
icon-only ghost buttons with tooltips, drawn in a `MessageActions` row at
|
|
168
|
+
the message's side. `ChatCopyAction` is the ready one: it copies the turn's
|
|
169
|
+
`text`, its Markdown source, and shows a check and "Copied" for a moment.
|
|
170
|
+
Add your own after it with `MessageAction` (an icon child, a `tooltip`, and
|
|
171
|
+
`label` when the tooltip isn't text).
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<Chat
|
|
175
|
+
messages={messages}
|
|
176
|
+
onSend={send}
|
|
177
|
+
messageActions={(message) => (
|
|
178
|
+
<>
|
|
179
|
+
<ChatCopyAction message={message} onCopy={(ok) => ok && track("copy")} />
|
|
180
|
+
<MessageAction tooltip="Good reply" onClick={() => rate(message.id, "up")}>
|
|
181
|
+
<ThumbsUp />
|
|
182
|
+
</MessageAction>
|
|
183
|
+
</>
|
|
184
|
+
)}
|
|
185
|
+
/>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **Which turns.** Assistant turns, by default. `ChatMessage.actions: false`
|
|
189
|
+
drops them from a turn that isn't a reply (a progress line), `true` gives
|
|
190
|
+
them to a user turn. The running line, a running turn, a turn with
|
|
191
|
+
`status: "sending"` (the user's own turn shown optimistically, until its
|
|
192
|
+
stored copy replaces it) and the footer never have them.
|
|
193
|
+
- **Always there.** The row shows on every screen, a phone included, rather
|
|
194
|
+
than on hover, so nothing moves when a pointer reaches it, and the copied
|
|
195
|
+
state swaps one icon for another of the same size. A button is 2rem
|
|
196
|
+
square, 2.75rem on a touch screen, where the tooltip can't show.
|
|
197
|
+
|
|
163
198
|
## File preview (1.3.0)
|
|
164
199
|
|
|
165
200
|
`primitives/file-preview` shows a file in a dialog without leaving the page:
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Tooltip,
|
|
4
|
+
TooltipContent,
|
|
5
|
+
TooltipProvider,
|
|
6
|
+
TooltipTrigger
|
|
7
|
+
} from "./chunk-ZRLUUZHK.js";
|
|
8
|
+
import {
|
|
9
|
+
Button
|
|
10
|
+
} from "./chunk-HQRWRRZJ.js";
|
|
2
11
|
import {
|
|
3
12
|
cn
|
|
4
13
|
} from "./chunk-G6SRSWXB.js";
|
|
5
14
|
|
|
6
15
|
// src/primitives/message.tsx
|
|
7
|
-
import
|
|
16
|
+
import * as React from "react";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
18
|
function MessageGroup({ className, ...props }) {
|
|
9
19
|
return /* @__PURE__ */ jsx(
|
|
10
20
|
"div",
|
|
@@ -85,6 +95,53 @@ function MessageFooter({ className, ...props }) {
|
|
|
85
95
|
}
|
|
86
96
|
);
|
|
87
97
|
}
|
|
98
|
+
function MessageActions({ className, ...props }) {
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
"div",
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "message-actions",
|
|
103
|
+
className: cn(
|
|
104
|
+
"cn-message-actions flex max-w-full min-w-0 items-center gap-0.5 text-muted-foreground empty:hidden group-data-[align=end]/message:justify-end",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
var MessageAction = React.forwardRef(
|
|
112
|
+
function MessageAction2({
|
|
113
|
+
tooltip,
|
|
114
|
+
label,
|
|
115
|
+
side = "bottom",
|
|
116
|
+
variant = "quiet",
|
|
117
|
+
type = "button",
|
|
118
|
+
className,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) {
|
|
122
|
+
const name = label ?? (typeof tooltip === "string" ? tooltip : void 0);
|
|
123
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
125
|
+
Button,
|
|
126
|
+
{
|
|
127
|
+
ref,
|
|
128
|
+
type,
|
|
129
|
+
variant,
|
|
130
|
+
size: "icon-compact",
|
|
131
|
+
"aria-label": name,
|
|
132
|
+
"data-slot": "message-action",
|
|
133
|
+
className: cn(
|
|
134
|
+
"cn-message-action size-8 shrink-0 rounded-full pointer-coarse:size-11",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props,
|
|
138
|
+
children
|
|
139
|
+
}
|
|
140
|
+
) }),
|
|
141
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, children: tooltip })
|
|
142
|
+
] }) });
|
|
143
|
+
}
|
|
144
|
+
);
|
|
88
145
|
|
|
89
146
|
export {
|
|
90
147
|
MessageGroup,
|
|
@@ -92,5 +149,7 @@ export {
|
|
|
92
149
|
MessageAvatar,
|
|
93
150
|
MessageContent,
|
|
94
151
|
MessageHeader,
|
|
95
|
-
MessageFooter
|
|
152
|
+
MessageFooter,
|
|
153
|
+
MessageActions,
|
|
154
|
+
MessageAction
|
|
96
155
|
};
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkU2NES7VRcjs = require('./chunk-U2NES7VR.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunkL4DH72UFcjs = require('./chunk-L4DH72UF.cjs');
|
|
2
11
|
|
|
3
12
|
|
|
4
13
|
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
5
14
|
|
|
6
15
|
// src/primitives/message.tsx
|
|
16
|
+
var _react = require('react'); var React = _interopRequireWildcard(_react);
|
|
7
17
|
var _jsxruntime = require('react/jsx-runtime');
|
|
8
18
|
function MessageGroup({ className, ...props }) {
|
|
9
19
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -85,6 +95,55 @@ function MessageFooter({ className, ...props }) {
|
|
|
85
95
|
}
|
|
86
96
|
);
|
|
87
97
|
}
|
|
98
|
+
function MessageActions({ className, ...props }) {
|
|
99
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
100
|
+
"div",
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "message-actions",
|
|
103
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
104
|
+
"cn-message-actions flex max-w-full min-w-0 items-center gap-0.5 text-muted-foreground empty:hidden group-data-[align=end]/message:justify-end",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
var MessageAction = React.forwardRef(
|
|
112
|
+
function MessageAction2({
|
|
113
|
+
tooltip,
|
|
114
|
+
label,
|
|
115
|
+
side = "bottom",
|
|
116
|
+
variant = "quiet",
|
|
117
|
+
type = "button",
|
|
118
|
+
className,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) {
|
|
122
|
+
const name = _nullishCoalesce(label, () => ( (typeof tooltip === "string" ? tooltip : void 0)));
|
|
123
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkU2NES7VRcjs.Tooltip, { children: [
|
|
124
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
125
|
+
_chunkL4DH72UFcjs.Button,
|
|
126
|
+
{
|
|
127
|
+
ref,
|
|
128
|
+
type,
|
|
129
|
+
variant,
|
|
130
|
+
size: "icon-compact",
|
|
131
|
+
"aria-label": name,
|
|
132
|
+
"data-slot": "message-action",
|
|
133
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
134
|
+
"cn-message-action size-8 shrink-0 rounded-full pointer-coarse:size-11",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props,
|
|
138
|
+
children
|
|
139
|
+
}
|
|
140
|
+
) }),
|
|
141
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipContent, { side, children: tooltip })
|
|
142
|
+
] }) });
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
|
|
88
147
|
|
|
89
148
|
|
|
90
149
|
|
|
@@ -93,4 +152,4 @@ function MessageFooter({ className, ...props }) {
|
|
|
93
152
|
|
|
94
153
|
|
|
95
154
|
|
|
96
|
-
exports.MessageGroup = MessageGroup; exports.Message = Message; exports.MessageAvatar = MessageAvatar; exports.MessageContent = MessageContent; exports.MessageHeader = MessageHeader; exports.MessageFooter = MessageFooter;
|
|
155
|
+
exports.MessageGroup = MessageGroup; exports.Message = Message; exports.MessageAvatar = MessageAvatar; exports.MessageContent = MessageContent; exports.MessageHeader = MessageHeader; exports.MessageFooter = MessageFooter; exports.MessageActions = MessageActions; exports.MessageAction = MessageAction;
|
package/dist/primitives/chat.cjs
CHANGED
|
@@ -23,7 +23,9 @@ var _chunkXABXUP6Lcjs = require('../chunk-XABXUP6L.cjs');
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
var _chunkLAN3K2JIcjs = require('../chunk-LAN3K2JI.cjs');
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
|
|
@@ -75,6 +77,9 @@ require('../chunk-PQUSJEXL.cjs');
|
|
|
75
77
|
var _chunkL4DH72UFcjs = require('../chunk-L4DH72UF.cjs');
|
|
76
78
|
|
|
77
79
|
|
|
80
|
+
var _chunk4LXN6GLZcjs = require('../chunk-4LXN6GLZ.cjs');
|
|
81
|
+
|
|
82
|
+
|
|
78
83
|
var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
|
|
79
84
|
|
|
80
85
|
|
|
@@ -104,8 +109,14 @@ var _react = require('react');
|
|
|
104
109
|
|
|
105
110
|
|
|
106
111
|
|
|
112
|
+
|
|
113
|
+
|
|
107
114
|
var _lucidereact = require('lucide-react');
|
|
108
115
|
var _jsxruntime = require('react/jsx-runtime');
|
|
116
|
+
function offersActions(message) {
|
|
117
|
+
if (message.status) return false;
|
|
118
|
+
return _nullishCoalesce(message.actions, () => ( message.role === "assistant"));
|
|
119
|
+
}
|
|
109
120
|
function useArrivingUserTurnId(messages) {
|
|
110
121
|
const seen = _react.useRef.call(void 0, null);
|
|
111
122
|
seen.current ??= new Set(messages.map((m) => m.id));
|
|
@@ -138,7 +149,7 @@ function ChatRunningLine({
|
|
|
138
149
|
align = "start",
|
|
139
150
|
workspace
|
|
140
151
|
}) {
|
|
141
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
152
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAN3K2JIcjs.Message, { align, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAN3K2JIcjs.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
153
|
}
|
|
143
154
|
var ChatThread = _react.forwardRef.call(void 0,
|
|
144
155
|
function ChatThread2({
|
|
@@ -153,6 +164,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
153
164
|
markdownComponents,
|
|
154
165
|
onOpenAttachment,
|
|
155
166
|
attachmentAction = "open",
|
|
167
|
+
messageActions,
|
|
156
168
|
className
|
|
157
169
|
}, ref) {
|
|
158
170
|
const markers = timelineMarkers(messages, /* @__PURE__ */ new Date());
|
|
@@ -186,6 +198,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
186
198
|
}
|
|
187
199
|
const isFullWidth = m.width === "full";
|
|
188
200
|
const marker = markers[index];
|
|
201
|
+
const actions = messageActions && offersActions(m) ? messageActions(m) : null;
|
|
189
202
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
190
203
|
_chunkXABXUP6Lcjs.MessageScrollerItem,
|
|
191
204
|
{
|
|
@@ -194,7 +207,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
194
207
|
className: _chunkKWLSBTB2cjs.cn.call(void 0, "flex flex-col", workspace ? "gap-5" : "gap-3"),
|
|
195
208
|
children: [
|
|
196
209
|
marker ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TimelineMarker, { label: marker }) : null,
|
|
197
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
210
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAN3K2JIcjs.Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkLAN3K2JIcjs.MessageContent, { children: [
|
|
198
211
|
(m.content || m.text) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
199
212
|
_chunkV4YWTRLDcjs.Bubble,
|
|
200
213
|
{
|
|
@@ -222,7 +235,21 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
222
235
|
uploadingLabel,
|
|
223
236
|
className: "px-0 pt-0"
|
|
224
237
|
}
|
|
225
|
-
)
|
|
238
|
+
),
|
|
239
|
+
actions != null && actions !== false ? (
|
|
240
|
+
// Unboxed workspace turns pull the row out by the
|
|
241
|
+
// button's inset, so the first icon lines up with
|
|
242
|
+
// the text above it.
|
|
243
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
244
|
+
_chunkLAN3K2JIcjs.MessageActions,
|
|
245
|
+
{
|
|
246
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
247
|
+
workspace && (isUser ? "-me-2 pointer-coarse:-me-3.5" : "-ms-2 pointer-coarse:-ms-3.5")
|
|
248
|
+
),
|
|
249
|
+
children: actions
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
) : null
|
|
226
253
|
] }) })
|
|
227
254
|
]
|
|
228
255
|
},
|
|
@@ -233,7 +260,7 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
233
260
|
footer && // Always painted: content-visibility:auto would contain the
|
|
234
261
|
// footer's paint and layout, clipping a ring or shadow at its
|
|
235
262
|
// edge and re-parenting anything fixed inside it.
|
|
236
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { className: "[content-visibility:visible]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
263
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { className: "[content-visibility:visible]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAN3K2JIcjs.Message, { align: "start", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLAN3K2JIcjs.MessageContent, { children: footer }) }) })
|
|
237
264
|
]
|
|
238
265
|
}
|
|
239
266
|
) }),
|
|
@@ -246,6 +273,29 @@ var ChatThread = _react.forwardRef.call(void 0,
|
|
|
246
273
|
) });
|
|
247
274
|
}
|
|
248
275
|
);
|
|
276
|
+
function ChatCopyAction({
|
|
277
|
+
message,
|
|
278
|
+
label = "Copy",
|
|
279
|
+
copiedLabel = "Copied",
|
|
280
|
+
onCopy,
|
|
281
|
+
resetAfter = 2e3
|
|
282
|
+
}) {
|
|
283
|
+
const { copied, copy } = _chunk4LXN6GLZcjs.useCopyToClipboard.call(void 0, { resetAfter });
|
|
284
|
+
const text = message.text;
|
|
285
|
+
if (!text) return null;
|
|
286
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
287
|
+
_chunkLAN3K2JIcjs.MessageAction,
|
|
288
|
+
{
|
|
289
|
+
tooltip: copied ? copiedLabel : label,
|
|
290
|
+
"data-copied": copied || void 0,
|
|
291
|
+
onClick: async () => {
|
|
292
|
+
const ok = await copy(text);
|
|
293
|
+
_optionalChain([onCopy, 'optionalCall', _ => _(ok)]);
|
|
294
|
+
},
|
|
295
|
+
children: copied ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Check, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Copy, {})
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
}
|
|
249
299
|
function formatFileSize(size) {
|
|
250
300
|
if (size === void 0) return "File";
|
|
251
301
|
if (size < 1024) return `${size} B`;
|
|
@@ -285,7 +335,7 @@ function ChatAttachmentList({
|
|
|
285
335
|
{
|
|
286
336
|
"aria-label": `${verb} ${attachment.name}`,
|
|
287
337
|
title: `${verb} ${attachment.name}`,
|
|
288
|
-
onClick: () => _optionalChain([onOpen, 'optionalCall',
|
|
338
|
+
onClick: () => _optionalChain([onOpen, 'optionalCall', _2 => _2(attachment)]),
|
|
289
339
|
className: "rounded-xl focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
290
340
|
}
|
|
291
341
|
),
|
|
@@ -430,7 +480,7 @@ function ChatInput({
|
|
|
430
480
|
"data-slot": "chat-input-actions",
|
|
431
481
|
onClick: (event) => {
|
|
432
482
|
if (!event.currentTarget.contains(event.target)) return;
|
|
433
|
-
if (!event.target.closest("button")) _optionalChain([ref, 'access',
|
|
483
|
+
if (!event.target.closest("button")) _optionalChain([ref, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.focus, 'call', _5 => _5()]);
|
|
434
484
|
},
|
|
435
485
|
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
436
486
|
"gap-2",
|
|
@@ -448,7 +498,7 @@ function ChatInput({
|
|
|
448
498
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Plus, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
|
|
449
499
|
}
|
|
450
500
|
) }),
|
|
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',
|
|
501
|
+
/* @__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', _6 => _6.current, 'optionalAccess', _7 => _7.click, 'call', _8 => _8()]), children: [
|
|
452
502
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Paperclip, { className: "h-4 w-4" }),
|
|
453
503
|
addFilesLabel
|
|
454
504
|
] }) })
|
|
@@ -655,6 +705,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
655
705
|
markdownComponents,
|
|
656
706
|
onOpenAttachment,
|
|
657
707
|
attachmentAction,
|
|
708
|
+
messageActions,
|
|
658
709
|
className
|
|
659
710
|
}, ref) {
|
|
660
711
|
const isMobile = _chunkR35FT53Gcjs.useIsMobile.call(void 0, );
|
|
@@ -679,14 +730,14 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
679
730
|
else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
|
|
680
731
|
else console.error(cause);
|
|
681
732
|
}
|
|
682
|
-
window.setTimeout(() => _optionalChain([inputRef, 'access',
|
|
733
|
+
window.setTimeout(() => _optionalChain([inputRef, 'access', _9 => _9.current, 'optionalAccess', _10 => _10.focus, 'call', _11 => _11()]), 0);
|
|
683
734
|
},
|
|
684
735
|
[attachments, mode, onSend, onSendError, pending]
|
|
685
736
|
);
|
|
686
737
|
_react.useImperativeHandle.call(void 0,
|
|
687
738
|
ref,
|
|
688
739
|
() => ({
|
|
689
|
-
focusInput: () => _optionalChain([inputRef, 'access',
|
|
740
|
+
focusInput: () => _optionalChain([inputRef, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.focus, 'call', _14 => _14()]),
|
|
690
741
|
clearInput: () => setInput("")
|
|
691
742
|
}),
|
|
692
743
|
[]
|
|
@@ -694,7 +745,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
694
745
|
const dropFiles = _react.useCallback.call(void 0,
|
|
695
746
|
(files) => {
|
|
696
747
|
if (!conversationStarted && mode === "voice") setUserMode("text");
|
|
697
|
-
return _optionalChain([onFilesSelected, 'optionalCall',
|
|
748
|
+
return _optionalChain([onFilesSelected, 'optionalCall', _15 => _15(files)]);
|
|
698
749
|
},
|
|
699
750
|
[conversationStarted, mode, onFilesSelected]
|
|
700
751
|
);
|
|
@@ -851,6 +902,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
851
902
|
markdownComponents,
|
|
852
903
|
onOpenAttachment,
|
|
853
904
|
attachmentAction,
|
|
905
|
+
messageActions,
|
|
854
906
|
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
855
907
|
"mb-3",
|
|
856
908
|
application && "min-h-0 flex-1 px-4 py-4 md:px-0 md:py-0",
|
|
@@ -905,4 +957,5 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
905
957
|
|
|
906
958
|
|
|
907
959
|
|
|
908
|
-
|
|
960
|
+
|
|
961
|
+
exports.Chat = Chat; exports.ChatCopyAction = ChatCopyAction; exports.ChatInput = ChatInput; exports.ChatThread = ChatThread;
|
|
@@ -43,8 +43,20 @@ type ChatMessage = {
|
|
|
43
43
|
* with the reply when that lands. The line is not a message: it has no time
|
|
44
44
|
* marker, files or rich `content`, and the scroller neither anchors nor
|
|
45
45
|
* tracks it.
|
|
46
|
+
*
|
|
47
|
+
* `"sending"`: a turn still on its way to being stored, such as the user's
|
|
48
|
+
* own turn shown optimistically. It is drawn as any turn, but offers no
|
|
49
|
+
* actions until its stored copy replaces it.
|
|
46
50
|
*/
|
|
47
|
-
status?: "running";
|
|
51
|
+
status?: "running" | "sending";
|
|
52
|
+
/**
|
|
53
|
+
* Whether the thread offers this turn the actions `messageActions` returns.
|
|
54
|
+
* By default an assistant turn has them and a user turn doesn't; `false`
|
|
55
|
+
* drops them from an assistant turn that isn't a reply (a progress line),
|
|
56
|
+
* and `true` gives them to a user turn. A running or sending turn never has
|
|
57
|
+
* them, whatever this says.
|
|
58
|
+
*/
|
|
59
|
+
actions?: boolean;
|
|
48
60
|
};
|
|
49
61
|
interface ChatThreadProps {
|
|
50
62
|
messages: ChatMessage[];
|
|
@@ -80,6 +92,15 @@ interface ChatThreadProps {
|
|
|
80
92
|
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
81
93
|
/** What opening a message's file does, for its label and icon. Defaults to `"open"`. */
|
|
82
94
|
attachmentAction?: ChatAttachmentAction;
|
|
95
|
+
/**
|
|
96
|
+
* The actions under a turn, in a `MessageActions` row: `ChatCopyAction`,
|
|
97
|
+
* then any `MessageAction`s of your own (a thumbs up or down). Called for
|
|
98
|
+
* each turn that offers them (`ChatMessage.actions`: assistant turns, by
|
|
99
|
+
* default), never for the running line, a running or sending turn or the
|
|
100
|
+
* footer. The row always shows, on a phone too, so nothing moves when a
|
|
101
|
+
* pointer reaches it; return `null` for none.
|
|
102
|
+
*/
|
|
103
|
+
messageActions?: (message: ChatMessage) => ReactNode;
|
|
83
104
|
className?: string;
|
|
84
105
|
}
|
|
85
106
|
/**
|
|
@@ -97,6 +118,24 @@ interface ChatThreadProps {
|
|
|
97
118
|
* appears. A turn with `status: "running"` draws the same line in its place.
|
|
98
119
|
*/
|
|
99
120
|
declare const ChatThread: React$1.ForwardRefExoticComponent<ChatThreadProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
121
|
+
interface ChatCopyActionProps {
|
|
122
|
+
/** The turn whose `text` (its Markdown source) is copied. */
|
|
123
|
+
message: Pick<ChatMessage, "text">;
|
|
124
|
+
/** The tooltip and accessible name. Defaults to "Copy". */
|
|
125
|
+
label?: string;
|
|
126
|
+
/** Both, for a moment after a copy. Defaults to "Copied". */
|
|
127
|
+
copiedLabel?: string;
|
|
128
|
+
/** Called after each copy, with whether the clipboard took the text. */
|
|
129
|
+
onCopy?: (success: boolean) => void;
|
|
130
|
+
/** How long the copied state shows, in ms. Defaults to 2000. */
|
|
131
|
+
resetAfter?: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The ready Copy action for `messageActions`: copies the turn's `text`, its
|
|
135
|
+
* Markdown source, and shows a check and "Copied" for a moment. A turn with
|
|
136
|
+
* no `text` (rich `content` only) has nothing to copy, so it draws nothing.
|
|
137
|
+
*/
|
|
138
|
+
declare function ChatCopyAction({ message, label, copiedLabel, onCopy, resetAfter, }: ChatCopyActionProps): react_jsx_runtime.JSX.Element | null;
|
|
100
139
|
interface ChatInputProps {
|
|
101
140
|
value: string;
|
|
102
141
|
onChange: (next: string) => void;
|
|
@@ -330,6 +369,11 @@ interface ChatProps {
|
|
|
330
369
|
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
331
370
|
/** What opening a message's file does, for its label and icon. Defaults to `"open"`. */
|
|
332
371
|
attachmentAction?: ChatAttachmentAction;
|
|
372
|
+
/**
|
|
373
|
+
* The actions under each turn that offers them (`ChatMessage.actions`:
|
|
374
|
+
* assistant turns, by default), such as `ChatCopyAction`. See `ChatThread`.
|
|
375
|
+
*/
|
|
376
|
+
messageActions?: (message: ChatMessage) => ReactNode;
|
|
333
377
|
className?: string;
|
|
334
378
|
}
|
|
335
379
|
interface ChatHandle {
|
|
@@ -361,4 +405,4 @@ interface ChatHandle {
|
|
|
361
405
|
*/
|
|
362
406
|
declare const Chat: React$1.ForwardRefExoticComponent<ChatProps & React$1.RefAttributes<ChatHandle>>;
|
|
363
407
|
|
|
364
|
-
export { Chat, type ChatAttachment, type ChatAttachmentAction, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps };
|
|
408
|
+
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps };
|
|
@@ -43,8 +43,20 @@ type ChatMessage = {
|
|
|
43
43
|
* with the reply when that lands. The line is not a message: it has no time
|
|
44
44
|
* marker, files or rich `content`, and the scroller neither anchors nor
|
|
45
45
|
* tracks it.
|
|
46
|
+
*
|
|
47
|
+
* `"sending"`: a turn still on its way to being stored, such as the user's
|
|
48
|
+
* own turn shown optimistically. It is drawn as any turn, but offers no
|
|
49
|
+
* actions until its stored copy replaces it.
|
|
46
50
|
*/
|
|
47
|
-
status?: "running";
|
|
51
|
+
status?: "running" | "sending";
|
|
52
|
+
/**
|
|
53
|
+
* Whether the thread offers this turn the actions `messageActions` returns.
|
|
54
|
+
* By default an assistant turn has them and a user turn doesn't; `false`
|
|
55
|
+
* drops them from an assistant turn that isn't a reply (a progress line),
|
|
56
|
+
* and `true` gives them to a user turn. A running or sending turn never has
|
|
57
|
+
* them, whatever this says.
|
|
58
|
+
*/
|
|
59
|
+
actions?: boolean;
|
|
48
60
|
};
|
|
49
61
|
interface ChatThreadProps {
|
|
50
62
|
messages: ChatMessage[];
|
|
@@ -80,6 +92,15 @@ interface ChatThreadProps {
|
|
|
80
92
|
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
81
93
|
/** What opening a message's file does, for its label and icon. Defaults to `"open"`. */
|
|
82
94
|
attachmentAction?: ChatAttachmentAction;
|
|
95
|
+
/**
|
|
96
|
+
* The actions under a turn, in a `MessageActions` row: `ChatCopyAction`,
|
|
97
|
+
* then any `MessageAction`s of your own (a thumbs up or down). Called for
|
|
98
|
+
* each turn that offers them (`ChatMessage.actions`: assistant turns, by
|
|
99
|
+
* default), never for the running line, a running or sending turn or the
|
|
100
|
+
* footer. The row always shows, on a phone too, so nothing moves when a
|
|
101
|
+
* pointer reaches it; return `null` for none.
|
|
102
|
+
*/
|
|
103
|
+
messageActions?: (message: ChatMessage) => ReactNode;
|
|
83
104
|
className?: string;
|
|
84
105
|
}
|
|
85
106
|
/**
|
|
@@ -97,6 +118,24 @@ interface ChatThreadProps {
|
|
|
97
118
|
* appears. A turn with `status: "running"` draws the same line in its place.
|
|
98
119
|
*/
|
|
99
120
|
declare const ChatThread: React$1.ForwardRefExoticComponent<ChatThreadProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
121
|
+
interface ChatCopyActionProps {
|
|
122
|
+
/** The turn whose `text` (its Markdown source) is copied. */
|
|
123
|
+
message: Pick<ChatMessage, "text">;
|
|
124
|
+
/** The tooltip and accessible name. Defaults to "Copy". */
|
|
125
|
+
label?: string;
|
|
126
|
+
/** Both, for a moment after a copy. Defaults to "Copied". */
|
|
127
|
+
copiedLabel?: string;
|
|
128
|
+
/** Called after each copy, with whether the clipboard took the text. */
|
|
129
|
+
onCopy?: (success: boolean) => void;
|
|
130
|
+
/** How long the copied state shows, in ms. Defaults to 2000. */
|
|
131
|
+
resetAfter?: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The ready Copy action for `messageActions`: copies the turn's `text`, its
|
|
135
|
+
* Markdown source, and shows a check and "Copied" for a moment. A turn with
|
|
136
|
+
* no `text` (rich `content` only) has nothing to copy, so it draws nothing.
|
|
137
|
+
*/
|
|
138
|
+
declare function ChatCopyAction({ message, label, copiedLabel, onCopy, resetAfter, }: ChatCopyActionProps): react_jsx_runtime.JSX.Element | null;
|
|
100
139
|
interface ChatInputProps {
|
|
101
140
|
value: string;
|
|
102
141
|
onChange: (next: string) => void;
|
|
@@ -330,6 +369,11 @@ interface ChatProps {
|
|
|
330
369
|
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
331
370
|
/** What opening a message's file does, for its label and icon. Defaults to `"open"`. */
|
|
332
371
|
attachmentAction?: ChatAttachmentAction;
|
|
372
|
+
/**
|
|
373
|
+
* The actions under each turn that offers them (`ChatMessage.actions`:
|
|
374
|
+
* assistant turns, by default), such as `ChatCopyAction`. See `ChatThread`.
|
|
375
|
+
*/
|
|
376
|
+
messageActions?: (message: ChatMessage) => ReactNode;
|
|
333
377
|
className?: string;
|
|
334
378
|
}
|
|
335
379
|
interface ChatHandle {
|
|
@@ -361,4 +405,4 @@ interface ChatHandle {
|
|
|
361
405
|
*/
|
|
362
406
|
declare const Chat: React$1.ForwardRefExoticComponent<ChatProps & React$1.RefAttributes<ChatHandle>>;
|
|
363
407
|
|
|
364
|
-
export { Chat, type ChatAttachment, type ChatAttachmentAction, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps };
|
|
408
|
+
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps };
|
package/dist/primitives/chat.js
CHANGED
|
@@ -22,8 +22,10 @@ import {
|
|
|
22
22
|
} from "../chunk-GFG2R5BZ.js";
|
|
23
23
|
import {
|
|
24
24
|
Message,
|
|
25
|
+
MessageAction,
|
|
26
|
+
MessageActions,
|
|
25
27
|
MessageContent
|
|
26
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-FGISSYXG.js";
|
|
27
29
|
import {
|
|
28
30
|
Marker,
|
|
29
31
|
MarkerContent
|
|
@@ -73,6 +75,9 @@ import "../chunk-QMA3WVB7.js";
|
|
|
73
75
|
import {
|
|
74
76
|
Button
|
|
75
77
|
} from "../chunk-HQRWRRZJ.js";
|
|
78
|
+
import {
|
|
79
|
+
useCopyToClipboard
|
|
80
|
+
} from "../chunk-ZWZAAGQF.js";
|
|
76
81
|
import {
|
|
77
82
|
useIsMobile
|
|
78
83
|
} from "../chunk-PIU5SSUV.js";
|
|
@@ -98,6 +103,8 @@ import {
|
|
|
98
103
|
ArrowRight,
|
|
99
104
|
ArrowUp,
|
|
100
105
|
ArrowUpRight,
|
|
106
|
+
Check,
|
|
107
|
+
Copy,
|
|
101
108
|
Download,
|
|
102
109
|
FileText,
|
|
103
110
|
LockKeyhole,
|
|
@@ -106,6 +113,10 @@ import {
|
|
|
106
113
|
X
|
|
107
114
|
} from "lucide-react";
|
|
108
115
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
116
|
+
function offersActions(message) {
|
|
117
|
+
if (message.status) return false;
|
|
118
|
+
return message.actions ?? message.role === "assistant";
|
|
119
|
+
}
|
|
109
120
|
function useArrivingUserTurnId(messages) {
|
|
110
121
|
const seen = useRef(null);
|
|
111
122
|
seen.current ??= new Set(messages.map((m) => m.id));
|
|
@@ -153,6 +164,7 @@ var ChatThread = forwardRef(
|
|
|
153
164
|
markdownComponents,
|
|
154
165
|
onOpenAttachment,
|
|
155
166
|
attachmentAction = "open",
|
|
167
|
+
messageActions,
|
|
156
168
|
className
|
|
157
169
|
}, ref) {
|
|
158
170
|
const markers = timelineMarkers(messages, /* @__PURE__ */ new Date());
|
|
@@ -186,6 +198,7 @@ var ChatThread = forwardRef(
|
|
|
186
198
|
}
|
|
187
199
|
const isFullWidth = m.width === "full";
|
|
188
200
|
const marker = markers[index];
|
|
201
|
+
const actions = messageActions && offersActions(m) ? messageActions(m) : null;
|
|
189
202
|
return /* @__PURE__ */ jsxs(
|
|
190
203
|
MessageScrollerItem,
|
|
191
204
|
{
|
|
@@ -222,7 +235,21 @@ var ChatThread = forwardRef(
|
|
|
222
235
|
uploadingLabel,
|
|
223
236
|
className: "px-0 pt-0"
|
|
224
237
|
}
|
|
225
|
-
)
|
|
238
|
+
),
|
|
239
|
+
actions != null && actions !== false ? (
|
|
240
|
+
// Unboxed workspace turns pull the row out by the
|
|
241
|
+
// button's inset, so the first icon lines up with
|
|
242
|
+
// the text above it.
|
|
243
|
+
/* @__PURE__ */ jsx(
|
|
244
|
+
MessageActions,
|
|
245
|
+
{
|
|
246
|
+
className: cn(
|
|
247
|
+
workspace && (isUser ? "-me-2 pointer-coarse:-me-3.5" : "-ms-2 pointer-coarse:-ms-3.5")
|
|
248
|
+
),
|
|
249
|
+
children: actions
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
) : null
|
|
226
253
|
] }) })
|
|
227
254
|
]
|
|
228
255
|
},
|
|
@@ -246,6 +273,29 @@ var ChatThread = forwardRef(
|
|
|
246
273
|
) });
|
|
247
274
|
}
|
|
248
275
|
);
|
|
276
|
+
function ChatCopyAction({
|
|
277
|
+
message,
|
|
278
|
+
label = "Copy",
|
|
279
|
+
copiedLabel = "Copied",
|
|
280
|
+
onCopy,
|
|
281
|
+
resetAfter = 2e3
|
|
282
|
+
}) {
|
|
283
|
+
const { copied, copy } = useCopyToClipboard({ resetAfter });
|
|
284
|
+
const text = message.text;
|
|
285
|
+
if (!text) return null;
|
|
286
|
+
return /* @__PURE__ */ jsx(
|
|
287
|
+
MessageAction,
|
|
288
|
+
{
|
|
289
|
+
tooltip: copied ? copiedLabel : label,
|
|
290
|
+
"data-copied": copied || void 0,
|
|
291
|
+
onClick: async () => {
|
|
292
|
+
const ok = await copy(text);
|
|
293
|
+
onCopy?.(ok);
|
|
294
|
+
},
|
|
295
|
+
children: copied ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(Copy, {})
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
}
|
|
249
299
|
function formatFileSize(size) {
|
|
250
300
|
if (size === void 0) return "File";
|
|
251
301
|
if (size < 1024) return `${size} B`;
|
|
@@ -655,6 +705,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
655
705
|
markdownComponents,
|
|
656
706
|
onOpenAttachment,
|
|
657
707
|
attachmentAction,
|
|
708
|
+
messageActions,
|
|
658
709
|
className
|
|
659
710
|
}, ref) {
|
|
660
711
|
const isMobile = useIsMobile();
|
|
@@ -851,6 +902,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
851
902
|
markdownComponents,
|
|
852
903
|
onOpenAttachment,
|
|
853
904
|
attachmentAction,
|
|
905
|
+
messageActions,
|
|
854
906
|
className: cn(
|
|
855
907
|
"mb-3",
|
|
856
908
|
application && "min-h-0 flex-1 px-4 py-4 md:px-0 md:py-0",
|
|
@@ -903,6 +955,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
903
955
|
});
|
|
904
956
|
export {
|
|
905
957
|
Chat,
|
|
958
|
+
ChatCopyAction,
|
|
906
959
|
ChatInput,
|
|
907
960
|
ChatThread
|
|
908
961
|
};
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
var _chunkLAN3K2JIcjs = require('../chunk-LAN3K2JI.cjs');
|
|
12
|
+
require('../chunk-U2NES7VR.cjs');
|
|
13
|
+
require('../chunk-L4DH72UF.cjs');
|
|
10
14
|
require('../chunk-KWLSBTB2.cjs');
|
|
11
15
|
|
|
12
16
|
|
|
@@ -15,4 +19,6 @@ require('../chunk-KWLSBTB2.cjs');
|
|
|
15
19
|
|
|
16
20
|
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
exports.Message = _chunkLAN3K2JIcjs.Message; exports.MessageAction = _chunkLAN3K2JIcjs.MessageAction; exports.MessageActions = _chunkLAN3K2JIcjs.MessageActions; exports.MessageAvatar = _chunkLAN3K2JIcjs.MessageAvatar; exports.MessageContent = _chunkLAN3K2JIcjs.MessageContent; exports.MessageFooter = _chunkLAN3K2JIcjs.MessageFooter; exports.MessageGroup = _chunkLAN3K2JIcjs.MessageGroup; exports.MessageHeader = _chunkLAN3K2JIcjs.MessageHeader;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { ButtonProps } from './button.cjs';
|
|
4
|
+
import { TooltipContent } from './tooltip.cjs';
|
|
5
|
+
import 'class-variance-authority/types';
|
|
6
|
+
import 'class-variance-authority';
|
|
7
|
+
import '@radix-ui/react-tooltip';
|
|
3
8
|
|
|
4
9
|
declare function MessageGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
5
10
|
declare function Message({ className, align, ...props }: React.ComponentProps<"div"> & {
|
|
@@ -9,5 +14,34 @@ declare function MessageAvatar({ className, ...props }: React.ComponentProps<"di
|
|
|
9
14
|
declare function MessageContent({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
10
15
|
declare function MessageHeader({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
11
16
|
declare function MessageFooter({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* A row of `MessageAction`s under a message: copy, then any others (a thumbs
|
|
19
|
+
* up or down). It sits at the message's side, the start of a turn from the
|
|
20
|
+
* other party and the end of one aligned to the end, and collapses when it
|
|
21
|
+
* holds nothing.
|
|
22
|
+
*/
|
|
23
|
+
declare function MessageActions({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
24
|
+
type MessageActionProps = Omit<ButtonProps, "size" | "aria-label"> & {
|
|
25
|
+
/** What the action does: its tooltip, and its accessible name when it is text. */
|
|
26
|
+
tooltip: React.ReactNode;
|
|
27
|
+
/** The accessible name, for a `tooltip` that isn't plain text. */
|
|
28
|
+
label?: string;
|
|
29
|
+
/** Which side of the button the tooltip opens on. Defaults to `"bottom"`. */
|
|
30
|
+
side?: React.ComponentPropsWithoutRef<typeof TooltipContent>["side"];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* One action in a `MessageActions` row: an icon-only ghost button (pass the
|
|
34
|
+
* icon as its child) with a tooltip and an accessible name. It is 2rem
|
|
35
|
+
* square, and 2.75rem on a touch screen, where the tooltip can't show on
|
|
36
|
+
* hover, so a finger has the kit's usual target.
|
|
37
|
+
*/
|
|
38
|
+
declare const MessageAction: React.ForwardRefExoticComponent<Omit<ButtonProps, "aria-label" | "size"> & {
|
|
39
|
+
/** What the action does: its tooltip, and its accessible name when it is text. */
|
|
40
|
+
tooltip: React.ReactNode;
|
|
41
|
+
/** The accessible name, for a `tooltip` that isn't plain text. */
|
|
42
|
+
label?: string;
|
|
43
|
+
/** Which side of the button the tooltip opens on. Defaults to `"bottom"`. */
|
|
44
|
+
side?: React.ComponentPropsWithoutRef<typeof TooltipContent>["side"];
|
|
45
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
12
46
|
|
|
13
|
-
export { Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader };
|
|
47
|
+
export { Message, MessageAction, type MessageActionProps, MessageActions, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader };
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { ButtonProps } from './button.js';
|
|
4
|
+
import { TooltipContent } from './tooltip.js';
|
|
5
|
+
import 'class-variance-authority/types';
|
|
6
|
+
import 'class-variance-authority';
|
|
7
|
+
import '@radix-ui/react-tooltip';
|
|
3
8
|
|
|
4
9
|
declare function MessageGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
5
10
|
declare function Message({ className, align, ...props }: React.ComponentProps<"div"> & {
|
|
@@ -9,5 +14,34 @@ declare function MessageAvatar({ className, ...props }: React.ComponentProps<"di
|
|
|
9
14
|
declare function MessageContent({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
10
15
|
declare function MessageHeader({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
11
16
|
declare function MessageFooter({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* A row of `MessageAction`s under a message: copy, then any others (a thumbs
|
|
19
|
+
* up or down). It sits at the message's side, the start of a turn from the
|
|
20
|
+
* other party and the end of one aligned to the end, and collapses when it
|
|
21
|
+
* holds nothing.
|
|
22
|
+
*/
|
|
23
|
+
declare function MessageActions({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
|
|
24
|
+
type MessageActionProps = Omit<ButtonProps, "size" | "aria-label"> & {
|
|
25
|
+
/** What the action does: its tooltip, and its accessible name when it is text. */
|
|
26
|
+
tooltip: React.ReactNode;
|
|
27
|
+
/** The accessible name, for a `tooltip` that isn't plain text. */
|
|
28
|
+
label?: string;
|
|
29
|
+
/** Which side of the button the tooltip opens on. Defaults to `"bottom"`. */
|
|
30
|
+
side?: React.ComponentPropsWithoutRef<typeof TooltipContent>["side"];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* One action in a `MessageActions` row: an icon-only ghost button (pass the
|
|
34
|
+
* icon as its child) with a tooltip and an accessible name. It is 2rem
|
|
35
|
+
* square, and 2.75rem on a touch screen, where the tooltip can't show on
|
|
36
|
+
* hover, so a finger has the kit's usual target.
|
|
37
|
+
*/
|
|
38
|
+
declare const MessageAction: React.ForwardRefExoticComponent<Omit<ButtonProps, "aria-label" | "size"> & {
|
|
39
|
+
/** What the action does: its tooltip, and its accessible name when it is text. */
|
|
40
|
+
tooltip: React.ReactNode;
|
|
41
|
+
/** The accessible name, for a `tooltip` that isn't plain text. */
|
|
42
|
+
label?: string;
|
|
43
|
+
/** Which side of the button the tooltip opens on. Defaults to `"bottom"`. */
|
|
44
|
+
side?: React.ComponentPropsWithoutRef<typeof TooltipContent>["side"];
|
|
45
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
12
46
|
|
|
13
|
-
export { Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader };
|
|
47
|
+
export { Message, MessageAction, type MessageActionProps, MessageActions, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader };
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
Message,
|
|
4
|
+
MessageAction,
|
|
5
|
+
MessageActions,
|
|
4
6
|
MessageAvatar,
|
|
5
7
|
MessageContent,
|
|
6
8
|
MessageFooter,
|
|
7
9
|
MessageGroup,
|
|
8
10
|
MessageHeader
|
|
9
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-FGISSYXG.js";
|
|
12
|
+
import "../chunk-ZRLUUZHK.js";
|
|
13
|
+
import "../chunk-HQRWRRZJ.js";
|
|
10
14
|
import "../chunk-G6SRSWXB.js";
|
|
11
15
|
export {
|
|
12
16
|
Message,
|
|
17
|
+
MessageAction,
|
|
18
|
+
MessageActions,
|
|
13
19
|
MessageAvatar,
|
|
14
20
|
MessageContent,
|
|
15
21
|
MessageFooter,
|
package/package.json
CHANGED