diff --git a/.changeset/nine-carpets-doubt.md b/.changeset/nine-carpets-doubt.md
new file mode 100644
index 000000000000..5abe918afe65
--- /dev/null
+++ b/.changeset/nine-carpets-doubt.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/svelte': minor
+---
+
+Bumps Svelte 5 peer dependency to `^5.0.0-next.190` and support the latest slots/snippets API
diff --git a/packages/integrations/svelte/client-v5.js b/packages/integrations/svelte/client-v5.js
index 755a6aa5381e..fda68ee54878 100644
--- a/packages/integrations/svelte/client-v5.js
+++ b/packages/integrations/svelte/client-v5.js
@@ -1,8 +1,4 @@
-import { hydrate, mount, unmount } from 'svelte';
-import { add_snippet_symbol } from 'svelte/internal/client';
-
-// Allow a slot to be rendered as a snippet (dev validation only)
-const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s;
+import { createRawSnippet, hydrate, mount, unmount } from 'svelte';
export default (element) => {
return async (Component, props, slotted, { client }) => {
@@ -11,11 +7,16 @@ export default (element) => {
let children = undefined;
let $$slots = undefined;
for (const [key, value] of Object.entries(slotted)) {
+ $$slots ??= {};
if (key === 'default') {
- children = createSlotDefinition(key, value);
+ $$slots.default = true;
+ children = createRawSnippet(() => ({
+ render: () => `${value}`,
+ }));
} else {
- $$slots ??= {};
- $$slots[key] = createSlotDefinition(key, value);
+ $$slots[key] = createRawSnippet(() => ({
+ render: () => `${value}`,
+ }));
}
}
@@ -33,18 +34,3 @@ export default (element) => {
element.addEventListener('astro:unmount', () => unmount(component), { once: true });
};
};
-
-function createSlotDefinition(key, children) {
- /**
- * @param {Comment} $$anchor A comment node for slots in Svelte 5
- */
- const fn = ($$anchor, _$$slotProps) => {
- const parent = $$anchor.parentNode;
- const el = document.createElement('div');
- el.innerHTML = `${children}`;
- parent.insertBefore(el.children[0], $$anchor);
- };
- return tagSlotAsSnippet(fn);
-}
diff --git a/packages/integrations/svelte/package.json b/packages/integrations/svelte/package.json
index 7d544328aca7..521daae536e3 100644
--- a/packages/integrations/svelte/package.json
+++ b/packages/integrations/svelte/package.json
@@ -61,7 +61,7 @@
},
"peerDependencies": {
"astro": "^4.0.0",
- "svelte": "^4.0.0 || ^5.0.0-next.90",
+ "svelte": "^4.0.0 || ^5.0.0-next.190",
"typescript": "^5.3.3"
},
"engines": {
diff --git a/packages/integrations/svelte/server-v5.js b/packages/integrations/svelte/server-v5.js
index 04a24eff2474..acffd10dfef0 100644
--- a/packages/integrations/svelte/server-v5.js
+++ b/packages/integrations/svelte/server-v5.js
@@ -1,9 +1,6 @@
-import { add_snippet_symbol } from 'svelte/internal/server';
+import { createRawSnippet } from 'svelte';
import { render } from 'svelte/server';
-// Allow a slot to be rendered as a snippet (dev validation only)
-const tagSlotAsSnippet = import.meta.env.DEV ? add_snippet_symbol : (s) => s;
-
function check(Component) {
// Svelte 5 generated components always accept these two props
const str = Component.toString();
@@ -21,22 +18,27 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) {
let children = undefined;
let $$slots = undefined;
for (const [key, value] of Object.entries(slotted)) {
+ $$slots ??= {};
if (key === 'default') {
- children = tagSlotAsSnippet(() => `<${tagName}>${value}${tagName}>`);
+ $$slots.default = true;
+ children = createRawSnippet(() => ({
+ render: () => `<${tagName}>${value}${tagName}>`,
+ }));
} else {
- $$slots ??= {};
- $$slots[key] = tagSlotAsSnippet(() => `<${tagName} name="${key}">${value}${tagName}>`);
+ $$slots[key] = createRawSnippet(() => ({
+ render: () => `<${tagName} name="${key}">${value}${tagName}>`,
+ }));
}
}
- const { html } = render(Component, {
+ const result = render(Component, {
props: {
...props,
children,
$$slots,
},
});
- return { html };
+ return { html: result.body };
}
export default {