···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# asyncEffect
77+88+Async effect system with abort, race protection, debounce, throttle, and error handling
99+1010+## asyncEffect
1111+1212+Creates an async side effect that runs when dependencies change.
1313+Supports abort signals, race protection, debouncing, throttling, and error handling.
1414+1515+```typescript
1616+export function asyncEffect( effectFunction: AsyncEffectFunction, dependencies: Array<Signal<unknown> | ComputedSignal<unknown>>, options: AsyncEffectOptions = {}, ): () => void
1717+```
1818+1919+**Example:**
2020+2121+```typescript
2222+// Fetch with abort on cleanup
2323+const query = signal('');
2424+const cleanup = asyncEffect(async (signal) => {
2525+ const response = await fetch(`/api/search?q=${query.get()}`, { signal });
2626+ const data = await response.json();
2727+ results.set(data);
2828+}, [query], { abortable: true });
2929+3030+// Debounced search
3131+asyncEffect(async () => {
3232+ const response = await fetch(`/api/search?q=${searchQuery.get()}`);
3333+ results.set(await response.json());
3434+}, [searchQuery], { debounce: 300 });
3535+3636+// Error handling with retries
3737+asyncEffect(async () => {
3838+ const response = await fetch('/api/data');
3939+ if (!response.ok) throw new Error('Failed to fetch');
4040+ data.set(await response.json());
4141+}, [refreshTrigger], {
4242+ retries: 3,
4343+ retryDelay: 1000,
4444+ onError: (error, retry) => {
4545+ console.error('Fetch failed:', error);
4646+ // Optionally call retry() to retry immediately
4747+ }
4848+});
4949+```
+1-2
docs/api/binder.md
···991010## mount
11111212-Mount Volt.js on a root element and its descendants.
1313-Binds all data-x-* attributes to the provided scope.
1212+Mount Volt.js on a root element and its descendants and binds all data-volt-* attributes to the provided scope.
1413Returns a cleanup function to unmount and dispose all bindings.
15141615```typescript
+35
docs/api/charge.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# charge
77+88+Charge system (bootstrap) for auto-discovery and initialization of Volt roots
99+1010+Handles declarative state initialization via data-volt-state and data-volt-computed
1111+1212+## charge
1313+1414+Discover and mount all Volt roots in the document.
1515+Parses data-volt-state for initial state and data-volt-computed for derived values.
1616+1717+```typescript
1818+export function charge(rootSelector = "[data-volt]"): ChargeResult
1919+```
2020+2121+**Example:**
2222+2323+```typescript
2424+```html
2525+<div data-volt data-volt-state='{"count": 0}' data-volt-computed:double="count * 2">
2626+ <p data-volt-text="count"></p>
2727+ <p data-volt-text="double"></p>
2828+</div>
2929+```
3030+3131+```ts
3232+const { cleanup } = charge();
3333+// Later: cleanup() to unmount all
3434+```
3535+```
+8-5
docs/api/dom.md
···991010## walkDOM
11111212-Walk the DOM tree and collect all elements with data-x-* attributes.
1313-Returns elements in document order (parent before children).
1212+Walk the DOM tree and collect all elements with data-volt-* attributes in document order (parent before children).
1313+1414+Skips children of elements with data-volt-for or data-volt-if since those will be processed when the parent element is cloned and mounted.
14151516```typescript
1617export function walkDOM(root: Element): Element[]
···18191920## hasVoltAttribute
20212121-Check if an element has any data-x-* attributes.
2222+Check if an element has any data-volt-* attributes.
22232324```typescript
2425export function hasVoltAttribute(element: Element): boolean
···26272728## getVoltAttributes
28292929-Get all data-x-* attributes from an element.
3030+Get all data-volt-\* attributes from an element.
3131+Excludes charge metadata attributes (state, computed:*) that are processed separately.
30323133```typescript
3234export function getVoltAttributes(element: Element): Map<string, string>
···6062## parseClassBinding
61636264Parse a class binding expression.
6363-Supports both string values ("active") and object notation ({active: true}).
6565+Supports string values ("active"), object notation ({active: true}),
6666+and other primitives (true, false, numbers) which are converted to strings.
64676568```typescript
6669export function parseClassBinding(value: unknown): Map<string, boolean>
+17-11
docs/api/evaluator.md
···5566# evaluator
7788-Safe expression evaluation of simple expressions without using eval() for bindings
88+Safe expression evaluation with operators support
991010-## Scope
1010+Implements a recursive descent parser for expressions without using eval()
11111212-Safe expression evaluation of simple expressions without using eval() for bindings
1212+## isSignal
13131414```typescript
1515-Record<string, unknown>
1515+export function isSignal(value: unknown): value is Dep
1616```
17171818## evaluate
19192020-Evaluate a simple expression against a scope object.
2121-Supports:
2222-- Property access: "count", "user.name", "items.length"
2323-- Simple literals: "true", "false", "null", "undefined"
2424-- Numbers: "42", "3.14"
2525-- Strings: "'hello'", '"world"'
2020+Evaluate an expression against a scope object.
2121+2222+Supports literals, property access, operators, and member access.
26232724```typescript
2828-export function evaluate(expression: string, scope: Scope): unknown
2525+export function evaluate(expr: string, scope: Scope): unknown
2626+```
2727+2828+## extractDependencies
2929+3030+Extract all signal dependencies from an expression by finding identifiers
3131+that correspond to signals in the scope.
3232+3333+```typescript
3434+export function extractDependencies(expr: string, scope: Scope): Array<Dep>
2935```
+135
docs/api/lifecycle.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# lifecycle
77+88+Global lifecycle hook system for Volt.js
99+Provides beforeMount, afterMount, beforeUnmount, and afterUnmount hooks
1010+1111+## registerGlobalHook
1212+1313+Register a global lifecycle hook.
1414+Global hooks run for every mount/unmount operation in the application.
1515+1616+```typescript
1717+export function registerGlobalHook(name: GlobalHookName, cb: MountHookCallback | UnmountHookCallback): () => void
1818+```
1919+2020+**Example:**
2121+2222+```typescript
2323+// Log every mount operation
2424+registerGlobalHook('beforeMount', (root, scope) => {
2525+ console.log('Mounting', root, 'with scope', scope);
2626+});
2727+2828+// Track mounted elements
2929+const mountedElements = new Set<Element>();
3030+registerGlobalHook('afterMount', (root) => {
3131+ mountedElements.add(root);
3232+});
3333+registerGlobalHook('beforeUnmount', (root) => {
3434+ mountedElements.delete(root);
3535+});
3636+```
3737+3838+## unregisterGlobalHook
3939+4040+Unregister a global lifecycle hook.
4141+4242+```typescript
4343+export function unregisterGlobalHook(name: GlobalHookName, cb: MountHookCallback | UnmountHookCallback): boolean
4444+```
4545+4646+## clearGlobalHooks
4747+4848+Clear all global hooks for a specific lifecycle event.
4949+5050+```typescript
5151+export function clearGlobalHooks(name: GlobalHookName): void
5252+```
5353+5454+## clearAllGlobalHooks
5555+5656+```typescript
5757+export function clearAllGlobalHooks(): void
5858+```
5959+6060+## getGlobalHooks
6161+6262+Get all registered hooks for a specific lifecycle event.
6363+Used internally by the binder system.
6464+6565+```typescript
6666+export function getGlobalHooks(name: GlobalHookName): Array<MountHookCallback | UnmountHookCallback>
6767+```
6868+6969+## executeGlobalHooks
7070+7171+Execute all registered hooks for a lifecycle event.
7272+Used internally by the binder system.
7373+7474+```typescript
7575+export function executeGlobalHooks(hookName: GlobalHookName, root: Element, scope?: Scope): void
7676+```
7777+7878+## registerElementHook
7979+8080+Register a per-element lifecycle hook.
8181+These hooks are specific to individual elements.
8282+8383+```typescript
8484+export function registerElementHook(element: Element, hookType: "mount" | "unmount", cb: () => void): void
8585+```
8686+8787+## notifyElementMounted
8888+8989+Notify that an element has been mounted.
9090+Executes all registered onMount callbacks for the element.
9191+9292+```typescript
9393+export function notifyElementMounted(element: Element): void
9494+```
9595+9696+## notifyElementUnmounted
9797+9898+Notify that an element is being unmounted.
9999+Executes all registered onUnmount callbacks for the element.
100100+101101+```typescript
102102+export function notifyElementUnmounted(element: Element): void
103103+```
104104+105105+## notifyBindingCreated
106106+107107+Notify that a binding has been created on an element.
108108+109109+```typescript
110110+export function notifyBindingCreated(element: Element, name: string): void
111111+```
112112+113113+## notifyBindingDestroyed
114114+115115+Notify that a binding has been destroyed on an element.
116116+117117+```typescript
118118+export function notifyBindingDestroyed(element: Element, name: string): void
119119+```
120120+121121+## isElementMounted
122122+123123+Check if an element is currently mounted.
124124+125125+```typescript
126126+export function isElementMounted(element: Element): boolean
127127+```
128128+129129+## getElementBindings
130130+131131+Get all bindings on an element.
132132+133133+```typescript
134134+export function getElementBindings(element: Element): string[]
135135+```
+33
docs/api/persist.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# persist
77+88+Persistence plugin for synchronizing signals with storage
99+Supports localStorage, sessionStorage, IndexedDB, and custom adapters
1010+1111+## registerStorageAdapter
1212+1313+Register a custom storage adapter.
1414+1515+```typescript
1616+export function registerStorageAdapter(name: string, adapter: StorageAdapter): void
1717+```
1818+1919+## persistPlugin
2020+2121+Persist plugin handler.
2222+Synchronizes signal values with persistent storage.
2323+2424+Syntax: data-volt-persist="signalPath:storageType"
2525+Examples:
2626+ - data-volt-persist="count:local"
2727+ - data-volt-persist="formData:session"
2828+ - data-volt-persist="userData:indexeddb"
2929+ - data-volt-persist="settings:customAdapter"
3030+3131+```typescript
3232+export function persistPlugin(context: PluginContext, value: string): void
3333+```
+74
docs/api/plugin.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# plugin
77+88+Plugin system for extending Volt.js with custom bindings
99+1010+## registerPlugin
1111+1212+Register a custom plugin with a given name.
1313+Plugins extend Volt.js with custom data-volt-* attribute bindings.
1414+1515+```typescript
1616+export function registerPlugin(name: string, handler: PluginHandler): void
1717+```
1818+1919+**Example:**
2020+2121+```typescript
2222+registerPlugin('tooltip', (context, value) => {
2323+ const tooltip = document.createElement('div');
2424+ tooltip.className = 'tooltip';
2525+ tooltip.textContent = value;
2626+ context.element.addEventListener('mouseenter', () => {
2727+ document.body.appendChild(tooltip);
2828+ });
2929+ context.element.addEventListener('mouseleave', () => {
3030+ tooltip.remove();
3131+ });
3232+ context.addCleanup(() => tooltip.remove());
3333+});
3434+```
3535+3636+## getPlugin
3737+3838+Get a plugin handler by name.
3939+4040+```typescript
4141+export function getPlugin(name: string): PluginHandler | undefined
4242+```
4343+4444+## hasPlugin
4545+4646+Check if a plugin is registered.
4747+4848+```typescript
4949+export function hasPlugin(name: string): boolean
5050+```
5151+5252+## unregisterPlugin
5353+5454+Unregister a plugin by name.
5555+5656+```typescript
5757+export function unregisterPlugin(name: string): boolean
5858+```
5959+6060+## getRegisteredPlugins
6161+6262+Get all registered plugin names.
6363+6464+```typescript
6565+export function getRegisteredPlugins(): string[]
6666+```
6767+6868+## clearPlugins
6969+7070+Clear all registered plugins.
7171+7272+```typescript
7373+export function clearPlugins(): void
7474+```
+25
docs/api/scroll.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# scroll
77+88+Scroll plugin for managing scroll behavior
99+Supports position restoration, scroll-to, scroll spy, and smooth scrolling
1010+1111+## scrollPlugin
1212+1313+Scroll plugin handler.
1414+Manages various scroll-related behaviors.
1515+1616+Syntax: data-volt-scroll="mode:signalPath"
1717+Modes:
1818+ - restore:signalPath - Save/restore scroll position
1919+ - scrollTo:signalPath - Scroll to element when signal changes
2020+ - spy:signalPath - Update signal when element is visible
2121+ - smooth:signalPath - Enable smooth scrolling behavior
2222+2323+```typescript
2424+export function scrollPlugin(context: PluginContext, value: string): void
2525+```
+7-9
docs/api/signal.md
···5566# signal
7788-A reactive primitive that notifies subscribers when its value changes.
88+Creates a new signal with the given initial value.
991010-## Signal
1010+@param initialValue - The initial value of the signal
1111+@returns A Signal object with get, set, and subscribe methods
11121212-A reactive primitive that notifies subscribers when its value changes.
1313-1414-## ComputedSignal
1515-1616-A computed signal that derives its value from other signals.
1313+@example
1414+const count = signal(0);
1515+count.subscribe(value => console.log('Count:', value));
1616+count.set(1); // Logs: Count: 1
17171818## signal
19192020Creates a new signal with the given initial value.
2121-Signals are reactive primitives that automatically notify subscribers when changed.
22212322```typescript
2423export function signal<T>(initialValue: T): Signal<T>
···5453## effect
55545655Creates a side effect that runs when dependencies change.
5757-Effects run immediately on creation and whenever dependencies update.
58565957```typescript
6058export function effect( effectFunction: () => void | (() => void), dependencies: Array<Signal<unknown> | ComputedSignal<unknown>>, ): () => void
+24
docs/api/url.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# url
77+88+URL plugin for synchronizing signals with URL parameters and hash routing
99+Supports one-way read, bidirectional sync, and hash-based routing
1010+1111+## urlPlugin
1212+1313+URL plugin handler.
1414+Synchronizes signal values with URL parameters and hash.
1515+1616+Syntax: data-volt-url="mode:signalPath"
1717+Modes:
1818+ - read:signalPath - Read URL param into signal on mount (one-way)
1919+ - sync:signalPath - Bidirectional sync between signal and URL param
2020+ - hash:signalPath - Sync with hash portion for routing
2121+2222+```typescript
2323+export function urlPlugin(context: PluginContext, value: string): void
2424+```
+188
docs/api/volt.d.md
···11+---
22+version: 1.0
33+updated: 2025-10-18
44+---
55+66+# volt.d
77+88+Context object available to all bindings
99+1010+## CleanupFunction
1111+1212+```typescript
1313+() => void
1414+```
1515+1616+## Scope
1717+1818+```typescript
1919+Record<string, unknown>
2020+```
2121+2222+## BindingContext
2323+2424+Context object available to all bindings
2525+2626+```typescript
2727+{ element: Element; scope: Scope; cleanups: CleanupFunction[] }
2828+```
2929+3030+## PluginContext
3131+3232+Context object provided to plugin handlers.
3333+Contains utilities and references for implementing custom bindings.
3434+3535+### Members
3636+3737+- **element**: `Element`
3838+ The DOM element the plugin is bound to
3939+- **scope**: `Scope`
4040+ The scope object containing signals and data
4141+- **lifecycle**: `PluginLifecycle`
4242+ Lifecycle hooks for plugin-specific mount/unmount behavior
4343+4444+## PluginHandler
4545+4646+Plugin handler function signature.
4747+Receives context and the attribute value, performs binding setup.
4848+4949+```typescript
5050+(context: PluginContext, value: string) => void
5151+```
5252+5353+## Signal
5454+5555+A reactive primitive that notifies subscribers when its value changes.
5656+5757+## ComputedSignal
5858+5959+A computed signal that derives its value from other signals.
6060+6161+## StorageAdapter
6262+6363+Storage adapter interface for custom persistence backends
6464+6565+## ChargedRoot
6666+6767+Information about a mounted Volt root after charging
6868+6969+element: The root element that was mounted
7070+scope: The reactive scope created for this root
7171+cleanup: Cleanup function to unmount this root
7272+7373+```typescript
7474+{ element: Element; scope: Scope; cleanup: CleanupFunction }
7575+```
7676+7777+## ChargeResult
7878+7979+Result of charging Volt roots
8080+8181+roots: Array of all charged roots
8282+cleanup: Cleanup function to unmount all roots
8383+8484+```typescript
8585+{ roots: ChargedRoot[]; cleanup: CleanupFunction }
8686+```
8787+8888+## Dep
8989+9090+```typescript
9191+{ get: () => unknown; subscribe: (callback: (value: unknown) => void) => () => void }
9292+```
9393+9494+## AsyncEffectOptions
9595+9696+Options for configuring async effects
9797+9898+### Members
9999+100100+- **abortable**: `boolean`
101101+ Enable automatic AbortController integration.
102102+When true, provides an AbortSignal to the effect function for canceling async operations.
103103+- **debounce**: `number`
104104+ Debounce delay in milliseconds.
105105+Effect execution is delayed until this duration has passed without dependencies changing.
106106+- **throttle**: `number`
107107+ Throttle delay in milliseconds.
108108+Effect execution is rate-limited to at most once per this duration.
109109+- **onError**: `(error: Error, retry: () => void) => void`
110110+ Error handler for async effect failures.
111111+Receives the error and a retry function.
112112+- **retries**: `number`
113113+ Number of automatic retry attempts on error.
114114+Defaults to 0 (no retries).
115115+- **retryDelay**: `number`
116116+ Delay in milliseconds between retry attempts.
117117+Defaults to 0 (immediate retry).
118118+119119+## AsyncEffectFunction
120120+121121+Async effect function signature.
122122+Receives an optional AbortSignal when abortable option is enabled.
123123+Can return a cleanup function or a Promise that resolves to a cleanup function.
124124+125125+```typescript
126126+(signal?: AbortSignal) => Promise<void | (() => void)>
127127+```
128128+129129+## LifecycleHookCallback
130130+131131+Lifecycle hook callback types
132132+133133+```typescript
134134+() => void
135135+```
136136+137137+## MountHookCallback
138138+139139+```typescript
140140+(root: Element, scope: Scope) => void
141141+```
142142+143143+## UnmountHookCallback
144144+145145+```typescript
146146+(root: Element) => void
147147+```
148148+149149+## ElementMountHookCallback
150150+151151+```typescript
152152+(element: Element, scope: Scope) => void
153153+```
154154+155155+## ElementUnmountHookCallback
156156+157157+```typescript
158158+(element: Element) => void
159159+```
160160+161161+## BindingHookCallback
162162+163163+```typescript
164164+(element: Element, bindingName: string) => void
165165+```
166166+167167+## GlobalHookName
168168+169169+Lifecycle hook names
170170+171171+```typescript
172172+"beforeMount" | "afterMount" | "beforeUnmount" | "afterUnmount"
173173+```
174174+175175+## PluginLifecycle
176176+177177+Extended plugin context with lifecycle hooks
178178+179179+### Members
180180+181181+- **onMount**: `(callback: LifecycleHookCallback) => void`
182182+ Register a callback to run when the plugin is initialized for an element
183183+- **onUnmount**: `(callback: LifecycleHookCallback) => void`
184184+ Register a callback to run when the element is being unmounted
185185+- **beforeBinding**: `(callback: LifecycleHookCallback) => void`
186186+ Register a callback to run before the binding is created
187187+- **afterBinding**: `(callback: LifecycleHookCallback) => void`
188188+ Register a callback to run after the binding is created
+11-23
docs/css/semantics.md
···2121- `--font-size-3xl`: `1.802rem`
2222- `--font-size-4xl`: `2.027rem`
2323- `--font-size-5xl`: `2.566rem`
2424-- `--font-sans`: `"Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif`
2525-- `--font-serif`: `"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif`
2626-- `--font-mono`: `"SF Mono", "Cascadia Code", "Fira Code", "Roboto Mono", Consolas, monospace`
2424+- `--font-sans`: `"Inter", sans-serif`
2525+- `--font-serif`: `"Libre Baskerville", serif`
2626+- `--font-mono`: `"Google Sans Code", monospace`
2727- `--line-height-tight`: `1.25`
2828- `--line-height-base`: `1.6`
2929- `--line-height-relaxed`: `1.8`
···124124125125### `*, *::before, *::after`
126126127127-Modern CSS reset with sensible defaults
127127+CSS reset
128128129129### `html`
130130···148148149149### `h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p`
150150151151-First paragraph after headings - No top margin Common convention in academic typography
151151+First paragraph after headings - No top margin Inspired by tufte.css
152152153153### `a`
154154155155-Links - Accessible and distinctive Uses accent color with underline for clarity
155155+Links Uses accent color with underline for clarity
156156157157### `em`
158158···172172173173### `ul, ol`
174174175175-List spacing and indentation Nested lists inherit proper spacing
175175+List spacing and indentation Nested lists inherit spacing
176176177177### `li`
178178···208208209209### `code`
210210211211-Inline code Monospace font with subtle background for distinction
211211+Inline code Monospace font with subtle background
212212213213### `kbd`
214214···228228229229### `hr`
230230231231-Section dividers Centered decorative element with breathing room
231231+Section dividers Centered decorative element
232232233233### `table`
234234···236236237237### `thead`
238238239239-Table header styling Bold text with bottom border for separation
239239+Table header styling Bold text with bottom border
240240241241### `td`
242242···296296297297### `video, audio`
298298299299-Video and audio Responsive and accessible
300300-301301-### `canvas, svg`
302302-303303-Canvas and SVG
304304-305305-### `iframe`
306306-307307-iframe - Responsive wrapper
299299+Video and audio
308300309301### `article, section`
310302···317309### `header`
318310319311Header and Footer
320320-321321-### `nav`
322322-323323-Nav Navigation menus
324312325313### `details`
326314
+12-12
docs/overview.md
···6677Volt.js is a lightweight, hypermedia based reactive framework for building declarative UIs.
8899-It combines HTML-driven behavior via `data-x-*` attributes with signal-based reactivity.
99+It combines HTML-driven behavior via `data-volt-*` attributes with signal-based reactivity.
10101111## Architecture
1212···33333434### Binding System
35353636-Bindings connect signals to DOM via `data-x-*` attributes:
3636+Bindings connect signals to DOM via `data-volt-*` attributes:
37373838```html
3939<div id="app">
4040- <p data-x-text="count">0</p>
4141- <button data-x-on-click="increment">+</button>
4242- <div data-x-if="isPositive">Positive</div>
4040+ <p data-volt-text="count">0</p>
4141+ <button data-volt-on-click="increment">+</button>
4242+ <div data-volt-if="isPositive">Positive</div>
4343</div>
4444```
4545···53535454Core bindings:
55555656-- `data-x-text` - Update text content
5757-- `data-x-html` - Update HTML content
5858-- `data-x-class` - Toggle CSS classes
5959-- `data-x-on-*` - Attach event handlers
6060-- `data-x-if` - Conditional rendering
6161-- `data-x-for` - List rendering
5656+- `data-volt-text` - Update text content
5757+- `data-volt-html` - Update HTML content
5858+- `data-volt-class` - Toggle CSS classes
5959+- `data-volt-on-*` - Attach event handlers
6060+- `data-volt-if` - Conditional rendering
6161+- `data-volt-for` - List rendering
62626363### Plugin System
64646565-Extend functionality via custom `data-x-*` bindings:
6565+Extend functionality via custom `data-volt-*` bindings:
66666767```js
6868import { registerPlugin } from 'volt';
+28-28
docs/plugin-spec.md
···2233## Overview
4455-The plugin system enables extending the framework with custom `data-x-*` attribute bindings.
55+The plugin system enables extending the framework with custom `data-volt-*` attribute bindings.
6677Plugins follow the same binding patterns as core bindings (text, html, class, events) but can implement specialized behaviors like persistence, scrolling, and URL synchronization.
88···3434registerPlugin(name: string, handler: PluginHandler): void
3535```
36363737-The plugin name becomes the `data-x-*` attribute suffix. For example, registering a plugin named `"tooltip"` enables `data-x-tooltip` attributes.
3737+The plugin name becomes the `data-volt-*` attribute suffix. For example, registering a plugin named `"tooltip"` enables `data-volt-tooltip` attributes.
38383939### Plugin Handler
4040···100100101101Volt.js ships with three built-in plugins that must be explicitly registered.
102102103103-### data-x-persist
103103+### data-volt-persist
104104105105Synchronizes signal values with persistent storage (`localStorage`, `sessionStorage`, `IndexedDB`).
106106107107**Syntax:**
108108109109```html
110110-<input data-x-persist="signalName:storageType" />
110110+<input data-volt-persist="signalName:storageType" />
111111```
112112113113**Storage Types:**
···127127128128```html
129129<!-- Persist counter to localStorage -->
130130-<div data-x-text="count" data-x-persist="count:local"></div>
130130+<div data-volt-text="count" data-volt-persist="count:local"></div>
131131132132<!-- Persist form state to sessionStorage -->
133133-<input data-x-on-input="updateForm" data-x-persist="formData:session" />
133133+<input data-volt-on-input="updateForm" data-volt-persist="formData:session" />
134134135135<!-- Persist large dataset to IndexedDB -->
136136-<div data-x-persist="userData:indexeddb"></div>
136136+<div data-volt-persist="userData:indexeddb"></div>
137137```
138138139139**Custom Storage Adapters:**
···152152});
153153```
154154155155-### data-x-scroll
155155+### data-volt-scroll
156156157157Manages scroll behavior including position restoration, programmatic scrolling, scroll spy, and smooth scrolling.
158158···160160161161```html
162162<!-- Scroll position restoration -->
163163-<div data-x-scroll="restore:position"></div>
163163+<div data-volt-scroll="restore:position"></div>
164164165165<!-- Scroll to element when signal changes -->
166166-<div data-x-scroll="scrollTo:targetId"></div>
166166+<div data-volt-scroll="scrollTo:targetId"></div>
167167168168<!-- Scroll spy (updates signal when in viewport) -->
169169-<div data-x-scroll="spy:isVisible"></div>
169169+<div data-volt-scroll="spy:isVisible"></div>
170170171171<!-- Smooth scroll behavior -->
172172-<div data-x-scroll="smooth:true"></div>
172172+<div data-volt-scroll="smooth:true"></div>
173173```
174174175175**Behaviors:**
···177177**Position Restoration:**
178178179179```html
180180-<div id="content" data-x-scroll="restore:scrollPos">
180180+<div id="content" data-volt-scroll="restore:scrollPos">
181181 <!-- scroll position saved on scroll, restored on mount -->
182182</div>
183183```
···187187**Scroll-To:**
188188189189```html
190190-<button data-x-on-click="scrollToSection.set('section2')">Go to Section 2</button>
191191-<div id="section2" data-x-scroll="scrollTo:scrollToSection"></div>
190190+<button data-volt-on-click="scrollToSection.set('section2')">Go to Section 2</button>
191191+<div id="section2" data-volt-scroll="scrollTo:scrollToSection"></div>
192192```
193193194194Scrolls to element when the specified signal changes to match element's ID or selector.
···197197198198```html
199199<nav>
200200- <a data-x-class="{ active: section1Visible }">Section 1</a>
201201- <a data-x-class="{ active: section2Visible }">Section 2</a>
200200+ <a data-volt-class="{ active: section1Visible }">Section 1</a>
201201+ <a data-volt-class="{ active: section2Visible }">Section 2</a>
202202</nav>
203203-<div data-x-scroll="spy:section1Visible"></div>
204204-<div data-x-scroll="spy:section2Visible"></div>
203203+<div data-volt-scroll="spy:section1Visible"></div>
204204+<div data-volt-scroll="spy:section2Visible"></div>
205205```
206206207207Updates signal with boolean visibility state using Intersection Observer.
···209209**Smooth Scrolling:**
210210211211```html
212212-<div data-x-scroll="smooth:behavior"></div>
212212+<div data-volt-scroll="smooth:behavior"></div>
213213```
214214215215Enables smooth scrolling with configurable behavior from signal.
216216217217-### data-x-url
217217+### data-volt-url
218218219219Synchronizes signal values with URL parameters and hash-based routing.
220220···222222223223```html
224224<!-- One-way: Read URL param into signal on mount -->
225225-<input data-x-url="read:searchQuery" />
225225+<input data-volt-url="read:searchQuery" />
226226227227<!-- Bidirectional: Keep URL and signal in sync -->
228228-<input data-x-url="sync:filter" />
228228+<input data-volt-url="sync:filter" />
229229230230<!-- Hash-based routing -->
231231-<div data-x-url="hash:currentRoute"></div>
231231+<div data-volt-url="hash:currentRoute"></div>
232232```
233233234234**Behaviors:**
···237237238238```html
239239<!-- Initialize signal from ?tab=profile -->
240240-<div data-x-url="read:tab"></div>
240240+<div data-volt-url="read:tab"></div>
241241```
242242243243Reads URL parameter on mount and sets signal value. Signal changes do not update URL.
···246246247247```html
248248<!-- Keep ?search=query in sync with searchQuery signal -->
249249-<input data-x-on-input="handleSearch" data-x-url="sync:searchQuery" />
249249+<input data-volt-on-input="handleSearch" data-volt-url="sync:searchQuery" />
250250```
251251252252Changes to signal update URL parameter, changes to URL update signal. Uses History API for clean URLs.
···255255256256```html
257257<!-- Sync with #/page/about -->
258258-<div data-x-url="hash:route"></div>
259259-<div data-x-text="route === '/page/about' ? 'About Page' : 'Home'"></div>
258258+<div data-volt-url="hash:route"></div>
259259+<div data-volt-text="route === '/page/about' ? 'About Page' : 'Home'"></div>
260260```
261261262262Keeps hash portion of URL in sync with signal. Useful for client-side routing.
···22 * Async effect system with abort, race protection, debounce, throttle, and error handling
33 */
4455-import type { AsyncEffectFunction, AsyncEffectOptions, ComputedSignal, Signal } from "../types/volt";
55+import type { AsyncEffectFunction, AsyncEffectOptions, ComputedSignal, Signal } from "$types/volt";
6677/**
88 * Creates an async side effect that runs when dependencies change.
+1-1
lib/src/core/binder.ts
···22 * Binder system for mounting and managing Volt.js bindings
33 */
4455-import type { BindingContext, CleanupFunction, PluginContext, Scope, Signal } from "../types/volt";
55+import type { BindingContext, CleanupFunction, PluginContext, Scope, Signal } from "$types/volt";
66import { getVoltAttributes, parseClassBinding, setHTML, setText, toggleClass, walkDOM } from "./dom";
77import { evaluate, extractDependencies, isSignal } from "./evaluator";
88import { executeGlobalHooks, notifyBindingCreated, notifyElementMounted, notifyElementUnmounted } from "./lifecycle";
+1-1
lib/src/core/charge.ts
···44 * Handles declarative state initialization via data-volt-state and data-volt-computed
55 */
6677-import type { ChargedRoot, ChargeResult, Scope } from "../types/volt";
77+import type { ChargedRoot, ChargeResult, Scope } from "$types/volt";
88import { mount } from "./binder";
99import { evaluate, extractDependencies } from "./evaluator";
1010import { computed, signal } from "./signal";
+3-3
lib/src/core/plugin.ts
···22 * Plugin system for extending Volt.js with custom bindings
33 */
4455-import type { PluginHandler } from "../types/volt";
55+import type { PluginHandler } from "$types/volt";
6677const pluginRegistry = new Map<string, PluginHandler>();
8899/**
1010 * Register a custom plugin with a given name.
1111- * Plugins extend Volt.js with custom data-x-* attribute bindings.
1111+ * Plugins extend Volt.js with custom data-volt-* attribute bindings.
1212 *
1313- * @param name - Plugin name (will be used as data-x-{name})
1313+ * @param name - Plugin name (will be used as data-volt-{name})
1414 * @param handler - Plugin handler function
1515 *
1616 * @example
+1-1
lib/src/core/signal.ts
···11-import type { ComputedSignal, Signal } from "../types/volt";
11+import type { ComputedSignal, Signal } from "$types/volt";
2233/**
44 * Creates a new signal with the given initial value.
+1-1
lib/src/index.ts
···2929} from "@volt/core/lifecycle";
3030export { clearPlugins, getRegisteredPlugins, hasPlugin, registerPlugin, unregisterPlugin } from "@volt/core/plugin";
3131export { computed, effect, signal } from "@volt/core/signal";
3232-export { persistPlugin, registerStorageAdapter, scrollPlugin, urlPlugin } from "@volt/plugins/index";
3232+export { persistPlugin, registerStorageAdapter, scrollPlugin, urlPlugin } from "@volt/plugins";
+2-2
lib/src/main.ts
···11-import { persistPlugin, scrollPlugin, urlPlugin } from "@volt/plugins/index";
22-import { computed, effect, mount, registerPlugin, signal } from "./index";
11+import { computed, effect, mount, registerPlugin, signal } from "@volt";
22+import { persistPlugin, scrollPlugin, urlPlugin } from "@volt/plugins";
3344registerPlugin("persist", persistPlugin);
55registerPlugin("scroll", scrollPlugin);
+1-1
lib/test/integration/list-rendering.test.ts
···11+import { computed, mount, signal } from "@volt";
12import { describe, expect, it } from "vitest";
22-import { computed, mount, signal } from "../../src/index";
3344describe("integration: list rendering", () => {
55 it("creates a reactive todo list", () => {
+1-1
lib/test/integration/mount.test.ts
···11+import { mount, signal } from "@volt";
12import { describe, expect, it } from "vitest";
22-import { mount, signal } from "../../src/index";
3344describe("integration: mount", () => {
55 it("creates a reactive counter", () => {