@commercetools-demo/puck-renderer 0.5.1 → 0.5.2

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/dist/index.d.mts CHANGED
@@ -51,6 +51,13 @@ interface PuckRendererProps {
51
51
  loadingComponent?: ReactElement;
52
52
  /** Custom error display. */
53
53
  errorComponent?: ReactElement;
54
+ /**
55
+ * Fallback content rendered when there is nothing to show — fetch error,
56
+ * not-found, or no identifying param (pageKey/slug/contentKey/query) given.
57
+ * Not used while loading. If `errorComponent` is provided it takes precedence
58
+ * over `children`.
59
+ */
60
+ children?: React.ReactNode;
54
61
  className?: string;
55
62
  style?: React.CSSProperties;
56
63
  }
package/dist/index.d.ts CHANGED
@@ -51,6 +51,13 @@ interface PuckRendererProps {
51
51
  loadingComponent?: ReactElement;
52
52
  /** Custom error display. */
53
53
  errorComponent?: ReactElement;
54
+ /**
55
+ * Fallback content rendered when there is nothing to show — fetch error,
56
+ * not-found, or no identifying param (pageKey/slug/contentKey/query) given.
57
+ * Not used while loading. If `errorComponent` is provided it takes precedence
58
+ * over `children`.
59
+ */
60
+ children?: React.ReactNode;
54
61
  className?: string;
55
62
  style?: React.CSSProperties;
56
63
  }
package/dist/index.js CHANGED
@@ -57,6 +57,7 @@ var PuckRendererInner = ({
57
57
  config,
58
58
  loadingComponent,
59
59
  errorComponent,
60
+ children,
60
61
  className,
61
62
  style
62
63
  }) => {
@@ -128,7 +129,7 @@ var PuckRendererInner = ({
128
129
  );
129
130
  }
130
131
  if (error || !data) {
131
- return errorComponent ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
132
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: errorComponent ?? children ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
132
133
  "div",
133
134
  {
134
135
  style: {
@@ -139,7 +140,7 @@ var PuckRendererInner = ({
139
140
  },
140
141
  children: error ?? "Failed to load"
141
142
  }
142
- );
143
+ ) });
143
144
  }
144
145
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PuckDataRenderer, { data, config, className, style });
145
146
  };
