@contentful/experiences-svelte 0.10.0 → 0.11.1

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,155 @@
1
+ ## 0.11.1 (2026-10-08)
2
+
3
+ ### 🚀 Features
4
+
5
+ - add fetchDestinationSitemap for paginated route listing [AIS-569] ([#218](https://github.com/contentful/experiences/pull/218))
6
+
7
+ ### 🧱 Updated Dependencies
8
+
9
+ - Updated live-preview to 0.6.1
10
+ - Updated client to 0.9.1
11
+
12
+ ## 0.11.0 (2026-10-08)
13
+
14
+ ### 🚀 Features
15
+
16
+ - ⚠️ remove sdk viewport surface [SPA-5275] ([#220](https://github.com/contentful/experiences/pull/220))
17
+
18
+ ### ⚠️ Breaking Changes
19
+
20
+ - remove sdk viewport surface [SPA-5275] ([#220](https://github.com/contentful/experiences/pull/220))
21
+ The SDK no longer exposes viewport definitions, viewport-aware design-value resolution, or active-viewport hooks. Use CSS media queries or application-owned matchMedia integration for responsive behavior. Delivered design property values are now flat and require no migration."
22
+ M AGENTS.md
23
+ M ARCHITECTURE.md
24
+ M CONTRIBUTING.md
25
+ M README.md
26
+ M catalog-info.yaml
27
+ M examples/angular/README.md
28
+ M examples/angular/src/app/components/heading.component.ts
29
+ D examples/angular/src/app/lib/detect-viewport.ts
30
+ M examples/angular/src/app/lib/experience-config.ts
31
+ M examples/angular/src/app/lib/experience-route-data.ts
32
+ M examples/angular/src/app/pages/experience-page.component.ts
33
+ M examples/angular/src/server.ts
34
+ M examples/nextjs/README.md
35
+ M examples/nextjs/app/[slug]/page.tsx
36
+ M examples/nextjs/components/Heading.tsx
37
+ M examples/nextjs/components/LivePreviewExperience.tsx
38
+ M examples/nextjs/components/Section.tsx
39
+ D examples/nextjs/lib/detect-viewport.ts
40
+ M examples/nextjs/lib/experience-config.tsx
41
+ M examples/scripts/bootstrap-example.ts
42
+ M examples/scripts/fixture/experience.ts
43
+ M examples/scripts/fixture/types.ts
44
+ M examples/sveltekit/README.md
45
+ M examples/sveltekit/src/lib/components/Heading.svelte
46
+ D examples/sveltekit/src/lib/detect-viewport.ts
47
+ M examples/sveltekit/src/lib/experience-config.ts
48
+ M examples/sveltekit/src/routes/[slug]/+page.server.ts
49
+ M examples/sveltekit/src/routes/[slug]/+page.svelte
50
+ M examples/sveltekit/vite.config.ts
51
+ M package-lock.json
52
+ M packages/adapter-angular/README.md
53
+ M packages/adapter-angular/src/client-experience-renderer.component.ts
54
+ M packages/adapter-angular/src/context.ts
55
+ M packages/adapter-angular/src/debug-experience.test.ts
56
+ M packages/adapter-angular/src/debug-panel-coverage.ssr.test.ts
57
+ M packages/adapter-angular/src/debug-panel-coverage.test.ts
58
+ M packages/adapter-angular/src/dom-parity.test.ts
59
+ M packages/adapter-angular/src/experience-defaults.ts
60
+ M packages/adapter-angular/src/experience-scope.ts
61
+ M packages/adapter-angular/src/index.ts
62
+ D packages/adapter-angular/src/inject-active-viewport.ts
63
+ M packages/adapter-angular/src/inject-design-values.ts
64
+ M packages/adapter-angular/src/inject-experience-plan.ts
65
+ M packages/adapter-angular/src/live-preview-experience.ssr.test.ts
66
+ M packages/adapter-angular/src/live-preview-experience.test.ts
67
+ M packages/adapter-angular/src/node-render-engine.test.ts
68
+ M packages/adapter-angular/src/node-render-engine.ts
69
+ M packages/adapter-angular/src/node-scopes.ts
70
+ M packages/adapter-angular/src/nodes-renderer.ssr.test.ts
71
+ M packages/adapter-angular/src/server-experience-renderer.component.ts
72
+ M packages/adapter-angular/src/server-renderer.test.ts
73
+ M packages/adapter-angular/src/test-fixtures/render-harness.ts
74
+ M packages/adapter-angular/src/types.ts
75
+ M packages/adapter-react/README.md
76
+ M packages/adapter-react/src/client-renderer.tsx
77
+ M packages/adapter-react/src/context.tsx
78
+ M packages/adapter-react/src/debug-experience.test.tsx
79
+ M packages/adapter-react/src/debug-experience.tsx
80
+ M packages/adapter-react/src/debug-panel-coverage.test.tsx
81
+ M packages/adapter-react/src/index.ts
82
+ M packages/adapter-react/src/nodes-renderer.ssr.test.tsx
83
+ M packages/adapter-react/src/nodes-renderer.test.tsx
84
+ M packages/adapter-react/src/nodes-renderer.tsx
85
+ M packages/adapter-react/src/server-renderer.test.tsx
86
+ M packages/adapter-react/src/server-renderer.tsx
87
+ M packages/adapter-react/src/types.ts
88
+ D packages/adapter-react/src/use-active-viewport.ts
89
+ M packages/adapter-react/src/use-design-values.tsx
90
+ M packages/adapter-react/src/use-experience-plan.test.tsx
91
+ M packages/adapter-react/src/use-experience-plan.ts
92
+ M packages/adapter-react/src/use-live-preview-experience.test.tsx
93
+ M packages/adapter-react/src/use-live-preview.test.tsx
94
+ M packages/adapter-svelte/README.md
95
+ M packages/adapter-svelte/src/ClientExperienceRenderer.svelte
96
+ M packages/adapter-svelte/src/DebugExperience.svelte
97
+ M packages/adapter-svelte/src/DebugExperience.test.ts
98
+ M packages/adapter-svelte/src/NodeRenderer.svelte
99
+ M packages/adapter-svelte/src/NodeRenderer.test.ts
100
+ M packages/adapter-svelte/src/NodesRenderer.svelte
101
+ M packages/adapter-svelte/src/ServerExperienceRenderer.svelte
102
+ M packages/adapter-svelte/src/component-props.ts
103
+ M packages/adapter-svelte/src/context.ts
104
+ M packages/adapter-svelte/src/debug-panel-coverage.ssr.test.ts
105
+ M packages/adapter-svelte/src/debug-panel-coverage.test.ts
106
+ M packages/adapter-svelte/src/get-design-values.ts
107
+ M packages/adapter-svelte/src/index.ts
108
+ M packages/adapter-svelte/src/nodes-renderer.ssr.test.ts
109
+ M packages/adapter-svelte/src/server-renderer.test.ts
110
+ M packages/adapter-svelte/src/types.ts
111
+ D packages/adapter-svelte/src/use-active-viewport.svelte.ts
112
+ M packages/adapter-svelte/src/use-experience-plan.test.ts
113
+ M packages/adapter-svelte/src/use-live-preview-experience.test.ts
114
+ M packages/adapter-svelte/src/use-live-preview.test.ts
115
+ M packages/client/src/contentful-experiences.test.ts
116
+ M packages/client/src/contentful-experiences.ts
117
+ M packages/client/src/fetch-experience.test.ts
118
+ M packages/client/src/fetch-experience.ts
119
+ M packages/core/README.md
120
+ A packages/core/src/design-properties.test.ts
121
+ A packages/core/src/design-properties.ts
122
+ M packages/core/src/index.ts
123
+ M packages/core/src/resolve-experience.test.ts
124
+ M packages/core/src/resolve-experience.ts
125
+ M packages/core/src/types.ts
126
+ D packages/core/src/viewport.test.ts
127
+ D packages/core/src/viewport.ts
128
+ M packages/design/README.md
129
+ M packages/design/package.json
130
+ M packages/design/src/index.ts
131
+ D packages/design/src/media-query-matchers.ts
132
+ D packages/design/src/select-resolved-design.ts
133
+ D packages/design/src/viewport.test.ts
134
+ D packages/design/src/viewport.ts
135
+ M packages/live-preview/README.md
136
+ M packages/live-preview/src/experience-payload.ts
137
+ M packages/live-preview/src/fetch-preview-session.test.ts
138
+ M packages/live-preview/src/fetch-preview-session.ts
139
+ M packages/live-preview/src/live-preview-client.test.ts
140
+ M packages/node/README.md
141
+ M packages/node/src/contentful-experiences.test.ts
142
+ M packages/node/src/contentful-experiences.ts
143
+ M packages/web/README.md
144
+ M packages/web/src/contentful-experiences.test.ts
145
+
146
+ ### 🧱 Updated Dependencies
147
+
148
+ - Updated live-preview to 0.6.0
149
+ - Updated client to 0.9.0
150
+ - Updated design to 0.12.0
151
+ - Updated core to 0.12.0
152
+
1
153
  ## 0.10.0 (2026-10-06)
2
154
 
3
155
  ### 🧱 Updated Dependencies
package/README.md CHANGED
@@ -107,11 +107,10 @@ fails. The last valid `data` remains available.
107
107
  ### Renderers
108
108
 
109
109
  ```ts
110
- ServerExperienceRenderer; // SSR-safe; active viewport seeded from initialViewportId
111
- ClientExperienceRenderer; // Subscribes to window.matchMedia via runes
110
+ ServerExperienceRenderer; // SSR-safe renderer
111
+ ClientExperienceRenderer; // Client renderer
112
112
  MissingComponent; // Default fallback for unregistered component types
113
113
  NodesRenderer; // Exposed so you can re-render a slot's raw nodes yourself (see Slot children)
114
- useActiveViewport; // Rune-backed reactive object; you'll rarely need it directly
115
114
  ```
116
115
 
117
116
  ### Styling + runtime context (helpers)
@@ -119,13 +118,13 @@ useActiveViewport; // Rune-backed reactive object; you'll rarely need it directl
119
118
  ```ts
120
119
  getDesignValues<T>(); // Escape hatch: the same resolved design record that auto-fills props; read in a $derived to stay reactive
121
120
  toCss(design, options?); // Turns a design record into a plain style object, keeping only real CSS keys
122
- getExperience(); // RenderContext: debug, metadata, viewports, activeViewport
121
+ getExperience(); // RenderContext: debug, metadata
123
122
  getContentfulComponent(); // Raw payload for the enclosing node (or undefined)
124
123
  getContentfulExperienceTemplate(); // Same, for an enclosing coded Experience Template node
125
124
  type ToCssOptions;
126
125
  ```
127
126
 
128
- Resolved design values (viewport-cascaded + token-resolved server-side) are **auto-filled onto your component's props** by key, alongside content. Styling from `$props()` is the one recommended path. `getDesignValues()` exposes the same record (read it in a `$derived` to stay reactive) as an escape hatch. Reach for it only for a nested child that isn't itself a registered component, or for design needed outside the render path (an effect, an imperative measurement) — see [Styling components](../../README.md#styling-components). Token resolution is configured with `resolveToken` on your `Config` (`type ResolveToken`).
127
+ Resolved design values are **auto-filled onto your component's props** by key, alongside content. Styling from `$props()` is the one recommended path. `getDesignValues()` exposes the same record as an escape hatch. Reach for it only for a nested child that isn't itself a registered component, or for design needed outside the render path (an effect, an imperative measurement) — see [Styling components](../../README.md#styling-components). Token resolution is configured with `resolveToken` on your `Config` (`type ResolveToken`).
129
128
 
130
129
  ### Re-exported types and utilities
131
130
 
@@ -137,12 +136,10 @@ type ContentfulComponent, ContentfulExperienceTemplate,
137
136
  type RenderContext, ResolveToken,
138
137
  type ExperiencePayload, ExperienceNode, ComponentNode, ExperienceTemplateNode,
139
138
  type PortableRenderPlan, PortableRenderNode, PortableRegistration,
140
- type DesignPropValue, ManualDesignValue, DesignToken, ValuesByViewport,
141
- type ViewportDef, ExperienceContext, ResolveContext,
139
+ type DesignPropValue, ManualDesignValue, DesignToken, ExperienceContext, ResolveContext,
142
140
  type ResolverConfig, ResolveExperienceOptions
143
141
 
144
- // From design (if you want to do your own viewport-aware resolution)
145
- getValueForViewport, getViewportIndex, resolveDesignProperties, toCssMediaQuery,
142
+ // From design
146
143
  isCssProperty, toCssKey, CSS_PROPERTIES
147
144
 
148
145
  // From client
@@ -244,7 +241,7 @@ Every slot arrives as a prop named after the slot, holding an **array of Snippet
244
241
 
245
242
  If you'd rather render a slot's raw nodes yourself, they are still on the payload at `getContentfulComponent().slots` (a `Record<string, PortableRenderNode[]>`) — hand them to `NodesRenderer`.
246
243
 
247
- For the full getting-started walkthrough, the merge-precedence rules, viewport handling, and design rationale, see the [root README](../../README.md) and [`AGENTS.md`](../../AGENTS.md).
244
+ For the full getting-started walkthrough, merge-precedence rules, and design rationale, see the [root README](../../README.md) and [`AGENTS.md`](../../AGENTS.md).
248
245
 
249
246
  ---
250
247
 
@@ -1,15 +1,9 @@
1
1
  <!--
2
- * Client Experience renderer. First paint matches the server renderer
3
- * (active viewport resolved from `initialViewportId`); after hydration,
4
- * `useActiveViewport` takes over via `window.matchMedia` and re-renders
5
- * when the viewport changes.
6
- *
7
- * Safe to render on the server: `useActiveViewport` no-ops outside the
8
- * browser, so SSR output matches `<ServerExperienceRenderer>` given the
9
- * same seed.
2
+ * Client Experience renderer. It renders the resolved plan directly, with no
3
+ * browser-only design-property work.
10
4
  -->
11
5
  <script lang="ts">
12
- import type { ExperienceContext, ViewportDef } from '@contentful/experiences-sdk-core';
6
+ import type { ExperienceContext } from '@contentful/experiences-sdk-core';
13
7
 
14
8
  import ComponentError from './ComponentError.svelte';
15
9
  import DebugExperience from './DebugExperience.svelte';
@@ -18,25 +12,15 @@
18
12
  import type { ClientExperienceRendererProps } from './component-props.js';
19
13
  import { setExperience } from './context.js';
20
14
  import type { RenderContext } from './types.js';
21
- import { useActiveViewport } from './use-active-viewport.svelte.js';
22
15
 
23
16
  const DEFAULT_CONTEXT: ExperienceContext = {
24
17
  debug: false,
25
18
  metadata: {},
26
- viewports: [],
27
- };
28
-
29
- const FALLBACK_VIEWPORT: ViewportDef = {
30
- id: '_',
31
- query: '*',
32
- displayName: 'Default',
33
- previewSize: '100%',
34
19
  };
35
20
 
36
21
  let {
37
22
  experience,
38
23
  config,
39
- initialViewportId,
40
24
  metadata,
41
25
  debug,
42
26
  renderUnknown = MissingComponent,
@@ -70,15 +54,8 @@
70
54
  });
71
55
  }
72
56
 
73
- const viewports = $derived(experience?.viewports ?? []);
74
- // Seed from the plan so first paint matches the server renderer.
75
- const seedViewportId = $derived(
76
- initialViewportId ?? experience?.viewports[experience.fallbackViewportIndex]?.id
77
- );
78
- const tracker = useActiveViewport(viewports, seedViewportId);
79
-
80
57
  // A $state-backed mirror so descendants reading getExperience() stay
81
- // reactive across viewport changes. The fields update in an $effect below.
58
+ // reactive when the plan or rendering options change.
82
59
  const liveContext = $state<RenderContext>({
83
60
  ...DEFAULT_CONTEXT,
84
61
  debug: debug ?? experience?.debug ?? false,
@@ -87,21 +64,12 @@
87
64
  ...(experience?.metadata ?? {}),
88
65
  ...(metadata ?? {}),
89
66
  },
90
- viewports: experience?.viewports ?? [],
91
- activeViewport: experience?.viewports[0] ?? FALLBACK_VIEWPORT,
92
- activeViewportIndex: 0,
93
- fallbackViewportIndex: experience?.fallbackViewportIndex ?? 0,
94
67
  });
95
68
 
96
69
  setExperience(liveContext);
97
70
 
98
71
  $effect(() => {
99
72
  if (!experience) return;
100
- const idx = tracker.activeViewportIndex;
101
- liveContext.viewports = experience.viewports;
102
- liveContext.activeViewport = experience.viewports[idx] ?? FALLBACK_VIEWPORT;
103
- liveContext.activeViewportIndex = idx;
104
- liveContext.fallbackViewportIndex = experience.fallbackViewportIndex;
105
73
  liveContext.debug = resolvedDebug;
106
74
  liveContext.metadata = {
107
75
  ...DEFAULT_CONTEXT.metadata,
@@ -1 +1 @@
1
- {"version":3,"file":"ClientExperienceRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/ClientExperienceRenderer.svelte.ts"],"names":[],"mappings":"AA+HA,QAAA,MAAM,wBAAwB,kGAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"ClientExperienceRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/ClientExperienceRenderer.svelte.ts"],"names":[],"mappings":"AAoGA,QAAA,MAAM,wBAAwB,kGAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
@@ -1,15 +1,15 @@
1
1
  <!--
2
2
  * First-party debug panel. Renders the resolved Experience plan as pretty
3
3
  * JSON so a customer can see exactly what the SDK interpreted from the payload
4
- * — node tree, registrations, resolved props, viewports.
4
+ * — node tree, registrations, and resolved props.
5
5
  *
6
6
  * Two ways to use it:
7
7
  * - Auto-mounted by the renderers when `debug` is on (above the tree).
8
8
  * - Mounted manually anywhere: `<DebugExperience experience={plan} />`.
9
9
  *
10
10
  * v1 is just the JSON dump wrapped in a native <details> so it collapses
11
- * without any extra JS. Room to grow into a node-tree explorer, viewport
12
- * indicator, and resolveData timing panel — kept deliberately small for now.
11
+ * without any extra JS. Room to grow into a node-tree explorer and resolveData
12
+ * timing panel — kept deliberately small for now.
13
13
  -->
14
14
  <script lang="ts">
15
15
  import type { DebugExperienceProps } from './component-props.js';
@@ -3,8 +3,6 @@ import { describe, expect, it } from 'vitest';
3
3
  import DebugExperience from './DebugExperience.svelte';
4
4
  const emptyPlan = {
5
5
  nodes: [],
6
- viewports: [],
7
- fallbackViewportIndex: 0,
8
6
  metadata: {},
9
7
  debug: false,
10
8
  diagnostics: [],
@@ -40,9 +38,7 @@ describe('DebugExperience.svelte', () => {
40
38
  const { container: zero } = render(DebugExperience, { props: { experience: emptyPlan } });
41
39
  expect(zero.innerHTML).toContain('Experience debug — 0 top-level nodes');
42
40
  const one = {
43
- viewports: [],
44
41
  nodes: [node('button')],
45
- fallbackViewportIndex: 0,
46
42
  metadata: {},
47
43
  debug: false,
48
44
  diagnostics: [],
@@ -52,9 +48,7 @@ describe('DebugExperience.svelte', () => {
52
48
  });
53
49
  it('names experienceTemplate nodes in the summary', () => {
54
50
  const plan = {
55
- viewports: [],
56
51
  nodes: [templateNode('page')],
57
- fallbackViewportIndex: 0,
58
52
  metadata: {},
59
53
  debug: false,
60
54
  diagnostics: [],
@@ -64,9 +58,7 @@ describe('DebugExperience.svelte', () => {
64
58
  });
65
59
  it('omits the experience-template summary for a composite experience', () => {
66
60
  const plan = {
67
- viewports: [],
68
61
  nodes: [node('button'), node('text')],
69
- fallbackViewportIndex: 0,
70
62
  metadata: {},
71
63
  debug: false,
72
64
  diagnostics: [],
@@ -77,9 +69,7 @@ describe('DebugExperience.svelte', () => {
77
69
  });
78
70
  it('dumps the plan as pretty JSON', () => {
79
71
  const plan = {
80
- viewports: [],
81
72
  nodes: [node('button', { label: 'Go' })],
82
- fallbackViewportIndex: 0,
83
73
  metadata: {},
84
74
  debug: false,
85
75
  diagnostics: [],
@@ -93,9 +83,7 @@ describe('DebugExperience.svelte', () => {
93
83
  const n = node('button');
94
84
  n.props.resolved = { self: n.props };
95
85
  const plan = {
96
- viewports: [],
97
86
  nodes: [n],
98
- fallbackViewportIndex: 0,
99
87
  metadata: {},
100
88
  debug: false,
101
89
  diagnostics: [],
@@ -117,9 +105,7 @@ describe('DebugExperience.svelte', () => {
117
105
  },
118
106
  });
119
107
  const plan = {
120
- viewports: [],
121
108
  nodes: [n],
122
- fallbackViewportIndex: 0,
123
109
  metadata: {},
124
110
  debug: false,
125
111
  diagnostics: [],
@@ -12,7 +12,6 @@
12
12
  import type { Snippet } from 'svelte';
13
13
 
14
14
  import type { PortableRenderNode } from '@contentful/experiences-sdk-core';
15
- import { selectResolvedDesign } from '@contentful/experiences-design';
16
15
 
17
16
  import {
18
17
  setContentfulComponent,
@@ -58,7 +57,7 @@
58
57
  const isExperienceTemplate = kind === 'experienceTemplate';
59
58
 
60
59
  // Any reactive re-run of this component's `$derived`/`{@const}` blocks
61
- // (e.g. an ancestor's viewport change) would otherwise re-report the same
60
+ // would otherwise re-report the same
62
61
  // diagnostic every time — matches Angular's `lastDiagnostics` guard in
63
62
  // NodeRenderEngine and React's equivalent in NodeRenderer. `reported` is a
64
63
  // plain (non-reactive) binding, stable for this component instance's
@@ -102,21 +101,7 @@
102
101
  setContentfulComponent(contentful);
103
102
  }
104
103
 
105
- const tokenResolvedDesign = $derived.by(() => {
106
- const { props, unresolved } = selectResolvedDesign(
107
- node.props,
108
- experience.viewports,
109
- experience.activeViewportIndex,
110
- experience.fallbackViewportIndex,
111
- config.resolveToken
112
- );
113
- if (unresolved.length && typeof console !== 'undefined') {
114
- console.warn(
115
- `[@contentful/experiences-svelte] resolveToken returned undefined for token id(s) on ${kind} "${id}": ${unresolved.join(', ')}. getDesignValues() will omit those keys.`
116
- );
117
- }
118
- return props;
119
- });
104
+ const tokenResolvedDesign = $derived(node.props.design);
120
105
 
121
106
  setResolvedDesign(() => tokenResolvedDesign);
122
107
 
@@ -1 +1 @@
1
- {"version":3,"file":"NodeRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/NodeRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAQ3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAKH,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB,UAAU,iBAAiB;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,aAAa,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;IACjC;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CACzC;AAgKH,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"NodeRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/NodeRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAO3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAKH,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB,UAAU,iBAAiB;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,aAAa,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;IACjC;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CACzC;AAiJH,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -5,7 +5,7 @@
5
5
  * for that documented, proven gap. Both `ServerExperienceRenderer` and
6
6
  * `ClientExperienceRenderer` share the same `NodesRenderer`/`NodeRenderer`
7
7
  * boundary code, so both are exercised — the distinction between the two
8
- * components is about viewport-tracking reactivity, not error handling.
8
+ * components is about client-side reactivity, not error handling.
9
9
  */
10
10
  import { render } from '@testing-library/svelte';
11
11
  import { describe, expect, it, vi } from 'vitest';
@@ -20,7 +20,6 @@ import ClientExperienceRenderer from './ClientExperienceRenderer.svelte';
20
20
  import ServerExperienceRenderer from './ServerExperienceRenderer.svelte';
21
21
  import BrokenFixture from './test-fixtures/BrokenFixture.svelte';
22
22
  import ButtonFixture from './test-fixtures/ButtonFixture.svelte';
23
- const VIEWPORTS = [{ id: 'desktop', query: '*', displayName: 'Desktop', previewSize: '100%' }];
24
23
  function componentNode(typeId, rest = {}) {
25
24
  return {
26
25
  component: {
@@ -41,7 +40,6 @@ describe.each([
41
40
  const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
42
41
  try {
43
42
  const payload = {
44
- viewports: VIEWPORTS,
45
43
  nodes: [
46
44
  componentNode('broken', { id: 'b' }),
47
45
  componentNode('contentful-button', { id: 'f', contentProperties: { label: 'sibling' } }),
@@ -81,7 +79,6 @@ describe.each([
81
79
  const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
82
80
  try {
83
81
  const payload = {
84
- viewports: VIEWPORTS,
85
82
  nodes: [componentNode('broken', { id: 'b' })],
86
83
  };
87
84
  const config = { components: { broken: BrokenFixture } };
@@ -102,7 +99,6 @@ describe('ClientExperienceRenderer — render-time diagnostics dedupe across re-
102
99
  const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
103
100
  try {
104
101
  const payload = {
105
- viewports: VIEWPORTS,
106
102
  nodes: [componentNode('missing', { id: 'm' })],
107
103
  };
108
104
  const config = { components: {} };
@@ -111,7 +107,7 @@ describe('ClientExperienceRenderer — render-time diagnostics dedupe across re-
111
107
  props: { experience: plan, config, debug: true },
112
108
  });
113
109
  // Force NodeRenderer's reactive blocks to re-run without any real new
114
- // occurrence — an ancestor re-render (a viewport change, an unrelated
110
+ // occurrence — an ancestor re-render (an unrelated
115
111
  // parent update) does the same thing in production.
116
112
  await rerender({ experience: plan, config, debug: true });
117
113
  expect(container.querySelectorAll('[data-experiences-debug-errors] li')).toHaveLength(1);
@@ -17,8 +17,7 @@
17
17
  * The Experience runtime context and the raw Contentful payload are read
18
18
  * via `getExperience` / `getContentfulComponent`.
19
19
  *
20
- * Server vs client variants share this component; they differ only in how
21
- * the active viewport is sourced (initial seed vs reactive matchMedia).
20
+ * Server and client renderers share this component.
22
21
  -->
23
22
  <script lang="ts">
24
23
  import type { Snippet } from 'svelte';
@@ -1,15 +1,12 @@
1
1
  <!--
2
- * Server-safe Experience renderer. Resolves the active viewport once from
3
- * `initialViewportId` (typically derived from User-Agent on the request)
4
- * and renders without any reactive subscription. SSR-friendly.
2
+ * Server-safe Experience renderer. It renders the resolved plan directly.
5
3
  *
6
4
  * SSR + interactive editor mode are mutually exclusive — the message-event
7
5
  * preview client requires window listeners and lives only in the client
8
6
  * renderer. For editor mode, render the client variant on a hydrated route.
9
7
  -->
10
8
  <script lang="ts">
11
- import type { ExperienceContext, ViewportDef } from '@contentful/experiences-sdk-core';
12
- import { getViewportIndex } from '@contentful/experiences-design';
9
+ import type { ExperienceContext } from '@contentful/experiences-sdk-core';
13
10
 
14
11
  import ComponentError from './ComponentError.svelte';
15
12
  import DebugExperience from './DebugExperience.svelte';
@@ -22,20 +19,11 @@
22
19
  const DEFAULT_CONTEXT: ExperienceContext = {
23
20
  debug: false,
24
21
  metadata: {},
25
- viewports: [],
26
- };
27
-
28
- const FALLBACK_VIEWPORT: ViewportDef = {
29
- id: '_',
30
- query: '*',
31
- displayName: 'Default',
32
- previewSize: '100%',
33
22
  };
34
23
 
35
24
  let {
36
25
  experience,
37
26
  config,
38
- initialViewportId,
39
27
  metadata,
40
28
  debug,
41
29
  renderUnknown = MissingComponent,
@@ -46,13 +34,6 @@
46
34
  const resolvedDebug = $derived(debug ?? experience?.debug ?? false);
47
35
 
48
36
  function buildContext(): RenderContext {
49
- const viewports = experience?.viewports ?? [];
50
- // Default to the pre-resolved viewport so first paint needs no recompute.
51
- const idx = !experience
52
- ? 0
53
- : initialViewportId === undefined
54
- ? experience.fallbackViewportIndex
55
- : getViewportIndex(experience.viewports, initialViewportId);
56
37
  return {
57
38
  ...DEFAULT_CONTEXT,
58
39
  debug: resolvedDebug,
@@ -61,10 +42,6 @@
61
42
  ...(experience?.metadata ?? {}),
62
43
  ...(metadata ?? {}),
63
44
  },
64
- viewports,
65
- activeViewport: experience?.viewports[idx] ?? FALLBACK_VIEWPORT,
66
- activeViewportIndex: idx,
67
- fallbackViewportIndex: experience?.fallbackViewportIndex ?? 0,
68
45
  };
69
46
  }
70
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"ServerExperienceRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/ServerExperienceRenderer.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AA0F1E,QAAA,MAAM,wBAAwB,mEAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"ServerExperienceRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/ServerExperienceRenderer.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAqE1E,QAAA,MAAM,wBAAwB,mEAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
@@ -4,7 +4,6 @@ import type { Config } from './types.js';
4
4
  export interface ServerExperienceRendererProps {
5
5
  experience: PortableRenderPlan | null | undefined;
6
6
  config: Config;
7
- initialViewportId?: string;
8
7
  /** Shallow-merges over the plan's `metadata`. Only needed to override it. */
9
8
  metadata?: Record<string, unknown>;
10
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"component-props.d.ts","sourceRoot":"","sources":["../src/component-props.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,yEAAyE;IACzE,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,6BAA6B,GAAG,6BAA6B,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,UAAU,EAAE,kBAAkB,CAAC;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB"}
1
+ {"version":3,"file":"component-props.d.ts","sourceRoot":"","sources":["../src/component-props.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAE3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,yEAAyE;IACzE,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,6BAA6B,GAAG,6BAA6B,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,UAAU,EAAE,kBAAkB,CAAC;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB"}
package/dist/context.d.ts CHANGED
@@ -5,7 +5,7 @@ export declare function setContentfulExperienceTemplate(tpl: ContentfulExperienc
5
5
  /**
6
6
  * Publish the resolved design values for the enclosing node or experience template. Takes a
7
7
  * getter (not a snapshot) so callers reading it inside a `$derived` stay
8
- * reactive across viewport changes.
8
+ * reactive across plan changes.
9
9
  */
10
10
  export declare function setResolvedDesign(getDesign: () => Record<string, unknown>): void;
11
11
  export declare function getExperience(): RenderContext;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4BAA4B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AASnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAEtD;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAEtE;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,4BAA4B,GAAG,IAAI,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEhF;AAED,wBAAgB,aAAa,IAAI,aAAa,CAQ7C;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,SAAS,CAExE;AAED,wBAAgB,+BAA+B,IAAI,4BAA4B,GAAG,SAAS,CAE1F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGvE"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,4BAA4B,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AASnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAEtD;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAEtE;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,4BAA4B,GAAG,IAAI,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEhF;AAED,wBAAgB,aAAa,IAAI,aAAa,CAQ7C;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,SAAS,CAExE;AAED,wBAAgB,+BAA+B,IAAI,4BAA4B,GAAG,SAAS,CAE1F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGvE"}
package/dist/context.js CHANGED
@@ -6,8 +6,7 @@
6
6
  * the helper from the top of its `<script>` block.
7
7
  *
8
8
  * Reactivity: the client renderer stores a `$state` proxy in context, so
9
- * reads through the returned object (`exp.activeViewport`, from the
10
- * template or a `$derived`) stay reactive across viewport changes.
9
+ * reads through the returned object stay reactive across plan changes.
11
10
  * Destructuring the return of `getExperience()` loses that reactivity —
12
11
  * same rule as Svelte 5 `$props()`.
13
12
  *
@@ -32,7 +31,7 @@ export function setContentfulExperienceTemplate(tpl) {
32
31
  /**
33
32
  * Publish the resolved design values for the enclosing node or experience template. Takes a
34
33
  * getter (not a snapshot) so callers reading it inside a `$derived` stay
35
- * reactive across viewport changes.
34
+ * reactive across plan changes.
36
35
  */
37
36
  export function setResolvedDesign(getDesign) {
38
37
  setContext(RESOLVED_DESIGN_KEY, getDesign);
@@ -16,7 +16,6 @@ import { render } from 'svelte/server';
16
16
  import { resolveExperience } from '@contentful/experiences-sdk-core';
17
17
  import ServerExperienceRenderer from './ServerExperienceRenderer.svelte';
18
18
  import ButtonFixture from './test-fixtures/ButtonFixture.svelte';
19
- const VIEWPORTS = [{ id: 'desktop', query: '*', displayName: 'Desktop', previewSize: '100%' }];
20
19
  function componentNode(typeId, rest = {}) {
21
20
  return {
22
21
  component: {
@@ -34,7 +33,6 @@ describe('debug panel — true SSR coverage of a resolve-time diagnostic', () =>
34
33
  const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
35
34
  try {
36
35
  const payload = {
37
- viewports: VIEWPORTS,
38
36
  nodes: [
39
37
  componentNode('button', {
40
38
  id: 'b',