@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.
Files changed (56) hide show
  1. package/lib/blocks/DamVideoBlock.d.ts +5 -13
  2. package/lib/blocks/DamVideoBlock.d.ts.map +1 -1
  3. package/lib/blocks/DamVideoBlock.js +9 -80
  4. package/lib/blocks/PixelImageBlock.js +1 -9
  5. package/lib/blocks/VimeoVideoBlock.d.ts +5 -13
  6. package/lib/blocks/VimeoVideoBlock.d.ts.map +1 -1
  7. package/lib/blocks/VimeoVideoBlock.js +8 -91
  8. package/lib/blocks/YouTubeVideoBlock.d.ts +5 -13
  9. package/lib/blocks/YouTubeVideoBlock.d.ts.map +1 -1
  10. package/lib/blocks/YouTubeVideoBlock.js +9 -99
  11. package/lib/blocks/factories/SeoBlock.js +0 -9
  12. package/lib/blocks/helpers/VideoPreviewImage.d.ts +4 -13
  13. package/lib/blocks/helpers/VideoPreviewImage.d.ts.map +1 -1
  14. package/lib/blocks/helpers/VideoPreviewImage.js +5 -19
  15. package/lib/blocks.generated.d.ts +1 -1
  16. package/lib/blocks.generated.d.ts.map +1 -1
  17. package/lib/image/Image.js +0 -9
  18. package/lib/index.d.ts +2 -9
  19. package/lib/index.d.ts.map +1 -1
  20. package/lib/index.js +30 -24
  21. package/lib/{blocks → site-react/lib/blocks}/DamFileDownloadLinkBlock.js +1 -8
  22. package/lib/site-react/lib/blocks/DamVideoBlock.js +67 -0
  23. package/lib/{blocks → site-react/lib/blocks}/ExternalLinkBlock.js +1 -9
  24. package/lib/site-react/lib/blocks/VimeoVideoBlock.js +78 -0
  25. package/lib/site-react/lib/blocks/YouTubeVideoBlock.js +94 -0
  26. package/lib/site-react/lib/blocks/helpers/VideoPreviewImage.js +23 -0
  27. package/lib/site-react/lib/graphQLFetch/fetchInMemoryCache.js +2 -2
  28. package/lib/site-react/lib/iframebridge/IFrameBridge.js +1 -1
  29. package/lib/site-react/lib/iframebridge/withPreview.js +1 -1
  30. package/lib/site-react/lib/persistedQueries/createPersistedQueryGraphQLFetch.js +68 -0
  31. package/lib/site-react/lib/persistedQueries/persistedQueryRoute.js +100 -0
  32. package/lib/site-react/lib/persistedQueries/webpackPersistedQueriesLoader.js +51 -0
  33. package/lib/sitePreview/SitePreviewProvider.d.ts.map +1 -1
  34. package/lib/sitePreview/SitePreviewProvider.js +3 -10
  35. package/lib/style.css +1 -1
  36. package/package.json +15 -12
  37. package/lib/blocks/DamFileDownloadLinkBlock.d.ts +0 -12
  38. package/lib/blocks/DamFileDownloadLinkBlock.d.ts.map +0 -1
  39. package/lib/blocks/EmailLinkBlock.d.ts +0 -12
  40. package/lib/blocks/EmailLinkBlock.d.ts.map +0 -1
  41. package/lib/blocks/ExternalLinkBlock.d.ts +0 -12
  42. package/lib/blocks/ExternalLinkBlock.d.ts.map +0 -1
  43. package/lib/blocks/PhoneLinkBlock.d.ts +0 -12
  44. package/lib/blocks/PhoneLinkBlock.d.ts.map +0 -1
  45. package/lib/sitePreview/iframebridge/SitePreviewIFrameMessage.d.ts +0 -18
  46. package/lib/sitePreview/iframebridge/SitePreviewIFrameMessage.d.ts.map +0 -1
  47. package/lib/sitePreview/iframebridge/sendSitePreviewIFrameMessage.d.ts +0 -3
  48. package/lib/sitePreview/iframebridge/sendSitePreviewIFrameMessage.d.ts.map +0 -1
  49. /package/lib/{blocks → site-react/lib/blocks}/DamVideoBlock.module.scss.js +0 -0
  50. /package/lib/{blocks → site-react/lib/blocks}/EmailLinkBlock.js +0 -0
  51. /package/lib/{blocks → site-react/lib/blocks}/PhoneLinkBlock.js +0 -0
  52. /package/lib/{blocks → site-react/lib/blocks}/VimeoVideoBlock.module.scss.js +0 -0
  53. /package/lib/{blocks → site-react/lib/blocks}/YouTubeVideoBlock.module.scss.js +0 -0
  54. /package/lib/{blocks → site-react/lib/blocks}/helpers/VideoPreviewImage.module.scss.js +0 -0
  55. /package/lib/{sitePreview → site-react/lib/sitePreview}/iframebridge/SitePreviewIFrameMessage.js +0 -0
  56. /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 { recursivelyLoadBlockData } from "./site-react/lib/blockLoader/blockLoader.js";
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 { ListBlock } from "./site-react/lib/blocks/factories/ListBlock.js";
24
- import { OneOfBlock } from "./site-react/lib/blocks/factories/OneOfBlock.js";
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 { useCookieBotCookieApi } from "./site-react/lib/cookies/useCookieBotCookieApi.js";
32
- import { useLocalStorageCookieApi } from "./site-react/lib/cookies/useLocalStorageCookieApi.js";
33
- import { useOneTrustCookieApi } from "./site-react/lib/cookies/useOneTrustCookieApi.js";
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 { convertPreviewDataToHeaders, createFetchWithPreviewHeaders, createGraphQLFetch, gql } from "./site-react/lib/graphQLFetch/graphQLFetch.js";
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 { AdminMessageType, IFrameMessageType } from "./site-react/lib/iframebridge/IFrameMessage.js";
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 { isWithPreviewPropsData, withPreview } from "./site-react/lib/iframebridge/withPreview.js";
43
- import "react/jsx-runtime";
44
- import { calculateInheritAspectRatio, generateImageUrl, getMaxDimensionsFromArea, parseAspectRatio } from "./site-react/lib/image/image.utils.js";
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 { PreviewSkeleton } from "./site-react/lib/previewskeleton/PreviewSkeleton.js";
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 "../site-react/lib/errorHandler/ErrorHandlerProvider.js";
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 "../site-react/lib/errorHandler/ErrorHandlerProvider.js";
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 { createContext, useState, useRef, useCallback, useEffect, useMemo } from "react";
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 { createContext, useContext } from "react";
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
+ };