@avatarfirst/react 0.1.0 → 0.2.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 +190 -70
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +232 -122
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -210,7 +210,7 @@ function useAvatarFirst(options) {
|
|
|
210
210
|
}
|
|
211
211
|
if (response.actions) {
|
|
212
212
|
for (const action of response.actions) {
|
|
213
|
-
optionsRef.current.onAction?.(action);
|
|
213
|
+
optionsRef.current.onAction?.({ type: action.intent, payload: action.data });
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
setIsProcessing(false);
|
|
@@ -247,6 +247,7 @@ function useAvatarFirst(options) {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
// src/components/overlays/OverlayContainer.tsx
|
|
250
|
+
import React2 from "react";
|
|
250
251
|
import { AnimatePresence, motion } from "framer-motion";
|
|
251
252
|
|
|
252
253
|
// src/animations/overlayAnimations.ts
|
|
@@ -311,7 +312,7 @@ function getOverlayVariants(animation = "fade") {
|
|
|
311
312
|
}
|
|
312
313
|
|
|
313
314
|
// src/components/overlays/OverlayContainer.tsx
|
|
314
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
315
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
315
316
|
function getPositionStyles(position = "bottom-center") {
|
|
316
317
|
if (typeof position === "object") {
|
|
317
318
|
return { position: "absolute", left: position.x, top: position.y };
|
|
@@ -320,6 +321,8 @@ function getPositionStyles(position = "bottom-center") {
|
|
|
320
321
|
switch (position) {
|
|
321
322
|
case "center":
|
|
322
323
|
return { ...base, top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
|
|
324
|
+
case "chest":
|
|
325
|
+
return { ...base, bottom: "5rem", left: "50%", transform: "translateX(-50%)", width: "90%", maxWidth: "28rem" };
|
|
323
326
|
case "bottom-center":
|
|
324
327
|
return { ...base, bottom: "2rem", left: "50%", transform: "translateX(-50%)" };
|
|
325
328
|
case "bottom-right":
|
|
@@ -343,41 +346,54 @@ function OverlayContainer({ components }) {
|
|
|
343
346
|
if (!Component) return null;
|
|
344
347
|
const variants = getOverlayVariants(overlay.animation);
|
|
345
348
|
const positionStyle = getPositionStyles(overlay.position);
|
|
346
|
-
return /* @__PURE__ */
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
349
|
+
return /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
350
|
+
overlay.position === "center" && /* @__PURE__ */ jsx2(
|
|
351
|
+
motion.div,
|
|
352
|
+
{
|
|
353
|
+
className: "fixed inset-0 bg-black/60 pointer-events-auto",
|
|
354
|
+
initial: { opacity: 0 },
|
|
355
|
+
animate: { opacity: 1 },
|
|
356
|
+
exit: { opacity: 0 },
|
|
357
|
+
onClick: () => overlay.dismissOnClickOutside !== false && hide(overlay.id)
|
|
358
|
+
},
|
|
359
|
+
`backdrop-${overlay.id}`
|
|
360
|
+
),
|
|
361
|
+
/* @__PURE__ */ jsx2(
|
|
362
|
+
motion.div,
|
|
363
|
+
{
|
|
364
|
+
variants,
|
|
365
|
+
initial: "initial",
|
|
366
|
+
animate: "animate",
|
|
367
|
+
exit: "exit",
|
|
368
|
+
style: positionStyle,
|
|
369
|
+
className: "pointer-events-auto",
|
|
370
|
+
onClick: overlay.dismissOnClickOutside ? (e) => {
|
|
371
|
+
if (e.target === e.currentTarget) hide(overlay.id);
|
|
372
|
+
} : void 0,
|
|
373
|
+
children: /* @__PURE__ */ jsx2(
|
|
374
|
+
Component,
|
|
375
|
+
{
|
|
376
|
+
data: overlay.data,
|
|
377
|
+
overlayId: overlay.id,
|
|
378
|
+
onDismiss: () => hide(overlay.id)
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
},
|
|
382
|
+
`content-${overlay.id}`
|
|
383
|
+
)
|
|
384
|
+
] }, overlay.id);
|
|
369
385
|
}) }) });
|
|
370
386
|
}
|
|
371
387
|
|
|
372
388
|
// src/components/AvatarAgent.tsx
|
|
373
|
-
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
389
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
374
390
|
function AvatarAgent({
|
|
375
391
|
config,
|
|
376
392
|
overlayComponents = {},
|
|
377
393
|
autoStart = false,
|
|
378
394
|
children
|
|
379
395
|
}) {
|
|
380
|
-
return /* @__PURE__ */
|
|
396
|
+
return /* @__PURE__ */ jsxs2(AvatarProvider, { agent: config, autoStart, children: [
|
|
381
397
|
children,
|
|
382
398
|
/* @__PURE__ */ jsx3(OverlayContainer, { components: overlayComponents })
|
|
383
399
|
] });
|
|
@@ -397,7 +413,7 @@ import { motion as motion3 } from "framer-motion";
|
|
|
397
413
|
|
|
398
414
|
// src/components/AvatarFallback.tsx
|
|
399
415
|
import { motion as motion2 } from "framer-motion";
|
|
400
|
-
import { jsx as jsx4, jsxs as
|
|
416
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
401
417
|
function AvatarFallback({ size, state }) {
|
|
402
418
|
const isSmall = size === "small";
|
|
403
419
|
const isMedium = size === "medium";
|
|
@@ -405,7 +421,7 @@ function AvatarFallback({ size, state }) {
|
|
|
405
421
|
const eyeSize = isSmall ? 4 : isMedium ? 6 : 12;
|
|
406
422
|
const mouthWidth = isSmall ? 15 : isMedium ? 25 : 50;
|
|
407
423
|
if (state === "connecting") {
|
|
408
|
-
return /* @__PURE__ */
|
|
424
|
+
return /* @__PURE__ */ jsxs3("div", { className: "relative w-full h-full flex items-center justify-center", children: [
|
|
409
425
|
/* @__PURE__ */ jsx4(
|
|
410
426
|
motion2.div,
|
|
411
427
|
{
|
|
@@ -432,7 +448,7 @@ function AvatarFallback({ size, state }) {
|
|
|
432
448
|
)
|
|
433
449
|
] });
|
|
434
450
|
}
|
|
435
|
-
return /* @__PURE__ */
|
|
451
|
+
return /* @__PURE__ */ jsxs3("div", { className: `relative ${faceSize}`, children: [
|
|
436
452
|
/* @__PURE__ */ jsx4(
|
|
437
453
|
motion2.div,
|
|
438
454
|
{
|
|
@@ -449,7 +465,7 @@ function AvatarFallback({ size, state }) {
|
|
|
449
465
|
}
|
|
450
466
|
),
|
|
451
467
|
/* @__PURE__ */ jsx4("div", { className: "absolute inset-2 rounded-full bg-gradient-to-br from-white/30 to-transparent" }),
|
|
452
|
-
/* @__PURE__ */
|
|
468
|
+
/* @__PURE__ */ jsxs3("svg", { viewBox: "0 0 100 100", className: "absolute inset-0 w-full h-full", children: [
|
|
453
469
|
/* @__PURE__ */ jsx4(
|
|
454
470
|
motion2.ellipse,
|
|
455
471
|
{
|
|
@@ -522,7 +538,7 @@ function AvatarFallback({ size, state }) {
|
|
|
522
538
|
}
|
|
523
539
|
|
|
524
540
|
// src/components/AvatarView.tsx
|
|
525
|
-
import { jsx as jsx5, jsxs as
|
|
541
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
526
542
|
var sizeClasses = {
|
|
527
543
|
small: "w-16 h-16",
|
|
528
544
|
medium: "w-32 h-32",
|
|
@@ -540,8 +556,8 @@ function AvatarView({ size = "medium", showStatus = true, className = "" }) {
|
|
|
540
556
|
}, [attachVideoElement]);
|
|
541
557
|
const isConnected = state === "connected" || state === "speaking" || state === "listening" || state === "thinking";
|
|
542
558
|
const isFullscreen = size === "fullscreen";
|
|
543
|
-
return /* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
559
|
+
return /* @__PURE__ */ jsxs4("div", { className: `relative ${className}`, children: [
|
|
560
|
+
/* @__PURE__ */ jsxs4(
|
|
545
561
|
motion3.div,
|
|
546
562
|
{
|
|
547
563
|
className: `relative overflow-hidden ${isFullscreen ? "rounded-2xl" : "rounded-full"} ${sizeClasses[size]}`,
|
|
@@ -605,17 +621,17 @@ function AvatarView({ size = "medium", showStatus = true, className = "" }) {
|
|
|
605
621
|
}
|
|
606
622
|
|
|
607
623
|
// src/components/overlays/CardOverlay.tsx
|
|
608
|
-
import { jsx as jsx6, jsxs as
|
|
624
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
609
625
|
function CardOverlay({ data, onDismiss }) {
|
|
610
626
|
const { title, description, items, actions } = data ?? {};
|
|
611
|
-
return /* @__PURE__ */
|
|
627
|
+
return /* @__PURE__ */ jsxs5("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[300px] max-w-md", children: [
|
|
612
628
|
title && /* @__PURE__ */ jsx6("h3", { className: "text-lg font-semibold mb-1", children: title }),
|
|
613
629
|
description && /* @__PURE__ */ jsx6("p", { className: "text-sm text-gray-500 mb-4", children: description }),
|
|
614
|
-
items && items.length > 0 && /* @__PURE__ */ jsx6("div", { className: "space-y-2 mb-4", children: items.map((item, i) => /* @__PURE__ */
|
|
630
|
+
items && items.length > 0 && /* @__PURE__ */ jsx6("div", { className: "space-y-2 mb-4", children: items.map((item, i) => /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between py-2 border-b border-gray-100 last:border-0", children: [
|
|
615
631
|
/* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-gray-700", children: item.label }),
|
|
616
632
|
item.value && /* @__PURE__ */ jsx6("span", { className: "text-sm text-gray-500", children: item.value })
|
|
617
633
|
] }, i)) }),
|
|
618
|
-
/* @__PURE__ */
|
|
634
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2 justify-end", children: [
|
|
619
635
|
actions?.map((action, i) => /* @__PURE__ */ jsx6(
|
|
620
636
|
"button",
|
|
621
637
|
{
|
|
@@ -639,7 +655,7 @@ function CardOverlay({ data, onDismiss }) {
|
|
|
639
655
|
|
|
640
656
|
// src/components/overlays/FormOverlay.tsx
|
|
641
657
|
import { useState as useState3 } from "react";
|
|
642
|
-
import { jsx as jsx7, jsxs as
|
|
658
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
643
659
|
function FormOverlay({ data, onDismiss }) {
|
|
644
660
|
const { title, fields = [], submitLabel = "Submit", onSubmit } = data ?? {};
|
|
645
661
|
const [values, setValues] = useState3({});
|
|
@@ -648,10 +664,10 @@ function FormOverlay({ data, onDismiss }) {
|
|
|
648
664
|
onSubmit?.(values);
|
|
649
665
|
onDismiss();
|
|
650
666
|
};
|
|
651
|
-
return /* @__PURE__ */
|
|
667
|
+
return /* @__PURE__ */ jsxs6("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-md", children: [
|
|
652
668
|
title && /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
653
|
-
/* @__PURE__ */
|
|
654
|
-
fields.map((field) => /* @__PURE__ */
|
|
669
|
+
/* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "space-y-3", children: [
|
|
670
|
+
fields.map((field) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
655
671
|
/* @__PURE__ */ jsx7("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: field.label }),
|
|
656
672
|
field.type === "textarea" ? /* @__PURE__ */ jsx7(
|
|
657
673
|
"textarea",
|
|
@@ -662,7 +678,7 @@ function FormOverlay({ data, onDismiss }) {
|
|
|
662
678
|
value: values[field.name] ?? "",
|
|
663
679
|
onChange: (e) => setValues((v) => ({ ...v, [field.name]: e.target.value }))
|
|
664
680
|
}
|
|
665
|
-
) : field.type === "select" ? /* @__PURE__ */
|
|
681
|
+
) : field.type === "select" ? /* @__PURE__ */ jsxs6(
|
|
666
682
|
"select",
|
|
667
683
|
{
|
|
668
684
|
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",
|
|
@@ -686,7 +702,7 @@ function FormOverlay({ data, onDismiss }) {
|
|
|
686
702
|
}
|
|
687
703
|
)
|
|
688
704
|
] }, field.name)),
|
|
689
|
-
/* @__PURE__ */
|
|
705
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex gap-2 justify-end pt-2", children: [
|
|
690
706
|
/* @__PURE__ */ jsx7(
|
|
691
707
|
"button",
|
|
692
708
|
{
|
|
@@ -710,15 +726,15 @@ function FormOverlay({ data, onDismiss }) {
|
|
|
710
726
|
}
|
|
711
727
|
|
|
712
728
|
// src/components/overlays/TableOverlay.tsx
|
|
713
|
-
import { jsx as jsx8, jsxs as
|
|
729
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
714
730
|
function TableOverlay({ data, onDismiss }) {
|
|
715
731
|
const { title, columns = [], rows = [] } = data ?? {};
|
|
716
|
-
return /* @__PURE__ */
|
|
717
|
-
title && /* @__PURE__ */
|
|
732
|
+
return /* @__PURE__ */ jsxs7("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[400px] max-w-2xl overflow-x-auto", children: [
|
|
733
|
+
title && /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between mb-4", children: [
|
|
718
734
|
/* @__PURE__ */ jsx8("h3", { className: "text-lg font-semibold", children: title }),
|
|
719
735
|
/* @__PURE__ */ jsx8("button", { onClick: onDismiss, className: "text-gray-400 hover:text-gray-600 text-sm", children: "Close" })
|
|
720
736
|
] }),
|
|
721
|
-
/* @__PURE__ */
|
|
737
|
+
/* @__PURE__ */ jsxs7("table", { className: "w-full", children: [
|
|
722
738
|
columns.length > 0 && /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsx8("tr", { className: "border-b", children: columns.map((col, i) => /* @__PURE__ */ jsx8("th", { className: "text-left py-2 px-3 text-sm font-medium text-gray-500", children: col }, i)) }) }),
|
|
723
739
|
/* @__PURE__ */ jsx8("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsx8("tr", { className: "border-b last:border-0 hover:bg-gray-50", children: row.map((cell, j) => /* @__PURE__ */ jsx8("td", { className: "py-2 px-3 text-sm text-gray-700", children: cell }, j)) }, i)) })
|
|
724
740
|
] })
|
|
@@ -726,12 +742,12 @@ function TableOverlay({ data, onDismiss }) {
|
|
|
726
742
|
}
|
|
727
743
|
|
|
728
744
|
// src/components/overlays/ProgressOverlay.tsx
|
|
729
|
-
import { jsx as jsx9, jsxs as
|
|
745
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
730
746
|
function ProgressOverlay({ data, onDismiss }) {
|
|
731
747
|
const { title, steps = [] } = data ?? {};
|
|
732
|
-
return /* @__PURE__ */
|
|
748
|
+
return /* @__PURE__ */ jsxs8("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
|
|
733
749
|
title && /* @__PURE__ */ jsx9("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
734
|
-
/* @__PURE__ */ jsx9("div", { className: "space-y-3", children: steps.map((step, i) => /* @__PURE__ */
|
|
750
|
+
/* @__PURE__ */ jsx9("div", { className: "space-y-3", children: steps.map((step, i) => /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
735
751
|
/* @__PURE__ */ jsx9(
|
|
736
752
|
"div",
|
|
737
753
|
{
|
|
@@ -753,13 +769,13 @@ function ProgressOverlay({ data, onDismiss }) {
|
|
|
753
769
|
}
|
|
754
770
|
|
|
755
771
|
// src/components/overlays/ConfirmOverlay.tsx
|
|
756
|
-
import { jsx as jsx10, jsxs as
|
|
772
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
757
773
|
function ConfirmOverlay({ data, onDismiss }) {
|
|
758
774
|
const { title, message, confirmLabel = "Confirm", cancelLabel = "Cancel", onConfirm, onCancel } = data ?? {};
|
|
759
|
-
return /* @__PURE__ */
|
|
775
|
+
return /* @__PURE__ */ jsxs9("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[300px] max-w-sm", children: [
|
|
760
776
|
title && /* @__PURE__ */ jsx10("h3", { className: "text-lg font-semibold mb-2", children: title }),
|
|
761
777
|
message && /* @__PURE__ */ jsx10("p", { className: "text-sm text-gray-500 mb-6", children: message }),
|
|
762
|
-
/* @__PURE__ */
|
|
778
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-3", children: [
|
|
763
779
|
/* @__PURE__ */ jsx10(
|
|
764
780
|
"button",
|
|
765
781
|
{
|
|
@@ -789,7 +805,7 @@ function ConfirmOverlay({ data, onDismiss }) {
|
|
|
789
805
|
// src/components/overlays/ChatOverlay.tsx
|
|
790
806
|
import { useState as useState4 } from "react";
|
|
791
807
|
import { motion as motion4 } from "framer-motion";
|
|
792
|
-
import { jsx as jsx11, jsxs as
|
|
808
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
793
809
|
function ChatOverlay({ data, onDismiss }) {
|
|
794
810
|
const { title = "Chat", messages: initialMessages = [], suggestions = [] } = data ?? {};
|
|
795
811
|
const [messages, setMessages] = useState4(initialMessages);
|
|
@@ -814,12 +830,12 @@ function ChatOverlay({ data, onDismiss }) {
|
|
|
814
830
|
};
|
|
815
831
|
setMessages((prev) => [...prev, aiMsg]);
|
|
816
832
|
};
|
|
817
|
-
return /* @__PURE__ */
|
|
818
|
-
/* @__PURE__ */
|
|
833
|
+
return /* @__PURE__ */ jsxs10("div", { className: "bg-white rounded-2xl shadow-2xl overflow-hidden w-96 flex flex-col", style: { maxHeight: "500px" }, children: [
|
|
834
|
+
/* @__PURE__ */ jsxs10("div", { className: "bg-gradient-to-r from-blue-500 to-blue-600 p-4 flex items-center justify-between", children: [
|
|
819
835
|
/* @__PURE__ */ jsx11("h3", { className: "text-white font-semibold", children: title }),
|
|
820
836
|
/* @__PURE__ */ jsx11("button", { onClick: onDismiss, className: "text-white/70 hover:text-white text-sm", children: "Close" })
|
|
821
837
|
] }),
|
|
822
|
-
/* @__PURE__ */ jsx11("div", { className: "flex-1 overflow-y-auto p-4 space-y-3", children: messages.length === 0 ? /* @__PURE__ */
|
|
838
|
+
/* @__PURE__ */ jsx11("div", { className: "flex-1 overflow-y-auto p-4 space-y-3", children: messages.length === 0 ? /* @__PURE__ */ jsxs10("div", { className: "text-center text-gray-400 py-8", children: [
|
|
823
839
|
/* @__PURE__ */ jsx11("p", { className: "font-medium mb-4", children: "How can I help?" }),
|
|
824
840
|
/* @__PURE__ */ jsx11("div", { className: "space-y-2", children: suggestions.map((s) => /* @__PURE__ */ jsx11(
|
|
825
841
|
"button",
|
|
@@ -836,14 +852,14 @@ function ChatOverlay({ data, onDismiss }) {
|
|
|
836
852
|
className: `flex ${msg.role === "user" ? "justify-end" : "justify-start"}`,
|
|
837
853
|
initial: { opacity: 0, y: 10 },
|
|
838
854
|
animate: { opacity: 1, y: 0 },
|
|
839
|
-
children: /* @__PURE__ */
|
|
855
|
+
children: /* @__PURE__ */ jsxs10("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: [
|
|
840
856
|
/* @__PURE__ */ jsx11("p", { className: "text-sm", children: msg.content }),
|
|
841
857
|
msg.timestamp && /* @__PURE__ */ jsx11("p", { className: `text-xs mt-1 ${msg.role === "user" ? "text-blue-100" : "text-gray-400"}`, children: msg.timestamp })
|
|
842
858
|
] })
|
|
843
859
|
},
|
|
844
860
|
msg.id
|
|
845
861
|
)) }),
|
|
846
|
-
/* @__PURE__ */ jsx11("div", { className: "p-3 border-t", children: /* @__PURE__ */
|
|
862
|
+
/* @__PURE__ */ jsx11("div", { className: "p-3 border-t", children: /* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
|
|
847
863
|
/* @__PURE__ */ jsx11(
|
|
848
864
|
"input",
|
|
849
865
|
{
|
|
@@ -869,7 +885,7 @@ function ChatOverlay({ data, onDismiss }) {
|
|
|
869
885
|
|
|
870
886
|
// src/components/overlays/InsightOverlay.tsx
|
|
871
887
|
import { motion as motion5 } from "framer-motion";
|
|
872
|
-
import { jsx as jsx12, jsxs as
|
|
888
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
873
889
|
var insightStyles = {
|
|
874
890
|
recommendation: { bg: "bg-green-50", border: "border-green-200", icon: "\u2191", iconColor: "text-green-500" },
|
|
875
891
|
comparison: { bg: "bg-blue-50", border: "border-blue-200", icon: "\u2261", iconColor: "text-blue-500" },
|
|
@@ -877,9 +893,9 @@ var insightStyles = {
|
|
|
877
893
|
};
|
|
878
894
|
function InsightOverlay({ data, onDismiss }) {
|
|
879
895
|
const { title, subtitle, insights = [], actions = [], onAction } = data ?? {};
|
|
880
|
-
return /* @__PURE__ */
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
896
|
+
return /* @__PURE__ */ jsxs11("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-md", children: [
|
|
897
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between mb-4", children: [
|
|
898
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
883
899
|
title && /* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold", children: title }),
|
|
884
900
|
subtitle && /* @__PURE__ */ jsx12("p", { className: "text-sm text-gray-500", children: subtitle })
|
|
885
901
|
] }),
|
|
@@ -894,11 +910,11 @@ function InsightOverlay({ data, onDismiss }) {
|
|
|
894
910
|
initial: { opacity: 0, x: -10 },
|
|
895
911
|
animate: { opacity: 1, x: 0 },
|
|
896
912
|
transition: { delay: i * 0.1 },
|
|
897
|
-
children: /* @__PURE__ */
|
|
913
|
+
children: /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-2", children: [
|
|
898
914
|
/* @__PURE__ */ jsx12("span", { className: style.iconColor, children: style.icon }),
|
|
899
|
-
/* @__PURE__ */
|
|
915
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex-1", children: [
|
|
900
916
|
/* @__PURE__ */ jsx12("p", { className: "text-sm", children: insight.text }),
|
|
901
|
-
insight.confidence != null && /* @__PURE__ */
|
|
917
|
+
insight.confidence != null && /* @__PURE__ */ jsxs11("p", { className: "text-xs text-gray-400 mt-1", children: [
|
|
902
918
|
"Confidence: ",
|
|
903
919
|
Math.round(insight.confidence * 100),
|
|
904
920
|
"%"
|
|
@@ -922,10 +938,10 @@ function InsightOverlay({ data, onDismiss }) {
|
|
|
922
938
|
}
|
|
923
939
|
|
|
924
940
|
// src/components/overlays/DetailCardOverlay.tsx
|
|
925
|
-
import { jsx as jsx13, jsxs as
|
|
941
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
926
942
|
function DetailCardOverlay({ data, onDismiss }) {
|
|
927
943
|
const { title, body, image, metadata, actions } = data ?? {};
|
|
928
|
-
return /* @__PURE__ */
|
|
944
|
+
return /* @__PURE__ */ jsxs12("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-lg", children: [
|
|
929
945
|
image && /* @__PURE__ */ jsx13(
|
|
930
946
|
"img",
|
|
931
947
|
{
|
|
@@ -936,11 +952,11 @@ function DetailCardOverlay({ data, onDismiss }) {
|
|
|
936
952
|
),
|
|
937
953
|
title && /* @__PURE__ */ jsx13("h3", { className: "text-lg font-semibold mb-1", children: title }),
|
|
938
954
|
body && /* @__PURE__ */ jsx13("p", { className: "text-sm text-gray-600 mb-4 leading-relaxed", children: body }),
|
|
939
|
-
metadata && Object.keys(metadata).length > 0 && /* @__PURE__ */ jsx13("div", { className: "space-y-1.5 mb-4", children: Object.entries(metadata).map(([key, value]) => /* @__PURE__ */
|
|
955
|
+
metadata && Object.keys(metadata).length > 0 && /* @__PURE__ */ jsx13("div", { className: "space-y-1.5 mb-4", children: Object.entries(metadata).map(([key, value]) => /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between py-1.5 border-b border-gray-100 last:border-0", children: [
|
|
940
956
|
/* @__PURE__ */ jsx13("span", { className: "text-xs font-medium text-gray-400 uppercase tracking-wider", children: key }),
|
|
941
957
|
/* @__PURE__ */ jsx13("span", { className: "text-sm text-gray-700", children: value })
|
|
942
958
|
] }, key)) }),
|
|
943
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex gap-2 justify-end", children: [
|
|
944
960
|
actions?.map((action, i) => /* @__PURE__ */ jsx13(
|
|
945
961
|
"button",
|
|
946
962
|
{
|
|
@@ -963,18 +979,18 @@ function DetailCardOverlay({ data, onDismiss }) {
|
|
|
963
979
|
}
|
|
964
980
|
|
|
965
981
|
// src/components/overlays/ComparisonOverlay.tsx
|
|
966
|
-
import { jsx as jsx14, jsxs as
|
|
982
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
967
983
|
function ComparisonOverlay({ data, onDismiss }) {
|
|
968
984
|
const { title, items } = data ?? {};
|
|
969
985
|
const attributeKeys = items?.length ? [...new Set(items.flatMap((item) => Object.keys(item.attributes)))] : [];
|
|
970
|
-
return /* @__PURE__ */
|
|
986
|
+
return /* @__PURE__ */ jsxs13("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[400px] max-w-2xl", children: [
|
|
971
987
|
title && /* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
972
|
-
items && items.length > 0 && /* @__PURE__ */ jsx14("div", { className: "overflow-x-auto mb-4", children: /* @__PURE__ */
|
|
973
|
-
/* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */
|
|
988
|
+
items && items.length > 0 && /* @__PURE__ */ jsx14("div", { className: "overflow-x-auto mb-4", children: /* @__PURE__ */ jsxs13("table", { className: "w-full text-sm", children: [
|
|
989
|
+
/* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsxs13("tr", { className: "border-b border-gray-200", children: [
|
|
974
990
|
/* @__PURE__ */ jsx14("th", { className: "text-left py-2 pr-4 text-gray-400 font-medium text-xs uppercase tracking-wider", children: "Feature" }),
|
|
975
991
|
items.map((item) => /* @__PURE__ */ jsx14("th", { className: "text-center py-2 px-3 font-semibold text-gray-800", children: item.name }, item.name))
|
|
976
992
|
] }) }),
|
|
977
|
-
/* @__PURE__ */ jsx14("tbody", { children: attributeKeys.map((key, i) => /* @__PURE__ */
|
|
993
|
+
/* @__PURE__ */ jsx14("tbody", { children: attributeKeys.map((key, i) => /* @__PURE__ */ jsxs13("tr", { className: i % 2 === 0 ? "bg-gray-50" : "", children: [
|
|
978
994
|
/* @__PURE__ */ jsx14("td", { className: "py-2 pr-4 text-gray-600 font-medium", children: key }),
|
|
979
995
|
items.map((item) => /* @__PURE__ */ jsx14("td", { className: "text-center py-2 px-3 text-gray-700", children: String(item.attributes[key] ?? "\u2014") }, item.name))
|
|
980
996
|
] }, key)) })
|
|
@@ -992,7 +1008,7 @@ function ComparisonOverlay({ data, onDismiss }) {
|
|
|
992
1008
|
|
|
993
1009
|
// src/components/overlays/CalendarOverlay.tsx
|
|
994
1010
|
import { useState as useState5, useMemo as useMemo3 } from "react";
|
|
995
|
-
import { Fragment, jsx as jsx15, jsxs as
|
|
1011
|
+
import { Fragment, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
996
1012
|
function CalendarOverlay({ data, onDismiss }) {
|
|
997
1013
|
const { title, available_slots, onSelect } = data ?? {};
|
|
998
1014
|
const [selectedDate, setSelectedDate] = useState5(null);
|
|
@@ -1016,9 +1032,9 @@ function CalendarOverlay({ data, onDismiss }) {
|
|
|
1016
1032
|
onDismiss();
|
|
1017
1033
|
}
|
|
1018
1034
|
};
|
|
1019
|
-
return /* @__PURE__ */
|
|
1035
|
+
return /* @__PURE__ */ jsxs14("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
|
|
1020
1036
|
title && /* @__PURE__ */ jsx15("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1021
|
-
dates.length > 0 && /* @__PURE__ */
|
|
1037
|
+
dates.length > 0 && /* @__PURE__ */ jsxs14(Fragment, { children: [
|
|
1022
1038
|
/* @__PURE__ */ jsx15("div", { className: "flex gap-2 overflow-x-auto pb-2 mb-3", children: dates.map((date) => /* @__PURE__ */ jsx15(
|
|
1023
1039
|
"button",
|
|
1024
1040
|
{
|
|
@@ -1046,7 +1062,7 @@ function CalendarOverlay({ data, onDismiss }) {
|
|
|
1046
1062
|
);
|
|
1047
1063
|
}) })
|
|
1048
1064
|
] }),
|
|
1049
|
-
/* @__PURE__ */
|
|
1065
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex gap-2 justify-end", children: [
|
|
1050
1066
|
selectedSlot && /* @__PURE__ */ jsx15(
|
|
1051
1067
|
"button",
|
|
1052
1068
|
{
|
|
@@ -1068,12 +1084,12 @@ function CalendarOverlay({ data, onDismiss }) {
|
|
|
1068
1084
|
}
|
|
1069
1085
|
|
|
1070
1086
|
// src/components/overlays/MediaOverlay.tsx
|
|
1071
|
-
import { jsx as jsx16, jsxs as
|
|
1087
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1072
1088
|
function MediaOverlay({ data, onDismiss }) {
|
|
1073
1089
|
const { title, url, type = "image", alt, autoplay } = data ?? {};
|
|
1074
|
-
return /* @__PURE__ */
|
|
1090
|
+
return /* @__PURE__ */ jsxs15("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-xl", children: [
|
|
1075
1091
|
title && /* @__PURE__ */ jsx16("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1076
|
-
url && /* @__PURE__ */
|
|
1092
|
+
url && /* @__PURE__ */ jsxs15("div", { className: "mb-4 rounded-xl overflow-hidden bg-gray-100", children: [
|
|
1077
1093
|
type === "video" && /* @__PURE__ */ jsx16(
|
|
1078
1094
|
"video",
|
|
1079
1095
|
{
|
|
@@ -1105,17 +1121,17 @@ function MediaOverlay({ data, onDismiss }) {
|
|
|
1105
1121
|
}
|
|
1106
1122
|
|
|
1107
1123
|
// src/components/overlays/MapOverlay.tsx
|
|
1108
|
-
import { jsx as jsx17, jsxs as
|
|
1124
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1109
1125
|
function MapOverlay({ data, onDismiss }) {
|
|
1110
1126
|
const { title, locations } = data ?? {};
|
|
1111
1127
|
const getMapsUrl = (loc) => `https://www.google.com/maps/search/?api=1&query=${loc.lat},${loc.lng}`;
|
|
1112
|
-
return /* @__PURE__ */
|
|
1128
|
+
return /* @__PURE__ */ jsxs16("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-md", children: [
|
|
1113
1129
|
title && /* @__PURE__ */ jsx17("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1114
|
-
locations && locations.length > 0 && /* @__PURE__ */ jsx17("div", { className: "space-y-3 mb-4", children: locations.map((loc, i) => /* @__PURE__ */
|
|
1130
|
+
locations && locations.length > 0 && /* @__PURE__ */ jsx17("div", { className: "space-y-3 mb-4", children: locations.map((loc, i) => /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-3 p-3 rounded-xl bg-gray-50", children: [
|
|
1115
1131
|
/* @__PURE__ */ jsx17("div", { className: "w-8 h-8 rounded-full bg-red-100 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx17("svg", { className: "w-4 h-4 text-red-500", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx17("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" }) }) }),
|
|
1116
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0", children: [
|
|
1117
1133
|
loc.label && /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-gray-800", children: loc.label }),
|
|
1118
|
-
/* @__PURE__ */
|
|
1134
|
+
/* @__PURE__ */ jsxs16("p", { className: "text-xs text-gray-400", children: [
|
|
1119
1135
|
loc.lat.toFixed(4),
|
|
1120
1136
|
", ",
|
|
1121
1137
|
loc.lng.toFixed(4)
|
|
@@ -1145,7 +1161,7 @@ function MapOverlay({ data, onDismiss }) {
|
|
|
1145
1161
|
|
|
1146
1162
|
// src/components/overlays/RichTextOverlay.tsx
|
|
1147
1163
|
import { useMemo as useMemo4 } from "react";
|
|
1148
|
-
import { jsx as jsx18, jsxs as
|
|
1164
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1149
1165
|
function parseMarkdown(md) {
|
|
1150
1166
|
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>');
|
|
1151
1167
|
return html;
|
|
@@ -1153,7 +1169,7 @@ function parseMarkdown(md) {
|
|
|
1153
1169
|
function RichTextOverlay({ data, onDismiss }) {
|
|
1154
1170
|
const { title, content } = data ?? {};
|
|
1155
1171
|
const html = useMemo4(() => content ? parseMarkdown(content) : "", [content]);
|
|
1156
|
-
return /* @__PURE__ */
|
|
1172
|
+
return /* @__PURE__ */ jsxs17("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[320px] max-w-lg", children: [
|
|
1157
1173
|
title && /* @__PURE__ */ jsx18("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1158
1174
|
html && /* @__PURE__ */ jsx18(
|
|
1159
1175
|
"div",
|
|
@@ -1174,11 +1190,11 @@ function RichTextOverlay({ data, onDismiss }) {
|
|
|
1174
1190
|
}
|
|
1175
1191
|
|
|
1176
1192
|
// src/components/overlays/ChartOverlay.tsx
|
|
1177
|
-
import { jsx as jsx19, jsxs as
|
|
1193
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1178
1194
|
var DEFAULT_COLORS = ["#3b82f6", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#06b6d4", "#ef4444", "#84cc16"];
|
|
1179
1195
|
function BarChart({ series }) {
|
|
1180
1196
|
const max = Math.max(...series.map((s) => s.value), 1);
|
|
1181
|
-
return /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: series.map((item, i) => /* @__PURE__ */
|
|
1197
|
+
return /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: series.map((item, i) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3", children: [
|
|
1182
1198
|
/* @__PURE__ */ jsx19("span", { className: "text-xs text-gray-500 w-20 truncate text-right", children: item.label }),
|
|
1183
1199
|
/* @__PURE__ */ jsx19("div", { className: "flex-1 h-6 bg-gray-100 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx19(
|
|
1184
1200
|
"div",
|
|
@@ -1198,7 +1214,7 @@ function PieChart({ series }) {
|
|
|
1198
1214
|
const radius = 60;
|
|
1199
1215
|
const circumference = 2 * Math.PI * radius;
|
|
1200
1216
|
let offset = 0;
|
|
1201
|
-
return /* @__PURE__ */
|
|
1217
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-6", children: [
|
|
1202
1218
|
/* @__PURE__ */ jsx19("svg", { width: "160", height: "160", viewBox: "0 0 160 160", className: "flex-shrink-0", children: series.map((item, i) => {
|
|
1203
1219
|
const dash = item.value / total * circumference;
|
|
1204
1220
|
const currentOffset = offset;
|
|
@@ -1219,7 +1235,7 @@ function PieChart({ series }) {
|
|
|
1219
1235
|
i
|
|
1220
1236
|
);
|
|
1221
1237
|
}) }),
|
|
1222
|
-
/* @__PURE__ */ jsx19("div", { className: "space-y-1.5", children: series.map((item, i) => /* @__PURE__ */
|
|
1238
|
+
/* @__PURE__ */ jsx19("div", { className: "space-y-1.5", children: series.map((item, i) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
1223
1239
|
/* @__PURE__ */ jsx19(
|
|
1224
1240
|
"div",
|
|
1225
1241
|
{
|
|
@@ -1228,7 +1244,7 @@ function PieChart({ series }) {
|
|
|
1228
1244
|
}
|
|
1229
1245
|
),
|
|
1230
1246
|
/* @__PURE__ */ jsx19("span", { className: "text-xs text-gray-600", children: item.label }),
|
|
1231
|
-
/* @__PURE__ */
|
|
1247
|
+
/* @__PURE__ */ jsxs18("span", { className: "text-xs font-medium text-gray-800", children: [
|
|
1232
1248
|
Math.round(item.value / total * 100),
|
|
1233
1249
|
"%"
|
|
1234
1250
|
] })
|
|
@@ -1245,8 +1261,8 @@ function LineChart({ series }) {
|
|
|
1245
1261
|
y: height - padding - item.value / max * (height - padding * 2)
|
|
1246
1262
|
}));
|
|
1247
1263
|
const pathD = points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
|
|
1248
|
-
return /* @__PURE__ */
|
|
1249
|
-
/* @__PURE__ */
|
|
1264
|
+
return /* @__PURE__ */ jsxs18("div", { children: [
|
|
1265
|
+
/* @__PURE__ */ jsxs18("svg", { width, height, viewBox: `0 0 ${width} ${height}`, className: "w-full", children: [
|
|
1250
1266
|
/* @__PURE__ */ jsx19("path", { d: pathD, fill: "none", stroke: "#3b82f6", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1251
1267
|
points.map((p, i) => /* @__PURE__ */ jsx19("circle", { cx: p.x, cy: p.y, r: "3", fill: "#3b82f6" }, i))
|
|
1252
1268
|
] }),
|
|
@@ -1255,9 +1271,9 @@ function LineChart({ series }) {
|
|
|
1255
1271
|
}
|
|
1256
1272
|
function ChartOverlay({ data, onDismiss }) {
|
|
1257
1273
|
const { title, type = "bar", series } = data ?? {};
|
|
1258
|
-
return /* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ jsxs18("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-md", children: [
|
|
1259
1275
|
title && /* @__PURE__ */ jsx19("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1260
|
-
series && series.length > 0 && /* @__PURE__ */
|
|
1276
|
+
series && series.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "mb-4", children: [
|
|
1261
1277
|
type === "bar" && /* @__PURE__ */ jsx19(BarChart, { series }),
|
|
1262
1278
|
type === "pie" && /* @__PURE__ */ jsx19(PieChart, { series }),
|
|
1263
1279
|
type === "line" && /* @__PURE__ */ jsx19(LineChart, { series })
|
|
@@ -1275,7 +1291,7 @@ function ChartOverlay({ data, onDismiss }) {
|
|
|
1275
1291
|
|
|
1276
1292
|
// src/components/overlays/FileUploadOverlay.tsx
|
|
1277
1293
|
import { useRef as useRef3, useState as useState6, useCallback as useCallback6 } from "react";
|
|
1278
|
-
import { jsx as jsx20, jsxs as
|
|
1294
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1279
1295
|
var MIME_MAP = {
|
|
1280
1296
|
pdf: "application/pdf",
|
|
1281
1297
|
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
@@ -1316,9 +1332,9 @@ function FileUploadOverlay({ data, onDismiss }) {
|
|
|
1316
1332
|
onDismiss();
|
|
1317
1333
|
}
|
|
1318
1334
|
};
|
|
1319
|
-
return /* @__PURE__ */
|
|
1335
|
+
return /* @__PURE__ */ jsxs19("div", { className: "bg-white rounded-2xl shadow-2xl p-6 min-w-[280px] max-w-sm", children: [
|
|
1320
1336
|
title && /* @__PURE__ */ jsx20("h3", { className: "text-lg font-semibold mb-4", children: title }),
|
|
1321
|
-
/* @__PURE__ */
|
|
1337
|
+
/* @__PURE__ */ jsxs19(
|
|
1322
1338
|
"div",
|
|
1323
1339
|
{
|
|
1324
1340
|
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"}`,
|
|
@@ -1337,7 +1353,7 @@ function FileUploadOverlay({ data, onDismiss }) {
|
|
|
1337
1353
|
/* @__PURE__ */ jsx20("svg", { className: "w-8 h-8 text-gray-300 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx20("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" }) }),
|
|
1338
1354
|
/* @__PURE__ */ jsx20("p", { className: "text-sm text-gray-500", children: "Drop files here or click to browse" }),
|
|
1339
1355
|
accept && /* @__PURE__ */ jsx20("p", { className: "text-xs text-gray-400 mt-1", children: accept.map((e) => `.${e}`).join(", ") }),
|
|
1340
|
-
max_size && /* @__PURE__ */
|
|
1356
|
+
max_size && /* @__PURE__ */ jsxs19("p", { className: "text-xs text-gray-400", children: [
|
|
1341
1357
|
"Max ",
|
|
1342
1358
|
formatSize(max_size)
|
|
1343
1359
|
] }),
|
|
@@ -1355,14 +1371,14 @@ function FileUploadOverlay({ data, onDismiss }) {
|
|
|
1355
1371
|
]
|
|
1356
1372
|
}
|
|
1357
1373
|
),
|
|
1358
|
-
files.length > 0 && /* @__PURE__ */ jsx20("div", { className: "space-y-2 mb-4", children: files.map((file, i) => /* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1374
|
+
files.length > 0 && /* @__PURE__ */ jsx20("div", { className: "space-y-2 mb-4", children: files.map((file, i) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between py-1.5 px-3 bg-gray-50 rounded-lg", children: [
|
|
1375
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
|
|
1360
1376
|
/* @__PURE__ */ jsx20("p", { className: "text-sm text-gray-700 truncate", children: file.name }),
|
|
1361
1377
|
/* @__PURE__ */ jsx20("p", { className: "text-xs text-gray-400", children: formatSize(file.size) })
|
|
1362
1378
|
] }),
|
|
1363
1379
|
/* @__PURE__ */ jsx20("button", { onClick: () => removeFile(i), className: "text-gray-400 hover:text-red-500 text-sm ml-2", children: "\xD7" })
|
|
1364
1380
|
] }, i)) }),
|
|
1365
|
-
/* @__PURE__ */
|
|
1381
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex gap-2 justify-end", children: [
|
|
1366
1382
|
files.length > 0 && /* @__PURE__ */ jsx20(
|
|
1367
1383
|
"button",
|
|
1368
1384
|
{
|
|
@@ -1384,27 +1400,40 @@ function FileUploadOverlay({ data, onDismiss }) {
|
|
|
1384
1400
|
}
|
|
1385
1401
|
|
|
1386
1402
|
// src/components/AvatarFirst.tsx
|
|
1387
|
-
import { jsx as jsx21, jsxs as
|
|
1403
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1388
1404
|
var defaultOverlays = {
|
|
1389
1405
|
card: CardOverlay,
|
|
1406
|
+
card_list: CardOverlay,
|
|
1407
|
+
detail: DetailCardOverlay,
|
|
1408
|
+
detail_card: DetailCardOverlay,
|
|
1390
1409
|
form: FormOverlay,
|
|
1391
1410
|
table: TableOverlay,
|
|
1392
1411
|
progress: ProgressOverlay,
|
|
1393
1412
|
confirm: ConfirmOverlay,
|
|
1394
1413
|
chat: ChatOverlay,
|
|
1395
|
-
insight: InsightOverlay
|
|
1414
|
+
insight: InsightOverlay,
|
|
1415
|
+
comparison: ComparisonOverlay,
|
|
1416
|
+
calendar: CalendarOverlay,
|
|
1417
|
+
media: MediaOverlay,
|
|
1418
|
+
map: MapOverlay,
|
|
1419
|
+
rich_text: RichTextOverlay,
|
|
1420
|
+
chart: ChartOverlay,
|
|
1421
|
+
file_upload: FileUploadOverlay
|
|
1396
1422
|
};
|
|
1397
1423
|
function AvatarFirstInner({
|
|
1398
1424
|
client,
|
|
1425
|
+
onContainer,
|
|
1426
|
+
onActions,
|
|
1399
1427
|
onOverlay,
|
|
1400
1428
|
onAction
|
|
1401
1429
|
}) {
|
|
1402
1430
|
const { state: avatarState, speak } = useAvatar();
|
|
1403
|
-
const { show } = useOverlay();
|
|
1431
|
+
const { show, hide } = useOverlay();
|
|
1404
1432
|
const [sessionId, setSessionId] = useState7(null);
|
|
1405
1433
|
const [greeting, setGreeting] = useState7(null);
|
|
1406
1434
|
const [hasGreeted, setHasGreeted] = useState7(false);
|
|
1407
1435
|
const [isProcessing, setIsProcessing] = useState7(false);
|
|
1436
|
+
const activeContainerRef = useRef4(null);
|
|
1408
1437
|
useEffect5(() => {
|
|
1409
1438
|
if (avatarState === "connected" && !sessionId) {
|
|
1410
1439
|
client.createSession().then((session) => {
|
|
@@ -1421,28 +1450,98 @@ function AvatarFirstInner({
|
|
|
1421
1450
|
speak(greeting);
|
|
1422
1451
|
}
|
|
1423
1452
|
}, [sessionId, avatarState, greeting, hasGreeted, speak]);
|
|
1453
|
+
const applyContainerAction = useCallback7((ui) => {
|
|
1454
|
+
if (!ui) return;
|
|
1455
|
+
switch (ui.action) {
|
|
1456
|
+
case "show": {
|
|
1457
|
+
const position = ui.position === "modal" ? "center" : "chest";
|
|
1458
|
+
const animation = ui.position === "modal" ? "fade" : "slide-up";
|
|
1459
|
+
show({
|
|
1460
|
+
id: ui.id,
|
|
1461
|
+
component: ui.type,
|
|
1462
|
+
data: {
|
|
1463
|
+
...ui.data,
|
|
1464
|
+
title: ui.title,
|
|
1465
|
+
intents: ui.intents
|
|
1466
|
+
},
|
|
1467
|
+
position,
|
|
1468
|
+
animation,
|
|
1469
|
+
dismissOnClickOutside: ui.dismissible ?? true
|
|
1470
|
+
});
|
|
1471
|
+
activeContainerRef.current = ui;
|
|
1472
|
+
onContainer?.(ui);
|
|
1473
|
+
break;
|
|
1474
|
+
}
|
|
1475
|
+
case "update": {
|
|
1476
|
+
if (activeContainerRef.current) {
|
|
1477
|
+
const updated = {
|
|
1478
|
+
...activeContainerRef.current,
|
|
1479
|
+
data: { ...activeContainerRef.current.data, ...ui.data }
|
|
1480
|
+
};
|
|
1481
|
+
show({
|
|
1482
|
+
id: updated.id,
|
|
1483
|
+
component: updated.type,
|
|
1484
|
+
data: {
|
|
1485
|
+
...updated.data,
|
|
1486
|
+
title: updated.title,
|
|
1487
|
+
intents: updated.intents
|
|
1488
|
+
},
|
|
1489
|
+
position: updated.position === "modal" ? "center" : "chest",
|
|
1490
|
+
animation: "none",
|
|
1491
|
+
dismissOnClickOutside: updated.dismissible ?? true
|
|
1492
|
+
});
|
|
1493
|
+
activeContainerRef.current = updated;
|
|
1494
|
+
}
|
|
1495
|
+
onContainer?.(ui);
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
case "dismiss": {
|
|
1499
|
+
hide(ui.id ?? activeContainerRef.current?.id);
|
|
1500
|
+
activeContainerRef.current = null;
|
|
1501
|
+
onContainer?.(ui);
|
|
1502
|
+
break;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}, [show, hide, onContainer]);
|
|
1424
1506
|
const handleResponse = useCallback7((data) => {
|
|
1425
1507
|
if (data.speech) {
|
|
1426
1508
|
speak(data.speech);
|
|
1427
1509
|
}
|
|
1428
|
-
if (data.
|
|
1510
|
+
if (data.ui) {
|
|
1511
|
+
applyContainerAction(data.ui);
|
|
1512
|
+
} else if (data.overlay) {
|
|
1429
1513
|
const overlayId = `overlay-${Date.now()}`;
|
|
1430
1514
|
show({
|
|
1431
1515
|
id: overlayId,
|
|
1432
1516
|
component: data.overlay.type,
|
|
1433
|
-
data: data.overlay.data,
|
|
1434
|
-
position: "
|
|
1435
|
-
animation: "slide-
|
|
1517
|
+
data: data.overlay.data ?? {},
|
|
1518
|
+
position: "chest",
|
|
1519
|
+
animation: "slide-up",
|
|
1436
1520
|
dismissOnClickOutside: true
|
|
1437
1521
|
});
|
|
1438
1522
|
onOverlay?.(data.overlay);
|
|
1439
1523
|
}
|
|
1440
|
-
if (data.actions) {
|
|
1441
|
-
|
|
1442
|
-
|
|
1524
|
+
if (data.actions && data.actions.length > 0) {
|
|
1525
|
+
onActions?.(data.actions);
|
|
1526
|
+
if (onAction) {
|
|
1527
|
+
for (const action of data.actions) {
|
|
1528
|
+
onAction({ type: action.intent, payload: action.data });
|
|
1529
|
+
}
|
|
1443
1530
|
}
|
|
1444
1531
|
}
|
|
1445
|
-
}, [speak, show, onOverlay, onAction]);
|
|
1532
|
+
}, [speak, applyContainerAction, show, onOverlay, onActions, onAction]);
|
|
1533
|
+
const handleIntent = useCallback7(async (intent) => {
|
|
1534
|
+
if (!sessionId || isProcessing) return;
|
|
1535
|
+
setIsProcessing(true);
|
|
1536
|
+
try {
|
|
1537
|
+
const response = await client.sendIntent(sessionId, intent);
|
|
1538
|
+
handleResponse(response);
|
|
1539
|
+
} catch (err) {
|
|
1540
|
+
console.error("[AvatarFirst] Intent failed:", err);
|
|
1541
|
+
} finally {
|
|
1542
|
+
setIsProcessing(false);
|
|
1543
|
+
}
|
|
1544
|
+
}, [client, sessionId, isProcessing, handleResponse]);
|
|
1446
1545
|
const handleSend = useCallback7(async (text) => {
|
|
1447
1546
|
if (!sessionId || isProcessing) return;
|
|
1448
1547
|
setIsProcessing(true);
|
|
@@ -1456,7 +1555,7 @@ function AvatarFirstInner({
|
|
|
1456
1555
|
}
|
|
1457
1556
|
}, [client, sessionId, isProcessing, handleResponse]);
|
|
1458
1557
|
const isConnected = avatarState === "connected" || avatarState === "speaking" || avatarState === "listening" || avatarState === "thinking";
|
|
1459
|
-
return /* @__PURE__ */
|
|
1558
|
+
return /* @__PURE__ */ jsxs20("div", { className: "relative w-full h-full", children: [
|
|
1460
1559
|
/* @__PURE__ */ jsx21(AvatarView, { size: "fullscreen", showStatus: false, className: "w-full h-full" }),
|
|
1461
1560
|
isConnected && sessionId && /* @__PURE__ */ jsx21("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 z-20 w-full max-w-md px-4", children: /* @__PURE__ */ jsx21(
|
|
1462
1561
|
"form",
|
|
@@ -1481,7 +1580,7 @@ function AvatarFirstInner({
|
|
|
1481
1580
|
)
|
|
1482
1581
|
}
|
|
1483
1582
|
) }),
|
|
1484
|
-
!isConnected && /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 flex items-center justify-center bg-slate-950/80 z-30", children: /* @__PURE__ */
|
|
1583
|
+
!isConnected && /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 flex items-center justify-center bg-slate-950/80 z-30", children: /* @__PURE__ */ jsxs20("div", { className: "text-center", children: [
|
|
1485
1584
|
/* @__PURE__ */ jsx21("div", { className: "w-12 h-12 border-2 border-purple-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" }),
|
|
1486
1585
|
/* @__PURE__ */ jsx21("p", { className: "text-white/60 text-sm", children: "Connecting..." })
|
|
1487
1586
|
] }) })
|
|
@@ -1490,6 +1589,8 @@ function AvatarFirstInner({
|
|
|
1490
1589
|
function AvatarFirst({
|
|
1491
1590
|
apiKey,
|
|
1492
1591
|
baseUrl,
|
|
1592
|
+
onContainer,
|
|
1593
|
+
onActions,
|
|
1493
1594
|
onOverlay,
|
|
1494
1595
|
onAction,
|
|
1495
1596
|
onStateChange,
|
|
@@ -1548,7 +1649,7 @@ function AvatarFirst({
|
|
|
1548
1649
|
}, [agent]);
|
|
1549
1650
|
if (error || !agent) {
|
|
1550
1651
|
if (error) {
|
|
1551
|
-
return /* @__PURE__ */ jsx21("div", { className: `flex items-center justify-center bg-slate-950 ${className || ""}`, children: /* @__PURE__ */
|
|
1652
|
+
return /* @__PURE__ */ jsx21("div", { className: `flex items-center justify-center bg-slate-950 ${className || ""}`, children: /* @__PURE__ */ jsxs20("div", { className: "text-center", children: [
|
|
1552
1653
|
/* @__PURE__ */ jsx21("p", { className: "text-red-400 mb-2 text-sm", children: "Failed to connect" }),
|
|
1553
1654
|
/* @__PURE__ */ jsx21(
|
|
1554
1655
|
"button",
|
|
@@ -1562,9 +1663,18 @@ function AvatarFirst({
|
|
|
1562
1663
|
}
|
|
1563
1664
|
return /* @__PURE__ */ jsx21("div", { className: `flex items-center justify-center bg-slate-950 ${className || ""}`, children: /* @__PURE__ */ jsx21("div", { className: "w-12 h-12 border-2 border-purple-500 border-t-transparent rounded-full animate-spin" }) });
|
|
1564
1665
|
}
|
|
1565
|
-
return /* @__PURE__ */ jsx21("div", { className, children: /* @__PURE__ */
|
|
1666
|
+
return /* @__PURE__ */ jsx21("div", { className, children: /* @__PURE__ */ jsxs20(AvatarProvider, { agent, autoStart: true, children: [
|
|
1566
1667
|
/* @__PURE__ */ jsx21(OverlayContainer, { components: mergedOverlays }),
|
|
1567
|
-
/* @__PURE__ */ jsx21(
|
|
1668
|
+
/* @__PURE__ */ jsx21(
|
|
1669
|
+
AvatarFirstInner,
|
|
1670
|
+
{
|
|
1671
|
+
client,
|
|
1672
|
+
onContainer,
|
|
1673
|
+
onActions,
|
|
1674
|
+
onOverlay,
|
|
1675
|
+
onAction
|
|
1676
|
+
}
|
|
1677
|
+
)
|
|
1568
1678
|
] }) });
|
|
1569
1679
|
}
|
|
1570
1680
|
|