@planetaexo/design-system 0.3.1 → 0.3.3

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
@@ -1475,6 +1475,87 @@ function BirthDateField({
1475
1475
  ) })
1476
1476
  ] });
1477
1477
  }
1478
+ function BookingShell({
1479
+ steps,
1480
+ currentStep,
1481
+ title = "Booking details",
1482
+ children,
1483
+ onNext,
1484
+ onBack,
1485
+ onCancel,
1486
+ nextLabel = "Next",
1487
+ backLabel = "Back",
1488
+ cancelLabel = "Cancel",
1489
+ nextDisabled,
1490
+ nextBlockedMessage,
1491
+ error,
1492
+ successMessage
1493
+ }) {
1494
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
1495
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: title }),
1497
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxRuntime.jsxs(React18__namespace.Fragment, { children: [
1498
+ /* @__PURE__ */ jsxRuntime.jsx(
1499
+ "span",
1500
+ {
1501
+ className: cn(
1502
+ "text-xs font-sans",
1503
+ i === currentStep ? "text-primary font-semibold" : i < currentStep ? "text-foreground" : "text-muted-foreground"
1504
+ ),
1505
+ children: label
1506
+ }
1507
+ ),
1508
+ i < steps.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "w-3 h-3 text-muted-foreground shrink-0" })
1509
+ ] }, i)) })
1510
+ ] }),
1511
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 flex flex-col gap-5", children: [
1512
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children }),
1513
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive font-sans", children: error }),
1514
+ successMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-sans rounded-lg px-3 py-2 bg-primary/10 border border-primary/30 text-primary", children: successMessage }),
1515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
1516
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1517
+ currentStep > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
1518
+ "button",
1519
+ {
1520
+ type: "button",
1521
+ onClick: onBack,
1522
+ className: "flex items-center gap-1.5 rounded-full border border-border px-5 py-2.5 text-sm text-foreground font-sans hover:bg-muted/50 transition-colors",
1523
+ children: [
1524
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftIcon, { className: "w-3.5 h-3.5" }),
1525
+ backLabel
1526
+ ]
1527
+ }
1528
+ ),
1529
+ /* @__PURE__ */ jsxRuntime.jsx(
1530
+ "button",
1531
+ {
1532
+ type: "button",
1533
+ onClick: onNext,
1534
+ disabled: nextDisabled,
1535
+ className: cn(
1536
+ "rounded-full bg-primary px-8 py-2.5 text-sm font-bold",
1537
+ "text-primary-foreground font-heading transition-colors hover:bg-primary/90",
1538
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1539
+ nextDisabled && "opacity-50 pointer-events-none"
1540
+ ),
1541
+ children: nextLabel
1542
+ }
1543
+ )
1544
+ ] }),
1545
+ nextDisabled && nextBlockedMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-amber-400 bg-amber-500/10 border border-amber-500/30 rounded-lg px-3 py-2", children: nextBlockedMessage }),
1546
+ currentStep === 0 && onCancel && /* @__PURE__ */ jsxRuntime.jsx(
1547
+ "button",
1548
+ {
1549
+ type: "button",
1550
+ onClick: onCancel,
1551
+ className: "text-sm text-muted-foreground font-sans hover:text-foreground transition-colors self-start underline underline-offset-2",
1552
+ children: cancelLabel
1553
+ }
1554
+ )
1555
+ ] })
1556
+ ] })
1557
+ ] });
1558
+ }
1478
1559
  var WIZARD_STEPS = [
1479
1560
  { id: "responsible", label: "Responsible party details" },
1480
1561
  { id: "travellers", label: "Travellers" },
@@ -1587,265 +1668,223 @@ function BookingWizard({
1587
1668
  )
1588
1669
  ] });
1589
1670
  }
