@prismicio/svelte 1.5.0 → 2.0.0-alpha.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.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/dist/PrismicEmbed.svelte +12 -2
  3. package/dist/PrismicEmbed.svelte.d.ts +8 -17
  4. package/dist/PrismicImage.svelte +140 -59
  5. package/dist/PrismicImage.svelte.d.ts +54 -64
  6. package/dist/PrismicLink.svelte +55 -20
  7. package/dist/PrismicLink.svelte.d.ts +30 -38
  8. package/dist/PrismicRichText/DefaultComponent.svelte +35 -23
  9. package/dist/PrismicRichText/DefaultComponent.svelte.d.ts +7 -17
  10. package/dist/PrismicRichText/PrismicRichText.svelte +23 -6
  11. package/dist/PrismicRichText/PrismicRichText.svelte.d.ts +13 -22
  12. package/dist/PrismicRichText/Serialize.svelte +35 -16
  13. package/dist/PrismicRichText/Serialize.svelte.d.ts +9 -19
  14. package/dist/PrismicTable/DefaultComponent.svelte +12 -2
  15. package/dist/PrismicTable/DefaultComponent.svelte.d.ts +7 -17
  16. package/dist/PrismicTable/PrismicTable.svelte +46 -30
  17. package/dist/PrismicTable/PrismicTable.svelte.d.ts +19 -31
  18. package/dist/PrismicText.svelte +49 -23
  19. package/dist/PrismicText.svelte.d.ts +17 -18
  20. package/dist/SliceZone/SliceZone.svelte +53 -8
  21. package/dist/SliceZone/SliceZone.svelte.d.ts +36 -110
  22. package/dist/SliceZone/TodoComponent.svelte +19 -9
  23. package/dist/SliceZone/TodoComponent.svelte.d.ts +8 -18
  24. package/dist/index.d.ts +1 -1
  25. package/dist/kit/PrismicPreview.svelte +107 -59
  26. package/dist/kit/PrismicPreview.svelte.d.ts +21 -28
  27. package/dist/lib/devMsg.js +1 -1
  28. package/dist/types.d.ts +95 -20
  29. package/package.json +35 -33
  30. package/src/PrismicEmbed.svelte +8 -4
  31. package/src/PrismicImage.svelte +65 -69
  32. package/src/PrismicLink.svelte +23 -19
  33. package/src/PrismicRichText/DefaultComponent.svelte +27 -19
  34. package/src/PrismicRichText/PrismicRichText.svelte +14 -10
  35. package/src/PrismicRichText/Serialize.svelte +13 -7
  36. package/src/PrismicTable/DefaultComponent.svelte +10 -2
  37. package/src/PrismicTable/PrismicTable.svelte +37 -43
  38. package/src/PrismicText.svelte +30 -22
  39. package/src/SliceZone/SliceZone.svelte +42 -89
  40. package/src/SliceZone/TodoComponent.svelte +14 -8
  41. package/src/index.ts +1 -1
  42. package/src/kit/PrismicPreview.svelte +30 -22
  43. package/src/lib/devMsg.ts +1 -1
  44. package/src/types.ts +105 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismicio/svelte",
3
- "version": "1.5.0",
3
+ "version": "2.0.0-alpha.0",
4
4
  "description": "Svelte components to present Prismic content.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -47,54 +47,56 @@
47
47
  "build": "svelte-package --input ./src",
48
48
  "dev": "svelte-package --input ./src --watch",
49
49
  "format": "prettier --write --plugin prettier-plugin-svelte .",
50
- "lint": "eslint --ext .js,.ts .",
50
+ "lint": "eslint",
51
51
  "prepare": "npm run build",
52
52
  "release": "npm run test && standard-version && git push --follow-tags && npm run build && npm publish",
53
- "release:alpha": "npm run test && standard-version --release-as minor --prerelease alpha && git push --follow-tags && npm run build && npm publish --tag alpha",
54
- "release:alpha:dry": "standard-version --release-as minor --prerelease alpha --dry-run",
53
+ "release:alpha": "npm run test && standard-version --release-as major --prerelease alpha && git push --follow-tags && npm run build && npm publish --tag alpha",
54
+ "release:alpha:dry": "standard-version --release-as major --prerelease alpha --dry-run",
55
55
  "release:dry": "standard-version --release-as patch --dry-run",
