@epicbagel/saas-kit 1.26.0 → 1.28.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 +26 -0
- package/dist/chunk-DHXKCMKY.cjs +198 -0
- package/dist/chunk-MP64UGRF.js +72 -0
- package/dist/chunk-PPYHNJMV.cjs +72 -0
- package/dist/chunk-SG4ZE2EN.js +198 -0
- package/dist/{chunk-NXFZULS3.js → chunk-T5AFBLP2.js} +4 -2
- package/dist/{chunk-U7XNNLVP.cjs → chunk-WP7CKIPE.cjs} +4 -2
- package/dist/primitives/activity-feed.cjs +2 -2
- package/dist/primitives/activity-feed.js +1 -1
- package/dist/primitives/chat.cjs +111 -2
- package/dist/primitives/chat.d.cts +35 -1
- package/dist/primitives/chat.d.ts +35 -1
- package/dist/primitives/chat.js +110 -1
- package/dist/primitives/chip-tabs.cjs +2 -2
- package/dist/primitives/chip-tabs.d.cts +13 -2
- package/dist/primitives/chip-tabs.d.ts +13 -2
- package/dist/primitives/chip-tabs.js +1 -1
- package/dist/primitives/item.cjs +24 -194
- package/dist/primitives/item.js +13 -183
- package/dist/primitives/person-avatar.cjs +2 -2
- package/dist/primitives/person-avatar.d.cts +6 -1
- package/dist/primitives/person-avatar.d.ts +6 -1
- package/dist/primitives/person-avatar.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-KGFL3VWY.cjs +0 -62
- package/dist/chunk-QD63LB2F.js +0 -62
package/dist/primitives/chat.cjs
CHANGED
|
@@ -17,7 +17,10 @@ var _chunkPNI354BYcjs = require('../chunk-PNI354BY.cjs');
|
|
|
17
17
|
var _chunkM4V7OJNFcjs = require('../chunk-M4V7OJNF.cjs');
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
var
|
|
20
|
+
var _chunkVMXKT67Ecjs = require('../chunk-VMXKT67E.cjs');
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
var _chunkWP7CKIPEcjs = require('../chunk-WP7CKIPE.cjs');
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
|
|
@@ -37,6 +40,14 @@ require('../chunk-2HV2KKOE.cjs');
|
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
var _chunkDHXKCMKYcjs = require('../chunk-DHXKCMKY.cjs');
|
|
47
|
+
require('../chunk-NQK5ZWC7.cjs');
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
40
51
|
var _chunkZLEM2SAUcjs = require('../chunk-ZLEM2SAU.cjs');
|
|
41
52
|
|
|
42
53
|
|
|
@@ -120,6 +131,7 @@ var _chunkH2UFRLLNcjs = require('../chunk-H2UFRLLN.cjs');
|
|
|
120
131
|
|
|
121
132
|
|
|
122
133
|
|
|
134
|
+
|
|
123
135
|
var _react = require('react');
|
|
124
136
|
|
|
125
137
|
|
|
@@ -178,7 +190,7 @@ function authorLines(messages, markers) {
|
|
|
178
190
|
});
|
|
179
191
|
}
|
|
180
192
|
function ChatAuthorLine({ author, align }) {
|
|
181
|
-
const avatar = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
193
|
+
const avatar = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkWP7CKIPEcjs.PersonAvatar, { name: author.name, photoUrl: author.avatarUrl, size: 20, fallbackClassName: "text-[9px]" });
|
|
182
194
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-author", className: _chunkKWLSBTB2cjs.cn.call(void 0, "flex items-center gap-2 text-xs", align === "end" ? "self-end" : "self-start"), children: [
|
|
183
195
|
align === "start" ? avatar : null,
|
|
184
196
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium text-foreground", children: author.name }),
|
|
@@ -758,6 +770,92 @@ function ChatSuggestions({
|
|
|
758
770
|
)
|
|
759
771
|
] });
|
|
760
772
|
}
|
|
773
|
+
var DEFAULT_EMPTY_ACTIONS_LABEL = "Pick up where you left off";
|
|
774
|
+
function ChatEmptyActionIcon({ icon }) {
|
|
775
|
+
if (!icon) return null;
|
|
776
|
+
if (_react.isValidElement.call(void 0, icon)) return icon;
|
|
777
|
+
if (typeof icon === "function" || typeof icon === "object" && icon !== null && "render" in icon) {
|
|
778
|
+
const IconComp = icon;
|
|
779
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IconComp, { "aria-hidden": true });
|
|
780
|
+
}
|
|
781
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: icon });
|
|
782
|
+
}
|
|
783
|
+
function ChatEmptyActions({
|
|
784
|
+
items,
|
|
785
|
+
label,
|
|
786
|
+
onError,
|
|
787
|
+
className
|
|
788
|
+
}) {
|
|
789
|
+
const labelId = _react.useId.call(void 0, );
|
|
790
|
+
const [running, setRunning] = _react.useState.call(void 0, null);
|
|
791
|
+
if (items.length === 0) return null;
|
|
792
|
+
const showLabel = label.length > 0;
|
|
793
|
+
const pick = async (item) => {
|
|
794
|
+
if (running !== null) return;
|
|
795
|
+
let result;
|
|
796
|
+
try {
|
|
797
|
+
result = item.onSelect();
|
|
798
|
+
} catch (cause) {
|
|
799
|
+
onError(cause);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (!result || typeof result.then !== "function") return;
|
|
803
|
+
setRunning(item.id);
|
|
804
|
+
try {
|
|
805
|
+
await result;
|
|
806
|
+
} catch (cause) {
|
|
807
|
+
onError(cause);
|
|
808
|
+
} finally {
|
|
809
|
+
setRunning(null);
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-empty-actions", className: _chunkKWLSBTB2cjs.cn.call(void 0, "w-full text-left", className), children: [
|
|
813
|
+
showLabel && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { id: labelId, "data-slot": "chat-empty-actions-label", className: "mb-1.5 px-3 text-xs text-muted-foreground", children: label }),
|
|
814
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
815
|
+
"div",
|
|
816
|
+
{
|
|
817
|
+
role: "group",
|
|
818
|
+
"aria-labelledby": showLabel ? labelId : void 0,
|
|
819
|
+
"aria-label": showLabel ? void 0 : DEFAULT_EMPTY_ACTIONS_LABEL,
|
|
820
|
+
className: "flex flex-col gap-0.5",
|
|
821
|
+
children: items.map((item) => {
|
|
822
|
+
const busy = running === item.id;
|
|
823
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkDHXKCMKYcjs.Item, { asChild: true, size: "sm", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
824
|
+
"button",
|
|
825
|
+
{
|
|
826
|
+
type: "button",
|
|
827
|
+
"data-slot": "chat-empty-action",
|
|
828
|
+
"data-state": busy ? "loading" : void 0,
|
|
829
|
+
"aria-busy": busy || void 0,
|
|
830
|
+
disabled: item.disabled || running !== null,
|
|
831
|
+
onClick: () => void pick(item),
|
|
832
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
833
|
+
"min-h-11 cursor-pointer flex-nowrap text-left",
|
|
834
|
+
"hover:bg-muted focus-visible:bg-muted",
|
|
835
|
+
"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent",
|
|
836
|
+
busy && "disabled:opacity-100"
|
|
837
|
+
),
|
|
838
|
+
children: [
|
|
839
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
840
|
+
_chunkDHXKCMKYcjs.ItemMedia,
|
|
841
|
+
{
|
|
842
|
+
variant: "icon",
|
|
843
|
+
className: "size-8 self-center rounded-md bg-muted text-muted-foreground group-has-data-[slot=item-description]/item:translate-y-0 group-has-data-[slot=item-description]/item:self-center",
|
|
844
|
+
children: busy ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVMXKT67Ecjs.Spinner, { "aria-hidden": true }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatEmptyActionIcon, { icon: item.icon })
|
|
845
|
+
}
|
|
846
|
+
),
|
|
847
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkDHXKCMKYcjs.ItemContent, { className: "min-w-0 flex-row flex-wrap items-baseline gap-x-2 gap-y-0.5 md:flex-nowrap", children: [
|
|
848
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkDHXKCMKYcjs.ItemTitle, { className: "w-auto min-w-0 shrink-0 font-normal text-foreground md:max-w-[60%] md:truncate", children: item.label }),
|
|
849
|
+
item.detail && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkDHXKCMKYcjs.ItemDescription, { className: "line-clamp-1 min-w-0 flex-1 truncate text-xs md:text-sm", children: item.detail })
|
|
850
|
+
] })
|
|
851
|
+
]
|
|
852
|
+
}
|
|
853
|
+
) }, item.id);
|
|
854
|
+
})
|
|
855
|
+
}
|
|
856
|
+
)
|
|
857
|
+
] });
|
|
858
|
+
}
|
|
761
859
|
function MobileReplySuggestions({
|
|
762
860
|
items,
|
|
763
861
|
onSelect,
|
|
@@ -913,6 +1011,8 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
913
1011
|
emptySubtitle,
|
|
914
1012
|
examplePrompts = [],
|
|
915
1013
|
examplePromptsLabel = "Try",
|
|
1014
|
+
emptyActions = [],
|
|
1015
|
+
emptyActionsLabel = DEFAULT_EMPTY_ACTIONS_LABEL,
|
|
916
1016
|
examplePromptsVariant = "chips",
|
|
917
1017
|
examplePromptsLoading = false,
|
|
918
1018
|
examplePromptsLoadingLabel = "Loading suggestions\u2026",
|
|
@@ -1152,6 +1252,15 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
1152
1252
|
}
|
|
1153
1253
|
),
|
|
1154
1254
|
error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { children: error }),
|
|
1255
|
+
!pending && emptyActions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1256
|
+
ChatEmptyActions,
|
|
1257
|
+
{
|
|
1258
|
+
items: emptyActions,
|
|
1259
|
+
label: emptyActionsLabel,
|
|
1260
|
+
onError: reportSendError,
|
|
1261
|
+
className: "mt-3"
|
|
1262
|
+
}
|
|
1263
|
+
),
|
|
1155
1264
|
!pending && examplePromptsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExamplePromptsLoading, { label: examplePromptsLoadingLabel }),
|
|
1156
1265
|
!pending && !examplePromptsLoading && examplePrompts.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1157
1266
|
ChatSuggestions,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React$1 from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
+
import { LucideIcon } from 'lucide-react';
|
|
4
5
|
import { VoiceSessionControlsProps } from './voice-session-controls.cjs';
|
|
5
6
|
import { ChatNavigatorItem } from './chat-turn-navigator.cjs';
|
|
6
7
|
import { MarkdownComponents } from './markdown.cjs';
|
|
@@ -259,6 +260,24 @@ interface ChatInputProps {
|
|
|
259
260
|
* device-aware default modes.
|
|
260
261
|
*/
|
|
261
262
|
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
263
|
+
/** A next step offered in the empty state, under the composer (`emptyActions`). */
|
|
264
|
+
interface ChatEmptyAction {
|
|
265
|
+
/** Stable key. */
|
|
266
|
+
id: string;
|
|
267
|
+
/** What picking it does, e.g. "Review 3 new people". */
|
|
268
|
+
label: ReactNode;
|
|
269
|
+
/** Where it applies, muted after the label, e.g. "Head of Sales · Northwind". One line, truncated. */
|
|
270
|
+
detail?: ReactNode;
|
|
271
|
+
/** Leading icon: a Lucide component or an element. */
|
|
272
|
+
icon?: LucideIcon | ReactNode;
|
|
273
|
+
/**
|
|
274
|
+
* Called when picked. While a returned promise is pending, that row shows a
|
|
275
|
+
* spinner and every row is disabled; a rejection re-enables them and is
|
|
276
|
+
* reported.
|
|
277
|
+
*/
|
|
278
|
+
onSelect: () => void | Promise<void>;
|
|
279
|
+
disabled?: boolean;
|
|
280
|
+
}
|
|
262
281
|
interface ChatProps {
|
|
263
282
|
/** Conversation messages. */
|
|
264
283
|
messages: ChatMessage[];
|
|
@@ -304,6 +323,21 @@ interface ChatProps {
|
|
|
304
323
|
examplePrompts?: ReadonlyArray<string>;
|
|
305
324
|
/** Label above the example prompts. Defaults to "Try". */
|
|
306
325
|
examplePromptsLabel?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Next steps under the empty-state composer, before `examplePrompts`,
|
|
328
|
+
* ChatGPT-style: a quiet list of rows, each an icon, what picking it does
|
|
329
|
+
* and where it applies (`ChatEmptyAction`). Picking one calls its
|
|
330
|
+
* `onSelect`; nothing is sent here. While a returned promise is pending
|
|
331
|
+
* the row shows a spinner and every row is disabled. Hidden while
|
|
332
|
+
* `pending`, like the example prompts.
|
|
333
|
+
*/
|
|
334
|
+
emptyActions?: ReadonlyArray<ChatEmptyAction>;
|
|
335
|
+
/**
|
|
336
|
+
* The actions' small heading and accessible name. Defaults to "Pick up
|
|
337
|
+
* where you left off"; `""` hides the heading and keeps that default as
|
|
338
|
+
* the list's accessible name.
|
|
339
|
+
*/
|
|
340
|
+
emptyActionsLabel?: string;
|
|
307
341
|
/**
|
|
308
342
|
* `chips` (the default) wrap onto as many lines as they need; `row` is one
|
|
309
343
|
* line that scrolls sideways, for a few short prompts where height is
|
|
@@ -500,4 +534,4 @@ interface ChatHandle {
|
|
|
500
534
|
*/
|
|
501
535
|
declare const Chat: React$1.ForwardRefExoticComponent<ChatProps & React$1.RefAttributes<ChatHandle>>;
|
|
502
536
|
|
|
503
|
-
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatMessageAuthor, ChatNavigatorItem, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps, authorLines };
|
|
537
|
+
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatEmptyAction, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatMessageAuthor, ChatNavigatorItem, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps, authorLines };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React$1 from 'react';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
|
+
import { LucideIcon } from 'lucide-react';
|
|
4
5
|
import { VoiceSessionControlsProps } from './voice-session-controls.js';
|
|
5
6
|
import { ChatNavigatorItem } from './chat-turn-navigator.js';
|
|
6
7
|
import { MarkdownComponents } from './markdown.js';
|
|
@@ -259,6 +260,24 @@ interface ChatInputProps {
|
|
|
259
260
|
* device-aware default modes.
|
|
260
261
|
*/
|
|
261
262
|
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
263
|
+
/** A next step offered in the empty state, under the composer (`emptyActions`). */
|
|
264
|
+
interface ChatEmptyAction {
|
|
265
|
+
/** Stable key. */
|
|
266
|
+
id: string;
|
|
267
|
+
/** What picking it does, e.g. "Review 3 new people". */
|
|
268
|
+
label: ReactNode;
|
|
269
|
+
/** Where it applies, muted after the label, e.g. "Head of Sales · Northwind". One line, truncated. */
|
|
270
|
+
detail?: ReactNode;
|
|
271
|
+
/** Leading icon: a Lucide component or an element. */
|
|
272
|
+
icon?: LucideIcon | ReactNode;
|
|
273
|
+
/**
|
|
274
|
+
* Called when picked. While a returned promise is pending, that row shows a
|
|
275
|
+
* spinner and every row is disabled; a rejection re-enables them and is
|
|
276
|
+
* reported.
|
|
277
|
+
*/
|
|
278
|
+
onSelect: () => void | Promise<void>;
|
|
279
|
+
disabled?: boolean;
|
|
280
|
+
}
|
|
262
281
|
interface ChatProps {
|
|
263
282
|
/** Conversation messages. */
|
|
264
283
|
messages: ChatMessage[];
|
|
@@ -304,6 +323,21 @@ interface ChatProps {
|
|
|
304
323
|
examplePrompts?: ReadonlyArray<string>;
|
|
305
324
|
/** Label above the example prompts. Defaults to "Try". */
|
|
306
325
|
examplePromptsLabel?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Next steps under the empty-state composer, before `examplePrompts`,
|
|
328
|
+
* ChatGPT-style: a quiet list of rows, each an icon, what picking it does
|
|
329
|
+
* and where it applies (`ChatEmptyAction`). Picking one calls its
|
|
330
|
+
* `onSelect`; nothing is sent here. While a returned promise is pending
|
|
331
|
+
* the row shows a spinner and every row is disabled. Hidden while
|
|
332
|
+
* `pending`, like the example prompts.
|
|
333
|
+
*/
|
|
334
|
+
emptyActions?: ReadonlyArray<ChatEmptyAction>;
|
|
335
|
+
/**
|
|
336
|
+
* The actions' small heading and accessible name. Defaults to "Pick up
|
|
337
|
+
* where you left off"; `""` hides the heading and keeps that default as
|
|
338
|
+
* the list's accessible name.
|
|
339
|
+
*/
|
|
340
|
+
emptyActionsLabel?: string;
|
|
307
341
|
/**
|
|
308
342
|
* `chips` (the default) wrap onto as many lines as they need; `row` is one
|
|
309
343
|
* line that scrolls sideways, for a few short prompts where height is
|
|
@@ -500,4 +534,4 @@ interface ChatHandle {
|
|
|
500
534
|
*/
|
|
501
535
|
declare const Chat: React$1.ForwardRefExoticComponent<ChatProps & React$1.RefAttributes<ChatHandle>>;
|
|
502
536
|
|
|
503
|
-
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatMessageAuthor, ChatNavigatorItem, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps, authorLines };
|
|
537
|
+
export { Chat, type ChatAttachment, type ChatAttachmentAction, ChatCopyAction, type ChatCopyActionProps, type ChatEmptyAction, type ChatHandle, ChatInput, type ChatInputProps, type ChatMessage, type ChatMessageAuthor, ChatNavigatorItem, type ChatProps, type ChatRole, ChatThread, type ChatThreadProps, authorLines };
|
package/dist/primitives/chat.js
CHANGED
|
@@ -15,9 +15,12 @@ import {
|
|
|
15
15
|
Suggestion,
|
|
16
16
|
Suggestions
|
|
17
17
|
} from "../chunk-IJG2B3Y2.js";
|
|
18
|
+
import {
|
|
19
|
+
Spinner
|
|
20
|
+
} from "../chunk-QZBPZLAB.js";
|
|
18
21
|
import {
|
|
19
22
|
PersonAvatar
|
|
20
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-T5AFBLP2.js";
|
|
21
24
|
import {
|
|
22
25
|
Marker,
|
|
23
26
|
MarkerContent
|
|
@@ -34,6 +37,14 @@ import {
|
|
|
34
37
|
InputGroupTextarea
|
|
35
38
|
} from "../chunk-QTPPNK6F.js";
|
|
36
39
|
import "../chunk-6FC65AZQ.js";
|
|
40
|
+
import {
|
|
41
|
+
Item,
|
|
42
|
+
ItemContent,
|
|
43
|
+
ItemDescription,
|
|
44
|
+
ItemMedia,
|
|
45
|
+
ItemTitle
|
|
46
|
+
} from "../chunk-SG4ZE2EN.js";
|
|
47
|
+
import "../chunk-HYTILYE5.js";
|
|
37
48
|
import {
|
|
38
49
|
FileDropArea,
|
|
39
50
|
FileDropzone
|
|
@@ -114,6 +125,7 @@ import {
|
|
|
114
125
|
// src/primitives/chat.tsx
|
|
115
126
|
import {
|
|
116
127
|
forwardRef,
|
|
128
|
+
isValidElement,
|
|
117
129
|
useCallback,
|
|
118
130
|
useEffect,
|
|
119
131
|
useId,
|
|
@@ -758,6 +770,92 @@ function ChatSuggestions({
|
|
|
758
770
|
)
|
|
759
771
|
] });
|
|
760
772
|
}
|
|
773
|
+
var DEFAULT_EMPTY_ACTIONS_LABEL = "Pick up where you left off";
|
|
774
|
+
function ChatEmptyActionIcon({ icon }) {
|
|
775
|
+
if (!icon) return null;
|
|
776
|
+
if (isValidElement(icon)) return icon;
|
|
777
|
+
if (typeof icon === "function" || typeof icon === "object" && icon !== null && "render" in icon) {
|
|
778
|
+
const IconComp = icon;
|
|
779
|
+
return /* @__PURE__ */ jsx(IconComp, { "aria-hidden": true });
|
|
780
|
+
}
|
|
781
|
+
return /* @__PURE__ */ jsx(Fragment, { children: icon });
|
|
782
|
+
}
|
|
783
|
+
function ChatEmptyActions({
|
|
784
|
+
items,
|
|
785
|
+
label,
|
|
786
|
+
onError,
|
|
787
|
+
className
|
|
788
|
+
}) {
|
|
789
|
+
const labelId = useId();
|
|
790
|
+
const [running, setRunning] = useState(null);
|
|
791
|
+
if (items.length === 0) return null;
|
|
792
|
+
const showLabel = label.length > 0;
|
|
793
|
+
const pick = async (item) => {
|
|
794
|
+
if (running !== null) return;
|
|
795
|
+
let result;
|
|
796
|
+
try {
|
|
797
|
+
result = item.onSelect();
|
|
798
|
+
} catch (cause) {
|
|
799
|
+
onError(cause);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (!result || typeof result.then !== "function") return;
|
|
803
|
+
setRunning(item.id);
|
|
804
|
+
try {
|
|
805
|
+
await result;
|
|
806
|
+
} catch (cause) {
|
|
807
|
+
onError(cause);
|
|
808
|
+
} finally {
|
|
809
|
+
setRunning(null);
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
return /* @__PURE__ */ jsxs("div", { "data-slot": "chat-empty-actions", className: cn("w-full text-left", className), children: [
|
|
813
|
+
showLabel && /* @__PURE__ */ jsx("p", { id: labelId, "data-slot": "chat-empty-actions-label", className: "mb-1.5 px-3 text-xs text-muted-foreground", children: label }),
|
|
814
|
+
/* @__PURE__ */ jsx(
|
|
815
|
+
"div",
|
|
816
|
+
{
|
|
817
|
+
role: "group",
|
|
818
|
+
"aria-labelledby": showLabel ? labelId : void 0,
|
|
819
|
+
"aria-label": showLabel ? void 0 : DEFAULT_EMPTY_ACTIONS_LABEL,
|
|
820
|
+
className: "flex flex-col gap-0.5",
|
|
821
|
+
children: items.map((item) => {
|
|
822
|
+
const busy = running === item.id;
|
|
823
|
+
return /* @__PURE__ */ jsx(Item, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxs(
|
|
824
|
+
"button",
|
|
825
|
+
{
|
|
826
|
+
type: "button",
|
|
827
|
+
"data-slot": "chat-empty-action",
|
|
828
|
+
"data-state": busy ? "loading" : void 0,
|
|
829
|
+
"aria-busy": busy || void 0,
|
|
830
|
+
disabled: item.disabled || running !== null,
|
|
831
|
+
onClick: () => void pick(item),
|
|
832
|
+
className: cn(
|
|
833
|
+
"min-h-11 cursor-pointer flex-nowrap text-left",
|
|
834
|
+
"hover:bg-muted focus-visible:bg-muted",
|
|
835
|
+
"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent",
|
|
836
|
+
busy && "disabled:opacity-100"
|
|
837
|
+
),
|
|
838
|
+
children: [
|
|
839
|
+
/* @__PURE__ */ jsx(
|
|
840
|
+
ItemMedia,
|
|
841
|
+
{
|
|
842
|
+
variant: "icon",
|
|
843
|
+
className: "size-8 self-center rounded-md bg-muted text-muted-foreground group-has-data-[slot=item-description]/item:translate-y-0 group-has-data-[slot=item-description]/item:self-center",
|
|
844
|
+
children: busy ? /* @__PURE__ */ jsx(Spinner, { "aria-hidden": true }) : /* @__PURE__ */ jsx(ChatEmptyActionIcon, { icon: item.icon })
|
|
845
|
+
}
|
|
846
|
+
),
|
|
847
|
+
/* @__PURE__ */ jsxs(ItemContent, { className: "min-w-0 flex-row flex-wrap items-baseline gap-x-2 gap-y-0.5 md:flex-nowrap", children: [
|
|
848
|
+
/* @__PURE__ */ jsx(ItemTitle, { className: "w-auto min-w-0 shrink-0 font-normal text-foreground md:max-w-[60%] md:truncate", children: item.label }),
|
|
849
|
+
item.detail && /* @__PURE__ */ jsx(ItemDescription, { className: "line-clamp-1 min-w-0 flex-1 truncate text-xs md:text-sm", children: item.detail })
|
|
850
|
+
] })
|
|
851
|
+
]
|
|
852
|
+
}
|
|
853
|
+
) }, item.id);
|
|
854
|
+
})
|
|
855
|
+
}
|
|
856
|
+
)
|
|
857
|
+
] });
|
|
858
|
+
}
|
|
761
859
|
function MobileReplySuggestions({
|
|
762
860
|
items,
|
|
763
861
|
onSelect,
|
|
@@ -913,6 +1011,8 @@ var Chat = forwardRef(function Chat2({
|
|
|
913
1011
|
emptySubtitle,
|
|
914
1012
|
examplePrompts = [],
|
|
915
1013
|
examplePromptsLabel = "Try",
|
|
1014
|
+
emptyActions = [],
|
|
1015
|
+
emptyActionsLabel = DEFAULT_EMPTY_ACTIONS_LABEL,
|
|
916
1016
|
examplePromptsVariant = "chips",
|
|
917
1017
|
examplePromptsLoading = false,
|
|
918
1018
|
examplePromptsLoadingLabel = "Loading suggestions\u2026",
|
|
@@ -1152,6 +1252,15 @@ var Chat = forwardRef(function Chat2({
|
|
|
1152
1252
|
}
|
|
1153
1253
|
),
|
|
1154
1254
|
error && /* @__PURE__ */ jsx(ChatError, { children: error }),
|
|
1255
|
+
!pending && emptyActions.length > 0 && /* @__PURE__ */ jsx(
|
|
1256
|
+
ChatEmptyActions,
|
|
1257
|
+
{
|
|
1258
|
+
items: emptyActions,
|
|
1259
|
+
label: emptyActionsLabel,
|
|
1260
|
+
onError: reportSendError,
|
|
1261
|
+
className: "mt-3"
|
|
1262
|
+
}
|
|
1263
|
+
),
|
|
1155
1264
|
!pending && examplePromptsLoading && /* @__PURE__ */ jsx(ExamplePromptsLoading, { label: examplePromptsLoadingLabel }),
|
|
1156
1265
|
!pending && !examplePromptsLoading && examplePrompts.length > 0 && /* @__PURE__ */ jsx(
|
|
1157
1266
|
ChatSuggestions,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkPPYHNJMVcjs = require('../chunk-PPYHNJMV.cjs');
|
|
5
5
|
require('../chunk-VGTINL5Q.cjs');
|
|
6
6
|
require('../chunk-I6GUOEBO.cjs');
|
|
7
7
|
require('../chunk-KWLSBTB2.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
exports.ChipTabs =
|
|
10
|
+
exports.ChipTabs = _chunkPPYHNJMVcjs.ChipTabs;
|
|
@@ -6,7 +6,7 @@ interface ChipTabItem {
|
|
|
6
6
|
label: ReactNode;
|
|
7
7
|
/** Optional count rendered after the label in a neutral count badge. */
|
|
8
8
|
count?: number;
|
|
9
|
-
/** Optional leading icon. */
|
|
9
|
+
/** Optional leading icon. Decorative: hidden from screen readers, since the label names the chip. */
|
|
10
10
|
icon?: ReactNode;
|
|
11
11
|
}
|
|
12
12
|
interface ChipTabsProps {
|
|
@@ -27,13 +27,24 @@ interface ChipTabsProps {
|
|
|
27
27
|
disabled?: boolean;
|
|
28
28
|
/** Visually guides attention to one option without selecting it. */
|
|
29
29
|
guidedValue?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The row's accessible name ("3 people shared from this search"): the
|
|
32
|
+
* chips become a labelled group. Or point at a visible caption with
|
|
33
|
+
* `labelledBy`.
|
|
34
|
+
*/
|
|
35
|
+
label?: string;
|
|
36
|
+
/** The id of an element whose text names the row, in place of `label`. */
|
|
37
|
+
labelledBy?: string;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* Pill-style tab strip — toggle row of chips with active/inactive states
|
|
33
41
|
* and an optional trailing actions slot. Distinct from `Tabs` (which
|
|
34
42
|
* uses an underlined trigger row for page-level navigation). Use this
|
|
35
43
|
* for compact filter / view selectors inside popovers, sidebars, etc.
|
|
44
|
+
*
|
|
45
|
+
* Each chip is a toggle button (`aria-pressed`), so a screen reader says
|
|
46
|
+
* which one is selected; `label` or `labelledBy` names the row as a group.
|
|
36
47
|
*/
|
|
37
|
-
declare function ChipTabs({ items, value, onChange, size, variant, trailing, className, marginBottom, placement, disabled, guidedValue, }: ChipTabsProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function ChipTabs({ items, value, onChange, size, variant, trailing, className, marginBottom, placement, disabled, guidedValue, label, labelledBy, }: ChipTabsProps): react_jsx_runtime.JSX.Element;
|
|
38
49
|
|
|
39
50
|
export { type ChipTabItem, ChipTabs, type ChipTabsProps };
|
|
@@ -6,7 +6,7 @@ interface ChipTabItem {
|
|
|
6
6
|
label: ReactNode;
|
|
7
7
|
/** Optional count rendered after the label in a neutral count badge. */
|
|
8
8
|
count?: number;
|
|
9
|
-
/** Optional leading icon. */
|
|
9
|
+
/** Optional leading icon. Decorative: hidden from screen readers, since the label names the chip. */
|
|
10
10
|
icon?: ReactNode;
|
|
11
11
|
}
|
|
12
12
|
interface ChipTabsProps {
|
|
@@ -27,13 +27,24 @@ interface ChipTabsProps {
|
|
|
27
27
|
disabled?: boolean;
|
|
28
28
|
/** Visually guides attention to one option without selecting it. */
|
|
29
29
|
guidedValue?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The row's accessible name ("3 people shared from this search"): the
|
|
32
|
+
* chips become a labelled group. Or point at a visible caption with
|
|
33
|
+
* `labelledBy`.
|
|
34
|
+
*/
|
|
35
|
+
label?: string;
|
|
36
|
+
/** The id of an element whose text names the row, in place of `label`. */
|
|
37
|
+
labelledBy?: string;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* Pill-style tab strip — toggle row of chips with active/inactive states
|
|
33
41
|
* and an optional trailing actions slot. Distinct from `Tabs` (which
|
|
34
42
|
* uses an underlined trigger row for page-level navigation). Use this
|
|
35
43
|
* for compact filter / view selectors inside popovers, sidebars, etc.
|
|
44
|
+
*
|
|
45
|
+
* Each chip is a toggle button (`aria-pressed`), so a screen reader says
|
|
46
|
+
* which one is selected; `label` or `labelledBy` names the row as a group.
|
|
36
47
|
*/
|
|
37
|
-
declare function ChipTabs({ items, value, onChange, size, variant, trailing, className, marginBottom, placement, disabled, guidedValue, }: ChipTabsProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function ChipTabs({ items, value, onChange, size, variant, trailing, className, marginBottom, placement, disabled, guidedValue, label, labelledBy, }: ChipTabsProps): react_jsx_runtime.JSX.Element;
|
|
38
49
|
|
|
39
50
|
export { type ChipTabItem, ChipTabs, type ChipTabsProps };
|