1590
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
1591
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
1592
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: "Booking details" }),
1593
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: WIZARD_STEPS.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs(React18__namespace.Fragment, { children: [
1594
- /* @__PURE__ */ jsxRuntime.jsx(
1595
- "span",
1596
- {
1597
- className: cn(
1598
- "text-xs font-sans",
1599
- s.id === step ? "text-primary font-semibold" : i < stepIndex ? "text-foreground" : "text-muted-foreground"
1600
- ),
1601
- children: s.label
1602
- }
1603
- ),
1604
- i < WIZARD_STEPS.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "w-3 h-3 text-muted-foreground shrink-0" })
1605
- ] }, s.id)) })
1606
- ] }),
1607
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 flex flex-col gap-5", children: [
1608
- step === "responsible" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
1609
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: "Enter the responsible person's details. This person will receive booking confirmations and is accountable for all travellers." }),
1610
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1611
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "First name", required: true, value: responsible.firstName, onChange: (e) => setR("firstName", e.target.value) }),
1612
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Last name", required: true, value: responsible.lastName, onChange: (e) => setR("lastName", e.target.value) })
1613
- ] }),
1614
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1615
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Email", type: "email", required: true, value: responsible.email, onChange: (e) => setR("email", e.target.value) }),
1616
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full min-w-0", children: [
1617
- /* @__PURE__ */ jsxRuntime.jsx(PhoneCountrySelect, { value: responsible.phoneCountry, onChange: (c) => setR("phoneCountry", c), className: "shrink-0" }),
1618
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1", children: [
1619
- /* @__PURE__ */ jsxRuntime.jsx(
1620
- "input",
1621
- {
1622
- id: "wiz-phone",
1623
- type: "tel",
1624
- placeholder: " ",
1625
- value: responsible.phone,
1626
- onChange: (e) => setR("phone", e.target.value),
1627
- className: "peer block h-14 w-full rounded-r-lg border border-border bg-background px-3 pt-5 pb-2 text-base text-foreground font-ui transition-colors placeholder-transparent focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary"
1628
- }
1629
- ),
1630
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "wiz-phone", className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-base text-muted-foreground font-ui transition-all duration-150 peer-focus:top-3 peer-focus:translate-y-0 peer-focus:text-xs peer-focus:text-primary peer-not-placeholder-shown:top-3 peer-not-placeholder-shown:translate-y-0 peer-not-placeholder-shown:text-xs", children: "Phone" })
1671
+ return /* @__PURE__ */ jsxRuntime.jsx(
1672
+ BookingShell,
1673
+ {
1674
+ steps: WIZARD_STEPS.map((s) => s.label),
1675
+ currentStep: stepIndex,
1676
+ title: "Booking details",
1677
+ onNext: goNext,
1678
+ onBack: goPrev,
1679
+ onCancel,
1680
+ nextLabel: step === "payment" ? "Confirm booking" : "Next",
1681
+ backLabel: "Back",
1682
+ cancelLabel: "Cancel",
1683
+ error,
1684
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1685
+ step === "responsible" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
1686
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: "Enter the responsible person's details. This person will receive booking confirmations and is accountable for all travellers." }),
1687
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1688
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "First name", required: true, value: responsible.firstName, onChange: (e) => setR("firstName", e.target.value) }),
1689
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Last name", required: true, value: responsible.lastName, onChange: (e) => setR("lastName", e.target.value) })
1690
+ ] }),
1691
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1692
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Email", type: "email", required: true, value: responsible.email, onChange: (e) => setR("email", e.target.value) }),
1693
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full min-w-0", children: [
1694
+ /* @__PURE__ */ jsxRuntime.jsx(PhoneCountrySelect, { value: responsible.phoneCountry, onChange: (c) => setR("phoneCountry", c), className: "shrink-0" }),
1695
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1", children: [
1696
+ /* @__PURE__ */ jsxRuntime.jsx(
1697
+ "input",
1698
+ {
1699
+ id: "wiz-phone",
1700
+ type: "tel",
1701
+ placeholder: " ",
1702
+ value: responsible.phone,
1703
+ onChange: (e) => setR("phone", e.target.value),
1704
+ className: "peer block h-14 w-full rounded-r-lg border border-border bg-background px-3 pt-5 pb-2 text-base text-foreground font-ui transition-colors placeholder-transparent focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary"
1705
+ }
1706
+ ),
1707
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "wiz-phone", className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-base text-muted-foreground font-ui transition-all duration-150 peer-focus:top-3 peer-focus:translate-y-0 peer-focus:text-xs peer-focus:text-primary peer-not-placeholder-shown:top-3 peer-not-placeholder-shown:translate-y-0 peer-not-placeholder-shown:text-xs", children: "Phone" })
1708
+ ] })
1631
1709
  ] })
