9.10. Svelte Integration¶
Wire a ComponentVMOf<M> to a Svelte component via Svelte 5 runes
($state, $derived, $effect) or, on Svelte 4, via a custom store.
9.10.1. Reactivity primitive¶
- Svelte 5:
$state(value)is a deeply reactive rune; reads in the template auto-track and re-render on mutation. - Svelte 4: the
{ subscribe }contract — any object with asubscribe(set)method that returns an unsubscribe function works as a store and is auto-tracked with the$storesyntax.
9.10.2. Mapping¶
| Svelte | VMx |
|---|---|
$state(x) / writable(x) |
PropertyChangedMessage<T> handler |
on:click={fn} |
command.execute() in fn |
$derived(...) / derived(...) |
DerivedProperty<T> / fromSources |
onDestroy(() => cleanup) |
dispose the subscription |
9.10.3. Adapter skeleton — Svelte 4 store¶
// lib/vmStore.ts
import { readable, type Readable } from "svelte/store";
import { filter } from "rxjs/operators";
import { ComponentVMOf, type IMessageHub, PropertyChangedMessage } from "@thekaveh/vmx";
export function vmStore<M, K extends keyof ComponentVMOf<M>>(
vm: ComponentVMOf<M>,
hub: IMessageHub,
property: K
): Readable<ComponentVMOf<M>[K]> {
return readable(vm[property], (set) => {
const sub = hub.messages
.pipe(filter((m): m is PropertyChangedMessage<unknown> =>
m instanceof PropertyChangedMessage &&
m.sender === vm &&
m.propertyName === property))
.subscribe(() => set(vm[property]));
return () => sub.unsubscribe();
});
}
<script lang="ts">
import { vmStore } from "$lib/vmStore";
import type { ComponentVMOf, ICommand, IMessageHub } from "@thekaveh/vmx";
export let vm: ComponentVMOf<Note>;
export let hub: IMessageHub;
export let saveCommand: ICommand;
const model = vmStore(vm, hub, "model");
</script>
<h1>{$model.title}</h1>
<button on:click={() => saveCommand.execute()}>Save</button>
For Svelte 5, drop the store wrapper and assign into a $state(...)
variable inside an $effect(...) that subscribes to the hub.
9.10.4. Fuller example¶
No worked Svelte Notes-Showcase ships yet. The React and Vue recipes share the same hub-subscription shape.