@handled-ai/design-system 0.8.0 → 0.9.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 +14 -4
- package/dist/charts/bar-chart-component.d.ts +24 -0
- package/dist/charts/bar-chart-component.js +123 -0
- package/dist/charts/bar-chart-component.js.map +1 -0
- package/dist/charts/chart-tooltip.d.ts +26 -0
- package/dist/charts/chart-tooltip.js +69 -0
- package/dist/charts/chart-tooltip.js.map +1 -0
- package/dist/charts/chart.d.ts +64 -0
- package/dist/charts/chart.js +285 -0
- package/dist/charts/chart.js.map +1 -0
- package/dist/charts/donut-chart.d.ts +21 -0
- package/dist/charts/donut-chart.js +96 -0
- package/dist/charts/donut-chart.js.map +1 -0
- package/dist/charts/index.d.ts +11 -0
- package/dist/charts/index.js +10 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/pipeline-overview.d.ts +76 -0
- package/dist/charts/pipeline-overview.js +372 -0
- package/dist/charts/pipeline-overview.js.map +1 -0
- package/dist/charts/sankey-chart.d.ts +52 -0
- package/dist/charts/sankey-chart.js +219 -0
- package/dist/charts/sankey-chart.js.map +1 -0
- package/dist/charts/top-line-metrics.d.ts +26 -0
- package/dist/charts/top-line-metrics.js +224 -0
- package/dist/charts/top-line-metrics.js.map +1 -0
- package/dist/charts/trend-area-chart.d.ts +21 -0
- package/dist/charts/trend-area-chart.js +150 -0
- package/dist/charts/trend-area-chart.js.map +1 -0
- package/dist/charts/volume-analysis-chart.d.ts +19 -0
- package/dist/charts/volume-analysis-chart.js +121 -0
- package/dist/charts/volume-analysis-chart.js.map +1 -0
- package/dist/components/activity-detail.d.ts +38 -0
- package/dist/components/activity-detail.js +163 -0
- package/dist/components/activity-detail.js.map +1 -0
- package/dist/components/activity-log.d.ts +21 -0
- package/dist/components/activity-log.js +61 -0
- package/dist/components/activity-log.js.map +1 -0
- package/dist/components/agent-popover.d.ts +71 -0
- package/dist/components/agent-popover.js +282 -0
- package/dist/components/agent-popover.js.map +1 -0
- package/dist/components/agent-widget.d.ts +24 -0
- package/dist/components/agent-widget.js +117 -0
- package/dist/components/agent-widget.js.map +1 -0
- package/dist/components/avatar.d.ts +13 -0
- package/dist/components/avatar.js +140 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +12 -0
- package/dist/components/badge.js +75 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.d.ts +13 -0
- package/dist/components/button.js +83 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.d.ts +11 -0
- package/dist/components/card.js +119 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/contact-list.d.ts +34 -0
- package/dist/components/contact-list.js +84 -0
- package/dist/components/contact-list.js.map +1 -0
- package/dist/components/dashboard-cards.d.ts +10 -0
- package/dist/components/dashboard-cards.js +164 -0
- package/dist/components/dashboard-cards.js.map +1 -0
- package/dist/components/data-table-display.d.ts +19 -0
- package/dist/components/data-table-display.js +109 -0
- package/dist/components/data-table-display.js.map +1 -0
- package/dist/components/data-table-filter.d.ts +18 -0
- package/dist/components/data-table-filter.js +107 -0
- package/dist/components/data-table-filter.js.map +1 -0
- package/dist/components/data-table-quick-views.d.ts +13 -0
- package/dist/components/data-table-quick-views.js +90 -0
- package/dist/components/data-table-quick-views.js.map +1 -0
- package/dist/components/data-table-toolbar.d.ts +18 -0
- package/dist/components/data-table-toolbar.js +45 -0
- package/dist/components/data-table-toolbar.js.map +1 -0
- package/dist/components/data-table.d.ts +39 -0
- package/dist/components/data-table.js +821 -0
- package/dist/components/data-table.js.map +1 -0
- package/dist/components/detail-view.d.ts +44 -0
- package/dist/components/detail-view.js +165 -0
- package/dist/components/detail-view.js.map +1 -0
- package/dist/components/dialog.d.ts +19 -0
- package/dist/components/dialog.js +188 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +27 -0
- package/dist/components/dropdown-menu.js +279 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/entity-panel.d.ts +69 -0
- package/dist/components/entity-panel.js +584 -0
- package/dist/components/entity-panel.js.map +1 -0
- package/dist/components/inbox-row.d.ts +27 -0
- package/dist/components/inbox-row.js +139 -0
- package/dist/components/inbox-row.js.map +1 -0
- package/dist/components/inbox-toolbar.d.ts +21 -0
- package/dist/components/inbox-toolbar.js +203 -0
- package/dist/components/inbox-toolbar.js.map +1 -0
- package/dist/components/input.d.ts +5 -0
- package/dist/components/input.js +50 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/insights-filter-bar.d.ts +21 -0
- package/dist/components/insights-filter-bar.js +99 -0
- package/dist/components/insights-filter-bar.js.map +1 -0
- package/dist/components/item-list-display.d.ts +22 -0
- package/dist/components/item-list-display.js +240 -0
- package/dist/components/item-list-display.js.map +1 -0
- package/dist/components/item-list-filter.d.ts +16 -0
- package/dist/components/item-list-filter.js +87 -0
- package/dist/components/item-list-filter.js.map +1 -0
- package/dist/components/item-list-toolbar.d.ts +25 -0
- package/dist/components/item-list-toolbar.js +79 -0
- package/dist/components/item-list-toolbar.js.map +1 -0
- package/dist/components/item-list.d.ts +20 -0
- package/dist/components/item-list.js +702 -0
- package/dist/components/item-list.js.map +1 -0
- package/dist/components/label.d.ts +6 -0
- package/dist/components/label.js +55 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/message.d.ts +23 -0
- package/dist/components/message.js +117 -0
- package/dist/components/message.js.map +1 -0
- package/dist/components/metric-card.d.ts +25 -0
- package/dist/components/metric-card.js +107 -0
- package/dist/components/metric-card.js.map +1 -0
- package/dist/components/performance-metrics-table.d.ts +38 -0
- package/dist/components/performance-metrics-table.js +342 -0
- package/dist/components/performance-metrics-table.js.map +1 -0
- package/dist/components/preview-list.d.ts +14 -0
- package/dist/components/preview-list.js +83 -0
- package/dist/components/preview-list.js.map +1 -0
- package/dist/components/progress.d.ts +6 -0
- package/dist/components/progress.js +69 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/quick-action-chat-area.d.ts +24 -0
- package/dist/components/quick-action-chat-area.js +178 -0
- package/dist/components/quick-action-chat-area.js.map +1 -0
- package/dist/components/quick-action-modal.d.ts +30 -0
- package/dist/components/quick-action-modal.js +288 -0
- package/dist/components/quick-action-modal.js.map +1 -0
- package/dist/components/quick-action-sidebar-nav.d.ts +51 -0
- package/dist/components/quick-action-sidebar-nav.js +528 -0
- package/dist/components/quick-action-sidebar-nav.js.map +1 -0
- package/dist/components/recommended-actions-section.d.ts +23 -0
- package/dist/components/recommended-actions-section.js +215 -0
- package/dist/components/recommended-actions-section.js.map +1 -0
- package/dist/components/report-card.d.ts +26 -0
- package/dist/components/report-card.js +69 -0
- package/dist/components/report-card.js.map +1 -0
- package/dist/components/score-analysis-modal.d.ts +26 -0
- package/dist/components/score-analysis-modal.js +141 -0
- package/dist/components/score-analysis-modal.js.map +1 -0
- package/dist/components/score-breakdown.d.ts +17 -0
- package/dist/components/score-breakdown.js +162 -0
- package/dist/components/score-breakdown.js.map +1 -0
- package/dist/components/score-feedback.d.ts +40 -0
- package/dist/components/score-feedback.js +209 -0
- package/dist/components/score-feedback.js.map +1 -0
- package/dist/components/score-ring.d.ts +14 -0
- package/dist/components/score-ring.js +79 -0
- package/dist/components/score-ring.js.map +1 -0
- package/dist/components/scroll-area.d.ts +7 -0
- package/dist/components/scroll-area.js +101 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/select.d.ts +17 -0
- package/dist/components/select.js +228 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +6 -0
- package/dist/components/separator.js +61 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +16 -0
- package/dist/components/sheet.js +168 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/sidebar.d.ts +73 -0
- package/dist/components/sidebar.js +723 -0
- package/dist/components/sidebar.js.map +1 -0
- package/dist/components/signal-feedback-inline.d.ts +51 -0
- package/dist/components/signal-feedback-inline.js +548 -0
- package/dist/components/signal-feedback-inline.js.map +1 -0
- package/dist/components/simple-data-table.d.ts +15 -0
- package/dist/components/simple-data-table.js +91 -0
- package/dist/components/simple-data-table.js.map +1 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.js +44 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/status-badge.d.ts +10 -0
- package/dist/components/status-badge.js +82 -0
- package/dist/components/status-badge.js.map +1 -0
- package/dist/components/styled-bar-list.d.ts +20 -0
- package/dist/components/styled-bar-list.js +59 -0
- package/dist/components/styled-bar-list.js.map +1 -0
- package/dist/components/suggested-actions.d.ts +110 -0
- package/dist/components/suggested-actions.js +1538 -0
- package/dist/components/suggested-actions.js.map +1 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +147 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +14 -0
- package/dist/components/tabs.js +129 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +5 -0
- package/dist/components/textarea.js +47 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/timeline-activity.d.ts +34 -0
- package/dist/components/timeline-activity.js +181 -0
- package/dist/components/timeline-activity.js.map +1 -0
- package/dist/components/tooltip.d.ts +9 -0
- package/dist/components/tooltip.js +93 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/view-mode-toggle.d.ts +16 -0
- package/dist/components/view-mode-toggle.js +24 -0
- package/dist/components/view-mode-toggle.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +21 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/index.d.ts +68 -1878
- package/dist/index.js +69 -10918
- package/dist/index.js.map +1 -1
- package/dist/lib/icons.d.ts +18 -0
- package/dist/lib/icons.js +21 -0
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/prototype/index.d.ts +20 -0
- package/dist/prototype/index.js +8 -0
- package/dist/prototype/index.js.map +1 -0
- package/dist/prototype/prototype-accounts-view.d.ts +22 -0
- package/dist/prototype/prototype-accounts-view.js +70 -0
- package/dist/prototype/prototype-accounts-view.js.map +1 -0
- package/dist/prototype/prototype-admin-view.d.ts +21 -0
- package/dist/prototype/prototype-admin-view.js +53 -0
- package/dist/prototype/prototype-admin-view.js.map +1 -0
- package/dist/prototype/prototype-config.d.ts +226 -0
- package/dist/prototype/prototype-config.js +1 -0
- package/dist/prototype/prototype-config.js.map +1 -0
- package/dist/prototype/prototype-inbox-view.d.ts +48 -0
- package/dist/prototype/prototype-inbox-view.js +701 -0
- package/dist/prototype/prototype-inbox-view.js.map +1 -0
- package/dist/prototype/prototype-insights-view.d.ts +23 -0
- package/dist/prototype/prototype-insights-view.js +335 -0
- package/dist/prototype/prototype-insights-view.js.map +1 -0
- package/dist/prototype/prototype-shell.d.ts +40 -0
- package/dist/prototype/prototype-shell.js +190 -0
- package/dist/prototype/prototype-shell.js.map +1 -0
- package/dist/prototype/prototype-work-queue-view.d.ts +8 -0
- package/dist/prototype/prototype-work-queue-view.js +17 -0
- package/dist/prototype/prototype-work-queue-view.js.map +1 -0
- package/dist/three/agent-orb.d.ts +39 -0
- package/dist/three/agent-orb.js +500 -0
- package/dist/three/agent-orb.js.map +1 -0
- package/dist/three/index.d.ts +2 -0
- package/dist/three/index.js +2 -0
- package/dist/three/index.js.map +1 -0
- package/package.json +98 -17
- package/src/charts/bar-chart-component.tsx +150 -0
- package/src/charts/chart-tooltip.tsx +86 -0
- package/src/charts/chart.tsx +371 -0
- package/src/charts/donut-chart.tsx +112 -0
- package/src/charts/index.ts +13 -0
- package/src/charts/pipeline-overview.tsx +476 -0
- package/src/charts/sankey-chart.tsx +290 -0
- package/src/charts/top-line-metrics.tsx +261 -0
- package/src/charts/trend-area-chart.tsx +150 -0
- package/src/charts/volume-analysis-chart.tsx +124 -0
- package/src/components/activity-detail.tsx +233 -0
- package/src/components/activity-log.tsx +89 -0
- package/src/components/agent-popover.tsx +373 -0
- package/src/components/agent-widget.tsx +163 -0
- package/src/components/avatar.tsx +109 -0
- package/src/components/badge.tsx +48 -0
- package/src/components/button.tsx +59 -0
- package/src/components/card.tsx +92 -0
- package/src/components/contact-list.tsx +121 -0
- package/src/components/dashboard-cards.tsx +170 -0
- package/src/components/data-table-display.tsx +139 -0
- package/src/components/data-table-filter.tsx +138 -0
- package/src/components/data-table-quick-views.tsx +103 -0
- package/src/components/data-table-toolbar.tsx +56 -0
- package/src/components/data-table.tsx +915 -0
- package/src/components/detail-view.tsx +237 -0
- package/src/components/dialog.tsx +158 -0
- package/src/components/dropdown-menu.tsx +257 -0
- package/src/components/entity-panel.tsx +767 -0
- package/src/components/inbox-row.tsx +132 -0
- package/src/components/inbox-toolbar.tsx +213 -0
- package/src/components/input.tsx +21 -0
- package/src/components/insights-filter-bar.tsx +132 -0
- package/src/components/item-list-display.tsx +278 -0
- package/src/components/item-list-filter.tsx +118 -0
- package/src/components/item-list-toolbar.tsx +97 -0
- package/src/components/item-list.tsx +843 -0
- package/src/components/label.tsx +24 -0
- package/src/components/message.tsx +83 -0
- package/src/components/metric-card.tsx +178 -0
- package/src/components/performance-metrics-table.tsx +442 -0
- package/src/components/preview-list.tsx +62 -0
- package/src/components/progress.tsx +31 -0
- package/src/components/quick-action-chat-area.tsx +156 -0
- package/src/components/quick-action-modal.tsx +331 -0
- package/src/components/quick-action-sidebar-nav.tsx +592 -0
- package/src/components/recommended-actions-section.tsx +258 -0
- package/src/components/report-card.tsx +106 -0
- package/src/components/score-analysis-modal.tsx +172 -0
- package/src/components/score-breakdown.tsx +179 -0
- package/src/components/score-feedback.tsx +288 -0
- package/src/components/score-ring.tsx +87 -0
- package/src/components/scroll-area.tsx +58 -0
- package/src/components/select.tsx +190 -0
- package/src/components/separator.tsx +28 -0
- package/src/components/sheet.tsx +143 -0
- package/src/components/sidebar.tsx +726 -0
- package/src/components/signal-feedback-inline.tsx +591 -0
- package/src/components/simple-data-table.tsx +124 -0
- package/src/components/skeleton.tsx +15 -0
- package/src/components/status-badge.tsx +63 -0
- package/src/components/styled-bar-list.tsx +70 -0
- package/src/components/suggested-actions.tsx +1985 -0
- package/src/components/table.tsx +116 -0
- package/src/components/tabs.tsx +91 -0
- package/src/components/textarea.tsx +18 -0
- package/src/components/timeline-activity.tsx +234 -0
- package/src/components/tooltip.tsx +57 -0
- package/src/components/view-mode-toggle.tsx +39 -0
- package/src/hooks/use-mobile.ts +21 -0
- package/src/index.ts +77 -0
- package/src/lib/icons.ts +18 -0
- package/src/lib/utils.ts +6 -0
- package/src/prototype/index.ts +11 -0
- package/src/prototype/prototype-accounts-view.tsx +112 -0
- package/src/prototype/prototype-admin-view.tsx +67 -0
- package/src/prototype/prototype-config.ts +243 -0
- package/src/prototype/prototype-inbox-view.tsx +810 -0
- package/src/prototype/prototype-insights-view.tsx +379 -0
- package/src/prototype/prototype-shell.tsx +219 -0
- package/src/prototype/prototype-work-queue-view.tsx +30 -0
- package/src/styles/globals.css +299 -0
- package/src/three/agent-orb.tsx +557 -0
- package/src/three/index.ts +5 -0
- package/src/types/r3f.d.ts +8 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Activity, Scale, Heart, MessageSquare, ArrowRight, ChevronDown } from "lucide-react";
|
|
4
|
+
import { format } from "date-fns";
|
|
5
|
+
const getIcon = (type) => {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case "workout":
|
|
8
|
+
return /* @__PURE__ */ jsx(Activity, { size: 16, className: "text-orange-500" });
|
|
9
|
+
case "weighin":
|
|
10
|
+
return /* @__PURE__ */ jsx(Scale, { size: 16, className: "text-blue-500" });
|
|
11
|
+
case "biometric":
|
|
12
|
+
return /* @__PURE__ */ jsx(Heart, { size: 16, className: "text-rose-500" });
|
|
13
|
+
case "checkin":
|
|
14
|
+
return /* @__PURE__ */ jsx(MessageSquare, { size: 16, className: "text-indigo-500" });
|
|
15
|
+
default:
|
|
16
|
+
return /* @__PURE__ */ jsx(Activity, { size: 16, className: "text-gray-500" });
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
function ActivityRow({ item }) {
|
|
20
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 py-3 border-b border-gray-100 last:border-0 hover:bg-gray-50 px-2 -mx-2 rounded-md transition-colors group", children: [
|
|
21
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-gray-50 border border-gray-200 flex items-center justify-center", children: getIcon(item.type) }),
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2", children: [
|
|
23
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm text-gray-900", children: item.title }),
|
|
24
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline text-gray-300", children: "\u2022" }),
|
|
25
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 truncate", children: item.details }),
|
|
26
|
+
item.type === "checkin" && /* @__PURE__ */ jsxs("button", { className: "ml-auto sm:ml-2 text-xs text-indigo-600 hover:text-indigo-800 font-medium flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity", children: [
|
|
27
|
+
"view ",
|
|
28
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 10 })
|
|
29
|
+
] })
|
|
30
|
+
] }),
|
|
31
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right flex-shrink-0", children: [
|
|
32
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: format(new Date(item.date), "MMM d") }),
|
|
33
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-gray-400", children: item.time })
|
|
34
|
+
] })
|
|
35
|
+
] });
|
|
36
|
+
}
|
|
37
|
+
function ActivityLog({ items, title = "Recent Activity", initialLimit = 5 }) {
|
|
38
|
+
const [limit, setLimit] = React.useState(initialLimit);
|
|
39
|
+
const displayedLogs = items.slice(0, limit);
|
|
40
|
+
const hasMore = limit < items.length;
|
|
41
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl border border-gray-200 p-6 shadow-sm", children: [
|
|
42
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-4", children: title }),
|
|
43
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col", children: displayedLogs.map((item) => /* @__PURE__ */ jsx(ActivityRow, { item }, item.id)) }),
|
|
44
|
+
hasMore && /* @__PURE__ */ jsxs(
|
|
45
|
+
"button",
|
|
46
|
+
{
|
|
47
|
+
onClick: () => setLimit((prev) => prev + 5),
|
|
48
|
+
className: "w-full mt-4 py-2 flex items-center justify-center gap-2 text-sm text-gray-500 hover:text-gray-900 hover:bg-gray-50 rounded-md transition-colors border border-dashed border-gray-200",
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: 14 }),
|
|
51
|
+
"Show more"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
ActivityLog,
|
|
59
|
+
ActivityRow
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=activity-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/activity-log.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { Activity, Scale, Heart, MessageSquare, ArrowRight, ChevronDown } from \"lucide-react\"\nimport { format } from \"date-fns\"\n\n\nexport interface ActivityLogItem {\n id: string\n type: \"workout\" | \"weighin\" | \"biometric\" | \"checkin\" | string\n title: string\n details: string\n date: string\n time: string\n}\n\nexport interface ActivityLogProps {\n items: ActivityLogItem[]\n title?: string\n initialLimit?: number\n}\n\nconst getIcon = (type: string) => {\n switch (type) {\n case \"workout\":\n return <Activity size={16} className=\"text-orange-500\" />\n case \"weighin\":\n return <Scale size={16} className=\"text-blue-500\" />\n case \"biometric\":\n return <Heart size={16} className=\"text-rose-500\" />\n case \"checkin\":\n return <MessageSquare size={16} className=\"text-indigo-500\" />\n default:\n return <Activity size={16} className=\"text-gray-500\" />\n }\n}\n\nexport function ActivityRow({ item }: { item: ActivityLogItem }) {\n return (\n <div className=\"flex items-center gap-4 py-3 border-b border-gray-100 last:border-0 hover:bg-gray-50 px-2 -mx-2 rounded-md transition-colors group\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full bg-gray-50 border border-gray-200 flex items-center justify-center\">\n {getIcon(item.type)}\n </div>\n\n <div className=\"flex-1 min-w-0 flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2\">\n <span className=\"font-medium text-sm text-gray-900\">{item.title}</span>\n <span className=\"hidden sm:inline text-gray-300\">•</span>\n <span className=\"text-xs text-gray-500 truncate\">{item.details}</span>\n\n {item.type === \"checkin\" && (\n <button className=\"ml-auto sm:ml-2 text-xs text-indigo-600 hover:text-indigo-800 font-medium flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity\">\n view <ArrowRight size={10} />\n </button>\n )}\n </div>\n\n <div className=\"text-right flex-shrink-0\">\n <div className=\"text-xs text-gray-500\">{format(new Date(item.date), \"MMM d\")}</div>\n <div className=\"text-[10px] text-gray-400\">{item.time}</div>\n </div>\n </div>\n )\n}\n\nexport function ActivityLog({ items, title = \"Recent Activity\", initialLimit = 5 }: ActivityLogProps) {\n const [limit, setLimit] = React.useState(initialLimit)\n const displayedLogs = items.slice(0, limit)\n const hasMore = limit < items.length\n\n return (\n <div className=\"bg-white rounded-xl border border-gray-200 p-6 shadow-sm\">\n <h2 className=\"text-lg font-semibold text-gray-900 mb-4\">{title}</h2>\n\n <div className=\"flex flex-col\">\n {displayedLogs.map((item) => (\n <ActivityRow key={item.id} item={item} />\n ))}\n </div>\n\n {hasMore && (\n <button\n onClick={() => setLimit((prev) => prev + 5)}\n className=\"w-full mt-4 py-2 flex items-center justify-center gap-2 text-sm text-gray-500 hover:text-gray-900 hover:bg-gray-50 rounded-md transition-colors border border-dashed border-gray-200\"\n >\n <ChevronDown size={14} />\n Show more\n </button>\n )}\n </div>\n )\n}\n"],"mappings":"AAuBa,cAyBH,YAzBG;AAvBb,YAAY,WAAW;AACvB,SAAS,UAAU,OAAO,OAAO,eAAe,YAAY,mBAAmB;AAC/E,SAAS,cAAc;AAkBvB,MAAM,UAAU,CAAC,SAAiB;AAChC,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,oBAAC,YAAS,MAAM,IAAI,WAAU,mBAAkB;AAAA,IACzD,KAAK;AACH,aAAO,oBAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB;AAAA,IACpD,KAAK;AACH,aAAO,oBAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB;AAAA,IACpD,KAAK;AACH,aAAO,oBAAC,iBAAc,MAAM,IAAI,WAAU,mBAAkB;AAAA,IAC9D;AACE,aAAO,oBAAC,YAAS,MAAM,IAAI,WAAU,iBAAgB;AAAA,EACzD;AACF;AAEO,SAAS,YAAY,EAAE,KAAK,GAA8B;AAC/D,SACE,qBAAC,SAAI,WAAU,sIACb;AAAA,wBAAC,SAAI,WAAU,yGACZ,kBAAQ,KAAK,IAAI,GACpB;AAAA,IAEA,qBAAC,SAAI,WAAU,2EACb;AAAA,0BAAC,UAAK,WAAU,qCAAqC,eAAK,OAAM;AAAA,MAChE,oBAAC,UAAK,WAAU,kCAAiC,oBAAC;AAAA,MAClD,oBAAC,UAAK,WAAU,kCAAkC,eAAK,SAAQ;AAAA,MAE9D,KAAK,SAAS,aACb,qBAAC,YAAO,WAAU,4JAA2J;AAAA;AAAA,QACtK,oBAAC,cAAW,MAAM,IAAI;AAAA,SAC7B;AAAA,OAEJ;AAAA,IAEA,qBAAC,SAAI,WAAU,4BACb;AAAA,0BAAC,SAAI,WAAU,yBAAyB,iBAAO,IAAI,KAAK,KAAK,IAAI,GAAG,OAAO,GAAE;AAAA,MAC7E,oBAAC,SAAI,WAAU,6BAA6B,eAAK,MAAK;AAAA,OACxD;AAAA,KACF;AAEJ;AAEO,SAAS,YAAY,EAAE,OAAO,QAAQ,mBAAmB,eAAe,EAAE,GAAqB;AACpG,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,YAAY;AACrD,QAAM,gBAAgB,MAAM,MAAM,GAAG,KAAK;AAC1C,QAAM,UAAU,QAAQ,MAAM;AAE9B,SACE,qBAAC,SAAI,WAAU,4DACb;AAAA,wBAAC,QAAG,WAAU,4CAA4C,iBAAM;AAAA,IAEhE,oBAAC,SAAI,WAAU,iBACZ,wBAAc,IAAI,CAAC,SAClB,oBAAC,eAA0B,QAAT,KAAK,EAAgB,CACxC,GACH;AAAA,IAEC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,MAAM,SAAS,CAAC,SAAS,OAAO,CAAC;AAAA,QAC1C,WAAU;AAAA,QAEV;AAAA,8BAAC,eAAY,MAAM,IAAI;AAAA,UAAE;AAAA;AAAA;AAAA,IAE3B;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { AgentWidgetMessage, AgentWidgetStatus, AgentWidgetMode } from './agent-widget.js';
|
|
3
|
+
|
|
4
|
+
type AgentPopoverStep = string;
|
|
5
|
+
interface AgentPopoverContextValue {
|
|
6
|
+
step: AgentPopoverStep;
|
|
7
|
+
setStep: (step: AgentPopoverStep) => void;
|
|
8
|
+
}
|
|
9
|
+
declare function useAgentPopover(): AgentPopoverContextValue;
|
|
10
|
+
interface AgentPopoverProps {
|
|
11
|
+
open: boolean;
|
|
12
|
+
onOpenChange: (open: boolean) => void;
|
|
13
|
+
defaultStep?: string;
|
|
14
|
+
step?: string;
|
|
15
|
+
onStepChange?: (step: string) => void;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
declare function AgentPopover({ open, onOpenChange, defaultStep, step: controlledStep, onStepChange, children, className, }: AgentPopoverProps): React.JSX.Element | null;
|
|
20
|
+
type ConnectionStatus = "ready" | "connected" | "listening" | "speaking";
|
|
21
|
+
interface AgentPopoverBrandingProps {
|
|
22
|
+
title?: string;
|
|
23
|
+
subtitle?: string;
|
|
24
|
+
badge?: string;
|
|
25
|
+
visualSlot?: React.ReactNode;
|
|
26
|
+
statusIndicator?: ConnectionStatus;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
declare function AgentPopoverBranding({ title, subtitle, badge, visualSlot, statusIndicator, className, }: AgentPopoverBrandingProps): React.JSX.Element;
|
|
30
|
+
interface AgentPopoverStepContentProps {
|
|
31
|
+
step: string;
|
|
32
|
+
children: React.ReactNode;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
declare function AgentPopoverStepContent({ step, children, className }: AgentPopoverStepContentProps): React.JSX.Element | null;
|
|
36
|
+
interface AgentPopoverFormField {
|
|
37
|
+
name: string;
|
|
38
|
+
label: string;
|
|
39
|
+
type?: "text" | "email" | "tel" | "textarea";
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
required?: boolean;
|
|
42
|
+
}
|
|
43
|
+
interface AgentPopoverFormProps {
|
|
44
|
+
fields?: AgentPopoverFormField[];
|
|
45
|
+
submitLabel?: string;
|
|
46
|
+
onSubmit?: (values: Record<string, string>) => void;
|
|
47
|
+
className?: string;
|
|
48
|
+
children?: React.ReactNode;
|
|
49
|
+
}
|
|
50
|
+
declare function AgentPopoverForm({ fields, submitLabel, onSubmit, className, children, }: AgentPopoverFormProps): React.JSX.Element;
|
|
51
|
+
interface AgentPopoverOverviewProps {
|
|
52
|
+
userSummary?: Record<string, string>;
|
|
53
|
+
discussionPoints?: string[];
|
|
54
|
+
actions?: React.ReactNode;
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
declare function AgentPopoverOverview({ userSummary, discussionPoints, actions, className, }: AgentPopoverOverviewProps): React.JSX.Element;
|
|
58
|
+
interface AgentPopoverChatProps {
|
|
59
|
+
messages?: AgentWidgetMessage[];
|
|
60
|
+
onSendMessage?: (text: string) => void;
|
|
61
|
+
onEndSession?: () => void;
|
|
62
|
+
inputMode?: "voice" | "text" | "voice+text";
|
|
63
|
+
visualSlot?: React.ReactNode;
|
|
64
|
+
assistantAvatarSlot?: React.ReactNode;
|
|
65
|
+
status?: AgentWidgetStatus;
|
|
66
|
+
mode?: AgentWidgetMode;
|
|
67
|
+
className?: string;
|
|
68
|
+
}
|
|
69
|
+
declare function AgentPopoverChat({ messages, onSendMessage, onEndSession, inputMode, visualSlot, assistantAvatarSlot, status, mode, className, }: AgentPopoverChatProps): React.JSX.Element;
|
|
70
|
+
|
|
71
|
+
export { AgentPopover, AgentPopoverBranding, type AgentPopoverBrandingProps, AgentPopoverChat, type AgentPopoverChatProps, type AgentPopoverContextValue, AgentPopoverForm, type AgentPopoverFormField, type AgentPopoverFormProps, AgentPopoverOverview, type AgentPopoverOverviewProps, type AgentPopoverProps, type AgentPopoverStep, AgentPopoverStepContent, type AgentPopoverStepContentProps, type ConnectionStatus, useAgentPopover };
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defProps = Object.defineProperties;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __spreadValues = (a, b) => {
|
|
12
|
+
for (var prop in b || (b = {}))
|
|
13
|
+
if (__hasOwnProp.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
if (__getOwnPropSymbols)
|
|
16
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
+
if (__propIsEnum.call(b, prop))
|
|
18
|
+
__defNormalProp(a, prop, b[prop]);
|
|
19
|
+
}
|
|
20
|
+
return a;
|
|
21
|
+
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
24
|
+
import * as React from "react";
|
|
25
|
+
import { X } from "lucide-react";
|
|
26
|
+
import { cn } from "../lib/utils.js";
|
|
27
|
+
import { AgentWidget } from "./agent-widget.js";
|
|
28
|
+
const AgentPopoverContext = React.createContext(null);
|
|
29
|
+
function useAgentPopover() {
|
|
30
|
+
const ctx = React.useContext(AgentPopoverContext);
|
|
31
|
+
if (!ctx) throw new Error("useAgentPopover must be used within <AgentPopover>");
|
|
32
|
+
return ctx;
|
|
33
|
+
}
|
|
34
|
+
function AgentPopover({
|
|
35
|
+
open,
|
|
36
|
+
onOpenChange,
|
|
37
|
+
defaultStep = "details",
|
|
38
|
+
step: controlledStep,
|
|
39
|
+
onStepChange,
|
|
40
|
+
children,
|
|
41
|
+
className
|
|
42
|
+
}) {
|
|
43
|
+
const [uncontrolledStep, setUncontrolledStep] = React.useState(defaultStep);
|
|
44
|
+
const step = controlledStep != null ? controlledStep : uncontrolledStep;
|
|
45
|
+
const setStep = React.useCallback(
|
|
46
|
+
(s) => {
|
|
47
|
+
if (controlledStep === void 0) setUncontrolledStep(s);
|
|
48
|
+
onStepChange == null ? void 0 : onStepChange(s);
|
|
49
|
+
},
|
|
50
|
+
[controlledStep, onStepChange]
|
|
51
|
+
);
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
if (!open) return;
|
|
54
|
+
const onKeyDown = (e) => {
|
|
55
|
+
if (e.key === "Escape") onOpenChange(false);
|
|
56
|
+
};
|
|
57
|
+
document.addEventListener("keydown", onKeyDown);
|
|
58
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
59
|
+
}, [open, onOpenChange]);
|
|
60
|
+
if (!open) return null;
|
|
61
|
+
return /* @__PURE__ */ jsxs(AgentPopoverContext.Provider, { value: { step, setStep }, children: [
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
className: "fixed inset-0 z-50 bg-black/30 backdrop-blur-sm animate-in fade-in duration-200",
|
|
66
|
+
onClick: () => onOpenChange(false)
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ jsxs(
|
|
70
|
+
"div",
|
|
71
|
+
{
|
|
72
|
+
role: "dialog",
|
|
73
|
+
"aria-modal": "true",
|
|
74
|
+
className: cn(
|
|
75
|
+
"fixed inset-4 z-50 flex overflow-hidden rounded-3xl bg-background shadow-2xl ring-1 ring-border/50 animate-in zoom-in-95 fade-in duration-300",
|
|
76
|
+
"md:inset-auto md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2 md:max-w-5xl md:w-[92vw] md:h-[85vh]",
|
|
77
|
+
className
|
|
78
|
+
),
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsx(
|
|
81
|
+
"button",
|
|
82
|
+
{
|
|
83
|
+
type: "button",
|
|
84
|
+
onClick: () => onOpenChange(false),
|
|
85
|
+
className: "absolute right-4 top-4 z-20 p-2 rounded-full bg-background/80 hover:bg-muted transition-colors text-foreground",
|
|
86
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
children
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
] });
|
|
94
|
+
}
|
|
95
|
+
function AgentPopoverBranding({
|
|
96
|
+
title,
|
|
97
|
+
subtitle,
|
|
98
|
+
badge,
|
|
99
|
+
visualSlot,
|
|
100
|
+
statusIndicator = "ready",
|
|
101
|
+
className
|
|
102
|
+
}) {
|
|
103
|
+
return /* @__PURE__ */ jsxs(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: cn(
|
|
107
|
+
"relative hidden w-[40%] shrink-0 flex-col items-center justify-center p-8 md:flex",
|
|
108
|
+
"bg-gradient-to-br from-primary/5 via-background to-primary/10",
|
|
109
|
+
className
|
|
110
|
+
),
|
|
111
|
+
children: [
|
|
112
|
+
/* @__PURE__ */ jsx(
|
|
113
|
+
"div",
|
|
114
|
+
{
|
|
115
|
+
className: "absolute inset-0 pointer-events-none opacity-[0.06]",
|
|
116
|
+
style: {
|
|
117
|
+
backgroundImage: "radial-gradient(circle, var(--primary) 1px, transparent 1px)",
|
|
118
|
+
backgroundSize: "24px 24px"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
),
|
|
122
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-10 flex flex-col items-center gap-6 text-center", children: [
|
|
123
|
+
visualSlot && /* @__PURE__ */ jsx("div", { className: "w-[200px] h-[200px] flex items-center justify-center", children: visualSlot }),
|
|
124
|
+
badge && /* @__PURE__ */ jsx("span", { className: "inline-flex px-3 py-1 rounded-full bg-primary/10 text-primary text-xs font-medium border border-primary/10", children: badge }),
|
|
125
|
+
title && /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children: title }),
|
|
126
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-[240px]", children: subtitle }),
|
|
127
|
+
/* @__PURE__ */ jsx(StatusPill, { status: statusIndicator })
|
|
128
|
+
] })
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
function StatusPill({ status }) {
|
|
134
|
+
const label = {
|
|
135
|
+
ready: "Ready to connect",
|
|
136
|
+
connected: "Connected",
|
|
137
|
+
listening: "Listening...",
|
|
138
|
+
speaking: "Speaking..."
|
|
139
|
+
};
|
|
140
|
+
const dotColor = {
|
|
141
|
+
ready: "bg-muted-foreground",
|
|
142
|
+
connected: "bg-green-500",
|
|
143
|
+
listening: "bg-green-500 animate-pulse",
|
|
144
|
+
speaking: "bg-primary animate-pulse"
|
|
145
|
+
};
|
|
146
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-full border border-border px-3 py-1.5 bg-background/50", children: [
|
|
147
|
+
/* @__PURE__ */ jsx("div", { className: cn("h-2 w-2 rounded-full", dotColor[status]) }),
|
|
148
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: label[status] })
|
|
149
|
+
] });
|
|
150
|
+
}
|
|
151
|
+
function AgentPopoverStepContent({ step, children, className }) {
|
|
152
|
+
const { step: currentStep } = useAgentPopover();
|
|
153
|
+
if (currentStep !== step) return null;
|
|
154
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex-1 flex flex-col overflow-hidden", className), children });
|
|
155
|
+
}
|
|
156
|
+
function AgentPopoverForm({
|
|
157
|
+
fields = [],
|
|
158
|
+
submitLabel = "Continue",
|
|
159
|
+
onSubmit,
|
|
160
|
+
className,
|
|
161
|
+
children
|
|
162
|
+
}) {
|
|
163
|
+
const [values, setValues] = React.useState({});
|
|
164
|
+
const handleSubmit = (e) => {
|
|
165
|
+
e.preventDefault();
|
|
166
|
+
onSubmit == null ? void 0 : onSubmit(values);
|
|
167
|
+
};
|
|
168
|
+
return /* @__PURE__ */ jsxs(
|
|
169
|
+
"form",
|
|
170
|
+
{
|
|
171
|
+
onSubmit: handleSubmit,
|
|
172
|
+
className: cn("flex flex-col h-full p-8 overflow-y-auto", className),
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-4", children: [
|
|
175
|
+
fields.map(
|
|
176
|
+
(field) => {
|
|
177
|
+
var _a, _b, _c;
|
|
178
|
+
return field.type === "textarea" ? /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", children: [
|
|
179
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-foreground", children: [
|
|
180
|
+
field.label,
|
|
181
|
+
field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
182
|
+
] }),
|
|
183
|
+
/* @__PURE__ */ jsx(
|
|
184
|
+
"textarea",
|
|
185
|
+
{
|
|
186
|
+
className: "w-full rounded-xl border border-border bg-background px-4 py-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary min-h-[80px] resize-none",
|
|
187
|
+
placeholder: field.placeholder,
|
|
188
|
+
required: field.required,
|
|
189
|
+
value: (_a = values[field.name]) != null ? _a : "",
|
|
190
|
+
onChange: (e) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [field.name]: e.target.value }))
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
] }, field.name) : /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", children: [
|
|
194
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-foreground", children: [
|
|
195
|
+
field.label,
|
|
196
|
+
field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
197
|
+
] }),
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
"input",
|
|
200
|
+
{
|
|
201
|
+
type: (_b = field.type) != null ? _b : "text",
|
|
202
|
+
className: "w-full rounded-xl border border-border bg-background px-4 py-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
203
|
+
placeholder: field.placeholder,
|
|
204
|
+
required: field.required,
|
|
205
|
+
value: (_c = values[field.name]) != null ? _c : "",
|
|
206
|
+
onChange: (e) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [field.name]: e.target.value }))
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
] }, field.name);
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
children
|
|
213
|
+
] }),
|
|
214
|
+
/* @__PURE__ */ jsx(
|
|
215
|
+
"button",
|
|
216
|
+
{
|
|
217
|
+
type: "submit",
|
|
218
|
+
className: "mt-6 w-full px-6 py-3 rounded-full bg-primary text-primary-foreground hover:bg-primary/90 font-medium transition-colors",
|
|
219
|
+
children: submitLabel
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
function AgentPopoverOverview({
|
|
227
|
+
userSummary,
|
|
228
|
+
discussionPoints,
|
|
229
|
+
actions,
|
|
230
|
+
className
|
|
231
|
+
}) {
|
|
232
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full p-8 overflow-y-auto", className), children: [
|
|
233
|
+
userSummary && Object.keys(userSummary).length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-6 rounded-xl bg-muted/50 p-4 space-y-2", children: Object.entries(userSummary).map(([key, val]) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
234
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground capitalize", children: key }),
|
|
235
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground font-medium", children: val })
|
|
236
|
+
] }, key)) }),
|
|
237
|
+
discussionPoints && discussionPoints.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
238
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground mb-3", children: "Discussion Points" }),
|
|
239
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-2", children: discussionPoints.map((point, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-sm text-foreground", children: [
|
|
240
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1.5 w-1.5 h-1.5 rounded-full bg-primary shrink-0" }),
|
|
241
|
+
point
|
|
242
|
+
] }, i)) })
|
|
243
|
+
] }),
|
|
244
|
+
actions && /* @__PURE__ */ jsx("div", { className: "mt-auto pt-6", children: actions })
|
|
245
|
+
] });
|
|
246
|
+
}
|
|
247
|
+
function AgentPopoverChat({
|
|
248
|
+
messages = [],
|
|
249
|
+
onSendMessage,
|
|
250
|
+
onEndSession,
|
|
251
|
+
inputMode = "voice+text",
|
|
252
|
+
visualSlot,
|
|
253
|
+
assistantAvatarSlot,
|
|
254
|
+
status = "connected",
|
|
255
|
+
mode = null,
|
|
256
|
+
className
|
|
257
|
+
}) {
|
|
258
|
+
return /* @__PURE__ */ jsx(
|
|
259
|
+
AgentWidget,
|
|
260
|
+
{
|
|
261
|
+
messages,
|
|
262
|
+
onSendMessage,
|
|
263
|
+
onEndSession,
|
|
264
|
+
inputMode,
|
|
265
|
+
visualSlot,
|
|
266
|
+
assistantAvatarSlot,
|
|
267
|
+
status,
|
|
268
|
+
mode,
|
|
269
|
+
className: cn("h-full", className)
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
export {
|
|
274
|
+
AgentPopover,
|
|
275
|
+
AgentPopoverBranding,
|
|
276
|
+
AgentPopoverChat,
|
|
277
|
+
AgentPopoverForm,
|
|
278
|
+
AgentPopoverOverview,
|
|
279
|
+
AgentPopoverStepContent,
|
|
280
|
+
useAgentPopover
|
|
281
|
+
};
|
|
282
|
+
//# sourceMappingURL=agent-popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/agent-popover.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { X } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\nimport { AgentWidget, type AgentWidgetMessage, type AgentWidgetStatus, type AgentWidgetMode } from \"./agent-widget\"\n\n/* ========================================\n AgentPopover (root)\n ======================================== */\n\nexport type AgentPopoverStep = string\n\nexport interface AgentPopoverContextValue {\n step: AgentPopoverStep\n setStep: (step: AgentPopoverStep) => void\n}\n\nconst AgentPopoverContext = React.createContext<AgentPopoverContextValue | null>(null)\n\nexport function useAgentPopover() {\n const ctx = React.useContext(AgentPopoverContext)\n if (!ctx) throw new Error(\"useAgentPopover must be used within <AgentPopover>\")\n return ctx\n}\n\nexport interface AgentPopoverProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n defaultStep?: string\n step?: string\n onStepChange?: (step: string) => void\n children: React.ReactNode\n className?: string\n}\n\nexport function AgentPopover({\n open,\n onOpenChange,\n defaultStep = \"details\",\n step: controlledStep,\n onStepChange,\n children,\n className,\n}: AgentPopoverProps) {\n const [uncontrolledStep, setUncontrolledStep] = React.useState(defaultStep)\n const step = controlledStep ?? uncontrolledStep\n const setStep = React.useCallback(\n (s: string) => {\n if (controlledStep === undefined) setUncontrolledStep(s)\n onStepChange?.(s)\n },\n [controlledStep, onStepChange],\n )\n\n React.useEffect(() => {\n if (!open) return\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onOpenChange(false)\n }\n document.addEventListener(\"keydown\", onKeyDown)\n return () => document.removeEventListener(\"keydown\", onKeyDown)\n }, [open, onOpenChange])\n\n if (!open) return null\n\n return (\n <AgentPopoverContext.Provider value={{ step, setStep }}>\n {/* Backdrop */}\n <div\n className=\"fixed inset-0 z-50 bg-black/30 backdrop-blur-sm animate-in fade-in duration-200\"\n onClick={() => onOpenChange(false)}\n />\n {/* Panel */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n className={cn(\n \"fixed inset-4 z-50 flex overflow-hidden rounded-3xl bg-background shadow-2xl ring-1 ring-border/50 animate-in zoom-in-95 fade-in duration-300\",\n \"md:inset-auto md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2 md:max-w-5xl md:w-[92vw] md:h-[85vh]\",\n className,\n )}\n >\n {/* Close button */}\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"absolute right-4 top-4 z-20 p-2 rounded-full bg-background/80 hover:bg-muted transition-colors text-foreground\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n\n {children}\n </div>\n </AgentPopoverContext.Provider>\n )\n}\n\n/* ========================================\n AgentPopoverBranding (left panel)\n ======================================== */\n\nexport type ConnectionStatus = \"ready\" | \"connected\" | \"listening\" | \"speaking\"\n\nexport interface AgentPopoverBrandingProps {\n title?: string\n subtitle?: string\n badge?: string\n visualSlot?: React.ReactNode\n statusIndicator?: ConnectionStatus\n className?: string\n}\n\nexport function AgentPopoverBranding({\n title,\n subtitle,\n badge,\n visualSlot,\n statusIndicator = \"ready\",\n className,\n}: AgentPopoverBrandingProps) {\n return (\n <div\n className={cn(\n \"relative hidden w-[40%] shrink-0 flex-col items-center justify-center p-8 md:flex\",\n \"bg-gradient-to-br from-primary/5 via-background to-primary/10\",\n className,\n )}\n >\n {/* Dot pattern overlay */}\n <div\n className=\"absolute inset-0 pointer-events-none opacity-[0.06]\"\n style={{\n backgroundImage: \"radial-gradient(circle, var(--primary) 1px, transparent 1px)\",\n backgroundSize: \"24px 24px\",\n }}\n />\n\n <div className=\"relative z-10 flex flex-col items-center gap-6 text-center\">\n {visualSlot && (\n <div className=\"w-[200px] h-[200px] flex items-center justify-center\">\n {visualSlot}\n </div>\n )}\n\n {badge && (\n <span className=\"inline-flex px-3 py-1 rounded-full bg-primary/10 text-primary text-xs font-medium border border-primary/10\">\n {badge}\n </span>\n )}\n\n {title && <h2 className=\"text-xl font-semibold text-foreground\">{title}</h2>}\n {subtitle && <p className=\"text-sm text-muted-foreground max-w-[240px]\">{subtitle}</p>}\n\n <StatusPill status={statusIndicator} />\n </div>\n </div>\n )\n}\n\nfunction StatusPill({ status }: { status: ConnectionStatus }) {\n const label: Record<ConnectionStatus, string> = {\n ready: \"Ready to connect\",\n connected: \"Connected\",\n listening: \"Listening...\",\n speaking: \"Speaking...\",\n }\n\n const dotColor: Record<ConnectionStatus, string> = {\n ready: \"bg-muted-foreground\",\n connected: \"bg-green-500\",\n listening: \"bg-green-500 animate-pulse\",\n speaking: \"bg-primary animate-pulse\",\n }\n\n return (\n <div className=\"flex items-center gap-2 rounded-full border border-border px-3 py-1.5 bg-background/50\">\n <div className={cn(\"h-2 w-2 rounded-full\", dotColor[status])} />\n <span className=\"text-xs text-muted-foreground\">{label[status]}</span>\n </div>\n )\n}\n\n/* ========================================\n AgentPopoverStepContent (right panel step)\n ======================================== */\n\nexport interface AgentPopoverStepContentProps {\n step: string\n children: React.ReactNode\n className?: string\n}\n\nexport function AgentPopoverStepContent({ step, children, className }: AgentPopoverStepContentProps) {\n const { step: currentStep } = useAgentPopover()\n if (currentStep !== step) return null\n return <div className={cn(\"flex-1 flex flex-col overflow-hidden\", className)}>{children}</div>\n}\n\n/* ========================================\n AgentPopoverForm (details step)\n ======================================== */\n\nexport interface AgentPopoverFormField {\n name: string\n label: string\n type?: \"text\" | \"email\" | \"tel\" | \"textarea\"\n placeholder?: string\n required?: boolean\n}\n\nexport interface AgentPopoverFormProps {\n fields?: AgentPopoverFormField[]\n submitLabel?: string\n onSubmit?: (values: Record<string, string>) => void\n className?: string\n children?: React.ReactNode\n}\n\nexport function AgentPopoverForm({\n fields = [],\n submitLabel = \"Continue\",\n onSubmit,\n className,\n children,\n}: AgentPopoverFormProps) {\n const [values, setValues] = React.useState<Record<string, string>>({})\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault()\n onSubmit?.(values)\n }\n\n return (\n <form\n onSubmit={handleSubmit}\n className={cn(\"flex flex-col h-full p-8 overflow-y-auto\", className)}\n >\n <div className=\"flex-1 space-y-4\">\n {fields.map((field) =>\n field.type === \"textarea\" ? (\n <label key={field.name} className=\"block space-y-1.5\">\n <span className=\"text-sm font-medium text-foreground\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </span>\n <textarea\n className=\"w-full rounded-xl border border-border bg-background px-4 py-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary min-h-[80px] resize-none\"\n placeholder={field.placeholder}\n required={field.required}\n value={values[field.name] ?? \"\"}\n onChange={(e) => setValues((prev) => ({ ...prev, [field.name]: e.target.value }))}\n />\n </label>\n ) : (\n <label key={field.name} className=\"block space-y-1.5\">\n <span className=\"text-sm font-medium text-foreground\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </span>\n <input\n type={field.type ?? \"text\"}\n className=\"w-full rounded-xl border border-border bg-background px-4 py-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder={field.placeholder}\n required={field.required}\n value={values[field.name] ?? \"\"}\n onChange={(e) => setValues((prev) => ({ ...prev, [field.name]: e.target.value }))}\n />\n </label>\n ),\n )}\n {children}\n </div>\n <button\n type=\"submit\"\n className=\"mt-6 w-full px-6 py-3 rounded-full bg-primary text-primary-foreground hover:bg-primary/90 font-medium transition-colors\"\n >\n {submitLabel}\n </button>\n </form>\n )\n}\n\n/* ========================================\n AgentPopoverOverview\n ======================================== */\n\nexport interface AgentPopoverOverviewProps {\n userSummary?: Record<string, string>\n discussionPoints?: string[]\n actions?: React.ReactNode\n className?: string\n}\n\nexport function AgentPopoverOverview({\n userSummary,\n discussionPoints,\n actions,\n className,\n}: AgentPopoverOverviewProps) {\n return (\n <div className={cn(\"flex flex-col h-full p-8 overflow-y-auto\", className)}>\n {userSummary && Object.keys(userSummary).length > 0 && (\n <div className=\"mb-6 rounded-xl bg-muted/50 p-4 space-y-2\">\n {Object.entries(userSummary).map(([key, val]) => (\n <div key={key} className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground capitalize\">{key}</span>\n <span className=\"text-foreground font-medium\">{val}</span>\n </div>\n ))}\n </div>\n )}\n\n {discussionPoints && discussionPoints.length > 0 && (\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-semibold text-foreground mb-3\">Discussion Points</h3>\n <ul className=\"space-y-2\">\n {discussionPoints.map((point, i) => (\n <li key={i} className=\"flex items-start gap-2 text-sm text-foreground\">\n <div className=\"mt-1.5 w-1.5 h-1.5 rounded-full bg-primary shrink-0\" />\n {point}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {actions && <div className=\"mt-auto pt-6\">{actions}</div>}\n </div>\n )\n}\n\n/* ========================================\n AgentPopoverChat (interview step)\n ======================================== */\n\nexport interface AgentPopoverChatProps {\n messages?: AgentWidgetMessage[]\n onSendMessage?: (text: string) => void\n onEndSession?: () => void\n inputMode?: \"voice\" | \"text\" | \"voice+text\"\n visualSlot?: React.ReactNode\n assistantAvatarSlot?: React.ReactNode\n status?: AgentWidgetStatus\n mode?: AgentWidgetMode\n className?: string\n}\n\nexport function AgentPopoverChat({\n messages = [],\n onSendMessage,\n onEndSession,\n inputMode = \"voice+text\",\n visualSlot,\n assistantAvatarSlot,\n status = \"connected\",\n mode = null,\n className,\n}: AgentPopoverChatProps) {\n return (\n <AgentWidget\n messages={messages}\n onSendMessage={onSendMessage}\n onEndSession={onEndSession}\n inputMode={inputMode}\n visualSlot={visualSlot}\n assistantAvatarSlot={assistantAvatarSlot}\n status={status}\n mode={mode}\n className={cn(\"h-full\", className)}\n />\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type AgentWidgetStatus = "idle" | "connecting" | "connected" | "error";
|
|
4
|
+
type AgentWidgetMode = "listening" | "speaking" | null;
|
|
5
|
+
interface AgentWidgetMessage {
|
|
6
|
+
from: "user" | "assistant";
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
interface AgentWidgetProps {
|
|
10
|
+
status?: AgentWidgetStatus;
|
|
11
|
+
mode?: AgentWidgetMode;
|
|
12
|
+
messages?: AgentWidgetMessage[];
|
|
13
|
+
onSendMessage?: (text: string) => void;
|
|
14
|
+
onEndSession?: () => void;
|
|
15
|
+
inputMode?: "voice" | "text" | "voice+text";
|
|
16
|
+
visualSlot?: React.ReactNode;
|
|
17
|
+
assistantAvatarSlot?: React.ReactNode;
|
|
18
|
+
header?: React.ReactNode;
|
|
19
|
+
footer?: React.ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
declare function AgentWidget({ status, mode, messages, onSendMessage, onEndSession, inputMode, visualSlot, assistantAvatarSlot, header, footer, className, }: AgentWidgetProps): React.JSX.Element;
|
|
23
|
+
|
|
24
|
+
export { AgentWidget, type AgentWidgetMessage, type AgentWidgetMode, type AgentWidgetProps, type AgentWidgetStatus };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { Mic, PhoneOff, Send, Sparkles } from "lucide-react";
|
|
7
|
+
import { cn } from "../lib/utils.js";
|
|
8
|
+
import { Message, MessageContent, MessageAvatar } from "./message.js";
|
|
9
|
+
function AgentWidget({
|
|
10
|
+
status = "idle",
|
|
11
|
+
mode = null,
|
|
12
|
+
messages = [],
|
|
13
|
+
onSendMessage,
|
|
14
|
+
onEndSession,
|
|
15
|
+
inputMode = "voice+text",
|
|
16
|
+
visualSlot,
|
|
17
|
+
assistantAvatarSlot,
|
|
18
|
+
header,
|
|
19
|
+
footer,
|
|
20
|
+
className
|
|
21
|
+
}) {
|
|
22
|
+
const [textInput, setTextInput] = React.useState("");
|
|
23
|
+
const messagesEndRef = React.useRef(null);
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
var _a;
|
|
26
|
+
(_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
|
|
27
|
+
}, [messages]);
|
|
28
|
+
const handleSend = () => {
|
|
29
|
+
if (!textInput.trim()) return;
|
|
30
|
+
onSendMessage == null ? void 0 : onSendMessage(textInput);
|
|
31
|
+
setTextInput("");
|
|
32
|
+
};
|
|
33
|
+
const showTextInput = inputMode === "text" || inputMode === "voice+text";
|
|
34
|
+
const isConnected = status === "connected";
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full overflow-hidden", className), children: [
|
|
36
|
+
header,
|
|
37
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-muted/20", children: messages.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full text-muted-foreground space-y-2 opacity-50", children: [
|
|
38
|
+
visualSlot != null ? visualSlot : /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(Sparkles, { className: "w-5 h-5" }) }),
|
|
39
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: status === "connecting" ? "Connecting..." : "Conversation started..." })
|
|
40
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
messages.map((msg, idx) => /* @__PURE__ */ jsxs(Message, { from: msg.from, children: [
|
|
42
|
+
msg.from === "assistant" && assistantAvatarSlot ? /* @__PURE__ */ jsx(MessageAvatar, { children: assistantAvatarSlot }) : null,
|
|
43
|
+
/* @__PURE__ */ jsx(MessageContent, { children: msg.text.replace(/^["']|["']$/g, "") })
|
|
44
|
+
] }, idx)),
|
|
45
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
46
|
+
] }) }),
|
|
47
|
+
inputMode !== "text" && isConnected && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-2 bg-background", children: mode === "listening" ? /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 px-4 py-2 bg-primary/5 rounded-full border border-primary/10", children: [
|
|
48
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }),
|
|
49
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Listening" })
|
|
50
|
+
] }) : mode === "speaking" ? /* @__PURE__ */ jsxs(
|
|
51
|
+
"button",
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
className: "inline-flex items-center gap-2 px-4 py-2 bg-background rounded-full border border-border hover:border-primary transition-colors",
|
|
55
|
+
children: [
|
|
56
|
+
/* @__PURE__ */ jsx(Mic, { className: "w-4 h-4 text-primary" }),
|
|
57
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Talk to interrupt" })
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
) : null }),
|
|
61
|
+
/* @__PURE__ */ jsx("div", { className: "flex-none p-4 bg-background border-t border-border", children: showTextInput ? /* @__PURE__ */ jsxs("div", { className: "relative border-2 border-foreground rounded-2xl p-4 bg-background shadow-sm transition-all focus-within:shadow-md", children: [
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
"textarea",
|
|
64
|
+
{
|
|
65
|
+
className: "w-full resize-none border-none focus:ring-0 p-0 text-sm placeholder:text-muted-foreground min-h-[60px] bg-transparent outline-none focus:outline-none pr-24",
|
|
66
|
+
placeholder: "Send a message...",
|
|
67
|
+
value: textInput,
|
|
68
|
+
onChange: (e) => setTextInput(e.target.value),
|
|
69
|
+
onKeyDown: (e) => {
|
|
70
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
handleSend();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-4 right-4 flex items-center gap-3", children: [
|
|
78
|
+
onEndSession && /* @__PURE__ */ jsx(
|
|
79
|
+
"button",
|
|
80
|
+
{
|
|
81
|
+
type: "button",
|
|
82
|
+
onClick: onEndSession,
|
|
83
|
+
className: "w-10 h-10 flex items-center justify-center rounded-full bg-background border border-border shadow-sm hover:bg-muted transition-colors group",
|
|
84
|
+
title: "End session",
|
|
85
|
+
children: /* @__PURE__ */ jsx(PhoneOff, { className: "w-5 h-5 text-foreground group-hover:text-destructive transition-colors" })
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
/* @__PURE__ */ jsx(
|
|
89
|
+
"button",
|
|
90
|
+
{
|
|
91
|
+
type: "button",
|
|
92
|
+
onClick: handleSend,
|
|
93
|
+
disabled: !textInput.trim(),
|
|
94
|
+
className: "w-10 h-10 flex items-center justify-center rounded-full bg-muted-foreground hover:bg-foreground disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-background shadow-sm",
|
|
95
|
+
children: /* @__PURE__ */ jsx(Send, { className: "w-5 h-5 ml-0.5" })
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
] })
|
|
99
|
+
] }) : onEndSession ? /* @__PURE__ */ jsxs(
|
|
100
|
+
"button",
|
|
101
|
+
{
|
|
102
|
+
type: "button",
|
|
103
|
+
onClick: onEndSession,
|
|
104
|
+
className: "flex items-center justify-center gap-2 w-full px-6 py-3 bg-destructive/5 hover:bg-destructive/10 text-destructive border border-destructive/20 rounded-full font-medium transition-all",
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ jsx("span", { className: "w-2 h-2 bg-destructive rounded-full" }),
|
|
107
|
+
"End Session"
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
) : null }),
|
|
111
|
+
footer
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
AgentWidget
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=agent-widget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/agent-widget.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { Mic, PhoneOff, Send, Sparkles } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\nimport { Message, MessageContent, MessageAvatar } from \"./message\"\n\nexport type AgentWidgetStatus = \"idle\" | \"connecting\" | \"connected\" | \"error\"\nexport type AgentWidgetMode = \"listening\" | \"speaking\" | null\n\nexport interface AgentWidgetMessage {\n from: \"user\" | \"assistant\"\n text: string\n}\n\nexport interface AgentWidgetProps {\n status?: AgentWidgetStatus\n mode?: AgentWidgetMode\n messages?: AgentWidgetMessage[]\n onSendMessage?: (text: string) => void\n onEndSession?: () => void\n inputMode?: \"voice\" | \"text\" | \"voice+text\"\n visualSlot?: React.ReactNode\n assistantAvatarSlot?: React.ReactNode\n header?: React.ReactNode\n footer?: React.ReactNode\n className?: string\n}\n\nexport function AgentWidget({\n status = \"idle\",\n mode = null,\n messages = [],\n onSendMessage,\n onEndSession,\n inputMode = \"voice+text\",\n visualSlot,\n assistantAvatarSlot,\n header,\n footer,\n className,\n}: AgentWidgetProps) {\n const [textInput, setTextInput] = React.useState(\"\")\n const messagesEndRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }, [messages])\n\n const handleSend = () => {\n if (!textInput.trim()) return\n onSendMessage?.(textInput)\n setTextInput(\"\")\n }\n\n const showTextInput = inputMode === \"text\" || inputMode === \"voice+text\"\n const isConnected = status === \"connected\"\n\n return (\n <div className={cn(\"flex flex-col h-full overflow-hidden\", className)}>\n {header}\n\n {/* Chat area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4 bg-muted/20\">\n {messages.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full text-muted-foreground space-y-2 opacity-50\">\n {visualSlot ?? (\n <div className=\"w-12 h-12 rounded-full bg-muted flex items-center justify-center\">\n <Sparkles className=\"w-5 h-5\" />\n </div>\n )}\n <p className=\"text-sm\">\n {status === \"connecting\" ? \"Connecting...\" : \"Conversation started...\"}\n </p>\n </div>\n ) : (\n <>\n {messages.map((msg, idx) => (\n <Message key={idx} from={msg.from}>\n {msg.from === \"assistant\" && assistantAvatarSlot ? (\n <MessageAvatar>{assistantAvatarSlot}</MessageAvatar>\n ) : null}\n <MessageContent>{msg.text.replace(/^[\"']|[\"']$/g, \"\")}</MessageContent>\n </Message>\n ))}\n <div ref={messagesEndRef} />\n </>\n )}\n </div>\n\n {/* Voice status indicator */}\n {inputMode !== \"text\" && isConnected && (\n <div className=\"flex justify-center py-2 bg-background\">\n {mode === \"listening\" ? (\n <div className=\"inline-flex items-center gap-2 px-4 py-2 bg-primary/5 rounded-full border border-primary/10\">\n <div className=\"w-2 h-2 bg-green-500 rounded-full animate-pulse\" />\n <span className=\"text-sm font-medium text-foreground\">Listening</span>\n </div>\n ) : mode === \"speaking\" ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-background rounded-full border border-border hover:border-primary transition-colors\"\n >\n <Mic className=\"w-4 h-4 text-primary\" />\n <span className=\"text-sm font-medium text-foreground\">Talk to interrupt</span>\n </button>\n ) : null}\n </div>\n )}\n\n {/* Input area */}\n <div className=\"flex-none p-4 bg-background border-t border-border\">\n {showTextInput ? (\n <div className=\"relative border-2 border-foreground rounded-2xl p-4 bg-background shadow-sm transition-all focus-within:shadow-md\">\n <textarea\n className=\"w-full resize-none border-none focus:ring-0 p-0 text-sm placeholder:text-muted-foreground min-h-[60px] bg-transparent outline-none focus:outline-none pr-24\"\n placeholder=\"Send a message...\"\n value={textInput}\n onChange={(e) => setTextInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }}\n />\n <div className=\"absolute bottom-4 right-4 flex items-center gap-3\">\n {onEndSession && (\n <button\n type=\"button\"\n onClick={onEndSession}\n className=\"w-10 h-10 flex items-center justify-center rounded-full bg-background border border-border shadow-sm hover:bg-muted transition-colors group\"\n title=\"End session\"\n >\n <PhoneOff className=\"w-5 h-5 text-foreground group-hover:text-destructive transition-colors\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!textInput.trim()}\n className=\"w-10 h-10 flex items-center justify-center rounded-full bg-muted-foreground hover:bg-foreground disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-background shadow-sm\"\n >\n <Send className=\"w-5 h-5 ml-0.5\" />\n </button>\n </div>\n </div>\n ) : onEndSession ? (\n <button\n type=\"button\"\n onClick={onEndSession}\n className=\"flex items-center justify-center gap-2 w-full px-6 py-3 bg-destructive/5 hover:bg-destructive/10 text-destructive border border-destructive/20 rounded-full font-medium transition-all\"\n >\n <span className=\"w-2 h-2 bg-destructive rounded-full\" />\n End Session\n </button>\n ) : null}\n </div>\n\n {footer}\n </div>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Avatar as Avatar$1 } from 'radix-ui';
|
|
3
|
+
|
|
4
|
+
declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof Avatar$1.Root> & {
|
|
5
|
+
size?: "default" | "sm" | "lg";
|
|
6
|
+
}): React.JSX.Element;
|
|
7
|
+
declare function AvatarImage({ className, ...props }: React.ComponentProps<typeof Avatar$1.Image>): React.JSX.Element;
|
|
8
|
+
declare function AvatarFallback({ className, ...props }: React.ComponentProps<typeof Avatar$1.Fallback>): React.JSX.Element;
|
|
9
|
+
declare function AvatarBadge({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
10
|
+
declare function AvatarGroup({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
11
|
+
declare function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage };
|