@wealthx/shadcn 1.5.28 → 1.5.29

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.
@@ -0,0 +1,1025 @@
1
+ import {
2
+ Tooltip,
3
+ TooltipContent,
4
+ TooltipProvider,
5
+ TooltipTrigger
6
+ } from "./chunk-3S6KVFF5.mjs";
7
+ import {
8
+ Card,
9
+ CardContent
10
+ } from "./chunk-3VDET466.mjs";
11
+ import {
12
+ Switch
13
+ } from "./chunk-PNSYFE3K.mjs";
14
+ import {
15
+ Tabs,
16
+ TabsContent,
17
+ TabsList,
18
+ TabsTrigger
19
+ } from "./chunk-WE4YKBDE.mjs";
20
+ import {
21
+ Table,
22
+ TableBody,
23
+ TableCell,
24
+ TableHead,
25
+ TableHeader,
26
+ TableRow
27
+ } from "./chunk-GT3RU6GA.mjs";
28
+ import {
29
+ Checkbox
30
+ } from "./chunk-IKXYTCSB.mjs";
31
+ import {
32
+ Select,
33
+ SelectContent,
34
+ SelectItem,
35
+ SelectTrigger,
36
+ SelectValue
37
+ } from "./chunk-K6VCC2MK.mjs";
38
+ import {
39
+ Dialog,
40
+ DialogContent,
41
+ DialogDescription,
42
+ DialogFooter,
43
+ DialogHeader,
44
+ DialogTitle
45
+ } from "./chunk-T5FRVEJQ.mjs";
46
+ import {
47
+ Avatar,
48
+ AvatarFallback,
49
+ AvatarImage
50
+ } from "./chunk-H6NQTIF4.mjs";
51
+ import {
52
+ Separator
53
+ } from "./chunk-2GIYVERS.mjs";
54
+ import {
55
+ Textarea
56
+ } from "./chunk-BS75ICOO.mjs";
57
+ import {
58
+ Badge
59
+ } from "./chunk-X6RC5UWB.mjs";
60
+ import {
61
+ Label
62
+ } from "./chunk-LSRGA5BI.mjs";
63
+ import {
64
+ Input
65
+ } from "./chunk-LBTHZSBT.mjs";
66
+ import {
67
+ Button
68
+ } from "./chunk-NOOEKOWY.mjs";
69
+ import {
70
+ cn
71
+ } from "./chunk-AFML43VJ.mjs";
72
+ import {
73
+ __async,
74
+ __spreadProps,
75
+ __spreadValues
76
+ } from "./chunk-WNQUEZJF.mjs";
77
+
78
+ // src/components/ui/ai-builder/agent-card.tsx
79
+ import { MoreHorizontal } from "lucide-react";
80
+ import { jsx, jsxs } from "react/jsx-runtime";
81
+ var AGENT_FEATURES = [
82
+ {
83
+ title: "Lead Capture",
84
+ description: "Automatically collect and qualify leads from website visitors."
85
+ },
86
+ {
87
+ title: "Initial Engagement",
88
+ description: "Instantly respond to inquiries with personalised mortgage guidance."
89
+ },
90
+ {
91
+ title: "Smart Follow-Up",
92
+ description: "Re-engage cold leads with timely, context-aware follow-up messages."
93
+ },
94
+ {
95
+ title: "Appointment Scheduling",
96
+ description: "Book qualified leads directly into advisor calendars without manual coordination."
97
+ },
98
+ {
99
+ title: "Performance Tracking",
100
+ description: "Monitor agent activity, response rates, and conversion metrics."
101
+ }
102
+ ];
103
+ function AgentCard({
104
+ agent,
105
+ onToggle,
106
+ onMenuClick,
107
+ className
108
+ }) {
109
+ const { id, title, description, tags, isEnabled, infoBadge, isComingSoon } = agent;
110
+ return /* @__PURE__ */ jsxs(
111
+ Card,
112
+ {
113
+ className: cn(
114
+ "flex flex-col gap-3 p-4 transition-opacity",
115
+ isComingSoon && "opacity-60",
116
+ className
117
+ ),
118
+ children: [
119
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
120
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center gap-2 min-w-0", children: [
121
+ /* @__PURE__ */ jsx(
122
+ "span",
123
+ {
124
+ className: cn(
125
+ "mt-0.5 size-2 shrink-0 rounded-full",
126
+ isEnabled && !isComingSoon ? "bg-success" : "bg-muted-foreground/40"
127
+ )
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsx("span", { className: "truncate text-label-medium leading-tight", children: title }),
131
+ isComingSoon && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "shrink-0 text-xs", children: "Coming Soon" })
132
+ ] }),
133
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
134
+ /* @__PURE__ */ jsx(
135
+ Switch,
136
+ {
137
+ checked: isEnabled,
138
+ disabled: isComingSoon,
139
+ onCheckedChange: (checked) => onToggle(id, checked),
140
+ "aria-label": `Toggle ${title}`
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx(
144
+ Button,
145
+ {
146
+ variant: "ghost",
147
+ size: "icon",
148
+ className: "h-7 w-7",
149
+ onClick: () => onMenuClick(id),
150
+ "aria-label": `View details for ${title}`,
151
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" })
152
+ }
153
+ )
154
+ ] })
155
+ ] }),
156
+ /* @__PURE__ */ jsx("p", { className: "text-body-small text-muted-foreground flex-1", children: description }),
157
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
158
+ infoBadge && /* @__PURE__ */ jsx("p", { className: "bg-info/10 text-info px-2 py-1 text-caption", children: infoBadge }),
159
+ tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: tag }, tag)) })
160
+ ] })
161
+ ]
162
+ }
163
+ );
164
+ }
165
+ function AgentMenuModal({
166
+ open,
167
+ onOpenChange,
168
+ agentTitle,
169
+ description = "AI-powered lead management that works around the clock to grow your mortgage business.",
170
+ features = AGENT_FEATURES
171
+ }) {
172
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-lg", children: [
173
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
174
+ /* @__PURE__ */ jsx(DialogTitle, { children: agentTitle }),
175
+ /* @__PURE__ */ jsx(DialogDescription, { children: description })
176
+ ] }),
177
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3 py-2", children: features.map((feature, index) => /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
178
+ /* @__PURE__ */ jsx(
179
+ Badge,
180
+ {
181
+ variant: "default",
182
+ className: "h-6 w-6 shrink-0 p-0 text-xs font-bold",
183
+ children: index + 1
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
187
+ /* @__PURE__ */ jsx("p", { className: "text-label-medium", children: feature.title }),
188
+ /* @__PURE__ */ jsx("p", { className: "text-body-small text-muted-foreground", children: feature.description })
189
+ ] })
190
+ ] }, feature.title)) })
191
+ ] }) });
192
+ }
193
+
194
+ // src/components/ui/ai-builder/integration-card.tsx
195
+ import { useState } from "react";
196
+ import { Check, CheckCircle2, Copy, Settings, User } from "lucide-react";
197
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
198
+ function IntegrationServiceCard({
199
+ title,
200
+ imageUrl,
201
+ iconNode,
202
+ description,
203
+ isConnected,
204
+ onCardClick,
205
+ onSettingsClick,
206
+ className
207
+ }) {
208
+ return /* @__PURE__ */ jsxs2(
209
+ Card,
210
+ {
211
+ className: cn(
212
+ "flex flex-col gap-3 p-4",
213
+ !isConnected && "cursor-pointer transition-colors hover:bg-accent/50",
214
+ className
215
+ ),
216
+ onClick: !isConnected ? onCardClick : void 0,
217
+ children: [
218
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-3", children: [
219
+ /* @__PURE__ */ jsxs2(Avatar, { className: "h-10 w-10 shrink-0", children: [
220
+ imageUrl && /* @__PURE__ */ jsx2(AvatarImage, { src: imageUrl, alt: title }),
221
+ /* @__PURE__ */ jsx2(AvatarFallback, { className: iconNode ? "bg-transparent p-0.5" : "", children: iconNode != null ? iconNode : /* @__PURE__ */ jsx2(User, { className: "h-5 w-5" }) })
222
+ ] }),
223
+ /* @__PURE__ */ jsx2("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
224
+ /* @__PURE__ */ jsx2("span", { className: "text-base font-semibold", children: title }),
225
+ isConnected && /* @__PURE__ */ jsxs2(Badge, { variant: "success", className: "gap-1 text-xs", children: [
226
+ /* @__PURE__ */ jsx2(CheckCircle2, { className: "h-3 w-3" }),
227
+ "Connected"
228
+ ] })
229
+ ] }) }),
230
+ isConnected && /* @__PURE__ */ jsx2(
231
+ Button,
232
+ {
233
+ variant: "ghost",
234
+ size: "icon",
235
+ className: "h-7 w-7 shrink-0",
236
+ onClick: (e) => {
237
+ e.stopPropagation();
238
+ onSettingsClick();
239
+ },
240
+ "aria-label": `Settings for ${title}`,
241
+ children: /* @__PURE__ */ jsx2(Settings, { className: "h-4 w-4" })
242
+ }
243
+ )
244
+ ] }),
245
+ /* @__PURE__ */ jsx2("p", { className: "text-sm leading-relaxed text-muted-foreground", children: description })
246
+ ]
247
+ }
248
+ );
249
+ }
250
+ function IntegrationInstructionCard({
251
+ title,
252
+ codeBlock,
253
+ onCopy,
254
+ className
255
+ }) {
256
+ const [copied, setCopied] = useState(false);
257
+ const handleCopy = () => __async(null, null, function* () {
258
+ try {
259
+ yield navigator.clipboard.writeText(codeBlock);
260
+ setCopied(true);
261
+ onCopy == null ? void 0 : onCopy();
262
+ setTimeout(() => setCopied(false), 2e3);
263
+ } catch (e) {
264
+ }
265
+ });
266
+ return /* @__PURE__ */ jsxs2(Card, { className: cn("flex flex-col gap-3 p-4", className), children: [
267
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-2", children: [
268
+ /* @__PURE__ */ jsx2("h3", { className: "text-sm font-semibold", children: title }),
269
+ /* @__PURE__ */ jsx2(
270
+ Button,
271
+ {
272
+ variant: "outline",
273
+ size: "sm",
274
+ className: "h-7 gap-1.5 text-xs",
275
+ onClick: handleCopy,
276
+ children: copied ? /* @__PURE__ */ jsxs2(Fragment, { children: [
277
+ /* @__PURE__ */ jsx2(Check, { className: "h-3 w-3" }),
278
+ "Copied"
279
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
280
+ /* @__PURE__ */ jsx2(Copy, { className: "h-3 w-3" }),
281
+ "Copy"
282
+ ] })
283
+ }
284
+ )
285
+ ] }),
286
+ /* @__PURE__ */ jsx2("pre", { className: "bg-muted overflow-x-auto p-3 text-xs leading-relaxed", children: /* @__PURE__ */ jsx2("code", { children: codeBlock }) })
287
+ ] });
288
+ }
289
+
290
+ // src/components/ui/ai-builder/service-config-modal.tsx
291
+ import { Check as Check2, CheckCircle2 as CheckCircle22, Clock, Mail, Shield, User as User2 } from "lucide-react";
292
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
293
+ function ServiceConfigurationModal({
294
+ open,
295
+ onOpenChange,
296
+ serviceTitle,
297
+ isConnected,
298
+ serviceData,
299
+ iconNode,
300
+ connectPermissions,
301
+ connectDescription = "Link your account to enable automated workflows with WealthX.",
302
+ onConnect,
303
+ onDisconnect,
304
+ onReconnect
305
+ }) {
306
+ return /* @__PURE__ */ jsx3(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx3(DialogContent, { className: "flex max-h-[90vh] flex-col max-w-md", children: isConnected ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
307
+ /* @__PURE__ */ jsxs3(DialogHeader, { children: [
308
+ /* @__PURE__ */ jsx3(DialogTitle, { children: serviceTitle }),
309
+ /* @__PURE__ */ jsx3(DialogDescription, { children: "Manage your integration settings." })
310
+ ] }),
311
+ /* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto py-2", children: [
312
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 px-3 py-2 text-xs font-medium bg-success/10 text-success", children: [
313
+ /* @__PURE__ */ jsx3(CheckCircle22, { className: "h-3.5 w-3.5 shrink-0" }),
314
+ "Active \u2014 integration is running"
315
+ ] }),
316
+ serviceData && /* @__PURE__ */ jsxs3(Fragment2, { children: [
317
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
318
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Account Information" }),
319
+ /* @__PURE__ */ jsx3(Card, { className: "py-0", children: /* @__PURE__ */ jsxs3(CardContent, { className: "flex flex-col gap-3 p-3", children: [
320
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-sm", children: [
321
+ /* @__PURE__ */ jsx3(User2, { className: "text-muted-foreground h-4 w-4 shrink-0" }),
322
+ /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
323
+ serviceData.accountIdentifierLabel,
324
+ ":"
325
+ ] }),
326
+ /* @__PURE__ */ jsx3("span", { className: "font-medium", children: serviceData.accountIdentifier })
327
+ ] }),
328
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-sm", children: [
329
+ /* @__PURE__ */ jsx3(Clock, { className: "text-muted-foreground h-4 w-4 shrink-0" }),
330
+ /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: "Connected on:" }),
331
+ /* @__PURE__ */ jsx3("span", { className: "font-medium", children: serviceData.connectedOn })
332
+ ] }),
333
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-sm", children: [
334
+ /* @__PURE__ */ jsx3(Clock, { className: "text-muted-foreground h-4 w-4 shrink-0" }),
335
+ /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: "Last synced:" }),
336
+ /* @__PURE__ */ jsx3("span", { className: "font-medium", children: serviceData.lastSynced })
337
+ ] })
338
+ ] }) })
339
+ ] }),
340
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
341
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Granted Permissions" }),
342
+ /* @__PURE__ */ jsx3(Card, { className: "py-0", children: /* @__PURE__ */ jsx3(CardContent, { className: "flex flex-col gap-2 p-3", children: serviceData.permissions.map((permission) => /* @__PURE__ */ jsxs3(
343
+ "div",
344
+ {
345
+ className: "flex items-center gap-2 text-sm",
346
+ children: [
347
+ /* @__PURE__ */ jsx3(Shield, { className: "text-success h-4 w-4 shrink-0" }),
348
+ /* @__PURE__ */ jsx3("span", { children: permission })
349
+ ]
350
+ },
351
+ permission
352
+ )) }) })
353
+ ] }),
354
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
355
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Sync Settings" }),
356
+ /* @__PURE__ */ jsx3(Card, { className: "py-0", children: /* @__PURE__ */ jsxs3(CardContent, { className: "flex items-center justify-between gap-3 p-3", children: [
357
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-0.5", children: [
358
+ /* @__PURE__ */ jsx3("p", { className: "text-sm font-medium", children: serviceData.syncLabel }),
359
+ /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-sm", children: serviceData.syncDescription })
360
+ ] }),
361
+ /* @__PURE__ */ jsx3(
362
+ Switch,
363
+ {
364
+ checked: serviceData.syncEnabled,
365
+ onCheckedChange: serviceData.onSyncToggle,
366
+ "aria-label": serviceData.syncLabel
367
+ }
368
+ )
369
+ ] }) })
370
+ ] }),
371
+ serviceData.emailCategories && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
372
+ /* @__PURE__ */ jsxs3("div", { children: [
373
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Email Filters" }),
374
+ /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-sm mt-0.5", children: "Choose which inbox categories to sync into WealthX." })
375
+ ] }),
376
+ /* @__PURE__ */ jsx3(Card, { className: "py-0", children: /* @__PURE__ */ jsx3(CardContent, { className: "flex flex-col gap-3 p-3", children: serviceData.emailCategories.available.map(
377
+ (category) => {
378
+ const checked = serviceData.emailCategories.selected.includes(
379
+ category
380
+ );
381
+ return /* @__PURE__ */ jsxs3(
382
+ "div",
383
+ {
384
+ className: "flex items-center gap-2",
385
+ children: [
386
+ /* @__PURE__ */ jsx3(
387
+ Checkbox,
388
+ {
389
+ id: `email-cat-${category}`,
390
+ checked,
391
+ onCheckedChange: (v) => {
392
+ const next = v ? [
393
+ ...serviceData.emailCategories.selected,
394
+ category
395
+ ] : serviceData.emailCategories.selected.filter(
396
+ (c) => c !== category
397
+ );
398
+ serviceData.emailCategories.onChange(
399
+ next
400
+ );
401
+ }
402
+ }
403
+ ),
404
+ /* @__PURE__ */ jsx3(
405
+ "label",
406
+ {
407
+ htmlFor: `email-cat-${category}`,
408
+ className: "text-sm cursor-pointer select-none",
409
+ children: category
410
+ }
411
+ )
412
+ ]
413
+ },
414
+ category
415
+ );
416
+ }
417
+ ) }) })
418
+ ] }),
419
+ serviceData.emailFilters && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
420
+ /* @__PURE__ */ jsxs3("div", { children: [
421
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Email Filters" }),
422
+ /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-sm mt-0.5", children: serviceData.emailFilters.description })
423
+ ] }),
424
+ /* @__PURE__ */ jsx3(Card, { className: "py-0", children: /* @__PURE__ */ jsx3(CardContent, { className: "flex flex-col gap-3 p-3 max-h-48 overflow-y-auto", children: serviceData.emailFilters.categories.map(
425
+ (category) => /* @__PURE__ */ jsxs3(
426
+ "div",
427
+ {
428
+ className: "flex items-center gap-2",
429
+ children: [
430
+ /* @__PURE__ */ jsx3(
431
+ Checkbox,
432
+ {
433
+ id: `email-cat-${category.id}`,
434
+ checked: category.enabled,
435
+ onCheckedChange: (v) => serviceData.emailFilters.onFilterChange(
436
+ category.id,
437
+ !!v
438
+ )
439
+ }
440
+ ),
441
+ /* @__PURE__ */ jsx3(
442
+ "label",
443
+ {
444
+ htmlFor: `email-cat-${category.id}`,
445
+ className: "text-sm cursor-pointer select-none",
446
+ children: category.label
447
+ }
448
+ )
449
+ ]
450
+ },
451
+ category.id
452
+ )
453
+ ) }) })
454
+ ] })
455
+ ] })
456
+ ] }),
457
+ /* @__PURE__ */ jsxs3(DialogFooter, { children: [
458
+ /* @__PURE__ */ jsx3(
459
+ Button,
460
+ {
461
+ variant: "destructive",
462
+ size: "sm",
463
+ onClick: onDisconnect,
464
+ className: "mr-auto",
465
+ children: "Disconnect"
466
+ }
467
+ ),
468
+ /* @__PURE__ */ jsx3(
469
+ Button,
470
+ {
471
+ variant: "outline-secondary",
472
+ size: "sm",
473
+ onClick: () => onOpenChange(false),
474
+ children: "Cancel"
475
+ }
476
+ ),
477
+ /* @__PURE__ */ jsx3(Button, { size: "sm", onClick: onReconnect, children: "Reconnect" })
478
+ ] })
479
+ ] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
480
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-4 py-2", children: [
481
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
482
+ /* @__PURE__ */ jsx3("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center bg-muted", children: iconNode != null ? iconNode : /* @__PURE__ */ jsx3(Mail, { className: "h-5 w-5 text-muted-foreground" }) }),
483
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-0.5", children: [
484
+ /* @__PURE__ */ jsxs3("p", { className: "text-sm font-semibold", children: [
485
+ "Connect ",
486
+ serviceTitle
487
+ ] }),
488
+ /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: connectDescription })
489
+ ] })
490
+ ] }),
491
+ connectPermissions && connectPermissions.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2 border border-border px-4 py-3", children: [
492
+ /* @__PURE__ */ jsx3("p", { className: "text-overline text-muted-foreground", children: "Permissions requested" }),
493
+ connectPermissions.map((perm) => /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
494
+ /* @__PURE__ */ jsx3(Check2, { className: "h-3.5 w-3.5 shrink-0 text-success" }),
495
+ /* @__PURE__ */ jsx3("span", { className: "text-sm text-muted-foreground", children: perm })
496
+ ] }, perm))
497
+ ] })
498
+ ] }),
499
+ /* @__PURE__ */ jsxs3(DialogFooter, { children: [
500
+ /* @__PURE__ */ jsx3(
501
+ Button,
502
+ {
503
+ variant: "outline-secondary",
504
+ size: "sm",
505
+ onClick: () => onOpenChange(false),
506
+ children: "Cancel"
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx3(Button, { size: "sm", onClick: onConnect, children: "Connect" })
510
+ ] })
511
+ ] }) }) });
512
+ }
513
+
514
+ // src/components/ui/ai-builder/agent-settings.tsx
515
+ import React2 from "react";
516
+ import {
517
+ closestCenter,
518
+ DndContext,
519
+ KeyboardSensor,
520
+ PointerSensor,
521
+ useSensor,
522
+ useSensors
523
+ } from "@dnd-kit/core";
524
+ import {
525
+ SortableContext,
526
+ sortableKeyboardCoordinates,
527
+ useSortable,
528
+ verticalListSortingStrategy
529
+ } from "@dnd-kit/sortable";
530
+ import { CSS } from "@dnd-kit/utilities";
531
+ import {
532
+ Download,
533
+ GripVertical,
534
+ Info,
535
+ Pencil,
536
+ Plus,
537
+ Trash2,
538
+ Upload
539
+ } from "lucide-react";
540
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
541
+ function SectionHeader({
542
+ title,
543
+ description,
544
+ className
545
+ }) {
546
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col gap-0.5", className), children: [
547
+ /* @__PURE__ */ jsx4("h2", { className: "text-h5", children: title }),
548
+ /* @__PURE__ */ jsx4("p", { className: "text-body-small text-muted-foreground", children: description })
549
+ ] });
550
+ }
551
+ function SettingRow({
552
+ icon,
553
+ label,
554
+ description,
555
+ control,
556
+ className
557
+ }) {
558
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex items-center gap-4 py-4", className), children: [
559
+ /* @__PURE__ */ jsx4("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: icon }),
560
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 flex-col gap-0.5", children: [
561
+ /* @__PURE__ */ jsx4("span", { className: "text-sm font-semibold", children: label }),
562
+ /* @__PURE__ */ jsx4("span", { className: "text-caption text-muted-foreground", children: description })
563
+ ] }),
564
+ /* @__PURE__ */ jsx4("div", { className: "shrink-0", children: control })
565
+ ] });
566
+ }
567
+ function SettingCard({ rows, className }) {
568
+ return /* @__PURE__ */ jsx4("div", { className: cn("rounded-none border px-4", className), children: rows.map((row, i) => /* @__PURE__ */ jsxs4(React2.Fragment, { children: [
569
+ /* @__PURE__ */ jsx4(SettingRow, __spreadValues({}, row)),
570
+ i < rows.length - 1 && /* @__PURE__ */ jsx4(Separator, {})
571
+ ] }, row.label)) });
572
+ }
573
+ function AgentConfigForm({
574
+ config,
575
+ onChange,
576
+ className
577
+ }) {
578
+ return /* @__PURE__ */ jsxs4(
579
+ "div",
580
+ {
581
+ className: cn("flex flex-col gap-4 rounded-none border p-6", className),
582
+ children: [
583
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5", children: [
584
+ /* @__PURE__ */ jsx4(Label, { htmlFor: "agent-name", children: "Agent Name" }),
585
+ /* @__PURE__ */ jsx4(
586
+ Input,
587
+ {
588
+ id: "agent-name",
589
+ value: config.name,
590
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, config), { name: e.target.value }))
591
+ }
592
+ )
593
+ ] }),
594
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5", children: [
595
+ /* @__PURE__ */ jsx4(Label, { htmlFor: "agent-desc", children: "Business Description" }),
596
+ /* @__PURE__ */ jsx4(
597
+ Textarea,
598
+ {
599
+ id: "agent-desc",
600
+ rows: 4,
601
+ placeholder: "What business is this agent for? What industry?",
602
+ value: config.businessDescription,
603
+ onChange: (e) => onChange(__spreadProps(__spreadValues({}, config), { businessDescription: e.target.value }))
604
+ }
605
+ )
606
+ ] })
607
+ ]
608
+ }
609
+ );
610
+ }
611
+ function ResponseTemplateEditModal({
612
+ open,
613
+ onOpenChange,
614
+ channel,
615
+ content,
616
+ onConfirm
617
+ }) {
618
+ const [draft, setDraft] = React2.useState(content);
619
+ React2.useEffect(() => {
620
+ if (open) setDraft(content);
621
+ }, [open, content]);
622
+ const isEmail = channel === "email";
623
+ const channelLabel = isEmail ? "Email" : "Chat";
624
+ const helperText = isEmail ? "Use {customer} to insert the customer name and {answer} to insert the response" : "Use {answer} to insert the response";
625
+ return /* @__PURE__ */ jsx4(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs4(DialogContent, { className: "max-w-lg", children: [
626
+ /* @__PURE__ */ jsx4(DialogHeader, { children: /* @__PURE__ */ jsxs4(DialogTitle, { children: [
627
+ "Edit ",
628
+ channelLabel,
629
+ " response template"
630
+ ] }) }),
631
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5 py-2", children: [
632
+ /* @__PURE__ */ jsxs4(Label, { htmlFor: "template-content", children: [
633
+ channelLabel,
634
+ " template content",
635
+ " ",
636
+ /* @__PURE__ */ jsx4("span", { className: "text-destructive", children: "*" })
637
+ ] }),
638
+ /* @__PURE__ */ jsx4(
639
+ Textarea,
640
+ {
641
+ id: "template-content",
642
+ rows: 6,
643
+ placeholder: `Enter content for ${channelLabel} template`,
644
+ value: draft,
645
+ onChange: (e) => setDraft(e.target.value)
646
+ }
647
+ ),
648
+ /* @__PURE__ */ jsx4("p", { className: "text-caption text-muted-foreground", children: helperText })
649
+ ] }),
650
+ /* @__PURE__ */ jsxs4(DialogFooter, { children: [
651
+ /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
652
+ /* @__PURE__ */ jsx4(
653
+ Button,
654
+ {
655
+ onClick: () => {
656
+ onConfirm(draft);
657
+ onOpenChange(false);
658
+ },
659
+ children: "Confirm"
660
+ }
661
+ )
662
+ ] })
663
+ ] }) });
664
+ }
665
+ function RuleOrderBadge({ order, className }) {
666
+ return /* @__PURE__ */ jsxs4(Badge, { variant: "secondary", className, children: [
667
+ "#",
668
+ order
669
+ ] });
670
+ }
671
+ function SortableRuleRow({
672
+ rule,
673
+ index,
674
+ onEdit,
675
+ onDelete,
676
+ onToggle
677
+ }) {
678
+ const {
679
+ attributes,
680
+ listeners,
681
+ setNodeRef,
682
+ transform,
683
+ transition,
684
+ isDragging
685
+ } = useSortable({ id: rule.id });
686
+ const style = {
687
+ transform: CSS.Transform.toString(transform),
688
+ transition
689
+ };
690
+ return /* @__PURE__ */ jsxs4(
691
+ TableRow,
692
+ {
693
+ ref: setNodeRef,
694
+ style,
695
+ className: cn(isDragging && "opacity-50 bg-muted/40"),
696
+ children: [
697
+ /* @__PURE__ */ jsx4(TableCell, { children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
698
+ /* @__PURE__ */ jsx4(
699
+ "button",
700
+ __spreadProps(__spreadValues(__spreadValues({
701
+ type: "button",
702
+ className: "cursor-grab touch-none text-muted-foreground hover:text-foreground active:cursor-grabbing",
703
+ "aria-label": `Drag to reorder rule ${index + 1}`
704
+ }, attributes), listeners), {
705
+ children: /* @__PURE__ */ jsx4(GripVertical, { className: "h-4 w-4" })
706
+ })
707
+ ),
708
+ /* @__PURE__ */ jsx4(RuleOrderBadge, { order: index + 1 })
709
+ ] }) }),
710
+ /* @__PURE__ */ jsx4(TableCell, { className: "text-body-small overflow-hidden", children: /* @__PURE__ */ jsx4("div", { className: "break-words whitespace-normal", children: rule.text }) }),
711
+ /* @__PURE__ */ jsx4(TableCell, { children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-end gap-1", children: [
712
+ /* @__PURE__ */ jsx4(
713
+ Switch,
714
+ {
715
+ checked: rule.isEnabled,
716
+ onCheckedChange: (checked) => onToggle(rule.id, checked),
717
+ "aria-label": `Toggle rule ${index + 1}`
718
+ }
719
+ ),
720
+ /* @__PURE__ */ jsx4(
721
+ Button,
722
+ {
723
+ variant: "ghost",
724
+ size: "icon",
725
+ className: "h-8 w-8",
726
+ onClick: () => onEdit(rule.id),
727
+ "aria-label": `Edit rule ${index + 1}`,
728
+ children: /* @__PURE__ */ jsx4(Pencil, { className: "h-3.5 w-3.5" })
729
+ }
730
+ ),
731
+ /* @__PURE__ */ jsx4(
732
+ Button,
733
+ {
734
+ variant: "ghost",
735
+ size: "icon",
736
+ className: "h-8 w-8 text-destructive hover:text-destructive",
737
+ onClick: () => onDelete(rule.id),
738
+ "aria-label": `Delete rule ${index + 1}`,
739
+ children: /* @__PURE__ */ jsx4(Trash2, { className: "h-3.5 w-3.5" })
740
+ }
741
+ )
742
+ ] }) })
743
+ ]
744
+ }
745
+ );
746
+ }
747
+ function RuleTable({
748
+ rules,
749
+ onEdit,
750
+ onDelete,
751
+ onToggle,
752
+ onReorder
753
+ }) {
754
+ const sensors = useSensors(
755
+ useSensor(PointerSensor),
756
+ useSensor(KeyboardSensor, {
757
+ coordinateGetter: sortableKeyboardCoordinates
758
+ })
759
+ );
760
+ function handleDragEnd(event) {
761
+ const { active, over } = event;
762
+ if (over && active.id !== over.id && onReorder) {
763
+ onReorder(String(active.id), String(over.id));
764
+ }
765
+ }
766
+ if (rules.length === 0) {
767
+ return /* @__PURE__ */ jsx4("div", { className: "flex h-24 items-center justify-center text-body-small text-muted-foreground", children: "No rules added yet." });
768
+ }
769
+ return /* @__PURE__ */ jsx4(
770
+ DndContext,
771
+ {
772
+ sensors,
773
+ collisionDetection: closestCenter,
774
+ onDragEnd: handleDragEnd,
775
+ children: /* @__PURE__ */ jsx4(
776
+ SortableContext,
777
+ {
778
+ items: rules.map((r) => r.id),
779
+ strategy: verticalListSortingStrategy,
780
+ children: /* @__PURE__ */ jsxs4(Table, { className: "table-fixed", children: [
781
+ /* @__PURE__ */ jsx4(TableHeader, { children: /* @__PURE__ */ jsxs4(TableRow, { children: [
782
+ /* @__PURE__ */ jsx4(TableHead, { className: "w-28", children: /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5", children: [
783
+ "Order",
784
+ /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsxs4(Tooltip, { children: [
785
+ /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx4(Info, { className: "h-3.5 w-3.5 text-muted-foreground cursor-default" }) }),
786
+ /* @__PURE__ */ jsx4(TooltipContent, { children: "Drag rows to reorder rules" })
787
+ ] }) })
788
+ ] }) }),
789
+ /* @__PURE__ */ jsx4(TableHead, { children: "Rule Set" }),
790
+ /* @__PURE__ */ jsx4(TableHead, { className: "w-36 text-right", children: "Actions" })
791
+ ] }) }),
792
+ /* @__PURE__ */ jsx4(TableBody, { children: rules.map((rule, index) => /* @__PURE__ */ jsx4(
793
+ SortableRuleRow,
794
+ {
795
+ rule,
796
+ index,
797
+ onEdit,
798
+ onDelete,
799
+ onToggle
800
+ },
801
+ rule.id
802
+ )) })
803
+ ] })
804
+ }
805
+ )
806
+ }
807
+ );
808
+ }
809
+ function RuleTabContent({
810
+ rules,
811
+ description,
812
+ onEditRule,
813
+ onDeleteRule,
814
+ onToggleRule,
815
+ onReorderRules,
816
+ rowsPerPage
817
+ }) {
818
+ return /* @__PURE__ */ jsxs4("div", { className: "mt-4 flex flex-col gap-3", children: [
819
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-2 rounded-none border border-blue-200 bg-blue-50 p-3", children: [
820
+ /* @__PURE__ */ jsx4(Info, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600" }),
821
+ /* @__PURE__ */ jsx4("p", { className: "text-caption text-blue-700", children: description })
822
+ ] }),
823
+ /* @__PURE__ */ jsx4(
824
+ RuleTable,
825
+ {
826
+ rules,
827
+ onEdit: onEditRule,
828
+ onDelete: onDeleteRule,
829
+ onToggle: onToggleRule,
830
+ onReorder: onReorderRules
831
+ }
832
+ ),
833
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-end gap-2 pt-2 text-body-small text-muted-foreground", children: [
834
+ /* @__PURE__ */ jsx4("span", { children: "Rows per page:" }),
835
+ /* @__PURE__ */ jsxs4(Select, { defaultValue: String(rowsPerPage), children: [
836
+ /* @__PURE__ */ jsx4(SelectTrigger, { className: "h-8 w-20", children: /* @__PURE__ */ jsx4(SelectValue, {}) }),
837
+ /* @__PURE__ */ jsxs4(SelectContent, { children: [
838
+ /* @__PURE__ */ jsx4(SelectItem, { value: "5", children: "5" }),
839
+ /* @__PURE__ */ jsx4(SelectItem, { value: "10", children: "10" }),
840
+ /* @__PURE__ */ jsx4(SelectItem, { value: "20", children: "20" }),
841
+ /* @__PURE__ */ jsx4(SelectItem, { value: "50", children: "50" })
842
+ ] })
843
+ ] })
844
+ ] })
845
+ ] });
846
+ }
847
+ function RuleSetSection({
848
+ standardRules,
849
+ handoffRules,
850
+ onAddRule,
851
+ onEditRule,
852
+ onDeleteRule,
853
+ onToggleRule,
854
+ onReorderRules,
855
+ onExport,
856
+ onImport,
857
+ rowsPerPage = 10,
858
+ className
859
+ }) {
860
+ const [activeTab, setActiveTab] = React2.useState(
861
+ "standard"
862
+ );
863
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col gap-4", className), children: [
864
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-start justify-between gap-4", children: [
865
+ /* @__PURE__ */ jsx4(
866
+ SectionHeader,
867
+ {
868
+ title: "Rule Set",
869
+ description: "You can adjust the behavior and response method of the Agent through rules."
870
+ }
871
+ ),
872
+ /* @__PURE__ */ jsxs4("div", { className: "flex shrink-0 items-center gap-2", children: [
873
+ /* @__PURE__ */ jsxs4(Button, { variant: "outline", size: "sm", onClick: onExport, children: [
874
+ /* @__PURE__ */ jsx4(Download, { className: "mr-1.5 h-3.5 w-3.5" }),
875
+ "Export"
876
+ ] }),
877
+ /* @__PURE__ */ jsxs4(Button, { variant: "outline", size: "sm", onClick: onImport, children: [
878
+ /* @__PURE__ */ jsx4(Upload, { className: "mr-1.5 h-3.5 w-3.5" }),
879
+ "Import"
880
+ ] }),
881
+ /* @__PURE__ */ jsxs4(Button, { size: "sm", onClick: () => onAddRule(activeTab), children: [
882
+ /* @__PURE__ */ jsx4(Plus, { className: "mr-1.5 h-3.5 w-3.5" }),
883
+ "Add rule"
884
+ ] })
885
+ ] })
886
+ ] }),
887
+ /* @__PURE__ */ jsxs4(
888
+ Tabs,
889
+ {
890
+ defaultValue: "standard",
891
+ onValueChange: (v) => setActiveTab(v),
892
+ children: [
893
+ /* @__PURE__ */ jsxs4(TabsList, { className: "w-full", children: [
894
+ /* @__PURE__ */ jsx4(TabsTrigger, { value: "standard", className: "flex-1", children: "Standard Rules" }),
895
+ /* @__PURE__ */ jsx4(TabsTrigger, { value: "handoff", className: "flex-1", children: "Hand-off Rules" })
896
+ ] }),
897
+ /* @__PURE__ */ jsx4(TabsContent, { value: "standard", children: /* @__PURE__ */ jsx4(
898
+ RuleTabContent,
899
+ {
900
+ rules: standardRules,
901
+ description: "Standard rules guide AI behavior during response generation. These rules help the AI understand how to respond appropriately.",
902
+ onEditRule,
903
+ onDeleteRule,
904
+ onToggleRule,
905
+ onReorderRules,
906
+ rowsPerPage
907
+ }
908
+ ) }),
909
+ /* @__PURE__ */ jsx4(TabsContent, { value: "handoff", children: /* @__PURE__ */ jsx4(
910
+ RuleTabContent,
911
+ {
912
+ rules: handoffRules,
913
+ description: "Hand-off rules define when the AI should transfer a conversation to a human agent.",
914
+ onEditRule,
915
+ onDeleteRule,
916
+ onToggleRule,
917
+ onReorderRules,
918
+ rowsPerPage
919
+ }
920
+ ) })
921
+ ]
922
+ }
923
+ )
924
+ ] });
925
+ }
926
+ function AddEditRuleModal({
927
+ open,
928
+ onOpenChange,
929
+ rule,
930
+ defaultType = "standard",
931
+ onConfirm
932
+ }) {
933
+ var _a;
934
+ const RULE_TYPE_LABELS = {
935
+ standard: "Standard Rule",
936
+ handoff: "Hand-off Rule"
937
+ };
938
+ const LABEL_TO_TYPE = {
939
+ "Standard Rule": "standard",
940
+ "Hand-off Rule": "handoff"
941
+ };
942
+ const isEdit = !!rule;
943
+ const [draft, setDraft] = React2.useState((_a = rule == null ? void 0 : rule.text) != null ? _a : "");
944
+ const [ruleType, setRuleType] = React2.useState(
945
+ defaultType
946
+ );
947
+ React2.useEffect(() => {
948
+ var _a2;
949
+ if (open) {
950
+ setDraft((_a2 = rule == null ? void 0 : rule.text) != null ? _a2 : "");
951
+ setRuleType(defaultType);
952
+ }
953
+ }, [open, rule, defaultType]);
954
+ return /* @__PURE__ */ jsx4(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs4(DialogContent, { className: "max-w-lg", children: [
955
+ /* @__PURE__ */ jsx4(DialogHeader, { children: /* @__PURE__ */ jsx4(DialogTitle, { children: isEdit ? "Edit Rule" : "Add Rule" }) }),
956
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-3 py-2", children: [
957
+ !isEdit && /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5", children: [
958
+ /* @__PURE__ */ jsxs4(Label, { htmlFor: "rule-type", children: [
959
+ "Rule Type ",
960
+ /* @__PURE__ */ jsx4("span", { className: "text-destructive", children: "*" })
961
+ ] }),
962
+ /* @__PURE__ */ jsxs4(
963
+ Select,
964
+ {
965
+ value: RULE_TYPE_LABELS[ruleType],
966
+ onValueChange: (v) => setRuleType(LABEL_TO_TYPE[v]),
967
+ children: [
968
+ /* @__PURE__ */ jsx4(SelectTrigger, { id: "rule-type", className: "w-full", children: /* @__PURE__ */ jsx4(SelectValue, {}) }),
969
+ /* @__PURE__ */ jsxs4(SelectContent, { children: [
970
+ /* @__PURE__ */ jsx4(SelectItem, { value: "Standard Rule", children: "Standard Rule" }),
971
+ /* @__PURE__ */ jsx4(SelectItem, { value: "Hand-off Rule", children: "Hand-off Rule" })
972
+ ] })
973
+ ]
974
+ }
975
+ )
976
+ ] }),
977
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-1.5", children: [
978
+ /* @__PURE__ */ jsxs4(Label, { htmlFor: "rule-draft", children: [
979
+ "Rule ",
980
+ /* @__PURE__ */ jsx4("span", { className: "text-destructive", children: "*" })
981
+ ] }),
982
+ /* @__PURE__ */ jsx4(
983
+ Textarea,
984
+ {
985
+ id: "rule-draft",
986
+ rows: 4,
987
+ placeholder: "Describe the rule the agent should follow\u2026",
988
+ value: draft,
989
+ onChange: (e) => setDraft(e.target.value)
990
+ }
991
+ )
992
+ ] })
993
+ ] }),
994
+ /* @__PURE__ */ jsxs4(DialogFooter, { children: [
995
+ /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
996
+ /* @__PURE__ */ jsx4(
997
+ Button,
998
+ {
999
+ disabled: !draft.trim(),
1000
+ onClick: () => {
1001
+ onConfirm(draft.trim(), ruleType);
1002
+ onOpenChange(false);
1003
+ },
1004
+ children: isEdit ? "Save" : "Add"
1005
+ }
1006
+ )
1007
+ ] })
1008
+ ] }) });
1009
+ }
1010
+
1011
+ export {
1012
+ AgentCard,
1013
+ AgentMenuModal,
1014
+ IntegrationServiceCard,
1015
+ IntegrationInstructionCard,
1016
+ ServiceConfigurationModal,
1017
+ SectionHeader,
1018
+ SettingRow,
1019
+ SettingCard,
1020
+ AgentConfigForm,
1021
+ ResponseTemplateEditModal,
1022
+ RuleOrderBadge,
1023
+ RuleSetSection,
1024
+ AddEditRuleModal
1025
+ };