Description
Describe the problem
I'm making a CodeMirror component with the goal of making it as thin/native as possible, while being able to use it in the Svelte way. Creating a CodeMirror editor gives me a view.dom
element that I need to insert, which forces me to have a wrapping element to insert it into:
<script>
let { ...rest } = $props();
const view = new EditorView({
doc: value,
});
let wrapper;
onMount(() => {
wrapper.appendChild(view.dom)
})
</script>
<div class="wrapper" bind:this={wrapper} {...rest}></div>
As a consequence, the rest props are passed to the wrapper instead of the actual editor element, so if the component user sets style="height: 300px"
it will actually behave like style="max-height: 300px"
on the editor element. All workarounds I've found have significant downsides and/or nasty edgecases.
TLDR
There is no way of placing elements created via document.createElement
into the root of a component or use Svelte features/syntax on them.
Describe the proposed solution
Given an HTML element, writing <svelte:element this={node} />
would:
- Insert the HTML element into the component at the provided location.
- Allow passing attributes and event handlers to it, just like any other element.
Behaviour in case of conflicting child elements / attributes is something that would need to be defined. For my use case it would be fine to overwrite children/attributes if provided in the component, but otherwise left as-is.
Looking at my example, this would fix my styling issue and make it more concise:
<script>
let { ...rest } = $props();
const view = new EditorView({
doc: value,
});
</script>
<svelte:element this={view.dom} {...rest} />
Importance
nice to have