@handled-ai/design-system 0.3.0 → 0.4.2

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/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import * as React52 from 'react';
4
- import { AlertCircle, Phone, Mail, MessageSquare, ArrowLeft, ExternalLink, ChevronDown, ArrowRight, Plus, Square, Video, Clock, Eye, CheckCircle2, CheckSquare, CheckIcon, CircleIcon, ChevronRightIcon, X, ListFilter, Search, ChevronDownIcon, ChevronUpIcon, LayoutGrid, ArrowUpDown, ArrowDown, ArrowUp, XIcon, ThumbsUp, ThumbsDown, Check, CirclePlus, Lock, ChevronUp, Briefcase, History, Calendar, DollarSign, Users, TrendingUp, User, Link, SearchX, CalendarDays, Minimize2, Maximize2, MessageCircle, FileText, Building2, List, Filter, SlidersHorizontal, LayoutTemplate, ArrowDownAZ, ArrowUpAZ, RotateCcw, Info, ChevronLeft, ChevronRight, Paperclip, Inbox, Building, Activity, BarChart2, MoreHorizontal, Settings, Code, LogOut, PanelLeftOpen, PanelLeftClose, MoreVertical, HelpCircle, SkipForward, PanelLeftIcon, Tag, Columns2, LayoutList, Heart, Scale, AlertTriangle, Undo2, Copy, RefreshCw, Redo2, Bold, Italic, Underline, AlignLeft, Trash, PenLine, Sparkles } from 'lucide-react';
4
+ import { useRef, useEffect, useMemo } from 'react';
5
+ import { AlertCircle, Phone, Mail, MessageSquare, ArrowLeft, ExternalLink, ChevronDown, ArrowRight, Plus, Square, Video, Clock, Eye, CheckCircle2, CheckSquare, CheckIcon, CircleIcon, ChevronRightIcon, X, ListFilter, Search, ChevronDownIcon, ChevronUpIcon, LayoutGrid, ArrowUpDown, ArrowDown, ArrowUp, XIcon, ThumbsUp, ThumbsDown, Check, CirclePlus, Lock, ChevronUp, Briefcase, History, Calendar, DollarSign, Users, TrendingUp, User, Link, SearchX, CalendarDays, Minimize2, Maximize2, MessageCircle, FileText, Building2, List, Filter, SlidersHorizontal, LayoutTemplate, ArrowDownAZ, ArrowUpAZ, RotateCcw, Info, ChevronLeft, ChevronRight, Paperclip, Inbox, Building, Activity, BarChart2, MoreHorizontal, Settings, Code, LogOut, PanelLeftOpen, PanelLeftClose, MoreVertical, HelpCircle, SkipForward, PanelLeftIcon, Tag, Columns2, LayoutList, Sparkles, Mic, PhoneOff, Send, Heart, Scale, AlertTriangle, Undo2, Copy, RefreshCw, Redo2, Bold, Italic, Underline, AlignLeft, Trash, PenLine } from 'lucide-react';
5
6
  import { cva } from 'class-variance-authority';
6
7
  import { Slot, Avatar as Avatar$1, DropdownMenu as DropdownMenu$1, Select as Select$1, Dialog as Dialog$1, HoverCard as HoverCard$1, Separator as Separator$1, Popover, ScrollArea as ScrollArea$1, Tooltip as Tooltip$1, Progress as Progress$1, Tabs as Tabs$1 } from 'radix-ui';
7
8
  import { format } from 'date-fns';
