@prismicio/svelte 1.6.0-alpha.0 → 2.0.0-alpha.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.
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 -19
  4. package/dist/PrismicImage.svelte +140 -59
  5. package/dist/PrismicImage.svelte.d.ts +54 -66
  6. package/dist/PrismicLink.svelte +55 -18
  7. package/dist/PrismicLink.svelte.d.ts +30 -40
  8. package/dist/PrismicRichText/DefaultComponent.svelte +31 -22
  9. package/dist/PrismicRichText/DefaultComponent.svelte.d.ts +5 -21
  10. package/dist/PrismicRichText/PrismicRichText.svelte +23 -5
  11. package/dist/PrismicRichText/PrismicRichText.svelte.d.ts +13 -23
  12. package/dist/PrismicRichText/Serialize.svelte +35 -16
  13. package/dist/PrismicRichText/Serialize.svelte.d.ts +8 -19
  14. package/dist/PrismicTable/DefaultComponent.svelte +12 -2
  15. package/dist/PrismicTable/DefaultComponent.svelte.d.ts +7 -19
  16. package/dist/PrismicTable/PrismicTable.svelte +46 -30
  17. package/dist/PrismicTable/PrismicTable.svelte.d.ts +19 -28
  18. package/dist/PrismicText.svelte +49 -23
  19. package/dist/PrismicText.svelte.d.ts +17 -20
  20. package/dist/SliceZone/SliceZone.svelte +53 -9
  21. package/dist/SliceZone/SliceZone.svelte.d.ts +36 -84
  22. package/dist/SliceZone/TodoComponent.svelte +19 -9
  23. package/dist/SliceZone/TodoComponent.svelte.d.ts +8 -20
  24. package/dist/index.d.ts +7 -1
  25. package/dist/kit/PrismicPreview.svelte +107 -58
  26. package/dist/kit/PrismicPreview.svelte.d.ts +21 -30
  27. package/dist/lib/devMsg.js +1 -1
  28. package/dist/types.d.ts +121 -74
  29. package/package.json +27 -24
  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 +24 -20
  34. package/src/PrismicRichText/PrismicRichText.svelte +15 -11
  35. package/src/PrismicRichText/Serialize.svelte +15 -9
  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 -91
  40. package/src/SliceZone/TodoComponent.svelte +14 -8
  41. package/src/index.ts +10 -1
  42. package/src/kit/PrismicPreview.svelte +30 -22
  43. package/src/lib/devMsg.ts +1 -1
  44. package/src/types.ts +178 -42
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismicio/svelte",
3
- "version": "1.6.0-alpha.0",
3
+ "version": "2.0.0-alpha.1",
4
4
  "description": "Svelte components to present Prismic content.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -47,53 +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/client": "^7.17.2",
65
- "esm-env": "^1.0.0"
64
+ "esm-env": "^1.2.2"
66
65
  },
67
66
  "devDependencies": {
67
+ "@eslint/compat": "^1.2.9",
68
+ "@eslint/js": "^9.27.0",
69
+ "@prismicio/client": "^7.17.2",
68
70
  "@prismicio/mock": "^0.7.1",
69
71
  "@size-limit/preset-small-lib": "^11.2.0",
70
72
  "@sveltejs/kit": "^2.21.0",
71
73
  "@sveltejs/package": "^2.3.11",
72
- "@sveltejs/vite-plugin-svelte": "^3.1.2",
73
- "@testing-library/svelte": "^4.2.3",
74
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
75
- "@typescript-eslint/eslint-plugin": "^6.21.0",
76
- "@typescript-eslint/parser": "^6.21.0",
77
- "@vitest/coverage-v8": "^1.6.1",
78
- "eslint": "^8.57.1",
79
- "eslint-config-prettier": "^9.1.0",
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",
80
81
  "eslint-plugin-prettier": "^5.4.0",
81
- "eslint-plugin-svelte": "^2.46.1",
82
- "eslint-plugin-tsdoc": "^0.2.17",
83
- "happy-dom": "^12.10.3",
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",
84
86
  "prettier": "^3.5.3",
85
87
  "prettier-plugin-jsdoc": "^1.3.2",
86
- "prettier-plugin-svelte": "^3.3.3",
88
+ "prettier-plugin-svelte": "^3.4.0",
87
89
  "size-limit": "^11.2.0",
88
90
  "standard-version": "^9.5.0",
89
- "svelte": "^4.2.19",
91
+ "svelte": "^5.30.1",
90
92
  "typescript": "^5.8.3",
91
- "vitest": "^1.6.1"
93
+ "typescript-eslint": "^8.32.1",
94
+ "vitest": "^3.1.3"
92
95
  },
93
96
  "peerDependencies": {
94
97
  "@prismicio/client": ">=7",
95
- "@sveltejs/kit": ">=1",
96
- "svelte": ">=4"
98
+ "@sveltejs/kit": "^2",
99
+ "svelte": "^5"
97
100
  },
98
101
  "peerDependenciesMeta": {
99
102
  "@sveltejs/kit": {
@@ -101,7 +104,7 @@
101
104
  }
102
105
  },
103
106
  "engines": {
104
- "node": ">=14.15.0"
107
+ "node": ">=20"
105
108
  },
