@contentful/experiences-react 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,104 @@
1
+ ## 0.7.0 (2026-08-07)
2
+
3
+ ### 🩹 Fixes
4
+
5
+ - ⚠️ bump @contentful/experience-delivery to 1.0.0-dev.6 + migrate to renamed API [AIS-339] ([#120](https://github.com/contentful/experiences/pull/120))
6
+
7
+ ### ⚠️ Breaking Changes
8
+
9
+ - bump @contentful/experience-delivery to 1.0.0-dev.6 + migrate to renamed API [AIS-339] ([#120](https://github.com/contentful/experiences/pull/120))
10
+ the public API uses the component / experienceTemplate vocabulary.
11
+ - `registration.componentTypeId` -> `registration.componentId`
12
+ - `plan.template` -> `plan.experienceTemplate`
13
+ - `PortableTemplate` -> `PortableExperienceTemplate` (`templateId` ->
14
+ `experienceTemplateId`)
15
+ - `Config.templates` -> `Config.experienceTemplates`; `Templates` ->
16
+ `ExperienceTemplates`
17
+ - `defineTemplate` -> `defineExperienceTemplate`; `TemplateConfig` ->
18
+ `ExperienceTemplateConfig`; `TemplateRegistration` ->
19
+ `ExperienceTemplateRegistration`; `normalizeTemplateRegistration` ->
20
+ `normalizeExperienceTemplateRegistration`
21
+ - `useContentfulTemplate()` / `getContentfulTemplate()` ->
22
+ `useContentfulExperienceTemplate()` / `getContentfulExperienceTemplate()`;
23
+ `ContentfulTemplate` -> `ContentfulExperienceTemplate`
24
+ - `MissingComponentProps.componentTypeId` -> `componentId`
25
+ - Core payload types: `ComponentTypeNode`/`ComponentTypeRef` ->
26
+ `ComponentNode`/`ComponentRef`; `TemplateNode`/`TemplateRef` ->
27
+ `ExperienceTemplateNode`/`ExperienceTemplateRef`
28
+ `packages/core` stays zero-dep, so its payload types are hand-mirrored from the
29
+ delivery package rather than imported; each carries a doc comment naming its
30
+ upstream counterpart, and `client:typecheck` catches drift when the delivery SDK
31
+ regenerates. Documented in AGENTS.md.
32
+ `examples/scripts/` is intentionally unchanged: it targets the management SDK
33
+ (`contentful-management`), which has its own entity-type surface, and adopting it
34
+ would require changing that dependency. The seed script therefore still
35
+ provisions the shapes that SDK produces.
36
+ Verified: build, typecheck, and 157 tests pass across all five packages.
37
+ Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
38
+ * docs: describe current state only in comments and docs
39
+ Drop ticket ids, tracker links, and before/after narrative from doc comments and
40
+ prose so they explain what the code does now rather than how it got here.
41
+ - `alpha-feature.ts`: state what the header selects and why it is required,
42
+ without the two-shapes-in-transition framing or the removal timeline.
43
+ - `core/src/types.ts`: keep each type's upstream counterpart in
44
+ `@contentful/experience-delivery` (load-bearing for maintenance) but drop the
45
+ "formerly known as" and old-link-type asides.
46
+ - README: replace the rename migration table with a description of the
47
+ alpha-feature header and when a caller needs to send it.
48
+ - AGENTS.md: reframe the rationale entries that opened on prior designs to state
49
+ the current design and its reason.
50
+ - Drop stale option-shape asides ("was nested under ...") and a test name that
51
+ described superseded behaviour.
52
+ Generated CHANGELOG.md files are untouched — they are release history.
53
+ Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
54
+ * feat!: migrate bootstrap fixture script to component/experienceTemplate entities
55
+ contentful-management@12.14.0 exposes the renamed ExO entities (Component,
56
+ ExperienceTemplate) alongside the deprecated ComponentType/Template ones. Adopt
57
+ the renamed shapes throughout examples/scripts so a freshly bootstrapped demo
58
+ Experience uses the same entity vocabulary the delivery-consuming packages now
59
+ read.
60
+ - Bump contentful-management to ^12.14.0 (existing dependency, version only —
61
+ no new packages).
62
+ - fixture/component-types.ts -> fixture/components.ts: ComponentTypeFixture ->
63
+ ComponentFixture.
64
+ - fixture/templates.ts -> fixture/experience-templates.ts:
65
+ TemplateFixture -> ExperienceTemplateFixture, TemplateTreeNode ->
66
+ ExperienceTemplateTreeNode.
67
+ - fixture/types.ts, fixture/experience.ts: ExperienceFixture.templateId ->
68
+ experienceTemplateId; node nodeType 'InlineFragment' ->
69
+ 'InlineExperienceFragment' with componentTypeId -> componentId, matching
70
+ contentful-management's InlineExperienceFragmentNode.
71
+ - fixture/data-assemblies.ts: dataAssemblyComponentTypeLinks ->
72
+ dataAssemblyComponentLinks (componentTypeId -> componentId).
73
+ - bootstrap-example.ts: cma.componentType -> cma.component,
74
+ cma.template -> cma.experienceTemplate; sys.type 'ComponentType' ->
75
+ 'Component', 'Template' -> 'ExperienceTemplate'; resource-link types
76
+ Contentful:ComponentType -> Contentful:Component and Contentful:Template ->
77
+ Contentful:ExperienceTemplate; URN segments components/ and
78
+ experienceTemplates/; seedComponentType -> seedComponent, seedTemplate ->
79
+ seedExperienceTemplate, linkDataAssembliesToComponentTypes ->
80
+ linkDataAssembliesToComponents.
81
+ The metadata.annotations.Template composed/coded-implementation marker is
82
+ unrelated to this rename (identical shape in 12.10.0 and 12.14.0) and is left
83
+ untouched.
84
+ Verified: examples/scripts typechecks clean; the main workspace's build,
85
+ typecheck, and 157 tests are unaffected.
86
+ Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
87
+
88
+ ### 🧱 Updated Dependencies
89
+
90
+ - Updated client to 0.3.0
91
+ - Updated design to 0.7.0
92
+ - Updated core to 0.7.0
93
+
94
+ ## 0.6.1 (2026-08-06)
95
+
96
+ ### 🧱 Updated Dependencies
97
+
98
+ - Updated client to 0.2.1
99
+ - Updated design to 0.6.1
100
+ - Updated core to 0.6.1
101
+
1
102
  ## 0.6.0 (2026-08-05)
2
103
 
3
104
  ### 🚀 Features
package/README.md CHANGED
@@ -18,7 +18,7 @@ This is the **only SDK package you install**. It re-exports everything you need
18
18
 
19
19
  ```ts
20
20
  defineComponent<Props>(config); // Type-narrowing identity for component-type configs
21
- defineTemplate<Props>(config); // Same shape, for page-level template wrappers
21
+ defineExperienceTemplate<Props>(config); // Same shape, for page-level Experience Template wrappers
22
22
  ```
23
23
 
24
24
  ### Fetching
@@ -54,7 +54,7 @@ useDesignValues<T>(); // Resolved design values for the current node (viewport-c
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)
57
- useContentfulTemplate(); // Same, for the page-level template
57
+ useContentfulExperienceTemplate(); // Same, for the page-level Experience Template
58
58
  type ToCssOptions;
59
59
  ```
60
60
 
@@ -64,12 +64,12 @@ Design is **not** injected as props; components read it via `useDesignValues()`.
64
64
 
65
65
  ```ts
66
66
  // From core
67
- type Config, Components, Templates, Registration, TemplateRegistration,
68
- type ComponentConfig, TemplateConfig,
69
- type ContentfulComponent, ContentfulTemplate,
67
+ type Config, Components, ExperienceTemplates, Registration, ExperienceTemplateRegistration,
68
+ type ComponentConfig, ExperienceTemplateConfig,
69
+ type ContentfulComponent, ContentfulExperienceTemplate,
70
70
  type RenderContext, ResolveToken,
71
- type ExperiencePayload, ExperienceNode, ComponentTypeNode, TemplateNode,
72
- type PortableRenderPlan, PortableRenderNode, PortableTemplate,
71
+ type ExperiencePayload, ExperienceNode, ComponentNode, ExperienceTemplateNode,
72
+ type PortableRenderPlan, PortableRenderNode, PortableExperienceTemplate,
73
73
  type DesignPropValue, ManualDesignValue, DesignToken, ValuesByViewport,
74
74
  type ViewportDef, ExperienceContext, ResolveContext,
75
75
  type ResolverConfig, ResolveExperienceOptions
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { DebugExperience } from "./debug-experience";
4
4
  import { ExperienceProvider } from "./context";
5
5
  import { MissingComponent } from "./missing-component";
6
- import { NodesRenderer, WrapWithTemplate } from "./nodes-renderer";
6
+ import { NodesRenderer, WrapWithExperienceTemplate } from "./nodes-renderer";
7
7
  import { useActiveViewport } from "./use-active-viewport";
8
8
  const DEFAULT_CONTEXT = {
9
9
  debug: false,
@@ -39,9 +39,9 @@ function ClientExperienceRenderer({
39
39
  return /* @__PURE__ */ jsxs(ExperienceProvider, { value: renderContext, children: [
40
40
  debug ? /* @__PURE__ */ jsx(DebugExperience, { experience }) : null,
41
41
  /* @__PURE__ */ jsx(
42
- WrapWithTemplate,
42
+ WrapWithExperienceTemplate,
43
43
  {
44
- template: experience.template,
44
+ experienceTemplate: experience.experienceTemplate,
45
45
  config,
46
46
  viewports: experience.viewports,
47
47
  activeViewportIndex,
@@ -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, WrapWithTemplate, 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 <WrapWithTemplate\n template={experience.template}\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 </WrapWithTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":";AAiFI,SACW,KADX;AAhEJ,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,wBAA4C;AAEpE,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,UAAU,WAAW;AAAA,QACrB;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
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,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
package/dist/context.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { ContentfulComponent, ContentfulTemplate, RenderContext } from './types.js';
2
+ import { ContentfulComponent, ContentfulExperienceTemplate, RenderContext } from './types.js';
3
3
  import '@contentful/experiences-sdk-core';
4
4
 
5
5
  declare function ExperienceProvider({ value, children, }: {
@@ -10,8 +10,8 @@ declare function ContentfulComponentProvider({ value, children, }: {
10
10
  value: ContentfulComponent;
11
11
  children: ReactNode;
12
12
  }): ReactNode;
13
- declare function ContentfulTemplateProvider({ value, children, }: {
14
- value: ContentfulTemplate;
13
+ declare function ContentfulExperienceTemplateProvider({ value, children, }: {
14
+ value: ContentfulExperienceTemplate;
15
15
  children: ReactNode;
16
16
  }): ReactNode;
17
17
  declare function ResolvedDesignProvider({ value, children, }: {
@@ -31,16 +31,16 @@ declare function useExperience(): RenderContext;
31
31
  */
32
32
  declare function useContentfulComponent(): ContentfulComponent | null;
33
33
  /**
34
- * Read the raw Contentful payload for the page-level template, if one is in
35
- * scope. Returns `null` outside a template's render tree.
34
+ * Read the raw Contentful payload for the page-level Experience Template, if
35
+ * one is in scope. Returns `null` outside an Experience Template's render tree.
36
36
  */
37
- declare function useContentfulTemplate(): ContentfulTemplate | null;
37
+ declare function useContentfulExperienceTemplate(): ContentfulExperienceTemplate | null;
38
38
  /**
39
39
  * Read the design values the renderer already resolved for the enclosing
40
- * node or template — viewport-cascaded and token-resolved, the same bag that
41
- * feeds the component's props. Returns `null` outside a rendered node/
42
- * template, which `useDesignValues` treats as "nothing to read."
40
+ * node or experience template — viewport-cascaded and token-resolved, the same
41
+ * bag that feeds the component's props. Returns `null` outside a rendered
42
+ * node / experience template, which `useDesignValues` treats as "nothing to read."
43
43
  */
44
44
  declare function useResolvedDesign(): Record<string, unknown> | null;
45
45
 
46
- export { ContentfulComponentProvider, ContentfulTemplateProvider, ExperienceProvider, ResolvedDesignProvider, useContentfulComponent, useContentfulTemplate, useExperience, useResolvedDesign };
46
+ export { ContentfulComponentProvider, ContentfulExperienceTemplateProvider, ExperienceProvider, ResolvedDesignProvider, useContentfulComponent, useContentfulExperienceTemplate, useExperience, useResolvedDesign };
package/dist/context.js CHANGED
@@ -3,7 +3,9 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { createContext, useContext } from "react";
4
4
  const ExperienceContext = createContext(null);
5
5
  const ContentfulComponentContext = createContext(null);
6
- const ContentfulTemplateContext = createContext(null);
6
+ const ContentfulExperienceTemplateContext = createContext(
7
+ null
8
+ );
7
9
  const ResolvedDesignContext = createContext(null);
8
10
  function ExperienceProvider({
9
11
  value,
@@ -17,11 +19,11 @@ function ContentfulComponentProvider({
17
19
  }) {
18
20
  return /* @__PURE__ */ jsx(ContentfulComponentContext.Provider, { value, children });
19
21
  }
20
- function ContentfulTemplateProvider({
22
+ function ContentfulExperienceTemplateProvider({
21
23
  value,
22
24
  children
23
25
  }) {
24
- return /* @__PURE__ */ jsx(ContentfulTemplateContext.Provider, { value, children });
26
+ return /* @__PURE__ */ jsx(ContentfulExperienceTemplateContext.Provider, { value, children });
25
27
  }
26
28
  function ResolvedDesignProvider({
27
29
  value,
@@ -41,19 +43,19 @@ function useExperience() {
41
43
  function useContentfulComponent() {
42
44
  return useContext(ContentfulComponentContext);
43
45
  }
44
- function useContentfulTemplate() {
45
- return useContext(ContentfulTemplateContext);
46
+ function useContentfulExperienceTemplate() {
47
+ return useContext(ContentfulExperienceTemplateContext);
46
48
  }
47
49
  function useResolvedDesign() {
48
50
  return useContext(ResolvedDesignContext);
49
51
  }
50
52
  export {
51
53
  ContentfulComponentProvider,
52
- ContentfulTemplateProvider,
54
+ ContentfulExperienceTemplateProvider,
53
55
  ExperienceProvider,
54
56
  ResolvedDesignProvider,
55
57
  useContentfulComponent,
56
- useContentfulTemplate,
58
+ useContentfulExperienceTemplate,
57
59
  useExperience,
58
60
  useResolvedDesign
59
61
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.tsx"],"sourcesContent":["/*\n * React context providers + hooks that expose runtime context and the raw\n * Contentful payload to descendants of a rendered Experience. Customer\n * components receive only their declared props via the renderer; anything\n * that needs the Experience runtime context or the underlying payload calls\n * the hook explicitly at the top of its component body.\n */\n\n'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\n\nimport type { ContentfulComponent, ContentfulTemplate, RenderContext } from './types';\n\nconst ExperienceContext = createContext<RenderContext | null>(null);\nconst ContentfulComponentContext = createContext<ContentfulComponent | null>(null);\nconst ContentfulTemplateContext = createContext<ContentfulTemplate | null>(null);\n// Plain data only (never the Config or its functions) so it crosses RSC cleanly.\nconst ResolvedDesignContext = createContext<Record<string, unknown> | null>(null);\n\n// Wrapped as real client-component functions, not re-exported `Context.Provider`\n// objects — the server renderer imports these across the RSC boundary and\n// Next.js requires a function reference there (\"Element type is invalid\" otherwise).\n\nexport function ExperienceProvider({\n value,\n children,\n}: {\n value: RenderContext;\n children: ReactNode;\n}): ReactNode {\n return <ExperienceContext.Provider value={value}>{children}</ExperienceContext.Provider>;\n}\n\nexport function ContentfulComponentProvider({\n value,\n children,\n}: {\n value: ContentfulComponent;\n children: ReactNode;\n}): ReactNode {\n return (\n <ContentfulComponentContext.Provider value={value}>\n {children}\n </ContentfulComponentContext.Provider>\n );\n}\n\nexport function ContentfulTemplateProvider({\n value,\n children,\n}: {\n value: ContentfulTemplate;\n children: ReactNode;\n}): ReactNode {\n return (\n <ContentfulTemplateContext.Provider value={value}>\n {children}\n </ContentfulTemplateContext.Provider>\n );\n}\n\nexport function ResolvedDesignProvider({\n value,\n children,\n}: {\n value: Record<string, unknown>;\n children: ReactNode;\n}): ReactNode {\n return <ResolvedDesignContext.Provider value={value}>{children}</ResolvedDesignContext.Provider>;\n}\n\n/**\n * Read the current Experience runtime context — viewports, the active\n * viewport, the `debug` flag, and free-form metadata. Throws when called\n * outside any Experience renderer subtree.\n */\nexport function useExperience(): RenderContext {\n const ctx = useContext(ExperienceContext);\n if (ctx === null) {\n throw new Error(\n 'useExperience() must be called inside a <ServerExperienceRenderer> or <ClientExperienceRenderer> subtree.'\n );\n }\n return ctx;\n}\n\n/**\n * Read the raw Contentful payload for the nearest enclosing Experience node.\n * Returns `null` outside any rendered node (e.g. from a template's chrome\n * that wraps the nodes but isn't itself a node).\n */\nexport function useContentfulComponent(): ContentfulComponent | null {\n return useContext(ContentfulComponentContext);\n}\n\n/**\n * Read the raw Contentful payload for the page-level template, if one is in\n * scope. Returns `null` outside a template's render tree.\n */\nexport function useContentfulTemplate(): ContentfulTemplate | null {\n return useContext(ContentfulTemplateContext);\n}\n\n/**\n * Read the design values the renderer already resolved for the enclosing\n * node or template — viewport-cascaded and token-resolved, the same bag that\n * feeds the component's props. Returns `null` outside a rendered node/\n * template, which `useDesignValues` treats as \"nothing to read.\"\n */\nexport function useResolvedDesign(): Record<string, unknown> | null {\n return useContext(ResolvedDesignContext);\n}\n"],"mappings":";AA+BS;AArBT,SAAS,eAAe,kBAAkC;AAI1D,MAAM,oBAAoB,cAAoC,IAAI;AAClE,MAAM,6BAA6B,cAA0C,IAAI;AACjF,MAAM,4BAA4B,cAAyC,IAAI;AAE/E,MAAM,wBAAwB,cAA8C,IAAI;AAMzE,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGc;AACZ,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAC7D;AAEO,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AACF,GAGc;AACZ,SACE,oBAAC,2BAA2B,UAA3B,EAAoC,OAClC,UACH;AAEJ;AAEO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AACF,GAGc;AACZ,SACE,oBAAC,0BAA0B,UAA1B,EAAmC,OACjC,UACH;AAEJ;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AACF,GAGc;AACZ,SAAO,oBAAC,sBAAsB,UAAtB,EAA+B,OAAe,UAAS;AACjE;AAOO,SAAS,gBAA+B;AAC7C,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,QAAQ,MAAM;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,yBAAqD;AACnE,SAAO,WAAW,0BAA0B;AAC9C;AAMO,SAAS,wBAAmD;AACjE,SAAO,WAAW,yBAAyB;AAC7C;AAQO,SAAS,oBAAoD;AAClE,SAAO,WAAW,qBAAqB;AACzC;","names":[]}
1
+ {"version":3,"sources":["../src/context.tsx"],"sourcesContent":["/*\n * React context providers + hooks that expose runtime context and the raw\n * Contentful payload to descendants of a rendered Experience. Customer\n * components receive only their declared props via the renderer; anything\n * that needs the Experience runtime context or the underlying payload calls\n * the hook explicitly at the top of its component body.\n */\n\n'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\n\nimport type { ContentfulComponent, ContentfulExperienceTemplate, RenderContext } from './types';\n\nconst ExperienceContext = createContext<RenderContext | null>(null);\nconst ContentfulComponentContext = createContext<ContentfulComponent | null>(null);\nconst ContentfulExperienceTemplateContext = createContext<ContentfulExperienceTemplate | null>(\n null\n);\n// Plain data only (never the Config or its functions) so it crosses RSC cleanly.\nconst ResolvedDesignContext = createContext<Record<string, unknown> | null>(null);\n\n// Wrapped as real client-component functions, not re-exported `Context.Provider`\n// objects — the server renderer imports these across the RSC boundary and\n// Next.js requires a function reference there (\"Element type is invalid\" otherwise).\n\nexport function ExperienceProvider({\n value,\n children,\n}: {\n value: RenderContext;\n children: ReactNode;\n}): ReactNode {\n return <ExperienceContext.Provider value={value}>{children}</ExperienceContext.Provider>;\n}\n\nexport function ContentfulComponentProvider({\n value,\n children,\n}: {\n value: ContentfulComponent;\n children: ReactNode;\n}): ReactNode {\n return (\n <ContentfulComponentContext.Provider value={value}>\n {children}\n </ContentfulComponentContext.Provider>\n );\n}\n\nexport function ContentfulExperienceTemplateProvider({\n value,\n children,\n}: {\n value: ContentfulExperienceTemplate;\n children: ReactNode;\n}): ReactNode {\n return (\n <ContentfulExperienceTemplateContext.Provider value={value}>\n {children}\n </ContentfulExperienceTemplateContext.Provider>\n );\n}\n\nexport function ResolvedDesignProvider({\n value,\n children,\n}: {\n value: Record<string, unknown>;\n children: ReactNode;\n}): ReactNode {\n return <ResolvedDesignContext.Provider value={value}>{children}</ResolvedDesignContext.Provider>;\n}\n\n/**\n * Read the current Experience runtime context — viewports, the active\n * viewport, the `debug` flag, and free-form metadata. Throws when called\n * outside any Experience renderer subtree.\n */\nexport function useExperience(): RenderContext {\n const ctx = useContext(ExperienceContext);\n if (ctx === null) {\n throw new Error(\n 'useExperience() must be called inside a <ServerExperienceRenderer> or <ClientExperienceRenderer> subtree.'\n );\n }\n return ctx;\n}\n\n/**\n * Read the raw Contentful payload for the nearest enclosing Experience node.\n * Returns `null` outside any rendered node (e.g. from a template's chrome\n * that wraps the nodes but isn't itself a node).\n */\nexport function useContentfulComponent(): ContentfulComponent | null {\n return useContext(ContentfulComponentContext);\n}\n\n/**\n * Read the raw Contentful payload for the page-level Experience Template, if\n * one is in scope. Returns `null` outside an Experience Template's render tree.\n */\nexport function useContentfulExperienceTemplate(): ContentfulExperienceTemplate | null {\n return useContext(ContentfulExperienceTemplateContext);\n}\n\n/**\n * Read the design values the renderer already resolved for the enclosing\n * node or experience template — viewport-cascaded and token-resolved, the same\n * bag that feeds the component's props. Returns `null` outside a rendered\n * node / experience template, which `useDesignValues` treats as \"nothing to read.\"\n */\nexport function useResolvedDesign(): Record<string, unknown> | null {\n return useContext(ResolvedDesignContext);\n}\n"],"mappings":";AAiCS;AAvBT,SAAS,eAAe,kBAAkC;AAI1D,MAAM,oBAAoB,cAAoC,IAAI;AAClE,MAAM,6BAA6B,cAA0C,IAAI;AACjF,MAAM,sCAAsC;AAAA,EAC1C;AACF;AAEA,MAAM,wBAAwB,cAA8C,IAAI;AAMzE,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGc;AACZ,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAC7D;AAEO,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AACF,GAGc;AACZ,SACE,oBAAC,2BAA2B,UAA3B,EAAoC,OAClC,UACH;AAEJ;AAEO,SAAS,qCAAqC;AAAA,EACnD;AAAA,EACA;AACF,GAGc;AACZ,SACE,oBAAC,oCAAoC,UAApC,EAA6C,OAC3C,UACH;AAEJ;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AACF,GAGc;AACZ,SAAO,oBAAC,sBAAsB,UAAtB,EAA+B,OAAe,UAAS;AACjE;AAOO,SAAS,gBAA+B;AAC7C,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,QAAQ,MAAM;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,yBAAqD;AACnE,SAAO,WAAW,0BAA0B;AAC9C;AAMO,SAAS,kCAAuE;AACrF,SAAO,WAAW,mCAAmC;AACvD;AAQO,SAAS,oBAAoD;AAClE,SAAO,WAAW,qBAAqB;AACzC;","names":[]}
@@ -4,7 +4,7 @@ function DebugExperience({
4
4
  defaultOpen = false
5
5
  }) {
6
6
  const nodeCount = experience.nodes.length;
7
- const summary = `Experience debug \u2014 ${nodeCount} top-level node${nodeCount === 1 ? "" : "s"}${experience.template ? `, template: ${experience.template.templateId}` : ""}`;
7
+ const summary = `Experience debug \u2014 ${nodeCount} top-level node${nodeCount === 1 ? "" : "s"}${experience.experienceTemplate ? `, experience template: ${experience.experienceTemplate.experienceTemplateId}` : ""}`;
8
8
  return /* @__PURE__ */ jsxs(
9
9
  "details",
10
10
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/debug-experience.tsx"],"sourcesContent":["/*\n * First-party debug panel. Renders the resolved Experience plan as pretty\n * JSON so a customer can see exactly what the SDK interpreted from the payload\n * — node tree, registrations, resolved props, viewports.\n *\n * Two ways to use it:\n * - Auto-mounted by the renderers when `debug` is on (above the tree).\n * - Mounted manually anywhere: `<DebugExperience experience={plan} />`.\n *\n * v1 is just the JSON dump wrapped in a native <details> so it collapses\n * without any client JS (safe in server components). Room to grow into a\n * node-tree explorer, viewport indicator, and resolveData timing panel — kept\n * deliberately small for now.\n *\n * No React hooks here on purpose: it must render in both server and client\n * renderer subtrees.\n */\n\nimport type { ReactNode } from 'react';\n\nimport type { PortableRenderPlan } from '@contentful/experiences-sdk-core';\n\nexport interface DebugExperienceProps {\n /** The resolved plan to inspect (what a renderer receives as `experience`). */\n experience: PortableRenderPlan;\n /** Start expanded. Defaults to collapsed to stay out of the way. */\n defaultOpen?: boolean;\n}\n\nexport function DebugExperience({\n experience,\n defaultOpen = false,\n}: DebugExperienceProps): ReactNode {\n const nodeCount = experience.nodes.length;\n const summary = `Experience debug — ${nodeCount} top-level node${nodeCount === 1 ? '' : 's'}${\n experience.template ? `, template: ${experience.template.templateId}` : ''\n }`;\n\n return (\n <details\n open={defaultOpen}\n data-experiences-debug\n style={{\n margin: '1rem 0',\n border: '1px solid #6b7280',\n borderRadius: '6px',\n background: '#0b1021',\n color: '#e2e8f0',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.75rem',\n overflow: 'hidden',\n }}\n >\n <summary\n style={{\n cursor: 'pointer',\n padding: '0.5rem 0.75rem',\n background: '#111827',\n userSelect: 'none',\n }}\n >\n {summary}\n </summary>\n <pre\n style={{\n margin: 0,\n padding: '0.75rem',\n overflow: 'auto',\n maxHeight: '32rem',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {safeStringify(experience)}\n </pre>\n </details>\n );\n}\n\n/**\n * JSON.stringify with a circular-reference guard. A resolved plan is plain\n * data, but a customer's `resolveData` could stash a non-serializable value on\n * `props.resolved` — degrade to a placeholder rather than throwing inside a\n * debug panel.\n */\nfunction safeStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n try {\n return JSON.stringify(\n value,\n (_key, val) => {\n if (typeof val === 'object' && val !== null) {\n if (seen.has(val)) return '[Circular]';\n seen.add(val);\n }\n if (typeof val === 'function') return `[Function ${val.name || 'anonymous'}]`;\n if (typeof val === 'undefined') return '[undefined]';\n return val;\n },\n 2\n );\n } catch (err) {\n return `[DebugExperience: could not serialize plan — ${(err as Error).message}]`;\n }\n}\n"],"mappings":"AAuCI,SAcE,KAdF;AAVG,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,cAAc;AAChB,GAAoC;AAClC,QAAM,YAAY,WAAW,MAAM;AACnC,QAAM,UAAU,2BAAsB,SAAS,kBAAkB,cAAc,IAAI,KAAK,GAAG,GACzF,WAAW,WAAW,eAAe,WAAW,SAAS,UAAU,KAAK,EAC1E;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,0BAAsB;AAAA,MACtB,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,YAAY;AAAA,YACd;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAW;AAAA,cACX,YAAY;AAAA,cACZ,WAAW;AAAA,YACb;AAAA,YAEC,wBAAc,UAAU;AAAA;AAAA,QAC3B;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,cAAc,OAAwB;AAC7C,QAAM,OAAO,oBAAI,QAAgB;AACjC,MAAI;AACF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC,MAAM,QAAQ;AACb,YAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,cAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,eAAK,IAAI,GAAG;AAAA,QACd;AACA,YAAI,OAAO,QAAQ,WAAY,QAAO,aAAa,IAAI,QAAQ,WAAW;AAC1E,YAAI,OAAO,QAAQ,YAAa,QAAO;AACvC,eAAO;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,qDAAiD,IAAc,OAAO;AAAA,EAC/E;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/debug-experience.tsx"],"sourcesContent":["/*\n * First-party debug panel. Renders the resolved Experience plan as pretty\n * JSON so a customer can see exactly what the SDK interpreted from the payload\n * — node tree, registrations, resolved props, viewports.\n *\n * Two ways to use it:\n * - Auto-mounted by the renderers when `debug` is on (above the tree).\n * - Mounted manually anywhere: `<DebugExperience experience={plan} />`.\n *\n * v1 is just the JSON dump wrapped in a native <details> so it collapses\n * without any client JS (safe in server components). Room to grow into a\n * node-tree explorer, viewport indicator, and resolveData timing panel — kept\n * deliberately small for now.\n *\n * No React hooks here on purpose: it must render in both server and client\n * renderer subtrees.\n */\n\nimport type { ReactNode } from 'react';\n\nimport type { PortableRenderPlan } from '@contentful/experiences-sdk-core';\n\nexport interface DebugExperienceProps {\n /** The resolved plan to inspect (what a renderer receives as `experience`). */\n experience: PortableRenderPlan;\n /** Start expanded. Defaults to collapsed to stay out of the way. */\n defaultOpen?: boolean;\n}\n\nexport function DebugExperience({\n experience,\n defaultOpen = false,\n}: DebugExperienceProps): ReactNode {\n const nodeCount = experience.nodes.length;\n const summary = `Experience debug — ${nodeCount} top-level node${nodeCount === 1 ? '' : 's'}${\n experience.experienceTemplate\n ? `, experience template: ${experience.experienceTemplate.experienceTemplateId}`\n : ''\n }`;\n\n return (\n <details\n open={defaultOpen}\n data-experiences-debug\n style={{\n margin: '1rem 0',\n border: '1px solid #6b7280',\n borderRadius: '6px',\n background: '#0b1021',\n color: '#e2e8f0',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.75rem',\n overflow: 'hidden',\n }}\n >\n <summary\n style={{\n cursor: 'pointer',\n padding: '0.5rem 0.75rem',\n background: '#111827',\n userSelect: 'none',\n }}\n >\n {summary}\n </summary>\n <pre\n style={{\n margin: 0,\n padding: '0.75rem',\n overflow: 'auto',\n maxHeight: '32rem',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n }}\n >\n {safeStringify(experience)}\n </pre>\n </details>\n );\n}\n\n/**\n * JSON.stringify with a circular-reference guard. A resolved plan is plain\n * data, but a customer's `resolveData` could stash a non-serializable value on\n * `props.resolved` — degrade to a placeholder rather than throwing inside a\n * debug panel.\n */\nfunction safeStringify(value: unknown): string {\n const seen = new WeakSet<object>();\n try {\n return JSON.stringify(\n value,\n (_key, val) => {\n if (typeof val === 'object' && val !== null) {\n if (seen.has(val)) return '[Circular]';\n seen.add(val);\n }\n if (typeof val === 'function') return `[Function ${val.name || 'anonymous'}]`;\n if (typeof val === 'undefined') return '[undefined]';\n return val;\n },\n 2\n );\n } catch (err) {\n return `[DebugExperience: could not serialize plan — ${(err as Error).message}]`;\n }\n}\n"],"mappings":"AAyCI,SAcE,KAdF;AAZG,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,cAAc;AAChB,GAAoC;AAClC,QAAM,YAAY,WAAW,MAAM;AACnC,QAAM,UAAU,2BAAsB,SAAS,kBAAkB,cAAc,IAAI,KAAK,GAAG,GACzF,WAAW,qBACP,0BAA0B,WAAW,mBAAmB,oBAAoB,KAC5E,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,0BAAsB;AAAA,MACtB,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,YAAY;AAAA,YACd;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAW;AAAA,cACX,YAAY;AAAA,cACZ,WAAW;AAAA,YACb;AAAA,YAEC,wBAAc,UAAU;AAAA;AAAA,QAC3B;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,cAAc,OAAwB;AAC7C,QAAM,OAAO,oBAAI,QAAgB;AACjC,MAAI;AACF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC,MAAM,QAAQ;AACb,YAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,cAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,eAAK,IAAI,GAAG;AAAA,QACd;AACA,YAAI,OAAO,QAAQ,WAAY,QAAO,aAAa,IAAI,QAAQ,WAAW;AAC1E,YAAI,OAAO,QAAQ,YAAa,QAAO;AACvC,eAAO;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,qDAAiD,IAAc,OAAO;AAAA,EAC/E;AACF;","names":[]}
package/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ export { MissingComponent, MissingComponentProps } from './missing-component.js'
4
4
  export { DebugExperience, DebugExperienceProps } from './debug-experience.js';
5
5
  export { UseActiveViewportResult, useActiveViewport } from './use-active-viewport.js';
6
6
  export { RenderUnknown } from './nodes-renderer.js';
7
- export { useContentfulComponent, useContentfulTemplate, useExperience } from './context.js';
7
+ export { useContentfulComponent, useContentfulExperienceTemplate, useExperience } from './context.js';
8
8
  export { useDesignValues } from './use-design-values.js';
9
9
  export { ToCssOptions, toCss } from './design-utils.js';
10
- export { ComponentConfig, Components, Config, ContentfulComponent, ContentfulTemplate, Registration, RenderContext, TemplateConfig, TemplateRegistration, Templates, defineComponent, defineTemplate, normalizeComponentRegistration, normalizeTemplateRegistration } from './types.js';
11
- export { ComponentTypeNode, ComponentTypeRef, DesignPropValue, DesignToken, ExperienceContext, ExperienceNode, ExperiencePayload, ExperienceSys, ManualDesignValue, PortableRegistration, PortableRenderNode, PortableRenderPlan, PortableTemplate, ResolveContext, ResolveExperienceOptions, ResolveToken, ResolverConfig, TemplateNode, TemplateRef, ValuesByViewport, ViewportDef, resolveExperience } from '@contentful/experiences-sdk-core';
10
+ export { ComponentConfig, Components, Config, ContentfulComponent, ContentfulExperienceTemplate, ExperienceTemplateConfig, ExperienceTemplateRegistration, ExperienceTemplates, Registration, RenderContext, defineComponent, defineExperienceTemplate, normalizeComponentRegistration, normalizeExperienceTemplateRegistration } from './types.js';
11
+ export { ComponentNode, ComponentRef, DesignPropValue, DesignToken, ExperienceContext, ExperienceNode, ExperiencePayload, ExperienceSys, ExperienceTemplateNode, ExperienceTemplateRef, ManualDesignValue, PortableExperienceTemplate, PortableRegistration, PortableRenderNode, PortableRenderPlan, ResolveContext, ResolveExperienceOptions, ResolveToken, ResolverConfig, ValuesByViewport, ViewportDef, resolveExperience } from '@contentful/experiences-sdk-core';
12
12
  export { CSS_PROPERTIES, getValueForViewport, getViewportIndex, isCssProperty, resolveDesignProperties, toCssKey, toCssMediaQuery } from '@contentful/experiences-design';
13
- export { ClientOptions, ContentfulViewDelivery, ContentfulViewDeliveryClient, CreateClientOptions, DELIVERY_HOST, ExperienceOptions, NotFoundError, PREVIEW_HOST, ResolveOptions, createClient, fetchExperience } from '@contentful/experiences-client';
13
+ export { ALPHA_FEATURE_HEADER, ClientOptions, ContentfulViewDelivery, ContentfulViewDeliveryClient, CreateClientOptions, DELIVERY_HOST, ExperienceOptions, NEW_EXO_ENTITY_TYPES, NEW_EXO_ENTITY_TYPES_HEADERS, NotFoundError, PREVIEW_HOST, ResolveOptions, createClient, fetchExperience } from '@contentful/experiences-client';
14
14
  import 'react';
package/dist/index.js CHANGED
@@ -6,14 +6,14 @@ import { ServerExperienceRenderer } from "./server-renderer";
6
6
  import { MissingComponent } from "./missing-component";
7
7
  import { DebugExperience } from "./debug-experience";
8
8
  import { useActiveViewport } from "./use-active-viewport";
9
- import { useExperience, useContentfulComponent, useContentfulTemplate } from "./context";
9
+ import { useExperience, useContentfulComponent, useContentfulExperienceTemplate } from "./context";
10
10
  import { useDesignValues } from "./use-design-values";
11
11
  import { toCss } from "./design-utils";
12
12
  import {
13
13
  defineComponent,
14
- defineTemplate,
14
+ defineExperienceTemplate,
15
15
  normalizeComponentRegistration,
16
- normalizeTemplateRegistration
16
+ normalizeExperienceTemplateRegistration
17
17
  } from "./types";
18
18
  import { resolveExperience } from "@contentful/experiences-sdk-core";
19
19
  import {
@@ -26,15 +26,19 @@ import {
26
26
  toCssMediaQuery
27
27
  } from "@contentful/experiences-design";
28
28
  import {
29
+ ALPHA_FEATURE_HEADER,
29
30
  ContentfulViewDelivery,
30
31
  ContentfulViewDeliveryClient,
31
32
  DELIVERY_HOST,
33
+ NEW_EXO_ENTITY_TYPES,
34
+ NEW_EXO_ENTITY_TYPES_HEADERS,
32
35
  NotFoundError,
33
36
  PREVIEW_HOST,
34
37
  createClient,
35
38
  fetchExperience
36
39
  } from "@contentful/experiences-client";
37
40
  export {
41
+ ALPHA_FEATURE_HEADER,
38
42
  CSS_PROPERTIES,
39
43
  ClientExperienceRenderer2 as ClientExperienceRenderer,
40
44
  ContentfulViewDelivery,
@@ -43,18 +47,20 @@ export {
43
47
  DebugExperience,
44
48
  ClientExperienceRenderer as ExperienceRenderer,
45
49
  MissingComponent,
50
+ NEW_EXO_ENTITY_TYPES,
51
+ NEW_EXO_ENTITY_TYPES_HEADERS,
46
52
  NotFoundError,
47
53
  PREVIEW_HOST,
48
54
  ServerExperienceRenderer,
49
55
  createClient,
50
56
  defineComponent,
51
- defineTemplate,
57
+ defineExperienceTemplate,
52
58
  fetchExperience,
53
59
  getValueForViewport,
54
60
  getViewportIndex,
55
61
  isCssProperty,
56
62
  normalizeComponentRegistration,
57
- normalizeTemplateRegistration,
63
+ normalizeExperienceTemplateRegistration,
58
64
  resolveDesignProperties,
59
65
  resolveExperience,
60
66
  toCss,
@@ -62,7 +68,7 @@ export {
62
68
  toCssMediaQuery,
63
69
  useActiveViewport,
64
70
  useContentfulComponent,
65
- useContentfulTemplate,
71
+ useContentfulExperienceTemplate,
66
72
  useDesignValues,
67
73
  useExperience
68
74
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/*\n * Public API surface for `@contentful/experiences-react`.\n *\n * Customers add ONLY this package to their app's dependencies. Everything\n * needed to render an Experience — types, the resolver, viewport utilities,\n * the renderer components, the authoring helpers — is re-exported from here.\n * The internal `@contentful/experiences-sdk-core` and\n * `@contentful/experiences-design` packages are workspace-only implementation\n * details; they are not part of the public API.\n *\n * `ExperienceRenderer` is an alias for `ClientExperienceRenderer`; SSR\n * consumers explicitly import `ServerExperienceRenderer`.\n */\n\n// ─── Renderers ─────────────────────────────────────────────────────────────\nexport {\n ClientExperienceRenderer as ExperienceRenderer,\n ClientExperienceRenderer,\n} from './client-renderer';\nexport type { ClientExperienceRendererProps as ExperienceRendererProps } from './client-renderer';\nexport type { ClientExperienceRendererProps } from './client-renderer';\n\nexport { ServerExperienceRenderer } from './server-renderer';\nexport type { ServerExperienceRendererProps } from './server-renderer';\n\nexport { MissingComponent } from './missing-component';\nexport type { MissingComponentProps } from './missing-component';\n\nexport { DebugExperience } from './debug-experience';\nexport type { DebugExperienceProps } from './debug-experience';\n\nexport { useActiveViewport } from './use-active-viewport';\nexport type { UseActiveViewportResult } from './use-active-viewport';\n\nexport type { RenderUnknown } from './nodes-renderer';\n\n// ─── Runtime context hooks ───────────────────────────────────────────────\nexport { useExperience, useContentfulComponent, useContentfulTemplate } from './context';\nexport { useDesignValues } from './use-design-values';\nexport { toCss } from './design-utils';\nexport type { ToCssOptions } from './design-utils';\n\n// ─── Authoring helpers + Config types ─────────────────────────────────────\nexport {\n defineComponent,\n defineTemplate,\n normalizeComponentRegistration,\n normalizeTemplateRegistration,\n} from './types';\nexport type {\n ComponentConfig,\n Components,\n Config,\n ContentfulComponent,\n ContentfulTemplate,\n Registration,\n RenderContext,\n ResolveToken,\n TemplateConfig,\n TemplateRegistration,\n Templates,\n} from './types';\n\n// ─── Resolver (re-exported from render-core) ──────────────────────────────\nexport { resolveExperience } from '@contentful/experiences-sdk-core';\nexport type { ResolverConfig, ResolveExperienceOptions } from '@contentful/experiences-sdk-core';\n\n// ─── Core IR + payload types (re-exported from render-core) ───────────────\nexport type {\n ComponentTypeNode,\n ComponentTypeRef,\n DesignPropValue,\n DesignToken,\n ExperienceContext,\n ExperienceNode,\n ExperiencePayload,\n ExperienceSys,\n ManualDesignValue,\n PortableRegistration,\n PortableRenderNode,\n PortableRenderPlan,\n PortableTemplate,\n ResolveContext,\n TemplateNode,\n TemplateRef,\n ValuesByViewport,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\n// ─── Design utilities (re-exported from design) ───────────────────────────\nexport {\n CSS_PROPERTIES,\n getValueForViewport,\n getViewportIndex,\n isCssProperty,\n resolveDesignProperties,\n toCssKey,\n toCssMediaQuery,\n} from '@contentful/experiences-design';\n\n// ─── Delivery client + fetchExperience ────────────────────────────────────\nexport {\n ContentfulViewDelivery,\n ContentfulViewDeliveryClient,\n DELIVERY_HOST,\n NotFoundError,\n PREVIEW_HOST,\n createClient,\n fetchExperience,\n} from '@contentful/experiences-client';\nexport type {\n ClientOptions,\n CreateClientOptions,\n ExperienceOptions,\n ResolveOptions,\n} from '@contentful/experiences-client';\n"],"mappings":"AAeA;AAAA,EAC8B;AAAA,EAC5B,4BAAAA;AAAA,OACK;AAIP,SAAS,gCAAgC;AAGzC,SAAS,wBAAwB;AAGjC,SAAS,uBAAuB;AAGhC,SAAS,yBAAyB;AAMlC,SAAS,eAAe,wBAAwB,6BAA6B;AAC7E,SAAS,uBAAuB;AAChC,SAAS,aAAa;AAItB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgBP,SAAS,yBAAyB;AA0BlC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":["ClientExperienceRenderer"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/*\n * Public API surface for `@contentful/experiences-react`.\n *\n * Customers add ONLY this package to their app's dependencies. Everything\n * needed to render an Experience — types, the resolver, viewport utilities,\n * the renderer components, the authoring helpers — is re-exported from here.\n * The internal `@contentful/experiences-sdk-core` and\n * `@contentful/experiences-design` packages are workspace-only implementation\n * details; they are not part of the public API.\n *\n * `ExperienceRenderer` is an alias for `ClientExperienceRenderer`; SSR\n * consumers explicitly import `ServerExperienceRenderer`.\n */\n\n// ─── Renderers ─────────────────────────────────────────────────────────────\nexport {\n ClientExperienceRenderer as ExperienceRenderer,\n ClientExperienceRenderer,\n} from './client-renderer';\nexport type { ClientExperienceRendererProps as ExperienceRendererProps } from './client-renderer';\nexport type { ClientExperienceRendererProps } from './client-renderer';\n\nexport { ServerExperienceRenderer } from './server-renderer';\nexport type { ServerExperienceRendererProps } from './server-renderer';\n\nexport { MissingComponent } from './missing-component';\nexport type { MissingComponentProps } from './missing-component';\n\nexport { DebugExperience } from './debug-experience';\nexport type { DebugExperienceProps } from './debug-experience';\n\nexport { useActiveViewport } from './use-active-viewport';\nexport type { UseActiveViewportResult } from './use-active-viewport';\n\nexport type { RenderUnknown } from './nodes-renderer';\n\n// ─── Runtime context hooks ───────────────────────────────────────────────\nexport { useExperience, useContentfulComponent, useContentfulExperienceTemplate } from './context';\nexport { useDesignValues } from './use-design-values';\nexport { toCss } from './design-utils';\nexport type { ToCssOptions } from './design-utils';\n\n// ─── Authoring helpers + Config types ─────────────────────────────────────\nexport {\n defineComponent,\n defineExperienceTemplate,\n normalizeComponentRegistration,\n normalizeExperienceTemplateRegistration,\n} from './types';\nexport type {\n ComponentConfig,\n Components,\n Config,\n ContentfulComponent,\n ContentfulExperienceTemplate,\n ExperienceTemplateConfig,\n ExperienceTemplateRegistration,\n ExperienceTemplates,\n Registration,\n RenderContext,\n ResolveToken,\n} from './types';\n\n// ─── Resolver (re-exported from render-core) ──────────────────────────────\nexport { resolveExperience } from '@contentful/experiences-sdk-core';\nexport type { ResolverConfig, ResolveExperienceOptions } from '@contentful/experiences-sdk-core';\n\n// ─── Core IR + payload types (re-exported from render-core) ───────────────\nexport type {\n ComponentNode,\n ComponentRef,\n DesignPropValue,\n DesignToken,\n ExperienceContext,\n ExperienceNode,\n ExperiencePayload,\n ExperienceSys,\n ExperienceTemplateNode,\n ExperienceTemplateRef,\n ManualDesignValue,\n PortableExperienceTemplate,\n PortableRegistration,\n PortableRenderNode,\n PortableRenderPlan,\n ResolveContext,\n ValuesByViewport,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\n\n// ─── Design utilities (re-exported from design) ───────────────────────────\nexport {\n CSS_PROPERTIES,\n getValueForViewport,\n getViewportIndex,\n isCssProperty,\n resolveDesignProperties,\n toCssKey,\n toCssMediaQuery,\n} from '@contentful/experiences-design';\n\n// ─── Delivery client + fetchExperience ────────────────────────────────────\nexport {\n ALPHA_FEATURE_HEADER,\n ContentfulViewDelivery,\n ContentfulViewDeliveryClient,\n DELIVERY_HOST,\n NEW_EXO_ENTITY_TYPES,\n NEW_EXO_ENTITY_TYPES_HEADERS,\n NotFoundError,\n PREVIEW_HOST,\n createClient,\n fetchExperience,\n} from '@contentful/experiences-client';\nexport type {\n ClientOptions,\n CreateClientOptions,\n ExperienceOptions,\n ResolveOptions,\n} from '@contentful/experiences-client';\n"],"mappings":"AAeA;AAAA,EAC8B;AAAA,EAC5B,4BAAAA;AAAA,OACK;AAIP,SAAS,gCAAgC;AAGzC,SAAS,wBAAwB;AAGjC,SAAS,uBAAuB;AAGhC,SAAS,yBAAyB;AAMlC,SAAS,eAAe,wBAAwB,uCAAuC;AACvF,SAAS,uBAAuB;AAChC,SAAS,aAAa;AAItB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgBP,SAAS,yBAAyB;AA0BlC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":["ClientExperienceRenderer"]}
@@ -1,10 +1,10 @@
1
1
  import { ReactNode } from 'react';
2
2
 
3
3
  interface MissingComponentProps {
4
- componentTypeId: string;
4
+ componentId: string;
5
5
  /** Optional — only present when the payload supplied an id for this node. */
6
6
  nodeId?: string;
7
7
  }
8
- declare function MissingComponent({ componentTypeId, nodeId }: MissingComponentProps): ReactNode;
8
+ declare function MissingComponent({ componentId, nodeId }: MissingComponentProps): ReactNode;
9
9
 
10
10
  export { MissingComponent, type MissingComponentProps };
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useExperience } from "./context";
4
- function MissingComponent({ componentTypeId, nodeId }) {
4
+ function MissingComponent({ componentId, nodeId }) {
5
5
  const { debug } = useExperience();
6
6
  if (typeof console !== "undefined") {
7
7
  const idLabel = nodeId ? ` (nodeId: ${nodeId})` : "";
8
8
  console.warn(
9
- `[@contentful/experiences] No component registered for type "${componentTypeId}"${idLabel}.`
9
+ `[@contentful/experiences] No component registered for id "${componentId}"${idLabel}.`
10
10
  );
11
11
  }
12
12
  if (!debug) return null;
@@ -21,11 +21,11 @@ function MissingComponent({ componentTypeId, nodeId }) {
21
21
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22
22
  fontSize: "0.8125rem"
23
23
  },
24
- "data-experiences-missing": componentTypeId,
24
+ "data-experiences-missing": componentId,
25
25
  children: [
26
26
  /* @__PURE__ */ jsxs("strong", { children: [
27
27
  "Missing component \u2018",
28
- componentTypeId,
28
+ componentId,
29
29
  "\u2019"
30
30
  ] }),
31
31
  /* @__PURE__ */ jsxs("p", { style: { margin: "0.5rem 0" }, children: [
@@ -33,7 +33,7 @@ function MissingComponent({ componentTypeId, nodeId }) {
33
33
  /* @__PURE__ */ jsx("code", { children: "components" }),
34
34
  " map:"
35
35
  ] }),
36
- /* @__PURE__ */ jsx("pre", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: JSON.stringify({ componentTypeId, nodeId: nodeId ?? null }, null, 2) })
36
+ /* @__PURE__ */ jsx("pre", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: JSON.stringify({ componentId, nodeId: nodeId ?? null }, null, 2) })
37
37
  ]
38
38
  }
39
39
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/missing-component.tsx"],"sourcesContent":["/*\n * Default fallback rendered when an instance references a component type\n * not present in the Config.\n *\n * Behavior: a visible debug box when `debug` is on, silent null otherwise.\n * The console.warn fires either way so the miss is never fully silent.\n * Customers can override per-render via <ExperienceRenderer renderUnknown=...>.\n */\n'use client';\n\nimport type { ReactNode } from 'react';\n\nimport { useExperience } from './context';\n\nexport interface MissingComponentProps {\n componentTypeId: string;\n /** Optional — only present when the payload supplied an id for this node. */\n nodeId?: string;\n}\n\nexport function MissingComponent({ componentTypeId, nodeId }: MissingComponentProps): ReactNode {\n const { debug } = useExperience();\n if (typeof console !== 'undefined') {\n const idLabel = nodeId ? ` (nodeId: ${nodeId})` : '';\n console.warn(\n `[@contentful/experiences] No component registered for type \"${componentTypeId}\"${idLabel}.`\n );\n }\n if (!debug) return null;\n // In debug mode the fallback is richer than a bare red box: it surfaces the\n // exact registration the customer needs to add (componentTypeId) and the\n // node id so a miss in a large tree is locatable.\n return (\n <div\n style={{\n border: '2px solid red',\n padding: '1rem',\n color: 'red',\n background: '#fff',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.8125rem',\n }}\n data-experiences-missing={componentTypeId}\n >\n <strong>Missing component &lsquo;{componentTypeId}&rsquo;</strong>\n <p style={{ margin: '0.5rem 0' }}>\n This component is referenced by the Experience payload but is not registered in the Config.\n Register it under this key in your <code>components</code> map:\n </p>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}>\n {JSON.stringify({ componentTypeId, nodeId: nodeId ?? null }, null, 2)}\n </pre>\n </div>\n );\n}\n"],"mappings":";AA4CM,SAGqC,KAHrC;AAhCN,SAAS,qBAAqB;AAQvB,SAAS,iBAAiB,EAAE,iBAAiB,OAAO,GAAqC;AAC9F,QAAM,EAAE,MAAM,IAAI,cAAc;AAChC,MAAI,OAAO,YAAY,aAAa;AAClC,UAAM,UAAU,SAAS,aAAa,MAAM,MAAM;AAClD,YAAQ;AAAA,MACN,+DAA+D,eAAe,IAAI,OAAO;AAAA,IAC3F;AAAA,EACF;AACA,MAAI,CAAC,MAAO,QAAO;AAInB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ;AAAA,MACA,4BAA0B;AAAA,MAE1B;AAAA,6BAAC,YAAO;AAAA;AAAA,UAA0B;AAAA,UAAgB;AAAA,WAAO;AAAA,QACzD,qBAAC,OAAE,OAAO,EAAE,QAAQ,WAAW,GAAG;AAAA;AAAA,UAEG,oBAAC,UAAK,wBAAU;AAAA,UAAO;AAAA,WAC5D;AAAA,QACA,oBAAC,SAAI,OAAO,EAAE,QAAQ,GAAG,YAAY,WAAW,GAC7C,eAAK,UAAU,EAAE,iBAAiB,QAAQ,UAAU,KAAK,GAAG,MAAM,CAAC,GACtE;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/missing-component.tsx"],"sourcesContent":["/*\n * Default fallback rendered when an instance references a component\n * not present in the Config.\n *\n * Behavior: a visible debug box when `debug` is on, silent null otherwise.\n * The console.warn fires either way so the miss is never fully silent.\n * Customers can override per-render via <ExperienceRenderer renderUnknown=...>.\n */\n'use client';\n\nimport type { ReactNode } from 'react';\n\nimport { useExperience } from './context';\n\nexport interface MissingComponentProps {\n componentId: string;\n /** Optional — only present when the payload supplied an id for this node. */\n nodeId?: string;\n}\n\nexport function MissingComponent({ componentId, nodeId }: MissingComponentProps): ReactNode {\n const { debug } = useExperience();\n if (typeof console !== 'undefined') {\n const idLabel = nodeId ? ` (nodeId: ${nodeId})` : '';\n console.warn(\n `[@contentful/experiences] No component registered for id \"${componentId}\"${idLabel}.`\n );\n }\n if (!debug) return null;\n // In debug mode the fallback is richer than a bare red box: it surfaces the\n // exact registration the customer needs to add (componentId) and the\n // node id so a miss in a large tree is locatable.\n return (\n <div\n style={{\n border: '2px solid red',\n padding: '1rem',\n color: 'red',\n background: '#fff',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: '0.8125rem',\n }}\n data-experiences-missing={componentId}\n >\n <strong>Missing component &lsquo;{componentId}&rsquo;</strong>\n <p style={{ margin: '0.5rem 0' }}>\n This component is referenced by the Experience payload but is not registered in the Config.\n Register it under this key in your <code>components</code> map:\n </p>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}>\n {JSON.stringify({ componentId, nodeId: nodeId ?? null }, null, 2)}\n </pre>\n </div>\n );\n}\n"],"mappings":";AA4CM,SAGqC,KAHrC;AAhCN,SAAS,qBAAqB;AAQvB,SAAS,iBAAiB,EAAE,aAAa,OAAO,GAAqC;AAC1F,QAAM,EAAE,MAAM,IAAI,cAAc;AAChC,MAAI,OAAO,YAAY,aAAa;AAClC,UAAM,UAAU,SAAS,aAAa,MAAM,MAAM;AAClD,YAAQ;AAAA,MACN,6DAA6D,WAAW,IAAI,OAAO;AAAA,IACrF;AAAA,EACF;AACA,MAAI,CAAC,MAAO,QAAO;AAInB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ;AAAA,MACA,4BAA0B;AAAA,MAE1B;AAAA,6BAAC,YAAO;AAAA;AAAA,UAA0B;AAAA,UAAY;AAAA,WAAO;AAAA,QACrD,qBAAC,OAAE,OAAO,EAAE,QAAQ,WAAW,GAAG;AAAA;AAAA,UAEG,oBAAC,UAAK,wBAAU;AAAA,UAAO;AAAA,WAC5D;AAAA,QACA,oBAAC,SAAI,OAAO,EAAE,QAAQ,GAAG,YAAY,WAAW,GAC7C,eAAK,UAAU,EAAE,aAAa,QAAQ,UAAU,KAAK,GAAG,MAAM,CAAC,GAClE;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { PortableRenderNode, ViewportDef, PortableTemplate } from '@contentful/experiences-sdk-core';
2
+ import { PortableRenderNode, ViewportDef, PortableExperienceTemplate } from '@contentful/experiences-sdk-core';
3
3
  import { MissingComponentProps } from './missing-component.js';
4
4
  import { Config } from './types.js';
5
5
 
@@ -12,17 +12,18 @@ interface NodesRendererProps {
12
12
  renderUnknown: RenderUnknown;
13
13
  }
14
14
  declare function NodesRenderer({ nodes, config, viewports, activeViewportIndex, renderUnknown, }: NodesRendererProps): ReactNode;
15
- interface WrapWithTemplateProps {
16
- template: PortableTemplate | undefined;
15
+ interface WrapWithExperienceTemplateProps {
16
+ experienceTemplate: PortableExperienceTemplate | undefined;
17
17
  config: Config;
18
18
  viewports: ViewportDef[];
19
19
  activeViewportIndex: number;
20
20
  children: ReactNode;
21
21
  }
22
22
  /**
23
- * Wraps the rendered nodes with the page-level template. If the template is
24
- * referenced but unregistered, warns once and renders children unwrapped.
23
+ * Wraps the rendered nodes with the page-level Experience Template. If the
24
+ * template is referenced but unregistered, warns once and renders children
25
+ * unwrapped.
25
26
  */
26
- declare function WrapWithTemplate({ template, config, viewports, activeViewportIndex, children, }: WrapWithTemplateProps): ReactNode;
27
+ declare function WrapWithExperienceTemplate({ experienceTemplate, config, viewports, activeViewportIndex, children, }: WrapWithExperienceTemplateProps): ReactNode;
27
28
 
28
- export { NodesRenderer, type NodesRendererProps, type RenderUnknown, WrapWithTemplate, type WrapWithTemplateProps };
29
+ export { NodesRenderer, type NodesRendererProps, type RenderUnknown, WrapWithExperienceTemplate, type WrapWithExperienceTemplateProps };
@@ -3,12 +3,12 @@ import { Fragment, createElement } from "react";
3
3
  import { applyTokenResolver, resolveDesignProperties } from "@contentful/experiences-design";
4
4
  import {
5
5
  ContentfulComponentProvider,
6
- ContentfulTemplateProvider,
6
+ ContentfulExperienceTemplateProvider,
7
7
  ResolvedDesignProvider
8
8
  } from "./context";
9
9
  import {
10
10
  normalizeComponentRegistration,
11
- normalizeTemplateRegistration
11
+ normalizeExperienceTemplateRegistration
12
12
  } from "./types";
13
13
  function NodesRenderer({
14
14
  nodes,
@@ -37,10 +37,10 @@ function NodeRenderer({
37
37
  activeViewportIndex,
38
38
  renderUnknown
39
39
  }) {
40
- const { componentTypeId } = node.registration;
41
- const entry = config.components[componentTypeId];
40
+ const { componentId } = node.registration;
41
+ const entry = config.components[componentId];
42
42
  if (!entry) {
43
- return createElement(renderUnknown, { componentTypeId, nodeId: node.nodeId });
43
+ return createElement(renderUnknown, { componentId, nodeId: node.nodeId });
44
44
  }
45
45
  const componentConfig = normalizeComponentRegistration(entry);
46
46
  const slotProps = {};
@@ -63,11 +63,11 @@ function NodeRenderer({
63
63
  );
64
64
  if (unresolved.length && typeof console !== "undefined") {
65
65
  console.warn(
66
- `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on "${componentTypeId}": ${unresolved.join(", ")}. useDesignValues() will omit those keys.`
66
+ `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on "${componentId}": ${unresolved.join(", ")}. useDesignValues() will omit those keys.`
67
67
  );
68
68
  }
69
69
  const contentful = {
70
- componentTypeId,
70
+ componentId,
71
71
  nodeId: node.nodeId,
72
72
  content: node.props.content,
73
73
  design: node.props.design,
@@ -81,26 +81,26 @@ function NodeRenderer({
81
81
  };
82
82
  return /* @__PURE__ */ jsx(ContentfulComponentProvider, { value: contentful, children: /* @__PURE__ */ jsx(ResolvedDesignProvider, { value: tokenResolvedDesign, children: createElement(componentConfig.component, composed) }) });
83
83
  }
84
- function WrapWithTemplate({
85
- template,
84
+ function WrapWithExperienceTemplate({
85
+ experienceTemplate,
86
86
  config,
87
87
  viewports,
88
88
  activeViewportIndex,
89
89
  children
90
90
  }) {
91
- if (!template) return /* @__PURE__ */ jsx(Fragment, { children });
92
- const entry = config.templates?.[template.templateId];
91
+ if (!experienceTemplate) return /* @__PURE__ */ jsx(Fragment, { children });
92
+ const entry = config.experienceTemplates?.[experienceTemplate.experienceTemplateId];
93
93
  if (!entry) {
94
94
  if (typeof console !== "undefined") {
95
95
  console.warn(
96
- `[@contentful/experiences-react] No template registered for id "${template.templateId}". Rendering nodes without the template wrapper.`
96
+ `[@contentful/experiences-react] No experience template registered for id "${experienceTemplate.experienceTemplateId}". Rendering nodes without the experience template wrapper.`
97
97
  );
98
98
  }
99
99
  return /* @__PURE__ */ jsx(Fragment, { children });
100
100
  }
101
- const templateConfig = normalizeTemplateRegistration(entry);
101
+ const experienceTemplateConfig = normalizeExperienceTemplateRegistration(entry);
102
102
  const resolvedDesign = resolveDesignProperties(
103
- template.props.design,
103
+ experienceTemplate.props.design,
104
104
  viewports,
105
105
  activeViewportIndex
106
106
  );
@@ -110,25 +110,25 @@ function WrapWithTemplate({
110
110
  );
111
111
  if (unresolved.length && typeof console !== "undefined") {
112
112
  console.warn(
113
- `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on template "${template.templateId}": ${unresolved.join(", ")}. useDesignValues() will omit those keys.`
113
+ `[@contentful/experiences-react] resolveToken returned undefined for token id(s) on experience template "${experienceTemplate.experienceTemplateId}": ${unresolved.join(", ")}. useDesignValues() will omit those keys.`
114
114
  );
115
115
  }
116
116
  const contentful = {
117
- templateId: template.templateId,
118
- content: template.props.content,
119
- design: template.props.design,
120
- resolved: template.props.resolved
117
+ experienceTemplateId: experienceTemplate.experienceTemplateId,
118
+ content: experienceTemplate.props.content,
119
+ design: experienceTemplate.props.design,
120
+ resolved: experienceTemplate.props.resolved
121
121
  };
122
122
  const composed = {
123
- ...templateConfig.defaults,
124
- ...template.props.content,
125
- ...template.props.resolved,
123
+ ...experienceTemplateConfig.defaults,
124
+ ...experienceTemplate.props.content,
125
+ ...experienceTemplate.props.resolved,
126
126
  children
127
127
  };
128
- return /* @__PURE__ */ jsx(ContentfulTemplateProvider, { value: contentful, children: /* @__PURE__ */ jsx(ResolvedDesignProvider, { value: tokenResolvedDesign, children: createElement(templateConfig.component, composed) }) });
128
+ return /* @__PURE__ */ jsx(ContentfulExperienceTemplateProvider, { value: contentful, children: /* @__PURE__ */ jsx(ResolvedDesignProvider, { value: tokenResolvedDesign, children: createElement(experienceTemplateConfig.component, composed) }) });
129
129
  }
130
130
  export {
131
131
  NodesRenderer,
132
- WrapWithTemplate
132
+ WrapWithExperienceTemplate
133
133
  };
134
134
  //# sourceMappingURL=nodes-renderer.js.map
@@ -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 PortableRenderNode,\n PortableTemplate,\n ViewportDef,\n} from '@contentful/experiences-sdk-core';\nimport { applyTokenResolver, resolveDesignProperties } from '@contentful/experiences-design';\n\nimport {\n ContentfulComponentProvider,\n ContentfulTemplateProvider,\n ResolvedDesignProvider,\n} from './context';\nimport type { MissingComponentProps } from './missing-component';\nimport {\n normalizeComponentRegistration,\n normalizeTemplateRegistration,\n type ContentfulComponent,\n type ContentfulTemplate,\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 { componentTypeId } = node.registration;\n const entry = config.components[componentTypeId];\n if (!entry) {\n return createElement(renderUnknown, { componentTypeId, nodeId: node.nodeId });\n }\n const componentConfig = normalizeComponentRegistration(entry);\n\n // Pre-render slot subtrees so components receive ReactNodes by slot name.\n const slotProps: Record<string, ReactNode> = {};\n for (const [slotName, children] of Object.entries(node.slots)) {\n slotProps[slotName] = (\n <NodesRenderer\n nodes={children}\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 \"${componentTypeId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulComponent = {\n componentTypeId,\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 WrapWithTemplateProps {\n template: PortableTemplate | 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 template. If the template is\n * referenced but unregistered, warns once and renders children unwrapped.\n */\nexport function WrapWithTemplate({\n template,\n config,\n viewports,\n activeViewportIndex,\n children,\n}: WrapWithTemplateProps): ReactNode {\n if (!template) return <Fragment>{children}</Fragment>;\n const entry = config.templates?.[template.templateId];\n if (!entry) {\n if (typeof console !== 'undefined') {\n console.warn(\n `[@contentful/experiences-react] No template registered for id \"${template.templateId}\". Rendering nodes without the template wrapper.`\n );\n }\n return <Fragment>{children}</Fragment>;\n }\n const templateConfig = normalizeTemplateRegistration(entry);\n\n const resolvedDesign = resolveDesignProperties(\n template.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 template \"${template.templateId}\": ${unresolved.join(', ')}. useDesignValues() will omit those keys.`\n );\n }\n\n const contentful: ContentfulTemplate = {\n templateId: template.templateId,\n content: template.props.content,\n design: template.props.design,\n resolved: template.props.resolved,\n };\n\n const composed = {\n ...templateConfig.defaults,\n ...template.props.content,\n ...template.props.resolved,\n children,\n };\n\n return (\n <ContentfulTemplateProvider value={contentful}>\n <ResolvedDesignProvider value={tokenResolvedDesign}>\n {createElement(templateConfig.component, composed)}\n </ResolvedDesignProvider>\n </ContentfulTemplateProvider>\n );\n}\n"],"mappings":"AAsDQ;AAhDR,SAAS,UAAU,qBAAqC;AAOxD,SAAS,oBAAoB,+BAA+B;AAE5D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAgBA,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,SACE,oBAAC,YACE,gBAAM,IAAI,CAAC,MAAM,UAChB;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IALK,KAAK,UAAU;AAAA,EAMtB,CACD,GACH;AAEJ;AAUA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiC;AAC/B,QAAM,EAAE,gBAAgB,IAAI,KAAK;AACjC,QAAM,QAAQ,OAAO,WAAW,eAAe;AAC/C,MAAI,CAAC,OAAO;AACV,WAAO,cAAc,eAAe,EAAE,iBAAiB,QAAQ,KAAK,OAAO,CAAC;AAAA,EAC9E;AACA,QAAM,kBAAkB,+BAA+B,KAAK;AAG5D,QAAM,YAAuC,CAAC;AAC9C,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAC7D,cAAU,QAAQ,IAChB;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,EAEJ;AAIA,QAAM,iBAAiB,wBAAwB,KAAK,MAAM,QAAQ,WAAW,mBAAmB;AAChG,QAAM,EAAE,OAAO,qBAAqB,WAAW,IAAI;AAAA,IACjD;AAAA,IACA,OAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,OAAO,YAAY,aAAa;AACvD,YAAQ;AAAA,MACN,uFAAuF,eAAe,MAAM,WAAW,KAAK,IAAI,CAAC;AAAA,IACnI;AAAA,EACF;AAEA,QAAM,aAAkC;AAAA,IACtC;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,MAAM;AAAA,IACpB,QAAQ,KAAK,MAAM;AAAA,IACnB,UAAU,KAAK,MAAM;AAAA,EACvB;AAGA,QAAM,WAAW;AAAA,IACf,GAAG,gBAAgB;AAAA,IACnB,GAAG,KAAK,MAAM;AAAA,IACd,GAAG,KAAK,MAAM;AAAA,IACd,GAAG;AAAA,EACL;AAEA,SACE,oBAAC,+BAA4B,OAAO,YAClC,8BAAC,0BAAuB,OAAO,qBAC5B,wBAAc,gBAAgB,WAAW,QAAQ,GACpD,GACF;AAEJ;AAcO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqC;AACnC,MAAI,CAAC,SAAU,QAAO,oBAAC,YAAU,UAAS;AAC1C,QAAM,QAAQ,OAAO,YAAY,SAAS,UAAU;AACpD,MAAI,CAAC,OAAO;AACV,QAAI,OAAO,YAAY,aAAa;AAClC,cAAQ;AAAA,QACN,kEAAkE,SAAS,UAAU;AAAA,MACvF;AAAA,IACF;AACA,WAAO,oBAAC,YAAU,UAAS;AAAA,EAC7B;AACA,QAAM,iBAAiB,8BAA8B,KAAK;AAE1D,QAAM,iBAAiB;AAAA,IACrB,SAAS,MAAM;AAAA,IACf;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,qBAAqB,WAAW,IAAI;AAAA,IACjD;AAAA,IACA,OAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,OAAO,YAAY,aAAa;AACvD,YAAQ;AAAA,MACN,gGAAgG,SAAS,UAAU,MAAM,WAAW,KAAK,IAAI,CAAC;AAAA,IAChJ;AAAA,EACF;AAEA,QAAM,aAAiC;AAAA,IACrC,YAAY,SAAS;AAAA,IACrB,SAAS,SAAS,MAAM;AAAA,IACxB,QAAQ,SAAS,MAAM;AAAA,IACvB,UAAU,SAAS,MAAM;AAAA,EAC3B;AAEA,QAAM,WAAW;AAAA,IACf,GAAG,eAAe;AAAA,IAClB,GAAG,SAAS,MAAM;AAAA,IAClB,GAAG,SAAS,MAAM;AAAA,IAClB;AAAA,EACF;AAEA,SACE,oBAAC,8BAA2B,OAAO,YACjC,8BAAC,0BAAuB,OAAO,qBAC5B,wBAAc,eAAe,WAAW,QAAQ,GACnD,GACF;AAEJ;","names":[]}
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 slot subtrees so components receive ReactNodes by slot name.\n const slotProps: Record<string, ReactNode> = {};\n for (const [slotName, children] of Object.entries(node.slots)) {\n slotProps[slotName] = (\n <NodesRenderer\n nodes={children}\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":"AAsDQ;AAhDR,SAAS,UAAU,qBAAqC;AAOxD,SAAS,oBAAoB,+BAA+B;AAE5D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAgBA,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,SACE,oBAAC,YACE,gBAAM,IAAI,CAAC,MAAM,UAChB;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IALK,KAAK,UAAU;AAAA,EAMtB,CACD,GACH;AAEJ;AAUA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiC;AAC/B,QAAM,EAAE,YAAY,IAAI,KAAK;AAC7B,QAAM,QAAQ,OAAO,WAAW,WAAW;AAC3C,MAAI,CAAC,OAAO;AACV,WAAO,cAAc,eAAe,EAAE,aAAa,QAAQ,KAAK,OAAO,CAAC;AAAA,EAC1E;AACA,QAAM,kBAAkB,+BAA+B,KAAK;AAG5D,QAAM,YAAuC,CAAC;AAC9C,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAC7D,cAAU,QAAQ,IAChB;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,EAEJ;AAIA,QAAM,iBAAiB,wBAAwB,KAAK,MAAM,QAAQ,WAAW,mBAAmB;AAChG,QAAM,EAAE,OAAO,qBAAqB,WAAW,IAAI;AAAA,IACjD;AAAA,IACA,OAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,OAAO,YAAY,aAAa;AACvD,YAAQ;AAAA,MACN,uFAAuF,WAAW,MAAM,WAAW,KAAK,IAAI,CAAC;AAAA,IAC/H;AAAA,EACF;AAEA,QAAM,aAAkC;AAAA,IACtC;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,MAAM;AAAA,IACpB,QAAQ,KAAK,MAAM;AAAA,IACnB,UAAU,KAAK,MAAM;AAAA,EACvB;AAGA,QAAM,WAAW;AAAA,IACf,GAAG,gBAAgB;AAAA,IACnB,GAAG,KAAK,MAAM;AAAA,IACd,GAAG,KAAK,MAAM;AAAA,IACd,GAAG;AAAA,EACL;AAEA,SACE,oBAAC,+BAA4B,OAAO,YAClC,8BAAC,0BAAuB,OAAO,qBAC5B,wBAAc,gBAAgB,WAAW,QAAQ,GACpD,GACF;AAEJ;AAeO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+C;AAC7C,MAAI,CAAC,mBAAoB,QAAO,oBAAC,YAAU,UAAS;AACpD,QAAM,QAAQ,OAAO,sBAAsB,mBAAmB,oBAAoB;AAClF,MAAI,CAAC,OAAO;AACV,QAAI,OAAO,YAAY,aAAa;AAClC,cAAQ;AAAA,QACN,6EAA6E,mBAAmB,oBAAoB;AAAA,MACtH;AAAA,IACF;AACA,WAAO,oBAAC,YAAU,UAAS;AAAA,EAC7B;AACA,QAAM,2BAA2B,wCAAwC,KAAK;AAE9E,QAAM,iBAAiB;AAAA,IACrB,mBAAmB,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,qBAAqB,WAAW,IAAI;AAAA,IACjD;AAAA,IACA,OAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,OAAO,YAAY,aAAa;AACvD,YAAQ;AAAA,MACN,2GAA2G,mBAAmB,oBAAoB,MAAM,WAAW,KAAK,IAAI,CAAC;AAAA,IAC/K;AAAA,EACF;AAEA,QAAM,aAA2C;AAAA,IAC/C,sBAAsB,mBAAmB;AAAA,IACzC,SAAS,mBAAmB,MAAM;AAAA,IAClC,QAAQ,mBAAmB,MAAM;AAAA,IACjC,UAAU,mBAAmB,MAAM;AAAA,EACrC;AAEA,QAAM,WAAW;AAAA,IACf,GAAG,yBAAyB;AAAA,IAC5B,GAAG,mBAAmB,MAAM;AAAA,IAC5B,GAAG,mBAAmB,MAAM;AAAA,IAC5B;AAAA,EACF;AAEA,SACE,oBAAC,wCAAqC,OAAO,YAC3C,8BAAC,0BAAuB,OAAO,qBAC5B,wBAAc,yBAAyB,WAAW,QAAQ,GAC7D,GACF;AAEJ;","names":[]}
@@ -3,7 +3,7 @@ import { getViewportIndex } from "@contentful/experiences-design";
3
3
  import { DebugExperience } from "./debug-experience";
4
4
  import { ExperienceProvider } from "./context";
5
5
  import { MissingComponent } from "./missing-component";
6
- import { NodesRenderer, WrapWithTemplate } from "./nodes-renderer";
6
+ import { NodesRenderer, WrapWithExperienceTemplate } from "./nodes-renderer";
7
7
  const DEFAULT_CONTEXT = {
8
8
  debug: false,
9
9
  metadata: {},
@@ -38,9 +38,9 @@ function ServerExperienceRenderer({
38
38
  return /* @__PURE__ */ jsxs(ExperienceProvider, { value: renderContext, children: [
39
39
  debug ? /* @__PURE__ */ jsx(DebugExperience, { experience }) : null,
40
40
  /* @__PURE__ */ jsx(
41
- WrapWithTemplate,
41
+ WrapWithExperienceTemplate,
42
42
  {
43
- template: experience.template,
43
+ experienceTemplate: experience.experienceTemplate,
44
44
  config,
45
45
  viewports: experience.viewports,
46
46
  activeViewportIndex,
@@ -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, WrapWithTemplate, 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 <WrapWithTemplate\n template={experience.template}\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 </WrapWithTemplate>\n </ExperienceProvider>\n );\n}\n"],"mappings":"AAmFI,SACW,KADX;AAvEJ,SAAS,wBAAwB;AAEjC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,eAAe,wBAA4C;AAGpE,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,UAAU,WAAW;AAAA,QACrB;AAAA,QACA,WAAW,WAAW;AAAA,QACtB;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
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,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,WAAW;AAAA,YAClB;AAAA,YACA,WAAW,WAAW;AAAA,YACtB;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
package/dist/types.d.ts CHANGED
@@ -6,7 +6,7 @@ export { ResolveContext, ResolveToken } from '@contentful/experiences-sdk-core';
6
6
  * The full Contentful-side payload for a single component instance, exposed
7
7
  * via `useContentfulComponent()` to any descendant of a rendered Experience
8
8
  * node. Useful for custom design-property resolution outside the SDK's
9
- * cascade, branching by `componentTypeId` in a generic wrapper, keying
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
12
  * Design properties stay in their **raw envelope form** here (the same shape
@@ -14,18 +14,19 @@ export { ResolveContext, ResolveToken } from '@contentful/experiences-sdk-core';
14
14
  * resolved values are what `useDesignValues()` returns.
15
15
  */
16
16
  interface ContentfulComponent {
17
- componentTypeId: string;
17
+ componentId: string;
18
18
  nodeId?: string;
19
19
  content: Record<string, unknown>;
20
20
  design: Record<string, DesignPropValue>;
21
21
  resolved?: Record<string, unknown>;
22
22
  }
23
23
  /**
24
- * Same shape as `ContentfulComponent`, but for the page-level template.
25
- * Exposed via `useContentfulTemplate()` inside a template's component tree.
24
+ * Same shape as `ContentfulComponent`, but for the page-level Experience
25
+ * Template. Exposed via `useContentfulExperienceTemplate()` inside an
26
+ * Experience Template's component tree.
26
27
  */
27
- interface ContentfulTemplate {
28
- templateId: string;
28
+ interface ContentfulExperienceTemplate {
29
+ experienceTemplateId: string;
29
30
  content: Record<string, unknown>;
30
31
  design: Record<string, DesignPropValue>;
31
32
  resolved?: Record<string, unknown>;
@@ -41,7 +42,7 @@ interface RenderContext extends ExperienceContext {
41
42
  activeViewportIndex: number;
42
43
  }
43
44
  /**
44
- * Customer-supplied configuration for a single component type. The `component`
45
+ * Customer-supplied configuration for a single component. The `component`
45
46
  * receives the merged prop bag (content + resolveData + slots). Design values
46
47
  * are not injected — a component reads them via `useDesignValues()`. Runtime
47
48
  * context and raw payload come from `useExperience()` / `useContentfulComponent()`.
@@ -74,10 +75,10 @@ interface ComponentConfig<Props extends object = Record<string, unknown>> {
74
75
  */
75
76
  type Registration<Props extends object = Record<string, unknown>> = ComponentType<Props> | ComponentConfig<Props>;
76
77
  /**
77
- * Customer-supplied configuration for a page-level template. The template's
78
- * component receives the rendered Experience nodes as `children`.
78
+ * Customer-supplied configuration for a page-level Experience Template. The
79
+ * template's component receives the rendered Experience nodes as `children`.
79
80
  */
80
- interface TemplateConfig<Props extends object = Record<string, unknown>> {
81
+ interface ExperienceTemplateConfig<Props extends object = Record<string, unknown>> {
81
82
  defaults?: Partial<Props>;
82
83
  resolveData?: (ctx: ResolveContext) => Partial<Props> | Promise<Partial<Props>>;
83
84
  component: ComponentType<Props & {
@@ -85,34 +86,36 @@ interface TemplateConfig<Props extends object = Record<string, unknown>> {
85
86
  }>;
86
87
  }
87
88
  /**
88
- * Registry value for templates. Same dual-shape as component registrations.
89
+ * Registry value for Experience Templates. Same dual-shape as component
90
+ * registrations.
89
91
  */
90
- type TemplateRegistration<Props extends object = Record<string, unknown>> = ComponentType<Props & {
92
+ type ExperienceTemplateRegistration<Props extends object = Record<string, unknown>> = ComponentType<Props & {
91
93
  children?: ReactNode;
92
- }> | TemplateConfig<Props>;
94
+ }> | ExperienceTemplateConfig<Props>;
93
95
  /**
94
96
  * Identity helper — returns the config as-is, but narrows the `resolveData`
95
97
  * and `component` parameter types to your declared `Props`.
96
98
  */
97
99
  declare function defineComponent<Props extends object = Record<string, unknown>>(config: ComponentConfig<Props>): ComponentConfig<Props>;
98
100
  /**
99
- * Identity helper — returns the template config as-is, with `Props` narrowing.
101
+ * Identity helper — returns the Experience Template config as-is, with `Props`
102
+ * narrowing.
100
103
  */
101
- declare function defineTemplate<Props extends object = Record<string, unknown>>(config: TemplateConfig<Props>): TemplateConfig<Props>;
104
+ declare function defineExperienceTemplate<Props extends object = Record<string, unknown>>(config: ExperienceTemplateConfig<Props>): ExperienceTemplateConfig<Props>;
102
105
  /**
103
- * Component registry — keyed by `componentTypeId` (last slash-segment of
104
- * `componentType.sys.urn`). Per-entry prop narrowing happens at
106
+ * Component registry — keyed by `componentId` (last slash-segment of
107
+ * `component.sys.urn`). Per-entry prop narrowing happens at
105
108
  * `defineComponent<Props>` or at the bare-component's own type.
106
109
  */
107
110
  type Components = Record<string, Registration<any>>;
108
111
  /**
109
- * Template registry — keyed by `templateId` (last slash-segment of
110
- * `payload.sys.template.sys.urn`).
112
+ * Experience Template registry — keyed by `experienceTemplateId` (last
113
+ * slash-segment of `payload.sys.experienceTemplate.sys.urn`).
111
114
  */
112
- type Templates = Record<string, TemplateRegistration<any>>;
115
+ type ExperienceTemplates = Record<string, ExperienceTemplateRegistration<any>>;
113
116
  interface Config {
114
117
  components: Components;
115
- templates?: Templates;
118
+ experienceTemplates?: ExperienceTemplates;
116
119
  /**
117
120
  * Resolves `DesignToken` envelopes to runtime values before they reach a
118
121
  * component. If omitted, envelopes pass through unchanged. See `ResolveToken`
@@ -130,6 +133,6 @@ interface Config {
130
133
  * `component` field and no `$$typeof`.
131
134
  */
132
135
  declare function normalizeComponentRegistration<P extends object>(reg: Registration<P>): ComponentConfig<P>;
133
- declare function normalizeTemplateRegistration<P extends object>(reg: TemplateRegistration<P>): TemplateConfig<P>;
136
+ declare function normalizeExperienceTemplateRegistration<P extends object>(reg: ExperienceTemplateRegistration<P>): ExperienceTemplateConfig<P>;
134
137
 
135
- export { type ComponentConfig, type Components, type Config, type ContentfulComponent, type ContentfulTemplate, type Registration, type RenderContext, type TemplateConfig, type TemplateRegistration, type Templates, defineComponent, defineTemplate, normalizeComponentRegistration, normalizeTemplateRegistration };
138
+ export { type ComponentConfig, type Components, type Config, type ContentfulComponent, type ContentfulExperienceTemplate, type ExperienceTemplateConfig, type ExperienceTemplateRegistration, type ExperienceTemplates, type Registration, type RenderContext, defineComponent, defineExperienceTemplate, normalizeComponentRegistration, normalizeExperienceTemplateRegistration };
package/dist/types.js CHANGED
@@ -1,7 +1,7 @@
1
1
  function defineComponent(config) {
2
2
  return config;
3
3
  }
4
- function defineTemplate(config) {
4
+ function defineExperienceTemplate(config) {
5
5
  return config;
6
6
  }
7
7
  function normalizeComponentRegistration(reg) {
@@ -10,7 +10,7 @@ function normalizeComponentRegistration(reg) {
10
10
  }
11
11
  return { component: reg };
12
12
  }
13
- function normalizeTemplateRegistration(reg) {
13
+ function normalizeExperienceTemplateRegistration(reg) {
14
14
  if (typeof reg === "object" && reg !== null && !("$$typeof" in reg) && "component" in reg) {
15
15
  return reg;
16
16
  }
@@ -18,8 +18,8 @@ function normalizeTemplateRegistration(reg) {
18
18
  }
19
19
  export {
20
20
  defineComponent,
21
- defineTemplate,
21
+ defineExperienceTemplate,
22
22
  normalizeComponentRegistration,
23
- normalizeTemplateRegistration
23
+ normalizeExperienceTemplateRegistration
24
24
  };
25
25
  //# sourceMappingURL=types.js.map
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 `componentTypeId` 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 envelope form** here (the same shape\n * `ctx.design` carries inside `resolveData`). The viewport-cascaded, token-\n * resolved values are what `useDesignValues()` returns.\n */\nexport interface ContentfulComponent {\n componentTypeId: 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 template.\n * Exposed via `useContentfulTemplate()` inside a template's component tree.\n */\nexport interface ContentfulTemplate {\n templateId: 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 type. The `component`\n * receives the merged prop bag (content + resolveData + slots). Design values\n * are not injected — a component reads them via `useDesignValues()`. Runtime\n * context and raw payload come from `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 template. The template's\n * component receives the rendered Experience nodes as `children`.\n */\nexport interface TemplateConfig<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 templates. Same dual-shape as component registrations.\n */\nexport type TemplateRegistration<Props extends object = Record<string, unknown>> =\n | ComponentType<Props & { children?: ReactNode }>\n | TemplateConfig<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 template config as-is, with `Props` narrowing.\n */\nexport function defineTemplate<Props extends object = Record<string, unknown>>(\n config: TemplateConfig<Props>\n): TemplateConfig<Props> {\n return config;\n}\n\n/**\n * Component registry — keyed by `componentTypeId` (last slash-segment of\n * `componentType.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 * Template registry — keyed by `templateId` (last slash-segment of\n * `payload.sys.template.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 Templates = Record<string, TemplateRegistration<any>>;\n\nexport interface Config {\n components: Components;\n templates?: Templates;\n /**\n * Resolves `DesignToken` envelopes to runtime values before they reach a\n * component. If omitted, envelopes 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 normalizeTemplateRegistration<P extends object>(\n reg: TemplateRegistration<P>\n): TemplateConfig<P> {\n if (typeof reg === 'object' && reg !== null && !('$$typeof' in reg) && 'component' in reg) {\n return reg as TemplateConfig<P>;\n }\n return { component: reg as ComponentType<P & { children?: ReactNode }> };\n}\n"],"mappings":"AAmHO,SAAS,gBACd,QACwB;AACxB,SAAO;AACT;AAKO,SAAS,eACd,QACuB;AACvB,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,8BACd,KACmB;AACnB,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,EAAE,cAAc,QAAQ,eAAe,KAAK;AACzF,WAAO;AAAA,EACT;AACA,SAAO,EAAE,WAAW,IAAmD;AACzE;","names":[]}
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 envelope form** here (the same shape\n * `ctx.design` carries inside `resolveData`). The viewport-cascaded, token-\n * 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 prop bag (content + resolveData + slots). Design values\n * are not injected — a component reads them via `useDesignValues()`. Runtime\n * context and raw payload come from `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` envelopes to runtime values before they reach a\n * component. If omitted, envelopes 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":"AAqHO,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.6.0",
3
+ "version": "0.7.0",
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.2.0",
34
- "@contentful/experiences-sdk-core": "0.6.0",
35
- "@contentful/experiences-design": "0.6.0"
33
+ "@contentful/experiences-client": "0.3.0",
34
+ "@contentful/experiences-sdk-core": "0.7.0",
35
+ "@contentful/experiences-design": "0.7.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "react": "^18.0.0 || ^19.0.0",