56
56
  "size": "size-limit",
57
57
  "test": "npm run lint && npm run types && npm run unit && npm run build && npm run size",
58
- "types": "vitest --typecheck.only --run && tsc --noEmit",
58
+ "types": "tsc --noEmit",
59
59
  "types:watch": "vitest watch --typecheck.only",
60
60
  "unit": "vitest run --coverage",
61
61
  "unit:watch": "vitest watch"
62
62
  },
63
63
  "dependencies": {
64
- "@prismicio/richtext": "^2.1.5",
65
- "esm-env": "^1.0.0"
64
+ "esm-env": "^1.2.2"
66
65
  },
67
66
  "devDependencies": {
68
- "@prismicio/client": "^7.17.0",
67
+ "@eslint/compat": "^1.2.9",
68
+ "@eslint/js": "^9.27.0",
69
+ "@prismicio/client": "^7.17.2",
69
70
  "@prismicio/mock": "^0.7.1",
70
- "@size-limit/preset-small-lib": "^11.0.1",
71
- "@sveltejs/kit": "^2.0.0",
72
- "@sveltejs/package": "^2.2.3",
73
- "@sveltejs/vite-plugin-svelte": "^3.0.1",
74
- "@testing-library/svelte": "^4.0.5",
75
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
76
- "@typescript-eslint/eslint-plugin": "^6.14.0",
77
- "@typescript-eslint/parser": "^6.14.0",
78
- "@vitest/coverage-v8": "^1.0.4",
79
- "eslint": "^8.55.0",
80
- "eslint-config-prettier": "^9.1.0",
81
- "eslint-plugin-prettier": "^5.0.1",
82
- "eslint-plugin-svelte": "^2.35.1",
83
- "eslint-plugin-tsdoc": "^0.2.17",
84
- "happy-dom": "^12.10.3",
85
- "prettier": "^3.1.1",
86
- "prettier-plugin-jsdoc": "^1.1.1",
87
- "prettier-plugin-svelte": "^3.1.2",
88
- "size-limit": "^11.0.1",
71
+ "@size-limit/preset-small-lib": "^11.2.0",
72
+ "@sveltejs/kit": "^2.21.0",
73
+ "@sveltejs/package": "^2.3.11",
74
+ "@sveltejs/vite-plugin-svelte": "^5.0.3",
75
+ "@testing-library/svelte": "^5.2.7",
76
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
77
+ "@types/node": "^22.15.18",
78
+ "@vitest/coverage-v8": "^3.1.3",
79
+ "eslint": "^9.27.0",
80
+ "eslint-config-prettier": "^10.1.5",
81
+ "eslint-plugin-prettier": "^5.4.0",
82
+ "eslint-plugin-svelte": "^3.7.0",
83
+ "eslint-plugin-tsdoc": "^0.4.0",
84
+ "globals": "^16.1.0",
85
+ "happy-dom": "^17.4.7",
86
+ "prettier": "^3.5.3",
87
+ "prettier-plugin-jsdoc": "^1.3.2",
88
+ "prettier-plugin-svelte": "^3.4.0",
89
+ "size-limit": "^11.2.0",
89
90
  "standard-version": "^9.5.0",
90
- "svelte": "^4.2.0",
91
- "typescript": "^5.3.3",
92
- "vitest": "^1.0.4"
91
+ "svelte": "^5.30.1",
92
+ "typescript": "^5.8.3",
93
+ "typescript-eslint": "^8.32.1",
94
+ "vitest": "^3.1.3"
93
95
  },
94
96
  "peerDependencies": {
95
97
  "@prismicio/client": ">=7",
96
- "@sveltejs/kit": ">=1",
97
- "svelte": ">=4 || ^5.0.0-next.1"
98
+ "@sveltejs/kit": "^2",
99
+ "svelte": "^5"
98
100
  },
99
101
  "peerDependenciesMeta": {
100
102
  "@sveltejs/kit": {
@@ -102,7 +104,7 @@
102
104
  }
103
105
  },
104
106
  "engines": {
105
- "node": ">=14.15.0"
107
+ "node": ">=20"
106
108
  },