106
109
  "publishConfig": {
107
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,47 @@
1
1
  <script lang="ts">
2
- import type { RTAnyNode } from "@prismicio/client";
2
+ import type { RichTextComponentProps } from "../types";
3
3
 
4
4
  import PrismicEmbed from "../PrismicEmbed.svelte";
5
5
  import PrismicImage from "../PrismicImage.svelte";
6
6
  import PrismicLink from "../PrismicLink.svelte";
7
7
 
8
- export let node: RTAnyNode;
8
+ type Props = RichTextComponentProps;
9
9
 
10
- $: dir = "direction" in node && node.direction === "rtl" ? "rtl" : undefined
10
+ const { node, children }: Props = $props();
11
+
12
+ const dirProp = $derived(
13
+ "direction" in node && node.direction === "rtl" ? { direction: "rtl" } : {},
14
+ );
11
15
  </script>
12
16
 
13
17
  {#if node.type === "heading1"}
14
- <h1 {dir}><slot /></h1>
18
+ <h1 {...dirProp}>{@render children()}</h1>
15
19
  {:else if node.type === "heading2"}
16
- <h2 {dir}><slot /></h2>
20
+ <h2 {...dirProp}>{@render children()}</h2>
17
21
  {:else if node.type === "heading3"}
18
- <h3 {dir}><slot /></h3>
22
+ <h3 {...dirProp}>{@render children()}</h3>
19
23
  {:else if node.type === "heading4"}
20
- <h4 {dir}><slot /></h4>
24
+ <h4 {...dirProp}>{@render children()}</h4>
21
25
  {:else if node.type === "heading5"}
22
- <h5 {dir}><slot /></h5>
26
+ <h5 {...dirProp}>{@render children()}</h5>
23
27
  {:else if node.type === "heading6"}
24
- <h6 {dir}><slot /></h6>
28
+ <h6 {...dirProp}>{@render children()}</h6>
25
29
  {:else if node.type === "paragraph"}
26
- <p {dir}><slot /></p>
30
+ <p {...dirProp}>{@render children()}</p>
27
31
  {:else if node.type === "preformatted"}
28
- <pre><slot /></pre>
32
+ <pre>{@render children()}</pre>
29
33
  {:else if node.type === "strong"}
30
- <strong><slot /></strong>
34
+ <strong>{@render children()}</strong>
31
35
  {:else if node.type === "em"}
32
- <em><slot /></em>
36
+ <em>{@render children()}</em>
33
37
  {:else if node.type === "list-item"}
34
- <li {dir}><slot /></li>
38
+ <li {...dirProp}>{@render children()}</li>
35
39
  {:else if node.type === "o-list-item"}
36
- <li {dir}><slot /></li>
40
+ <li {...dirProp}>{@render children()}</li>
37
41
  {:else if node.type === "group-list-item"}
38
- <ul><slot /></ul>
42
+ <ul>{@render children()}</ul>
39
43
  {:else if node.type === "group-o-list-item"}
40
- <ol><slot /></ol>
44
+ <ol>{@render children()}</ol>
41
45
  {:else if node.type === "image"}
42
46
  <p class="block-img">
43
47
  <PrismicImage field={node} />
@@ -45,11 +49,11 @@
45
49
  {:else if node.type === "embed"}
46
50
  <PrismicEmbed field={node.oembed} />
47
51
  {:else if node.type === "hyperlink"}
48
- <PrismicLink field={node.data}><slot /></PrismicLink>
52
+ <PrismicLink field={node.data}>{@render children()}</PrismicLink>
49
53
  {:else if node.type === "label"}
50
- <span class={node.data.label}><slot /></span>
54
+ <span class={node.data.label}>{@render children()}</span>
51
55
  {:else}
52
- {#each node.text.split("\n") as line, index}
56
+ {#each node.text.split("\n") as line, index (index)}
53
57
  {#if index > 0}<br />{/if}{line}
54
58
  {/each}
55
59
  {/if}
@@ -1,22 +1,26 @@
1
1
  <script lang="ts">
2
- import { asTree } from "@prismicio/client/richtext";
3
2
  import type { RichTextField } from "@prismicio/client";
3
+ import { asTree } from "@prismicio/client/richtext";
4
4
 
5
- import type { SvelteRichTextSerializer } from "../types";
5
+ import type { RichTextComponents } 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;
14
+
15
+ /**
16
+ * An object that maps a rich text block type to a Svelte component.
17
+ */
18
+ components?: RichTextComponents;
19
+ };
13
20
 
14
- /**
15
- * An object that maps a rich text block type to a Svelte component.
16
- */
17
- export let components: SvelteRichTextSerializer = {};
21
+ const { field, components = {} }: Props = $props();
18
22
 
19
- $: children = asTree(field).children;
23
+ const children = $derived(asTree(field).children);
20
24
  </script>
21
25
 
22
26
  <!--
@@ -1,12 +1,17 @@
1
1
  <script lang="ts">
2
2
  import type { asTree } from "@prismicio/client/richtext";
3
3
 
4
- import type { SvelteRichTextSerializer } from "../types";
4
+ import type { RichTextComponent, RichTextComponents } 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: RichTextComponents;
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",
@@ -17,20 +22,21 @@
17
22
 
18
23
  function getComponent(child: ReturnType<typeof asTree>["children"][number]) {
19
24
  return (
20
- components[
25
+ (components[
21
26
  CHILD_TYPE_RENAMES[child.type as keyof typeof CHILD_TYPE_RENAMES] ||
22
27
  (child.type as keyof typeof components)
23
- ] || DefaultComponent
28
+ ] as RichTextComponent) || DefaultComponent
24
29
  );
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
+
5
+ import type { RichTextComponents, TableComponents } from "../types";
4
6
 
5
7
  import PrismicRichText from "../PrismicRichText/PrismicRichText.svelte";
6
- import type { SvelteRichTextSerializer, TableComponents } from "../types";
7
- import DefaultComponent from "./DefaultComponent.svelte";
8
8
 
9
- /**
10
- * The Prismic table field to render.
11
- */
12
- export let field: TableField;
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 & RichTextComponents;
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}