1710
+ ] }),
1711
+ /* @__PURE__ */ jsxRuntime.jsx(CountrySearchField, { required: true, value: responsible.country, onChange: (code) => setR("country", code) }),
1712
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Passport / CPF", required: true, value: responsible.passport, onChange: (e) => setR("passport", e.target.value) }),
1713
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1714
+ /* @__PURE__ */ jsxRuntime.jsx(
1715
+ "textarea",
1716
+ {
1717
+ id: "wiz-notes",
1718
+ placeholder: " ",
1719
+ rows: 3,
1720
+ value: responsible.notes,
1721
+ onChange: (e) => setR("notes", e.target.value),
1722
+ className: "peer block w-full resize-none rounded-lg border border-border bg-background px-3 pt-6 pb-3 text-base text-foreground font-ui transition-colors placeholder-transparent focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary"
1723
+ }
1724
+ ),
1725
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "wiz-notes", className: "pointer-events-none absolute left-3 top-4 text-base text-muted-foreground font-ui transition-all duration-150 peer-focus:top-2 peer-focus:text-xs peer-focus:text-primary peer-not-placeholder-shown:top-2 peer-not-placeholder-shown:text-xs", children: "Notes (optional)" })
1632
1726
  ] })
1633
1727
  ] }),
1634
- /* @__PURE__ */ jsxRuntime.jsx(CountrySearchField, { required: true, value: responsible.country, onChange: (code) => setR("country", code) }),
1635
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Passport / CPF", required: true, value: responsible.passport, onChange: (e) => setR("passport", e.target.value) }),
1636
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1637
- /* @__PURE__ */ jsxRuntime.jsx(
1638
- "textarea",
1639
- {
1640
- id: "wiz-notes",
1641
- placeholder: " ",
1642
- rows: 3,
1643
- value: responsible.notes,
1644
- onChange: (e) => setR("notes", e.target.value),
1645
- className: "peer block w-full resize-none rounded-lg border border-border bg-background px-3 pt-6 pb-3 text-base text-foreground font-ui transition-colors placeholder-transparent focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary"
1646
- }
1647
- ),
1648
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "wiz-notes", className: "pointer-events-none absolute left-3 top-4 text-base text-muted-foreground font-ui transition-all duration-150 peer-focus:top-2 peer-focus:text-xs peer-focus:text-primary peer-not-placeholder-shown:top-2 peer-not-placeholder-shown:text-xs", children: "Notes (optional)" })
1649
- ] })
1650
- ] }),
1651
- step === "travellers" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1652
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1653
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-5 h-5 text-primary shrink-0" }),
1654
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "Traveller details" })
1655
- ] }),
1656
- travellers.map((t, i) => {
1657
- const isChild = i >= totalAdults;
1658
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1659
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1660
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-bold text-foreground font-heading", children: [
1661
- "Traveller ",
1662
- i + 1
1663
- ] }),
1664
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1665
- "text-xs font-semibold font-heading rounded-full px-2.5 py-0.5",
1666
- isChild ? "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400" : "bg-primary/10 text-primary"
1667
- ), children: isChild ? "Crian\xE7a" : "Adulto" })
1668
- ] }),
1669
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
1670
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "First name", required: true, value: t.firstName, onChange: (e) => setT(i, "firstName", e.target.value) }),
1671
- /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Last name", required: true, value: t.lastName, onChange: (e) => setT(i, "lastName", e.target.value) })
1672
- ] }),
1673
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
1674
- /* @__PURE__ */ jsxRuntime.jsx(
1675
- BirthDateField,
1676
- {
1677
- label: "Date of birth",
1678
- required: isChild,
1679
- value: t.dateOfBirth,
1680
- onChange: (d) => setTDob(i, d)
1681
- }
1682
- ),
1683
- /* @__PURE__ */ jsxRuntime.jsx(
1684
- FloatingInput,
1685
- {
1686
- label: "Email",
1687
- type: "email",
1688
- value: t.email,
1689
- onChange: (e) => setT(i, "email", e.target.value)
1690
- }
1691
- )
1692
- ] })
1693
- ] }, i);
1694
- })
1695
- ] }),
1696
- step === "payment" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1697
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: "When you confirm, we will open secure online payment (Stripe). Choose deposit vs full amount below when applicable." }),
1698
- depositInfo && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
1699
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-bold text-foreground font-heading", children: "What do you want to pay now?" }),
1700
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-2", children: ["deposit", "full"].map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
1701
- "button",
1702
- {
1703
- type: "button",
1704
- onClick: () => setPayAmount(opt),
1705
- className: cn(
1706
- "rounded-lg border-2 px-4 py-3 text-sm text-left font-sans transition-colors",
1707
- payAmount === opt ? "border-primary bg-primary/5 text-foreground font-semibold" : "border-border bg-background text-muted-foreground hover:border-primary/40"
1708
- ),
1709
- children: opt === "deposit" ? depositLabel : fullLabel
1710
- },
1711
- opt
1712
- )) })
1713
- ] }),
1714
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1715
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest flex items-center gap-1.5", children: [
1716
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "$" }),
1717
- " Payment method"
1728
+ step === "travellers" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1729
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1730
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-5 h-5 text-primary shrink-0" }),
1731
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "Traveller details" })
1718
1732
  ] }),