@@ -156,6 +157,7 @@ var PuckRenderer = ({
156
157
  config = DEFAULT_CONFIG,
157
158
  loadingComponent,
158
159
  errorComponent,
160
+ children,
159
161
  className,
160
162
  style
161
163
  }) => {
@@ -172,7 +174,8 @@ var PuckRenderer = ({
172
174
  loadingComponent,
173
175
  errorComponent,
174
176
  className,
175
- style
177
+ style,
178
+ children
176
179
  }
177
180
  );
178
181
  if (baseURL && projectKey && businessUnitKey) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/PuckDataRenderer.tsx","../src/PuckRenderer.tsx"],"sourcesContent":["export { PuckDataRenderer } from './PuckDataRenderer';\nexport type { PuckDataRendererProps } from './PuckDataRenderer';\n\nexport { PuckRenderer } from './PuckRenderer';\nexport type { PuckRendererProps } from './PuckRenderer';\n","import React from 'react';\nimport { Render } from '@measured/puck';\nimport type { Config, Data } from '@measured/puck';\nimport type { PuckData, PuckConfig } from '@commercetools-demo/puck-types';\n\nexport interface PuckDataRendererProps {\n /** The Puck Data to render (from the API or SSR props). */\n data: PuckData;\n /**\n * The Puck Config that defines available components and their render functions.\n * Must match the config used in the editor to ensure consistent output.\n */\n config: PuckConfig;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * SSR-friendly renderer — no data fetching, renders whatever Data you pass in.\n * Wrap with PuckApiProvider only if you use it alongside API hooks.\n */\nexport const PuckDataRenderer: React.FC<PuckDataRendererProps> = ({\n data,\n config,\n className,\n style,\n}) => {\n return (\n <div className={className} style={style}>\n <Render config={config as Config} data={data as Data} />\n </div>\n );\n};\n","import React, { useEffect, useState, type ReactElement } from 'react';\nimport { PuckApiProvider, usePuckApiContext } from '@commercetools-demo/puck-api';\nimport { defaultPuckConfig } from '@commercetools-demo/puck-editor';\nimport {\n getPublishedPuckPageApi,\n getPreviewPuckPageApi,\n queryPuckPageApi,\n getPublishedPuckContentApi,\n getPreviewPuckContentApi,\n queryPuckContentApi,\n} from '@commercetools-demo/puck-api';\nimport type { PuckConfig, PuckData } from '@commercetools-demo/puck-types';\nimport { PuckDataRenderer } from './PuckDataRenderer';\n\nconst DEFAULT_CONFIG: PuckConfig = {\n ...defaultPuckConfig,\n components: { ...defaultPuckConfig.components },\n};\n\n// ---------------------------------------------------------------------------\n// Inner component (needs PuckApiContext)\n// ---------------------------------------------------------------------------\n\ninterface PuckRendererInnerProps {\n type: 'page' | 'content';\n pageKey?: string;\n slug?: string;\n contentKey?: string;\n query?: string;\n mode: 'published' | 'preview';\n config: PuckConfig;\n loadingComponent?: ReactElement;\n errorComponent?: ReactElement;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst PuckRendererInner: React.FC<PuckRendererInnerProps> = ({\n type,\n pageKey,\n slug,\n contentKey,\n query,\n mode,\n config,\n loadingComponent,\n errorComponent,\n className,\n style,\n}) => {\n const { baseURL, projectKey, businessUnitKey } = usePuckApiContext();\n\n const [data, setData] = useState<PuckData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n if (type === 'content') {\n let puckData: PuckData | null = null;\n\n if (contentKey) {\n const value =\n mode === 'published'\n ? await getPublishedPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey)\n : await getPreviewPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey);\n puckData = value.data;\n } else if (query) {\n const value = await queryPuckContentApi(baseURL, projectKey, businessUnitKey, { query: `contentType = \"${query}\"` }, mode);\n puckData = value?.data ?? null;\n }\n\n if (!cancelled) {\n if (puckData) {\n setData(puckData);\n } else {\n setError('Content not found');\n }\n }\n } else {\n // type === 'page'\n let pageValue = null;\n\n if (pageKey) {\n pageValue =\n mode === 'published'\n ? await getPublishedPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey)\n : await getPreviewPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey);\n } else if (slug) {\n pageValue = await queryPuckPageApi(baseURL, projectKey, businessUnitKey, { query: `slug = \"${slug}\"` }, mode);\n }\n\n if (!cancelled) {\n if (pageValue) {\n setData(pageValue.puckData);\n } else {\n setError('Page not found');\n }\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message);\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void fetchData();\n return () => {\n cancelled = true;\n };\n }, [baseURL, projectKey, businessUnitKey, type, pageKey, slug, contentKey, query, mode]);\n\n if (loading) {\n return (\n loadingComponent ?? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px',\n color: '#6b7280',\n }}\n >\n Loading…\n </div>\n )\n );\n }\n\n if (error || !data) {\n return (\n errorComponent ?? (\n <div\n style={{\n padding: '32px',\n color: '#dc2626',\n background: '#fef2f2',\n borderRadius: '8px',\n }}\n >\n {error ?? 'Failed to load'}\n </div>\n )\n );\n }\n\n return <PuckDataRenderer data={data} config={config} className={className} style={style} />;\n};\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PuckRendererProps {\n /**\n * Whether to render a page or a content item. Defaults to 'page'.\n * - 'page': use pageKey or slug to fetch\n * - 'content': use contentKey or query (contentType) to fetch\n */\n type?: 'page' | 'content';\n\n /**\n * Service base URL. Can be omitted if a PuckApiProvider is already in the tree.\n */\n baseURL?: string;\n /** CommerceTools project key. Can be omitted if provider is in tree. */\n projectKey?: string;\n /** Business unit key. Can be omitted if provider is in tree. */\n businessUnitKey?: string;\n\n /** [type=page] Fetch by page key. */\n pageKey?: string;\n /** [type=page] OR fetch by slug (URL path). */\n slug?: string;\n\n /** [type=content] Fetch by content key. */\n contentKey?: string;\n /** [type=content] OR fetch by contentType query string. */\n query?: string;\n\n /** 'published' (default) or 'preview' (draft || published). */\n mode?: 'published' | 'preview';\n\n /**\n * Puck config — must match the config used in the editor. Defaults to defaultPuckConfig.\n */\n config?: PuckConfig;\n\n /** Custom loading indicator. */\n loadingComponent?: ReactElement;\n /** Custom error display. */\n errorComponent?: ReactElement;\n\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const PuckRenderer: React.FC<PuckRendererProps> = ({\n type = 'page',\n baseURL,\n projectKey,\n businessUnitKey,\n pageKey,\n slug,\n contentKey,\n query,\n mode = 'published',\n config = DEFAULT_CONFIG,\n loadingComponent,\n errorComponent,\n className,\n style,\n}) => {\n const inner = (\n <PuckRendererInner\n type={type}\n pageKey={pageKey}\n slug={slug}\n contentKey={contentKey}\n query={query}\n mode={mode}\n config={config}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n className={className}\n style={style}\n />\n );\n\n if (baseURL && projectKey && businessUnitKey) {\n return (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n >\n {inner}\n </PuckApiProvider>\n );\n }\n\n return inner;\n};\n"],"mappings":"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","names":["import_puck_api","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/PuckDataRenderer.tsx","../src/PuckRenderer.tsx"],"sourcesContent":["export { PuckDataRenderer } from './PuckDataRenderer';\nexport type { PuckDataRendererProps } from './PuckDataRenderer';\n\nexport { PuckRenderer } from './PuckRenderer';\nexport type { PuckRendererProps } from './PuckRenderer';\n","import React from 'react';\nimport { Render } from '@measured/puck';\nimport type { Config, Data } from '@measured/puck';\nimport type { PuckData, PuckConfig } from '@commercetools-demo/puck-types';\n\nexport interface PuckDataRendererProps {\n /** The Puck Data to render (from the API or SSR props). */\n data: PuckData;\n /**\n * The Puck Config that defines available components and their render functions.\n * Must match the config used in the editor to ensure consistent output.\n */\n config: PuckConfig;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * SSR-friendly renderer — no data fetching, renders whatever Data you pass in.\n * Wrap with PuckApiProvider only if you use it alongside API hooks.\n */\nexport const PuckDataRenderer: React.FC<PuckDataRendererProps> = ({\n data,\n config,\n className,\n style,\n}) => {\n return (\n <div className={className} style={style}>\n <Render config={config as Config} data={data as Data} />\n </div>\n );\n};\n","import React, { useEffect, useState, type ReactElement } from 'react';\nimport { PuckApiProvider, usePuckApiContext } from '@commercetools-demo/puck-api';\nimport { defaultPuckConfig } from '@commercetools-demo/puck-editor';\nimport {\n getPublishedPuckPageApi,\n getPreviewPuckPageApi,\n queryPuckPageApi,\n getPublishedPuckContentApi,\n getPreviewPuckContentApi,\n queryPuckContentApi,\n} from '@commercetools-demo/puck-api';\nimport type { PuckConfig, PuckData } from '@commercetools-demo/puck-types';\nimport { PuckDataRenderer } from './PuckDataRenderer';\n\nconst DEFAULT_CONFIG: PuckConfig = {\n ...defaultPuckConfig,\n components: { ...defaultPuckConfig.components },\n};\n\n// ---------------------------------------------------------------------------\n// Inner component (needs PuckApiContext)\n// ---------------------------------------------------------------------------\n\ninterface PuckRendererInnerProps {\n type: 'page' | 'content';\n pageKey?: string;\n slug?: string;\n contentKey?: string;\n query?: string;\n mode: 'published' | 'preview';\n config: PuckConfig;\n loadingComponent?: ReactElement;\n errorComponent?: ReactElement;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst PuckRendererInner: React.FC<PuckRendererInnerProps> = ({\n type,\n pageKey,\n slug,\n contentKey,\n query,\n mode,\n config,\n loadingComponent,\n errorComponent,\n children,\n className,\n style,\n}) => {\n const { baseURL, projectKey, businessUnitKey } = usePuckApiContext();\n\n const [data, setData] = useState<PuckData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n if (type === 'content') {\n let puckData: PuckData | null = null;\n\n if (contentKey) {\n const value =\n mode === 'published'\n ? await getPublishedPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey)\n : await getPreviewPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey);\n puckData = value.data;\n } else if (query) {\n const value = await queryPuckContentApi(baseURL, projectKey, businessUnitKey, { query: `contentType = \"${query}\"` }, mode);\n puckData = value?.data ?? null;\n }\n\n if (!cancelled) {\n if (puckData) {\n setData(puckData);\n } else {\n setError('Content not found');\n }\n }\n } else {\n // type === 'page'\n let pageValue = null;\n\n if (pageKey) {\n pageValue =\n mode === 'published'\n ? await getPublishedPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey)\n : await getPreviewPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey);\n } else if (slug) {\n pageValue = await queryPuckPageApi(baseURL, projectKey, businessUnitKey, { query: `slug = \"${slug}\"` }, mode);\n }\n\n if (!cancelled) {\n if (pageValue) {\n setData(pageValue.puckData);\n } else {\n setError('Page not found');\n }\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message);\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void fetchData();\n return () => {\n cancelled = true;\n };\n }, [baseURL, projectKey, businessUnitKey, type, pageKey, slug, contentKey, query, mode]);\n\n if (loading) {\n return (\n loadingComponent ?? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px',\n color: '#6b7280',\n }}\n >\n Loading…\n </div>\n )\n );\n }\n\n if (error || !data) {\n return (\n <>\n {errorComponent ?? children ?? (\n <div\n style={{\n padding: '32px',\n color: '#dc2626',\n background: '#fef2f2',\n borderRadius: '8px',\n }}\n >\n {error ?? 'Failed to load'}\n </div>\n )}\n </>\n );\n }\n\n return <PuckDataRenderer data={data} config={config} className={className} style={style} />;\n};\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PuckRendererProps {\n /**\n * Whether to render a page or a content item. Defaults to 'page'.\n * - 'page': use pageKey or slug to fetch\n * - 'content': use contentKey or query (contentType) to fetch\n */\n type?: 'page' | 'content';\n\n /**\n * Service base URL. Can be omitted if a PuckApiProvider is already in the tree.\n */\n baseURL?: string;\n /** CommerceTools project key. Can be omitted if provider is in tree. */\n projectKey?: string;\n /** Business unit key. Can be omitted if provider is in tree. */\n businessUnitKey?: string;\n\n /** [type=page] Fetch by page key. */\n pageKey?: string;\n /** [type=page] OR fetch by slug (URL path). */\n slug?: string;\n\n /** [type=content] Fetch by content key. */\n contentKey?: string;\n /** [type=content] OR fetch by contentType query string. */\n query?: string;\n\n /** 'published' (default) or 'preview' (draft || published). */\n mode?: 'published' | 'preview';\n\n /**\n * Puck config — must match the config used in the editor. Defaults to defaultPuckConfig.\n */\n config?: PuckConfig;\n\n /** Custom loading indicator. */\n loadingComponent?: ReactElement;\n /** Custom error display. */\n errorComponent?: ReactElement;\n\n /**\n * Fallback content rendered when there is nothing to show — fetch error,\n * not-found, or no identifying param (pageKey/slug/contentKey/query) given.\n * Not used while loading. If `errorComponent` is provided it takes precedence\n * over `children`.\n */\n children?: React.ReactNode;\n\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const PuckRenderer: React.FC<PuckRendererProps> = ({\n type = 'page',\n baseURL,\n projectKey,\n businessUnitKey,\n pageKey,\n slug,\n contentKey,\n query,\n mode = 'published',\n config = DEFAULT_CONFIG,\n loadingComponent,\n errorComponent,\n children,\n className,\n style,\n}) => {\n const inner = (\n <PuckRendererInner\n type={type}\n pageKey={pageKey}\n slug={slug}\n contentKey={contentKey}\n query={query}\n mode={mode}\n config={config}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n className={className}\n style={style}\n >\n {children}\n </PuckRendererInner>\n );\n\n if (baseURL && projectKey && businessUnitKey) {\n return (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n >\n {inner}\n </PuckApiProvider>\n );\n }\n\n return inner;\n};\n"],"mappings":"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","names":["import_puck_api","import_jsx_runtime"]}
package/dist/index.mjs CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  getPreviewPuckContentApi,
23
23
  queryPuckContentApi
24
24
  } from "@commercetools-demo/puck-api";
25
- import { jsx as jsx2 } from "react/jsx-runtime";
25
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
26
26
  var DEFAULT_CONFIG = {
27
27
  ...defaultPuckConfig,
28
28
  components: { ...defaultPuckConfig.components }
@@ -37,6 +37,7 @@ var PuckRendererInner = ({
37
37
  config,
38
38
  loadingComponent,
39
39
  errorComponent,
40
+ children,
40
41
  className,
41
42
  style
42
43
  }) => {
@@ -108,7 +109,7 @@ var PuckRendererInner = ({
108
109
  );
109
110
  }
110
111
  if (error || !data) {
111
- return errorComponent ?? /* @__PURE__ */ jsx2(
112
+ return /* @__PURE__ */ jsx2(Fragment, { children: errorComponent ?? children ?? /* @__PURE__ */ jsx2(
112
113
  "div",
113
114
  {
114
115
  style: {
@@ -119,7 +120,7 @@ var PuckRendererInner = ({
119
120
  },
120
121
  children: error ?? "Failed to load"
121
122
  }
122
- );
123
+ ) });
123
124
  }
124
125
  return /* @__PURE__ */ jsx2(PuckDataRenderer, { data, config, className, style });
125
126
  };
@@ -136,6 +137,7 @@ var PuckRenderer = ({
136
137
  config = DEFAULT_CONFIG,
137
138
  loadingComponent,
138
139
  errorComponent,
140
+ children,
139
141
  className,
140
142
  style
141
143
  }) => {
@@ -152,7 +154,8 @@ var PuckRenderer = ({
152
154
  loadingComponent,
153
155
  errorComponent,
154
156
  className,
155
- style
157
+ style,
158
+ children
156
159
  }
157
160
  );
158
161
  if (baseURL && projectKey && businessUnitKey) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PuckDataRenderer.tsx","../src/PuckRenderer.tsx"],"sourcesContent":["import React from 'react';\nimport { Render } from '@measured/puck';\nimport type { Config, Data } from '@measured/puck';\nimport type { PuckData, PuckConfig } from '@commercetools-demo/puck-types';\n\nexport interface PuckDataRendererProps {\n /** The Puck Data to render (from the API or SSR props). */\n data: PuckData;\n /**\n * The Puck Config that defines available components and their render functions.\n * Must match the config used in the editor to ensure consistent output.\n */\n config: PuckConfig;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * SSR-friendly renderer — no data fetching, renders whatever Data you pass in.\n * Wrap with PuckApiProvider only if you use it alongside API hooks.\n */\nexport const PuckDataRenderer: React.FC<PuckDataRendererProps> = ({\n data,\n config,\n className,\n style,\n}) => {\n return (\n <div className={className} style={style}>\n <Render config={config as Config} data={data as Data} />\n </div>\n );\n};\n","import React, { useEffect, useState, type ReactElement } from 'react';\nimport { PuckApiProvider, usePuckApiContext } from '@commercetools-demo/puck-api';\nimport { defaultPuckConfig } from '@commercetools-demo/puck-editor';\nimport {\n getPublishedPuckPageApi,\n getPreviewPuckPageApi,\n queryPuckPageApi,\n getPublishedPuckContentApi,\n getPreviewPuckContentApi,\n queryPuckContentApi,\n} from '@commercetools-demo/puck-api';\nimport type { PuckConfig, PuckData } from '@commercetools-demo/puck-types';\nimport { PuckDataRenderer } from './PuckDataRenderer';\n\nconst DEFAULT_CONFIG: PuckConfig = {\n ...defaultPuckConfig,\n components: { ...defaultPuckConfig.components },\n};\n\n// ---------------------------------------------------------------------------\n// Inner component (needs PuckApiContext)\n// ---------------------------------------------------------------------------\n\ninterface PuckRendererInnerProps {\n type: 'page' | 'content';\n pageKey?: string;\n slug?: string;\n contentKey?: string;\n query?: string;\n mode: 'published' | 'preview';\n config: PuckConfig;\n loadingComponent?: ReactElement;\n errorComponent?: ReactElement;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst PuckRendererInner: React.FC<PuckRendererInnerProps> = ({\n type,\n pageKey,\n slug,\n contentKey,\n query,\n mode,\n config,\n loadingComponent,\n errorComponent,\n className,\n style,\n}) => {\n const { baseURL, projectKey, businessUnitKey } = usePuckApiContext();\n\n const [data, setData] = useState<PuckData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n if (type === 'content') {\n let puckData: PuckData | null = null;\n\n if (contentKey) {\n const value =\n mode === 'published'\n ? await getPublishedPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey)\n : await getPreviewPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey);\n puckData = value.data;\n } else if (query) {\n const value = await queryPuckContentApi(baseURL, projectKey, businessUnitKey, { query: `contentType = \"${query}\"` }, mode);\n puckData = value?.data ?? null;\n }\n\n if (!cancelled) {\n if (puckData) {\n setData(puckData);\n } else {\n setError('Content not found');\n }\n }\n } else {\n // type === 'page'\n let pageValue = null;\n\n if (pageKey) {\n pageValue =\n mode === 'published'\n ? await getPublishedPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey)\n : await getPreviewPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey);\n } else if (slug) {\n pageValue = await queryPuckPageApi(baseURL, projectKey, businessUnitKey, { query: `slug = \"${slug}\"` }, mode);\n }\n\n if (!cancelled) {\n if (pageValue) {\n setData(pageValue.puckData);\n } else {\n setError('Page not found');\n }\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message);\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void fetchData();\n return () => {\n cancelled = true;\n };\n }, [baseURL, projectKey, businessUnitKey, type, pageKey, slug, contentKey, query, mode]);\n\n if (loading) {\n return (\n loadingComponent ?? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px',\n color: '#6b7280',\n }}\n >\n Loading…\n </div>\n )\n );\n }\n\n if (error || !data) {\n return (\n errorComponent ?? (\n <div\n style={{\n padding: '32px',\n color: '#dc2626',\n background: '#fef2f2',\n borderRadius: '8px',\n }}\n >\n {error ?? 'Failed to load'}\n </div>\n )\n );\n }\n\n return <PuckDataRenderer data={data} config={config} className={className} style={style} />;\n};\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PuckRendererProps {\n /**\n * Whether to render a page or a content item. Defaults to 'page'.\n * - 'page': use pageKey or slug to fetch\n * - 'content': use contentKey or query (contentType) to fetch\n */\n type?: 'page' | 'content';\n\n /**\n * Service base URL. Can be omitted if a PuckApiProvider is already in the tree.\n */\n baseURL?: string;\n /** CommerceTools project key. Can be omitted if provider is in tree. */\n projectKey?: string;\n /** Business unit key. Can be omitted if provider is in tree. */\n businessUnitKey?: string;\n\n /** [type=page] Fetch by page key. */\n pageKey?: string;\n /** [type=page] OR fetch by slug (URL path). */\n slug?: string;\n\n /** [type=content] Fetch by content key. */\n contentKey?: string;\n /** [type=content] OR fetch by contentType query string. */\n query?: string;\n\n /** 'published' (default) or 'preview' (draft || published). */\n mode?: 'published' | 'preview';\n\n /**\n * Puck config — must match the config used in the editor. Defaults to defaultPuckConfig.\n */\n config?: PuckConfig;\n\n /** Custom loading indicator. */\n loadingComponent?: ReactElement;\n /** Custom error display. */\n errorComponent?: ReactElement;\n\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const PuckRenderer: React.FC<PuckRendererProps> = ({\n type = 'page',\n baseURL,\n projectKey,\n businessUnitKey,\n pageKey,\n slug,\n contentKey,\n query,\n mode = 'published',\n config = DEFAULT_CONFIG,\n loadingComponent,\n errorComponent,\n className,\n style,\n}) => {\n const inner = (\n <PuckRendererInner\n type={type}\n pageKey={pageKey}\n slug={slug}\n contentKey={contentKey}\n query={query}\n mode={mode}\n config={config}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n className={className}\n style={style}\n />\n );\n\n if (baseURL && projectKey && businessUnitKey) {\n return (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n >\n {inner}\n </PuckApiProvider>\n );\n }\n\n return inner;\n};\n"],"mappings":"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","names":["jsx"]}
1
+ {"version":3,"sources":["../src/PuckDataRenderer.tsx","../src/PuckRenderer.tsx"],"sourcesContent":["import React from 'react';\nimport { Render } from '@measured/puck';\nimport type { Config, Data } from '@measured/puck';\nimport type { PuckData, PuckConfig } from '@commercetools-demo/puck-types';\n\nexport interface PuckDataRendererProps {\n /** The Puck Data to render (from the API or SSR props). */\n data: PuckData;\n /**\n * The Puck Config that defines available components and their render functions.\n * Must match the config used in the editor to ensure consistent output.\n */\n config: PuckConfig;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * SSR-friendly renderer — no data fetching, renders whatever Data you pass in.\n * Wrap with PuckApiProvider only if you use it alongside API hooks.\n */\nexport const PuckDataRenderer: React.FC<PuckDataRendererProps> = ({\n data,\n config,\n className,\n style,\n}) => {\n return (\n <div className={className} style={style}>\n <Render config={config as Config} data={data as Data} />\n </div>\n );\n};\n","import React, { useEffect, useState, type ReactElement } from 'react';\nimport { PuckApiProvider, usePuckApiContext } from '@commercetools-demo/puck-api';\nimport { defaultPuckConfig } from '@commercetools-demo/puck-editor';\nimport {\n getPublishedPuckPageApi,\n getPreviewPuckPageApi,\n queryPuckPageApi,\n getPublishedPuckContentApi,\n getPreviewPuckContentApi,\n queryPuckContentApi,\n} from '@commercetools-demo/puck-api';\nimport type { PuckConfig, PuckData } from '@commercetools-demo/puck-types';\nimport { PuckDataRenderer } from './PuckDataRenderer';\n\nconst DEFAULT_CONFIG: PuckConfig = {\n ...defaultPuckConfig,\n components: { ...defaultPuckConfig.components },\n};\n\n// ---------------------------------------------------------------------------\n// Inner component (needs PuckApiContext)\n// ---------------------------------------------------------------------------\n\ninterface PuckRendererInnerProps {\n type: 'page' | 'content';\n pageKey?: string;\n slug?: string;\n contentKey?: string;\n query?: string;\n mode: 'published' | 'preview';\n config: PuckConfig;\n loadingComponent?: ReactElement;\n errorComponent?: ReactElement;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst PuckRendererInner: React.FC<PuckRendererInnerProps> = ({\n type,\n pageKey,\n slug,\n contentKey,\n query,\n mode,\n config,\n loadingComponent,\n errorComponent,\n children,\n className,\n style,\n}) => {\n const { baseURL, projectKey, businessUnitKey } = usePuckApiContext();\n\n const [data, setData] = useState<PuckData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n if (type === 'content') {\n let puckData: PuckData | null = null;\n\n if (contentKey) {\n const value =\n mode === 'published'\n ? await getPublishedPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey)\n : await getPreviewPuckContentApi(baseURL, projectKey, businessUnitKey, contentKey);\n puckData = value.data;\n } else if (query) {\n const value = await queryPuckContentApi(baseURL, projectKey, businessUnitKey, { query: `contentType = \"${query}\"` }, mode);\n puckData = value?.data ?? null;\n }\n\n if (!cancelled) {\n if (puckData) {\n setData(puckData);\n } else {\n setError('Content not found');\n }\n }\n } else {\n // type === 'page'\n let pageValue = null;\n\n if (pageKey) {\n pageValue =\n mode === 'published'\n ? await getPublishedPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey)\n : await getPreviewPuckPageApi(baseURL, projectKey, businessUnitKey, pageKey);\n } else if (slug) {\n pageValue = await queryPuckPageApi(baseURL, projectKey, businessUnitKey, { query: `slug = \"${slug}\"` }, mode);\n }\n\n if (!cancelled) {\n if (pageValue) {\n setData(pageValue.puckData);\n } else {\n setError('Page not found');\n }\n }\n }\n } catch (err) {\n if (!cancelled) setError((err as Error).message);\n } finally {\n if (!cancelled) setLoading(false);\n }\n };\n\n void fetchData();\n return () => {\n cancelled = true;\n };\n }, [baseURL, projectKey, businessUnitKey, type, pageKey, slug, contentKey, query, mode]);\n\n if (loading) {\n return (\n loadingComponent ?? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px',\n color: '#6b7280',\n }}\n >\n Loading…\n </div>\n )\n );\n }\n\n if (error || !data) {\n return (\n <>\n {errorComponent ?? children ?? (\n <div\n style={{\n padding: '32px',\n color: '#dc2626',\n background: '#fef2f2',\n borderRadius: '8px',\n }}\n >\n {error ?? 'Failed to load'}\n </div>\n )}\n </>\n );\n }\n\n return <PuckDataRenderer data={data} config={config} className={className} style={style} />;\n};\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PuckRendererProps {\n /**\n * Whether to render a page or a content item. Defaults to 'page'.\n * - 'page': use pageKey or slug to fetch\n * - 'content': use contentKey or query (contentType) to fetch\n */\n type?: 'page' | 'content';\n\n /**\n * Service base URL. Can be omitted if a PuckApiProvider is already in the tree.\n */\n baseURL?: string;\n /** CommerceTools project key. Can be omitted if provider is in tree. */\n projectKey?: string;\n /** Business unit key. Can be omitted if provider is in tree. */\n businessUnitKey?: string;\n\n /** [type=page] Fetch by page key. */\n pageKey?: string;\n /** [type=page] OR fetch by slug (URL path). */\n slug?: string;\n\n /** [type=content] Fetch by content key. */\n contentKey?: string;\n /** [type=content] OR fetch by contentType query string. */\n query?: string;\n\n /** 'published' (default) or 'preview' (draft || published). */\n mode?: 'published' | 'preview';\n\n /**\n * Puck config — must match the config used in the editor. Defaults to defaultPuckConfig.\n */\n config?: PuckConfig;\n\n /** Custom loading indicator. */\n loadingComponent?: ReactElement;\n /** Custom error display. */\n errorComponent?: ReactElement;\n\n /**\n * Fallback content rendered when there is nothing to show — fetch error,\n * not-found, or no identifying param (pageKey/slug/contentKey/query) given.\n * Not used while loading. If `errorComponent` is provided it takes precedence\n * over `children`.\n */\n children?: React.ReactNode;\n\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const PuckRenderer: React.FC<PuckRendererProps> = ({\n type = 'page',\n baseURL,\n projectKey,\n businessUnitKey,\n pageKey,\n slug,\n contentKey,\n query,\n mode = 'published',\n config = DEFAULT_CONFIG,\n loadingComponent,\n errorComponent,\n children,\n className,\n style,\n}) => {\n const inner = (\n <PuckRendererInner\n type={type}\n pageKey={pageKey}\n slug={slug}\n contentKey={contentKey}\n query={query}\n mode={mode}\n config={config}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n className={className}\n style={style}\n >\n {children}\n </PuckRendererInner>\n );\n\n if (baseURL && projectKey && businessUnitKey) {\n return (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n >\n {inner}\n </PuckApiProvider>\n );\n }\n\n return inner;\n};\n"],"mappings":";AACA,SAAS,cAAc;AA4BjB;AARC,IAAM,mBAAoD,CAAC;AAAA,EAChE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,SACE,oBAAC,SAAI,WAAsB,OACzB,8BAAC,UAAO,QAA0B,MAAoB,GACxD;AAEJ;;;AChCA,SAAgB,WAAW,gBAAmC;AAC9D,SAAS,iBAAiB,yBAAyB;AACnD,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAkHC,SAiBF,UAjBE,OAAAA,YAAA;AA9GR,IAAM,iBAA6B;AAAA,EACjC,GAAG;AAAA,EACH,YAAY,EAAE,GAAG,kBAAkB,WAAW;AAChD;AAqBA,IAAM,oBAAsD,CAAC;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,SAAS,YAAY,gBAAgB,IAAI,kBAAkB;AAEnE,QAAM,CAAC,MAAM,OAAO,IAAI,SAA0B,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,YAAU,MAAM;AACd,QAAI,YAAY;AAEhB,UAAM,YAAY,YAAY;AAC5B,iBAAW,IAAI;AACf,eAAS,IAAI;AAEb,UAAI;AACF,YAAI,SAAS,WAAW;AACtB,cAAI,WAA4B;AAEhC,cAAI,YAAY;AACd,kBAAM,QACJ,SAAS,cACL,MAAM,2BAA2B,SAAS,YAAY,iBAAiB,UAAU,IACjF,MAAM,yBAAyB,SAAS,YAAY,iBAAiB,UAAU;AACrF,uBAAW,MAAM;AAAA,UACnB,WAAW,OAAO;AAChB,kBAAM,QAAQ,MAAM,oBAAoB,SAAS,YAAY,iBAAiB,EAAE,OAAO,kBAAkB,KAAK,IAAI,GAAG,IAAI;AACzH,uBAAW,OAAO,QAAQ;AAAA,UAC5B;AAEA,cAAI,CAAC,WAAW;AACd,gBAAI,UAAU;AACZ,sBAAQ,QAAQ;AAAA,YAClB,OAAO;AACL,uBAAS,mBAAmB;AAAA,YAC9B;AAAA,UACF;AAAA,QACF,OAAO;AAEL,cAAI,YAAY;AAEhB,cAAI,SAAS;AACX,wBACE,SAAS,cACL,MAAM,wBAAwB,SAAS,YAAY,iBAAiB,OAAO,IAC3E,MAAM,sBAAsB,SAAS,YAAY,iBAAiB,OAAO;AAAA,UACjF,WAAW,MAAM;AACf,wBAAY,MAAM,iBAAiB,SAAS,YAAY,iBAAiB,EAAE,OAAO,WAAW,IAAI,IAAI,GAAG,IAAI;AAAA,UAC9G;AAEA,cAAI,CAAC,WAAW;AACd,gBAAI,WAAW;AACb,sBAAQ,UAAU,QAAQ;AAAA,YAC5B,OAAO;AACL,uBAAS,gBAAgB;AAAA,YAC3B;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,CAAC,UAAW,UAAU,IAAc,OAAO;AAAA,MACjD,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AAEA,SAAK,UAAU;AACf,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,SAAS,YAAY,iBAAiB,MAAM,SAAS,MAAM,YAAY,OAAO,IAAI,CAAC;AAEvF,MAAI,SAAS;AACX,WACE,oBACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,QACD;AAAA;AAAA,IAED;AAAA,EAGN;AAEA,MAAI,SAAS,CAAC,MAAM;AAClB,WACE,gBAAAA,KAAA,YACG,4BAAkB,YACjB,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,cAAc;AAAA,QAChB;AAAA,QAEC,mBAAS;AAAA;AAAA,IACZ,GAEJ;AAAA,EAEJ;AAEA,SAAO,gBAAAA,KAAC,oBAAiB,MAAY,QAAgB,WAAsB,OAAc;AAC3F;AA0DO,IAAM,eAA4C,CAAC;AAAA,EACxD,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,QACJ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAGF,MAAI,WAAW,cAAc,iBAAiB;AAC5C,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SAAO;AACT;","names":["jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-demo/puck-renderer",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Lightweight Puck page renderer for storefronts",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",