@contentful/experiences-react 0.7.1 → 0.7.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/CHANGELOG.md +12 -0
- package/README.md +12 -7
- package/dist/client-renderer.js +2 -0
- package/dist/client-renderer.js.map +1 -1
- package/dist/nodes-renderer.d.ts +6 -2
- package/dist/nodes-renderer.js +25 -11
- package/dist/nodes-renderer.js.map +1 -1
- package/dist/server-renderer.js +2 -0
- package/dist/server-renderer.js.map +1 -1
- package/dist/types.d.ts +9 -8
- package/dist/types.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 0.7.2 (2026-08-07)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- server-side design pre-resolution against a fallback viewport [AIS-386] ([#119](https://github.com/contentful/experiences/pull/119))
|
|
6
|
+
|
|
7
|
+
### 🧱 Updated Dependencies
|
|
8
|
+
|
|
9
|
+
- Updated client to 0.3.1
|
|
10
|
+
- Updated design to 0.7.1
|
|
11
|
+
- Updated core to 0.7.1
|
|
12
|
+
|
|
1
13
|
## 0.7.1 (2026-08-07)
|
|
2
14
|
|
|
3
15
|
### 🚀 Features
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ useActiveViewport; // Hook used inside ClientExperienceRenderer (you'll rarely n
|
|
|
50
50
|
### Styling + runtime context (hooks)
|
|
51
51
|
|
|
52
52
|
```ts
|
|
53
|
-
useDesignValues<T>(); //
|
|
53
|
+
useDesignValues<T>(); // Optional hook: the same resolved design record that auto-fills props
|
|
54
54
|
toCss(design, options?); // Turns a design record into CSSProperties, keeping only real CSS keys
|
|
55
55
|
useExperience(); // RenderContext: debug, metadata, viewports, activeViewport
|
|
56
56
|
useContentfulComponent(); // Raw payload for the enclosing node (or null)
|
|
@@ -58,7 +58,7 @@ useContentfulExperienceTemplate(); // Same, for the page-level Experience Templa
|
|
|
58
58
|
type ToCssOptions;
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Resolved design values (viewport-cascaded + token-resolved server-side) are **auto-filled onto your component's props** by key, alongside content. Styling straight from props is the recommended path; `useDesignValues()` exposes the same record for cases props don't cover. Token resolution is configured with `resolveToken` on your `Config` (`type ResolveToken`).
|
|
62
62
|
|
|
63
63
|
### Re-exported types and utilities
|
|
64
64
|
|
|
@@ -84,14 +84,19 @@ isCssProperty, toCssKey, CSS_PROPERTIES
|
|
|
84
84
|
## Quick reference
|
|
85
85
|
|
|
86
86
|
```tsx
|
|
87
|
-
// components/Button.tsx:
|
|
87
|
+
// components/Button.tsx: content + resolved design both arrive as props
|
|
88
88
|
'use client';
|
|
89
|
-
import { toCss, useDesignValues } from '@contentful/experiences-react';
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
interface ButtonProps {
|
|
91
|
+
label?: string;
|
|
92
|
+
url?: string;
|
|
93
|
+
backgroundColor?: string; // resolved design, auto-filled
|
|
94
|
+
color?: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function Button({ label, url, backgroundColor, color }: ButtonProps) {
|
|
93
98
|
return (
|
|
94
|
-
<a href={url} style={
|
|
99
|
+
<a href={url} style={{ background: backgroundColor, color }}>
|
|
95
100
|
{label}
|
|
96
101
|
</a>
|
|
97
102
|
);
|
package/dist/client-renderer.js
CHANGED
|
@@ -45,6 +45,7 @@ function ClientExperienceRenderer({
|
|
|
45
45
|
config,
|
|
46
46
|
viewports: experience.viewports,
|
|
47
47
|
activeViewportIndex,
|
|
48
|
+
fallbackViewportIndex: experience.fallbackViewportIndex,
|
|
48
49
|
children: /* @__PURE__ */ jsx(
|
|
49
50
|
NodesRenderer,
|
|
50
51
|
{
|
|
@@ -52,6 +53,7 @@ function ClientExperienceRenderer({
|
|
|
52
53
|
config,
|
|
53
54
|
viewports: experience.viewports,
|
|
54
55
|
activeViewportIndex,
|
|
56
|
+
fallbackViewportIndex: experience.fallbackViewportIndex,
|
|
55
57
|
renderUnknown
|
|
56
58
|
}
|
|
57
59
|
)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client-renderer.tsx"],"sourcesContent":["/*\n * Client Experience renderer. First paint matches the server renderer; after\n * hydration `useActiveViewport` takes over via `matchMedia`. Server-safe: the\n * hook returns the seeded index and registers no listeners when there's no\n * window, so SSR output matches `<ServerExperienceRenderer>`.\n */\n\n'use client';\n\nimport type { ReactNode } from 'react';\n\nimport type {\n ExperienceContext,\n PortableRenderPlan,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\nimport { DebugExperience } from './debug-experience';\nimport { ExperienceProvider } from './context';\nimport { MissingComponent } from './missing-component';\nimport { NodesRenderer, WrapWithExperienceTemplate, type RenderUnknown } from './nodes-renderer';\nimport type { Config, RenderContext } from './types';\nimport { useActiveViewport } from './use-active-viewport';\n\nconst DEFAULT_CONTEXT: ExperienceContext = {\n debug: false,\n metadata: {},\n viewports: [],\n};\n\nconst FALLBACK_VIEWPORT: ViewportDef = {\n id: '_',\n query: '*',\n displayName: 'Default',\n previewSize: '100%',\n};\n\nexport interface ClientExperienceRendererProps {\n experience: PortableRenderPlan | null | undefined;\n config: Config;\n /** Initial viewport seed; should match what the server-rendered output used. */\n initialViewportId?: string;\n /**\n * Arbitrary per-render metadata, readable by descendants via\n * `useExperience()` and by resolvers via `ctx.experience.metadata`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: renders the visible missing-component box,\n * turns the default `renderUnknown` fallback into the debug component, and\n * auto-mounts `<DebugExperience>` after the tree.\n */\n debug?: boolean;\n renderUnknown?: RenderUnknown;\n}\n\nexport function ClientExperienceRenderer({\n experience,\n config,\n initialViewportId,\n metadata,\n debug = false,\n renderUnknown = MissingComponent,\n}: ClientExperienceRendererProps): ReactNode {\n if (!experience) return null;\n const { activeViewportIndex } = useActiveViewport(experience.viewports, initialViewportId);\n // Copy so the context shares no object identity with the plan arrays — see\n // the note in `server-renderer.tsx`.\n const contextViewports = experience.viewports.map((v) => ({ ...v }));\n const activeViewport = { ...(experience.viewports[activeViewportIndex] ?? FALLBACK_VIEWPORT) };\n\n const renderContext: RenderContext = {\n ...DEFAULT_CONTEXT,\n debug,\n metadata: { ...DEFAULT_CONTEXT.metadata, ...(metadata ?? {}) },\n viewports: contextViewports,\n activeViewport,\n activeViewportIndex,\n };\n\n return (\n <ExperienceProvider value={renderContext}>\n {debug ? <DebugExperience experience={experience} /> : null}\n <WrapWithExperienceTemplate\n experienceTemplate={experience.experienceTemplate}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n >\n <NodesRenderer\n nodes={experience.nodes}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n renderUnknown={renderUnknown}\n />\n </WrapWithExperienceTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":";AAiFI,SACW,KADX;AAhEJ,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,kCAAsD;AAE9E,SAAS,yBAAyB;AAElC,MAAM,kBAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU,CAAC;AAAA,EACX,WAAW,CAAC;AACd;AAEA,MAAM,oBAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AAAA,EACb,aAAa;AACf;AAqBO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,gBAAgB;AAClB,GAA6C;AAC3C,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,EAAE,oBAAoB,IAAI,kBAAkB,WAAW,WAAW,iBAAiB;AAGzF,QAAM,mBAAmB,WAAW,UAAU,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACnE,QAAM,iBAAiB,EAAE,GAAI,WAAW,UAAU,mBAAmB,KAAK,kBAAmB;AAE7F,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH;AAAA,IACA,UAAU,EAAE,GAAG,gBAAgB,UAAU,GAAI,YAAY,CAAC,EAAG;AAAA,IAC7D,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,sBAAmB,OAAO,eACxB;AAAA,YAAQ,oBAAC,mBAAgB,YAAwB,IAAK;AAAA,IACvD;AAAA,MAAC;AAAA;AAAA,QACC,oBAAoB,WAAW;AAAA,QAC/B;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/client-renderer.tsx"],"sourcesContent":["/*\n * Client Experience renderer. First paint matches the server renderer; after\n * hydration `useActiveViewport` takes over via `matchMedia`. Server-safe: the\n * hook returns the seeded index and registers no listeners when there's no\n * window, so SSR output matches `<ServerExperienceRenderer>`.\n */\n\n'use client';\n\nimport type { ReactNode } from 'react';\n\nimport type {\n ExperienceContext,\n PortableRenderPlan,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\nimport { DebugExperience } from './debug-experience';\nimport { ExperienceProvider } from './context';\nimport { MissingComponent } from './missing-component';\nimport { NodesRenderer, WrapWithExperienceTemplate, type RenderUnknown } from './nodes-renderer';\nimport type { Config, RenderContext } from './types';\nimport { useActiveViewport } from './use-active-viewport';\n\nconst DEFAULT_CONTEXT: ExperienceContext = {\n debug: false,\n metadata: {},\n viewports: [],\n};\n\nconst FALLBACK_VIEWPORT: ViewportDef = {\n id: '_',\n query: '*',\n displayName: 'Default',\n previewSize: '100%',\n};\n\nexport interface ClientExperienceRendererProps {\n experience: PortableRenderPlan | null | undefined;\n config: Config;\n /** Initial viewport seed; should match what the server-rendered output used. */\n initialViewportId?: string;\n /**\n * Arbitrary per-render metadata, readable by descendants via\n * `useExperience()` and by resolvers via `ctx.experience.metadata`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: renders the visible missing-component box,\n * turns the default `renderUnknown` fallback into the debug component, and\n * auto-mounts `<DebugExperience>` after the tree.\n */\n debug?: boolean;\n renderUnknown?: RenderUnknown;\n}\n\nexport function ClientExperienceRenderer({\n experience,\n config,\n initialViewportId,\n metadata,\n debug = false,\n renderUnknown = MissingComponent,\n}: ClientExperienceRendererProps): ReactNode {\n if (!experience) return null;\n const { activeViewportIndex } = useActiveViewport(experience.viewports, initialViewportId);\n // Copy so the context shares no object identity with the plan arrays — see\n // the note in `server-renderer.tsx`.\n const contextViewports = experience.viewports.map((v) => ({ ...v }));\n const activeViewport = { ...(experience.viewports[activeViewportIndex] ?? FALLBACK_VIEWPORT) };\n\n const renderContext: RenderContext = {\n ...DEFAULT_CONTEXT,\n debug,\n metadata: { ...DEFAULT_CONTEXT.metadata, ...(metadata ?? {}) },\n viewports: contextViewports,\n activeViewport,\n activeViewportIndex,\n };\n\n return (\n <ExperienceProvider value={renderContext}>\n {debug ? <DebugExperience experience={experience} /> : null}\n <WrapWithExperienceTemplate\n experienceTemplate={experience.experienceTemplate}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={experience.fallbackViewportIndex}\n >\n <NodesRenderer\n nodes={experience.nodes}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={experience.fallbackViewportIndex}\n renderUnknown={renderUnknown}\n />\n </WrapWithExperienceTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":";AAiFI,SACW,KADX;AAhEJ,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,kCAAsD;AAE9E,SAAS,yBAAyB;AAElC,MAAM,kBAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU,CAAC;AAAA,EACX,WAAW,CAAC;AACd;AAEA,MAAM,oBAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AAAA,EACb,aAAa;AACf;AAqBO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,gBAAgB;AAClB,GAA6C;AAC3C,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,EAAE,oBAAoB,IAAI,kBAAkB,WAAW,WAAW,iBAAiB;AAGzF,QAAM,mBAAmB,WAAW,UAAU,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACnE,QAAM,iBAAiB,EAAE,GAAI,WAAW,UAAU,mBAAmB,KAAK,kBAAmB;AAE7F,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH;AAAA,IACA,UAAU,EAAE,GAAG,gBAAgB,UAAU,GAAI,YAAY,CAAC,EAAG;AAAA,IAC7D,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,sBAAmB,OAAO,eACxB;AAAA,YAAQ,oBAAC,mBAAgB,YAAwB,IAAK;AAAA,IACvD;AAAA,MAAC;AAAA;AAAA,QACC,oBAAoB,WAAW;AAAA,QAC/B;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,QACA,uBAAuB,WAAW;AAAA,QAElC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA,uBAAuB,WAAW;AAAA,YAClC;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/nodes-renderer.d.ts
CHANGED
|
@@ -9,14 +9,18 @@ interface NodesRendererProps {
|
|
|
9
9
|
config: Config;
|
|
10
10
|
viewports: ViewportDef[];
|
|
11
11
|
activeViewportIndex: number;
|
|
12
|
+
/** Viewport index the server pre-resolved design against. */
|
|
13
|
+
fallbackViewportIndex: number;
|
|
12
14
|
renderUnknown: RenderUnknown;
|
|
13
15
|
}
|
|
14
|
-
declare function NodesRenderer({ nodes, config, viewports, activeViewportIndex, renderUnknown, }: NodesRendererProps): ReactNode;
|
|
16
|
+
declare function NodesRenderer({ nodes, config, viewports, activeViewportIndex, fallbackViewportIndex, renderUnknown, }: NodesRendererProps): ReactNode;
|
|
15
17
|
interface WrapWithExperienceTemplateProps {
|
|
16
18
|
experienceTemplate: PortableExperienceTemplate | undefined;
|
|
17
19
|
config: Config;
|
|
18
20
|
viewports: ViewportDef[];
|
|
19
21
|
activeViewportIndex: number;
|
|
22
|
+
/** Viewport index the server pre-resolved design against. */
|
|
23
|
+
fallbackViewportIndex: number;
|
|
20
24
|
children: ReactNode;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
@@ -24,6 +28,6 @@ interface WrapWithExperienceTemplateProps {
|
|
|
24
28
|
* template is referenced but unregistered, warns once and renders children
|
|
25
29
|
* unwrapped.
|
|
26
30
|
*/
|
|
27
|
-
declare function WrapWithExperienceTemplate({ experienceTemplate, config, viewports, activeViewportIndex, children, }: WrapWithExperienceTemplateProps): ReactNode;
|
|
31
|
+
declare function WrapWithExperienceTemplate({ experienceTemplate, config, viewports, activeViewportIndex, fallbackViewportIndex, children, }: WrapWithExperienceTemplateProps): ReactNode;
|
|
28
32
|
|
|
29
33
|
export { NodesRenderer, type NodesRendererProps, type RenderUnknown, WrapWithExperienceTemplate, type WrapWithExperienceTemplateProps };
|
package/dist/nodes-renderer.js
CHANGED
|
@@ -10,11 +10,19 @@ import {
|
|
|
10
10
|
normalizeComponentRegistration,
|
|
11
11
|
normalizeExperienceTemplateRegistration
|
|
12
12
|
} from "./types";
|
|
13
|
+
function selectResolvedDesign(props, viewports, activeViewportIndex, fallbackViewportIndex, resolveToken) {
|
|
14
|
+
if (activeViewportIndex === fallbackViewportIndex) {
|
|
15
|
+
return { props: props.design, unresolved: [] };
|
|
16
|
+
}
|
|
17
|
+
const resolvedDesign = resolveDesignProperties(props.designRaw, viewports, activeViewportIndex);
|
|
18
|
+
return applyTokenResolver(resolvedDesign, resolveToken);
|
|
19
|
+
}
|
|
13
20
|
function NodesRenderer({
|
|
14
21
|
nodes,
|
|
15
22
|
config,
|
|
16
23
|
viewports,
|
|
17
24
|
activeViewportIndex,
|
|
25
|
+
fallbackViewportIndex,
|
|
18
26
|
renderUnknown
|
|
19
27
|
}) {
|
|
20
28
|
if (!nodes.length) return null;
|
|
@@ -25,6 +33,7 @@ function NodesRenderer({
|
|
|
25
33
|
config,
|
|
26
34
|
viewports,
|
|
27
35
|
activeViewportIndex,
|
|
36
|
+
fallbackViewportIndex,
|
|
28
37
|
renderUnknown
|
|
29
38
|
},
|
|
30
39
|
node.nodeId ?? index
|
|
@@ -35,6 +44,7 @@ function NodeRenderer({
|
|
|
35
44
|
config,
|
|
36
45
|
viewports,
|
|
37
46
|
activeViewportIndex,
|
|
47
|
+
fallbackViewportIndex,
|
|
38
48
|
renderUnknown
|
|
39
49
|
}) {
|
|
40
50
|
const { componentId } = node.registration;
|
|
@@ -52,14 +62,17 @@ function NodeRenderer({
|
|
|
52
62
|
config,
|
|
53
63
|
viewports,
|
|
54
64
|
activeViewportIndex,
|
|
65
|
+
fallbackViewportIndex,
|
|
55
66
|
renderUnknown
|
|
56
67
|
},
|
|
57
68
|
child.nodeId ?? index
|
|
58
69
|
));
|
|
59
70
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
const { props: tokenResolvedDesign, unresolved } = selectResolvedDesign(
|
|
72
|
+
node.props,
|
|
73
|
+
viewports,
|
|
74
|
+
activeViewportIndex,
|
|
75
|
+
fallbackViewportIndex,
|
|
63
76
|
config.resolveToken
|
|
64
77
|
);
|
|
65
78
|
if (unresolved.length && typeof console !== "undefined") {
|
|
@@ -71,11 +84,12 @@ function NodeRenderer({
|
|
|
71
84
|
componentId,
|
|
72
85
|
nodeId: node.nodeId,
|
|
73
86
|
content: node.props.content,
|
|
74
|
-
design: node.props.
|
|
87
|
+
design: node.props.designRaw,
|
|
75
88
|
resolved: node.props.resolved
|
|
76
89
|
};
|
|
77
90
|
const composed = {
|
|
78
91
|
...componentConfig.defaults,
|
|
92
|
+
...tokenResolvedDesign,
|
|
79
93
|
...node.props.content,
|
|
80
94
|
...node.props.resolved,
|
|
81
95
|
...slotProps
|
|
@@ -87,6 +101,7 @@ function WrapWithExperienceTemplate({
|
|
|
87
101
|
config,
|
|
88
102
|
viewports,
|
|
89
103
|
activeViewportIndex,
|
|
104
|
+
fallbackViewportIndex,
|
|
90
105
|
children
|
|
91
106
|
}) {
|
|
92
107
|
if (!experienceTemplate) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
@@ -100,13 +115,11 @@ function WrapWithExperienceTemplate({
|
|
|
100
115
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
101
116
|
}
|
|
102
117
|
const experienceTemplateConfig = normalizeExperienceTemplateRegistration(entry);
|
|
103
|
-
const
|
|
104
|
-
experienceTemplate.props
|
|
118
|
+
const { props: tokenResolvedDesign, unresolved } = selectResolvedDesign(
|
|
119
|
+
experienceTemplate.props,
|
|
105
120
|
viewports,
|
|
106
|
-
activeViewportIndex
|
|
107
|
-
|
|
108
|
-
const { props: tokenResolvedDesign, unresolved } = applyTokenResolver(
|
|
109
|
-
resolvedDesign,
|
|
121
|
+
activeViewportIndex,
|
|
122
|
+
fallbackViewportIndex,
|
|
110
123
|
config.resolveToken
|
|
111
124
|
);
|
|
112
125
|
if (unresolved.length && typeof console !== "undefined") {
|
|
@@ -117,11 +130,12 @@ function WrapWithExperienceTemplate({
|
|
|
117
130
|
const contentful = {
|
|
118
131
|
experienceTemplateId: experienceTemplate.experienceTemplateId,
|
|
119
132
|
content: experienceTemplate.props.content,
|
|
120
|
-
design: experienceTemplate.props.
|
|
133
|
+
design: experienceTemplate.props.designRaw,
|
|
121
134
|
resolved: experienceTemplate.props.resolved
|
|
122
135
|
};
|
|
123
136
|
const composed = {
|
|
124
137
|
...experienceTemplateConfig.defaults,
|
|
138
|
+
...tokenResolvedDesign,
|
|
125
139
|
...experienceTemplate.props.content,
|
|
126
140
|
...experienceTemplate.props.resolved,
|
|
127
141
|
children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nodes-renderer.tsx"],"sourcesContent":["/*\n * Recursive renderer over PortableRenderNodes. Customer components receive the\n * merged prop bag (defaults + content + resolveData + slots); design values\n * are read via `useDesignValues()`, not injected as props.\n */\n\nimport { Fragment, createElement, type ReactNode } from 'react';\n\nimport type {\n PortableExperienceTemplate,\n PortableRenderNode,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\nimport { applyTokenResolver, resolveDesignProperties } from '@contentful/experiences-design';\n\nimport {\n ContentfulComponentProvider,\n ContentfulExperienceTemplateProvider,\n ResolvedDesignProvider,\n} from './context';\nimport type { MissingComponentProps } from './missing-component';\nimport {\n normalizeComponentRegistration,\n normalizeExperienceTemplateRegistration,\n type ContentfulComponent,\n type ContentfulExperienceTemplate,\n type Config,\n} from './types';\n\nexport type RenderUnknown = (props: MissingComponentProps) => ReactNode;\n\n// Internal renderers take `viewports` + `activeViewportIndex`, not the whole\n// RenderContext object — the context is published once via ExperienceProvider,\n// and re-threading it as an element prop makes React's RSC serializer back-patch\n// a shared reference into frozen props (\"Cannot assign to read only property\").\nexport interface NodesRendererProps {\n nodes: PortableRenderNode[];\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n renderUnknown: RenderUnknown;\n}\n\nexport function NodesRenderer({\n nodes,\n config,\n viewports,\n activeViewportIndex,\n renderUnknown,\n}: NodesRendererProps): ReactNode {\n if (!nodes.length) return null;\n return (\n <Fragment>\n {nodes.map((node, index) => (\n <NodeRenderer\n key={node.nodeId ?? index}\n node={node}\n config={config}\n viewports={viewports}\n activeViewportIndex={activeViewportIndex}\n renderUnknown={renderUnknown}\n />\n ))}\n </Fragment>\n );\n}\n\ninterface NodeRendererProps {\n node: PortableRenderNode;\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n renderUnknown: RenderUnknown;\n}\n\nfunction NodeRenderer({\n node,\n config,\n viewports,\n activeViewportIndex,\n renderUnknown,\n}: NodeRendererProps): ReactNode {\n const { componentId } = node.registration;\n const entry = config.components[componentId];\n if (!entry) {\n return createElement(renderUnknown, { componentId, nodeId: node.nodeId });\n }\n const componentConfig = normalizeComponentRegistration(entry);\n\n // Pre-render each slot's children as an *array* of ReactNodes (one keyed\n // element per child), not a single wrapping node. A component can drop the\n // array straight into JSX for the common \"just render them\" case (React\n // renders keyed arrays), or map/filter/wrap the children individually.\n const slotProps: Record<string, ReactNode[]> = {};\n for (const [slotName, children] of Object.entries(node.slots)) {\n slotProps[slotName] = children.map((child, index) => (\n <NodeRenderer\n key={child.nodeId ?? index}\n node={child}\n config={config}\n viewports={viewports}\n activeViewportIndex={activeViewportIndex}\n renderUnknown={renderUnknown}\n />\n ));\n }\n\n // Cascade design to the active viewport, then resolve DesignToken envelopes.\n // Published on context for useDesignValues() — never spread onto props.\n const resolvedDesign = resolveDesignProperties(node.props.design, viewports, activeViewportIndex);\n const { props: tokenResolvedDesign, unresolved } = applyTokenResolver(\n resolvedDesign,\n config.resolveToken\n );\n if (unresolved.length && typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on \"${componentId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulComponent = {\n componentId,\n nodeId: node.nodeId,\n content: node.props.content,\n design: node.props.design,\n resolved: node.props.resolved,\n };\n\n // Merge precedence (last wins): defaults < content < resolveData < slots.\n const composed = {\n ...componentConfig.defaults,\n ...node.props.content,\n ...node.props.resolved,\n ...slotProps,\n };\n\n return (\n <ContentfulComponentProvider value={contentful}>\n <ResolvedDesignProvider value={tokenResolvedDesign}>\n {createElement(componentConfig.component, composed)}\n </ResolvedDesignProvider>\n </ContentfulComponentProvider>\n );\n}\n\nexport interface WrapWithExperienceTemplateProps {\n experienceTemplate: PortableExperienceTemplate | undefined;\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n children: ReactNode;\n}\n\n/**\n * Wraps the rendered nodes with the page-level Experience Template. If the\n * template is referenced but unregistered, warns once and renders children\n * unwrapped.\n */\nexport function WrapWithExperienceTemplate({\n experienceTemplate,\n config,\n viewports,\n activeViewportIndex,\n children,\n}: WrapWithExperienceTemplateProps): ReactNode {\n if (!experienceTemplate) return <Fragment>{children}</Fragment>;\n const entry = config.experienceTemplates?.[experienceTemplate.experienceTemplateId];\n if (!entry) {\n if (typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] No experience template registered for id \"${experienceTemplate.experienceTemplateId}\". Rendering nodes without the experience template wrapper.`\n );\n }\n return <Fragment>{children}</Fragment>;\n }\n const experienceTemplateConfig = normalizeExperienceTemplateRegistration(entry);\n\n const resolvedDesign = resolveDesignProperties(\n experienceTemplate.props.design,\n viewports,\n activeViewportIndex\n );\n\n const { props: tokenResolvedDesign, unresolved } = applyTokenResolver(\n resolvedDesign,\n config.resolveToken\n );\n if (unresolved.length && typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on experience template \"${experienceTemplate.experienceTemplateId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulExperienceTemplate = {\n experienceTemplateId: experienceTemplate.experienceTemplateId,\n content: experienceTemplate.props.content,\n design: experienceTemplate.props.design,\n resolved: experienceTemplate.props.resolved,\n };\n\n const composed = {\n ...experienceTemplateConfig.defaults,\n ...experienceTemplate.props.content,\n ...experienceTemplate.props.resolved,\n children,\n };\n\n return (\n <ContentfulExperienceTemplateProvider value={contentful}>\n <ResolvedDesignProvider value={tokenResolvedDesign}>\n {createElement(experienceTemplateConfig.component, composed)}\n </ResolvedDesignProvider>\n </ContentfulExperienceTemplateProvider>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/nodes-renderer.tsx"],"sourcesContent":["/*\n * Recursive renderer over PortableRenderNodes. Resolved design values auto-fill\n * matching props (below content/resolveData) and are also available via\n * `useDesignValues()`.\n */\n\nimport { Fragment, createElement, type ReactNode } from 'react';\n\nimport type {\n DesignPropValue,\n PortableExperienceTemplate,\n PortableRenderNode,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\nimport { applyTokenResolver, resolveDesignProperties } from '@contentful/experiences-design';\n\nimport {\n ContentfulComponentProvider,\n ContentfulExperienceTemplateProvider,\n ResolvedDesignProvider,\n} from './context';\nimport type { MissingComponentProps } from './missing-component';\nimport {\n normalizeComponentRegistration,\n normalizeExperienceTemplateRegistration,\n type ContentfulComponent,\n type ContentfulExperienceTemplate,\n type Config,\n} from './types';\n\nexport type RenderUnknown = (props: MissingComponentProps) => ReactNode;\n\n// Use the server-resolved `props.design` when the active viewport matches the\n// fallback; otherwise recompute the cascade from raw `props.designRaw`.\nfunction selectResolvedDesign(\n props: { design: Record<string, unknown>; designRaw: Record<string, DesignPropValue> },\n viewports: ViewportDef[],\n activeViewportIndex: number,\n fallbackViewportIndex: number,\n resolveToken: Config['resolveToken']\n): { props: Record<string, unknown>; unresolved: string[] } {\n if (activeViewportIndex === fallbackViewportIndex) {\n return { props: props.design, unresolved: [] };\n }\n const resolvedDesign = resolveDesignProperties(props.designRaw, viewports, activeViewportIndex);\n return applyTokenResolver(resolvedDesign, resolveToken);\n}\n\n// Internal renderers take `viewports` + `activeViewportIndex`, not the whole\n// RenderContext object — the context is published once via ExperienceProvider,\n// and re-threading it as an element prop makes React's RSC serializer back-patch\n// a shared reference into frozen props (\"Cannot assign to read only property\").\nexport interface NodesRendererProps {\n nodes: PortableRenderNode[];\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n /** Viewport index the server pre-resolved design against. */\n fallbackViewportIndex: number;\n renderUnknown: RenderUnknown;\n}\n\nexport function NodesRenderer({\n nodes,\n config,\n viewports,\n activeViewportIndex,\n fallbackViewportIndex,\n renderUnknown,\n}: NodesRendererProps): ReactNode {\n if (!nodes.length) return null;\n return (\n <Fragment>\n {nodes.map((node, index) => (\n <NodeRenderer\n key={node.nodeId ?? index}\n node={node}\n config={config}\n viewports={viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={fallbackViewportIndex}\n renderUnknown={renderUnknown}\n />\n ))}\n </Fragment>\n );\n}\n\ninterface NodeRendererProps {\n node: PortableRenderNode;\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n fallbackViewportIndex: number;\n renderUnknown: RenderUnknown;\n}\n\nfunction NodeRenderer({\n node,\n config,\n viewports,\n activeViewportIndex,\n fallbackViewportIndex,\n renderUnknown,\n}: NodeRendererProps): ReactNode {\n const { componentId } = node.registration;\n const entry = config.components[componentId];\n if (!entry) {\n return createElement(renderUnknown, { componentId, nodeId: node.nodeId });\n }\n const componentConfig = normalizeComponentRegistration(entry);\n\n // Pre-render each slot's children as an *array* of ReactNodes (one keyed\n // element per child), not a single wrapping node. A component can drop the\n // array straight into JSX for the common \"just render them\" case (React\n // renders keyed arrays), or map/filter/wrap the children individually.\n const slotProps: Record<string, ReactNode[]> = {};\n for (const [slotName, children] of Object.entries(node.slots)) {\n slotProps[slotName] = children.map((child, index) => (\n <NodeRenderer\n key={child.nodeId ?? index}\n node={child}\n config={config}\n viewports={viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={fallbackViewportIndex}\n renderUnknown={renderUnknown}\n />\n ));\n }\n\n const { props: tokenResolvedDesign, unresolved } = selectResolvedDesign(\n node.props,\n viewports,\n activeViewportIndex,\n fallbackViewportIndex,\n config.resolveToken\n );\n if (unresolved.length && typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on \"${componentId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulComponent = {\n componentId,\n nodeId: node.nodeId,\n content: node.props.content,\n design: node.props.designRaw,\n resolved: node.props.resolved,\n };\n\n // Merge precedence (last wins): defaults < design < content < resolveData < slots.\n const composed = {\n ...componentConfig.defaults,\n ...tokenResolvedDesign,\n ...node.props.content,\n ...node.props.resolved,\n ...slotProps,\n };\n\n return (\n <ContentfulComponentProvider value={contentful}>\n <ResolvedDesignProvider value={tokenResolvedDesign}>\n {createElement(componentConfig.component, composed)}\n </ResolvedDesignProvider>\n </ContentfulComponentProvider>\n );\n}\n\nexport interface WrapWithExperienceTemplateProps {\n experienceTemplate: PortableExperienceTemplate | undefined;\n config: Config;\n viewports: ViewportDef[];\n activeViewportIndex: number;\n /** Viewport index the server pre-resolved design against. */\n fallbackViewportIndex: number;\n children: ReactNode;\n}\n\n/**\n * Wraps the rendered nodes with the page-level Experience Template. If the\n * template is referenced but unregistered, warns once and renders children\n * unwrapped.\n */\nexport function WrapWithExperienceTemplate({\n experienceTemplate,\n config,\n viewports,\n activeViewportIndex,\n fallbackViewportIndex,\n children,\n}: WrapWithExperienceTemplateProps): ReactNode {\n if (!experienceTemplate) return <Fragment>{children}</Fragment>;\n const entry = config.experienceTemplates?.[experienceTemplate.experienceTemplateId];\n if (!entry) {\n if (typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] No experience template registered for id \"${experienceTemplate.experienceTemplateId}\". Rendering nodes without the experience template wrapper.`\n );\n }\n return <Fragment>{children}</Fragment>;\n }\n const experienceTemplateConfig = normalizeExperienceTemplateRegistration(entry);\n\n const { props: tokenResolvedDesign, unresolved } = selectResolvedDesign(\n experienceTemplate.props,\n viewports,\n activeViewportIndex,\n fallbackViewportIndex,\n config.resolveToken\n );\n if (unresolved.length && typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on experience template \"${experienceTemplate.experienceTemplateId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulExperienceTemplate = {\n experienceTemplateId: experienceTemplate.experienceTemplateId,\n content: experienceTemplate.props.content,\n design: experienceTemplate.props.designRaw,\n resolved: experienceTemplate.props.resolved,\n };\n\n // Same precedence as component nodes, ending in `children`.\n const composed = {\n ...experienceTemplateConfig.defaults,\n ...tokenResolvedDesign,\n ...experienceTemplate.props.content,\n ...experienceTemplate.props.resolved,\n children,\n };\n\n return (\n <ContentfulExperienceTemplateProvider value={contentful}>\n <ResolvedDesignProvider value={tokenResolvedDesign}>\n {createElement(experienceTemplateConfig.component, composed)}\n </ResolvedDesignProvider>\n </ContentfulExperienceTemplateProvider>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/server-renderer.js
CHANGED
|
@@ -44,6 +44,7 @@ function ServerExperienceRenderer({
|
|
|
44
44
|
config,
|
|
45
45
|
viewports: experience.viewports,
|
|
46
46
|
activeViewportIndex,
|
|
47
|
+
fallbackViewportIndex: experience.fallbackViewportIndex,
|
|
47
48
|
children: /* @__PURE__ */ jsx(
|
|
48
49
|
NodesRenderer,
|
|
49
50
|
{
|
|
@@ -51,6 +52,7 @@ function ServerExperienceRenderer({
|
|
|
51
52
|
config,
|
|
52
53
|
viewports: experience.viewports,
|
|
53
54
|
activeViewportIndex,
|
|
55
|
+
fallbackViewportIndex: experience.fallbackViewportIndex,
|
|
54
56
|
renderUnknown
|
|
55
57
|
}
|
|
56
58
|
)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server-renderer.tsx"],"sourcesContent":["/*\n * Server-safe Experience renderer. Resolves the active viewport once from\n * `initialViewportId` and renders without any reactive subscription.\n */\n\nimport type { ReactNode } from 'react';\n\nimport type {\n ExperienceContext,\n PortableRenderPlan,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\nimport { getViewportIndex } from '@contentful/experiences-design';\n\nimport { DebugExperience } from './debug-experience';\nimport { ExperienceProvider } from './context';\nimport { MissingComponent } from './missing-component';\nimport { NodesRenderer, WrapWithExperienceTemplate, type RenderUnknown } from './nodes-renderer';\nimport type { Config, RenderContext } from './types';\n\nconst DEFAULT_CONTEXT: ExperienceContext = {\n debug: false,\n metadata: {},\n viewports: [],\n};\n\n// Keeps `activeViewport` non-null when a payload declares no viewports.\nconst FALLBACK_VIEWPORT: ViewportDef = {\n id: '_',\n query: '*',\n displayName: 'Default',\n previewSize: '100%',\n};\n\nexport interface ServerExperienceRendererProps {\n experience: PortableRenderPlan | null | undefined;\n config: Config;\n /** Initial viewport seed (e.g. derived from User-Agent). Defaults to viewport[0]. */\n initialViewportId?: string;\n /**\n * Arbitrary per-render metadata, readable by descendants via\n * `useExperience()` and by resolvers via `ctx.experience.metadata`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: renders the visible missing-component box,\n * turns the default `renderUnknown` fallback into the debug component, and\n * auto-mounts `<DebugExperience>` (the resolved-plan JSON panel) after the\n * tree. Pair with `debug` on `fetchExperience` for end-to-end logging.\n */\n debug?: boolean;\n /** Override the fallback rendered for unregistered component types. */\n renderUnknown?: RenderUnknown;\n}\n\nexport function ServerExperienceRenderer({\n experience,\n config,\n initialViewportId,\n metadata,\n debug = false,\n renderUnknown = MissingComponent,\n}: ServerExperienceRendererProps): ReactNode {\n if (!experience) return null;\n\n const activeViewportIndex = getViewportIndex(experience.viewports, initialViewportId);\n\n // Copy viewports/activeViewport so the context (serialized + frozen by RSC)\n // shares no object identity with the plan arrays the renderers read below —\n // a shared reference makes Flight back-patch into frozen props and throw.\n const contextViewports = experience.viewports.map((v) => ({ ...v }));\n const activeViewport = { ...(experience.viewports[activeViewportIndex] ?? FALLBACK_VIEWPORT) };\n\n const renderContext: RenderContext = {\n ...DEFAULT_CONTEXT,\n debug,\n metadata: { ...DEFAULT_CONTEXT.metadata, ...(metadata ?? {}) },\n viewports: contextViewports,\n activeViewport,\n activeViewportIndex,\n };\n\n return (\n <ExperienceProvider value={renderContext}>\n {debug ? <DebugExperience experience={experience} /> : null}\n <WrapWithExperienceTemplate\n experienceTemplate={experience.experienceTemplate}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n >\n <NodesRenderer\n nodes={experience.nodes}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n renderUnknown={renderUnknown}\n />\n </WrapWithExperienceTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":"AAmFI,SACW,KADX;AAvEJ,SAAS,wBAAwB;AAEjC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,kCAAsD;AAG9E,MAAM,kBAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU,CAAC;AAAA,EACX,WAAW,CAAC;AACd;AAGA,MAAM,oBAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AAAA,EACb,aAAa;AACf;AAuBO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,gBAAgB;AAClB,GAA6C;AAC3C,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,sBAAsB,iBAAiB,WAAW,WAAW,iBAAiB;AAKpF,QAAM,mBAAmB,WAAW,UAAU,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACnE,QAAM,iBAAiB,EAAE,GAAI,WAAW,UAAU,mBAAmB,KAAK,kBAAmB;AAE7F,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH;AAAA,IACA,UAAU,EAAE,GAAG,gBAAgB,UAAU,GAAI,YAAY,CAAC,EAAG;AAAA,IAC7D,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,sBAAmB,OAAO,eACxB;AAAA,YAAQ,oBAAC,mBAAgB,YAAwB,IAAK;AAAA,IACvD;AAAA,MAAC;AAAA;AAAA,QACC,oBAAoB,WAAW;AAAA,QAC/B;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/server-renderer.tsx"],"sourcesContent":["/*\n * Server-safe Experience renderer. Resolves the active viewport once from\n * `initialViewportId` and renders without any reactive subscription.\n */\n\nimport type { ReactNode } from 'react';\n\nimport type {\n ExperienceContext,\n PortableRenderPlan,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\nimport { getViewportIndex } from '@contentful/experiences-design';\n\nimport { DebugExperience } from './debug-experience';\nimport { ExperienceProvider } from './context';\nimport { MissingComponent } from './missing-component';\nimport { NodesRenderer, WrapWithExperienceTemplate, type RenderUnknown } from './nodes-renderer';\nimport type { Config, RenderContext } from './types';\n\nconst DEFAULT_CONTEXT: ExperienceContext = {\n debug: false,\n metadata: {},\n viewports: [],\n};\n\n// Keeps `activeViewport` non-null when a payload declares no viewports.\nconst FALLBACK_VIEWPORT: ViewportDef = {\n id: '_',\n query: '*',\n displayName: 'Default',\n previewSize: '100%',\n};\n\nexport interface ServerExperienceRendererProps {\n experience: PortableRenderPlan | null | undefined;\n config: Config;\n /** Initial viewport seed (e.g. derived from User-Agent). Defaults to viewport[0]. */\n initialViewportId?: string;\n /**\n * Arbitrary per-render metadata, readable by descendants via\n * `useExperience()` and by resolvers via `ctx.experience.metadata`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: renders the visible missing-component box,\n * turns the default `renderUnknown` fallback into the debug component, and\n * auto-mounts `<DebugExperience>` (the resolved-plan JSON panel) after the\n * tree. Pair with `debug` on `fetchExperience` for end-to-end logging.\n */\n debug?: boolean;\n /** Override the fallback rendered for unregistered component types. */\n renderUnknown?: RenderUnknown;\n}\n\nexport function ServerExperienceRenderer({\n experience,\n config,\n initialViewportId,\n metadata,\n debug = false,\n renderUnknown = MissingComponent,\n}: ServerExperienceRendererProps): ReactNode {\n if (!experience) return null;\n\n const activeViewportIndex = getViewportIndex(experience.viewports, initialViewportId);\n\n // Copy viewports/activeViewport so the context (serialized + frozen by RSC)\n // shares no object identity with the plan arrays the renderers read below —\n // a shared reference makes Flight back-patch into frozen props and throw.\n const contextViewports = experience.viewports.map((v) => ({ ...v }));\n const activeViewport = { ...(experience.viewports[activeViewportIndex] ?? FALLBACK_VIEWPORT) };\n\n const renderContext: RenderContext = {\n ...DEFAULT_CONTEXT,\n debug,\n metadata: { ...DEFAULT_CONTEXT.metadata, ...(metadata ?? {}) },\n viewports: contextViewports,\n activeViewport,\n activeViewportIndex,\n };\n\n return (\n <ExperienceProvider value={renderContext}>\n {debug ? <DebugExperience experience={experience} /> : null}\n <WrapWithExperienceTemplate\n experienceTemplate={experience.experienceTemplate}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={experience.fallbackViewportIndex}\n >\n <NodesRenderer\n nodes={experience.nodes}\n config={config}\n viewports={experience.viewports}\n activeViewportIndex={activeViewportIndex}\n fallbackViewportIndex={experience.fallbackViewportIndex}\n renderUnknown={renderUnknown}\n />\n </WrapWithExperienceTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":"AAmFI,SACW,KADX;AAvEJ,SAAS,wBAAwB;AAEjC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,kCAAsD;AAG9E,MAAM,kBAAqC;AAAA,EACzC,OAAO;AAAA,EACP,UAAU,CAAC;AAAA,EACX,WAAW,CAAC;AACd;AAGA,MAAM,oBAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AAAA,EACb,aAAa;AACf;AAuBO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,gBAAgB;AAClB,GAA6C;AAC3C,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,sBAAsB,iBAAiB,WAAW,WAAW,iBAAiB;AAKpF,QAAM,mBAAmB,WAAW,UAAU,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACnE,QAAM,iBAAiB,EAAE,GAAI,WAAW,UAAU,mBAAmB,KAAK,kBAAmB;AAE7F,QAAM,gBAA+B;AAAA,IACnC,GAAG;AAAA,IACH;AAAA,IACA,UAAU,EAAE,GAAG,gBAAgB,UAAU,GAAI,YAAY,CAAC,EAAG;AAAA,IAC7D,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,sBAAmB,OAAO,eACxB;AAAA,YAAQ,oBAAC,mBAAgB,YAAwB,IAAK;AAAA,IACvD;AAAA,MAAC;AAAA;AAAA,QACC,oBAAoB,WAAW;AAAA,QAC/B;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,QACA,uBAAuB,WAAW;AAAA,QAElC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA,uBAAuB,WAAW;AAAA,YAClC;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,9 +9,9 @@ export { ResolveContext, ResolveToken } from '@contentful/experiences-sdk-core';
|
|
|
9
9
|
* cascade, branching by `componentId` in a generic wrapper, keying
|
|
10
10
|
* analytics on `nodeId`, or rendering a raw-payload panel in preview.
|
|
11
11
|
*
|
|
12
|
-
* Design properties stay in their **raw
|
|
13
|
-
* `ctx.design` carries inside `resolveData`). The viewport-cascaded,
|
|
14
|
-
* resolved values are what `useDesignValues()` returns.
|
|
12
|
+
* Design properties stay in their **raw discriminated form** here (the same
|
|
13
|
+
* shape `ctx.design` carries inside `resolveData`). The viewport-cascaded,
|
|
14
|
+
* token-resolved values are what `useDesignValues()` returns.
|
|
15
15
|
*/
|
|
16
16
|
interface ContentfulComponent {
|
|
17
17
|
componentId: string;
|
|
@@ -43,9 +43,10 @@ interface RenderContext extends ExperienceContext {
|
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Customer-supplied configuration for a single component. The `component`
|
|
46
|
-
* receives the merged
|
|
47
|
-
*
|
|
48
|
-
* context and raw payload come from
|
|
46
|
+
* receives the merged props (design + content + resolveData + slots); resolved
|
|
47
|
+
* design values auto-fill matching props and are also readable via
|
|
48
|
+
* `useDesignValues()`. Runtime context and raw payload come from
|
|
49
|
+
* `useExperience()` / `useContentfulComponent()`.
|
|
49
50
|
*/
|
|
50
51
|
interface ComponentConfig<Props extends object = Record<string, unknown>> {
|
|
51
52
|
/**
|
|
@@ -117,8 +118,8 @@ interface Config {
|
|
|
117
118
|
components: Components;
|
|
118
119
|
experienceTemplates?: ExperienceTemplates;
|
|
119
120
|
/**
|
|
120
|
-
* Resolves `DesignToken`
|
|
121
|
-
* component. If omitted,
|
|
121
|
+
* Resolves `DesignToken` values to runtime values before they reach a
|
|
122
|
+
* component. If omitted, they pass through unchanged. See `ResolveToken`
|
|
122
123
|
* in `@contentful/experiences-sdk-core` for the full contract.
|
|
123
124
|
*/
|
|
124
125
|
resolveToken?: ResolveToken;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { ComponentType, ReactNode } from 'react';\n\nimport type {\n DesignPropValue,\n ExperienceContext,\n ResolveContext,\n ResolveToken,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\n/**\n * Re-exported for ergonomics: customer code authoring `resolveData` doesn't\n * have to dig into the core package for the context type.\n */\nexport type { ResolveContext, ResolveToken };\n\n/**\n * The full Contentful-side payload for a single component instance, exposed\n * via `useContentfulComponent()` to any descendant of a rendered Experience\n * node. Useful for custom design-property resolution outside the SDK's\n * cascade, branching by `componentId` in a generic wrapper, keying\n * analytics on `nodeId`, or rendering a raw-payload panel in preview.\n *\n * Design properties stay in their **raw
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { ComponentType, ReactNode } from 'react';\n\nimport type {\n DesignPropValue,\n ExperienceContext,\n ResolveContext,\n ResolveToken,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\n/**\n * Re-exported for ergonomics: customer code authoring `resolveData` doesn't\n * have to dig into the core package for the context type.\n */\nexport type { ResolveContext, ResolveToken };\n\n/**\n * The full Contentful-side payload for a single component instance, exposed\n * via `useContentfulComponent()` to any descendant of a rendered Experience\n * node. Useful for custom design-property resolution outside the SDK's\n * cascade, branching by `componentId` in a generic wrapper, keying\n * analytics on `nodeId`, or rendering a raw-payload panel in preview.\n *\n * Design properties stay in their **raw discriminated form** here (the same\n * shape `ctx.design` carries inside `resolveData`). The viewport-cascaded,\n * token-resolved values are what `useDesignValues()` returns.\n */\nexport interface ContentfulComponent {\n componentId: string;\n nodeId?: string;\n content: Record<string, unknown>;\n design: Record<string, DesignPropValue>;\n resolved?: Record<string, unknown>;\n}\n\n/**\n * Same shape as `ContentfulComponent`, but for the page-level Experience\n * Template. Exposed via `useContentfulExperienceTemplate()` inside an\n * Experience Template's component tree.\n */\nexport interface ContentfulExperienceTemplate {\n experienceTemplateId: string;\n content: Record<string, unknown>;\n design: Record<string, DesignPropValue>;\n resolved?: Record<string, unknown>;\n}\n\n/**\n * Render-time experience context. Extends the core `ExperienceContext` with\n * the active viewport — a render-time value that resolvers cannot see (they\n * run once before viewport resolution and are not re-triggered by viewport\n * changes). Exposed via `useExperience()` to any descendant of the renderer.\n */\nexport interface RenderContext extends ExperienceContext {\n activeViewport: ViewportDef;\n activeViewportIndex: number;\n}\n\n/**\n * Customer-supplied configuration for a single component. The `component`\n * receives the merged props (design + content + resolveData + slots); resolved\n * design values auto-fill matching props and are also readable via\n * `useDesignValues()`. Runtime context and raw payload come from\n * `useExperience()` / `useContentfulComponent()`.\n */\nexport interface ComponentConfig<Props extends object = Record<string, unknown>> {\n /**\n * Lowest-precedence prop bag. Merged in before content / resolveData /\n * slots. Useful for variant fallbacks the editorial layer doesn't always supply.\n */\n defaults?: Partial<Props>;\n /**\n * Optional sync-or-async hook that derives final props from the raw\n * Experience inputs. Runs once during `resolveExperience`, before render —\n * does NOT re-fire on viewport changes.\n */\n resolveData?: (ctx: ResolveContext) => Partial<Props> | Promise<Partial<Props>>;\n /**\n * The React component to render. Receives the merged prop bag as its props.\n */\n component: ComponentType<Props>;\n}\n\n/**\n * Registry value. Register a bare React component for the common case, or\n * the full `ComponentConfig` shape when you need defaults or a `resolveData`\n * hook.\n *\n * button: Button, // bare\n * header: { component: Header, defaults: {...} }, // with defaults\n * card: defineComponent<CardProps>({ component: Card, resolveData: ... }),\n */\nexport type Registration<Props extends object = Record<string, unknown>> =\n | ComponentType<Props>\n | ComponentConfig<Props>;\n\n/**\n * Customer-supplied configuration for a page-level Experience Template. The\n * template's component receives the rendered Experience nodes as `children`.\n */\nexport interface ExperienceTemplateConfig<Props extends object = Record<string, unknown>> {\n defaults?: Partial<Props>;\n resolveData?: (ctx: ResolveContext) => Partial<Props> | Promise<Partial<Props>>;\n component: ComponentType<Props & { children?: ReactNode }>;\n}\n\n/**\n * Registry value for Experience Templates. Same dual-shape as component\n * registrations.\n */\nexport type ExperienceTemplateRegistration<Props extends object = Record<string, unknown>> =\n | ComponentType<Props & { children?: ReactNode }>\n | ExperienceTemplateConfig<Props>;\n\n/**\n * Identity helper — returns the config as-is, but narrows the `resolveData`\n * and `component` parameter types to your declared `Props`.\n */\nexport function defineComponent<Props extends object = Record<string, unknown>>(\n config: ComponentConfig<Props>\n): ComponentConfig<Props> {\n return config;\n}\n\n/**\n * Identity helper — returns the Experience Template config as-is, with `Props`\n * narrowing.\n */\nexport function defineExperienceTemplate<Props extends object = Record<string, unknown>>(\n config: ExperienceTemplateConfig<Props>\n): ExperienceTemplateConfig<Props> {\n return config;\n}\n\n/**\n * Component registry — keyed by `componentId` (last slash-segment of\n * `component.sys.urn`). Per-entry prop narrowing happens at\n * `defineComponent<Props>` or at the bare-component's own type.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- per-entry narrowing happens at the registration author's call site.\nexport type Components = Record<string, Registration<any>>;\n\n/**\n * Experience Template registry — keyed by `experienceTemplateId` (last\n * slash-segment of `payload.sys.experienceTemplate.sys.urn`).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- per-entry narrowing happens at the registration author's call site.\nexport type ExperienceTemplates = Record<string, ExperienceTemplateRegistration<any>>;\n\nexport interface Config {\n components: Components;\n experienceTemplates?: ExperienceTemplates;\n /**\n * Resolves `DesignToken` values to runtime values before they reach a\n * component. If omitted, they pass through unchanged. See `ResolveToken`\n * in `@contentful/experiences-sdk-core` for the full contract.\n */\n resolveToken?: ResolveToken;\n}\n\n/**\n * Normalize a registry entry — bare component OR config object — into the\n * common `ComponentConfig` shape used by the renderer.\n *\n * React function components are plain functions; `React.memo` /\n * `React.forwardRef` yield objects carrying a `$$typeof` symbol. Both count\n * as bare components; a config object is discriminated by having a\n * `component` field and no `$$typeof`.\n */\nexport function normalizeComponentRegistration<P extends object>(\n reg: Registration<P>\n): ComponentConfig<P> {\n if (typeof reg === 'object' && reg !== null && !('$$typeof' in reg) && 'component' in reg) {\n return reg as ComponentConfig<P>;\n }\n return { component: reg as ComponentType<P> };\n}\n\nexport function normalizeExperienceTemplateRegistration<P extends object>(\n reg: ExperienceTemplateRegistration<P>\n): ExperienceTemplateConfig<P> {\n if (typeof reg === 'object' && reg !== null && !('$$typeof' in reg) && 'component' in reg) {\n return reg as ExperienceTemplateConfig<P>;\n }\n return { component: reg as ComponentType<P & { children?: ReactNode }> };\n}\n"],"mappings":"AAsHO,SAAS,gBACd,QACwB;AACxB,SAAO;AACT;AAMO,SAAS,yBACd,QACiC;AACjC,SAAO;AACT;AAqCO,SAAS,+BACd,KACoB;AACpB,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,EAAE,cAAc,QAAQ,eAAe,KAAK;AACzF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,WAAW,IAAwB;AAC9C;AAEO,SAAS,wCACd,KAC6B;AAC7B,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,EAAE,cAAc,QAAQ,eAAe,KAAK;AACzF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,WAAW,IAAmD;AACzE;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experiences-react",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "React adapter for Contentful Experiences — Server and Client renderers over a PortableRenderPlan",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"directory": "packages/adapter-react"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@contentful/experiences-client": "0.3.
|
|
34
|
-
"@contentful/experiences-sdk-core": "0.7.
|
|
35
|
-
"@contentful/experiences-design": "0.7.
|
|
33
|
+
"@contentful/experiences-client": "0.3.1",
|
|
34
|
+
"@contentful/experiences-sdk-core": "0.7.1",
|
|
35
|
+
"@contentful/experiences-design": "0.7.1"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": "^18.0.0 || ^19.0.0",
|