Quick guide for using Custom Elements Runtime components inside Svelte.
- Register a component:
import {
component,
ref,
html,
useProps,
useEmit,
} from '@jasonshimmy/custom-elements-runtime';
component('my-counter', () => {
const props = useProps({ initialCount: 0 });
const count = ref(props.initialCount);
const emit = useEmit();
const handleClick = () => {
count.value++;
emit('count-changed', { count: count.value });
};
return html` <button @click="${handleClick}">Count: ${count.value}</button> `;
});- Use in markup:
<my-counter initialCount={5} on:count-changed={handleCountChange} />- For simple values you can use attributes; prefer using property bindings when you need reactive values or non-string types. Svelte's
bind:propbehavior is for Svelte components and may not automatically wire to arbitrary custom elements — useon:update:<prop>orbind:this+ set the property if you need deterministic behavior. - When using our compiler the
:modeland:model:propshorthands will be compiled to explicit prop +update:<prop>wiring. The runtime promotes bound attributes into JS properties for custom elements (mapping kebab-case attributes to camelCase properties) so property bindings and compiler-emitted wiring are the recommended pattern for non-string values and reactive flows. - Listen to CustomEvents declaratively with
on:event(preferred). If you need closure capture, usebind:thisandaddEventListener.
Compatibility note: useEmit() and the internal emit() helper dispatch standard DOM CustomEvents and will also dispatch alternate event-name variants in some cases (for example update:model-value and update:modelValue). If Svelte's template parser or tooling complains about colon-containing event names, prefer bind:this + addEventListener on the element reference and read event.detail for the payload.
- Emit
update:<prop>events from your element to support host-side updates. In Svelte you can handle them declaratively:
<my-custom bind:value on:update:value={(e) => value = e.detail} />- When using our compiler,
:model:propis compiled into explicit prop + onUpdate: wiring. Emitted events are kebab-cased (for exampleupdate:model-value) and should carry the new value inevent.detail(usebubbles: true, composed: true).
Parser caveat: if your host tooling or linter complains about on:update:... or colon-containing event names, use bind:this + addEventListener as an alternative.
Runtime note: the renderer optimizes updates and will only notify custom elements when a prop or attribute actually changes; parent renders that don't change a child's props/attrs won't re-trigger the child's apply/update lifecycle.
-
Compiler shorthand (source):
-
Svelte component consuming a runtime custom element (declarative on:update):
<script>
import { onMount } from 'svelte';
let value = 'hello';
let el;
onMount(() => {
// optional: imperative wiring or props
if (el) el.value = value;
});
</script>
<my-custom bind:this={el} on:update:value={(e) => value = e.detail} />
<p>{value}</p>See Events Deep Dive. Works with Svelte 3.x+.
Mix and match with Svelte power! 🌈