@@ -11,6 +12,9 @@ import { Slot as Slot$1 } from '@radix-ui/react-slot';
11
12
  import { createColumnHelper, useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
12
13
  import * as LabelPrimitive from '@radix-ui/react-label';
13
14
  import { ResponsiveSankey } from '@nivo/sankey';
15
+ import { useTexture } from '@react-three/drei';
16
+ import { Canvas, useThree, useFrame } from '@react-three/fiber';
17
+ import { Color, RepeatWrapping, Uniform } from 'three';
14
18
 
15
19
  var __defProp = Object.defineProperty;
16
20
  var __defProps = Object.defineProperties;
@@ -5878,8 +5882,11 @@ function NavItemRow({
5878
5882
  item,
5879
5883
  isActive,
5880
5884
  isCollapsed,
5885
+ activeVariant = "default",
5881
5886
  onClick
5882
5887
  }) {
5888
+ const activeClasses = activeVariant === "gradient" ? "bg-gradient-to-r from-primary/10 to-transparent text-primary" : "bg-sidebar-accent text-sidebar-accent-foreground";
5889
+ const iconActiveClasses = activeVariant === "gradient" ? "text-primary" : "";
5883
5890
  const content = /* @__PURE__ */ React52.createElement(
5884
5891
  "button",
5885
5892
  {
@@ -5888,10 +5895,10 @@ function NavItemRow({
5888
5895
  className: cn(
5889
5896
  "flex w-full items-center gap-3 rounded-lg text-sm font-medium transition-colors",
5890
5897
  isCollapsed ? "justify-center p-2" : "px-3 py-2",
5891
- isActive ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent"
5898
+ isActive ? activeClasses : "text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent"
5892
5899
  )
5893
5900
  },
5894
- /* @__PURE__ */ React52.createElement(item.icon, { className: cn("shrink-0", isCollapsed ? "w-5 h-5" : "w-4 h-4") }),
5901
+ /* @__PURE__ */ React52.createElement(item.icon, { className: cn("shrink-0", isCollapsed ? "w-5 h-5" : "w-4 h-4", isActive && iconActiveClasses) }),
5895
5902
  !isCollapsed && /* @__PURE__ */ React52.createElement("span", { className: "flex-1 truncate text-left" }, item.label)
5896
5903
  );
5897
5904
  if (isCollapsed) {
@@ -5903,6 +5910,7 @@ function NavSection({
5903
5910
  section,
5904
5911
  activeItemId,
5905
5912
  isCollapsed,
5913
+ activeVariant = "default",
5906
5914
  onNavigate
5907
5915
  }) {
5908
5916
  var _a;
@@ -5932,6 +5940,7 @@ function NavSection({
5932
5940
  item,
5933
5941
  isActive: activeItemId === item.id,
5934
5942
  isCollapsed,
5943
+ activeVariant,
5935
5944
  onClick: () => onNavigate == null ? void 0 : onNavigate(item.id)
5936
5945
  }
5937
5946
  )), !isCollapsed && section.moreItems && section.moreItems.length > 0 && /* @__PURE__ */ React52.createElement(DropdownMenu, null, /* @__PURE__ */ React52.createElement(DropdownMenuTrigger, { className: "flex items-center gap-3 w-full px-3 py-2 rounded-lg text-sm font-medium text-sidebar-foreground/70 hover:text-sidebar-foreground hover:bg-sidebar-accent transition-colors outline-none" }, /* @__PURE__ */ React52.createElement(MoreHorizontal, { className: "shrink-0 w-4 h-4" }), /* @__PURE__ */ React52.createElement("span", { className: "flex-1 text-left" }, "More")), /* @__PURE__ */ React52.createElement(DropdownMenuContent, { align: "start", side: "bottom", className: "w-48" }, section.moreItems.map((item) => /* @__PURE__ */ React52.createElement(
@@ -5950,6 +5959,7 @@ function NavSection({
5950
5959
  item,
5951
5960
  isActive: activeItemId === item.id,
5952
5961
  isCollapsed,
5962
+ activeVariant,
5953
5963
  onClick: () => onNavigate == null ? void 0 : onNavigate(item.id)
5954
5964
  }
5955
5965
  )))));
@@ -5961,6 +5971,7 @@ function QuickActionSidebarNav(_a) {
5961
5971
  brandSubtitle = "Placeholder",
5962
5972
  navSections = DEFAULT_NAV_SECTIONS,
5963
5973
  activeItemId = "inbox",
5974
+ activeVariant = "default",
5964
5975
  onNavigate,
5965
5976
  user = DEFAULT_USER,
5966
5977
  userMenuItems = DEFAULT_USER_MENU,
@@ -5973,6 +5984,7 @@ function QuickActionSidebarNav(_a) {
5973
5984
  "brandSubtitle",
5974
5985
  "navSections",
5975
5986
  "activeItemId",
5987
+ "activeVariant",
5976
5988
  "onNavigate",
5977
5989
  "user",
5978
5990
  "userMenuItems",
@@ -6024,6 +6036,7 @@ function QuickActionSidebarNav(_a) {
6024
6036
  section,
6025
6037
  activeItemId,
6026
6038
  isCollapsed,
6039
+ activeVariant,
6027
6040
  onNavigate
6028
6041
  }
6029
6042
  ));
@@ -9346,9 +9359,10 @@ var DEFAULT_ENTITY_SECTIONS = [
9346
9359
  function PrototypeShell({
9347
9360
  config,
9348
9361
  headerActions,
9349
- entityPanelChildren
9362
+ entityPanelChildren,
9363
+ onNavigate
9350
9364
  }) {
9351
- var _a, _b, _c, _d, _e, _f, _g;
9365
+ var _a, _b, _c, _d, _e, _f, _g, _h;
9352
9366
  const [currentView, setCurrentView] = React52.useState(config.defaultView);
9353
9367
  const [isEntityPanelOpen, setIsEntityPanelOpen] = React52.useState(false);
9354
9368
  const navigableViews = React52.useMemo(() => {
@@ -9365,8 +9379,9 @@ function PrototypeShell({
9365
9379
  if (navigableViews.includes(id)) {
9366
9380
  setCurrentView(id);
9367
9381
  }
9382
+ onNavigate == null ? void 0 : onNavigate(id);
9368
9383
  },
9369
- [navigableViews]
9384
+ [navigableViews, onNavigate]
9370
9385
  );
9371
9386
  const handleOpenEntityPanel = React52.useCallback(() => setIsEntityPanelOpen(true), []);
9372
9387
  const handleOpenRecentActivity = React52.useCallback(() => {
@@ -9383,6 +9398,8 @@ function PrototypeShell({
9383
9398
  QuickActionSidebarNav,
9384
9399
  {
9385
9400
  className: "z-20 h-screen shrink-0",
9401
+ brandLabel: (_f = config.brand) == null ? void 0 : _f.name,
9402
+ brandSubtitle: void 0,
9386
9403
  navSections: config.sidebar,
9387
9404
  activeItemId: currentView,
9388
9405
  onNavigate: handleNavigate,
@@ -9393,7 +9410,7 @@ function PrototypeShell({
9393
9410
  ), /* @__PURE__ */ React52.createElement("main", { className: "flex min-w-0 flex-1 flex-col overflow-hidden bg-background" }, /* @__PURE__ */ React52.createElement("div", { className: "relative h-full flex-1 overflow-auto" }, resolvedViewKey === "insights" && config.views.insights ? /* @__PURE__ */ React52.createElement(
9394
9411
  PrototypeInsightsView,
9395
9412
  __spreadProps(__spreadValues({}, config.views.insights), {
9396
- assistantName: (_f = config.brand) == null ? void 0 : _f.assistantName,
9413
+ assistantName: (_g = config.brand) == null ? void 0 : _g.assistantName,
9397
9414
  headerActions,
9398
9415
  onNavigateToInbox: () => setCurrentView("inbox")
9399
9416
  })
@@ -9415,7 +9432,7 @@ function PrototypeShell({
9415
9432
  {
9416
9433
  headerActions
9417
9434
  }
9418
- ) : null)), /* @__PURE__ */ React52.createElement(EntityPanel, { isOpen: isEntityPanelOpen, onClose: setIsEntityPanelOpen }, (_g = typeof entityPanelChildren === "function" ? entityPanelChildren({ onClose: () => setIsEntityPanelOpen(false) }) : entityPanelChildren) != null ? _g : /* @__PURE__ */ React52.createElement(React52.Fragment, null, entitySections.map((section, i) => {
9435
+ ) : null)), /* @__PURE__ */ React52.createElement(EntityPanel, { isOpen: isEntityPanelOpen, onClose: setIsEntityPanelOpen }, (_h = typeof entityPanelChildren === "function" ? entityPanelChildren({ onClose: () => setIsEntityPanelOpen(false) }) : entityPanelChildren) != null ? _h : /* @__PURE__ */ React52.createElement(React52.Fragment, null, entitySections.map((section, i) => {
9419
9436
  var _a2, _b2;
9420
9437
  switch (section.type) {
9421
9438
  case "details":
@@ -9457,7 +9474,927 @@ function PrototypeShell({
9457
9474
  }
9458
9475
  }))));
9459
9476
  }
9477
+ var Message = (_a) => {
9478
+ var _b = _a, { className, from } = _b, props = __objRest(_b, ["className", "from"]);
9479
+ return /* @__PURE__ */ React.createElement(
9480
+ "div",
9481
+ __spreadValues({
9482
+ "data-slot": "message",
9483
+ className: cn(
9484
+ "group flex w-full items-end gap-3 py-2",
9485
+ from === "user" ? "is-user justify-end" : "is-assistant justify-start",
9486
+ className
9487
+ )
9488
+ }, props)
9489
+ );
9490
+ };
9491
+ var messageContentVariants = cva(
9492
+ "flex flex-col gap-2 overflow-hidden text-sm leading-relaxed shadow-sm whitespace-pre-wrap",
9493
+ {
9494
+ variants: {
9495
+ variant: {
9496
+ contained: [
9497
+ "max-w-[85%] px-6 py-4 rounded-[24px]",
9498
+ "group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground group-[.is-user]:rounded-br-sm",
9499
+ "group-[.is-assistant]:bg-muted group-[.is-assistant]:text-foreground group-[.is-assistant]:rounded-bl-sm"
9500
+ ],
9501
+ flat: [
9502
+ "group-[.is-user]:max-w-[85%] group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
9503
+ "group-[.is-assistant]:text-foreground"
9504
+ ]
9505
+ }
9506
+ },
9507
+ defaultVariants: {
9508
+ variant: "contained"
9509
+ }
9510
+ }
9511
+ );
9512
+ var MessageContent = (_a) => {
9513
+ var _b = _a, {
9514
+ children,
9515
+ className,
9516
+ variant
9517
+ } = _b, props = __objRest(_b, [
9518
+ "children",
9519
+ "className",
9520
+ "variant"
9521
+ ]);
9522
+ return /* @__PURE__ */ React.createElement(
9523
+ "div",
9524
+ __spreadValues({
9525
+ "data-slot": "message-content",
9526
+ className: cn(messageContentVariants({ variant, className }))
9527
+ }, props),
9528
+ children
9529
+ );
9530
+ };
9531
+ var MessageAvatar = (_a) => {
9532
+ var _b = _a, {
9533
+ src,
9534
+ name,
9535
+ className,
9536
+ children
9537
+ } = _b, props = __objRest(_b, [
9538
+ "src",
9539
+ "name",
9540
+ "className",
9541
+ "children"
9542
+ ]);
9543
+ return /* @__PURE__ */ React.createElement(Avatar, __spreadValues({ className: cn("ring-border size-8 ring-1 shrink-0", className) }, props), children, src && /* @__PURE__ */ React.createElement(AvatarImage, { alt: "", className: "mt-0 mb-0", src }), !children && !src && /* @__PURE__ */ React.createElement(AvatarFallback, null, (name == null ? void 0 : name.slice(0, 2)) || "ME"));
9544
+ };
9545
+ var DEFAULT_STATUS_MAP = {};
9546
+ var STATUS_KEYWORDS = {
9547
+ success: ["active", "hired", "completed", "success", "shortlist", "approved", "resolved", "done"],
9548
+ warning: ["pending", "new", "scheduled", "screening", "draft", "paused", "in_progress", "review"],
9549
+ error: ["rejected", "failed", "cancelled", "error", "no_answer", "dropped", "blocked"],
9550
+ neutral: []
9551
+ };
9552
+ function inferStatusType(status, statusMap) {
9553
+ const lower = status.toLowerCase();
9554
+ if (statusMap[lower]) return statusMap[lower];
9555
+ for (const [type, keywords] of Object.entries(STATUS_KEYWORDS)) {
9556
+ if (keywords.some((kw) => lower.includes(kw))) return type;
9557
+ }
9558
+ return "neutral";
9559
+ }
9560
+ var STATUS_STYLES = {
9561
+ success: "bg-green-100 text-green-950 dark:bg-green-950 dark:text-green-100",
9562
+ warning: "bg-yellow-100 text-yellow-950 dark:bg-yellow-950 dark:text-yellow-100",
9563
+ error: "bg-red-100 text-red-950 dark:bg-red-950 dark:text-red-100",
9564
+ neutral: "bg-muted text-foreground"
9565
+ };
9566
+ function formatStatus(status) {
9567
+ return status.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
9568
+ }
9569
+ function StatusBadge(_a) {
9570
+ var _b = _a, { status, statusMap = DEFAULT_STATUS_MAP, className } = _b, props = __objRest(_b, ["status", "statusMap", "className"]);
9571
+ const type = inferStatusType(status, statusMap);
9572
+ return /* @__PURE__ */ React52.createElement(
9573
+ "div",
9574
+ __spreadValues({
9575
+ "data-slot": "status-badge",
9576
+ "data-status": type,
9577
+ className: cn(
9578
+ "inline-flex items-center justify-center rounded-full px-2.5 h-6 text-xs font-medium transition-colors",
9579
+ STATUS_STYLES[type],
9580
+ className
9581
+ )
9582
+ }, props),
9583
+ formatStatus(status)
9584
+ );
9585
+ }
9586
+ function SimpleDataTable({
9587
+ columns,
9588
+ data,
9589
+ onRowClick,
9590
+ emptyIcon,
9591
+ emptyMessage = "No rows found",
9592
+ emptyDescription = "Try adjusting your filters",
9593
+ className
9594
+ }) {
9595
+ const [sorting, setSorting] = React52.useState([]);
9596
+ const table = useReactTable({
9597
+ data,
9598
+ columns,
9599
+ state: { sorting },
9600
+ onSortingChange: setSorting,
9601
+ getCoreRowModel: getCoreRowModel(),
9602
+ getSortedRowModel: getSortedRowModel()
9603
+ });
9604
+ return /* @__PURE__ */ React52.createElement("div", { className: cn("w-full", className) }, /* @__PURE__ */ React52.createElement("table", { className: "w-full border-collapse text-sm" }, /* @__PURE__ */ React52.createElement("thead", null, table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ React52.createElement(
9605
+ "tr",
9606
+ {
9607
+ key: headerGroup.id,
9608
+ className: "border-b border-border/50 hover:bg-transparent"
9609
+ },
9610
+ headerGroup.headers.map((header) => /* @__PURE__ */ React52.createElement(
9611
+ "th",
9612
+ {
9613
+ key: header.id,
9614
+ className: "h-9 px-3 text-left align-middle text-xs font-medium text-muted-foreground whitespace-nowrap"
9615
+ },
9616
+ header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ React52.createElement(
9617
+ "button",
9618
+ {
9619
+ type: "button",
9620
+ className: "inline-flex items-center gap-1 hover:text-foreground transition-colors",
9621
+ onClick: header.column.getToggleSortingHandler()
9622
+ },
9623
+ flexRender(header.column.columnDef.header, header.getContext()),
9624
+ header.column.getIsSorted() === "asc" ? /* @__PURE__ */ React52.createElement(ArrowUp, { className: "w-3 h-3" }) : header.column.getIsSorted() === "desc" ? /* @__PURE__ */ React52.createElement(ArrowDown, { className: "w-3 h-3" }) : /* @__PURE__ */ React52.createElement(ArrowUpDown, { className: "w-3 h-3 opacity-0 group-hover:opacity-50" })
9625
+ ) : flexRender(header.column.columnDef.header, header.getContext())
9626
+ ))
9627
+ ))), /* @__PURE__ */ React52.createElement("tbody", null, table.getRowModel().rows.length > 0 ? table.getRowModel().rows.map((row) => /* @__PURE__ */ React52.createElement(
9628
+ "tr",
9629
+ {
9630
+ key: row.id,
9631
+ onClick: () => onRowClick == null ? void 0 : onRowClick(row.original),
9632
+ className: cn(
9633
+ "group border-none transition-colors",
9634
+ onRowClick && "cursor-pointer"
9635
+ )
9636
+ },
9637
+ row.getVisibleCells().map((cell, cellIdx) => /* @__PURE__ */ React52.createElement(
9638
+ "td",
9639
+ {
9640
+ key: cell.id,
9641
+ className: cn(
9642
+ "px-3 py-3 align-middle whitespace-nowrap group-hover:bg-muted/50",
9643
+ cellIdx === 0 && "rounded-l-lg",
9644
+ cellIdx === row.getVisibleCells().length - 1 && "rounded-r-lg"
9645
+ )
9646
+ },
9647
+ flexRender(cell.column.columnDef.cell, cell.getContext())
9648
+ ))
9649
+ )) : /* @__PURE__ */ React52.createElement("tr", null, /* @__PURE__ */ React52.createElement("td", { colSpan: columns.length, className: "h-52 px-4 text-center" }, /* @__PURE__ */ React52.createElement("div", { className: "flex flex-col items-center gap-1 text-muted-foreground" }, emptyIcon != null ? emptyIcon : /* @__PURE__ */ React52.createElement(SearchX, { className: "h-7 w-7 opacity-40" }), /* @__PURE__ */ React52.createElement("p", { className: "text-sm font-medium" }, emptyMessage), /* @__PURE__ */ React52.createElement("p", { className: "text-xs" }, emptyDescription)))))));
9650
+ }
9651
+ var PERLIN_NOISE_URL = "https://storage.googleapis.com/eleven-public-cdn/images/perlin-noise.png";
9652
+ function AgentOrb({
9653
+ state = null,
9654
+ colors,
9655
+ volumeMode = "auto",
9656
+ manualInput,
9657
+ manualOutput,
9658
+ inputVolumeRef,
9659
+ outputVolumeRef,
9660
+ getInputVolume,
9661
+ getOutputVolume,
9662
+ seed,
9663
+ showGlow = true,
9664
+ className
9665
+ }) {
9666
+ const resolvedColors = useResolvedColors(colors);
9667
+ const isSpeaking = state === "talking";
9668
+ const isListening = state === "listening";
9669
+ return /* @__PURE__ */ React.createElement("div", { className: cn("relative h-full w-full", className) }, showGlow && /* @__PURE__ */ React.createElement(
9670
+ GlowLayer,
9671
+ {
9672
+ isSpeaking,
9673
+ isListening
9674
+ }
9675
+ ), /* @__PURE__ */ React.createElement(
9676
+ "div",
9677
+ {
9678
+ className: cn(
9679
+ "relative z-10 w-full h-full transition-transform duration-700 ease-out",
9680
+ isListening ? "scale-90" : "scale-100"
9681
+ )
9682
+ },
9683
+ /* @__PURE__ */ React.createElement(
9684
+ AgentOrbCanvas,
9685
+ {
9686
+ colors: resolvedColors,
9687
+ seed,
9688
+ agentState: state,
9689
+ volumeMode,
9690
+ manualInput,
9691
+ manualOutput,
9692
+ inputVolumeRef,
9693
+ outputVolumeRef,
9694
+ getInputVolume,
9695
+ getOutputVolume,
9696
+ className: "w-full h-full"
9697
+ }
9698
+ )
9699
+ ));
9700
+ }
9701
+ function useResolvedColors(colors) {
9702
+ const ref = useRef(colors != null ? colors : ["#000000", "#000000"]);
9703
+ useEffect(() => {
9704
+ if (colors) {
9705
+ ref.current = colors;
9706
+ return;
9707
+ }
9708
+ if (typeof document === "undefined") return;
9709
+ const style = getComputedStyle(document.documentElement);
9710
+ const primary = style.getPropertyValue("--primary").trim() || "#000000";
9711
+ ref.current = [primary, primary];
9712
+ }, [colors]);
9713
+ return ref.current;
9714
+ }
9715
+ function GlowLayer({ isSpeaking, isListening }) {
9716
+ return /* @__PURE__ */ React.createElement(
9717
+ "div",
9718
+ {
9719
+ className: cn(
9720
+ "absolute inset-0 flex items-center justify-center transition-all duration-700 ease-out",
9721
+ isListening ? "scale-90" : "scale-100"
9722
+ )
9723
+ },
9724
+ isListening && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
9725
+ "div",
9726
+ {
9727
+ className: "absolute inset-0 rounded-full animate-[spin_8s_linear_infinite]",
9728
+ style: {
9729
+ background: "conic-gradient(from 0deg, color-mix(in srgb, var(--primary) 30%, transparent) 0deg, transparent 60deg, color-mix(in srgb, var(--primary) 30%, transparent) 120deg, transparent 180deg, color-mix(in srgb, var(--primary) 30%, transparent) 240deg, transparent 300deg)",
9730
+ filter: "blur(20px)"
9731
+ }
9732
+ }
9733
+ ), /* @__PURE__ */ React.createElement(
9734
+ "div",
9735
+ {
9736
+ className: "absolute inset-0 rounded-full animate-[spin_12s_linear_infinite_reverse]",
9737
+ style: {
9738
+ background: "conic-gradient(from 45deg, transparent 0deg, color-mix(in srgb, var(--primary) 20%, transparent) 90deg, transparent 180deg, color-mix(in srgb, var(--primary) 20%, transparent) 270deg)",
9739
+ filter: "blur(25px)"
9740
+ }
9741
+ }
9742
+ )),
9743
+ isSpeaking && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
9744
+ "div",
9745
+ {
9746
+ className: "absolute inset-0 rounded-full animate-[spin_6s_linear_infinite]",
9747
+ style: {
9748
+ background: "conic-gradient(from 0deg, color-mix(in srgb, var(--primary) 40%, transparent) 0deg, transparent 45deg, color-mix(in srgb, var(--primary) 40%, transparent) 90deg, transparent 135deg, color-mix(in srgb, var(--primary) 40%, transparent) 180deg, transparent 225deg, color-mix(in srgb, var(--primary) 40%, transparent) 270deg, transparent 315deg)",
9749
+ filter: "blur(30px)"
9750
+ }
9751
+ }
9752
+ ), /* @__PURE__ */ React.createElement(
9753
+ "div",
9754
+ {
9755
+ className: "absolute inset-0 rounded-full animate-pulse",
9756
+ style: {
9757
+ animationDuration: "2s",
9758
+ background: "radial-gradient(circle, color-mix(in srgb, var(--primary) 30%, transparent) 0%, transparent 70%)",
9759
+ filter: "blur(20px)"
9760
+ }
9761
+ }
9762
+ )),
9763
+ !isSpeaking && !isListening && /* @__PURE__ */ React.createElement(
9764
+ "div",
9765
+ {
9766
+ className: "absolute inset-0 rounded-full",
9767
+ style: {
9768
+ background: "radial-gradient(circle, color-mix(in srgb, var(--primary) 15%, transparent) 0%, transparent 70%)",
9769
+ filter: "blur(25px)"
9770
+ }
9771
+ }
9772
+ )
9773
+ );
9774
+ }
9775
+ function AgentOrbCanvas({
9776
+ colors = ["#000000", "#000000"],
9777
+ seed,
9778
+ agentState = null,
9779
+ volumeMode = "auto",
9780
+ manualInput,
9781
+ manualOutput,
9782
+ inputVolumeRef,
9783
+ outputVolumeRef,
9784
+ getInputVolume,
9785
+ getOutputVolume,
9786
+ className,
9787
+ resizeDebounce = 100
9788
+ }) {
9789
+ return /* @__PURE__ */ React.createElement("div", { className: className != null ? className : "relative h-full w-full" }, /* @__PURE__ */ React.createElement(
9790
+ Canvas,
9791
+ {
9792
+ resize: { debounce: resizeDebounce },
9793
+ gl: { alpha: true, antialias: true, premultipliedAlpha: true }
9794
+ },
9795
+ /* @__PURE__ */ React.createElement(
9796
+ OrbScene,
9797
+ {
9798
+ colors,
9799
+ seed,
9800
+ agentState,
9801
+ volumeMode,
9802
+ manualInput,
9803
+ manualOutput,
9804
+ inputVolumeRef,
9805
+ outputVolumeRef,
9806
+ getInputVolume,
9807
+ getOutputVolume
9808
+ }
9809
+ )
9810
+ ));
9811
+ }
9812
+ function OrbScene({
9813
+ colors,
9814
+ seed,
9815
+ agentState,
9816
+ volumeMode,
9817
+ manualInput,
9818
+ manualOutput,
9819
+ inputVolumeRef,
9820
+ outputVolumeRef,
9821
+ getInputVolume,
9822
+ getOutputVolume
9823
+ }) {
9824
+ const { gl } = useThree();
9825
+ const circleRef = useRef(null);
9826
+ const initialColorsRef = useRef(colors);
9827
+ const targetColor1Ref = useRef(new Color(colors[0]));
9828
+ const targetColor2Ref = useRef(new Color(colors[1]));
9829
+ const animSpeedRef = useRef(0.1);
9830
+ const perlinNoiseTexture = useTexture(PERLIN_NOISE_URL);
9831
+ const agentRef = useRef(agentState);
9832
+ const modeRef = useRef(volumeMode);
9833
+ const curInRef = useRef(0);
9834
+ const curOutRef = useRef(0);
9835
+ useEffect(() => {
9836
+ agentRef.current = agentState;
9837
+ }, [agentState]);
9838
+ useEffect(() => {
9839
+ modeRef.current = volumeMode;
9840
+ }, [volumeMode]);
9841
+ useEffect(() => {
9842
+ targetColor1Ref.current = new Color(colors[0]);
9843
+ targetColor2Ref.current = new Color(colors[1]);
9844
+ }, [colors]);
9845
+ const random = useMemo(
9846
+ () => splitmix32(seed != null ? seed : Math.floor(Math.random() * 2 ** 32)),
9847
+ [seed]
9848
+ );
9849
+ const offsets = useMemo(
9850
+ () => new Float32Array(Array.from({ length: 7 }, () => random() * Math.PI * 2)),
9851
+ [random]
9852
+ );
9853
+ useEffect(() => {
9854
+ const apply = () => {
9855
+ if (!circleRef.current) return;
9856
+ const isDark = document.documentElement.classList.contains("dark");
9857
+ circleRef.current.material.uniforms.uInverted.value = isDark ? 1 : 0;
9858
+ };
9859
+ apply();
9860
+ const observer = new MutationObserver(apply);
9861
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
9862
+ return () => observer.disconnect();
9863
+ }, []);
9864
+ useFrame((_, delta) => {
9865
+ var _a, _b, _c, _d, _e;
9866
+ const mat = (_a = circleRef.current) == null ? void 0 : _a.material;
9867
+ if (!mat) return;
9868
+ const u = mat.uniforms;
9869
+ u.uTime.value += delta * 0.5;
9870
+ if (u.uOpacity.value < 1) {
9871
+ u.uOpacity.value = Math.min(1, u.uOpacity.value + delta * 2);
9872
+ }
9873
+ let targetIn = 0;
9874
+ let targetOut = 0.3;
9875
+ if (modeRef.current === "manual") {
9876
+ targetIn = clamp01((_c = (_b = manualInput != null ? manualInput : inputVolumeRef == null ? void 0 : inputVolumeRef.current) != null ? _b : getInputVolume == null ? void 0 : getInputVolume()) != null ? _c : 0);
9877
+ targetOut = clamp01((_e = (_d = manualOutput != null ? manualOutput : outputVolumeRef == null ? void 0 : outputVolumeRef.current) != null ? _d : getOutputVolume == null ? void 0 : getOutputVolume()) != null ? _e : 0);
9878
+ } else {
9879
+ const t = u.uTime.value * 2;
9880
+ if (agentRef.current === null) {
9881
+ targetIn = 0;
9882
+ targetOut = 0.3;
9883
+ } else if (agentRef.current === "listening") {
9884
+ targetIn = clamp01(0.55 + Math.sin(t * 3.2) * 0.35);
9885
+ targetOut = 0.45;
9886
+ } else if (agentRef.current === "talking") {
9887
+ targetIn = clamp01(0.65 + Math.sin(t * 4.8) * 0.22);
9888
+ targetOut = clamp01(0.75 + Math.sin(t * 3.6) * 0.22);
9889
+ } else {
9890
+ const base = 0.38 + 0.07 * Math.sin(t * 0.7);
9891
+ const wander = 0.05 * Math.sin(t * 2.1) * Math.sin(t * 0.37 + 1.2);
9892
+ targetIn = clamp01(base + wander);
9893
+ targetOut = clamp01(0.48 + 0.12 * Math.sin(t * 1.05 + 0.6));
9894
+ }
9895
+ }
9896
+ curInRef.current += (targetIn - curInRef.current) * 0.2;
9897
+ curOutRef.current += (targetOut - curOutRef.current) * 0.2;
9898
+ const targetSpeed = 0.1 + (1 - Math.pow(curOutRef.current - 1, 2)) * 0.9;
9899
+ animSpeedRef.current += (targetSpeed - animSpeedRef.current) * 0.12;
9900
+ u.uAnimation.value += delta * animSpeedRef.current;
9901
+ u.uInputVolume.value = curInRef.current;
9902
+ u.uOutputVolume.value = curOutRef.current;
9903
+ u.uColor1.value.lerp(targetColor1Ref.current, 0.08);
9904
+ u.uColor2.value.lerp(targetColor2Ref.current, 0.08);
9905
+ });
9906
+ useEffect(() => {
9907
+ const canvas = gl.domElement;
9908
+ const onContextLost = (event) => {
9909
+ event.preventDefault();
9910
+ setTimeout(() => {
9911
+ gl.forceContextRestore();
9912
+ }, 1);
9913
+ };
9914
+ canvas.addEventListener("webglcontextlost", onContextLost, false);
9915
+ return () => canvas.removeEventListener("webglcontextlost", onContextLost, false);
9916
+ }, [gl]);
9917
+ const uniforms = useMemo(() => {
9918
+ perlinNoiseTexture.wrapS = RepeatWrapping;
9919
+ perlinNoiseTexture.wrapT = RepeatWrapping;
9920
+ const isDark = typeof document !== "undefined" && document.documentElement.classList.contains("dark");
9921
+ return {
9922
+ uColor1: new Uniform(new Color(initialColorsRef.current[0])),
9923
+ uColor2: new Uniform(new Color(initialColorsRef.current[1])),
9924
+ uOffsets: { value: offsets },
9925
+ uPerlinTexture: new Uniform(perlinNoiseTexture),
9926
+ uTime: new Uniform(0),
9927
+ uAnimation: new Uniform(0.1),
9928
+ uInverted: new Uniform(isDark ? 1 : 0),
9929
+ uInputVolume: new Uniform(0),
9930
+ uOutputVolume: new Uniform(0),
9931
+ uOpacity: new Uniform(0)
9932
+ };
9933
+ }, [perlinNoiseTexture, offsets]);
9934
+ return /* @__PURE__ */ React.createElement("mesh", { ref: circleRef }, /* @__PURE__ */ React.createElement("circleGeometry", { args: [3.5, 64] }), /* @__PURE__ */ React.createElement(
9935
+ "shaderMaterial",
9936
+ {
9937
+ uniforms,
9938
+ fragmentShader,
9939
+ vertexShader,
9940
+ transparent: true
9941
+ }
9942
+ ));
9943
+ }
9944
+ function splitmix32(a) {
9945
+ return function() {
9946
+ a |= 0;
9947
+ a = a + 2654435769 | 0;
9948
+ let t = a ^ a >>> 16;
9949
+ t = Math.imul(t, 569420461);
9950
+ t = t ^ t >>> 15;
9951
+ t = Math.imul(t, 1935289751);
9952
+ return ((t = t ^ t >>> 15) >>> 0) / 4294967296;
9953
+ };
9954
+ }
9955
+ function clamp01(n) {
9956
+ if (!Number.isFinite(n)) return 0;
9957
+ return Math.min(1, Math.max(0, n));
9958
+ }
9959
+ var vertexShader = (
9960
+ /* glsl */
9961
+ `
9962
+ uniform float uTime;
9963
+ uniform sampler2D uPerlinTexture;
9964
+ varying vec2 vUv;
9965
+ void main() {
9966
+ vUv = uv;
9967
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
9968
+ }
9969
+ `
9970
+ );
9971
+ var fragmentShader = (
9972
+ /* glsl */
9973
+ `
9974
+ uniform float uTime;
9975
+ uniform float uAnimation;
9976
+ uniform float uInverted;
9977
+ uniform float uOffsets[7];
9978
+ uniform vec3 uColor1;
9979
+ uniform vec3 uColor2;
9980
+ uniform float uInputVolume;
9981
+ uniform float uOutputVolume;
9982
+ uniform float uOpacity;
9983
+ uniform sampler2D uPerlinTexture;
9984
+ varying vec2 vUv;
9985
+
9986
+ const float PI = 3.14159265358979323846;
9987
+
9988
+ bool drawOval(vec2 polarUv, vec2 polarCenter, float a, float b, bool reverseGradient, float softness, out vec4 color) {
9989
+ vec2 p = polarUv - polarCenter;
9990
+ float oval = (p.x * p.x) / (a * a) + (p.y * p.y) / (b * b);
9991
+ float edge = smoothstep(1.0, 1.0 - softness, oval);
9992
+ if (edge > 0.0) {
9993
+ float gradient = reverseGradient ? (1.0 - (p.x / a + 1.0) / 2.0) : ((p.x / a + 1.0) / 2.0);
9994
+ gradient = mix(0.5, gradient, 0.1);
9995
+ color = vec4(vec3(gradient), 0.85 * edge);
9996
+ return true;
9997
+ }
9998
+ return false;
9999
+ }
10000
+
10001
+ vec3 colorRamp(float grayscale, vec3 color1, vec3 color2, vec3 color3, vec3 color4) {
10002
+ if (grayscale < 0.33) return mix(color1, color2, grayscale * 3.0);
10003
+ else if (grayscale < 0.66) return mix(color2, color3, (grayscale - 0.33) * 3.0);
10004
+ else return mix(color3, color4, (grayscale - 0.66) * 3.0);
10005
+ }
10006
+
10007
+ vec2 hash2(vec2 p) {
10008
+ return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453);
10009
+ }
10010
+
10011
+ float noise2D(vec2 p) {
10012
+ vec2 i = floor(p);
10013
+ vec2 f = fract(p);
10014
+ vec2 u = f * f * (3.0 - 2.0 * f);
10015
+ float n = mix(
10016
+ mix(dot(hash2(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)),
10017
+ dot(hash2(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
10018
+ mix(dot(hash2(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
10019
+ dot(hash2(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x),
10020
+ u.y
10021
+ );
10022
+ return 0.5 + 0.5 * n;
10023
+ }
10024
+
10025
+ float sharpRing(vec3 decomposed, float time) {
10026
+ float ringStart = 1.0;
10027
+ float ringWidth = 0.3;
10028
+ float noiseScale = 5.0;
10029
+ float noise = mix(
10030
+ noise2D(vec2(decomposed.x, time) * noiseScale),
10031
+ noise2D(vec2(decomposed.y, time) * noiseScale),
10032
+ decomposed.z
10033
+ );
10034
+ noise = (noise - 0.5) * 2.5;
10035
+ return ringStart + noise * ringWidth * 1.5;
10036
+ }
10037
+
10038
+ float smoothRing(vec3 decomposed, float time) {
10039
+ float ringStart = 0.9;
10040
+ float ringWidth = 0.2;
10041
+ float noiseScale = 6.0;
10042
+ float noise = mix(
10043
+ noise2D(vec2(decomposed.x, time) * noiseScale),
10044
+ noise2D(vec2(decomposed.y, time) * noiseScale),
10045
+ decomposed.z
10046
+ );
10047
+ noise = (noise - 0.5) * 5.0;
10048
+ return ringStart + noise * ringWidth;
10049
+ }
10050
+
10051
+ float flow(vec3 decomposed, float time) {
10052
+ return mix(
10053
+ texture(uPerlinTexture, vec2(time, decomposed.x / 2.0)).r,
10054
+ texture(uPerlinTexture, vec2(time, decomposed.y / 2.0)).r,
10055
+ decomposed.z
10056
+ );
10057
+ }
10058
+
10059
+ void main() {
10060
+ vec2 uv = vUv * 2.0 - 1.0;
10061
+ float radius = length(uv);
10062
+ float theta = atan(uv.y, uv.x);
10063
+ if (theta < 0.0) theta += 2.0 * PI;
10064
+
10065
+ vec3 decomposed = vec3(
10066
+ theta / (2.0 * PI),
10067
+ mod(theta / (2.0 * PI) + 0.5, 1.0) + 1.0,
10068
+ abs(theta / PI - 1.0)
10069
+ );
10070
+
10071
+ float noise = flow(decomposed, radius * 0.03 - uAnimation * 0.2) - 0.5;
10072
+ theta += noise * mix(0.08, 0.25, uOutputVolume);
10073
+
10074
+ vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
10075
+ float originalCenters[7] = float[7](0.0, 0.5 * PI, 1.0 * PI, 1.5 * PI, 2.0 * PI, 2.5 * PI, 3.0 * PI);
10076
+ float centers[7];
10077
+ for (int i = 0; i < 7; i++) {
10078
+ centers[i] = originalCenters[i] + 0.5 * sin(uTime / 20.0 + uOffsets[i]);
10079
+ }
10080
+ float a, b;
10081
+ vec4 ovalColor;
10082
+ for (int i = 0; i < 7; i++) {
10083
+ float noise = texture(uPerlinTexture, vec2(mod(centers[i] + uTime * 0.05, 1.0), 0.5)).r;
10084
+ a = 0.5 + noise * 0.3;
10085
+ b = noise * mix(3.5, 2.5, uInputVolume);
10086
+ bool reverseGradient = (i % 2 == 1);
10087
+ float distTheta = min(abs(theta - centers[i]), min(abs(theta + 2.0 * PI - centers[i]), abs(theta - 2.0 * PI - centers[i])));
10088
+ float distRadius = radius;
10089
+ float softness = 0.6;
10090
+ if (drawOval(vec2(distTheta, distRadius), vec2(0.0, 0.0), a, b, reverseGradient, softness, ovalColor)) {
10091
+ color.rgb = mix(color.rgb, ovalColor.rgb, ovalColor.a);
10092
+ color.a = max(color.a, ovalColor.a);
10093
+ }
10094
+ }
10095
+
10096
+ float ringRadius1 = sharpRing(decomposed, uTime * 0.1);
10097
+ float ringRadius2 = smoothRing(decomposed, uTime * 0.1);
10098
+ float inputRadius1 = radius + uInputVolume * 0.2;
10099
+ float inputRadius2 = radius + uInputVolume * 0.15;
10100
+ float opacity1 = mix(0.2, 0.6, uInputVolume);
10101
+ float opacity2 = mix(0.15, 0.45, uInputVolume);
10102
+ float ringAlpha1 = (inputRadius2 >= ringRadius1) ? opacity1 : 0.0;
10103
+ float ringAlpha2 = smoothstep(ringRadius2 - 0.05, ringRadius2 + 0.05, inputRadius1) * opacity2;
10104
+ float totalRingAlpha = max(ringAlpha1, ringAlpha2);
10105
+ vec3 ringColor = vec3(1.0);
10106
+ color.rgb = 1.0 - (1.0 - color.rgb) * (1.0 - ringColor * totalRingAlpha);
10107
+
10108
+ vec3 color1 = vec3(0.0, 0.0, 0.0);
10109
+ vec3 color2 = uColor1;
10110
+ vec3 color3 = uColor2;
10111
+ vec3 color4 = vec3(1.0, 1.0, 1.0);
10112
+ float luminance = mix(color.r, 1.0 - color.r, uInverted);
10113
+ color.rgb = colorRamp(luminance, color1, color2, color3, color4);
10114
+ color.a *= uOpacity;
10115
+ gl_FragColor = color;
10116
+ }
10117
+ `
10118
+ );
10119
+ function AgentWidget({
10120
+ status = "idle",
10121
+ mode = null,
10122
+ messages = [],
10123
+ onSendMessage,
10124
+ onEndSession,
10125
+ inputMode = "voice+text",
10126
+ visualSlot,
10127
+ assistantAvatarSlot,
10128
+ header,
10129
+ footer,
10130
+ className
10131
+ }) {
10132
+ const [textInput, setTextInput] = React52.useState("");
10133
+ const messagesEndRef = React52.useRef(null);
10134
+ React52.useEffect(() => {
10135
+ var _a;
10136
+ (_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
10137
+ }, [messages]);
10138
+ const handleSend = () => {
10139
+ if (!textInput.trim()) return;
10140
+ onSendMessage == null ? void 0 : onSendMessage(textInput);
10141
+ setTextInput("");
10142
+ };
10143
+ const showTextInput = inputMode === "text" || inputMode === "voice+text";
10144
+ const isConnected = status === "connected";
10145
+ return /* @__PURE__ */ React52.createElement("div", { className: cn("flex flex-col h-full overflow-hidden", className) }, header, /* @__PURE__ */ React52.createElement("div", { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-muted/20" }, messages.length === 0 ? /* @__PURE__ */ React52.createElement("div", { className: "flex flex-col items-center justify-center h-full text-muted-foreground space-y-2 opacity-50" }, visualSlot != null ? visualSlot : /* @__PURE__ */ React52.createElement("div", { className: "w-12 h-12 rounded-full bg-muted flex items-center justify-center" }, /* @__PURE__ */ React52.createElement(Sparkles, { className: "w-5 h-5" })), /* @__PURE__ */ React52.createElement("p", { className: "text-sm" }, status === "connecting" ? "Connecting..." : "Conversation started...")) : /* @__PURE__ */ React52.createElement(React52.Fragment, null, messages.map((msg, idx) => /* @__PURE__ */ React52.createElement(Message, { key: idx, from: msg.from }, msg.from === "assistant" && assistantAvatarSlot ? /* @__PURE__ */ React52.createElement(MessageAvatar, null, assistantAvatarSlot) : null, /* @__PURE__ */ React52.createElement(MessageContent, null, msg.text.replace(/^["']|["']$/g, "")))), /* @__PURE__ */ React52.createElement("div", { ref: messagesEndRef }))), inputMode !== "text" && isConnected && /* @__PURE__ */ React52.createElement("div", { className: "flex justify-center py-2 bg-background" }, mode === "listening" ? /* @__PURE__ */ React52.createElement("div", { className: "inline-flex items-center gap-2 px-4 py-2 bg-primary/5 rounded-full border border-primary/10" }, /* @__PURE__ */ React52.createElement("div", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }), /* @__PURE__ */ React52.createElement("span", { className: "text-sm font-medium text-foreground" }, "Listening")) : mode === "speaking" ? /* @__PURE__ */ React52.createElement(
10146
+ "button",
10147
+ {
10148
+ type: "button",
10149
+ className: "inline-flex items-center gap-2 px-4 py-2 bg-background rounded-full border border-border hover:border-primary transition-colors"
10150
+ },
10151
+ /* @__PURE__ */ React52.createElement(Mic, { className: "w-4 h-4 text-primary" }),
10152
+ /* @__PURE__ */ React52.createElement("span", { className: "text-sm font-medium text-foreground" }, "Talk to interrupt")
10153
+ ) : null), /* @__PURE__ */ React52.createElement("div", { className: "flex-none p-4 bg-background border-t border-border" }, showTextInput ? /* @__PURE__ */ React52.createElement("div", { className: "relative border-2 border-foreground rounded-2xl p-4 bg-background shadow-sm transition-all focus-within:shadow-md" }, /* @__PURE__ */ React52.createElement(
10154
+ "textarea",
10155
+ {
10156
+ 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",
10157
+ placeholder: "Send a message...",
10158
+ value: textInput,
10159
+ onChange: (e) => setTextInput(e.target.value),
10160
+ onKeyDown: (e) => {
10161
+ if (e.key === "Enter" && !e.shiftKey) {
10162
+ e.preventDefault();
10163
+ handleSend();
10164
+ }
10165
+ }
10166
+ }
10167
+ ), /* @__PURE__ */ React52.createElement("div", { className: "absolute bottom-4 right-4 flex items-center gap-3" }, onEndSession && /* @__PURE__ */ React52.createElement(
10168
+ "button",
10169
+ {
10170
+ type: "button",
10171
+ onClick: onEndSession,
10172
+ 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",
10173
+ title: "End session"
10174
+ },
10175
+ /* @__PURE__ */ React52.createElement(PhoneOff, { className: "w-5 h-5 text-foreground group-hover:text-destructive transition-colors" })
10176
+ ), /* @__PURE__ */ React52.createElement(
10177
+ "button",
10178
+ {
10179
+ type: "button",
10180
+ onClick: handleSend,
10181
+ disabled: !textInput.trim(),
10182
+ 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"
10183
+ },
10184
+ /* @__PURE__ */ React52.createElement(Send, { className: "w-5 h-5 ml-0.5" })
10185
+ ))) : onEndSession ? /* @__PURE__ */ React52.createElement(
10186
+ "button",
10187
+ {
10188
+ type: "button",
10189
+ onClick: onEndSession,
10190
+ 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"
10191
+ },
10192
+ /* @__PURE__ */ React52.createElement("span", { className: "w-2 h-2 bg-destructive rounded-full" }),
10193
+ "End Session"
10194
+ ) : null), footer);
10195
+ }
10196
+
10197
+ // registry/new-york/ui/agent-popover.tsx
10198
+ var AgentPopoverContext = React52.createContext(null);
10199
+ function useAgentPopover() {
10200
+ const ctx = React52.useContext(AgentPopoverContext);
10201
+ if (!ctx) throw new Error("useAgentPopover must be used within <AgentPopover>");
10202
+ return ctx;
10203
+ }
10204
+ function AgentPopover({
10205
+ open,
10206
+ onOpenChange,
10207
+ defaultStep = "details",
10208
+ step: controlledStep,
10209
+ onStepChange,
10210
+ children,
10211
+ className
10212
+ }) {
10213
+ const [uncontrolledStep, setUncontrolledStep] = React52.useState(defaultStep);
10214
+ const step = controlledStep != null ? controlledStep : uncontrolledStep;
10215
+ const setStep = React52.useCallback(
10216
+ (s) => {
10217
+ if (controlledStep === void 0) setUncontrolledStep(s);
10218
+ onStepChange == null ? void 0 : onStepChange(s);
10219
+ },
10220
+ [controlledStep, onStepChange]
10221
+ );
10222
+ React52.useEffect(() => {
10223
+ if (!open) return;
10224
+ const onKeyDown = (e) => {
10225
+ if (e.key === "Escape") onOpenChange(false);
10226
+ };
10227
+ document.addEventListener("keydown", onKeyDown);
10228
+ return () => document.removeEventListener("keydown", onKeyDown);
10229
+ }, [open, onOpenChange]);
10230
+ if (!open) return null;
10231
+ return /* @__PURE__ */ React52.createElement(AgentPopoverContext.Provider, { value: { step, setStep } }, /* @__PURE__ */ React52.createElement(
10232
+ "div",
10233
+ {
10234
+ className: "fixed inset-0 z-50 bg-black/30 backdrop-blur-sm animate-in fade-in duration-200",
10235
+ onClick: () => onOpenChange(false)
10236
+ }
10237
+ ), /* @__PURE__ */ React52.createElement(
10238
+ "div",
10239
+ {
10240
+ role: "dialog",
10241
+ "aria-modal": "true",
10242
+ className: cn(
10243
+ "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",
10244
+ "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]",
10245
+ className
10246
+ )
10247
+ },
10248
+ /* @__PURE__ */ React52.createElement(
10249
+ "button",
10250
+ {
10251
+ type: "button",
10252
+ onClick: () => onOpenChange(false),
10253
+ className: "absolute right-4 top-4 z-20 p-2 rounded-full bg-background/80 hover:bg-muted transition-colors text-foreground"
10254
+ },
10255
+ /* @__PURE__ */ React52.createElement(X, { className: "w-4 h-4" })
10256
+ ),
10257
+ children
10258
+ ));
10259
+ }
10260
+ function AgentPopoverBranding({
10261
+ title,
10262
+ subtitle,
10263
+ badge,
10264
+ visualSlot,
10265
+ statusIndicator = "ready",
10266
+ className
10267
+ }) {
10268
+ return /* @__PURE__ */ React52.createElement(
10269
+ "div",
10270
+ {
10271
+ className: cn(
10272
+ "relative hidden w-[40%] shrink-0 flex-col items-center justify-center p-8 md:flex",
10273
+ "bg-gradient-to-br from-primary/5 via-background to-primary/10",
10274
+ className
10275
+ )
10276
+ },
10277
+ /* @__PURE__ */ React52.createElement(
10278
+ "div",
10279
+ {
10280
+ className: "absolute inset-0 pointer-events-none opacity-[0.06]",
10281
+ style: {
10282
+ backgroundImage: "radial-gradient(circle, var(--primary) 1px, transparent 1px)",
10283
+ backgroundSize: "24px 24px"
10284
+ }
10285
+ }
10286
+ ),
10287
+ /* @__PURE__ */ React52.createElement("div", { className: "relative z-10 flex flex-col items-center gap-6 text-center" }, visualSlot && /* @__PURE__ */ React52.createElement("div", { className: "w-[200px] h-[200px] flex items-center justify-center" }, visualSlot), badge && /* @__PURE__ */ React52.createElement("span", { className: "inline-flex px-3 py-1 rounded-full bg-primary/10 text-primary text-xs font-medium border border-primary/10" }, badge), title && /* @__PURE__ */ React52.createElement("h2", { className: "text-xl font-semibold text-foreground" }, title), subtitle && /* @__PURE__ */ React52.createElement("p", { className: "text-sm text-muted-foreground max-w-[240px]" }, subtitle), /* @__PURE__ */ React52.createElement(StatusPill, { status: statusIndicator }))
10288
+ );
10289
+ }
10290
+ function StatusPill({ status }) {
10291
+ const label = {
10292
+ ready: "Ready to connect",
10293
+ connected: "Connected",
10294
+ listening: "Listening...",
10295
+ speaking: "Speaking..."
10296
+ };
10297
+ const dotColor = {
10298
+ ready: "bg-muted-foreground",
10299
+ connected: "bg-green-500",
10300
+ listening: "bg-green-500 animate-pulse",
10301
+ speaking: "bg-primary animate-pulse"
10302
+ };
10303
+ return /* @__PURE__ */ React52.createElement("div", { className: "flex items-center gap-2 rounded-full border border-border px-3 py-1.5 bg-background/50" }, /* @__PURE__ */ React52.createElement("div", { className: cn("h-2 w-2 rounded-full", dotColor[status]) }), /* @__PURE__ */ React52.createElement("span", { className: "text-xs text-muted-foreground" }, label[status]));
10304
+ }
10305
+ function AgentPopoverStepContent({ step, children, className }) {
10306
+ const { step: currentStep } = useAgentPopover();
10307
+ if (currentStep !== step) return null;
10308
+ return /* @__PURE__ */ React52.createElement("div", { className: cn("flex-1 flex flex-col overflow-hidden", className) }, children);
10309
+ }
10310
+ function AgentPopoverForm({
10311
+ fields = [],
10312
+ submitLabel = "Continue",
10313
+ onSubmit,
10314
+ className,
10315
+ children
10316
+ }) {
10317
+ const [values, setValues] = React52.useState({});
10318
+ const handleSubmit = (e) => {
10319
+ e.preventDefault();
10320
+ onSubmit == null ? void 0 : onSubmit(values);
10321
+ };
10322
+ return /* @__PURE__ */ React52.createElement(
10323
+ "form",
10324
+ {
10325
+ onSubmit: handleSubmit,
10326
+ className: cn("flex flex-col h-full p-8 overflow-y-auto", className)
10327
+ },
10328
+ /* @__PURE__ */ React52.createElement("div", { className: "flex-1 space-y-4" }, fields.map(
10329
+ (field) => {
10330
+ var _a, _b, _c;
10331
+ return field.type === "textarea" ? /* @__PURE__ */ React52.createElement("label", { key: field.name, className: "block space-y-1.5" }, /* @__PURE__ */ React52.createElement("span", { className: "text-sm font-medium text-foreground" }, field.label, field.required && /* @__PURE__ */ React52.createElement("span", { className: "text-destructive ml-0.5" }, "*")), /* @__PURE__ */ React52.createElement(
10332
+ "textarea",
10333
+ {
10334
+ 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",
10335
+ placeholder: field.placeholder,
10336
+ required: field.required,
10337
+ value: (_a = values[field.name]) != null ? _a : "",
10338
+ onChange: (e) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [field.name]: e.target.value }))
10339
+ }
10340
+ )) : /* @__PURE__ */ React52.createElement("label", { key: field.name, className: "block space-y-1.5" }, /* @__PURE__ */ React52.createElement("span", { className: "text-sm font-medium text-foreground" }, field.label, field.required && /* @__PURE__ */ React52.createElement("span", { className: "text-destructive ml-0.5" }, "*")), /* @__PURE__ */ React52.createElement(
10341
+ "input",
10342
+ {
10343
+ type: (_b = field.type) != null ? _b : "text",
10344
+ 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",
10345
+ placeholder: field.placeholder,
10346
+ required: field.required,
10347
+ value: (_c = values[field.name]) != null ? _c : "",
10348
+ onChange: (e) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [field.name]: e.target.value }))
10349
+ }
10350
+ ));
10351
+ }
10352
+ ), children),
10353
+ /* @__PURE__ */ React52.createElement(
10354
+ "button",
10355
+ {
10356
+ type: "submit",
10357
+ className: "mt-6 w-full px-6 py-3 rounded-full bg-primary text-primary-foreground hover:bg-primary/90 font-medium transition-colors"
10358
+ },
10359
+ submitLabel
10360
+ )
10361
+ );
10362
+ }
10363
+ function AgentPopoverOverview({
10364
+ userSummary,
10365
+ discussionPoints,
10366
+ actions,
10367
+ className
10368
+ }) {
10369
+ return /* @__PURE__ */ React52.createElement("div", { className: cn("flex flex-col h-full p-8 overflow-y-auto", className) }, userSummary && Object.keys(userSummary).length > 0 && /* @__PURE__ */ React52.createElement("div", { className: "mb-6 rounded-xl bg-muted/50 p-4 space-y-2" }, Object.entries(userSummary).map(([key, val]) => /* @__PURE__ */ React52.createElement("div", { key, className: "flex items-center justify-between text-sm" }, /* @__PURE__ */ React52.createElement("span", { className: "text-muted-foreground capitalize" }, key), /* @__PURE__ */ React52.createElement("span", { className: "text-foreground font-medium" }, val)))), discussionPoints && discussionPoints.length > 0 && /* @__PURE__ */ React52.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React52.createElement("h3", { className: "text-sm font-semibold text-foreground mb-3" }, "Discussion Points"), /* @__PURE__ */ React52.createElement("ul", { className: "space-y-2" }, discussionPoints.map((point, i) => /* @__PURE__ */ React52.createElement("li", { key: i, className: "flex items-start gap-2 text-sm text-foreground" }, /* @__PURE__ */ React52.createElement("div", { className: "mt-1.5 w-1.5 h-1.5 rounded-full bg-primary shrink-0" }), point)))), actions && /* @__PURE__ */ React52.createElement("div", { className: "mt-auto pt-6" }, actions));
10370
+ }
10371
+ function AgentPopoverChat({
10372
+ messages = [],
10373
+ onSendMessage,
10374
+ onEndSession,
10375
+ inputMode = "voice+text",
10376
+ visualSlot,
10377
+ assistantAvatarSlot,
10378
+ status = "connected",
10379
+ mode = null,
10380
+ className
10381
+ }) {
10382
+ return /* @__PURE__ */ React52.createElement(
10383
+ AgentWidget,
10384
+ {
10385
+ messages,
10386
+ onSendMessage,
10387
+ onEndSession,
10388
+ inputMode,
10389
+ visualSlot,
10390
+ assistantAvatarSlot,
10391
+ status,
10392
+ mode,
10393
+ className: cn("h-full", className)
10394
+ }
10395
+ );
10396
+ }
9460
10397
 
9461
- export { ActivityDetail, ActivityLog, ActivityRow, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartComponent, Button, CHART_CURSOR_STYLE, CHART_TOOLTIP_STYLE, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CheckInsCard, Citation, ConnectedApps, ContactList, DataTable, DataTableDisplay, DataTableFilter, DataTableQuickViews, DataTableToolbar, DetailViewHeader, DetailViewSummary, DetailViewThread, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DonutChart, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EntityActivityItem, EntityDetails, EntityMetadataGrid, EntityPanel, EntityPanelHeader, EntityPanelTabs, EntitySection, GroupedListView, InboxGroupHeader, InboxRow, InboxToolbar, Input, ItemList, ItemListDisplay, ItemListFilter, ItemListToolbar, Label2 as Label, MetricCard, PerformanceMetricsTable, PipelineOverview, PotentialContacts, PreviewList, PreviewListItem, Progress, PrototypeAccountsView, PrototypeInboxView, PrototypeInsightsView, PrototypeShell, PrototypeWorkQueueView, QuickActionChatArea, QuickActionModal, QuickActionSidebarNav, RecentActivity, RecentlyCompletedCard, RecommendedActionsSection, ReportCard, SankeyChart, ScoreAnalysisModal, ScoreAnalysisPanel, ScoreBreakdown, ScoreFeedback, ScoreRing, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignalApproval, Actions as SignalApprovalActions, Gate as SignalApprovalGate, Root as SignalApprovalRoot, SimpleChartTooltip, Skeleton, SourceList, StyledBarList, SuggestedActions, SystemActivity, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThreadMessage, TimelineActivity, Tooltip4 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopLineMetrics, TopTasksCard, TrendAreaChart, UpcomingMeetingsCard, ViewModeToggle, VolumeAnalysisChart, badgeVariants, buttonVariants, cn, getScoreColor, tabsListVariants, useIsMobile, useScoreFeedback, useSidebar, useSignalApproval };
10398
+ export { ActivityDetail, ActivityLog, ActivityRow, AgentOrb, AgentOrbCanvas, AgentPopover, AgentPopoverBranding, AgentPopoverChat, AgentPopoverForm, AgentPopoverOverview, AgentPopoverStepContent, AgentWidget, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartComponent, Button, CHART_CURSOR_STYLE, CHART_TOOLTIP_STYLE, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CheckInsCard, Citation, ConnectedApps, ContactList, DataTable, DataTableDisplay, DataTableFilter, DataTableQuickViews, DataTableToolbar, DetailViewHeader, DetailViewSummary, DetailViewThread, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DonutChart, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EntityActivityItem, EntityDetails, EntityMetadataGrid, EntityPanel, EntityPanelHeader, EntityPanelTabs, EntitySection, GroupedListView, InboxGroupHeader, InboxRow, InboxToolbar, Input, ItemList, ItemListDisplay, ItemListFilter, ItemListToolbar, Label2 as Label, Message, MessageAvatar, MessageContent, MetricCard, PerformanceMetricsTable, PipelineOverview, PotentialContacts, PreviewList, PreviewListItem, Progress, PrototypeAccountsView, PrototypeInboxView, PrototypeInsightsView, PrototypeShell, PrototypeWorkQueueView, QuickActionChatArea, QuickActionModal, QuickActionSidebarNav, RecentActivity, RecentlyCompletedCard, RecommendedActionsSection, ReportCard, SankeyChart, ScoreAnalysisModal, ScoreAnalysisPanel, ScoreBreakdown, ScoreFeedback, ScoreRing, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SignalApproval, Actions as SignalApprovalActions, Gate as SignalApprovalGate, Root as SignalApprovalRoot, SimpleChartTooltip, SimpleDataTable, Skeleton, SourceList, StatusBadge, StyledBarList, SuggestedActions, SystemActivity, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThreadMessage, TimelineActivity, Tooltip4 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TopLineMetrics, TopTasksCard, TrendAreaChart, UpcomingMeetingsCard, ViewModeToggle, VolumeAnalysisChart, badgeVariants, buttonVariants, cn, getScoreColor, tabsListVariants, useAgentPopover, useIsMobile, useScoreFeedback, useSidebar, useSignalApproval };
9462
10399
  //# sourceMappingURL=index.js.map
9463
10400
  //# sourceMappingURL=index.js.map