@planetaexo/design-system 0.4.15 → 0.4.16

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,132 @@ 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 focusSlot = (index) => {
5029
+ var _a;
5030
+ if (index >= 0 && index < length) {
5031
+ (_a = inputRefs.current[index]) == null ? void 0 : _a.focus();
5032
+ }
5033
+ };
5034
+ const handleChange = (index, raw) => {
5035
+ const numeric = raw.replace(/\D/g, "");
5036
+ if (!numeric) return;
5037
+ const newDigits = [...digits];
5038
+ newDigits[index] = numeric[numeric.length - 1];
5039
+ updateValue(newDigits);
5040
+ if (index < length - 1) {
5041
+ focusSlot(index + 1);
5042
+ }
5043
+ };
5044
+ const handleKeyDown = (index, e) => {
5045
+ if (e.key === "Backspace") {
5046
+ e.preventDefault();
5047
+ const newDigits = [...digits];
5048
+ if (newDigits[index]) {
5049
+ newDigits[index] = "";
5050
+ updateValue(newDigits);
5051
+ } else if (index > 0) {
5052
+ newDigits[index - 1] = "";
5053
+ updateValue(newDigits);
5054
+ focusSlot(index - 1);
5055
+ }
5056
+ } else if (e.key === "ArrowLeft") {
5057
+ e.preventDefault();
5058
+ focusSlot(index - 1);
5059
+ } else if (e.key === "ArrowRight") {
5060
+ e.preventDefault();
5061
+ focusSlot(index + 1);
5062
+ } else if (e.key === "Tab") ; else if (!/^\d$/.test(e.key) && e.key.length === 1) {
5063
+ e.preventDefault();
5064
+ }
5065
+ };
5066
+ const handlePaste = (e) => {
5067
+ e.preventDefault();
5068
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
5069
+ if (!pasted) return;
5070
+ const newDigits = [...digits];
5071
+ for (let i = 0; i < pasted.length; i++) {
5072
+ newDigits[i] = pasted[i];
5073
+ }
5074
+ updateValue(newDigits);
5075
+ const nextEmpty = newDigits.findIndex((d, i) => i >= pasted.length && !d);
5076
+ focusSlot(nextEmpty !== -1 ? nextEmpty : Math.min(pasted.length, length - 1));
5077
+ };
5078
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
5079
+ /* @__PURE__ */ jsx(
5080
+ "label",
5081
+ {
5082
+ className: cn(
5083
+ "text-sm text-muted-foreground mb-2",
5084
+ required && "after:content-['*'] after:text-primary after:ml-0.5"
5085
+ ),
5086
+ children: label
5087
+ }
5088
+ ),
5089
+ /* @__PURE__ */ jsx(
5090
+ "div",
5091
+ {
5092
+ className: cn(
5093
+ "flex gap-2",
5094
+ disabled && "opacity-50 pointer-events-none"
5095
+ ),
5096
+ role: "group",
5097
+ "aria-label": label,
5098
+ children: digits.map((digit, index) => /* @__PURE__ */ jsx(
5099
+ "input",
5100
+ {
5101
+ ref: (el) => {
5102
+ inputRefs.current[index] = el;
5103
+ },
5104
+ id: index === 0 ? baseId : `${baseId}-${index}`,
5105
+ type: "text",
5106
+ inputMode: "numeric",
5107
+ pattern: "\\d*",
5108
+ maxLength: 1,
5109
+ value: digit,
5110
+ autoComplete: index === 0 ? "one-time-code" : "off",
5111
+ "aria-label": `${label} d\xEDgito ${index + 1} de ${length}`,
5112
+ disabled,
5113
+ onChange: (e) => handleChange(index, e.target.value),
5114
+ onKeyDown: (e) => handleKeyDown(index, e),
5115
+ onPaste: handlePaste,
5116
+ onFocus: (e) => e.target.select(),
5117
+ className: cn(
5118
+ "w-10 h-12 text-center text-lg rounded-lg border",
5119
+ "bg-background text-foreground border-border",
5120
+ "transition-colors",
5121
+ "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary",
5122
+ error && "border-destructive focus:border-destructive focus:ring-destructive"
5123
+ )
5124
+ },
5125
+ index
5126
+ ))
5127
+ }
5128
+ ),
5129
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: error })
5130
+ ] });
5131
+ };
5132
+ OTPCodeInput.displayName = "OTPCodeInput";
5007
5133
  function Checkbox(_a) {
5008
5134
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
5009
5135
  return /* @__PURE__ */ jsx(
@@ -5029,7 +5155,7 @@ function Checkbox(_a) {
5029
5155
  })
5030
5156
  );
