@avatarfirst/react 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,1731 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AvatarAgent: () => AvatarAgent,
24
+ AvatarContext: () => AvatarContext,
25
+ AvatarFallback: () => AvatarFallback,
26
+ AvatarFirst: () => AvatarFirst,
27
+ AvatarProvider: () => AvatarProvider,
28
+ AvatarView: () => AvatarView,
29
+ CalendarOverlay: () => CalendarOverlay,
30
+ CardOverlay: () => CardOverlay,
31
+ ChartOverlay: () => ChartOverlay,
32
+ ChatOverlay: () => ChatOverlay,
33
+ ComparisonOverlay: () => ComparisonOverlay,
34
+ ConfirmOverlay: () => ConfirmOverlay,
35
+ DetailCardOverlay: () => DetailCardOverlay,
36
+ FileUploadOverlay: () => FileUploadOverlay,
37
+ FormOverlay: () => FormOverlay,
38
+ InsightOverlay: () => InsightOverlay,
39
+ MapOverlay: () => MapOverlay,
40
+ MediaOverlay: () => MediaOverlay,
41
+ OverlayContainer: () => OverlayContainer,
42
+ ProgressOverlay: () => ProgressOverlay,
43
+ RichTextOverlay: () => RichTextOverlay,
44
+ TableOverlay: () => TableOverlay,
45
+ avatarPulse: () => avatarPulse,
46
+ cardHover: () => cardHover,
47
+ cn: () => cn,
48
+ fadeIn: () => fadeIn,
49
+ fadeInUp: () => fadeInUp,
50
+ getOverlayVariants: () => getOverlayVariants,
51
+ pageTransition: () => pageTransition,
52
+ scaleIn: () => scaleIn,
53
+ slideIn: () => slideIn,
54
+ staggerContainer: () => staggerContainer,
55
+ useAction: () => useAction,
56
+ useAvatar: () => useAvatar,
57
+ useAvatarEvent: () => useAvatarEvent,
58
+ useAvatarFirst: () => useAvatarFirst,
59
+ useOverlay: () => useOverlay
60
+ });
61
+ module.exports = __toCommonJS(index_exports);
62
+
63
+ // src/context/AvatarProvider.tsx
64
+ var import_react2 = require("react");
65
+
66
+ // src/context/AvatarContext.ts
67
+ var import_react = require("react");
68
+ var AvatarContext = (0, import_react.createContext)(null);
69
+
70
+ // src/context/AvatarProvider.tsx
71
+ var import_jsx_runtime = require("react/jsx-runtime");
72
+ function AvatarProvider({ agent, autoStart = false, children }) {
73
+ const [state, setState] = (0, import_react2.useState)(agent.getState());
74
+ const [overlays, setOverlays] = (0, import_react2.useState)(agent.getVisibleOverlays());
75
+ (0, import_react2.useEffect)(() => {
76
+ const unsubState = agent.on("state:changed", ({ to }) => {
77
+ setState(to);
78
+ });
79
+ const unsubOverlay = agent.overlays.events.on("overlay:change", (visible) => {
80
+ setOverlays([...visible]);
81
+ });
82
+ if (autoStart) {
83
+ agent.start();
84
+ }
85
+ return () => {
86
+ unsubState();
87
+ unsubOverlay();
88
+ };
89
+ }, [agent, autoStart]);
90
+ const isConnected = state === "connected" || state === "speaking" || state === "listening" || state === "thinking";
91
+ const value = (0, import_react2.useMemo)(
92
+ () => ({ agent, state, isConnected, overlays }),
93
+ [agent, state, isConnected, overlays]
94
+ );
95
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AvatarContext.Provider, { value, children });
96
+ }
97
+
98
+ // src/hooks/useAvatar.ts
99
+ var import_react3 = require("react");
100
+ function useAvatar() {
101
+ const ctx = (0, import_react3.useContext)(AvatarContext);
102
+ if (!ctx) {
103
+ throw new Error("useAvatar must be used within an AvatarProvider");
104
+ }
105
+ const { agent, state, isConnected } = ctx;
106
+ const start = (0, import_react3.useCallback)(async () => {
107
+ await agent?.start();
108
+ }, [agent]);
109
+ const stop = (0, import_react3.useCallback)(async () => {
110
+ await agent?.stop();
111
+ }, [agent]);
112
+ const speak = (0, import_react3.useCallback)(
113
+ async (text) => {
114
+ await agent?.speak(text);
115
+ },
116
+ [agent]
117
+ );
118
+ const message = (0, import_react3.useCallback)(
119
+ async (text) => {
120
+ await agent?.message(text);
121
+ },
122
+ [agent]
123
+ );
124
+ const interrupt = (0, import_react3.useCallback)(async () => {
125
+ await agent?.interrupt();
126
+ }, [agent]);
127
+ const startListening = (0, import_react3.useCallback)(() => {
128
+ agent?.startListening();
129
+ }, [agent]);
130
+ const stopListening = (0, import_react3.useCallback)(() => {
131
+ agent?.stopListening();
132
+ }, [agent]);
133
+ const attachVideoElement = (0, import_react3.useCallback)(
134
+ (el) => {
135
+ agent?.attachVideoElement(el);
136
+ },
137
+ [agent]
138
+ );
139
+ return {
140
+ agent,
141
+ state,
142
+ isConnected,
143
+ start,
144
+ stop,
145
+ speak,
146
+ message,
147
+ interrupt,
148
+ startListening,
149
+ stopListening,
150
+ attachVideoElement
151
+ };
152
+ }
153
+
154
+ // src/hooks/useOverlay.ts
155
+ var import_react4 = require("react");
156
+ function useOverlay(overlayId) {
157
+ const ctx = (0, import_react4.useContext)(AvatarContext);
158
+ if (!ctx) {
159
+ throw new Error("useOverlay must be used within an AvatarProvider");
160
+ }
161
+ const { agent, overlays } = ctx;
162
+ const isVisible = (0, import_react4.useMemo)(() => {
163
+ if (!overlayId) return false;
164
+ return overlays.some((o) => o.id === overlayId);
165
+ }, [overlayId, overlays]);
166
+ const overlayData = (0, import_react4.useMemo)(() => {
167
+ if (!overlayId) return void 0;
168
+ return overlays.find((o) => o.id === overlayId);
169
+ }, [overlayId, overlays]);
170
+ const show = (0, import_react4.useCallback)(
171
+ (config) => {
172
+ agent?.showOverlay(config);
173
+ },
174
+ [agent]
175
+ );
176
+ const hide = (0, import_react4.useCallback)(
177
+ (id) => {
178
+ agent?.hideOverlay(id ?? overlayId ?? "");
179
+ },
180
+ [agent, overlayId]
181
+ );
182
+ return {
183
+ overlays,
184
+ isVisible,
185
+ overlayData,
186
+ show,
187
+ hide
188
+ };
189
+ }
190
+
191
+ // src/hooks/useAvatarEvent.ts
192
+ var import_react5 = require("react");
193
+ function useAvatarEvent(event, handler) {
194
+ const ctx = (0, import_react5.useContext)(AvatarContext);
195
+ if (!ctx) {
196
+ throw new Error("useAvatarEvent must be used within an AvatarProvider");
197
+ }
198
+ (0, import_react5.useEffect)(() => {
199
+ if (!ctx.agent) return;
200
+ const unsub = ctx.agent.on(event, handler);
201
+ return unsub;
202
+ }, [ctx.agent, event, handler]);
203
+ }
204
+
205
+ // src/hooks/useAction.ts
206
+ var import_react6 = require("react");
207
+ function useAction() {
208
+ const ctx = (0, import_react6.useContext)(AvatarContext);
209
+ if (!ctx) {
210
+ throw new Error("useAction must be used within an AvatarProvider");
211
+ }
212
+ const trigger = (0, import_react6.useCallback)(
213
+ (actionId) => {
214
+ ctx.agent?.triggerAction(actionId);
215
+ },
216
+ [ctx.agent]
217
+ );
218
+ return { trigger };
219
+ }
220
+
221
+ // src/hooks/useAvatarFirst.ts
222
+ var import_react7 = require("react");
223
+ var import_core = require("@avatarfirst/core");
224
+ function useAvatarFirst(options) {
225
+ const [state, setState] = (0, import_react7.useState)("idle");
226
+ const [sessionId, setSessionId] = (0, import_react7.useState)(null);
227
+ const [greeting, setGreeting] = (0, import_react7.useState)(null);
228
+ const [avatarToken, setAvatarToken] = (0, import_react7.useState)(null);
229
+ const [overlays, setOverlays] = (0, import_react7.useState)([]);
230
+ const [isProcessing, setIsProcessing] = (0, import_react7.useState)(false);
231
+ const [error, setError] = (0, import_react7.useState)(null);
232
+ const clientRef = (0, import_react7.useRef)(null);
233
+ const optionsRef = (0, import_react7.useRef)(options);
234
+ optionsRef.current = options;
235
+ (0, import_react7.useEffect)(() => {
236
+ clientRef.current = new import_core.AvatarFirstClient({
237
+ apiKey: options.apiKey,
238
+ baseUrl: options.baseUrl
239
+ });
240
+ }, [options.apiKey, options.baseUrl]);
241
+ const connect = (0, import_react7.useCallback)(async () => {
242
+ if (!clientRef.current) return null;
243
+ setState("connecting");
244
+ setError(null);
245
+ optionsRef.current.onStateChange?.("connecting");
246
+ try {
247
+ const session = await clientRef.current.createSession();
248
+ setSessionId(session.sessionId);
249
+ setGreeting(session.greeting);
250
+ setAvatarToken(session.avatar ?? null);
251
+ setState("connected");
252
+ optionsRef.current.onStateChange?.("connected");
253
+ return session;
254
+ } catch (err) {
255
+ const msg = err.message;
256
+ setError(msg);
257
+ setState("error");
258
+ optionsRef.current.onStateChange?.("error");
259
+ return null;
260
+ }
261
+ }, []);
262
+ const sendMessage = (0, import_react7.useCallback)(async (text) => {
263
+ if (!clientRef.current || !sessionId || isProcessing) return null;
264
+ setIsProcessing(true);
265
+ try {
266
+ const response = await clientRef.current.sendMessage(sessionId, text);
267
+ if (response.overlay) {
268
+ setOverlays((prev) => [...prev, response.overlay]);
269
+ optionsRef.current.onOverlay?.(response.overlay);
270
+ }
271
+ if (response.actions) {
272
+ for (const action of response.actions) {
273
+ optionsRef.current.onAction?.(action);
274
+ }
275
+ }
276
+ setIsProcessing(false);
277
+ return response;
278
+ } catch (err) {
279
+ setError(err.message);
280
+ setIsProcessing(false);
281
+ return null;
282
+ }
283
+ }, [sessionId, isProcessing]);
284
+ const disconnect = (0, import_react7.useCallback)(() => {
285
+ if (clientRef.current && sessionId) {
286
+ clientRef.current.endSession(sessionId);
287
+ }
288
+ setSessionId(null);
289
+ setGreeting(null);
290
+ setAvatarToken(null);
291
+ setOverlays([]);
292
+ setState("idle");
293
+ optionsRef.current.onStateChange?.("idle");
294
+ }, [sessionId]);
295
+ return {
296
+ state,
297
+ sessionId,
298
+ greeting,
299
+ avatarToken,
300
+ overlays,
301
+ isProcessing,
302
+ error,
303
+ connect,
304
+ sendMessage,
305
+ disconnect
306
+ };
307
+ }
308
+
309
+ // src/components/overlays/OverlayContainer.tsx
310
+ var import_framer_motion = require("framer-motion");
311
+
312
+ // src/animations/overlayAnimations.ts
313
+ function getOverlayVariants(animation = "fade") {
314
+ if (typeof animation === "object") {
315
+ return {
316
+ initial: animation.enter,
317
+ animate: animation.enter,
318
+ exit: animation.exit
319
+ };
320
+ }
321
+ switch (animation) {
322
+ case "fade":
323
+ return {
324
+ initial: { opacity: 0 },
325
+ animate: { opacity: 1, transition: { duration: 0.3 } },
326
+ exit: { opacity: 0, transition: { duration: 0.2 } }
327
+ };
328
+ case "slide-up":
329
+ return {
330
+ initial: { opacity: 0, y: 40 },
331
+ animate: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 25 } },
332
+ exit: { opacity: 0, y: 40, transition: { duration: 0.2 } }
333
+ };
334
+ case "slide-down":
335
+ return {
336
+ initial: { opacity: 0, y: -40 },
337
+ animate: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 25 } },
338
+ exit: { opacity: 0, y: -40, transition: { duration: 0.2 } }
339
+ };
340
+ case "slide-left":
341
+ return {
342
+ initial: { opacity: 0, x: 40 },
343
+ animate: { opacity: 1, x: 0, transition: { type: "spring", stiffness: 300, damping: 25 } },
344
+ exit: { opacity: 0, x: 40, transition: { duration: 0.2 } }
345
+ };
346
+ case "slide-right":
347
+ return {
348
+ initial: { opacity: 0, x: -40 },
349
+ animate: { opacity: 1, x: 0, transition: { type: "spring", stiffness: 300, damping: 25 } },
350
+ exit: { opacity: 0, x: -40, transition: { duration: 0.2 } }
351
+ };
352
+ case "scale":
353
+ return {
354
+ initial: { opacity: 0, scale: 0.85 },
355
+ animate: { opacity: 1, scale: 1, transition: { type: "spring", stiffness: 300, damping: 25 } },
356
+ exit: { opacity: 0, scale: 0.85, transition: { duration: 0.2 } }
357
+ };
358
+ case "none":
359
+ return {
360
+ initial: {},
361
+ animate: {},
362
+ exit: {}
363
+ };
364
+ default:
365
+ return {
366
+ initial: { opacity: 0 },
367
+ animate: { opacity: 1 },
368
+ exit: { opacity: 0 }
369
+ };
370
+ }
371
+ }
372
+
373
+ // src/components/overlays/OverlayContainer.tsx
374
+ var import_jsx_runtime2 = require("react/jsx-runtime");
375
+ function getPositionStyles(position = "bottom-center") {
376
+ if (typeof position === "object") {
377
+ return { position: "absolute", left: position.x, top: position.y };
378
+ }
379
+ const base = { position: "absolute" };
380
+ switch (position) {
381
+ case "center":
382
+ return { ...base, top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
383
+ case "bottom-center":
384
+ return { ...base, bottom: "2rem", left: "50%", transform: "translateX(-50%)" };
385
+ case "bottom-right":
386
+ return { ...base, bottom: "2rem", right: "2rem" };
387
+ case "bottom-left":
388
+ return { ...base, bottom: "2rem", left: "2rem" };
389
+ case "top-center":
390
+ return { ...base, top: "2rem", left: "50%", transform: "translateX(-50%)" };
391
+ case "right-center":
392
+ return { ...base, top: "50%", right: "2rem", transform: "translateY(-50%)" };
393
+ case "fullscreen":
394
+ return { ...base, inset: 0 };
395
+ default:
396
+ return { ...base, bottom: "2rem", left: "50%", transform: "translateX(-50%)" };
397
+ }
398
+ }
399
+ function OverlayContainer({ components }) {
400
+ const { overlays, hide } = useOverlay();
401
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fixed inset-0 pointer-events-none z-40", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_framer_motion.AnimatePresence, { children: overlays.map((overlay) => {
402
+ const Component = components[overlay.component];
403
+ if (!Component) return null;
404
+ const variants = getOverlayVariants(overlay.animation);
405
+ const positionStyle = getPositionStyles(overlay.position);
406
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
407
+ import_framer_motion.motion.div,
408
+ {
409
+ variants,
410
+ initial: "initial",
411
+ animate: "animate",
412
+ exit: "exit",
413
+ style: positionStyle,
414
+ className: "pointer-events-auto",
415
+ onClick: overlay.dismissOnClickOutside ? (e) => {
416
+ if (e.target === e.currentTarget) hide(overlay.id);
417
+ } : void 0,
418
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
419
+ Component,
420
+ {
421
+ data: overlay.data,
422
+ overlayId: overlay.id,
423
+ onDismiss: () => hide(overlay.id)
424
+ }
425
+ )
426
+ },
427
+ overlay.id
428
+ );
429
+ }) }) });
430
+ }
431
+
432
+ // src/components/AvatarAgent.tsx
433
+ var import_jsx_runtime3 = require("react/jsx-runtime");
434
+ function AvatarAgent({
435
+ config,
436
+ overlayComponents = {},
437
+ autoStart = false,
438
+ children
439
+ }) {
440
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(AvatarProvider, { agent: config, autoStart, children: [
441
+ children,
442
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(OverlayContainer, { components: overlayComponents })
443
+ ] });
444
+ }
445
+
446
+ // src/components/AvatarFirst.tsx
447
+ var import_react14 = require("react");
448
+ var import_core2 = require("@avatarfirst/core");
449
+
450
+ // src/components/AvatarView.tsx
451
+ var import_react8 = require("react");
452
+ var import_framer_motion3 = require("framer-motion");
453
+
454
+ // src/components/AvatarFallback.tsx
455
+ var import_framer_motion2 = require("framer-motion");
456
+ var import_jsx_runtime4 = require("react/jsx-runtime");
457
+ function AvatarFallback({ size, state }) {
458
+ const isSmall = size === "small";
459
+ const isMedium = size === "medium";
460
+ const faceSize = isSmall ? "w-12 h-12" : isMedium ? "w-24 h-24" : "w-full h-full";
461
+ const eyeSize = isSmall ? 4 : isMedium ? 6 : 12;
462
+ const mouthWidth = isSmall ? 15 : isMedium ? 25 : 50;
463
+ if (state === "connecting") {
464
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative w-full h-full flex items-center justify-center", children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
466
+ import_framer_motion2.motion.div,
467
+ {
468
+ className: "absolute inset-4 rounded-full border-4 border-blue-500/30",
469
+ animate: { scale: [1, 1.2, 1], opacity: [0.5, 0, 0.5] },
470
+ transition: { duration: 2, repeat: Infinity }
471
+ }
472
+ ),
473
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
474
+ import_framer_motion2.motion.div,
475
+ {
476
+ className: "absolute inset-8 rounded-full border-4 border-purple-500/30",
477
+ animate: { scale: [1, 1.3, 1], opacity: [0.5, 0, 0.5] },
478
+ transition: { duration: 2, repeat: Infinity, delay: 0.3 }
479
+ }
480
+ ),
481
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
482
+ import_framer_motion2.motion.div,
483
+ {
484
+ className: "w-10 h-10 border-4 border-white/30 border-t-white rounded-full",
485
+ animate: { rotate: 360 },
486
+ transition: { duration: 1, repeat: Infinity, ease: "linear" }
487
+ }
488
+ )
489
+ ] });
490
+ }
491
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `relative ${faceSize}`, children: [
492
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
493
+ import_framer_motion2.motion.div,
494
+ {
495
+ className: "absolute inset-0 rounded-full bg-gradient-to-br from-blue-400 via-purple-500 to-pink-500",
496
+ animate: {
497
+ background: [
498
+ "linear-gradient(135deg, #60a5fa, #a855f7, #ec4899)",
499
+ "linear-gradient(135deg, #a855f7, #ec4899, #60a5fa)",
500
+ "linear-gradient(135deg, #ec4899, #60a5fa, #a855f7)",
501
+ "linear-gradient(135deg, #60a5fa, #a855f7, #ec4899)"
502
+ ]
503
+ },
504
+ transition: { duration: 8, repeat: Infinity, ease: "linear" }
505
+ }
506
+ ),
507
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute inset-2 rounded-full bg-gradient-to-br from-white/30 to-transparent" }),
508
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { viewBox: "0 0 100 100", className: "absolute inset-0 w-full h-full", children: [
509
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
510
+ import_framer_motion2.motion.ellipse,
511
+ {
512
+ cx: "35",
513
+ cy: "42",
514
+ rx: eyeSize,
515
+ ry: eyeSize,
516
+ fill: "white",
517
+ animate: { ry: [eyeSize, eyeSize * 0.1, eyeSize] },
518
+ transition: { duration: 0.15, repeat: Infinity, repeatDelay: 4, times: [0, 0.5, 1] }
519
+ }
520
+ ),
521
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
522
+ import_framer_motion2.motion.circle,
523
+ {
524
+ cx: "35",
525
+ cy: "42",
526
+ r: eyeSize * 0.5,
527
+ fill: "#1e293b",
528
+ animate: { cx: [35, 37, 35, 33, 35] },
529
+ transition: { duration: 3, repeat: Infinity, ease: "easeInOut" }
530
+ }
531
+ ),
532
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "37", cy: "40", r: eyeSize * 0.2, fill: "white", opacity: "0.8" }),
533
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
534
+ import_framer_motion2.motion.ellipse,
535
+ {
536
+ cx: "65",
537
+ cy: "42",
538
+ rx: eyeSize,
539
+ ry: eyeSize,
540
+ fill: "white",
541
+ animate: { ry: [eyeSize, eyeSize * 0.1, eyeSize] },
542
+ transition: { duration: 0.15, repeat: Infinity, repeatDelay: 4, times: [0, 0.5, 1] }
543
+ }
544
+ ),
545
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
546
+ import_framer_motion2.motion.circle,
547
+ {
548
+ cx: "65",
549
+ cy: "42",
550
+ r: eyeSize * 0.5,
551
+ fill: "#1e293b",
552
+ animate: { cx: [65, 67, 65, 63, 65] },
553
+ transition: { duration: 3, repeat: Infinity, ease: "easeInOut" }
554
+ }
555
+ ),
556
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "67", cy: "40", r: eyeSize * 0.2, fill: "white", opacity: "0.8" }),
557
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
558
+ import_framer_motion2.motion.path,
559
+ {
560
+ d: state === "speaking" ? `M ${50 - mouthWidth / 2} 62 Q 50 75 ${50 + mouthWidth / 2} 62` : `M ${50 - mouthWidth / 2} 65 Q 50 72 ${50 + mouthWidth / 2} 65`,
561
+ stroke: "white",
562
+ strokeWidth: isSmall ? 2 : isMedium ? 3 : 4,
563
+ fill: state === "speaking" ? "rgba(255,255,255,0.3)" : "none",
564
+ strokeLinecap: "round",
565
+ animate: state === "speaking" ? {
566
+ d: [
567
+ `M ${50 - mouthWidth / 2} 62 Q 50 75 ${50 + mouthWidth / 2} 62`,
568
+ `M ${50 - mouthWidth / 2} 62 Q 50 68 ${50 + mouthWidth / 2} 62`,
569
+ `M ${50 - mouthWidth / 2} 62 Q 50 78 ${50 + mouthWidth / 2} 62`,
570
+ `M ${50 - mouthWidth / 2} 62 Q 50 70 ${50 + mouthWidth / 2} 62`
571
+ ]
572
+ } : {},
573
+ transition: { duration: 0.3, repeat: Infinity, ease: "easeInOut" }
574
+ }
575
+ )
576
+ ] })
577
+ ] });
578
+ }
579
+
580
+ // src/components/AvatarView.tsx
581
+ var import_jsx_runtime5 = require("react/jsx-runtime");
582
+ var sizeClasses = {
583
+ small: "w-16 h-16",
584
+ medium: "w-32 h-32",
585
+ large: "w-64 h-64",
586
+ fullscreen: "w-full h-full",
587
+ hero: "w-[500px] h-[500px]"
588
+ };
589
+ function AvatarView({ size = "medium", showStatus = true, className = "" }) {
590
+ const { state, attachVideoElement } = useAvatar();
591
+ const videoRef = (0, import_react8.useRef)(null);
592
+ (0, import_react8.useEffect)(() => {
593
+ if (videoRef.current) {
594
+ attachVideoElement(videoRef.current);
595
+ }
596
+ }, [attachVideoElement]);
597
+ const isConnected = state === "connected" || state === "speaking" || state === "listening" || state === "thinking";
598
+ const isFullscreen = size === "fullscreen";
599
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `relative ${className}`, children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
601
+ import_framer_motion3.motion.div,
602
+ {
603
+ className: `relative overflow-hidden ${isFullscreen ? "rounded-2xl" : "rounded-full"} ${sizeClasses[size]}`,
604
+ animate: {
605
+ scale: state === "speaking" ? [1, 1.02, 1] : 1
606
+ },
607
+ transition: {
608
+ duration: state === "speaking" ? 0.5 : 0.3,
609
+ repeat: state === "speaking" ? Infinity : 0
610
+ },
611
+ children: [
612
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
613
+ "video",
614
+ {
615
+ ref: videoRef,
616
+ autoPlay: true,
617
+ playsInline: true,
618
+ className: `absolute inset-0 w-full h-full object-cover ${!isConnected ? "hidden" : ""}`
619
+ }
620
+ ),
621
+ !isConnected && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-gradient-to-br from-slate-800 to-slate-900", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AvatarFallback, { state, size }) }),
622
+ state === "connecting" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
623
+ import_framer_motion3.motion.div,
624
+ {
625
+ className: "absolute inset-0 rounded-full border-4 border-yellow-500",
626
+ animate: { rotate: 360 },
627
+ transition: { duration: 2, repeat: Infinity, ease: "linear" },
628
+ style: { borderTopColor: "transparent", borderLeftColor: "transparent" }
629
+ }
630
+ ),
631
+ state === "connected" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
632
+ import_framer_motion3.motion.div,
633
+ {
634
+ className: "absolute inset-0 rounded-full border-4 border-green-500/50",
635
+ animate: { opacity: [0.3, 0.6, 0.3] },
636
+ transition: { duration: 2, repeat: Infinity }
637
+ }
638
+ ),
639
+ state === "speaking" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
640
+ import_framer_motion3.motion.div,
641
+ {
642
+ className: "absolute inset-0 rounded-full border-4 border-blue-400",
643
+ animate: { scale: [1, 1.03, 1], opacity: [0.7, 1, 0.7] },
644
+ transition: { duration: 0.5, repeat: Infinity }
645
+ }
646
+ )
647
+ ]
648
+ }
649
+ ),
650
+ showStatus && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
651
+ import_framer_motion3.motion.div,
652
+ {
653
+ className: `absolute flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium shadow-lg ${state === "disconnected" ? "bg-slate-600 text-white" : state === "connecting" ? "bg-yellow-500 text-white" : state === "connected" ? "bg-green-500 text-white" : state === "speaking" ? "bg-blue-500 text-white" : state === "listening" ? "bg-purple-500 text-white" : "bg-slate-600 text-white"} ${size === "small" ? "-bottom-1 -right-1 text-[10px] px-1.5 py-0.5" : size === "medium" ? "bottom-0 right-0" : size === "large" ? "bottom-2 right-2" : "bottom-4 right-4 text-sm px-3 py-1.5"}`,
654
+ initial: { scale: 0 },
655
+ animate: { scale: 1 },
656
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "capitalize", children: state === "disconnected" ? "Offline" : state })
657
+ },
658
+ state
659
+ )
660
+ ] });
661
+ }
662
+
663
+ // src/components/overlays/CardOverlay.tsx
664
+ var import_jsx_runtime6 = require("react/jsx-runtime");
665
+ function CardOverlay({ data, onDismiss }) {
666
+ const { title, description, items, actions } = data ?? {};
667
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[300px] max-w-md", children: [
668
+ title && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-lg font-semibold mb-1", children: title }),
669
+ description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-sm text-gray-500 mb-4", children: description }),
670
+ items && items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "space-y-2 mb-4", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between py-2 border-b border-gray-100 last:border-0", children: [
671
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm font-medium text-gray-700", children: item.label }),
672
+ item.value && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm text-gray-500", children: item.value })
673
+ ] }, i)) }),
674
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2 justify-end", children: [
675
+ actions?.map((action, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
676
+ "button",
677
+ {
678
+ onClick: action.onClick,
679
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
680
+ children: action.label
681
+ },
682
+ i
683
+ )),
684
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
685
+ "button",
686
+ {
687
+ onClick: onDismiss,
688
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
689
+ children: "Close"
690
+ }
691
+ )
692
+ ] })
693
+ ] });
694
+ }
695
+
696
+ // src/components/overlays/FormOverlay.tsx
697
+ var import_react9 = require("react");
698
+ var import_jsx_runtime7 = require("react/jsx-runtime");
699
+ function FormOverlay({ data, onDismiss }) {
700
+ const { title, fields = [], submitLabel = "Submit", onSubmit } = data ?? {};
701
+ const [values, setValues] = (0, import_react9.useState)({});
702
+ const handleSubmit = (e) => {
703
+ e.preventDefault();
704
+ onSubmit?.(values);
705
+ onDismiss();
706
+ };
707
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-md", children: [
708
+ title && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
709
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-3", children: [
710
+ fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
711
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: field.label }),
712
+ field.type === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
713
+ "textarea",
714
+ {
715
+ className: "w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500",
716
+ placeholder: field.placeholder,
717
+ required: field.required,
718
+ value: values[field.name] ?? "",
719
+ onChange: (e) => setValues((v) => ({ ...v, [field.name]: e.target.value }))
720
+ }
721
+ ) : field.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
722
+ "select",
723
+ {
724
+ className: "w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500",
725
+ required: field.required,
726
+ value: values[field.name] ?? "",
727
+ onChange: (e) => setValues((v) => ({ ...v, [field.name]: e.target.value })),
728
+ children: [
729
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: field.placeholder ?? "Select..." }),
730
+ field.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: opt, children: opt }, opt))
731
+ ]
732
+ }
733
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
734
+ "input",
735
+ {
736
+ type: field.type ?? "text",
737
+ className: "w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500",
738
+ placeholder: field.placeholder,
739
+ required: field.required,
740
+ value: values[field.name] ?? "",
741
+ onChange: (e) => setValues((v) => ({ ...v, [field.name]: e.target.value }))
742
+ }
743
+ )
744
+ ] }, field.name)),
745
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2 justify-end pt-2", children: [
746
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
747
+ "button",
748
+ {
749
+ type: "submit",
750
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
751
+ children: submitLabel
752
+ }
753
+ ),
754
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
755
+ "button",
756
+ {
757
+ type: "button",
758
+ onClick: onDismiss,
759
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
760
+ children: "Cancel"
761
+ }
762
+ )
763
+ ] })
764
+ ] })
765
+ ] });
766
+ }
767
+
768
+ // src/components/overlays/TableOverlay.tsx
769
+ var import_jsx_runtime8 = require("react/jsx-runtime");
770
+ function TableOverlay({ data, onDismiss }) {
771
+ const { title, columns = [], rows = [] } = data ?? {};
772
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[400px] max-w-2xl overflow-x-auto", children: [
773
+ title && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
774
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-lg font-semibold", children: title }),
775
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: onDismiss, className: "text-gray-400 hover:text-gray-600 text-sm", children: "Close" })
776
+ ] }),
777
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("table", { className: "w-full", children: [
778
+ columns.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { className: "border-b", children: columns.map((col, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("th", { className: "text-left py-2 px-3 text-sm font-medium text-gray-500", children: col }, i)) }) }),
779
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tbody", { children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { className: "border-b last:border-0 hover:bg-gray-50", children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { className: "py-2 px-3 text-sm text-gray-700", children: cell }, j)) }, i)) })
780
+ ] })
781
+ ] });
782
+ }
783
+
784
+ // src/components/overlays/ProgressOverlay.tsx
785
+ var import_jsx_runtime9 = require("react/jsx-runtime");
786
+ function ProgressOverlay({ data, onDismiss }) {
787
+ const { title, steps = [] } = data ?? {};
788
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
789
+ title && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
790
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "space-y-3", children: steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-3", children: [
791
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
792
+ "div",
793
+ {
794
+ className: `w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium ${step.completed ? "bg-green-500 text-white" : step.active ? "bg-blue-500 text-white" : "bg-gray-100 text-gray-400"}`,
795
+ children: step.completed ? "\u2713" : i + 1
796
+ }
797
+ ),
798
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: `text-sm ${step.completed ? "text-gray-500 line-through" : step.active ? "text-gray-900 font-medium" : "text-gray-400"}`, children: step.label })
799
+ ] }, i)) }),
800
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
801
+ "button",
802
+ {
803
+ onClick: onDismiss,
804
+ className: "mt-4 w-full py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
805
+ children: "Close"
806
+ }
807
+ )
808
+ ] });
809
+ }
810
+
811
+ // src/components/overlays/ConfirmOverlay.tsx
812
+ var import_jsx_runtime10 = require("react/jsx-runtime");
813
+ function ConfirmOverlay({ data, onDismiss }) {
814
+ const { title, message, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel } = data ?? {};
815
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[300px] max-w-sm", children: [
816
+ title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-lg font-semibold mb-2", children: title }),
817
+ message && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-gray-500 mb-6", children: message }),
818
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-3", children: [
819
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
820
+ "button",
821
+ {
822
+ onClick: () => {
823
+ onConfirm?.();
824
+ onDismiss();
825
+ },
826
+ className: "flex-1 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
827
+ children: confirmLabel
828
+ }
829
+ ),
830
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
831
+ "button",
832
+ {
833
+ onClick: () => {
834
+ onCancel?.();
835
+ onDismiss();
836
+ },
837
+ className: "flex-1 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
838
+ children: cancelLabel
839
+ }
840
+ )
841
+ ] })
842
+ ] });
843
+ }
844
+
845
+ // src/components/overlays/ChatOverlay.tsx
846
+ var import_react10 = require("react");
847
+ var import_framer_motion4 = require("framer-motion");
848
+ var import_jsx_runtime11 = require("react/jsx-runtime");
849
+ function ChatOverlay({ data, onDismiss }) {
850
+ const { title = "Chat", messages: initialMessages = [], suggestions = [] } = data ?? {};
851
+ const [messages, setMessages] = (0, import_react10.useState)(initialMessages);
852
+ const [input, setInput] = (0, import_react10.useState)("");
853
+ const { speak } = useAvatar();
854
+ const handleSend = async () => {
855
+ if (!input.trim()) return;
856
+ const userMsg = {
857
+ id: Date.now().toString(),
858
+ role: "user",
859
+ content: input,
860
+ timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
861
+ };
862
+ setMessages((prev) => [...prev, userMsg]);
863
+ setInput("");
864
+ await speak(`I understand you want to ${input.toLowerCase()}. Let me help you with that.`);
865
+ const aiMsg = {
866
+ id: (Date.now() + 1).toString(),
867
+ role: "assistant",
868
+ content: `I'll help you ${input.toLowerCase()}. This action has been queued.`,
869
+ timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
870
+ };
871
+ setMessages((prev) => [...prev, aiMsg]);
872
+ };
873
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl overflow-hidden w-96 flex flex-col", style: { maxHeight: "500px" }, children: [
874
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "bg-gradient-to-r from-blue-500 to-blue-600 p-4 flex items-center justify-between", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { className: "text-white font-semibold", children: title }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: onDismiss, className: "text-white/70 hover:text-white text-sm", children: "Close" })
877
+ ] }),
878
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 overflow-y-auto p-4 space-y-3", children: messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "text-center text-gray-400 py-8", children: [
879
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "font-medium mb-4", children: "How can I help?" }),
880
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-2", children: suggestions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
881
+ "button",
882
+ {
883
+ className: "block w-full text-left text-sm p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors",
884
+ onClick: () => setInput(s),
885
+ children: s
886
+ },
887
+ s
888
+ )) })
889
+ ] }) : messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
890
+ import_framer_motion4.motion.div,
891
+ {
892
+ className: `flex ${msg.role === "user" ? "justify-end" : "justify-start"}`,
893
+ initial: { opacity: 0, y: 10 },
894
+ animate: { opacity: 1, y: 0 },
895
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `max-w-[80%] p-3 rounded-2xl ${msg.role === "user" ? "bg-blue-500 text-white rounded-br-none" : "bg-gray-100 text-gray-800 rounded-bl-none"}`, children: [
896
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-sm", children: msg.content }),
897
+ msg.timestamp && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: `text-xs mt-1 ${msg.role === "user" ? "text-blue-100" : "text-gray-400"}`, children: msg.timestamp })
898
+ ] })
899
+ },
900
+ msg.id
901
+ )) }),
902
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-3 border-t", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-2", children: [
903
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
904
+ "input",
905
+ {
906
+ value: input,
907
+ onChange: (e) => setInput(e.target.value),
908
+ onKeyDown: (e) => e.key === "Enter" && handleSend(),
909
+ placeholder: "Type a message...",
910
+ className: "flex-1 border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
911
+ }
912
+ ),
913
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
914
+ "button",
915
+ {
916
+ onClick: handleSend,
917
+ disabled: !input.trim(),
918
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 disabled:opacity-50 transition-colors",
919
+ children: "Send"
920
+ }
921
+ )
922
+ ] }) })
923
+ ] });
924
+ }
925
+
926
+ // src/components/overlays/InsightOverlay.tsx
927
+ var import_framer_motion5 = require("framer-motion");
928
+ var import_jsx_runtime12 = require("react/jsx-runtime");
929
+ var insightStyles = {
930
+ recommendation: { bg: "bg-green-50", border: "border-green-200", icon: "\u2191", iconColor: "text-green-500" },
931
+ comparison: { bg: "bg-blue-50", border: "border-blue-200", icon: "\u2261", iconColor: "text-blue-500" },
932
+ warning: { bg: "bg-yellow-50", border: "border-yellow-200", icon: "\u26A0", iconColor: "text-yellow-500" }
933
+ };
934
+ function InsightOverlay({ data, onDismiss }) {
935
+ const { title, subtitle, insights = [], actions = [], onAction } = data ?? {};
936
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-md", children: [
937
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
938
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
939
+ title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold", children: title }),
940
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-gray-500", children: subtitle })
941
+ ] }),
942
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { onClick: onDismiss, className: "text-gray-400 hover:text-gray-600 text-sm", children: "Close" })
943
+ ] }),
944
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: insights.map((insight, i) => {
945
+ const style = insightStyles[insight.type];
946
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
947
+ import_framer_motion5.motion.div,
948
+ {
949
+ className: `p-3 rounded-lg border ${style.bg} ${style.border}`,
950
+ initial: { opacity: 0, x: -10 },
951
+ animate: { opacity: 1, x: 0 },
952
+ transition: { delay: i * 0.1 },
953
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start gap-2", children: [
954
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: style.iconColor, children: style.icon }),
955
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex-1", children: [
956
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm", children: insight.text }),
957
+ insight.confidence != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-xs text-gray-400 mt-1", children: [
958
+ "Confidence: ",
959
+ Math.round(insight.confidence * 100),
960
+ "%"
961
+ ] })
962
+ ] })
963
+ ] })
964
+ },
965
+ i
966
+ );
967
+ }) }),
968
+ actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-4 pt-3 border-t flex flex-wrap gap-2", children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
969
+ "button",
970
+ {
971
+ onClick: () => onAction?.(action),
972
+ className: "text-xs px-3 py-1.5 rounded-full bg-purple-100 text-purple-700 hover:bg-purple-200 transition-colors",
973
+ children: action
974
+ },
975
+ action
976
+ )) })
977
+ ] });
978
+ }
979
+
980
+ // src/components/overlays/DetailCardOverlay.tsx
981
+ var import_jsx_runtime13 = require("react/jsx-runtime");
982
+ function DetailCardOverlay({ data, onDismiss }) {
983
+ const { title, body, image, metadata, actions } = data ?? {};
984
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-lg", children: [
985
+ image && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
986
+ "img",
987
+ {
988
+ src: image,
989
+ alt: title ?? "Detail",
990
+ className: "w-full h-48 object-cover rounded-xl mb-4"
991
+ }
992
+ ),
993
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-lg font-semibold mb-1", children: title }),
994
+ body && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm text-gray-600 mb-4 leading-relaxed", children: body }),
995
+ metadata && Object.keys(metadata).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "space-y-1.5 mb-4", children: Object.entries(metadata).map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between py-1.5 border-b border-gray-100 last:border-0", children: [
996
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-xs font-medium text-gray-400 uppercase tracking-wider", children: key }),
997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm text-gray-700", children: value })
998
+ ] }, key)) }),
999
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-2 justify-end", children: [
1000
+ actions?.map((action, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1001
+ "button",
1002
+ {
1003
+ onClick: action.onClick,
1004
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
1005
+ children: action.label
1006
+ },
1007
+ i
1008
+ )),
1009
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1010
+ "button",
1011
+ {
1012
+ onClick: onDismiss,
1013
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1014
+ children: "Close"
1015
+ }
1016
+ )
1017
+ ] })
1018
+ ] });
1019
+ }
1020
+
1021
+ // src/components/overlays/ComparisonOverlay.tsx
1022
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1023
+ function ComparisonOverlay({ data, onDismiss }) {
1024
+ const { title, items } = data ?? {};
1025
+ const attributeKeys = items?.length ? [...new Set(items.flatMap((item) => Object.keys(item.attributes)))] : [];
1026
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[400px] max-w-2xl", children: [
1027
+ title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1028
+ items && items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "overflow-x-auto mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("table", { className: "w-full text-sm", children: [
1029
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("tr", { className: "border-b border-gray-200", children: [
1030
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("th", { className: "text-left py-2 pr-4 text-gray-400 font-medium text-xs uppercase tracking-wider", children: "Feature" }),
1031
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("th", { className: "text-center py-2 px-3 font-semibold text-gray-800", children: item.name }, item.name))
1032
+ ] }) }),
1033
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("tbody", { children: attributeKeys.map((key, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("tr", { className: i % 2 === 0 ? "bg-gray-50" : "", children: [
1034
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("td", { className: "py-2 pr-4 text-gray-600 font-medium", children: key }),
1035
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("td", { className: "text-center py-2 px-3 text-gray-700", children: String(item.attributes[key] ?? "\u2014") }, item.name))
1036
+ ] }, key)) })
1037
+ ] }) }),
1038
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1039
+ "button",
1040
+ {
1041
+ onClick: onDismiss,
1042
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1043
+ children: "Close"
1044
+ }
1045
+ ) })
1046
+ ] });
1047
+ }
1048
+
1049
+ // src/components/overlays/CalendarOverlay.tsx
1050
+ var import_react11 = require("react");
1051
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1052
+ function CalendarOverlay({ data, onDismiss }) {
1053
+ const { title, available_slots, onSelect } = data ?? {};
1054
+ const [selectedDate, setSelectedDate] = (0, import_react11.useState)(null);
1055
+ const [selectedSlot, setSelectedSlot] = (0, import_react11.useState)(null);
1056
+ const groupedSlots = (0, import_react11.useMemo)(() => {
1057
+ if (!available_slots) return /* @__PURE__ */ new Map();
1058
+ const groups = /* @__PURE__ */ new Map();
1059
+ for (const slot of available_slots) {
1060
+ const existing = groups.get(slot.date) ?? [];
1061
+ existing.push(slot);
1062
+ groups.set(slot.date, existing);
1063
+ }
1064
+ return groups;
1065
+ }, [available_slots]);
1066
+ const dates = [...groupedSlots.keys()];
1067
+ const activeDate = selectedDate ?? dates[0] ?? null;
1068
+ const slotsForDate = activeDate ? groupedSlots.get(activeDate) ?? [] : [];
1069
+ const handleConfirm = () => {
1070
+ if (selectedSlot) {
1071
+ onSelect?.(selectedSlot);
1072
+ onDismiss();
1073
+ }
1074
+ };
1075
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
1076
+ title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1077
+ dates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
1078
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex gap-2 overflow-x-auto pb-2 mb-3", children: dates.map((date) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1079
+ "button",
1080
+ {
1081
+ onClick: () => {
1082
+ setSelectedDate(date);
1083
+ setSelectedSlot(null);
1084
+ },
1085
+ className: `px-3 py-1.5 text-xs font-medium rounded-full whitespace-nowrap transition-colors ${activeDate === date ? "bg-blue-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
1086
+ children: date
1087
+ },
1088
+ date
1089
+ )) }),
1090
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex flex-wrap gap-2 mb-4", children: slotsForDate.map((slot, i) => {
1091
+ const isAvailable = slot.available !== false;
1092
+ const isSelected = selectedSlot === slot;
1093
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1094
+ "button",
1095
+ {
1096
+ disabled: !isAvailable,
1097
+ onClick: () => setSelectedSlot(slot),
1098
+ className: `px-3 py-1.5 text-sm rounded-lg transition-colors ${!isAvailable ? "bg-gray-50 text-gray-300 cursor-not-allowed" : isSelected ? "bg-blue-500 text-white ring-2 ring-blue-300" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
1099
+ children: slot.time
1100
+ },
1101
+ i
1102
+ );
1103
+ }) })
1104
+ ] }),
1105
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex gap-2 justify-end", children: [
1106
+ selectedSlot && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1107
+ "button",
1108
+ {
1109
+ onClick: handleConfirm,
1110
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
1111
+ children: "Confirm"
1112
+ }
1113
+ ),
1114
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1115
+ "button",
1116
+ {
1117
+ onClick: onDismiss,
1118
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1119
+ children: "Close"
1120
+ }
1121
+ )
1122
+ ] })
1123
+ ] });
1124
+ }
1125
+
1126
+ // src/components/overlays/MediaOverlay.tsx
1127
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1128
+ function MediaOverlay({ data, onDismiss }) {
1129
+ const { title, url, type = "image", alt, autoplay } = data ?? {};
1130
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-xl", children: [
1131
+ title && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1132
+ url && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "mb-4 rounded-xl overflow-hidden bg-gray-100", children: [
1133
+ type === "video" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1134
+ "video",
1135
+ {
1136
+ src: url,
1137
+ controls: true,
1138
+ autoPlay: autoplay,
1139
+ className: "w-full max-h-80 object-contain"
1140
+ }
1141
+ ),
1142
+ type === "audio" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "p-6 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("audio", { src: url, controls: true, autoPlay: autoplay, className: "w-full" }) }),
1143
+ type === "image" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1144
+ "img",
1145
+ {
1146
+ src: url,
1147
+ alt: alt ?? title ?? "Media",
1148
+ className: "w-full max-h-80 object-contain"
1149
+ }
1150
+ )
1151
+ ] }),
1152
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1153
+ "button",
1154
+ {
1155
+ onClick: onDismiss,
1156
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1157
+ children: "Close"
1158
+ }
1159
+ ) })
1160
+ ] });
1161
+ }
1162
+
1163
+ // src/components/overlays/MapOverlay.tsx
1164
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1165
+ function MapOverlay({ data, onDismiss }) {
1166
+ const { title, locations } = data ?? {};
1167
+ const getMapsUrl = (loc) => `https://www.google.com/maps/search/?api=1&query=${loc.lat},${loc.lng}`;
1168
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-md", children: [
1169
+ title && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1170
+ locations && locations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "space-y-3 mb-4", children: locations.map((loc, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-start gap-3 p-3 rounded-xl bg-gray-50", children: [
1171
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "w-8 h-8 rounded-full bg-red-100 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { className: "w-4 h-4 text-red-500", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { fillRule: "evenodd", d: "M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z", clipRule: "evenodd" }) }) }),
1172
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
1173
+ loc.label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-gray-800", children: loc.label }),
1174
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { className: "text-xs text-gray-400", children: [
1175
+ loc.lat.toFixed(4),
1176
+ ", ",
1177
+ loc.lng.toFixed(4)
1178
+ ] }),
1179
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1180
+ "a",
1181
+ {
1182
+ href: getMapsUrl(loc),
1183
+ target: "_blank",
1184
+ rel: "noopener noreferrer",
1185
+ className: "text-xs text-blue-500 hover:text-blue-600 font-medium",
1186
+ children: "Open in Maps \u2192"
1187
+ }
1188
+ )
1189
+ ] })
1190
+ ] }, i)) }),
1191
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1192
+ "button",
1193
+ {
1194
+ onClick: onDismiss,
1195
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1196
+ children: "Close"
1197
+ }
1198
+ ) })
1199
+ ] });
1200
+ }
1201
+
1202
+ // src/components/overlays/RichTextOverlay.tsx
1203
+ var import_react12 = require("react");
1204
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1205
+ function parseMarkdown(md) {
1206
+ let html = md.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre class="bg-gray-900 text-gray-100 rounded-lg p-3 text-xs overflow-x-auto my-2"><code>$2</code></pre>').replace(/`([^`]+)`/g, '<code class="bg-gray-100 text-gray-800 px-1 py-0.5 rounded text-xs">$1</code>').replace(/^### (.+)$/gm, '<h4 class="text-base font-semibold mt-3 mb-1">$1</h4>').replace(/^## (.+)$/gm, '<h3 class="text-lg font-semibold mt-4 mb-1">$1</h3>').replace(/^# (.+)$/gm, '<h2 class="text-xl font-bold mt-4 mb-2">$1</h2>').replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>").replace(/\*(.+?)\*/g, "<em>$1</em>").replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" class="text-blue-500 hover:text-blue-600 underline">$1</a>').replace(/^- (.+)$/gm, '<li class="ml-4 list-disc text-sm">$1</li>').replace(/^(?!<[hlupao])(.*\S.*)$/gm, '<p class="text-sm text-gray-600 my-1">$1</p>');
1207
+ return html;
1208
+ }
1209
+ function RichTextOverlay({ data, onDismiss }) {
1210
+ const { title, content } = data ?? {};
1211
+ const html = (0, import_react12.useMemo)(() => content ? parseMarkdown(content) : "", [content]);
1212
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-lg", children: [
1213
+ title && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1214
+ html && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1215
+ "div",
1216
+ {
1217
+ className: "max-h-96 overflow-y-auto mb-4",
1218
+ dangerouslySetInnerHTML: { __html: html }
1219
+ }
1220
+ ),
1221
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1222
+ "button",
1223
+ {
1224
+ onClick: onDismiss,
1225
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1226
+ children: "Close"
1227
+ }
1228
+ ) })
1229
+ ] });
1230
+ }
1231
+
1232
+ // src/components/overlays/ChartOverlay.tsx
1233
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1234
+ var DEFAULT_COLORS = ["#3b82f6", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#06b6d4", "#ef4444", "#84cc16"];
1235
+ function BarChart({ series }) {
1236
+ const max = Math.max(...series.map((s) => s.value), 1);
1237
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-2", children: series.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-3", children: [
1238
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs text-gray-500 w-20 truncate text-right", children: item.label }),
1239
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex-1 h-6 bg-gray-100 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1240
+ "div",
1241
+ {
1242
+ className: "h-full rounded-full transition-all duration-500",
1243
+ style: {
1244
+ width: `${item.value / max * 100}%`,
1245
+ backgroundColor: item.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length]
1246
+ }
1247
+ }
1248
+ ) }),
1249
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs font-medium text-gray-700 w-12", children: item.value })
1250
+ ] }, i)) });
1251
+ }
1252
+ function PieChart({ series }) {
1253
+ const total = series.reduce((sum, s) => sum + s.value, 0) || 1;
1254
+ const radius = 60;
1255
+ const circumference = 2 * Math.PI * radius;
1256
+ let offset = 0;
1257
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-6", children: [
1258
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: "160", height: "160", viewBox: "0 0 160 160", className: "flex-shrink-0", children: series.map((item, i) => {
1259
+ const dash = item.value / total * circumference;
1260
+ const currentOffset = offset;
1261
+ offset += dash;
1262
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1263
+ "circle",
1264
+ {
1265
+ cx: "80",
1266
+ cy: "80",
1267
+ r: radius,
1268
+ fill: "none",
1269
+ stroke: item.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length],
1270
+ strokeWidth: "24",
1271
+ strokeDasharray: `${dash} ${circumference - dash}`,
1272
+ strokeDashoffset: -currentOffset,
1273
+ transform: "rotate(-90 80 80)"
1274
+ },
1275
+ i
1276
+ );
1277
+ }) }),
1278
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-1.5", children: series.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
1279
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1280
+ "div",
1281
+ {
1282
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
1283
+ style: { backgroundColor: item.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length] }
1284
+ }
1285
+ ),
1286
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs text-gray-600", children: item.label }),
1287
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-xs font-medium text-gray-800", children: [
1288
+ Math.round(item.value / total * 100),
1289
+ "%"
1290
+ ] })
1291
+ ] }, i)) })
1292
+ ] });
1293
+ }
1294
+ function LineChart({ series }) {
1295
+ const max = Math.max(...series.map((s) => s.value), 1);
1296
+ const width = 300;
1297
+ const height = 120;
1298
+ const padding = 8;
1299
+ const points = series.map((item, i) => ({
1300
+ x: padding + i / Math.max(series.length - 1, 1) * (width - padding * 2),
1301
+ y: height - padding - item.value / max * (height - padding * 2)
1302
+ }));
1303
+ const pathD = points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
1304
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
1305
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { width, height, viewBox: `0 0 ${width} ${height}`, className: "w-full", children: [
1306
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: pathD, fill: "none", stroke: "#3b82f6", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1307
+ points.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("circle", { cx: p.x, cy: p.y, r: "3", fill: "#3b82f6" }, i))
1308
+ ] }),
1309
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex justify-between mt-1", children: series.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[10px] text-gray-400", children: item.label }, i)) })
1310
+ ] });
1311
+ }
1312
+ function ChartOverlay({ data, onDismiss }) {
1313
+ const { title, type = "bar", series } = data ?? {};
1314
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-md", children: [
1315
+ title && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1316
+ series && series.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mb-4", children: [
1317
+ type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(BarChart, { series }),
1318
+ type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PieChart, { series }),
1319
+ type === "line" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LineChart, { series })
1320
+ ] }),
1321
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1322
+ "button",
1323
+ {
1324
+ onClick: onDismiss,
1325
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1326
+ children: "Close"
1327
+ }
1328
+ ) })
1329
+ ] });
1330
+ }
1331
+
1332
+ // src/components/overlays/FileUploadOverlay.tsx
1333
+ var import_react13 = require("react");
1334
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1335
+ var MIME_MAP = {
1336
+ pdf: "application/pdf",
1337
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1338
+ doc: "application/msword",
1339
+ txt: "text/plain",
1340
+ csv: "text/csv",
1341
+ png: "image/png",
1342
+ jpg: "image/jpeg",
1343
+ jpeg: "image/jpeg",
1344
+ gif: "image/gif",
1345
+ svg: "image/svg+xml"
1346
+ };
1347
+ function formatSize(bytes) {
1348
+ if (bytes < 1024) return `${bytes} B`;
1349
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
1350
+ return `${(bytes / 1048576).toFixed(1)} MB`;
1351
+ }
1352
+ function FileUploadOverlay({ data, onDismiss }) {
1353
+ const { title, accept, max_size, multiple, onUpload } = data ?? {};
1354
+ const inputRef = (0, import_react13.useRef)(null);
1355
+ const [files, setFiles] = (0, import_react13.useState)([]);
1356
+ const [dragging, setDragging] = (0, import_react13.useState)(false);
1357
+ const acceptMime = accept?.map((ext) => MIME_MAP[ext.toLowerCase()] ?? `.${ext}`).join(",");
1358
+ const addFiles = (0, import_react13.useCallback)((newFiles) => {
1359
+ if (!newFiles) return;
1360
+ const arr = Array.from(newFiles).filter((f) => {
1361
+ if (max_size && f.size > max_size) return false;
1362
+ return true;
1363
+ });
1364
+ setFiles((prev) => multiple ? [...prev, ...arr] : arr.slice(0, 1));
1365
+ }, [max_size, multiple]);
1366
+ const removeFile = (index) => {
1367
+ setFiles((prev) => prev.filter((_, i) => i !== index));
1368
+ };
1369
+ const handleSubmit = () => {
1370
+ if (files.length > 0) {
1371
+ onUpload?.(files);
1372
+ onDismiss();
1373
+ }
1374
+ };
1375
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
1376
+ title && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-lg font-semibold mb-4", children: title }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1378
+ "div",
1379
+ {
1380
+ className: `border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-colors mb-3 ${dragging ? "border-blue-400 bg-blue-50" : "border-gray-200 hover:border-gray-300"}`,
1381
+ onClick: () => inputRef.current?.click(),
1382
+ onDragOver: (e) => {
1383
+ e.preventDefault();
1384
+ setDragging(true);
1385
+ },
1386
+ onDragLeave: () => setDragging(false),
1387
+ onDrop: (e) => {
1388
+ e.preventDefault();
1389
+ setDragging(false);
1390
+ addFiles(e.dataTransfer.files);
1391
+ },
1392
+ children: [
1393
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("svg", { className: "w-8 h-8 text-gray-300 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }),
1394
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-gray-500", children: "Drop files here or click to browse" }),
1395
+ accept && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-gray-400 mt-1", children: accept.map((e) => `.${e}`).join(", ") }),
1396
+ max_size && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: "text-xs text-gray-400", children: [
1397
+ "Max ",
1398
+ formatSize(max_size)
1399
+ ] }),
1400
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1401
+ "input",
1402
+ {
1403
+ ref: inputRef,
1404
+ type: "file",
1405
+ className: "hidden",
1406
+ accept: acceptMime,
1407
+ multiple,
1408
+ onChange: (e) => addFiles(e.target.files)
1409
+ }
1410
+ )
1411
+ ]
1412
+ }
1413
+ ),
1414
+ files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "space-y-2 mb-4", children: files.map((file, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center justify-between py-1.5 px-3 bg-gray-50 rounded-lg", children: [
1415
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "min-w-0", children: [
1416
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-gray-700 truncate", children: file.name }),
1417
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-gray-400", children: formatSize(file.size) })
1418
+ ] }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => removeFile(i), className: "text-gray-400 hover:text-red-500 text-sm ml-2", children: "\xD7" })
1420
+ ] }, i)) }),
1421
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-2 justify-end", children: [
1422
+ files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1423
+ "button",
1424
+ {
1425
+ onClick: handleSubmit,
1426
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors",
1427
+ children: "Upload"
1428
+ }
1429
+ ),
1430
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1431
+ "button",
1432
+ {
1433
+ onClick: onDismiss,
1434
+ className: "px-4 py-2 text-sm font-medium rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200 transition-colors",
1435
+ children: "Close"
1436
+ }
1437
+ )
1438
+ ] })
1439
+ ] });
1440
+ }
1441
+
1442
+ // src/components/AvatarFirst.tsx
1443
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1444
+ var defaultOverlays = {
1445
+ card: CardOverlay,
1446
+ form: FormOverlay,
1447
+ table: TableOverlay,
1448
+ progress: ProgressOverlay,
1449
+ confirm: ConfirmOverlay,
1450
+ chat: ChatOverlay,
1451
+ insight: InsightOverlay
1452
+ };
1453
+ function AvatarFirstInner({
1454
+ client,
1455
+ onOverlay,
1456
+ onAction
1457
+ }) {
1458
+ const { state: avatarState, speak } = useAvatar();
1459
+ const { show } = useOverlay();
1460
+ const [sessionId, setSessionId] = (0, import_react14.useState)(null);
1461
+ const [greeting, setGreeting] = (0, import_react14.useState)(null);
1462
+ const [hasGreeted, setHasGreeted] = (0, import_react14.useState)(false);
1463
+ const [isProcessing, setIsProcessing] = (0, import_react14.useState)(false);
1464
+ (0, import_react14.useEffect)(() => {
1465
+ if (avatarState === "connected" && !sessionId) {
1466
+ client.createSession().then((session) => {
1467
+ setSessionId(session.sessionId);
1468
+ setGreeting(session.greeting);
1469
+ }).catch((err) => {
1470
+ console.error("[AvatarFirst] Session init failed:", err);
1471
+ });
1472
+ }
1473
+ }, [avatarState, sessionId, client]);
1474
+ (0, import_react14.useEffect)(() => {
1475
+ if (sessionId && avatarState === "connected" && greeting && !hasGreeted) {
1476
+ setHasGreeted(true);
1477
+ speak(greeting);
1478
+ }
1479
+ }, [sessionId, avatarState, greeting, hasGreeted, speak]);
1480
+ const handleResponse = (0, import_react14.useCallback)((data) => {
1481
+ if (data.speech) {
1482
+ speak(data.speech);
1483
+ }
1484
+ if (data.overlay) {
1485
+ const overlayId = `overlay-${Date.now()}`;
1486
+ show({
1487
+ id: overlayId,
1488
+ component: data.overlay.type,
1489
+ data: data.overlay.data,
1490
+ position: "right-center",
1491
+ animation: "slide-left",
1492
+ dismissOnClickOutside: true
1493
+ });
1494
+ onOverlay?.(data.overlay);
1495
+ }
1496
+ if (data.actions) {
1497
+ for (const action of data.actions) {
1498
+ onAction?.(action);
1499
+ }
1500
+ }
1501
+ }, [speak, show, onOverlay, onAction]);
1502
+ const handleSend = (0, import_react14.useCallback)(async (text) => {
1503
+ if (!sessionId || isProcessing) return;
1504
+ setIsProcessing(true);
1505
+ try {
1506
+ const response = await client.sendMessage(sessionId, text);
1507
+ handleResponse(response);
1508
+ } catch (err) {
1509
+ console.error("[AvatarFirst] Message failed:", err);
1510
+ } finally {
1511
+ setIsProcessing(false);
1512
+ }
1513
+ }, [client, sessionId, isProcessing, handleResponse]);
1514
+ const isConnected = avatarState === "connected" || avatarState === "speaking" || avatarState === "listening" || avatarState === "thinking";
1515
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative w-full h-full", children: [
1516
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AvatarView, { size: "fullscreen", showStatus: false, className: "w-full h-full" }),
1517
+ isConnected && sessionId && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-20 w-full max-w-md px-4", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1518
+ "form",
1519
+ {
1520
+ onSubmit: (e) => {
1521
+ e.preventDefault();
1522
+ const input = e.currentTarget.elements.namedItem("message");
1523
+ if (input.value.trim()) {
1524
+ handleSend(input.value.trim());
1525
+ input.value = "";
1526
+ }
1527
+ },
1528
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1529
+ "input",
1530
+ {
1531
+ name: "message",
1532
+ type: "text",
1533
+ placeholder: "Type a message...",
1534
+ disabled: isProcessing,
1535
+ className: "w-full px-4 py-3 bg-white/10 backdrop-blur-md border border-white/20 rounded-full text-white placeholder-white/50 outline-none focus:border-white/40"
1536
+ }
1537
+ )
1538
+ }
1539
+ ) }),
1540
+ !isConnected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-slate-950/80 z-30", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-center", children: [
1541
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-12 h-12 border-2 border-purple-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" }),
1542
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-white/60 text-sm", children: "Connecting..." })
1543
+ ] }) })
1544
+ ] });
1545
+ }
1546
+ function AvatarFirst({
1547
+ apiKey,
1548
+ baseUrl,
1549
+ onOverlay,
1550
+ onAction,
1551
+ onStateChange,
1552
+ className,
1553
+ overlayComponents
1554
+ }) {
1555
+ const [agent, setAgent] = (0, import_react14.useState)(null);
1556
+ const [error, setError] = (0, import_react14.useState)(false);
1557
+ const client = (0, import_react14.useMemo)(
1558
+ () => new import_core2.AvatarFirstClient({ apiKey, baseUrl }),
1559
+ [apiKey, baseUrl]
1560
+ );
1561
+ const mergedOverlays = (0, import_react14.useMemo)(
1562
+ () => ({ ...defaultOverlays, ...overlayComponents }),
1563
+ [overlayComponents]
1564
+ );
1565
+ const onStateChangeRef = (0, import_react14.useRef)(onStateChange);
1566
+ onStateChangeRef.current = onStateChange;
1567
+ (0, import_react14.useEffect)(() => {
1568
+ let cancelled = false;
1569
+ async function init() {
1570
+ try {
1571
+ onStateChangeRef.current?.("connecting");
1572
+ const session = await client.createSession();
1573
+ if (cancelled) return;
1574
+ const engine = new import_core2.HeyGenAdapter();
1575
+ const avatarAgent = (0, import_core2.createAvatarAgent)({
1576
+ engine,
1577
+ engineConfig: {
1578
+ serverUrl: baseUrl || "https://avatarfirst.dev",
1579
+ sessionToken: session.avatar?.token,
1580
+ language: "en",
1581
+ voiceChat: false
1582
+ },
1583
+ actions: []
1584
+ });
1585
+ setAgent(avatarAgent);
1586
+ onStateChangeRef.current?.("connected");
1587
+ } catch (err) {
1588
+ if (!cancelled) {
1589
+ console.error("[AvatarFirst] Init failed:", err);
1590
+ setError(true);
1591
+ onStateChangeRef.current?.("error");
1592
+ }
1593
+ }
1594
+ }
1595
+ init();
1596
+ return () => {
1597
+ cancelled = true;
1598
+ };
1599
+ }, [client, baseUrl]);
1600
+ (0, import_react14.useEffect)(() => {
1601
+ return () => {
1602
+ agent?.destroy();
1603
+ };
1604
+ }, [agent]);
1605
+ if (error || !agent) {
1606
+ if (error) {
1607
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `flex items-center justify-center bg-slate-950 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-center", children: [
1608
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-red-400 mb-2 text-sm", children: "Failed to connect" }),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1610
+ "button",
1611
+ {
1612
+ onClick: () => window.location.reload(),
1613
+ className: "text-white/60 text-xs underline hover:text-white/80",
1614
+ children: "Retry"
1615
+ }
1616
+ )
1617
+ ] }) });
1618
+ }
1619
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `flex items-center justify-center bg-slate-950 ${className || ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-12 h-12 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" }) });
1620
+ }
1621
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(AvatarProvider, { agent, autoStart: true, children: [
1622
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OverlayContainer, { components: mergedOverlays }),
1623
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AvatarFirstInner, { client, onOverlay, onAction })
1624
+ ] }) });
1625
+ }
1626
+
1627
+ // src/animations/variants.ts
1628
+ var pageTransition = {
1629
+ initial: { opacity: 0, x: -20 },
1630
+ animate: { opacity: 1, x: 0, transition: { duration: 0.3 } },
1631
+ exit: { opacity: 0, x: 20, transition: { duration: 0.2 } }
1632
+ };
1633
+ var fadeIn = {
1634
+ initial: { opacity: 0 },
1635
+ animate: { opacity: 1, transition: { duration: 0.5 } },
1636
+ exit: { opacity: 0 }
1637
+ };
1638
+ var fadeInUp = {
1639
+ initial: { opacity: 0, y: 20 },
1640
+ animate: { opacity: 1, y: 0, transition: { duration: 0.4 } }
1641
+ };
1642
+ var cardHover = {
1643
+ initial: { scale: 1, y: 0 },
1644
+ hover: {
1645
+ scale: 1.03,
1646
+ y: -8,
1647
+ transition: { type: "spring", stiffness: 300, damping: 20 }
1648
+ },
1649
+ tap: { scale: 0.98 }
1650
+ };
1651
+ var avatarPulse = {
1652
+ idle: {
1653
+ scale: [1, 1.02, 1],
1654
+ transition: { repeat: Infinity, duration: 3, ease: "easeInOut" }
1655
+ },
1656
+ speaking: {
1657
+ scale: [1, 1.03, 1],
1658
+ transition: { repeat: Infinity, duration: 0.5, ease: "easeInOut" }
1659
+ },
1660
+ listening: {
1661
+ scale: 1,
1662
+ transition: { duration: 0.2 }
1663
+ },
1664
+ thinking: {
1665
+ scale: [1, 1.01, 1],
1666
+ transition: { repeat: Infinity, duration: 1, ease: "easeInOut" }
1667
+ }
1668
+ };
1669
+ var staggerContainer = {
1670
+ initial: {},
1671
+ animate: {
1672
+ transition: { staggerChildren: 0.1 }
1673
+ }
1674
+ };
1675
+ var slideIn = {
1676
+ initial: { x: "100%", opacity: 0 },
1677
+ animate: { x: 0, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 30 } },
1678
+ exit: { x: "100%", opacity: 0 }
1679
+ };
1680
+ var scaleIn = {
1681
+ initial: { scale: 0.8, opacity: 0 },
1682
+ animate: { scale: 1, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 25 } },
1683
+ exit: { scale: 0.8, opacity: 0 }
1684
+ };
1685
+
1686
+ // src/utils/cn.ts
1687
+ var import_clsx = require("clsx");
1688
+ var import_tailwind_merge = require("tailwind-merge");
1689
+ function cn(...inputs) {
1690
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
1691
+ }
1692
+ // Annotate the CommonJS export names for ESM import in node:
1693
+ 0 && (module.exports = {
1694
+ AvatarAgent,
1695
+ AvatarContext,
1696
+ AvatarFallback,
1697
+ AvatarFirst,
1698
+ AvatarProvider,
1699
+ AvatarView,
1700
+ CalendarOverlay,
1701
+ CardOverlay,
1702
+ ChartOverlay,
1703
+ ChatOverlay,
1704
+ ComparisonOverlay,
1705
+ ConfirmOverlay,
1706
+ DetailCardOverlay,
1707
+ FileUploadOverlay,
1708
+ FormOverlay,
1709
+ InsightOverlay,
1710
+ MapOverlay,
1711
+ MediaOverlay,
1712
+ OverlayContainer,
1713
+ ProgressOverlay,
1714
+ RichTextOverlay,
1715
+ TableOverlay,
1716
+ avatarPulse,
1717
+ cardHover,
1718
+ cn,
1719
+ fadeIn,
1720
+ fadeInUp,
1721
+ getOverlayVariants,
1722
+ pageTransition,
1723
+ scaleIn,
1724
+ slideIn,
1725
+ staggerContainer,
1726
+ useAction,
1727
+ useAvatar,
1728
+ useAvatarEvent,
1729
+ useAvatarFirst,
1730
+ useOverlay
1731
+ });