1719
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: [
1720
- { id: "stripe", label: "Credit / Debit card", sub: "Secure payment via Stripe" },
1721
- { id: "pix", label: "PIX", sub: "Instant transfer \u2014 Brazil only" },
1722
- { id: "bank", label: "Bank transfer", sub: "Wire / TED / DOC" }
1723
- ].map((m) => /* @__PURE__ */ jsxRuntime.jsxs(
1724
- "button",
1725
- {
1726
- type: "button",
1727
- onClick: () => setPayMethod(m.id),
1728
- className: cn(
1729
- "flex items-start gap-3 rounded-lg border-2 px-4 py-3 text-left transition-colors",
1730
- payMethod === m.id ? "border-primary bg-primary/5" : "border-border bg-background hover:border-primary/40"
1731
- ),
1732
- children: [
1733
+ travellers.map((t, i) => {
1734
+ const isChild = i >= totalAdults;
1735
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1736
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1737
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-bold text-foreground font-heading", children: [
1738
+ "Traveller ",
1739
+ i + 1
1740
+ ] }),
1733
1741
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1734
- "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
1735
- payMethod === m.id ? "border-primary" : "border-border"
1736
- ), children: payMethod === m.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-primary" }) }),
1737
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col gap-0.5", children: [
1738
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1739
- "text-sm font-semibold font-sans",
1740
- payMethod === m.id ? "text-primary" : "text-foreground"
1741
- ), children: m.label }),
1742
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground font-sans", children: m.sub })
1743
- ] })
1744
- ]
1745
- },
1746
- m.id
1747
- )) })
1742
+ "text-xs font-semibold font-heading rounded-full px-2.5 py-0.5",
1743
+ isChild ? "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400" : "bg-primary/10 text-primary"
1744
+ ), children: isChild ? "Crian\xE7a" : "Adulto" })
1745
+ ] }),
1746
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
1747
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "First name", required: true, value: t.firstName, onChange: (e) => setT(i, "firstName", e.target.value) }),
1748
+ /* @__PURE__ */ jsxRuntime.jsx(FloatingInput, { label: "Last name", required: true, value: t.lastName, onChange: (e) => setT(i, "lastName", e.target.value) })
1749
+ ] }),
1750
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
1751
+ /* @__PURE__ */ jsxRuntime.jsx(
1752
+ BirthDateField,
1753
+ {
1754
+ label: "Date of birth",
1755
+ required: isChild,
1756
+ value: t.dateOfBirth,
1757
+ onChange: (d) => setTDob(i, d)
1758
+ }
1759
+ ),
1760
+ /* @__PURE__ */ jsxRuntime.jsx(
1761
+ FloatingInput,
1762
+ {
1763
+ label: "Email",
1764
+ type: "email",
1765
+ value: t.email,
1766
+ onChange: (e) => setT(i, "email", e.target.value)
1767
+ }
1768
+ )
1769
+ ] })
1770
+ ] }, i);
1771
+ })
1748
1772
  ] }),
