@planetaexo/design-system 0.51.0 → 0.52.1

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 CHANGED
@@ -3562,6 +3562,7 @@ function BookingDetails({
3562
3562
  status,
3563
3563
  statusLabel,
3564
3564
  createdAt,
3565
+ cancelledAt,
3565
3566
  contact,
3566
3567
  agent,
3567
3568
  agentName,
@@ -3606,7 +3607,7 @@ function BookingDetails({
3606
3607
  labels,
3607
3608
  className
3608
3609
  }) {
3609
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H;
3610
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J;
3610
3611
  const people = totalPeople(adventures);
3611
3612
  const hasSubmitAddTraveller = !!onSubmitAddTraveller;
3612
3613
  const hasSubmitEditTraveller = !!onSubmitEditTraveller;
@@ -3739,12 +3740,18 @@ function BookingDetails({
3739
3740
  bookingId
3740
3741
  ] })
3741
3742
  ] }),
3742
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: (_b = (_a = labels == null ? void 0 : labels.createdOn) == null ? void 0 : _a.call(labels, createdAt)) != null ? _b : `Created on ${createdAt}` })
3743
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground font-sans", children: [
3744
+ (_b = (_a = labels == null ? void 0 : labels.createdOn) == null ? void 0 : _a.call(labels, createdAt)) != null ? _b : `Created on ${createdAt}`,
3745
+ cancelledAt && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3746
+ ", ",
3747
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive font-medium", children: (_d = (_c = labels == null ? void 0 : labels.cancelledOn) == null ? void 0 : _c.call(labels, cancelledAt)) != null ? _d : `cancelled on ${cancelledAt}` })
3748
+ ] })
3749
+ ] })
3743
3750
  ] }),
3744
3751
  /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status, label: statusLabel })
3745
3752
  ] }),
3746
3753
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-3", children: [
3747
- /* @__PURE__ */ jsxRuntime.jsxs(InfoCard, { label: (_c = labels == null ? void 0 : labels.contactInfo) != null ? _c : "Contact", children: [
3754
+ /* @__PURE__ */ jsxRuntime.jsxs(InfoCard, { label: (_e = labels == null ? void 0 : labels.contactInfo) != null ? _e : "Contact", children: [
3748
3755
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: contact.name }),
3749
3756
  contact.email && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans truncate", children: contact.email })
3750
3757
  ] }),
@@ -3752,7 +3759,7 @@ function BookingDetails({
3752
3759
  AgentContactCard,
3753
3760
  {
3754
3761
  layout: "compact",
3755
- name: (_d = agent == null ? void 0 : agent.name) != null ? _d : agentName,
3762
+ name: (_f = agent == null ? void 0 : agent.name) != null ? _f : agentName,
3756
3763
  avatar: agent == null ? void 0 : agent.avatar,
3757
3764
  email: agent == null ? void 0 : agent.email,
3758
3765
  whatsappUrl: agent == null ? void 0 : agent.whatsappUrl,
@@ -3762,20 +3769,20 @@ function BookingDetails({
3762
3769
  legacyContactLabel: agentContactLabel
3763
3770
  }
3764
3771
  ),
3765
- /* @__PURE__ */ jsxRuntime.jsxs(InfoCard, { label: (_e = labels == null ? void 0 : labels.totalPeople) != null ? _e : "Total People", children: [
3772
+ /* @__PURE__ */ jsxRuntime.jsxs(InfoCard, { label: (_g = labels == null ? void 0 : labels.totalPeople) != null ? _g : "Total People", children: [
3766
3773
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3767
3774
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-4 h-4 text-primary shrink-0" }),
3768
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: (_g = (_f = labels == null ? void 0 : labels.personCount) == null ? void 0 : _f.call(labels, people.total)) != null ? _g : `${people.total} person(s)` })
3775
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: (_i = (_h = labels == null ? void 0 : labels.personCount) == null ? void 0 : _h.call(labels, people.total)) != null ? _i : `${people.total} person(s)` })
3769
3776
  ] }),
3770
3777
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: [
3771
- people.adults > 0 ? (_j = (_i = (_h = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _h.adults) == null ? void 0 : _i.call(_h, people.adults)) != null ? _j : `Adults: ${people.adults}` : null,
3772
- people.children > 0 ? (_m = (_l = (_k = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _k.children) == null ? void 0 : _l.call(_k, people.children)) != null ? _m : `Children: ${people.children}` : null,
3773
- people.seniors > 0 ? (_p = (_o = (_n = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _n.seniors) == null ? void 0 : _o.call(_n, people.seniors)) != null ? _p : `Seniors: ${people.seniors}` : null
3778
+ people.adults > 0 ? (_l = (_k = (_j = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _j.adults) == null ? void 0 : _k.call(_j, people.adults)) != null ? _l : `Adults: ${people.adults}` : null,
3779
+ people.children > 0 ? (_o = (_n = (_m = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _m.children) == null ? void 0 : _n.call(_m, people.children)) != null ? _o : `Children: ${people.children}` : null,
3780
+ people.seniors > 0 ? (_r = (_q = (_p = labels == null ? void 0 : labels.peopleBreakdown) == null ? void 0 : _p.seniors) == null ? void 0 : _q.call(_p, people.seniors)) != null ? _r : `Seniors: ${people.seniors}` : null
3774
3781
  ].filter(Boolean).join(" \xB7 ") })
3775
3782
  ] })
3776
3783
  ] }),
