@planetaexo/design-system 0.57.2 → 0.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as React30 from 'react';
1
+ import * as React31 from 'react';
2
2
  import { useState, useRef, useCallback, useEffect, useId } from 'react';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
@@ -81,7 +81,7 @@ var buttonVariants = cva(
81
81
  }
82
82
  }
83
83
  );
84
- var Button = React30.forwardRef(
84
+ var Button = React31.forwardRef(
85
85
  (_a, ref) => {
86
86
  var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
87
87
  return /* @__PURE__ */ jsx(
@@ -310,10 +310,10 @@ function DialogDescription(_a) {
310
310
  }, props)
311
311
  );
312
312
  }
313
- var FloatingInput = React30.forwardRef(
313
+ var FloatingInput = React31.forwardRef(
314
314
  (_a, ref) => {
315
315
  var _b = _a, { label, error, id, className, required } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required"]);
316
- const inputId = id != null ? id : React30.useId();
316
+ const inputId = id != null ? id : React31.useId();
317
317
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
318
318
  /* @__PURE__ */ jsx(
319
319
  "input",
@@ -353,10 +353,10 @@ var FloatingInput = React30.forwardRef(
353
353
  }
354
354
  );
355
355
  FloatingInput.displayName = "FloatingInput";
356
- var FloatingSelect = React30.forwardRef(
356
+ var FloatingSelect = React31.forwardRef(
357
357
  (_a, ref) => {
358
358
  var _b = _a, { label, error, id, className, required, children, value } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required", "children", "value"]);
359
- const inputId = id != null ? id : React30.useId();
359
+ const inputId = id != null ? id : React31.useId();
360
360
  const hasValue = typeof value === "string" ? value !== "" : value !== void 0 && value !== null;
361
361
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
362
362
  /* @__PURE__ */ jsx(
@@ -620,11 +620,11 @@ function PhoneCountrySelect({
620
620
  disabled
621
621
  }) {
622
622
  var _a;
623
- const [open, setOpen] = React30.useState(false);
624
- const containerRef = React30.useRef(null);
625
- const listRef = React30.useRef(null);
623
+ const [open, setOpen] = React31.useState(false);
624
+ const containerRef = React31.useRef(null);
625
+ const listRef = React31.useRef(null);
626
626
  const selected = (_a = PHONE_COUNTRIES.find((c) => c.code === value)) != null ? _a : PHONE_COUNTRIES[0];
627
- React30.useEffect(() => {
627
+ React31.useEffect(() => {
628
628
  if (!open) return;
629
629
  const handler = (e) => {
630
630
  var _a2;
@@ -635,7 +635,7 @@ function PhoneCountrySelect({
635
635
  document.addEventListener("mousedown", handler);
636
636
  return () => document.removeEventListener("mousedown", handler);
637
637
  }, [open]);
638
- React30.useEffect(() => {
638
+ React31.useEffect(() => {
639
639
  if (!open || !listRef.current) return;
640
640
  const activeEl = listRef.current.querySelector("[data-selected=true]");
641
641
  activeEl == null ? void 0 : activeEl.scrollIntoView({ block: "nearest" });
@@ -905,8 +905,8 @@ function CalendarDayButton(_a) {
905
905
  "locale"
906
906
  ]);
907
907
  const defaultClassNames = getDefaultClassNames();
908
- const ref = React30.useRef(null);
909
- React30.useEffect(() => {
908
+ const ref = React31.useRef(null);
909
+ React31.useEffect(() => {
910
910
  var _a2;
911
911
  if (modifiers.focused) (_a2 = ref.current) == null ? void 0 : _a2.focus();
912
912
  }, [modifiers.focused]);
@@ -937,16 +937,16 @@ function BirthDateField({
937
937
  className,
938
938
  disabled
939
939
  }) {
940
- const [open, setOpen] = React30.useState(false);
941
- const [text, setText] = React30.useState(
940
+ const [open, setOpen] = React31.useState(false);
941
+ const [text, setText] = React31.useState(
942
942
  value ? format(value, "dd/MM/yyyy") : ""
943
943
  );
944
- const containerRef = React30.useRef(null);
945
- const inputId = React30.useId();
946
- React30.useEffect(() => {
944
+ const containerRef = React31.useRef(null);
945
+ const inputId = React31.useId();
946
+ React31.useEffect(() => {
947
947
  setText(value ? format(value, "dd/MM/yyyy") : "");
948
948
  }, [value]);
949
- React30.useEffect(() => {
949
+ React31.useEffect(() => {
950
950
  if (!open) return;
951
951
  const handler = (e) => {
952
952
  var _a;
@@ -1155,14 +1155,14 @@ function CountrySearchField({
1155
1155
  }) {
1156
1156
  var _a;
1157
1157
  const list = countries != null ? countries : COUNTRIES;
1158
- const [query, setQuery] = React30.useState("");
1159
- const [open, setOpen] = React30.useState(false);
1160
- const containerRef = React30.useRef(null);
1161
- const searchRef = React30.useRef(null);
1158
+ const [query, setQuery] = React31.useState("");
1159
+ const [open, setOpen] = React31.useState(false);
1160
+ const containerRef = React31.useRef(null);
1161
+ const searchRef = React31.useRef(null);
1162
1162
  const selected = list.find((c) => c.code === value);
1163
1163
  const isFloated = open || !!selected;
1164
1164
  const filtered = query.trim() ? list.filter((c) => c.name.toLowerCase().includes(query.toLowerCase())) : list;
1165
- React30.useEffect(() => {
1165
+ React31.useEffect(() => {
1166
1166
  if (!open) return;
1167
1167
  const handler = (e) => {
1168
1168
  var _a2;
@@ -1307,10 +1307,10 @@ function AdventureCard({
1307
1307
  }) {
1308
1308
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
1309
1309
  const isControlled = (_b = (_a = adventure.optionals) == null ? void 0 : _a.some((o) => o.onCheckedChange !== void 0)) != null ? _b : false;
1310
- const [checkedInternal, setCheckedInternal] = React30.useState(
1310
+ const [checkedInternal, setCheckedInternal] = React31.useState(
1311
1311
  new Set((_d = (_c = adventure.optionals) == null ? void 0 : _c.filter((o) => o.defaultChecked).map((o) => o.id)) != null ? _d : [])
1312
1312
  );
1313
- const [openDescriptionId, setOpenDescriptionId] = React30.useState(null);
1313
+ const [openDescriptionId, setOpenDescriptionId] = React31.useState(null);
1314
1314
  const openDescriptionOptional = openDescriptionId ? (_e = adventure.optionals) == null ? void 0 : _e.find((o) => o.id === openDescriptionId) : void 0;
1315
1315
  const isChecked = (opt) => {
1316
1316
  var _a2;
@@ -1740,7 +1740,7 @@ function BookingShell({
1740
1740
  return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
1741
1741
  /* @__PURE__ */ jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
1742
1742
  /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: title }),
1743
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React30.Fragment, { children: [
1743
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React31.Fragment, { children: [
1744
1744
  /* @__PURE__ */ jsx(
1745
1745
  "span",
1746
1746
  {
@@ -1939,7 +1939,7 @@ function TermsSection({
1939
1939
  termsContent
1940
1940
  }) {
1941
1941
  var _a;
1942
- const [modalOpen, setModalOpen] = React30.useState(false);
1942
+ const [modalOpen, setModalOpen] = React31.useState(false);
1943
1943
  const i18n = (_a = TERMS_I18N[locale]) != null ? _a : TERMS_I18N.en;
1944
1944
  return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1945
1945
  /* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: title }),
@@ -2077,9 +2077,9 @@ function BookingWizard({
2077
2077
  }) {
2078
2078
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T;
2079
2079
  const wizardSteps = WIZARD_STEPS_FN(labels);
2080
- const [step, setStep] = React30.useState("responsible");
2081
- const [error, setError] = React30.useState(null);
2082
- const [responsible, setResponsible] = React30.useState({
2080
+ const [step, setStep] = React31.useState("responsible");
2081
+ const [error, setError] = React31.useState(null);
2082
+ const [responsible, setResponsible] = React31.useState({
2083
2083
  firstName: "",
2084
2084
  lastName: "",
2085
2085
  email: "",
@@ -2098,7 +2098,7 @@ function BookingWizard({
2098
2098
  return s + ((_b2 = (_a2 = a.slots) == null ? void 0 : _a2.children) != null ? _b2 : 0);
2099
2099
  }, 0);
2100
2100
  const totalPax = totalAdults + totalChildren;
2101
- const [travellers, setTravellers] = React30.useState(
2101
+ const [travellers, setTravellers] = React31.useState(
2102
2102
  Array.from({ length: Math.max(totalPax, 1) }, () => ({
2103
2103
  firstName: "",
2104
2104
  lastName: "",
@@ -2106,9 +2106,9 @@ function BookingWizard({
2106
2106
  email: ""
2107
2107
  }))
2108
2108
  );
2109
- const [payAmount, setPayAmount] = React30.useState("full");
2110
- const [payMethod, setPayMethod] = React30.useState("stripe");
2111
- const [termsAccepted, setTermsAccepted] = React30.useState(false);
2109
+ const [payAmount, setPayAmount] = React31.useState("full");
2110
+ const [payMethod, setPayMethod] = React31.useState("stripe");
2111
+ const [termsAccepted, setTermsAccepted] = React31.useState(false);
2112
2112
  const setR = (k, v) => setResponsible((p) => __spreadProps(__spreadValues({}, p), { [k]: v }));
2113
2113
  const setT = (i, k, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { [k]: v }) : t));
2114
2114
  const setTDob = (i, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { dateOfBirth: v }) : t));
@@ -2336,7 +2336,7 @@ function Offer({
2336
2336
  className
2337
2337
  }) {
2338
2338
  var _a, _b, _c;
2339
- const [showBooking, setShowBooking] = React30.useState(false);
2339
+ const [showBooking, setShowBooking] = React31.useState(false);
2340
2340
  const isShowingCheckout = !confirmedState && (!!checkoutSlot || internalDemoCheckout && showBooking);
2341
2341
  const handleBook = () => {
2342
2342
  if (!checkoutSlot && !externalBookingFlow && internalDemoCheckout) {
@@ -2703,7 +2703,7 @@ function AdventureSection({
2703
2703
  labels
2704
2704
  }) {
2705
2705
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
2706
- const [detailsOpen, setDetailsOpen] = React30.useState(false);
2706
+ const [detailsOpen, setDetailsOpen] = React31.useState(false);
2707
2707
  const handleCopyUrl = (url) => {
2708
2708
  if (onCopyFormLink) {
2709
2709
  onCopyFormLink(url);
@@ -3216,8 +3216,8 @@ function AddTravellerDialog({
3216
3216
  errorMessage
3217
3217
  }) {
3218
3218
  var _a, _b, _c, _d, _e;
3219
- const [form, setForm] = React30.useState(() => createInitialAddFormData(config));
3220
- React30.useEffect(() => {
3219
+ const [form, setForm] = React31.useState(() => createInitialAddFormData(config));
3220
+ React31.useEffect(() => {
3221
3221
  if (open) {
3222
3222
  setForm(createInitialAddFormData(config));
3223
3223
  }
@@ -3277,7 +3277,7 @@ function EditTravellerDialog({
3277
3277
  errorMessage
3278
3278
  }) {
3279
3279
  var _a, _b, _c, _d, _e;
3280
- const [form, setForm] = React30.useState(() => ({
3280
+ const [form, setForm] = React31.useState(() => ({
3281
3281
  firstName: "",
3282
3282
  lastName: "",
3283
3283
  email: "",
@@ -3286,7 +3286,7 @@ function EditTravellerDialog({
3286
3286
  birthDate: "",
3287
3287
  personType: "ADULT"
3288
3288
  }));
3289
- React30.useEffect(() => {
3289
+ React31.useEffect(() => {
3290
3290
  var _a2, _b2, _c2, _d2, _e2, _f;
3291
3291
  if (open && traveller) {
3292
3292
  setForm({
@@ -3622,48 +3622,48 @@ function BookingDetails({
3622
3622
  const hasSubmitAddTraveller = !!onSubmitAddTraveller;
3623
3623
  const hasSubmitEditTraveller = !!onSubmitEditTraveller;
3624
3624
  const hasConfirmRemoveTraveller = !!onConfirmRemoveTraveller;
3625
- const [addModalState, setAddModalState] = React30.useState({
3625
+ const [addModalState, setAddModalState] = React31.useState({
3626
3626
  open: false,
3627
3627
  adventureId: null
3628
3628
  });
3629
- const [editModalState, setEditModalState] = React30.useState({ open: false, adventureId: null, traveller: null });
3630
- const [deleteModalState, setDeleteModalState] = React30.useState({ open: false, adventureId: null, traveller: null });
3631
- const [resendInviteDialogState, setResendInviteDialogState] = React30.useState({ open: false, traveller: null });
3632
- const handleRequestOpenAddModal = React30.useCallback((adventureId) => {
3629
+ const [editModalState, setEditModalState] = React31.useState({ open: false, adventureId: null, traveller: null });
3630
+ const [deleteModalState, setDeleteModalState] = React31.useState({ open: false, adventureId: null, traveller: null });
3631
+ const [resendInviteDialogState, setResendInviteDialogState] = React31.useState({ open: false, traveller: null });
3632
+ const handleRequestOpenAddModal = React31.useCallback((adventureId) => {
3633
3633
  setAddModalState({ open: true, adventureId });
3634
3634
  }, []);
3635
- const handleRequestOpenEditModal = React30.useCallback(
3635
+ const handleRequestOpenEditModal = React31.useCallback(
3636
3636
  (adventureId, traveller) => {
3637
3637
  setEditModalState({ open: true, adventureId, traveller });
3638
3638
  },
3639
3639
  []
3640
3640
  );
3641
- const handleRequestOpenDeleteModal = React30.useCallback(
3641
+ const handleRequestOpenDeleteModal = React31.useCallback(
3642
3642
  (adventureId, traveller) => {
3643
3643
  setDeleteModalState({ open: true, adventureId, traveller });
3644
3644
  },
3645
3645
  []
3646
3646
  );
3647
- const handleRequestOpenResendInviteDialog = React30.useCallback(
3647
+ const handleRequestOpenResendInviteDialog = React31.useCallback(
3648
3648
  (traveller) => {
3649
3649
  setResendInviteDialogState({ open: true, traveller });
3650
3650
  },
3651
3651
  []
3652
3652
  );
3653
- const closeAddModal = React30.useCallback(() => {
3653
+ const closeAddModal = React31.useCallback(() => {
3654
3654
  setAddModalState({ open: false, adventureId: null });
3655
3655
  }, []);
3656
- const closeEditModal = React30.useCallback(() => {
3656
+ const closeEditModal = React31.useCallback(() => {
3657
3657
  setEditModalState({ open: false, adventureId: null, traveller: null });
3658
3658
  }, []);
3659
- const closeDeleteModal = React30.useCallback(() => {
3659
+ const closeDeleteModal = React31.useCallback(() => {
3660
3660
  setDeleteModalState({ open: false, adventureId: null, traveller: null });
3661
3661
  }, []);
3662
- const closeResendInviteDialog = React30.useCallback(() => {
3662
+ const closeResendInviteDialog = React31.useCallback(() => {
3663
3663
  setResendInviteDialogState({ open: false, traveller: null });
3664
3664
  }, []);
3665
- const submitInFlightRef = React30.useRef(false);
3666
- const handleAddSubmit = React30.useCallback(
3665
+ const submitInFlightRef = React31.useRef(false);
3666
+ const handleAddSubmit = React31.useCallback(
3667
3667
  async (adventureId, data) => {
3668
3668
  if (!onSubmitAddTraveller) return;
3669
3669
  if (submitInFlightRef.current) return;
@@ -3678,7 +3678,7 @@ function BookingDetails({
3678
3678
  },
3679
3679
  [onSubmitAddTraveller, closeAddModal]
3680
3680
  );
3681
- const handleEditSubmit = React30.useCallback(
3681
+ const handleEditSubmit = React31.useCallback(
3682
3682
  async (adventureId, travellerId, data) => {
3683
3683
  if (!onSubmitEditTraveller) return;
3684
3684
  if (submitInFlightRef.current) return;
@@ -3693,7 +3693,7 @@ function BookingDetails({
3693
3693
  },
3694
3694
  [onSubmitEditTraveller, closeEditModal]
3695
3695
  );
3696
- const handleDeleteConfirm = React30.useCallback(
3696
+ const handleDeleteConfirm = React31.useCallback(
3697
3697
  async (adventureId, travellerId) => {
3698
3698
  if (!onConfirmRemoveTraveller) return;
3699
3699
  if (submitInFlightRef.current) return;
@@ -5269,7 +5269,7 @@ function BookingCreatedEmail({
5269
5269
  }, children: i + 1 }) }),
5270
5270
  /* @__PURE__ */ jsx("td", { style: { verticalAlign: "top" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "14px", color: emailTokens.bodyText, lineHeight: "1.6", margin: 0 }, children: step }) })
5271
5271
  ] }) }) }, i)) }),
5272
- nextStepsImportant && nextStepsImportant.trim().length > 0 && /* @__PURE__ */ jsx("p", { style: { marginBottom: "32px", fontSize: "14px", color: emailTokens.foreground, lineHeight: "1.6" }, children: nextStepsImportant.split("\n").map((line, idx, arr) => /* @__PURE__ */ jsxs(React30.Fragment, { children: [
5272
+ nextStepsImportant && nextStepsImportant.trim().length > 0 && /* @__PURE__ */ jsx("p", { style: { marginBottom: "32px", fontSize: "14px", color: emailTokens.foreground, lineHeight: "1.6" }, children: nextStepsImportant.split("\n").map((line, idx, arr) => /* @__PURE__ */ jsxs(React31.Fragment, { children: [
5273
5273
  idx === 0 ? /* @__PURE__ */ jsx("strong", { children: line }) : line,
5274
5274
  idx < arr.length - 1 ? /* @__PURE__ */ jsx("br", {}) : null
5275
5275
  ] }, idx)) })
@@ -7289,11 +7289,11 @@ function DatePickerField({
7289
7289
  fromDate,
7290
7290
  className
7291
7291
  }) {
7292
- const [open, setOpen] = React30.useState(false);
7293
- const containerRef = React30.useRef(null);
7294
- const [calendarWidth, setCalendarWidth] = React30.useState();
7292
+ const [open, setOpen] = React31.useState(false);
7293
+ const containerRef = React31.useRef(null);
7294
+ const [calendarWidth, setCalendarWidth] = React31.useState();
7295
7295
  const hasValue = !!value;
7296
- React30.useEffect(() => {
7296
+ React31.useEffect(() => {
7297
7297
  if (!containerRef.current) return;
7298
7298
  const observer = new ResizeObserver(([entry]) => {
7299
7299
  setCalendarWidth(entry.contentRect.width);
@@ -7402,7 +7402,7 @@ function BookingForm({
7402
7402
  subtitle = "Free enquiry \u2013 no commitment",
7403
7403
  className
7404
7404
  }) {
7405
- const [values, setValues] = React30.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
7405
+ const [values, setValues] = React31.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
7406
7406
  const set = (key, value) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [key]: value }));
7407
7407
  const handleSubmit = (e) => {
7408
7408
  e.preventDefault();
@@ -7970,11 +7970,11 @@ function FloatingTextarea({
7970
7970
  }
7971
7971
  function SelectField({ field, value, onChange, error, disabled }) {
7972
7972
  var _a, _b, _c;
7973
- const [open, setOpen] = React30.useState(false);
7974
- const containerRef = React30.useRef(null);
7973
+ const [open, setOpen] = React31.useState(false);
7974
+ const containerRef = React31.useRef(null);
7975
7975
  const options = (_a = field.options) != null ? _a : [];
7976
7976
  const selectedOpt = (_b = options.find((o) => o.value === value)) != null ? _b : null;
7977
- React30.useEffect(() => {
7977
+ React31.useEffect(() => {
7978
7978
  if (!open) return;
7979
7979
  const handleOutside = (e) => {
7980
7980
  if (containerRef.current && !containerRef.current.contains(e.target)) {
@@ -8439,11 +8439,11 @@ function RegistrationForm({
8439
8439
  readOnly = false
8440
8440
  }) {
8441
8441
  var _a;
8442
- const L = React30.useMemo(
8442
+ const L = React31.useMemo(
8443
8443
  () => __spreadValues(__spreadValues({}, DEFAULT_LABELS12), labels != null ? labels : {}),
8444
8444
  [labels]
8445
8445
  );
8446
- const sortedFields = React30.useMemo(
8446
+ const sortedFields = React31.useMemo(
8447
8447
  () => [...fields].sort((a, b) => {
8448
8448
  var _a2, _b;
8449
8449
  return ((_a2 = a.order) != null ? _a2 : 0) - ((_b = b.order) != null ? _b : 0);
@@ -8451,7 +8451,7 @@ function RegistrationForm({
8451
8451
  [fields]
8452
8452
  );
8453
8453
  const isControlled = values !== void 0;
8454
- const [internal, setInternal] = React30.useState(
8454
+ const [internal, setInternal] = React31.useState(
8455
8455
  () => initializeValues(
8456
8456
  sortedFields,
8457
8457
  defaultValues != null ? defaultValues : {},
@@ -8459,9 +8459,9 @@ function RegistrationForm({
8459
8459
  includeTerms
8460
8460
  )
8461
8461
  );
8462
- const [submitAttempted, setSubmitAttempted] = React30.useState(false);
8463
- const [validationErrors, setValidationErrors] = React30.useState({});
8464
- React30.useEffect(() => {
8462
+ const [submitAttempted, setSubmitAttempted] = React31.useState(false);
8463
+ const [validationErrors, setValidationErrors] = React31.useState({});
8464
+ React31.useEffect(() => {
8465
8465
  if (isControlled) return;
8466
8466
  setInternal((prev) => {
8467
8467
  const next = initializeValues(
@@ -8518,7 +8518,7 @@ function RegistrationForm({
8518
8518
  const termsError = submitAttempted && termsEnabled && !termsAccepted;
8519
8519
  const firstErrorFieldId = Object.keys(fieldErrors)[0];
8520
8520
  const scrollTargetId = firstErrorFieldId ? `rf-${firstErrorFieldId}` : termsError ? "rf-terms" : null;
8521
- React30.useEffect(() => {
8521
+ React31.useEffect(() => {
8522
8522
  if (!submitAttempted || !scrollTargetId) return;
8523
8523
  const timer = setTimeout(() => {
8524
8524
  const elem = document.getElementById(scrollTargetId);
@@ -8980,10 +8980,10 @@ var OTPCodeInput = ({
8980
8980
  id,
8981
8981
  required
8982
8982
  }) => {
8983
- const baseId = id != null ? id : React30.useId();
8984
- const inputRef = React30.useRef(null);
8985
- const [focused, setFocused] = React30.useState(false);
8986
- const digits = React30.useMemo(() => {
8983
+ const baseId = id != null ? id : React31.useId();
8984
+ const inputRef = React31.useRef(null);
8985
+ const [focused, setFocused] = React31.useState(false);
8986
+ const digits = React31.useMemo(() => {
8987
8987
  const arr = value.split("").slice(0, length);
8988
8988
  while (arr.length < length) arr.push("");
8989
8989
  return arr;
@@ -9096,7 +9096,7 @@ function Checkbox(_a) {
9096
9096
  })
9097
9097
  );
9098
9098
  }
9099
- var AccordionVariantContext = React30.createContext("default");
9099
+ var AccordionVariantContext = React31.createContext("default");
9100
9100
  function Accordion(_a) {
9101
9101
  var _b = _a, { className, variant = "default" } = _b, props = __objRest(_b, ["className", "variant"]);
9102
9102
  return /* @__PURE__ */ jsx(AccordionVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
@@ -9114,7 +9114,7 @@ function Accordion(_a) {
9114
9114
  }
9115
9115
  function AccordionItem(_a) {
9116
9116
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
9117
- const variant = React30.useContext(AccordionVariantContext);
9117
+ const variant = React31.useContext(AccordionVariantContext);
9118
9118
  return /* @__PURE__ */ jsx(
9119
9119
  Accordion$1.Item,
9120
9120
  __spreadValues({
@@ -9135,7 +9135,7 @@ function AccordionTrigger(_a) {
9135
9135
  "className",
9136
9136
  "children"
9137
9137
  ]);
9138
- const variant = React30.useContext(AccordionVariantContext);
9138
+ const variant = React31.useContext(AccordionVariantContext);
9139
9139
  return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
9140
9140
  Accordion$1.Trigger,
9141
9141
  __spreadProps(__spreadValues({
@@ -9189,7 +9189,7 @@ function AccordionContent(_a) {
9189
9189
  "className",
9190
9190
  "children"
9191
9191
  ]);
9192
- const variant = React30.useContext(AccordionVariantContext);
9192
+ const variant = React31.useContext(AccordionVariantContext);
9193
9193
  return /* @__PURE__ */ jsx(
9194
9194
  Accordion$1.Panel,
9195
9195
  __spreadProps(__spreadValues({
@@ -9407,15 +9407,15 @@ function FilterPanel({
9407
9407
  onSortChange
9408
9408
  }) {
9409
9409
  var _a, _b;
9410
- const resolvedGroups = React30.useMemo(() => resolveGroups(groups), [groups]);
9411
- const [internalValue, setInternalValue] = React30.useState(
9410
+ const resolvedGroups = React31.useMemo(() => resolveGroups(groups), [groups]);
9411
+ const [internalValue, setInternalValue] = React31.useState(
9412
9412
  () => Object.fromEntries(groups.map((g) => [g.id, []]))
9413
9413
  );
9414
9414
  const selected = value != null ? value : internalValue;
9415
- const [expandedItems, setExpandedItems] = React30.useState(
9415
+ const [expandedItems, setExpandedItems] = React31.useState(
9416
9416
  () => new Set(groups.flatMap((g) => getDefaultExpandedIds(g.items)))
9417
9417
  );
9418
- const toggleExpanded = React30.useCallback((id) => {
9418
+ const toggleExpanded = React31.useCallback((id) => {
9419
9419
  setExpandedItems((prev) => {
9420
9420
  const next = new Set(prev);
9421
9421
  if (next.has(id)) next.delete(id);
@@ -9799,11 +9799,11 @@ function FilterPanel({
9799
9799
  var TRUSTPILOT_SCRIPT_SRC = "https://widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js";
9800
9800
  function TrustpilotEmbed({ config }) {
9801
9801
  var _a, _b, _c, _d, _e, _f;
9802
- const ref = React30.useRef(null);
9803
- const [widgetReady, setWidgetReady] = React30.useState(false);
9804
- const [delayPassed, setDelayPassed] = React30.useState(false);
9802
+ const ref = React31.useRef(null);
9803
+ const [widgetReady, setWidgetReady] = React31.useState(false);
9804
+ const [delayPassed, setDelayPassed] = React31.useState(false);
9805
9805
  const showFallback = delayPassed && !widgetReady;
9806
- React30.useEffect(() => {
9806
+ React31.useEffect(() => {
9807
9807
  var _a2;
9808
9808
  if (typeof document === "undefined" || !ref.current) return;
9809
9809
  const node = ref.current;
@@ -9990,6 +9990,55 @@ function webpVariantUrl(src) {
9990
9990
  const withoutQuery = query ? src.slice(0, -query.length) : src;
9991
9991
  return `${withoutQuery}.webp${query}`;
9992
9992
  }
9993
+ function PictureLoader() {
9994
+ const gradientId = React31.useId();
9995
+ return /* @__PURE__ */ jsx(
9996
+ "span",
9997
+ {
9998
+ "aria-hidden": true,
9999
+ className: "pointer-events-none absolute inset-0 flex items-center justify-center",
10000
+ children: /* @__PURE__ */ jsxs(
10001
+ "svg",
10002
+ {
10003
+ viewBox: "0 0 200 200",
10004
+ xmlns: "http://www.w3.org/2000/svg",
10005
+ className: "h-10 w-10 text-primary",
10006
+ fill: "none",
10007
+ children: [
10008
+ /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, children: [
10009
+ /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "currentColor", stopOpacity: "0" }),
10010
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "currentColor" })
10011
+ ] }),
10012
+ /* @__PURE__ */ jsx(
10013
+ "circle",
10014
+ {
10015
+ stroke: `url(#${gradientId})`,
10016
+ strokeWidth: "15",
10017
+ strokeLinecap: "round",
10018
+ strokeDasharray: "0 44 0 44 0 44 0 44 0 360",
10019
+ cx: "100",
10020
+ cy: "100",
10021
+ r: "70",
10022
+ style: { transformOrigin: "center" },
10023
+ children: /* @__PURE__ */ jsx(
10024
+ "animateTransform",
10025
+ {
10026
+ type: "rotate",
10027
+ attributeName: "transform",
10028
+ calcMode: "discrete",
10029
+ dur: "2s",
10030
+ values: "360;324;288;252;216;180;144;108;72;36",
10031
+ repeatCount: "indefinite"
10032
+ }
10033
+ )
10034
+ }
10035
+ )
10036
+ ]
10037
+ }
10038
+ )
10039
+ }
10040
+ );
10041
+ }
9993
10042
  var PLACEHOLDER_SRC = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
9994
10043
  function Picture(_a) {
9995
10044
  var _b = _a, {
@@ -9998,18 +10047,23 @@ function Picture(_a) {
9998
10047
  eager = false,
9999
10048
  rootMargin = "200px",
10000
10049
  decoding,
10001
- loading
10050
+ loading,
10051
+ onLoad,
10052
+ onError
10002
10053
  } = _b, imgProps = __objRest(_b, [
10003
10054
  "src",
10004
10055
  "extraSources",
10005
10056
  "eager",
10006
10057
  "rootMargin",
10007
10058
  "decoding",
10008
- "loading"
10059
+ "loading",
10060
+ "onLoad",
10061
+ "onError"
10009
10062
  ]);
10010
- const ref = React30.useRef(null);
10011
- const [visible, setVisible] = React30.useState(eager);
10012
- React30.useEffect(() => {
10063
+ const ref = React31.useRef(null);
10064
+ const [visible, setVisible] = React31.useState(eager);
10065
+ const [loaded, setLoaded] = React31.useState(false);
10066
+ React31.useEffect(() => {
10013
10067
  if (eager || visible) return;
10014
10068
  const el = ref.current;
10015
10069
  if (!el || typeof IntersectionObserver === "undefined") {
@@ -10028,35 +10082,57 @@ function Picture(_a) {
10028
10082
  io.observe(el);
10029
10083
  return () => io.disconnect();
10030
10084
  }, [eager, visible, rootMargin]);
10085
+ React31.useEffect(() => {
10086
+ setLoaded(false);
10087
+ }, [src]);
10031
10088
  const webp = webpVariantUrl(src);
10032
10089
  const realSrc = visible ? src : PLACEHOLDER_SRC;
10033
10090
  const decodingResolved = decoding != null ? decoding : eager ? void 0 : "async";
10091
+ const handleLoad = (e) => {
10092
+ if (visible) setLoaded(true);
10093
+ onLoad == null ? void 0 : onLoad(e);
10094
+ };
10095
+ const handleError = (e) => {
10096
+ if (visible) setLoaded(true);
10097
+ onError == null ? void 0 : onError(e);
10098
+ };
10099
+ const showLoader = visible && !loaded;
10034
10100
  if (!webp) {
10035
- return /* @__PURE__ */ jsx(
10036
- "img",
10037
- __spreadValues({
10038
- ref,
10039
- src: realSrc,
10040
- "data-src": visible ? void 0 : src,
10041
- decoding: decodingResolved,
10042
- loading: loading != null ? loading : eager ? void 0 : "lazy"
10043
- }, imgProps)
10044
- );
10101
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
10102
+ showLoader && /* @__PURE__ */ jsx(PictureLoader, {}),
10103
+ /* @__PURE__ */ jsx(
10104
+ "img",
10105
+ __spreadValues({
10106
+ ref,
10107
+ src: realSrc,
10108
+ "data-src": visible ? void 0 : src,
10109
+ decoding: decodingResolved,
10110
+ loading: loading != null ? loading : eager ? void 0 : "lazy",
10111
+ onLoad: handleLoad,
10112
+ onError: handleError
10113
+ }, imgProps)
10114
+ )
10115
+ ] });
10045
10116
  }
10046
- return /* @__PURE__ */ jsxs("picture", { style: { display: "contents" }, children: [
10047
- visible && /* @__PURE__ */ jsx("source", { srcSet: webp, type: "image/webp" }),
10048
- extraSources,
10049
- /* @__PURE__ */ jsx(
10050
- "img",
10051
- __spreadValues({
10052
- ref,
10053
- src: realSrc,
10054
- "data-src": visible ? void 0 : src,
10055
- "data-srcset-webp": visible ? void 0 : webp,
10056
- decoding: decodingResolved,
10057
- loading: loading != null ? loading : eager ? void 0 : "lazy"
10058
- }, imgProps)
10059
- )
10117
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
10118
+ showLoader && /* @__PURE__ */ jsx(PictureLoader, {}),
10119
+ /* @__PURE__ */ jsxs("picture", { style: { display: "contents" }, children: [
10120
+ visible && /* @__PURE__ */ jsx("source", { srcSet: webp, type: "image/webp" }),
10121
+ extraSources,
10122
+ /* @__PURE__ */ jsx(
10123
+ "img",
10124
+ __spreadValues({
10125
+ ref,
10126
+ src: realSrc,
10127
+ "data-src": visible ? void 0 : src,
10128
+ "data-srcset-webp": visible ? void 0 : webp,
10129
+ decoding: decodingResolved,
10130
+ loading: loading != null ? loading : eager ? void 0 : "lazy",
10131
+ onLoad: handleLoad,
10132
+ onError: handleError
10133
+ }, imgProps)
10134
+ )
10135
+ ] })
10060
10136
  ] });
10061
10137
  }
10062
10138
  function ItineraryDayCard({
@@ -10125,11 +10201,11 @@ function ItineraryModal({
10125
10201
  onNext
10126
10202
  }) {
10127
10203
  var _a, _b, _c;
10128
- const [imgIndex, setImgIndex] = React30.useState(0);
10204
+ const [imgIndex, setImgIndex] = React31.useState(0);
10129
10205
  const images = stop ? [stop.coverImage, ...(_a = stop.images) != null ? _a : []] : [];
10130
10206
  const isFirst = (stop == null ? void 0 : stop.dayNumber) === ((_b = allStops[0]) == null ? void 0 : _b.dayNumber);
10131
10207
  const isLast = (stop == null ? void 0 : stop.dayNumber) === ((_c = allStops[allStops.length - 1]) == null ? void 0 : _c.dayNumber);
10132
- React30.useEffect(() => {
10208
+ React31.useEffect(() => {
10133
10209
  setImgIndex(0);
10134
10210
  }, [stop == null ? void 0 : stop.dayNumber]);
10135
10211
  if (!stop) return null;
@@ -10256,8 +10332,8 @@ function ItineraryModal({
10256
10332
  ) });
10257
10333
  }
10258
10334
  function Itinerary({ title, subtitle, stops, className }) {
10259
- const [activeIndex, setActiveIndex] = React30.useState(null);
10260
- const scrollRef = React30.useRef(null);
10335
+ const [activeIndex, setActiveIndex] = React31.useState(null);
10336
+ const scrollRef = React31.useRef(null);
10261
10337
  const activeStop = activeIndex !== null ? stops[activeIndex] : null;
10262
10338
  const scrollBy = (dir) => {
10263
10339
  if (!scrollRef.current) return;
@@ -10349,18 +10425,18 @@ function Lightbox({
10349
10425
  onClose
10350
10426
  }) {
10351
10427
  var _a;
10352
- const [index, setIndex] = React30.useState(initialIndex);
10428
+ const [index, setIndex] = React31.useState(initialIndex);
10353
10429
  const total = photos.length;
10354
10430
  const photo = photos[index];
10355
- const prev = React30.useCallback(
10431
+ const prev = React31.useCallback(
10356
10432
  () => setIndex((i) => (i - 1 + total) % total),
10357
10433
  [total]
10358
10434
  );
10359
- const next = React30.useCallback(
10435
+ const next = React31.useCallback(
10360
10436
  () => setIndex((i) => (i + 1) % total),
10361
10437
  [total]
10362
10438
  );
10363
- React30.useEffect(() => {
10439
+ React31.useEffect(() => {
10364
10440
  const onKey = (e) => {
10365
10441
  if (e.key === "Escape") onClose();
10366
10442
  if (e.key === "ArrowLeft") prev();
@@ -10465,7 +10541,8 @@ function PhotoTile({
10465
10541
  photo,
10466
10542
  index,
10467
10543
  className,
10468
- onClick
10544
+ onClick,
10545
+ showCredit = false
10469
10546
  }) {
10470
10547
  var _a, _b;
10471
10548
  return /* @__PURE__ */ jsxs(
@@ -10488,7 +10565,8 @@ function PhotoTile({
10488
10565
  loading: "lazy"
10489
10566
  }
10490
10567
  ),
10491
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-300 flex items-center justify-center", children: /* @__PURE__ */ jsx(ZoomInIcon, { className: "h-8 w-8 text-white opacity-0 group-hover:opacity-100 transition-opacity duration-300 drop-shadow-lg" }) })
10568
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-300 flex items-center justify-center", children: /* @__PURE__ */ jsx(ZoomInIcon, { className: "h-8 w-8 text-white opacity-0 group-hover:opacity-100 transition-opacity duration-300 drop-shadow-lg" }) }),
10569
+ showCredit && photo.credit && /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute bottom-2 right-2.5 text-[11px] font-ui text-white/90 [text-shadow:0_1px_3px_rgba(0,0,0,0.7)]", children: photo.credit })
10492
10570
  ]
10493
10571
  }
10494
10572
  );
@@ -10526,7 +10604,7 @@ function GridGallery({
10526
10604
  initialVisible,
10527
10605
  onOpen
10528
10606
  }) {
10529
- const [expanded, setExpanded] = React30.useState(false);
10607
+ const [expanded, setExpanded] = React31.useState(false);
10530
10608
  const cols = gridCols(photos.length);
10531
10609
  const hasMore = photos.length > initialVisible;
10532
10610
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
@@ -10556,7 +10634,7 @@ function CompactGridGallery({
10556
10634
  initialVisible,
10557
10635
  onOpen
10558
10636
  }) {
10559
- const [expanded, setExpanded] = React30.useState(false);
10637
+ const [expanded, setExpanded] = React31.useState(false);
10560
10638
  const hasMore = photos.length > initialVisible;
10561
10639
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
10562
10640
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -10585,7 +10663,7 @@ function MasonryGallery({
10585
10663
  initialVisible,
10586
10664
  onOpen
10587
10665
  }) {
10588
- const [expanded, setExpanded] = React30.useState(false);
10666
+ const [expanded, setExpanded] = React31.useState(false);
10589
10667
  const hasMore = photos.length > initialVisible;
10590
10668
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
10591
10669
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -10658,7 +10736,7 @@ function FeaturedGallery({
10658
10736
  photos,
10659
10737
  onOpen
10660
10738
  }) {
10661
- const [expanded, setExpanded] = React30.useState(false);
10739
+ const [expanded, setExpanded] = React31.useState(false);
10662
10740
  const featured = photos.slice(0, 3);
10663
10741
  const extra = photos.slice(3);
10664
10742
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -10728,6 +10806,37 @@ function FeaturedGallery({
10728
10806
  )
10729
10807
  ] });
10730
10808
  }
10809
+ function CollageGallery({
10810
+ photos,
10811
+ onOpen,
10812
+ seamless = false
10813
+ }) {
10814
+ const [hero, ...rest] = photos;
10815
+ const gap = seamless ? "gap-0" : "gap-1.5";
10816
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", gap), children: [
10817
+ hero && /* @__PURE__ */ jsx(
10818
+ PhotoTile,
10819
+ {
10820
+ photo: hero,
10821
+ index: 0,
10822
+ className: "aspect-[16/10] sm:aspect-[2/1]",
10823
+ onClick: () => onOpen(0),
10824
+ showCredit: true
10825
+ }
10826
+ ),
10827
+ rest.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-2", gap), children: rest.map((p, i) => /* @__PURE__ */ jsx(
10828
+ PhotoTile,
10829
+ {
10830
+ photo: p,
10831
+ index: i + 1,
10832
+ className: "aspect-[4/3]",
10833
+ onClick: () => onOpen(i + 1),
10834
+ showCredit: true
10835
+ },
10836
+ i + 1
10837
+ )) })
10838
+ ] });
10839
+ }
10731
10840
  function CarouselGallery({
10732
10841
  photos,
10733
10842
  index,
@@ -10825,9 +10934,9 @@ function PhotoGallery({
10825
10934
  onPhotoClick,
10826
10935
  className
10827
10936
  }) {
10828
- const [lightboxIndex, setLightboxIndex] = React30.useState(null);
10829
- const [carouselIndex, setCarouselIndex] = React30.useState(0);
10830
- const normalised = React30.useMemo(() => photos.map(normalise), [photos]);
10937
+ const [lightboxIndex, setLightboxIndex] = React31.useState(null);
10938
+ const [carouselIndex, setCarouselIndex] = React31.useState(0);
10939
+ const normalised = React31.useMemo(() => photos.map(normalise), [photos]);
10831
10940
  const handleOpen = (index) => {
10832
10941
  setLightboxIndex(index);
10833
10942
  onPhotoClick == null ? void 0 : onPhotoClick(normalised[index].src, index);
@@ -10887,6 +10996,8 @@ function PhotoGallery({
10887
10996
  ),
10888
10997
  variant === "filmstrip" && /* @__PURE__ */ jsx(FilmstripGallery, { photos: normalised, onOpen: handleOpen }),
10889
10998
  variant === "featured" && /* @__PURE__ */ jsx(FeaturedGallery, { photos: normalised, onOpen: handleOpen }),
10999
+ variant === "collage" && /* @__PURE__ */ jsx(CollageGallery, { photos: normalised, onOpen: handleOpen }),
11000
+ variant === "collageTight" && /* @__PURE__ */ jsx(CollageGallery, { photos: normalised, onOpen: handleOpen, seamless: true }),
10890
11001
  lightbox
10891
11002
  ] });
10892
11003
  }
@@ -10911,7 +11022,7 @@ function ItineraryDay({
10911
11022
  photoLayout = "rounded",
10912
11023
  className
10913
11024
  }) {
10914
- const photoList = React30.useMemo(() => normalisePhotos(photos), [photos]);
11025
+ const photoList = React31.useMemo(() => normalisePhotos(photos), [photos]);
10915
11026
  const isFullBleed = photoLayout === "fullBleed" || photoLayout === "fullBleedBottom";
10916
11027
  const photoPosition = photoLayout === "fullBleedBottom" ? "bottom" : "top";
10917
11028
  const gallery = photoList.length > 0 && /* @__PURE__ */ jsx(
@@ -10966,8 +11077,8 @@ function MenuTrip({
10966
11077
  bold = true,
10967
11078
  className
10968
11079
  }) {
10969
- const scrollRef = React30.useRef(null);
10970
- React30.useEffect(() => {
11080
+ const scrollRef = React31.useRef(null);
11081
+ React31.useEffect(() => {
10971
11082
  if (!scrollRef.current || !activeSection) return;
10972
11083
  const container = scrollRef.current;
10973
11084
  const btn = container.querySelector(
@@ -11163,8 +11274,8 @@ function PricingTrip({
11163
11274
  className
11164
11275
  }) {
11165
11276
  const rOuter = sharp ? "rounded-none" : "rounded-2xl";
11166
- const [showEstimates, setShowEstimates] = React30.useState(false);
11167
- const [showPriceInfo, setShowPriceInfo] = React30.useState(false);
11277
+ const [showEstimates, setShowEstimates] = React31.useState(false);
11278
+ const [showPriceInfo, setShowPriceInfo] = React31.useState(false);
11168
11279
  if (variant === "compact") {
11169
11280
  const showOverlay = showPriceInfo && (!!priceInfo || !!currencyEstimates && currencyEstimates.length > 0);
11170
11281
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
@@ -11604,14 +11715,14 @@ function SiteHeader({
11604
11715
  }) {
11605
11716
  const t = VARIANT[variant];
11606
11717
  const resolvedLogo = logoSrc != null ? logoSrc : variant === "white" ? logoSrcDark : logoSrcLight;
11607
- const [openMenu, setOpenMenu] = React30.useState(null);
11608
- const [langOpen, setLangOpen] = React30.useState(false);
11609
- const [mobileOpen, setMobileOpen] = React30.useState(false);
11610
- const [openMobileSection, setOpenMobileSection] = React30.useState(null);
11611
- const [activeLang, setActiveLang] = React30.useState(currentLanguage);
11718
+ const [openMenu, setOpenMenu] = React31.useState(null);
11719
+ const [langOpen, setLangOpen] = React31.useState(false);
11720
+ const [mobileOpen, setMobileOpen] = React31.useState(false);
11721
+ const [openMobileSection, setOpenMobileSection] = React31.useState(null);
11722
+ const [activeLang, setActiveLang] = React31.useState(currentLanguage);
11612
11723
  const toggleMobileSection = (label) => setOpenMobileSection((prev) => prev === label ? null : label);
11613
- const menuCloseTimer = React30.useRef(void 0);
11614
- const langCloseTimer = React30.useRef(void 0);
11724
+ const menuCloseTimer = React31.useRef(void 0);
11725
+ const langCloseTimer = React31.useRef(void 0);
11615
11726
  const handleMenuEnter = (label) => {
11616
11727
  clearTimeout(menuCloseTimer.current);
11617
11728
  setOpenMenu(label);
@@ -11632,7 +11743,7 @@ function SiteHeader({
11632
11743
  setOpenMenu(null);
11633
11744
  setLangOpen(false);
11634
11745
  };
11635
- React30.useEffect(() => () => {
11746
+ React31.useEffect(() => () => {
11636
11747
  clearTimeout(menuCloseTimer.current);
11637
11748
  clearTimeout(langCloseTimer.current);
11638
11749
  }, []);
@@ -11908,7 +12019,7 @@ function SiteHeader({
11908
12019
  ), children: [
11909
12020
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: languages.map((lang, i) => {
11910
12021
  const isActive = lang.code === activeLang;
11911
- return /* @__PURE__ */ jsxs(React30.Fragment, { children: [
12022
+ return /* @__PURE__ */ jsxs(React31.Fragment, { children: [
11912
12023
  i > 0 && /* @__PURE__ */ jsx("span", { className: cn(
11913
12024
  "text-xs select-none",
11914
12025
  variant === "white" ? "text-border" : "text-white/15"
@@ -11970,8 +12081,8 @@ function SiteHeader({
11970
12081
  );
11971
12082
  }
11972
12083
  function ThemeToggle({ className }) {
11973
- const [dark, setDark] = React30.useState(false);
11974
- React30.useEffect(() => {
12084
+ const [dark, setDark] = React31.useState(false);
12085
+ React31.useEffect(() => {
11975
12086
  const saved = localStorage.getItem("theme");
11976
12087
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
11977
12088
  const isDark = saved === "dark" || !saved && prefersDark;
@@ -12021,7 +12132,7 @@ var chipVariants = cva(
12021
12132
  }
12022
12133
  }
12023
12134
  );
12024
- var Chip = React30.forwardRef(function Chip2(_a, ref) {
12135
+ var Chip = React31.forwardRef(function Chip2(_a, ref) {
12025
12136
  var _b = _a, { className, variant, size, href, children } = _b, props = __objRest(_b, ["className", "variant", "size", "href", "children"]);
12026
12137
  const classes = cn(chipVariants({ variant, size }), className);
12027
12138
  if (href) {
@@ -12123,7 +12234,7 @@ function TripCardEditorial(props) {
12123
12234
  tag,
12124
12235
  tagHref
12125
12236
  } = props;
12126
- const [internalFav, setInternalFav] = React30.useState(false);
12237
+ const [internalFav, setInternalFav] = React31.useState(false);
12127
12238
  const favorited = favoritedProp != null ? favoritedProp : internalFav;
12128
12239
  const handleFav = (e) => {
12129
12240
  e.preventDefault();
@@ -12308,8 +12419,387 @@ function TripCard(props) {
12308
12419
  }
12309
12420
  );
12310
12421
  }
12422
+ function ArrowIcon2() {
12423
+ return /* @__PURE__ */ jsxs(
12424
+ "svg",
12425
+ {
12426
+ width: "13",
12427
+ height: "13",
12428
+ viewBox: "0 0 24 24",
12429
+ fill: "none",
12430
+ stroke: "currentColor",
12431
+ strokeWidth: "2.2",
12432
+ strokeLinecap: "round",
12433
+ strokeLinejoin: "round",
12434
+ children: [
12435
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
12436
+ /* @__PURE__ */ jsx("polyline", { points: "12 5 19 12 12 19" })
12437
+ ]
12438
+ }
12439
+ );
12440
+ }
12441
+ var sizeConfig2 = {
12442
+ sm: {
12443
+ card: "h-72 w-56",
12444
+ title: "text-lg font-bold",
12445
+ meta: "text-xs",
12446
+ excerpt: "text-xs"
12447
+ },
12448
+ md: {
12449
+ card: "h-96 w-72",
12450
+ title: "text-xl font-bold",
12451
+ meta: "text-xs",
12452
+ excerpt: "text-sm"
12453
+ },
12454
+ lg: {
12455
+ card: "h-[28rem] w-96",
12456
+ title: "text-2xl font-bold",
12457
+ meta: "text-sm",
12458
+ excerpt: "text-sm"
12459
+ }
12460
+ };
12461
+ function BlogCard({
12462
+ image,
12463
+ imageAlt = "",
12464
+ category,
12465
+ readingTime,
12466
+ date,
12467
+ title,
12468
+ excerpt,
12469
+ href,
12470
+ external,
12471
+ cta,
12472
+ size = "md",
12473
+ className
12474
+ }) {
12475
+ var _a;
12476
+ const s = sizeConfig2[size];
12477
+ const meta = [date != null ? date : null, readingTime != null ? readingTime : null].filter(Boolean).join(" | ");
12478
+ const ctaLabel = (_a = cta == null ? void 0 : cta.label) != null ? _a : "Read more";
12479
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
12480
+ /* @__PURE__ */ jsx(
12481
+ "img",
12482
+ {
12483
+ src: image,
12484
+ alt: imageAlt,
12485
+ loading: "lazy",
12486
+ className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
12487
+ }
12488
+ ),
12489
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-black/10" }),
12490
+ category ? /* @__PURE__ */ jsx("div", { className: "relative z-10 p-3", children: /* @__PURE__ */ jsx(Chip, { variant: "glass", children: category }) }) : /* @__PURE__ */ jsx("div", { className: "relative z-10" }),
12491
+ /* @__PURE__ */ jsxs("div", { className: "relative z-10 flex flex-col gap-1.5 p-5", children: [
12492
+ meta && /* @__PURE__ */ jsx("p", { className: cn("text-white/70 font-medium font-ui", s.meta), children: meta }),
12493
+ /* @__PURE__ */ jsx("h3", { className: cn("text-white leading-snug", s.title), children: title }),
12494
+ excerpt && /* @__PURE__ */ jsx(
12495
+ "p",
12496
+ {
12497
+ className: cn(
12498
+ "text-white/80 leading-relaxed -mt-1 line-clamp-2",
12499
+ s.excerpt
12500
+ ),
12501
+ children: excerpt
12502
+ }
12503
+ ),
12504
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex items-center justify-between gap-4", children: /* @__PURE__ */ jsxs(
12505
+ "span",
12506
+ {
12507
+ className: cn(
12508
+ "group/cta inline-flex items-center gap-1.5 border-b border-white/70 pb-0.5",
12509
+ "text-sm font-semibold text-white transition-colors hover:border-white hover:text-white",
12510
+ "font-ui"
12511
+ ),
12512
+ children: [
12513
+ ctaLabel,
12514
+ /* @__PURE__ */ jsx("span", { className: "transition-transform duration-150 group-hover/cta:translate-x-0.5", children: /* @__PURE__ */ jsx(ArrowIcon2, {}) })
12515
+ ]
12516
+ }
12517
+ ) })
12518
+ ] })
12519
+ ] });
12520
+ const baseClasses = cn(
12521
+ "group relative flex flex-col justify-between overflow-hidden rounded-2xl",
12522
+ "shadow-md transition-shadow duration-300 hover:shadow-xl",
12523
+ s.card,
12524
+ className
12525
+ );
12526
+ return href ? /* @__PURE__ */ jsx(
12527
+ "a",
12528
+ {
12529
+ href,
12530
+ onClick: cta == null ? void 0 : cta.onClick,
12531
+ className: baseClasses,
12532
+ "aria-label": title,
12533
+ target: external ? "_blank" : void 0,
12534
+ rel: external ? "noopener noreferrer" : void 0,
12535
+ children: inner
12536
+ }
12537
+ ) : /* @__PURE__ */ jsx("div", { className: baseClasses, children: inner });
12538
+ }
12539
+ var alignClass = {
12540
+ left: "text-left",
12541
+ center: "text-center",
12542
+ right: "text-right"
12543
+ };
12544
+ function Figure({
12545
+ caption,
12546
+ wide,
12547
+ children
12548
+ }) {
12549
+ return /* @__PURE__ */ jsxs("figure", { className: cn(wide && "lg:-mx-24"), children: [
12550
+ children,
12551
+ caption && /* @__PURE__ */ jsx("figcaption", { className: "mt-2.5 text-center text-xs text-muted-foreground font-sans italic", children: caption })
12552
+ ] });
12553
+ }
12554
+ function renderBlock(block, i) {
12555
+ var _a, _b, _c, _d, _e;
12556
+ switch (block.type) {
12557
+ case "paragraph":
12558
+ return /* @__PURE__ */ jsx(
12559
+ "p",
12560
+ {
12561
+ className: cn(
12562
+ "font-sans text-foreground/90",
12563
+ block.lead ? "text-lg sm:text-xl leading-relaxed text-foreground" : "text-base sm:text-lg leading-relaxed"
12564
+ ),
12565
+ children: block.text
12566
+ },
12567
+ i
12568
+ );
12569
+ case "heading": {
12570
+ const level = (_a = block.level) != null ? _a : 2;
12571
+ const Tag = level === 2 ? "h2" : "h3";
12572
+ return /* @__PURE__ */ jsx(
12573
+ Tag,
12574
+ {
12575
+ id: block.id,
12576
+ className: cn(
12577
+ "font-heading font-bold text-foreground scroll-mt-24",
12578
+ level === 2 ? "text-2xl sm:text-3xl leading-tight pt-2" : "text-xl sm:text-2xl leading-snug"
12579
+ ),
12580
+ children: block.text
12581
+ },
12582
+ i
12583
+ );
12584
+ }
12585
+ case "image":
12586
+ return /* @__PURE__ */ jsxs(Figure, { caption: block.caption, wide: block.wide, children: [
12587
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-2xl bg-muted shadow-sm", children: /* @__PURE__ */ jsx(
12588
+ Picture,
12589
+ {
12590
+ src: block.src,
12591
+ alt: (_b = block.alt) != null ? _b : "",
12592
+ loading: "lazy",
12593
+ className: "w-full h-auto object-cover"
12594
+ }
12595
+ ) }),
12596
+ block.credit && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
12597
+ "Photo: ",
12598
+ block.credit
12599
+ ] })
12600
+ ] }, i);
12601
+ case "collage":
12602
+ return /* @__PURE__ */ jsx(Figure, { caption: block.caption, wide: block.wide, children: /* @__PURE__ */ jsx(
12603
+ PhotoGallery,
12604
+ {
12605
+ photos: block.photos,
12606
+ variant: (_c = block.variant) != null ? _c : "collage",
12607
+ initialVisible: Infinity
12608
+ }
12609
+ ) }, i);
12610
+ case "table":
12611
+ return /* @__PURE__ */ jsx(Figure, { caption: block.caption, children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-xl border border-border", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
12612
+ /* @__PURE__ */ jsx("thead", { className: "bg-muted/60", children: /* @__PURE__ */ jsx("tr", { children: block.columns.map((col) => {
12613
+ var _a2;
12614
+ return /* @__PURE__ */ jsx(
12615
+ "th",
12616
+ {
12617
+ className: cn(
12618
+ "px-4 py-3 font-ui font-semibold text-foreground whitespace-nowrap",
12619
+ alignClass[(_a2 = col.align) != null ? _a2 : "left"]
12620
+ ),
12621
+ children: col.label
12622
+ },
12623
+ col.key
12624
+ );
12625
+ }) }) }),
12626
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: block.rows.map((row, ri) => /* @__PURE__ */ jsx("tr", { className: "hover:bg-muted/30 transition-colors", children: block.columns.map((col) => {
12627
+ var _a2;
12628
+ return /* @__PURE__ */ jsx(
12629
+ "td",
12630
+ {
12631
+ className: cn(
12632
+ "px-4 py-3 font-sans text-foreground/90 align-top",
12633
+ alignClass[(_a2 = col.align) != null ? _a2 : "left"]
12634
+ ),
12635
+ children: row[col.key]
12636
+ },
12637
+ col.key
12638
+ );
12639
+ }) }, ri)) })
12640
+ ] }) }) }, i);
12641
+ case "callout": {
12642
+ const icon = (_d = block.icon) != null ? _d : "\u{1F449}";
12643
+ const cta = (_e = block.cta) != null ? _e : "Read more";
12644
+ const body = /* @__PURE__ */ jsxs(
12645
+ "div",
12646
+ {
12647
+ className: cn(
12648
+ "rounded-r-xl border-l-4 border-primary bg-muted/40 px-5 py-4",
12649
+ block.href && "transition-colors hover:bg-muted/70 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
12650
+ ),
12651
+ children: [
12652
+ block.title && /* @__PURE__ */ jsx("p", { className: "font-ui font-semibold text-foreground", children: block.title }),
12653
+ /* @__PURE__ */ jsxs(
12654
+ "p",
12655
+ {
12656
+ className: cn(
12657
+ "font-sans text-foreground/90 leading-relaxed",
12658
+ block.title && "mt-1"
12659
+ ),
12660
+ children: [
12661
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mr-1.5", children: icon }),
12662
+ block.text
12663
+ ]
12664
+ }
12665
+ ),
12666
+ block.href && /* @__PURE__ */ jsxs("span", { className: "mt-2 inline-flex items-center gap-1.5 font-ui text-sm font-semibold text-primary", children: [
12667
+ cta,
12668
+ /* @__PURE__ */ jsx(ArrowRightIcon, { className: "h-3.5 w-3.5" })
12669
+ ] })
12670
+ ]
12671
+ }
12672
+ );
12673
+ return block.href ? /* @__PURE__ */ jsx(
12674
+ "a",
12675
+ {
12676
+ href: block.href,
12677
+ target: block.external ? "_blank" : void 0,
12678
+ rel: block.external ? "noopener noreferrer" : void 0,
12679
+ className: "block no-underline",
12680
+ children: body
12681
+ },
12682
+ i
12683
+ ) : /* @__PURE__ */ jsx("div", { children: body }, i);
12684
+ }
12685
+ case "quote":
12686
+ return /* @__PURE__ */ jsxs(
12687
+ "blockquote",
12688
+ {
12689
+ className: "border-l-4 border-border pl-5 py-1 font-sans text-xl sm:text-2xl italic leading-snug text-foreground",
12690
+ children: [
12691
+ block.text,
12692
+ block.cite && /* @__PURE__ */ jsxs("cite", { className: "mt-2 block font-ui text-sm not-italic font-semibold text-muted-foreground", children: [
12693
+ "\u2014 ",
12694
+ block.cite
12695
+ ] })
12696
+ ]
12697
+ },
12698
+ i
12699
+ );
12700
+ case "list": {
12701
+ const Tag = block.ordered ? "ol" : "ul";
12702
+ return /* @__PURE__ */ jsx(
12703
+ Tag,
12704
+ {
12705
+ className: cn(
12706
+ "font-sans text-base sm:text-lg leading-relaxed text-foreground/90 pl-5 space-y-2",
12707
+ block.ordered ? "list-decimal" : "list-disc"
12708
+ ),
12709
+ children: block.items.map((item, li) => /* @__PURE__ */ jsx("li", { className: "pl-1", children: item }, li))
12710
+ },
12711
+ i
12712
+ );
12713
+ }
12714
+ default:
12715
+ return null;
12716
+ }
12717
+ }
12718
+ function BlogPost({
12719
+ image,
12720
+ imageAlt = "",
12721
+ title,
12722
+ category,
12723
+ breadcrumb,
12724
+ author,
12725
+ date,
12726
+ readingTime,
12727
+ blocks,
12728
+ children,
12729
+ related,
12730
+ relatedTitle = "Keep reading",
12731
+ className
12732
+ }) {
12733
+ const hasMeta = !!(author || date || readingTime);
12734
+ return /* @__PURE__ */ jsxs("article", { className: cn("w-full", className), children: [
12735
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full overflow-hidden bg-muted", children: [
12736
+ /* @__PURE__ */ jsx("div", { className: "relative h-[62vh] min-h-[460px] w-full", children: /* @__PURE__ */ jsx(
12737
+ Picture,
12738
+ {
12739
+ src: image,
12740
+ alt: imageAlt || title,
12741
+ fetchPriority: "high",
12742
+ eager: true,
12743
+ className: "absolute inset-0 h-full w-full object-cover"
12744
+ }
12745
+ ) }),
12746
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 bg-gradient-to-t from-black/90 via-black/45 to-transparent" }),
12747
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-6 sm:px-8 pb-9 sm:pb-11", children: [
12748
+ 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(React31.Fragment, { children: [
12749
+ i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
12750
+ crumb.href ? /* @__PURE__ */ jsx(
12751
+ "a",
12752
+ {
12753
+ href: crumb.href,
12754
+ className: "text-xs text-white/70 font-ui hover:text-white transition-colors",
12755
+ children: crumb.label
12756
+ }
12757
+ ) : /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui", children: crumb.label })
12758
+ ] }, i)) }),
12759
+ category && /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(Chip, { variant: "glass", children: category }) }),
12760
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-5xl font-bold text-white font-heading leading-tight", children: title }),
12761
+ hasMeta && /* @__PURE__ */ jsxs("div", { className: "mt-5 flex items-center gap-4 flex-wrap", children: [
12762
+ author && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
12763
+ author.avatar && // eslint-disable-next-line @next/next/no-img-element
12764
+ /* @__PURE__ */ jsx(
12765
+ "img",
12766
+ {
12767
+ src: author.avatar,
12768
+ alt: author.name,
12769
+ loading: "lazy",
12770
+ className: "h-10 w-10 rounded-full object-cover ring-2 ring-white/30"
12771
+ }
12772
+ ),
12773
+ /* @__PURE__ */ jsxs("div", { className: "leading-tight", children: [
12774
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white font-ui", children: author.name }),
12775
+ author.role && /* @__PURE__ */ jsx("p", { className: "text-xs text-white/70 font-ui", children: author.role })
12776
+ ] })
12777
+ ] }),
12778
+ (date || readingTime) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 text-white/80", children: [
12779
+ date && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-sm font-ui", children: [
12780
+ /* @__PURE__ */ jsx(CalendarIcon, { className: "h-4 w-4 shrink-0 text-primary-400" }),
12781
+ date
12782
+ ] }),
12783
+ readingTime && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-sm font-ui", children: [
12784
+ /* @__PURE__ */ jsx(ClockIcon, { className: "h-4 w-4 shrink-0 text-primary-400" }),
12785
+ readingTime
12786
+ ] })
12787
+ ] })
12788
+ ] })
12789
+ ] }) })
12790
+ ] }),
12791
+ /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-3xl px-6 sm:px-8 pt-10 sm:pt-12 pb-16", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
12792
+ blocks.map((block, i) => renderBlock(block, i)),
12793
+ children
12794
+ ] }) }),
12795
+ related && related.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t border-border bg-muted/30", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-5xl px-6 sm:px-8 py-12", children: [
12796
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold font-heading text-foreground mb-6", children: relatedTitle }),
12797
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5", children: related.map((post, i) => /* @__PURE__ */ jsx(BlogCard, __spreadProps(__spreadValues({}, post), { className: "w-full" }), i)) })
12798
+ ] }) })
12799
+ ] });
12800
+ }
12311
12801
  function useHlsVideo(videoRef, src) {
12312
- React30.useEffect(() => {
12802
+ React31.useEffect(() => {
12313
12803
  if (!src || !videoRef.current) return;
12314
12804
  const video = videoRef.current;
12315
12805
  if (!src.includes(".m3u8")) return;
@@ -12353,11 +12843,11 @@ function TripHeader({
12353
12843
  className
12354
12844
  }) {
12355
12845
  var _a;
12356
- const [heroIndex, setHeroIndex] = React30.useState(0);
12357
- const [videoReady, setVideoReady] = React30.useState(false);
12358
- const videoRef = React30.useRef(null);
12846
+ const [heroIndex, setHeroIndex] = React31.useState(0);
12847
+ const [videoReady, setVideoReady] = React31.useState(false);
12848
+ const videoRef = React31.useRef(null);
12359
12849
  const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
12360
- const validImages = React30.useMemo(
12850
+ const validImages = React31.useMemo(
12361
12851
  () => images.map((u) => u == null ? void 0 : u.trim()).filter(Boolean),
12362
12852
  [images]
12363
12853
  );
@@ -12372,7 +12862,7 @@ function TripHeader({
12372
12862
  const nights = duration ? (_a = duration.nights) != null ? _a : Math.max(duration.days - 1, 1) : null;
12373
12863
  const hasMeta = !!(destination || duration);
12374
12864
  useHlsVideo(videoRef, isHls ? videoUrl : void 0);
12375
- React30.useEffect(() => {
12865
+ React31.useEffect(() => {
12376
12866
  if (!videoUrl) return;
12377
12867
  const el = videoRef.current;
12378
12868
  if (!el) return;
@@ -12515,7 +13005,7 @@ function TripHeader({
12515
13005
  chips && chips.length > 0 ? siteHeader ? "-mt-[200px] sm:-mt-[214px]" : "-mt-[168px] sm:-mt-[182px]" : siteHeader ? "-mt-44" : "-mt-36"
12516
13006
  ),
12517
13007
  children: [
12518
- 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(React30.Fragment, { children: [
13008
+ 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(React31.Fragment, { children: [
12519
13009
  i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
12520
13010
  /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui hover:text-white/90 cursor-default", children: crumb.label })
12521
13011
  ] }, i)) }),
@@ -12681,10 +13171,10 @@ function LanguagePicker({
12681
13171
  }) {
12682
13172
  var _a;
12683
13173
  const t = VARIANT2[variant];
12684
- const [open, setOpen] = React30.useState(false);
12685
- const ref = React30.useRef(null);
13174
+ const [open, setOpen] = React31.useState(false);
13175
+ const ref = React31.useRef(null);
12686
13176
  const active = (_a = languages.find((l) => l.code === currentLanguage)) != null ? _a : languages[0];
12687
- React30.useEffect(() => {
13177
+ React31.useEffect(() => {
12688
13178
  if (!open) return;
12689
13179
  const onDocClick = (e) => {
12690
13180
  if (ref.current && !ref.current.contains(e.target)) {
@@ -12885,7 +13375,7 @@ function SiteFooter({
12885
13375
  children: wrapper
12886
13376
  },
12887
13377
  b.alt + i
12888
- ) : /* @__PURE__ */ jsx(React30.Fragment, { children: wrapper }, b.alt + i);
13378
+ ) : /* @__PURE__ */ jsx(React31.Fragment, { children: wrapper }, b.alt + i);
12889
13379
  }) })
12890
13380
  ] }),
12891
13381
  themes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "lg:col-span-3", children: [
@@ -13060,10 +13550,10 @@ function TripPage({
13060
13550
  className
13061
13551
  }) {
13062
13552
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
13063
- const [activeSection, setActiveSection] = React30.useState("");
13064
- const [accordionValue, setAccordionValue] = React30.useState([]);
13065
- const [faqsExpanded, setFaqsExpanded] = React30.useState(false);
13066
- const accordionSectionIds = React30.useMemo(
13553
+ const [activeSection, setActiveSection] = React31.useState("");
13554
+ const [accordionValue, setAccordionValue] = React31.useState([]);
13555
+ const [faqsExpanded, setFaqsExpanded] = React31.useState(false);
13556
+ const accordionSectionIds = React31.useMemo(
13067
13557
  () => /* @__PURE__ */ new Set([
13068
13558
  "when-it-operates",
13069
13559
  "how-to-get-there",
@@ -13077,18 +13567,18 @@ function TripPage({
13077
13567
  ]),
13078
13568
  []
13079
13569
  );
13080
- const [navFloating, setNavFloating] = React30.useState(false);
13081
- const [navHidden, setNavHidden] = React30.useState(false);
13082
- const [isFloating, setIsFloating] = React30.useState(false);
13083
- const [sidebarPos, setSidebarPos] = React30.useState(null);
13084
- const [pricingBarVisible, setPricingBarVisible] = React30.useState(false);
13085
- const navRef = React30.useRef(null);
13086
- const navSentinelRef = React30.useRef(null);
13087
- const sentinelRef = React30.useRef(null);
13088
- const sidebarPlaceholderRef = React30.useRef(null);
13089
- const pricingBarRef = React30.useRef(null);
13090
- const galleryRef = React30.useRef(null);
13091
- const sections = React30.useMemo(
13570
+ const [navFloating, setNavFloating] = React31.useState(false);
13571
+ const [navHidden, setNavHidden] = React31.useState(false);
13572
+ const [isFloating, setIsFloating] = React31.useState(false);
13573
+ const [sidebarPos, setSidebarPos] = React31.useState(null);
13574
+ const [pricingBarVisible, setPricingBarVisible] = React31.useState(false);
13575
+ const navRef = React31.useRef(null);
13576
+ const navSentinelRef = React31.useRef(null);
13577
+ const sentinelRef = React31.useRef(null);
13578
+ const sidebarPlaceholderRef = React31.useRef(null);
13579
+ const pricingBarRef = React31.useRef(null);
13580
+ const galleryRef = React31.useRef(null);
13581
+ const sections = React31.useMemo(
13092
13582
  () => {
13093
13583
  var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2;
13094
13584
  return [
@@ -13110,7 +13600,7 @@ function TripPage({
13110
13600
  // eslint-disable-next-line react-hooks/exhaustive-deps
13111
13601
  []
13112
13602
  );
13113
- React30.useEffect(() => {
13603
+ React31.useEffect(() => {
13114
13604
  const sentinel = navSentinelRef.current;
13115
13605
  if (!sentinel) return;
13116
13606
  const update = () => setNavFloating(sentinel.getBoundingClientRect().top < 1);
@@ -13118,7 +13608,7 @@ function TripPage({
13118
13608
  update();
13119
13609
  return () => document.removeEventListener("scroll", update, { capture: true });
13120
13610
  }, []);
13121
- React30.useEffect(() => {
13611
+ React31.useEffect(() => {
13122
13612
  const sentinel = sentinelRef.current;
13123
13613
  if (!sentinel) return;
13124
13614
  const update = () => setIsFloating(sentinel.getBoundingClientRect().top < 1);
@@ -13126,7 +13616,7 @@ function TripPage({
13126
13616
  update();
13127
13617
  return () => document.removeEventListener("scroll", update, { capture: true });
13128
13618
  }, []);
13129
- React30.useEffect(() => {
13619
+ React31.useEffect(() => {
13130
13620
  const measure = () => {
13131
13621
  if (!sidebarPlaceholderRef.current) return;
13132
13622
  const rect = sidebarPlaceholderRef.current.getBoundingClientRect();
@@ -13136,7 +13626,7 @@ function TripPage({
13136
13626
  window.addEventListener("resize", measure);
13137
13627
  return () => window.removeEventListener("resize", measure);
13138
13628
  }, [isFloating]);
13139
- React30.useEffect(() => {
13629
+ React31.useEffect(() => {
13140
13630
  const check = () => {
13141
13631
  var _a2;
13142
13632
  const target = (_a2 = galleryRef.current) != null ? _a2 : pricingBarRef.current;
@@ -13147,7 +13637,7 @@ function TripPage({
13147
13637
  check();
13148
13638
  return () => document.removeEventListener("scroll", check, { capture: true });
13149
13639
  }, []);
13150
- React30.useEffect(() => {
13640
+ React31.useEffect(() => {
13151
13641
  const check = () => {
13152
13642
  if (!pricingBarRef.current) return;
13153
13643
  setNavHidden(pricingBarRef.current.getBoundingClientRect().top < window.innerHeight * 0.92);
@@ -13156,7 +13646,7 @@ function TripPage({
13156
13646
  check();
13157
13647
  return () => document.removeEventListener("scroll", check, { capture: true });
13158
13648
  }, []);
13159
- React30.useEffect(() => {
13649
+ React31.useEffect(() => {
13160
13650
  if (sections.length === 0) return;
13161
13651
  setActiveSection(sections[0].id);
13162
13652
  const update = () => {
@@ -13631,123 +14121,6 @@ function TripPage({
13631
14121
  }
13632
14122
  );
13633
14123
  }
13634
- function ArrowIcon2() {
13635
- return /* @__PURE__ */ jsxs(
13636
- "svg",
13637
- {
13638
- width: "13",
13639
- height: "13",
13640
- viewBox: "0 0 24 24",
13641
- fill: "none",
13642
- stroke: "currentColor",
13643
- strokeWidth: "2.2",
13644
- strokeLinecap: "round",
13645
- strokeLinejoin: "round",
13646
- children: [
13647
- /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
13648
- /* @__PURE__ */ jsx("polyline", { points: "12 5 19 12 12 19" })
13649
- ]
13650
- }
13651
- );
13652
- }
13653
- var sizeConfig2 = {
13654
- sm: {
13655
- card: "h-72 w-56",
13656
- title: "text-lg font-bold",
13657
- meta: "text-xs",
13658
- excerpt: "text-xs"
13659
- },
13660
- md: {
13661
- card: "h-96 w-72",
13662
- title: "text-xl font-bold",
13663
- meta: "text-xs",
13664
- excerpt: "text-sm"
13665
- },
13666
- lg: {
13667
- card: "h-[28rem] w-96",
13668
- title: "text-2xl font-bold",
13669
- meta: "text-sm",
13670
- excerpt: "text-sm"
13671
- }
13672
- };
13673
- function BlogCard({
13674
- image,
13675
- imageAlt = "",
13676
- category,
13677
- readingTime,
13678
- date,
13679
- title,
13680
- excerpt,
13681
- href,
13682
- external,
13683
- cta,
13684
- size = "md",
13685
- className
13686
- }) {
13687
- var _a;
13688
- const s = sizeConfig2[size];
13689
- const meta = [date != null ? date : null, readingTime != null ? readingTime : null].filter(Boolean).join(" | ");
13690
- const ctaLabel = (_a = cta == null ? void 0 : cta.label) != null ? _a : "Read more";
13691
- const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
13692
- /* @__PURE__ */ jsx(
13693
- "img",
13694
- {
13695
- src: image,
13696
- alt: imageAlt,
13697
- loading: "lazy",
13698
- className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
13699
- }
13700
- ),
13701
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-black/10" }),
13702
- category ? /* @__PURE__ */ jsx("div", { className: "relative z-10 p-3", children: /* @__PURE__ */ jsx(Chip, { variant: "glass", children: category }) }) : /* @__PURE__ */ jsx("div", { className: "relative z-10" }),
13703
- /* @__PURE__ */ jsxs("div", { className: "relative z-10 flex flex-col gap-1.5 p-5", children: [
13704
- meta && /* @__PURE__ */ jsx("p", { className: cn("text-white/70 font-medium font-ui", s.meta), children: meta }),
13705
- /* @__PURE__ */ jsx("h3", { className: cn("text-white leading-snug", s.title), children: title }),
13706
- excerpt && /* @__PURE__ */ jsx(
13707
- "p",
13708
- {
13709
- className: cn(
13710
- "text-white/80 leading-relaxed -mt-1 line-clamp-2",
13711
- s.excerpt
13712
- ),
13713
- children: excerpt
13714
- }
13715
- ),
13716
- /* @__PURE__ */ jsx("div", { className: "mt-3 flex items-center justify-between gap-4", children: /* @__PURE__ */ jsxs(
13717
- "span",
13718
- {
13719
- className: cn(
13720
- "group/cta inline-flex items-center gap-1.5 border-b border-white/70 pb-0.5",
13721
- "text-sm font-semibold text-white transition-colors hover:border-white hover:text-white",
13722
- "font-ui"
13723
- ),
13724
- children: [
13725
- ctaLabel,
13726
- /* @__PURE__ */ jsx("span", { className: "transition-transform duration-150 group-hover/cta:translate-x-0.5", children: /* @__PURE__ */ jsx(ArrowIcon2, {}) })
13727
- ]
13728
- }
13729
- ) })
13730
- ] })
13731
- ] });
13732
- const baseClasses = cn(
13733
- "group relative flex flex-col justify-between overflow-hidden rounded-2xl",
13734
- "shadow-md transition-shadow duration-300 hover:shadow-xl",
13735
- s.card,
13736
- className
13737
- );
13738
- return href ? /* @__PURE__ */ jsx(
13739
- "a",
13740
- {
13741
- href,
13742
- onClick: cta == null ? void 0 : cta.onClick,
13743
- className: baseClasses,
13744
- "aria-label": title,
13745
- target: external ? "_blank" : void 0,
13746
- rel: external ? "noopener noreferrer" : void 0,
13747
- children: inner
13748
- }
13749
- ) : /* @__PURE__ */ jsx("div", { className: baseClasses, children: inner });
13750
- }
13751
14124
  function SectionHeading({
13752
14125
  eyebrow,
13753
14126
  title,
@@ -13798,11 +14171,11 @@ function CategoryPage2({
13798
14171
  className
13799
14172
  }) {
13800
14173
  var _a;
13801
- const [videoReady, setVideoReady] = React30.useState(false);
13802
- const videoRef = React30.useRef(null);
14174
+ const [videoReady, setVideoReady] = React31.useState(false);
14175
+ const videoRef = React31.useRef(null);
13803
14176
  const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
13804
14177
  useHlsVideo(videoRef, isHls ? videoUrl : void 0);
13805
- React30.useEffect(() => {
14178
+ React31.useEffect(() => {
13806
14179
  if (!videoUrl) return;
13807
14180
  const el = videoRef.current;
13808
14181
  if (!el) return;
@@ -13817,13 +14190,13 @@ function CategoryPage2({
13817
14190
  io.observe(el);
13818
14191
  return () => io.disconnect();
13819
14192
  }, [videoUrl]);
13820
- const [faqsExpanded, setFaqsExpanded] = React30.useState(false);
13821
- const [tripsExpanded, setTripsExpanded] = React30.useState(false);
13822
- const [filterValue, setFilterValue] = React30.useState({});
13823
- const [sort, setSort] = React30.useState(
14193
+ const [faqsExpanded, setFaqsExpanded] = React31.useState(false);
14194
+ const [tripsExpanded, setTripsExpanded] = React31.useState(false);
14195
+ const [filterValue, setFilterValue] = React31.useState({});
14196
+ const [sort, setSort] = React31.useState(
13824
14197
  defaultSort != null ? defaultSort : (_a = sortOptions == null ? void 0 : sortOptions[0]) == null ? void 0 : _a.id
13825
14198
  );
13826
- const sortedTrips = React30.useMemo(() => {
14199
+ const sortedTrips = React31.useMemo(() => {
13827
14200
  const active = Object.entries(filterValue).filter(
13828
14201
  ([, vals]) => vals && vals.length > 0
13829
14202
  );
@@ -13927,7 +14300,7 @@ function CategoryPage2({
13927
14300
  /* @__PURE__ */ jsxs("div", { className: "relative mx-auto w-full max-w-6xl px-6 sm:px-8", children: [
13928
14301
  breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-center gap-1.5 flex-wrap", children: breadcrumb.map((crumb, i) => {
13929
14302
  const isLast = i === breadcrumb.length - 1;
13930
- return /* @__PURE__ */ jsxs(React30.Fragment, { children: [
14303
+ return /* @__PURE__ */ jsxs(React31.Fragment, { children: [
13931
14304
  i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
13932
14305
  crumb.href && !isLast ? /* @__PURE__ */ jsx(
13933
14306
  "a",
@@ -14215,12 +14588,12 @@ function Toast({
14215
14588
  duration = 6e3,
14216
14589
  className
14217
14590
  }) {
14218
- const [mounted, setMounted] = React30.useState(false);
14219
- const [visible, setVisible] = React30.useState(true);
14220
- React30.useEffect(() => {
14591
+ const [mounted, setMounted] = React31.useState(false);
14592
+ const [visible, setVisible] = React31.useState(true);
14593
+ React31.useEffect(() => {
14221
14594
  setMounted(true);
14222
14595
  }, []);
14223
- React30.useEffect(() => {
14596
+ React31.useEffect(() => {
14224
14597
  if (duration === 0) return;
14225
14598
  const t = setTimeout(() => {
14226
14599
  setVisible(false);
@@ -15722,8 +16095,8 @@ function ShareWidget({
15722
16095
  title = "Invite friends & lower the price",
15723
16096
  className
15724
16097
  }) {
15725
- const [copied, setCopied] = React30.useState(false);
15726
- const [showToast, setShowToast] = React30.useState(false);
16098
+ const [copied, setCopied] = React31.useState(false);
16099
+ const [showToast, setShowToast] = React31.useState(false);
15727
16100
  const encodedUrl = encodeURIComponent(url);
15728
16101
  const encodedMsg = encodeURIComponent(`${message} ${url}`);
15729
16102
  const channels = [
@@ -15873,6 +16246,6 @@ function StickyBookingCard({
15873
16246
  );
15874
16247
  }
15875
16248
 
15876
- export { ActivityCard, AgentContactCard, Alert, AskExo, BirthDateField, BookingAdventureCard, BookingCancellationEmail, BookingConfirmedCard, BookingCreatedEmail, BookingDetails, BookingForm, BookingOtpEmail, BookingPaymentConfirmationEmail, BookingShell, BookingSummary, Button, COUNTRIES, CategoryPage2, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, STATUS_MAP as DEPARTURE_STATUS_MAP, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, ExoOrb, FilterPanel, FloatingInput, FloatingSelect, GroupProgressBar, GroupStatusBanner, Itinerary, ItineraryDay, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, ParticipantCounter, ParticipantList, PartnerBookingCreatedEmail, PartnerRegistrationCompleteEmail, PaymentAmountSelector, PaymentDetailsBlock, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PaymentReminderEmail, PhoneCountrySelect, PhotoGallery, Picture, PriceProgress, PricingMatrixCard, PricingTrip, RegistrationForm, RegistrationProgressBar, RegistrationReminderEmail, RegistrationReminderIndividualEmail, RegistrationSuccessCard, ShareWidget, SiteHeader, StatusBadge2 as StatusBadge, StickyBookingCard, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TransferDetailsBlock, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, TrustpilotEmbed, buttonVariants, cn, emailTokens, formatCpf, getStripeAppearance, itineraryDaySpecIcons, stripeAppearance, validateCpf, webpVariantUrl, wrapEmailHtml };
16249
+ export { ActivityCard, AgentContactCard, Alert, AskExo, BirthDateField, BlogCard, BlogPost, BookingAdventureCard, BookingCancellationEmail, BookingConfirmedCard, BookingCreatedEmail, BookingDetails, BookingForm, BookingOtpEmail, BookingPaymentConfirmationEmail, BookingShell, BookingSummary, Button, COUNTRIES, CategoryPage2, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, STATUS_MAP as DEPARTURE_STATUS_MAP, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, ExoOrb, FilterPanel, FloatingInput, FloatingSelect, GroupProgressBar, GroupStatusBanner, Itinerary, ItineraryDay, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, ParticipantCounter, ParticipantList, PartnerBookingCreatedEmail, PartnerRegistrationCompleteEmail, PaymentAmountSelector, PaymentDetailsBlock, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PaymentReminderEmail, PhoneCountrySelect, PhotoGallery, Picture, PriceProgress, PricingMatrixCard, PricingTrip, RegistrationForm, RegistrationProgressBar, RegistrationReminderEmail, RegistrationReminderIndividualEmail, RegistrationSuccessCard, ShareWidget, SiteHeader, StatusBadge2 as StatusBadge, StickyBookingCard, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TransferDetailsBlock, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, TrustpilotEmbed, buttonVariants, cn, emailTokens, formatCpf, getStripeAppearance, itineraryDaySpecIcons, stripeAppearance, validateCpf, webpVariantUrl, wrapEmailHtml };
15877
16250
  //# sourceMappingURL=index.js.map
15878
16251
  //# sourceMappingURL=index.js.map