1749
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1750
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: "Terms and conditions" }),
1751
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-start gap-2.5 cursor-pointer", children: [
1752
- /* @__PURE__ */ jsxRuntime.jsx(
1753
- "input",
1773
+ step === "payment" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1774
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground font-sans", children: "When you confirm, we will open secure online payment (Stripe). Choose deposit vs full amount below when applicable." }),
1775
+ depositInfo && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
1776
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-bold text-foreground font-heading", children: "What do you want to pay now?" }),
1777
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-2", children: ["deposit", "full"].map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
1778
+ "button",
1754
1779
  {
1755
- type: "checkbox",
1756
- checked: termsAccepted,
1757
- onChange: (e) => setTermsAccepted(e.target.checked),
1758
- className: "h-4 w-4 shrink-0 mt-0.5 rounded border-border accent-primary cursor-pointer"
1759
- }
1760
- ),
1761
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-sans text-foreground/80 leading-snug", children: [
1762
- "I have read and accept the",
1763
- " ",
1780
+ type: "button",
1781
+ onClick: () => setPayAmount(opt),
1782
+ className: cn(
1783
+ "rounded-lg border-2 px-4 py-3 text-sm text-left font-sans transition-colors",
1784
+ payAmount === opt ? "border-primary bg-primary/5 text-foreground font-semibold" : "border-border bg-background text-muted-foreground hover:border-primary/40"
1785
+ ),
1786
+ children: opt === "deposit" ? depositLabel : fullLabel
1787
+ },
1788
+ opt
1789
+ )) })
1790
+ ] }),
1791
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1792
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest flex items-center gap-1.5", children: [
1793
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "$" }),
1794
+ " Payment method"
1795
+ ] }),
1796
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: [
1797
+ { id: "stripe", label: "Credit / Debit card", sub: "Secure payment via Stripe" },
1798
+ { id: "pix", label: "PIX", sub: "Instant transfer \u2014 Brazil only" },
1799
+ { id: "bank", label: "Bank transfer", sub: "Wire / TED / DOC" }
1800
+ ].map((m) => /* @__PURE__ */ jsxRuntime.jsxs(
1801
+ "button",
1802
+ {
1803
+ type: "button",
1804
+ onClick: () => setPayMethod(m.id),
1805
+ className: cn(
1806
+ "flex items-start gap-3 rounded-lg border-2 px-4 py-3 text-left transition-colors",
1807
+ payMethod === m.id ? "border-primary bg-primary/5" : "border-border bg-background hover:border-primary/40"
1808
+ ),
1809
+ children: [
1810
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1811
+ "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
1812
+ payMethod === m.id ? "border-primary" : "border-border"
1813
+ ), children: payMethod === m.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-primary" }) }),
1814
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col gap-0.5", children: [
1815
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
1816
+ "text-sm font-semibold font-sans",
1817
+ payMethod === m.id ? "text-primary" : "text-foreground"
1818
+ ), children: m.label }),
1819
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground font-sans", children: m.sub })
1820
+ ] })
1821
+ ]
1822
+ },
1823
+ m.id
1824
+ )) })
1825
+ ] }),
1826
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1827
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: "Terms and conditions" }),
1828
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-start gap-2.5 cursor-pointer", children: [
1764
1829
  /* @__PURE__ */ jsxRuntime.jsx(
1765
- "button",
1830
+ "input",
1766
1831
  {
1767
- type: "button",
1768
- onClick: () => setTermsModalOpen(true),
1769
- className: "underline underline-offset-2 text-primary hover:text-primary/80 transition-colors font-semibold",
1770
- children: "terms and conditions"
1832
+ type: "checkbox",
1833
+ checked: termsAccepted,
1834
+ onChange: (e) => setTermsAccepted(e.target.checked),
1835
+ className: "h-4 w-4 shrink-0 mt-0.5 rounded border-border accent-primary cursor-pointer"
1771
1836
  }
1772
1837
  ),
