@wealthx/shadcn 1.5.39 → 1.5.41
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/.turbo/turbo-build.log +118 -118
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-MGIDYXOP.mjs → chunk-DWNLBUDC.mjs} +459 -67
- package/dist/{chunk-EFHPSKVF.mjs → chunk-EGM4DARZ.mjs} +110 -1
- package/dist/{chunk-R7M657QL.mjs → chunk-GIQGZFP6.mjs} +138 -46
- package/dist/{chunk-B5PSUONN.mjs → chunk-TF5TOVIM.mjs} +1 -1
- package/dist/{chunk-RRROLESJ.mjs → chunk-XHZONBL4.mjs} +1 -1
- package/dist/components/ui/ai-assistant-drawer.js +101 -0
- package/dist/components/ui/ai-assistant-drawer.mjs +2 -2
- package/dist/components/ui/ai-conversations/index.js +101 -0
- package/dist/components/ui/ai-conversations/index.mjs +2 -2
- package/dist/components/ui/chat-input-area.js +101 -0
- package/dist/components/ui/chat-input-area.mjs +1 -1
- package/dist/components/ui/policy-ai/index.js +818 -261
- package/dist/components/ui/policy-ai/index.mjs +11 -2
- package/dist/components/ui/support-agent/index.js +233 -45
- package/dist/components/ui/support-agent/index.mjs +2 -2
- package/dist/index.js +3521 -3330
- package/dist/index.mjs +5 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ui/chat-input-area.tsx +181 -2
- package/src/components/ui/policy-ai/index.tsx +12 -0
- package/src/components/ui/policy-ai/policy-ai-context-sidebar.tsx +231 -0
- package/src/components/ui/policy-ai/policy-ai-history-panel.tsx +175 -0
- package/src/components/ui/policy-ai/policy-ai-page.tsx +243 -0
- package/src/components/ui/policy-ai/policy-ai-panel.tsx +64 -57
- package/src/components/ui/policy-ai/policy-ai-responses.tsx +8 -12
- package/src/components/ui/support-agent/support-agent-panel.tsx +170 -48
- package/src/styles/styles-css.ts +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import ReactMarkdown from "react-markdown";
|
|
3
|
+
import rehypeRaw from "rehype-raw";
|
|
4
|
+
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
|
|
2
5
|
import { Bot, ChevronLeft, ChevronRight, SquarePen, X } from "lucide-react";
|
|
3
6
|
import { cn } from "@/lib/utils";
|
|
4
7
|
import { Sheet, SheetContent } from "@/components/ui/sheet";
|
|
@@ -66,6 +69,12 @@ export interface SupportAgentMessage {
|
|
|
66
69
|
richContent?: SupportAgentRichContent;
|
|
67
70
|
/** True while the assistant response is streaming in. */
|
|
68
71
|
isStreaming?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Status text shown beside the animated dots while the response streams
|
|
74
|
+
* (e.g. "Checking the help center"). Rendered only while the bubble is empty
|
|
75
|
+
* and streaming. The trailing "…" animates on its own — do not include dots here.
|
|
76
|
+
*/
|
|
77
|
+
streamingLabel?: string;
|
|
69
78
|
/** True if the message errored. */
|
|
70
79
|
isErrored?: boolean;
|
|
71
80
|
}
|
|
@@ -153,6 +162,28 @@ function SupportTypingIndicator() {
|
|
|
153
162
|
);
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// StreamingStatus — optional status label with an animated "…" ellipsis
|
|
167
|
+
// (e.g. "Checking the help center" + animated dots), shown while streaming.
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
function StreamingStatus({ label }: { label?: string }) {
|
|
171
|
+
// No label → the standard DS typing indicator (3 bouncing dots).
|
|
172
|
+
if (!label) return <SupportTypingIndicator />;
|
|
173
|
+
|
|
174
|
+
// With label → status text + the same DS typing dots: "Checking the help center • • •"
|
|
175
|
+
return (
|
|
176
|
+
<span
|
|
177
|
+
className="flex items-center gap-1.5 text-sm text-muted-foreground"
|
|
178
|
+
role="status"
|
|
179
|
+
aria-label={`${label}…`}
|
|
180
|
+
>
|
|
181
|
+
<span>{label}</span>
|
|
182
|
+
<SupportTypingIndicator />
|
|
183
|
+
</span>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
156
187
|
// ---------------------------------------------------------------------------
|
|
157
188
|
// MessageBubble — renders a single message with optional rich content
|
|
158
189
|
// ---------------------------------------------------------------------------
|
|
@@ -185,11 +216,24 @@ function MessageBubble({ message }: MessageBubbleProps) {
|
|
|
185
216
|
data-role={message.role}
|
|
186
217
|
>
|
|
187
218
|
{isEmpty && message.isStreaming ? (
|
|
188
|
-
<
|
|
189
|
-
) : (
|
|
219
|
+
<StreamingStatus label={message.streamingLabel} />
|
|
220
|
+
) : isUser ? (
|
|
190
221
|
<span className="whitespace-pre-wrap break-words leading-relaxed">
|
|
191
222
|
{message.content}
|
|
192
223
|
</span>
|
|
224
|
+
) : (
|
|
225
|
+
<div className="break-words text-sm leading-relaxed [&_a]:text-primary [&_a]:underline [&_p]:m-0 [&_p:not(:last-child)]:mb-2 [&_ul]:my-1 [&_ul]:list-disc [&_ul]:pl-4 [&_ol]:my-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_li]:mb-0.5">
|
|
226
|
+
<ReactMarkdown
|
|
227
|
+
rehypePlugins={[rehypeRaw, [rehypeSanitize, defaultSchema]]}
|
|
228
|
+
components={{
|
|
229
|
+
a: ({ node, ...props }) => (
|
|
230
|
+
<a {...props} target="_blank" rel="noopener noreferrer" />
|
|
231
|
+
),
|
|
232
|
+
}}
|
|
233
|
+
>
|
|
234
|
+
{message.content}
|
|
235
|
+
</ReactMarkdown>
|
|
236
|
+
</div>
|
|
193
237
|
)}
|
|
194
238
|
{message.isErrored && (
|
|
195
239
|
<p className="mt-1 text-xs opacity-70">
|
|
@@ -240,6 +284,54 @@ function RichContentRenderer({ richContent }: RichContentRendererProps) {
|
|
|
240
284
|
return null;
|
|
241
285
|
}
|
|
242
286
|
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Local sub-components
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
/** Reusable close button — consistent across all panel header variants. */
|
|
292
|
+
function CloseButton({ onClick }: { onClick: () => void }) {
|
|
293
|
+
return (
|
|
294
|
+
<Button
|
|
295
|
+
variant="ghost"
|
|
296
|
+
size="icon"
|
|
297
|
+
className="size-7 shrink-0"
|
|
298
|
+
onClick={onClick}
|
|
299
|
+
title="Close"
|
|
300
|
+
>
|
|
301
|
+
<X className="size-3.5" />
|
|
302
|
+
<span className="sr-only">Close</span>
|
|
303
|
+
</Button>
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** Single conversation row — used in both home recents and all-conversations list. */
|
|
308
|
+
function ConversationRow({
|
|
309
|
+
conv,
|
|
310
|
+
onClick,
|
|
311
|
+
className,
|
|
312
|
+
}: {
|
|
313
|
+
conv: SupportAgentRecentConversation;
|
|
314
|
+
onClick: () => void;
|
|
315
|
+
className?: string;
|
|
316
|
+
}) {
|
|
317
|
+
return (
|
|
318
|
+
<button
|
|
319
|
+
type="button"
|
|
320
|
+
onClick={onClick}
|
|
321
|
+
className={cn(
|
|
322
|
+
"flex w-full items-center justify-between gap-2 text-left text-sm text-foreground hover:bg-muted/50",
|
|
323
|
+
className,
|
|
324
|
+
)}
|
|
325
|
+
>
|
|
326
|
+
<span className="flex-1 truncate">{conv.title}</span>
|
|
327
|
+
<ChevronRight
|
|
328
|
+
className="size-3.5 shrink-0 text-muted-foreground"
|
|
329
|
+
aria-hidden="true"
|
|
330
|
+
/>
|
|
331
|
+
</button>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
243
335
|
// ---------------------------------------------------------------------------
|
|
244
336
|
// SupportAgentPanel
|
|
245
337
|
// ---------------------------------------------------------------------------
|
|
@@ -264,6 +356,7 @@ export function SupportAgentPanel({
|
|
|
264
356
|
className,
|
|
265
357
|
}: SupportAgentPanelProps) {
|
|
266
358
|
const [inputValue, setInputValue] = React.useState("");
|
|
359
|
+
const [showAllConversations, setShowAllConversations] = React.useState(false);
|
|
267
360
|
const messagesEndRef = React.useRef<HTMLDivElement>(null);
|
|
268
361
|
|
|
269
362
|
const hasMessages = messages.length > 0;
|
|
@@ -271,6 +364,11 @@ export function SupportAgentPanel({
|
|
|
271
364
|
// Chat header mode: has messages AND a conversation title
|
|
272
365
|
const isChatMode = hasMessages && !!conversationTitle;
|
|
273
366
|
|
|
367
|
+
// Reset "all conversations" view when panel closes
|
|
368
|
+
React.useEffect(() => {
|
|
369
|
+
if (!open) setShowAllConversations(false);
|
|
370
|
+
}, [open]);
|
|
371
|
+
|
|
274
372
|
// Auto-scroll to latest message
|
|
275
373
|
React.useEffect(() => {
|
|
276
374
|
if (!messagesEndRef.current) return;
|
|
@@ -296,6 +394,16 @@ export function SupportAgentPanel({
|
|
|
296
394
|
);
|
|
297
395
|
|
|
298
396
|
const hasRecents = !!recentConversations?.length;
|
|
397
|
+
// Home state shows only the 3 most recent; "View all" expands to the full list.
|
|
398
|
+
const recentsPreview = React.useMemo(
|
|
399
|
+
() => recentConversations?.slice(0, 3) ?? [],
|
|
400
|
+
[recentConversations],
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
const handleViewAll = React.useCallback(() => {
|
|
404
|
+
setShowAllConversations(true);
|
|
405
|
+
onViewAllConversations?.(); // optional analytics callback
|
|
406
|
+
}, [onViewAllConversations]);
|
|
299
407
|
|
|
300
408
|
return (
|
|
301
409
|
<Sheet open={open} onOpenChange={(o) => !o && onClose()}>
|
|
@@ -310,7 +418,25 @@ export function SupportAgentPanel({
|
|
|
310
418
|
>
|
|
311
419
|
{/* ── Header ── */}
|
|
312
420
|
<div className="shrink-0 border-b border-border px-3 py-2.5">
|
|
313
|
-
{
|
|
421
|
+
{showAllConversations ? (
|
|
422
|
+
/* All-conversations mode: [←] All conversations [✕] */
|
|
423
|
+
<div className="flex items-center gap-1">
|
|
424
|
+
<Button
|
|
425
|
+
variant="ghost"
|
|
426
|
+
size="icon"
|
|
427
|
+
className="size-7 shrink-0"
|
|
428
|
+
onClick={() => setShowAllConversations(false)}
|
|
429
|
+
title="Back"
|
|
430
|
+
>
|
|
431
|
+
<ChevronLeft className="size-3.5" />
|
|
432
|
+
<span className="sr-only">Back</span>
|
|
433
|
+
</Button>
|
|
434
|
+
<span className="flex-1 truncate px-1 text-sm font-medium text-foreground">
|
|
435
|
+
All conversations
|
|
436
|
+
</span>
|
|
437
|
+
<CloseButton onClick={onClose} />
|
|
438
|
+
</div>
|
|
439
|
+
) : isChatMode ? (
|
|
314
440
|
/* Chat mode: [←] Conversation title [✕] */
|
|
315
441
|
<div className="flex items-center gap-1">
|
|
316
442
|
{onBack && (
|
|
@@ -328,16 +454,7 @@ export function SupportAgentPanel({
|
|
|
328
454
|
<span className="flex-1 truncate px-1 text-sm font-medium text-foreground">
|
|
329
455
|
{conversationTitle}
|
|
330
456
|
</span>
|
|
331
|
-
<
|
|
332
|
-
variant="ghost"
|
|
333
|
-
size="icon"
|
|
334
|
-
className="size-7 shrink-0"
|
|
335
|
-
onClick={onClose}
|
|
336
|
-
title="Close"
|
|
337
|
-
>
|
|
338
|
-
<X className="size-3.5" />
|
|
339
|
-
<span className="sr-only">Close</span>
|
|
340
|
-
</Button>
|
|
457
|
+
<CloseButton onClick={onClose} />
|
|
341
458
|
</div>
|
|
342
459
|
) : (
|
|
343
460
|
/* Home mode: [Bot icon] Support Assistant [✕] */
|
|
@@ -353,20 +470,11 @@ export function SupportAgentPanel({
|
|
|
353
470
|
Support Assistant
|
|
354
471
|
</span>
|
|
355
472
|
</div>
|
|
356
|
-
<
|
|
357
|
-
variant="ghost"
|
|
358
|
-
size="icon"
|
|
359
|
-
className="size-7"
|
|
360
|
-
onClick={onClose}
|
|
361
|
-
title="Close"
|
|
362
|
-
>
|
|
363
|
-
<X className="size-3.5" />
|
|
364
|
-
<span className="sr-only">Close</span>
|
|
365
|
-
</Button>
|
|
473
|
+
<CloseButton onClick={onClose} />
|
|
366
474
|
</div>
|
|
367
475
|
)}
|
|
368
|
-
{/* Context chip — shown below header title in
|
|
369
|
-
{context && (
|
|
476
|
+
{/* Context chip — shown below header title in home and chat modes only */}
|
|
477
|
+
{context && !showAllConversations && (
|
|
370
478
|
<div className="mt-2">
|
|
371
479
|
<SupportContextChip context={context} />
|
|
372
480
|
</div>
|
|
@@ -383,6 +491,27 @@ export function SupportAgentPanel({
|
|
|
383
491
|
<p className="text-sm text-muted-foreground">Loading…</p>
|
|
384
492
|
</div>
|
|
385
493
|
</div>
|
|
494
|
+
) : showAllConversations ? (
|
|
495
|
+
/* All conversations — full scrollable list (Jira Rovo pattern) */
|
|
496
|
+
<div className="flex flex-col">
|
|
497
|
+
{recentConversations?.length ? (
|
|
498
|
+
recentConversations.map((conv) => (
|
|
499
|
+
<ConversationRow
|
|
500
|
+
key={conv.id}
|
|
501
|
+
conv={conv}
|
|
502
|
+
onClick={() => {
|
|
503
|
+
setShowAllConversations(false);
|
|
504
|
+
onOpenConversation?.(conv.id);
|
|
505
|
+
}}
|
|
506
|
+
className="border-b border-border px-4 py-3"
|
|
507
|
+
/>
|
|
508
|
+
))
|
|
509
|
+
) : (
|
|
510
|
+
<p className="p-4 text-sm text-muted-foreground">
|
|
511
|
+
No conversations yet.
|
|
512
|
+
</p>
|
|
513
|
+
)}
|
|
514
|
+
</div>
|
|
386
515
|
) : !hasMessages ? (
|
|
387
516
|
/* Home state — Rovo pattern: New Chat CTA + Recents + Suggested */
|
|
388
517
|
<div className="flex flex-col gap-5 p-4">
|
|
@@ -399,39 +528,31 @@ export function SupportAgentPanel({
|
|
|
399
528
|
</Button>
|
|
400
529
|
)}
|
|
401
530
|
|
|
402
|
-
{/* Recents —
|
|
531
|
+
{/* Recents — 3 most recent conversations */}
|
|
403
532
|
{hasRecents && (
|
|
404
533
|
<div className="flex flex-col gap-1">
|
|
405
534
|
<p className="px-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">
|
|
406
535
|
Recents
|
|
407
536
|
</p>
|
|
408
537
|
<div className="flex flex-col">
|
|
409
|
-
{
|
|
410
|
-
<
|
|
538
|
+
{recentsPreview.map((conv) => (
|
|
539
|
+
<ConversationRow
|
|
411
540
|
key={conv.id}
|
|
412
|
-
|
|
541
|
+
conv={conv}
|
|
413
542
|
onClick={() => onOpenConversation?.(conv.id)}
|
|
414
|
-
className="
|
|
415
|
-
|
|
416
|
-
<span className="flex-1 truncate">{conv.title}</span>
|
|
417
|
-
<ChevronRight
|
|
418
|
-
className="size-3.5 shrink-0 text-muted-foreground"
|
|
419
|
-
aria-hidden="true"
|
|
420
|
-
/>
|
|
421
|
-
</button>
|
|
543
|
+
className="px-1 py-2.5"
|
|
544
|
+
/>
|
|
422
545
|
))}
|
|
423
546
|
</div>
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
</Button>
|
|
434
|
-
)}
|
|
547
|
+
<Button
|
|
548
|
+
variant="ghost"
|
|
549
|
+
size="sm"
|
|
550
|
+
onClick={handleViewAll}
|
|
551
|
+
className="h-auto w-fit gap-0.5 px-1 py-1 text-xs text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
552
|
+
>
|
|
553
|
+
View all conversations
|
|
554
|
+
<ChevronRight className="size-3.5" aria-hidden="true" />
|
|
555
|
+
</Button>
|
|
435
556
|
</div>
|
|
436
557
|
)}
|
|
437
558
|
|
|
@@ -490,6 +611,7 @@ export function SupportAgentPanel({
|
|
|
490
611
|
onAttachImage={onAttachImage}
|
|
491
612
|
disabled={isLoading || isStreaming}
|
|
492
613
|
placeholder="Ask anything…"
|
|
614
|
+
showMarkdownToolbar
|
|
493
615
|
/>
|
|
494
616
|
</div>
|
|
495
617
|
</SheetContent>
|