@comet/site-nextjs 9.0.0-canary-20251013121422 → 9.0.0-canary-20251124092450
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/lib/blocks/DamVideoBlock.d.ts +5 -13
- package/lib/blocks/DamVideoBlock.d.ts.map +1 -1
- package/lib/blocks/DamVideoBlock.js +9 -80
- package/lib/blocks/PixelImageBlock.js +1 -9
- package/lib/blocks/VimeoVideoBlock.d.ts +5 -13
- package/lib/blocks/VimeoVideoBlock.d.ts.map +1 -1
- package/lib/blocks/VimeoVideoBlock.js +8 -91
- package/lib/blocks/YouTubeVideoBlock.d.ts +5 -13
- package/lib/blocks/YouTubeVideoBlock.d.ts.map +1 -1
- package/lib/blocks/YouTubeVideoBlock.js +9 -99
- package/lib/blocks/factories/SeoBlock.js +0 -9
- package/lib/blocks/helpers/VideoPreviewImage.d.ts +4 -13
- package/lib/blocks/helpers/VideoPreviewImage.d.ts.map +1 -1
- package/lib/blocks/helpers/VideoPreviewImage.js +5 -19
- package/lib/blocks.generated.d.ts +1 -1
- package/lib/blocks.generated.d.ts.map +1 -1
- package/lib/image/Image.js +0 -9
- package/lib/index.d.ts +2 -9
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +30 -24
- package/lib/{blocks → site-react/lib/blocks}/DamFileDownloadLinkBlock.js +1 -8
- package/lib/site-react/lib/blocks/DamVideoBlock.js +67 -0
- package/lib/{blocks → site-react/lib/blocks}/ExternalLinkBlock.js +1 -9
- package/lib/site-react/lib/blocks/VimeoVideoBlock.js +78 -0
- package/lib/site-react/lib/blocks/YouTubeVideoBlock.js +94 -0
- package/lib/site-react/lib/blocks/helpers/VideoPreviewImage.js +23 -0
- package/lib/site-react/lib/graphQLFetch/fetchInMemoryCache.js +2 -2
- package/lib/site-react/lib/iframebridge/IFrameBridge.js +1 -1
- package/lib/site-react/lib/iframebridge/withPreview.js +1 -1
- package/lib/site-react/lib/persistedQueries/createPersistedQueryGraphQLFetch.js +68 -0
- package/lib/site-react/lib/persistedQueries/persistedQueryRoute.js +100 -0
- package/lib/site-react/lib/persistedQueries/webpackPersistedQueriesLoader.js +51 -0
- package/lib/sitePreview/SitePreviewProvider.d.ts.map +1 -1
- package/lib/sitePreview/SitePreviewProvider.js +3 -10
- package/lib/style.css +1 -1
- package/package.json +15 -12
- package/lib/blocks/DamFileDownloadLinkBlock.d.ts +0 -12
- package/lib/blocks/DamFileDownloadLinkBlock.d.ts.map +0 -1
- package/lib/blocks/EmailLinkBlock.d.ts +0 -12
- package/lib/blocks/EmailLinkBlock.d.ts.map +0 -1
- package/lib/blocks/ExternalLinkBlock.d.ts +0 -12
- package/lib/blocks/ExternalLinkBlock.d.ts.map +0 -1
- package/lib/blocks/PhoneLinkBlock.d.ts +0 -12
- package/lib/blocks/PhoneLinkBlock.d.ts.map +0 -1
- package/lib/sitePreview/iframebridge/SitePreviewIFrameMessage.d.ts +0 -18
- package/lib/sitePreview/iframebridge/SitePreviewIFrameMessage.d.ts.map +0 -1
- package/lib/sitePreview/iframebridge/sendSitePreviewIFrameMessage.d.ts +0 -3
- package/lib/sitePreview/iframebridge/sendSitePreviewIFrameMessage.d.ts.map +0 -1
- /package/lib/{blocks → site-react/lib/blocks}/DamVideoBlock.module.scss.js +0 -0
- /package/lib/{blocks → site-react/lib/blocks}/EmailLinkBlock.js +0 -0
- /package/lib/{blocks → site-react/lib/blocks}/PhoneLinkBlock.js +0 -0
- /package/lib/{blocks → site-react/lib/blocks}/VimeoVideoBlock.module.scss.js +0 -0
- /package/lib/{blocks → site-react/lib/blocks}/YouTubeVideoBlock.module.scss.js +0 -0
- /package/lib/{blocks → site-react/lib/blocks}/helpers/VideoPreviewImage.module.scss.js +0 -0
- /package/lib/{sitePreview → site-react/lib/sitePreview}/iframebridge/SitePreviewIFrameMessage.js +0 -0
- /package/lib/{sitePreview → site-react/lib/sitePreview}/iframebridge/sendSitePreviewIFrameMessage.js +0 -0
package/lib/index.js
CHANGED
|
@@ -1,51 +1,53 @@
|
|
|
1
1
|
/* empty css */
|
|
2
|
-
import { DamFileDownloadLinkBlock } from "./blocks/DamFileDownloadLinkBlock.js";
|
|
3
2
|
import { DamVideoBlock } from "./blocks/DamVideoBlock.js";
|
|
4
|
-
import { EmailLinkBlock } from "./blocks/EmailLinkBlock.js";
|
|
5
|
-
import { ExternalLinkBlock } from "./blocks/ExternalLinkBlock.js";
|
|
6
3
|
import { SeoBlock } from "./blocks/factories/SeoBlock.js";
|
|
7
4
|
import { VideoPreviewImage } from "./blocks/helpers/VideoPreviewImage.js";
|
|
8
5
|
import { InternalLinkBlock } from "./blocks/InternalLinkBlock.js";
|
|
9
|
-
import { PhoneLinkBlock } from "./blocks/PhoneLinkBlock.js";
|
|
10
6
|
import { PixelImageBlock } from "./blocks/PixelImageBlock.js";
|
|
11
7
|
import { VimeoVideoBlock } from "./blocks/VimeoVideoBlock.js";
|
|
12
8
|
import { YouTubeVideoBlock } from "./blocks/YouTubeVideoBlock.js";
|
|
13
9
|
import { createFetchWithDefaultNextRevalidate, createFetchWithDefaults } from "./graphQLFetch/graphQLFetch.js";
|
|
14
10
|
import { Image } from "./image/Image.js";
|
|
15
11
|
import { sitePreviewRoute } from "./sitePreview/appRouter/sitePreviewRoute.js";
|
|
16
|
-
import { sendSitePreviewIFrameMessage } from "./sitePreview/iframebridge/sendSitePreviewIFrameMessage.js";
|
|
17
|
-
import { SitePreviewIFrameMessageType } from "./sitePreview/iframebridge/SitePreviewIFrameMessage.js";
|
|
18
12
|
import { legacyPagesRouterSitePreviewApiHandler } from "./sitePreview/pagesRouter/legacyPagesRouterSitePreviewApiHandler.js";
|
|
19
13
|
import { legacyPagesRouterPreviewParams, previewParams } from "./sitePreview/previewUtils.js";
|
|
20
14
|
import { SitePreviewProvider } from "./sitePreview/SitePreviewProvider.js";
|
|
21
|
-
import {
|
|
15
|
+
import { AdminMessageType, IFrameMessageType } from "./site-react/lib/iframebridge/IFrameMessage.js";
|
|
16
|
+
import { BlockPreviewProvider } from "./site-react/lib/preview/BlockPreviewProvider.js";
|
|
22
17
|
import { BlocksBlock } from "./site-react/lib/blocks/factories/BlocksBlock.js";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { OptionalBlock } from "./site-react/lib/blocks/factories/OptionalBlock.js";
|
|
26
|
-
import { hasRichTextBlockContent } from "./site-react/lib/blocks/helpers/RichTextBlockHelper.js";
|
|
27
|
-
import { useIsElementInViewport } from "./site-react/lib/blocks/helpers/useIsElementInViewport.js";
|
|
28
|
-
import { SvgImageBlock } from "./site-react/lib/blocks/SvgImageBlock.js";
|
|
18
|
+
import { calculateInheritAspectRatio, generateImageUrl, getMaxDimensionsFromArea, parseAspectRatio } from "./site-react/lib/image/image.utils.js";
|
|
19
|
+
import { convertPreviewDataToHeaders, createFetchWithPreviewHeaders, createGraphQLFetch, gql } from "./site-react/lib/graphQLFetch/graphQLFetch.js";
|
|
29
20
|
import { CookieApiProvider, useCookieApi } from "./site-react/lib/cookies/CookieApiContext.js";
|
|
30
21
|
import { CookieSafe } from "./site-react/lib/cookies/CookieSafe.js";
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
22
|
+
import { createFetchInMemoryCache } from "./site-react/lib/graphQLFetch/fetchInMemoryCache.js";
|
|
23
|
+
import { createPersistedQueryGraphQLFetch } from "./site-react/lib/persistedQueries/createPersistedQueryGraphQLFetch.js";
|
|
24
|
+
import { DamFileDownloadLinkBlock } from "./site-react/lib/blocks/DamFileDownloadLinkBlock.js";
|
|
25
|
+
import { EmailLinkBlock } from "./site-react/lib/blocks/EmailLinkBlock.js";
|
|
34
26
|
import { ErrorHandlerBoundary } from "./site-react/lib/errorHandler/ErrorHandlerBoundary.js";
|
|
35
27
|
import { ErrorHandlerProvider } from "./site-react/lib/errorHandler/ErrorHandlerProvider.js";
|
|
36
|
-
import {
|
|
28
|
+
import { ExternalLinkBlock } from "./site-react/lib/blocks/ExternalLinkBlock.js";
|
|
29
|
+
import { hasRichTextBlockContent } from "./site-react/lib/blocks/helpers/RichTextBlockHelper.js";
|
|
37
30
|
import { IFrameBridgeProvider } from "./site-react/lib/iframebridge/IFrameBridge.js";
|
|
38
|
-
import {
|
|
31
|
+
import { isWithPreviewPropsData, withPreview } from "./site-react/lib/iframebridge/withPreview.js";
|
|
32
|
+
import { ListBlock } from "./site-react/lib/blocks/factories/ListBlock.js";
|
|
33
|
+
import { OneOfBlock } from "./site-react/lib/blocks/factories/OneOfBlock.js";
|
|
34
|
+
import { OptionalBlock } from "./site-react/lib/blocks/factories/OptionalBlock.js";
|
|
35
|
+
import { persistedQueryRoute } from "./site-react/lib/persistedQueries/persistedQueryRoute.js";
|
|
36
|
+
import { PhoneLinkBlock } from "./site-react/lib/blocks/PhoneLinkBlock.js";
|
|
39
37
|
import { Preview } from "./site-react/lib/iframebridge/Preview.js";
|
|
38
|
+
import { PreviewSkeleton } from "./site-react/lib/previewskeleton/PreviewSkeleton.js";
|
|
39
|
+
import { recursivelyLoadBlockData } from "./site-react/lib/blockLoader/blockLoader.js";
|
|
40
|
+
import { sendSitePreviewIFrameMessage } from "./site-react/lib/sitePreview/iframebridge/sendSitePreviewIFrameMessage.js";
|
|
41
|
+
import { SitePreviewIFrameMessageType } from "./site-react/lib/sitePreview/iframebridge/SitePreviewIFrameMessage.js";
|
|
42
|
+
import { SvgImageBlock } from "./site-react/lib/blocks/SvgImageBlock.js";
|
|
40
43
|
import { useBlockPreviewFetch } from "./site-react/lib/iframebridge/useBlockPreviewFetch.js";
|
|
44
|
+
import { useCookieBotCookieApi } from "./site-react/lib/cookies/useCookieBotCookieApi.js";
|
|
41
45
|
import { useIFrameBridge } from "./site-react/lib/iframebridge/useIFrameBridge.js";
|
|
42
|
-
import {
|
|
43
|
-
import "react/
|
|
44
|
-
import {
|
|
45
|
-
import { BlockPreviewProvider } from "./site-react/lib/preview/BlockPreviewProvider.js";
|
|
46
|
-
import "./site-react/lib/preview/PreviewContext.js";
|
|
46
|
+
import { useIsElementInViewport } from "./site-react/lib/blocks/helpers/useIsElementInViewport.js";
|
|
47
|
+
import { useLocalStorageCookieApi } from "./site-react/lib/cookies/useLocalStorageCookieApi.js";
|
|
48
|
+
import { useOneTrustCookieApi } from "./site-react/lib/cookies/useOneTrustCookieApi.js";
|
|
47
49
|
import { usePreview } from "./site-react/lib/preview/usePreview.js";
|
|
48
|
-
import {
|
|
50
|
+
import { default as default2 } from "./site-react/lib/persistedQueries/webpackPersistedQueriesLoader.js";
|
|
49
51
|
export {
|
|
50
52
|
AdminMessageType,
|
|
51
53
|
BlockPreviewProvider,
|
|
@@ -78,10 +80,12 @@ export {
|
|
|
78
80
|
YouTubeVideoBlock,
|
|
79
81
|
calculateInheritAspectRatio,
|
|
80
82
|
convertPreviewDataToHeaders,
|
|
83
|
+
createFetchInMemoryCache,
|
|
81
84
|
createFetchWithDefaultNextRevalidate,
|
|
82
85
|
createFetchWithDefaults,
|
|
83
86
|
createFetchWithPreviewHeaders,
|
|
84
87
|
createGraphQLFetch,
|
|
88
|
+
createPersistedQueryGraphQLFetch,
|
|
85
89
|
generateImageUrl,
|
|
86
90
|
getMaxDimensionsFromArea,
|
|
87
91
|
gql,
|
|
@@ -90,6 +94,7 @@ export {
|
|
|
90
94
|
legacyPagesRouterPreviewParams,
|
|
91
95
|
legacyPagesRouterSitePreviewApiHandler,
|
|
92
96
|
parseAspectRatio,
|
|
97
|
+
persistedQueryRoute,
|
|
93
98
|
previewParams,
|
|
94
99
|
recursivelyLoadBlockData,
|
|
95
100
|
sendSitePreviewIFrameMessage,
|
|
@@ -102,5 +107,6 @@ export {
|
|
|
102
107
|
useLocalStorageCookieApi,
|
|
103
108
|
useOneTrustCookieApi,
|
|
104
109
|
usePreview,
|
|
110
|
+
default2 as webpackPersistedQueriesLoader,
|
|
105
111
|
withPreview
|
|
106
112
|
};
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { cloneElement } from "react";
|
|
4
|
-
import "../
|
|
5
|
-
import "../site-react/lib/iframebridge/IFrameBridge.js";
|
|
6
|
-
import "../site-react/lib/preview/PreviewContext.js";
|
|
7
|
-
import { withPreview } from "../site-react/lib/iframebridge/withPreview.js";
|
|
8
|
-
import "../site-react/lib/cookies/CookieApiContext.js";
|
|
9
|
-
import "usehooks-ts";
|
|
10
|
-
import "scroll-into-view-if-needed";
|
|
11
|
-
import "../site-react/lib/preview/BlockPreviewProvider.js";
|
|
4
|
+
import { withPreview } from "../iframebridge/withPreview.js";
|
|
12
5
|
const DamFileDownloadLinkBlock = withPreview(
|
|
13
6
|
({ data: { file, openFileType }, children, title, className, legacyBehavior }) => {
|
|
14
7
|
if (!file) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useState, useRef } from "react";
|
|
5
|
+
import { withPreview } from "../iframebridge/withPreview.js";
|
|
6
|
+
import { PreviewSkeleton } from "../previewskeleton/PreviewSkeleton.js";
|
|
7
|
+
import styles from "./DamVideoBlock.module.scss.js";
|
|
8
|
+
import { useIsElementInViewport } from "./helpers/useIsElementInViewport.js";
|
|
9
|
+
const DamVideoBlock = withPreview(
|
|
10
|
+
({
|
|
11
|
+
data: { damFile, autoplay, loop, showControls, previewImage },
|
|
12
|
+
aspectRatio = "16x9",
|
|
13
|
+
previewImageSizes,
|
|
14
|
+
renderPreviewImage,
|
|
15
|
+
fill,
|
|
16
|
+
previewImageIcon,
|
|
17
|
+
playButtonAriaLabel
|
|
18
|
+
}) => {
|
|
19
|
+
var _a;
|
|
20
|
+
if (damFile === void 0) {
|
|
21
|
+
return /* @__PURE__ */ jsx(PreviewSkeleton, { type: "media", hasContent: false, aspectRatio });
|
|
22
|
+
}
|
|
23
|
+
const [showPreviewImage, setShowPreviewImage] = useState(true);
|
|
24
|
+
const hasPreviewImage = Boolean(previewImage && previewImage.damFile);
|
|
25
|
+
const videoRef = useRef(null);
|
|
26
|
+
useIsElementInViewport(videoRef, (inView) => {
|
|
27
|
+
if (autoplay && videoRef.current) {
|
|
28
|
+
if (inView) {
|
|
29
|
+
videoRef.current.play();
|
|
30
|
+
} else {
|
|
31
|
+
videoRef.current.pause();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return /* @__PURE__ */ jsx(Fragment, { children: hasPreviewImage && showPreviewImage ? renderPreviewImage({
|
|
36
|
+
onPlay: () => setShowPreviewImage(false),
|
|
37
|
+
image: previewImage,
|
|
38
|
+
aspectRatio,
|
|
39
|
+
sizes: previewImageSizes,
|
|
40
|
+
fill,
|
|
41
|
+
icon: previewImageIcon,
|
|
42
|
+
playButtonAriaLabel
|
|
43
|
+
}) : /* @__PURE__ */ jsxs(
|
|
44
|
+
"video",
|
|
45
|
+
{
|
|
46
|
+
autoPlay: autoplay || hasPreviewImage && !showPreviewImage,
|
|
47
|
+
controls: showControls,
|
|
48
|
+
loop,
|
|
49
|
+
playsInline: true,
|
|
50
|
+
muted: autoplay,
|
|
51
|
+
ref: videoRef,
|
|
52
|
+
className: clsx(styles.video, fill && styles.fill),
|
|
53
|
+
style: !fill ? { "--aspect-ratio": aspectRatio.replace("x", " / ") } : void 0,
|
|
54
|
+
children: [
|
|
55
|
+
(_a = damFile.captions) == null ? void 0 : _a.map((caption) => {
|
|
56
|
+
return /* @__PURE__ */ jsx("track", { src: caption.fileUrl, kind: "captions", srcLang: caption.language }, caption.id);
|
|
57
|
+
}),
|
|
58
|
+
/* @__PURE__ */ jsx("source", { src: damFile.fileUrl, type: damFile.mimetype })
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
) });
|
|
62
|
+
},
|
|
63
|
+
{ label: "Video" }
|
|
64
|
+
);
|
|
65
|
+
export {
|
|
66
|
+
DamVideoBlock
|
|
67
|
+
};
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { cloneElement } from "react";
|
|
4
|
-
import "../
|
|
5
|
-
import { usePreview } from "../site-react/lib/preview/usePreview.js";
|
|
6
|
-
import "../site-react/lib/iframebridge/withPreview.js";
|
|
7
|
-
import "../site-react/lib/cookies/CookieApiContext.js";
|
|
8
|
-
import "usehooks-ts";
|
|
9
|
-
import "../site-react/lib/iframebridge/IFrameBridge.js";
|
|
10
|
-
import "scroll-into-view-if-needed";
|
|
11
|
-
import "../site-react/lib/preview/BlockPreviewProvider.js";
|
|
12
|
-
import "../site-react/lib/preview/PreviewContext.js";
|
|
4
|
+
import { usePreview } from "../preview/usePreview.js";
|
|
13
5
|
import { sendSitePreviewIFrameMessage } from "../sitePreview/iframebridge/sendSitePreviewIFrameMessage.js";
|
|
14
6
|
import { SitePreviewIFrameMessageType } from "../sitePreview/iframebridge/SitePreviewIFrameMessage.js";
|
|
15
7
|
function ExternalLinkBlock({ data: { targetUrl, openInNewWindow }, children, title, className, legacyBehavior }) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useState, useRef } from "react";
|
|
5
|
+
import { withPreview } from "../iframebridge/withPreview.js";
|
|
6
|
+
import { PreviewSkeleton } from "../previewskeleton/PreviewSkeleton.js";
|
|
7
|
+
import { useIsElementInViewport } from "./helpers/useIsElementInViewport.js";
|
|
8
|
+
import styles from "./VimeoVideoBlock.module.scss.js";
|
|
9
|
+
function parseVimeoIdentifier(vimeoIdentifier) {
|
|
10
|
+
const urlRegEx = /^(https?:\/\/)?((www\.|player\.)?vimeo\.com\/?(showcase\/)*([0-9a-z]*\/)*([0-9]{6,11})[?]?.*)$/;
|
|
11
|
+
const idRegEx = /^([0-9]{6,11})$/;
|
|
12
|
+
const urlRegExMatch = vimeoIdentifier.match(urlRegEx);
|
|
13
|
+
const idRegExMatch = vimeoIdentifier.match(idRegEx);
|
|
14
|
+
if (!urlRegExMatch && !idRegExMatch) return void 0;
|
|
15
|
+
if (urlRegExMatch) {
|
|
16
|
+
return urlRegExMatch[6];
|
|
17
|
+
} else if (idRegExMatch) {
|
|
18
|
+
return idRegExMatch[1];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const VimeoVideoBlock = withPreview(
|
|
22
|
+
({
|
|
23
|
+
data: { vimeoIdentifier, autoplay, loop, showControls, previewImage },
|
|
24
|
+
aspectRatio = "16x9",
|
|
25
|
+
previewImageSizes,
|
|
26
|
+
renderPreviewImage,
|
|
27
|
+
fill,
|
|
28
|
+
previewImageIcon,
|
|
29
|
+
playButtonAriaLabel
|
|
30
|
+
}) => {
|
|
31
|
+
const [showPreviewImage, setShowPreviewImage] = useState(true);
|
|
32
|
+
const hasPreviewImage = !!(previewImage && previewImage.damFile);
|
|
33
|
+
const inViewRef = useRef(null);
|
|
34
|
+
const iframeRef = useRef(null);
|
|
35
|
+
const handleVisibilityChange = (isVisible) => {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
(_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage(
|
|
38
|
+
JSON.stringify({ method: isVisible && autoplay ? "play" : "pause" }),
|
|
39
|
+
"https://player.vimeo.com"
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
useIsElementInViewport(inViewRef, handleVisibilityChange);
|
|
43
|
+
if (!vimeoIdentifier) {
|
|
44
|
+
return /* @__PURE__ */ jsx(PreviewSkeleton, { type: "media", hasContent: false, aspectRatio });
|
|
45
|
+
}
|
|
46
|
+
const identifier = parseVimeoIdentifier(vimeoIdentifier);
|
|
47
|
+
const searchParams = new URLSearchParams();
|
|
48
|
+
if (hasPreviewImage && !showPreviewImage) searchParams.append("autoplay", "1");
|
|
49
|
+
if (autoplay) searchParams.append("muted", "1");
|
|
50
|
+
if (loop !== void 0) searchParams.append("loop", Number(loop).toString());
|
|
51
|
+
if (showControls !== void 0) searchParams.append("controls", Number(showControls).toString());
|
|
52
|
+
searchParams.append("dnt", "1");
|
|
53
|
+
const vimeoBaseUrl = "https://player.vimeo.com/video/";
|
|
54
|
+
const vimeoUrl = new URL(`${vimeoBaseUrl}${identifier ?? ""}`);
|
|
55
|
+
vimeoUrl.search = searchParams.toString();
|
|
56
|
+
return /* @__PURE__ */ jsx(Fragment, { children: hasPreviewImage && showPreviewImage ? renderPreviewImage({
|
|
57
|
+
onPlay: () => setShowPreviewImage(false),
|
|
58
|
+
image: previewImage,
|
|
59
|
+
aspectRatio,
|
|
60
|
+
sizes: previewImageSizes,
|
|
61
|
+
fill,
|
|
62
|
+
icon: previewImageIcon,
|
|
63
|
+
playButtonAriaLabel
|
|
64
|
+
}) : /* @__PURE__ */ jsx(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
ref: inViewRef,
|
|
68
|
+
className: clsx(styles.videoContainer, fill && styles.fill),
|
|
69
|
+
style: !fill ? { "--aspect-ratio": aspectRatio.replace("x", "/") } : void 0,
|
|
70
|
+
children: /* @__PURE__ */ jsx("iframe", { ref: iframeRef, className: styles.vimeoContainer, src: vimeoUrl.toString(), allow: "autoplay", allowFullScreen: true })
|
|
71
|
+
}
|
|
72
|
+
) });
|
|
73
|
+
},
|
|
74
|
+
{ label: "Video" }
|
|
75
|
+
);
|
|
76
|
+
export {
|
|
77
|
+
VimeoVideoBlock
|
|
78
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useState, useRef } from "react";
|
|
5
|
+
import { withPreview } from "../iframebridge/withPreview.js";
|
|
6
|
+
import { PreviewSkeleton } from "../previewskeleton/PreviewSkeleton.js";
|
|
7
|
+
import { useIsElementInViewport } from "./helpers/useIsElementInViewport.js";
|
|
8
|
+
import styles from "./YouTubeVideoBlock.module.scss.js";
|
|
9
|
+
const EXPECTED_YT_ID_LENGTH = 11;
|
|
10
|
+
const parseYoutubeIdentifier = (value) => {
|
|
11
|
+
const regExp = /(https?:\/\/)?(((m|www)\.)?(youtube(-nocookie)?|youtube.googleapis)\.com.*(v\/|v=|vi=|vi\/|e\/|embed\/|user\/.*\/u\/\d+\/)|youtu\.be\/)([_0-9a-zA-Z-]+)/;
|
|
12
|
+
const match = value.match(regExp);
|
|
13
|
+
const youtubeId = value.length === EXPECTED_YT_ID_LENGTH ? value : match && match[8].length === EXPECTED_YT_ID_LENGTH ? match[8] : null;
|
|
14
|
+
return youtubeId ?? void 0;
|
|
15
|
+
};
|
|
16
|
+
const YouTubeVideoBlock = withPreview(
|
|
17
|
+
({
|
|
18
|
+
data: { youtubeIdentifier, autoplay, loop, showControls, previewImage },
|
|
19
|
+
aspectRatio = "16x9",
|
|
20
|
+
previewImageSizes,
|
|
21
|
+
renderPreviewImage,
|
|
22
|
+
fill,
|
|
23
|
+
previewImageIcon,
|
|
24
|
+
playButtonAriaLabel
|
|
25
|
+
}) => {
|
|
26
|
+
const [showPreviewImage, setShowPreviewImage] = useState(true);
|
|
27
|
+
const hasPreviewImage = !!(previewImage && previewImage.damFile);
|
|
28
|
+
const iframeRef = useRef(null);
|
|
29
|
+
const inViewRef = useRef(null);
|
|
30
|
+
const pauseYouTubeVideo = () => {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
(_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage(`{"event":"command","func":"pauseVideo","args":""}`, "https://www.youtube-nocookie.com");
|
|
33
|
+
};
|
|
34
|
+
const playYouTubeVideo = () => {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
(_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage(`{"event":"command","func":"playVideo","args":""}`, "https://www.youtube-nocookie.com");
|
|
37
|
+
};
|
|
38
|
+
useIsElementInViewport(inViewRef, (inView) => {
|
|
39
|
+
if (autoplay) {
|
|
40
|
+
if (inView) {
|
|
41
|
+
playYouTubeVideo();
|
|
42
|
+
} else {
|
|
43
|
+
pauseYouTubeVideo();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
if (!youtubeIdentifier) {
|
|
48
|
+
return /* @__PURE__ */ jsx(PreviewSkeleton, { type: "media", hasContent: false, aspectRatio });
|
|
49
|
+
}
|
|
50
|
+
const identifier = parseYoutubeIdentifier(youtubeIdentifier);
|
|
51
|
+
const searchParams = new URLSearchParams();
|
|
52
|
+
searchParams.append("modestbranding", "1");
|
|
53
|
+
searchParams.append("rel", "0");
|
|
54
|
+
searchParams.append("enablejsapi", "1");
|
|
55
|
+
if (hasPreviewImage && !showPreviewImage) searchParams.append("autoplay", "1");
|
|
56
|
+
if (autoplay) searchParams.append("mute", "1");
|
|
57
|
+
if (showControls !== void 0) searchParams.append("controls", Number(showControls).toString());
|
|
58
|
+
if (loop !== void 0) searchParams.append("loop", Number(loop).toString());
|
|
59
|
+
if (loop && identifier) searchParams.append("playlist", identifier);
|
|
60
|
+
const youtubeBaseUrl = "https://www.youtube-nocookie.com/embed/";
|
|
61
|
+
const youtubeUrl = new URL(`${youtubeBaseUrl}${identifier ?? ""}`);
|
|
62
|
+
youtubeUrl.search = searchParams.toString();
|
|
63
|
+
return /* @__PURE__ */ jsx(Fragment, { children: hasPreviewImage && showPreviewImage ? renderPreviewImage({
|
|
64
|
+
onPlay: () => setShowPreviewImage(false),
|
|
65
|
+
image: previewImage,
|
|
66
|
+
aspectRatio,
|
|
67
|
+
sizes: previewImageSizes,
|
|
68
|
+
fill,
|
|
69
|
+
icon: previewImageIcon,
|
|
70
|
+
playButtonAriaLabel
|
|
71
|
+
}) : /* @__PURE__ */ jsx(
|
|
72
|
+
"div",
|
|
73
|
+
{
|
|
74
|
+
ref: inViewRef,
|
|
75
|
+
className: clsx(styles.videoContainer, fill && styles.fill),
|
|
76
|
+
style: !fill ? { "--aspect-ratio": aspectRatio.replace("x", "/") } : void 0,
|
|
77
|
+
children: /* @__PURE__ */ jsx(
|
|
78
|
+
"iframe",
|
|
79
|
+
{
|
|
80
|
+
ref: iframeRef,
|
|
81
|
+
className: styles.youtubeContainer,
|
|
82
|
+
allow: "autoplay",
|
|
83
|
+
referrerPolicy: "strict-origin-when-cross-origin",
|
|
84
|
+
src: youtubeUrl.toString()
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
) });
|
|
89
|
+
},
|
|
90
|
+
{ label: "Video" }
|
|
91
|
+
);
|
|
92
|
+
export {
|
|
93
|
+
YouTubeVideoBlock
|
|
94
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import styles from "./VideoPreviewImage.module.scss.js";
|
|
4
|
+
const VideoPreviewImage = ({
|
|
5
|
+
onPlay,
|
|
6
|
+
image,
|
|
7
|
+
aspectRatio,
|
|
8
|
+
sizes = "100vw",
|
|
9
|
+
fill,
|
|
10
|
+
playButtonAriaLabel = "Play video",
|
|
11
|
+
icon = /* @__PURE__ */ jsx(PlayIcon, { playButtonAriaLabel }),
|
|
12
|
+
className,
|
|
13
|
+
renderImage
|
|
14
|
+
}) => {
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { className: clsx(styles.root, fill && styles.fill, className), children: [
|
|
16
|
+
renderImage({ data: image, aspectRatio, sizes, fill }),
|
|
17
|
+
/* @__PURE__ */ jsx("button", { className: styles.iconWrapper, onClick: onPlay, children: icon })
|
|
18
|
+
] });
|
|
19
|
+
};
|
|
20
|
+
const PlayIcon = ({ playButtonAriaLabel }) => /* @__PURE__ */ jsx("span", { className: styles.playIcon, "aria-label": playButtonAriaLabel });
|
|
21
|
+
export {
|
|
22
|
+
VideoPreviewImage
|
|
23
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const cache = {};
|
|
2
2
|
function createFetchInMemoryCache(fetch) {
|
|
3
3
|
return async function(input, init) {
|
|
4
|
-
var _a;
|
|
4
|
+
var _a, _b;
|
|
5
5
|
let cacheKey;
|
|
6
6
|
if ((init == null ? void 0 : init.cache) === "no-store") ;
|
|
7
7
|
else if (((_a = init == null ? void 0 : init.method) == null ? void 0 : _a.toUpperCase()) === "GET") {
|
|
@@ -11,7 +11,7 @@ function createFetchInMemoryCache(fetch) {
|
|
|
11
11
|
if (bodyString.startsWith("{")) {
|
|
12
12
|
try {
|
|
13
13
|
const body = JSON.parse(init.body.toString());
|
|
14
|
-
if (body.query && body.variables) {
|
|
14
|
+
if ((body.query || ((_b = body.extensions) == null ? void 0 : _b.persistedQuery)) && body.variables) {
|
|
15
15
|
cacheKey = `${input.toString()}#${init.body.toString()}`;
|
|
16
16
|
}
|
|
17
17
|
} catch {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { decodeJwt } from "jose";
|
|
4
4
|
import isEqual from "lodash.isequal";
|
|
5
|
-
import {
|
|
5
|
+
import { useState, useRef, useCallback, useEffect, useMemo, createContext } from "react";
|
|
6
6
|
import { useDebounceCallback } from "usehooks-ts";
|
|
7
7
|
import styles from "./IFrameBridge.module.scss.js";
|
|
8
8
|
import { AdminMessageType, IFrameMessageType } from "./IFrameMessage.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useContext, createContext } from "react";
|
|
4
4
|
import { Preview } from "./Preview.js";
|
|
5
5
|
function isWithPreviewPropsData(block) {
|
|
6
6
|
return block.adminMeta !== void 0;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function createPersistedQueryGraphQLFetch(fetch, url) {
|
|
2
|
+
return async function(query, variables, init) {
|
|
3
|
+
if (typeof query === "string") throw new Error("at runtime only hashed queries are supported");
|
|
4
|
+
const hash = query.hash;
|
|
5
|
+
let response;
|
|
6
|
+
if ((init == null ? void 0 : init.method) === "GET") {
|
|
7
|
+
const fetchUrl = new URL(url, window.location.origin);
|
|
8
|
+
fetchUrl.searchParams.append("extensions.persistedQuery.sha256Hash", hash);
|
|
9
|
+
fetchUrl.searchParams.append("variables", JSON.stringify(variables));
|
|
10
|
+
response = await fetch(fetchUrl, {
|
|
11
|
+
...init,
|
|
12
|
+
headers: {
|
|
13
|
+
/**
|
|
14
|
+
* It's recommended to add the `Apollo-Require-Preflight` header to GET requests, running on an Apollo Server 4.
|
|
15
|
+
*
|
|
16
|
+
* If this header is missing, Apollo Server 4 will return: This operation has been blocked as a potential Cross-Site Request Forgery (CSRF).
|
|
17
|
+
*
|
|
18
|
+
* see: https://www.apollographql.com/docs/graphos/routing/security/csrf#enable-csrf-prevention
|
|
19
|
+
*/
|
|
20
|
+
"Apollo-Require-Preflight": "true",
|
|
21
|
+
...init.headers
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
response = await fetch(url, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
...init,
|
|
28
|
+
headers: { "Content-Type": "application/json", ...init == null ? void 0 : init.headers },
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
extensions: {
|
|
31
|
+
persistedQuery: {
|
|
32
|
+
version: 1,
|
|
33
|
+
sha256Hash: hash
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
variables
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
let errorMessage = `Network response was not ok. Status: ${response.status}`;
|
|
42
|
+
const body = await response.text();
|
|
43
|
+
try {
|
|
44
|
+
const json = JSON.parse(body);
|
|
45
|
+
const { errors: errors2 } = json;
|
|
46
|
+
if (errors2) {
|
|
47
|
+
errorMessage += `
|
|
48
|
+
|
|
49
|
+
GraphQL error(s):
|
|
50
|
+
- ${errors2.map((error) => error.message).join("\n- ")}`;
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
errorMessage += `
|
|
54
|
+
${body}`;
|
|
55
|
+
}
|
|
56
|
+
throw new Error(errorMessage);
|
|
57
|
+
}
|
|
58
|
+
const { data, errors } = await response.json();
|
|
59
|
+
if (errors) {
|
|
60
|
+
throw new Error(`GraphQL error(s):
|
|
61
|
+
- ${errors.map((error) => error.message).join("\n- ")}`);
|
|
62
|
+
}
|
|
63
|
+
return data;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
createPersistedQueryGraphQLFetch
|
|
68
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
let queryMap;
|
|
3
|
+
let fragmentsMap;
|
|
4
|
+
async function loadPersistedQueries(path) {
|
|
5
|
+
const file = await readFile(path, { encoding: "utf-8" });
|
|
6
|
+
queryMap = JSON.parse(file.toString());
|
|
7
|
+
fragmentsMap = {};
|
|
8
|
+
for (const [, query] of Object.entries(queryMap)) {
|
|
9
|
+
const match = query.match(/^\s*fragment\s+(\w+)\s+on\s+\w+/m);
|
|
10
|
+
if (match) {
|
|
11
|
+
const fragmentName = match[1];
|
|
12
|
+
fragmentsMap[fragmentName] = query.replace(/\${.*?}/g, "");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function injectFragments(query) {
|
|
17
|
+
query = query.replace(/\${.*?}/g, "");
|
|
18
|
+
const injected = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const m of query.matchAll(/^\s*fragment\s+(\w+)\s+on\s+\w+/gm)) {
|
|
20
|
+
injected.add(m[1]);
|
|
21
|
+
}
|
|
22
|
+
function inject(q) {
|
|
23
|
+
const spreads = Array.from(q.matchAll(/\.\.\.(\w+)/g)).map((m) => m[1]);
|
|
24
|
+
let result = q;
|
|
25
|
+
for (const fragmentName of spreads) {
|
|
26
|
+
if (!injected.has(fragmentName) && fragmentsMap[fragmentName]) {
|
|
27
|
+
injected.add(fragmentName);
|
|
28
|
+
result += `
|
|
29
|
+
${inject(fragmentsMap[fragmentName])}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
query = inject(query);
|
|
35
|
+
return query;
|
|
36
|
+
}
|
|
37
|
+
async function persistedQueryRoute(req, {
|
|
38
|
+
graphqlTarget,
|
|
39
|
+
headers: headersInit,
|
|
40
|
+
persistedQueriesPath = ".persisted-queries.json",
|
|
41
|
+
cacheMaxAge
|
|
42
|
+
}) {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
if (!queryMap) {
|
|
45
|
+
await loadPersistedQueries(persistedQueriesPath);
|
|
46
|
+
}
|
|
47
|
+
let hash;
|
|
48
|
+
let variables;
|
|
49
|
+
if (req.method === "POST") {
|
|
50
|
+
const body = await req.json();
|
|
51
|
+
hash = (_b = (_a = body.extensions) == null ? void 0 : _a.persistedQuery) == null ? void 0 : _b.sha256Hash;
|
|
52
|
+
variables = body.variables;
|
|
53
|
+
} else if (req.method === "GET") {
|
|
54
|
+
const url = new URL(req.url);
|
|
55
|
+
hash = url.searchParams.get("extensions.persistedQuery.sha256Hash");
|
|
56
|
+
const variablesParam = url.searchParams.get("variables");
|
|
57
|
+
variables = variablesParam ? JSON.parse(variablesParam) : void 0;
|
|
58
|
+
} else {
|
|
59
|
+
return Response.json({ error: "MethodNotAllowed" }, { status: 405 });
|
|
60
|
+
}
|
|
61
|
+
if (!hash) {
|
|
62
|
+
return Response.json({ error: "OnlyPersistedQueriesAllowed" }, { status: 400 });
|
|
63
|
+
}
|
|
64
|
+
let query = queryMap[hash];
|
|
65
|
+
if (!query) {
|
|
66
|
+
return Response.json({ error: "PersistedQueryNotFound", hash }, { status: 400 });
|
|
67
|
+
}
|
|
68
|
+
query = injectFragments(query);
|
|
69
|
+
if (req.method === "GET") {
|
|
70
|
+
const apolloPreflight = req.headers.get("Apollo-Require-Preflight");
|
|
71
|
+
if (apolloPreflight !== "true") {
|
|
72
|
+
return Response.json({ error: "CSRFProtection", message: "Missing Apollo-Require-Preflight header" }, { status: 403 });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const headers = new Headers(headersInit);
|
|
76
|
+
headers.set("Content-Type", "application/json");
|
|
77
|
+
for (const header of ["x-include-invisible-content", "x-preview-dam-urls"]) {
|
|
78
|
+
const value = req.headers.get(header);
|
|
79
|
+
if (value !== null) {
|
|
80
|
+
headers.set(header, value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const upstreamRes = await fetch(graphqlTarget, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers,
|
|
86
|
+
body: JSON.stringify({ query, variables })
|
|
87
|
+
});
|
|
88
|
+
const responseHeaders = {
|
|
89
|
+
"Content-Type": "application/json"
|
|
90
|
+
};
|
|
91
|
+
if (req.method === "GET" && upstreamRes.ok && cacheMaxAge !== void 0) {
|
|
92
|
+
responseHeaders["Cache-Control"] = `public, max-age=${cacheMaxAge}`;
|
|
93
|
+
}
|
|
94
|
+
return new Response(upstreamRes.body, {
|
|
95
|
+
headers: responseHeaders
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
persistedQueryRoute
|
|
100
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
function loadHashMap(path) {
|
|
4
|
+
if (fs.existsSync(path)) {
|
|
5
|
+
return JSON.parse(fs.readFileSync(path, "utf-8"));
|
|
6
|
+
}
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
function saveHashMap(path, hashMap) {
|
|
10
|
+
fs.writeFileSync(path, JSON.stringify(hashMap, null, 2));
|
|
11
|
+
}
|
|
12
|
+
function hashQuery(query) {
|
|
13
|
+
return createHash("sha256").update(query).digest("hex");
|
|
14
|
+
}
|
|
15
|
+
const gqlTagRegex = /gql`([\s\S]*?)`/gm;
|
|
16
|
+
const webpackPersistedQueriesLoader = function(source) {
|
|
17
|
+
const options = this.getOptions() || {};
|
|
18
|
+
const persistedQueriesPath = options.persistedQueriesPath || ".persisted-queries.json";
|
|
19
|
+
const hashMap = loadHashMap(persistedQueriesPath);
|
|
20
|
+
const replacements = [];
|
|
21
|
+
let match;
|
|
22
|
+
while ((match = gqlTagRegex.exec(source)) !== null) {
|
|
23
|
+
const query = match[1];
|
|
24
|
+
const hash = hashQuery(query);
|
|
25
|
+
hashMap[hash] = query;
|
|
26
|
+
const fragmentVariables = Array.from(query.matchAll(/\${.*?}/g) ?? []).map((m) => m[0]).join(" ");
|
|
27
|
+
if (query.match(/^\s*fragment\s+(\w+)\s+on\s+\w+/)) {
|
|
28
|
+
replacements.push({
|
|
29
|
+
start: match.index,
|
|
30
|
+
end: match.index + match[0].length,
|
|
31
|
+
replacement: `{ fragment: true, fragmentVariables: \`${fragmentVariables}\` }`
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
replacements.push({
|
|
35
|
+
start: match.index,
|
|
36
|
+
end: match.index + match[0].length,
|
|
37
|
+
replacement: `{ hash: "${hash}", fragmentVariables: \`${fragmentVariables}\` }`
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
let modifiedSource = source;
|
|
42
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
43
|
+
const { start, end, replacement } = replacements[i];
|
|
44
|
+
modifiedSource = modifiedSource.slice(0, start) + replacement + modifiedSource.slice(end);
|
|
45
|
+
}
|
|
46
|
+
saveHashMap(persistedQueriesPath, hashMap);
|
|
47
|
+
return modifiedSource;
|
|
48
|
+
};
|
|
49
|
+
export {
|
|
50
|
+
webpackPersistedQueriesLoader as default
|
|
51
|
+
};
|