1773
- " ",
1774
- "of the reservation."
1775
- ] })
1776
- ] })
1777
- ] }),
1778
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: termsModalOpen, onOpenChange: setTermsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "!max-w-[80vw] w-[80vw] max-h-[85vh] overflow-y-auto", children: [
1779
- /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "font-heading text-xl", children: "Terms and Conditions" }) }),
1780
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 text-sm font-sans text-foreground/80 leading-relaxed", children: [
1781
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: 'These terms and conditions ("Terms") govern the booking of travel experiences offered through Planeta EXO ("Company"). By confirming a booking, you agree to these Terms in full.' }),
1782
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "1. Bookings and payments" }),
1783
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "A booking is confirmed upon receipt of the required deposit or full payment. The deposit amount is specified in your offer. The remaining balance must be paid by the balance due date stated in your offer." }),
1784
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "2. Cancellation policy" }),
1785
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Cancellations made more than 60 days before departure are eligible for a full refund of the deposit. Cancellations between 30 and 60 days forfeit 50% of the deposit. Cancellations within 30 days of departure are non-refundable." }),
1786
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "3. Changes and modifications" }),
1787
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "The Company reserves the right to modify itineraries due to weather, safety, or operational reasons. Equivalent alternatives will be offered wherever possible." }),
1788
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "4. Travel insurance" }),
1789
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Comprehensive travel insurance is strongly recommended. The Company is not liable for costs arising from trip interruption, medical emergencies, or personal loss." }),
1790
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "5. Liability" }),
1791
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Participation in adventure activities carries inherent risk. By booking, you acknowledge and accept these risks. The Company's liability is limited to the total booking amount." }),
1792
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
1793
- DialogClose,
1794
- {
1795
- render: /* @__PURE__ */ jsxRuntime.jsx(
1838
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-sans text-foreground/80 leading-snug", children: [
1839
+ "I have read and accept the",
1840
+ " ",
1841
+ /* @__PURE__ */ jsxRuntime.jsx(
1796
1842
  "button",
1797
1843
  {
1798
1844
  type: "button",
1799
- className: "rounded-full bg-primary px-6 py-2.5 text-sm font-bold text-primary-foreground font-heading hover:bg-primary/90 transition-colors"
1845
+ onClick: () => setTermsModalOpen(true),
1846
+ className: "underline underline-offset-2 text-primary hover:text-primary/80 transition-colors font-semibold",
1847
+ children: "terms and conditions"
1800
1848
  }
1801
1849
  ),
1802
- children: "Close"
1803
- }
1804
- ) })
1805
- ] })
1806
- ] }) })
1807
- ] }),
1808
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive font-sans", children: error }),
1809
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
1810
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1811
- stepIndex > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
1812
- "button",
1813
- {
1814
- type: "button",
1815
- onClick: goPrev,
1816
- className: "flex items-center gap-1.5 rounded-full border border-border px-5 py-2.5 text-sm text-foreground font-sans hover:bg-muted/50 transition-colors",
1817
- children: [
1818
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftIcon, { className: "w-3.5 h-3.5" }),
1819
- "Back"
1820
- ]
1821
- }
1822
- ),
1823
- /* @__PURE__ */ jsxRuntime.jsx(
1824
- "button",
1825
- {
1826
- type: "button",
1827
- onClick: goNext,
1828
- className: cn(
1829
- "rounded-full bg-primary px-8 py-2.5 text-sm font-bold",
1830
- "text-primary-foreground font-heading transition-colors hover:bg-primary/90",
1831
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1832
- ),
1833
- children: step === "payment" ? "Confirm booking" : "Next"
1834
- }
1835
- )
1836
- ] }),
1837
- stepIndex === 0 && /* @__PURE__ */ jsxRuntime.jsx(
1838
- "button",
1839
- {
1840
- type: "button",
1841
- onClick: onCancel,
1842
- className: "text-sm text-muted-foreground font-sans hover:text-foreground transition-colors self-start underline underline-offset-2",
1843
- children: "Cancel"
1844
- }
1845
- )
1850
+ " ",
1851
+ "of the reservation."
1852
+ ] })
1853
+ ] })
1854
+ ] }),
1855
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: termsModalOpen, onOpenChange: setTermsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "!max-w-[80vw] w-[80vw] max-h-[85vh] overflow-y-auto", children: [
1856
+ /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "font-heading text-xl", children: "Terms and Conditions" }) }),
1857
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 text-sm font-sans text-foreground/80 leading-relaxed", children: [
1858
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: 'These terms and conditions ("Terms") govern the booking of travel experiences offered through Planeta EXO ("Company"). By confirming a booking, you agree to these Terms in full.' }),
1859
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "1. Bookings and payments" }),
1860
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "A booking is confirmed upon receipt of the required deposit or full payment. The deposit amount is specified in your offer. The remaining balance must be paid by the balance due date stated in your offer." }),
1861
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "2. Cancellation policy" }),
1862
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Cancellations made more than 60 days before departure are eligible for a full refund of the deposit. Cancellations between 30 and 60 days forfeit 50% of the deposit. Cancellations within 30 days of departure are non-refundable." }),
1863
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "3. Changes and modifications" }),
1864
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "The Company reserves the right to modify itineraries due to weather, safety, or operational reasons. Equivalent alternatives will be offered wherever possible." }),
1865
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "4. Travel insurance" }),
1866
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Comprehensive travel insurance is strongly recommended. The Company is not liable for costs arising from trip interruption, medical emergencies, or personal loss." }),
1867
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-foreground font-heading text-base", children: "5. Liability" }),
1868
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Participation in adventure activities carries inherent risk. By booking, you acknowledge and accept these risks. The Company's liability is limited to the total booking amount." }),
1869
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
1870
+ DialogClose,
1871
+ {
1872
+ render: /* @__PURE__ */ jsxRuntime.jsx(
1873
+ "button",
1874
+ {
1875
+ type: "button",
1876
+ className: "rounded-full bg-primary px-6 py-2.5 text-sm font-bold text-primary-foreground font-heading hover:bg-primary/90 transition-colors"
1877
+ }
1878
+ ),
1879
+ children: "Close"
1880
+ }
1881
+ ) })
1882
+ ] })
1883
+ ] }) })
1884
+ ] })
1846
1885
  ] })