3777
3784
  /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-4", children: [
3778
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: (_r = (_q = labels == null ? void 0 : labels.adventuresSection) == null ? void 0 : _q.call(labels, adventures.length)) != null ? _r : `Adventures (${adventures.length})` }),
3785
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: (_t = (_s = labels == null ? void 0 : labels.adventuresSection) == null ? void 0 : _s.call(labels, adventures.length)) != null ? _t : `Adventures (${adventures.length})` }),
3779
3786
  adventures.map((adventure) => /* @__PURE__ */ jsxRuntime.jsx(
3780
3787
  AdventureSection,
3781
3788
  {
@@ -3820,23 +3827,23 @@ function BookingDetails({
3820
3827
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: contactSectionLabel != null ? contactSectionLabel : "Responsible Person" }),
3821
3828
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-x-6 gap-y-3", children: [
3822
3829
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3823
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_t = (_s = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _s.name) != null ? _t : "Name" }),
3830
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_v = (_u = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _u.name) != null ? _v : "Name" }),
3824
3831
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground font-sans", children: contact.name })
3825
3832
  ] }),
3826
3833
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3827
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_v = (_u = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _u.email) != null ? _v : "Email" }),
3828
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans truncate", children: (_w = contact.email) != null ? _w : "\u2014" })
3834
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_x = (_w = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _w.email) != null ? _x : "Email" }),
3835
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans truncate", children: (_y = contact.email) != null ? _y : "\u2014" })
3829
3836
  ] }),
3830
3837
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3831
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_y = (_x = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _x.phone) != null ? _y : "Phone" }),
3832
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans", children: (_z = contact.phone) != null ? _z : "\u2014" })
3838
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_A = (_z = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _z.phone) != null ? _A : "Phone" }),
3839
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans", children: (_B = contact.phone) != null ? _B : "\u2014" })
3833
3840
  ] }),
3834
3841
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3835
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_B = (_A = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _A.country) != null ? _B : "Country" }),
3836
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans", children: (_C = contact.country) != null ? _C : "\u2014" })
3842
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_D = (_C = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _C.country) != null ? _D : "Country" }),
3843
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans", children: (_E = contact.country) != null ? _E : "\u2014" })
3837
3844
  ] }),
3838
3845
  contact.passport && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3839
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_E = (_D = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _D.document) != null ? _E : "Passport / ID" }),
3846
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground/60 font-heading uppercase tracking-widest mb-0.5", children: (_G = (_F = labels == null ? void 0 : labels.contactDetailsFields) == null ? void 0 : _F.document) != null ? _G : "Passport / ID" }),
3840
3847
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground font-sans", children: contact.passport })
3841
3848
  ] }),
