feat: allow dom elements as `svelte:element` `this` attribute

svelte-element-element
paoloricciuti 6 months ago
parent e2bbc560e4
commit 5385faf360

@ -0,0 +1,5 @@
---
'svelte': minor
---
feat: allow dom elements as `svelte:element` `this` attribute

@ -26,7 +26,7 @@ import { is_raw_text_element } from '../../../../utils.js';
/**
* @param {Comment | Element} node
* @param {() => string} get_tag
* @param {() => string | HTMLElement | SVGElement} get_tag
* @param {boolean} is_svg
* @param {undefined | ((element: Element, anchor: Node | null) => void)} render_fn,
* @param {undefined | (() => string)} get_namespace
@ -42,10 +42,10 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
var filename = DEV && location && component_context?.function[FILENAME];
/** @type {string | null} */
/** @type {string | HTMLElement | SVGElement | null} */
var tag;
/** @type {string | null} */
/** @type {string | HTMLElement | SVGElement | null} */
var current_tag;
/** @type {null | Element} */
@ -100,9 +100,11 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
effect = branch(() => {
element = hydrating
? /** @type {Element} */ (element)
: ns
: typeof next_tag === 'string'
? ns
? document.createElementNS(ns, next_tag)
: document.createElement(next_tag);
: document.createElement(next_tag)
: next_tag;
if (DEV && location) {
// @ts-expect-error
@ -118,7 +120,10 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
assign_nodes(element, element);
if (render_fn) {
if (hydrating && is_raw_text_element(next_tag)) {
if (
hydrating &&
is_raw_text_element(typeof next_tag === 'string' ? next_tag : next_tag.nodeName)
) {
// prevent hydration glitches
element.append(document.createComment(''));
}

@ -7,13 +7,14 @@ import * as e from './errors.js';
export { invalid_default_snippet } from './errors.js';
/**
* @param {() => string} tag_fn
* @param {() => string | HTMLElement | SVGElement} tag_fn
* @returns {void}
*/
export function validate_void_dynamic_element(tag_fn) {
const tag = tag_fn();
if (tag && is_void(tag)) {
w.dynamic_void_element_content(tag);
const tag_name = typeof tag === 'string' ? tag : tag?.tagName;
if (tag_name && is_void(tag_name)) {
w.dynamic_void_element_content(tag_name);
}
}
@ -21,7 +22,8 @@ export function validate_void_dynamic_element(tag_fn) {
export function validate_dynamic_element_tag(tag_fn) {
const tag = tag_fn();
const is_string = typeof tag === 'string';
if (tag && !is_string) {
const is_element = tag instanceof HTMLElement || tag instanceof SVGElement;
if (tag && !(is_string || is_element)) {
e.svelte_element_invalid_this_value();
}
}

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
ssrHtml: ``,
test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `<div><b>children</b><p>children</p></div>`);
}
});

@ -0,0 +1,13 @@
<script>
let div = $state(null);
$effect(()=>{
const to_add = document.createElement("div");
to_add.innerHTML=`<b>children</b>`;
div = to_add;
})
</script>
<svelte:element this={div}>
<p>children</p>
</svelte:element>

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
ssrHtml: `<div><p>children</p></div>`,
test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `<div><b>children</b><p>children</p></div>`);
}
});

@ -0,0 +1,13 @@
<script>
let div = $state(null);
$effect(()=>{
const to_add = document.createElement("div");
to_add.innerHTML=`<b>children</b>`;
div = to_add;
})
</script>
<svelte:element this={div ?? "div"}>
<p>children</p>
</svelte:element>
Loading…
Cancel
Save