1847
- ] })
1848
- ] });
1886
+ }
1887
+ );
1849
1888
  }
1850
1889
  function OfferAdventureCard({ adventure }) {
1851
1890
  return /* @__PURE__ */ jsxRuntime.jsx(AdventureCard, { adventure });
@@ -1863,14 +1902,16 @@ function Offer({
1863
1902
  onContinue,
1864
1903
  continueLabel = "Book now",
1865
1904
  externalBookingFlow,
1905
+ checkoutSlot,
1866
1906
  summaryNotesSlot,
1867
1907
  summaryDiscountLine,
1868
1908
  continueDisabled,
1869
1909
  className
1870
1910
  }) {
1871
1911
  const [showBooking, setShowBooking] = React18__namespace.useState(false);
1912
+ const isShowingCheckout = !!checkoutSlot || showBooking;
1872
1913
  const handleBook = () => {
1873
- if (!externalBookingFlow) setShowBooking(true);
1914
+ if (!checkoutSlot && !externalBookingFlow) setShowBooking(true);
1874
1915
  onContinue == null ? void 0 : onContinue();
1875
1916
  };
1876
1917
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full max-w-5xl mx-auto flex flex-col gap-6 pb-20 lg:pb-0", className), children: [
@@ -1886,7 +1927,7 @@ function Offer({
1886
1927
  ] }),
1887
1928
  adventures.map((adventure) => /* @__PURE__ */ jsxRuntime.jsx(AdventureCard, { adventure }, adventure.id))
1888
1929
  ] }),
