# Svelte 5 Runes Overview --- ## $State --- --- --- --- --- ---

{todo.text} - {todo.done ? 'Done' : 'Not done'}

--- ---

{person.name} is {person.age} years old.

--- ---

Count: {counter.count}

--- ---

{a} + {b} = {total()}

--- name, (v) => name = v.trimStart() } />

Hello, {name}!

--- ## $Derived --- ---

{count} doubled is {doubled}

--- - `$derived(count * 2)` ensures `doubled` always reflects the latest `count`. - You **cannot** modify state inside `$derived`, e.g., `count++` inside the expression. ---

{numbers.join(' + ')} = {total}

--- - `$derived.by(() => { ... })` is useful when the derived state requires loops or multiple steps. - The derived state (`total`) automatically updates when `numbers` change. ---

{count} is {isEven ? 'Even' : 'Odd'}

--- - `$derived` tracks all **synchronously accessed** state inside its expression. - If `count` changes, `isEven` will automatically update. ---

Is count large? {large}

--- - Svelte **only updates** when `large` changes (`false` β†’ `true` or vice versa). - If `count` changes **within the same threshold** (e.g., `5 β†’ 6`), no update occurs. --- --- ## $Effect --- --- --- ---

{count}

--- --- --- ---
{#each messages as message}

{message}

{/each}
--- ---

{count} doubled is {doubled}

--- --- --- ## $Bindable --- --- ---

{message}

--- --- --- --- --- --- --- - The input's `value` and `disabled` states can both be bound to the parent. - The button toggles the `disabled` state dynamically. - Useful for forms and UI elements requiring controlled states. --- ## $Props --- --- ---

This component is {props.adjective}

--- ---

This component is {adjective}

--- ---

This component is {adjective}

--- ---

Song lyric: {trouper}

--- ---

a: {a}, b: {b}, c: {c}

Other props: {JSON.stringify(others)}

--- --- --- --- --- --- --- --- --- --- ---
--- --- ## $Host --- --- --- count -= 1} onincrement={() => count += 1} >

count: {count}

--- - `$host()` only works in components compiled as **custom elements** (``). - This approach allows dispatching custom events from a **shadow DOM encapsulated component**. - Ensure the parent component listens to the dispatched events (`ondecrement`, `onincrement`). --- ## $Inspect --- --- --- --- --- --- --- --- --- --- --- --- # Svelte 5 Event Handling **Svelte 5 replaces `on:` directives with direct property bindings for event handlers.** --- ```svelte ``` **Key changes**: - Removed `on:click`, replacing it with `{onclick}` as a property. - Uses a named function (`onclick`) instead of inline arrow functions. --- **In Svelte 5, components no longer use `createEventDispatcher()`. Instead, they accept callback props.** --- ```svelte Pump power: {power} ``` --- ```svelte {#if burst} πŸ’₯ {:else} 🎈 {/if} ``` **Key changes**: - Removed `createEventDispatcher()`, instead using callback props (`inflate`, `deflate`). - Events are now just function calls inside `Pump.svelte`. - **Parent (App.svelte)** passes handlers like `inflateHandler` to `Pump`. --- **To forward an event from an element to a component, use callback props instead of `on:`.** --- ```svelte ``` **Key changes**: - No need to manually forward events like `on:click` β†’ `{onclick}` does the job. --- **Instead of manually listing every event, just spread props.** --- ```svelte ``` **Key changes**: - `{...props}` automatically applies all attributes, including event handlers like `onclick`. --- **Instead of duplicate event bindings, combine handlers manually.** --- ```svelte ``` **Key changes**: - Instead of multiple `on:click={one} on:click={two}`, handlers are manually merged. --- **Ensure that when spreading props, local event handlers still execute.** --- ```svelte ``` **Key changes**: - The local `onclick` executes **before** the `props.onclick`, preventing overwrites. --- **Modifiers like `once` and `preventDefault` should now be implemented manually.** --- ```svelte ``` **Key changes**: - Used **higher-order functions** to replace `on:click|once|preventDefault={handler}`. --- --- // svelte/events - `on` function // `on` attaches an event handler and returns a cleanup function. // It ensures correct handler order compared to `addEventListener`. import { on } from 'svelte/events'; // Attach an event to `window` function on( window: Window, type: Type, handler: (this: Window, event: WindowEventMap[Type]) => any, options?: AddEventListenerOptions ): () => void; // Attach an event to `document` function on( document: Document, type: Type, handler: (this: Document, event: DocumentEventMap[Type]) => any, options?: AddEventListenerOptions ): () => void; // Attach an event to an `HTMLElement` function on( element: Element, type: Type, handler: (this: Element, event: HTMLElementEventMap[Type]) => any, options?: AddEventListenerOptions ): () => void; // Attach an event to a `MediaQueryList` function on( element: Element, type: Type, handler: (this: Element, event: MediaQueryListEventMap[Type]) => any, options?: AddEventListenerOptions ): () => void; // Generic event attachment function on( element: EventTarget, type: string, handler: EventListener, options?: AddEventListenerOptions ): () => void; --- --- Use `on:eventname={handler}` to attach handlers (e.g., `onclick={() => ...}`). - Handlers can mutate `$state` directly; UI updates automatically. - Shorthand `{eventname}` works if the handler is a variable or function. - Events like `click`, `input`, etc., are delegated; assume bubbling unless stopped. - Events fire after bindings (e.g., `oninput` after `bind:value`). - Case-sensitive: `onclick` β‰  `onClick` (custom events may use uppercase). text = e.target.value} bind:value={text} placeholder="Type here" />

You typed: {text}

e.key === 'Enter' && count++} placeholder="Press Enter to increment" /> Note: For other events (e.g., `onmouseover`, `onfocus`), follow the same pattern: `on:eventname={() => ...}` or `{eventname}`. Adjust the handler logic based on the event’s purpose. # Svelte 5 Snippets --- {#snippet figure(image)}
{image.caption}
{image.caption}
{/snippet} {#each images as image} {#if image.href} {@render figure(image)} {:else} {@render figure(image)} {/if} {/each} --- ---
{#snippet x()} {#snippet y()}

Inside y

{/snippet} {@render y()} {/snippet} {@render y()}
{@render x()} --- --- {#snippet blastoff()} πŸš€ {/snippet} {#snippet countdown(n)} {#if n > 0} {n}... {@render countdown(n - 1)} {:else} {@render blastoff()} {/if} {/snippet} {@render countdown(5)} --- --- {@render header()} {#each data as item} {@render row(item)} {/each}
--- {#snippet header()} Fruit Qty Price Total {/snippet} {#snippet row(d)} {d.name} {d.qty} {d.price} {d.qty * d.price} {/snippet} --- --- --- --- --- {#if children} {@render children()} {:else}

Fallback content

{/if} --- {#snippet children()}

Custom content

{/snippet}
--- --- {#snippet add(a, b)} {a} + {b} = {a + b} {/snippet} --- {@render add(2, 3)} --- ---
{@render header?.()}
{@render main?.()}
{@render footer?.()}
--- {#snippet header()}

My Website

{/snippet} {#snippet main()}

Welcome to my website!

{/snippet} {#snippet footer()}

Β© 2023 My Website

{/snippet}
--- --- {#if items.length}
    {#each items as entry}
  • {@render item(entry)}
  • {/each}
{:else} {@render empty?.()} {/if} --- {#snippet item(fruit)} {fruit} {/snippet} {#snippet empty()} No fruits available {/snippet} --- # Svelte 5 + TypeScript --- --- ### Notes: - Adding `lang="ts"` enables TypeScript. - Type annotations (`string`) help with static checking. - No runtime overhead since TypeScript removes type annotations at compile time. --- ---

Hello, {name}!

--- --- ### Notes: - `Props` interface ensures `name` is always a string. - `$props()` extracts the component’s props with proper typing. --- --- {#each items as item} {/each} --- --- ### Notes: - `generics="Item"` allows the component to accept any item type. - Ensures `items` and `select` function operate on the same type. --- --- --- ### Notes: - `$state(0)` initializes a reactive variable with a type. - Without an initial value, TypeScript infers `number | undefined`. --- --- --- --- ### Notes: - `HTMLButtonAttributes` ensures `Button.svelte` supports all standard button attributes. - `...rest` spreads remaining props onto the ` ``` Below is a concise, mostly bullet-pointed summary of the changes, focusing on code snippets: --- ### Event Changes - **Svelte 4** used `on:` directives. - **Svelte 5**: Use regular properties like `onclick` instead (no `:`). **Example:** ```svelte ``` **Shorthand Example:** ```svelte ``` --- ### Component Events - **Svelte 4**: `createEventDispatcher` for emitting events. - **Svelte 5**: Use callback props instead. **Example (App.svelte):** ```svelte { size += power; if (size > 75) burst = true; }} deflate={(power) => { if (size > 0) size -= power; }} /> {#if burst} πŸ’₯ {:else} 🎈 {/if} ``` **Example (Pump.svelte):** ```svelte Pump power: {power} ``` --- ### Bubbling Events - No more ` ``` - Can β€œspread” handlers with other props: ```svelte ``` --- ### Event Modifiers - **Svelte 4** example: ` ``` - For `capture`, do: `onclickcapture={...}` - For `passive` or `nonpassive`, use an action to attach the event. --- ### Multiple Event Handlers - **Svelte 4** allowed ` ``` - When spreading props, place local handlers afterward to avoid overwriting: ```svelte ``` --- --- ### **Svelte 5 Changes - Condensed Bullet Points** #### **Component Changes** - **No More Class Components** β†’ Components are now functions. - **Instantiation** β†’ Use `mount` or `hydrate` instead of `new Component()`. - **Mount vs. Hydrate** β†’ `hydrate` picks up server-rendered HTML, otherwise identical to `mount`. - **No `$on`, `$set`, `$destroy`** - `$on` β†’ Use `events` property instead (though callbacks are preferred). - `$set` β†’ Use `$state` for reactivity. - `$destroy` β†’ Use `unmount`. #### **Code Examples** ```js import { mount } from 'svelte'; import App from './App.svelte'; const app = mount(App, { target: document.getElementById("app"), events: { event: callback } // Replacement for $on }); const props = $state({ foo: 'bar' }); // Replacement for $set props.foo = 'baz'; import { unmount } from 'svelte'; unmount(app); // Replacement for $destroy ``` #### **Legacy Compatibility** - Use `createClassComponent` from `svelte/legacy` if needed. - `compatibility.componentApi` option enables auto-backwards compatibility. ```js export default { compilerOptions: { compatibility: { componentApi: 4 } } }; ``` #### **Asynchronous Behavior** - `mount` and `hydrate` are **not** synchronous. - Use `flushSync()` if onMount must be guaranteed to run. #### **Server-Side Rendering (SSR)** - No `render()` method in components. - Instead, use `render()` from `svelte/server`. ```js import { render } from 'svelte/server'; import App from './App.svelte'; const { html, head } = render(App, { props: { message: 'hello' }}); ``` - **CSS not included by default** β†’ Use `css: 'injected'` to include styles. #### **Typing Changes** - `SvelteComponent` deprecated β†’ Use `Component` type. - `ComponentEvents` & `ComponentType` deprecated. ```ts import type { Component } from 'svelte'; export declare const MyComponent: Component<{ foo: string }>; ``` #### **bind:this Changes** - No longer returns `$set`, `$on`, or `$destroy` methods. - Now only returns instance exports & property accessors (if enabled). #### **Dynamic Components** - `` no longer needed. - Components update dynamically when reassigned. ```svelte ``` #### **Other Changes** - **Dot Notation** (``) now treated as a **component**, not an HTML tag. - **Whitespace Handling Simplified** β†’ Predictable behavior. - **Reserved `children` Prop** β†’ Cannot use `children` as a prop name; it's reserved.