@clubmed/trident-ui 2.0.0-beta.74 → 2.0.0-beta.76
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/examples/chapters-demo.d.ts +1 -0
- package/examples/chapters-demo.js +46 -0
- package/examples/chapters-demo.js.map +1 -0
- package/examples/criteria-transports-b2b-demo.d.ts +1 -1
- package/examples/criteria-transports-b2b-demo.js +100 -33
- package/examples/criteria-transports-b2b-demo.js.map +1 -1
- package/examples/criteria-transports-demo.js +209 -20
- package/examples/criteria-transports-demo.js.map +1 -1
- package/examples/promises-demo.d.ts +1 -0
- package/examples/promises-demo.js +50 -0
- package/examples/promises-demo.js.map +1 -0
- package/examples/sparkle-wrapper-demo.d.ts +1 -0
- package/examples/sparkle-wrapper-demo.js +34 -0
- package/examples/sparkle-wrapper-demo.js.map +1 -0
- package/package.json +1 -1
- package/styles/animate.css +19 -0
- package/styles/theme.css +1 -0
- package/ui/Chapters/Chapter.d.ts +7 -0
- package/ui/Chapters/Chapter.js +36 -0
- package/ui/Chapters/Chapter.js.map +1 -0
- package/ui/Chapters/ChapterTitle.d.ts +14 -0
- package/ui/Chapters/ChapterTitle.js +35 -0
- package/ui/Chapters/ChapterTitle.js.map +1 -0
- package/ui/Chapters/Chapters.d.ts +15 -0
- package/ui/Chapters/Chapters.js +42 -0
- package/ui/Chapters/Chapters.js.map +1 -0
- package/ui/Chapters/Chapters.themes.d.ts +9 -0
- package/ui/Chapters/Chapters.themes.js +65 -0
- package/ui/Chapters/Chapters.themes.js.map +1 -0
- package/ui/Chapters/ChaptersSummary.d.ts +17 -0
- package/ui/Chapters/ChaptersSummary.js +29 -0
- package/ui/Chapters/ChaptersSummary.js.map +1 -0
- package/ui/ElasticHeight.js +1 -0
- package/ui/ElasticHeight.js.map +1 -1
- package/ui/Promises/Promises.d.ts +26 -0
- package/ui/Promises/Promises.js +42 -0
- package/ui/Promises/Promises.js.map +1 -0
- package/ui/Promises/PromisesMedia.d.ts +12 -0
- package/ui/Promises/PromisesMedia.js +64 -0
- package/ui/Promises/PromisesMedia.js.map +1 -0
- package/ui/Promises/PromisesMenu.d.ts +11 -0
- package/ui/Promises/PromisesMenu.js +154 -0
- package/ui/Promises/PromisesMenu.js.map +1 -0
- package/ui/SparkleWrapper.d.ts +5 -0
- package/ui/SparkleWrapper.js +56 -0
- package/ui/SparkleWrapper.js.map +1 -0
- package/ui/criteria/CriteriaTransports.d.ts +36 -55
- package/ui/criteria/CriteriaTransports.js +256 -206
- package/ui/criteria/CriteriaTransports.js.map +1 -1
- package/ui/forms/NumberField.d.ts +23 -23
- package/examples/criteria-transports-b2c-demo.d.ts +0 -1
- package/examples/criteria-transports-b2c-demo.js +0 -37
- package/examples/criteria-transports-b2c-demo.js.map +0 -1
- package/examples/criteria-transports-data.d.ts +0 -7
- package/examples/criteria-transports-data.js +0 -151
- package/examples/criteria-transports-data.js.map +0 -1
- package/examples/criteria-transports-error-demo.d.ts +0 -1
- package/examples/criteria-transports-error-demo.js +0 -29
- package/examples/criteria-transports-error-demo.js.map +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../../chunks/clsx.js";
|
|
3
|
+
import { Button as t } from "../buttons/Button.js";
|
|
4
|
+
import { n } from "../../chunks/Carousel.context.js";
|
|
5
|
+
import { Carousel as r } from "../carousel/Carousel.js";
|
|
6
|
+
import { CarouselBody as i } from "../carousel/CarouselBody.js";
|
|
7
|
+
import { CarouselItem as a } from "../carousel/CarouselItem.js";
|
|
8
|
+
import { useEffect as o, useId as s, useLayoutEffect as c, useMemo as l, useRef as u } from "react";
|
|
9
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
10
|
+
//#region lib/ui/Promises/PromisesMenu.tsx
|
|
11
|
+
var m = ({ anchorLabel: n, anchorName: r, isActive: i, labelNode: a }) => {
|
|
12
|
+
let o = u(null), s = u(null);
|
|
13
|
+
return c(() => {
|
|
14
|
+
if (!o.current || !s.current) return;
|
|
15
|
+
let e = new ResizeObserver(() => {
|
|
16
|
+
s.current && o.current && (s.current.style.height = `${o.current.offsetHeight}px`);
|
|
17
|
+
});
|
|
18
|
+
return e.observe(o.current), () => e.disconnect();
|
|
19
|
+
}, []), /* @__PURE__ */ f("li", {
|
|
20
|
+
className: e("relative isolate transition-[opacity,height,margin-inline-start] ms-0 duration-300 overflow-hidden rounded-32 bg-white p-20", { "@3xl/promises:ms-52": !i }),
|
|
21
|
+
children: /* @__PURE__ */ p("div", {
|
|
22
|
+
ref: s,
|
|
23
|
+
className: "flex justify-between items-start overflow-hidden",
|
|
24
|
+
style: { anchorName: r },
|
|
25
|
+
children: [/* @__PURE__ */ f("div", {
|
|
26
|
+
ref: o,
|
|
27
|
+
className: "pe-40",
|
|
28
|
+
children: a
|
|
29
|
+
}), i && /* @__PURE__ */ f(t, {
|
|
30
|
+
"aria-hidden": !0,
|
|
31
|
+
className: "opacity-0 pointer-events-none",
|
|
32
|
+
icon: "ArrowDefaultRight",
|
|
33
|
+
inert: !0,
|
|
34
|
+
tabIndex: -1,
|
|
35
|
+
variant: "pill",
|
|
36
|
+
children: n
|
|
37
|
+
})]
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
}, h = ({ activeIndex: e, onSelect: t }) => {
|
|
41
|
+
let { api: r, snapped: i } = n(), a = u(t);
|
|
42
|
+
a.current = t;
|
|
43
|
+
let s = i[0];
|
|
44
|
+
return o(() => {
|
|
45
|
+
s !== void 0 && a.current(s);
|
|
46
|
+
}, [s]), o(() => {
|
|
47
|
+
r?.scrollTo(e);
|
|
48
|
+
}, [r, e]), null;
|
|
49
|
+
}, g = ({ activeIndex: t, className: n, onSelect: o, sliderItems: s }) => {
|
|
50
|
+
let c = u(t), m = l(() => ({
|
|
51
|
+
active: s.length > 1,
|
|
52
|
+
align: "center",
|
|
53
|
+
startIndex: c.current
|
|
54
|
+
}), [s.length]);
|
|
55
|
+
return /* @__PURE__ */ f(d, { children: /* @__PURE__ */ p(r, {
|
|
56
|
+
className: e("relative isolate flex h-full items-center", n),
|
|
57
|
+
options: m,
|
|
58
|
+
children: [/* @__PURE__ */ f(h, {
|
|
59
|
+
activeIndex: t,
|
|
60
|
+
onSelect: o
|
|
61
|
+
}), /* @__PURE__ */ f(i, {
|
|
62
|
+
className: "w-full px-20",
|
|
63
|
+
scrollClassName: "gap-12 md:gap-40 auto-cols-full",
|
|
64
|
+
children: s.map((t, n) => /* @__PURE__ */ f(a, {
|
|
65
|
+
index: n,
|
|
66
|
+
children: /* @__PURE__ */ f("div", {
|
|
67
|
+
"aria-label": `${n + 1}/${s.length}`,
|
|
68
|
+
className: e("rounded-16 overflow-hidden bg-white"),
|
|
69
|
+
children: t
|
|
70
|
+
})
|
|
71
|
+
}, n))
|
|
72
|
+
})]
|
|
73
|
+
}) });
|
|
74
|
+
}, _ = ({ activeIndex: n, className: r, items: i, labels: a, onClickMenu: o }) => {
|
|
75
|
+
let c = s(), u = c.replace(/[^a-zA-Z0-9_-]/g, ""), { menuItems: h, sliderItems: _ } = l(() => {
|
|
76
|
+
let r = i.map(({ href: t, id: r, title: i }, a) => {
|
|
77
|
+
let s = a === n, l = r ?? `${c}_${a}`;
|
|
78
|
+
return {
|
|
79
|
+
anchorName: `--promises-${u}-${a}`,
|
|
80
|
+
href: t,
|
|
81
|
+
id: r,
|
|
82
|
+
isActive: s,
|
|
83
|
+
itemId: l,
|
|
84
|
+
labelNode: /* @__PURE__ */ f("button", {
|
|
85
|
+
id: l,
|
|
86
|
+
"aria-label": i,
|
|
87
|
+
className: e("text-start hover:underline text-h4 text-center font-serif @3xl/promises:text-h4 @5xl/promises:text-h2 @6xl/promises:text-h1 @3xl/promises:text-start"),
|
|
88
|
+
onClick: () => o(a),
|
|
89
|
+
type: "button",
|
|
90
|
+
children: i
|
|
91
|
+
}),
|
|
92
|
+
title: i
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
menuItems: r,
|
|
97
|
+
sliderItems: r.map(({ labelNode: e, href: n, itemId: r }) => /* @__PURE__ */ p("div", {
|
|
98
|
+
className: "rounded-32 p-16",
|
|
99
|
+
children: [e, /* @__PURE__ */ f(t, {
|
|
100
|
+
"aria-describedby": r,
|
|
101
|
+
"aria-label": a.anchor.continue,
|
|
102
|
+
href: n,
|
|
103
|
+
icon: "ArrowDefaultRight",
|
|
104
|
+
variant: "pill",
|
|
105
|
+
children: a.anchor.continue
|
|
106
|
+
})]
|
|
107
|
+
}))
|
|
108
|
+
};
|
|
109
|
+
}, [
|
|
110
|
+
n,
|
|
111
|
+
i,
|
|
112
|
+
a,
|
|
113
|
+
c,
|
|
114
|
+
o,
|
|
115
|
+
u
|
|
116
|
+
]), v = h[n];
|
|
117
|
+
return /* @__PURE__ */ p(d, { children: [
|
|
118
|
+
/* @__PURE__ */ f("ul", {
|
|
119
|
+
className: e("hidden @3xl/promises:block", "absolute bottom-0 inset-x-0 overflow-hidden @3xl/promises:-ms-52 text-black w-full", "@3xl/promises:pointer-events-auto @3xl/promises:static @3xl/promises:p-0 @3xl/promises:pt-40", r),
|
|
120
|
+
children: h.map(({ anchorName: e, id: t, isActive: n, labelNode: r, title: i }, o) => /* @__PURE__ */ f(m, {
|
|
121
|
+
anchorLabel: a.anchor.continue,
|
|
122
|
+
anchorName: e,
|
|
123
|
+
isActive: n,
|
|
124
|
+
labelNode: r
|
|
125
|
+
}, t ?? `${i}-${o}`))
|
|
126
|
+
}),
|
|
127
|
+
v && /* @__PURE__ */ f(t, {
|
|
128
|
+
"aria-describedby": v.itemId,
|
|
129
|
+
"aria-label": a.anchor.continue,
|
|
130
|
+
className: "hidden @3xl/promises:inline-flex transition-[top] duration-200 ease-out-quad absolute z-1",
|
|
131
|
+
href: v.href,
|
|
132
|
+
icon: "ArrowDefaultRight",
|
|
133
|
+
style: {
|
|
134
|
+
positionAnchor: v.anchorName,
|
|
135
|
+
top: "anchor(top)",
|
|
136
|
+
right: "anchor(right)"
|
|
137
|
+
},
|
|
138
|
+
variant: "pill",
|
|
139
|
+
children: a.anchor.continue
|
|
140
|
+
}),
|
|
141
|
+
/* @__PURE__ */ f("div", {
|
|
142
|
+
className: "@3xl/promises:hidden absolute inset-x-0 bottom-20",
|
|
143
|
+
children: /* @__PURE__ */ f(g, {
|
|
144
|
+
activeIndex: n,
|
|
145
|
+
onSelect: o,
|
|
146
|
+
sliderItems: _
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
] });
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
152
|
+
export { _ as PromisesMenu };
|
|
153
|
+
|
|
154
|
+
//# sourceMappingURL=PromisesMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromisesMenu.js","names":[],"sources":["../../../lib/ui/Promises/PromisesMenu.tsx"],"sourcesContent":["'use client';\nimport clsx from 'clsx';\nimport type { FunctionComponent, ReactNode } from 'react';\nimport { useEffect, useId, useMemo, useRef, useLayoutEffect } from 'react';\nimport { useCarousel } from '../carousel/Carousel.context';\n\nimport { Carousel } from '../carousel/Carousel';\nimport { CarouselBody } from '../carousel/CarouselBody';\nimport { CarouselItem } from '../carousel/CarouselItem';\nimport { Button } from '../buttons/Button';\nimport type { PromisesItem, PromisesLabels } from './Promises';\n\ninterface MenuItemProps {\n anchorLabel: string;\n anchorName: string;\n isActive: boolean;\n labelNode: ReactNode;\n}\n\nconst PromisesMenuItem: FunctionComponent<MenuItemProps> = ({\n anchorLabel,\n anchorName,\n isActive,\n labelNode,\n}) => {\n const labelRef = useRef<HTMLDivElement>(null);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!labelRef.current || !containerRef.current) return;\n const resizeObserver = new ResizeObserver(() => {\n if (containerRef.current && labelRef.current) {\n containerRef.current.style.height = `${labelRef.current.offsetHeight}px`;\n }\n });\n resizeObserver.observe(labelRef.current);\n return () => resizeObserver.disconnect();\n }, []);\n\n return (\n <li\n className={clsx(\n 'relative isolate transition-[opacity,height,margin-inline-start] ms-0 duration-300 overflow-hidden rounded-32 bg-white p-20',\n { '@3xl/promises:ms-52': !isActive },\n )}\n >\n <div\n ref={containerRef}\n className=\"flex justify-between items-start overflow-hidden\"\n style={{ anchorName } as unknown as React.CSSProperties}\n >\n <div ref={labelRef} className=\"pe-40\">\n {labelNode}\n </div>\n {isActive && (\n <Button\n aria-hidden\n className=\"opacity-0 pointer-events-none\"\n icon=\"ArrowDefaultRight\"\n inert\n tabIndex={-1}\n variant=\"pill\"\n >\n {anchorLabel}\n </Button>\n )}\n </div>\n </li>\n );\n};\n\ninterface Props {\n activeIndex: number;\n className?: string;\n items: PromisesItem[];\n labels: PromisesLabels;\n onClickMenu: (index: number) => void;\n}\n\ninterface PromisesItemSliderProps {\n activeIndex: number;\n className?: string;\n onSelect: (index: number) => void;\n sliderItems: ReactNode[];\n}\n\nconst CarouselSync: FunctionComponent<{\n activeIndex: number;\n onSelect: (index: number) => void;\n}> = ({ activeIndex, onSelect }) => {\n const { api, snapped } = useCarousel();\n const onSelectRef = useRef(onSelect);\n onSelectRef.current = onSelect;\n\n const snappedIndex = snapped[0];\n useEffect(() => {\n if (snappedIndex !== undefined) onSelectRef.current(snappedIndex);\n }, [snappedIndex]);\n\n useEffect(() => {\n api?.scrollTo(activeIndex);\n }, [api, activeIndex]);\n\n return null;\n};\n\nconst PromisesItemSlider: FunctionComponent<PromisesItemSliderProps> = ({\n activeIndex,\n className,\n onSelect,\n sliderItems,\n}) => {\n const initialIndex = useRef(activeIndex);\n const carouselOptions = useMemo(\n () => ({\n active: sliderItems.length > 1,\n align: 'center' as const,\n startIndex: initialIndex.current,\n }),\n [sliderItems.length],\n );\n\n return (\n <>\n <Carousel\n className={clsx('relative isolate flex h-full items-center', className)}\n options={carouselOptions}\n >\n <CarouselSync activeIndex={activeIndex} onSelect={onSelect} />\n <CarouselBody className=\"w-full px-20\" scrollClassName=\"gap-12 md:gap-40 auto-cols-full\">\n {sliderItems.map((item, i) => (\n <CarouselItem index={i} key={i}>\n <div\n aria-label={`${i + 1}/${sliderItems.length}`}\n className={clsx('rounded-16 overflow-hidden bg-white')}\n >\n {item}\n </div>\n </CarouselItem>\n ))}\n </CarouselBody>\n </Carousel>\n </>\n );\n};\n\nexport const PromisesMenu: FunctionComponent<Props> = ({\n activeIndex,\n className,\n items,\n labels,\n onClickMenu,\n}) => {\n const menuId = useId();\n const safeMenuId = menuId.replace(/[^a-zA-Z0-9_-]/g, '');\n\n const { menuItems, sliderItems } = useMemo(() => {\n const mItems = items.map(({ href, id, title }, index) => {\n const isActive = index === activeIndex;\n const itemId = id ?? `${menuId}_${index}`;\n const anchorName = `--promises-${safeMenuId}-${index}`;\n\n const labelNode = (\n <button\n id={itemId}\n aria-label={title}\n className={clsx(\n 'text-start hover:underline text-h4 text-center font-serif @3xl/promises:text-h4 @5xl/promises:text-h2 @6xl/promises:text-h1 @3xl/promises:text-start',\n )}\n onClick={() => onClickMenu(index)}\n type=\"button\"\n >\n {title}\n </button>\n );\n\n return { anchorName, href, id, isActive, itemId, labelNode, title };\n });\n\n const sItems = mItems.map(({ labelNode, href, itemId }) => (\n <div className=\"rounded-32 p-16\">\n {labelNode}\n <Button\n aria-describedby={itemId}\n aria-label={labels.anchor.continue}\n href={href}\n icon=\"ArrowDefaultRight\"\n variant=\"pill\"\n >\n {labels.anchor.continue}\n </Button>\n </div>\n ));\n\n return { menuItems: mItems, sliderItems: sItems };\n }, [activeIndex, items, labels, menuId, onClickMenu, safeMenuId]);\n\n const activeItem = menuItems[activeIndex];\n\n return (\n <>\n <ul\n className={clsx(\n 'hidden @3xl/promises:block',\n 'absolute bottom-0 inset-x-0 overflow-hidden @3xl/promises:-ms-52 text-black w-full',\n '@3xl/promises:pointer-events-auto @3xl/promises:static @3xl/promises:p-0 @3xl/promises:pt-40',\n className,\n )}\n >\n {menuItems.map(({ anchorName, id, isActive, labelNode, title }, index) => (\n <PromisesMenuItem\n anchorLabel={labels.anchor.continue}\n anchorName={anchorName}\n isActive={isActive}\n key={id ?? `${title}-${index}`}\n labelNode={labelNode}\n />\n ))}\n </ul>\n {activeItem && (\n <Button\n aria-describedby={activeItem.itemId}\n aria-label={labels.anchor.continue}\n className=\"hidden @3xl/promises:inline-flex transition-[top] duration-200 ease-out-quad absolute z-1\"\n href={activeItem.href}\n icon=\"ArrowDefaultRight\"\n style={\n {\n positionAnchor: activeItem.anchorName,\n top: 'anchor(top)',\n right: 'anchor(right)',\n } as React.CSSProperties\n }\n variant=\"pill\"\n >\n {labels.anchor.continue}\n </Button>\n )}\n <div className=\"@3xl/promises:hidden absolute inset-x-0 bottom-20\">\n <PromisesItemSlider\n activeIndex={activeIndex}\n onSelect={onClickMenu}\n sliderItems={sliderItems}\n />\n </div>\n </>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { HTMLAttributes, PropsWithChildren } from 'react';
|
|
2
|
+
export interface SparkleWrapperProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
count?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function SparkleWrapper({ children, className, count, ...props }: PropsWithChildren<SparkleWrapperProps>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as e } from "../chunks/clsx.js";
|
|
3
|
+
import { useLayoutEffect as t, useRef as n, useState as r } from "react";
|
|
4
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
5
|
+
import { Icon as o } from "@clubmed/trident-icons";
|
|
6
|
+
//#region lib/ui/SparkleWrapper.tsx
|
|
7
|
+
function s(e, t) {
|
|
8
|
+
return e + Math.random() * (t - e);
|
|
9
|
+
}
|
|
10
|
+
function c(e) {
|
|
11
|
+
return Array.from({ length: e }, () => ({
|
|
12
|
+
angle: Math.random() * 360,
|
|
13
|
+
distance: s(60, 110),
|
|
14
|
+
delay: Math.round(s(0, 150)),
|
|
15
|
+
size: Math.round(s(8, 20))
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
function l(e, t, n, r) {
|
|
19
|
+
return Math.abs(e) < 1e-6 ? r / Math.abs(t) : Math.abs(t) < 1e-6 ? n / Math.abs(e) : Math.min(n / Math.abs(e), r / Math.abs(t));
|
|
20
|
+
}
|
|
21
|
+
function u({ children: u, className: d, count: f = 7, ...p }) {
|
|
22
|
+
let m = n(null), [h, g] = r([0, 0]), [_] = r(() => c(Math.round(s(f, f + 3))));
|
|
23
|
+
return t(() => {
|
|
24
|
+
if (!m.current) return;
|
|
25
|
+
let { width: e, height: t } = m.current.getBoundingClientRect();
|
|
26
|
+
g([e / 2, t / 2]);
|
|
27
|
+
}, []), /* @__PURE__ */ a("div", {
|
|
28
|
+
...p,
|
|
29
|
+
className: e("relative inline-flex items-center justify-center", d),
|
|
30
|
+
children: [_.map(({ angle: e, distance: t, delay: n, size: r }, a) => {
|
|
31
|
+
let s = e * Math.PI / 180, c = Math.cos(s), u = Math.sin(s), [d, f] = h, p = d > 0 || f > 0 ? l(c, u, d, f) : 0;
|
|
32
|
+
return /* @__PURE__ */ i(o, {
|
|
33
|
+
name: "Diamond",
|
|
34
|
+
"aria-hidden": "true",
|
|
35
|
+
className: "absolute top-1/2 left-1/2 animate-sparkle-fly pointer-events-none",
|
|
36
|
+
style: {
|
|
37
|
+
"--sparkle-start-x": `${Math.round(c * p)}px`,
|
|
38
|
+
"--sparkle-start-y": `${Math.round(u * p)}px`,
|
|
39
|
+
"--sparkle-end-x": `${Math.round(c * (p + t))}px`,
|
|
40
|
+
"--sparkle-end-y": `${Math.round(u * (p + t))}px`,
|
|
41
|
+
animationDelay: `${n}ms`,
|
|
42
|
+
width: `${r}px`,
|
|
43
|
+
height: `${r}px`
|
|
44
|
+
}
|
|
45
|
+
}, a);
|
|
46
|
+
}), /* @__PURE__ */ i("div", {
|
|
47
|
+
ref: m,
|
|
48
|
+
className: "relative z-10 animate-bounce-enter",
|
|
49
|
+
children: u
|
|
50
|
+
})]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { u as SparkleWrapper };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=SparkleWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SparkleWrapper.js","names":[],"sources":["../../lib/ui/SparkleWrapper.tsx"],"sourcesContent":["'use client';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport type { HTMLAttributes, PropsWithChildren } from 'react';\nimport { useLayoutEffect, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nfunction randomBetween(min: number, max: number) {\n return min + Math.random() * (max - min);\n}\n\nfunction generateSparkles(count: number) {\n return Array.from({ length: count }, () => ({\n angle: Math.random() * 360,\n distance: randomBetween(60, 110),\n delay: Math.round(randomBetween(0, 150)),\n size: Math.round(randomBetween(8, 20)),\n }));\n}\n\nfunction edgeT(cos: number, sin: number, hw: number, hh: number): number {\n if (Math.abs(cos) < 1e-6) return hh / Math.abs(sin);\n if (Math.abs(sin) < 1e-6) return hw / Math.abs(cos);\n return Math.min(hw / Math.abs(cos), hh / Math.abs(sin));\n}\n\nexport interface SparkleWrapperProps extends HTMLAttributes<HTMLDivElement> {\n count?: number;\n}\n\nexport function SparkleWrapper({\n children,\n className,\n count = 7,\n ...props\n}: PropsWithChildren<SparkleWrapperProps>) {\n const childRef = useRef<HTMLDivElement>(null);\n const [halfSize, setHalfSize] = useState<[number, number]>([0, 0]);\n const [sparkles] = useState(() => generateSparkles(Math.round(randomBetween(count, count + 3))));\n\n useLayoutEffect(() => {\n if (!childRef.current) return;\n const { width, height } = childRef.current.getBoundingClientRect();\n setHalfSize([width / 2, height / 2]);\n }, []);\n\n return (\n <div {...props} className={clsx('relative inline-flex items-center justify-center', className)}>\n {sparkles.map(({ angle, distance, delay, size }, i) => {\n const rad = (angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const [hw, hh] = halfSize;\n const t = hw > 0 || hh > 0 ? edgeT(cos, sin, hw, hh) : 0;\n\n return (\n <Icon\n key={i}\n name=\"Diamond\"\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-1/2 animate-sparkle-fly pointer-events-none\"\n style={\n {\n '--sparkle-start-x': `${Math.round(cos * t)}px`,\n '--sparkle-start-y': `${Math.round(sin * t)}px`,\n '--sparkle-end-x': `${Math.round(cos * (t + distance))}px`,\n '--sparkle-end-y': `${Math.round(sin * (t + distance))}px`,\n animationDelay: `${delay}ms`,\n width: `${size}px`,\n height: `${size}px`,\n } as React.CSSProperties\n }\n />\n );\n })}\n <div ref={childRef} className=\"relative z-10 animate-bounce-enter\">\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAOA,SAAS,EAAc,GAAa,GAAa;AAC/C,QAAO,IAAM,KAAK,QAAQ,IAAI,IAAM;;AAGtC,SAAS,EAAiB,GAAe;AACvC,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAO,SAAS;EAC1C,OAAO,KAAK,QAAQ,GAAG;EACvB,UAAU,EAAc,IAAI,IAAI;EAChC,OAAO,KAAK,MAAM,EAAc,GAAG,IAAI,CAAC;EACxC,MAAM,KAAK,MAAM,EAAc,GAAG,GAAG,CAAA;EACtC,EAAE;;AAGL,SAAS,EAAM,GAAa,GAAa,GAAY,GAAoB;AAGvE,QAFI,KAAK,IAAI,EAAI,GAAG,OAAa,IAAK,KAAK,IAAI,EAAI,GAC/C,KAAK,IAAI,EAAI,GAAG,OAAa,IAAK,KAAK,IAAI,EAAI,GAC5C,KAAK,IAAI,IAAK,KAAK,IAAI,EAAI,EAAE,IAAK,KAAK,IAAI,EAAI,CAAC;;AAOzD,SAAgB,EAAe,EAC7B,aACA,cACA,WAAQ,GACR,GAAG,KACsC;CACzC,IAAM,IAAW,EAAuB,KAAK,EACvC,CAAC,GAAU,KAAe,EAA2B,CAAC,GAAG,EAAE,CAAC,EAC5D,CAAC,KAAY,QAAe,EAAiB,KAAK,MAAM,EAAc,GAAO,IAAQ,EAAE,CAAC,CAAC,CAAC;AAQhG,QANA,QAAsB;AACpB,MAAI,CAAC,EAAS,QAAS;EACvB,IAAM,EAAE,UAAO,cAAW,EAAS,QAAQ,uBAAuB;AAClE,IAAY,CAAC,IAAQ,GAAG,IAAS,EAAE,CAAC;IACnC,EAAE,CAAC,EAGJ,kBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,EAAK,oDAAoD,EAAU;YAA9F,CACG,EAAS,KAAK,EAAE,UAAO,aAAU,UAAO,WAAQ,MAAM;GACrD,IAAM,IAAO,IAAQ,KAAK,KAAM,KAC1B,IAAM,KAAK,IAAI,EAAI,EACnB,IAAM,KAAK,IAAI,EAAI,EACnB,CAAC,GAAI,KAAM,GACX,IAAI,IAAK,KAAK,IAAK,IAAI,EAAM,GAAK,GAAK,GAAI,EAAG,GAAG;AAEvD,UACE,kBAAC,GAAD;IAEE,MAAK;IACL,eAAY;IACZ,WAAU;IACV,OACE;KACE,qBAAqB,GAAG,KAAK,MAAM,IAAM,EAAE,CAAC;KAC5C,qBAAqB,GAAG,KAAK,MAAM,IAAM,EAAE,CAAC;KAC5C,mBAAmB,GAAG,KAAK,MAAM,KAAO,IAAI,GAAU,CAAC;KACvD,mBAAmB,GAAG,KAAK,MAAM,KAAO,IAAI,GAAU,CAAC;KACvD,gBAAgB,GAAG,EAAM;KACzB,OAAO,GAAG,EAAK;KACf,QAAQ,GAAG,EAAK;;IAGpB,EAfK,EAeL;IAEJ,EACF,kBAAC,OAAD;GAAK,KAAK;GAAU,WAAU;GAC3B;GACG,CAAA,CAAA"}
|
|
@@ -1,72 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export interface TransportSection {
|
|
7
|
-
title: string;
|
|
8
|
-
options: TransportOption[];
|
|
9
|
-
}
|
|
10
|
-
export interface TransportPromotionalCard {
|
|
11
|
-
icon?: string;
|
|
12
|
-
title: string;
|
|
13
|
-
description: string;
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
import { RadioSelectOption } from '../forms/RadioSelect';
|
|
3
|
+
export interface Airport {
|
|
4
|
+
code: string;
|
|
5
|
+
name: string;
|
|
14
6
|
}
|
|
15
7
|
export interface CriteriaTransportsLabels {
|
|
16
|
-
|
|
8
|
+
toggleLabel: string;
|
|
9
|
+
topCitiesLabel: string;
|
|
10
|
+
otherCitiesLabel: string;
|
|
11
|
+
clubMedTransportTitle: string;
|
|
12
|
+
clubMedTransportDescription: string;
|
|
17
13
|
reset?: string;
|
|
18
14
|
apply?: string;
|
|
19
15
|
}
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} | {
|
|
27
|
-
type: 'flightType';
|
|
28
|
-
payload: 'round-trip' | 'one-way';
|
|
29
|
-
} | {
|
|
30
|
-
type: 'flightClass';
|
|
31
|
-
payload: string;
|
|
32
|
-
} | {
|
|
33
|
-
type: 'fromQuery';
|
|
34
|
-
payload: string;
|
|
35
|
-
};
|
|
16
|
+
export interface CriteriaTransportsB2BLabels {
|
|
17
|
+
roundTripLabel: string;
|
|
18
|
+
oneWayLabel: string;
|
|
19
|
+
cabinClassLabel: string;
|
|
20
|
+
departureDateLabel: string;
|
|
21
|
+
}
|
|
36
22
|
export interface CriteriaTransportsProps {
|
|
37
23
|
labels: CriteriaTransportsLabels;
|
|
38
24
|
title?: string;
|
|
39
|
-
/** card (default): white outer card with sand inner. flat: no background,
|
|
25
|
+
/** card (default): white outer card with sand inner. flat: no background, fields rendered directly */
|
|
40
26
|
variant?: 'card' | 'flat';
|
|
41
|
-
/**
|
|
27
|
+
/** Switches between B2C (default) and B2B mode. B2B mode adds flight type, cabin class, and departure selectors. */
|
|
42
28
|
mode?: 'b2c' | 'b2b';
|
|
43
29
|
enabled: boolean;
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
topCities: Airport[];
|
|
31
|
+
otherCities: Airport[];
|
|
32
|
+
selectedAirportCode?: string | null;
|
|
46
33
|
className?: string;
|
|
47
|
-
|
|
34
|
+
onToggle: (enabled: boolean) => void;
|
|
35
|
+
onSelect: (code: string | null) => void;
|
|
48
36
|
onReset?: () => void;
|
|
49
37
|
onApply?: () => void;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
b2bLabels?: CriteriaTransportsB2BLabels;
|
|
39
|
+
/** Currently selected flight type (B2B mode). Defaults to 'roundtrip'. */
|
|
40
|
+
flightType?: 'roundtrip' | 'oneway';
|
|
41
|
+
onFlightTypeChange?: (type: 'roundtrip' | 'oneway') => void;
|
|
42
|
+
/** Currently selected cabin class value (B2B mode). */
|
|
43
|
+
cabinClass?: string;
|
|
44
|
+
/** Options for the cabin class RadioSelect (B2B mode). */
|
|
45
|
+
cabinClassOptions?: RadioSelectOption<string>[];
|
|
46
|
+
onCabinClassChange?: (event: Event, value: string) => void;
|
|
47
|
+
/** Controlled value for the departure airport TextField; also used to filter the airport list. */
|
|
48
|
+
departureQuery?: string;
|
|
49
|
+
onDepartureQueryChange?: (event: Event, value: string) => void;
|
|
50
|
+
/** Error message shown in B2B mode when a prerequisite (e.g. resort selection) is missing. */
|
|
53
51
|
error?: string;
|
|
54
|
-
/** B2B: controlled flight type */
|
|
55
|
-
flightType?: 'round-trip' | 'one-way';
|
|
56
|
-
/** B2B: labels for the round-trip/one-way radio row */
|
|
57
|
-
flightTypeLabels?: {
|
|
58
|
-
roundTrip: string;
|
|
59
|
-
oneWay: string;
|
|
60
|
-
};
|
|
61
|
-
/** B2B: controlled selected class label */
|
|
62
|
-
flightClass?: string;
|
|
63
|
-
/** B2B: label for the class selector field */
|
|
64
|
-
flightClassLabel?: string;
|
|
65
|
-
/** B2B: available class options */
|
|
66
|
-
flightClasses?: string[];
|
|
67
|
-
/** B2B: controlled from/search query */
|
|
68
|
-
fromQuery?: string;
|
|
69
|
-
/** B2B: label for the from search field */
|
|
70
|
-
fromQueryLabel?: string;
|
|
71
52
|
}
|
|
72
53
|
export declare const CriteriaTransports: FunctionComponent<CriteriaTransportsProps>;
|