1889
- !showBooking && /* @__PURE__ */ jsxRuntime.jsx(
1930
+ !isShowingCheckout && /* @__PURE__ */ jsxRuntime.jsx(
1890
1931
  OfferSummarySection,
1891
1932
  {
1892
1933
  adventures,
@@ -1900,7 +1941,7 @@ function Offer({
1900
1941
  continueDisabled
1901
1942
  }
1902
1943
  ),
1903
- showBooking && !externalBookingFlow && /* @__PURE__ */ jsxRuntime.jsx(
1944
+ isShowingCheckout && (checkoutSlot != null ? checkoutSlot : /* @__PURE__ */ jsxRuntime.jsx(
1904
1945
  BookingWizard,
1905
1946
  {
1906
1947
  adventures,
@@ -1908,7 +1949,7 @@ function Offer({
1908
1949
  depositInfo,
1909
1950
  onCancel: () => setShowBooking(false)
1910
1951
  }
1911
- )
1952
+ ))
1912
1953
  ] }),
1913
1954
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lg:sticky lg:top-8", children: /* @__PURE__ */ jsxRuntime.jsx(
1914
1955
  OfferSidebar,
@@ -1921,7 +1962,7 @@ function Offer({
1921
1962
  }
1922
1963
  ) })
1923
1964
  ] }),
1924
- !showBooking && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed bottom-0 inset-x-0 z-40 border-t border-border bg-background/95 backdrop-blur-sm px-4 py-3 lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 max-w-5xl mx-auto", children: [
1965
+ !isShowingCheckout && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed bottom-0 inset-x-0 z-40 border-t border-border bg-background/95 backdrop-blur-sm px-4 py-3 lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 max-w-5xl mx-auto", children: [
1925
1966
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1926
1967
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-widest text-muted-foreground font-heading", children: "Total" }),
1927
1968
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xl font-black text-primary font-heading leading-tight", children: total })
@@ -6690,6 +6731,7 @@ exports.BookingConfirmation = BookingConfirmation;
6690
6731
  exports.BookingConfirmationEmail = BookingConfirmationEmail;
6691
6732
  exports.BookingDetails = BookingDetails;
6692
6733
  exports.BookingForm = BookingForm;
6734
+ exports.BookingShell = BookingShell;
6693
6735
  exports.COUNTRIES = COUNTRIES;
6694
6736
  exports.CounterField = CounterField;
6695
6737
  exports.CountrySearchField = CountrySearchField;