@planetaexo/design-system 0.22.2 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1132 -548
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +275 -18
- package/dist/index.d.ts +275 -18
- package/dist/index.js +1113 -533
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React25 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';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, ChevronLeftIcon, ClockIcon, ChevronUpIcon, UserIcon, MenuIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon,
|
|
7
|
+
import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, ClockIcon, CheckIcon, ChevronUpIcon, UserIcon, MenuIcon, SunIcon, MoonIcon, MapPinIcon, InfoIcon, PackageIcon, SparklesIcon, BackpackIcon, BedDoubleIcon, UtensilsIcon, ReceiptIcon, Loader2Icon, SendIcon, CheckCircleIcon, MailIcon, PhoneIcon, MessageCircleIcon, CompassIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, LayoutGridIcon } from 'lucide-react';
|
|
8
8
|
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
9
9
|
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
10
10
|
import { Button as Button$1 } from '@base-ui/react/button';
|
|
@@ -81,7 +81,7 @@ var buttonVariants = cva(
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
);
|
|
84
|
-
var Button =
|
|
84
|
+
var Button = React25.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(
|
|
@@ -302,10 +302,10 @@ function DialogDescription(_a) {
|
|
|
302
302
|
}, props)
|
|
303
303
|
);
|
|
304
304
|
}
|
|
305
|
-
var FloatingInput =
|
|
305
|
+
var FloatingInput = React25.forwardRef(
|
|
306
306
|
(_a, ref) => {
|
|
307
307
|
var _b = _a, { label, error, id, className, required } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required"]);
|
|
308
|
-
const inputId = id != null ? id :
|
|
308
|
+
const inputId = id != null ? id : React25.useId();
|
|
309
309
|
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
310
310
|
/* @__PURE__ */ jsx(
|
|
311
311
|
"input",
|
|
@@ -345,10 +345,10 @@ var FloatingInput = React23.forwardRef(
|
|
|
345
345
|
}
|
|
346
346
|
);
|
|
347
347
|
FloatingInput.displayName = "FloatingInput";
|
|
348
|
-
var FloatingSelect =
|
|
348
|
+
var FloatingSelect = React25.forwardRef(
|
|
349
349
|
(_a, ref) => {
|
|
350
350
|
var _b = _a, { label, error, id, className, required, children, value } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required", "children", "value"]);
|
|
351
|
-
const inputId = id != null ? id :
|
|
351
|
+
const inputId = id != null ? id : React25.useId();
|
|
352
352
|
const hasValue = typeof value === "string" ? value !== "" : value !== void 0 && value !== null;
|
|
353
353
|
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
354
354
|
/* @__PURE__ */ jsx(
|
|
@@ -612,11 +612,11 @@ function PhoneCountrySelect({
|
|
|
612
612
|
disabled
|
|
613
613
|
}) {
|
|
614
614
|
var _a;
|
|
615
|
-
const [open, setOpen] =
|
|
616
|
-
const containerRef =
|
|
617
|
-
const listRef =
|
|
615
|
+
const [open, setOpen] = React25.useState(false);
|
|
616
|
+
const containerRef = React25.useRef(null);
|
|
617
|
+
const listRef = React25.useRef(null);
|
|
618
618
|
const selected = (_a = PHONE_COUNTRIES.find((c) => c.code === value)) != null ? _a : PHONE_COUNTRIES[0];
|
|
619
|
-
|
|
619
|
+
React25.useEffect(() => {
|
|
620
620
|
if (!open) return;
|
|
621
621
|
const handler = (e) => {
|
|
622
622
|
var _a2;
|
|
@@ -627,7 +627,7 @@ function PhoneCountrySelect({
|
|
|
627
627
|
document.addEventListener("mousedown", handler);
|
|
628
628
|
return () => document.removeEventListener("mousedown", handler);
|
|
629
629
|
}, [open]);
|
|
630
|
-
|
|
630
|
+
React25.useEffect(() => {
|
|
631
631
|
if (!open || !listRef.current) return;
|
|
632
632
|
const activeEl = listRef.current.querySelector("[data-selected=true]");
|
|
633
633
|
activeEl == null ? void 0 : activeEl.scrollIntoView({ block: "nearest" });
|
|
@@ -897,8 +897,8 @@ function CalendarDayButton(_a) {
|
|
|
897
897
|
"locale"
|
|
898
898
|
]);
|
|
899
899
|
const defaultClassNames = getDefaultClassNames();
|
|
900
|
-
const ref =
|
|
901
|
-
|
|
900
|
+
const ref = React25.useRef(null);
|
|
901
|
+
React25.useEffect(() => {
|
|
902
902
|
var _a2;
|
|
903
903
|
if (modifiers.focused) (_a2 = ref.current) == null ? void 0 : _a2.focus();
|
|
904
904
|
}, [modifiers.focused]);
|
|
@@ -929,16 +929,16 @@ function BirthDateField({
|
|
|
929
929
|
className,
|
|
930
930
|
disabled
|
|
931
931
|
}) {
|
|
932
|
-
const [open, setOpen] =
|
|
933
|
-
const [text, setText] =
|
|
932
|
+
const [open, setOpen] = React25.useState(false);
|
|
933
|
+
const [text, setText] = React25.useState(
|
|
934
934
|
value ? format(value, "dd/MM/yyyy") : ""
|
|
935
935
|
);
|
|
936
|
-
const containerRef =
|
|
937
|
-
const inputId =
|
|
938
|
-
|
|
936
|
+
const containerRef = React25.useRef(null);
|
|
937
|
+
const inputId = React25.useId();
|
|
938
|
+
React25.useEffect(() => {
|
|
939
939
|
setText(value ? format(value, "dd/MM/yyyy") : "");
|
|
940
940
|
}, [value]);
|
|
941
|
-
|
|
941
|
+
React25.useEffect(() => {
|
|
942
942
|
if (!open) return;
|
|
943
943
|
const handler = (e) => {
|
|
944
944
|
var _a;
|
|
@@ -1147,14 +1147,14 @@ function CountrySearchField({
|
|
|
1147
1147
|
}) {
|
|
1148
1148
|
var _a;
|
|
1149
1149
|
const list = countries != null ? countries : COUNTRIES;
|
|
1150
|
-
const [query, setQuery] =
|
|
1151
|
-
const [open, setOpen] =
|
|
1152
|
-
const containerRef =
|
|
1153
|
-
const searchRef =
|
|
1150
|
+
const [query, setQuery] = React25.useState("");
|
|
1151
|
+
const [open, setOpen] = React25.useState(false);
|
|
1152
|
+
const containerRef = React25.useRef(null);
|
|
1153
|
+
const searchRef = React25.useRef(null);
|
|
1154
1154
|
const selected = list.find((c) => c.code === value);
|
|
1155
1155
|
const isFloated = open || !!selected;
|
|
1156
1156
|
const filtered = query.trim() ? list.filter((c) => c.name.toLowerCase().includes(query.toLowerCase())) : list;
|
|
1157
|
-
|
|
1157
|
+
React25.useEffect(() => {
|
|
1158
1158
|
if (!open) return;
|
|
1159
1159
|
const handler = (e) => {
|
|
1160
1160
|
var _a2;
|
|
@@ -1268,7 +1268,7 @@ function AdventureCard({
|
|
|
1268
1268
|
}) {
|
|
1269
1269
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1270
1270
|
const isControlled = (_b = (_a = adventure.optionals) == null ? void 0 : _a.some((o) => o.onCheckedChange !== void 0)) != null ? _b : false;
|
|
1271
|
-
const [checkedInternal, setCheckedInternal] =
|
|
1271
|
+
const [checkedInternal, setCheckedInternal] = React25.useState(
|
|
1272
1272
|
new Set((_d = (_c = adventure.optionals) == null ? void 0 : _c.filter((o) => o.defaultChecked).map((o) => o.id)) != null ? _d : [])
|
|
1273
1273
|
);
|
|
1274
1274
|
const isChecked = (opt) => {
|
|
@@ -1666,7 +1666,7 @@ function BookingShell({
|
|
|
1666
1666
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
|
|
1667
1667
|
/* @__PURE__ */ jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
|
|
1668
1668
|
/* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: title }),
|
|
1669
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(
|
|
1669
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React25.Fragment, { children: [
|
|
1670
1670
|
/* @__PURE__ */ jsx(
|
|
1671
1671
|
"span",
|
|
1672
1672
|
{
|
|
@@ -1865,7 +1865,7 @@ function TermsSection({
|
|
|
1865
1865
|
termsContent
|
|
1866
1866
|
}) {
|
|
1867
1867
|
var _a;
|
|
1868
|
-
const [modalOpen, setModalOpen] =
|
|
1868
|
+
const [modalOpen, setModalOpen] = React25.useState(false);
|
|
1869
1869
|
const i18n = (_a = TERMS_I18N[locale]) != null ? _a : TERMS_I18N.en;
|
|
1870
1870
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
|
|
1871
1871
|
/* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: title }),
|
|
@@ -1934,7 +1934,7 @@ function BookingConfirmedCard({
|
|
|
1934
1934
|
" ",
|
|
1935
1935
|
/* @__PURE__ */ jsx("span", { className: "font-bold text-foreground font-heading", children: bookingNumber })
|
|
1936
1936
|
] }),
|
|
1937
|
-
/* @__PURE__ */ jsx("
|
|
1937
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground font-sans max-w-sm mx-auto leading-relaxed", children: message != null ? message : /* @__PURE__ */ jsxs("p", { children: [
|
|
1938
1938
|
"A confirmation email has been sent to",
|
|
1939
1939
|
" ",
|
|
1940
1940
|
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: email || "your email" }),
|
|
@@ -1960,6 +1960,32 @@ function BookingConfirmedCard({
|
|
|
1960
1960
|
)
|
|
1961
1961
|
] });
|
|
1962
1962
|
}
|
|
1963
|
+
function TransferDetailsBlock({
|
|
1964
|
+
label,
|
|
1965
|
+
items,
|
|
1966
|
+
className
|
|
1967
|
+
}) {
|
|
1968
|
+
if (!items.length) return null;
|
|
1969
|
+
return /* @__PURE__ */ jsxs(
|
|
1970
|
+
"div",
|
|
1971
|
+
{
|
|
1972
|
+
className: [
|
|
1973
|
+
"w-full max-w-md mx-auto rounded-xl border border-border bg-muted/40 px-5 py-4 text-left",
|
|
1974
|
+
className != null ? className : ""
|
|
1975
|
+
].filter(Boolean).join(" "),
|
|
1976
|
+
children: [
|
|
1977
|
+
/* @__PURE__ */ jsx("div", { className: "mb-3 text-xs uppercase tracking-wide text-muted-foreground font-heading", children: label }),
|
|
1978
|
+
/* @__PURE__ */ jsx("dl", { className: "space-y-1.5 text-sm font-mono", children: items.map(([term, value], i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [
|
|
1979
|
+
/* @__PURE__ */ jsxs("dt", { className: "text-muted-foreground shrink-0", children: [
|
|
1980
|
+
term,
|
|
1981
|
+
":"
|
|
1982
|
+
] }),
|
|
1983
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-semibold break-all", children: value })
|
|
1984
|
+
] }, i)) })
|
|
1985
|
+
]
|
|
1986
|
+
}
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1963
1989
|
var WIZARD_STEPS_FN = (l) => {
|
|
1964
1990
|
var _a, _b, _c, _d, _e, _f;
|
|
1965
1991
|
return [
|
|
@@ -1977,9 +2003,9 @@ function BookingWizard({
|
|
|
1977
2003
|
}) {
|
|
1978
2004
|
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;
|
|
1979
2005
|
const wizardSteps = WIZARD_STEPS_FN(labels);
|
|
1980
|
-
const [step, setStep] =
|
|
1981
|
-
const [error, setError] =
|
|
1982
|
-
const [responsible, setResponsible] =
|
|
2006
|
+
const [step, setStep] = React25.useState("responsible");
|
|
2007
|
+
const [error, setError] = React25.useState(null);
|
|
2008
|
+
const [responsible, setResponsible] = React25.useState({
|
|
1983
2009
|
firstName: "",
|
|
1984
2010
|
lastName: "",
|
|
1985
2011
|
email: "",
|
|
@@ -1998,7 +2024,7 @@ function BookingWizard({
|
|
|
1998
2024
|
return s + ((_b2 = (_a2 = a.slots) == null ? void 0 : _a2.children) != null ? _b2 : 0);
|
|
1999
2025
|
}, 0);
|
|
2000
2026
|
const totalPax = totalAdults + totalChildren;
|
|
2001
|
-
const [travellers, setTravellers] =
|
|
2027
|
+
const [travellers, setTravellers] = React25.useState(
|
|
2002
2028
|
Array.from({ length: Math.max(totalPax, 1) }, () => ({
|
|
2003
2029
|
firstName: "",
|
|
2004
2030
|
lastName: "",
|
|
@@ -2006,9 +2032,9 @@ function BookingWizard({
|
|
|
2006
2032
|
email: ""
|
|
2007
2033
|
}))
|
|
2008
2034
|
);
|
|
2009
|
-
const [payAmount, setPayAmount] =
|
|
2010
|
-
const [payMethod, setPayMethod] =
|
|
2011
|
-
const [termsAccepted, setTermsAccepted] =
|
|
2035
|
+
const [payAmount, setPayAmount] = React25.useState("full");
|
|
2036
|
+
const [payMethod, setPayMethod] = React25.useState("stripe");
|
|
2037
|
+
const [termsAccepted, setTermsAccepted] = React25.useState(false);
|
|
2012
2038
|
const setR = (k, v) => setResponsible((p) => __spreadProps(__spreadValues({}, p), { [k]: v }));
|
|
2013
2039
|
const setT = (i, k, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { [k]: v }) : t));
|
|
2014
2040
|
const setTDob = (i, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { dateOfBirth: v }) : t));
|
|
@@ -2235,7 +2261,7 @@ function Offer({
|
|
|
2235
2261
|
className
|
|
2236
2262
|
}) {
|
|
2237
2263
|
var _a, _b, _c;
|
|
2238
|
-
const [showBooking, setShowBooking] =
|
|
2264
|
+
const [showBooking, setShowBooking] = React25.useState(false);
|
|
2239
2265
|
const isShowingCheckout = !confirmedState && (!!checkoutSlot || showBooking);
|
|
2240
2266
|
const handleBook = () => {
|
|
2241
2267
|
if (!checkoutSlot && !externalBookingFlow) setShowBooking(true);
|
|
@@ -2596,7 +2622,7 @@ function AdventureSection({
|
|
|
2596
2622
|
labels
|
|
2597
2623
|
}) {
|
|
2598
2624
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
2599
|
-
const [detailsOpen, setDetailsOpen] =
|
|
2625
|
+
const [detailsOpen, setDetailsOpen] = React25.useState(false);
|
|
2600
2626
|
const handleCopyUrl = (url) => {
|
|
2601
2627
|
if (onCopyFormLink) {
|
|
2602
2628
|
onCopyFormLink(url);
|
|
@@ -2780,8 +2806,15 @@ function AdventureSection({
|
|
|
2780
2806
|
] })
|
|
2781
2807
|
] }),
|
|
2782
2808
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col divide-y divide-border", children: adventure.travellers.map((t) => {
|
|
2783
|
-
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2;
|
|
2784
|
-
const canRemoveTraveller = adventure.travellers.length > 1;
|
|
2809
|
+
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2;
|
|
2810
|
+
const canRemoveTraveller = adventure.travellers.length > 1 || adventure.allowEmptyAdventure === true;
|
|
2811
|
+
const isRemovingLastTraveller = adventure.allowEmptyAdventure === true && adventure.travellers.length === 1;
|
|
2812
|
+
const confirmRemoveLastMessage = (_b2 = (_a2 = labels == null ? void 0 : labels.confirmRemoveLastTraveller) == null ? void 0 : _a2.message) != null ? _b2 : "The adventure will be empty. Continue?";
|
|
2813
|
+
const confirmIfLast = () => {
|
|
2814
|
+
if (!isRemovingLastTraveller) return true;
|
|
2815
|
+
if (typeof window === "undefined") return true;
|
|
2816
|
+
return window.confirm(confirmRemoveLastMessage);
|
|
2817
|
+
};
|
|
2785
2818
|
const disabledRemoveTitle = canRemoveTraveller ? void 0 : cannotRemoveLastTravellerLabel != null ? cannotRemoveLastTravellerLabel : "Cannot remove last traveller";
|
|
2786
2819
|
return /* @__PURE__ */ jsxs(
|
|
2787
2820
|
"div",
|
|
@@ -2795,7 +2828,7 @@ function AdventureSection({
|
|
|
2795
2828
|
" ",
|
|
2796
2829
|
t.lastName
|
|
2797
2830
|
] }),
|
|
2798
|
-
t.isChild && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold font-heading rounded-full px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400 shrink-0", children: (
|
|
2831
|
+
t.isChild && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold font-heading rounded-full px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400 shrink-0", children: (_c2 = labels == null ? void 0 : labels.childBadge) != null ? _c2 : "Child" })
|
|
2799
2832
|
] }),
|
|
2800
2833
|
t.formUrl && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2801
2834
|
/* @__PURE__ */ jsxs(
|
|
@@ -2807,7 +2840,7 @@ function AdventureSection({
|
|
|
2807
2840
|
className: "flex items-center gap-1 text-xs text-primary hover:text-primary/80 transition-colors font-ui",
|
|
2808
2841
|
children: [
|
|
2809
2842
|
/* @__PURE__ */ jsx(ExternalLinkIcon, { className: "w-3 h-3" }),
|
|
2810
|
-
(
|
|
2843
|
+
(_d2 = labels == null ? void 0 : labels.openFormLink) != null ? _d2 : "Open"
|
|
2811
2844
|
]
|
|
2812
2845
|
}
|
|
2813
2846
|
),
|
|
@@ -2817,7 +2850,7 @@ function AdventureSection({
|
|
|
2817
2850
|
type: "button",
|
|
2818
2851
|
onClick: () => handleCopyUrl(t.formUrl),
|
|
2819
2852
|
className: "flex items-center text-xs text-muted-foreground hover:text-primary transition-colors font-ui",
|
|
2820
|
-
"aria-label": (
|
|
2853
|
+
"aria-label": (_e2 = labels == null ? void 0 : labels.copyFormUrlAria) != null ? _e2 : "Copy form URL",
|
|
2821
2854
|
children: /* @__PURE__ */ jsx(CopyIcon, { className: "w-3 h-3" })
|
|
2822
2855
|
}
|
|
2823
2856
|
)
|
|
@@ -2831,7 +2864,7 @@ function AdventureSection({
|
|
|
2831
2864
|
"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-bold font-heading uppercase tracking-wider shrink-0",
|
|
2832
2865
|
t.status === "completed" ? "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400" : "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"
|
|
2833
2866
|
),
|
|
2834
|
-
children: t.status === "completed" ? (
|
|
2867
|
+
children: t.status === "completed" ? (_f2 = labels == null ? void 0 : labels.travellerStatusCompleted) != null ? _f2 : t.status : (_g2 = labels == null ? void 0 : labels.travellerStatusPending) != null ? _g2 : t.status
|
|
2835
2868
|
}
|
|
2836
2869
|
),
|
|
2837
2870
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [
|
|
@@ -2847,7 +2880,7 @@ function AdventureSection({
|
|
|
2847
2880
|
}
|
|
2848
2881
|
},
|
|
2849
2882
|
className: "flex h-8 w-8 sm:h-7 sm:w-7 items-center justify-center rounded-lg text-muted-foreground hover:text-primary hover:bg-primary/10 transition-colors",
|
|
2850
|
-
"aria-label": (
|
|
2883
|
+
"aria-label": (_i2 = (_h2 = labels == null ? void 0 : labels.editTravellerAria) == null ? void 0 : _h2.call(labels, t.firstName)) != null ? _i2 : `Edit ${t.firstName}`,
|
|
2851
2884
|
children: /* @__PURE__ */ jsx(PencilIcon, { className: "w-3.5 h-3.5" })
|
|
2852
2885
|
}
|
|
2853
2886
|
),
|
|
@@ -2857,6 +2890,7 @@ function AdventureSection({
|
|
|
2857
2890
|
type: "button",
|
|
2858
2891
|
onClick: () => {
|
|
2859
2892
|
if (!canRemoveTraveller) return;
|
|
2893
|
+
if (!confirmIfLast()) return;
|
|
2860
2894
|
if (onRemoveTraveller) {
|
|
2861
2895
|
onRemoveTraveller(adventure.id, t.id);
|
|
2862
2896
|
} else {
|
|
@@ -2870,7 +2904,7 @@ function AdventureSection({
|
|
|
2870
2904
|
"flex h-8 w-8 sm:h-7 sm:w-7 items-center justify-center rounded-lg text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors",
|
|
2871
2905
|
"disabled:opacity-40 disabled:cursor-not-allowed disabled:pointer-events-none disabled:hover:text-muted-foreground disabled:hover:bg-transparent"
|
|
2872
2906
|
),
|
|
2873
|
-
"aria-label": (
|
|
2907
|
+
"aria-label": (_k2 = (_j2 = labels == null ? void 0 : labels.deleteTravellerAria) == null ? void 0 : _j2.call(labels, t.firstName)) != null ? _k2 : `Delete ${t.firstName}`,
|
|
2874
2908
|
children: /* @__PURE__ */ jsx(Trash2Icon, { className: "w-3.5 h-3.5" })
|
|
2875
2909
|
}
|
|
2876
2910
|
),
|
|
@@ -2880,6 +2914,7 @@ function AdventureSection({
|
|
|
2880
2914
|
type: "button",
|
|
2881
2915
|
onClick: () => {
|
|
2882
2916
|
if (!canRemoveTraveller) return;
|
|
2917
|
+
if (!confirmIfLast()) return;
|
|
2883
2918
|
if (onUnassignFromAdventure) {
|
|
2884
2919
|
onUnassignFromAdventure(adventure.id, t.id);
|
|
2885
2920
|
} else if (onRemoveTraveller) {
|
|
@@ -2895,7 +2930,7 @@ function AdventureSection({
|
|
|
2895
2930
|
"flex h-8 w-8 sm:h-7 sm:w-7 items-center justify-center rounded-lg text-muted-foreground hover:text-amber-500 hover:bg-amber-500/10 transition-colors",
|
|
2896
2931
|
"disabled:opacity-40 disabled:cursor-not-allowed disabled:pointer-events-none disabled:hover:text-muted-foreground disabled:hover:bg-transparent"
|
|
2897
2932
|
),
|
|
2898
|
-
"aria-label": (
|
|
2933
|
+
"aria-label": (_m2 = (_l2 = labels == null ? void 0 : labels.removeFromAdventureAria) == null ? void 0 : _l2.call(labels, t.firstName)) != null ? _m2 : `Remove ${t.firstName} from adventure`,
|
|
2899
2934
|
children: /* @__PURE__ */ jsx(UserMinusIcon, { className: "w-3.5 h-3.5" })
|
|
2900
2935
|
}
|
|
2901
2936
|
)
|
|
@@ -3081,8 +3116,8 @@ function AddTravellerDialog({
|
|
|
3081
3116
|
errorMessage
|
|
3082
3117
|
}) {
|
|
3083
3118
|
var _a, _b, _c, _d, _e;
|
|
3084
|
-
const [form, setForm] =
|
|
3085
|
-
|
|
3119
|
+
const [form, setForm] = React25.useState(() => createInitialAddFormData(config));
|
|
3120
|
+
React25.useEffect(() => {
|
|
3086
3121
|
if (open) {
|
|
3087
3122
|
setForm(createInitialAddFormData(config));
|
|
3088
3123
|
}
|
|
@@ -3142,7 +3177,7 @@ function EditTravellerDialog({
|
|
|
3142
3177
|
errorMessage
|
|
3143
3178
|
}) {
|
|
3144
3179
|
var _a, _b, _c, _d, _e;
|
|
3145
|
-
const [form, setForm] =
|
|
3180
|
+
const [form, setForm] = React25.useState(() => ({
|
|
3146
3181
|
firstName: "",
|
|
3147
3182
|
lastName: "",
|
|
3148
3183
|
email: "",
|
|
@@ -3151,7 +3186,7 @@ function EditTravellerDialog({
|
|
|
3151
3186
|
birthDate: "",
|
|
3152
3187
|
personType: "ADULT"
|
|
3153
3188
|
}));
|
|
3154
|
-
|
|
3189
|
+
React25.useEffect(() => {
|
|
3155
3190
|
var _a2, _b2, _c2, _d2, _e2, _f;
|
|
3156
3191
|
if (open && traveller) {
|
|
3157
3192
|
setForm({
|
|
@@ -3431,38 +3466,38 @@ function BookingDetails({
|
|
|
3431
3466
|
const hasSubmitAddTraveller = !!onSubmitAddTraveller;
|
|
3432
3467
|
const hasSubmitEditTraveller = !!onSubmitEditTraveller;
|
|
3433
3468
|
const hasConfirmRemoveTraveller = !!onConfirmRemoveTraveller;
|
|
3434
|
-
const [addModalState, setAddModalState] =
|
|
3469
|
+
const [addModalState, setAddModalState] = React25.useState({
|
|
3435
3470
|
open: false,
|
|
3436
3471
|
adventureId: null
|
|
3437
3472
|
});
|
|
3438
|
-
const [editModalState, setEditModalState] =
|
|
3439
|
-
const [deleteModalState, setDeleteModalState] =
|
|
3440
|
-
const handleRequestOpenAddModal =
|
|
3473
|
+
const [editModalState, setEditModalState] = React25.useState({ open: false, adventureId: null, traveller: null });
|
|
3474
|
+
const [deleteModalState, setDeleteModalState] = React25.useState({ open: false, adventureId: null, traveller: null });
|
|
3475
|
+
const handleRequestOpenAddModal = React25.useCallback((adventureId) => {
|
|
3441
3476
|
setAddModalState({ open: true, adventureId });
|
|
3442
3477
|
}, []);
|
|
3443
|
-
const handleRequestOpenEditModal =
|
|
3478
|
+
const handleRequestOpenEditModal = React25.useCallback(
|
|
3444
3479
|
(adventureId, traveller) => {
|
|
3445
3480
|
setEditModalState({ open: true, adventureId, traveller });
|
|
3446
3481
|
},
|
|
3447
3482
|
[]
|
|
3448
3483
|
);
|
|
3449
|
-
const handleRequestOpenDeleteModal =
|
|
3484
|
+
const handleRequestOpenDeleteModal = React25.useCallback(
|
|
3450
3485
|
(adventureId, traveller) => {
|
|
3451
3486
|
setDeleteModalState({ open: true, adventureId, traveller });
|
|
3452
3487
|
},
|
|
3453
3488
|
[]
|
|
3454
3489
|
);
|
|
3455
|
-
const closeAddModal =
|
|
3490
|
+
const closeAddModal = React25.useCallback(() => {
|
|
3456
3491
|
setAddModalState({ open: false, adventureId: null });
|
|
3457
3492
|
}, []);
|
|
3458
|
-
const closeEditModal =
|
|
3493
|
+
const closeEditModal = React25.useCallback(() => {
|
|
3459
3494
|
setEditModalState({ open: false, adventureId: null, traveller: null });
|
|
3460
3495
|
}, []);
|
|
3461
|
-
const closeDeleteModal =
|
|
3496
|
+
const closeDeleteModal = React25.useCallback(() => {
|
|
3462
3497
|
setDeleteModalState({ open: false, adventureId: null, traveller: null });
|
|
3463
3498
|
}, []);
|
|
3464
|
-
const submitInFlightRef =
|
|
3465
|
-
const handleAddSubmit =
|
|
3499
|
+
const submitInFlightRef = React25.useRef(false);
|
|
3500
|
+
const handleAddSubmit = React25.useCallback(
|
|
3466
3501
|
async (adventureId, data) => {
|
|
3467
3502
|
if (!onSubmitAddTraveller) return;
|
|
3468
3503
|
if (submitInFlightRef.current) return;
|
|
@@ -3477,7 +3512,7 @@ function BookingDetails({
|
|
|
3477
3512
|
},
|
|
3478
3513
|
[onSubmitAddTraveller, closeAddModal]
|
|
3479
3514
|
);
|
|
3480
|
-
const handleEditSubmit =
|
|
3515
|
+
const handleEditSubmit = React25.useCallback(
|
|
3481
3516
|
async (adventureId, travellerId, data) => {
|
|
3482
3517
|
if (!onSubmitEditTraveller) return;
|
|
3483
3518
|
if (submitInFlightRef.current) return;
|
|
@@ -3492,7 +3527,7 @@ function BookingDetails({
|
|
|
3492
3527
|
},
|
|
3493
3528
|
[onSubmitEditTraveller, closeEditModal]
|
|
3494
3529
|
);
|
|
3495
|
-
const handleDeleteConfirm =
|
|
3530
|
+
const handleDeleteConfirm = React25.useCallback(
|
|
3496
3531
|
async (adventureId, travellerId) => {
|
|
3497
3532
|
if (!onConfirmRemoveTraveller) return;
|
|
3498
3533
|
if (submitInFlightRef.current) return;
|
|
@@ -4222,7 +4257,7 @@ function BookingConfirmationEmail({
|
|
|
4222
4257
|
}, children: i + 1 }) }),
|
|
4223
4258
|
/* @__PURE__ */ jsx("td", { style: { verticalAlign: "top" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "14px", color: emailTokens.bodyText, lineHeight: "1.6", margin: 0 }, children: step }) })
|
|
4224
4259
|
] }) }) }, i)) }),
|
|
4225
|
-
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(
|
|
4260
|
+
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(React25.Fragment, { children: [
|
|
4226
4261
|
idx === 0 ? /* @__PURE__ */ jsx("strong", { children: line }) : line,
|
|
4227
4262
|
idx < arr.length - 1 ? /* @__PURE__ */ jsx("br", {}) : null
|
|
4228
4263
|
] }, idx)) })
|
|
@@ -4675,11 +4710,11 @@ function DatePickerField({
|
|
|
4675
4710
|
fromDate,
|
|
4676
4711
|
className
|
|
4677
4712
|
}) {
|
|
4678
|
-
const [open, setOpen] =
|
|
4679
|
-
const containerRef =
|
|
4680
|
-
const [calendarWidth, setCalendarWidth] =
|
|
4713
|
+
const [open, setOpen] = React25.useState(false);
|
|
4714
|
+
const containerRef = React25.useRef(null);
|
|
4715
|
+
const [calendarWidth, setCalendarWidth] = React25.useState();
|
|
4681
4716
|
const hasValue = !!value;
|
|
4682
|
-
|
|
4717
|
+
React25.useEffect(() => {
|
|
4683
4718
|
if (!containerRef.current) return;
|
|
4684
4719
|
const observer = new ResizeObserver(([entry]) => {
|
|
4685
4720
|
setCalendarWidth(entry.contentRect.width);
|
|
@@ -4788,7 +4823,7 @@ function BookingForm({
|
|
|
4788
4823
|
subtitle = "Free enquiry \u2013 no commitment",
|
|
4789
4824
|
className
|
|
4790
4825
|
}) {
|
|
4791
|
-
const [values, setValues] =
|
|
4826
|
+
const [values, setValues] = React25.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
|
|
4792
4827
|
const set = (key, value) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [key]: value }));
|
|
4793
4828
|
const handleSubmit = (e) => {
|
|
4794
4829
|
e.preventDefault();
|
|
@@ -5325,11 +5360,11 @@ function FloatingTextarea({
|
|
|
5325
5360
|
}
|
|
5326
5361
|
function SelectField({ field, value, onChange, error, disabled }) {
|
|
5327
5362
|
var _a, _b, _c;
|
|
5328
|
-
const [open, setOpen] =
|
|
5329
|
-
const containerRef =
|
|
5363
|
+
const [open, setOpen] = React25.useState(false);
|
|
5364
|
+
const containerRef = React25.useRef(null);
|
|
5330
5365
|
const options = (_a = field.options) != null ? _a : [];
|
|
5331
5366
|
const selectedOpt = (_b = options.find((o) => o.value === value)) != null ? _b : null;
|
|
5332
|
-
|
|
5367
|
+
React25.useEffect(() => {
|
|
5333
5368
|
if (!open) return;
|
|
5334
5369
|
const handleOutside = (e) => {
|
|
5335
5370
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
@@ -5718,11 +5753,11 @@ function RegistrationForm({
|
|
|
5718
5753
|
readOnly = false
|
|
5719
5754
|
}) {
|
|
5720
5755
|
var _a;
|
|
5721
|
-
const L =
|
|
5756
|
+
const L = React25.useMemo(
|
|
5722
5757
|
() => __spreadValues(__spreadValues({}, DEFAULT_LABELS4), labels != null ? labels : {}),
|
|
5723
5758
|
[labels]
|
|
5724
5759
|
);
|
|
5725
|
-
const sortedFields =
|
|
5760
|
+
const sortedFields = React25.useMemo(
|
|
5726
5761
|
() => [...fields].sort((a, b) => {
|
|
5727
5762
|
var _a2, _b;
|
|
5728
5763
|
return ((_a2 = a.order) != null ? _a2 : 0) - ((_b = b.order) != null ? _b : 0);
|
|
@@ -5730,7 +5765,7 @@ function RegistrationForm({
|
|
|
5730
5765
|
[fields]
|
|
5731
5766
|
);
|
|
5732
5767
|
const isControlled = values !== void 0;
|
|
5733
|
-
const [internal, setInternal] =
|
|
5768
|
+
const [internal, setInternal] = React25.useState(
|
|
5734
5769
|
() => initializeValues(
|
|
5735
5770
|
sortedFields,
|
|
5736
5771
|
defaultValues != null ? defaultValues : {},
|
|
@@ -5738,9 +5773,9 @@ function RegistrationForm({
|
|
|
5738
5773
|
includeTerms
|
|
5739
5774
|
)
|
|
5740
5775
|
);
|
|
5741
|
-
const [submitAttempted, setSubmitAttempted] =
|
|
5742
|
-
const [validationErrors, setValidationErrors] =
|
|
5743
|
-
|
|
5776
|
+
const [submitAttempted, setSubmitAttempted] = React25.useState(false);
|
|
5777
|
+
const [validationErrors, setValidationErrors] = React25.useState({});
|
|
5778
|
+
React25.useEffect(() => {
|
|
5744
5779
|
if (isControlled) return;
|
|
5745
5780
|
setInternal((prev) => {
|
|
5746
5781
|
const next = initializeValues(
|
|
@@ -5797,7 +5832,7 @@ function RegistrationForm({
|
|
|
5797
5832
|
const termsError = submitAttempted && termsEnabled && !termsAccepted;
|
|
5798
5833
|
const firstErrorFieldId = Object.keys(fieldErrors)[0];
|
|
5799
5834
|
const scrollTargetId = firstErrorFieldId ? `rf-${firstErrorFieldId}` : termsError ? "rf-terms" : null;
|
|
5800
|
-
|
|
5835
|
+
React25.useEffect(() => {
|
|
5801
5836
|
if (!submitAttempted || !scrollTargetId) return;
|
|
5802
5837
|
const timer = setTimeout(() => {
|
|
5803
5838
|
const elem = document.getElementById(scrollTargetId);
|
|
@@ -6259,10 +6294,10 @@ var OTPCodeInput = ({
|
|
|
6259
6294
|
id,
|
|
6260
6295
|
required
|
|
6261
6296
|
}) => {
|
|
6262
|
-
const baseId = id != null ? id :
|
|
6263
|
-
const inputRef =
|
|
6264
|
-
const [focused, setFocused] =
|
|
6265
|
-
const digits =
|
|
6297
|
+
const baseId = id != null ? id : React25.useId();
|
|
6298
|
+
const inputRef = React25.useRef(null);
|
|
6299
|
+
const [focused, setFocused] = React25.useState(false);
|
|
6300
|
+
const digits = React25.useMemo(() => {
|
|
6266
6301
|
const arr = value.split("").slice(0, length);
|
|
6267
6302
|
while (arr.length < length) arr.push("");
|
|
6268
6303
|
return arr;
|
|
@@ -6378,7 +6413,7 @@ function Checkbox(_a) {
|
|
|
6378
6413
|
})
|
|
6379
6414
|
);
|
|
6380
6415
|
}
|
|
6381
|
-
var AccordionVariantContext =
|
|
6416
|
+
var AccordionVariantContext = React25.createContext("default");
|
|
6382
6417
|
function Accordion(_a) {
|
|
6383
6418
|
var _b = _a, { className, variant = "default" } = _b, props = __objRest(_b, ["className", "variant"]);
|
|
6384
6419
|
return /* @__PURE__ */ jsx(AccordionVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
|
|
@@ -6396,7 +6431,7 @@ function Accordion(_a) {
|
|
|
6396
6431
|
}
|
|
6397
6432
|
function AccordionItem(_a) {
|
|
6398
6433
|
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
6399
|
-
const variant =
|
|
6434
|
+
const variant = React25.useContext(AccordionVariantContext);
|
|
6400
6435
|
return /* @__PURE__ */ jsx(
|
|
6401
6436
|
Accordion$1.Item,
|
|
6402
6437
|
__spreadValues({
|
|
@@ -6417,7 +6452,7 @@ function AccordionTrigger(_a) {
|
|
|
6417
6452
|
"className",
|
|
6418
6453
|
"children"
|
|
6419
6454
|
]);
|
|
6420
|
-
const variant =
|
|
6455
|
+
const variant = React25.useContext(AccordionVariantContext);
|
|
6421
6456
|
return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
6422
6457
|
Accordion$1.Trigger,
|
|
6423
6458
|
__spreadProps(__spreadValues({
|
|
@@ -6471,7 +6506,7 @@ function AccordionContent(_a) {
|
|
|
6471
6506
|
"className",
|
|
6472
6507
|
"children"
|
|
6473
6508
|
]);
|
|
6474
|
-
const variant =
|
|
6509
|
+
const variant = React25.useContext(AccordionVariantContext);
|
|
6475
6510
|
return /* @__PURE__ */ jsx(
|
|
6476
6511
|
Accordion$1.Panel,
|
|
6477
6512
|
__spreadProps(__spreadValues({
|
|
@@ -6503,7 +6538,7 @@ function FilterPanel({
|
|
|
6503
6538
|
title = "Filters",
|
|
6504
6539
|
className
|
|
6505
6540
|
}) {
|
|
6506
|
-
const [internalValue, setInternalValue] =
|
|
6541
|
+
const [internalValue, setInternalValue] = React25.useState(
|
|
6507
6542
|
() => Object.fromEntries(groups.map((g) => [g.id, []]))
|
|
6508
6543
|
);
|
|
6509
6544
|
const selected = value != null ? value : internalValue;
|
|
@@ -6599,6 +6634,76 @@ function FilterPanel({
|
|
|
6599
6634
|
)
|
|
6600
6635
|
] });
|
|
6601
6636
|
}
|
|
6637
|
+
var TRUSTPILOT_SCRIPT_SRC = "https://widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js";
|
|
6638
|
+
function TrustpilotEmbed({ config }) {
|
|
6639
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6640
|
+
const ref = React25.useRef(null);
|
|
6641
|
+
React25.useEffect(() => {
|
|
6642
|
+
if (typeof document === "undefined" || !ref.current) return;
|
|
6643
|
+
let cancelled = false;
|
|
6644
|
+
const initWidget = () => {
|
|
6645
|
+
if (cancelled || !ref.current) return;
|
|
6646
|
+
const tp = window.Trustpilot;
|
|
6647
|
+
if (tp == null ? void 0 : tp.loadFromElement) {
|
|
6648
|
+
tp.loadFromElement(ref.current, true);
|
|
6649
|
+
}
|
|
6650
|
+
};
|
|
6651
|
+
const existing = document.querySelector(
|
|
6652
|
+
`script[src="${TRUSTPILOT_SCRIPT_SRC}"]`
|
|
6653
|
+
);
|
|
6654
|
+
if (existing) {
|
|
6655
|
+
const tp = window.Trustpilot;
|
|
6656
|
+
if (tp == null ? void 0 : tp.loadFromElement) {
|
|
6657
|
+
initWidget();
|
|
6658
|
+
} else {
|
|
6659
|
+
existing.addEventListener("load", initWidget, { once: true });
|
|
6660
|
+
}
|
|
6661
|
+
return () => {
|
|
6662
|
+
cancelled = true;
|
|
6663
|
+
existing.removeEventListener("load", initWidget);
|
|
6664
|
+
};
|
|
6665
|
+
}
|
|
6666
|
+
const s = document.createElement("script");
|
|
6667
|
+
s.src = TRUSTPILOT_SCRIPT_SRC;
|
|
6668
|
+
s.async = true;
|
|
6669
|
+
s.addEventListener("load", initWidget, { once: true });
|
|
6670
|
+
document.body.appendChild(s);
|
|
6671
|
+
return () => {
|
|
6672
|
+
cancelled = true;
|
|
6673
|
+
s.removeEventListener("load", initWidget);
|
|
6674
|
+
};
|
|
6675
|
+
}, [config]);
|
|
6676
|
+
const sku = Array.isArray(config.sku) ? config.sku.join(",") : config.sku;
|
|
6677
|
+
return /* @__PURE__ */ jsx(
|
|
6678
|
+
"div",
|
|
6679
|
+
{
|
|
6680
|
+
ref,
|
|
6681
|
+
className: "trustpilot-widget",
|
|
6682
|
+
"data-locale": (_a = config.locale) != null ? _a : "en-US",
|
|
6683
|
+
"data-template-id": (_b = config.templateId) != null ? _b : "5763bccae0a06d08e809ecbb",
|
|
6684
|
+
"data-businessunit-id": config.businessUnitId,
|
|
6685
|
+
"data-style-height": (_c = config.styleHeight) != null ? _c : "700px",
|
|
6686
|
+
"data-style-width": (_d = config.styleWidth) != null ? _d : "100%",
|
|
6687
|
+
"data-sku": sku,
|
|
6688
|
+
"data-no-reviews": (_e = config.noReviews) != null ? _e : "hide",
|
|
6689
|
+
"data-fullwidth": "true",
|
|
6690
|
+
"data-theme": config.theme,
|
|
6691
|
+
"data-token": config.token,
|
|
6692
|
+
"data-scroll-to-list": config.scrollToList ? "true" : void 0,
|
|
6693
|
+
"data-style-alignment": config.styleAlignment,
|
|
6694
|
+
"data-star-color": config.starColor,
|
|
6695
|
+
children: /* @__PURE__ */ jsx(
|
|
6696
|
+
"a",
|
|
6697
|
+
{
|
|
6698
|
+
href: (_f = config.fallbackHref) != null ? _f : "https://www.trustpilot.com/",
|
|
6699
|
+
target: "_blank",
|
|
6700
|
+
rel: "noopener noreferrer",
|
|
6701
|
+
children: "Trustpilot"
|
|
6702
|
+
}
|
|
6703
|
+
)
|
|
6704
|
+
}
|
|
6705
|
+
);
|
|
6706
|
+
}
|
|
6602
6707
|
function ItineraryDayCard({
|
|
6603
6708
|
stop,
|
|
6604
6709
|
onOpen
|
|
@@ -6665,11 +6770,11 @@ function ItineraryModal({
|
|
|
6665
6770
|
onNext
|
|
6666
6771
|
}) {
|
|
6667
6772
|
var _a, _b, _c;
|
|
6668
|
-
const [imgIndex, setImgIndex] =
|
|
6773
|
+
const [imgIndex, setImgIndex] = React25.useState(0);
|
|
6669
6774
|
const images = stop ? [stop.coverImage, ...(_a = stop.images) != null ? _a : []] : [];
|
|
6670
6775
|
const isFirst = (stop == null ? void 0 : stop.dayNumber) === ((_b = allStops[0]) == null ? void 0 : _b.dayNumber);
|
|
6671
6776
|
const isLast = (stop == null ? void 0 : stop.dayNumber) === ((_c = allStops[allStops.length - 1]) == null ? void 0 : _c.dayNumber);
|
|
6672
|
-
|
|
6777
|
+
React25.useEffect(() => {
|
|
6673
6778
|
setImgIndex(0);
|
|
6674
6779
|
}, [stop == null ? void 0 : stop.dayNumber]);
|
|
6675
6780
|
if (!stop) return null;
|
|
@@ -6796,8 +6901,8 @@ function ItineraryModal({
|
|
|
6796
6901
|
) });
|
|
6797
6902
|
}
|
|
6798
6903
|
function Itinerary({ title, subtitle, stops, className }) {
|
|
6799
|
-
const [activeIndex, setActiveIndex] =
|
|
6800
|
-
const scrollRef =
|
|
6904
|
+
const [activeIndex, setActiveIndex] = React25.useState(null);
|
|
6905
|
+
const scrollRef = React25.useRef(null);
|
|
6801
6906
|
const activeStop = activeIndex !== null ? stops[activeIndex] : null;
|
|
6802
6907
|
const scrollBy = (dir) => {
|
|
6803
6908
|
if (!scrollRef.current) return;
|
|
@@ -6875,147 +6980,6 @@ function Itinerary({ title, subtitle, stops, className }) {
|
|
|
6875
6980
|
)
|
|
6876
6981
|
] });
|
|
6877
6982
|
}
|
|
6878
|
-
function MenuTrip({
|
|
6879
|
-
sections,
|
|
6880
|
-
activeSection,
|
|
6881
|
-
onSelect,
|
|
6882
|
-
variant = "pill",
|
|
6883
|
-
bold = true,
|
|
6884
|
-
className
|
|
6885
|
-
}) {
|
|
6886
|
-
const scrollRef = React23.useRef(null);
|
|
6887
|
-
React23.useEffect(() => {
|
|
6888
|
-
if (!scrollRef.current || !activeSection) return;
|
|
6889
|
-
const container = scrollRef.current;
|
|
6890
|
-
const btn = container.querySelector(
|
|
6891
|
-
`[data-section="${activeSection}"]`
|
|
6892
|
-
);
|
|
6893
|
-
if (!btn) return;
|
|
6894
|
-
const btnLeft = btn.offsetLeft;
|
|
6895
|
-
const btnRight = btnLeft + btn.offsetWidth;
|
|
6896
|
-
const cLeft = container.scrollLeft;
|
|
6897
|
-
const cRight = cLeft + container.offsetWidth;
|
|
6898
|
-
if (btnLeft < cLeft) {
|
|
6899
|
-
container.scrollTo({ left: btnLeft - 16, behavior: "smooth" });
|
|
6900
|
-
} else if (btnRight > cRight) {
|
|
6901
|
-
container.scrollTo({ left: btnRight - container.offsetWidth + 16, behavior: "smooth" });
|
|
6902
|
-
}
|
|
6903
|
-
}, [activeSection]);
|
|
6904
|
-
if (variant === "underline") {
|
|
6905
|
-
return /* @__PURE__ */ jsx(
|
|
6906
|
-
"div",
|
|
6907
|
-
{
|
|
6908
|
-
ref: scrollRef,
|
|
6909
|
-
className: cn(
|
|
6910
|
-
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
6911
|
-
"border-b border-border",
|
|
6912
|
-
className
|
|
6913
|
-
),
|
|
6914
|
-
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-end gap-0", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
6915
|
-
"button",
|
|
6916
|
-
{
|
|
6917
|
-
"data-section": s.id,
|
|
6918
|
-
type: "button",
|
|
6919
|
-
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
6920
|
-
className: cn(
|
|
6921
|
-
"relative px-4 py-2.5 text-sm font-ui whitespace-nowrap transition-colors duration-150",
|
|
6922
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
6923
|
-
"after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:rounded-full after:transition-all",
|
|
6924
|
-
bold ? "font-semibold" : "font-normal",
|
|
6925
|
-
activeSection === s.id ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent"
|
|
6926
|
-
),
|
|
6927
|
-
children: s.label
|
|
6928
|
-
},
|
|
6929
|
-
s.id
|
|
6930
|
-
)) })
|
|
6931
|
-
}
|
|
6932
|
-
);
|
|
6933
|
-
}
|
|
6934
|
-
if (variant === "outlined") {
|
|
6935
|
-
return /* @__PURE__ */ jsx(
|
|
6936
|
-
"div",
|
|
6937
|
-
{
|
|
6938
|
-
ref: scrollRef,
|
|
6939
|
-
className: cn(
|
|
6940
|
-
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
6941
|
-
className
|
|
6942
|
-
),
|
|
6943
|
-
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-2", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
6944
|
-
"button",
|
|
6945
|
-
{
|
|
6946
|
-
"data-section": s.id,
|
|
6947
|
-
type: "button",
|
|
6948
|
-
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
6949
|
-
className: cn(
|
|
6950
|
-
"rounded-full border px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
6951
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6952
|
-
bold ? "font-semibold" : "font-normal",
|
|
6953
|
-
activeSection === s.id ? "border-foreground bg-foreground text-background" : "border-border bg-background text-muted-foreground hover:border-foreground/50 hover:text-foreground"
|
|
6954
|
-
),
|
|
6955
|
-
children: s.label
|
|
6956
|
-
},
|
|
6957
|
-
s.id
|
|
6958
|
-
)) })
|
|
6959
|
-
}
|
|
6960
|
-
);
|
|
6961
|
-
}
|
|
6962
|
-
if (variant === "floating") {
|
|
6963
|
-
return /* @__PURE__ */ jsx(
|
|
6964
|
-
"div",
|
|
6965
|
-
{
|
|
6966
|
-
ref: scrollRef,
|
|
6967
|
-
className: cn(
|
|
6968
|
-
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
6969
|
-
"py-1 px-0.5",
|
|
6970
|
-
/* padding so shadow isn't clipped by overflow */
|
|
6971
|
-
className
|
|
6972
|
-
),
|
|
6973
|
-
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-0.5 rounded-full border border-border/40 bg-background/90 backdrop-blur-md shadow-sm px-1.5 py-1.5", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
6974
|
-
"button",
|
|
6975
|
-
{
|
|
6976
|
-
"data-section": s.id,
|
|
6977
|
-
type: "button",
|
|
6978
|
-
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
6979
|
-
className: cn(
|
|
6980
|
-
"rounded-full px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
6981
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6982
|
-
bold ? "font-semibold" : "font-normal",
|
|
6983
|
-
activeSection === s.id ? "bg-foreground text-background shadow-sm" : "text-foreground/60 hover:text-foreground hover:bg-muted/60"
|
|
6984
|
-
),
|
|
6985
|
-
children: s.label
|
|
6986
|
-
},
|
|
6987
|
-
s.id
|
|
6988
|
-
)) })
|
|
6989
|
-
}
|
|
6990
|
-
);
|
|
6991
|
-
}
|
|
6992
|
-
return /* @__PURE__ */ jsx(
|
|
6993
|
-
"div",
|
|
6994
|
-
{
|
|
6995
|
-
ref: scrollRef,
|
|
6996
|
-
className: cn(
|
|
6997
|
-
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
6998
|
-
className
|
|
6999
|
-
),
|
|
7000
|
-
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-1 p-1", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
7001
|
-
"button",
|
|
7002
|
-
{
|
|
7003
|
-
"data-section": s.id,
|
|
7004
|
-
type: "button",
|
|
7005
|
-
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
7006
|
-
className: cn(
|
|
7007
|
-
"rounded-full px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
7008
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7009
|
-
bold ? "font-semibold" : "font-normal",
|
|
7010
|
-
activeSection === s.id ? "bg-foreground text-background shadow-sm" : "bg-white text-foreground/70 hover:text-foreground shadow-sm"
|
|
7011
|
-
),
|
|
7012
|
-
children: s.label
|
|
7013
|
-
},
|
|
7014
|
-
s.id
|
|
7015
|
-
)) })
|
|
7016
|
-
}
|
|
7017
|
-
);
|
|
7018
|
-
}
|
|
7019
6983
|
function normalise(p) {
|
|
7020
6984
|
return typeof p === "string" ? { src: p } : p;
|
|
7021
6985
|
}
|
|
@@ -7030,18 +6994,18 @@ function Lightbox({
|
|
|
7030
6994
|
onClose
|
|
7031
6995
|
}) {
|
|
7032
6996
|
var _a;
|
|
7033
|
-
const [index, setIndex] =
|
|
6997
|
+
const [index, setIndex] = React25.useState(initialIndex);
|
|
7034
6998
|
const total = photos.length;
|
|
7035
6999
|
const photo = photos[index];
|
|
7036
|
-
const prev =
|
|
7000
|
+
const prev = React25.useCallback(
|
|
7037
7001
|
() => setIndex((i) => (i - 1 + total) % total),
|
|
7038
7002
|
[total]
|
|
7039
7003
|
);
|
|
7040
|
-
const next =
|
|
7004
|
+
const next = React25.useCallback(
|
|
7041
7005
|
() => setIndex((i) => (i + 1) % total),
|
|
7042
7006
|
[total]
|
|
7043
7007
|
);
|
|
7044
|
-
|
|
7008
|
+
React25.useEffect(() => {
|
|
7045
7009
|
const onKey = (e) => {
|
|
7046
7010
|
if (e.key === "Escape") onClose();
|
|
7047
7011
|
if (e.key === "ArrowLeft") prev();
|
|
@@ -7115,55 +7079,27 @@ function Lightbox({
|
|
|
7115
7079
|
]
|
|
7116
7080
|
}
|
|
7117
7081
|
),
|
|
7118
|
-
total > 1 && /* @__PURE__ */
|
|
7082
|
+
total > 1 && /* @__PURE__ */ jsx(
|
|
7119
7083
|
"div",
|
|
7120
7084
|
{
|
|
7121
|
-
className: "absolute bottom-5 inset-x-0 flex items-center justify-center
|
|
7085
|
+
className: "absolute bottom-5 inset-x-0 flex items-center justify-center px-5",
|
|
7122
7086
|
onClick: (e) => e.stopPropagation(),
|
|
7123
|
-
children:
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
prev();
|
|
7131
|
-
},
|
|
7132
|
-
className: "flex h-9 w-9 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors",
|
|
7133
|
-
"aria-label": "Previous photo",
|
|
7134
|
-
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "h-4 w-4" })
|
|
7135
|
-
}
|
|
7136
|
-
),
|
|
7137
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: photos.map((_, i) => /* @__PURE__ */ jsx(
|
|
7138
|
-
"button",
|
|
7139
|
-
{
|
|
7140
|
-
type: "button",
|
|
7141
|
-
onClick: (e) => {
|
|
7142
|
-
e.stopPropagation();
|
|
7143
|
-
setIndex(i);
|
|
7144
|
-
},
|
|
7145
|
-
"aria-label": `Go to photo ${i + 1}`,
|
|
7146
|
-
className: cn(
|
|
7147
|
-
"h-1.5 rounded-full transition-all duration-300 focus-visible:outline-none",
|
|
7148
|
-
i === index ? "w-6 bg-primary" : "w-1.5 bg-white/40 hover:bg-white/70"
|
|
7149
|
-
)
|
|
7087
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: photos.map((_, i) => /* @__PURE__ */ jsx(
|
|
7088
|
+
"button",
|
|
7089
|
+
{
|
|
7090
|
+
type: "button",
|
|
7091
|
+
onClick: (e) => {
|
|
7092
|
+
e.stopPropagation();
|
|
7093
|
+
setIndex(i);
|
|
7150
7094
|
},
|
|
7151
|
-
i
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
next();
|
|
7160
|
-
},
|
|
7161
|
-
className: "flex h-9 w-9 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors",
|
|
7162
|
-
"aria-label": "Next photo",
|
|
7163
|
-
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-4 w-4" })
|
|
7164
|
-
}
|
|
7165
|
-
)
|
|
7166
|
-
]
|
|
7095
|
+
"aria-label": `Go to photo ${i + 1}`,
|
|
7096
|
+
className: cn(
|
|
7097
|
+
"h-1.5 rounded-full transition-all duration-300 focus-visible:outline-none",
|
|
7098
|
+
i === index ? "w-6 bg-primary" : "w-1.5 bg-white/40 hover:bg-white/70"
|
|
7099
|
+
)
|
|
7100
|
+
},
|
|
7101
|
+
i
|
|
7102
|
+
)) })
|
|
7167
7103
|
}
|
|
7168
7104
|
)
|
|
7169
7105
|
]
|
|
@@ -7235,7 +7171,7 @@ function GridGallery({
|
|
|
7235
7171
|
initialVisible,
|
|
7236
7172
|
onOpen
|
|
7237
7173
|
}) {
|
|
7238
|
-
const [expanded, setExpanded] =
|
|
7174
|
+
const [expanded, setExpanded] = React25.useState(false);
|
|
7239
7175
|
const cols = gridCols(photos.length);
|
|
7240
7176
|
const hasMore = photos.length > initialVisible;
|
|
7241
7177
|
const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
|
|
@@ -7265,7 +7201,7 @@ function MasonryGallery({
|
|
|
7265
7201
|
initialVisible,
|
|
7266
7202
|
onOpen
|
|
7267
7203
|
}) {
|
|
7268
|
-
const [expanded, setExpanded] =
|
|
7204
|
+
const [expanded, setExpanded] = React25.useState(false);
|
|
7269
7205
|
const hasMore = photos.length > initialVisible;
|
|
7270
7206
|
const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
|
|
7271
7207
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -7338,7 +7274,7 @@ function FeaturedGallery({
|
|
|
7338
7274
|
photos,
|
|
7339
7275
|
onOpen
|
|
7340
7276
|
}) {
|
|
7341
|
-
const [expanded, setExpanded] =
|
|
7277
|
+
const [expanded, setExpanded] = React25.useState(false);
|
|
7342
7278
|
const featured = photos.slice(0, 3);
|
|
7343
7279
|
const extra = photos.slice(3);
|
|
7344
7280
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -7408,66 +7344,386 @@ function FeaturedGallery({
|
|
|
7408
7344
|
)
|
|
7409
7345
|
] });
|
|
7410
7346
|
}
|
|
7411
|
-
function
|
|
7347
|
+
function CarouselGallery({
|
|
7412
7348
|
photos,
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7349
|
+
index,
|
|
7350
|
+
onIndexChange,
|
|
7351
|
+
onOpen,
|
|
7416
7352
|
className
|
|
7417
7353
|
}) {
|
|
7418
|
-
|
|
7419
|
-
const
|
|
7420
|
-
const
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7354
|
+
var _a;
|
|
7355
|
+
const total = photos.length;
|
|
7356
|
+
const photo = photos[index];
|
|
7357
|
+
const prev = () => onIndexChange((index - 1 + total) % total);
|
|
7358
|
+
const next = () => onIndexChange((index + 1) % total);
|
|
7359
|
+
return /* @__PURE__ */ jsxs(
|
|
7360
|
+
"div",
|
|
7361
|
+
{
|
|
7362
|
+
className: cn(
|
|
7363
|
+
"relative w-full aspect-[4/3] sm:aspect-[16/10] overflow-hidden bg-muted group/photo",
|
|
7364
|
+
className
|
|
7365
|
+
),
|
|
7366
|
+
children: [
|
|
7367
|
+
/* @__PURE__ */ jsx(
|
|
7368
|
+
"button",
|
|
7369
|
+
{
|
|
7370
|
+
type: "button",
|
|
7371
|
+
onClick: () => onOpen(index),
|
|
7372
|
+
"aria-label": `Open photo ${index + 1} fullscreen`,
|
|
7373
|
+
className: "absolute inset-0 w-full h-full cursor-zoom-in focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
7374
|
+
children: /* @__PURE__ */ jsx(
|
|
7375
|
+
"img",
|
|
7376
|
+
{
|
|
7377
|
+
src: photo.src,
|
|
7378
|
+
alt: (_a = photo.alt) != null ? _a : `Photo ${index + 1}`,
|
|
7379
|
+
className: "h-full w-full object-cover transition-transform duration-500 group-hover/photo:scale-[1.02]",
|
|
7380
|
+
loading: "lazy"
|
|
7381
|
+
},
|
|
7382
|
+
photo.src
|
|
7383
|
+
)
|
|
7384
|
+
}
|
|
7385
|
+
),
|
|
7386
|
+
total > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7387
|
+
/* @__PURE__ */ jsx(
|
|
7388
|
+
"button",
|
|
7389
|
+
{
|
|
7390
|
+
type: "button",
|
|
7391
|
+
onClick: prev,
|
|
7392
|
+
"aria-label": "Previous photo",
|
|
7393
|
+
className: cn(
|
|
7394
|
+
"absolute left-3 sm:left-4 top-1/2 -translate-y-1/2 z-10",
|
|
7395
|
+
"flex h-8 w-8 items-center justify-center rounded-full",
|
|
7396
|
+
"bg-black/25 text-white backdrop-blur-sm",
|
|
7397
|
+
"hover:bg-black/45 transition-colors",
|
|
7398
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60"
|
|
7399
|
+
),
|
|
7400
|
+
children: /* @__PURE__ */ jsx(ChevronLeftIcon, { className: "h-4 w-4" })
|
|
7401
|
+
}
|
|
7402
|
+
),
|
|
7403
|
+
/* @__PURE__ */ jsx(
|
|
7404
|
+
"button",
|
|
7405
|
+
{
|
|
7406
|
+
type: "button",
|
|
7407
|
+
onClick: next,
|
|
7408
|
+
"aria-label": "Next photo",
|
|
7409
|
+
className: cn(
|
|
7410
|
+
"absolute right-3 sm:right-4 top-1/2 -translate-y-1/2 z-10",
|
|
7411
|
+
"flex h-8 w-8 items-center justify-center rounded-full",
|
|
7412
|
+
"bg-black/25 text-white backdrop-blur-sm",
|
|
7413
|
+
"hover:bg-black/45 transition-colors",
|
|
7414
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60"
|
|
7415
|
+
),
|
|
7416
|
+
children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-4 w-4" })
|
|
7417
|
+
}
|
|
7418
|
+
)
|
|
7419
|
+
] }),
|
|
7420
|
+
total > 1 && /* @__PURE__ */ jsx("div", { className: "absolute bottom-3 sm:bottom-4 inset-x-0 z-10 flex justify-center pointer-events-none", children: /* @__PURE__ */ jsx("div", { className: "pointer-events-auto flex items-center gap-1.5 rounded-full bg-black/25 backdrop-blur-sm px-2 py-1.5", children: photos.map((_, i) => /* @__PURE__ */ jsx(
|
|
7421
|
+
"button",
|
|
7422
|
+
{
|
|
7423
|
+
type: "button",
|
|
7424
|
+
onClick: () => onIndexChange(i),
|
|
7425
|
+
"aria-label": `Go to photo ${i + 1}`,
|
|
7426
|
+
className: cn(
|
|
7427
|
+
"h-1.5 rounded-full transition-all duration-300",
|
|
7428
|
+
i === index ? "w-5 bg-white" : "w-1.5 bg-white/45 hover:bg-white/75"
|
|
7429
|
+
)
|
|
7430
|
+
},
|
|
7431
|
+
i
|
|
7432
|
+
)) }) })
|
|
7433
|
+
]
|
|
7434
|
+
}
|
|
7435
|
+
);
|
|
7436
|
+
}
|
|
7437
|
+
function PhotoGallery({
|
|
7438
|
+
photos,
|
|
7439
|
+
variant = "grid",
|
|
7440
|
+
initialVisible = 6,
|
|
7441
|
+
onPhotoClick,
|
|
7442
|
+
className
|
|
7443
|
+
}) {
|
|
7444
|
+
const [lightboxIndex, setLightboxIndex] = React25.useState(null);
|
|
7445
|
+
const [carouselIndex, setCarouselIndex] = React25.useState(0);
|
|
7446
|
+
const normalised = React25.useMemo(() => photos.map(normalise), [photos]);
|
|
7447
|
+
const handleOpen = (index) => {
|
|
7448
|
+
setLightboxIndex(index);
|
|
7449
|
+
onPhotoClick == null ? void 0 : onPhotoClick(normalised[index].src, index);
|
|
7450
|
+
};
|
|
7451
|
+
if (normalised.length === 0) return null;
|
|
7452
|
+
const lightbox = lightboxIndex !== null && /* @__PURE__ */ jsx(
|
|
7453
|
+
Lightbox,
|
|
7454
|
+
{
|
|
7455
|
+
photos: normalised,
|
|
7456
|
+
initialIndex: lightboxIndex,
|
|
7457
|
+
onClose: () => setLightboxIndex(null)
|
|
7458
|
+
}
|
|
7459
|
+
);
|
|
7460
|
+
if (variant === "carousel" || variant === "fullBleed") {
|
|
7461
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7462
|
+
/* @__PURE__ */ jsx(
|
|
7463
|
+
CarouselGallery,
|
|
7464
|
+
{
|
|
7465
|
+
photos: normalised,
|
|
7466
|
+
index: carouselIndex,
|
|
7467
|
+
onIndexChange: setCarouselIndex,
|
|
7468
|
+
onOpen: handleOpen,
|
|
7469
|
+
className: cn(
|
|
7470
|
+
variant === "carousel" && "rounded-2xl",
|
|
7471
|
+
variant === "fullBleed" && "w-screen mx-[calc(50%-50vw)] lg:w-full lg:mx-0",
|
|
7472
|
+
className
|
|
7473
|
+
)
|
|
7474
|
+
}
|
|
7475
|
+
),
|
|
7476
|
+
lightbox
|
|
7477
|
+
] });
|
|
7478
|
+
}
|
|
7479
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
|
|
7480
|
+
variant === "grid" && /* @__PURE__ */ jsx(
|
|
7481
|
+
GridGallery,
|
|
7482
|
+
{
|
|
7483
|
+
photos: normalised,
|
|
7484
|
+
initialVisible,
|
|
7485
|
+
onOpen: handleOpen
|
|
7486
|
+
}
|
|
7487
|
+
),
|
|
7488
|
+
variant === "masonry" && /* @__PURE__ */ jsx(
|
|
7489
|
+
MasonryGallery,
|
|
7490
|
+
{
|
|
7491
|
+
photos: normalised,
|
|
7492
|
+
initialVisible,
|
|
7493
|
+
onOpen: handleOpen
|
|
7494
|
+
}
|
|
7495
|
+
),
|
|
7496
|
+
variant === "filmstrip" && /* @__PURE__ */ jsx(FilmstripGallery, { photos: normalised, onOpen: handleOpen }),
|
|
7497
|
+
variant === "featured" && /* @__PURE__ */ jsx(FeaturedGallery, { photos: normalised, onOpen: handleOpen }),
|
|
7498
|
+
lightbox
|
|
7499
|
+
] });
|
|
7500
|
+
}
|
|
7501
|
+
var itineraryDaySpecIcons = {
|
|
7502
|
+
hiking: /* @__PURE__ */ jsx(FootprintsIcon, { className: "h-5 w-5", strokeWidth: 1.75 }),
|
|
7503
|
+
swimming: /* @__PURE__ */ jsx(WavesIcon, { className: "h-5 w-5", strokeWidth: 1.75 }),
|
|
7504
|
+
driving: /* @__PURE__ */ jsx(CarIcon, { className: "h-5 w-5", strokeWidth: 1.75 }),
|
|
7505
|
+
boat: /* @__PURE__ */ jsx(SailboatIcon, { className: "h-5 w-5", strokeWidth: 1.75 }),
|
|
7506
|
+
lodging: /* @__PURE__ */ jsx(HomeIcon, { className: "h-5 w-5", strokeWidth: 1.75 })
|
|
7507
|
+
};
|
|
7508
|
+
function normalisePhotos(input) {
|
|
7509
|
+
const list = Array.isArray(input) ? input : [input];
|
|
7510
|
+
return list.filter(Boolean).map((p) => typeof p === "string" ? { src: p } : p);
|
|
7511
|
+
}
|
|
7512
|
+
function ItineraryDay({
|
|
7513
|
+
dayNumber,
|
|
7514
|
+
dayLabel,
|
|
7515
|
+
title,
|
|
7516
|
+
photos,
|
|
7517
|
+
specs,
|
|
7518
|
+
description,
|
|
7519
|
+
photoLayout = "rounded",
|
|
7520
|
+
className
|
|
7521
|
+
}) {
|
|
7522
|
+
const photoList = React25.useMemo(() => normalisePhotos(photos), [photos]);
|
|
7523
|
+
const isFullBleed = photoLayout === "fullBleed" || photoLayout === "fullBleedBottom";
|
|
7524
|
+
const photoPosition = photoLayout === "fullBleedBottom" ? "bottom" : "top";
|
|
7525
|
+
const gallery = photoList.length > 0 && /* @__PURE__ */ jsx(
|
|
7526
|
+
PhotoGallery,
|
|
7527
|
+
{
|
|
7528
|
+
photos: photoList,
|
|
7529
|
+
variant: isFullBleed ? "fullBleed" : "carousel"
|
|
7530
|
+
}
|
|
7531
|
+
);
|
|
7532
|
+
return /* @__PURE__ */ jsxs("article", { className: cn("w-full flex flex-col gap-5", className), children: [
|
|
7533
|
+
photoPosition === "top" && gallery,
|
|
7534
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-2", children: [
|
|
7535
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-widest text-muted-foreground font-ui", children: dayLabel != null ? dayLabel : `Day ${dayNumber}` }),
|
|
7536
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground leading-tight font-heading", children: title })
|
|
7537
|
+
] }),
|
|
7538
|
+
specs && specs.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-3 sm:gap-2.5", children: specs.map((spec, i) => /* @__PURE__ */ jsxs(
|
|
7539
|
+
"li",
|
|
7540
|
+
{
|
|
7541
|
+
className: "flex items-start gap-3 text-base text-foreground font-ui",
|
|
7542
|
+
children: [
|
|
7543
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true, children: spec.icon }),
|
|
7544
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
7545
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [
|
|
7546
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: spec.label }),
|
|
7547
|
+
spec.detail && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: spec.detail })
|
|
7548
|
+
] }),
|
|
7549
|
+
spec.subdetail && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: spec.subdetail })
|
|
7550
|
+
] })
|
|
7551
|
+
]
|
|
7552
|
+
},
|
|
7553
|
+
i
|
|
7554
|
+
)) }),
|
|
7555
|
+
description && /* @__PURE__ */ jsx(
|
|
7556
|
+
"div",
|
|
7557
|
+
{
|
|
7558
|
+
className: cn(
|
|
7559
|
+
"text-base text-foreground/85 leading-relaxed space-y-3",
|
|
7560
|
+
"[&_strong]:font-semibold [&_strong]:text-foreground",
|
|
7561
|
+
"[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2 hover:[&_a]:no-underline"
|
|
7562
|
+
),
|
|
7563
|
+
children: description
|
|
7564
|
+
}
|
|
7565
|
+
),
|
|
7566
|
+
photoPosition === "bottom" && gallery
|
|
7567
|
+
] });
|
|
7568
|
+
}
|
|
7569
|
+
function MenuTrip({
|
|
7570
|
+
sections,
|
|
7571
|
+
activeSection,
|
|
7572
|
+
onSelect,
|
|
7573
|
+
variant = "pill",
|
|
7574
|
+
bold = true,
|
|
7575
|
+
className
|
|
7576
|
+
}) {
|
|
7577
|
+
const scrollRef = React25.useRef(null);
|
|
7578
|
+
React25.useEffect(() => {
|
|
7579
|
+
if (!scrollRef.current || !activeSection) return;
|
|
7580
|
+
const container = scrollRef.current;
|
|
7581
|
+
const btn = container.querySelector(
|
|
7582
|
+
`[data-section="${activeSection}"]`
|
|
7583
|
+
);
|
|
7584
|
+
if (!btn) return;
|
|
7585
|
+
const btnLeft = btn.offsetLeft;
|
|
7586
|
+
const btnRight = btnLeft + btn.offsetWidth;
|
|
7587
|
+
const cLeft = container.scrollLeft;
|
|
7588
|
+
const cRight = cLeft + container.offsetWidth;
|
|
7589
|
+
if (btnLeft < cLeft) {
|
|
7590
|
+
container.scrollTo({ left: btnLeft - 16, behavior: "smooth" });
|
|
7591
|
+
} else if (btnRight > cRight) {
|
|
7592
|
+
container.scrollTo({ left: btnRight - container.offsetWidth + 16, behavior: "smooth" });
|
|
7593
|
+
}
|
|
7594
|
+
}, [activeSection]);
|
|
7595
|
+
if (variant === "underline") {
|
|
7596
|
+
return /* @__PURE__ */ jsx(
|
|
7597
|
+
"div",
|
|
7598
|
+
{
|
|
7599
|
+
ref: scrollRef,
|
|
7600
|
+
className: cn(
|
|
7601
|
+
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
7602
|
+
"border-b border-border",
|
|
7603
|
+
className
|
|
7604
|
+
),
|
|
7605
|
+
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-end gap-0", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
7606
|
+
"button",
|
|
7607
|
+
{
|
|
7608
|
+
"data-section": s.id,
|
|
7609
|
+
type: "button",
|
|
7610
|
+
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
7611
|
+
className: cn(
|
|
7612
|
+
"relative px-4 py-2.5 text-sm font-ui whitespace-nowrap transition-colors duration-150",
|
|
7613
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
7614
|
+
"after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:rounded-full after:transition-all",
|
|
7615
|
+
bold ? "font-semibold" : "font-normal",
|
|
7616
|
+
activeSection === s.id ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent"
|
|
7617
|
+
),
|
|
7618
|
+
children: s.label
|
|
7619
|
+
},
|
|
7620
|
+
s.id
|
|
7621
|
+
)) })
|
|
7622
|
+
}
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
7625
|
+
if (variant === "outlined") {
|
|
7626
|
+
return /* @__PURE__ */ jsx(
|
|
7627
|
+
"div",
|
|
7628
|
+
{
|
|
7629
|
+
ref: scrollRef,
|
|
7630
|
+
className: cn(
|
|
7631
|
+
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
7632
|
+
className
|
|
7633
|
+
),
|
|
7634
|
+
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-2", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
7635
|
+
"button",
|
|
7636
|
+
{
|
|
7637
|
+
"data-section": s.id,
|
|
7638
|
+
type: "button",
|
|
7639
|
+
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
7640
|
+
className: cn(
|
|
7641
|
+
"rounded-full border px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
7642
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7643
|
+
bold ? "font-semibold" : "font-normal",
|
|
7644
|
+
activeSection === s.id ? "border-foreground bg-foreground text-background" : "border-border bg-background text-muted-foreground hover:border-foreground/50 hover:text-foreground"
|
|
7645
|
+
),
|
|
7646
|
+
children: s.label
|
|
7647
|
+
},
|
|
7648
|
+
s.id
|
|
7649
|
+
)) })
|
|
7650
|
+
}
|
|
7651
|
+
);
|
|
7652
|
+
}
|
|
7653
|
+
if (variant === "floating") {
|
|
7654
|
+
return /* @__PURE__ */ jsx(
|
|
7655
|
+
"div",
|
|
7656
|
+
{
|
|
7657
|
+
ref: scrollRef,
|
|
7658
|
+
className: cn(
|
|
7659
|
+
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
7660
|
+
"py-1 px-0.5",
|
|
7661
|
+
/* padding so shadow isn't clipped by overflow */
|
|
7662
|
+
className
|
|
7663
|
+
),
|
|
7664
|
+
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-0.5 rounded-full border border-border/40 bg-background/90 backdrop-blur-md shadow-sm px-1.5 py-1.5", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
7665
|
+
"button",
|
|
7666
|
+
{
|
|
7667
|
+
"data-section": s.id,
|
|
7668
|
+
type: "button",
|
|
7669
|
+
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
7670
|
+
className: cn(
|
|
7671
|
+
"rounded-full px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
7672
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7673
|
+
bold ? "font-semibold" : "font-normal",
|
|
7674
|
+
activeSection === s.id ? "bg-foreground text-background shadow-sm" : "text-foreground/60 hover:text-foreground hover:bg-muted/60"
|
|
7675
|
+
),
|
|
7676
|
+
children: s.label
|
|
7677
|
+
},
|
|
7678
|
+
s.id
|
|
7679
|
+
)) })
|
|
7680
|
+
}
|
|
7681
|
+
);
|
|
7682
|
+
}
|
|
7683
|
+
return /* @__PURE__ */ jsx(
|
|
7684
|
+
"div",
|
|
7685
|
+
{
|
|
7686
|
+
ref: scrollRef,
|
|
7687
|
+
className: cn(
|
|
7688
|
+
"overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
|
|
7689
|
+
className
|
|
7690
|
+
),
|
|
7691
|
+
children: /* @__PURE__ */ jsx("div", { className: "inline-flex min-w-max items-center gap-1 p-1", children: sections.map((s) => /* @__PURE__ */ jsx(
|
|
7692
|
+
"button",
|
|
7693
|
+
{
|
|
7694
|
+
"data-section": s.id,
|
|
7695
|
+
type: "button",
|
|
7696
|
+
onClick: () => onSelect == null ? void 0 : onSelect(s.id),
|
|
7697
|
+
className: cn(
|
|
7698
|
+
"rounded-full px-4 py-1.5 text-sm font-ui whitespace-nowrap transition-all duration-150",
|
|
7699
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7700
|
+
bold ? "font-semibold" : "font-normal",
|
|
7701
|
+
activeSection === s.id ? "bg-foreground text-background shadow-sm" : "bg-white text-foreground/70 hover:text-foreground shadow-sm"
|
|
7702
|
+
),
|
|
7703
|
+
children: s.label
|
|
7704
|
+
},
|
|
7705
|
+
s.id
|
|
7706
|
+
)) })
|
|
7707
|
+
}
|
|
7708
|
+
);
|
|
7709
|
+
}
|
|
7710
|
+
var badgeVariants = cva(
|
|
7711
|
+
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
|
|
7712
|
+
{
|
|
7713
|
+
variants: {
|
|
7714
|
+
variant: {
|
|
7715
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
7716
|
+
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
7717
|
+
destructive: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
|
|
7718
|
+
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
|
7719
|
+
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
7720
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
7721
|
+
}
|
|
7722
|
+
},
|
|
7723
|
+
defaultVariants: {
|
|
7724
|
+
variant: "default"
|
|
7725
|
+
}
|
|
7726
|
+
}
|
|
7471
7727
|
);
|
|
7472
7728
|
function Badge(_a) {
|
|
7473
7729
|
var _b = _a, {
|
|
@@ -7499,34 +7755,124 @@ function PricingTrip({
|
|
|
7499
7755
|
currency = "CHF",
|
|
7500
7756
|
season,
|
|
7501
7757
|
departureTimes,
|
|
7502
|
-
pricingOptions,
|
|
7503
7758
|
onBook,
|
|
7504
7759
|
bookLabel = "Check availability",
|
|
7505
7760
|
variant = "card",
|
|
7761
|
+
sharp = false,
|
|
7762
|
+
belowPrice,
|
|
7763
|
+
benefits,
|
|
7764
|
+
currencyEstimates,
|
|
7765
|
+
priceInfo,
|
|
7506
7766
|
className
|
|
7507
7767
|
}) {
|
|
7508
|
-
const
|
|
7768
|
+
const rOuter = sharp ? "rounded-none" : "rounded-2xl";
|
|
7769
|
+
const [showEstimates, setShowEstimates] = React25.useState(false);
|
|
7770
|
+
const [showPriceInfo, setShowPriceInfo] = React25.useState(false);
|
|
7509
7771
|
if (variant === "compact") {
|
|
7510
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex
|
|
7511
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7512
|
-
/* @__PURE__ */
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7772
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
|
|
7773
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7774
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
7775
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] uppercase tracking-wide text-muted-foreground font-ui leading-none mb-0.5", children: "from" }),
|
|
7776
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5 flex-wrap", children: [
|
|
7777
|
+
/* @__PURE__ */ jsxs("p", { className: "text-lg font-bold text-foreground font-heading leading-none", children: [
|
|
7778
|
+
currency,
|
|
7779
|
+
" ",
|
|
7780
|
+
priceFrom,
|
|
7781
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-normal text-muted-foreground font-ui ml-1", children: "/ per person" })
|
|
7782
|
+
] }),
|
|
7783
|
+
(priceInfo || currencyEstimates && currencyEstimates.length > 0) && /* @__PURE__ */ jsx(
|
|
7784
|
+
"button",
|
|
7785
|
+
{
|
|
7786
|
+
type: "button",
|
|
7787
|
+
onClick: () => setShowPriceInfo((v) => !v),
|
|
7788
|
+
"aria-label": "Price details and currency estimates",
|
|
7789
|
+
"aria-expanded": showPriceInfo,
|
|
7790
|
+
className: cn(
|
|
7791
|
+
"inline-flex h-4 w-4 items-center justify-center rounded-full translate-y-px",
|
|
7792
|
+
"text-muted-foreground hover:text-foreground transition-colors",
|
|
7793
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7794
|
+
),
|
|
7795
|
+
children: /* @__PURE__ */ jsx(
|
|
7796
|
+
ChevronDownIcon,
|
|
7797
|
+
{
|
|
7798
|
+
className: cn(
|
|
7799
|
+
"h-4 w-4 transition-transform",
|
|
7800
|
+
showPriceInfo && "rotate-180"
|
|
7801
|
+
)
|
|
7802
|
+
}
|
|
7803
|
+
)
|
|
7804
|
+
}
|
|
7805
|
+
)
|
|
7806
|
+
] })
|
|
7807
|
+
] }),
|
|
7808
|
+
/* @__PURE__ */ jsx(
|
|
7809
|
+
"button",
|
|
7810
|
+
{
|
|
7811
|
+
type: "button",
|
|
7812
|
+
onClick: onBook,
|
|
7813
|
+
className: cn(
|
|
7814
|
+
"shrink-0 rounded-full bg-primary px-5 py-2 text-sm font-semibold",
|
|
7815
|
+
"text-primary-foreground font-ui transition-colors hover:bg-primary/90",
|
|
7816
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7817
|
+
),
|
|
7818
|
+
children: bookLabel
|
|
7819
|
+
}
|
|
7820
|
+
)
|
|
7518
7821
|
] }),
|
|
7519
|
-
/* @__PURE__ */
|
|
7520
|
-
"
|
|
7822
|
+
showPriceInfo && (priceInfo || currencyEstimates && currencyEstimates.length > 0) && /* @__PURE__ */ jsxs(
|
|
7823
|
+
"div",
|
|
7521
7824
|
{
|
|
7522
|
-
type: "button",
|
|
7523
|
-
onClick: onBook,
|
|
7524
7825
|
className: cn(
|
|
7525
|
-
"
|
|
7526
|
-
"
|
|
7527
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7826
|
+
"rounded-xl border border-border bg-muted/40 overflow-hidden",
|
|
7827
|
+
"font-ui text-sm leading-relaxed text-foreground"
|
|
7528
7828
|
),
|
|
7529
|
-
children:
|
|
7829
|
+
children: [
|
|
7830
|
+
priceInfo && /* @__PURE__ */ jsx(
|
|
7831
|
+
"div",
|
|
7832
|
+
{
|
|
7833
|
+
className: cn(
|
|
7834
|
+
"p-3",
|
|
7835
|
+
"[&_a]:font-semibold [&_a]:text-primary [&_a]:underline-offset-4",
|
|
7836
|
+
"[&_a]:underline [&_a]:decoration-primary/30 hover:[&_a]:decoration-primary"
|
|
7837
|
+
),
|
|
7838
|
+
children: priceInfo
|
|
7839
|
+
}
|
|
7840
|
+
),
|
|
7841
|
+
currencyEstimates && currencyEstimates.length > 0 && /* @__PURE__ */ jsxs(
|
|
7842
|
+
"div",
|
|
7843
|
+
{
|
|
7844
|
+
className: cn(
|
|
7845
|
+
"bg-background",
|
|
7846
|
+
priceInfo && "border-t border-border"
|
|
7847
|
+
),
|
|
7848
|
+
children: [
|
|
7849
|
+
/* @__PURE__ */ jsx("p", { className: "px-3 pt-3 pb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "See estimates in other currencies" }),
|
|
7850
|
+
currencyEstimates.map((est, i) => /* @__PURE__ */ jsxs(
|
|
7851
|
+
"div",
|
|
7852
|
+
{
|
|
7853
|
+
className: cn(
|
|
7854
|
+
"flex items-center justify-between px-3 py-2 text-sm",
|
|
7855
|
+
"border-t border-border"
|
|
7856
|
+
),
|
|
7857
|
+
children: [
|
|
7858
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: est.currency }),
|
|
7859
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-foreground", children: [
|
|
7860
|
+
est.symbol ? `${est.symbol} ` : "",
|
|
7861
|
+
est.price
|
|
7862
|
+
] })
|
|
7863
|
+
]
|
|
7864
|
+
},
|
|
7865
|
+
i
|
|
7866
|
+
)),
|
|
7867
|
+
/* @__PURE__ */ jsxs("p", { className: "px-3 py-2 text-[11px] leading-snug text-muted-foreground bg-muted/40 italic border-t border-border", children: [
|
|
7868
|
+
"Estimates based on the current exchange rate. The final price charged is in ",
|
|
7869
|
+
currency,
|
|
7870
|
+
"."
|
|
7871
|
+
] })
|
|
7872
|
+
]
|
|
7873
|
+
}
|
|
7874
|
+
)
|
|
7875
|
+
]
|
|
7530
7876
|
}
|
|
7531
7877
|
)
|
|
7532
7878
|
] });
|
|
@@ -7536,7 +7882,8 @@ function PricingTrip({
|
|
|
7536
7882
|
"div",
|
|
7537
7883
|
{
|
|
7538
7884
|
className: cn(
|
|
7539
|
-
"flex items-center gap-4
|
|
7885
|
+
"flex items-center gap-4 border border-border bg-card px-5 py-3 shadow-sm",
|
|
7886
|
+
rOuter,
|
|
7540
7887
|
className
|
|
7541
7888
|
),
|
|
7542
7889
|
children: [
|
|
@@ -7580,67 +7927,103 @@ function PricingTrip({
|
|
|
7580
7927
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", className), children: [
|
|
7581
7928
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
7582
7929
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui uppercase tracking-wide", children: "From" }),
|
|
7583
|
-
/* @__PURE__ */ jsxs("p", { className: "text-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7930
|
+
/* @__PURE__ */ jsxs("p", { className: "text-2xl font-bold text-foreground font-heading flex items-center gap-2 flex-wrap", children: [
|
|
7931
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
7932
|
+
currency,
|
|
7933
|
+
" ",
|
|
7934
|
+
priceFrom,
|
|
7935
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-normal text-muted-foreground font-ui", children: " / per person" })
|
|
7936
|
+
] }),
|
|
7937
|
+
priceInfo && /* @__PURE__ */ jsx(
|
|
7938
|
+
"button",
|
|
7939
|
+
{
|
|
7940
|
+
type: "button",
|
|
7941
|
+
onClick: () => setShowPriceInfo((v) => !v),
|
|
7942
|
+
"aria-label": "Why does the price vary?",
|
|
7943
|
+
"aria-expanded": showPriceInfo,
|
|
7944
|
+
className: cn(
|
|
7945
|
+
"inline-flex h-5 w-5 items-center justify-center rounded-full",
|
|
7946
|
+
"translate-y-[3px] -translate-x-[3px]",
|
|
7947
|
+
"text-muted-foreground hover:text-foreground transition-colors",
|
|
7948
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
7949
|
+
),
|
|
7950
|
+
children: /* @__PURE__ */ jsx(
|
|
7951
|
+
ChevronDownIcon,
|
|
7952
|
+
{
|
|
7953
|
+
className: cn(
|
|
7954
|
+
"h-4 w-4 transition-transform",
|
|
7955
|
+
showPriceInfo && "rotate-180"
|
|
7956
|
+
)
|
|
7957
|
+
}
|
|
7958
|
+
)
|
|
7959
|
+
}
|
|
7960
|
+
)
|
|
7588
7961
|
] })
|
|
7589
7962
|
] }),
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7963
|
+
priceInfo && showPriceInfo && /* @__PURE__ */ jsx(
|
|
7964
|
+
"div",
|
|
7965
|
+
{
|
|
7966
|
+
className: cn(
|
|
7967
|
+
"rounded-xl border border-border bg-muted/40 p-4",
|
|
7968
|
+
"font-ui text-sm leading-relaxed text-foreground",
|
|
7969
|
+
"[&_a]:font-semibold [&_a]:text-primary [&_a]:underline-offset-4",
|
|
7970
|
+
"[&_a]:underline [&_a]:decoration-primary/30 hover:[&_a]:decoration-primary"
|
|
7971
|
+
),
|
|
7972
|
+
children: priceInfo
|
|
7973
|
+
}
|
|
7974
|
+
),
|
|
7975
|
+
belowPrice && /* @__PURE__ */ jsx("div", { children: belowPrice }),
|
|
7976
|
+
benefits && benefits.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: benefits.map((b, i) => /* @__PURE__ */ jsxs(
|
|
7977
|
+
"li",
|
|
7978
|
+
{
|
|
7979
|
+
className: "flex items-start gap-2.5 text-sm text-foreground font-ui",
|
|
7980
|
+
children: [
|
|
7981
|
+
/* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4 shrink-0 text-primary mt-0.5" }),
|
|
7982
|
+
b
|
|
7983
|
+
]
|
|
7984
|
+
},
|
|
7985
|
+
i
|
|
7986
|
+
)) }),
|
|
7987
|
+
currencyEstimates && currencyEstimates.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
7599
7988
|
/* @__PURE__ */ jsx(
|
|
7600
7989
|
"button",
|
|
7601
7990
|
{
|
|
7602
7991
|
type: "button",
|
|
7603
|
-
onClick: () =>
|
|
7992
|
+
onClick: () => setShowEstimates((v) => !v),
|
|
7604
7993
|
className: "flex items-center gap-1 text-xs text-primary font-ui text-left hover:underline underline-offset-2",
|
|
7605
|
-
children:
|
|
7606
|
-
"
|
|
7994
|
+
children: showEstimates ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7995
|
+
"Hide estimates in other currencies ",
|
|
7607
7996
|
/* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-3 w-3" })
|
|
7608
7997
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7609
|
-
"Show
|
|
7998
|
+
"Show estimates in other currencies ",
|
|
7610
7999
|
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3 w-3" })
|
|
7611
8000
|
] })
|
|
7612
8001
|
}
|
|
7613
8002
|
),
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
opt.originalPrice
|
|
7628
|
-
] }),
|
|
7629
|
-
/* @__PURE__ */ jsxs("span", { className: "font-bold text-foreground font-ui", children: [
|
|
7630
|
-
currency,
|
|
7631
|
-
" ",
|
|
7632
|
-
opt.price,
|
|
7633
|
-
opt.unit && /* @__PURE__ */ jsxs("span", { className: "text-xs font-normal text-muted-foreground", children: [
|
|
7634
|
-
" ",
|
|
7635
|
-
"/ ",
|
|
7636
|
-
opt.unit
|
|
7637
|
-
] })
|
|
8003
|
+
showEstimates && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border overflow-hidden", children: [
|
|
8004
|
+
currencyEstimates.map((est, i) => /* @__PURE__ */ jsxs(
|
|
8005
|
+
"div",
|
|
8006
|
+
{
|
|
8007
|
+
className: cn(
|
|
8008
|
+
"flex items-center justify-between px-3 py-2 text-sm font-ui",
|
|
8009
|
+
i < currencyEstimates.length - 1 && "border-b border-border"
|
|
8010
|
+
),
|
|
8011
|
+
children: [
|
|
8012
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: est.currency }),
|
|
8013
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-foreground", children: [
|
|
8014
|
+
est.symbol ? `${est.symbol} ` : "",
|
|
8015
|
+
est.price
|
|
7638
8016
|
] })
|
|
7639
|
-
]
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
8017
|
+
]
|
|
8018
|
+
},
|
|
8019
|
+
i
|
|
8020
|
+
)),
|
|
8021
|
+
/* @__PURE__ */ jsxs("p", { className: "px-3 py-2 text-[11px] leading-snug text-muted-foreground bg-muted/40 italic font-ui border-t border-border", children: [
|
|
8022
|
+
"Estimates based on the current exchange rate. The final price charged is in ",
|
|
8023
|
+
currency,
|
|
8024
|
+
"."
|
|
8025
|
+
] })
|
|
8026
|
+
] })
|
|
7644
8027
|
] }),
|
|
7645
8028
|
/* @__PURE__ */ jsx(
|
|
7646
8029
|
"button",
|
|
@@ -7828,14 +8211,14 @@ function SiteHeader({
|
|
|
7828
8211
|
className
|
|
7829
8212
|
}) {
|
|
7830
8213
|
const t = VARIANT[variant];
|
|
7831
|
-
const [openMenu, setOpenMenu] =
|
|
7832
|
-
const [langOpen, setLangOpen] =
|
|
7833
|
-
const [mobileOpen, setMobileOpen] =
|
|
7834
|
-
const [openMobileSection, setOpenMobileSection] =
|
|
7835
|
-
const [activeLang, setActiveLang] =
|
|
8214
|
+
const [openMenu, setOpenMenu] = React25.useState(null);
|
|
8215
|
+
const [langOpen, setLangOpen] = React25.useState(false);
|
|
8216
|
+
const [mobileOpen, setMobileOpen] = React25.useState(false);
|
|
8217
|
+
const [openMobileSection, setOpenMobileSection] = React25.useState(null);
|
|
8218
|
+
const [activeLang, setActiveLang] = React25.useState(currentLanguage);
|
|
7836
8219
|
const toggleMobileSection = (label) => setOpenMobileSection((prev) => prev === label ? null : label);
|
|
7837
|
-
const menuCloseTimer =
|
|
7838
|
-
const langCloseTimer =
|
|
8220
|
+
const menuCloseTimer = React25.useRef(void 0);
|
|
8221
|
+
const langCloseTimer = React25.useRef(void 0);
|
|
7839
8222
|
const handleMenuEnter = (label) => {
|
|
7840
8223
|
clearTimeout(menuCloseTimer.current);
|
|
7841
8224
|
setOpenMenu(label);
|
|
@@ -7856,7 +8239,7 @@ function SiteHeader({
|
|
|
7856
8239
|
setOpenMenu(null);
|
|
7857
8240
|
setLangOpen(false);
|
|
7858
8241
|
};
|
|
7859
|
-
|
|
8242
|
+
React25.useEffect(() => () => {
|
|
7860
8243
|
clearTimeout(menuCloseTimer.current);
|
|
7861
8244
|
clearTimeout(langCloseTimer.current);
|
|
7862
8245
|
}, []);
|
|
@@ -8121,7 +8504,7 @@ function SiteHeader({
|
|
|
8121
8504
|
), children: [
|
|
8122
8505
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: languages.map((lang, i) => {
|
|
8123
8506
|
const isActive = lang.code === activeLang;
|
|
8124
|
-
return /* @__PURE__ */ jsxs(
|
|
8507
|
+
return /* @__PURE__ */ jsxs(React25.Fragment, { children: [
|
|
8125
8508
|
i > 0 && /* @__PURE__ */ jsx("span", { className: cn(
|
|
8126
8509
|
"text-xs select-none",
|
|
8127
8510
|
variant === "white" ? "text-border" : "text-white/15"
|
|
@@ -8183,8 +8566,8 @@ function SiteHeader({
|
|
|
8183
8566
|
);
|
|
8184
8567
|
}
|
|
8185
8568
|
function ThemeToggle({ className }) {
|
|
8186
|
-
const [dark, setDark] =
|
|
8187
|
-
|
|
8569
|
+
const [dark, setDark] = React25.useState(false);
|
|
8570
|
+
React25.useEffect(() => {
|
|
8188
8571
|
const saved = localStorage.getItem("theme");
|
|
8189
8572
|
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
8190
8573
|
const isDark = saved === "dark" || !saved && prefersDark;
|
|
@@ -8335,7 +8718,7 @@ function TripCard({
|
|
|
8335
8718
|
);
|
|
8336
8719
|
}
|
|
8337
8720
|
function useHlsVideo(videoRef, src) {
|
|
8338
|
-
|
|
8721
|
+
React25.useEffect(() => {
|
|
8339
8722
|
if (!src || !videoRef.current) return;
|
|
8340
8723
|
const video = videoRef.current;
|
|
8341
8724
|
if (!src.includes(".m3u8")) return;
|
|
@@ -8372,16 +8755,17 @@ function TripHeader({
|
|
|
8372
8755
|
destination,
|
|
8373
8756
|
duration,
|
|
8374
8757
|
tagline,
|
|
8758
|
+
belowMeta,
|
|
8375
8759
|
siteHeader,
|
|
8376
8760
|
uiVariant = "v1",
|
|
8377
8761
|
className
|
|
8378
8762
|
}) {
|
|
8379
8763
|
var _a;
|
|
8380
|
-
const [heroIndex, setHeroIndex] =
|
|
8381
|
-
const [videoReady, setVideoReady] =
|
|
8382
|
-
const videoRef =
|
|
8764
|
+
const [heroIndex, setHeroIndex] = React25.useState(0);
|
|
8765
|
+
const [videoReady, setVideoReady] = React25.useState(false);
|
|
8766
|
+
const videoRef = React25.useRef(null);
|
|
8383
8767
|
const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
|
|
8384
|
-
const validImages =
|
|
8768
|
+
const validImages = React25.useMemo(
|
|
8385
8769
|
() => images.map((u) => u == null ? void 0 : u.trim()).filter(Boolean),
|
|
8386
8770
|
[images]
|
|
8387
8771
|
);
|
|
@@ -8396,7 +8780,7 @@ function TripHeader({
|
|
|
8396
8780
|
const nights = duration ? (_a = duration.nights) != null ? _a : Math.max(duration.days - 1, 1) : null;
|
|
8397
8781
|
const hasMeta = !!(destination || duration);
|
|
8398
8782
|
useHlsVideo(videoRef, isHls ? videoUrl : void 0);
|
|
8399
|
-
|
|
8783
|
+
React25.useEffect(() => {
|
|
8400
8784
|
if (!videoUrl) return;
|
|
8401
8785
|
const el = videoRef.current;
|
|
8402
8786
|
if (!el) return;
|
|
@@ -8538,7 +8922,7 @@ function TripHeader({
|
|
|
8538
8922
|
siteHeader ? "-mt-44" : "-mt-36"
|
|
8539
8923
|
),
|
|
8540
8924
|
children: [
|
|
8541
|
-
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(
|
|
8925
|
+
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(React25.Fragment, { children: [
|
|
8542
8926
|
i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
|
|
8543
8927
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui hover:text-white/90 cursor-default", children: crumb.label })
|
|
8544
8928
|
] }, i)) }),
|
|
@@ -8563,7 +8947,8 @@ function TripHeader({
|
|
|
8563
8947
|
duration.days === 1 ? "dia" : "dias"
|
|
8564
8948
|
] })
|
|
8565
8949
|
] })
|
|
8566
|
-
] }) : tagline ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm sm:text-base text-white/80 font-ui", children: tagline }) : null
|
|
8950
|
+
] }) : tagline ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm sm:text-base text-white/80 font-ui", children: tagline }) : null,
|
|
8951
|
+
belowMeta && /* @__PURE__ */ jsx("div", { className: "mt-3", children: belowMeta })
|
|
8567
8952
|
]
|
|
8568
8953
|
}
|
|
8569
8954
|
) })
|
|
@@ -8596,12 +8981,12 @@ function ItineraryTimeline({ steps }) {
|
|
|
8596
8981
|
] }),
|
|
8597
8982
|
step.isTransfer && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs font-ui h-5 px-2", children: "Transfer" })
|
|
8598
8983
|
] }),
|
|
8599
|
-
/* @__PURE__ */ jsx("div", { className: "text-
|
|
8984
|
+
/* @__PURE__ */ jsx("div", { className: "text-base text-muted-foreground leading-relaxed [&_p:not(:last-child)]:mb-2 [&_strong]:text-foreground [&_strong]:font-semibold", children: step.description })
|
|
8600
8985
|
] })
|
|
8601
8986
|
] }, i)) });
|
|
8602
8987
|
}
|
|
8603
8988
|
function Checklist({ items, icon }) {
|
|
8604
|
-
return /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2.5 text-
|
|
8989
|
+
return /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2.5 text-base text-foreground", children: [
|
|
8605
8990
|
/* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 text-primary", children: icon != null ? icon : /* @__PURE__ */ jsx(CheckIcon, { className: "h-4 w-4" }) }),
|
|
8606
8991
|
item
|
|
8607
8992
|
] }, i)) });
|
|
@@ -8616,21 +9001,36 @@ function TripPage({
|
|
|
8616
9001
|
breadcrumb,
|
|
8617
9002
|
highlights,
|
|
8618
9003
|
infoGroups,
|
|
9004
|
+
keyInfo,
|
|
8619
9005
|
recommendedFor,
|
|
8620
9006
|
overview,
|
|
9007
|
+
overviewHighlights,
|
|
8621
9008
|
itinerary,
|
|
9009
|
+
itineraryDays,
|
|
8622
9010
|
gallery,
|
|
8623
9011
|
included,
|
|
9012
|
+
notIncluded,
|
|
8624
9013
|
whatToBring,
|
|
8625
9014
|
weather,
|
|
9015
|
+
optionalExtras,
|
|
9016
|
+
accommodation,
|
|
9017
|
+
food,
|
|
9018
|
+
termsAndConditions,
|
|
8626
9019
|
meetingPoints,
|
|
9020
|
+
meetingPoint,
|
|
8627
9021
|
faqs,
|
|
9022
|
+
sectionIcons,
|
|
8628
9023
|
reviews,
|
|
9024
|
+
trustpilot,
|
|
9025
|
+
trustpilotMini,
|
|
9026
|
+
trustpilotHero,
|
|
8629
9027
|
priceFrom,
|
|
8630
9028
|
currency = "CHF",
|
|
8631
9029
|
season,
|
|
8632
9030
|
departureTimes,
|
|
8633
|
-
|
|
9031
|
+
benefits,
|
|
9032
|
+
currencyEstimates,
|
|
9033
|
+
priceInfo,
|
|
8634
9034
|
onBook,
|
|
8635
9035
|
bookLabel,
|
|
8636
9036
|
siteHeader,
|
|
@@ -8638,34 +9038,51 @@ function TripPage({
|
|
|
8638
9038
|
features,
|
|
8639
9039
|
className
|
|
8640
9040
|
}) {
|
|
8641
|
-
const [activeSection, setActiveSection] =
|
|
8642
|
-
const [
|
|
8643
|
-
const
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
9041
|
+
const [activeSection, setActiveSection] = React25.useState("");
|
|
9042
|
+
const [accordionValue, setAccordionValue] = React25.useState([]);
|
|
9043
|
+
const accordionSectionIds = React25.useMemo(
|
|
9044
|
+
() => /* @__PURE__ */ new Set([
|
|
9045
|
+
"key-info",
|
|
9046
|
+
"what-to-bring",
|
|
9047
|
+
"weather",
|
|
9048
|
+
"optional-extras",
|
|
9049
|
+
"accommodation",
|
|
9050
|
+
"food",
|
|
9051
|
+
"meeting",
|
|
9052
|
+
"terms"
|
|
9053
|
+
]),
|
|
9054
|
+
[]
|
|
9055
|
+
);
|
|
9056
|
+
const [navFloating, setNavFloating] = React25.useState(false);
|
|
9057
|
+
const [navHidden, setNavHidden] = React25.useState(false);
|
|
9058
|
+
const [isFloating, setIsFloating] = React25.useState(false);
|
|
9059
|
+
const [sidebarPos, setSidebarPos] = React25.useState(null);
|
|
9060
|
+
const [pricingBarVisible, setPricingBarVisible] = React25.useState(false);
|
|
9061
|
+
const navRef = React25.useRef(null);
|
|
9062
|
+
const navSentinelRef = React25.useRef(null);
|
|
9063
|
+
const sentinelRef = React25.useRef(null);
|
|
9064
|
+
const sidebarPlaceholderRef = React25.useRef(null);
|
|
9065
|
+
const pricingBarRef = React25.useRef(null);
|
|
9066
|
+
const galleryRef = React25.useRef(null);
|
|
9067
|
+
const sections = React25.useMemo(
|
|
8654
9068
|
() => [
|
|
8655
|
-
{ id: "
|
|
8656
|
-
{
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
{ id: "
|
|
9069
|
+
{ id: "overview", label: "Overview", show: !!(overview || (overviewHighlights == null ? void 0 : overviewHighlights.length)) },
|
|
9070
|
+
{
|
|
9071
|
+
id: "itinerary",
|
|
9072
|
+
label: "Itinerary",
|
|
9073
|
+
show: !!((itineraryDays == null ? void 0 : itineraryDays.length) || (itinerary == null ? void 0 : itinerary.length))
|
|
9074
|
+
},
|
|
9075
|
+
{ id: "included", label: "What is Included", show: !!(included == null ? void 0 : included.length) },
|
|
9076
|
+
{ id: "what-to-bring", label: "What to Bring", show: !!(whatToBring == null ? void 0 : whatToBring.length) },
|
|
9077
|
+
{ id: "accommodation", label: "Accommodation", show: !!accommodation },
|
|
9078
|
+
{ id: "terms", label: "Terms", show: !!termsAndConditions },
|
|
8662
9079
|
{ id: "faq", label: "FAQ", show: !!(faqs == null ? void 0 : faqs.length) },
|
|
8663
|
-
{ id: "
|
|
9080
|
+
{ id: "reviews", label: "Reviews", show: !!(trustpilot || (reviews == null ? void 0 : reviews.length)) }
|
|
8664
9081
|
].filter((s) => s.show),
|
|
8665
9082
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8666
9083
|
[]
|
|
8667
9084
|
);
|
|
8668
|
-
|
|
9085
|
+
React25.useEffect(() => {
|
|
8669
9086
|
const sentinel = navSentinelRef.current;
|
|
8670
9087
|
if (!sentinel) return;
|
|
8671
9088
|
const update = () => setNavFloating(sentinel.getBoundingClientRect().top < 1);
|
|
@@ -8673,7 +9090,7 @@ function TripPage({
|
|
|
8673
9090
|
update();
|
|
8674
9091
|
return () => document.removeEventListener("scroll", update, { capture: true });
|
|
8675
9092
|
}, []);
|
|
8676
|
-
|
|
9093
|
+
React25.useEffect(() => {
|
|
8677
9094
|
const sentinel = sentinelRef.current;
|
|
8678
9095
|
if (!sentinel) return;
|
|
8679
9096
|
const update = () => setIsFloating(sentinel.getBoundingClientRect().top < 1);
|
|
@@ -8681,7 +9098,7 @@ function TripPage({
|
|
|
8681
9098
|
update();
|
|
8682
9099
|
return () => document.removeEventListener("scroll", update, { capture: true });
|
|
8683
9100
|
}, []);
|
|
8684
|
-
|
|
9101
|
+
React25.useEffect(() => {
|
|
8685
9102
|
const measure = () => {
|
|
8686
9103
|
if (!sidebarPlaceholderRef.current) return;
|
|
8687
9104
|
const rect = sidebarPlaceholderRef.current.getBoundingClientRect();
|
|
@@ -8691,7 +9108,7 @@ function TripPage({
|
|
|
8691
9108
|
window.addEventListener("resize", measure);
|
|
8692
9109
|
return () => window.removeEventListener("resize", measure);
|
|
8693
9110
|
}, [isFloating]);
|
|
8694
|
-
|
|
9111
|
+
React25.useEffect(() => {
|
|
8695
9112
|
const check = () => {
|
|
8696
9113
|
var _a;
|
|
8697
9114
|
const target = (_a = galleryRef.current) != null ? _a : pricingBarRef.current;
|
|
@@ -8702,7 +9119,7 @@ function TripPage({
|
|
|
8702
9119
|
check();
|
|
8703
9120
|
return () => document.removeEventListener("scroll", check, { capture: true });
|
|
8704
9121
|
}, []);
|
|
8705
|
-
|
|
9122
|
+
React25.useEffect(() => {
|
|
8706
9123
|
const check = () => {
|
|
8707
9124
|
if (!pricingBarRef.current) return;
|
|
8708
9125
|
setNavHidden(pricingBarRef.current.getBoundingClientRect().top < window.innerHeight * 0.92);
|
|
@@ -8711,7 +9128,7 @@ function TripPage({
|
|
|
8711
9128
|
check();
|
|
8712
9129
|
return () => document.removeEventListener("scroll", check, { capture: true });
|
|
8713
9130
|
}, []);
|
|
8714
|
-
|
|
9131
|
+
React25.useEffect(() => {
|
|
8715
9132
|
if (sections.length === 0) return;
|
|
8716
9133
|
setActiveSection(sections[0].id);
|
|
8717
9134
|
const update = () => {
|
|
@@ -8746,20 +9163,28 @@ function TripPage({
|
|
|
8746
9163
|
}
|
|
8747
9164
|
};
|
|
8748
9165
|
const scrollToSection = (id) => {
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
scrollEl
|
|
8760
|
-
|
|
8761
|
-
|
|
9166
|
+
const performScroll = () => {
|
|
9167
|
+
var _a, _b, _c;
|
|
9168
|
+
const el = document.getElementById(`trip-section-${id}`);
|
|
9169
|
+
if (!el) return;
|
|
9170
|
+
const navHeight = (_b = (_a = navRef.current) == null ? void 0 : _a.offsetHeight) != null ? _b : 56;
|
|
9171
|
+
const scrollEl = (_c = navRef.current) == null ? void 0 : _c.closest("main");
|
|
9172
|
+
const currentScroll = scrollEl ? scrollEl.scrollTop : window.scrollY;
|
|
9173
|
+
const elTop = el.getBoundingClientRect().top;
|
|
9174
|
+
const containerTop = scrollEl ? scrollEl.getBoundingClientRect().top : 0;
|
|
9175
|
+
const target = currentScroll + (elTop - containerTop) - navHeight - 12;
|
|
9176
|
+
if (scrollEl) {
|
|
9177
|
+
scrollEl.scrollTo({ top: target, behavior: "smooth" });
|
|
9178
|
+
} else {
|
|
9179
|
+
window.scrollTo({ top: target, behavior: "smooth" });
|
|
9180
|
+
}
|
|
9181
|
+
};
|
|
9182
|
+
if (accordionSectionIds.has(id)) {
|
|
9183
|
+
setAccordionValue([id]);
|
|
9184
|
+
window.setTimeout(performScroll, 320);
|
|
9185
|
+
return;
|
|
8762
9186
|
}
|
|
9187
|
+
performScroll();
|
|
8763
9188
|
};
|
|
8764
9189
|
return /* @__PURE__ */ jsxs(
|
|
8765
9190
|
"div",
|
|
@@ -8779,10 +9204,11 @@ function TripPage({
|
|
|
8779
9204
|
duration,
|
|
8780
9205
|
tagline,
|
|
8781
9206
|
siteHeader,
|
|
8782
|
-
uiVariant
|
|
9207
|
+
uiVariant,
|
|
9208
|
+
belowMeta: trustpilotHero ? /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilotHero }) : void 0
|
|
8783
9209
|
}
|
|
8784
9210
|
),
|
|
8785
|
-
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-
|
|
9211
|
+
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8", children: [
|
|
8786
9212
|
highlights && highlights.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-6 flex flex-wrap justify-center gap-6 py-2", children: highlights.map((h, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 text-center", children: [
|
|
8787
9213
|
h.icon && /* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full border-2 border-border text-foreground", children: h.icon }),
|
|
8788
9214
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground font-ui", children: h.label })
|
|
@@ -8792,7 +9218,7 @@ function TripPage({
|
|
|
8792
9218
|
"div",
|
|
8793
9219
|
{
|
|
8794
9220
|
className: cn(
|
|
8795
|
-
"
|
|
9221
|
+
"pt-8 pb-2 flex justify-center transition-opacity duration-150",
|
|
8796
9222
|
navFloating ? "opacity-0 pointer-events-none" : "opacity-100"
|
|
8797
9223
|
),
|
|
8798
9224
|
children: /* @__PURE__ */ jsx(
|
|
@@ -8809,67 +9235,208 @@ function TripPage({
|
|
|
8809
9235
|
/* @__PURE__ */ jsx("div", { ref: sentinelRef, className: "h-px -mt-px", "aria-hidden": true }),
|
|
8810
9236
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8 mt-4", children: [
|
|
8811
9237
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-12 pb-12", children: [
|
|
8812
|
-
|
|
8813
|
-
/* @__PURE__ */
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
/* @__PURE__ */ jsx(
|
|
8820
|
-
|
|
8821
|
-
] }, i)) })
|
|
8822
|
-
|
|
8823
|
-
overview && /* @__PURE__ */ jsxs("section", { id: "trip-section-overview", className: "scroll-mt-20", children: [
|
|
8824
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-4", children: "Overview" }),
|
|
8825
|
-
recommendedFor && /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2.5 rounded-xl bg-primary/8 border border-primary/20 p-4 mb-4", children: [
|
|
9238
|
+
(overview || (overviewHighlights == null ? void 0 : overviewHighlights.length)) && /* @__PURE__ */ jsxs("section", { id: "trip-section-overview", className: "scroll-mt-20", children: [
|
|
9239
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-4 flex items-center gap-2", children: [
|
|
9240
|
+
(sectionIcons == null ? void 0 : sectionIcons.overview) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.overview }) : /* @__PURE__ */ jsx(InfoIcon, { className: "h-5 w-5 text-primary" }),
|
|
9241
|
+
"Overview"
|
|
9242
|
+
] }),
|
|
9243
|
+
overview && /* @__PURE__ */ jsx("div", { className: "text-lg text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: overview }),
|
|
9244
|
+
overviewHighlights && overviewHighlights.length > 0 && /* @__PURE__ */ jsx("ul", { className: cn("flex flex-col gap-5", overview && "mt-8"), children: overviewHighlights.map((h, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4", children: [
|
|
9245
|
+
h.icon && /* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center text-foreground [&_svg]:h-8 [&_svg]:w-8", children: h.icon }),
|
|
9246
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 pt-1 text-base text-foreground leading-relaxed [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: h.description })
|
|
9247
|
+
] }, i)) }),
|
|
9248
|
+
recommendedFor && /* @__PURE__ */ jsxs("div", { className: "mt-6 flex items-start gap-2.5 rounded-xl bg-primary/8 border border-primary/20 p-4", children: [
|
|
8826
9249
|
/* @__PURE__ */ jsx(UsersIcon, { className: "h-4 w-4 text-primary mt-0.5 shrink-0" }),
|
|
8827
|
-
/* @__PURE__ */ jsxs("p", { className: "text-
|
|
9250
|
+
/* @__PURE__ */ jsxs("p", { className: "text-base text-foreground font-ui", children: [
|
|
8828
9251
|
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: "Recommended for: " }),
|
|
8829
9252
|
recommendedFor
|
|
8830
9253
|
] })
|
|
8831
|
-
] })
|
|
8832
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: overview })
|
|
9254
|
+
] })
|
|
8833
9255
|
] }),
|
|
8834
|
-
|
|
8835
|
-
/* @__PURE__ */
|
|
9256
|
+
itineraryDays && itineraryDays.length > 0 ? /* @__PURE__ */ jsxs("section", { id: "trip-section-itinerary", className: "scroll-mt-20", children: [
|
|
9257
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-6 flex items-center gap-2", children: [
|
|
9258
|
+
(sectionIcons == null ? void 0 : sectionIcons.itinerary) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.itinerary }) : /* @__PURE__ */ jsx(ClockIcon, { className: "h-5 w-5 text-primary" }),
|
|
9259
|
+
"Itinerary"
|
|
9260
|
+
] }),
|
|
9261
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-12", children: itineraryDays.map((day) => /* @__PURE__ */ jsx(
|
|
9262
|
+
ItineraryDay,
|
|
9263
|
+
__spreadProps(__spreadValues({}, day), {
|
|
9264
|
+
photoLayout: "fullBleedBottom"
|
|
9265
|
+
}),
|
|
9266
|
+
day.dayNumber
|
|
9267
|
+
)) })
|
|
9268
|
+
] }) : itinerary && itinerary.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-itinerary", className: "scroll-mt-20", children: [
|
|
9269
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-6 flex items-center gap-2", children: [
|
|
9270
|
+
(sectionIcons == null ? void 0 : sectionIcons.itinerary) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.itinerary }) : /* @__PURE__ */ jsx(ClockIcon, { className: "h-5 w-5 text-primary" }),
|
|
9271
|
+
"Itinerary"
|
|
9272
|
+
] }),
|
|
8836
9273
|
/* @__PURE__ */ jsx(ItineraryTimeline, { steps: itinerary })
|
|
8837
9274
|
] }),
|
|
8838
9275
|
included && included.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-included", className: "scroll-mt-20", children: [
|
|
8839
9276
|
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-4 flex items-center gap-2", children: [
|
|
8840
|
-
/* @__PURE__ */ jsx(PackageIcon, { className: "h-5 w-5 text-primary" }),
|
|
9277
|
+
(sectionIcons == null ? void 0 : sectionIcons.whatIsIncluded) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.whatIsIncluded }) : /* @__PURE__ */ jsx(PackageIcon, { className: "h-5 w-5 text-primary" }),
|
|
8841
9278
|
"Included"
|
|
8842
9279
|
] }),
|
|
8843
9280
|
/* @__PURE__ */ jsx(Checklist, { items: included })
|
|
8844
9281
|
] }),
|
|
8845
|
-
|
|
8846
|
-
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-4 flex items-center gap-2", children: [
|
|
8847
|
-
/* @__PURE__ */ jsx(PackageIcon, { className: "h-5 w-5 text-primary" }),
|
|
8848
|
-
"What to bring"
|
|
8849
|
-
] }),
|
|
8850
|
-
/* @__PURE__ */ jsx(Checklist, { items: whatToBring, icon: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4" }) })
|
|
8851
|
-
] }),
|
|
8852
|
-
weather && /* @__PURE__ */ jsxs("section", { id: "trip-section-weather", className: "scroll-mt-20", children: [
|
|
9282
|
+
notIncluded && notIncluded.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-not-included", className: "scroll-mt-20", children: [
|
|
8853
9283
|
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-4 flex items-center gap-2", children: [
|
|
8854
|
-
/* @__PURE__ */ jsx(
|
|
8855
|
-
"
|
|
9284
|
+
/* @__PURE__ */ jsx(XIcon, { className: "h-5 w-5 text-muted-foreground" }),
|
|
9285
|
+
"Not included"
|
|
8856
9286
|
] }),
|
|
8857
|
-
/* @__PURE__ */ jsx(
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: meetingPoints.map((mp, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-border p-4", children: [
|
|
8865
|
-
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(MapPinIcon, { className: "h-4 w-4 text-primary" }) }),
|
|
8866
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
8867
|
-
mp.type && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui uppercase tracking-wide mb-0.5", children: mp.type === "activity" ? "Activity location" : mp.type === "alternative" ? "Alternative meeting point" : "Meeting point" }),
|
|
8868
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold text-foreground font-heading", children: mp.name }),
|
|
8869
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui mt-0.5", children: mp.address })
|
|
8870
|
-
] })
|
|
8871
|
-
] }, i)) })
|
|
9287
|
+
/* @__PURE__ */ jsx(
|
|
9288
|
+
Checklist,
|
|
9289
|
+
{
|
|
9290
|
+
items: notIncluded,
|
|
9291
|
+
icon: /* @__PURE__ */ jsx(XIcon, { className: "h-4 w-4 text-muted-foreground" })
|
|
9292
|
+
}
|
|
9293
|
+
)
|
|
8872
9294
|
] }),
|
|
9295
|
+
((infoGroups == null ? void 0 : infoGroups.length) || keyInfo || (whatToBring == null ? void 0 : whatToBring.length) || weather || optionalExtras || accommodation || food || (meetingPoints == null ? void 0 : meetingPoints.length) || meetingPoint || termsAndConditions) && /* @__PURE__ */ jsxs(
|
|
9296
|
+
Accordion,
|
|
9297
|
+
{
|
|
9298
|
+
multiple: false,
|
|
9299
|
+
value: accordionValue,
|
|
9300
|
+
onValueChange: setAccordionValue,
|
|
9301
|
+
className: "border-t border-border",
|
|
9302
|
+
children: [
|
|
9303
|
+
(keyInfo || infoGroups && infoGroups.length > 0) && /* @__PURE__ */ jsxs(
|
|
9304
|
+
AccordionItem,
|
|
9305
|
+
{
|
|
9306
|
+
value: "key-info",
|
|
9307
|
+
id: "trip-section-key-info",
|
|
9308
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9309
|
+
children: [
|
|
9310
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9311
|
+
(sectionIcons == null ? void 0 : sectionIcons.keyInfo) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.keyInfo }) : /* @__PURE__ */ jsx(InfoIcon, { className: "h-5 w-5 text-primary" }),
|
|
9312
|
+
"Key info"
|
|
9313
|
+
] }) }),
|
|
9314
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: keyInfo ? /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: keyInfo }) : /* @__PURE__ */ jsx("div", { className: "space-y-6", children: infoGroups.map((group, i) => /* @__PURE__ */ jsxs("div", { children: [
|
|
9315
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
|
|
9316
|
+
group.icon && /* @__PURE__ */ jsx("span", { className: "text-primary", children: group.icon }),
|
|
9317
|
+
/* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading", children: group.title })
|
|
9318
|
+
] }),
|
|
9319
|
+
/* @__PURE__ */ jsx(Checklist, { items: group.items }),
|
|
9320
|
+
i < infoGroups.length - 1 && /* @__PURE__ */ jsx(Separator, { className: "mt-6" })
|
|
9321
|
+
] }, i)) }) })
|
|
9322
|
+
]
|
|
9323
|
+
}
|
|
9324
|
+
),
|
|
9325
|
+
(meetingPoint || meetingPoints && meetingPoints.length > 0) && /* @__PURE__ */ jsxs(
|
|
9326
|
+
AccordionItem,
|
|
9327
|
+
{
|
|
9328
|
+
value: "meeting",
|
|
9329
|
+
id: "trip-section-meeting",
|
|
9330
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9331
|
+
children: [
|
|
9332
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9333
|
+
(sectionIcons == null ? void 0 : sectionIcons.meetingPoint) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.meetingPoint }) : /* @__PURE__ */ jsx(MapPinIcon, { className: "h-5 w-5 text-primary" }),
|
|
9334
|
+
"Meeting point"
|
|
9335
|
+
] }) }),
|
|
9336
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: meetingPoint ? /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: meetingPoint }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: meetingPoints.map((mp, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-border p-4", children: [
|
|
9337
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(MapPinIcon, { className: "h-4 w-4 text-primary" }) }),
|
|
9338
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
9339
|
+
mp.type && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui uppercase tracking-wide mb-0.5", children: mp.type === "activity" ? "Activity location" : mp.type === "alternative" ? "Alternative meeting point" : "Meeting point" }),
|
|
9340
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold text-foreground font-heading", children: mp.name }),
|
|
9341
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui mt-0.5", children: mp.address })
|
|
9342
|
+
] })
|
|
9343
|
+
] }, i)) }) })
|
|
9344
|
+
]
|
|
9345
|
+
}
|
|
9346
|
+
),
|
|
9347
|
+
optionalExtras && /* @__PURE__ */ jsxs(
|
|
9348
|
+
AccordionItem,
|
|
9349
|
+
{
|
|
9350
|
+
value: "optional-extras",
|
|
9351
|
+
id: "trip-section-optional-extras",
|
|
9352
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9353
|
+
children: [
|
|
9354
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9355
|
+
(sectionIcons == null ? void 0 : sectionIcons.optionalExtras) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.optionalExtras }) : /* @__PURE__ */ jsx(SparklesIcon, { className: "h-5 w-5 text-primary" }),
|
|
9356
|
+
"Optional extras"
|
|
9357
|
+
] }) }),
|
|
9358
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: optionalExtras }) })
|
|
9359
|
+
]
|
|
9360
|
+
}
|
|
9361
|
+
),
|
|
9362
|
+
whatToBring && whatToBring.length > 0 && /* @__PURE__ */ jsxs(
|
|
9363
|
+
AccordionItem,
|
|
9364
|
+
{
|
|
9365
|
+
value: "what-to-bring",
|
|
9366
|
+
id: "trip-section-what-to-bring",
|
|
9367
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9368
|
+
children: [
|
|
9369
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9370
|
+
(sectionIcons == null ? void 0 : sectionIcons.whatToBring) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.whatToBring }) : /* @__PURE__ */ jsx(BackpackIcon, { className: "h-5 w-5 text-primary" }),
|
|
9371
|
+
"What to bring"
|
|
9372
|
+
] }) }),
|
|
9373
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx(Checklist, { items: whatToBring, icon: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4" }) }) })
|
|
9374
|
+
]
|
|
9375
|
+
}
|
|
9376
|
+
),
|
|
9377
|
+
accommodation && /* @__PURE__ */ jsxs(
|
|
9378
|
+
AccordionItem,
|
|
9379
|
+
{
|
|
9380
|
+
value: "accommodation",
|
|
9381
|
+
id: "trip-section-accommodation",
|
|
9382
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9383
|
+
children: [
|
|
9384
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9385
|
+
(sectionIcons == null ? void 0 : sectionIcons.accommodation) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.accommodation }) : /* @__PURE__ */ jsx(BedDoubleIcon, { className: "h-5 w-5 text-primary" }),
|
|
9386
|
+
"Accommodation"
|
|
9387
|
+
] }) }),
|
|
9388
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: accommodation }) })
|
|
9389
|
+
]
|
|
9390
|
+
}
|
|
9391
|
+
),
|
|
9392
|
+
food && /* @__PURE__ */ jsxs(
|
|
9393
|
+
AccordionItem,
|
|
9394
|
+
{
|
|
9395
|
+
value: "food",
|
|
9396
|
+
id: "trip-section-food",
|
|
9397
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9398
|
+
children: [
|
|
9399
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9400
|
+
(sectionIcons == null ? void 0 : sectionIcons.food) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.food }) : /* @__PURE__ */ jsx(UtensilsIcon, { className: "h-5 w-5 text-primary" }),
|
|
9401
|
+
"Food"
|
|
9402
|
+
] }) }),
|
|
9403
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: food }) })
|
|
9404
|
+
]
|
|
9405
|
+
}
|
|
9406
|
+
),
|
|
9407
|
+
weather && /* @__PURE__ */ jsxs(
|
|
9408
|
+
AccordionItem,
|
|
9409
|
+
{
|
|
9410
|
+
value: "weather",
|
|
9411
|
+
id: "trip-section-weather",
|
|
9412
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9413
|
+
children: [
|
|
9414
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9415
|
+
(sectionIcons == null ? void 0 : sectionIcons.weather) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.weather }) : /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 text-primary" }),
|
|
9416
|
+
"Weather"
|
|
9417
|
+
] }) }),
|
|
9418
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "flex items-start gap-3 rounded-xl bg-muted/60 border border-border p-5", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-2 [&_strong]:font-semibold", children: weather }) }) })
|
|
9419
|
+
]
|
|
9420
|
+
}
|
|
9421
|
+
),
|
|
9422
|
+
termsAndConditions && /* @__PURE__ */ jsxs(
|
|
9423
|
+
AccordionItem,
|
|
9424
|
+
{
|
|
9425
|
+
value: "terms",
|
|
9426
|
+
id: "trip-section-terms",
|
|
9427
|
+
className: "scroll-mt-20 border-b border-border",
|
|
9428
|
+
children: [
|
|
9429
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
9430
|
+
(sectionIcons == null ? void 0 : sectionIcons.terms) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.terms }) : /* @__PURE__ */ jsx(ReceiptIcon, { className: "h-5 w-5 text-primary" }),
|
|
9431
|
+
"Terms & conditions"
|
|
9432
|
+
] }) }),
|
|
9433
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: termsAndConditions }) })
|
|
9434
|
+
]
|
|
9435
|
+
}
|
|
9436
|
+
)
|
|
9437
|
+
]
|
|
9438
|
+
}
|
|
9439
|
+
),
|
|
8873
9440
|
faqs && faqs.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-faq", className: "scroll-mt-20", children: [
|
|
8874
9441
|
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-6", children: "FAQ" }),
|
|
8875
9442
|
/* @__PURE__ */ jsx(Accordion, { variant: "faq", children: faqs.map((faq, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `faq-${i}`, children: [
|
|
@@ -8877,14 +9444,18 @@ function TripPage({
|
|
|
8877
9444
|
/* @__PURE__ */ jsx(AccordionContent, { children: faq.answer })
|
|
8878
9445
|
] }, i)) })
|
|
8879
9446
|
] }),
|
|
8880
|
-
|
|
9447
|
+
trustpilot ? /* @__PURE__ */ jsxs("section", { id: "trip-section-reviews", className: "scroll-mt-20", children: [
|
|
9448
|
+
/* @__PURE__ */ jsx(Separator, { className: "mb-10" }),
|
|
9449
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-5", children: "What our guests think" }),
|
|
9450
|
+
/* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilot })
|
|
9451
|
+
] }) : reviews && reviews.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-reviews", className: "scroll-mt-20", children: [
|
|
8881
9452
|
/* @__PURE__ */ jsx(Separator, { className: "mb-10" }),
|
|
8882
9453
|
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-5", children: "What our guests think" }),
|
|
8883
9454
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: reviews.map((r, i) => {
|
|
8884
9455
|
var _a;
|
|
8885
9456
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 rounded-xl border border-border p-5", children: [
|
|
8886
9457
|
/* @__PURE__ */ jsx(Stars, { count: (_a = r.rating) != null ? _a : 5 }),
|
|
8887
|
-
/* @__PURE__ */ jsxs("p", { className: "text-
|
|
9458
|
+
/* @__PURE__ */ jsxs("p", { className: "text-base text-foreground leading-relaxed line-clamp-4", children: [
|
|
8888
9459
|
"\u201C",
|
|
8889
9460
|
r.text,
|
|
8890
9461
|
"\u201D"
|
|
@@ -8904,10 +9475,13 @@ function TripPage({
|
|
|
8904
9475
|
currency,
|
|
8905
9476
|
season,
|
|
8906
9477
|
departureTimes,
|
|
8907
|
-
pricingOptions,
|
|
8908
9478
|
onBook: (gallery == null ? void 0 : gallery.length) ? scrollToBookingForm : onBook,
|
|
8909
9479
|
bookLabel: bookLabel != null ? bookLabel : "Check availability",
|
|
8910
|
-
variant: "card"
|
|
9480
|
+
variant: "card",
|
|
9481
|
+
belowPrice: trustpilotMini ? /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilotMini }) : void 0,
|
|
9482
|
+
benefits,
|
|
9483
|
+
currencyEstimates,
|
|
9484
|
+
priceInfo
|
|
8911
9485
|
}
|
|
8912
9486
|
) }) })
|
|
8913
9487
|
] })
|
|
@@ -8920,7 +9494,7 @@ function TripPage({
|
|
|
8920
9494
|
"fixed top-0 left-0 right-0 z-20 py-3 transition-all duration-200",
|
|
8921
9495
|
navFloating && !navHidden ? "translate-y-0 opacity-100" : "-translate-y-full opacity-0 pointer-events-none"
|
|
8922
9496
|
),
|
|
8923
|
-
children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-
|
|
9497
|
+
children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
8924
9498
|
MenuTrip,
|
|
8925
9499
|
{
|
|
8926
9500
|
sections,
|
|
@@ -8943,10 +9517,13 @@ function TripPage({
|
|
|
8943
9517
|
currency,
|
|
8944
9518
|
season,
|
|
8945
9519
|
departureTimes,
|
|
8946
|
-
pricingOptions,
|
|
8947
9520
|
onBook: (gallery == null ? void 0 : gallery.length) ? scrollToBookingForm : onBook,
|
|
8948
9521
|
bookLabel: bookLabel != null ? bookLabel : "Check availability",
|
|
8949
|
-
variant: "card"
|
|
9522
|
+
variant: "card",
|
|
9523
|
+
belowPrice: trustpilotMini ? /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilotMini }) : void 0,
|
|
9524
|
+
benefits,
|
|
9525
|
+
currencyEstimates,
|
|
9526
|
+
priceInfo
|
|
8950
9527
|
}
|
|
8951
9528
|
) })
|
|
8952
9529
|
}
|
|
@@ -8959,7 +9536,7 @@ function TripPage({
|
|
|
8959
9536
|
initialVisible: 6
|
|
8960
9537
|
}
|
|
8961
9538
|
) }),
|
|
8962
|
-
gallery && gallery.length > 0 && /* @__PURE__ */ jsx("div", { ref: pricingBarRef, className: "mx-auto w-full max-w-
|
|
9539
|
+
gallery && gallery.length > 0 && /* @__PURE__ */ jsx("div", { ref: pricingBarRef, className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: /* @__PURE__ */ jsx("div", { id: "trip-booking-form", className: "rounded-2xl border border-border bg-card p-8 shadow-sm", children: /* @__PURE__ */ jsx(BookingForm, { onSubmit: onBook ? (values) => onBook() : void 0 }) }) }),
|
|
8963
9540
|
/* @__PURE__ */ jsx("div", { className: "fixed bottom-0 inset-x-0 z-30 lg:hidden border-t border-border bg-background/95 backdrop-blur-sm px-4 py-3", children: /* @__PURE__ */ jsx(
|
|
8964
9541
|
PricingTrip,
|
|
8965
9542
|
{
|
|
@@ -8967,7 +9544,10 @@ function TripPage({
|
|
|
8967
9544
|
currency,
|
|
8968
9545
|
onBook: (gallery == null ? void 0 : gallery.length) ? scrollToBookingForm : onBook,
|
|
8969
9546
|
bookLabel: bookLabel != null ? bookLabel : "Book now",
|
|
8970
|
-
variant: "compact"
|
|
9547
|
+
variant: "compact",
|
|
9548
|
+
sharp: true,
|
|
9549
|
+
priceInfo,
|
|
9550
|
+
currencyEstimates
|
|
8971
9551
|
}
|
|
8972
9552
|
) }),
|
|
8973
9553
|
/* @__PURE__ */ jsx("div", { className: "h-20 lg:hidden" })
|
|
@@ -9076,12 +9656,12 @@ function Toast({
|
|
|
9076
9656
|
duration = 6e3,
|
|
9077
9657
|
className
|
|
9078
9658
|
}) {
|
|
9079
|
-
const [mounted, setMounted] =
|
|
9080
|
-
const [visible, setVisible] =
|
|
9081
|
-
|
|
9659
|
+
const [mounted, setMounted] = React25.useState(false);
|
|
9660
|
+
const [visible, setVisible] = React25.useState(true);
|
|
9661
|
+
React25.useEffect(() => {
|
|
9082
9662
|
setMounted(true);
|
|
9083
9663
|
}, []);
|
|
9084
|
-
|
|
9664
|
+
React25.useEffect(() => {
|
|
9085
9665
|
if (duration === 0) return;
|
|
9086
9666
|
const t = setTimeout(() => {
|
|
9087
9667
|
setVisible(false);
|
|
@@ -9785,6 +10365,6 @@ function LeadCapturePopup({
|
|
|
9785
10365
|
);
|
|
9786
10366
|
}
|
|
9787
10367
|
|
|
9788
|
-
export { ActivityCard, AgentContactCard, Alert, BirthDateField, BookingConfirmation, BookingConfirmationEmail, BookingConfirmedCard, BookingDetails, BookingForm, BookingOtpEmail, BookingShell, Button, COUNTRIES, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FilterPanel, FloatingInput, FloatingSelect, Itinerary, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, PaymentAmountSelector, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PhoneCountrySelect, PhotoGallery, PricingTrip, RegistrationForm, RegistrationSuccessCard, SiteHeader, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, buttonVariants, cn, emailTokens, getStripeAppearance, stripeAppearance, wrapEmailHtml };
|
|
10368
|
+
export { ActivityCard, AgentContactCard, Alert, BirthDateField, BookingConfirmation, BookingConfirmationEmail, BookingConfirmedCard, BookingDetails, BookingForm, BookingOtpEmail, BookingShell, Button, COUNTRIES, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, FilterPanel, FloatingInput, FloatingSelect, Itinerary, ItineraryDay, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, PaymentAmountSelector, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PhoneCountrySelect, PhotoGallery, PricingTrip, RegistrationForm, RegistrationSuccessCard, SiteHeader, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TransferDetailsBlock, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, TrustpilotEmbed, buttonVariants, cn, emailTokens, getStripeAppearance, itineraryDaySpecIcons, stripeAppearance, wrapEmailHtml };
|
|
9789
10369
|
//# sourceMappingURL=index.js.map
|
|
9790
10370
|
//# sourceMappingURL=index.js.map
|