@planetaexo/design-system 0.4.15 → 0.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as React21 from 'react';
1
+ import * as React22 from 'react';
2
2
  import { useState, useRef, useCallback, useEffect } from 'react';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
@@ -80,7 +80,7 @@ var buttonVariants = cva(
80
80
  }
81
81
  }
82
82
  );
83
- var Button = React21.forwardRef(
83
+ var Button = React22.forwardRef(
84
84
  (_a, ref) => {
85
85
  var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
86
86
  return /* @__PURE__ */ jsx(
@@ -275,10 +275,10 @@ function DialogDescription(_a) {
275
275
  }, props)
276
276
  );
277
277
  }
278
- var FloatingInput = React21.forwardRef(
278
+ var FloatingInput = React22.forwardRef(
279
279
  (_a, ref) => {
280
280
  var _b = _a, { label, error, id, className, required } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required"]);
281
- const inputId = id != null ? id : React21.useId();
281
+ const inputId = id != null ? id : React22.useId();
282
282
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
283
283
  /* @__PURE__ */ jsx(
284
284
  "input",
@@ -318,10 +318,10 @@ var FloatingInput = React21.forwardRef(
318
318
  }
319
319
  );
320
320
  FloatingInput.displayName = "FloatingInput";
321
- var FloatingSelect = React21.forwardRef(
321
+ var FloatingSelect = React22.forwardRef(
322
322
  (_a, ref) => {
323
323
  var _b = _a, { label, error, id, className, required, children, value } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required", "children", "value"]);
324
- const inputId = id != null ? id : React21.useId();
324
+ const inputId = id != null ? id : React22.useId();
325
325
  const hasValue = typeof value === "string" ? value !== "" : value !== void 0 && value !== null;
326
326
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
327
327
  /* @__PURE__ */ jsx(
@@ -584,11 +584,11 @@ function PhoneCountrySelect({
584
584
  className
585
585
  }) {
586
586
  var _a;
587
- const [open, setOpen] = React21.useState(false);
588
- const containerRef = React21.useRef(null);
589
- const listRef = React21.useRef(null);
587
+ const [open, setOpen] = React22.useState(false);
588
+ const containerRef = React22.useRef(null);
589
+ const listRef = React22.useRef(null);
590
590
  const selected = (_a = PHONE_COUNTRIES.find((c) => c.code === value)) != null ? _a : PHONE_COUNTRIES[0];
591
- React21.useEffect(() => {
591
+ React22.useEffect(() => {
592
592
  if (!open) return;
593
593
  const handler = (e) => {
594
594
  var _a2;
@@ -599,7 +599,7 @@ function PhoneCountrySelect({
599
599
  document.addEventListener("mousedown", handler);
600
600
  return () => document.removeEventListener("mousedown", handler);
601
601
  }, [open]);
602
- React21.useEffect(() => {
602
+ React22.useEffect(() => {
603
603
  if (!open || !listRef.current) return;
604
604
  const activeEl = listRef.current.querySelector("[data-selected=true]");
605
605
  activeEl == null ? void 0 : activeEl.scrollIntoView({ block: "nearest" });
@@ -863,8 +863,8 @@ function CalendarDayButton(_a) {
863
863
  "locale"
864
864
  ]);
865
865
  const defaultClassNames = getDefaultClassNames();
866
- const ref = React21.useRef(null);
867
- React21.useEffect(() => {
866
+ const ref = React22.useRef(null);
867
+ React22.useEffect(() => {
868
868
  var _a2;
869
869
  if (modifiers.focused) (_a2 = ref.current) == null ? void 0 : _a2.focus();
870
870
  }, [modifiers.focused]);
@@ -894,16 +894,16 @@ function BirthDateField({
894
894
  error,
895
895
  className
896
896
  }) {
897
- const [open, setOpen] = React21.useState(false);
898
- const [text, setText] = React21.useState(
897
+ const [open, setOpen] = React22.useState(false);
898
+ const [text, setText] = React22.useState(
899
899
  value ? format(value, "dd/MM/yyyy") : ""
900
900
  );
901
- const containerRef = React21.useRef(null);
902
- const inputId = React21.useId();
903
- React21.useEffect(() => {
901
+ const containerRef = React22.useRef(null);
902
+ const inputId = React22.useId();
903
+ React22.useEffect(() => {
904
904
  setText(value ? format(value, "dd/MM/yyyy") : "");
905
905
  }, [value]);
906
- React21.useEffect(() => {
906
+ React22.useEffect(() => {
907
907
  if (!open) return;
908
908
  const handler = (e) => {
909
909
  var _a;
@@ -1106,14 +1106,14 @@ function CountrySearchField({
1106
1106
  }) {
1107
1107
  var _a;
1108
1108
  const list = countries != null ? countries : COUNTRIES;
1109
- const [query, setQuery] = React21.useState("");
1110
- const [open, setOpen] = React21.useState(false);
1111
- const containerRef = React21.useRef(null);
1112
- const searchRef = React21.useRef(null);
1109
+ const [query, setQuery] = React22.useState("");
1110
+ const [open, setOpen] = React22.useState(false);
1111
+ const containerRef = React22.useRef(null);
1112
+ const searchRef = React22.useRef(null);
1113
1113
  const selected = list.find((c) => c.code === value);
1114
1114
  const isFloated = open || !!selected;
1115
1115
  const filtered = query.trim() ? list.filter((c) => c.name.toLowerCase().includes(query.toLowerCase())) : list;
1116
- React21.useEffect(() => {
1116
+ React22.useEffect(() => {
1117
1117
  if (!open) return;
1118
1118
  const handler = (e) => {
1119
1119
  var _a2;
@@ -1220,7 +1220,7 @@ function Alert({ variant = "info", children, className }) {
1220
1220
  function AdventureCard({ adventure }) {
1221
1221
  var _a, _b, _c, _d, _e, _f;
1222
1222
  const isControlled = (_b = (_a = adventure.optionals) == null ? void 0 : _a.some((o) => o.onCheckedChange !== void 0)) != null ? _b : false;
1223
- const [checkedInternal, setCheckedInternal] = React21.useState(
1223
+ const [checkedInternal, setCheckedInternal] = React22.useState(
1224
1224
  new Set((_d = (_c = adventure.optionals) == null ? void 0 : _c.filter((o) => o.defaultChecked).map((o) => o.id)) != null ? _d : [])
1225
1225
  );
1226
1226
  const isChecked = (opt) => {
@@ -1557,7 +1557,7 @@ function BookingShell({
1557
1557
  return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
1558
1558
  /* @__PURE__ */ jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
1559
1559
  /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: title }),
1560
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
1560
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React22.Fragment, { children: [
1561
1561
  /* @__PURE__ */ jsx(
1562
1562
  "span",
1563
1563
  {
@@ -1756,7 +1756,7 @@ function TermsSection({
1756
1756
  termsContent
1757
1757
  }) {
1758
1758
  var _a;
1759
- const [modalOpen, setModalOpen] = React21.useState(false);
1759
+ const [modalOpen, setModalOpen] = React22.useState(false);
1760
1760
  const i18n = (_a = TERMS_I18N[locale]) != null ? _a : TERMS_I18N.en;
1761
1761
  return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1762
1762
  /* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: title }),
@@ -1844,9 +1844,9 @@ function BookingWizard({
1844
1844
  depositInfo,
1845
1845
  onCancel
1846
1846
  }) {
1847
- const [step, setStep] = React21.useState("responsible");
1848
- const [error, setError] = React21.useState(null);
1849
- const [responsible, setResponsible] = React21.useState({
1847
+ const [step, setStep] = React22.useState("responsible");
1848
+ const [error, setError] = React22.useState(null);
1849
+ const [responsible, setResponsible] = React22.useState({
1850
1850
  firstName: "",
1851
1851
  lastName: "",
1852
1852
  email: "",
@@ -1865,7 +1865,7 @@ function BookingWizard({
1865
1865
  return s + ((_b = (_a = a.slots) == null ? void 0 : _a.children) != null ? _b : 0);
1866
1866
  }, 0);
1867
1867
  const totalPax = totalAdults + totalChildren;
1868
- const [travellers, setTravellers] = React21.useState(
1868
+ const [travellers, setTravellers] = React22.useState(
1869
1869
  Array.from({ length: Math.max(totalPax, 1) }, () => ({
1870
1870
  firstName: "",
1871
1871
  lastName: "",
@@ -1873,9 +1873,9 @@ function BookingWizard({
1873
1873
  email: ""
1874
1874
  }))
1875
1875
  );
1876
- const [payAmount, setPayAmount] = React21.useState("full");
1877
- const [payMethod, setPayMethod] = React21.useState("stripe");
1878
- const [termsAccepted, setTermsAccepted] = React21.useState(false);
1876
+ const [payAmount, setPayAmount] = React22.useState("full");
1877
+ const [payMethod, setPayMethod] = React22.useState("stripe");
1878
+ const [termsAccepted, setTermsAccepted] = React22.useState(false);
1879
1879
  const setR = (k, v) => setResponsible((p) => __spreadProps(__spreadValues({}, p), { [k]: v }));
1880
1880
  const setT = (i, k, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { [k]: v }) : t));
1881
1881
  const setTDob = (i, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { dateOfBirth: v }) : t));
@@ -2076,7 +2076,7 @@ function Offer({
2076
2076
  continueDisabled,
2077
2077
  className
2078
2078
  }) {
2079
- const [showBooking, setShowBooking] = React21.useState(false);
2079
+ const [showBooking, setShowBooking] = React22.useState(false);
2080
2080
  const isShowingCheckout = !!checkoutSlot || showBooking;
2081
2081
  const handleBook = () => {
2082
2082
  if (!checkoutSlot && !externalBookingFlow) setShowBooking(true);
@@ -2198,9 +2198,9 @@ function AdventureSection({
2198
2198
  onAddSuggestedTraveller
2199
2199
  }) {
2200
2200
  var _a, _b, _c;
2201
- const [detailsOpen, setDetailsOpen] = React21.useState(false);
2202
- const [addModalOpen, setAddModalOpen] = React21.useState(false);
2203
- const [newTraveller, setNewTraveller] = React21.useState({
2201
+ const [detailsOpen, setDetailsOpen] = React22.useState(false);
2202
+ const [addModalOpen, setAddModalOpen] = React22.useState(false);
2203
+ const [newTraveller, setNewTraveller] = React22.useState({
2204
2204
  firstName: "",
2205
2205
  lastName: "",
2206
2206
  passport: "",
@@ -3619,11 +3619,11 @@ function DatePickerField({
3619
3619
  fromDate,
3620
3620
  className
3621
3621
  }) {
3622
- const [open, setOpen] = React21.useState(false);
3623
- const containerRef = React21.useRef(null);
3624
- const [calendarWidth, setCalendarWidth] = React21.useState();
3622
+ const [open, setOpen] = React22.useState(false);
3623
+ const containerRef = React22.useRef(null);
3624
+ const [calendarWidth, setCalendarWidth] = React22.useState();
3625
3625
  const hasValue = !!value;
3626
- React21.useEffect(() => {
3626
+ React22.useEffect(() => {
3627
3627
  if (!containerRef.current) return;
3628
3628
  const observer = new ResizeObserver(([entry]) => {
3629
3629
  setCalendarWidth(entry.contentRect.width);
@@ -3732,7 +3732,7 @@ function BookingForm({
3732
3732
  subtitle = "Free enquiry \u2013 no commitment",
3733
3733
  className
3734
3734
  }) {
3735
- const [values, setValues] = React21.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
3735
+ const [values, setValues] = React22.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
3736
3736
  const set = (key, value) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [key]: value }));
3737
3737
  const handleSubmit = (e) => {
3738
3738
  e.preventDefault();
@@ -4246,11 +4246,11 @@ function FloatingTextarea({
4246
4246
  }
4247
4247
  function SelectField({ field, value, onChange, error }) {
4248
4248
  var _a, _b, _c;
4249
- const [open, setOpen] = React21.useState(false);
4250
- const containerRef = React21.useRef(null);
4249
+ const [open, setOpen] = React22.useState(false);
4250
+ const containerRef = React22.useRef(null);
4251
4251
  const options = (_a = field.options) != null ? _a : [];
4252
4252
  const selectedOpt = (_b = options.find((o) => o.value === value)) != null ? _b : null;
4253
- React21.useEffect(() => {
4253
+ React22.useEffect(() => {
4254
4254
  if (!open) return;
4255
4255
  const handleOutside = (e) => {
4256
4256
  if (containerRef.current && !containerRef.current.contains(e.target)) {
@@ -4617,11 +4617,11 @@ function RegistrationForm({
4617
4617
  className
4618
4618
  }) {
4619
4619
  var _a;
4620
- const L = React21.useMemo(
4620
+ const L = React22.useMemo(
4621
4621
  () => __spreadValues(__spreadValues({}, DEFAULT_LABELS3), labels != null ? labels : {}),
4622
4622
  [labels]
4623
4623
  );
4624
- const sortedFields = React21.useMemo(
4624
+ const sortedFields = React22.useMemo(
4625
4625
  () => [...fields].sort((a, b) => {
4626
4626
  var _a2, _b;
4627
4627
  return ((_a2 = a.order) != null ? _a2 : 0) - ((_b = b.order) != null ? _b : 0);
@@ -4629,7 +4629,7 @@ function RegistrationForm({
4629
4629
  [fields]
4630
4630
  );
4631
4631
  const isControlled = values !== void 0;
4632
- const [internal, setInternal] = React21.useState(
4632
+ const [internal, setInternal] = React22.useState(
4633
4633
  () => initializeValues(
4634
4634
  sortedFields,
4635
4635
  defaultValues != null ? defaultValues : {},
@@ -4637,9 +4637,9 @@ function RegistrationForm({
4637
4637
  includeTerms
4638
4638
  )
4639
4639
  );
4640
- const [submitAttempted, setSubmitAttempted] = React21.useState(false);
4641
- const [validationErrors, setValidationErrors] = React21.useState({});
4642
- React21.useEffect(() => {
4640
+ const [submitAttempted, setSubmitAttempted] = React22.useState(false);
4641
+ const [validationErrors, setValidationErrors] = React22.useState({});
4642
+ React22.useEffect(() => {
4643
4643
  if (isControlled) return;
4644
4644
  setInternal((prev) => {
4645
4645
  const next = initializeValues(
@@ -4696,7 +4696,7 @@ function RegistrationForm({
4696
4696
  const termsError = submitAttempted && termsEnabled && !termsAccepted;
4697
4697
  const firstErrorFieldId = Object.keys(fieldErrors)[0];
4698
4698
  const scrollTargetId = firstErrorFieldId ? `rf-${firstErrorFieldId}` : termsError ? "rf-terms" : null;
4699
- React21.useEffect(() => {
4699
+ React22.useEffect(() => {
4700
4700
  if (!submitAttempted || !scrollTargetId) return;
4701
4701
  const timer = setTimeout(() => {
4702
4702
  const elem = document.getElementById(scrollTargetId);
@@ -5004,6 +5004,138 @@ function RegistrationSuccessCard({
5004
5004
  ] }, f.id)) }) })
5005
5005
  ] });
5006
5006
  }
5007
+ var OTPCodeInput = ({
5008
+ value,
5009
+ onChange,
5010
+ label,
5011
+ error,
5012
+ disabled = false,
5013
+ length = 6,
5014
+ className,
5015
+ id,
5016
+ required
5017
+ }) => {
5018
+ const baseId = id != null ? id : React22.useId();
5019
+ const inputRefs = React22.useRef([]);
5020
+ const digits = React22.useMemo(() => {
5021
+ const arr = value.split("").slice(0, length);
5022
+ while (arr.length < length) arr.push("");
5023
+ return arr;
5024
+ }, [value, length]);
5025
+ const updateValue = (newDigits) => {
5026
+ onChange(newDigits.join(""));
5027
+ };
5028
+ const focusedIndexRef = React22.useRef(0);
5029
+ const focusSlot = (index) => {
5030
+ var _a;
5031
+ if (index >= 0 && index < length) {
5032
+ (_a = inputRefs.current[index]) == null ? void 0 : _a.focus();
5033
+ }
5034
+ };
5035
+ const handleChange = (index, raw) => {
5036
+ const numeric = raw.replace(/\D/g, "");
5037
+ if (!numeric) return;
5038
+ const newDigits = [...digits];
5039
+ newDigits[index] = numeric[numeric.length - 1];
5040
+ updateValue(newDigits);
5041
+ if (index < length - 1) {
5042
+ focusSlot(index + 1);
5043
+ }
5044
+ };
5045
+ const handleKeyDown = (index, e) => {
5046
+ if (e.key === "Backspace") {
5047
+ e.preventDefault();
5048
+ const newDigits = [...digits];
5049
+ if (newDigits[index]) {
5050
+ newDigits[index] = "";
5051
+ updateValue(newDigits);
5052
+ } else if (index > 0) {
5053
+ newDigits[index - 1] = "";
5054
+ updateValue(newDigits);
5055
+ focusSlot(index - 1);
5056
+ }
5057
+ } else if (e.key === "ArrowLeft") {
5058
+ e.preventDefault();
5059
+ focusSlot(index - 1);
5060
+ } else if (e.key === "ArrowRight") {
5061
+ e.preventDefault();
5062
+ focusSlot(index + 1);
5063
+ } else if (e.key === "Tab") ; else if (!/^\d$/.test(e.key) && e.key.length === 1) {
5064
+ e.preventDefault();
5065
+ }
5066
+ };
5067
+ const handlePaste = (e) => {
5068
+ e.preventDefault();
5069
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
5070
+ if (!pasted) return;
5071
+ const startIndex = focusedIndexRef.current;
5072
+ const newDigits = [...digits];
5073
+ for (let i = 0; i < pasted.length && startIndex + i < length; i++) {
5074
+ newDigits[startIndex + i] = pasted[i];
5075
+ }
5076
+ updateValue(newDigits);
5077
+ const lastFilled = Math.min(startIndex + pasted.length, length) - 1;
5078
+ focusSlot(lastFilled < length - 1 ? lastFilled + 1 : lastFilled);
5079
+ };
5080
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center", className), children: [
5081
+ /* @__PURE__ */ jsx(
5082
+ "label",
5083
+ {
5084
+ htmlFor: baseId,
5085
+ className: cn(
5086
+ "self-start text-sm text-muted-foreground font-ui mb-2",
5087
+ required && "after:content-['*'] after:text-primary after:ml-0.5"
5088
+ ),
5089
+ children: label
5090
+ }
5091
+ ),
5092
+ /* @__PURE__ */ jsx(
5093
+ "div",
5094
+ {
5095
+ className: cn(
5096
+ "flex justify-center gap-2",
5097
+ disabled && "opacity-50 pointer-events-none"
5098
+ ),
5099
+ role: "group",
5100
+ "aria-label": label,
5101
+ onPaste: handlePaste,
5102
+ children: digits.map((digit, index) => /* @__PURE__ */ jsx(
5103
+ "input",
5104
+ {
5105
+ ref: (el) => {
5106
+ inputRefs.current[index] = el;
5107
+ },
5108
+ id: index === 0 ? baseId : `${baseId}-${index}`,
5109
+ type: "text",
5110
+ inputMode: "numeric",
5111
+ pattern: "\\d*",
5112
+ maxLength: 2,
5113
+ value: digit,
5114
+ autoComplete: index === 0 ? "one-time-code" : "off",
5115
+ "aria-label": `${label} d\xEDgito ${index + 1} de ${length}`,
5116
+ disabled,
5117
+ onChange: (e) => handleChange(index, e.target.value),
5118
+ onKeyDown: (e) => handleKeyDown(index, e),
5119
+ onFocus: (e) => {
5120
+ focusedIndexRef.current = index;
5121
+ e.target.select();
5122
+ },
5123
+ className: cn(
5124
+ "w-11 h-14 text-center text-lg rounded-lg border font-ui",
5125
+ "bg-background text-foreground border-border",
5126
+ "transition-colors",
5127
+ "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary",
5128
+ error && "border-destructive focus:border-destructive focus:ring-destructive"
5129
+ )
5130
+ },
5131
+ index
5132
+ ))
5133
+ }
5134
+ ),
5135
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive font-ui self-start", children: error })
5136
+ ] });
5137
+ };
5138
+ OTPCodeInput.displayName = "OTPCodeInput";
5007
5139
  function Checkbox(_a) {
5008
5140
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
5009
5141
  return /* @__PURE__ */ jsx(
@@ -5029,7 +5161,7 @@ function Checkbox(_a) {
5029
5161
  })
5030
5162
  );
5031
5163
  }
5032
- var AccordionVariantContext = React21.createContext("default");
5164
+ var AccordionVariantContext = React22.createContext("default");
5033
5165
  function Accordion(_a) {
5034
5166
  var _b = _a, { className, variant = "default" } = _b, props = __objRest(_b, ["className", "variant"]);
5035
5167
  return /* @__PURE__ */ jsx(AccordionVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
@@ -5047,7 +5179,7 @@ function Accordion(_a) {
5047
5179
  }
5048
5180
  function AccordionItem(_a) {
5049
5181
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
5050
- const variant = React21.useContext(AccordionVariantContext);
5182
+ const variant = React22.useContext(AccordionVariantContext);
5051
5183
  return /* @__PURE__ */ jsx(
5052
5184
  Accordion$1.Item,
5053
5185
  __spreadValues({
@@ -5068,7 +5200,7 @@ function AccordionTrigger(_a) {
5068
5200
  "className",
5069
5201
  "children"
5070
5202
  ]);
5071
- const variant = React21.useContext(AccordionVariantContext);
5203
+ const variant = React22.useContext(AccordionVariantContext);
5072
5204
  return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
5073
5205
  Accordion$1.Trigger,
5074
5206
  __spreadProps(__spreadValues({
@@ -5122,7 +5254,7 @@ function AccordionContent(_a) {
5122
5254
  "className",
5123
5255
  "children"
5124
5256
  ]);
5125
- const variant = React21.useContext(AccordionVariantContext);
5257
+ const variant = React22.useContext(AccordionVariantContext);
5126
5258
  return /* @__PURE__ */ jsx(
5127
5259
  Accordion$1.Panel,
5128
5260
  __spreadProps(__spreadValues({
@@ -5154,7 +5286,7 @@ function FilterPanel({
5154
5286
  title = "Filters",
5155
5287
  className
5156
5288
  }) {
5157
- const [internalValue, setInternalValue] = React21.useState(
5289
+ const [internalValue, setInternalValue] = React22.useState(
5158
5290
  () => Object.fromEntries(groups.map((g) => [g.id, []]))
5159
5291
  );
5160
5292
  const selected = value != null ? value : internalValue;
@@ -5316,11 +5448,11 @@ function ItineraryModal({
5316
5448
  onNext
5317
5449
  }) {
5318
5450
  var _a, _b, _c;
5319
- const [imgIndex, setImgIndex] = React21.useState(0);
5451
+ const [imgIndex, setImgIndex] = React22.useState(0);
5320
5452
  const images = stop ? [stop.coverImage, ...(_a = stop.images) != null ? _a : []] : [];
5321
5453
  const isFirst = (stop == null ? void 0 : stop.dayNumber) === ((_b = allStops[0]) == null ? void 0 : _b.dayNumber);
5322
5454
  const isLast = (stop == null ? void 0 : stop.dayNumber) === ((_c = allStops[allStops.length - 1]) == null ? void 0 : _c.dayNumber);
5323
- React21.useEffect(() => {
5455
+ React22.useEffect(() => {
5324
5456
  setImgIndex(0);
5325
5457
  }, [stop == null ? void 0 : stop.dayNumber]);
5326
5458
  if (!stop) return null;
@@ -5447,8 +5579,8 @@ function ItineraryModal({
5447
5579
  ) });
5448
5580
  }
5449
5581
  function Itinerary({ title, subtitle, stops, className }) {
5450
- const [activeIndex, setActiveIndex] = React21.useState(null);
5451
- const scrollRef = React21.useRef(null);
5582
+ const [activeIndex, setActiveIndex] = React22.useState(null);
5583
+ const scrollRef = React22.useRef(null);
5452
5584
  const activeStop = activeIndex !== null ? stops[activeIndex] : null;
5453
5585
  const scrollBy = (dir) => {
5454
5586
  if (!scrollRef.current) return;
@@ -5534,8 +5666,8 @@ function MenuTrip({
5534
5666
  bold = true,
5535
5667
  className
5536
5668
  }) {
5537
- const scrollRef = React21.useRef(null);
5538
- React21.useEffect(() => {
5669
+ const scrollRef = React22.useRef(null);
5670
+ React22.useEffect(() => {
5539
5671
  if (!scrollRef.current || !activeSection) return;
5540
5672
  const container = scrollRef.current;
5541
5673
  const btn = container.querySelector(
@@ -5681,18 +5813,18 @@ function Lightbox({
5681
5813
  onClose
5682
5814
  }) {
5683
5815
  var _a;
5684
- const [index, setIndex] = React21.useState(initialIndex);
5816
+ const [index, setIndex] = React22.useState(initialIndex);
5685
5817
  const total = photos.length;
5686
5818
  const photo = photos[index];
5687
- const prev = React21.useCallback(
5819
+ const prev = React22.useCallback(
5688
5820
  () => setIndex((i) => (i - 1 + total) % total),
5689
5821
  [total]
5690
5822
  );
5691
- const next = React21.useCallback(
5823
+ const next = React22.useCallback(
5692
5824
  () => setIndex((i) => (i + 1) % total),
5693
5825
  [total]
5694
5826
  );
5695
- React21.useEffect(() => {
5827
+ React22.useEffect(() => {
5696
5828
  const onKey = (e) => {
5697
5829
  if (e.key === "Escape") onClose();
5698
5830
  if (e.key === "ArrowLeft") prev();
@@ -5886,7 +6018,7 @@ function GridGallery({
5886
6018
  initialVisible,
5887
6019
  onOpen
5888
6020
  }) {
5889
- const [expanded, setExpanded] = React21.useState(false);
6021
+ const [expanded, setExpanded] = React22.useState(false);
5890
6022
  const cols = gridCols(photos.length);
5891
6023
  const hasMore = photos.length > initialVisible;
5892
6024
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
@@ -5916,7 +6048,7 @@ function MasonryGallery({
5916
6048
  initialVisible,
5917
6049
  onOpen
5918
6050
  }) {
5919
- const [expanded, setExpanded] = React21.useState(false);
6051
+ const [expanded, setExpanded] = React22.useState(false);
5920
6052
  const hasMore = photos.length > initialVisible;
5921
6053
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
5922
6054
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -5989,7 +6121,7 @@ function FeaturedGallery({
5989
6121
  photos,
5990
6122
  onOpen
5991
6123
  }) {
5992
- const [expanded, setExpanded] = React21.useState(false);
6124
+ const [expanded, setExpanded] = React22.useState(false);
5993
6125
  const featured = photos.slice(0, 3);
5994
6126
  const extra = photos.slice(3);
5995
6127
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -6066,8 +6198,8 @@ function PhotoGallery({
6066
6198
  onPhotoClick,
6067
6199
  className
6068
6200
  }) {
6069
- const [lightboxIndex, setLightboxIndex] = React21.useState(null);
6070
- const normalised = React21.useMemo(() => photos.map(normalise), [photos]);
6201
+ const [lightboxIndex, setLightboxIndex] = React22.useState(null);
6202
+ const normalised = React22.useMemo(() => photos.map(normalise), [photos]);
6071
6203
  const handleOpen = (index) => {
6072
6204
  setLightboxIndex(index);
6073
6205
  onPhotoClick == null ? void 0 : onPhotoClick(normalised[index].src, index);
@@ -6156,7 +6288,7 @@ function PricingTrip({
6156
6288
  variant = "card",
6157
6289
  className
6158
6290
  }) {
6159
- const [showPricing, setShowPricing] = React21.useState(false);
6291
+ const [showPricing, setShowPricing] = React22.useState(false);
6160
6292
  if (variant === "compact") {
6161
6293
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3", className), children: [
6162
6294
  /* @__PURE__ */ jsxs("div", { children: [
@@ -6479,14 +6611,14 @@ function SiteHeader({
6479
6611
  className
6480
6612
  }) {
6481
6613
  const t = VARIANT[variant];
6482
- const [openMenu, setOpenMenu] = React21.useState(null);
6483
- const [langOpen, setLangOpen] = React21.useState(false);
6484
- const [mobileOpen, setMobileOpen] = React21.useState(false);
6485
- const [openMobileSection, setOpenMobileSection] = React21.useState(null);
6486
- const [activeLang, setActiveLang] = React21.useState(currentLanguage);
6614
+ const [openMenu, setOpenMenu] = React22.useState(null);
6615
+ const [langOpen, setLangOpen] = React22.useState(false);
6616
+ const [mobileOpen, setMobileOpen] = React22.useState(false);
6617
+ const [openMobileSection, setOpenMobileSection] = React22.useState(null);
6618
+ const [activeLang, setActiveLang] = React22.useState(currentLanguage);
6487
6619
  const toggleMobileSection = (label) => setOpenMobileSection((prev) => prev === label ? null : label);
6488
- const menuCloseTimer = React21.useRef(void 0);
6489
- const langCloseTimer = React21.useRef(void 0);
6620
+ const menuCloseTimer = React22.useRef(void 0);
6621
+ const langCloseTimer = React22.useRef(void 0);
6490
6622
  const handleMenuEnter = (label) => {
6491
6623
  clearTimeout(menuCloseTimer.current);
6492
6624
  setOpenMenu(label);
@@ -6507,7 +6639,7 @@ function SiteHeader({
6507
6639
  setOpenMenu(null);
6508
6640
  setLangOpen(false);
6509
6641
  };
6510
- React21.useEffect(() => () => {
6642
+ React22.useEffect(() => () => {
6511
6643
  clearTimeout(menuCloseTimer.current);
6512
6644
  clearTimeout(langCloseTimer.current);
6513
6645
  }, []);
@@ -6772,7 +6904,7 @@ function SiteHeader({
6772
6904
  ), children: [
6773
6905
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: languages.map((lang, i) => {
6774
6906
  const isActive = lang.code === activeLang;
6775
- return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
6907
+ return /* @__PURE__ */ jsxs(React22.Fragment, { children: [
6776
6908
  i > 0 && /* @__PURE__ */ jsx("span", { className: cn(
6777
6909
  "text-xs select-none",
6778
6910
  variant === "white" ? "text-border" : "text-white/15"
@@ -6834,8 +6966,8 @@ function SiteHeader({
6834
6966
  );
6835
6967
  }
6836
6968
  function ThemeToggle({ className }) {
6837
- const [dark, setDark] = React21.useState(false);
6838
- React21.useEffect(() => {
6969
+ const [dark, setDark] = React22.useState(false);
6970
+ React22.useEffect(() => {
6839
6971
  const saved = localStorage.getItem("theme");
6840
6972
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
6841
6973
  const isDark = saved === "dark" || !saved && prefersDark;
@@ -6986,7 +7118,7 @@ function TripCard({
6986
7118
  );
6987
7119
  }
6988
7120
  function useHlsVideo(videoRef, src) {
6989
- React21.useEffect(() => {
7121
+ React22.useEffect(() => {
6990
7122
  if (!src || !videoRef.current) return;
6991
7123
  const video = videoRef.current;
6992
7124
  if (!src.includes(".m3u8")) return;
@@ -7028,11 +7160,11 @@ function TripHeader({
7028
7160
  className
7029
7161
  }) {
7030
7162
  var _a;
7031
- const [heroIndex, setHeroIndex] = React21.useState(0);
7032
- const [videoReady, setVideoReady] = React21.useState(false);
7033
- const videoRef = React21.useRef(null);
7163
+ const [heroIndex, setHeroIndex] = React22.useState(0);
7164
+ const [videoReady, setVideoReady] = React22.useState(false);
7165
+ const videoRef = React22.useRef(null);
7034
7166
  const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
7035
- const validImages = React21.useMemo(
7167
+ const validImages = React22.useMemo(
7036
7168
  () => images.map((u) => u == null ? void 0 : u.trim()).filter(Boolean),
7037
7169
  [images]
7038
7170
  );
@@ -7047,7 +7179,7 @@ function TripHeader({
7047
7179
  const nights = duration ? (_a = duration.nights) != null ? _a : Math.max(duration.days - 1, 1) : null;
7048
7180
  const hasMeta = !!(destination || duration);
7049
7181
  useHlsVideo(videoRef, isHls ? videoUrl : void 0);
7050
- React21.useEffect(() => {
7182
+ React22.useEffect(() => {
7051
7183
  if (!videoUrl) return;
7052
7184
  const el = videoRef.current;
7053
7185
  if (!el) return;
@@ -7189,7 +7321,7 @@ function TripHeader({
7189
7321
  siteHeader ? "-mt-44" : "-mt-36"
7190
7322
  ),
7191
7323
  children: [
7192
- breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-center gap-1.5 flex-wrap", children: breadcrumb.map((crumb, i) => /* @__PURE__ */ jsxs(React21.Fragment, { children: [
7324
+ breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-center gap-1.5 flex-wrap", children: breadcrumb.map((crumb, i) => /* @__PURE__ */ jsxs(React22.Fragment, { children: [
7193
7325
  i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
7194
7326
  /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui hover:text-white/90 cursor-default", children: crumb.label })
7195
7327
  ] }, i)) }),
@@ -7289,19 +7421,19 @@ function TripPage({
7289
7421
  features,
7290
7422
  className
7291
7423
  }) {
7292
- const [activeSection, setActiveSection] = React21.useState("");
7293
- const [navFloating, setNavFloating] = React21.useState(false);
7294
- const [navHidden, setNavHidden] = React21.useState(false);
7295
- const [isFloating, setIsFloating] = React21.useState(false);
7296
- const [sidebarPos, setSidebarPos] = React21.useState(null);
7297
- const [pricingBarVisible, setPricingBarVisible] = React21.useState(false);
7298
- const navRef = React21.useRef(null);
7299
- const navSentinelRef = React21.useRef(null);
7300
- const sentinelRef = React21.useRef(null);
7301
- const sidebarPlaceholderRef = React21.useRef(null);
7302
- const pricingBarRef = React21.useRef(null);
7303
- const galleryRef = React21.useRef(null);
7304
- const sections = React21.useMemo(
7424
+ const [activeSection, setActiveSection] = React22.useState("");
7425
+ const [navFloating, setNavFloating] = React22.useState(false);
7426
+ const [navHidden, setNavHidden] = React22.useState(false);
7427
+ const [isFloating, setIsFloating] = React22.useState(false);
7428
+ const [sidebarPos, setSidebarPos] = React22.useState(null);
7429
+ const [pricingBarVisible, setPricingBarVisible] = React22.useState(false);
7430
+ const navRef = React22.useRef(null);
7431
+ const navSentinelRef = React22.useRef(null);
7432
+ const sentinelRef = React22.useRef(null);
7433
+ const sidebarPlaceholderRef = React22.useRef(null);
7434
+ const pricingBarRef = React22.useRef(null);
7435
+ const galleryRef = React22.useRef(null);
7436
+ const sections = React22.useMemo(
7305
7437
  () => [
7306
7438
  { id: "key-info", label: "Key info", show: !!(infoGroups == null ? void 0 : infoGroups.length) },
7307
7439
  { id: "overview", label: "Overview", show: !!overview },
@@ -7316,7 +7448,7 @@ function TripPage({
7316
7448
  // eslint-disable-next-line react-hooks/exhaustive-deps
7317
7449
  []
7318
7450
  );
7319
- React21.useEffect(() => {
7451
+ React22.useEffect(() => {
7320
7452
  const sentinel = navSentinelRef.current;
7321
7453
  if (!sentinel) return;
7322
7454
  const update = () => setNavFloating(sentinel.getBoundingClientRect().top < 1);
@@ -7324,7 +7456,7 @@ function TripPage({
7324
7456
  update();
7325
7457
  return () => document.removeEventListener("scroll", update, { capture: true });
7326
7458
  }, []);
7327
- React21.useEffect(() => {
7459
+ React22.useEffect(() => {
7328
7460
  const sentinel = sentinelRef.current;
7329
7461
  if (!sentinel) return;
7330
7462
  const update = () => setIsFloating(sentinel.getBoundingClientRect().top < 1);
@@ -7332,7 +7464,7 @@ function TripPage({
7332
7464
  update();
7333
7465
  return () => document.removeEventListener("scroll", update, { capture: true });
7334
7466
  }, []);
7335
- React21.useEffect(() => {
7467
+ React22.useEffect(() => {
7336
7468
  const measure = () => {
7337
7469
  if (!sidebarPlaceholderRef.current) return;
7338
7470
  const rect = sidebarPlaceholderRef.current.getBoundingClientRect();
@@ -7342,7 +7474,7 @@ function TripPage({
7342
7474
  window.addEventListener("resize", measure);
7343
7475
  return () => window.removeEventListener("resize", measure);
7344
7476
  }, [isFloating]);
7345
- React21.useEffect(() => {
7477
+ React22.useEffect(() => {
7346
7478
  const check = () => {
7347
7479
  var _a;
7348
7480
  const target = (_a = galleryRef.current) != null ? _a : pricingBarRef.current;
@@ -7353,7 +7485,7 @@ function TripPage({
7353
7485
  check();
7354
7486
  return () => document.removeEventListener("scroll", check, { capture: true });
7355
7487
  }, []);
7356
- React21.useEffect(() => {
7488
+ React22.useEffect(() => {
7357
7489
  const check = () => {
7358
7490
  if (!pricingBarRef.current) return;
7359
7491
  setNavHidden(pricingBarRef.current.getBoundingClientRect().top < window.innerHeight * 0.92);
@@ -7362,7 +7494,7 @@ function TripPage({
7362
7494
  check();
7363
7495
  return () => document.removeEventListener("scroll", check, { capture: true });
7364
7496
  }, []);
7365
- React21.useEffect(() => {
7497
+ React22.useEffect(() => {
7366
7498
  if (sections.length === 0) return;
7367
7499
  setActiveSection(sections[0].id);
7368
7500
  const update = () => {
@@ -8376,6 +8508,6 @@ function LeadCapturePopup({
8376
8508
  );
8377
8509
  }
8378
8510
 
8379
- export { ActivityCard, Alert, BirthDateField, BookingConfirmation, BookingConfirmationEmail, BookingConfirmedCard, BookingDetails, BookingForm, BookingOtpEmail, BookingShell, Button, COUNTRIES, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, DatePickerField, FilterPanel, FloatingInput, FloatingSelect, Itinerary, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, Offer, OfferAdventureCard, PaymentAmountSelector, PaymentMethodSelector, PaymentModalShell, PhoneCountrySelect, PhotoGallery, PricingTrip, RegistrationForm, RegistrationSuccessCard, SiteHeader, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, buttonVariants, cn, emailTokens, getStripeAppearance, stripeAppearance, wrapEmailHtml };
8511
+ export { ActivityCard, Alert, BirthDateField, BookingConfirmation, BookingConfirmationEmail, BookingConfirmedCard, BookingDetails, BookingForm, BookingOtpEmail, BookingShell, Button, COUNTRIES, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, DatePickerField, FilterPanel, FloatingInput, FloatingSelect, Itinerary, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, PaymentAmountSelector, PaymentMethodSelector, PaymentModalShell, PhoneCountrySelect, PhotoGallery, PricingTrip, RegistrationForm, RegistrationSuccessCard, SiteHeader, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, buttonVariants, cn, emailTokens, getStripeAppearance, stripeAppearance, wrapEmailHtml };
8380
8512
  //# sourceMappingURL=index.js.map
8381
8513
  //# sourceMappingURL=index.js.map