@planetaexo/design-system 0.93.0 → 0.94.0
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 +102 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +102 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -4174,6 +4174,14 @@ interface CategoryPage2Props {
|
|
|
4174
4174
|
title: string;
|
|
4175
4175
|
intro?: React.ReactNode;
|
|
4176
4176
|
heroImage?: string;
|
|
4177
|
+
/**
|
|
4178
|
+
* Responsive variants of `heroImage` for the LCP `<img>` — same
|
|
4179
|
+
* `srcSet`/`sizes` contract as `TripHeader`, so phones fetch a viewport-
|
|
4180
|
+
* sized cover instead of the full-width desktop one. Optional; the `<img>`
|
|
4181
|
+
* falls back to the single `heroImage` src when they are absent.
|
|
4182
|
+
*/
|
|
4183
|
+
heroImageSrcSet?: string;
|
|
4184
|
+
heroImageSizes?: string;
|
|
4177
4185
|
/**
|
|
4178
4186
|
* Optional hero background video. Plays muted/looping over the hero with
|
|
4179
4187
|
* `heroImage` as the instant poster (crossfades out once the video is ready).
|
|
@@ -4280,7 +4288,7 @@ interface CategoryPage2Props {
|
|
|
4280
4288
|
filterLabels?: FilterPanelLabels;
|
|
4281
4289
|
className?: string;
|
|
4282
4290
|
}
|
|
4283
|
-
declare function CategoryPage2({ title, intro, heroImage, videoUrl, trustpilotMini, breadcrumb, siteHeader, heroRightSlot, popularTours, popularToursTitle, popularToursEyebrow, trips, tripsTitle, tripsEyebrow, filterGroups, sortOptions, defaultSort, tripsInitialCount, tripListingSlot, trustpilot, reviewsTitle, reviewsSubtitle, blogPosts, aboutTitle, aboutContent, blogIntro, travelGuideHref, travelGuideLabel, blogPostsTitle, blogPostsViewAllHref, faqs, faqsTitle, faqInitialCount, gallery, galleryTitle, galleryLightbox, loadMoreLabel, showLessLabel, seeMoreLabel, viewAllPostsLabel, cardLabels, filterLabels, footerBadges, footer, className, }: CategoryPage2Props): react_jsx_runtime.JSX.Element;
|
|
4291
|
+
declare function CategoryPage2({ title, intro, heroImage, heroImageSrcSet, heroImageSizes, videoUrl, trustpilotMini, breadcrumb, siteHeader, heroRightSlot, popularTours, popularToursTitle, popularToursEyebrow, trips, tripsTitle, tripsEyebrow, filterGroups, sortOptions, defaultSort, tripsInitialCount, tripListingSlot, trustpilot, reviewsTitle, reviewsSubtitle, blogPosts, aboutTitle, aboutContent, blogIntro, travelGuideHref, travelGuideLabel, blogPostsTitle, blogPostsViewAllHref, faqs, faqsTitle, faqInitialCount, gallery, galleryTitle, galleryLightbox, loadMoreLabel, showLessLabel, seeMoreLabel, viewAllPostsLabel, cardLabels, filterLabels, footerBadges, footer, className, }: CategoryPage2Props): react_jsx_runtime.JSX.Element;
|
|
4284
4292
|
|
|
4285
4293
|
type ActivityCardSize = "sm" | "md" | "lg";
|
|
4286
4294
|
interface ActivityCardProps {
|
|
@@ -5421,10 +5429,13 @@ interface ReviewsSpotlightProps {
|
|
|
5421
5429
|
className?: string;
|
|
5422
5430
|
}
|
|
5423
5431
|
/**
|
|
5424
|
-
* ReviewsSpotlight — a
|
|
5425
|
-
*
|
|
5426
|
-
*
|
|
5427
|
-
*
|
|
5432
|
+
* ReviewsSpotlight — a swipeable row of testimonials. Each review is a
|
|
5433
|
+
* full-width slide on a native horizontal scroll-snap track, so on touch it
|
|
5434
|
+
* can be flicked one review at a time; on desktop the dots advance it. One
|
|
5435
|
+
* large serif quote with Trustpilot stars, auto-advancing through `items` with
|
|
5436
|
+
* the pagination dots synced to scroll position. Autoplay pauses on
|
|
5437
|
+
* hover / focus / active swipe and is skipped entirely under
|
|
5438
|
+
* `prefers-reduced-motion`. The dark band matches the rest of {@link NewHome}.
|
|
5428
5439
|
*/
|
|
5429
5440
|
declare function ReviewsSpotlight({ eyebrow, title, link, items, intervalMs, className, }: ReviewsSpotlightProps): react_jsx_runtime.JSX.Element | null;
|
|
5430
5441
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4174,6 +4174,14 @@ interface CategoryPage2Props {
|
|
|
4174
4174
|
title: string;
|
|
4175
4175
|
intro?: React.ReactNode;
|
|
4176
4176
|
heroImage?: string;
|
|
4177
|
+
/**
|
|
4178
|
+
* Responsive variants of `heroImage` for the LCP `<img>` — same
|
|
4179
|
+
* `srcSet`/`sizes` contract as `TripHeader`, so phones fetch a viewport-
|
|
4180
|
+
* sized cover instead of the full-width desktop one. Optional; the `<img>`
|
|
4181
|
+
* falls back to the single `heroImage` src when they are absent.
|
|
4182
|
+
*/
|
|
4183
|
+
heroImageSrcSet?: string;
|
|
4184
|
+
heroImageSizes?: string;
|
|
4177
4185
|
/**
|
|
4178
4186
|
* Optional hero background video. Plays muted/looping over the hero with
|
|
4179
4187
|
* `heroImage` as the instant poster (crossfades out once the video is ready).
|
|
@@ -4280,7 +4288,7 @@ interface CategoryPage2Props {
|
|
|
4280
4288
|
filterLabels?: FilterPanelLabels;
|
|
4281
4289
|
className?: string;
|
|
4282
4290
|
}
|
|
4283
|
-
declare function CategoryPage2({ title, intro, heroImage, videoUrl, trustpilotMini, breadcrumb, siteHeader, heroRightSlot, popularTours, popularToursTitle, popularToursEyebrow, trips, tripsTitle, tripsEyebrow, filterGroups, sortOptions, defaultSort, tripsInitialCount, tripListingSlot, trustpilot, reviewsTitle, reviewsSubtitle, blogPosts, aboutTitle, aboutContent, blogIntro, travelGuideHref, travelGuideLabel, blogPostsTitle, blogPostsViewAllHref, faqs, faqsTitle, faqInitialCount, gallery, galleryTitle, galleryLightbox, loadMoreLabel, showLessLabel, seeMoreLabel, viewAllPostsLabel, cardLabels, filterLabels, footerBadges, footer, className, }: CategoryPage2Props): react_jsx_runtime.JSX.Element;
|
|
4291
|
+
declare function CategoryPage2({ title, intro, heroImage, heroImageSrcSet, heroImageSizes, videoUrl, trustpilotMini, breadcrumb, siteHeader, heroRightSlot, popularTours, popularToursTitle, popularToursEyebrow, trips, tripsTitle, tripsEyebrow, filterGroups, sortOptions, defaultSort, tripsInitialCount, tripListingSlot, trustpilot, reviewsTitle, reviewsSubtitle, blogPosts, aboutTitle, aboutContent, blogIntro, travelGuideHref, travelGuideLabel, blogPostsTitle, blogPostsViewAllHref, faqs, faqsTitle, faqInitialCount, gallery, galleryTitle, galleryLightbox, loadMoreLabel, showLessLabel, seeMoreLabel, viewAllPostsLabel, cardLabels, filterLabels, footerBadges, footer, className, }: CategoryPage2Props): react_jsx_runtime.JSX.Element;
|
|
4284
4292
|
|
|
4285
4293
|
type ActivityCardSize = "sm" | "md" | "lg";
|
|
4286
4294
|
interface ActivityCardProps {
|
|
@@ -5421,10 +5429,13 @@ interface ReviewsSpotlightProps {
|
|
|
5421
5429
|
className?: string;
|
|
5422
5430
|
}
|
|
5423
5431
|
/**
|
|
5424
|
-
* ReviewsSpotlight — a
|
|
5425
|
-
*
|
|
5426
|
-
*
|
|
5427
|
-
*
|
|
5432
|
+
* ReviewsSpotlight — a swipeable row of testimonials. Each review is a
|
|
5433
|
+
* full-width slide on a native horizontal scroll-snap track, so on touch it
|
|
5434
|
+
* can be flicked one review at a time; on desktop the dots advance it. One
|
|
5435
|
+
* large serif quote with Trustpilot stars, auto-advancing through `items` with
|
|
5436
|
+
* the pagination dots synced to scroll position. Autoplay pauses on
|
|
5437
|
+
* hover / focus / active swipe and is skipped entirely under
|
|
5438
|
+
* `prefers-reduced-motion`. The dark band matches the rest of {@link NewHome}.
|
|
5428
5439
|
*/
|
|
5429
5440
|
declare function ReviewsSpotlight({ eyebrow, title, link, items, intervalMs, className, }: ReviewsSpotlightProps): react_jsx_runtime.JSX.Element | null;
|
|
5430
5441
|
|
package/dist/index.js
CHANGED
|
@@ -16430,6 +16430,8 @@ function CategoryPage2({
|
|
|
16430
16430
|
title,
|
|
16431
16431
|
intro,
|
|
16432
16432
|
heroImage,
|
|
16433
|
+
heroImageSrcSet,
|
|
16434
|
+
heroImageSizes,
|
|
16433
16435
|
videoUrl,
|
|
16434
16436
|
trustpilotMini,
|
|
16435
16437
|
breadcrumb,
|
|
@@ -16565,6 +16567,8 @@ function CategoryPage2({
|
|
|
16565
16567
|
"img",
|
|
16566
16568
|
{
|
|
16567
16569
|
src: heroImage,
|
|
16570
|
+
srcSet: heroImageSrcSet,
|
|
16571
|
+
sizes: heroImageSizes,
|
|
16568
16572
|
alt: "",
|
|
16569
16573
|
"aria-hidden": true,
|
|
16570
16574
|
fetchPriority: "high",
|
|
@@ -20206,10 +20210,18 @@ function ReviewsSpotlight({
|
|
|
20206
20210
|
intervalMs = 7e3,
|
|
20207
20211
|
className
|
|
20208
20212
|
}) {
|
|
20213
|
+
const trackRef = React20.useRef(null);
|
|
20209
20214
|
const [index, setIndex] = React20.useState(0);
|
|
20210
|
-
const [visible, setVisible] = React20.useState(true);
|
|
20211
20215
|
const reduced = React20.useRef(false);
|
|
20212
|
-
const
|
|
20216
|
+
const hoverRef = React20.useRef(false);
|
|
20217
|
+
const focusRef = React20.useRef(false);
|
|
20218
|
+
const interactRef = React20.useRef(false);
|
|
20219
|
+
const programmaticRef = React20.useRef(false);
|
|
20220
|
+
const rafRef = React20.useRef(null);
|
|
20221
|
+
const interactTimer = React20.useRef(null);
|
|
20222
|
+
const programmaticTimer = React20.useRef(
|
|
20223
|
+
null
|
|
20224
|
+
);
|
|
20213
20225
|
React20.useEffect(() => {
|
|
20214
20226
|
var _a;
|
|
20215
20227
|
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
@@ -20223,56 +20235,107 @@ function ReviewsSpotlight({
|
|
|
20223
20235
|
return (_a2 = mq.removeEventListener) == null ? void 0 : _a2.call(mq, "change", onChange);
|
|
20224
20236
|
};
|
|
20225
20237
|
}, []);
|
|
20226
|
-
const
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
|
|
20238
|
+
const scrollToIndex = React20.useCallback((i) => {
|
|
20239
|
+
const el = trackRef.current;
|
|
20240
|
+
if (!el) return;
|
|
20241
|
+
const smooth = !reduced.current;
|
|
20242
|
+
programmaticRef.current = true;
|
|
20243
|
+
el.scrollTo({ left: i * el.clientWidth, behavior: smooth ? "smooth" : "auto" });
|
|
20244
|
+
if (programmaticTimer.current) clearTimeout(programmaticTimer.current);
|
|
20245
|
+
programmaticTimer.current = setTimeout(
|
|
20246
|
+
() => {
|
|
20247
|
+
programmaticRef.current = false;
|
|
20248
|
+
},
|
|
20249
|
+
smooth ? 600 : 50
|
|
20250
|
+
);
|
|
20251
|
+
}, []);
|
|
20252
|
+
const onScroll = React20.useCallback(() => {
|
|
20253
|
+
const el = trackRef.current;
|
|
20254
|
+
if (!el) return;
|
|
20255
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
20256
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
20257
|
+
const i = Math.round(el.scrollLeft / Math.max(1, el.clientWidth));
|
|
20258
|
+
setIndex((prev) => prev === i ? prev : i);
|
|
20259
|
+
});
|
|
20260
|
+
if (!programmaticRef.current) {
|
|
20261
|
+
interactRef.current = true;
|
|
20262
|
+
if (interactTimer.current) clearTimeout(interactTimer.current);
|
|
20263
|
+
interactTimer.current = setTimeout(() => {
|
|
20264
|
+
interactRef.current = false;
|
|
20265
|
+
}, 1500);
|
|
20230
20266
|
}
|
|
20231
|
-
setVisible(false);
|
|
20232
|
-
swapRef.current = setTimeout(() => {
|
|
20233
|
-
setIndex((i) => resolve(i));
|
|
20234
|
-
setVisible(true);
|
|
20235
|
-
}, 260);
|
|
20236
20267
|
}, []);
|
|
20237
20268
|
React20.useEffect(() => {
|
|
20238
20269
|
if (items.length <= 1 || intervalMs <= 0) return;
|
|
20239
20270
|
const id = setInterval(() => {
|
|
20240
|
-
if (
|
|
20271
|
+
if (reduced.current) return;
|
|
20272
|
+
if (hoverRef.current || focusRef.current || interactRef.current) return;
|
|
20273
|
+
const el = trackRef.current;
|
|
20274
|
+
if (!el) return;
|
|
20275
|
+
const cur = Math.round(el.scrollLeft / Math.max(1, el.clientWidth));
|
|
20276
|
+
scrollToIndex((cur + 1) % items.length);
|
|
20241
20277
|
}, intervalMs);
|
|
20242
|
-
return () =>
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
|
|
20246
|
-
|
|
20278
|
+
return () => clearInterval(id);
|
|
20279
|
+
}, [items.length, intervalMs, scrollToIndex]);
|
|
20280
|
+
React20.useEffect(
|
|
20281
|
+
() => () => {
|
|
20282
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
20283
|
+
if (interactTimer.current) clearTimeout(interactTimer.current);
|
|
20284
|
+
if (programmaticTimer.current) clearTimeout(programmaticTimer.current);
|
|
20285
|
+
},
|
|
20286
|
+
[]
|
|
20287
|
+
);
|
|
20247
20288
|
if (!items.length) return null;
|
|
20248
|
-
const
|
|
20249
|
-
const review = items[safe];
|
|
20289
|
+
const active = Math.min(index, items.length - 1);
|
|
20250
20290
|
return /* @__PURE__ */ jsx(
|
|
20251
20291
|
"section",
|
|
20252
20292
|
{
|
|
20253
20293
|
className: cn(SURFACE_PRIMARY_9002, "py-24 text-white sm:py-32", className),
|
|
20294
|
+
onMouseEnter: () => {
|
|
20295
|
+
hoverRef.current = true;
|
|
20296
|
+
},
|
|
20297
|
+
onMouseLeave: () => {
|
|
20298
|
+
hoverRef.current = false;
|
|
20299
|
+
},
|
|
20300
|
+
onFocus: () => {
|
|
20301
|
+
focusRef.current = true;
|
|
20302
|
+
},
|
|
20303
|
+
onBlur: () => {
|
|
20304
|
+
focusRef.current = false;
|
|
20305
|
+
},
|
|
20254
20306
|
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl px-6 text-center sm:px-8", children: [
|
|
20255
20307
|
eyebrow && /* @__PURE__ */ jsx("p", { className: "font-ui text-xs font-bold uppercase tracking-[0.22em] text-primary", children: eyebrow }),
|
|
20256
20308
|
/* @__PURE__ */ jsx("h2", { className: "sr-only", children: title }),
|
|
20257
|
-
/* @__PURE__ */
|
|
20309
|
+
/* @__PURE__ */ jsx(
|
|
20258
20310
|
"div",
|
|
20259
20311
|
{
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
"
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
20275
|
-
|
|
20312
|
+
ref: trackRef,
|
|
20313
|
+
onScroll,
|
|
20314
|
+
"aria-roledescription": "carousel",
|
|
20315
|
+
"aria-label": title,
|
|
20316
|
+
className: "flex snap-x snap-mandatory overflow-x-auto scrollbar-none",
|
|
20317
|
+
children: items.map((review, i) => /* @__PURE__ */ jsxs(
|
|
20318
|
+
"div",
|
|
20319
|
+
{
|
|
20320
|
+
role: "group",
|
|
20321
|
+
"aria-roledescription": "slide",
|
|
20322
|
+
"aria-label": `Review ${i + 1} of ${items.length}`,
|
|
20323
|
+
className: "w-full shrink-0 snap-start",
|
|
20324
|
+
children: [
|
|
20325
|
+
/* @__PURE__ */ jsx("div", { className: "mt-8 flex justify-center", children: /* @__PURE__ */ jsx(TrustpilotStars, { stars: review.stars, className: "h-7 w-7" }) }),
|
|
20326
|
+
/* @__PURE__ */ jsxs("blockquote", { className: "mx-auto mt-8 flex min-h-[15rem] max-w-[20ch] items-center justify-center font-sans text-3xl font-normal italic leading-[1.3] text-white sm:min-h-[18rem] sm:text-4xl", children: [
|
|
20327
|
+
"\u201C",
|
|
20328
|
+
review.quote,
|
|
20329
|
+
"\u201D"
|
|
20330
|
+
] }),
|
|
20331
|
+
(review.author || review.location) && /* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
|
|
20332
|
+
review.author && /* @__PURE__ */ jsx("p", { className: "font-ui text-base font-bold tracking-wide text-white", children: review.author }),
|
|
20333
|
+
review.location && /* @__PURE__ */ jsx("p", { className: "mt-1 font-sans text-sm text-white/55", children: review.location })
|
|
20334
|
+
] })
|
|
20335
|
+
]
|
|
20336
|
+
},
|
|
20337
|
+
i
|
|
20338
|
+
))
|
|
20276
20339
|
}
|
|
20277
20340
|
),
|
|
20278
20341
|
items.length > 1 && /* @__PURE__ */ jsx("div", { className: "mt-10 flex justify-center gap-2.5", children: items.map((_, i) => /* @__PURE__ */ jsx(
|
|
@@ -20280,11 +20343,11 @@ function ReviewsSpotlight({
|
|
|
20280
20343
|
{
|
|
20281
20344
|
type: "button",
|
|
20282
20345
|
"aria-label": `Show review ${i + 1} of ${items.length}`,
|
|
20283
|
-
"aria-current": i ===
|
|
20284
|
-
onClick: () =>
|
|
20346
|
+
"aria-current": i === active,
|
|
20347
|
+
onClick: () => scrollToIndex(i),
|
|
20285
20348
|
className: cn(
|
|
20286
20349
|
"h-2 w-2 rounded-full transition-colors",
|
|
20287
|
-
i ===
|
|
20350
|
+
i === active ? "bg-primary" : "bg-white/25 hover:bg-white/45"
|
|
20288
20351
|
)
|
|
20289
20352
|
},
|
|
20290
20353
|
i
|