@contentful/experiences-sdk-react 1.15.2-dev-20240912T1641-eb25944.0 → 1.16.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,17 +3,21 @@ import { jsx } from 'react/jsx-runtime';
3
3
  import { createExperience, validateExperienceBuilderConfig, VisualEditorMode } from '@contentful/experiences-core';
4
4
  import { PreviewDeliveryRoot } from './blocks/preview/PreviewDeliveryRoot.js';
5
5
  import { VisualEditorRoot } from './blocks/editor/VisualEditorRoot.js';
6
- import { useDetectEditorMode } from './hooks/useDetectEditorMode.js';
6
+ import { useDetectCanvasMode } from './hooks/useDetectCanvasMode.js';
7
+ import { StudioCanvasMode } from '@contentful/experiences-core/constants';
7
8
 
8
9
  const ExperienceRoot = ({ locale, experience, visualEditorMode = VisualEditorMode.LazyLoad, }) => {
9
- const isEditorMode = useDetectEditorMode();
10
+ const mode = useDetectCanvasMode();
10
11
  //If experience is passed in as a JSON string, recreate it to an experience object
11
12
  const experienceObject = typeof experience === 'string' ? createExperience(experience) : experience;
12
13
  validateExperienceBuilderConfig({
13
14
  locale,
14
- isEditorMode,
15
+ mode,
15
16
  });
16
- if (isEditorMode) {
17
+ if (mode === StudioCanvasMode.EDITOR) {
18
+ return (jsx(VisualEditorRoot, { experience: experienceObject, visualEditorMode: visualEditorMode, initialLocale: locale }));
19
+ }
20
+ if (mode === StudioCanvasMode.READ_ONLY) {
17
21
  return (jsx(VisualEditorRoot, { experience: experienceObject, visualEditorMode: visualEditorMode, initialLocale: locale }));
18
22
  }
19
23
  if (!experienceObject)
@@ -1 +1 @@
1
- {"version":3,"file":"ExperienceRoot.js","sources":["../../src/ExperienceRoot.tsx"],"sourcesContent":["'use client';\nimport React from 'react';\nimport {\n VisualEditorMode,\n createExperience,\n validateExperienceBuilderConfig,\n} from '@contentful/experiences-core';\nimport { EntityStore } from '@contentful/experiences-core';\nimport type { Experience } from '@contentful/experiences-core/types';\nimport { PreviewDeliveryRoot } from './blocks/preview/PreviewDeliveryRoot';\nimport VisualEditorRoot from './blocks/editor/VisualEditorRoot';\nimport { useDetectEditorMode } from './hooks/useDetectEditorMode';\n\ntype ExperienceRootProps = {\n experience?: Experience<EntityStore> | string | null;\n locale: string;\n visualEditorMode?: VisualEditorMode;\n};\n\nexport const ExperienceRoot = ({\n locale,\n experience,\n visualEditorMode = VisualEditorMode.LazyLoad,\n}: ExperienceRootProps) => {\n const isEditorMode = useDetectEditorMode();\n //If experience is passed in as a JSON string, recreate it to an experience object\n const experienceObject =\n typeof experience === 'string' ? createExperience(experience) : experience;\n\n validateExperienceBuilderConfig({\n locale,\n isEditorMode,\n });\n\n if (isEditorMode) {\n return (\n <VisualEditorRoot\n experience={experienceObject as Experience<EntityStore> | undefined}\n visualEditorMode={visualEditorMode}\n initialLocale={locale}\n />\n );\n }\n\n if (!experienceObject) return null;\n\n return <PreviewDeliveryRoot locale={locale} experience={experienceObject} />;\n};\n"],"names":[],"mappings":";;;;;;;AAmBa;AAKX;;AAEA;AAGA;;;AAGC;;AAGC;;AASF;AAAuB;;AAGzB;;"}
1
+ {"version":3,"file":"ExperienceRoot.js","sources":["../../src/ExperienceRoot.tsx"],"sourcesContent":["'use client';\nimport React from 'react';\nimport {\n VisualEditorMode,\n createExperience,\n validateExperienceBuilderConfig,\n} from '@contentful/experiences-core';\nimport { EntityStore } from '@contentful/experiences-core';\nimport type { Experience } from '@contentful/experiences-core/types';\nimport { PreviewDeliveryRoot } from './blocks/preview/PreviewDeliveryRoot';\nimport VisualEditorRoot from './blocks/editor/VisualEditorRoot';\nimport { useDetectCanvasMode } from './hooks/useDetectCanvasMode';\nimport { StudioCanvasMode } from '@contentful/experiences-core/constants';\n\ntype ExperienceRootProps = {\n experience?: Experience<EntityStore> | string | null;\n locale: string;\n visualEditorMode?: VisualEditorMode;\n};\n\nexport const ExperienceRoot = ({\n locale,\n experience,\n visualEditorMode = VisualEditorMode.LazyLoad,\n}: ExperienceRootProps) => {\n const mode = useDetectCanvasMode();\n\n //If experience is passed in as a JSON string, recreate it to an experience object\n const experienceObject =\n typeof experience === 'string' ? createExperience(experience) : experience;\n\n validateExperienceBuilderConfig({\n locale,\n mode,\n });\n\n if (mode === StudioCanvasMode.EDITOR) {\n return (\n <VisualEditorRoot\n experience={experienceObject as Experience<EntityStore> | undefined}\n visualEditorMode={visualEditorMode}\n initialLocale={locale}\n />\n );\n }\n\n if (mode === StudioCanvasMode.READ_ONLY) {\n return (\n <VisualEditorRoot\n experience={experienceObject as Experience<EntityStore> | undefined}\n visualEditorMode={visualEditorMode}\n initialLocale={locale}\n />\n );\n }\n\n if (!experienceObject) return null;\n\n return <PreviewDeliveryRoot locale={locale} experience={experienceObject} />;\n};\n"],"names":[],"mappings":";;;;;;;;AAoBa;AAKX;;AAGA;AAGA;;;AAGC;AAED;AACE;;AASF;AACE;;AASF;AAAuB;;AAGzB;;"}
@@ -3,8 +3,8 @@ import { CompositionBlock } from './CompositionBlock.js';
3
3
  import { compatibleVersions } from '../../constants.js';
4
4
  import { useBreakpoints } from '../../hooks/useBreakpoints.js';
5
5
  import 'react';
6
- import '@contentful/experiences-core';
7
6
  import '@contentful/experiences-core/constants';
7
+ import '@contentful/experiences-core';
8
8
 
9
9
  const PreviewDeliveryRoot = ({ locale, experience }) => {
10
10
  const { entityStore } = experience;
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { useState, useRef, useCallback, useEffect } from 'react';
3
+ import { doesMismatchMessageSchema, tryParseMessage, sendMessage } from '@contentful/experiences-core';
4
+ import { StudioCanvasMode, INCOMING_EVENTS, OUTGOING_EVENTS } from '@contentful/experiences-core/constants';
5
+ import { sdkFeatures } from '../core/sdkFeatures.js';
6
+
7
+ const useDetectCanvasMode = ({ isClientSide = false } = {}) => {
8
+ const [mounted, setMounted] = useState(false);
9
+ const recievedModeMessage = useRef(false);
10
+ const [mode, setMode] = useState(() => {
11
+ // if we are client side and running in an iframe, then initialize to read only,
12
+ // Editor mode can be requested later.
13
+ if (isClientSide && inIframe()) {
14
+ return StudioCanvasMode.READ_ONLY;
15
+ }
16
+ else {
17
+ return StudioCanvasMode.NONE;
18
+ }
19
+ });
20
+ const onMessage = useCallback((event) => {
21
+ if (doesMismatchMessageSchema(event)) {
22
+ return;
23
+ }
24
+ const eventData = tryParseMessage(event);
25
+ const isRequestingCanvasMode = eventData.eventType === INCOMING_EVENTS.RequestEditorMode ||
26
+ eventData.eventType === INCOMING_EVENTS.RequestReadOnlyMode;
27
+ if (!isRequestingCanvasMode) {
28
+ return;
29
+ }
30
+ const isEditorMode = eventData.eventType === INCOMING_EVENTS.RequestEditorMode;
31
+ const mode = isEditorMode ? StudioCanvasMode.EDITOR : StudioCanvasMode.READ_ONLY;
32
+ recievedModeMessage.current = true;
33
+ setMode(mode);
34
+ if (typeof window !== 'undefined') {
35
+ // Once we definitely know that we are in editor mode, we set this flag so future postMessage connect calls are not made
36
+ if (!window.__EB__) {
37
+ window.__EB__ = {};
38
+ }
39
+ window.__EB__.isReadOnlyMode = !isEditorMode;
40
+ window.__EB__.isEditorMode = isEditorMode;
41
+ }
42
+ window.removeEventListener('message', onMessage);
43
+ }, []);
44
+ useEffect(() => {
45
+ const handleHandshakeTimeout = () => {
46
+ if (!recievedModeMessage.current) {
47
+ setMode(StudioCanvasMode.NONE);
48
+ }
49
+ };
50
+ // Only run check after component is mounted on the client to avoid hydration ssr issues
51
+ if (mounted) {
52
+ // Double check if we are in editor mode by listening to postMessage events
53
+ if (typeof window !== 'undefined') {
54
+ window.addEventListener('message', onMessage);
55
+ sendMessage(OUTGOING_EVENTS.Connected, undefined);
56
+ sendMessage(OUTGOING_EVENTS.SDKFeatures, sdkFeatures);
57
+ setTimeout(handleHandshakeTimeout, 100);
58
+ }
59
+ }
60
+ else {
61
+ setMounted(true);
62
+ }
63
+ return () => window.removeEventListener('message', onMessage);
64
+ }, [mounted, onMessage]);
65
+ return mode;
66
+ };
67
+ function inIframe() {
68
+ try {
69
+ return window.self !== window.top;
70
+ }
71
+ catch (e) {
72
+ return false;
73
+ }
74
+ }
75
+
76
+ export { useDetectCanvasMode };
77
+ //# sourceMappingURL=useDetectCanvasMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDetectCanvasMode.js","sources":["../../../src/hooks/useDetectCanvasMode.tsx"],"sourcesContent":["'use client';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n doesMismatchMessageSchema,\n sendMessage,\n tryParseMessage,\n} from '@contentful/experiences-core';\nimport {\n INCOMING_EVENTS,\n OUTGOING_EVENTS,\n StudioCanvasMode,\n} from '@contentful/experiences-core/constants';\nimport { sdkFeatures } from '../core/sdkFeatures';\n\ntype useDetectCanvasModeArgs = {\n /** If running from a known client side only situation (ie: useFetchBySlug),\n * set this to true to kick in editor mode check sooner (which avoids a render cycle) */\n isClientSide?: boolean;\n};\n\nexport const useDetectCanvasMode = ({ isClientSide = false }: useDetectCanvasModeArgs = {}) => {\n const [mounted, setMounted] = useState(false);\n const recievedModeMessage = useRef(false);\n const [mode, setMode] = useState<StudioCanvasMode>(() => {\n // if we are client side and running in an iframe, then initialize to read only,\n // Editor mode can be requested later.\n if (isClientSide && inIframe()) {\n return StudioCanvasMode.READ_ONLY;\n } else {\n return StudioCanvasMode.NONE;\n }\n });\n\n const onMessage = useCallback((event: MessageEvent) => {\n if (doesMismatchMessageSchema(event)) {\n return;\n }\n const eventData = tryParseMessage(event);\n const isRequestingCanvasMode =\n eventData.eventType === INCOMING_EVENTS.RequestEditorMode ||\n eventData.eventType === INCOMING_EVENTS.RequestReadOnlyMode;\n\n if (!isRequestingCanvasMode) {\n return;\n }\n\n const isEditorMode = eventData.eventType === INCOMING_EVENTS.RequestEditorMode;\n const mode = isEditorMode ? StudioCanvasMode.EDITOR : StudioCanvasMode.READ_ONLY;\n\n recievedModeMessage.current = true;\n setMode(mode);\n\n if (typeof window !== 'undefined') {\n // Once we definitely know that we are in editor mode, we set this flag so future postMessage connect calls are not made\n if (!window.__EB__) {\n window.__EB__ = {};\n }\n window.__EB__.isReadOnlyMode = !isEditorMode;\n window.__EB__.isEditorMode = isEditorMode;\n }\n\n window.removeEventListener('message', onMessage);\n }, []);\n\n useEffect(() => {\n const handleHandshakeTimeout = () => {\n if (!recievedModeMessage.current) {\n setMode(StudioCanvasMode.NONE);\n }\n };\n\n // Only run check after component is mounted on the client to avoid hydration ssr issues\n if (mounted) {\n // Double check if we are in editor mode by listening to postMessage events\n if (typeof window !== 'undefined') {\n window.addEventListener('message', onMessage);\n sendMessage(OUTGOING_EVENTS.Connected, undefined);\n sendMessage(OUTGOING_EVENTS.SDKFeatures, sdkFeatures);\n\n setTimeout(handleHandshakeTimeout, 100);\n }\n } else {\n setMounted(true);\n }\n\n return () => window.removeEventListener('message', onMessage);\n }, [mounted, onMessage]);\n\n return mode;\n};\n\nfunction inIframe() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return false;\n }\n}\n"],"names":[],"mappings":";;;;;;AAoBO;;AAEL;;;;AAIE;;;;;;AAKF;AAEA;AACE;;;AAGA;;AAGE;;;;;AAOF;AAEA;;AAGA;;AAEE;AACE;;AAEF;AACA;;AAGF;;;;AAKE;AACE;;AAEJ;;;;AAKE;AACE;AACA;AACA;AAEA;;;;;;;AAON;AAEA;AACF;AAEA;AACE;AACE;;;AAEA;;AAEJ;;"}
@@ -1,15 +1,16 @@
1
1
  "use client";
2
2
  import { useState, useEffect } from 'react';
3
+ import { StudioCanvasMode } from '@contentful/experiences-core/constants';
3
4
 
4
- const useFetchByBase = (fetchMethod, isEditorMode) => {
5
+ const useFetchByBase = (fetchMethod, mode) => {
5
6
  const [experience, setExperience] = useState();
6
7
  const [isLoading, setIsLoading] = useState(false);
7
8
  const [error, setError] = useState();
8
9
  useEffect(() => {
9
10
  (async () => {
10
- // if we are in editor mode, we don't want to fetch the experience here
11
+ // if we are in editor/read only mode, we don't want to fetch the experience here
11
12
  // it is passed via postMessage instead
12
- if (isEditorMode) {
13
+ if (mode === StudioCanvasMode.EDITOR || mode === StudioCanvasMode.READ_ONLY) {
13
14
  return;
14
15
  }
15
16
  setIsLoading(true);
@@ -25,12 +26,12 @@ const useFetchByBase = (fetchMethod, isEditorMode) => {
25
26
  setIsLoading(false);
26
27
  }
27
28
  })();
28
- }, [fetchMethod, isEditorMode]);
29
+ }, [fetchMethod, mode]);
29
30
  return {
30
31
  error,
31
32
  experience,
32
33
  isLoading,
33
- isEditorMode,
34
+ mode,
34
35
  };
35
36
  };
36
37
 
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchByBase.js","sources":["../../../src/hooks/useFetchByBase.ts"],"sourcesContent":["'use client';\nimport { useEffect, useState } from 'react';\nimport { EntityStore } from '@contentful/experiences-core';\nimport type { Experience } from '@contentful/experiences-core/types';\n\nexport const useFetchByBase = (\n fetchMethod: () => Promise<Experience<EntityStore> | undefined>,\n isEditorMode: boolean,\n) => {\n const [experience, setExperience] = useState<Experience<EntityStore>>();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error>();\n\n useEffect(() => {\n (async () => {\n // if we are in editor mode, we don't want to fetch the experience here\n // it is passed via postMessage instead\n if (isEditorMode) {\n return;\n }\n setIsLoading(true);\n setError(undefined);\n try {\n const exp = await fetchMethod();\n setExperience(exp);\n } catch (error) {\n setError(error as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }, [fetchMethod, isEditorMode]);\n\n return {\n error,\n experience,\n isLoading,\n isEditorMode,\n };\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAsBM;AACE;;;;;;;;;;AAQN;;;;;;;AAQF;;"}
1
+ {"version":3,"file":"useFetchByBase.js","sources":["../../../src/hooks/useFetchByBase.ts"],"sourcesContent":["'use client';\nimport { useEffect, useState } from 'react';\nimport { EntityStore } from '@contentful/experiences-core';\nimport type { Experience } from '@contentful/experiences-core/types';\nimport { StudioCanvasMode } from '@contentful/experiences-core/constants';\n\nexport const useFetchByBase = (\n fetchMethod: () => Promise<Experience<EntityStore> | undefined>,\n mode: StudioCanvasMode,\n) => {\n const [experience, setExperience] = useState<Experience<EntityStore>>();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error>();\n\n useEffect(() => {\n (async () => {\n // if we are in editor/read only mode, we don't want to fetch the experience here\n // it is passed via postMessage instead\n if (mode === StudioCanvasMode.EDITOR || mode === StudioCanvasMode.READ_ONLY) {\n return;\n }\n setIsLoading(true);\n setError(undefined);\n try {\n const exp = await fetchMethod();\n setExperience(exp);\n } catch (error) {\n setError(error as Error);\n } finally {\n setIsLoading(false);\n }\n })();\n }, [fetchMethod, mode]);\n\n return {\n error,\n experience,\n isLoading,\n mode,\n };\n};\n"],"names":[],"mappings":";;;;;;;;;;;;AAkBM;;;;;AAKA;AACE;;;;;;;;;;AAQN;;;;;;;AAQF;;"}
@@ -1,14 +1,14 @@
1
1
  import { useCallback } from 'react';
2
2
  import { useFetchByBase } from './useFetchByBase.js';
3
3
  import { fetchById } from '@contentful/experiences-core';
4
- import { useDetectEditorMode } from './useDetectEditorMode.js';
4
+ import { useDetectCanvasMode } from './useDetectCanvasMode.js';
5
5
 
6
6
  const useFetchById = ({ id, localeCode, client, experienceTypeId, hyperlinkPattern, }) => {
7
- const isEditorMode = useDetectEditorMode({ isClientSide: typeof window !== 'undefined' });
7
+ const mode = useDetectCanvasMode({ isClientSide: typeof window !== 'undefined' });
8
8
  const fetchMethod = useCallback(() => {
9
9
  return fetchById({ id, localeCode, client, experienceTypeId });
10
10
  }, [id, localeCode, client, experienceTypeId]);
11
- const fetchResult = useFetchByBase(fetchMethod, isEditorMode);
11
+ const fetchResult = useFetchByBase(fetchMethod, mode);
12
12
  return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };
13
13
  };
14
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchById.js","sources":["../../../src/hooks/useFetchById.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport type { ContentfulClientApi } from 'contentful';\nimport { useFetchByBase } from './useFetchByBase';\nimport { fetchById } from '@contentful/experiences-core';\nimport { useDetectEditorMode } from './useDetectEditorMode';\n\nexport type UseFetchByIdArgs = {\n client: ContentfulClientApi<undefined>;\n id: string;\n experienceTypeId: string;\n localeCode: string;\n hyperlinkPattern?: string;\n};\n\nexport const useFetchById = ({\n id,\n localeCode,\n client,\n experienceTypeId,\n hyperlinkPattern,\n}: UseFetchByIdArgs) => {\n const isEditorMode = useDetectEditorMode({ isClientSide: typeof window !== 'undefined' });\n\n const fetchMethod = useCallback(() => {\n return fetchById({ id, localeCode, client, experienceTypeId });\n }, [id, localeCode, client, experienceTypeId]);\n\n const fetchResult = useFetchByBase(fetchMethod, isEditorMode);\n\n return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };\n};\n"],"names":[],"mappings":";;;;;AAca,MAAA,YAAY,GAAG,CAAC,EAC3B,EAAE,EACF,UAAU,EACV,MAAM,EACN,gBAAgB,EAChB,gBAAgB,GACC,KAAI;AACrB,IAAA,MAAM,YAAY,GAAG,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC;AAE1F,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;AACnC,QAAA,OAAO,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;KAChE,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAE9D,IAAA,OAAO,EAAE,GAAG,WAAW,EAAE,UAAU,EAAE,EAAE,GAAG,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;AACzF;;;;"}
1
+ {"version":3,"file":"useFetchById.js","sources":["../../../src/hooks/useFetchById.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport type { ContentfulClientApi } from 'contentful';\nimport { useFetchByBase } from './useFetchByBase';\nimport { fetchById } from '@contentful/experiences-core';\nimport { useDetectCanvasMode } from './useDetectCanvasMode';\n\nexport type UseFetchByIdArgs = {\n client: ContentfulClientApi<undefined>;\n id: string;\n experienceTypeId: string;\n localeCode: string;\n hyperlinkPattern?: string;\n};\n\nexport const useFetchById = ({\n id,\n localeCode,\n client,\n experienceTypeId,\n hyperlinkPattern,\n}: UseFetchByIdArgs) => {\n const mode = useDetectCanvasMode({ isClientSide: typeof window !== 'undefined' });\n\n const fetchMethod = useCallback(() => {\n return fetchById({ id, localeCode, client, experienceTypeId });\n }, [id, localeCode, client, experienceTypeId]);\n\n const fetchResult = useFetchByBase(fetchMethod, mode);\n\n return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };\n};\n"],"names":[],"mappings":";;;;;AAca,MAAA,YAAY,GAAG,CAAC,EAC3B,EAAE,EACF,UAAU,EACV,MAAM,EACN,gBAAgB,EAChB,gBAAgB,GACC,KAAI;AACrB,IAAA,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC;AAElF,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;AACnC,QAAA,OAAO,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;KAChE,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAEtD,IAAA,OAAO,EAAE,GAAG,WAAW,EAAE,UAAU,EAAE,EAAE,GAAG,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;AACzF;;;;"}
@@ -1,14 +1,14 @@
1
1
  import { useCallback } from 'react';
2
2
  import { useFetchByBase } from './useFetchByBase.js';
3
3
  import { fetchBySlug } from '@contentful/experiences-core';
4
- import { useDetectEditorMode } from './useDetectEditorMode.js';
4
+ import { useDetectCanvasMode } from './useDetectCanvasMode.js';
5
5
 
6
6
  const useFetchBySlug = ({ slug, localeCode, client, experienceTypeId, hyperlinkPattern, }) => {
7
- const isEditorMode = useDetectEditorMode({ isClientSide: typeof window !== 'undefined' });
7
+ const mode = useDetectCanvasMode({ isClientSide: typeof window !== 'undefined' });
8
8
  const fetchMethod = useCallback(() => {
9
9
  return fetchBySlug({ slug, localeCode, client, experienceTypeId });
10
10
  }, [slug, localeCode, client, experienceTypeId]);
11
- const fetchResult = useFetchByBase(fetchMethod, isEditorMode);
11
+ const fetchResult = useFetchByBase(fetchMethod, mode);
12
12
  return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };
13
13
  };
14
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchBySlug.js","sources":["../../../src/hooks/useFetchBySlug.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport type { ContentfulClientApi } from 'contentful';\nimport { useFetchByBase } from './useFetchByBase';\nimport { fetchBySlug } from '@contentful/experiences-core';\nimport { useDetectEditorMode } from './useDetectEditorMode';\n\nexport type UseFetchBySlugArgs = {\n client: ContentfulClientApi<undefined>;\n slug: string;\n experienceTypeId: string;\n localeCode: string;\n /** The pattern being used to generate links for hyperlink properties **/\n hyperlinkPattern?: string;\n};\n\nexport const useFetchBySlug = ({\n slug,\n localeCode,\n client,\n experienceTypeId,\n hyperlinkPattern,\n}: UseFetchBySlugArgs) => {\n const isEditorMode = useDetectEditorMode({ isClientSide: typeof window !== 'undefined' });\n\n const fetchMethod = useCallback(() => {\n return fetchBySlug({ slug, localeCode, client, experienceTypeId });\n }, [slug, localeCode, client, experienceTypeId]);\n\n const fetchResult = useFetchByBase(fetchMethod, isEditorMode);\n\n return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };\n};\n"],"names":[],"mappings":";;;;;AAea,MAAA,cAAc,GAAG,CAAC,EAC7B,IAAI,EACJ,UAAU,EACV,MAAM,EACN,gBAAgB,EAChB,gBAAgB,GACG,KAAI;AACvB,IAAA,MAAM,YAAY,GAAG,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC;AAE1F,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;AACnC,QAAA,OAAO,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;KACpE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAE9D,IAAA,OAAO,EAAE,GAAG,WAAW,EAAE,UAAU,EAAE,EAAE,GAAG,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;AACzF;;;;"}
1
+ {"version":3,"file":"useFetchBySlug.js","sources":["../../../src/hooks/useFetchBySlug.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport type { ContentfulClientApi } from 'contentful';\nimport { useFetchByBase } from './useFetchByBase';\nimport { fetchBySlug } from '@contentful/experiences-core';\nimport { useDetectCanvasMode } from './useDetectCanvasMode';\n\nexport type UseFetchBySlugArgs = {\n client: ContentfulClientApi<undefined>;\n slug: string;\n experienceTypeId: string;\n localeCode: string;\n /** The pattern being used to generate links for hyperlink properties **/\n hyperlinkPattern?: string;\n};\n\nexport const useFetchBySlug = ({\n slug,\n localeCode,\n client,\n experienceTypeId,\n hyperlinkPattern,\n}: UseFetchBySlugArgs) => {\n const mode = useDetectCanvasMode({ isClientSide: typeof window !== 'undefined' });\n\n const fetchMethod = useCallback(() => {\n return fetchBySlug({ slug, localeCode, client, experienceTypeId });\n }, [slug, localeCode, client, experienceTypeId]);\n\n const fetchResult = useFetchByBase(fetchMethod, mode);\n\n return { ...fetchResult, experience: { ...fetchResult.experience, hyperlinkPattern } };\n};\n"],"names":[],"mappings":";;;;;AAea,MAAA,cAAc,GAAG,CAAC,EAC7B,IAAI,EACJ,UAAU,EACV,MAAM,EACN,gBAAgB,EAChB,gBAAgB,GACG,KAAI;AACvB,IAAA,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC;AAElF,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;AACnC,QAAA,OAAO,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;KACpE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAEtD,IAAA,OAAO,EAAE,GAAG,WAAW,EAAE,UAAU,EAAE,EAAE,GAAG,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;AACzF;;;;"}
package/dist/index.d.ts CHANGED
@@ -4,8 +4,9 @@ import { EntityStore, VisualEditorMode } from '@contentful/experiences-core';
4
4
  export { VisualEditorMode, createExperience, defineBreakpoints, defineDesignTokens, detachExperienceStyles, fetchById, fetchBySlug } from '@contentful/experiences-core';
5
5
  import { Experience, ComponentRegistration, ComponentRegistrationOptions } from '@contentful/experiences-core/types';
6
6
  export { ComponentDefinition } from '@contentful/experiences-core/types';
7
- import { ContentfulClientApi } from 'contentful';
7
+ import * as _contentful_experiences_core_constants from '@contentful/experiences-core/constants';
8
8
  export { CF_STYLE_ATTRIBUTES, CONTENTFUL_COMPONENTS, LATEST_SCHEMA_VERSION } from '@contentful/experiences-core/constants';
9
+ import { ContentfulClientApi } from 'contentful';
9
10
 
10
11
  type ExperienceRootProps = {
11
12
  experience?: Experience<EntityStore> | string | null;
@@ -28,7 +29,7 @@ declare const useFetchById: ({ id, localeCode, client, experienceTypeId, hyperli
28
29
  };
29
30
  error: Error | undefined;
30
31
  isLoading: boolean;
31
- isEditorMode: boolean;
32
+ mode: _contentful_experiences_core_constants.StudioCanvasMode;
32
33
  };
33
34
 
34
35
  type UseFetchBySlugArgs = {
@@ -46,7 +47,7 @@ declare const useFetchBySlug: ({ slug, localeCode, client, experienceTypeId, hyp
46
47
  };
47
48
  error: Error | undefined;
48
49
  isLoading: boolean;
49
- isEditorMode: boolean;
50
+ mode: _contentful_experiences_core_constants.StudioCanvasMode;
50
51
  };
51
52
 
52
53
  /**
@@ -1,4 +1,4 @@
1
- const SDK_VERSION = '1.15.2-dev-20240912T1641-eb25944.0';
1
+ const SDK_VERSION = '1.16.0-beta.0';
2
2
 
3
3
  export { SDK_VERSION };
4
4
  //# sourceMappingURL=sdkVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdkVersion.js","sources":["../../src/sdkVersion.ts"],"sourcesContent":["export const SDK_VERSION = '1.15.2-dev-20240912T1641-eb25944.0';\n"],"names":[],"mappings":"AAAO,MAAM,WAAW,GAAG;;;;"}
1
+ {"version":3,"file":"sdkVersion.js","sources":["../../src/sdkVersion.ts"],"sourcesContent":["export const SDK_VERSION = '1.16.0-beta.0';\n"],"names":[],"mappings":"AAAO,MAAM,WAAW,GAAG;;;;"}
@@ -1,7 +1,8 @@
1
- type UseDetectEditorModeArgs = {
1
+ import { StudioCanvasMode } from '@contentful/experiences-core/constants';
2
+ type useDetectCanvasModeArgs = {
2
3
  /** If running from a known client side only situation (ie: useFetchBySlug),
3
4
  * set this to true to kick in editor mode check sooner (which avoids a render cycle) */
4
5
  isClientSide?: boolean;
5
6
  };
6
- export declare const useDetectEditorMode: ({ isClientSide }?: UseDetectEditorModeArgs) => boolean;
7
+ export declare const useDetectCanvasMode: ({ isClientSide }?: useDetectCanvasModeArgs) => StudioCanvasMode;
7
8
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,9 @@
1
1
  import { EntityStore } from '@contentful/experiences-core';
2
2
  import type { Experience } from '@contentful/experiences-core/types';
3
- export declare const useFetchByBase: (fetchMethod: () => Promise<Experience<EntityStore> | undefined>, isEditorMode: boolean) => {
3
+ import { StudioCanvasMode } from '@contentful/experiences-core/constants';
4
+ export declare const useFetchByBase: (fetchMethod: () => Promise<Experience<EntityStore> | undefined>, mode: StudioCanvasMode) => {
4
5
  error: Error | undefined;
5
6
  experience: Experience<EntityStore> | undefined;
6
7
  isLoading: boolean;
7
- isEditorMode: boolean;
8
+ mode: StudioCanvasMode;
8
9
  };
@@ -13,5 +13,5 @@ export declare const useFetchById: ({ id, localeCode, client, experienceTypeId,
13
13
  };
14
14
  error: Error | undefined;
15
15
  isLoading: boolean;
16
- isEditorMode: boolean;
16
+ mode: import("@contentful/experiences-core/constants").StudioCanvasMode;
17
17
  };
@@ -14,5 +14,5 @@ export declare const useFetchBySlug: ({ slug, localeCode, client, experienceType
14
14
  };
15
15
  error: Error | undefined;
16
16
  isLoading: boolean;
17
- isEditorMode: boolean;
17
+ mode: import("@contentful/experiences-core/constants").StudioCanvasMode;
18
18
  };
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "1.15.2-dev-20240912T1641-eb25944.0";
1
+ export declare const SDK_VERSION = "1.16.0-beta.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experiences-sdk-react",
3
- "version": "1.15.2-dev-20240912T1641-eb25944.0",
3
+ "version": "1.16.0-beta.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "typings": "./dist/src/index.d.ts",
@@ -41,10 +41,10 @@
41
41
  "depcruise": "depcruise src"
42
42
  },
43
43
  "dependencies": {
44
- "@contentful/experiences-components-react": "1.15.2-dev-20240912T1641-eb25944.0",
45
- "@contentful/experiences-core": "1.15.2-dev-20240912T1641-eb25944.0",
46
- "@contentful/experiences-validators": "1.15.2-dev-20240912T1641-eb25944.0",
47
- "@contentful/experiences-visual-editor-react": "1.15.2-dev-20240912T1641-eb25944.0",
44
+ "@contentful/experiences-components-react": "1.16.0-beta.0",
45
+ "@contentful/experiences-core": "1.16.0-beta.0",
46
+ "@contentful/experiences-validators": "1.16.0-beta.0",
47
+ "@contentful/experiences-visual-editor-react": "1.16.0-beta.0",
48
48
  "@contentful/rich-text-types": "^16.2.1",
49
49
  "classnames": "^2.3.2",
50
50
  "csstype": "^3.1.2",
@@ -102,5 +102,5 @@
102
102
  "dist",
103
103
  "package.json"
104
104
  ],
105
- "gitHead": "d432a22073ea0bde6e86bb2283c10160589b385a"
105
+ "gitHead": "afd5b44b8b1663e4db1b3aac67a37e66c3e68af5"
106
106
  }
@@ -1,63 +0,0 @@
1
- "use client";
2
- import { useState, useRef, useEffect } from 'react';
3
- import { sendMessage, doesMismatchMessageSchema, tryParseMessage } from '@contentful/experiences-core';
4
- import { OUTGOING_EVENTS, INCOMING_EVENTS } from '@contentful/experiences-core/constants';
5
- import { sdkFeatures } from '../core/sdkFeatures.js';
6
-
7
- const useDetectEditorMode = ({ isClientSide = false } = {}) => {
8
- const [mounted, setMounted] = useState(false);
9
- const [isEditorMode, setIsEditorMode] = useState(isClientSide ? inIframe() : false);
10
- const receivedMessage = useRef(false);
11
- useEffect(() => {
12
- const onMessage = (event) => {
13
- if (doesMismatchMessageSchema(event)) {
14
- return;
15
- }
16
- const eventData = tryParseMessage(event);
17
- if (eventData.eventType === INCOMING_EVENTS.RequestEditorMode) {
18
- setIsEditorMode(true);
19
- receivedMessage.current = true;
20
- if (typeof window !== 'undefined') {
21
- //Once we definitely know that we are in editor mode, we set this flag so future postMessage connect calls are not made
22
- if (!window.__EB__) {
23
- window.__EB__ = {};
24
- }
25
- window.__EB__.isEditorMode = true;
26
- window.removeEventListener('message', onMessage);
27
- }
28
- }
29
- };
30
- //Only run check after component is mounted on the client to avoid hydration ssr issues
31
- if (mounted) {
32
- setIsEditorMode(inIframe());
33
- //Double check if we are in editor mode by listening to postMessage events
34
- if (typeof window !== 'undefined' && !window.__EB__?.isEditorMode) {
35
- window.addEventListener('message', onMessage);
36
- sendMessage(OUTGOING_EVENTS.Connected, undefined);
37
- sendMessage(OUTGOING_EVENTS.SDKFeatures, sdkFeatures);
38
- setTimeout(() => {
39
- if (!receivedMessage.current) {
40
- // if message is not received back in time, set editorMode back to false
41
- setIsEditorMode(false);
42
- }
43
- }, 100);
44
- }
45
- }
46
- else {
47
- setMounted(true);
48
- }
49
- return () => window.removeEventListener('message', onMessage);
50
- }, [mounted]);
51
- return isEditorMode;
52
- };
53
- function inIframe() {
54
- try {
55
- return window.self !== window.top;
56
- }
57
- catch (e) {
58
- return false;
59
- }
60
- }
61
-
62
- export { useDetectEditorMode };
63
- //# sourceMappingURL=useDetectEditorMode.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDetectEditorMode.js","sources":["../../../src/hooks/useDetectEditorMode.tsx"],"sourcesContent":["'use client';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n doesMismatchMessageSchema,\n sendMessage,\n tryParseMessage,\n} from '@contentful/experiences-core';\nimport { INCOMING_EVENTS, OUTGOING_EVENTS } from '@contentful/experiences-core/constants';\nimport { sdkFeatures } from '../core/sdkFeatures';\n\ntype UseDetectEditorModeArgs = {\n /** If running from a known client side only situation (ie: useFetchBySlug),\n * set this to true to kick in editor mode check sooner (which avoids a render cycle) */\n isClientSide?: boolean;\n};\n\nexport const useDetectEditorMode = ({ isClientSide = false }: UseDetectEditorModeArgs = {}) => {\n const [mounted, setMounted] = useState(false);\n const [isEditorMode, setIsEditorMode] = useState(isClientSide ? inIframe() : false);\n const receivedMessage = useRef(false);\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n if (doesMismatchMessageSchema(event)) {\n return;\n }\n const eventData = tryParseMessage(event);\n\n if (eventData.eventType === INCOMING_EVENTS.RequestEditorMode) {\n setIsEditorMode(true);\n receivedMessage.current = true;\n if (typeof window !== 'undefined') {\n //Once we definitely know that we are in editor mode, we set this flag so future postMessage connect calls are not made\n if (!window.__EB__) {\n window.__EB__ = {};\n }\n window.__EB__.isEditorMode = true;\n window.removeEventListener('message', onMessage);\n }\n }\n };\n\n //Only run check after component is mounted on the client to avoid hydration ssr issues\n if (mounted) {\n setIsEditorMode(inIframe());\n //Double check if we are in editor mode by listening to postMessage events\n if (typeof window !== 'undefined' && !window.__EB__?.isEditorMode) {\n window.addEventListener('message', onMessage);\n sendMessage(OUTGOING_EVENTS.Connected, undefined);\n sendMessage(OUTGOING_EVENTS.SDKFeatures, sdkFeatures);\n\n setTimeout(() => {\n if (!receivedMessage.current) {\n // if message is not received back in time, set editorMode back to false\n setIsEditorMode(false);\n }\n }, 100);\n }\n } else {\n setMounted(true);\n }\n\n return () => window.removeEventListener('message', onMessage);\n }, [mounted]);\n\n return isEditorMode;\n};\n\nfunction inIframe() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return false;\n }\n}\n"],"names":[],"mappings":";;;;;;AAgBO;;AAEL;AACA;;AAGE;AACE;;;AAGA;;;AAIE;AACA;;AAEE;AACE;;AAEF;AACA;;;AAGN;;;AAIE;;AAEA;AACE;AACA;AACA;;AAGE;;;;;;;;;;;AAWR;AAEA;AACF;AAEA;AACE;AACE;;;AAEA;;AAEJ;;"}