107
109
  "publishConfig": {
108
110
  "access": "public"
@@ -2,10 +2,14 @@
2
2
  import type { EmbedField } from "@prismicio/client";
3
3
  import { isFilled } from "@prismicio/client";
4
4
 
5
- /**
6
- * An Embed field from Prismic.
7
- */
8
- export let field: EmbedField;
5
+ type Props = {
6
+ /**
7
+ * An Embed field from Prismic.
8
+ */
9
+ field: EmbedField;
10
+ };
11
+
12
+ const { field }: Props = $props();
9
13
  </script>
10
14
 
11
15
  <!--
@@ -1,14 +1,14 @@
1
1
  <script lang="ts">
2
2
  import {
3
- asImageWidthSrcSet,
3
+ type ImageFieldImage,
4
4
  asImagePixelDensitySrcSet,
5
+ asImageWidthSrcSet,
5
6
  isFilled,
6
- type ImageFieldImage,
7
7
  } from "@prismicio/client";
8
8
  import type { ImgixURLParams } from "imgix-url-builder";
9
9
  import type { HTMLImgAttributes } from "svelte/elements";
10
10
 
11
- type $$Props = Omit<HTMLImgAttributes, "src" | "srcset" | "alt"> & {
11
+ type Props = Omit<HTMLImgAttributes, "src" | "srcset" | "alt"> & {
12
12
  /**
13
13
  * The Prismic image field or thumbnail to render.
14
14
  */
@@ -71,73 +71,69 @@
71
71
  }
72
72
  );
73
73
 
74
- export let field: $$Props["field"];
75
- export let imgixParams: $$Props["imgixParams"] = {};
76
- export let alt: $$Props["alt"] = undefined;
77
- export let fallbackAlt: $$Props["fallbackAlt"] = undefined;
78
- export let width: $$Props["width"] = undefined;
79
- export let height: $$Props["width"] = undefined;
80
- export let widths: $$Props["widths"] = undefined;
81
- export let pixelDensities: $$Props["pixelDensities"] = undefined;
82
-
83
- let src: string | undefined = undefined;
84
- let srcset: string | undefined = undefined;
85
- let resolvedWidth: $$Props["width"] = undefined;
86
- let resolvedHeight: $$Props["height"] = undefined;
87
-
88
- $: {
89
- if (isFilled.imageThumbnail(field)) {
90
- const castInt = (
91
- input: string | number | null | undefined,
92
- ): number | null | undefined => {
93
- if (
94
- typeof input === "number" ||
95
- typeof input === "undefined" ||
96
- input === null
97
- ) {
98
- return input;
99
- } else {
100
- const parsed = Number.parseInt(input);
101
-
102
- if (Number.isNaN(parsed)) {
103
- return undefined;
104
- } else {
105
- return parsed;
106
- }
107
- }
108
- };
109
-
110
- const ar = field.dimensions.width / field.dimensions.height;
111
-
112
- const castedWidth = castInt(width);
113
- const castedHeight = castInt(height);
114
-
115
- resolvedWidth = castedWidth ?? field.dimensions.width;
116
- resolvedHeight = castedHeight ?? field.dimensions.height;
117
-
118
- if (castedWidth != null && castedHeight == null) {
119
- resolvedHeight = castedWidth / ar;
120
- } else if (castedWidth == null && castedHeight != null) {
121
- resolvedWidth = castedHeight * ar;
122
- }
74
+ const {
75
+ field,
76
+ imgixParams = {},
77
+ alt,
78
+ fallbackAlt,
79
+ width,
80
+ height,
81
+ widths,
82
+ pixelDensities,
83
+ ...restProps
84
+ }: Props = $props();
85
+
86
+ const { resolvedWidth, resolvedHeight } = $derived.by(() => {
87
+ if (!isFilled.imageThumbnail(field))
88
+ return { resolvedWidth: undefined, resolvedHeight: undefined };
89
+
90
+ const ar = field.dimensions.width / field.dimensions.height;
91
+
92
+ let resolvedWidth = castInt(width) ?? field.dimensions.width;
93
+ let resolvedHeight = castInt(height) ?? field.dimensions.height;
94
+ if (resolvedWidth != null && resolvedHeight == null) {
95
+ resolvedHeight = resolvedWidth / ar;
96
+ } else if (resolvedWidth == null && resolvedHeight != null) {
97
+ resolvedWidth = resolvedHeight * ar;
98
+ }
123
99
 
124
- if (widths || !pixelDensities) {
125
- const res = asImageWidthSrcSet(field, {
126
- ...imgixParams,
127
- widths: widths === "defaults" ? undefined : widths,
128
- });
129
-
130
- src = res.src;
131
- srcset = res.srcset;
132
- } else if (pixelDensities) {
133
- const res = asImagePixelDensitySrcSet(field, {
134
- ...imgixParams,
135
- pixelDensities:
136
- pixelDensities === "defaults" ? undefined : pixelDensities,
137
- } as ImgixURLParams);
100
+ return { resolvedWidth, resolvedHeight };
101
+ });
102
+
103
+ const { src, srcset } = $derived.by(() => {
104
+ if (!isFilled.imageThumbnail(field))
105
+ return { src: undefined, srcset: undefined };
106
+
107
+ if (pixelDensities) {
108
+ return asImagePixelDensitySrcSet(field, {
109
+ ...imgixParams,
110
+ pixelDensities:
111
+ pixelDensities === "defaults" ? undefined : pixelDensities,
112
+ } as ImgixURLParams);
113
+ }
138
114
 
139
- src = res.src;
140
- srcset = res.srcset;
115
+ return asImageWidthSrcSet(field, {
116
+ ...imgixParams,
117
+ widths: widths === "defaults" ? undefined : widths,
118
+ });
119
+ });
120
+
121
+ function castInt(
122
+ input: string | number | null | undefined,
123
+ ): number | null | undefined {
124
+ if (
125
+ typeof input === "number" ||
126
+ typeof input === "undefined" ||
127
+ input === null
128
+ ) {
129
+ return input;
130
+ } else {
131
+ const parsed = Number.parseInt(input);
132
+
133
+ if (Number.isNaN(parsed)) {
134
+ return undefined;
135
+ } else {
136
+ return parsed;
141
137
  }
142
138
  }
143
139
  }
@@ -163,6 +159,6 @@
163
159
  alt={alt ?? (field.alt || fallbackAlt)}
164
160
  width={resolvedWidth}
165
161
  height={resolvedHeight}
166
- {...$$restProps}
162
+ {...restProps}
167
163
  />
168
164
  {/if}
@@ -1,13 +1,13 @@
1
1
  <script lang="ts">
2
2
  import {
3
- asLinkAttrs,
4
3
  type AsLinkAttrsConfig,
5
4
  type LinkField,
6
5
  type PrismicDocument,
6
+ asLinkAttrs,
7
7
  } from "@prismicio/client";
8
8
  import type { HTMLAnchorAttributes } from "svelte/elements";
9
9
 
10
- type $$Props = Omit<HTMLAnchorAttributes, "rel" | "href"> & {
10
+ type Props = Omit<HTMLAnchorAttributes, "rel" | "href"> & {
11
11
  /**
12
12
  * The `rel` attribute for the link. By default, `"noreferrer"` is provided
13
13
  * if the link's URL is external. This prop can be provided a function to
@@ -20,27 +20,37 @@
20
20
  * A Prismic link field, content relationship field, or link to media
21
21
  * field.
22
22
  */
23
- field: LinkField;
23
+ field: LinkField | null | undefined;
24
24
  document?: never;
25
+ href?: never;
25
26
  }
26
27
  | {
27
28
  /**
28
29
  * A Prismic document.
29
30
  */
30
- document: PrismicDocument;
31
+ document: PrismicDocument | null | undefined;
32
+ field?: never;
33
+ href?: never;
34
+ }
35
+ | {
36
+ href: HTMLAnchorAttributes["href"];
37
+ document: never;
31
38
  field?: never;
32
39
  }
33
40
  );
34
41
 
35
- export let field: $$Props["field"] = undefined;
36
- export let document: $$Props["document"] = undefined;
37
- export let rel: $$Props["rel"] = undefined;
42
+ const { field, document, rel, children, ...restProps }: Props = $props();
38
43
 
39
- $: linkAttrs = asLinkAttrs(field ?? document, {
40
- rel: typeof rel === "function" ? rel : undefined,
41
- });
44
+ const linkAttrs = $derived(
45
+ asLinkAttrs(field ?? document, {
46
+ rel: typeof rel === "function" ? rel : undefined,
47
+ }),
48
+ );
49
+ const href = $derived(
50
+ ("href" in restProps ? restProps.href : linkAttrs.href) || "",
51
+ );
42
52
 
43
- $: resolvedRel = typeof rel === "string" ? rel : linkAttrs.rel;
53
+ const resolvedRel = $derived(typeof rel === "string" ? rel : linkAttrs.rel);
44
54
  </script>
45
55
 
46
56
  <!--
@@ -53,12 +63,6 @@
53
63
  ```
54
64
  -->
55
65
 
56
- <a
57
- {...linkAttrs}
58
- rel={resolvedRel}
59
- href={linkAttrs.href}
60
- on:click
61
- {...$$restProps}
62
- >
63
- <slot>{field?.text}</slot>
66
+ <a {...linkAttrs} rel={resolvedRel} {href} {...restProps}>
67
+ {#if children}{@render children?.()}{:else}{field?.text}{/if}
64
68
  </a>
@@ -1,43 +1,51 @@
1
1
  <script lang="ts">
2
2
  import type { RTAnyNode } from "@prismicio/client";
3
+ import type { Snippet } from "svelte";
3
4
 
4
5
  import PrismicEmbed from "../PrismicEmbed.svelte";
5
6
  import PrismicImage from "../PrismicImage.svelte";
6
7
  import PrismicLink from "../PrismicLink.svelte";
7
8
 
8
- export let node: RTAnyNode;
9
+ type Props = {
10
+ node: RTAnyNode;
11
+ children?: Snippet;
12
+ };
9
13
 
10
- $: dir = "direction" in node && node.direction === "rtl" ? "rtl" : undefined
14
+ const { node, children }: Props = $props();
15
+
16
+ const dirProp = $derived(
17
+ "direction" in node && node.direction === "rtl" ? { direction: "rtl" } : {},
18
+ );
11
19
  </script>
12
20
 
13
21
  {#if node.type === "heading1"}
14
- <h1 {dir}><slot /></h1>
22
+ <h1 {...dirProp}>{@render children?.()}</h1>
15
23
  {:else if node.type === "heading2"}
16
- <h2 {dir}><slot /></h2>
24
+ <h2 {...dirProp}>{@render children?.()}</h2>
17
25
  {:else if node.type === "heading3"}
18
- <h3 {dir}><slot /></h3>
26
+ <h3 {...dirProp}>{@render children?.()}</h3>
19
27
  {:else if node.type === "heading4"}
20
- <h4 {dir}><slot /></h4>
28
+ <h4 {...dirProp}>{@render children?.()}</h4>
21
29
  {:else if node.type === "heading5"}
22
- <h5 {dir}><slot /></h5>
30
+ <h5 {...dirProp}>{@render children?.()}</h5>
23
31
  {:else if node.type === "heading6"}
24
- <h6 {dir}><slot /></h6>
32
+ <h6 {...dirProp}>{@render children?.()}</h6>
25
33
  {:else if node.type === "paragraph"}
26
- <p {dir}><slot /></p>
34
+ <p {...dirProp}>{@render children?.()}</p>
27
35
  {:else if node.type === "preformatted"}
28
- <pre><slot /></pre>
36
+ <pre>{@render children?.()}</pre>
29
37
  {:else if node.type === "strong"}
30
- <strong><slot /></strong>
38
+ <strong>{@render children?.()}</strong>
31
39
  {:else if node.type === "em"}
32
- <em><slot /></em>
40
+ <em>{@render children?.()}</em>
33
41
  {:else if node.type === "list-item"}
34
- <li {dir}><slot /></li>
42
+ <li {...dirProp}>{@render children?.()}</li>
35
43
  {:else if node.type === "o-list-item"}
36
- <li {dir}><slot /></li>
44
+ <li {...dirProp}>{@render children?.()}</li>
37
45
  {:else if node.type === "group-list-item"}
38
- <ul><slot /></ul>
46
+ <ul>{@render children?.()}</ul>
39
47
  {:else if node.type === "group-o-list-item"}
40
- <ol><slot /></ol>
48
+ <ol>{@render children?.()}</ol>
41
49
  {:else if node.type === "image"}
42
50
  <p class="block-img">
43
51
  <PrismicImage field={node} />
@@ -45,11 +53,11 @@
45
53
  {:else if node.type === "embed"}
46
54
  <PrismicEmbed field={node.oembed} />
47
55
  {:else if node.type === "hyperlink"}
48
- <PrismicLink field={node.data}><slot /></PrismicLink>
56
+ <PrismicLink field={node.data}>{@render children?.()}</PrismicLink>
49
57
  {:else if node.type === "label"}
50
- <span class={node.data.label}><slot /></span>
58
+ <span class={node.data.label}>{@render children?.()}</span>
51
59
  {:else}
52
- {#each node.text.split("\n") as line, index}
60
+ {#each node.text.split("\n") as line, index (index)}
53
61
  {#if index > 0}<br />{/if}{line}
54
62
  {/each}
55
63
  {/if}
@@ -1,22 +1,26 @@
1
1
  <script lang="ts">
2
- import { asTree } from "@prismicio/richtext";
3
2
  import type { RichTextField } from "@prismicio/client";
3
+ import { asTree } from "@prismicio/client/richtext";
4
4
 
5
5
  import type { SvelteRichTextSerializer } from "../types";
6
6
 
7
7
  import Serialize from "./Serialize.svelte";
8
8
 
9
- /**
10
- * The Prismic rich text field to render.
11
- */
12
- export let field: RichTextField;
9
+ type Props = {
10
+ /**
11
+ * The Prismic rich text field to render.
12
+ */
13
+ field: RichTextField;
13
14
 
14
- /**
15
- * An object that maps a rich text block type to a Svelte component.
16
- */
17
- export let components: SvelteRichTextSerializer = {};
15
+ /**
16
+ * An object that maps a rich text block type to a Svelte component.
17
+ */
18
+ components?: SvelteRichTextSerializer;
19
+ };
18
20
 
19
- $: children = asTree(field).children;
21
+ const { field, components = {} }: Props = $props();
22
+
23
+ const children = $derived(asTree(field).children);
20
24
  </script>
21
25
 
22
26
  <!--
@@ -1,12 +1,17 @@
1
1
  <script lang="ts">
2
- import type { asTree } from "@prismicio/richtext";
2
+ import type { asTree } from "@prismicio/client/richtext";
3
3
 
4
4
  import type { SvelteRichTextSerializer } from "../types";
5
5
 
6
6
  import DefaultComponent from "./DefaultComponent.svelte";
7
+ import Serialize from "./Serialize.svelte";
7
8
 
8
- export let components: SvelteRichTextSerializer = {};
9
- export let children: ReturnType<typeof asTree>["children"];
9
+ type Props = {
10
+ components: SvelteRichTextSerializer;
11
+ children: ReturnType<typeof asTree>["children"];
12
+ };
13
+
14
+ const { components, children }: Props = $props();
10
15
 
11
16
  const CHILD_TYPE_RENAMES = {
12
17
  "list-item": "listItem",
@@ -25,12 +30,13 @@
25
30
  }
26
31
  </script>
27
32
 
28
- {#each children as child}
29
- <svelte:component this={getComponent(child)} node={child.node}>
33
+ {#each children as child (child.key)}
34
+ {@const Component = getComponent(child)}
35
+ <Component node={child.node}>
30
36
  <!-- This formatting is intentional to prevent unwanted whitespace between elements. -->
31
- {#if child.children.length > 0}<svelte:self
37
+ {#if child.children.length > 0}<Serialize
32
38
  children={child.children}
33
39
  {components}
34
- />{/if}</svelte:component
40
+ />{/if}</Component
35
41
  >
36
42
  {/each}
@@ -1,6 +1,14 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+
2
4
  import type { TableComponents } from "../types";
3
- export let type: keyof TableComponents;
5
+
6
+ type Props = {
7
+ type: keyof TableComponents;
8
+ children?: Snippet;
9
+ };
10
+
11
+ const { type, children }: Props = $props();
4
12
  </script>
5
13
 
6
- <svelte:element this={type}><slot /></svelte:element>
14
+ <svelte:element this={type}>{@render children?.()}</svelte:element>
@@ -1,73 +1,67 @@
1
1
  <script lang="ts">
2
- import { isFilled, type TableField } from "@prismicio/client";
3
- import { type ComponentType } from "svelte";
2
+ import { type TableField, isFilled } from "@prismicio/client";
3
+ import { type Component } from "svelte";
4
4
 
5
- import PrismicRichText from "../PrismicRichText/PrismicRichText.svelte";
6
5
  import type { SvelteRichTextSerializer, TableComponents } from "../types";
7
- import DefaultComponent from "./DefaultComponent.svelte";
8
6
 
9
- /**
10
- * The Prismic table field to render.
11
- */
12
- export let field: TableField;
7
+ import PrismicRichText from "../PrismicRichText/PrismicRichText.svelte";
8
+
9
+ import DefaultComponent from "./DefaultComponent.svelte";
13
10
 
14
- /**
15
- * An object that maps a rich text block type to a Svelte component.
16
- */
17
- export let components: TableComponents & SvelteRichTextSerializer = {};
11
+ type Props = {
12
+ /**
13
+ * The Prismic table field to render.
14
+ */
15
+ field: TableField;
18
16
 
19
- /**
20
- * The component rendered when the field is empty. If a fallback is not given,
21
- * `null` will be rendered.
22
- */
23
- export let fallback: ComponentType | undefined = undefined;
17
+ /**
18
+ * An object that maps a rich text block type to a Svelte component.
19
+ */
20
+ components?: TableComponents & SvelteRichTextSerializer;
24
21
 
25
- /**
26
- * This function creates the needed table components, prioritizing any user
27
- * provided custom components and falling back to the default components.
28
- */
29
- const createComponent = (type: keyof TableComponents) => {
30
- const Component: ComponentType = components[type] ?? DefaultComponent;
31
- return {
32
- Component,
33
- props: Component === DefaultComponent ? { type } : {},
34
- };
22
+ /**
23
+ * The component rendered when the field is empty. If a fallback is not
24
+ * given, `null` will be rendered.
25
+ */
26
+ fallback?: Component;
35
27
  };
36
28
 
37
- const { Component: Table, props: tableProps } = createComponent("table");
38
- const { Component: Thead, props: theadProps } = createComponent("thead");
39
- const { Component: Tbody, props: tbodyProps } = createComponent("tbody");
40
- const { Component: Tr, props: trProps } = createComponent("tr");
41
- const { Component: Th, props: thProps } = createComponent("th");
42
- const { Component: Td, props: tdProps } = createComponent("td");
29
+ const { field, components = {}, fallback: Fallback }: Props = $props();
30
+
31
+ const Table = components.table ?? DefaultComponent;
32
+ const Thead = components.thead ?? DefaultComponent;
33
+ const Tbody = components.tbody ?? DefaultComponent;
34
+ const Tr = components.tr ?? DefaultComponent;
35
+ const Th = components.th ?? DefaultComponent;
36
+ const Td = components.td ?? DefaultComponent;
43
37
  </script>
44
38
 
45
39
  <!-- This formatting is intentional to prevent unwanted whitespace between elements. -->
46
40
  {#if isFilled.table(field)}
47
- <Table {...tableProps} table={field}>
41
+ <Table type="table" table={field}>
48
42
  {#if field?.head}
49
- <Thead {...theadProps} head={field.head}>
43
+ <Thead type="thead" head={field.head}>
50
44
  {#each field.head.rows as row (row.key)}
51
- <Tr {...trProps} {row}>
45
+ <Tr type="tr" {row}>
52
46
  {#each row.cells as cell (cell.key)}
53
- <Th {...thProps} {cell}>
47
+ <Th type="th" {cell}>
54
48
  <PrismicRichText field={cell.content} {components} /></Th
55
49
  >{/each}</Tr
56
50
  >{/each}</Thead
57
- >{/if}<Tbody {...tbodyProps} body={field.body}>
51
+ >{/if}<Tbody type="tbody" body={field.body}>
58
52
  {#each field.body.rows as row (row.key)}
59
- <Tr {...trProps} {row}>
53
+ <Tr type="tr" {row}>
60
54
  {#each row.cells as cell (cell.key)}
61
55
  {#if cell.type === "header"}
62
- <Th {...thProps} {cell}>
56
+ <Th type="th" {cell}>
63
57
  <PrismicRichText field={cell.content} {components} /></Th
64
- >{:else}<Td {...tdProps} {cell}>
58
+ >{:else}<Td type="td" {cell}>
65
59
  <PrismicRichText field={cell.content} {components} /></Td
66
60
  >{/if}{/each}</Tr
67
61
  >
68
62
  {/each}
69
63
  </Tbody>
70
64
  </Table>
71
- {:else if fallback !== undefined}
72
- <svelte:component this={fallback} />
65
+ {:else if Fallback}
66
+ <Fallback />
73
67
  {/if}