5031
5157
  }
5032
- var AccordionVariantContext = React21.createContext("default");
5158
+ var AccordionVariantContext = React22.createContext("default");
5033
5159
  function Accordion(_a) {
5034
5160
  var _b = _a, { className, variant = "default" } = _b, props = __objRest(_b, ["className", "variant"]);
5035
5161
  return /* @__PURE__ */ jsx(AccordionVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
@@ -5047,7 +5173,7 @@ function Accordion(_a) {
5047
5173
  }
5048
5174
  function AccordionItem(_a) {
5049
5175
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
5050
- const variant = React21.useContext(AccordionVariantContext);
5176
+ const variant = React22.useContext(AccordionVariantContext);
5051
5177
  return /* @__PURE__ */ jsx(
5052
5178
  Accordion$1.Item,
5053
5179
  __spreadValues({
@@ -5068,7 +5194,7 @@ function AccordionTrigger(_a) {
5068
5194
  "className",
5069
5195
  "children"
5070
5196
  ]);
5071
- const variant = React21.useContext(AccordionVariantContext);
5197
+ const variant = React22.useContext(AccordionVariantContext);
5072
5198
  return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
5073
5199
  Accordion$1.Trigger,
5074
5200
  __spreadProps(__spreadValues({
@@ -5122,7 +5248,7 @@ function AccordionContent(_a) {
5122
5248
  "className",
5123
5249
  "children"
5124
5250
  ]);
5125
- const variant = React21.useContext(AccordionVariantContext);
5251
+ const variant = React22.useContext(AccordionVariantContext);
5126
5252
  return /* @__PURE__ */ jsx(
5127
5253
  Accordion$1.Panel,
5128
5254
  __spreadProps(__spreadValues({
@@ -5154,7 +5280,7 @@ function FilterPanel({
5154
5280
  title = "Filters",
5155
5281
  className
5156
5282
  }) {
5157
- const [internalValue, setInternalValue] = React21.useState(
5283
+ const [internalValue, setInternalValue] = React22.useState(
5158
5284
  () => Object.fromEntries(groups.map((g) => [g.id, []]))
5159
5285
  );
5160
5286
  const selected = value != null ? value : internalValue;
@@ -5316,11 +5442,11 @@ function ItineraryModal({
5316
5442
  onNext
5317
5443
  }) {
5318
5444
  var _a, _b, _c;
5319
- const [imgIndex, setImgIndex] = React21.useState(0);
5445
+ const [imgIndex, setImgIndex] = React22.useState(0);
5320
5446
  const images = stop ? [stop.coverImage, ...(_a = stop.images) != null ? _a : []] : [];
5321
5447
  const isFirst = (stop == null ? void 0 : stop.dayNumber) === ((_b = allStops[0]) == null ? void 0 : _b.dayNumber);
5322
5448
  const isLast = (stop == null ? void 0 : stop.dayNumber) === ((_c = allStops[allStops.length - 1]) == null ? void 0 : _c.dayNumber);
5323
- React21.useEffect(() => {
5449
+ React22.useEffect(() => {
5324
5450
  setImgIndex(0);
5325
5451
  }, [stop == null ? void 0 : stop.dayNumber]);
5326
5452
  if (!stop) return null;
@@ -5447,8 +5573,8 @@ function ItineraryModal({
5447
5573
  ) });
5448
5574
  }
5449
5575
  function Itinerary({ title, subtitle, stops, className }) {
5450
- const [activeIndex, setActiveIndex] = React21.useState(null);
5451
- const scrollRef = React21.useRef(null);
5576
+ const [activeIndex, setActiveIndex] = React22.useState(null);
5577
+ const scrollRef = React22.useRef(null);
5452
5578
  const activeStop = activeIndex !== null ? stops[activeIndex] : null;
5453
5579
  const scrollBy = (dir) => {
5454
5580
  if (!scrollRef.current) return;
@@ -5534,8 +5660,8 @@ function MenuTrip({
5534
5660
  bold = true,
5535
5661
  className
5536
5662
  }) {
5537
- const scrollRef = React21.useRef(null);
5538
- React21.useEffect(() => {
5663
+ const scrollRef = React22.useRef(null);
5664
+ React22.useEffect(() => {
5539
5665
  if (!scrollRef.current || !activeSection) return;
5540
5666
  const container = scrollRef.current;
5541
5667
  const btn = container.querySelector(
@@ -5681,18 +5807,18 @@ function Lightbox({
5681
5807
  onClose
5682
5808
  }) {
5683
5809
  var _a;
5684
- const [index, setIndex] = React21.useState(initialIndex);
5810
+ const [index, setIndex] = React22.useState(initialIndex);
5685
5811
  const total = photos.length;
5686
5812
  const photo = photos[index];
5687
- const prev = React21.useCallback(
5813
+ const prev = React22.useCallback(
5688
5814
  () => setIndex((i) => (i - 1 + total) % total),
5689
5815
  [total]
5690
5816
  );
5691
- const next = React21.useCallback(
5817
+ const next = React22.useCallback(
5692
5818
  () => setIndex((i) => (i + 1) % total),
5693
5819
  [total]
5694
5820
  );
5695
- React21.useEffect(() => {
5821
+ React22.useEffect(() => {
5696
5822
  const onKey = (e) => {
5697
5823
  if (e.key === "Escape") onClose();
5698
5824
  if (e.key === "ArrowLeft") prev();
@@ -5886,7 +6012,7 @@ function GridGallery({
5886
6012
  initialVisible,
5887
6013
  onOpen
5888
6014
  }) {
5889
- const [expanded, setExpanded] = React21.useState(false);
6015
+ const [expanded, setExpanded] = React22.useState(false);
5890
6016
  const cols = gridCols(photos.length);
5891
6017
  const hasMore = photos.length > initialVisible;
5892
6018
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
@@ -5916,7 +6042,7 @@ function MasonryGallery({
5916
6042
  initialVisible,
5917
6043
  onOpen
5918
6044
  }) {
5919
- const [expanded, setExpanded] = React21.useState(false);
6045
+ const [expanded, setExpanded] = React22.useState(false);
5920
6046
  const hasMore = photos.length > initialVisible;
5921
6047
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
5922
6048
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -5989,7 +6115,7 @@ function FeaturedGallery({
5989
6115
  photos,
5990
6116
  onOpen
5991
6117
  }) {
5992
- const [expanded, setExpanded] = React21.useState(false);
6118
+ const [expanded, setExpanded] = React22.useState(false);
5993
6119
  const featured = photos.slice(0, 3);
5994
6120
  const extra = photos.slice(3);
5995
6121
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -6066,8 +6192,8 @@ function PhotoGallery({
6066
6192
  onPhotoClick,
6067
6193
  className
6068
6194
  }) {
6069
- const [lightboxIndex, setLightboxIndex] = React21.useState(null);
6070
- const normalised = React21.useMemo(() => photos.map(normalise), [photos]);
6195
+ const [lightboxIndex, setLightboxIndex] = React22.useState(null);
6196
+ const normalised = React22.useMemo(() => photos.map(normalise), [photos]);
6071
6197
  const handleOpen = (index) => {
6072
6198
  setLightboxIndex(index);
6073
6199
  onPhotoClick == null ? void 0 : onPhotoClick(normalised[index].src, index);
@@ -6156,7 +6282,7 @@ function PricingTrip({
6156
6282
  variant = "card",
6157
6283
  className
6158
6284
  }) {
6159
- const [showPricing, setShowPricing] = React21.useState(false);
6285
+ const [showPricing, setShowPricing] = React22.useState(false);
6160
6286
  if (variant === "compact") {
6161
6287
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3", className), children: [
6162
6288
  /* @__PURE__ */ jsxs("div", { children: [
@@ -6479,14 +6605,14 @@ function SiteHeader({
6479
6605
  className
6480
6606
  }) {
6481
6607
  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);
6608
+ const [openMenu, setOpenMenu] = React22.useState(null);
6609
+ const [langOpen, setLangOpen] = React22.useState(false);
6610
+ const [mobileOpen, setMobileOpen] = React22.useState(false);
6611
+ const [openMobileSection, setOpenMobileSection] = React22.useState(null);
6612
+ const [activeLang, setActiveLang] = React22.useState(currentLanguage);
6487
6613
  const toggleMobileSection = (label) => setOpenMobileSection((prev) => prev === label ? null : label);
6488
- const menuCloseTimer = React21.useRef(void 0);
6489
- const langCloseTimer = React21.useRef(void 0);
6614
+ const menuCloseTimer = React22.useRef(void 0);
6615
+ const langCloseTimer = React22.useRef(void 0);
6490
6616
  const handleMenuEnter = (label) => {
6491
6617
  clearTimeout(menuCloseTimer.current);
6492
6618
  setOpenMenu(label);
@@ -6507,7 +6633,7 @@ function SiteHeader({
6507
6633
  setOpenMenu(null);
6508
6634
  setLangOpen(false);
6509
6635
  };
6510
- React21.useEffect(() => () => {
6636
+ React22.useEffect(() => () => {
6511
6637
  clearTimeout(menuCloseTimer.current);
6512
6638
  clearTimeout(langCloseTimer.current);
6513
6639
  }, []);
@@ -6772,7 +6898,7 @@ function SiteHeader({
6772
6898
  ), children: [
6773
6899
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: languages.map((lang, i) => {
6774
6900
  const isActive = lang.code === activeLang;
6775
- return /* @__PURE__ */ jsxs(React21.Fragment, { children: [
6901
+ return /* @__PURE__ */ jsxs(React22.Fragment, { children: [
6776
6902
  i > 0 && /* @__PURE__ */ jsx("span", { className: cn(
6777
6903
  "text-xs select-none",
6778
6904
  variant === "white" ? "text-border" : "text-white/15"
@@ -6834,8 +6960,8 @@ function SiteHeader({
6834
6960
  );
6835
6961
  }
6836
6962
  function ThemeToggle({ className }) {
6837
- const [dark, setDark] = React21.useState(false);
6838
- React21.useEffect(() => {
6963
+ const [dark, setDark] = React22.useState(false);
6964
+ React22.useEffect(() => {
6839
6965
  const saved = localStorage.getItem("theme");
6840
6966
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
6841
6967
  const isDark = saved === "dark" || !saved && prefersDark;
@@ -6986,7 +7112,7 @@ function TripCard({
6986
7112
  );
6987
7113
  }
6988
7114
  function useHlsVideo(videoRef, src) {
6989
- React21.useEffect(() => {
7115
+ React22.useEffect(() => {
6990
7116
  if (!src || !videoRef.current) return;
6991
7117
  const video = videoRef.current;
6992
7118
  if (!src.includes(".m3u8")) return;
@@ -7028,11 +7154,11 @@ function TripHeader({
7028
7154
  className
7029
7155
  }) {
7030
7156
  var _a;
7031
- const [heroIndex, setHeroIndex] = React21.useState(0);
7032
- const [videoReady, setVideoReady] = React21.useState(false);
7033
- const videoRef = React21.useRef(null);
7157
+ const [heroIndex, setHeroIndex] = React22.useState(0);
7158
+ const [videoReady, setVideoReady] = React22.useState(false);
7159
+ const videoRef = React22.useRef(null);
7034
7160
  const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
7035
- const validImages = React21.useMemo(
7161
+ const validImages = React22.useMemo(
7036
7162
  () => images.map((u) => u == null ? void 0 : u.trim()).filter(Boolean),
7037
7163
  [images]
7038
7164
  );
@@ -7047,7 +7173,7 @@ function TripHeader({
7047
7173
  const nights = duration ? (_a = duration.nights) != null ? _a : Math.max(duration.days - 1, 1) : null;
7048
7174
  const hasMeta = !!(destination || duration);
7049
7175
  useHlsVideo(videoRef, isHls ? videoUrl : void 0);
7050
- React21.useEffect(() => {
7176
+ React22.useEffect(() => {
7051
7177
  if (!videoUrl) return;
7052
7178
  const el = videoRef.current;
7053
7179
  if (!el) return;
@@ -7189,7 +7315,7 @@ function TripHeader({
7189
7315
  siteHeader ? "-mt-44" : "-mt-36"
7190
7316
  ),
7191
7317
  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: [
7318
+ 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
7319
  i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
7194
7320
  /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui hover:text-white/90 cursor-default", children: crumb.label })
7195
7321
  ] }, i)) }),
@@ -7289,19 +7415,19 @@ function TripPage({
7289
7415
  features,
7290
7416
  className
7291
7417
  }) {
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(
7418
+ const [activeSection, setActiveSection] = React22.useState("");
7419
+ const [navFloating, setNavFloating] = React22.useState(false);
7420
+ const [navHidden, setNavHidden] = React22.useState(false);
7421
+ const [isFloating, setIsFloating] = React22.useState(false);
7422
+ const [sidebarPos, setSidebarPos] = React22.useState(null);
7423
+ const [pricingBarVisible, setPricingBarVisible] = React22.useState(false);
7424
+ const navRef = React22.useRef(null);
7425
+ const navSentinelRef = React22.useRef(null);
7426
+ const sentinelRef = React22.useRef(null);
7427
+ const sidebarPlaceholderRef = React22.useRef(null);
7428
+ const pricingBarRef = React22.useRef(null);
7429
+ const galleryRef = React22.useRef(null);
7430
+ const sections = React22.useMemo(
7305
7431
  () => [
7306
7432
  { id: "key-info", label: "Key info", show: !!(infoGroups == null ? void 0 : infoGroups.length) },
7307
7433
  { id: "overview", label: "Overview", show: !!overview },
@@ -7316,7 +7442,7 @@ function TripPage({
7316
7442
  // eslint-disable-next-line react-hooks/exhaustive-deps
7317
7443
  []
7318
7444
  );
7319
- React21.useEffect(() => {
7445
+ React22.useEffect(() => {
7320
7446
  const sentinel = navSentinelRef.current;
7321
7447
  if (!sentinel) return;
7322
7448
  const update = () => setNavFloating(sentinel.getBoundingClientRect().top < 1);
@@ -7324,7 +7450,7 @@ function TripPage({
7324
7450
  update();
7325
7451
  return () => document.removeEventListener("scroll", update, { capture: true });
7326
7452
  }, []);
7327
- React21.useEffect(() => {
7453
+ React22.useEffect(() => {
7328
7454
  const sentinel = sentinelRef.current;
7329
7455
  if (!sentinel) return;
7330
7456
  const update = () => setIsFloating(sentinel.getBoundingClientRect().top < 1);
@@ -7332,7 +7458,7 @@ function TripPage({
7332
7458
  update();
7333
7459
  return () => document.removeEventListener("scroll", update, { capture: true });
7334
7460
  }, []);
7335
- React21.useEffect(() => {
7461
+ React22.useEffect(() => {
7336
7462
  const measure = () => {
7337
7463
  if (!sidebarPlaceholderRef.current) return;
7338
7464
  const rect = sidebarPlaceholderRef.current.getBoundingClientRect();
@@ -7342,7 +7468,7 @@ function TripPage({
7342
7468
  window.addEventListener("resize", measure);
7343
7469
  return () => window.removeEventListener("resize", measure);
7344
7470
  }, [isFloating]);
7345
- React21.useEffect(() => {
7471
+ React22.useEffect(() => {
7346
7472
  const check = () => {
7347
7473
  var _a;
7348
7474
  const target = (_a = galleryRef.current) != null ? _a : pricingBarRef.current;
@@ -7353,7 +7479,7 @@ function TripPage({
7353
7479
  check();
7354
7480
  return () => document.removeEventListener("scroll", check, { capture: true });
7355
7481
  }, []);
7356
- React21.useEffect(() => {
7482
+ React22.useEffect(() => {
7357
7483
  const check = () => {
7358
7484
  if (!pricingBarRef.current) return;
7359
7485
  setNavHidden(pricingBarRef.current.getBoundingClientRect().top < window.innerHeight * 0.92);
@@ -7362,7 +7488,7 @@ function TripPage({
7362
7488
  check();
7363
7489
  return () => document.removeEventListener("scroll", check, { capture: true });
7364
7490
  }, []);
7365
- React21.useEffect(() => {
7491
+ React22.useEffect(() => {
7366
7492
  if (sections.length === 0) return;
7367
7493
  setActiveSection(sections[0].id);
7368
7494
  const update = () => {
@@ -8376,6 +8502,6 @@ function LeadCapturePopup({
8376
8502
  );
8377
8503
  }
8378
8504
 
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 };
8505
+ 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
8506
  //# sourceMappingURL=index.js.map
8381
8507
  //# sourceMappingURL=index.js.map