Spec Registry
Help your agents use open-source better. Learn more.
Find usage specs for your project’s dependencies
- Author
- tessl
- Last updated
- Spec files
npm-svelte
Describes: npm/svelte
- Description
- A cybernetically enhanced web application framework that compiles to highly optimized JavaScript with reactive state management and component-based architecture.
- Author
- tessl
- Last updated
runes.md docs/
1# Runes System23Svelte 5 introduces runes - a powerful reactivity system that replaces the previous assignment-based reactivity. Runes provide explicit, fine-grained reactivity with better TypeScript support and more predictable behavior.45## Capabilities67### $state89Declares reactive state that triggers updates when changed.1011```typescript { .api }12/**13* Declares reactive state14* @param initial - Initial value for the state15* @returns Reactive state value16*/17declare function $state<T>(initial: T): T;18declare function $state<T>(): T | undefined;19```2021**Usage Examples:**2223```typescript24// Basic state25let count = $state(0);26let name = $state("Alice");27let items = $state([]);2829// State without initial value30let user = $state(); // undefined initially3132// Object state (deeply reactive by default)33let settings = $state({34theme: "dark",35language: "en",36notifications: {37email: true,38push: false39}40});4142// Updating state triggers reactivity43count += 1; // This will trigger updates44settings.theme = "light"; // This will trigger updates45settings.notifications.email = false; // Deep updates work too46```4748### $state.raw4950Declares state that is not deeply reactive - you must reassign the entire value to trigger updates.5152```typescript { .api }53/**54* Declares state that is not made deeply reactive55* @param initial - Initial value for the raw state56* @returns Non-deeply reactive state value57*/58declare function raw<T>(initial: T): T;59declare function raw<T>(): T | undefined;60```6162**Usage Examples:**6364```typescript65let items = $state.raw([{ id: 1, name: "Item 1" }]);6667// This won't trigger updates68items[0].name = "Updated Item";6970// This will trigger updates71items = [...items, { id: 2, name: "Item 2" }];72items = items.map(item =>73item.id === 1 ? { ...item, name: "Updated Item" } : item74);75```7677### $state.snapshot7879Takes a static snapshot of deeply reactive state, useful for logging or serialization.8081```typescript { .api }82/**83* Takes a static snapshot of a deeply reactive state proxy84* @param state - The state to snapshot85* @returns Static snapshot of the state86*/87declare function snapshot<T>(state: T): Snapshot<T>;88```8990**Usage Examples:**9192```typescript93let counter = $state({ count: 0, history: [] });9495function logState() {96// Will log the actual object, not the Proxy97console.log($state.snapshot(counter));98}99100function saveToLocalStorage() {101const snapshot = $state.snapshot(counter);102localStorage.setItem("counter", JSON.stringify(snapshot));103}104```105106### $derived107108Creates derived state that automatically updates when its dependencies change.109110```typescript { .api }111/**112* Declares derived state that depends on other reactive values113* @param expression - Expression that computes the derived value114* @returns Derived reactive value115*/116declare function $derived<T>(expression: T): T;117```118119**Usage Examples:**120121```typescript122let count = $state(0);123let name = $state("Alice");124125// Simple derived values126let doubled = $derived(count * 2);127let greeting = $derived(`Hello, ${name}!`);128let isEven = $derived(count % 2 === 0);129130// Derived from multiple sources131let summary = $derived(`${name} has clicked ${count} times`);132133// Complex derived values134let expensiveComputation = $derived(() => {135return someHeavyCalculation(count);136});137```138139### $derived.by140141Creates complex derived state using a function for more elaborate computations.142143```typescript { .api }144/**145* Creates complex derived state using a function146* @param fn - Function that computes the derived value147* @returns Derived reactive value148*/149declare function by<T>(fn: () => T): T;150```151152**Usage Examples:**153154```typescript155let numbers = $state([1, 2, 3, 4, 5]);156157let total = $derived.by(() => {158let result = 0;159for (const n of numbers) {160result += n;161}162return result;163});164165let filtered = $derived.by(() => {166return numbers.filter(n => n > 2);167});168169// Complex async-like patterns (though derived should be sync)170let processedData = $derived.by(() => {171if (!rawData.length) return [];172173return rawData174.map(item => processItem(item))175.filter(item => item.isValid)176.sort((a, b) => a.priority - b.priority);177});178```179180### $effect181182Runs side effects when reactive dependencies change.183184```typescript { .api }185/**186* Runs code when dependencies change, after DOM updates187* @param fn - Function to run, can return cleanup function188*/189declare function $effect(fn: () => void | (() => void)): void;190```191192**Usage Examples:**193194```typescript195let count = $state(0);196let name = $state("Alice");197198// Basic effect199$effect(() => {200console.log(`Count is now ${count}`);201});202203// Effect with cleanup204$effect(() => {205const interval = setInterval(() => {206console.log(`Count: ${count}`);207}, 1000);208209return () => clearInterval(interval);210});211212// Effect with multiple dependencies213$effect(() => {214document.title = `${name} - Count: ${count}`;215});216217// Conditional effects218$effect(() => {219if (count > 10) {220console.log("Count is getting high!");221}222});223```224225### $effect.pre226227Runs effects before DOM updates, useful for reading DOM state before changes.228229```typescript { .api }230/**231* Runs code before DOM updates when dependencies change232* @param fn - Function to run, can return cleanup function233*/234declare function pre(fn: () => void | (() => void)): void;235```236237**Usage Examples:**238239```typescript240let items = $state([]);241let container;242243$effect.pre(() => {244if (container) {245const scrollableDistance = container.scrollHeight - container.offsetHeight;246const shouldAutoScroll = container.scrollTop > (scrollableDistance - 20);247248if (shouldAutoScroll) {249// Will scroll after DOM updates250$effect(() => {251container.scrollTo(0, container.scrollHeight);252});253}254}255});256```257258### $effect.root259260Creates a non-tracked effect scope that doesn't auto-cleanup and can be manually controlled.261262```typescript { .api }263/**264* Creates a non-tracked scope that doesn't auto-cleanup265* @param fn - Function to run, can return cleanup function266* @returns Cleanup function to manually destroy the effect267*/268declare function root(fn: () => void | (() => void)): () => void;269```270271**Usage Examples:**272273```typescript274let count = $state(0);275276const cleanup = $effect.root(() => {277$effect(() => {278console.log(`Count: ${count}`);279});280281return () => {282console.log("Root effect cleaned up");283};284});285286// Later, manually cleanup287cleanup();288```289290### $effect.tracking291292Checks whether code is running inside a tracking context.293294```typescript { .api }295/**296* Checks if code is running inside a tracking context297* @returns true if inside an effect or template, false otherwise298*/299declare function tracking(): boolean;300```301302**Usage Examples:**303304```typescript305function myUtility() {306if ($effect.tracking()) {307// We're inside an effect or template, safe to read reactive state308return someReactiveValue;309} else {310// Not in tracking context, perhaps return cached value311return cachedValue;312}313}314```315316### $props317318Declares component props with proper typing and reactivity.319320```typescript { .api }321/**322* Declares the props that a component accepts323* @returns Props object with reactive properties324*/325declare function $props(): any;326```327328**Usage Examples:**329330```typescript331// Basic props332let { name, age, email } = $props();333334// Props with defaults335let { theme = "light", size = "medium" } = $props();336337// Typed props (in TypeScript)338interface Props {339name: string;340age?: number;341onSubmit?: (data: any) => void;342}343344let { name, age = 0, onSubmit }: Props = $props();345346// Bindable props347let { value = $bindable() } = $props();348```349350### $bindable351352Declares a prop as bindable, allowing parent components to bind to it.353354```typescript { .api }355/**356* Declares a prop as bindable357* @param fallback - Default value if not bound358* @returns Bindable prop value359*/360declare function $bindable<T>(fallback?: T): T;361```362363**Usage Examples:**364365```typescript366// Child component367let { value = $bindable("") } = $props();368369// Parent can now use bind:value370// <ChildComponent bind:value={parentValue} />371372// With default value373let { isOpen = $bindable(false) } = $props();374375// The parent can bind to it376// <Modal bind:isOpen={showModal} />377```378379### $inspect380381Development utility for inspecting reactive values and their changes.382383```typescript { .api }384/**385* Inspects reactive values and logs changes386* @param values - Values to inspect387* @returns Object with 'with' method for custom inspection388*/389declare function $inspect<T extends any[]>(390...values: T391): { with: (fn: (type: 'init' | 'update', ...values: T) => void) => void };392```393394**Usage Examples:**395396```typescript397let count = $state(0);398let name = $state("Alice");399400// Basic inspection (logs to console)401$inspect(count);402$inspect(count, name);403404// Custom inspection405$inspect(count).with((type, value) => {406console.log(`${type}: count is ${value}`);407});408409$inspect(count, name).with((type, countVal, nameVal) => {410if (type === 'update') {411console.log(`Update: ${nameVal} has count ${countVal}`);412}413});414```415416## Types417418```typescript { .api }419type Snapshot<T> = T extends Primitive420? T421: T extends Cloneable422? NonReactive<T>423: T extends { toJSON(): infer R }424? R425: T extends Array<infer U>426? Array<Snapshot<U>>427: T extends object428? { [K in keyof T]: Snapshot<T[K]> }429: never;430431type Primitive = string | number | boolean | null | undefined;432433type NotFunction<T> = T extends Function ? never : T;434```435436## Migration from Svelte 4437438- Replace `let count = 0` with `let count = $state(0)`439- Replace `$: doubled = count * 2` with `let doubled = $derived(count * 2)`440- Replace `$: { console.log(count); }` with `$effect(() => { console.log(count); })`441- Use `$props()` instead of `export let` for component props