@contentful/experiences-svelte 0.4.1 → 0.5.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 +93 -0
- package/README.md +7 -7
- package/dist/ClientExperienceRenderer.svelte +3 -3
- package/dist/DebugExperience.svelte +3 -1
- package/dist/DebugExperience.svelte.d.ts.map +1 -1
- package/dist/DebugExperience.test.js +6 -6
- package/dist/MissingComponent.svelte +6 -6
- package/dist/NodeRenderer.svelte +4 -4
- package/dist/ServerExperienceRenderer.svelte +3 -3
- package/dist/WrapWithExperienceTemplate.svelte +87 -0
- package/dist/WrapWithExperienceTemplate.svelte.d.ts +13 -0
- package/dist/WrapWithExperienceTemplate.svelte.d.ts.map +1 -0
- package/dist/component-props.d.ts +1 -1
- package/dist/component-props.d.ts.map +1 -1
- package/dist/context.d.ts +6 -5
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +8 -7
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/server-renderer.test.js +29 -29
- package/dist/test-fixtures/{TemplateFixture.svelte → ExperienceTemplateFixture.svelte} +1 -1
- package/dist/test-fixtures/ExperienceTemplateFixture.svelte.d.ts +9 -0
- package/dist/test-fixtures/ExperienceTemplateFixture.svelte.d.ts.map +1 -0
- package/dist/types.d.ts +13 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/package.json +5 -5
- package/dist/WrapWithTemplate.svelte +0 -87
- package/dist/WrapWithTemplate.svelte.d.ts +0 -13
- package/dist/WrapWithTemplate.svelte.d.ts.map +0 -1
- package/dist/test-fixtures/TemplateFixture.svelte.d.ts +0 -9
- package/dist/test-fixtures/TemplateFixture.svelte.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,96 @@
|
|
|
1
|
+
## 0.5.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
|
+
|
|
1
94
|
## 0.4.1 (2026-08-06)
|
|
2
95
|
|
|
3
96
|
### 🧱 Updated Dependencies
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ The public API mirrors `@contentful/experiences-react` 1:1 in shape; only the re
|
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
22
|
defineComponent<Props>(config); // Type-narrowing identity for component-type configs
|
|
23
|
-
|
|
23
|
+
defineExperienceTemplate<Props>(config); // Same shape, for page-level Experience Template wrappers
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
### Resolver
|
|
@@ -46,7 +46,7 @@ getDesignValues<T>(); // Resolved design values for the current node; read in a
|
|
|
46
46
|
toCss(design, options?); // Turns a design record into a plain style object, keeping only real CSS keys
|
|
47
47
|
getExperience(); // RenderContext: debug, metadata, viewports, activeViewport
|
|
48
48
|
getContentfulComponent(); // Raw payload for the enclosing node (or undefined)
|
|
49
|
-
|
|
49
|
+
getContentfulExperienceTemplate(); // Same, for the page-level Experience Template
|
|
50
50
|
type ToCssOptions;
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -56,12 +56,12 @@ Design is **not** injected as props; components read it via `getDesignValues()`
|
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
58
|
// From core
|
|
59
|
-
type Config, Components,
|
|
60
|
-
type ComponentConfig,
|
|
61
|
-
type ContentfulComponent,
|
|
59
|
+
type Config, Components, ExperienceTemplates, Registration, ExperienceTemplateRegistration,
|
|
60
|
+
type ComponentConfig, ExperienceTemplateConfig,
|
|
61
|
+
type ContentfulComponent, ContentfulExperienceTemplate,
|
|
62
62
|
type RenderContext, ResolveToken,
|
|
63
|
-
type ExperiencePayload, ExperienceNode,
|
|
64
|
-
type PortableRenderPlan, PortableRenderNode,
|
|
63
|
+
type ExperiencePayload, ExperienceNode, ComponentNode, ExperienceTemplateNode,
|
|
64
|
+
type PortableRenderPlan, PortableRenderNode, PortableExperienceTemplate,
|
|
65
65
|
type DesignPropValue, ManualDesignValue, DesignToken, ValuesByViewport,
|
|
66
66
|
type ViewportDef, ExperienceContext, ResolveContext,
|
|
67
67
|
type ResolverConfig, ResolveExperienceOptions
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import DebugExperience from './DebugExperience.svelte';
|
|
15
15
|
import MissingComponent from './MissingComponent.svelte';
|
|
16
16
|
import NodesRenderer from './NodesRenderer.svelte';
|
|
17
|
-
import
|
|
17
|
+
import WrapWithExperienceTemplate from './WrapWithExperienceTemplate.svelte';
|
|
18
18
|
import type { ClientExperienceRendererProps } from './component-props.js';
|
|
19
19
|
import { setExperience } from './context.js';
|
|
20
20
|
import type { RenderContext } from './types.js';
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
{#if debug}
|
|
74
74
|
<DebugExperience {experience} />
|
|
75
75
|
{/if}
|
|
76
|
-
<
|
|
76
|
+
<WrapWithExperienceTemplate experienceTemplate={experience.experienceTemplate} {config} experience={liveContext}>
|
|
77
77
|
{#snippet children()}
|
|
78
78
|
<NodesRenderer
|
|
79
79
|
nodes={experience.nodes}
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
{renderUnknown}
|
|
83
83
|
/>
|
|
84
84
|
{/snippet}
|
|
85
|
-
</
|
|
85
|
+
</WrapWithExperienceTemplate>
|
|
86
86
|
{/if}
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
const nodeCount = $derived(experience.nodes.length);
|
|
20
20
|
const summary = $derived(
|
|
21
21
|
`Experience debug — ${nodeCount} top-level node${nodeCount === 1 ? '' : 's'}${
|
|
22
|
-
experience.
|
|
22
|
+
experience.experienceTemplate
|
|
23
|
+
? `, experience template: ${experience.experienceTemplate.experienceTemplateId}`
|
|
24
|
+
: ''
|
|
23
25
|
}`
|
|
24
26
|
);
|
|
25
27
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DebugExperience.svelte.d.ts","sourceRoot":"","sources":["../src/DebugExperience.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"DebugExperience.svelte.d.ts","sourceRoot":"","sources":["../src/DebugExperience.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAqDjE,QAAA,MAAM,eAAe,0DAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -2,9 +2,9 @@ import { render } from '@testing-library/svelte';
|
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
3
|
import DebugExperience from './DebugExperience.svelte';
|
|
4
4
|
const emptyPlan = { nodes: [], viewports: [] };
|
|
5
|
-
function node(
|
|
5
|
+
function node(componentId, content = {}) {
|
|
6
6
|
return {
|
|
7
|
-
registration: {
|
|
7
|
+
registration: { componentId },
|
|
8
8
|
props: { content, design: {} },
|
|
9
9
|
slots: {},
|
|
10
10
|
};
|
|
@@ -29,14 +29,14 @@ describe('DebugExperience.svelte', () => {
|
|
|
29
29
|
const { container } = render(DebugExperience, { props: { experience: one } });
|
|
30
30
|
expect(container.innerHTML).toContain('Experience debug — 1 top-level node');
|
|
31
31
|
});
|
|
32
|
-
it('names the
|
|
32
|
+
it('names the experienceTemplate in the summary when present', () => {
|
|
33
33
|
const plan = {
|
|
34
34
|
viewports: [],
|
|
35
35
|
nodes: [],
|
|
36
|
-
|
|
36
|
+
experienceTemplate: { experienceTemplateId: 'page', props: { content: {}, design: {} } },
|
|
37
37
|
};
|
|
38
38
|
const { container } = render(DebugExperience, { props: { experience: plan } });
|
|
39
|
-
expect(container.innerHTML).toContain('template: page');
|
|
39
|
+
expect(container.innerHTML).toContain('experience template: page');
|
|
40
40
|
});
|
|
41
41
|
it('dumps the plan as pretty JSON', () => {
|
|
42
42
|
const plan = {
|
|
@@ -44,7 +44,7 @@ describe('DebugExperience.svelte', () => {
|
|
|
44
44
|
nodes: [node('button', { label: 'Go' })],
|
|
45
45
|
};
|
|
46
46
|
const { container } = render(DebugExperience, { props: { experience: plan } });
|
|
47
|
-
expect(container.innerHTML).toContain('
|
|
47
|
+
expect(container.innerHTML).toContain('componentId');
|
|
48
48
|
expect(container.innerHTML).toContain('button');
|
|
49
49
|
expect(container.innerHTML).toContain('Go');
|
|
50
50
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
* Default fallback rendered when an instance references a component
|
|
2
|
+
* Default fallback rendered when an instance references a component
|
|
3
3
|
* not present in the Config.
|
|
4
4
|
*
|
|
5
5
|
* Behavior: a visible debug box when `debug` is on, silent null otherwise.
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
import type { MissingComponentProps } from './component-props.js';
|
|
11
11
|
import { getExperience } from './context.js';
|
|
12
12
|
|
|
13
|
-
let {
|
|
13
|
+
let { componentId, nodeId }: MissingComponentProps = $props();
|
|
14
14
|
const experience = getExperience();
|
|
15
15
|
|
|
16
16
|
$effect(() => {
|
|
17
17
|
if (typeof console !== 'undefined') {
|
|
18
18
|
const idLabel = nodeId ? ` (nodeId: ${nodeId})` : '';
|
|
19
19
|
console.warn(
|
|
20
|
-
`[@contentful/experiences] No component registered for
|
|
20
|
+
`[@contentful/experiences] No component registered for id "${componentId}"${idLabel}.`
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
});
|
|
@@ -26,15 +26,15 @@
|
|
|
26
26
|
{#if experience.debug}
|
|
27
27
|
<div
|
|
28
28
|
style="border: 2px solid red; padding: 1rem; color: red; background: #fff; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8125rem;"
|
|
29
|
-
data-experiences-missing={
|
|
29
|
+
data-experiences-missing={componentId}
|
|
30
30
|
>
|
|
31
|
-
<strong>Missing component ‘{
|
|
31
|
+
<strong>Missing component ‘{componentId}’</strong>
|
|
32
32
|
<p style="margin: 0.5rem 0;">
|
|
33
33
|
This component is referenced by the Experience payload but is not registered in the Config.
|
|
34
34
|
Register it under this key in your <code>components</code> map:
|
|
35
35
|
</p>
|
|
36
36
|
<pre style="margin: 0; white-space: pre-wrap;">{JSON.stringify(
|
|
37
|
-
{
|
|
37
|
+
{ componentId, nodeId: nodeId ?? null },
|
|
38
38
|
null,
|
|
39
39
|
2
|
|
40
40
|
)}</pre>
|
package/dist/NodeRenderer.svelte
CHANGED
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
|
|
29
29
|
let { node, config, experience, renderUnknown, children }: NodeRendererProps = $props();
|
|
30
30
|
|
|
31
|
-
const entry = $derived(config.components[node.registration.
|
|
31
|
+
const entry = $derived(config.components[node.registration.componentId]);
|
|
32
32
|
const componentConfig = $derived(entry ? normalizeComponentRegistration(entry) : null);
|
|
33
33
|
|
|
34
34
|
const contentful: ContentfulComponent = {
|
|
35
|
-
|
|
35
|
+
componentId: node.registration.componentId,
|
|
36
36
|
nodeId: node.nodeId,
|
|
37
37
|
content: node.props.content,
|
|
38
38
|
design: node.props.design,
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
const { props, unresolved } = applyTokenResolver(resolvedDesign, config.resolveToken);
|
|
53
53
|
if (unresolved.length && typeof console !== 'undefined') {
|
|
54
54
|
console.warn(
|
|
55
|
-
`[@contentful/experiences-svelte] resolveToken returned undefined for token id(s) on "${node.registration.
|
|
55
|
+
`[@contentful/experiences-svelte] resolveToken returned undefined for token id(s) on "${node.registration.componentId}": ${unresolved.join(', ')}. getDesignValues() will omit those keys.`
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
return props;
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
{:else}
|
|
78
78
|
{@const Unknown = renderUnknown}
|
|
79
79
|
<Unknown
|
|
80
|
-
|
|
80
|
+
componentId={node.registration.componentId}
|
|
81
81
|
nodeId={node.nodeId}
|
|
82
82
|
/>
|
|
83
83
|
{/if}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import DebugExperience from './DebugExperience.svelte';
|
|
15
15
|
import MissingComponent from './MissingComponent.svelte';
|
|
16
16
|
import NodesRenderer from './NodesRenderer.svelte';
|
|
17
|
-
import
|
|
17
|
+
import WrapWithExperienceTemplate from './WrapWithExperienceTemplate.svelte';
|
|
18
18
|
import type { ServerExperienceRendererProps } from './component-props.js';
|
|
19
19
|
import { setExperience } from './context.js';
|
|
20
20
|
import type { RenderContext } from './types.js';
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
{#if debug}
|
|
63
63
|
<DebugExperience {experience} />
|
|
64
64
|
{/if}
|
|
65
|
-
<
|
|
65
|
+
<WrapWithExperienceTemplate experienceTemplate={experience.experienceTemplate} {config} experience={renderContext}>
|
|
66
66
|
{#snippet children()}
|
|
67
67
|
<NodesRenderer
|
|
68
68
|
nodes={experience.nodes}
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
{renderUnknown}
|
|
72
72
|
/>
|
|
73
73
|
{/snippet}
|
|
74
|
-
</
|
|
74
|
+
</WrapWithExperienceTemplate>
|
|
75
75
|
{/if}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* Wraps the rendered Experience nodes with the page-level Experience Template when the
|
|
3
|
+
* plan carries one and the customer registered an Experience Template config under that
|
|
4
|
+
* id. When the Experience Template is referenced but unregistered, warns once and
|
|
5
|
+
* renders children unwrapped — graceful degradation matches the
|
|
6
|
+
* unknown-component fallback story.
|
|
7
|
+
-->
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
|
|
11
|
+
import type { PortableExperienceTemplate } from '@contentful/experiences-sdk-core';
|
|
12
|
+
import { applyTokenResolver, resolveDesignProperties } from '@contentful/experiences-design';
|
|
13
|
+
|
|
14
|
+
import { setContentfulExperienceTemplate, setResolvedDesign } from './context.js';
|
|
15
|
+
import {
|
|
16
|
+
normalizeExperienceTemplateRegistration,
|
|
17
|
+
type ContentfulExperienceTemplate,
|
|
18
|
+
type Config,
|
|
19
|
+
type RenderContext,
|
|
20
|
+
} from './types.js';
|
|
21
|
+
|
|
22
|
+
interface WrapWithExperienceTemplateProps {
|
|
23
|
+
experienceTemplate: PortableExperienceTemplate | undefined;
|
|
24
|
+
config: Config;
|
|
25
|
+
experience: RenderContext;
|
|
26
|
+
children: Snippet;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let { experienceTemplate, config, experience, children }: WrapWithExperienceTemplateProps = $props();
|
|
30
|
+
|
|
31
|
+
// setContext must run during synchronous component init — call once with
|
|
32
|
+
// the initial value (Experience Templates do not toggle on/off mid-mount).
|
|
33
|
+
if (experienceTemplate) {
|
|
34
|
+
setContentfulExperienceTemplate({
|
|
35
|
+
experienceTemplateId: experienceTemplate.experienceTemplateId,
|
|
36
|
+
content: experienceTemplate.props.content,
|
|
37
|
+
design: experienceTemplate.props.design,
|
|
38
|
+
resolved: experienceTemplate.props.resolved,
|
|
39
|
+
} satisfies ContentfulExperienceTemplate);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const entry = $derived(experienceTemplate ? config.experienceTemplates?.[experienceTemplate.experienceTemplateId] : undefined);
|
|
43
|
+
const experienceTemplateConfig = $derived(entry ? normalizeExperienceTemplateRegistration(entry) : null);
|
|
44
|
+
|
|
45
|
+
const tokenResolvedDesign = $derived.by(() => {
|
|
46
|
+
if (!experienceTemplate) return {};
|
|
47
|
+
const resolvedDesign = resolveDesignProperties(
|
|
48
|
+
experienceTemplate.props.design,
|
|
49
|
+
experience.viewports,
|
|
50
|
+
experience.activeViewportIndex
|
|
51
|
+
);
|
|
52
|
+
const { props, unresolved } = applyTokenResolver(resolvedDesign, config.resolveToken);
|
|
53
|
+
if (unresolved.length && typeof console !== 'undefined') {
|
|
54
|
+
console.warn(
|
|
55
|
+
`[@contentful/experiences-svelte] resolveToken returned undefined for token id(s) on experience template "${experienceTemplate.experienceTemplateId}": ${unresolved.join(', ')}. getDesignValues() will omit those keys.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return props;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// A getter (not a snapshot) so getDesignValues() stays reactive; not merged into props.
|
|
62
|
+
setResolvedDesign(() => tokenResolvedDesign);
|
|
63
|
+
|
|
64
|
+
const composed = $derived.by(() => {
|
|
65
|
+
if (!experienceTemplate || !experienceTemplateConfig) return null;
|
|
66
|
+
return {
|
|
67
|
+
...experienceTemplateConfig.defaults,
|
|
68
|
+
...experienceTemplate.props.content,
|
|
69
|
+
...experienceTemplate.props.resolved,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
$effect(() => {
|
|
74
|
+
if (experienceTemplate && !experienceTemplateConfig && typeof console !== 'undefined') {
|
|
75
|
+
console.warn(
|
|
76
|
+
`[@contentful/experiences-svelte] No experience template registered for id "${experienceTemplate.experienceTemplateId}". Rendering nodes without the experience template wrapper.`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
{#if experienceTemplate && experienceTemplateConfig && composed}
|
|
83
|
+
{@const Tpl = experienceTemplateConfig.component}
|
|
84
|
+
<Tpl {...composed} {children} />
|
|
85
|
+
{:else}
|
|
86
|
+
{@render children()}
|
|
87
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { PortableExperienceTemplate } from '@contentful/experiences-sdk-core';
|
|
3
|
+
import { type Config, type RenderContext } from './types.js';
|
|
4
|
+
interface WrapWithExperienceTemplateProps {
|
|
5
|
+
experienceTemplate: PortableExperienceTemplate | undefined;
|
|
6
|
+
config: Config;
|
|
7
|
+
experience: RenderContext;
|
|
8
|
+
children: Snippet;
|
|
9
|
+
}
|
|
10
|
+
declare const WrapWithExperienceTemplate: import("svelte").Component<WrapWithExperienceTemplateProps, {}, "">;
|
|
11
|
+
type WrapWithExperienceTemplate = ReturnType<typeof WrapWithExperienceTemplate>;
|
|
12
|
+
export default WrapWithExperienceTemplate;
|
|
13
|
+
//# sourceMappingURL=WrapWithExperienceTemplate.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WrapWithExperienceTemplate.svelte.d.ts","sourceRoot":"","sources":["../src/WrapWithExperienceTemplate.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAInF,OAAO,EAGH,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB,UAAU,+BAA+B;IACvC,kBAAkB,EAAE,0BAA0B,GAAG,SAAS,CAAC;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AA0EH,QAAA,MAAM,0BAA0B,qEAAwC,CAAC;AACzE,KAAK,0BAA0B,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAChF,eAAe,0BAA0B,CAAC"}
|
|
@@ -20,7 +20,7 @@ export interface ServerExperienceRendererProps {
|
|
|
20
20
|
}
|
|
21
21
|
export type ClientExperienceRendererProps = ServerExperienceRendererProps;
|
|
22
22
|
export interface MissingComponentProps {
|
|
23
|
-
|
|
23
|
+
componentId: string;
|
|
24
24
|
/** Optional — only present when the payload supplied an id for this node. */
|
|
25
25
|
nodeId?: string;
|
|
26
26
|
}
|
|
@@ -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;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,MAAM,6BAA6B,GAAG,6BAA6B,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,
|
|
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;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;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,oBAAoB;IACnC,+EAA+E;IAC/E,UAAU,EAAE,kBAAkB,CAAC;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB"}
|
package/dist/context.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import type { ContentfulComponent,
|
|
1
|
+
import type { ContentfulComponent, ContentfulExperienceTemplate, RenderContext } from './types.js';
|
|
2
2
|
export declare function setExperience(ctx: RenderContext): void;
|
|
3
3
|
export declare function setContentfulComponent(node: ContentfulComponent): void;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function setContentfulExperienceTemplate(tpl: ContentfulExperienceTemplate): void;
|
|
5
5
|
/**
|
|
6
|
-
* Publish the resolved design values for the enclosing node
|
|
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
8
|
* reactive across viewport changes.
|
|
9
9
|
*/
|
|
10
10
|
export declare function setResolvedDesign(getDesign: () => Record<string, unknown>): void;
|
|
11
11
|
export declare function getExperience(): RenderContext;
|
|
12
12
|
export declare function getContentfulComponent(): ContentfulComponent | undefined;
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function getContentfulExperienceTemplate(): ContentfulExperienceTemplate | undefined;
|
|
14
14
|
/**
|
|
15
15
|
* Read the design values the renderer resolved for the enclosing node or
|
|
16
|
-
* template. Returns `undefined` outside a rendered node
|
|
16
|
+
* experience template. Returns `undefined` outside a rendered node or
|
|
17
|
+
* experience template, which
|
|
17
18
|
* `getDesignValues` treats as "nothing to read."
|
|
18
19
|
*/
|
|
19
20
|
export declare function getResolvedDesign(): Record<string, unknown> | undefined;
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,
|
|
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"}
|
package/dist/context.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { getContext, setContext } from 'svelte';
|
|
19
19
|
const EXPERIENCE_KEY = Symbol('@contentful/experiences-svelte::experience');
|
|
20
20
|
const COMPONENT_KEY = Symbol('@contentful/experiences-svelte::contentful-component');
|
|
21
|
-
const
|
|
21
|
+
const EXPERIENCE_TEMPLATE_KEY = Symbol('@contentful/experiences-svelte::contentful-experience-template');
|
|
22
22
|
const RESOLVED_DESIGN_KEY = Symbol('@contentful/experiences-svelte::resolved-design');
|
|
23
23
|
export function setExperience(ctx) {
|
|
24
24
|
setContext(EXPERIENCE_KEY, ctx);
|
|
@@ -26,11 +26,11 @@ export function setExperience(ctx) {
|
|
|
26
26
|
export function setContentfulComponent(node) {
|
|
27
27
|
setContext(COMPONENT_KEY, node);
|
|
28
28
|
}
|
|
29
|
-
export function
|
|
30
|
-
setContext(
|
|
29
|
+
export function setContentfulExperienceTemplate(tpl) {
|
|
30
|
+
setContext(EXPERIENCE_TEMPLATE_KEY, tpl);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Publish the resolved design values for the enclosing node
|
|
33
|
+
* Publish the resolved design values for the enclosing node or experience template. Takes a
|
|
34
34
|
* getter (not a snapshot) so callers reading it inside a `$derived` stay
|
|
35
35
|
* reactive across viewport changes.
|
|
36
36
|
*/
|
|
@@ -47,12 +47,13 @@ export function getExperience() {
|
|
|
47
47
|
export function getContentfulComponent() {
|
|
48
48
|
return getContext(COMPONENT_KEY);
|
|
49
49
|
}
|
|
50
|
-
export function
|
|
51
|
-
return getContext(
|
|
50
|
+
export function getContentfulExperienceTemplate() {
|
|
51
|
+
return getContext(EXPERIENCE_TEMPLATE_KEY);
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Read the design values the renderer resolved for the enclosing node or
|
|
55
|
-
* template. Returns `undefined` outside a rendered node
|
|
55
|
+
* experience template. Returns `undefined` outside a rendered node or
|
|
56
|
+
* experience template, which
|
|
56
57
|
* `getDesignValues` treats as "nothing to read."
|
|
57
58
|
*/
|
|
58
59
|
export function getResolvedDesign() {
|
package/dist/index.d.ts
CHANGED
|
@@ -6,17 +6,17 @@ export { default as DebugExperience } from './DebugExperience.svelte';
|
|
|
6
6
|
export { default as NodesRenderer } from './NodesRenderer.svelte';
|
|
7
7
|
export { useActiveViewport } from './use-active-viewport.svelte.js';
|
|
8
8
|
export type { UseActiveViewportResult } from './use-active-viewport.svelte.js';
|
|
9
|
-
export { getExperience, getContentfulComponent,
|
|
9
|
+
export { getExperience, getContentfulComponent, getContentfulExperienceTemplate, } from './context.js';
|
|
10
10
|
export { getDesignValues } from './get-design-values.js';
|
|
11
11
|
export { toCss } from './design-utils.js';
|
|
12
12
|
export type { ToCssOptions } from './design-utils.js';
|
|
13
13
|
export type { ClientExperienceRendererProps, ClientExperienceRendererProps as ExperienceRendererProps, DebugExperienceProps, MissingComponentProps, RenderUnknown, ServerExperienceRendererProps, } from './component-props.js';
|
|
14
|
-
export { defineComponent,
|
|
15
|
-
export type { ComponentConfig, Components, Config, ContentfulComponent,
|
|
14
|
+
export { defineComponent, defineExperienceTemplate, normalizeComponentRegistration, normalizeExperienceTemplateRegistration, } from './types.js';
|
|
15
|
+
export type { ComponentConfig, Components, Config, ContentfulComponent, ContentfulExperienceTemplate, ExperienceTemplateConfig, ExperienceTemplateRegistration, ExperienceTemplates, Registration, RenderContext, ResolveToken, } from './types.js';
|
|
16
16
|
export { resolveExperience } from '@contentful/experiences-sdk-core';
|
|
17
17
|
export type { ResolverConfig, ResolveExperienceOptions } from '@contentful/experiences-sdk-core';
|
|
18
|
-
export type {
|
|
18
|
+
export type { ComponentNode, ComponentRef, DesignPropValue, DesignToken, ExperienceContext, ExperienceNode, ExperiencePayload, ExperienceSys, ExperienceTemplateNode, ExperienceTemplateRef, ManualDesignValue, PortableExperienceTemplate, PortableRegistration, PortableRenderNode, PortableRenderPlan, ResolveContext, ValuesByViewport, ViewportDef, } from '@contentful/experiences-sdk-core';
|
|
19
19
|
export { CSS_PROPERTIES, getValueForViewport, getViewportIndex, isCssProperty, resolveDesignProperties, toCssKey, toCssMediaQuery, } from '@contentful/experiences-design';
|
|
20
|
-
export { ContentfulViewDelivery, ContentfulViewDeliveryClient, DELIVERY_HOST, NotFoundError, PREVIEW_HOST, createClient, fetchExperience, } from '@contentful/experiences-client';
|
|
20
|
+
export { ALPHA_FEATURE_HEADER, ContentfulViewDelivery, ContentfulViewDeliveryClient, DELIVERY_HOST, NEW_EXO_ENTITY_TYPES, NEW_EXO_ENTITY_TYPES_HEADERS, NotFoundError, PREVIEW_HOST, createClient, fetchExperience, } from '@contentful/experiences-client';
|
|
21
21
|
export type { ClientOptions, CreateClientOptions, ExperienceOptions, ResolveOptions, } from '@contentful/experiences-client';
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAItE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAG/E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAItE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAG/E,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,+BAA+B,GAChC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,YAAY,EACV,6BAA6B,EAC7B,6BAA6B,IAAI,uBAAuB,EACxD,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,8BAA8B,EAC9B,uCAAuC,GACxC,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,eAAe,EACf,UAAU,EACV,MAAM,EACN,mBAAmB,EACnB,4BAA4B,EAC5B,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAGjG,YAAY,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,0BAA0B,EAC1B,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,WAAW,GACZ,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,QAAQ,EACR,eAAe,GAChB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,4BAA4B,EAC5B,aAAa,EACb,oBAAoB,EACpB,4BAA4B,EAC5B,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,GACf,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22,14 +22,14 @@ export { default as DebugExperience } from './DebugExperience.svelte';
|
|
|
22
22
|
export { default as NodesRenderer } from './NodesRenderer.svelte';
|
|
23
23
|
export { useActiveViewport } from './use-active-viewport.svelte.js';
|
|
24
24
|
// ─── Runtime context helpers ─────────────────────────────────────────────
|
|
25
|
-
export { getExperience, getContentfulComponent,
|
|
25
|
+
export { getExperience, getContentfulComponent, getContentfulExperienceTemplate, } from './context.js';
|
|
26
26
|
export { getDesignValues } from './get-design-values.js';
|
|
27
27
|
export { toCss } from './design-utils.js';
|
|
28
28
|
// ─── Authoring helpers + Config types ─────────────────────────────────────
|
|
29
|
-
export { defineComponent,
|
|
29
|
+
export { defineComponent, defineExperienceTemplate, normalizeComponentRegistration, normalizeExperienceTemplateRegistration, } from './types.js';
|
|
30
30
|
// ─── Resolver (re-exported from render-core) ──────────────────────────────
|
|
31
31
|
export { resolveExperience } from '@contentful/experiences-sdk-core';
|
|
32
32
|
// ─── Design utilities (re-exported from design) ───────────────────────────
|
|
33
33
|
export { CSS_PROPERTIES, getValueForViewport, getViewportIndex, isCssProperty, resolveDesignProperties, toCssKey, toCssMediaQuery, } from '@contentful/experiences-design';
|
|
34
34
|
// ─── Delivery client + fetchExperience ────────────────────────────────────
|
|
35
|
-
export { ContentfulViewDelivery, ContentfulViewDeliveryClient, DELIVERY_HOST, NotFoundError, PREVIEW_HOST, createClient, fetchExperience, } from '@contentful/experiences-client';
|
|
35
|
+
export { ALPHA_FEATURE_HEADER, ContentfulViewDelivery, ContentfulViewDeliveryClient, DELIVERY_HOST, NEW_EXO_ENTITY_TYPES, NEW_EXO_ENTITY_TYPES_HEADERS, NotFoundError, PREVIEW_HOST, createClient, fetchExperience, } from '@contentful/experiences-client';
|
|
@@ -8,7 +8,7 @@ import ContainerFixture from './test-fixtures/ContainerFixture.svelte';
|
|
|
8
8
|
import HeadingFixture from './test-fixtures/HeadingFixture.svelte';
|
|
9
9
|
import ItemFixture from './test-fixtures/ItemFixture.svelte';
|
|
10
10
|
import PrecedenceFixture from './test-fixtures/PrecedenceFixture.svelte';
|
|
11
|
-
import
|
|
11
|
+
import ExperienceTemplateFixture from './test-fixtures/ExperienceTemplateFixture.svelte';
|
|
12
12
|
import { captureSink } from './test-fixtures/capture-sink.js';
|
|
13
13
|
import { toCss } from './design-utils.js';
|
|
14
14
|
const VIEWPORTS = [
|
|
@@ -24,11 +24,11 @@ const vbv = (values) => ({
|
|
|
24
24
|
const dt = (value) => ({ type: 'DesignToken', value });
|
|
25
25
|
function componentNode(typeId, rest = {}) {
|
|
26
26
|
return {
|
|
27
|
-
|
|
27
|
+
component: {
|
|
28
28
|
sys: {
|
|
29
29
|
type: 'ResourceLink',
|
|
30
|
-
linkType: 'Contentful:
|
|
31
|
-
urn: `crn:contentful:::experience:spaces/$self/environments/$self/
|
|
30
|
+
linkType: 'Contentful:Component',
|
|
31
|
+
urn: `crn:contentful:::experience:spaces/$self/environments/$self/components/${typeId}`,
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
...rest,
|
|
@@ -156,13 +156,13 @@ describe('ServerExperienceRenderer', () => {
|
|
|
156
156
|
nodes: [
|
|
157
157
|
{
|
|
158
158
|
nodeId: 'root',
|
|
159
|
-
registration: {
|
|
159
|
+
registration: { componentId: 'contentful-container' },
|
|
160
160
|
props: { content: {}, design: {} },
|
|
161
161
|
slots: {
|
|
162
162
|
children: [
|
|
163
163
|
{
|
|
164
164
|
nodeId: 'ghost',
|
|
165
|
-
registration: {
|
|
165
|
+
registration: { componentId: 'NotRegistered' },
|
|
166
166
|
props: { content: {}, design: {} },
|
|
167
167
|
slots: {},
|
|
168
168
|
},
|
|
@@ -244,7 +244,7 @@ describe('ServerExperienceRenderer', () => {
|
|
|
244
244
|
nodes: [
|
|
245
245
|
{
|
|
246
246
|
nodeId: 'r',
|
|
247
|
-
registration: {
|
|
247
|
+
registration: { componentId: 'item' },
|
|
248
248
|
props: {
|
|
249
249
|
content: { value: 'fromContent' },
|
|
250
250
|
design: {},
|
|
@@ -259,20 +259,20 @@ describe('ServerExperienceRenderer', () => {
|
|
|
259
259
|
});
|
|
260
260
|
expect(container.innerHTML).toContain('data-value="fromResolveData"');
|
|
261
261
|
});
|
|
262
|
-
it('wraps rendered nodes with the registered
|
|
262
|
+
it('wraps rendered nodes with the registered experienceTemplate', async () => {
|
|
263
263
|
const tplConfig = {
|
|
264
264
|
components: { item: PrecedenceFixture },
|
|
265
|
-
|
|
266
|
-
page: { component:
|
|
265
|
+
experienceTemplates: {
|
|
266
|
+
page: { component: ExperienceTemplateFixture, defaults: { title: 'Default Title' } },
|
|
267
267
|
},
|
|
268
268
|
};
|
|
269
269
|
const tplPayload = {
|
|
270
270
|
sys: {
|
|
271
|
-
|
|
271
|
+
experienceTemplate: {
|
|
272
272
|
sys: {
|
|
273
273
|
type: 'ResourceLink',
|
|
274
|
-
linkType: 'Contentful:
|
|
275
|
-
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/
|
|
274
|
+
linkType: 'Contentful:ExperienceTemplate',
|
|
275
|
+
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/experienceTemplates/page',
|
|
276
276
|
},
|
|
277
277
|
},
|
|
278
278
|
},
|
|
@@ -283,20 +283,20 @@ describe('ServerExperienceRenderer', () => {
|
|
|
283
283
|
const { container } = render(ServerExperienceRenderer, {
|
|
284
284
|
props: { experience: plan, config: tplConfig },
|
|
285
285
|
});
|
|
286
|
-
expect(container.innerHTML).toContain('data-template="page"');
|
|
286
|
+
expect(container.innerHTML).toContain('data-experience-template="page"');
|
|
287
287
|
expect(container.innerHTML).toContain('data-title="Default Title"');
|
|
288
288
|
expect(container.innerHTML).toContain('inside');
|
|
289
289
|
});
|
|
290
|
-
it('renders nodes unwrapped + warns when the
|
|
290
|
+
it('renders nodes unwrapped + warns when the experienceTemplate is not registered', async () => {
|
|
291
291
|
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
292
292
|
const cfg = { components: { item: PrecedenceFixture } };
|
|
293
293
|
const tplPayload = {
|
|
294
294
|
sys: {
|
|
295
|
-
|
|
295
|
+
experienceTemplate: {
|
|
296
296
|
sys: {
|
|
297
297
|
type: 'ResourceLink',
|
|
298
|
-
linkType: 'Contentful:
|
|
299
|
-
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/
|
|
298
|
+
linkType: 'Contentful:ExperienceTemplate',
|
|
299
|
+
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/experienceTemplates/missing-experienceTemplate',
|
|
300
300
|
},
|
|
301
301
|
},
|
|
302
302
|
},
|
|
@@ -308,8 +308,8 @@ describe('ServerExperienceRenderer', () => {
|
|
|
308
308
|
props: { experience: plan, config: cfg },
|
|
309
309
|
});
|
|
310
310
|
expect(container.innerHTML).toContain('data-value="unwrapped"');
|
|
311
|
-
expect(container.innerHTML).not.toContain('data-template');
|
|
312
|
-
expect(warn).toHaveBeenCalledWith(expect.stringContaining('missing-
|
|
311
|
+
expect(container.innerHTML).not.toContain('data-experience-template');
|
|
312
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('missing-experienceTemplate'));
|
|
313
313
|
warn.mockRestore();
|
|
314
314
|
});
|
|
315
315
|
});
|
|
@@ -365,7 +365,7 @@ describe('ServerExperienceRenderer — getContentfulComponent()', () => {
|
|
|
365
365
|
});
|
|
366
366
|
const contentful = captureSink[0].contentful;
|
|
367
367
|
expect(contentful).toMatchObject({
|
|
368
|
-
|
|
368
|
+
componentId: 'capture',
|
|
369
369
|
nodeId: 'btn-1',
|
|
370
370
|
content: { label: 'Buy now' },
|
|
371
371
|
design: { cfPadding: vbv({ desktop: m('40px') }) },
|
|
@@ -434,7 +434,7 @@ describe('ServerExperienceRenderer — resolveToken', () => {
|
|
|
434
434
|
expect(warn).toHaveBeenCalledWith(expect.stringContaining('contentful-button'));
|
|
435
435
|
warn.mockRestore();
|
|
436
436
|
});
|
|
437
|
-
it('leaves envelopes untouched when no resolver is supplied
|
|
437
|
+
it('leaves envelopes untouched when no resolver is supplied', async () => {
|
|
438
438
|
const cfg = { components: { 'contentful-button': ButtonFixture } };
|
|
439
439
|
const plan = await resolveExperience({
|
|
440
440
|
viewports: VIEWPORTS,
|
|
@@ -454,19 +454,19 @@ describe('ServerExperienceRenderer — resolveToken', () => {
|
|
|
454
454
|
// unchanged, so the customer can inspect it or resolve it themselves.
|
|
455
455
|
expect(container.innerHTML).toContain('data-bg="[object Object]"');
|
|
456
456
|
});
|
|
457
|
-
it('runs on page-level
|
|
457
|
+
it('runs on page-level experienceTemplate design props too', async () => {
|
|
458
458
|
const tplConfig = {
|
|
459
459
|
components: { item: PrecedenceFixture },
|
|
460
|
-
|
|
460
|
+
experienceTemplates: { page: ExperienceTemplateFixture },
|
|
461
461
|
resolveToken: (ref) => (ref.value === 'brand/canvas' ? '#111827' : undefined),
|
|
462
462
|
};
|
|
463
463
|
const tplPayload = {
|
|
464
464
|
sys: {
|
|
465
|
-
|
|
465
|
+
experienceTemplate: {
|
|
466
466
|
sys: {
|
|
467
467
|
type: 'ResourceLink',
|
|
468
|
-
linkType: 'Contentful:
|
|
469
|
-
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/
|
|
468
|
+
linkType: 'Contentful:ExperienceTemplate',
|
|
469
|
+
urn: 'crn:contentful:::experience:spaces/$self/environments/$self/experienceTemplates/page',
|
|
470
470
|
},
|
|
471
471
|
},
|
|
472
472
|
},
|
|
@@ -475,8 +475,8 @@ describe('ServerExperienceRenderer — resolveToken', () => {
|
|
|
475
475
|
};
|
|
476
476
|
const plan = await resolveExperience(tplPayload, tplConfig);
|
|
477
477
|
// Templates don't carry design props in the current XDA payload shape;
|
|
478
|
-
// seed one on the resolved plan so we exercise the
|
|
479
|
-
plan.
|
|
478
|
+
// seed one on the resolved plan so we exercise the experienceTemplate path.
|
|
479
|
+
plan.experienceTemplate.props.design = { cfBackground: dt('brand/canvas') };
|
|
480
480
|
const { container } = render(ServerExperienceRenderer, {
|
|
481
481
|
props: { experience: plan, config: tplConfig },
|
|
482
482
|
});
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
const design = $derived(getDesignValues());
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<main data-template="page" data-title={title} data-bg={design.cfBackground as string}>
|
|
16
|
+
<main data-experience-template="page" data-title={title} data-bg={design.cfBackground as string}>
|
|
17
17
|
{@render children()}
|
|
18
18
|
</main>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
title?: string;
|
|
4
|
+
children: Snippet;
|
|
5
|
+
};
|
|
6
|
+
declare const ExperienceTemplateFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type ExperienceTemplateFixture = ReturnType<typeof ExperienceTemplateFixture>;
|
|
8
|
+
export default ExperienceTemplateFixture;
|
|
9
|
+
//# sourceMappingURL=ExperienceTemplateFixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExperienceTemplateFixture.svelte.d.ts","sourceRoot":"","sources":["../../src/test-fixtures/ExperienceTemplateFixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIrC,KAAK,gBAAgB,GAAI;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAmBJ,QAAA,MAAM,yBAAyB,sDAAwC,CAAC;AACxE,KAAK,yBAAyB,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC9E,eAAe,yBAAyB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { ResolveContext, ResolveToken };
|
|
|
5
5
|
* The full Contentful-side payload for a single component instance, exposed
|
|
6
6
|
* via `getContentfulComponent()` to any descendant of a rendered Experience
|
|
7
7
|
* node. Useful for custom design-property resolution outside the SDK's
|
|
8
|
-
* cascade, branching by `
|
|
8
|
+
* cascade, branching by `componentId` in a generic wrapper, keying
|
|
9
9
|
* analytics on `nodeId`, rendering a raw-payload panel in preview, or
|
|
10
10
|
* rendering non-`children` slots through the exported `<NodesRenderer />`.
|
|
11
11
|
*
|
|
@@ -14,7 +14,7 @@ export type { ResolveContext, ResolveToken };
|
|
|
14
14
|
* resolved values are what `getDesignValues()` returns.
|
|
15
15
|
*/
|
|
16
16
|
export interface ContentfulComponent {
|
|
17
|
-
|
|
17
|
+
componentId: string;
|
|
18
18
|
nodeId?: string;
|
|
19
19
|
content: Record<string, unknown>;
|
|
20
20
|
design: Record<string, DesignPropValue>;
|
|
@@ -28,11 +28,12 @@ export interface ContentfulComponent {
|
|
|
28
28
|
slots: Record<string, unknown>;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Same shape as `ContentfulComponent`, but for the page-level
|
|
32
|
-
*
|
|
31
|
+
* Same shape as `ContentfulComponent`, but for the page-level Experience
|
|
32
|
+
* Template.
|
|
33
|
+
* Exposed via `getContentfulExperienceTemplate()` inside an Experience Template's component tree.
|
|
33
34
|
*/
|
|
34
|
-
export interface
|
|
35
|
-
|
|
35
|
+
export interface ContentfulExperienceTemplate {
|
|
36
|
+
experienceTemplateId: string;
|
|
36
37
|
content: Record<string, unknown>;
|
|
37
38
|
design: Record<string, DesignPropValue>;
|
|
38
39
|
resolved?: Record<string, unknown>;
|
|
@@ -68,19 +69,19 @@ export interface ComponentConfig<Props extends object = Record<string, unknown>>
|
|
|
68
69
|
* card: defineComponent<CardProps>({ component: Card, resolveData: ... }),
|
|
69
70
|
*/
|
|
70
71
|
export type Registration<Props extends object = Record<string, unknown>> = Component<any> | ComponentConfig<Props>;
|
|
71
|
-
export interface
|
|
72
|
+
export interface ExperienceTemplateConfig<Props extends object = Record<string, unknown>> {
|
|
72
73
|
defaults?: Partial<Props>;
|
|
73
74
|
resolveData?: (ctx: ResolveContext) => Partial<Props> | Promise<Partial<Props>>;
|
|
74
75
|
component: Component<any>;
|
|
75
76
|
}
|
|
76
|
-
export type
|
|
77
|
-
export declare function
|
|
77
|
+
export type ExperienceTemplateRegistration<Props extends object = Record<string, unknown>> = Component<any> | ExperienceTemplateConfig<Props>;
|
|
78
|
+
export declare function defineExperienceTemplate<Props extends object = Record<string, unknown>>(config: ExperienceTemplateConfig<Props>): ExperienceTemplateConfig<Props>;
|
|
78
79
|
export declare function defineComponent<Props extends object = Record<string, unknown>>(config: ComponentConfig<Props>): ComponentConfig<Props>;
|
|
79
80
|
export type Components = Record<string, Registration<any>>;
|
|
80
|
-
export type
|
|
81
|
+
export type ExperienceTemplates = Record<string, ExperienceTemplateRegistration<any>>;
|
|
81
82
|
export interface Config {
|
|
82
83
|
components: Components;
|
|
83
|
-
|
|
84
|
+
experienceTemplates?: ExperienceTemplates;
|
|
84
85
|
/**
|
|
85
86
|
* Resolves `DesignToken` envelopes to runtime values before they reach a
|
|
86
87
|
* component. If omitted, envelopes pass through unchanged. See `ResolveToken`
|
|
@@ -95,5 +96,5 @@ export interface Config {
|
|
|
95
96
|
* a `component` field, so `typeof` is enough to discriminate.
|
|
96
97
|
*/
|
|
97
98
|
export declare function normalizeComponentRegistration<P extends object>(reg: Registration<P>): ComponentConfig<P>;
|
|
98
|
-
export declare function
|
|
99
|
+
export declare function normalizeExperienceTemplateRegistration<P extends object>(reg: ExperienceTemplateRegistration<P>): ExperienceTemplateConfig<P>;
|
|
99
100
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,WAAW,EACZ,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAClC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function defineExperienceTemplate(config) {
|
|
2
2
|
return config;
|
|
3
3
|
}
|
|
4
4
|
export function defineComponent(config) {
|
|
@@ -17,7 +17,7 @@ export function normalizeComponentRegistration(reg) {
|
|
|
17
17
|
}
|
|
18
18
|
return reg;
|
|
19
19
|
}
|
|
20
|
-
export function
|
|
20
|
+
export function normalizeExperienceTemplateRegistration(reg) {
|
|
21
21
|
if (typeof reg === 'function') {
|
|
22
22
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
23
|
return { component: reg };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experiences-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Svelte adapter for Contentful Experiences — Server and Client renderers over a PortableRenderPlan",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@contentful/experiences-client": "0.
|
|
39
|
-
"@contentful/experiences-sdk-core": "0.
|
|
40
|
-
"@contentful/experiences-design": "0.
|
|
38
|
+
"@contentful/experiences-client": "0.3.0",
|
|
39
|
+
"@contentful/experiences-sdk-core": "0.7.0",
|
|
40
|
+
"@contentful/experiences-design": "0.7.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"svelte": "^5.55.7"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@testing-library/jest-dom": "^6.9.1",
|
|
49
49
|
"@testing-library/svelte": "^5.4.2",
|
|
50
50
|
"jsdom": "^29.1.1",
|
|
51
|
-
"publint": "^0.3.
|
|
51
|
+
"publint": "^0.3.23",
|
|
52
52
|
"svelte": "^5.56.8",
|
|
53
53
|
"svelte-check": "^4.7.4"
|
|
54
54
|
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
* Wraps the rendered Experience nodes with the page-level template when the
|
|
3
|
-
* plan carries one and the customer registered a template config under that
|
|
4
|
-
* id. When the template is referenced but unregistered, warns once and
|
|
5
|
-
* renders children unwrapped — graceful degradation matches the
|
|
6
|
-
* unknown-component fallback story.
|
|
7
|
-
-->
|
|
8
|
-
<script lang="ts">
|
|
9
|
-
import type { Snippet } from 'svelte';
|
|
10
|
-
|
|
11
|
-
import type { PortableTemplate } from '@contentful/experiences-sdk-core';
|
|
12
|
-
import { applyTokenResolver, resolveDesignProperties } from '@contentful/experiences-design';
|
|
13
|
-
|
|
14
|
-
import { setContentfulTemplate, setResolvedDesign } from './context.js';
|
|
15
|
-
import {
|
|
16
|
-
normalizeTemplateRegistration,
|
|
17
|
-
type ContentfulTemplate,
|
|
18
|
-
type Config,
|
|
19
|
-
type RenderContext,
|
|
20
|
-
} from './types.js';
|
|
21
|
-
|
|
22
|
-
interface WrapWithTemplateProps {
|
|
23
|
-
template: PortableTemplate | undefined;
|
|
24
|
-
config: Config;
|
|
25
|
-
experience: RenderContext;
|
|
26
|
-
children: Snippet;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let { template, config, experience, children }: WrapWithTemplateProps = $props();
|
|
30
|
-
|
|
31
|
-
// setContext must run during synchronous component init — call once with
|
|
32
|
-
// the initial template value (templates don't toggle on/off mid-mount).
|
|
33
|
-
if (template) {
|
|
34
|
-
setContentfulTemplate({
|
|
35
|
-
templateId: template.templateId,
|
|
36
|
-
content: template.props.content,
|
|
37
|
-
design: template.props.design,
|
|
38
|
-
resolved: template.props.resolved,
|
|
39
|
-
} satisfies ContentfulTemplate);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const entry = $derived(template ? config.templates?.[template.templateId] : undefined);
|
|
43
|
-
const templateConfig = $derived(entry ? normalizeTemplateRegistration(entry) : null);
|
|
44
|
-
|
|
45
|
-
const tokenResolvedDesign = $derived.by(() => {
|
|
46
|
-
if (!template) return {};
|
|
47
|
-
const resolvedDesign = resolveDesignProperties(
|
|
48
|
-
template.props.design,
|
|
49
|
-
experience.viewports,
|
|
50
|
-
experience.activeViewportIndex
|
|
51
|
-
);
|
|
52
|
-
const { props, unresolved } = applyTokenResolver(resolvedDesign, config.resolveToken);
|
|
53
|
-
if (unresolved.length && typeof console !== 'undefined') {
|
|
54
|
-
console.warn(
|
|
55
|
-
`[@contentful/experiences-svelte] resolveToken returned undefined for token id(s) on template "${template.templateId}": ${unresolved.join(', ')}. getDesignValues() will omit those keys.`
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
return props;
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// A getter (not a snapshot) so getDesignValues() stays reactive; not merged into props.
|
|
62
|
-
setResolvedDesign(() => tokenResolvedDesign);
|
|
63
|
-
|
|
64
|
-
const composed = $derived.by(() => {
|
|
65
|
-
if (!template || !templateConfig) return null;
|
|
66
|
-
return {
|
|
67
|
-
...templateConfig.defaults,
|
|
68
|
-
...template.props.content,
|
|
69
|
-
...template.props.resolved,
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
$effect(() => {
|
|
74
|
-
if (template && !templateConfig && typeof console !== 'undefined') {
|
|
75
|
-
console.warn(
|
|
76
|
-
`[@contentful/experiences-svelte] No template registered for id "${template.templateId}". Rendering nodes without the template wrapper.`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
</script>
|
|
81
|
-
|
|
82
|
-
{#if template && templateConfig && composed}
|
|
83
|
-
{@const Tpl = templateConfig.component}
|
|
84
|
-
<Tpl {...composed} {children} />
|
|
85
|
-
{:else}
|
|
86
|
-
{@render children()}
|
|
87
|
-
{/if}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { PortableTemplate } from '@contentful/experiences-sdk-core';
|
|
3
|
-
import { type Config, type RenderContext } from './types.js';
|
|
4
|
-
interface WrapWithTemplateProps {
|
|
5
|
-
template: PortableTemplate | undefined;
|
|
6
|
-
config: Config;
|
|
7
|
-
experience: RenderContext;
|
|
8
|
-
children: Snippet;
|
|
9
|
-
}
|
|
10
|
-
declare const WrapWithTemplate: import("svelte").Component<WrapWithTemplateProps, {}, "">;
|
|
11
|
-
type WrapWithTemplate = ReturnType<typeof WrapWithTemplate>;
|
|
12
|
-
export default WrapWithTemplate;
|
|
13
|
-
//# sourceMappingURL=WrapWithTemplate.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WrapWithTemplate.svelte.d.ts","sourceRoot":"","sources":["../src/WrapWithTemplate.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIzE,OAAO,EAGH,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAGpB,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AA0EH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type $$ComponentProps = {
|
|
3
|
-
title?: string;
|
|
4
|
-
children: Snippet;
|
|
5
|
-
};
|
|
6
|
-
declare const TemplateFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
-
type TemplateFixture = ReturnType<typeof TemplateFixture>;
|
|
8
|
-
export default TemplateFixture;
|
|
9
|
-
//# sourceMappingURL=TemplateFixture.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateFixture.svelte.d.ts","sourceRoot":"","sources":["../../src/test-fixtures/TemplateFixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIrC,KAAK,gBAAgB,GAAI;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAmBJ,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|