3842
3849
  (() => {
@@ -3897,7 +3904,7 @@ function BookingDetails({
3897
3904
  className: "flex items-center gap-1.5 text-xs font-ui text-muted-foreground hover:text-destructive transition-colors underline underline-offset-2",
3898
3905
  children: [
3899
3906
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "w-3 h-3" }),
3900
- (_F = labels == null ? void 0 : labels.cancelRequestLabel) != null ? _F : "Request cancellation"
3907
+ (_H = labels == null ? void 0 : labels.cancelRequestLabel) != null ? _H : "Request cancellation"
3901
3908
  ]
3902
3909
  }
3903
3910
  )
@@ -3947,7 +3954,7 @@ function BookingDetails({
3947
3954
  ResendInviteConfirmDialog,
3948
3955
  {
3949
3956
  open: resendInviteDialogState.open,
3950
- travellerName: resendInviteDialogState.traveller ? `${(_G = resendInviteDialogState.traveller.firstName) != null ? _G : ""} ${(_H = resendInviteDialogState.traveller.lastName) != null ? _H : ""}`.trim() : "",
3957
+ travellerName: resendInviteDialogState.traveller ? `${(_I = resendInviteDialogState.traveller.firstName) != null ? _I : ""} ${(_J = resendInviteDialogState.traveller.lastName) != null ? _J : ""}`.trim() : "",
3951
3958
  onClose: closeResendInviteDialog,
3952
3959
  onConfirm: () => {
3953
3960
  const traveller = resendInviteDialogState.traveller;
@@ -14291,10 +14298,450 @@ function LeadCapturePopup({
14291
14298
  }
14292
14299
  );
14293
14300
  }
14301
+ function ExoOrb({
14302
+ size = 80,
14303
+ logoSrc = "/white_transparent_exo.png",
14304
+ pulse = true,
14305
+ trackCursor = true,
14306
+ className
14307
+ }) {
14308
+ const uid = React28.useId().replace(/:/g, "");
14309
+ const id = (name) => `exo-orb-${uid}-${name}`;
14310
+ const rootRef = React28.useRef(null);
14311
+ const pupilRef = React28.useRef(null);
14312
+ React28.useEffect(() => {
14313
+ if (!trackCursor) return;
14314
+ if (typeof window === "undefined") return;
14315
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
14316
+ const root = rootRef.current;
14317
+ const pupil = pupilRef.current;
14318
+ if (!root || !pupil) return;
14319
+ const MAX_OFFSET = 3.5;
14320
+ const REACH_PX = 260;
14321
+ const EASE = 0.18;
14322
+ let targetX = 0, targetY = 0, curX = 0, curY = 0;
14323
+ let raf = 0;
14324
+ const onMove = (e) => {
14325
+ const r = root.getBoundingClientRect();
14326
+ const cx = r.left + r.width / 2;
14327
+ const cy = r.top + r.height / 2;
14328
+ const dx = e.clientX - cx;
14329
+ const dy = e.clientY - cy;
14330
+ const dist = Math.hypot(dx, dy) || 1;
14331
+ const factor = Math.min(dist, REACH_PX) / REACH_PX;
14332
+ targetX = dx / dist * MAX_OFFSET * factor;
14333
+ targetY = dy / dist * MAX_OFFSET * factor;
14334
+ };
14335
+ const onLeave = () => {
14336
+ targetX = 0;
14337
+ targetY = 0;
14338
+ };
14339
+ const tick = () => {
14340
+ curX += (targetX - curX) * EASE;
14341
+ curY += (targetY - curY) * EASE;
14342
+ pupil.setAttribute(
14343
+ "transform",
14344
+ `translate(${curX.toFixed(2)} ${curY.toFixed(2)})`
14345
+ );
14346
+ raf = requestAnimationFrame(tick);
14347
+ };
14348
+ window.addEventListener("pointermove", onMove, { passive: true });
14349
+ window.addEventListener("pointerleave", onLeave);
14350
+ window.addEventListener("blur", onLeave);
14351
+ raf = requestAnimationFrame(tick);
14352
+ return () => {
14353
+ cancelAnimationFrame(raf);
14354
+ window.removeEventListener("pointermove", onMove);
14355
+ window.removeEventListener("pointerleave", onLeave);
14356
+ window.removeEventListener("blur", onLeave);
14357
+ };
14358
+ }, [trackCursor]);
14359
+ return /* @__PURE__ */ jsxRuntime.jsxs(
14360
+ "span",
14361
+ {
14362
+ ref: rootRef,
14363
+ "aria-hidden": "true",
14364
+ className: cn("inline-block leading-none", className),
14365
+ style: { width: size, height: size },
14366
+ children: [
14367
+ /* @__PURE__ */ jsxRuntime.jsxs(
14368
+ "svg",
14369
+ {
14370
+ width: size,
14371
+ height: size,
14372
+ viewBox: "0 0 100 100",
14373
+ fill: "none",
14374
+ xmlns: "http://www.w3.org/2000/svg",
14375
+ className: cn(
14376
+ "block overflow-visible",
14377
+ pulse && "motion-safe:animate-[exo-orb-pulse_3.6s_ease-in-out_infinite]"
14378
+ ),
14379
+ children: [
14380
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
14381
+ /* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: id("body"), cx: "35%", cy: "30%", r: "75%", children: [
14382
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#a8efe2" }),
14383
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "35%", stopColor: "#5bd3bf" }),
14384
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "70%", stopColor: "#47bca9" }),
14385
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#155b52" })
14386
+ ] }),
14387
+ /* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: id("highlight"), cx: "30%", cy: "22%", r: "35%", children: [
14388
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "0.85" }),
14389
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "60%", stopColor: "#ffffff", stopOpacity: "0.10" }),
14390
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#ffffff", stopOpacity: "0" })
14391
+ ] }),
14392
+ /* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: id("rim"), cx: "60%", cy: "85%", r: "65%", children: [
14393
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "60%", stopColor: "#000000", stopOpacity: "0" }),
14394
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: "0.35" })
14395
+ ] }),
14396
+ /* @__PURE__ */ jsxRuntime.jsxs(
14397
+ "filter",
14398
+ {
14399
+ id: id("glow"),
14400
+ x: "-60%",
14401
+ y: "-60%",
14402
+ width: "220%",
14403
+ height: "220%",
14404
+ children: [
14405
+ /* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "6", result: "blur" }),
14406
+ /* @__PURE__ */ jsxRuntime.jsx(
14407
+ "feColorMatrix",
14408
+ {
14409
+ in: "blur",
14410
+ type: "matrix",
14411
+ values: "0 0 0 0 0.28\n 0 0 0 0 0.74\n 0 0 0 0 0.66\n 0 0 0 1 0",
14412
+ result: "tinted"
14413
+ }
14414
+ ),
14415
+ /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: "tinted", result: "strong", children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "linear", slope: 1.6 }) }),
14416
+ /* @__PURE__ */ jsxRuntime.jsxs("feMerge", { children: [
14417
+ /* @__PURE__ */ jsxRuntime.jsx("feMergeNode", { in: "strong" }),
14418
+ /* @__PURE__ */ jsxRuntime.jsx("feMergeNode", { in: "SourceGraphic" })
14419
+ ] })
14420
+ ]
14421
+ }
14422
+ ),
14423
+ /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: id("clip"), children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "22" }) })
14424
+ ] }),
14425
+ /* @__PURE__ */ jsxRuntime.jsx(
14426
+ "circle",
14427
+ {
14428
+ cx: "50",
14429
+ cy: "50",
14430
+ r: "30",
14431
+ fill: "#47bca9",
14432
+ opacity: "0.18",
14433
+ filter: `url(#${id("glow")})`
14434
+ }
14435
+ ),
14436
+ /* @__PURE__ */ jsxRuntime.jsxs("g", { filter: `url(#${id("glow")})`, children: [
14437
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "22", fill: `url(#${id("body")})` }),
14438
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "22", fill: `url(#${id("highlight")})` }),
14439
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "22", fill: `url(#${id("rim")})` })
14440
+ ] }),
14441
+ /* @__PURE__ */ jsxRuntime.jsx(
14442
+ "path",
14443
+ {
14444
+ d: "M 34 38 Q 50 28 66 38",
14445
+ stroke: "#ffffff",
14446
+ strokeOpacity: "0.45",
14447
+ strokeWidth: "1.4",
14448
+ strokeLinecap: "round",
14449
+ fill: "none"
14450
+ }
14451
+ ),
14452
+ /* @__PURE__ */ jsxRuntime.jsx("g", { clipPath: `url(#${id("clip")})`, children: /* @__PURE__ */ jsxRuntime.jsx("g", { ref: pupilRef, children: /* @__PURE__ */ jsxRuntime.jsx(
14453
+ "image",
14454
+ {
14455
+ href: logoSrc,
14456
+ x: "33.8",
14457
+ y: "33.8",
14458
+ width: "32.4",
14459
+ height: "32.4",
14460
+ preserveAspectRatio: "xMidYMid meet"
14461
+ }
14462
+ ) }) })
14463
+ ]
14464
+ }
14465
+ ),
14466
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes exo-orb-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.04)}}` })
14467
+ ]
14468
+ }
14469
+ );
14470
+ }
14471
+ function Textarea(_a) {
14472
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
14473
+ return /* @__PURE__ */ jsxRuntime.jsx(
14474
+ "textarea",
14475
+ __spreadValues({
14476
+ "data-slot": "textarea",
14477
+ className: cn(
14478
+ "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
14479
+ className
14480
+ )
14481
+ }, props)
14482
+ );
14483
+ }
14484
+ var DEFAULT_BASE_URL = "https://staging.ask.planetaexo.com";
14485
+ var DEFAULT_SUGGESTIONS = [
14486
+ { label: "Where do I start?", ask: "I am new to PlanetaEXO, what should I check out first?" },
14487
+ { label: "Destinations", ask: "What destinations does PlanetaEXO offer?" },
14488
+ { label: "5 days in the Amazon", ask: "Plan a 5-day trip to the Amazon for two travelers." },
14489
+ { label: "Mount Roraima trek", ask: "What is included in the Mount Roraima trek?" },
14490
+ { label: "Best time for Pantanal", ask: "Best time of year to visit the Pantanal?" },
14491
+ { label: "Fitness level needed", ask: "How fit do I need to be for an EXO trek?" }
14492
+ ];
14493
+ function AskExo({
14494
+ baseUrl = DEFAULT_BASE_URL,
14495
+ variant = "suggestions",
14496
+ eyebrow = "PLANETAEXO",
14497
+ title = "Ask EXO",
14498
+ subtitle = "Our AI travel concierge will answer in seconds.",
14499
+ suggestions = DEFAULT_SUGGESTIONS,
14500
+ inputPlaceholder,
14501
+ submitLabel = "Ask",
14502
+ logoSrc = "/white_transparent_exo.png",
14503
+ className,
14504
+ teaser = "Need help?",
14505
+ teaserDelayMs = 2500,
14506
+ teaserDurationMs = 6e3
14507
+ }) {
14508
+ const [open, setOpen] = React28.useState(false);
14509
+ const [question, setQuestion] = React28.useState("");
14510
+ const [teaserVisible, setTeaserVisible] = React28.useState(false);
14511
+ const teaserEnabled = !!teaser && teaser !== "";
14512
+ const inputRef = React28.useRef(null);
14513
+ const textareaRef = React28.useRef(null);
14514
+ React28.useEffect(() => {
14515
+ if (!open) {
14516
+ setQuestion("");
14517
+ return;
14518
+ }
14519
+ const t = setTimeout(() => {
14520
+ var _a, _b;
14521
+ if (variant === "compose") (_a = textareaRef.current) == null ? void 0 : _a.focus();
14522
+ else (_b = inputRef.current) == null ? void 0 : _b.focus();
14523
+ }, 200);
14524
+ return () => clearTimeout(t);
14525
+ }, [open, variant]);
14526
+ React28.useEffect(() => {
14527
+ if (!open) return;
14528
+ const onKey = (e) => {
14529
+ if (e.key === "Escape") setOpen(false);
14530
+ };
14531
+ document.addEventListener("keydown", onKey);
14532
+ return () => document.removeEventListener("keydown", onKey);
14533
+ }, [open]);
14534
+ React28.useEffect(() => {
14535
+ if (!teaserEnabled || open) return;
14536
+ if (typeof window === "undefined") return;
14537
+ const showTimer = setTimeout(() => setTeaserVisible(true), teaserDelayMs);
14538
+ const hideTimer = setTimeout(
14539
+ () => setTeaserVisible(false),
14540
+ teaserDelayMs + teaserDurationMs
14541
+ );
14542
+ return () => {
14543
+ clearTimeout(showTimer);
14544
+ clearTimeout(hideTimer);
14545
+ };
14546
+ }, [teaserEnabled, teaserDelayMs, teaserDurationMs, open]);
14547
+ React28.useEffect(() => {
14548
+ if (open) setTeaserVisible(false);
14549
+ }, [open]);
14550
+ const askExo = (q) => {
14551
+ const trimmed = q.trim();
14552
+ if (!trimmed) return;
14553
+ const url = baseUrl.replace(/\/+$/, "") + "/?q=" + encodeURIComponent(trimmed) + "&source=" + encodeURIComponent(window.location.href);
14554
+ window.open(url, "_blank", "noopener,noreferrer");
14555
+ setOpen(false);
14556
+ };
14557
+ const placeholder = inputPlaceholder != null ? inputPlaceholder : variant === "compose" ? "Type your question\u2026" : "Ask your own question\u2026";
14558
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14559
+ teaserEnabled && /* @__PURE__ */ jsxRuntime.jsx(
14560
+ "button",
14561
+ {
14562
+ type: "button",
14563
+ "aria-hidden": !teaserVisible,
14564
+ tabIndex: teaserVisible ? 0 : -1,
14565
+ onClick: () => setOpen(true),
14566
+ className: cn(
14567
+ // shape + tone
14568
+ "fixed right-24 bottom-13 z-40 cursor-pointer rounded-full border border-border bg-card px-3.5 py-1.5",
14569
+ "font-sans text-[12.5px] leading-none font-normal whitespace-nowrap text-muted-foreground",
14570
+ "shadow-[0_6px_18px_oklch(0.20_0.002_60_/_0.12)]",
14571
+ // entrance / exit animation
14572
+ "transition-[opacity,transform,color] duration-300 ease-out",
14573
+ teaserVisible ? "translate-x-0 scale-100 opacity-100" : "pointer-events-none translate-x-1 scale-95 opacity-0",
14574
+ // hover
14575
+ "hover:text-foreground",
14576
+ // a11y
14577
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2",
14578
+ "max-[480px]:hidden"
14579
+ ),
14580
+ children: teaser
14581
+ }
14582
+ ),
14583
+ /* @__PURE__ */ jsxRuntime.jsx(
14584
+ "button",
14585
+ {
14586
+ type: "button",
14587
+ "aria-label": open ? "Close Ask EXO" : "Open Ask EXO",
14588
+ "aria-expanded": open,
14589
+ "aria-controls": "ask-exo-panel",
14590
+ onClick: () => setOpen((v) => !v),
14591
+ className: cn(
14592
+ "fixed right-5 bottom-6 z-40 size-20 cursor-pointer border-0 bg-transparent p-0",
14593
+ "transition-transform duration-200 ease-out hover:-translate-y-px hover:scale-[1.04] active:translate-y-0 active:scale-[0.98]",
14594
+ "focus-visible:outline-none [-webkit-tap-highlight-color:transparent]"
14595
+ ),
14596
+ children: /* @__PURE__ */ jsxRuntime.jsx(ExoOrb, { size: 80, logoSrc })
14597
+ }
14598
+ ),
14599
+ /* @__PURE__ */ jsxRuntime.jsxs(
14600
+ "aside",
14601
+ {
14602
+ id: "ask-exo-panel",
14603
+ role: "dialog",
14604
+ "aria-labelledby": "ask-exo-title",
14605
+ "aria-hidden": !open,
14606
+ "data-open": open,
14607
+ className: cn(
14608
+ "fixed right-5 bottom-30 z-50 w-[400px] max-h-[min(640px,80vh)]",
14609
+ variant === "compose" && "max-h-[min(560px,82vh)]",
14610
+ "flex flex-col overflow-hidden rounded-2xl border border-border bg-card text-card-foreground",
14611
+ "shadow-[0_40px_100px_oklch(0.20_0.002_60_/_0.35)]",
14612
+ "transition-[opacity,transform] duration-200 ease-out",
14613
+ "data-[open=false]:pointer-events-none data-[open=false]:translate-y-4 data-[open=false]:scale-[0.985] data-[open=false]:opacity-0",
14614
+ "data-[open=true]:pointer-events-auto data-[open=true]:translate-y-0 data-[open=true]:scale-100 data-[open=true]:opacity-100",
14615
+ "max-[480px]:right-2 max-[480px]:bottom-28 max-[480px]:w-[calc(100%-1rem)] max-[480px]:rounded-xl",
14616
+ className
14617
+ ),
14618
+ children: [
14619
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "relative border-b border-border bg-gradient-to-b from-primary-300/20 to-transparent px-5 py-4", children: [
14620
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 mb-1 font-ui text-[10.5px] font-bold tracking-[1.4px] text-primary-800 uppercase", children: eyebrow }),
14621
+ /* @__PURE__ */ jsxRuntime.jsx(
14622
+ "h2",
14623
+ {
14624
+ id: "ask-exo-title",
14625
+ className: "m-0 font-heading text-[20px] font-bold tracking-[-0.3px] text-foreground",
14626
+ children: title
14627
+ }
14628
+ ),
14629
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1.5 mb-0 font-sans text-[13.5px] leading-relaxed text-muted-foreground", children: subtitle }),
14630
+ /* @__PURE__ */ jsxRuntime.jsx(
14631
+ "button",
14632
+ {
14633
+ type: "button",
14634
+ "aria-label": "Close",
14635
+ onClick: () => setOpen(false),
14636
+ className: cn(
14637
+ "absolute top-3 right-3 inline-flex size-8 cursor-pointer items-center justify-center rounded-full border-0 bg-transparent text-muted-foreground transition-colors",
14638
+ "hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
14639
+ ),
14640
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, { className: "size-4" })
14641
+ }
14642
+ )
14643
+ ] }),
14644
+ variant === "compose" ? (
14645
+ /* — Compose variant: just a big textarea — */
14646
+ /* @__PURE__ */ jsxRuntime.jsxs(
14647
+ "form",
14648
+ {
14649
+ className: "flex flex-1 flex-col gap-2.5 overflow-y-auto p-5",
14650
+ onSubmit: (e) => {
14651
+ e.preventDefault();
14652
+ askExo(question);
14653
+ },
14654
+ children: [
14655
+ /* @__PURE__ */ jsxRuntime.jsx(
14656
+ Textarea,
14657
+ {
14658
+ ref: textareaRef,
14659
+ placeholder,
14660
+ value: question,
14661
+ onChange: (e) => setQuestion(e.target.value),
14662
+ maxLength: 500,
14663
+ className: "min-h-[220px] flex-1 resize-y bg-muted/50 px-4 py-3.5 font-sans text-[15px] leading-relaxed placeholder:italic focus-visible:bg-card"
14664
+ }
14665
+ ),
14666
+ /* @__PURE__ */ jsxRuntime.jsx(
14667
+ Button2,
14668
+ {
14669
+ type: "submit",
14670
+ disabled: !question.trim(),
14671
+ className: "h-11 w-full font-ui text-[13px] font-bold tracking-[0.5px] uppercase",
14672
+ children: submitLabel
14673
+ }
14674
+ ),
14675
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 mb-0 text-center font-ui text-[10.5px] font-bold tracking-[0.5px] text-muted-foreground uppercase", children: "Opens in a new tab" })
14676
+ ]
14677
+ }
14678
+ )
14679
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14680
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col gap-3.5 overflow-y-auto px-5 py-4", children: [
14681
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 mb-0 font-ui text-[10.5px] font-bold tracking-[1.2px] text-muted-foreground uppercase", children: "Suggested questions" }),
14682
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: suggestions.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
14683
+ "button",
14684
+ {
14685
+ type: "button",
14686
+ onClick: () => askExo(s.ask),
14687
+ className: cn(
14688
+ "cursor-pointer rounded-full border border-border bg-muted/60 px-3.5 py-2 text-left font-ui text-[12.5px] font-bold leading-tight text-foreground",
14689
+ "transition-colors hover:border-primary hover:bg-primary-100 hover:text-primary-800",
14690
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
14691
+ ),
14692
+ children: s.label
14693
+ },
14694
+ s.label
14695
+ )) })
14696
+ ] }),
14697
+ /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: "border-t border-border bg-card px-4 py-3.5", children: [
14698
+ /* @__PURE__ */ jsxRuntime.jsxs(
14699
+ "form",
14700
+ {
14701
+ className: "flex items-stretch gap-2",
14702
+ onSubmit: (e) => {
14703
+ e.preventDefault();
14704
+ askExo(question);
14705
+ },
14706
+ children: [
14707
+ /* @__PURE__ */ jsxRuntime.jsx(
14708
+ Input,
14709
+ {
14710
+ ref: inputRef,
14711
+ type: "text",
14712
+ placeholder,
14713
+ value: question,
14714
+ onChange: (e) => setQuestion(e.target.value),
14715
+ maxLength: 500,
14716
+ "aria-label": "Ask EXO",
14717
+ className: "h-10 flex-1 rounded-xl bg-muted/50 px-3.5 py-2.5 font-sans text-[14.5px] focus-visible:bg-card"
14718
+ }
14719
+ ),
14720
+ /* @__PURE__ */ jsxRuntime.jsx(
14721
+ Button2,
14722
+ {
14723
+ type: "submit",
14724
+ disabled: !question.trim(),
14725
+ className: "h-10 min-w-[86px] rounded-xl font-ui text-[12px] font-bold tracking-[0.5px] uppercase",
14726
+ children: submitLabel
14727
+ }
14728
+ )
14729
+ ]
14730
+ }
14731
+ ),
14732
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2.5 mb-0 text-center font-ui text-[10.5px] font-bold tracking-[0.5px] text-muted-foreground uppercase", children: "Opens in a new tab" })
14733
+ ] })
14734
+ ] })
14735
+ ]
14736
+ }
14737
+ )
14738
+ ] });
14739
+ }
14294
14740
 
14295
14741
  exports.ActivityCard = ActivityCard;
14296
14742
  exports.AgentContactCard = AgentContactCard;
14297
14743
  exports.Alert = Alert;
14744
+ exports.AskExo = AskExo;
14298
14745
  exports.BirthDateField = BirthDateField;
14299
14746
  exports.BookingAdventureCard = BookingAdventureCard;
14300
14747
  exports.BookingCancellationEmail = BookingCancellationEmail;
@@ -14320,6 +14767,7 @@ exports.DialogDescription = DialogDescription;
14320
14767
  exports.DialogFooter = DialogFooter;
14321
14768
  exports.DialogHeader = DialogHeader;
14322
14769
  exports.DialogTitle = DialogTitle;
14770
+ exports.ExoOrb = ExoOrb;
14323
14771
  exports.FilterPanel = FilterPanel;
14324
14772
  exports.FloatingInput = FloatingInput;
14325
14773
  exports.FloatingSelect = FloatingSelect;