@windstream/react-shared-components 0.1.31 → 0.1.33
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/README.md +635 -635
- package/dist/contentful/index.d.ts +14 -2
- package/dist/contentful/index.esm.js +3 -3
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +3 -3
- package/dist/contentful/index.js.map +1 -1
- package/dist/core.d.ts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/index.esm.js +1 -1
- package/dist/utils/index.esm.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +182 -182
- package/src/components/accordion/Accordion.stories.tsx +230 -230
- package/src/components/accordion/index.tsx +70 -70
- package/src/components/accordion/types.ts +12 -12
- package/src/components/alert-card/AlertCard.stories.tsx +171 -171
- package/src/components/alert-card/index.tsx +41 -41
- package/src/components/alert-card/types.ts +13 -13
- package/src/components/brand-button/BrandButton.stories.tsx +223 -223
- package/src/components/brand-button/helpers.ts +35 -35
- package/src/components/brand-button/index.tsx +114 -115
- package/src/components/brand-button/types.ts +37 -37
- package/src/components/button/Button.stories.tsx +108 -108
- package/src/components/button/index.tsx +27 -27
- package/src/components/button/types.ts +14 -14
- package/src/components/call-button/CallButton.stories.tsx +324 -324
- package/src/components/call-button/index.tsx +86 -86
- package/src/components/call-button/types.ts +11 -11
- package/src/components/checkbox/Checkbox.stories.tsx +247 -247
- package/src/components/checkbox/index.tsx +197 -197
- package/src/components/checkbox/types.ts +27 -27
- package/src/components/checklist/Checklist.stories.tsx +150 -150
- package/src/components/checklist/index.tsx +63 -61
- package/src/components/checklist/types.ts +18 -17
- package/src/components/collapse/Collapse.stories.tsx +255 -255
- package/src/components/collapse/index.tsx +46 -46
- package/src/components/collapse/types.ts +6 -6
- package/src/components/divider/Divider.stories.tsx +205 -205
- package/src/components/divider/index.tsx +22 -22
- package/src/components/divider/type.ts +3 -3
- package/src/components/image/Image.stories.tsx +113 -113
- package/src/components/image/index.tsx +25 -25
- package/src/components/image/types.ts +40 -40
- package/src/components/input/Input.stories.tsx +325 -325
- package/src/components/input/index.tsx +177 -177
- package/src/components/input/types.ts +37 -37
- package/src/components/link/Link.stories.tsx +163 -163
- package/src/components/link/types.ts +25 -25
- package/src/components/list/List.stories.tsx +272 -272
- package/src/components/list/index.tsx +88 -88
- package/src/components/list/list-item/index.tsx +38 -38
- package/src/components/list/list-item/types.ts +13 -13
- package/src/components/list/types.ts +29 -29
- package/src/components/material-icon/MaterialIcon.stories.tsx +322 -322
- package/src/components/material-icon/constants.ts +98 -98
- package/src/components/material-icon/index.tsx +47 -47
- package/src/components/material-icon/types.ts +31 -31
- package/src/components/modal/Modal.stories.tsx +171 -171
- package/src/components/modal/index.tsx +164 -164
- package/src/components/modal/types.ts +24 -24
- package/src/components/next-image/index.tsx +54 -54
- package/src/components/next-image/types.ts +1 -1
- package/src/components/pagination/index.tsx +100 -100
- package/src/components/pagination/types.ts +6 -6
- package/src/components/radio-button/RadioButton.stories.tsx +307 -307
- package/src/components/radio-button/index.tsx +75 -75
- package/src/components/radio-button/types.ts +21 -21
- package/src/components/see-more/SeeMore.stories.tsx +181 -181
- package/src/components/see-more/index.tsx +44 -44
- package/src/components/see-more/types.ts +4 -4
- package/src/components/select/Select.stories.tsx +411 -411
- package/src/components/select/index.tsx +155 -155
- package/src/components/select/types.ts +36 -36
- package/src/components/select-plan-button/SelectPlanButton.stories.tsx +184 -184
- package/src/components/select-plan-button/index.tsx +59 -59
- package/src/components/select-plan-button/types.ts +17 -17
- package/src/components/skeleton/Skeleton.stories.tsx +179 -179
- package/src/components/skeleton/index.tsx +61 -61
- package/src/components/skeleton/types.ts +4 -4
- package/src/components/spinner/Spinner.stories.tsx +335 -335
- package/src/components/spinner/index.tsx +44 -44
- package/src/components/spinner/types.ts +5 -5
- package/src/components/text/Text.stories.tsx +321 -321
- package/src/components/text/index.tsx +25 -25
- package/src/components/text/types.ts +45 -45
- package/src/components/tooltip/Tooltip.stories.tsx +219 -219
- package/src/components/tooltip/index.tsx +74 -74
- package/src/components/tooltip/types.ts +7 -7
- package/src/components/view-cart-button/ViewCartButton.stories.tsx +252 -252
- package/src/components/view-cart-button/index.tsx +42 -42
- package/src/components/view-cart-button/types.ts +5 -5
- package/src/contentful/blocks/accordion/index.tsx +62 -62
- package/src/contentful/blocks/address-input-banner/index.tsx +52 -52
- package/src/contentful/blocks/address-input-banner/types.ts +14 -14
- package/src/contentful/blocks/anchored-bottom-banner/index.tsx +65 -65
- package/src/contentful/blocks/anchored-bottom-banner/types.ts +9 -9
- package/src/contentful/blocks/blogs-grid/index.tsx +134 -134
- package/src/contentful/blocks/blogs-grid/types.ts +26 -26
- package/src/contentful/blocks/button/Button.stories.tsx +40 -40
- package/src/contentful/blocks/button/index.tsx +129 -129
- package/src/contentful/blocks/button/types.ts +39 -39
- package/src/contentful/blocks/callout/Callout.stories.tsx +23 -23
- package/src/contentful/blocks/callout/index.tsx +88 -88
- package/src/contentful/blocks/callout/types.ts +15 -15
- package/src/contentful/blocks/cards/Cards.stories.tsx +23 -23
- package/src/contentful/blocks/cards/blog-card/index.tsx +110 -110
- package/src/contentful/blocks/cards/blog-card/types.ts +18 -18
- package/src/contentful/blocks/cards/index.tsx +13 -13
- package/src/contentful/blocks/cards/product-card/index.tsx +252 -252
- package/src/contentful/blocks/cards/product-card/types.ts +28 -28
- package/src/contentful/blocks/cards/simple-card/index.tsx +89 -89
- package/src/contentful/blocks/cards/testimonial-card/index.tsx +90 -90
- package/src/contentful/blocks/cards/testimonial-card/types.tsx +12 -12
- package/src/contentful/blocks/cards/types.ts +1 -1
- package/src/contentful/blocks/carousel/Carousel.stories.tsx +23 -23
- package/src/contentful/blocks/carousel/helper.tsx +440 -440
- package/src/contentful/blocks/carousel/index.tsx +85 -85
- package/src/contentful/blocks/carousel/types.ts +144 -144
- package/src/contentful/blocks/cookiebanner/index.tsx +146 -0
- package/src/contentful/blocks/cookiebanner/type.ts +7 -0
- package/src/contentful/blocks/cta-callout/CtaCallout.stories.tsx +46 -46
- package/src/contentful/blocks/cta-callout/index.tsx +60 -60
- package/src/contentful/blocks/cta-callout/types.ts +26 -26
- package/src/contentful/blocks/dynamic-tabs/index.tsx +204 -204
- package/src/contentful/blocks/dynamic-tabs/types.ts +21 -21
- package/src/contentful/blocks/find-kinetic/index.tsx +130 -130
- package/src/contentful/blocks/floating-banner/FloatingBanner.stories.tsx +34 -34
- package/src/contentful/blocks/floating-banner/index.tsx +97 -97
- package/src/contentful/blocks/floating-banner/types.ts +22 -22
- package/src/contentful/blocks/footer/Footer.stories.tsx +30 -30
- package/src/contentful/blocks/footer/index.tsx +90 -90
- package/src/contentful/blocks/image-promo-bar/ImagePromoBar.stories.tsx +23 -23
- package/src/contentful/blocks/image-promo-bar/helper.tsx +28 -28
- package/src/contentful/blocks/image-promo-bar/index.tsx +14 -12
- package/src/contentful/blocks/image-promo-bar/types.ts +44 -44
- package/src/contentful/blocks/image-promo-bar/vimeo-embed.tsx +93 -93
- package/src/contentful/blocks/image-promo-bar/youtube-embed.tsx +46 -46
- package/src/contentful/blocks/modal/constants.ts +53 -53
- package/src/contentful/blocks/modal/types.ts +12 -12
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.tsx +113 -113
- package/src/contentful/blocks/navigation/index.tsx +394 -394
- package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.tsx +82 -82
- package/src/contentful/blocks/navigation/types.ts +41 -41
- package/src/contentful/blocks/primary-hero/PrimaryHero.stories.tsx +23 -23
- package/src/contentful/blocks/primary-hero/index.tsx +234 -234
- package/src/contentful/blocks/primary-hero/types.ts +35 -35
- package/src/contentful/blocks/search-block/index.tsx +90 -90
- package/src/contentful/blocks/shape-background-wrapper/ShapeBackgroundWrapper.stories.tsx +26 -26
- package/src/contentful/blocks/shape-background-wrapper/index.tsx +124 -124
- package/src/contentful/blocks/shape-background-wrapper/types.ts +36 -36
- package/src/contentful/blocks/text/Text.stories.tsx +23 -23
- package/src/contentful/blocks/text/index.tsx +12 -12
- package/src/contentful/blocks/text/types.ts +1 -1
- package/src/contentful/index.ts +81 -78
- package/src/hooks/use-body-scroll-lock.ts +34 -34
- package/src/hooks/use-carousel-swipe.ts +264 -264
- package/src/hooks/use-outside-click.ts +17 -17
- package/src/index.ts +101 -101
- package/src/next/index.ts +5 -5
- package/src/setupTests.ts +46 -46
- package/src/stories/DocsTemplate.tsx +24 -24
- package/src/styles/globals.css +343 -343
- package/src/types/global.d.ts +9 -9
- package/src/types/micro-components.ts +99 -99
- package/src/types/utm.ts +49 -49
- package/src/utils/cookie.ts +80 -58
- package/src/utils/index.ts +65 -65
- package/src/utils/utm.ts +221 -221
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import React, { useMemo } from "react";
|
|
2
|
-
import { VideoEmbedProps } from "./types";
|
|
3
|
-
|
|
4
|
-
import { cx } from "@shared/utils";
|
|
5
|
-
|
|
6
|
-
const extractVimeoIdandHash = (href: string) => {
|
|
7
|
-
// Strip query parameters and fragments
|
|
8
|
-
const cleanHref = href.split(/[?#]/)[0].replace(/\/+$/, "");
|
|
9
|
-
const match =
|
|
10
|
-
cleanHref.match(/vimeo\.com\/(?:.*\/)?(\d{6,})/) ||
|
|
11
|
-
cleanHref.match(/player\.vimeo\.com\/video\/(\d{6,})/);
|
|
12
|
-
|
|
13
|
-
const parts = cleanHref.split("/");
|
|
14
|
-
const hash = parts[parts.length - 1];
|
|
15
|
-
|
|
16
|
-
if (!match?.[1]) return "";
|
|
17
|
-
if (match[1] === hash) return match[1];
|
|
18
|
-
return `${match[1]}/${hash}`;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const VimeoEmbed: React.FC<VideoEmbedProps> = props => {
|
|
22
|
-
const { link, containerClassName, autoplay = false, debug = false } = props;
|
|
23
|
-
|
|
24
|
-
const { href, embedId } = useMemo(() => {
|
|
25
|
-
if (!link) return { href: "", embedId: "" };
|
|
26
|
-
const resolved = link.toString();
|
|
27
|
-
const id = extractVimeoIdandHash(resolved);
|
|
28
|
-
return { href: resolved, embedId: id };
|
|
29
|
-
}, [link]);
|
|
30
|
-
|
|
31
|
-
if (debug) {
|
|
32
|
-
// eslint-disable-next-line no-console
|
|
33
|
-
console.log("[VimeoEmbed] href:", href, "id:", embedId);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!embedId) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const params = new URLSearchParams({
|
|
41
|
-
autoplay: autoplay ? "1" : "0",
|
|
42
|
-
muted: "0",
|
|
43
|
-
playsinline: "1",
|
|
44
|
-
dnt: "1",
|
|
45
|
-
title: "0",
|
|
46
|
-
byline: "0",
|
|
47
|
-
portrait: "0",
|
|
48
|
-
autopause: "1",
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const o_src = `https://player.vimeo.com/video/${embedId}?${params.toString()}`;
|
|
52
|
-
const src = normalizeVimeoPlayerSrc(o_src);
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<div
|
|
56
|
-
className={cx(
|
|
57
|
-
"relative h-0 w-full overflow-hidden pb-[56.25%]",
|
|
58
|
-
containerClassName
|
|
59
|
-
)}
|
|
60
|
-
>
|
|
61
|
-
<iframe
|
|
62
|
-
className="absolute left-0 top-0 h-full w-full"
|
|
63
|
-
src={src}
|
|
64
|
-
allow="autoplay; fullscreen; picture-in-picture"
|
|
65
|
-
allowFullScreen={true}
|
|
66
|
-
referrerPolicy="strict-origin-when-cross-origin"
|
|
67
|
-
title="Embedded vimeo"
|
|
68
|
-
/>
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
function normalizeVimeoPlayerSrc(src: string): string {
|
|
74
|
-
try {
|
|
75
|
-
const u = new URL(src);
|
|
76
|
-
// Expect path like /video/{id}
|
|
77
|
-
const parts = u.pathname.split("/").filter(Boolean);
|
|
78
|
-
// Handle /video/{id}/{hash} -> move {hash} to ?h=...
|
|
79
|
-
if (parts[0] === "video" && parts.length >= 2) {
|
|
80
|
-
const id = parts[1];
|
|
81
|
-
const maybeHash = parts[2];
|
|
82
|
-
// Rebuild base
|
|
83
|
-
const base = `https://player.vimeo.com/video/${id}`;
|
|
84
|
-
if (maybeHash && /^[a-f0-9]+$/i.test(maybeHash)) {
|
|
85
|
-
u.searchParams.set("h", maybeHash);
|
|
86
|
-
}
|
|
87
|
-
return `${base}?${u.searchParams.toString()}`;
|
|
88
|
-
}
|
|
89
|
-
return src;
|
|
90
|
-
} catch {
|
|
91
|
-
return src;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { VideoEmbedProps } from "./types";
|
|
3
|
+
|
|
4
|
+
import { cx } from "@shared/utils";
|
|
5
|
+
|
|
6
|
+
const extractVimeoIdandHash = (href: string) => {
|
|
7
|
+
// Strip query parameters and fragments
|
|
8
|
+
const cleanHref = href.split(/[?#]/)[0].replace(/\/+$/, "");
|
|
9
|
+
const match =
|
|
10
|
+
cleanHref.match(/vimeo\.com\/(?:.*\/)?(\d{6,})/) ||
|
|
11
|
+
cleanHref.match(/player\.vimeo\.com\/video\/(\d{6,})/);
|
|
12
|
+
|
|
13
|
+
const parts = cleanHref.split("/");
|
|
14
|
+
const hash = parts[parts.length - 1];
|
|
15
|
+
|
|
16
|
+
if (!match?.[1]) return "";
|
|
17
|
+
if (match[1] === hash) return match[1];
|
|
18
|
+
return `${match[1]}/${hash}`;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const VimeoEmbed: React.FC<VideoEmbedProps> = props => {
|
|
22
|
+
const { link, containerClassName, autoplay = false, debug = false } = props;
|
|
23
|
+
|
|
24
|
+
const { href, embedId } = useMemo(() => {
|
|
25
|
+
if (!link) return { href: "", embedId: "" };
|
|
26
|
+
const resolved = link.toString();
|
|
27
|
+
const id = extractVimeoIdandHash(resolved);
|
|
28
|
+
return { href: resolved, embedId: id };
|
|
29
|
+
}, [link]);
|
|
30
|
+
|
|
31
|
+
if (debug) {
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
console.log("[VimeoEmbed] href:", href, "id:", embedId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!embedId) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const params = new URLSearchParams({
|
|
41
|
+
autoplay: autoplay ? "1" : "0",
|
|
42
|
+
muted: "0",
|
|
43
|
+
playsinline: "1",
|
|
44
|
+
dnt: "1",
|
|
45
|
+
title: "0",
|
|
46
|
+
byline: "0",
|
|
47
|
+
portrait: "0",
|
|
48
|
+
autopause: "1",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const o_src = `https://player.vimeo.com/video/${embedId}?${params.toString()}`;
|
|
52
|
+
const src = normalizeVimeoPlayerSrc(o_src);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
className={cx(
|
|
57
|
+
"relative h-0 w-full overflow-hidden pb-[56.25%]",
|
|
58
|
+
containerClassName
|
|
59
|
+
)}
|
|
60
|
+
>
|
|
61
|
+
<iframe
|
|
62
|
+
className="absolute left-0 top-0 h-full w-full"
|
|
63
|
+
src={src}
|
|
64
|
+
allow="autoplay; fullscreen; picture-in-picture"
|
|
65
|
+
allowFullScreen={true}
|
|
66
|
+
referrerPolicy="strict-origin-when-cross-origin"
|
|
67
|
+
title="Embedded vimeo"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
function normalizeVimeoPlayerSrc(src: string): string {
|
|
74
|
+
try {
|
|
75
|
+
const u = new URL(src);
|
|
76
|
+
// Expect path like /video/{id}
|
|
77
|
+
const parts = u.pathname.split("/").filter(Boolean);
|
|
78
|
+
// Handle /video/{id}/{hash} -> move {hash} to ?h=...
|
|
79
|
+
if (parts[0] === "video" && parts.length >= 2) {
|
|
80
|
+
const id = parts[1];
|
|
81
|
+
const maybeHash = parts[2];
|
|
82
|
+
// Rebuild base
|
|
83
|
+
const base = `https://player.vimeo.com/video/${id}`;
|
|
84
|
+
if (maybeHash && /^[a-f0-9]+$/i.test(maybeHash)) {
|
|
85
|
+
u.searchParams.set("h", maybeHash);
|
|
86
|
+
}
|
|
87
|
+
return `${base}?${u.searchParams.toString()}`;
|
|
88
|
+
}
|
|
89
|
+
return src;
|
|
90
|
+
} catch {
|
|
91
|
+
return src;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import React, { useMemo } from "react";
|
|
2
|
-
import { VideoEmbedProps } from "./types";
|
|
3
|
-
|
|
4
|
-
import { cx } from "@shared/utils";
|
|
5
|
-
|
|
6
|
-
// import styles from "./styles.module.scss";
|
|
7
|
-
|
|
8
|
-
export type Props = {
|
|
9
|
-
containerClassName?: string;
|
|
10
|
-
autoplay?: boolean; // Add the autoplay prop
|
|
11
|
-
} & VideoEmbedProps;
|
|
12
|
-
|
|
13
|
-
export const YoutubeEmbed: React.FC<Props> = props => {
|
|
14
|
-
const { link, containerClassName, autoplay = false } = props;
|
|
15
|
-
|
|
16
|
-
const embedId = useMemo(() => {
|
|
17
|
-
if (!link) return "";
|
|
18
|
-
|
|
19
|
-
const href = link.toString();
|
|
20
|
-
const regExp =
|
|
21
|
-
/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
|
|
22
|
-
const match = href.match(regExp);
|
|
23
|
-
|
|
24
|
-
return match && match[7].length === 11 ? match[7] : "";
|
|
25
|
-
}, [link]);
|
|
26
|
-
|
|
27
|
-
// Add autoplay parameter to the URL if autoplay is true
|
|
28
|
-
const autoplayParam = autoplay ? "?autoplay=1" : "";
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div
|
|
32
|
-
className={cx(
|
|
33
|
-
"relative h-0 w-full overflow-hidden pb-[56.25%]",
|
|
34
|
-
containerClassName
|
|
35
|
-
)}
|
|
36
|
-
>
|
|
37
|
-
<iframe
|
|
38
|
-
className="absolute left-0 top-0 h-full w-full"
|
|
39
|
-
src={`https://www.youtube.com/embed/${embedId}${autoplayParam}`}
|
|
40
|
-
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
41
|
-
allowFullScreen={true}
|
|
42
|
-
title="Embedded youtube"
|
|
43
|
-
/>
|
|
44
|
-
</div>
|
|
45
|
-
);
|
|
46
|
-
};
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { VideoEmbedProps } from "./types";
|
|
3
|
+
|
|
4
|
+
import { cx } from "@shared/utils";
|
|
5
|
+
|
|
6
|
+
// import styles from "./styles.module.scss";
|
|
7
|
+
|
|
8
|
+
export type Props = {
|
|
9
|
+
containerClassName?: string;
|
|
10
|
+
autoplay?: boolean; // Add the autoplay prop
|
|
11
|
+
} & VideoEmbedProps;
|
|
12
|
+
|
|
13
|
+
export const YoutubeEmbed: React.FC<Props> = props => {
|
|
14
|
+
const { link, containerClassName, autoplay = false } = props;
|
|
15
|
+
|
|
16
|
+
const embedId = useMemo(() => {
|
|
17
|
+
if (!link) return "";
|
|
18
|
+
|
|
19
|
+
const href = link.toString();
|
|
20
|
+
const regExp =
|
|
21
|
+
/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
|
|
22
|
+
const match = href.match(regExp);
|
|
23
|
+
|
|
24
|
+
return match && match[7].length === 11 ? match[7] : "";
|
|
25
|
+
}, [link]);
|
|
26
|
+
|
|
27
|
+
// Add autoplay parameter to the URL if autoplay is true
|
|
28
|
+
const autoplayParam = autoplay ? "?autoplay=1" : "";
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
className={cx(
|
|
33
|
+
"relative h-0 w-full overflow-hidden pb-[56.25%]",
|
|
34
|
+
containerClassName
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
<iframe
|
|
38
|
+
className="absolute left-0 top-0 h-full w-full"
|
|
39
|
+
src={`https://www.youtube.com/embed/${embedId}${autoplayParam}`}
|
|
40
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
41
|
+
allowFullScreen={true}
|
|
42
|
+
title="Embedded youtube"
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
export const backdropAnimationVariants = {
|
|
2
|
-
closed: {
|
|
3
|
-
opacity: 0,
|
|
4
|
-
},
|
|
5
|
-
open: {
|
|
6
|
-
opacity: 1,
|
|
7
|
-
},
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const contentAnimationVariants = {
|
|
11
|
-
closed: {
|
|
12
|
-
opacity: 0,
|
|
13
|
-
scale: 0.96,
|
|
14
|
-
},
|
|
15
|
-
open: {
|
|
16
|
-
opacity: 1,
|
|
17
|
-
scale: 1,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const popperAnimationVariants = {
|
|
22
|
-
closed: {
|
|
23
|
-
opacity: 0,
|
|
24
|
-
y: "-100%",
|
|
25
|
-
x: "-50%",
|
|
26
|
-
},
|
|
27
|
-
open: {
|
|
28
|
-
opacity: 1,
|
|
29
|
-
y: "-50%",
|
|
30
|
-
x: "-50%",
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const bottomSheetAnimationVariants = {
|
|
35
|
-
closed: {
|
|
36
|
-
opacity: 0,
|
|
37
|
-
y: "100%",
|
|
38
|
-
x: "-50%",
|
|
39
|
-
},
|
|
40
|
-
open: {
|
|
41
|
-
opacity: 1,
|
|
42
|
-
y: "-50%",
|
|
43
|
-
x: "-50%",
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const sizeToPixel = {
|
|
48
|
-
xs: "475px",
|
|
49
|
-
sm: "640px",
|
|
50
|
-
md: "768px",
|
|
51
|
-
lg: "1024px",
|
|
52
|
-
xl: "1280px",
|
|
53
|
-
};
|
|
1
|
+
export const backdropAnimationVariants = {
|
|
2
|
+
closed: {
|
|
3
|
+
opacity: 0,
|
|
4
|
+
},
|
|
5
|
+
open: {
|
|
6
|
+
opacity: 1,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const contentAnimationVariants = {
|
|
11
|
+
closed: {
|
|
12
|
+
opacity: 0,
|
|
13
|
+
scale: 0.96,
|
|
14
|
+
},
|
|
15
|
+
open: {
|
|
16
|
+
opacity: 1,
|
|
17
|
+
scale: 1,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const popperAnimationVariants = {
|
|
22
|
+
closed: {
|
|
23
|
+
opacity: 0,
|
|
24
|
+
y: "-100%",
|
|
25
|
+
x: "-50%",
|
|
26
|
+
},
|
|
27
|
+
open: {
|
|
28
|
+
opacity: 1,
|
|
29
|
+
y: "-50%",
|
|
30
|
+
x: "-50%",
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const bottomSheetAnimationVariants = {
|
|
35
|
+
closed: {
|
|
36
|
+
opacity: 0,
|
|
37
|
+
y: "100%",
|
|
38
|
+
x: "-50%",
|
|
39
|
+
},
|
|
40
|
+
open: {
|
|
41
|
+
opacity: 1,
|
|
42
|
+
y: "-50%",
|
|
43
|
+
x: "-50%",
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const sizeToPixel = {
|
|
48
|
+
xs: "475px",
|
|
49
|
+
sm: "640px",
|
|
50
|
+
md: "768px",
|
|
51
|
+
lg: "1024px",
|
|
52
|
+
xl: "1280px",
|
|
53
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export type ModalProps = {
|
|
4
|
-
isOpen: boolean;
|
|
5
|
-
onRequestClose?: () => void;
|
|
6
|
-
size?: "lg" | "md" | "sm" | "xl" | "xs";
|
|
7
|
-
title?: string;
|
|
8
|
-
description?: React.ReactNode;
|
|
9
|
-
content?: React.ReactNode;
|
|
10
|
-
children?: React.ReactNode;
|
|
11
|
-
bodyClassName?: string;
|
|
12
|
-
};
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export type ModalProps = {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onRequestClose?: () => void;
|
|
6
|
+
size?: "lg" | "md" | "sm" | "xl" | "xs";
|
|
7
|
+
title?: string;
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
content?: React.ReactNode;
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
bodyClassName?: string;
|
|
12
|
+
};
|
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
import React, { CSSProperties } from "react";
|
|
2
|
-
|
|
3
|
-
import { MaterialIcon } from "@shared/components/material-icon";
|
|
4
|
-
import { Text } from "@shared/components/text";
|
|
5
|
-
import { Button } from "@shared/contentful/blocks/button";
|
|
6
|
-
import { ButtonProps as ContentfulButtonProps } from "@shared/contentful/blocks/button/types";
|
|
7
|
-
import { useOutsideClick } from "@shared/hooks/use-outside-click";
|
|
8
|
-
import { cx } from "@shared/utils";
|
|
9
|
-
|
|
10
|
-
type ComponentButtonGroup = {
|
|
11
|
-
anchorId?: string | null;
|
|
12
|
-
title?: string | null;
|
|
13
|
-
items?: { items?: ContentfulButtonProps[] | null } | null;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
type Link = ContentfulButtonProps | ComponentButtonGroup;
|
|
17
|
-
|
|
18
|
-
type LinkGroupsProps = {
|
|
19
|
-
link?: Link;
|
|
20
|
-
anchorName: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const isButton = (link: Link): link is ContentfulButtonProps => {
|
|
24
|
-
// If your group never has `href`, this is a simple and effective guard
|
|
25
|
-
return typeof (link as ContentfulButtonProps).href === "string";
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const DesktopLinkGroups: React.FC<LinkGroupsProps> = ({
|
|
29
|
-
link,
|
|
30
|
-
anchorName,
|
|
31
|
-
}) => {
|
|
32
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
33
|
-
|
|
34
|
-
const ref = React.useRef<HTMLDivElement>(null);
|
|
35
|
-
useOutsideClick(ref, () => setIsOpen(false));
|
|
36
|
-
|
|
37
|
-
if (!link) return null;
|
|
38
|
-
|
|
39
|
-
// Single button
|
|
40
|
-
if (isButton(link)) {
|
|
41
|
-
return (
|
|
42
|
-
<Button
|
|
43
|
-
key={`submenu-link-btn-${link.anchorId}`}
|
|
44
|
-
{...link}
|
|
45
|
-
linkClassName="body3 flex items-center text-text h-full"
|
|
46
|
-
linkVariant="unstyled"
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Group
|
|
52
|
-
const { anchorId, title, items } = link;
|
|
53
|
-
const subMenu = Array.isArray(items?.items) ? items!.items! : [];
|
|
54
|
-
const fullAnchorName = `--link-anchor-${anchorName}`;
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<div
|
|
58
|
-
className="relative h-full"
|
|
59
|
-
style={{ anchorName: fullAnchorName } as CSSProperties}
|
|
60
|
-
ref={ref}
|
|
61
|
-
>
|
|
62
|
-
<Button
|
|
63
|
-
onClick={() => setIsOpen(prev => !prev)}
|
|
64
|
-
aria-expanded={isOpen}
|
|
65
|
-
buttonClassName="group body3 flex h-full text-text items-center"
|
|
66
|
-
key={anchorId}
|
|
67
|
-
showButtonAs="unstyled"
|
|
68
|
-
>
|
|
69
|
-
<Text as="span" className="group-hover:underline">
|
|
70
|
-
{title ?? null}
|
|
71
|
-
</Text>
|
|
72
|
-
<MaterialIcon
|
|
73
|
-
weight="200"
|
|
74
|
-
size={24}
|
|
75
|
-
className="text-icon-secondary group-hover:opacity-50"
|
|
76
|
-
name={isOpen ? "keyboard_arrow_up" : "keyboard_arrow_down"}
|
|
77
|
-
/>
|
|
78
|
-
</Button>
|
|
79
|
-
|
|
80
|
-
<div
|
|
81
|
-
className={cx(
|
|
82
|
-
"shadow-navDrop fixed z-
|
|
83
|
-
"transition-[opacity,transform] ease-out",
|
|
84
|
-
isOpen && subMenu.length > 0
|
|
85
|
-
? "pointer-events-auto translate-y-0 opacity-100 duration-75"
|
|
86
|
-
: "pointer-events-none -translate-y-2 opacity-0 duration-0"
|
|
87
|
-
)}
|
|
88
|
-
style={
|
|
89
|
-
{
|
|
90
|
-
positionAnchor: fullAnchorName,
|
|
91
|
-
top: "anchor(bottom)",
|
|
92
|
-
left: "calc((anchor(left) + anchor(right)) / 2)",
|
|
93
|
-
translate: "-50% 0",
|
|
94
|
-
} as CSSProperties
|
|
95
|
-
}
|
|
96
|
-
>
|
|
97
|
-
<ul className="flex flex-col gap-2 py-2">
|
|
98
|
-
{subMenu.map((site, index) => {
|
|
99
|
-
return (
|
|
100
|
-
<li key={`submenu-link-${index}`} className="submenu-link">
|
|
101
|
-
<Button
|
|
102
|
-
{...site}
|
|
103
|
-
linkVariant="unstyled"
|
|
104
|
-
linkClassName="body3 px-4 hover:bg-bg-surface-hover flex items-center w-full h-11 text-text-link"
|
|
105
|
-
/>
|
|
106
|
-
</li>
|
|
107
|
-
);
|
|
108
|
-
})}
|
|
109
|
-
</ul>
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
};
|
|
1
|
+
import React, { CSSProperties } from "react";
|
|
2
|
+
|
|
3
|
+
import { MaterialIcon } from "@shared/components/material-icon";
|
|
4
|
+
import { Text } from "@shared/components/text";
|
|
5
|
+
import { Button } from "@shared/contentful/blocks/button";
|
|
6
|
+
import { ButtonProps as ContentfulButtonProps } from "@shared/contentful/blocks/button/types";
|
|
7
|
+
import { useOutsideClick } from "@shared/hooks/use-outside-click";
|
|
8
|
+
import { cx } from "@shared/utils";
|
|
9
|
+
|
|
10
|
+
type ComponentButtonGroup = {
|
|
11
|
+
anchorId?: string | null;
|
|
12
|
+
title?: string | null;
|
|
13
|
+
items?: { items?: ContentfulButtonProps[] | null } | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type Link = ContentfulButtonProps | ComponentButtonGroup;
|
|
17
|
+
|
|
18
|
+
type LinkGroupsProps = {
|
|
19
|
+
link?: Link;
|
|
20
|
+
anchorName: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const isButton = (link: Link): link is ContentfulButtonProps => {
|
|
24
|
+
// If your group never has `href`, this is a simple and effective guard
|
|
25
|
+
return typeof (link as ContentfulButtonProps).href === "string";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const DesktopLinkGroups: React.FC<LinkGroupsProps> = ({
|
|
29
|
+
link,
|
|
30
|
+
anchorName,
|
|
31
|
+
}) => {
|
|
32
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
33
|
+
|
|
34
|
+
const ref = React.useRef<HTMLDivElement>(null);
|
|
35
|
+
useOutsideClick(ref, () => setIsOpen(false));
|
|
36
|
+
|
|
37
|
+
if (!link) return null;
|
|
38
|
+
|
|
39
|
+
// Single button
|
|
40
|
+
if (isButton(link)) {
|
|
41
|
+
return (
|
|
42
|
+
<Button
|
|
43
|
+
key={`submenu-link-btn-${link.anchorId}`}
|
|
44
|
+
{...link}
|
|
45
|
+
linkClassName="body3 flex items-center text-text h-full"
|
|
46
|
+
linkVariant="unstyled"
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Group
|
|
52
|
+
const { anchorId, title, items } = link;
|
|
53
|
+
const subMenu = Array.isArray(items?.items) ? items!.items! : [];
|
|
54
|
+
const fullAnchorName = `--link-anchor-${anchorName}`;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div
|
|
58
|
+
className="relative h-full"
|
|
59
|
+
style={{ anchorName: fullAnchorName } as CSSProperties}
|
|
60
|
+
ref={ref}
|
|
61
|
+
>
|
|
62
|
+
<Button
|
|
63
|
+
onClick={() => setIsOpen(prev => !prev)}
|
|
64
|
+
aria-expanded={isOpen}
|
|
65
|
+
buttonClassName="group body3 flex h-full text-text items-center"
|
|
66
|
+
key={anchorId}
|
|
67
|
+
showButtonAs="unstyled"
|
|
68
|
+
>
|
|
69
|
+
<Text as="span" className="group-hover:underline">
|
|
70
|
+
{title ?? null}
|
|
71
|
+
</Text>
|
|
72
|
+
<MaterialIcon
|
|
73
|
+
weight="200"
|
|
74
|
+
size={24}
|
|
75
|
+
className="text-icon-secondary group-hover:opacity-50"
|
|
76
|
+
name={isOpen ? "keyboard_arrow_up" : "keyboard_arrow_down"}
|
|
77
|
+
/>
|
|
78
|
+
</Button>
|
|
79
|
+
|
|
80
|
+
<div
|
|
81
|
+
className={cx(
|
|
82
|
+
"shadow-navDrop fixed z-[1001] min-w-44 rounded-input-poppers border border-border bg-bg",
|
|
83
|
+
"transition-[opacity,transform] ease-out",
|
|
84
|
+
isOpen && subMenu.length > 0
|
|
85
|
+
? "pointer-events-auto translate-y-0 opacity-100 duration-75"
|
|
86
|
+
: "pointer-events-none -translate-y-2 opacity-0 duration-0"
|
|
87
|
+
)}
|
|
88
|
+
style={
|
|
89
|
+
{
|
|
90
|
+
positionAnchor: fullAnchorName,
|
|
91
|
+
top: "anchor(bottom)",
|
|
92
|
+
left: "calc((anchor(left) + anchor(right)) / 2)",
|
|
93
|
+
translate: "-50% 0",
|
|
94
|
+
} as CSSProperties
|
|
95
|
+
}
|
|
96
|
+
>
|
|
97
|
+
<ul className="flex flex-col gap-2 py-2">
|
|
98
|
+
{subMenu.map((site, index) => {
|
|
99
|
+
return (
|
|
100
|
+
<li key={`submenu-link-${index}`} className="submenu-link">
|
|
101
|
+
<Button
|
|
102
|
+
{...site}
|
|
103
|
+
linkVariant="unstyled"
|
|
104
|
+
linkClassName="body3 px-4 hover:bg-bg-surface-hover flex items-center w-full h-11 text-text-link"
|
|
105
|
+
/>
|
|
106
|
+
</li>
|
|
107
|
+
);
|
|
108
|
+
})}
|
|
109
|
+
</ul>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
};
|