diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..fd10e47 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "svstate-demo", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "demo"], + "port": 5173 + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index ad62893..6d2cba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,58 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] - 2026-07-31 + +A functional correctness pass over the whole library. Several long-standing bugs silently corrupted +state or leaked resources; fixing them changes observable behavior, hence the major version. + +### Breaking + +- **`delete` now fires a change** — deleting a property through the reactive proxy (`delete data.draft`) previously bypassed dirty tracking, validation, persistence and every plugin hook. It now emits a change event with `currentValue: undefined`, so validators and plugins see it. Code that relied on deletes being invisible will now see extra events. +- **Change paths keep numeric object keys** — a key like `data.users['123'].name` was reported as `users.name` because any numeric-looking key was treated as an array index. It is now reported as `users.123.name`. Only true array indices are collapsed. Async validator paths and `isDirtyByField` keys change accordingly. +- **Array `length` writes report the array path** — `data.list.length = 0` (and `pop`/`splice`) reported `list.length`; they now report `list`, matching index writes. +- **Proxy identity is stable** — `data.nested === data.nested` was `false` because a new proxy was created on every read. Child proxies are now cached, so identity comparisons and keyed `{#each}` blocks work. +- **Assigning a nested value no longer stores a proxy** — `data.b = data.a` used to write the _proxy_ of `a` into `b`, after which `data.b.x = 1` fired twice, once with the stale path `a.x`. The raw value is now unwrapped before assignment, and self-assignment is a no-op. +- **`actionError` is always an `Error`** — a thrown primitive (`throw 'boom'`) previously produced `undefined`, silently swallowing the failure. It is now wrapped, keeping the `.message` → `.body.message` → `String()` precedence. +- **`NaN` no longer passes numeric rules** — `min`, `max`, `between`, `positive`, `negative`, `nonNegative`, `notZero`, `integer`, `multipleOf`, `step`, `decimal` and `percentage` skip `NaN` like they skip `null`/`undefined`; only `required()` reports it. +- **State is re-baselined after plugin hydration** — `persistPlugin` and `historyPlugin` restore state in `onInit`, which used to mark every restored field dirty and leave the `Initial` snapshot holding pre-restore data (so `reset()` reverted past the restore). Restored state is now the baseline: `isDirty` is `false` and `reset()` returns to the restored values. + +### Added + +- **`validate()`** — runs sync validation immediately, bypassing the debounce, and returns `{ errors, hasErrors }`. Previously the only way to be sure errors were current before submitting was to wait for a microtask. +- **`batch(fn)`** — applies many mutations as one unit: one validation pass, each async validator scheduled at most once, and a single snapshot (undo point) for the whole batch. `effect` and plugin `onChange` still fire per mutation. +- **`onPluginError` option** — receives `(error, pluginName, hook)` when a plugin hook throws; defaults to `console.error`. +- **`PersistOptions.onError` and `AnalyticsOptions.onError`** — surface storage and sink failures instead of letting them escape. +- **New exports** — `UndoRedoOptions`, `ValidationResult`, `PluginHook`, and the `PersistPluginInstance`, `AutosavePluginInstance`, `AnalyticsPluginInstance` types. + +### Fixed + +- **Snapshots destroyed `Map`, `Set` and `RegExp`** — `deepClone` rebuilt them with `Object.create` plus own keys, producing objects that passed `instanceof` but threw on every method call (`clonedMap.get(k)` → `TypeError: called on incompatible receiver`). They are now reconstructed properly, and `Error`, `Promise`, `WeakMap`/`WeakSet`, `ArrayBuffer` and typed arrays are carried by reference instead of being mangled. +- **Circular state crashed the clone** — a self-referencing object caused unbounded recursion during snapshot; already-cloned objects are now reused. +- **Getters were flattened into values** by cloning; accessor descriptors are now preserved. +- **`destroy()` leaked async validations** — despite being documented as cancelling them, it only called plugin `destroy` hooks. It now cancels in-flight and debounced async validations, clears the pending validation timer, ignores later mutations, and is safe to call twice. +- **Rollback left keys added after the snapshot** — `rollback()`/`reset()` merged the snapshot over live state; keys that did not exist in the snapshot are now removed. +- **A throwing plugin aborted the mutation** and skipped every later plugin; hooks are now isolated and reported through `onPluginError`. +- **`redo()` wiped the rest of the redo stack** — applying a redo fired `onChange`, which cleared the stack, so only the first redo of a chain worked. Consecutive redos now step back correctly, each keeping its own snapshot. +- **`analyticsPlugin` always reported `hasErrors: true`** — it checked `errors !== undefined`, which is true on every pass whenever a validator exists; it now inspects the actual error leaves. `redact` also covers nested paths (`redact: ['user']` redacts `user.ssn`), and a rejected `onFlush` no longer becomes an unhandled rejection. +- **`persistPlugin` could throw out of a timer** — `JSON.stringify` and `setItem` ran unguarded, so a `QuotaExceededError` escaped asynchronously. +- **`autosavePlugin` dropped overlapping saves** — a save requested while another was in flight was discarded; it now runs once the current one settles. +- **`syncPlugin` dropped the newest inbound update** — messages arriving inside the throttle window were discarded, losing the final state. Bursts now collapse to the last payload, applied when the window closes. +- **`decimal()` miscounted exponential notation** — `1e-7` counted as 0 decimal places. +- **`multipleOf()`/`step()` failed on floats** — `0.3` was reported as not a multiple of `0.1` due to exact modulo; comparison is now epsilon-tolerant, and a zero divisor is rejected. +- **Array item comparison collided across types** — `unique()`, `includes()`, `includesAny()` and `includesAll()` keyed items with `String()`/`JSON.stringify`, so `1` matched `'1'`, `null` matched `'null'`, and `{a:1,b:2}` differed from `{b:2,a:1}`. Keys are now type-tagged with stable key ordering, and `Date` values compare by time. + +### Internal + +- Shared helpers moved to `src/internal/` (`clone.ts`, `paths.ts`, `errors.ts`), removing five duplicated copies of `deepClone`, `DANGEROUS_KEYS`, `getValueAtPath` and `setValueAtPath` — one of which (in `undoRedoPlugin`) was missing the prototype-pollution guard entirely. + +### Demo + +- Every demo page's "Fill with Valid Data" now uses `batch()` instead of sequential assignments — one validation pass per fill, and pages driven by an `effect` that calls `snapshot()` now produce a single undo point per fill instead of one per field. +- Added a "Validate Now" control to the Options demo (`validate()` bypassing `debounceValidation`) and a plugin-error simulation to the Devtools demo (`onPluginError`, showing a throwing hook doesn't abort the mutation or block other plugins). +- Wired `persistPlugin`'s and `analyticsPlugin`'s new `onError` option into the Persist/Sync and Autosave/Analytics demos. +- Deduplicated repeated markup: a shared `Spinner` component replaces seven copy-pasted loading SVGs, a shared `formatFieldName` helper replaces four inline copies, and `DemoSidebar` gained an `extra` snippet prop so pages no longer double-wrap it to append custom sidebar panels. + ## [1.5.6] - 2026-07-31 ### Changed diff --git a/CLAUDE.md b/CLAUDE.md index 81b167f..3221974 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -83,11 +83,16 @@ Note: The demo has its own `node_modules` and uses Zod for some validation examp ### Core Files -- `src/index.ts` - Public exports: `createSvState`, validator builders, plugin types and built-in plugins, types (`Snapshot`, `EffectContext`, `SnapshotFunction`, `SvStateOptions`, `Validator`, `AsyncValidator`, `AsyncValidatorFunction`, `AsyncErrors`, `DirtyFields`, `SvStatePlugin`, `PluginContext`, `PluginStores`, `ChangeEvent`, `ActionEvent`) +- `src/index.ts` - Public exports: `createSvState`, validator builders, plugin types and built-in plugins, types (`Snapshot`, `EffectContext`, `SnapshotFunction`, `SvStateOptions`, `Validator`, `AsyncValidator`, `AsyncValidatorFunction`, `AsyncErrors`, `DirtyFields`, `SvStatePlugin`, `PluginContext`, `PluginStores`, `ChangeEvent`, `ActionEvent`, `ValidationResult`, `PluginHook`, and per-plugin option/instance types) - `src/state.svelte.ts` - Main `createSvState()` function with snapshot/undo system, async validation, and plugin integration - `src/proxy.ts` - `ChangeProxy` deep reactive proxy implementation - `src/validators.ts` - Fluent validator builders (string, number, array, date) -- `src/plugin.ts` - Plugin type definitions (`SvStatePlugin`, `PluginContext`, `PluginStores`, `ChangeEvent`, `ActionEvent`) +- `src/plugin.ts` - Plugin type definitions (`SvStatePlugin`, `PluginContext`, `PluginStores`, `ChangeEvent`, `ActionEvent`). `PluginStores` is an alias of `StateResult` — the same stores `createSvState` returns, with the error type widened +- `src/internal/` - Internal helpers shared by the core and the plugins, not exported publicly: + - `clone.ts` — `deepClone` (prototype-preserving, reconstructs `Map`/`Set`/`RegExp`, handles cycles) + - `paths.ts` — `DANGEROUS_KEYS`, `getValueAtPath`, `setValueAtPath`, `isPlainObject`, `safeMerge`, `asRecord`, `getMatchingPaths` + - `errors.ts` — `hasAnyErrors`, `toError` + - `timers.ts` — `createDebouncer` (trailing-edge debounce with `schedule`/`cancel`/`flush`/`isPending`), shared by `persist`, `autosave` and `sync` - `src/plugins/` - Built-in plugins: `persistPlugin`, `autosavePlugin`, `devtoolsPlugin`, `historyPlugin`, `syncPlugin`, `undoRedoPlugin`, `analyticsPlugin` ### createSvState Function (src/state.svelte.ts) @@ -95,7 +100,7 @@ Note: The demo has its own `node_modules` and uses Zod for some validation examp The main export creates a validated state object with snapshot/undo support: ```typescript -const { data, execute, state, rollback, rollbackTo, reset, destroy } = createSvState(init, actuators?, options?); +const { data, execute, state, rollback, rollbackTo, reset, destroy, validate, batch } = createSvState(init, actuators?, options?); ``` **Returns:** @@ -105,14 +110,16 @@ const { data, execute, state, rollback, rollbackTo, reset, destroy } = createSvS - `rollback(steps?)` - Undo N steps (default 1), restores state and triggers validation - `rollbackTo(title)` - Roll back to the last snapshot matching `title`, returns `boolean` (true if found) - `reset()` - Return to initial snapshot, triggers validation -- `destroy()` - Cleanup function: calls plugin `destroy` hooks in reverse order, cancels async validations +- `destroy()` - Cleanup function: cancels in-flight and debounced async validations, clears the pending validation timer, ignores later mutations, then calls plugin `destroy` hooks in reverse order. Idempotent. +- `validate()` - Runs sync validation immediately (bypassing debounce) and returns `ValidationResult` = `{ errors, hasErrors }` +- `batch(fn)` - Applies `fn(draft)` as one unit: one validation pass, each async validator scheduled at most once, and a single snapshot for the whole batch. `effect` and plugin `onChange` still fire per mutation. Nested `batch()` calls join the outer batch. - `state` - Object containing reactive stores: - `errors: Readable` - Validation errors (sync) - `hasErrors: Readable` - Whether any sync validation errors exist - `isDirty: Readable` - Whether state has been modified (derived from `isDirtyByField`) - `isDirtyByField: Readable` - Per-field dirty tracking; keys are dot-notation property paths. When a nested field changes, all parent paths are also marked dirty (e.g., changing `customer.address.street` marks `customer.address` and `customer` as dirty). Cleared on `reset()`, `rollback()`, and successful action (respecting `resetDirtyOnAction`). - `actionInProgress: Readable` - Action execution status - - `actionError: Readable` - Last action error; non-`Error` thrown objects are wrapped by reading `.message` then `.body.message` before falling back to `String()` + - `actionError: Readable` - Last action error; anything thrown is wrapped into an `Error` by reading `.message` then `.body.message` before falling back to `String()` (primitives included) - `snapshots: Readable[]>` - Snapshot history for undo - `asyncErrors: Readable` - Async validation errors (keyed by property path) - `hasAsyncErrors: Readable` - Whether any async validation errors exist @@ -138,6 +145,7 @@ const { data, execute, state, rollback, rollbackTo, reset, destroy } = createSvS - `clearAsyncErrorsOnChange: boolean` (default: `true`) - Clear async error for a path when that property changes - `maxConcurrentAsyncValidations: number` (default: `4`) - Maximum concurrent async validators running simultaneously - `maxSnapshots: number` (default: `50`) - Maximum number of snapshots to keep; oldest non-Initial snapshots are trimmed when exceeded. `0` = unlimited. +- `onPluginError: (error, pluginName, hook) => void` (default: `console.error`) - Called when a plugin hook throws; the mutation and the remaining plugins are unaffected - `plugins: SvStatePlugin[]` (default: `[]`) - Array of plugins to extend behavior (see Plugin System) ### Snapshot/Undo System @@ -216,21 +224,23 @@ Plugins extend `createSvState` via lifecycle hooks. They are registered via `opt **Hook execution:** Hooks are called in plugin array order (first to last), except `destroy` which runs last-to-first. All hooks are optional. -**Internal implementation:** `createSvState` uses a `callPlugins(hook, ...args)` helper that iterates plugins and calls matching hook functions. +**Internal implementation:** `createSvState` uses a `callPlugins(hook, ...args)` helper that iterates plugins and calls matching hook functions. Each call is wrapped in `try`/`catch` — a throwing plugin is reported via `onPluginError` and never aborts the mutation or blocks later plugins. + +**Hydration re-baseline:** plugins that restore state in `onInit` (persist, history) write through the live proxy. Validation is deferred across the `onInit` hook, and if any change occurred the state is re-baselined afterwards: dirty fields are cleared and snapshot 0 is rewritten from the hydrated state. So restored values are the initial state, not a dirty change on top of it. **Built-in plugins (src/plugins/):** -| Plugin | File | Purpose | Key options | -| ----------------- | -------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `persistPlugin` | `persist.ts` | Persist state to localStorage/custom storage | `key`, `storage`, `throttle`, `version`, `migrate`, `include`, `exclude` | -| `autosavePlugin` | `autosave.ts` | Auto-save after idle/interval | `save` (required), `idle`, `interval`, `saveOnDestroy`, `onlyWhenDirty` | -| `devtoolsPlugin` | `devtools.ts` | Console logging of all events | `name`, `collapsed`, `logValidation`, `enabled`, `logValues` | -| `historyPlugin` | `history.ts` | Sync state fields to URL params | `fields` (required), `mode`, `serialize`, `deserialize` | -| `syncPlugin` | `sync.ts` | Cross-tab sync via BroadcastChannel | `key` (required), `throttle`, `merge`; uses JSON serialization (Dates become strings, undefined/functions dropped); incoming payloads deeper than 10 levels are rejected | -| `undoRedoPlugin` | `undo-redo.ts` | Redo stack on top of built-in rollback | `maxRedoStack`; exposes `redo()`, `canRedo()`, `redoStack` | -| `analyticsPlugin` | `analytics.ts` | Batch event buffering for analytics | `onFlush` (required), `batchSize`, `flushInterval`, `include`, `redact` | +| Plugin | File | Purpose | Key options | +| ----------------- | -------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `persistPlugin` | `persist.ts` | Persist state to localStorage/custom storage | `key`, `storage`, `throttle`, `version`, `migrate`, `include`, `exclude`, `onError` | +| `autosavePlugin` | `autosave.ts` | Auto-save after idle/interval | `save` (required), `idle`, `interval`, `saveOnDestroy`, `onlyWhenDirty` | +| `devtoolsPlugin` | `devtools.ts` | Console logging of all events | `name`, `collapsed`, `logValidation`, `enabled`, `logValues` | +| `historyPlugin` | `history.ts` | Sync state fields to URL params | `fields` (required), `mode`, `serialize`, `deserialize`, `onError`; dotted field paths match both ways (changing `filters` updates a registered `filters.q`, and vice versa) | +| `syncPlugin` | `sync.ts` | Cross-tab sync via BroadcastChannel | `key` (required), `throttle`, `merge`, `onError`; uses JSON serialization (Dates become strings, undefined/functions dropped); incoming payloads deeper than 10 levels are rejected | +| `undoRedoPlugin` | `undo-redo.ts` | Redo stack on top of built-in rollback | `maxRedoStack`; exposes `redo()`, `canRedo()`, `redoStack` | +| `analyticsPlugin` | `analytics.ts` | Batch event buffering for analytics | `onFlush` (required), `batchSize`, `flushInterval`, `include`, `redact` (covers nested paths), `onError` | -### Deep Clone System (src/state.svelte.ts) +### Deep Clone System (src/internal/clone.ts) The `deepClone` function preserves object prototypes using `Object.create(Object.getPrototypeOf(object))`. This allows state objects to include methods that operate on `this`: @@ -248,18 +258,30 @@ data.format(); // Works — method preserved Methods are preserved through snapshots, rollback, and reset operations. +Other cloning behavior: + +- `Date`, `Map`, `Set` and `RegExp` are reconstructed, not rebuilt from own keys (rebuilding produced objects that passed `instanceof` but threw on every method call) +- `Error`, `Promise`, `WeakMap`, `WeakSet`, `WeakRef`, `ArrayBuffer` and typed arrays are carried by reference +- Circular references resolve to the already-cloned instance via a `WeakMap` of visited objects +- Accessor descriptors (getters/setters) are preserved instead of being flattened into values +- Keys in `DANGEROUS_KEYS` are skipped + ### Deep Proxy System (src/proxy.ts) - `ChangeProxy()` wraps objects with recursive Proxy handlers - Tracks property paths via dot notation (e.g., `"address.zip"`) -- **Loop Prevention**: Uses strict equality (`!==`) to skip unchanged values +- **Loop Prevention**: uses `Object.is` to skip unchanged values (so writing `NaN` over `NaN` is a no-op) +- **Stable identity**: child proxies are cached per (raw object, path) in a `WeakMap` of `WeakRef`s, so `data.nested === data.nested` +- **No proxies in the raw tree**: values are unwrapped (via a `RAW` symbol) before assignment, so `data.b = data.a` stores the raw object; later `data.b.x = 1` reports `b.x` once instead of firing twice with a stale `a.x` +- **`deleteProperty` trap**: `delete data.x` emits a change with `currentValue: undefined` (nothing is emitted if the key was absent) - Excludes non-proxiable types: Date, Map, Set, WeakMap, WeakSet, RegExp, Error, Promise -- Array indices are collapsed in paths (only named properties tracked) +- Array indices and array `length` writes collapse to the array's own path; numeric-looking keys on plain objects keep their segment (`users.123.name`) ### Security Model -- **Prototype pollution** — all path-traversal and deep-clone code guards against `__proto__`, `constructor`, and `prototype` keys via a shared `DANGEROUS_KEYS` set (`src/state.svelte.ts`, `src/plugins/persist.ts`, `src/plugins/sync.ts`) -- **BroadcastChannel messages** — `syncPlugin` rejects incoming payloads exceeding 10 levels of nesting (`isWithinDepthLimit` in `src/plugins/sync.ts`) +- **Prototype pollution** — all path-traversal and deep-clone code guards against `__proto__`, `constructor`, and `prototype` keys via the shared `DANGEROUS_KEYS` set in `src/internal/paths.ts` (used by the core, `persist`, `history` and `sync`) +- **BroadcastChannel messages** — `syncPlugin` rejects incoming payloads exceeding 10 levels of nesting (`isWithinDepthLimit` in `src/plugins/sync.ts`); accepted payloads are throttled with a trailing apply so a burst collapses to the newest state rather than dropping it +- **Plugin isolation** — a throwing plugin hook cannot abort a state mutation or block later plugins; errors surface through `onPluginError` - **JSON serialization in sync** — state is serialized with `JSON.stringify`/`JSON.parse` (structuredClone cannot be used on Svelte reactive proxies); `Date` objects become strings and `undefined`/functions are dropped — document this for users - **No eval/Function** — the codebase contains no dynamic code execution - **Async race conditions** — handled via `AbortController` in `src/state.svelte.ts` @@ -291,13 +313,13 @@ Four chainable validator builders with `getError()` to extract the first error. - `.min(n)`, `.max(n)`, `.between(min, max)` - Range constraints - `.integer()`, `.decimal(places)` - Type constraints - `.positive()`, `.negative()`, `.nonNegative()`, `.notZero()` - Sign constraints - - `.multipleOf(n)`, `.step(n)` - Divisibility checks + - `.multipleOf(n)`, `.step(n)` - Divisibility checks (epsilon-tolerant, so `0.3` is a multiple of `0.1`; a zero divisor never matches) - `.percentage()` - Must be 0-100 - **arrayValidator(input)** - Array validation - `.required()`, `.requiredIf(cond)` - Require non-empty array - `.minLength(n)`, `.maxLength(n)`, `.ofLength(n)` - Length constraints - - `.unique()` - All items must be unique + - `.unique()` - All items must be unique (keys are type-tagged, so `1` and `'1'` differ; object key order is irrelevant; dates compare by time) - `.includes(item)`, `.includesAny(items)`, `.includesAll(items)` - Item presence - **dateValidator(input)** - Date validation (accepts Date, string, or number) @@ -330,9 +352,9 @@ Test files go in `test/` directory: Current test files: -- `validators.test.ts` - Fluent validator builder tests (~320 cases) -- `proxy.test.ts` - ChangeProxy deep proxy tests -- `state.test.svelte.ts` - Core createSvState tests (~90 cases) +- `validators.test.ts` - Fluent validator builder tests (~330 cases) +- `proxy.test.ts` - ChangeProxy deep proxy tests, including delete events, proxy identity and path resolution +- `state.test.svelte.ts` - Core createSvState tests (~105 cases), including `validate()`, `batch()`, destroy cleanup, non-plain values (Map/Set/RegExp/cycles) and plugin error isolation - `async-validation.test.svelte.ts` - Async validator tests - `performance.test.svelte.ts` - Performance/stress tests - `plugins.test.svelte.ts` - Plugin system integration tests diff --git a/FAQ.md b/FAQ.md index a6b22ab..3353c2e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -176,6 +176,46 @@ createSvState(data, actuators, { --- +### How do I force validation to run immediately, bypassing the debounce? + +Call `validate()`. It runs sync validation right away — no microtask, no debounce delay — and returns the result directly, so you can check it before submitting: + +```typescript +const { data, validate, execute } = createSvState(form, { validator, action }); + +function submit() { + const { errors, hasErrors } = validate(); + if (hasErrors) return; // errors store is already up to date too + execute(); +} +``` + +This is the reliable way to know errors are current right before an action, even with a long `debounceValidation`. + +--- + +### How do I apply several changes as a single validation pass and undo point? + +Use `batch(fn)`. Every mutation made inside the callback is applied normally (so `effect` and plugin `onChange` still fire once per property), but validation runs only once at the end, each async validator is scheduled at most once, and the whole group produces a single snapshot instead of one per field: + +```typescript +const { data, batch, rollback } = createSvState(formData, { + effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) +}); + +batch((draft) => { + draft.firstName = 'Ada'; + draft.lastName = 'Lovelace'; + draft.address.city = 'London'; +}); + +rollback(); // undoes all three fields at once, not just the last one +``` + +This is the right tool for "fill form with sample data" buttons, bulk imports, or any place you'd otherwise mutate several fields back-to-back. + +--- + ### Can I use Zod, Yup, or other validation libraries instead of built-in validators? **Yes!** The `validator` function just needs to return an object matching your error structure. Use any validation library: @@ -420,8 +460,13 @@ The `property` is a dot-notation path string: | `data.billing.bank.iban = '...'` | `"billing.bank.iban"` | | `data.contacts[0].email = '...'` | `"contacts.email"` | | `data.tags.push('new')` | `"tags"` | +| `data.tags.length = 0` | `"tags"` | +| `delete data.draft` | `"draft"` | +| `data.users['123'].name = '...'` | `"users.123.name"` | + +**Note:** Array indices and array `length` writes are collapsed onto the array's own path — you get `"contacts.email"` not `"contacts.0.email"`. Numeric-looking keys on plain objects are _not_ collapsed, so a record keyed by id keeps its segment (`"users.123.name"`). -**Note:** Array indices are collapsed — you get `"contacts.email"` not `"contacts.0.email"`. +Deleting a property (`delete data.draft`) also emits a change, with `currentValue` set to `undefined`. --- @@ -593,6 +638,7 @@ import type { Snapshot, SnapshotFunction, SvStateOptions, + ValidationResult, AsyncValidator, AsyncValidatorFunction, AsyncErrors, @@ -600,6 +646,7 @@ import type { SvStatePlugin, PluginContext, PluginStores, + PluginHook, ChangeEvent, ActionEvent } from 'svstate'; @@ -615,6 +662,7 @@ import type { AnalyticsEvent } from 'svstate'; | `SnapshotFunction` | Type for the `snapshot` function parameter | | `Snapshot` | Type for snapshot history entries | | `SvStateOptions` | Type for configuration options | +| `ValidationResult` | Return type of `validate()`: `{ errors, hasErrors }` | | `AsyncValidator` | Object mapping property paths to async validator functions | | `AsyncValidatorFunction` | Async function: `(value, source, signal) => Promise` | | `AsyncErrors` | Object mapping property paths to error strings | @@ -622,6 +670,7 @@ import type { AnalyticsEvent } from 'svstate'; | `SvStatePlugin` | Plugin interface with lifecycle hooks | | `PluginContext` | Context passed to `onInit`: `{ data, state, options, snapshot }` | | `PluginStores` | All readable stores exposed to plugins | +| `PluginHook` | Hook name passed to `onPluginError`, e.g. `'onChange'` | | `ChangeEvent` | Payload for `onChange`: `{ target, property, currentValue, oldValue }` | | `ActionEvent` | Payload for `onAction`: `{ phase, params?, error? }` | | `AnalyticsEvent` | Event object buffered by `analyticsPlugin` | @@ -827,6 +876,38 @@ const myPlugin: SvStatePlugin = { --- +### What happens if a plugin hook throws an error? + +**It's isolated.** A throwing hook no longer aborts the mutation or blocks later plugins — it's caught and reported through the `onPluginError` option, which defaults to `console.error`: + +```typescript +const { data } = createSvState(formData, actuators, { + plugins: [myFlakyPlugin, devtoolsPlugin()], + onPluginError: (error, pluginName, hook) => { + console.error(`Plugin "${pluginName}" failed in ${hook}:`, error); + // e.g. report(error) to your error tracker + } +}); +``` + +`data.name = 'new value'` still applies, `myFlakyPlugin`'s failing hook doesn't stop `devtoolsPlugin` from running, and you get told exactly which plugin and hook failed. + +`persistPlugin` and `analyticsPlugin` have their own `onError` option for storage/sink failures specifically (quota exceeded, `onFlush` rejecting), separate from `onPluginError`: + +```typescript +persistPlugin({ + key: 'my-form', + onError: (error) => report('persist failed', error) // e.g. QuotaExceededError +}); + +analyticsPlugin({ + onFlush: (events) => sendToAnalytics(events), + onError: (error) => report('analytics flush failed', error) // onFlush threw or rejected +}); +``` + +--- + ### Can I combine multiple plugins? **Yes!** Plugins are composed via the `plugins` array. They run independently and don't interfere with each other: diff --git a/README.md b/README.md index 75ee5c8..283488b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20-green.svg)](https://nodejs.org/) [![Svelte 5](https://img.shields.io/badge/Svelte-5-orange.svg)](https://svelte.dev/) [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC) -[![Tests](https://img.shields.io/badge/tests-500%2B-brightgreen.svg)](<>) +[![Tests](https://img.shields.io/badge/tests-600%2B-brightgreen.svg)](<>) [![Coverage](https://img.shields.io/badge/coverage-%3E98%25-brightgreen.svg)](<>) > **Deep reactive proxy with validation, snapshot/undo, side effects, and plugins — built for complex, real-world applications.** @@ -413,18 +413,62 @@ const { data } = createSvState(formData, actuators, { }); ``` -| Option | Default | Description | -| ------------------------------- | ------- | ------------------------------------------ | -| `resetDirtyOnAction` | `true` | Clear dirty flag after successful action | -| `debounceValidation` | `0` | Delay sync validation (0 = next microtask) | -| `allowConcurrentActions` | `false` | Block execute() while action runs | -| `persistActionError` | `false` | Clear error on next change or action | -| `debounceAsyncValidation` | `300` | Delay async validation in ms | -| `runAsyncValidationOnInit` | `false` | Run async validators on creation | -| `clearAsyncErrorsOnChange` | `true` | Clear async error when property changes | -| `maxConcurrentAsyncValidations` | `4` | Max concurrent async validators | -| `maxSnapshots` | `50` | Max snapshots to keep (0 = unlimited) | -| `plugins` | `[]` | Array of plugins to extend behavior | +| Option | Default | Description | +| ------------------------------- | --------------- | --------------------------------------------------------------- | +| `resetDirtyOnAction` | `true` | Clear dirty flag after successful action | +| `debounceValidation` | `0` | Delay sync validation (0 = next microtask) | +| `allowConcurrentActions` | `false` | Block execute() while action runs | +| `persistActionError` | `false` | Clear error on next change or action | +| `debounceAsyncValidation` | `300` | Delay async validation in ms | +| `runAsyncValidationOnInit` | `false` | Run async validators on creation | +| `clearAsyncErrorsOnChange` | `true` | Clear async error when property changes | +| `maxConcurrentAsyncValidations` | `4` | Max concurrent async validators | +| `maxSnapshots` | `50` | Max snapshots to keep (0 = unlimited) | +| `onPluginError` | `console.error` | Called as `(error, pluginName, hook)` when a plugin hook throws | +| `plugins` | `[]` | Array of plugins to extend behavior | + +#### Validating before submit + +Validation is deferred (a microtask by default, or `debounceValidation` ms), so the `errors` store may lag a mutation that just happened. Call `validate()` to force a synchronous pass and get the result directly: + +```typescript +const { data, validate, execute } = createSvState(form, { validator, action }); + +function submit() { + const { hasErrors } = validate(); + if (hasErrors) return; + execute(); +} +``` + +#### Applying many changes at once + +`batch()` applies a group of mutations as one unit — validation runs once at the end, each async validator is scheduled at most once, and the whole group produces a single snapshot (one undo point): + +```typescript +batch((draft) => { + draft.firstName = 'Ada'; + draft.lastName = 'Lovelace'; + draft.address.city = 'London'; +}); + +rollback(); // undoes all three at once +``` + +`effect` and plugin `onChange` still fire once per mutation, so per-property side effects keep working. + +#### Handling plugin errors + +A throwing plugin hook is isolated — it doesn't abort the mutation or block later plugins. It's caught and reported through `onPluginError`, which defaults to `console.error`: + +```typescript +const { data } = createSvState(formData, actuators, { + plugins: [thirdPartyPlugin, devtoolsPlugin()], + onPluginError: (error, pluginName, hook) => { + report(`plugin "${pluginName}" failed in ${hook}`, error); + } +}); +``` --- @@ -525,7 +569,8 @@ const persist = persistPlugin({ version: 1, // Schema version (default: 1) migrate: (data, v) => data, // Migration on version mismatch include: ['name', 'email'], // Only persist these paths - exclude: ['password'] // Exclude these paths + exclude: ['password'], // Exclude these paths + onError: (error) => report(error) // Storage write failures (e.g. quota exceeded) }); // Extra methods: @@ -533,6 +578,8 @@ persist.isRestored(); // Was state hydrated from storage? persist.clearPersistedState(); // Remove stored data ``` +Restored state becomes the baseline: after hydration `isDirty` is `false` and `reset()` returns to the restored values, not to the defaults passed to `createSvState`. + **`autosavePlugin`** — Auto-save after idle period or on interval. ```typescript @@ -576,13 +623,18 @@ const history = historyPlugin({ fields: { search: 'q', page: 'p' }, // { stateField: 'urlParam' } mode: 'replace', // 'push' | 'replace' (default: 'replace') serialize: (value) => String(value), - deserialize: (param) => param + deserialize: (param) => param, + onError: (error) => report(error) // serialize/deserialize threw }); // Extra method: history.syncFromUrl(); // Manually re-read URL into state ``` +> **Nested fields:** field keys may be dot-notation paths (`{ 'filters.q': 'q' }`). Matching works in both +> directions — replacing the parent (`data.filters = {...}`) and mutating the leaf (`data.filters.q = '…'`) +> both update the URL, and a registered parent (`{ filters: 'f' }`) is updated when any of its children change. + **`syncPlugin`** — Sync state across browser tabs via BroadcastChannel. ```typescript @@ -591,7 +643,8 @@ import { syncPlugin } from 'svstate'; const sync = syncPlugin({ key: 'my-form-sync', // Required: channel name throttle: 100, // Broadcast debounce ms (default: 100) - merge: 'overwrite' // 'overwrite' | 'ignore' (default: 'overwrite') + merge: 'overwrite', // 'overwrite' | 'ignore' (default: 'overwrite') + onError: (error) => report(error) // State could not be serialized or posted }); // Extra method: @@ -625,7 +678,8 @@ analyticsPlugin({ batchSize: 20, // Flush at N events (default: 20) flushInterval: 5000, // Periodic flush ms (default: 5000) include: ['change', 'action'], // Filter event types - redact: ['password', 'creditCard'] // Replace values for these paths with '[redacted]' + redact: ['password', 'creditCard'], // Replace values for these paths (and everything below) with '[redacted]' + onError: (error) => report(error) // onFlush threw or rejected }); ``` @@ -1032,25 +1086,27 @@ Creates a supercharged state object. **Returns:** -| Property | Type | Description | -| ------------------------- | ---------------------------- | ------------------------------------------------------ | -| `data` | `T` | Deep reactive proxy — bind directly, methods preserved | -| `execute(params?)` | `(P?) => Promise` | Run the configured action | -| `rollback(steps?)` | `(n?: number) => void` | Undo N changes (default: 1) | -| `rollbackTo(title)` | `(title: string) => boolean` | Roll back to last snapshot with matching title | -| `reset()` | `() => void` | Return to initial state | -| `destroy()` | `() => void` | Cleanup plugins and cancel async validations | -| `state.errors` | `Readable` | Sync validation errors store | -| `state.hasErrors` | `Readable` | Has sync errors? | -| `state.isDirty` | `Readable` | Has state changed? (derived from `isDirtyByField`) | -| `state.isDirtyByField` | `Readable` | Per-field dirty tracking (dot-notation paths) | -| `state.actionInProgress` | `Readable` | Is action running? | -| `state.actionError` | `Readable` | Last action error | -| `state.snapshots` | `Readable` | Undo history | -| `state.asyncErrors` | `Readable` | Async validation errors (keyed by path) | -| `state.hasAsyncErrors` | `Readable` | Has async errors? | -| `state.asyncValidating` | `Readable` | Paths currently validating | -| `state.hasCombinedErrors` | `Readable` | Has sync OR async errors? | +| Property | Type | Description | +| ------------------------- | ------------------------------ | --------------------------------------------------------------- | +| `data` | `T` | Deep reactive proxy — bind directly, methods preserved | +| `execute(params?)` | `(P?) => Promise` | Run the configured action | +| `rollback(steps?)` | `(n?: number) => void` | Undo N changes (default: 1) | +| `rollbackTo(title)` | `(title: string) => boolean` | Roll back to last snapshot with matching title | +| `reset()` | `() => void` | Return to initial state | +| `validate()` | `() => ValidationResult` | Run sync validation now, returns `{ errors, hasErrors }` | +| `batch(fn)` | `((draft: T) => void) => void` | Apply many mutations as one unit (one validation, one snapshot) | +| `destroy()` | `() => void` | Cleanup plugins and cancel async validations | +| `state.errors` | `Readable` | Sync validation errors store | +| `state.hasErrors` | `Readable` | Has sync errors? | +| `state.isDirty` | `Readable` | Has state changed? (derived from `isDirtyByField`) | +| `state.isDirtyByField` | `Readable` | Per-field dirty tracking (dot-notation paths) | +| `state.actionInProgress` | `Readable` | Is action running? | +| `state.actionError` | `Readable` | Last action error | +| `state.snapshots` | `Readable` | Undo history | +| `state.asyncErrors` | `Readable` | Async validation errors (keyed by path) | +| `state.hasAsyncErrors` | `Readable` | Has async errors? | +| `state.asyncValidating` | `Readable` | Paths currently validating | +| `state.hasCombinedErrors` | `Readable` | Has sync OR async errors? | ### Built-in Validators @@ -1076,6 +1132,7 @@ import type { Snapshot, SnapshotFunction, SvStateOptions, + ValidationResult, AsyncValidator, AsyncValidatorFunction, AsyncErrors, @@ -1083,6 +1140,7 @@ import type { SvStatePlugin, PluginContext, PluginStores, + PluginHook, ChangeEvent, ActionEvent } from 'svstate'; @@ -1095,6 +1153,7 @@ import type { | `SnapshotFunction` | Type for the `snapshot(title, shouldReplace?)` function used in effects | | `Snapshot` | Shape of a snapshot entry: `{ title: string; data: T }` | | `SvStateOptions` | Configuration options type for `createSvState` | +| `ValidationResult` | Return type of `validate()`: `{ errors, hasErrors }` | | `AsyncValidator` | Object mapping property paths to async validator functions | | `AsyncValidatorFunction` | Async function: `(value, source, signal) => Promise` | | `AsyncErrors` | Object mapping property paths to error strings | @@ -1102,6 +1161,7 @@ import type { | `SvStatePlugin` | Plugin interface with lifecycle hooks (`onInit`, `onChange`, `onAction`, etc.) | | `PluginContext` | Context passed to `onInit`: `{ data, state, options, snapshot }` | | `PluginStores` | All readable stores exposed to plugins | +| `PluginHook` | Hook name passed to `onPluginError`, e.g. `'onChange'` | | `ChangeEvent` | Payload for `onChange`: `{ target, property, currentValue, oldValue }` | | `ActionEvent` | Payload for `onAction`: `{ phase, params?, error? }` | diff --git a/STORES-vs-RUNES.md b/STORES-vs-RUNES.md index 949613b..20edb15 100644 --- a/STORES-vs-RUNES.md +++ b/STORES-vs-RUNES.md @@ -4,7 +4,7 @@ The library already uses a **hybrid approach**: -- `$state()` for the reactive data object (line 86) +- `$state()` for the reactive data object (`src/state.svelte.ts`, `stateObject`) - Svelte stores (`writable`, `derived`) for metadata: errors, hasErrors, isDirty, actionInProgress, actionError, snapshots ```typescript diff --git a/demo/package.json b/demo/package.json index dfe96f5..c902f2d 100644 --- a/demo/package.json +++ b/demo/package.json @@ -12,7 +12,7 @@ "build": "vite build", "ts:check": "svelte-check --tsconfig ./tsconfig.json", "format:check": "prettier --check .", - "format:fix": "prettier --write . | grep -v 'unchanged' | sed G", + "format:fix": "prettier --write --list-different .", "lint:check": "eslint .", "lint:fix": "eslint --fix .", "npm:reinstall": "rm -rf ./node_modules && rm -f ./package-lock.json && npm i && npm i", diff --git a/demo/src/components/DemoSidebar.svelte b/demo/src/components/DemoSidebar.svelte index b149c68..f88adbf 100644 --- a/demo/src/components/DemoSidebar.svelte +++ b/demo/src/components/DemoSidebar.svelte @@ -1,4 +1,6 @@
@@ -49,4 +52,6 @@ > Fill with Valid Data + + {@render extra?.()}
diff --git a/demo/src/components/Spinner.svelte b/demo/src/components/Spinner.svelte new file mode 100644 index 0000000..c847f3d --- /dev/null +++ b/demo/src/components/Spinner.svelte @@ -0,0 +1,16 @@ + + + + + + diff --git a/demo/src/lib/utilities.ts b/demo/src/lib/utilities.ts index 000b07d..53fcf4a 100644 --- a/demo/src/lib/utilities.ts +++ b/demo/src/lib/utilities.ts @@ -1,3 +1,6 @@ export const randomId = () => Math.random().toString(36).slice(2, 8); export const randomInt = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min; + +export const formatFieldName = (property: string) => + property.charAt(0).toUpperCase() + property.slice(1).replaceAll(/([A-Z])/g, ' $1'); diff --git a/demo/src/pages/ActionDemo.svelte b/demo/src/pages/ActionDemo.svelte index 58c1526..47fbe11 100644 --- a/demo/src/pages/ActionDemo.svelte +++ b/demo/src/pages/ActionDemo.svelte @@ -6,6 +6,7 @@ import FormField from '$components/FormField.svelte'; import PageLayout from '$components/PageLayout.svelte'; import SourceCodeSection from '$components/SourceCodeSection.svelte'; + import Spinner from '$components/Spinner.svelte'; import StatusBadges from '$components/StatusBadges.svelte'; import { randomId, randomInt } from '$lib/utilities'; @@ -19,6 +20,7 @@ const { data, + batch, execute, state: { errors, hasErrors, isDirty, actionInProgress, actionError } } = createSvState(sourceData, { @@ -45,8 +47,10 @@ }); const fillWithValidData = () => { - data.title = `Task ${randomId()}`; - data.description = `This is a sample task description with ID ${randomId()}`; + batch((draft) => { + draft.title = `Task ${randomId()}`; + draft.description = `This is a sample task description with ID ${randomId()}`; + }); }; const handleSubmit = () => { @@ -57,7 +61,7 @@ // ───────────────────────────────────────────── // Source code examples for the collapsible section // ───────────────────────────────────────────── - const stateSourceCode = `const { data, execute, state: { errors, hasErrors, isDirty, actionInProgress, actionError } } = + const stateSourceCode = `const { data, batch, execute, state: { errors, hasErrors, isDirty, actionInProgress, actionError } } = createSvState(sourceData, { validator: (source) => ({ title: stringValidator(source.title).prepare('trim').required().minLength(3).maxLength(50).getError(), @@ -78,6 +82,14 @@ } });`; + const batchSourceCode = `// One validation pass for the whole fill +const fillWithValidData = () => { + batch((draft) => { + draft.title = 'Task 1'; + draft.description = 'A sample task description.'; + }); +};`; + const executeSourceCode = `// Execute the action - + + {#snippet extra()} +
+
Quick Fill
+ +
-
-
Async Validation State
-
-
asyncValidating: [{$asyncValidating.join(', ')}]
-
hasAsyncErrors: {$hasAsyncErrors}
-
hasCombinedErrors: {$hasCombinedErrors}
+
+
Async Validation State
+
+
asyncValidating: [{$asyncValidating.join(', ')}]
+
hasAsyncErrors: {$hasAsyncErrors}
+
hasCombinedErrors: {$hasCombinedErrors}
+
-
-
-
Async Errors
-
{JSON.stringify($asyncErrors, undefined, 2)}
-
-
+
+
Async Errors
+
{JSON.stringify($asyncErrors, undefined, 2)}
+
+ {/snippet} +
{/snippet} {#snippet sourceCode()} + diff --git a/demo/src/pages/BasicValidation.svelte b/demo/src/pages/BasicValidation.svelte index 42cc520..38194e1 100644 --- a/demo/src/pages/BasicValidation.svelte +++ b/demo/src/pages/BasicValidation.svelte @@ -22,6 +22,7 @@ const { data, + batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => ({ @@ -40,11 +41,13 @@ }); const fillWithValidData = () => { - data.username = `user${randomId()}`; - data.email = `${randomId()}@example.com`; - data.age = randomInt(18, 65); - data.bio = 'Hello, I am a demo user!'; - data.website = `https://${randomId()}.com`; + batch((draft) => { + draft.username = `user${randomId()}`; + draft.email = `${randomId()}@example.com`; + draft.age = randomInt(18, 65); + draft.bio = 'Hello, I am a demo user!'; + draft.website = `https://${randomId()}.com`; + }); }; // ───────────────────────────────────────────── @@ -58,7 +61,7 @@ website: '' }; -const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => ({ username: stringValidator(source.username).prepare('trim').required().minLength(3).maxLength(20).noSpace().getError(), email: stringValidator(source.email).prepare('trim').required().email().getError(), @@ -68,6 +71,18 @@ const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSv }) });`; + const batchSourceCode = `// batch() applies many mutations as one unit: +// one validation pass instead of five +const fillWithValidData = () => { + batch((draft) => { + draft.username = 'user123'; + draft.email = 'user123@example.com'; + draft.age = 30; + draft.bio = 'Hello, I am a demo user!'; + draft.website = 'https://user123.com'; + }); +};`; + const formSourceCode = ` + {/snippet} diff --git a/demo/src/pages/CalculatedClass.svelte b/demo/src/pages/CalculatedClass.svelte index 54ea89f..e210596 100644 --- a/demo/src/pages/CalculatedClass.svelte +++ b/demo/src/pages/CalculatedClass.svelte @@ -48,6 +48,7 @@ const { data, + batch, state: { errors, hasErrors, isDirty } } = createSvState(createSourceData(), { validator: (source) => ({ @@ -63,9 +64,11 @@ }); const fillWithValidData = () => { - data.productName = `Widget ${randomId()}`; - data.item.unitPrice = randomInt(10, 100); - data.item.quantity = randomInt(1, 10); + batch((draft) => { + draft.productName = `Widget ${randomId()}`; + draft.item.unitPrice = randomInt(10, 100); + draft.item.quantity = randomInt(1, 10); + }); }; // ───────────────────────────────────────────── @@ -103,7 +106,7 @@ const createSourceData = (): SourceData => ({ } });`; - const stateSourceCode = `const { data, state: { errors, hasErrors, isDirty } } = createSvState(createSourceData(), { + const stateSourceCode = `const { data, batch, state: { errors, hasErrors, isDirty } } = createSvState(createSourceData(), { validator: (source) => ({ productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), item: { @@ -118,6 +121,13 @@ const createSourceData = (): SourceData => ({ } });`; + const batchSourceCode = `// One validation pass for the whole fill +batch((draft) => { + draft.productName = 'Widget'; + draft.item.unitPrice = 42; + draft.item.quantity = 3; +});`; + const templateSourceCode = ` {data.formatCurrency(data.subtotal)} {data.formatTotal()}`; @@ -200,6 +210,7 @@ const createSourceData = (): SourceData => ({ + {/snippet} diff --git a/demo/src/pages/CalculatedFields.svelte b/demo/src/pages/CalculatedFields.svelte index 4cf97bd..5631711 100644 --- a/demo/src/pages/CalculatedFields.svelte +++ b/demo/src/pages/CalculatedFields.svelte @@ -27,6 +27,7 @@ const { data, + batch, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { validator: (source) => ({ @@ -46,9 +47,11 @@ }); const fillWithValidData = () => { - data.productName = `Widget ${randomId()}`; - data.item.unitPrice = randomInt(10, 100); - data.item.quantity = randomInt(1, 10); + batch((draft) => { + draft.productName = `Widget ${randomId()}`; + draft.item.unitPrice = randomInt(10, 100); + draft.item.quantity = randomInt(1, 10); + }); }; const formatCurrency = (value: number) => `$${value.toFixed(2)}`; @@ -64,7 +67,7 @@ const TAX_RATE = 0.08; -const { data, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { validator: (source) => ({ productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), item: { @@ -81,6 +84,14 @@ const { data, state: { errors, hasErrors, isDirty } } = createSvState(sourceData } });`; + const batchSourceCode = `// One validation pass for the whole fill; +// effect still recalculates the totals on each field it touches +batch((draft) => { + draft.productName = 'Widget'; + draft.item.unitPrice = 42; + draft.item.quantity = 3; +});`; + const effectSourceCode = `effect: ({ property }) => { if (property === 'item.unitPrice' || property === 'item.quantity') { data.subtotal = data.item.unitPrice * data.item.quantity; @@ -162,6 +173,7 @@ const { data, state: { errors, hasErrors, isDirty } } = createSvState(sourceData + {/snippet} diff --git a/demo/src/pages/NestedObjects.svelte b/demo/src/pages/NestedObjects.svelte index ca9b95b..7683963 100644 --- a/demo/src/pages/NestedObjects.svelte +++ b/demo/src/pages/NestedObjects.svelte @@ -32,6 +32,7 @@ const { data, + batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => ({ @@ -53,14 +54,16 @@ }); const fillWithValidData = () => { - data.name = `John ${randomId()}`; - data.address.street = `${randomInt(100, 9999)} Main Street`; - data.address.city = 'New York'; - data.address.zip = String(randomInt(10_000, 99_999)); - data.company.name = `Acme ${randomId()} Inc`; - data.company.department = 'Engineering'; - data.company.contact.phone = `555-${randomInt(100, 999)}-${randomInt(1000, 9999)}`; - data.company.contact.email = `contact@${randomId()}.com`; + batch((draft) => { + draft.name = `John ${randomId()}`; + draft.address.street = `${randomInt(100, 9999)} Main Street`; + draft.address.city = 'New York'; + draft.address.zip = String(randomInt(10_000, 99_999)); + draft.company.name = `Acme ${randomId()} Inc`; + draft.company.department = 'Engineering'; + draft.company.contact.phone = `555-${randomInt(100, 999)}-${randomInt(1000, 9999)}`; + draft.company.contact.email = `contact@${randomId()}.com`; + }); }; // ───────────────────────────────────────────── @@ -76,7 +79,7 @@ } }; -const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => ({ name: stringValidator(source.name).prepare('trim').required().minLength(2).maxLength(50).getError(), address: { @@ -95,6 +98,16 @@ const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSv }) });`; + const batchSourceCode = `// batch() runs validation once for the whole nested fill, +// instead of once per touched field (8 fields here) +batch((draft) => { + draft.name = 'John Doe'; + draft.address.street = '123 Main Street'; + draft.address.city = 'New York'; + draft.company.contact.email = 'contact@acme.com'; + // ... +});`; + const formSourceCode = ` @@ -226,6 +239,7 @@ const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSv {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/OptionsDemo.svelte b/demo/src/pages/OptionsDemo.svelte index af9eab5..20a951b 100644 --- a/demo/src/pages/OptionsDemo.svelte +++ b/demo/src/pages/OptionsDemo.svelte @@ -6,6 +6,7 @@ import FormField from '$components/FormField.svelte'; import PageLayout from '$components/PageLayout.svelte'; import SourceCodeSection from '$components/SourceCodeSection.svelte'; + import Spinner from '$components/Spinner.svelte'; import StatusBadges from '$components/StatusBadges.svelte'; import { randomId, randomInt } from '$lib/utilities'; @@ -19,6 +20,7 @@ let simulateError = $state(false); let lastActionResult = $state(); let lastChangedProperty = $state(); + let validateResult = $state(); const getInitialData = () => ({ name: `User ${randomId()}`, @@ -70,6 +72,7 @@ const handleOptionsChange = () => { lastChangedProperty = undefined; lastActionResult = undefined; + validateResult = undefined; stateInstance = createState({ resetDirtyOnAction, debounceValidation, @@ -86,8 +89,10 @@ const actionError = $derived(stateInstance.state.actionError); const fillWithValidData = () => { - stateInstance.data.name = `User ${randomId()}`; - stateInstance.data.email = `${randomId()}@example.com`; + stateInstance.batch((draft) => { + draft.name = `User ${randomId()}`; + draft.email = `${randomId()}@example.com`; + }); }; const handleSubmit = () => { @@ -95,6 +100,14 @@ stateInstance.execute(); }; + const handleValidateNow = () => { + const result = stateInstance.validate(); + const errorCount = Object.values(result.errors ?? {}).filter(Boolean).length; + validateResult = result.hasErrors + ? `Validated immediately — ${errorCount} field(s) have errors` + : 'Validated immediately — all fields valid'; + }; + // ───────────────────────────────────────────── // Source code examples // ───────────────────────────────────────────── @@ -128,6 +141,11 @@ await execute(); // Validation runs 500ms after the last change // Useful for expensive validators or rapid typing`; + const validateSourceCode = `// validate() runs sync validation immediately, bypassing the debounce +const { errors, hasErrors } = validate(); + +// Useful right before submitting, even with a long debounceValidation`; + const persistErrorSourceCode = `// With persistActionError: false (default) data.name = 'new value'; // actionError is cleared immediately @@ -224,14 +242,7 @@ data.name = 'new value'; > {#if $actionInProgress} - - - - + Submitting... {:else} @@ -243,80 +254,90 @@ data.name = 'new value'; {/snippet} {#snippet sidebar()} -
- - -
-
Options
- -
-
-
- - + + {#snippet extra()} +
+
Options
+ +
+
+
+ + +
+

Reset isDirty after successful action

-

Reset isDirty after successful action

-
-
- - -

Try 500ms and type quickly

-
- -
-
+
+ - +

Try 500ms and type quickly

+ + {#if validateResult} +

{validateResult}

+ {/if} +
+ +
+
+ + +
+

Keep errors until next action

-

Keep errors until next action

-
- + +
-
-
-
Current Options
-
-
resetDirtyOnAction: {resetDirtyOnAction}
-
debounceValidation: {debounceValidation}
-
persistActionError: {persistActionError}
+
+
Current Options
+
+
resetDirtyOnAction: {resetDirtyOnAction}
+
debounceValidation: {debounceValidation}
+
persistActionError: {persistActionError}
+
-
-
+ {/snippet} + {/snippet} {#snippet sourceCode()} @@ -324,6 +345,7 @@ data.name = 'new value'; + {/snippet} diff --git a/demo/src/pages/PluginAutosaveAnalytics.svelte b/demo/src/pages/PluginAutosaveAnalytics.svelte index 95599f0..d4e2054 100644 --- a/demo/src/pages/PluginAutosaveAnalytics.svelte +++ b/demo/src/pages/PluginAutosaveAnalytics.svelte @@ -10,7 +10,7 @@ import PageLayout from '$components/PageLayout.svelte'; import SourceCodeSection from '$components/SourceCodeSection.svelte'; import StatusBadges from '$components/StatusBadges.svelte'; - import { randomId } from '$lib/utilities'; + import { formatFieldName, randomId } from '$lib/utilities'; type SaveLogEntry = { id: string; timestamp: string; data: string }; type FlushLogEntry = { id: string; timestamp: string; eventCount: number; types: string }; @@ -18,6 +18,7 @@ let saveLog = $state([]); let flushLog = $state([]); let bufferedCount = $state(0); + let lastAnalyticsError = $state(); const autosave = autosavePlugin<{ title: string; category: string; notes: string }>({ save: async (d) => { @@ -41,11 +42,15 @@ }, batchSize: 10, flushInterval: 10_000, - include: ['change', 'action', 'snapshot'] + include: ['change', 'action', 'snapshot'], + onError: (error) => { + lastAnalyticsError = error instanceof Error ? error.message : String(error); + } }); const { data, + batch, execute, reset, state: { errors, hasErrors, isDirty, actionInProgress } @@ -58,8 +63,7 @@ notes: stringValidator(source.notes).maxLength(500).getError() }), effect: ({ snapshot, property }) => { - const label = property.charAt(0).toUpperCase() + property.slice(1); - snapshot(`Changed ${label}`); + snapshot(`Changed ${formatFieldName(property)}`); }, action: async () => { await new Promise((resolve) => setTimeout(resolve, 500)); @@ -69,9 +73,11 @@ ); const fillWithValidData = () => { - data.title = `Article ${randomId()}`; - data.category = 'tech'; - data.notes = 'Some interesting notes about the topic that should pass validation.'; + batch((draft) => { + draft.title = `Article ${randomId()}`; + draft.category = 'tech'; + draft.notes = 'Some interesting notes about the topic that should pass validation.'; + }); }; $effect(() => { @@ -100,7 +106,10 @@ const analytics = analyticsPlugin({ }, batchSize: 10, // Flush after 10 events flushInterval: 10000, // Or every 10 seconds - include: ['change', 'action', 'snapshot'] // Filter event types + include: ['change', 'action', 'snapshot'], // Filter event types + onError: (error) => { + console.error('Analytics flush failed:', error); + } }); const { data, execute, state } = createSvState( @@ -108,6 +117,14 @@ const { data, execute, state } = createSvState( { plugins: [autosave, analytics] } );`; + const batchSourceCode = `// One validation pass, one buffered analytics 'change' event per +// field (still per-mutation), but a single snapshot for the fill +batch((draft) => { + draft.title = 'Article Title'; + draft.category = 'tech'; + draft.notes = 'Some notes.'; +});`; + const apiSourceCode = `// autosavePlugin API autosave.saveNow(); // Force immediate save autosave.isSaving(); // Check if currently saving @@ -213,75 +230,80 @@ analytics.eventCount(); // Number of buffered events`; {/snippet} {#snippet sidebar()} -
- - -
-
Autosave Log
- {#if saveLog.length === 0} -

No saves yet — edit the form and wait 2s

- {:else} -
    - {#each saveLog as entry (entry.id)} -
  • - - save - - {entry.data} - {entry.timestamp} -
  • - {/each} -
- {/if} -
+ + {#snippet extra()} +
+
Autosave Log
+ {#if saveLog.length === 0} +

No saves yet — edit the form and wait 2s

+ {:else} +
    + {#each saveLog as entry (entry.id)} +
  • + + save + + {entry.data} + {entry.timestamp} +
  • + {/each} +
+ {/if} +
-
-
Analytics Buffer
-
-
Buffered: {bufferedCount} event{bufferedCount === 1 ? '' : 's'}
-
Batch size: 10
-
Flush interval: 10s
-
Tracked: change, action, snapshot
+
+
Analytics Buffer
+
+
Buffered: {bufferedCount} event{bufferedCount === 1 ? '' : 's'}
+
Batch size: 10
+
Flush interval: 10s
+
Tracked: change, action, snapshot
+
+ Last onError: + {lastAnalyticsError ?? 'none'} +
+
-
-
-
Flush History
- {#if flushLog.length === 0} -

No flushes yet

- {:else} -
    - {#each flushLog as entry (entry.id)} -
  • - - flush - - - {entry.eventCount} event{entry.eventCount === 1 ? '' : 's'} ({entry.types}) - - {entry.timestamp} -
  • - {/each} -
- {/if} -
-
+
+
Flush History
+ {#if flushLog.length === 0} +

No flushes yet

+ {:else} +
    + {#each flushLog as entry (entry.id)} +
  • + + flush + + + {entry.eventCount} event{entry.eventCount === 1 ? '' : 's'} ({entry.types}) + + {entry.timestamp} +
  • + {/each} +
+ {/if} +
+ {/snippet} +
{/snippet} {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/PluginDevtools.svelte b/demo/src/pages/PluginDevtools.svelte index bbb37e9..4e35064 100644 --- a/demo/src/pages/PluginDevtools.svelte +++ b/demo/src/pages/PluginDevtools.svelte @@ -10,7 +10,7 @@ import PageLayout from '$components/PageLayout.svelte'; import SourceCodeSection from '$components/SourceCodeSection.svelte'; import StatusBadges from '$components/StatusBadges.svelte'; - import { randomId } from '$lib/utilities'; + import { formatFieldName, randomId } from '$lib/utilities'; type LogEntry = { id: string; @@ -20,6 +20,8 @@ }; let logEntries = $state([]); + let simulatePluginError = $state(false); + let lastPluginError = $state(); const addLog = (type: LogEntry['type'], message: string) => { const timestamp = new Date().toISOString().slice(11, 23); @@ -31,6 +33,7 @@ const logMirrorPlugin: SvStatePlugin = { name: 'log-mirror', onChange(event: ChangeEvent) { + if (simulatePluginError) throw new Error(`Simulated failure while mirroring "${event.property}"`); addLog('change', `${event.property}: "${event.oldValue}" → "${event.currentValue}"`); }, onValidation(errors) { @@ -53,6 +56,7 @@ const { data, + batch, execute, reset, rollback, @@ -66,22 +70,26 @@ message: stringValidator(source.message).prepare('trim').required().minLength(5).getError() }), effect: ({ snapshot, property }) => { - const label = property.charAt(0).toUpperCase() + property.slice(1); - snapshot(`Changed ${label}`); + snapshot(`Changed ${formatFieldName(property)}`); }, action: async () => { await new Promise((resolve) => setTimeout(resolve, 500)); } }, { - plugins: [devtoolsPlugin({ name: 'demo-devtools', enabled: true, logValidation: true }), logMirrorPlugin] + plugins: [devtoolsPlugin({ name: 'demo-devtools', enabled: true, logValidation: true }), logMirrorPlugin], + onPluginError: (error, pluginName, hook) => { + lastPluginError = `[${pluginName}/${hook}] ${error instanceof Error ? error.message : String(error)}`; + } } ); const fillWithValidData = () => { - data.name = `John Doe ${randomId()}`; - data.email = `john.${randomId()}@example.com`; - data.message = 'Hello, this is a test message for the devtools demo.'; + batch((draft) => { + draft.name = `John Doe ${randomId()}`; + draft.email = `john.${randomId()}@example.com`; + draft.message = 'Hello, this is a test message for the devtools demo.'; + }); }; const clearLog = () => { @@ -127,6 +135,15 @@ const { data, execute, reset, rollback, state } = createSvState( // - onAction: action start/complete/error // - onRollback: rollback with target snapshot title // - onReset: state reset events`; + + const pluginErrorSourceCode = `// A throwing plugin hook no longer aborts the mutation or blocks +// later plugins — it's caught and reported via onPluginError. +createSvState(sourceData, actuators, { + plugins: [devtoolsPlugin(), logMirrorPlugin], + onPluginError: (error, pluginName, hook) => { + console.error(\`Plugin "\${pluginName}" failed in \${hook}:\`, error); + } +});`;
+
+ + +
+
+
+ {#if logEntries.length === 0} +

No events yet — interact with the form

+ {:else} +
    + {#each logEntries as entry (entry.id)} +
  • + + {entry.type} + + {entry.message} + {entry.timestamp} +
  • + {/each} +
+ {/if} +
-
-
-
Event Log
- +
+
onPluginError
+ {#if lastPluginError} +

{lastPluginError}

+ {:else} +

No plugin errors caught yet

+ {/if}
- {#if logEntries.length === 0} -

No events yet — interact with the form

- {:else} -
    - {#each logEntries as entry (entry.id)} -
  • - - {entry.type} - - {entry.message} - {entry.timestamp} -
  • - {/each} -
- {/if} -
-
+ {/snippet} + {/snippet} {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/PluginPersistSync.svelte b/demo/src/pages/PluginPersistSync.svelte index 58c088e..81e42d8 100644 --- a/demo/src/pages/PluginPersistSync.svelte +++ b/demo/src/pages/PluginPersistSync.svelte @@ -17,10 +17,15 @@ notifications: boolean; }; + let lastPersistError = $state(); + const persist = persistPlugin({ key: 'svstate-demo-settings', throttle: 300, - exclude: ['notifications'] + exclude: ['notifications'], + onError: (error) => { + lastPersistError = error instanceof Error ? error.message : String(error); + } }); const sync = syncPlugin({ @@ -30,6 +35,7 @@ const { data, + batch, reset, state: { errors, hasErrors, isDirty } } = createSvState( @@ -53,10 +59,12 @@ }; const fillWithValidData = () => { - data.username = 'demo_user'; - data.theme = 'dark'; - data.fontSize = 16; - data.notifications = false; + batch((draft) => { + draft.username = 'demo_user'; + draft.theme = 'dark'; + draft.fontSize = 16; + draft.notifications = false; + }); }; let storedJson = $state(''); @@ -79,7 +87,10 @@ const persist = persistPlugin({ key: 'svstate-demo-settings', throttle: 300, - exclude: ['notifications'] // Don't persist this field + exclude: ['notifications'], // Don't persist this field + onError: (error) => { + console.error('Failed to persist state:', error); + } }); const sync = syncPlugin({ @@ -93,6 +104,13 @@ const { data, reset, state } = createSvState( { plugins: [persist, sync] } );`; + const batchSourceCode = `// One validation pass, one persisted write, for the whole fill +batch((draft) => { + draft.username = 'demo_user'; + draft.theme = 'dark'; + draft.fontSize = 16; +});`; + const apiSourceCode = `// persistPlugin API persist.isRestored(); // true if data was loaded from storage persist.clearPersistedState(); // Remove stored data @@ -181,44 +199,49 @@ persist.clearPersistedState(); // Remove stored data {/snippet} {#snippet sidebar()} -
- - -
-
Persistence Info
-
-
Restored: {isRestored}
-
Key: svstate-demo-settings
-
Excluded: notifications
+ + {#snippet extra()} +
+
Persistence Info
+
+
Restored: {isRestored}
+
Key: svstate-demo-settings
+
Excluded: notifications
+
+ Last onError: + {lastPersistError ?? 'none'} +
+
-
-
-
Raw localStorage
-
{storedJson}
-
+
+
Raw localStorage
+
{storedJson}
+
-
-
Sync Info
-
-
Channel: svstate-demo-sync
-
Throttle: 200ms
-
Merge: overwrite (default)
+
+
Sync Info
+
+
Channel: svstate-demo-sync
+
Throttle: 200ms
+
Merge: overwrite (default)
+
-
-
+ {/snippet} + {/snippet} {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/PluginUndoRedo.svelte b/demo/src/pages/PluginUndoRedo.svelte index dd36988..20e46c9 100644 --- a/demo/src/pages/PluginUndoRedo.svelte +++ b/demo/src/pages/PluginUndoRedo.svelte @@ -11,7 +11,7 @@ import PageLayout from '$components/PageLayout.svelte'; import SourceCodeSection from '$components/SourceCodeSection.svelte'; import StatusBadges from '$components/StatusBadges.svelte'; - import { randomId } from '$lib/utilities'; + import { formatFieldName, randomId } from '$lib/utilities'; const undoRedo = undoRedoPlugin<{ title: string; @@ -19,12 +19,9 @@ priority: string; }>(); - const formatFieldName = (property: string) => { - return property.charAt(0).toUpperCase() + property.slice(1).replaceAll(/([A-Z])/g, ' $1'); - }; - const { data, + batch, reset, rollback, state: { errors, hasErrors, isDirty, snapshots } @@ -44,9 +41,11 @@ ); const fillWithValidData = () => { - data.title = `Project Report ${randomId()}`; - data.content = 'This is a detailed document with enough content to pass validation requirements.'; - data.priority = 'high'; + batch((draft) => { + draft.title = `Project Report ${randomId()}`; + draft.content = 'This is a detailed document with enough content to pass validation requirements.'; + draft.priority = 'high'; + }); }; let redoStack = $state(get(undoRedo.redoStack)); @@ -73,6 +72,14 @@ const { data, reset, rollback, state } = createSvState( { maxSnapshots: 10, plugins: [undoRedo] } );`; + const batchSourceCode = `// Effect-driven snapshots collapse into one for the whole batch +batch((draft) => { + draft.title = 'Project Report'; + draft.content = 'Detailed document content.'; + draft.priority = 'high'; +}); +// Result: one new snapshot, not three`; + const usageSourceCode = `// Undo (built-in rollback) rollback(); @@ -169,61 +176,62 @@ undoRedo.redoStack; // Readable`; {/snippet} {#snippet sidebar()} -
- - -
-
Snapshot History
- {#if $snapshots.length === 0} -

No snapshots yet

- {:else} -
    - {#each $snapshots as snap, index} -
  • - - {index + 1} - - {snap.title} -
  • - {/each} -
- {/if} -
- -
-
Redo Stack
- {#if redoStack.length === 0} -

No redo entries — undo something first

- {:else} -
    - {#each redoStack as snap, index} -
  • - - {index + 1} - - {snap.title} -
  • - {/each} -
- {/if} -
-
+ + {#snippet extra()} +
+
Snapshot History
+ {#if $snapshots.length === 0} +

No snapshots yet

+ {:else} +
    + {#each $snapshots as snap, index} +
  • + + {index + 1} + + {snap.title} +
  • + {/each} +
+ {/if} +
+ +
+
Redo Stack
+ {#if redoStack.length === 0} +

No redo entries — undo something first

+ {:else} +
    + {#each redoStack as snap, index} +
  • + + {index + 1} + + {snap.title} +
  • + {/each} +
+ {/if} +
+ {/snippet} +
{/snippet} {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/ResetDemo.svelte b/demo/src/pages/ResetDemo.svelte index 688b266..fe67bd3 100644 --- a/demo/src/pages/ResetDemo.svelte +++ b/demo/src/pages/ResetDemo.svelte @@ -22,6 +22,7 @@ const { data, + batch, reset, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { @@ -35,11 +36,13 @@ }); const fillWithValidData = () => { - data.firstName = 'John'; - data.lastName = `Doe${randomId()}`; - data.email = `john.doe.${randomId()}@example.com`; - data.phone = `555-${randomId().slice(0, 3)}-${randomId().slice(0, 4)}`; - data.bio = 'Software developer with a passion for clean code.'; + batch((draft) => { + draft.firstName = 'John'; + draft.lastName = `Doe${randomId()}`; + draft.email = `john.doe.${randomId()}@example.com`; + draft.phone = `555-${randomId().slice(0, 3)}-${randomId().slice(0, 4)}`; + draft.bio = 'Software developer with a passion for clean code.'; + }); }; // ───────────────────────────────────────────── @@ -53,7 +56,7 @@ bio: '' }; -const { data, reset, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { +const { data, batch, reset, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { validator: (source) => ({ firstName: stringValidator(source.firstName).prepare('trim').required().minLength(2).maxLength(30).getError(), lastName: stringValidator(source.lastName).prepare('trim').required().minLength(2).maxLength(30).getError(), @@ -63,6 +66,13 @@ const { data, reset, state: { errors, hasErrors, isDirty } } = createSvState(sou }) });`; + const batchSourceCode = `// One validation pass for the whole fill +batch((draft) => { + draft.firstName = 'John'; + draft.lastName = 'Doe'; + draft.email = 'john.doe@example.com'; +});`; + const resetButtonCode = ` {#if $isDirty} - - {/each} - - {/if} -
-
+ + {#snippet extra()} +
+
Snapshot History
+ {#if $snapshots.length === 0} +

No snapshots yet

+ {:else} +
    + {#each $snapshots as snap, index} +
  • + + {index + 1} + + +
  • + {/each} +
+ {/if} +
+ {/snippet} +
{/snippet} {#snippet sourceCode()} + {/snippet} diff --git a/demo/src/pages/ZodValidation.svelte b/demo/src/pages/ZodValidation.svelte index 04c59e6..64d56f6 100644 --- a/demo/src/pages/ZodValidation.svelte +++ b/demo/src/pages/ZodValidation.svelte @@ -73,17 +73,20 @@ const { data, + batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => zodToSvstateErrors(userSchema, source, allFields) }); const fillWithValidData = () => { - data.username = `user${randomId()}`; - data.email = `${randomId()}@example.com`; - data.age = randomInt(18, 65); - data.bio = 'Hello, I am a demo user!'; - data.website = `https://${randomId()}.com`; + batch((draft) => { + draft.username = `user${randomId()}`; + draft.email = `${randomId()}@example.com`; + draft.age = randomInt(18, 65); + draft.bio = 'Hello, I am a demo user!'; + draft.website = `https://${randomId()}.com`; + }); }; // ───────────────────────────────────────────── @@ -114,8 +117,14 @@ const userSchema = z.object({ ); } -const { data, state: { errors, hasErrors } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors } } = createSvState(sourceData, { validator: (source) => zodToSvstateErrors(userSchema, source, allFields) +}); + +// batch() runs the Zod schema once for the whole fill, not once per field +batch((draft) => { + draft.username = 'user123'; + draft.email = 'user123@example.com'; });`; const dynamicSourceCode = `// Pick a subset of fields for dynamic rendering diff --git a/demo/vite.config.ts b/demo/vite.config.ts index ba0bbe1..3eec11f 100644 --- a/demo/vite.config.ts +++ b/demo/vite.config.ts @@ -1,4 +1,3 @@ - /* eslint-disable unicorn/prefer-node-protocol */ import { svelte } from '@sveltejs/vite-plugin-svelte'; import tailwindcss from '@tailwindcss/vite'; diff --git a/docs/assets/index-HgetjkG7.js b/docs/assets/index-HgetjkG7.js new file mode 100644 index 0000000..89f0120 --- /dev/null +++ b/docs/assets/index-HgetjkG7.js @@ -0,0 +1,635 @@ +(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){return e()}function p(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}var h=1024,g=2048,_=4096,v=8192,y=16384,b=32768,x=1<<25,S=65536,C=1<<19,w=1<<20,T=1<<25,E=65536,ee=1<<21,te=1<<22,ne=1<<23,re=Symbol(`$state`),ie=Symbol(`legacy props`),ae=Symbol(``),oe=Symbol(`attributes`),se=Symbol(`class`),ce=Symbol(`style`),le=Symbol(`text`),ue=Symbol(`form reset`),de=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},fe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`);function pe(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function me(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function he(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function ge(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function _e(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function ve(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function ye(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function be(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function xe(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Se(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Ce(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var we={},Te=Symbol(`uninitialized`),Ee=`http://www.w3.org/1999/xhtml`;function De(){console.warn(`https://svelte.dev/e/derived_inert`)}function Oe(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ke(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function Ae(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var D=!1;function je(e){D=e}var O;function Me(e){if(e===null)throw Oe(),we;return O=e}function Ne(){return Me(Sn(O))}function k(e){if(D){if(Sn(O)!==null)throw Oe(),we;O=e}}function Pe(e=1){if(D){for(var t=e,n=O;t--;)n=Sn(n);O=n}}function Fe(e=!0){for(var t=0,n=O;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=Sn(n);e&&n.remove(),n=i}}function Ie(e){if(!e||e.nodeType!==8)throw Oe(),we;return e.data}function Le(e){return e===this.v}function Re(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function ze(e){return!Re(e,this.v)}var Be=!1;function Ve(){Be=!0}var He=null;function Ue(e){He=e}function We(e,t=!1,n){He={p:He,i:!1,c:null,e:null,s:e,x:null,r:B,l:Be&&!t?{s:null,u:null,$:[]}:null}}function Ge(e){var t=He,n=t.e;if(n!==null){t.e=null;for(var r of n)Nn(r)}return e!==void 0&&(t.x=e),t.i=!0,He=t.p,e??{}}function Ke(){return!Be||He!==null&&He.l===null}var qe=[];function Je(){var e=qe;qe=[],p(e)}function Ye(e){if(qe.length===0&&!Bt){var t=qe;queueMicrotask(()=>{t===qe&&Je()})}qe.push(e)}function Xe(){for(;qe.length>0;)Je()}function Ze(e){var t=B;if(t===null)return z.f|=ne,e;if(!(t.f&32768)&&!(t.f&4))throw e;Qe(e,t)}function Qe(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}var $e=~(g|_|h);function et(e,t){e.f=e.f&$e|t}function tt(e){e.f&512||e.deps===null?et(e,h):et(e,_)}function nt(e){if(e!==null)for(let t of e)!(t.f&2)||!(t.f&65536)||(t.f^=E,nt(t.deps))}function rt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),nt(e.deps),et(e,h)}function it(e,t,n){if(e==null)return t(void 0),n&&n(void 0),d;let r=Tr(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}var at=[];function ot(e,t){return{subscribe:st(e,t).subscribe}}function st(e,t=d){let n=null,r=new Set;function i(t){if(Re(e,t)&&(e=t,n)){let t=!at.length;for(let t of r)t[1](),at.push(t,e);if(t){for(let e=0;e{r.delete(c),r.size===0&&n&&(n(),n=null)}}return{set:i,update:a,subscribe:o}}function ct(e,t,n){let r=!Array.isArray(e),i=r?[e]:e;if(!i.every(Boolean))throw Error(`derived() expects stores as input, got a falsy value`);let a=t.length<2;return ot(n,(e,n)=>{let o=!1,s=[],c=0,l=d,u=()=>{if(c)return;l();let i=t(r?s[0]:s,e,n);a?e(i):l=typeof i==`function`?i:d},f=i.map((e,t)=>it(e,e=>{s[t]=e,c&=~(1<{c|=1<t=e)(),t}var ut=!1,dt=Symbol(`unmounted`);function A(e,t,n){let r=n[t]??={store:null,source:an(void 0),unsubscribe:d};if(r.store!==e&&!(dt in n))if(r.unsubscribe(),r.store=e??null,e==null)r.source.v=void 0,r.unsubscribe=d;else{var i=!0;r.unsubscribe=it(e,e=>{i?r.source.v=e:P(r.source,e)}),i=!1}return e&&dt in n?lt(e):V(r.source)}function ft(){let e={};function t(){jn(()=>{for(var t in e)e[t].unsubscribe();i(e,dt,{enumerable:!1,value:!0})})}return[e,t]}function pt(e){var t=ut;try{return ut=!1,[e(),ut]}finally{ut=t}}function mt(e){D&&xn(e)!==null&&Cn(e)}var ht=!1;function gt(){ht||(ht=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[ue]?.()})},{capture:!0}))}function _t(e){var t=z,n=B;rr(null),ir(null);try{return e()}finally{rr(t),ir(n)}}function vt(e,t,n,r=n){e.addEventListener(t,()=>_t(n));let i=e[ue];e[ue]=i?()=>{i(),r(!0)}:()=>r(!0),gt()}function yt(e){let t=0,n=rn(0),r;return()=>{An()&&(V(n),Rn(()=>(t===0&&(r=Tr(()=>e(()=>un(n)))),t+=1,()=>{Ye(()=>{--t,t===0&&(r?.(),r=void 0,un(n))})})))}}var bt=S|C;function xt(e,t,n,r){new St(e,t,n,r)}var St=class{parent;is_pending=!1;transform_error;#e;#t=D?O:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=yt(()=>(this.#m=rn(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=B;t.b=this,t.f|=128,n(e)},this.parent=B.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=zn(()=>{if(D){let e=this.#t;Ne();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},bt),D&&(this.#e=O)}#g(){try{this.#a=Bn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Ye(r),t&&(this.#s=Bn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){Ae();return}t=!0,n&&Ce(),this.#s!==null&&qn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){Qe(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=Bn(()=>e(this.#e)),Ye(()=>{var e=this.#c=document.createDocumentFragment(),t=bn();e.append(t),this.#a=this.#S(()=>Bn(()=>this.#r(t))),this.#u===0&&(this.#e.before(e),this.#c=null,qn(this.#o,()=>{this.#o=null}),this.#x(M))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=Bn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();Zn(this.#a,e);let t=this.#n.pending;this.#o=Bn(()=>t(this.#e))}else this.#x(M)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){rt(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=B,n=z,r=He;ir(this.#i),rr(this.#i),Ue(this.#i.ctx);try{return Kt.ensure(),e()}catch(e){return Ze(e),null}finally{ir(t),rr(n),Ue(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&qn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Ye(()=>{this.#d=!1,this.#m&&sn(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),V(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;M?.is_fork?(this.#a&&M.skip_effect(this.#a),this.#o&&M.skip_effect(this.#o),this.#s&&M.skip_effect(this.#s),M.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(Wn(this.#a),null),this.#o&&=(Wn(this.#o),null),this.#s&&=(Wn(this.#s),null),D&&(Me(this.#t),Pe(),Me(Fe()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return Bn(()=>{var r=B;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return Qe(e,this.#i.parent),null}}))};Ye(()=>{var t;try{t=this.transform_error(e)}catch(e){Qe(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>Qe(e,this.#i&&this.#i.parent)):n(t)})}};function Ct(e,t,n,r){let i=Ke()?Dt:At;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=B,c=wt(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){Qe(e,s)}Tt()}}var d=Et();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>kt(e))).then(u).catch(e=>Qe(e,s)).finally(d)}l?l.then(()=>{c(),f(),Tt()}):f()}function wt(){var e=B,t=z,n=He,r=M;return function(i=!0){ir(e),rr(t),Ue(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function Tt(e=!0){ir(null),rr(null),Ue(null),e&&M?.deactivate()}function Et(){var e=B,t=e.b,n=M,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function Dt(e){var t=2|g;return B!==null&&(B.f|=C),{ctx:He,deps:null,effects:null,equals:Le,f:t,fn:e,reactions:null,rv:0,v:Te,wv:0,parent:B,ac:null}}var Ot=Symbol(`obsolete`);function kt(e,t,n){let r=B;r===null&&pe();var i=void 0,a=rn(Te),o=!z,s=new Set;return Ln(()=>{var t=B,n=m();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==de&&n.reject(e)}).finally(Tt)}catch(e){n.reject(e),Tt()}var c=M;if(o){if(t.f&32768)var l=Et();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(Ot);else for(let e of s.values())e.reject(Ot);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==Ot&&(c.activate(),t?(a.f|=ne,sn(a,t)):(a.f&8388608&&(a.f^=ne),sn(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),jn(()=>{for(let e of s)e.reject(Ot)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function j(e){let t=Dt(e);return or(t),t}function At(e){let t=Dt(e);return t.equals=ze,t}function jt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(de),t.ac=null}),t.fn!==null&&(t.teardown=d),br(t,0),Hn(t))}function Ft(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&xr(t)}var It=null,M=null,Lt=null,Rt=null,zt=null,Bt=!1,Vt=!1,Ht=null,Ut=null,Wt=0,Gt=1,Kt=class e{id=Gt++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){It===null?It=this:(It.#n=this,this.#t=It),It=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)et(r,g),t(r);for(r of n.m)et(r,_),t(r)}this.#p.add(e)}#g(){this.#e=!0,Wt++>1e3&&(this.#x(),Jt());for(let e of this.#u)this.#d.delete(e),et(e,g),this.schedule(e);for(let e of this.#d)et(e,_),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=Ht=[],r=[],i=Ut=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw $t(e),this.#h()||this.discard(),t}if(M=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(Ht=null,Ut=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Qt(e,t);i.length>0&&M.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),Lt=this,Xt(r),Xt(n),Lt=null,this.#s?.resolve();var s=M;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0)if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this;s!==null&&s.#g()}#_(e,t,n){e.f^=h;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=h:i&4?t.push(r):gr(r)&&(i&16&&this.#d.add(r),xr(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),et(i,g),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),M=this,this.#g()}#b(e){for(var t=0;t{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=m()).promise}static ensure(){if(M===null){let t=M=new e;!Vt&&!Bt&&Ye(()=>{t.#e||t.flush()})}return M}apply(){Rt=null}schedule(e){if(zt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(Ht!==null&&t===B&&(z===null||!(z.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=h}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?It=e:t.#t=e,this.linked=!1}}};function qt(e){var t=Bt;Bt=!0;try{var n;for(e&&(M!==null&&!M.is_fork&&M.flush(),n=e());;){if(Xe(),M===null)return n;M.flush()}}finally{Bt=t}}function Jt(){try{ve()}catch(e){Qe(e,zt)}}var Yt=null;function Xt(e){var t=e.length;if(t!==0){for(var n=0;n0)){tn.clear();for(let e of Yt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Yt.has(n)&&(Yt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||xr(n)}}Yt.clear()}}Yt=null}}function Zt(e){M.schedule(e)}function Qt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),et(e,h);for(var n=e.first;n!==null;)Qt(n,t),n=n.next}}function $t(e){et(e,h);for(var t=e.first;t!==null;)$t(t),t=t.next}var en=new Set,tn=new Map,nn=!1;function rn(e,t){return{f:0,v:e,reactions:null,equals:Le,rv:0,wv:0}}function N(e,t){let n=rn(e,t);return or(n),n}function an(e,t=!1,n=!0){let r=rn(e);return t||(r.equals=ze),Be&&n&&He!==null&&He.l!==null&&(He.l.s??=[]).push(r),r}function on(e,t){return P(e,Tr(()=>V(e))),t}function P(e,t,n=!1){return z!==null&&(!nr||z.f&131072)&&Ke()&&z.f&4325394&&(ar===null||!ar.has(e))&&Se(),sn(e,n?fn(t):t,Ut)}function sn(e,t,n=null){if(!e.equals(t)){tn.set(e,er?t:e.v);var r=Kt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&Mt(t),Rt===null&&tt(t)}e.wv=hr(),dn(e,g,n),Ke()&&B!==null&&B.f&1024&&!(B.f&96)&&(lr===null?ur([e]):lr.push(e)),!r.is_fork&&en.size>0&&!nn&&cn()}return t}function cn(){nn=!1;for(let e of en){e.f&1024&&et(e,_);let t;try{t=gr(e)}catch{t=!0}t&&xr(e)}en.clear()}function ln(e,t=1){var n=V(e),r=t===1?n++:n--;return P(e,n),r}function un(e){P(e,e.v+1)}function dn(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ke(),a=r.length,o=0;o{if(pr===d)return e();var t=z,n=pr;rr(null),mr(d);var r=e();return rr(t),mr(n),r};return i&&r.set(`length`,N(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&be();var i=r.get(t);return i===void 0?f(()=>{var e=N(n.value,u);return r.set(t,e),e}):P(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>N(Te,u));r.set(t,e),un(o)}}else P(n,Te),un(o);return!0},get(e,n,i){if(n===re)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>N(fn(s?e[n]:Te),u)),r.set(n,o)),o!==void 0){var c=V(o);return c===Te?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=V(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==Te)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===re)return!0;var n=r.get(t),i=n!==void 0&&n.v!==Te||Reflect.has(e,t);return(n!==void 0||B!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>N(i?fn(e[t]):Te,u)),r.set(t,n)),V(n)===Te)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dN(Te,u)),r.set(d+``,p)):P(p,Te)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>N(void 0,u)),P(c,fn(n)),r.set(t,c));else{l=c.v!==Te;var m=f(()=>fn(n));P(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&P(g,_+1)}un(o)}return!0},ownKeys(e){V(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==Te});for(var[n,i]of r)i.v!==Te&&!(n in e)&&t.push(n);return t},setPrototypeOf(){xe()}})}function pn(e){try{if(typeof e==`object`&&e&&re in e)return e[re]}catch{}return e}function mn(e,t){return Object.is(pn(e),pn(t))}var hn,gn,_n,vn;function yn(){if(hn===void 0){hn=window,gn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;_n=a(t,`firstChild`).get,vn=a(t,`nextSibling`).get,u(e)&&(e[se]=void 0,e[oe]=null,e[ce]=void 0,e.__e=void 0),u(n)&&(n[le]=void 0)}}function bn(e=``){return document.createTextNode(e)}function xn(e){return _n.call(e)}function Sn(e){return vn.call(e)}function F(e,t){if(!D)return xn(e);var n=xn(O);if(n===null)n=O.appendChild(bn());else if(t&&n.nodeType!==3){var r=bn();return n?.before(r),Me(r),r}return t&&En(n),Me(n),n}function I(e,t=!1){if(!D){var n=xn(e);return n instanceof Comment&&n.data===``?Sn(n):n}if(t){if(O?.nodeType!==3){var r=bn();return O?.before(r),Me(r),r}En(O)}return O}function L(e,t=1,n=!1){let r=D?O:e;for(var i;t--;)i=r,r=Sn(r);if(!D)return r;if(n){if(r?.nodeType!==3){var a=bn();return r===null?i?.after(a):r.before(a),Me(a),a}En(r)}return Me(r),r}function Cn(e){e.textContent=``}function wn(){return!1}function Tn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function En(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function Dn(e){B===null&&(z===null&&_e(e),ge()),er&&he(e)}function On(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function kn(e,t){var n=B;n!==null&&n.f&8192&&(e|=v);var r={ctx:He,deps:null,nodes:null,f:e|g|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};M?.register_created_effect(r);var i=r;if(e&4)Ht===null?Kt.ensure().schedule(r):Ht.push(r);else if(t!==null){try{xr(r)}catch(e){throw Wn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=S))}if(i!==null&&(i.parent=n,n!==null&&On(i,n),z!==null&&z.f&2&&!(e&64))){var a=z;(a.effects??=[]).push(i)}return r}function An(){return z!==null&&!nr}function jn(e){let t=kn(8,null);return et(t,h),t.teardown=e,t}function Mn(e){Dn(`$effect`);var t=B.f;if(!z&&t&32&&He!==null&&!He.i){var n=He;(n.e??=[]).push(e)}else return Nn(e)}function Nn(e){return kn(4|w,e)}function Pn(e){return Dn(`$effect.pre`),kn(8|w,e)}function Fn(e){Kt.ensure();let t=kn(64|C,e);return(e={})=>new Promise(n=>{e.outro?qn(t,()=>{Wn(t),n(void 0)}):(Wn(t),n(void 0))})}function In(e){return kn(4,e)}function Ln(e){return kn(te|C,e)}function Rn(e,t=0){return kn(8|t,e)}function R(e,t=[],n=[],r=[]){Ct(r,t,n,t=>{kn(8,()=>{e(...t.map(V))})})}function zn(e,t=0){return kn(16|t,e)}function Bn(e){return kn(32|C,e)}function Vn(e){var t=e.teardown;if(t!==null){let e=er,n=z;tr(!0),rr(null);try{t.call(null)}finally{tr(e),rr(n)}}}function Hn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&_t(()=>{e.abort(de)});var r=n.next;n.f&64?n.parent=null:Wn(n,t),n=r}}function Un(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||Wn(t),t=n}}function Wn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Gn(e.nodes.start,e.nodes.end),n=!0),e.f|=x,Hn(e,t&&!n),br(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();Vn(e),e.f^=x,e.f|=y;var i=e.parent;i!==null&&i.first!==null&&Kn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Gn(e,t){for(;e!==null;){var n=e===t?null:Sn(e);e.remove(),e=n}}function Kn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function qn(e,t,n=!0){var r=[];Jn(e,r,!0);var i=()=>{n&&Wn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Jn(e,t,n){if(!(e.f&8192)){e.f^=v;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);Jn(i,t,o?n:!1)}i=a}}}function Yn(e){Xn(e,!0)}function Xn(e,t){if(e.f&8192){e.f^=v,e.f&1024||(et(e,g),Kt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Xn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function Zn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:Sn(n);t.append(n),n=i}}var Qn=null,$n=!1,er=!1;function tr(e){er=e}var z=null,nr=!1;function rr(e){z=e}var B=null;function ir(e){B=e}var ar=null;function or(e){z!==null&&(ar??=new Set).add(e)}var sr=null,cr=0,lr=null;function ur(e){lr=e}var dr=1,fr=0,pr=fr;function mr(e){pr=e}function hr(){return++dr}function gr(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~E),t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&Rt===null&&et(e,h)}return!1}function _r(e,t,n=!0){var r=e.reactions;if(r!==null&&!(ar!==null&&ar.has(e)))for(var i=0;i{e.ac.abort(de)}),e.ac=null);try{e.f|=ee;var u=e.fn,d=u();e.f|=b;var f=e.deps,p=M?.is_fork;if(sr!==null){var m;if(p||br(e,cr),f!==null&&cr>0)for(f.length=cr+sr.length,m=0;m{s.ac.abort(de),s.ac=null,et(s,g)}),Pt(s),br(s,0)}}function br(e,t){var n=e.deps;if(n!==null)for(var r=t;r{throw e});throw p}}finally{e[Ar]=t,delete e.currentTarget,rr(d),ir(f)}}}var Ir=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function Lr(e){return Ir?.createHTML(e)??e}function Rr(e){var t=Tn(`template`);return t.innerHTML=Lr(e.replaceAll(``,``)),t.content}function zr(e,t){var n=B;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function U(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(D)return zr(O,null),O;i===void 0&&(i=Rr(a?e:``+e),n||(i=xn(i)));var t=r||gn?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=xn(t),s=t.lastChild;zr(o,s)}else zr(t,t);return t}}function Br(e,t,n=`svg`){var r=!e.startsWith(``),i=!!(t&1),a=`<${n}>${r?e:``+e}`,o;return()=>{if(D)return zr(O,null),O;if(!o){var e=xn(Rr(a));if(i)for(o=document.createDocumentFragment();xn(e);)o.appendChild(xn(e));else o=xn(e)}var t=o.cloneNode(!0);if(i){var n=xn(t),r=t.lastChild;zr(n,r)}else zr(t,t);return t}}function Vr(e,t){return Br(e,t,`svg`)}function Hr(e=``){if(!D){var t=bn(e+``);return zr(t,t),t}var n=O;return n.nodeType===3?En(n):(n.before(n=bn()),Me(n)),zr(n,n),n}function Ur(){if(D)return zr(O,null),O;var e=document.createDocumentFragment(),t=document.createComment(``),n=bn();return e.append(t,n),zr(t,n),e}function W(e,t){if(D){var n=B;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=O),Ne();return}e!==null&&e.before(t)}function G(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[le]??=e.nodeValue)&&(e[le]=n,e.nodeValue=`${n}`)}function Wr(e,t){return Kr(e,t)}var Gr=new Map;function Kr(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){yn();var l=void 0,u=Fn(()=>{var s=n??t.appendChild(bn());xt(s,{pending:()=>{}},t=>{We({});var n=He;if(o&&(n.c=o),a&&(i.$$events=a),D&&zr(t,null),l=e(t,i)||{},D&&(B.nodes.end=O,O===null||O.nodeType!==8||O.data!==`]`))throw Oe(),we;Ge()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=Gr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,Fr),r.delete(e),r.size===0&&Gr.delete(n)):r.set(e,i)}Mr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return qr.set(l,u),l}var qr=new WeakMap,Jr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)Yn(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(Yn(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(Wn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();Zn(r,t),t.append(bn()),this.#n.set(e,{effect:r,fragment:t})}else Wn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),qn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(Wn(n.effect),this.#n.delete(e))};ensure(e,t){var n=M,r=wn();if(t&&!this.#t.has(e)&&!this.#n.has(e))if(r){var i=document.createDocumentFragment(),a=bn();i.append(a),this.#n.set(e,{effect:Bn(()=>t(a)),fragment:i})}else this.#t.set(e,Bn(()=>t(this.anchor)));if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else D&&(this.anchor=O),this.#a(n)}};function K(e,t,n=!1){var r;D&&(r=O,Ne());var i=new Jr(e),a=n?S:0;function o(e,t){if(D){var n=Ie(r);if(e!==parseInt(n.substring(1))){var a=Fe();Me(a),i.anchor=a,je(!1),i.ensure(e,t),je(!0);return}}i.ensure(e,t)}zn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var Yr=Symbol(`NaN`);function Xr(e,t,n){D&&Ne();var r=new Jr(e),i=!Ke();zn(()=>{var e=t();e!==e&&(e=Yr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function Zr(e,t){return t}function Qr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;$r(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null;if(l){var u=n,d=u.parentNode;Cn(d),d.append(u),e.items.clear()}$r(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function $r(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,ri(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=T,ai(d,null,c)):Yn(d):qn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:zn(()=>{p=V(f);var e=p.length;let t=!1;D&&Ie(c)===`[!`!=(e===0)&&(c=Fe(),Me(c),je(!1),t=!0);for(var r=new Set,u=M,v=wn(),y=0;ys(c)):(d=Bn(()=>s(ei??=bn())),d.f|=T)),e>r.size&&me(``,``,``),D&&e>0&&Me(Fe()),!h)if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u);t&&je(!0),V(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,D&&(c=O)}function ni(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function ri(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=ni(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var ee=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function ii(e,t,n,r,i,a,o,s){var c=o&1?o&16?rn(n):an(n,!1,!1):null,l=o&2?rn(i):null;return{v:c,i:l,e:Bn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function ai(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=Sn(r);if(a.before(r),r===i)return;r=o}}function oi(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function si(e,t,...n){var r=new Jr(e);zn(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},S)}var ci=[...` +\r\f\xA0\v`];function li(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||ci.includes(r[o-1]))&&(s===r.length||ci.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ui(e,t,n,r,i,a){var o=e[se];if(D||o!==n||o===void 0){var s=li(n,r,a);(!D||s!==e.getAttribute(`class`))&&(s==null?e.removeAttribute(`class`):t?e.className=s:e.setAttribute(`class`,s)),e[se]=n}else if(a&&i!==a)for(var c in a){var l=!!a[c];(i==null||l!==!!i[c])&&e.classList.toggle(c,l)}return a}function di(t,n,r=!1){if(t.multiple){if(n==null)return;if(!e(n))return ke();for(var i of t.options)i.selected=n.includes(mi(i));return}for(i of t.options)if(mn(mi(i),n)){i.selected=!0;return}(!r||n!==void 0)&&(t.selectedIndex=-1)}function fi(e){var t=new MutationObserver(()=>{`__value`in e&&di(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),jn(()=>{t.disconnect()})}function pi(e,t,n=t){var r=new WeakSet,i=!0;vt(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),mi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&mi(o)}n(a),e.__value=a,M!==null&&r.add(M)}),In(()=>{var a=t();if(e===document.activeElement){var o=M;if(r.has(o))return}if(di(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=mi(s),n(a))}e.__value=a,i=!1}),fi(e)}function mi(e){return`__value`in e?e.__value:e.value}var hi=Symbol(`is custom element`),gi=Symbol(`is html`),_i=fe?`link`:`LINK`;function vi(e){if(D){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;yi(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;yi(e,`checked`,null),e.checked=r}}};e[ue]=n,Ye(n),gt()}}function yi(e,t,n,r){var i=bi(e);D&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===_i)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[ae]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Si(e).includes(t)?e[t]=n:e.setAttribute(t,n))}function bi(e){return e[oe]??={[hi]:e.nodeName.includes(`-`),[gi]:e.namespaceURI===Ee}}var xi=new Map;function Si(e){var t=e.getAttribute(`is`)||e.nodeName,n=xi.get(t);if(n)return n;xi.set(t,n=[]);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.push(s);i=l(i)}return n}function Ci(e,t,n=t){var r=new WeakSet;vt(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Ti(e)?Ei(a):a,n(a),M!==null&&r.add(M),await Sr(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(D&&e.defaultValue!==e.value||Tr(t)==null&&e.value)&&(n(Ti(e)?Ei(e.value):e.value),M!==null&&r.add(M)),Rn(()=>{var n=t();if(e===document.activeElement){var i=M;if(r.has(i))return}Ti(e)&&n===Ei(e.value)||e.type===`date`&&!n&&!e.value||n!==e.value&&(e.value=n??``)})}function wi(e,t,n=t){vt(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(D&&e.defaultChecked!==e.checked||Tr(t)==null)&&n(e.checked),Rn(()=>{e.checked=!!t()})}function Ti(e){var t=e.type;return t===`number`||t===`range`}function Ei(e){return e===``?null:+e}function Di(e=!1){let t=He,n=t.l.u;if(!n)return;let r=()=>Er(t.s);if(e){let e=0,n={},i=Dt(()=>{let r=!1,i=t.s;for(let e in i)i[e]!==n[e]&&(n[e]=i[e],r=!0);return r&&e++,e});r=()=>V(i)}n.b.length&&Pn(()=>{Oi(t,r),p(n.b)}),Mn(()=>{let e=Tr(()=>n.m.map(f));return()=>{for(let t of e)typeof t==`function`&&t()}}),n.a.length&&Mn(()=>{Oi(t,r),p(n.a)})}function Oi(e,t){if(e.l.s)for(let t of e.l.s)V(t);t()}function ki(e,t,n,r){var i=!Be||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=Dt(r),V(u)):(l&&(l=!1,c=s?Tr(r):r),c);let f;if(o){var p=re in e||ie in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=pt(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&ye(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?Dt:At)(()=>(v=!1,g()));o&&V(y);var b=B;return(function(e,t){if(arguments.length>0){let n=t?V(y):i&&o?fn(e):e;return P(y,n),v=!0,c!==void 0&&(c=n),e}return er&&v||b.f&16384?y.v:V(y)})}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);var Ai=e=>Object.values(e).some(e=>typeof e==`string`?!!e:Ai(e)),ji=e=>!!e&&Ai(e),Mi=e=>{if(e instanceof Error)return e;if(typeof e==`object`&&e){let t=e;return Error(String(t.message??t.body?.message??e))}return Error(String(e))};function Ni(e){let t=e.batchSize??20,n=e.flushInterval??5e3,r=e.include,i=[],a,o=e=>!r||r.includes(e),s=t=>e.redact?.some(e=>t===e||t.startsWith(e+`.`))??!1,c=(e,n)=>{o(e)&&(i.push({type:e,timestamp:Date.now(),detail:n}),i.length>=t&&u())},l=async t=>{try{await e.onFlush(t)}catch(t){e.onError?.(t)}},u=()=>{if(i.length===0)return;let e=i.slice();i.length=0,l(e)};return{name:`analytics`,onInit(){n>0&&(a=setInterval(u,n))},onChange(e){let t=s(e.property);c(`change`,{property:e.property,currentValue:t?`[redacted]`:e.currentValue,oldValue:t?`[redacted]`:e.oldValue})},onValidation(e){c(`validation`,{hasErrors:ji(e)})},onSnapshot(e){c(`snapshot`,{title:e.title})},onAction(e){c(`action`,{phase:e.phase,error:e.error?.message})},onRollback(e){c(`rollback`,{title:e.title})},onReset(){c(`reset`,{})},destroy(){a!==void 0&&clearInterval(a),u()},flush(){u()},eventCount(){return i.length}}}var Pi=(e,t)=>{let n,r=()=>{n!==void 0&&(clearTimeout(n),n=void 0)};return{schedule(){r(),n=setTimeout(()=>{n=void 0,e()},t)},cancel:r,flush(){n!==void 0&&(r(),e())},isPending:()=>n!==void 0}};function Fi(e){let t=e.idle??1e3,n=e.interval??0,r=e.saveOnDestroy??!0,i=e.onlyWhenDirty??!0,a,o,s=!1,c=!1,l=!1,u=!1,d=async()=>{if(a&&!(i&&!lt(a.state.isDirty))){if(c){u=!0;return}c=!0;try{await e.save(a.data)}catch(t){e.onError?.(t)}finally{c=!1}u&&!l&&(u=!1,await d())}},f=Pi(()=>void d(),t),p=()=>{typeof document<`u`&&document.visibilityState===`hidden`&&d()};return{name:`autosave`,onInit(t){a=t,n>0&&(o=setInterval(d,n)),typeof document<`u`&&e.onVisibilityHidden&&(document.addEventListener(`visibilitychange`,p),s=!0)},onChange(){f.schedule()},onAction(e){e.phase===`after`&&!e.error&&f.cancel()},destroy(){l=!0,u=!1,f.cancel(),o!==void 0&&clearInterval(o),s&&=(document.removeEventListener(`visibilitychange`,p),!1),r&&a&&(c=!1,d())},async saveNow(){l||(f.cancel(),c=!1,u=!1,await d())},isSaving(){return c}}}var Ii=()=>{try{return import.meta.env?.PROD===!0}catch{return!1}};function Li(e){let t=e?.name??`svstate`,n=e?.collapsed??!0,r=e?.logValidation??!1,i=e?.logValues??!1,a=e?.enabled??!Ii(),o=(e,...r)=>{if(!a)return;let i=new Date().toISOString().slice(11,23);(n?console.groupCollapsed:console.group)(`[${t}] ${e} (${i})`);for(let e of r)console.log(e);console.groupEnd()};return{name:`devtools`,onChange(e){i?o(`change`,{property:e.property,from:e.oldValue,to:e.currentValue}):o(`change`,{property:e.property})},onValidation(e){r&&o(`validation`,e)},onSnapshot(e){o(`snapshot`,{title:e.title})},onAction(e){e.error?o(`action:${e.phase}`,{params:e.params,error:e.error.message}):o(`action:${e.phase}`,{params:e.params})},onRollback(e){o(`rollback`,{title:e.title})},onReset(){o(`reset`)}}}var Ri=new Set([`__proto__`,`constructor`,`prototype`]),zi=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Bi=e=>e,Vi=(e,t)=>e.filter(e=>e===t||e.startsWith(t+`.`)||t.startsWith(e+`.`)),Hi=(e,t)=>{let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},Ui=(e,t,n)=>{let r=t.split(`.`),i=e;for(let e=0;e{for(let[n,r]of Object.entries(t))Ri.has(n)||(e[n]=r)},Gi=e=>zi(e)&&typeof e.version==`number`&&zi(e.data),Ki=(e,t)=>{let n=t.split(`.`);if(n.length===1){delete e[t];return}let r=e;for(let e=0;e{if(t){let n={};for(let r of t){let t=Hi(e,r);t!==void 0&&Ui(n,r,t)}return n}if(n){let t={...e};for(let e of n)Ki(t,e);return t}return e};function Ji(e){let t=e.storage??(typeof localStorage>`u`?void 0:localStorage),n=e.throttle??300,r=e.version??1,i=!1,a,o=()=>{if(!(!t||!a))try{let n=qi(Bi(a),e.include,e.exclude),i={version:r,data:n};t.setItem(e.key,JSON.stringify(i))}catch(t){e.onError?.(t)}},s=Pi(o,n);return{name:`persist`,onInit(n){if(a=n.data,!t)return;let o=t.getItem(e.key);if(o)try{let t=JSON.parse(o);if(!Gi(t))return;let a=t;if(e.migrate&&a.version!==r){let t=e.migrate(a.data,a.version);if(!zi(t))return;a={version:r,data:t}}Wi(Bi(n.data),a.data),i=!0}catch{}},onChange(){s.schedule()},onReset(){o()},destroy(){s.flush()},clearPersistedState(){t?.removeItem(e.key)},isRestored(){return i}}}var Yi=10,Xi=(e,t=0)=>t>Yi?!1:!zi(e)||Object.values(e).every(e=>Xi(e,t+1));function Zi(e){let t=e.throttle??100,n=e.merge??`overwrite`,r,i,a=!1,o=0,s,c,l=Pi(()=>{if(!(!r||!i))try{let e=JSON.parse(JSON.stringify(i.data));r.postMessage({type:`sync`,data:e})}catch(t){e.onError?.(t)}},t),u=e=>{if(i){a=!0;try{Wi(Bi(i.data),e)}finally{a=!1}}},d=e=>{let n=Date.now()-o;if(n>=t){o=Date.now(),u(e);return}s=e,c===void 0&&(c=setTimeout(()=>{c=void 0;let e=s;s=void 0,e&&(o=Date.now(),u(e))},t-n))},f=()=>{l.cancel(),clearTimeout(c),c=void 0,s=void 0,r&&=(r.close(),void 0)};return{name:`sync`,onInit(t){i=t,!(typeof BroadcastChannel>`u`)&&(r=new BroadcastChannel(e.key),r.addEventListener(`message`,e=>{!i||n===`ignore`||e.data?.type===`sync`&&zi(e.data.data)&&Xi(e.data.data)&&d(e.data.data)}))},onChange(){a||l.schedule()},destroy(){f()},disconnect(){f()}}}var Qi=e=>e instanceof Promise||e instanceof WeakMap||e instanceof WeakSet||e instanceof WeakRef||e instanceof Error||e instanceof ArrayBuffer||ArrayBuffer.isView(e),$i=(e,t=new WeakMap)=>{if(typeof e!=`object`||!e)return e;let n=e;if(t.has(n))return t.get(n);if(e instanceof Date)return new Date(e);if(e instanceof RegExp){let t=new RegExp(e.source,e.flags);return t.lastIndex=e.lastIndex,t}if(Qi(n))return e;if(Array.isArray(e)){let r=[];t.set(n,r);for(let n of e)r.push($i(n,t));return r}if(e instanceof Map){let r=new Map;t.set(n,r);for(let[n,i]of e)r.set($i(n,t),$i(i,t));return r}if(e instanceof Set){let r=new Set;t.set(n,r);for(let n of e)r.add($i(n,t));return r}let r=Object.create(Object.getPrototypeOf(n));t.set(n,r);for(let[e,i]of Object.entries(n)){if(Ri.has(e))continue;let a=Object.getOwnPropertyDescriptor(n,e);a&&(a.get||a.set)?Object.defineProperty(r,e,a):r[e]=$i(i,t)}return r};function ea(e){let t=st([]),n=[],r,i,a,o=!1;return{name:`undo-redo`,redoStack:{subscribe:t.subscribe},onInit(e){r=e,i=e.state.snapshots.subscribe(e=>{e.length0&&(a=n.at(-1)),n=e})},onRollback(){a&&=(t.update(t=>{let n=[...t,a],r=e?.maxRedoStack;return r&&r>0?n.slice(-r):n}),void 0)},onChange(){o||t.set([])},onReset(){t.set([])},redo(){if(!r)return;let e=lt(t);if(e.length===0)return;let n=e.at(-1);t.set(e.slice(0,-1)),o=!0;try{r.snapshot(`Undo`,!1),Object.assign(r.data,$i(n.data))}finally{o=!1}},canRedo(){return lt(t).length>0},destroy(){i?.()}}}var ta=Symbol(`svstate.raw`),na=/^(?:0|[1-9]\d*)$/,ra=e=>typeof e==`object`&&!!e&&!(e instanceof Date)&&!(e instanceof Map)&&!(e instanceof Set)&&!(e instanceof WeakMap)&&!(e instanceof WeakSet)&&!(e instanceof RegExp)&&!(e instanceof Error)&&!(e instanceof Promise),ia=e=>typeof e!=`object`||!e?e:e[ta]??e,aa=(e,t,n)=>Array.isArray(e)&&(t===`length`||na.test(t))?n:n?`${n}.${t}`:t,oa=(e,t)=>{let n=new WeakMap,r=(e,a)=>{let o=n.get(e);if(o){let e=o.get(a)?.deref();if(e)return e}else o=new Map,n.set(e,o);let s=new Proxy(e,{get(e,t){if(t===ta)return e;if(typeof t==`symbol`)return e[t];let n=e[t];return ra(n)?r(n,aa(e,t,a)):n},set(e,n,r){if(typeof n==`symbol`)return e[n]=r,!0;let o=ia(r),s=e[n];return Object.is(s,o)?!0:(e[n]=o,t(i,aa(e,n,a),o,s),!0)},deleteProperty(e,n){if(typeof n==`symbol`)return Reflect.deleteProperty(e,n);if(!Object.hasOwn(e,n))return!0;let r=e[n];return Reflect.deleteProperty(e,n)?(t(i,aa(e,n,a),void 0,r),!0):!1}});return o.set(a,new WeakRef(s)),s},i=r(e,``);return i},sa=(e,t)=>{let n=e;for(let e of t.split(`.`)){if(!zi(n))return``;n=n[e]}return typeof n==`string`?n:``},ca=`Initial`,la={resetDirtyOnAction:!0,debounceValidation:0,allowConcurrentActions:!1,persistActionError:!1,debounceAsyncValidation:300,runAsyncValidationOnInit:!1,clearAsyncErrorsOnChange:!0,maxConcurrentAsyncValidations:4,maxSnapshots:50,onPluginError:(e,t,n)=>console.error(`svstate: plugin "${t}" threw in ${n}`,e),plugins:[]};function ua(e,t,n){let r={...la,...n},{validator:i,effect:a,asyncValidator:o}=t??{},s=st(),c=ct(s,ji),l=st({}),u=ct(l,e=>Object.keys(e).length>0),d=st(!1),f=st(),p=st([{title:ca,data:$i(e)}]),m=st({}),h=st(new Set),g=ct(h,e=>[...e]),_=ct(m,e=>Object.values(e).some(e=>!!e)),v=ct([c,_],([e,t])=>e||t),y=new Map,b=[],x=!1,S=e=>{l.update(t=>{let n={...t,[e]:!0},r=e.split(`.`);for(let e=1;e{let i=e[t];if(typeof i==`function`)try{i.apply(e,n)}catch(n){r.onPluginError(n,e.name,t)}},re=(e,...t)=>{for(let n of te)ne(n,e,t)},ie=()=>{if(!i)return;let e=i(be);s.set(e),re(`onValidation`,e)},ae=(e,t=!0)=>{if(w){E??=e;return}let n=lt(p),i={title:e,data:$i(C)},a=n.at(-1),o=t&&a&&a.title===e?[...n.slice(0,-1),i]:[...n,i];if(r.maxSnapshots>0&&o.length>r.maxSnapshots){let e=o.length-r.maxSnapshots;o=[o[0],...o.slice(1+e)]}p.set(o),re(`onSnapshot`,i)},oe=!1,se,ce=()=>{se!==void 0&&(clearTimeout(se),se=void 0)},le=()=>{if(!(!i||x))if(r.debounceValidation>0)clearTimeout(se),se=setTimeout(()=>{se=void 0,ie()},r.debounceValidation);else{if(oe)return;oe=!0,queueMicrotask(()=>{oe=!1,x||ie()})}},ue=e=>{let t=b.indexOf(e);t!==-1&&b.splice(t,1)},de=e=>h.update(t=>new Set([...t,e])),fe=e=>h.update(t=>(t.delete(e),new Set(t))),pe=e=>{ue(e);let t=y.get(e);t&&(t.kind===`debounced`?clearTimeout(t.timeoutId):t.controller.abort(),y.delete(e),fe(e))},me=()=>{b.length=0;for(let e of y.keys())pe(e);m.set({})},he=async(e,t)=>{let n=o?.[e];if(!n||x||sa(lt(s),e)){t();return}let r=new AbortController;y.set(e,{kind:`running`,controller:r}),de(e);try{let t=await n(Hi(be,e),be,r.signal);r.signal.aborted||m.update(n=>({...n,[e]:t}))}catch(t){if(t instanceof Error&&t.name===`AbortError`)return;r.signal.aborted||m.update(n=>({...n,[e]:Mi(t).message}))}finally{y.delete(e),fe(e),t()}},ge=()=>{for(;b.length>0&&!(lt(h).size>=r.maxConcurrentAsyncValidations);){let e=b.shift();e&&he(e,ge)}},_e=e=>{if(x||!o||!Object.hasOwn(o,e))return;pe(e),r.clearAsyncErrorsOnChange&&m.update(t=>{let n={...t};return delete n[e],n});let t=setTimeout(()=>{y.delete(e),lt(h).size{let e=[...ee];ee.clear(),le();for(let t of e)_e(t)},ye=e=>{if(!o)return;let t=Vi(Object.keys(o),e);if(w){for(let e of t)ee.add(e);return}for(let e of t)_e(e)},be=oa(C,(e,t,n,i)=>{if(!x){if(T=!0,r.persistActionError||f.set(void 0),S(t),a?.({snapshot:ae,target:e,property:t,currentValue:n,oldValue:i})instanceof Promise)throw Error(`svstate: effect callback must be synchronous. Use action for async operations.`);re(`onChange`,{target:e,property:t,currentValue:n,oldValue:i}),w||le(),ye(t)}});ie();let xe=()=>{ce(),ie();let e=lt(s);return{errors:e,hasErrors:ji(e)}},Se=e=>{if(!x){if(w){e(be);return}w=!0;try{e(be)}finally{if(w=!1,E!==void 0){let e=E;E=void 0,ae(e,!1)}ve()}}};if(o&&r.runAsyncValidationOnInit)for(let e of Object.keys(o))_e(e);let Ce=(e=!0)=>{e&&l.set({}),p.set([{title:ca,data:$i(C)}])},we=async e=>{if(!(!r.allowConcurrentActions&<(d))){re(`onAction`,{phase:`before`,params:e}),f.set(void 0),d.set(!0);try{await t?.action?.(e),Ce(r.resetDirtyOnAction),await t?.actionCompleted?.(),re(`onAction`,{phase:`after`,params:e})}catch(n){await t?.actionCompleted?.(n);let r=Mi(n);f.set(r),re(`onAction`,{phase:`after`,params:e,error:r})}finally{d.set(!1)}}},Te=e=>{let t=$i(e);for(let e of Object.keys(C))Object.hasOwn(t,e)||delete C[e];Object.assign(C,t)},Ee=(e,t)=>{let n=t[e];if(n)return me(),l.set({}),Te(n.data),p.set(t.slice(0,e+1)),ie(),n},De=(e,t)=>{let n=Ee(e,t);n&&re(`onRollback`,n)},Oe=(e=1)=>{let t=lt(p);t.length<=1||De(Math.max(0,t.length-1-e),t)},ke=e=>{let t=lt(p);if(t.length<=1)return!1;for(let n=t.length-1;n>=0;n--)if(t[n].title===e)return De(n,t),!0;return!1},Ae=()=>{let e=lt(p);e[0]&&(Ee(0,e),re(`onReset`))},D={errors:s,hasErrors:c,isDirty:u,isDirtyByField:l,actionInProgress:d,actionError:f,snapshots:p,asyncErrors:m,hasAsyncErrors:_,asyncValidating:g,hasCombinedErrors:v},je=()=>{if(!x){x=!0,ce(),me();for(let e=te.length-1;e>=0;e--){let t=te[e];t&&ne(t,`destroy`,[])}}};w=!0;try{re(`onInit`,{data:be,state:D,options:r,snapshot:ae})}finally{w=!1}return E=void 0,T?(Ce(),ve()):ee.clear(),{data:be,execute:we,state:D,rollback:Oe,rollbackTo:ke,reset:Ae,destroy:je,validate:xe,batch:Se}}var da=1e-9,fa=e=>{if(Number.isSafeInteger(e))return 0;let t=String(e),n=t.indexOf(`e-`);if(n===-1)return t.split(`.`,2)[1]?.length??0;let r=t.slice(0,n),i=Number(t.slice(n+2));return(r.split(`.`,2)[1]?.length??0)+i},pa=(e,t)=>{if(t===0)return!1;let n=Math.abs(e%t);return ntypeof e!=`object`||!e?JSON.stringify(e)??String(e):e instanceof Date?`Date(${e.getTime()})`:Array.isArray(e)?`[${e.map(e=>ma(e)).join(`,`)}]`:`{${Object.entries(e).toSorted(([e],[t])=>e`${JSON.stringify(e)}:${ma(t)}`).join(`,`)}}`,ha=e=>e===null?`null`:typeof e==`object`?`object:${ma(e)}`:`${typeof e}:${String(e)}`,ga=e=>typeof e==`object`&&e?JSON.stringify(e):String(e),_a={trim:e=>e.trim(),normalize:e=>e.replaceAll(/\s{2,}/g,` `),upper:e=>e.toUpperCase(),lower:e=>e.toLowerCase(),localeUpper:e=>e.toLocaleUpperCase(),localeLower:e=>e.toLocaleLowerCase()};function q(e){let t=``,n=e==null,r=e??``,i=e=>{t||=e},a={prepare(...e){return r=e.reduce((e,t)=>_a[t](e),r),a},required(){return!t&&(n||!r)&&i(`Required`),a},requiredIf(e){return e&&!t&&(n||!r)&&i(`Required`),a},noSpace(){return n||!t&&r.includes(` `)&&i(`No space allowed`),a},notBlank(){return n||!t&&r.length>0&&r.trim().length===0&&i(`Must not be blank`),a},minLength(e){return n||!t&&r.lengthe&&i(`Max length ${e}`),a},uppercase(){return n||!t&&r!==r.toUpperCase()&&i(`Uppercase only`),a},lowercase(){return n||!t&&r!==r.toLowerCase()&&i(`Lowercase only`),a},startsWith(e){if(t)return a;let n=Array.isArray(e)?e:[e];return r&&n.every(e=>!r.startsWith(e))&&i(`Must start with ${n.join(`, `)}`),a},regexp(e,n){return!t&&r&&!e.test(r)&&i(n??`Not allowed chars`),a},in(e){if(t)return a;let n=Array.isArray(e)?e:Object.keys(e);return r&&!n.includes(r)&&i(`Must be one of: ${n.join(`, `)}`),a},notIn(e){if(t)return a;let n=Array.isArray(e)?e:Object.keys(e);return r&&n.includes(r)&&i(`Must not be one of: ${n.join(`, `)}`),a},email(){return!t&&r&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r)&&i(`Invalid email format`),a},website(e=`optional`){if(t||!r||e===`optional`)return a;let n=/^https?:\/\//.test(r);return e===`required`&&!n?i(`Must start with http:// or https://`):e===`forbidden`&&n&&i(`Must not start with http:// or https://`),a},endsWith(e){if(t||!r)return a;let n=Array.isArray(e)?e:[e];return n.every(e=>!r.endsWith(e))&&i(`Must end with ${n.join(`, `)}`),a},contains(e){return!t&&r&&!r.includes(e)&&i(`Must contain "${e}"`),a},alphanumeric(){return!t&&r&&!/^[\dA-Za-z]+$/.test(r)&&i(`Only letters and numbers allowed`),a},numeric(){return!t&&r&&!/^\d+$/.test(r)&&i(`Only numbers allowed`),a},slug(){return!t&&r&&!/^[\da-z-]+$/.test(r)&&i(`Invalid slug format`),a},identifier(){return!t&&r&&!/^[A-Z_a-z]\w*$/.test(r)&&i(`Invalid identifier format`),a},getError(){return t}};return a}function va(e){let t=``,n=e==null||Number.isNaN(e),r=e=>{t||=e},i={required(){return!t&&n&&r(`Required`),i},requiredIf(e){return e&&!t&&n&&r(`Required`),i},min(a){return n||!t&&ea&&r(`Maximum ${a}`),i},between(a,o){return n||!t&&(eo)&&r(`Must be between ${a} and ${o}`),i},integer(){return n||!t&&!Number.isSafeInteger(e)&&r(`Must be an integer`),i},positive(){return n||!t&&e<=0&&r(`Must be positive`),i},negative(){return n||!t&&e>=0&&r(`Must be negative`),i},nonNegative(){return n||!t&&e<0&&r(`Must be non-negative`),i},notZero(){return n||!t&&e===0&&r(`Must not be zero`),i},multipleOf(a){return n||!t&&!pa(e,a)&&r(`Must be a multiple of ${a}`),i},step(e){return i.multipleOf(e)},decimal(a){return n||!t&&fa(e)>a&&r(`Maximum ${a} decimal places`),i},percentage(){return n||!t&&(e<0||e>100)&&r(`Must be between 0 and 100`),i},getError(){return t}};return i}function ya(e){let t=``,n=e==null,r=e??[],i=e=>{t||=e},a={required(){return!t&&(n||r.length===0)&&i(`Required`),a},requiredIf(e){return e&&!t&&(n||r.length===0)&&i(`Required`),a},minLength(e){return n||!t&&r.lengthe&&i(`Maximum ${e} items`),a},unique(){if(n||t)return a;let e=new Set;for(let t of r){let n=ha(t);if(e.has(n)){i(`Items must be unique`);break}e.add(n)}return a},ofLength(e){return n||!t&&r.length!==e&&i(`Must have exactly ${e} items`),a},includes(e){if(n||t)return a;let o=ha(e);return r.some(e=>ha(e)===o)||i(`Must include ${ga(e)}`),a},includesAny(e){if(n||t)return a;let o=new Set(e.map(e=>ha(e)));return r.some(e=>o.has(ha(e)))||i(`Must include at least one of: ${e.map(e=>ga(e)).join(`, `)}`),a},includesAll(e){if(n||t)return a;let o=new Set(r.map(e=>ha(e))),s=e.filter(e=>!o.has(ha(e)));return s.length>0&&i(`Missing required items: ${s.map(e=>ga(e)).join(`, `)}`),a},getError(){return t}};return a}var ba=U(`
`),xa=U(`
 
`);function J(e,t){var n=xa(),r=F(n),i=e=>{var n=ba(),r=F(n,!0);k(n),R(()=>G(r,t.title)),W(e,n)};K(r,e=>{t.title&&e(i)});var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>G(o,t.code)),W(e,n)}var Sa=U(`
Dirty Fields
 
`),Ca=U(`
State Object
 
State Info
isDirty:
hasErrors:
Errors
 
`);function wa(e,t){We(t,!0);let n=ki(t,`width`,3,`xl:w-80`);var r=Ca(),i=F(r),a=L(F(i),2),o=F(a,!0);k(a),k(i);var s=L(i,2),c=L(F(s),2),l=F(c),u=L(F(l));k(l);var f=L(l,2),p=L(F(f));k(f),k(c),k(s);var m=L(s,2),h=e=>{var n=Sa(),r=L(F(n),2),i=F(r,!0);k(r),k(n),R(e=>G(i,e),[()=>JSON.stringify(t.isDirtyByField,Object.keys(t.isDirtyByField).toSorted((e,t)=>e.localeCompare(t)),2)]),W(e,n)};K(m,e=>{t.isDirtyByField&&e(h)});var g=L(m,2),_=L(F(g),2),v=F(_,!0);k(_),k(g);var y=L(g,2);si(L(y,2),()=>t.extra??d),k(r),R((e,i)=>{ui(r,1,`w-full ${n()??``} flex-shrink-0 space-y-4`),G(o,e),G(u,` ${t.isDirty??``}`),G(p,` ${t.hasErrors??``}`),G(v,i)},[()=>JSON.stringify(t.data,void 0,2),()=>JSON.stringify(t.errors,void 0,2)]),H(`click`,y,function(...e){t.onFill?.apply(this,e)}),W(e,r),Ge()}Nr([`click`]);var Ta=U(`

`);function Ea(e,t){var n=Ur(),r=I(n),i=e=>{var n=Ta(),r=F(n,!0);k(n),R(()=>G(r,t.error)),W(e,n)};K(r,e=>{t.error&&e(i)}),W(e,n)}var Da=U(``),Oa=U(`
`);function Y(e,t){We(t,!0);let n=ki(t,`type`,3,`text`),r=ki(t,`placeholder`,3,``),i=ki(t,`value`,15),a=ki(t,`error`,3,``),o=ki(t,`required`,3,!0),s=ki(t,`disabled`,3,!1),c=ki(t,`variant`,3,`default`),l=j(()=>c()===`nested`?`bg-white`:`bg-gray-50`);var u=Oa(),d=F(u),f=F(d),p=L(f),m=e=>{W(e,Da())};K(p,e=>{t.isDirty&&e(m)}),k(d);var h=L(d,2);vi(h);var g=L(h,2);{let e=j(()=>a()??``);Ea(g,{get error(){return V(e)}})}k(u),R(()=>{ui(d,1,`mb-2 block text-sm text-gray-900 ${o()?`font-bold`:``}`),yi(d,`for`,t.id),G(f,`${t.label??``} `),yi(h,`id`,t.id),ui(h,1,`block w-full rounded-lg border p-2.5 text-sm ${a()?`border-red-500 bg-red-50 text-red-900 placeholder-red-400 focus:border-red-500 focus:ring-red-500`:`border-gray-300 ${V(l)} text-gray-900 focus:border-blue-500 focus:ring-blue-500`} ${s()?`cursor-not-allowed opacity-50`:``}`),h.disabled=s(),yi(h,`max`,t.max),yi(h,`min`,t.min),yi(h,`placeholder`,r()),yi(h,`step`,t.step),yi(h,`type`,n())}),Ci(h,i),W(e,u),Ge()}var ka=U(`

`),Aa=U(`
`),ja=U(`
`,1);function Ma(e,t){var n=ja(),r=I(n),i=F(r),a=F(i),o=F(a,!0);k(a);var s=L(a,2),c=e=>{var n=ka(),r=F(n,!0);k(n),R(()=>G(r,t.description)),W(e,n)},l=e=>{W(e,Aa())};K(s,e=>{t.description?e(c):e(l,-1)}),si(L(s,2),()=>t.main),k(i),si(L(i,2),()=>t.sidebar),k(r);var u=L(r,2),d=e=>{var n=Ur();si(I(n),()=>t.sourceCode),W(e,n)};K(u,e=>{t.sourceCode&&e(d)}),R(()=>G(o,t.title)),W(e,n)}var Na=U(`
`),Pa=U(`
`);function Fa(e,t){let n=N(!1);var r=Pa(),i=F(r),a=L(F(i),2);k(i);var o=L(i,2),s=e=>{var n=Na();si(F(n),()=>t.children),k(n),W(e,n)};K(o,e=>{V(n)&&e(s)}),k(r),R(()=>{ui(i,1,`flex w-full cursor-pointer items-center justify-between px-4 py-3 text-left text-sm font-medium text-gray-900 hover:bg-gray-50 ${V(n)?`border-b border-gray-200`:``}`),ui(a,0,`h-5 w-5 transform transition-transform ${V(n)?`rotate-180`:``}`)}),H(`click`,i,()=>P(n,!V(n))),W(e,r)}Nr([`click`]);var Ia=Vr(``);function La(e,t){let n=ki(t,`class`,3,`h-4 w-4`);var r=Ia();R(()=>ui(r,0,`${n()??``} animate-spin`)),W(e,r)}var Ra=U(`
`);function za(e,t){var n=Ra(),r=F(n),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{ui(r,1,`rounded px-2.5 py-0.5 text-xs font-medium ${t.hasErrors?`bg-red-100 text-red-800`:`bg-green-100 text-green-800`}`),G(i,t.hasErrors?`Has Errors`:`Valid`),ui(a,1,`rounded px-2.5 py-0.5 text-xs font-medium ${t.isDirty?`bg-yellow-100 text-yellow-800`:`bg-gray-100 text-gray-800`}`),G(o,t.isDirty?`Modified`:`Clean`)}),W(e,n)}var X=()=>Math.random().toString(36).slice(2,8),Ba=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,Va=e=>e.charAt(0).toUpperCase()+e.slice(1).replaceAll(/([A-Z])/g,` $1`),Ha=U(`
`),Ua=U(`
`),Wa=U(` Submitting...`),Ga=U(`
`,1),Ka=U(`
Action State
actionInProgress:
actionError:
`),qa=U(` `,1);function Ja(e,t){We(t,!0);let n=()=>A(g,`$hasErrors`,s),r=()=>A(_,`$isDirty`,s),i=()=>A(v,`$actionInProgress`,s),a=()=>A(h,`$errors`,s),o=()=>A(y,`$actionError`,s),[s,c]=ft(),l={title:`Task ${X()}`,description:`This is a sample task description with ID ${X()}`},u=N(!1),d=N(void 0),{data:f,batch:p,execute:m,state:{errors:h,hasErrors:g,isDirty:_,actionInProgress:v,actionError:y}}=ua(l,{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(3).maxLength(50).getError(),description:q(e.description).prepare(`trim`).required().minLength(10).maxLength(200).getError()}),action:async()=>{let e=Ba(100,1e3);if(await new Promise(t=>setTimeout(t,e)),V(u))throw Error(`Simulated server error after ${e}ms`);P(d,`Submitted successfully in ${e}ms!`)},actionCompleted:e=>{e&&P(d,void 0)}}),b=()=>{p(e=>{e.title=`Task ${X()}`,e.description=`This is a sample task description with ID ${X()}`})},x=()=>{P(d,void 0),m()};Ma(e,{description:`Demonstrates async action execution with loading states and error handling.`,title:`Action Demo`,main:e=>{var t=Ga(),s=I(t);za(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=F(c),p=F(l,!0);k(l),k(c);var m=L(c,2),h=F(m);{let e=j(()=>a()?.title);Y(h,{id:`title`,get disabled(){return i()},get error(){return V(e)},label:`Title`,placeholder:`Enter task title`,get value(){return f.title},set value(e){f.title=e}})}var g=L(h,2);{let e=j(()=>a()?.description);Y(g,{id:`description`,get disabled(){return i()},get error(){return V(e)},label:`Description`,placeholder:`Enter task description (min 10 characters)`,get value(){return f.description},set value(e){f.description=e}})}var _=L(g,2),v=F(_);vi(v),Pe(2),k(_),k(m);var y=L(m,2),b=e=>{var t=Ha(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,o().message)),W(e,t)};K(y,e=>{o()&&e(b)});var S=L(y,2),C=e=>{var t=Ua(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,V(d))),W(e,t)};K(S,e=>{V(d)&&e(C)});var w=L(S,2),T=F(w),E=F(T),ee=e=>{var t=Wa();La(F(t),{}),Pe(),k(t),W(e,t)},te=e=>{W(e,Hr(`Submit`))};K(E,e=>{i()?e(ee):e(te,-1)}),k(T),k(w),R(()=>{ui(l,1,`rounded px-2.5 py-0.5 text-xs font-medium ${i()?`bg-blue-100 text-blue-800`:`bg-gray-100 text-gray-800`}`),G(p,i()?`In Progress`:`Idle`),v.disabled=i(),T.disabled=n()||i()}),wi(v,()=>V(u),e=>P(u,e)),H(`click`,T,x),W(e,t)},sidebar:e=>{wa(e,{get data(){return f},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:b,extra:e=>{var t=Ka(),n=L(F(t),2),r=F(n),a=L(F(r));k(r);var s=L(r,2),c=L(F(s));k(s),k(n),k(t),R(()=>{G(a,` ${i()??``}`),G(c,` ${o()?.message??`none`??``}`)}),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=qa(),r=I(n);J(r,{code:`const { data, batch, execute, state: { errors, hasErrors, isDirty, actionInProgress, actionError } } = + createSvState(sourceData, { + validator: (source) => ({ + title: stringValidator(source.title).prepare('trim').required().minLength(3).maxLength(50).getError(), + description: stringValidator(source.description).prepare('trim').required().minLength(10).getError() + }), + action: async () => { + // Simulate API call with 100-1000ms delay + const delay = randomInt(100, 1000); + await new Promise((resolve) => setTimeout(resolve, delay)); + + if (shouldFail) { + throw new Error('Simulated server error'); + } + }, + actionCompleted: (error) => { + // Called after action completes (success or failure) + console.log(error ? 'Action failed' : 'Action succeeded'); + } + });`,title:`State Setup with Action`});var i=L(r,2);J(i,{code:`// One validation pass for the whole fill +const fillWithValidData = () => { + batch((draft) => { + draft.title = 'Task 1'; + draft.description = 'A sample task description.'; + }); +};`,title:`Batching Fill Updates`});var a=L(i,2);J(a,{code:`// Execute the action + + +// With parameters (if action accepts them) +execute({ userId: 123 });`,title:`Execute Action`}),J(L(a,2),{code:`// Display action error +{#if $actionError} +
+ {$actionError.message} +
+{/if} + +// Check if action is in progress +{#if $actionInProgress} +
Submitting...
+{/if}`,title:`Error & Loading States`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var Ya=U(`
`);function Xa(e,t){let n=ki(t,`label`,3,`Item`);var r=Ya(),i=F(r),a=F(i),o=F(a);k(a);var s=L(a,2);k(i),si(L(i,2),()=>t.children),k(r),R(()=>G(o,`${n()??``} #${t.index+1}`)),H(`click`,s,function(...e){t.onRemove?.apply(this,e)}),W(e,r)}Nr([`click`]);var Za=U(`

`);function Qa(e,t){var n=Za(),r=F(n),i=F(r,!0);k(r),k(n),R(()=>G(i,t.message)),W(e,n)}var $a=U(`
`),eo=U(`
`),to=U(`
`),no=U(`
Contacts
`,1),ro=U(` `,1);function io(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,a),r=()=>A(d,`$isDirty`,a),i=()=>A(l,`$errors`,a),[a,o]=ft(),{data:s,batch:c,state:{errors:l,hasErrors:u,isDirty:d}}=ua({listName:``,items:[]},{validator:e=>({listName:q(e.listName).prepare(`trim`).required().minLength(2).getError(),items:ya(e.items).required().minLength(1).getError(),...Object.fromEntries(e.items.map((e,t)=>[`item_${t}`,{name:q(e.name).prepare(`trim`).required().minLength(2).getError(),email:q(e.email).prepare(`trim`).required().email().getError()}]))})}),f=()=>{s.items=[...s.items,{name:``,email:``}]},p=e=>{s.items=s.items.filter((t,n)=>n!==e)},m=()=>{c(e=>{e.listName=`Contact List ${X()}`,e.items=[{name:`John Doe`,email:`john@example.com`},{name:`Jane Smith`,email:`jane@example.com`},{name:`Bob Wilson`,email:`bob@example.com`}]})};Ma(e,{description:`Shows how to validate dynamic arrays with per-item validation using indexed error keys.`,title:`Array Property Demo`,main:e=>{var t=no(),a=I(t);za(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.listName);Y(c,{id:`listName`,get error(){return V(e)},label:`List Name`,placeholder:`Enter list name`,get value(){return s.listName},set value(e){s.listName=e}})}var l=L(c,2),u=F(l),d=F(u),m=L(F(d)),h=F(m);k(m),k(d);var g=L(d,2);k(u);var _=L(u,2),v=e=>{var t=$a();Ea(F(t),{get error(){return i().items}}),k(t),W(e,t)};K(_,e=>{i()?.items&&e(v)});var y=L(_,2),b=e=>{Qa(e,{message:`No contacts yet. Click "Add Contact" to get started.`})},x=e=>{var t=to();ti(t,21,()=>s.items,Zr,(e,t,n)=>{Xa(e,{index:n,label:`Contact`,onRemove:()=>p(n),children:(e,r)=>{var a=eo(),o=F(a),s=F(o);yi(s,`for`,`item-name-${n}`);var c=L(s,2);vi(c),yi(c,`id`,`item-name-${n}`);var l=L(c,2);{let e=j(()=>i()?.[`item_${n}`]?.name??``);Ea(l,{get error(){return V(e)}})}k(o);var u=L(o,2),d=F(u);yi(d,`for`,`item-email-${n}`);var f=L(d,2);vi(f),yi(f,`id`,`item-email-${n}`);var p=L(f,2);{let e=j(()=>i()?.[`item_${n}`]?.email??``);Ea(p,{get error(){return V(e)}})}k(u),k(a),R(()=>{ui(c,1,`block w-full rounded-lg border p-2 text-sm ${i()?.[`item_${n}`]?.name?`border-red-500 bg-red-50 text-red-900 placeholder-red-400`:`border-gray-300 bg-white text-gray-900`}`),ui(f,1,`block w-full rounded-lg border p-2 text-sm ${i()?.[`item_${n}`]?.email?`border-red-500 bg-red-50 text-red-900 placeholder-red-400`:`border-gray-300 bg-white text-gray-900`}`)}),Ci(c,()=>V(t).name,e=>V(t).name=e),Ci(f,()=>V(t).email,e=>V(t).email=e),W(e,a)},$$slots:{default:!0}})}),k(t),W(e,t)};K(y,e=>{s.items.length===0?e(b):e(x,-1)}),k(l),k(o),R(()=>G(h,`${s.items.length??``} items`)),H(`click`,g,f),W(e,t)},sidebar:e=>{wa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:m,width:`xl:w-96`})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=ro(),r=I(n);J(r,{code:`const sourceData = { + listName: '', + items: [] as { name: string; email: string }[] +}; + +const { data, batch, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { + validator: (source) => ({ + listName: stringValidator(source.listName).prepare('trim').required().minLength(2).getError(), + items: arrayValidator(source.items).required().minLength(1).getError(), + // Per-item validation using indexed keys + ...Object.fromEntries( + source.items.map((item, index) => [ + \`item_\${index}\`, + { + name: stringValidator(item.name).prepare('trim').required().minLength(2).getError(), + email: stringValidator(item.email).prepare('trim').required().email().getError() + } + ]) + ) + }) +});`,title:`State Setup with Array Item Validation`});var i=L(r,2);J(i,{code:`// batch() runs one validation pass for the name + whole array swap +batch((draft) => { + draft.listName = 'Contact List'; + draft.items = [{ name: 'John Doe', email: 'john@example.com' }]; +});`,title:`Batching listName + items`}),J(L(i,2),{code:`// Define type for item errors +type ItemErrors = Record; + +{#each data.items as item, index} + + + + + +{/each}`,title:`Array Form Binding Examples`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]),Ve();var ao=U(`
`),oo=U(` Validating...`),so=U(`
Taken usernames:
Taken emails:
Taken slugs:
Concurrency limit: maxConcurrentAsyncValidations = 2
Only 2 async validations run simultaneously. Try filling all 3 fields at once to see queuing in action.
`,1),co=U(`
Quick Fill
Async Validation State
asyncValidating:
hasAsyncErrors:
hasCombinedErrors:
Async Errors
 
`,1),lo=U(` `,1);function uo(e,t){We(t,!1);let n=()=>A(v,`$hasErrors`,l),r=()=>A(y,`$isDirty`,l),i=()=>A(x,`$hasAsyncErrors`,l),a=()=>A(C,`$hasCombinedErrors`,l),o=()=>A(_,`$errors`,l),s=()=>A(b,`$asyncErrors`,l),c=()=>A(S,`$asyncValidating`,l),[l,u]=ft(),d=[`admin`,`user`,`test`,`demo`,`root`],f=[`admin@example.com`,`test@example.com`,`user@example.com`],p=[`admin`,`about`,`contact`,`help`,`support`],m=ua({username:``,email:``,slug:``},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(3).maxLength(20).noSpace().getError(),email:q(e.email).prepare(`trim`).required().email().getError(),slug:q(e.slug).prepare(`trim`).required().minLength(2).slug().getError()}),asyncValidator:{username:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,500);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return d.includes(r)?`Username is already taken`:``},email:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,400);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return f.includes(r)?`Email is already registered`:``},slug:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,600);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return p.includes(r)?`URL slug is already in use`:``}}},{maxConcurrentAsyncValidations:2}),h=an(m.data),g=m.batch,_=m.state.errors,v=m.state.hasErrors,y=m.state.isDirty,b=m.state.asyncErrors,x=m.state.hasAsyncErrors,S=m.state.asyncValidating,C=m.state.hasCombinedErrors,w=()=>{g(e=>{e.username=`newuser${X()}`,e.email=`${X()}@example.com`,e.slug=`my-page-${X()}`})},T=()=>{g(e=>{e.username=`admin`,e.email=`admin@example.com`,e.slug=`about`})};Di(),Ma(e,{description:`Demonstrates async validation with simulated API calls for username and email uniqueness checks.`,title:`Async Validation Demo`,main:e=>{var t=so(),l=I(t);za(l,{get hasErrors(){return n()},get isDirty(){return r()}});var u=L(l,2),m=F(u),g=F(m);k(m);var _=L(m,2),v=F(_);k(_),k(u);var y=L(u,2),b=F(y),x=F(b);{let e=At(()=>o()?.username||s().username);Y(x,{id:`username`,get error(){return V(e)},label:`Username`,placeholder:`Enter username (try 'admin', 'user', 'test')`,get value(){return V(h).username},set value(e){on(h,V(h).username=e)},$$legacy:!0})}var S=L(x,2),C=e=>{var t=ao();La(F(t),{class:`h-5 w-5 text-blue-500`}),k(t),W(e,t)},w=j(()=>c().includes(`username`));K(S,e=>{V(w)&&e(C)}),k(b);var T=L(b,2),E=F(T);{let e=At(()=>o()?.email||s().email);Y(E,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email (try 'admin@example.com')`,type:`email`,get value(){return V(h).email},set value(e){on(h,V(h).email=e)},$$legacy:!0})}var ee=L(E,2),te=e=>{var t=ao();La(F(t),{class:`h-5 w-5 text-blue-500`}),k(t),W(e,t)},ne=j(()=>c().includes(`email`));K(ee,e=>{V(ne)&&e(te)}),k(T);var re=L(T,2),ie=F(re);{let e=At(()=>o()?.slug||s().slug);Y(ie,{id:`slug`,get error(){return V(e)},label:`URL Slug`,placeholder:`Enter slug (try 'admin', 'about', 'contact')`,get value(){return V(h).slug},set value(e){on(h,V(h).slug=e)},$$legacy:!0})}var ae=L(ie,2),oe=e=>{var t=ao();La(F(t),{class:`h-5 w-5 text-blue-500`}),k(t),W(e,t)},se=j(()=>c().includes(`slug`));K(ae,e=>{V(se)&&e(oe)}),k(re),k(y);var ce=L(y,2),le=F(ce),ue=L(F(le));k(le);var de=L(le,2),fe=L(F(de));k(de);var pe=L(de,2),me=L(F(pe));k(pe),k(ce);var he=L(ce,4),ge=F(he),_e=F(ge),ve=e=>{var t=oo();La(F(t),{}),Pe(),k(t),W(e,t)},ye=e=>{W(e,Hr(`Submit`))};K(_e,e=>{c().length>0?e(ve):e(ye,-1)}),k(ge),k(he),R((e,t,n)=>{ui(m,1,`rounded px-2.5 py-0.5 text-xs font-medium ${i()?`bg-red-100 text-red-800`:`bg-gray-100 text-gray-800`}`),G(g,`Async Errors: ${i()?`Yes`:`No`}`),ui(_,1,`rounded px-2.5 py-0.5 text-xs font-medium ${a()?`bg-red-100 text-red-800`:`bg-green-100 text-green-800`}`),G(v,`Combined: ${a()?`Has Errors`:`Valid`}`),G(ue,` ${e??``}`),G(fe,` ${t??``}`),G(me,` ${n??``}`),ge.disabled=a()||c().length>0},[()=>d.join(`, `),()=>f.join(`, `),()=>p.join(`, `)]),W(e,t)},sidebar:e=>{wa(e,{get data(){return V(h)},get errors(){return o()},get hasErrors(){return n()},get isDirty(){return r()},onFill:w,extra:e=>{var t=co(),n=I(t),r=L(F(n),2);k(n);var o=L(n,2),l=L(F(o),2),u=F(l),d=L(F(u));k(u);var f=L(u,2),p=L(F(f));k(f);var m=L(f,2),h=L(F(m));k(m),k(l),k(o);var g=L(o,2),_=L(F(g),2),v=F(_,!0);k(_),k(g),R((e,t)=>{G(d,` [${e??``}]`),G(p,` ${i()??``}`),G(h,` ${a()??``}`),G(v,t)},[()=>c().join(`, `),()=>JSON.stringify(s(),void 0,2)]),H(`click`,r,T),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=lo(),r=I(n);J(r,{code:`const { data, batch, state: { errors, asyncErrors, asyncValidating, hasCombinedErrors } } = + createSvState(sourceData, { + validator: (source) => ({ + username: stringValidator(source.username).required().minLength(3).noSpace().getError(), + email: stringValidator(source.email).required().email().getError(), + slug: stringValidator(source.slug).required().minLength(2).slug().getError() + }), + asyncValidator: { + username: async (value, source, signal) => { + const res = await fetch(\`/api/check-username?u=\${value}\`, { signal }); + return (await res.json()).available ? '' : 'Username already taken'; + }, + email: async (value, source, signal) => { + const res = await fetch(\`/api/check-email?e=\${value}\`, { signal }); + return (await res.json()).available ? '' : 'Email already registered'; + }, + slug: async (value, source, signal) => { + const res = await fetch(\`/api/check-slug?s=\${value}\`, { signal }); + return (await res.json()).available ? '' : 'URL slug already in use'; + } + } + }, + { maxConcurrentAsyncValidations: 2 } // Only 2 async validations run at a time +);`,title:`State Setup with Async Validators`});var i=L(r,2);J(i,{code:`// One sync validation pass, and each async validator scheduled +// at most once — instead of three separate rounds +batch((draft) => { + draft.username = 'newuser'; + draft.email = 'newuser@example.com'; + draft.slug = 'my-page'; +});`,title:`Batching Field Updates`});var a=L(i,2);J(a,{code:` +{#if $asyncValidating.includes('username')} + ... +{/if} + + +{#if $asyncErrors.username} + {$asyncErrors.username} +{/if} + + +`,title:`Template Usage`}),J(L(a,2),{code:`// Available stores for async validation: +$errors // Sync validation errors (nested object) +$hasErrors // true if any sync errors + +$asyncErrors // Async validation errors (flat map by path) +$hasAsyncErrors // true if any async errors + +$asyncValidating // Array of paths currently being validated +$hasCombinedErrors // hasErrors || hasAsyncErrors`,title:`Available Stores`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),u()}Nr([`click`]);var fo=U(``),po=U(`
`);function mo(e,t){We(t,!0);let n=ki(t,`placeholder`,3,``),r=ki(t,`value`,15),i=ki(t,`error`,3,``),a=ki(t,`required`,3,!1),o=ki(t,`rows`,3,3);var s=po(),c=F(s),l=F(c),u=L(l),d=e=>{W(e,fo())};K(u,e=>{t.isDirty&&e(d)}),k(c);var f=L(c,2);mt(f);var p=L(f,2);{let e=j(()=>i()??``);Ea(p,{get error(){return V(e)}})}k(s),R(()=>{ui(c,1,`mb-2 block text-sm text-gray-900 ${a()?`font-bold`:``}`),yi(c,`for`,t.id),G(l,`${t.label??``} `),yi(f,`id`,t.id),ui(f,1,`block w-full rounded-lg border p-2.5 text-sm ${i()?`border-red-500 bg-red-50 text-red-900 placeholder-red-400 focus:border-red-500 focus:ring-red-500`:`border-gray-300 bg-gray-50 text-gray-900 focus:border-blue-500 focus:ring-blue-500`}`),yi(f,`placeholder`,n()),yi(f,`rows`,o())}),Ci(f,r),W(e,s),Ge()}var ho=U(`
`,1),go=U(` `,1);function _o(e,t){We(t,!0);let n=()=>A(d,`$hasErrors`,o),r=()=>A(f,`$isDirty`,o),i=()=>A(u,`$errors`,o),a=()=>A(p,`$isDirtyByField`,o),[o,s]=ft(),{data:c,batch:l,state:{errors:u,hasErrors:d,isDirty:f,isDirtyByField:p}}=ua({username:``,email:``,age:0,bio:``,website:``},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(3).maxLength(20).noSpace().getError(),email:q(e.email).prepare(`trim`).required().email().getError(),age:va(e.age).required().min(18).max(120).integer().getError(),bio:q(e.bio).maxLength(200).getError(),website:q(e.website).prepare(`trim`).website(`required`).getError()})}),m=()=>{l(e=>{e.username=`user${X()}`,e.email=`${X()}@example.com`,e.age=Ba(18,65),e.bio=`Hello, I am a demo user!`,e.website=`https://${X()}.com`})};Ma(e,{description:`Demonstrates form validation with string, number, and email validators using the fluent API.`,title:`Basic Validation Demo`,main:e=>{var t=ho(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s);{let e=j(()=>i()?.username);Y(l,{id:`username`,get error(){return V(e)},get isDirty(){return a().username},label:`Username`,placeholder:`Enter username`,get value(){return c.username},set value(e){c.username=e}})}var u=L(l,2);{let e=j(()=>i()?.email);Y(u,{id:`email`,get error(){return V(e)},get isDirty(){return a().email},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return c.email},set value(e){c.email=e}})}var d=L(u,2);{let e=j(()=>i()?.age);Y(d,{id:`age`,get error(){return V(e)},get isDirty(){return a().age},label:`Age`,placeholder:`Enter age`,type:`number`,get value(){return c.age},set value(e){c.age=e}})}var f=L(d,2);{let e=j(()=>i()?.bio);mo(f,{id:`bio`,get error(){return V(e)},get isDirty(){return a().bio},label:`Bio`,placeholder:`Tell us about yourself`,get value(){return c.bio},set value(e){c.bio=e}})}var p=L(f,2);{let e=j(()=>i()?.website);Y(p,{id:`website`,get error(){return V(e)},get isDirty(){return a().website},label:`Website`,placeholder:`https://example.com`,required:!1,get value(){return c.website},set value(e){c.website=e}})}k(s),W(e,t)},sidebar:e=>{wa(e,{get data(){return c},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return a()},onFill:m})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=go(),r=I(n);J(r,{code:`const sourceData = { + username: '', + email: '', + age: 0, + bio: '', + website: '' +}; + +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { + validator: (source) => ({ + username: stringValidator(source.username).prepare('trim').required().minLength(3).maxLength(20).noSpace().getError(), + email: stringValidator(source.email).prepare('trim').required().email().getError(), + age: numberValidator(source.age).required().min(18).max(120).integer().getError(), + bio: stringValidator(source.bio).maxLength(200).getError(), + website: stringValidator(source.website).prepare('trim').website('required').getError() + }) +});`,title:`State Setup`});var i=L(r,2);J(i,{code:`// batch() applies many mutations as one unit: +// one validation pass instead of five +const fillWithValidData = () => { + batch((draft) => { + draft.username = 'user123'; + draft.email = 'user123@example.com'; + draft.age = 30; + draft.bio = 'Hello, I am a demo user!'; + draft.website = 'https://user123.com'; + }); +};`,title:`Batching Multiple Field Updates`}),J(L(i,2),{code:` +`,title:`Form Binding Example`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var vo=U(` `),yo=U(`
`);function bo(e,t){var n=yo(),r=F(n),i=L(r),a=e=>{var n=vo(),r=F(n);k(n),R(()=>G(r,`(${t.subtitle??``})`)),W(e,n)};K(i,e=>{t.subtitle&&e(a)});var o=L(i,2),s=e=>{var n=Ur();si(I(n),()=>t.children),W(e,n)};K(o,e=>{t.children&&e(s)}),k(n),R(()=>G(r,`${t.title??``} `)),W(e,n)}var xo=U(`
Subtotal:
Tax (8%):
Total:

Values formatted using methods on state: data.formatCurrency() and data.formatTotal()

`,1),So=U(` `,1);function Co(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,a),r=()=>A(d,`$isDirty`,a),i=()=>A(l,`$errors`,a),[a,o]=ft(),{data:s,batch:c,state:{errors:l,hasErrors:u,isDirty:d}}=ua({productName:`Widget ${X()}`,item:{unitPrice:0,quantity:1},subtotal:0,tax:0,total:0,formatTotal(){return`$${this.total.toFixed(2)}`},formatCurrency(e){return`$${e.toFixed(2)}`},calculateTotals(e=.08){this.subtotal=this.item.unitPrice*this.item.quantity,this.tax=this.subtotal*e,this.total=this.subtotal+this.tax}},{validator:e=>({productName:q(e.productName).prepare(`trim`).required().minLength(2).getError(),item:{unitPrice:va(e.item.unitPrice).required().positive().getError(),quantity:va(e.item.quantity).required().integer().min(1).max(100).getError()}}),effect:({property:e})=>{(e===`item.unitPrice`||e===`item.quantity`)&&s.calculateTotals()}}),f=()=>{c(e=>{e.productName=`Widget ${X()}`,e.item.unitPrice=Ba(10,100),e.item.quantity=Ba(1,10)})};Ma(e,{description:`Demonstrates using objects with methods as state. The effect callback can call methods directly on the state object.`,title:`State with Methods Demo`,main:e=>{var t=xo(),a=I(t);za(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.productName);Y(c,{id:`productName`,get error(){return V(e)},label:`Product Name`,placeholder:`Enter product name`,get value(){return s.productName},set value(e){s.productName=e}})}var l=L(c,2),u=F(l);bo(u,{subtitle:`nested object`,title:`Item Details`});var d=L(u,2),f=F(d);{let e=j(()=>i()?.item?.unitPrice);Y(f,{id:`unitPrice`,get error(){return V(e)},label:`Unit Price ($)`,min:0,placeholder:`0.00`,step:.01,type:`number`,get value(){return s.item.unitPrice},set value(e){s.item.unitPrice=e}})}var p=L(f,2);{let e=j(()=>i()?.item?.quantity);Y(p,{id:`quantity`,get error(){return V(e)},label:`Quantity`,max:100,min:1,placeholder:`1`,type:`number`,get value(){return s.item.quantity},set value(e){s.item.quantity=e}})}k(d),k(l);var m=L(l,2),h=F(m);bo(h,{subtitle:`computed by method`,title:`Calculated Totals`});var g=L(h,2),_=F(g),v=F(_),y=L(F(v),2),b=F(y,!0);k(y),k(v);var x=L(v,2),S=L(F(x),2),C=F(S,!0);k(S),k(x);var w=L(x,2),T=L(F(w),2),E=F(T,!0);k(T),k(w),k(_),k(g),Pe(2),k(m),k(o),R((e,t,n)=>{G(b,e),G(C,t),G(E,n)},[()=>s.formatCurrency(s.subtotal),()=>s.formatCurrency(s.tax),()=>s.formatTotal()]),W(e,t)},sidebar:e=>{wa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:f})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=So(),r=I(n);J(r,{code:`// Define state type with methods +type SourceData = { + productName: string; + item: { unitPrice: number; quantity: number }; + subtotal: number; + tax: number; + total: number; + formatTotal: () => string; + formatCurrency: (value: number) => string; + calculateTotals: (taxRate?: number) => void; +}; + +// Create initial state as object with methods +const createSourceData = (): SourceData => ({ + productName: '', + item: { unitPrice: 0, quantity: 1 }, + subtotal: 0, + tax: 0, + total: 0, + formatTotal() { + return \`$\${this.total.toFixed(2)}\`; + }, + formatCurrency(value: number) { + return \`$\${value.toFixed(2)}\`; + }, + calculateTotals(taxRate: number = 0.08) { + this.subtotal = this.item.unitPrice * this.item.quantity; + this.tax = this.subtotal * taxRate; + this.total = this.subtotal + this.tax; + } +});`,title:`Class Definition`});var i=L(r,2);J(i,{code:`const { data, batch, state: { errors, hasErrors, isDirty } } = createSvState(createSourceData(), { + validator: (source) => ({ + productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), + item: { + unitPrice: numberValidator(source.item.unitPrice).required().positive().getError(), + quantity: numberValidator(source.item.quantity).required().integer().min(1).max(100).getError() + } + }), + effect: ({ property }) => { + if (property === 'item.unitPrice' || property === 'item.quantity') { + data.calculateTotals(); // Call method on state object! + } + } +});`,title:`State Setup with Class Instance`});var a=L(i,2);J(a,{code:`// One validation pass for the whole fill +batch((draft) => { + draft.productName = 'Widget'; + draft.item.unitPrice = 42; + draft.item.quantity = 3; +});`,title:`Batching Item Field Updates`}),J(L(a,2),{code:` +{data.formatCurrency(data.subtotal)} +{data.formatTotal()}`,title:`Template Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}var wo=U(`
Subtotal:
Tax (8%):
Total:
`,1),To=U(` `,1);function Eo(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,a),r=()=>A(d,`$isDirty`,a),i=()=>A(l,`$errors`,a),[a,o]=ft(),{data:s,batch:c,state:{errors:l,hasErrors:u,isDirty:d}}=ua({productName:`Widget ${X()}`,item:{unitPrice:0,quantity:1},subtotal:0,tax:0,total:0},{validator:e=>({productName:q(e.productName).prepare(`trim`).required().minLength(2).getError(),item:{unitPrice:va(e.item.unitPrice).required().positive().getError(),quantity:va(e.item.quantity).required().integer().min(1).max(100).getError()}}),effect:({property:e})=>{(e===`item.unitPrice`||e===`item.quantity`)&&(s.subtotal=s.item.unitPrice*s.item.quantity,s.tax=s.subtotal*.08,s.total=s.subtotal+s.tax)}}),f=()=>{c(e=>{e.productName=`Widget ${X()}`,e.item.unitPrice=Ba(10,100),e.item.quantity=Ba(1,10)})},p=e=>`$${e.toFixed(2)}`;Ma(e,{description:`Uses the effect callback to automatically compute derived values like subtotals, taxes, and totals.`,title:`Calculated Fields Demo`,main:e=>{var t=wo(),a=I(t);za(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.productName);Y(c,{id:`productName`,get error(){return V(e)},label:`Product Name`,placeholder:`Enter product name`,get value(){return s.productName},set value(e){s.productName=e}})}var l=L(c,2),u=F(l);bo(u,{subtitle:`nested object`,title:`Item Details`});var d=L(u,2),f=F(d);{let e=j(()=>i()?.item?.unitPrice);Y(f,{id:`unitPrice`,get error(){return V(e)},label:`Unit Price ($)`,min:0,placeholder:`0.00`,step:.01,type:`number`,get value(){return s.item.unitPrice},set value(e){s.item.unitPrice=e}})}var m=L(f,2);{let e=j(()=>i()?.item?.quantity);Y(m,{id:`quantity`,get error(){return V(e)},label:`Quantity`,max:100,min:1,placeholder:`1`,type:`number`,get value(){return s.item.quantity},set value(e){s.item.quantity=e}})}k(d),k(l);var h=L(l,2),g=F(h);bo(g,{subtitle:`computed by effect`,title:`Calculated Totals`});var _=L(g,2),v=F(_),y=F(v),b=L(F(y),2),x=F(b,!0);k(b),k(y);var S=L(y,2),C=L(F(S),2),w=F(C,!0);k(C),k(S);var T=L(S,2),E=L(F(T),2),ee=F(E,!0);k(E),k(T),k(v),k(_),k(h),k(o),R((e,t,n)=>{G(x,e),G(w,t),G(ee,n)},[()=>p(s.subtotal),()=>p(s.tax),()=>p(s.total)]),W(e,t)},sidebar:e=>{wa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:f})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=To(),r=I(n);J(r,{code:`const sourceData = { + productName: '', + item: { unitPrice: 0, quantity: 1 }, + subtotal: 0, tax: 0, total: 0 // Calculated fields (set by effect) +}; + +const TAX_RATE = 0.08; + +const { data, batch, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { + validator: (source) => ({ + productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), + item: { + unitPrice: numberValidator(source.item.unitPrice).required().positive().getError(), + quantity: numberValidator(source.item.quantity).required().integer().min(1).max(100).getError() + } + }), + effect: ({ property }) => { + if (property === 'item.unitPrice' || property === 'item.quantity') { + data.subtotal = data.item.unitPrice * data.item.quantity; + data.tax = data.subtotal * TAX_RATE; + data.total = data.subtotal + data.tax; + } + } +});`,title:`State Setup with Effect`});var i=L(r,2);J(i,{code:`effect: ({ property }) => { + if (property === 'item.unitPrice' || property === 'item.quantity') { + data.subtotal = data.item.unitPrice * data.item.quantity; + data.tax = data.subtotal * TAX_RATE; + data.total = data.subtotal + data.tax; + } +}`,title:`Effect Function`}),J(L(i,2),{code:`// One validation pass for the whole fill; +// effect still recalculates the totals on each field it touches +batch((draft) => { + draft.productName = 'Widget'; + draft.item.unitPrice = 42; + draft.item.quantity = 3; +});`,title:`Batching Item Field Updates`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}var Do=U(` `),Oo=U(``),ko=U(`
`);function Ao(e,t){var n=ko(),r=F(n),i=F(r),a=L(i),o=e=>{var n=Do(),r=F(n);k(n),R(()=>G(r,`(${t.subtitle??``})`)),W(e,n)};K(a,e=>{t.subtitle&&e(o)});var s=L(a,2),c=e=>{W(e,Oo())};K(s,e=>{t.isDirty&&e(c)}),k(r),si(L(r,2),()=>t.children),k(n),R(()=>G(i,`${t.title??``} `)),W(e,n)}var jo=U(``),Mo=U(`
`),No=U(`
`,1),Po=U(` `,1);function Fo(e,t){We(t,!0);let n=()=>A(d,`$hasErrors`,o),r=()=>A(f,`$isDirty`,o),i=()=>A(p,`$isDirtyByField`,o),a=()=>A(u,`$errors`,o),[o,s]=ft(),{data:c,batch:l,state:{errors:u,hasErrors:d,isDirty:f,isDirtyByField:p}}=ua({name:``,address:{street:``,city:``,zip:``},company:{name:``,department:``,contact:{phone:``,email:``}}},{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),address:{street:q(e.address.street).prepare(`trim`).required().minLength(5).getError(),city:q(e.address.city).prepare(`trim`).required().minLength(2).getError(),zip:q(e.address.zip).prepare(`trim`).required().minLength(5).maxLength(10).getError()},company:{name:q(e.company.name).prepare(`trim`).required().minLength(2).getError(),department:q(e.company.department).prepare(`trim`).maxLength(50).getError(),contact:{phone:q(e.company.contact.phone).prepare(`trim`).required().minLength(10).getError(),email:q(e.company.contact.email).prepare(`trim`).required().email().getError()}}})}),m=()=>{l(e=>{e.name=`John ${X()}`,e.address.street=`${Ba(100,9999)} Main Street`,e.address.city=`New York`,e.address.zip=String(Ba(1e4,99999)),e.company.name=`Acme ${X()} Inc`,e.company.department=`Engineering`,e.company.contact.phone=`555-${Ba(100,999)}-${Ba(1e3,9999)}`,e.company.contact.email=`contact@${X()}.com`})};Ma(e,{description:`Illustrates validating deeply nested object structures with multi-level property paths.`,title:`Nested Objects Demo`,main:e=>{var t=No(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),u=F(l);bo(u,{title:`Personal Info`,children:(e,t)=>{var n=Ur(),r=I(n),a=e=>{W(e,jo())};K(r,e=>{i().name&&e(a)}),W(e,n)},$$slots:{default:!0}});var d=L(u,2);{let e=j(()=>a()?.name);Y(d,{id:`name`,get error(){return V(e)},label:`Full Name`,placeholder:`Enter your full name`,get value(){return c.name},set value(e){c.name=e}})}k(l);var f=L(l,2),p=F(f);bo(p,{subtitle:`2-level nested`,title:`Address`,children:(e,t)=>{var n=Ur(),r=I(n),a=e=>{W(e,jo())};K(r,e=>{i().address&&e(a)}),W(e,n)},$$slots:{default:!0}});var m=L(p,2),h=F(m);{let e=j(()=>a()?.address?.street);Y(h,{id:`street`,get error(){return V(e)},label:`Street`,placeholder:`Enter street address`,get value(){return c.address.street},set value(e){c.address.street=e}})}var g=L(h,2),_=F(g);{let e=j(()=>a()?.address?.city);Y(_,{id:`city`,get error(){return V(e)},label:`City`,placeholder:`Enter city`,get value(){return c.address.city},set value(e){c.address.city=e}})}var v=L(_,2);{let e=j(()=>a()?.address?.zip);Y(v,{id:`zip`,get error(){return V(e)},label:`ZIP Code`,placeholder:`Enter ZIP`,get value(){return c.address.zip},set value(e){c.address.zip=e}})}k(g),k(m),k(f);var y=L(f,2),b=F(y);bo(b,{subtitle:`3-level nested`,title:`Company`,children:(e,t)=>{var n=Ur(),r=I(n),a=e=>{W(e,jo())};K(r,e=>{i().company&&e(a)}),W(e,n)},$$slots:{default:!0}});var x=L(b,2),S=F(x),C=F(S);{let e=j(()=>a()?.company?.name);Y(C,{id:`company-name`,get error(){return V(e)},label:`Company Name`,placeholder:`Enter company name`,get value(){return c.company.name},set value(e){c.company.name=e}})}var w=L(C,2);{let e=j(()=>a()?.company?.department);Y(w,{id:`department`,get error(){return V(e)},label:`Department`,placeholder:`Enter department`,required:!1,get value(){return c.company.department},set value(e){c.company.department=e}})}k(S),Ao(L(S,2),{get isDirty(){return i()[`company.contact`]},subtitle:`3rd level`,title:`Contact Info`,children:(e,t)=>{var n=Mo(),r=F(n);{let e=j(()=>a()?.company?.contact?.phone);Y(r,{id:`contact-phone`,get error(){return V(e)},label:`Phone`,placeholder:`Enter phone number`,variant:`nested`,get value(){return c.company.contact.phone},set value(e){c.company.contact.phone=e}})}var i=L(r,2);{let e=j(()=>a()?.company?.contact?.email);Y(i,{id:`contact-email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email address`,type:`email`,variant:`nested`,get value(){return c.company.contact.email},set value(e){c.company.contact.email=e}})}k(n),W(e,n)},$$slots:{default:!0}}),k(x),k(y),k(s),W(e,t)},sidebar:e=>{wa(e,{get data(){return c},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return i()},onFill:m,width:`xl:w-96`})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=Po(),r=I(n);J(r,{code:`const sourceData = { + name: '', + address: { street: '', city: '', zip: '' }, // 2-level nested + company: { // 3-level nested + name: '', + department: '', + contact: { phone: '', email: '' } + } +}; + +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { + validator: (source) => ({ + name: stringValidator(source.name).prepare('trim').required().minLength(2).maxLength(50).getError(), + address: { + street: stringValidator(source.address.street).prepare('trim').required().minLength(5).getError(), + city: stringValidator(source.address.city).prepare('trim').required().minLength(2).getError(), + zip: stringValidator(source.address.zip).prepare('trim').required().minLength(5).maxLength(10).getError() + }, + company: { + name: stringValidator(source.company.name).prepare('trim').required().minLength(2).getError(), + department: stringValidator(source.company.department).prepare('trim').maxLength(50).getError(), + contact: { + phone: stringValidator(source.company.contact.phone).prepare('trim').required().minLength(10).getError(), + email: stringValidator(source.company.contact.email).prepare('trim').required().email().getError() + } + } + }) +});`,title:`State Setup with Nested Validation`});var i=L(r,2);J(i,{code:`// batch() runs validation once for the whole nested fill, +// instead of once per touched field (8 fields here) +batch((draft) => { + draft.name = 'John Doe'; + draft.address.street = '123 Main Street'; + draft.address.city = 'New York'; + draft.company.contact.email = 'contact@acme.com'; + // ... +});`,title:`Batching Nested Field Updates`}),J(L(i,2),{code:` + + + + + +`,title:`Nested Form Binding Examples`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var Io=U(`
Effect triggered:
`),Lo=U(`
`),Ro=U(`
`),zo=U(` Submitting...`),Bo=U(`
`,1),Vo=U(`

`),Ho=U(`
Options

Reset isDirty after successful action

Try 500ms and type quickly

Keep errors until next action

Current Options
`,1),Uo=U(` `,1);function Wo(e,t){We(t,!0);let n=()=>A(V(S),`$hasErrors`,s),r=()=>A(V(C),`$isDirty`,s),i=()=>A(V(w),`$actionInProgress`,s),a=()=>A(V(x),`$errors`,s),o=()=>A(V(T),`$actionError`,s),[s,c]=ft(),l=N(!0),u=N(0),d=N(!1),f=N(0),p=N(!1),m=N(void 0),h=N(void 0),g=N(void 0),_=()=>({name:`User ${X()}`,email:`${X()}@example.com`}),v=e=>ua(_(),{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),email:q(e.email).prepare(`trim`).required().email().getError()}),effect:({property:e})=>{P(h,e,!0)},action:async()=>{let e=Ba(100,800);if(await new Promise(t=>setTimeout(t,e)),V(p))throw Error(`Simulated error after ${e}ms`);P(m,`Submitted successfully in ${e}ms!`)},actionCompleted:e=>{e&&P(m,void 0)}},e),y=N(fn(v({resetDirtyOnAction:!0,debounceValidation:0,persistActionError:!1}))),b=()=>{P(h,void 0),P(m,void 0),P(g,void 0),P(y,v({resetDirtyOnAction:V(l),debounceValidation:V(u),persistActionError:V(d)}),!0),ln(f)},x=j(()=>V(y).state.errors),S=j(()=>V(y).state.hasErrors),C=j(()=>V(y).state.isDirty),w=j(()=>V(y).state.actionInProgress),T=j(()=>V(y).state.actionError),E=()=>{V(y).batch(e=>{e.name=`User ${X()}`,e.email=`${X()}@example.com`})},ee=()=>{P(m,void 0),V(y).execute()},te=()=>{let e=V(y).validate(),t=Object.values(e.errors??{}).filter(Boolean).length;P(g,e.hasErrors?`Validated immediately — ${t} field(s) have errors`:`Validated immediately — all fields valid`,!0)};Ma(e,{description:`Interactive playground for configuring createSvState options like debouncing and error persistence.`,title:`Options Demo`,main:e=>{var t=Ur();Xr(I(t),()=>V(f),e=>{var t=Bo(),s=I(t);za(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=e=>{var t=Io(),n=F(t),r=L(F(n));k(n),k(t),R(()=>G(r,` property "${V(h)??``}" changed`)),W(e,t)};K(c,e=>{V(h)&&e(l)});var u=L(c,2),d=F(u);{let e=j(()=>a()?.name);Y(d,{id:`name`,get disabled(){return i()},get error(){return V(e)},label:`Name`,placeholder:`Enter name`,get value(){return V(y).data.name},set value(e){V(y).data.name=e}})}var f=L(d,2);{let e=j(()=>a()?.email);Y(f,{id:`email`,get disabled(){return i()},get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return V(y).data.email},set value(e){V(y).data.email=e}})}var g=L(f,2),_=F(g);vi(_),Pe(2),k(g),k(u);var v=L(u,2),b=e=>{var t=Lo(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,o().message)),W(e,t)};K(v,e=>{o()&&e(b)});var x=L(v,2),S=e=>{var t=Ro(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,V(m))),W(e,t)};K(x,e=>{V(m)&&e(S)});var C=L(x,2),w=F(C),T=F(w),E=e=>{var t=zo();La(F(t),{}),Pe(),k(t),W(e,t)},te=e=>{W(e,Hr(`Submit`))};K(T,e=>{i()?e(E):e(te,-1)}),k(w),k(C),R(()=>{_.disabled=i(),w.disabled=n()||i()}),wi(_,()=>V(p),e=>P(p,e)),H(`click`,w,ee),W(e,t)}),W(e,t)},sidebar:e=>{wa(e,{get data(){return V(y).data},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:E,extra:e=>{var t=Ho(),n=I(t),r=L(F(n),2),i=F(r),a=F(i),o=F(a);vi(o),Pe(2),k(a),Pe(2),k(i);var s=L(i,2),c=L(F(s),2);vi(c);var f=L(c,4),p=L(f,2),m=e=>{var t=Vo(),n=F(t,!0);k(t),R(()=>G(n,V(g))),W(e,t)};K(p,e=>{V(g)&&e(m)}),k(s);var h=L(s,2),_=F(h),v=F(_);vi(v),Pe(2),k(_),Pe(2),k(h);var y=L(h,2);k(r),k(n);var x=L(n,2),S=L(F(x),2),C=F(S),w=F(C);k(C);var T=L(C,2),E=F(T);k(T);var ee=L(T,2),ne=F(ee);k(ee),k(S),k(x),R(()=>{G(w,`resetDirtyOnAction: ${V(l)??``}`),G(E,`debounceValidation: ${V(u)??``}`),G(ne,`persistActionError: ${V(d)??``}`)}),wi(o,()=>V(l),e=>P(l,e)),Ci(c,()=>V(u),e=>P(u,e)),H(`click`,f,te),wi(v,()=>V(d),e=>P(d,e)),H(`click`,y,b),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=Uo(),r=I(n);J(r,{code:`const { data, execute, state } = createSvState( + sourceData, + { validator, effect, action }, + { + // Reset isDirty to false after successful action + resetDirtyOnAction: true, // default: true + + // Debounce validation by N milliseconds + debounceValidation: 0, // default: 0 (uses queueMicrotask) + + // Keep action errors until next action (not cleared on data change) + persistActionError: false // default: false + } +);`,title:`Options Overview`});var i=L(r,2);J(i,{code:`// With resetDirtyOnAction: true (default) +await execute(); +// isDirty is now false + +// With resetDirtyOnAction: false +await execute(); +// isDirty remains true`,title:`resetDirtyOnAction`});var a=L(i,2);J(a,{code:`// With debounceValidation: 0 (default) +// Validation runs via queueMicrotask after each change + +// With debounceValidation: 500 +// Validation runs 500ms after the last change +// Useful for expensive validators or rapid typing`,title:`debounceValidation`});var o=L(a,2);J(o,{code:`// validate() runs sync validation immediately, bypassing the debounce +const { errors, hasErrors } = validate(); + +// Useful right before submitting, even with a long debounceValidation`,title:`validate() Bypasses the Debounce`}),J(L(o,2),{code:`// With persistActionError: false (default) +data.name = 'new value'; +// actionError is cleared immediately + +// With persistActionError: true +data.name = 'new value'; +// actionError remains until next execute() call`,title:`persistActionError`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var Go=U(`Saving...`),Ko=U(``),qo=U(`
Auto-save triggers 2 seconds after the last change. Analytics events buffer and flush at 10 events or every 10 + seconds.
`,1),Jo=U(`

No saves yet — edit the form and wait 2s

`),Yo=U(`
  • save
  • `),Xo=U(`
      `),Zo=U(`

      No flushes yet

      `),Qo=U(`
    • flush
    • `),$o=U(`
      Autosave Log
      Analytics Buffer
      Buffered:
      Batch size: 10
      Flush interval: 10s
      Tracked: change, action, snapshot
      Last onError:
      Flush History
      `,1),es=U(` `,1);function ts(e,t){We(t,!0);let n=()=>A(y,`$hasErrors`,o),r=()=>A(b,`$isDirty`,o),i=()=>A(v,`$errors`,o),a=()=>A(x,`$actionInProgress`,o),[o,s]=ft(),c=N(fn([])),l=N(fn([])),u=N(0),d=N(void 0),f=Fi({save:async e=>{await new Promise(e=>setTimeout(e,300));let t=new Date().toISOString().slice(11,23);P(c,[...V(c),{id:X(),timestamp:t,data:`${e.title} (${e.category})`}],!0)},idle:2e3,onlyWhenDirty:!0}),p=Ni({onFlush:e=>{let t=new Date().toISOString().slice(11,23),n={};for(let t of e)n[t.type]=(n[t.type]??0)+1;let r=Object.entries(n).map(([e,t])=>`${e}:${t}`).join(`, `);P(l,[...V(l),{id:X(),timestamp:t,eventCount:e.length,types:r}],!0)},batchSize:10,flushInterval:1e4,include:[`change`,`action`,`snapshot`],onError:e=>{P(d,e instanceof Error?e.message:String(e),!0)}}),{data:m,batch:h,execute:g,reset:_,state:{errors:v,hasErrors:y,isDirty:b,actionInProgress:x}}=ua({title:``,category:`general`,notes:``},{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(2).maxLength(100).getError(),category:``,notes:q(e.notes).maxLength(500).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${Va(t)}`)},action:async()=>{await new Promise(e=>setTimeout(e,500))}},{plugins:[f,p]}),S=()=>{h(e=>{e.title=`Article ${X()}`,e.category=`tech`,e.notes=`Some interesting notes about the topic that should pass validation.`})};Mn(()=>{let e=setInterval(()=>{P(u,p.eventCount(),!0)},500);return()=>clearInterval(e)}),Ma(e,{description:`Auto-save with idle timer (autosavePlugin) and batched event analytics (analyticsPlugin).`,title:`Plugin: Autosave & Analytics`,main:e=>{var t=qo(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),d=F(l);k(l);var h=L(l,2),v=F(h);k(h);var y=L(h,2),b=e=>{W(e,Go())},x=j(()=>f.isSaving());K(y,e=>{V(x)&&e(b)}),k(s);var S=L(s,4),C=F(S);{let e=j(()=>i()?.title);Y(C,{id:`title`,get error(){return V(e)},label:`Title`,placeholder:`Enter article title`,get value(){return m.title},set value(e){m.title=e}})}var w=L(C,2),T=L(F(w),2),E=F(T);E.value=E.__value=`general`;var ee=L(E);ee.value=ee.__value=`tech`;var te=L(ee);te.value=te.__value=`science`;var ne=L(te);ne.value=ne.__value=`culture`,k(T),k(w);var re=L(w,2);{let e=j(()=>i()?.notes);mo(re,{id:`notes`,get error(){return V(e)},label:`Notes`,placeholder:`Write your notes (max 500 chars)`,rows:4,get value(){return m.notes},set value(e){m.notes=e}})}k(S);var ie=L(S,2),ae=F(ie),oe=F(ae,!0);k(ae);var se=L(ae,2),ce=L(se,2),le=L(ce,2),ue=e=>{var t=Ko();H(`click`,t,_),W(e,t)};K(le,e=>{r()&&e(ue)}),k(ie),R(()=>{G(d,`${V(c).length??``} Save${V(c).length===1?``:`s`}`),G(v,`${V(u)??``} Buffered Event${V(u)===1?``:`s`}`),ae.disabled=n()||a(),G(oe,a()?`Submitting...`:`Submit`)}),pi(T,()=>m.category,e=>m.category=e),H(`click`,ae,()=>g()),H(`click`,se,()=>f.saveNow()),H(`click`,ce,()=>p.flush()),W(e,t)},sidebar:e=>{wa(e,{get data(){return m},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:S,width:`xl:w-96`,extra:e=>{var t=$o(),n=I(t),r=L(F(n),2),i=e=>{W(e,Jo())},a=e=>{var t=Xo();ti(t,21,()=>V(c),e=>e.id,(e,t)=>{var n=Yo(),r=L(F(n),2),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{G(i,V(t).data),G(o,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(r,e=>{V(c).length===0?e(i):e(a,-1)}),k(n);var o=L(n,2),s=L(F(o),2),f=F(s),p=L(F(f));k(f);var m=L(f,8),h=L(F(m));k(m),k(s),k(o);var g=L(o,2),_=L(F(g),2),v=e=>{W(e,Zo())},y=e=>{var t=Xo();ti(t,21,()=>V(l),e=>e.id,(e,t)=>{var n=Qo(),r=L(F(n),2),i=F(r);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{G(i,`${V(t).eventCount??``} event${V(t).eventCount===1?``:`s`} (${V(t).types??``})`),G(o,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(_,e=>{V(l).length===0?e(v):e(y,-1)}),k(g),R(()=>{G(p,` ${V(u)??``} event${V(u)===1?``:`s`}`),G(h,` ${V(d)??`none`??``}`)}),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=es(),r=I(n);J(r,{code:`import { createSvState, autosavePlugin, analyticsPlugin } from 'svstate'; + +const autosave = autosavePlugin({ + save: async (data) => { + await fetch('/api/save', { + method: 'POST', + body: JSON.stringify(data) + }); + }, + idle: 2000, // Save 2s after last change + onlyWhenDirty: true // Skip save if nothing changed +}); + +const analytics = analyticsPlugin({ + onFlush: (events) => { + sendToAnalytics(events); // Your analytics endpoint + }, + batchSize: 10, // Flush after 10 events + flushInterval: 10000, // Or every 10 seconds + include: ['change', 'action', 'snapshot'], // Filter event types + onError: (error) => { + console.error('Analytics flush failed:', error); + } +}); + +const { data, execute, state } = createSvState( + initialData, actuators, + { plugins: [autosave, analytics] } +);`,title:`autosavePlugin + analyticsPlugin Setup`});var i=L(r,2);J(i,{code:`// One validation pass, one buffered analytics 'change' event per +// field (still per-mutation), but a single snapshot for the fill +batch((draft) => { + draft.title = 'Article Title'; + draft.category = 'tech'; + draft.notes = 'Some notes.'; +});`,title:`Batching Fill Updates`}),J(L(i,2),{code:`// autosavePlugin API +autosave.saveNow(); // Force immediate save +autosave.isSaving(); // Check if currently saving + +// analyticsPlugin API +analytics.flush(); // Force flush buffered events +analytics.eventCount(); // Number of buffered events`,title:`Plugin API`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var ns=U(``),rs=U(`
      `,1),is=U(`

      No events yet — interact with the form

      `),as=U(`
    • `),os=U(`
        `),ss=U(`

        `),cs=U(`

        No plugin errors caught yet

        `),ls=U(`
        Event Log
        onPluginError
        `,1),us=U(` `,1);function ds(e,t){We(t,!0);let n=()=>A(y,`$hasErrors`,s),r=()=>A(b,`$isDirty`,s),i=()=>A(v,`$errors`,s),a=()=>A(S,`$actionInProgress`,s),o=()=>A(x,`$snapshots`,s),[s,c]=ft(),l=N(fn([])),u=N(!1),d=N(void 0),f=(e,t)=>{let n=new Date().toISOString().slice(11,23);P(l,[...V(l),{id:X(),type:e,message:t,timestamp:n}],!0)},{data:p,batch:m,execute:h,reset:g,rollback:_,state:{errors:v,hasErrors:y,isDirty:b,snapshots:x,actionInProgress:S}}=ua({name:``,email:``,message:``},{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),message:q(e.message).prepare(`trim`).required().minLength(5).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${Va(t)}`)},action:async()=>{await new Promise(e=>setTimeout(e,500))}},{plugins:[Li({name:`demo-devtools`,enabled:!0,logValidation:!0}),{name:`log-mirror`,onChange(e){if(V(u))throw Error(`Simulated failure while mirroring "${e.property}"`);f(`change`,`${e.property}: "${e.oldValue}" → "${e.currentValue}"`)},onValidation(e){f(`validation`,e?`Has errors`:`Valid`)},onSnapshot(e){f(`snapshot`,e.title)},onAction(e){e.phase===`before`?f(`action`,`Action started`):f(`action`,e.error?`Action failed: ${e.error.message}`:`Action completed`)},onRollback(e){f(`rollback`,`Rolled back to: ${e.title}`)},onReset(){f(`reset`,`State reset to initial`)}}],onPluginError:(e,t,n)=>{P(d,`[${t}/${n}] ${e instanceof Error?e.message:String(e)}`)}}),C=()=>{m(e=>{e.name=`John Doe ${X()}`,e.email=`john.${X()}@example.com`,e.message=`Hello, this is a test message for the devtools demo.`})},w=()=>{P(l,[],!0)},T={change:`bg-blue-100 text-blue-800`,validation:`bg-yellow-100 text-yellow-800`,snapshot:`bg-purple-100 text-purple-800`,action:`bg-green-100 text-green-800`,rollback:`bg-amber-100 text-amber-800`,reset:`bg-red-100 text-red-800`};Ma(e,{description:`Shows devtoolsPlugin console logging and a custom log-mirror plugin that captures all events in-page.`,title:`Plugin: Devtools`,main:e=>{var t=rs(),s=I(t);za(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=F(c);{let e=j(()=>i()?.name);Y(l,{id:`name`,get error(){return V(e)},label:`Name`,placeholder:`Enter your name`,get value(){return p.name},set value(e){p.name=e}})}var d=L(l,2);{let e=j(()=>i()?.email);Y(d,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter your email`,type:`email`,get value(){return p.email},set value(e){p.email=e}})}var f=L(d,2);{let e=j(()=>i()?.message);mo(f,{id:`message`,get error(){return V(e)},label:`Message`,placeholder:`Enter a message (min 5 chars)`,required:!0,get value(){return p.message},set value(e){p.message=e}})}k(c);var m=L(c,2),v=F(m);vi(v),Pe(2),k(m);var y=L(m,2),b=F(y),x=F(b,!0);k(b);var S=L(b,2),C=L(S,2),w=e=>{var t=ns();H(`click`,t,g),W(e,t)};K(C,e=>{r()&&e(w)}),k(y),R(()=>{b.disabled=n()||a(),G(x,a()?`Submitting...`:`Submit`),S.disabled=o().length<=1}),wi(v,()=>V(u),e=>P(u,e)),H(`click`,b,()=>h()),H(`click`,S,()=>_()),W(e,t)},sidebar:e=>{wa(e,{get data(){return p},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:C,width:`xl:w-96`,extra:e=>{var t=ls(),n=I(t),r=F(n),i=L(F(r),2);k(r);var a=L(r,2),o=e=>{W(e,is())},s=e=>{var t=os();ti(t,21,()=>V(l),e=>e.id,(e,t)=>{var n=as(),r=F(n),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a);var s=L(a,2),c=F(s,!0);k(s),k(n),R(()=>{ui(r,1,`mt-0.5 flex-shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium ${T[V(t).type]??``}`),G(i,V(t).type),G(o,V(t).message),G(c,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(a,e=>{V(l).length===0?e(o):e(s,-1)}),k(n);var c=L(n,2),u=L(F(c),2),f=e=>{var t=ss(),n=F(t,!0);k(t),R(()=>G(n,V(d))),W(e,t)},p=e=>{W(e,cs())};K(u,e=>{V(d)?e(f):e(p,-1)}),k(c),H(`click`,i,w),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=us(),r=I(n);J(r,{code:`import { createSvState, devtoolsPlugin } from 'svstate'; + +const { data, execute, reset, rollback, state } = createSvState( + { name: '', email: '', message: '' }, + { + validator: (source) => ({ /* ... */ }), + effect: ({ snapshot, property }) => { + snapshot(\`Changed \${property}\`); + }, + action: async () => { await saveToServer(); } + }, + { + plugins: [ + devtoolsPlugin({ + name: 'my-form', // Label in console + enabled: true, // Auto-disabled in production + collapsed: true, // Console groups collapsed + logValidation: true // Also log validation events + }) + ] + } +);`,title:`devtoolsPlugin Setup`});var i=L(r,2);J(i,{code:`// devtoolsPlugin logs these events to the console: +// - onChange: property changes with old/new values +// - onValidation: validation results (if logValidation: true) +// - onSnapshot: snapshot creation with title +// - onAction: action start/complete/error +// - onRollback: rollback with target snapshot title +// - onReset: state reset events`,title:`What Gets Logged`}),J(L(i,2),{code:`// A throwing plugin hook no longer aborts the mutation or blocks +// later plugins — it's caught and reported via onPluginError. +createSvState(sourceData, actuators, { + plugins: [devtoolsPlugin(), logMirrorPlugin], + onPluginError: (error, pluginName, hook) => { + console.error(\`Plugin "\${pluginName}" failed in \${hook}:\`, error); + } +});`,title:`onPluginError — Plugin Isolation`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var fs=U(`Restored from storage`),ps=U(`Fresh state`),ms=U(``),hs=U(`
        Try: Reload the page to see persistence. Open this page in another tab to see cross-tab sync.
        `,1),gs=U(`
        Persistence Info
        Restored:
        Key: svstate-demo-settings
        Excluded: notifications
        Last onError:
        Raw localStorage
         
        Sync Info
        Channel: svstate-demo-sync
        Throttle: 200ms
        Merge: overwrite (default)
        `,1),_s=U(` `,1);function vs(e,t){We(t,!0);let n=()=>A(p,`$hasErrors`,a),r=()=>A(m,`$isDirty`,a),i=()=>A(f,`$errors`,a),[a,o]=ft(),s=N(void 0),c=Ji({key:`svstate-demo-settings`,throttle:300,exclude:[`notifications`],onError:e=>{P(s,e instanceof Error?e.message:String(e),!0)}}),{data:l,batch:u,reset:d,state:{errors:f,hasErrors:p,isDirty:m}}=ua({username:``,theme:`light`,fontSize:14,notifications:!0},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(2).maxLength(30).getError(),theme:``,fontSize:``,notifications:``})},{plugins:[c,Zi({key:`svstate-demo-sync`,throttle:200})]}),h=c.isRestored(),g=()=>{c.clearPersistedState(),d()},_=()=>{u(e=>{e.username=`demo_user`,e.theme=`dark`,e.fontSize=16,e.notifications=!1})},v=N(``);Mn(()=>{l.username,l.theme,l.fontSize,l.notifications;let e=setTimeout(()=>{P(v,localStorage.getItem(`svstate-demo-settings`)??`(empty)`,!0)},500);return()=>clearTimeout(e)}),Ma(e,{description:`Settings form with persistPlugin (localStorage) and syncPlugin (cross-tab sync via BroadcastChannel).`,title:`Plugin: Persist & Sync`,main:e=>{var t=hs(),a=I(t);za(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),s=F(o),c=e=>{W(e,fs())},u=e=>{W(e,ps())};K(s,e=>{h?e(c):e(u,-1)}),k(o);var f=L(o,4),p=F(f);{let e=j(()=>i()?.username);Y(p,{id:`username`,get error(){return V(e)},label:`Username`,placeholder:`Enter username`,get value(){return l.username},set value(e){l.username=e}})}var m=L(p,2),_=L(F(m),2),v=F(_);v.value=v.__value=`light`;var y=L(v);y.value=y.__value=`dark`;var b=L(y);b.value=b.__value=`system`,k(_),k(m);var x=L(m,2);Y(x,{id:`fontSize`,label:`Font Size`,max:32,min:8,step:1,type:`number`,get value(){return l.fontSize},set value(e){l.fontSize=e}});var S=L(x,2),C=F(S),w=F(C);vi(w),Pe(4),k(C),k(S),k(f);var T=L(f,2),E=F(T),ee=L(E,2),te=e=>{var t=ms();H(`click`,t,d),W(e,t)};K(ee,e=>{r()&&e(te)}),k(T),pi(_,()=>l.theme,e=>l.theme=e),wi(w,()=>l.notifications,e=>l.notifications=e),H(`click`,E,g),W(e,t)},sidebar:e=>{wa(e,{get data(){return l},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:_,width:`xl:w-96`,extra:e=>{var t=gs(),n=I(t),r=L(F(n),2),i=F(r),a=L(F(i));k(i);var o=L(i,6),c=L(F(o));k(o),k(r),k(n);var l=L(n,2),u=L(F(l),2),d=F(u,!0);k(u),k(l),Pe(2),R(()=>{G(a,` ${h??``}`),G(c,` ${V(s)??`none`??``}`),G(d,V(v))}),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=_s(),r=I(n);J(r,{code:`import { createSvState, persistPlugin, syncPlugin } from 'svstate'; + +const persist = persistPlugin({ + key: 'svstate-demo-settings', + throttle: 300, + exclude: ['notifications'], // Don't persist this field + onError: (error) => { + console.error('Failed to persist state:', error); + } +}); + +const sync = syncPlugin({ + key: 'svstate-demo-sync', + throttle: 200 +}); + +const { data, reset, state } = createSvState( + { username: '', theme: 'light', fontSize: 14, notifications: true }, + { validator: (source) => ({ /* ... */ }) }, + { plugins: [persist, sync] } +);`,title:`persistPlugin + syncPlugin Setup`});var i=L(r,2);J(i,{code:`// One validation pass, one persisted write, for the whole fill +batch((draft) => { + draft.username = 'demo_user'; + draft.theme = 'dark'; + draft.fontSize = 16; +});`,title:`Batching Fill Updates`}),J(L(i,2),{code:`// persistPlugin API +persist.isRestored(); // true if data was loaded from storage +persist.clearPersistedState(); // Remove stored data + +// syncPlugin: automatic cross-tab sync via BroadcastChannel +// Changes in one tab appear in all other tabs with same key`,title:`Plugin API`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]);var ys=U(``),bs=U(`
        Max: 10
        `,1),xs=U(`

        No snapshots yet

        `),Ss=U(`
      • `),Cs=U(`
          `),ws=U(`

          No redo entries — undo something first

          `),Ts=U(`
        • `),Es=U(`
          Snapshot History
          Redo Stack
          `,1),Ds=U(` `,1);function Os(e,t){We(t,!0);let n=()=>A(m,`$hasErrors`,o),r=()=>A(h,`$isDirty`,o),i=()=>A(g,`$snapshots`,o),a=()=>A(p,`$errors`,o),[o,s]=ft(),c=ea(),{data:l,batch:u,reset:d,rollback:f,state:{errors:p,hasErrors:m,isDirty:h,snapshots:g}}=ua({title:`My Document`,content:``,priority:`medium`},{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(2).maxLength(100).getError(),content:q(e.content).prepare(`trim`).required().minLength(10).getError(),priority:``}),effect:({snapshot:e,property:t})=>{e(`Changed ${Va(t)}`)}},{maxSnapshots:10,plugins:[c]}),_=()=>{u(e=>{e.title=`Project Report ${X()}`,e.content=`This is a detailed document with enough content to pass validation requirements.`,e.priority=`high`})},v=N(fn(lt(c.redoStack)));Mn(()=>c.redoStack.subscribe(e=>{P(v,e,!0)})),Ma(e,{description:`Combines the built-in snapshot/rollback system with the undoRedoPlugin for full undo/redo support.`,title:`Plugin: Undo/Redo`,main:e=>{var t=bs(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),u=F(s),p=F(u);k(u);var m=L(u,2),h=F(m);k(m),Pe(2),k(s);var g=L(s,2),_=F(g);{let e=j(()=>a()?.title);Y(_,{id:`title`,get error(){return V(e)},label:`Title`,placeholder:`Enter document title`,get value(){return l.title},set value(e){l.title=e}})}var y=L(_,2);{let e=j(()=>a()?.content);mo(y,{id:`content`,get error(){return V(e)},label:`Content`,placeholder:`Write your document content (min 10 chars)`,required:!0,rows:4,get value(){return l.content},set value(e){l.content=e}})}var b=L(y,2),x=L(F(b),2),S=F(x);S.value=S.__value=`low`;var C=L(S);C.value=C.__value=`medium`;var w=L(C);w.value=w.__value=`high`;var T=L(w);T.value=T.__value=`critical`,k(x),k(b),k(g);var E=L(g,2),ee=F(E),te=L(ee,2),ne=L(te,2),re=e=>{var t=ys();H(`click`,t,d),W(e,t)};K(ne,e=>{r()&&e(re)}),k(E),R(()=>{G(p,`${i().length??``} Snapshot${i().length===1?``:`s`}`),G(h,`${V(v).length??``} Redo${V(v).length===1?``:`s`}`),ee.disabled=i().length<=1,te.disabled=V(v).length===0}),pi(x,()=>l.priority,e=>l.priority=e),H(`click`,ee,()=>f()),H(`click`,te,()=>c.redo()),W(e,t)},sidebar:e=>{wa(e,{get data(){return l},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:_,width:`xl:w-96`,extra:e=>{var t=Es(),n=I(t),r=L(F(n),2),a=e=>{W(e,xs())},o=e=>{var t=Cs();ti(t,5,i,Zr,(e,t,n)=>{var r=Ss(),i=F(r);i.textContent=n+1;var a=L(i,2),o=F(a,!0);k(a),k(r),R(()=>G(o,V(t).title)),W(e,r)}),k(t),W(e,t)};K(r,e=>{i().length===0?e(a):e(o,-1)}),k(n);var s=L(n,2),c=L(F(s),2),l=e=>{W(e,ws())},u=e=>{var t=Cs();ti(t,21,()=>V(v),Zr,(e,t,n)=>{var r=Ts(),i=F(r);i.textContent=n+1;var a=L(i,2),o=F(a,!0);k(a),k(r),R(()=>G(o,V(t).title)),W(e,r)}),k(t),W(e,t)};K(c,e=>{V(v).length===0?e(l):e(u,-1)}),k(s),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=Ds(),r=I(n);J(r,{code:`import { createSvState, undoRedoPlugin } from 'svstate'; + +const undoRedo = undoRedoPlugin(); + +const { data, reset, rollback, state } = createSvState( + { title: 'My Document', content: '', priority: 'medium' }, + { + validator: (source) => ({ /* ... */ }), + effect: ({ snapshot, property }) => { + snapshot(\`Changed \${property}\`); + } + }, + { maxSnapshots: 10, plugins: [undoRedo] } +);`,title:`Setup with undoRedoPlugin`});var i=L(r,2);J(i,{code:`// Effect-driven snapshots collapse into one for the whole batch +batch((draft) => { + draft.title = 'Project Report'; + draft.content = 'Detailed document content.'; + draft.priority = 'high'; +}); +// Result: one new snapshot, not three`,title:`Batching Fill Updates`}),J(L(i,2),{code:`// Undo (built-in rollback) +rollback(); + +// Redo (from undoRedoPlugin) +undoRedo.redo(); + +// Check if redo is available +undoRedo.canRedo(); // boolean + +// Subscribe to redo stack +undoRedo.redoStack; // Readable`,title:`Undo/Redo Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var ks=U(`
          `),As=U(`
          `,1),js=U(` `,1);function Ms(e,t){We(t,!0);let n=()=>A(d,`$hasErrors`,a),r=()=>A(f,`$isDirty`,a),i=()=>A(u,`$errors`,a),[a,o]=ft(),{data:s,batch:c,reset:l,state:{errors:u,hasErrors:d,isDirty:f}}=ua({firstName:`Alice`,lastName:`Smith`,email:`alice.smith@example.com`,phone:``,bio:``},{validator:e=>({firstName:q(e.firstName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),lastName:q(e.lastName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),phone:q(e.phone).prepare(`trim`).required().minLength(10).getError(),bio:q(e.bio).maxLength(200).getError()})}),p=()=>{c(e=>{e.firstName=`John`,e.lastName=`Doe${X()}`,e.email=`john.doe.${X()}@example.com`,e.phone=`555-${X().slice(0,3)}-${X().slice(0,4)}`,e.bio=`Software developer with a passion for clean code.`})};Ma(e,{description:`Demonstrates the reset() function to restore state back to its initial values.`,title:`Reset Demo`,main:e=>{var t=As(),a=I(t);za(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.firstName);Y(c,{id:`firstName`,get error(){return V(e)},label:`First Name`,placeholder:`Enter first name`,get value(){return s.firstName},set value(e){s.firstName=e}})}var u=L(c,2);{let e=j(()=>i()?.lastName);Y(u,{id:`lastName`,get error(){return V(e)},label:`Last Name`,placeholder:`Enter last name`,get value(){return s.lastName},set value(e){s.lastName=e}})}var d=L(u,2);{let e=j(()=>i()?.email);Y(d,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return s.email},set value(e){s.email=e}})}var f=L(d,2);{let e=j(()=>i()?.phone);Y(f,{id:`phone`,get error(){return V(e)},label:`Phone`,placeholder:`555-123-4567`,get value(){return s.phone},set value(e){s.phone=e}})}var p=L(f,2);{let e=j(()=>i()?.bio);mo(p,{id:`bio`,get error(){return V(e)},label:`Bio`,placeholder:`Tell us about yourself`,required:!1,get value(){return s.bio},set value(e){s.bio=e}})}k(o);var m=L(o,2),h=e=>{var t=ks(),n=F(t);k(t),H(`click`,n,l),W(e,t)};K(m,e=>{r()&&e(h)}),W(e,t)},sidebar:e=>{wa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:p})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=js(),r=I(n);J(r,{code:`const sourceData = { + firstName: 'Alice', + lastName: 'Smith', + email: 'alice.smith@example.com', + phone: '', + bio: '' +}; + +const { data, batch, reset, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { + validator: (source) => ({ + firstName: stringValidator(source.firstName).prepare('trim').required().minLength(2).maxLength(30).getError(), + lastName: stringValidator(source.lastName).prepare('trim').required().minLength(2).maxLength(30).getError(), + email: stringValidator(source.email).prepare('trim').required().email().getError(), + phone: stringValidator(source.phone).prepare('trim').required().minLength(10).getError(), + bio: stringValidator(source.bio).maxLength(200).getError() + }) +});`,title:`State Setup with Reset`});var i=L(r,2);J(i,{code:`// One validation pass for the whole fill +batch((draft) => { + draft.firstName = 'John'; + draft.lastName = 'Doe'; + draft.email = 'john.doe@example.com'; +});`,title:`Batching Fill Updates`}),J(L(i,2),{code:` +{#if $isDirty} + +{/if} + + +`,title:`Conditional Reset Button`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]);var Ns=U(``),Ps=U(`
          Max: 5
          `,1),Fs=U(`

          No snapshots yet

          `),Is=U(`
        • `),Ls=U(`
            `),Rs=U(`
            Snapshot History
            `),zs=U(` `,1);function Bs(e,t){We(t,!0);let n=()=>A(m,`$hasErrors`,o),r=()=>A(h,`$isDirty`,o),i=()=>A(g,`$snapshots`,o),a=()=>A(p,`$errors`,o),[o,s]=ft(),{data:c,batch:l,reset:u,rollback:d,rollbackTo:f,state:{errors:p,hasErrors:m,isDirty:h,snapshots:g}}=ua({firstName:`Alice`,lastName:`Smith`,email:`alice.smith@example.com`,phone:``,bio:``},{validator:e=>({firstName:q(e.firstName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),lastName:q(e.lastName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),phone:q(e.phone).prepare(`trim`).required().minLength(10).getError(),bio:q(e.bio).maxLength(200).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${Va(t)}`)}},{maxSnapshots:5}),_=()=>{l(e=>{e.firstName=`John`,e.lastName=`Doe${X()}`,e.email=`john.doe.${X()}@example.com`,e.phone=`555-${X().slice(0,3)}-${X().slice(0,4)}`,e.bio=`Software developer with a passion for clean code.`})};Ma(e,{description:`Shows snapshot creation for undo functionality with rollback(), rollbackTo(), and maxSnapshots support.`,title:`Snapshot & Rollback Demo`,main:e=>{var t=Ps(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),p=F(l);k(l),Pe(2),k(s);var m=L(s,2),h=F(m);{let e=j(()=>a()?.firstName);Y(h,{id:`firstName`,get error(){return V(e)},label:`First Name`,placeholder:`Enter first name`,get value(){return c.firstName},set value(e){c.firstName=e}})}var g=L(h,2);{let e=j(()=>a()?.lastName);Y(g,{id:`lastName`,get error(){return V(e)},label:`Last Name`,placeholder:`Enter last name`,get value(){return c.lastName},set value(e){c.lastName=e}})}var _=L(g,2);{let e=j(()=>a()?.email);Y(_,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return c.email},set value(e){c.email=e}})}var v=L(_,2);{let e=j(()=>a()?.phone);Y(v,{id:`phone`,get error(){return V(e)},label:`Phone`,placeholder:`555-123-4567`,get value(){return c.phone},set value(e){c.phone=e}})}var y=L(v,2);{let e=j(()=>a()?.bio);mo(y,{id:`bio`,get error(){return V(e)},label:`Bio`,placeholder:`Tell us about yourself`,required:!1,get value(){return c.bio},set value(e){c.bio=e}})}k(m);var b=L(m,2),x=F(b),S=L(x,2),C=L(S,2),w=e=>{var t=Ns();H(`click`,t,u),W(e,t)};K(C,e=>{r()&&e(w)}),k(b),R(()=>{G(p,`${i().length??``} Snapshot${i().length===1?``:`s`}`),x.disabled=i().length<=1,S.disabled=i().length<=1}),H(`click`,x,()=>d()),H(`click`,S,()=>f(`Initial`)),W(e,t)},sidebar:e=>{wa(e,{get data(){return c},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:_,width:`xl:w-96`,extra:e=>{var t=Rs(),n=L(F(t),2),r=e=>{W(e,Fs())},a=e=>{var t=Ls();ti(t,5,i,Zr,(e,t,n)=>{var r=Is(),a=F(r);a.textContent=n+1;var o=L(a,2),s=F(o,!0);k(o),k(r),R(()=>{o.disabled=i().length<=1,G(s,V(t).title)}),H(`click`,o,()=>f(V(t).title)),W(e,r)}),k(t),W(e,t)};K(n,e=>{i().length===0?e(r):e(a,-1)}),k(t),W(e,t)},$$slots:{extra:!0}})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=zs(),r=I(n);J(r,{code:`const sourceData = { + firstName: 'Alice', lastName: 'Smith', email: 'alice.smith@example.com', phone: '', bio: '' +}; + +const { data, batch, reset, rollback, rollbackTo, state: { errors, hasErrors, isDirty, snapshots } } = + createSvState(sourceData, { + validator: (source) => ({ /* validation rules */ }), + effect: ({ snapshot, property }) => { + snapshot(\`Changed \${formatFieldName(property)}\`); + } + }, { maxSnapshots: 5 });`,title:`State Setup with Snapshots & maxSnapshots`});var i=L(r,2);J(i,{code:`// Effect callback creates snapshots on each change +effect: ({ snapshot, property }) => { + snapshot(\`Changed \${property}\`); // Creates undo point + // If same title, replaces last snapshot (debouncing) + // Use snapshot(title, false) to always create new +}`,title:`Effect with Snapshot Creation`});var a=L(i,2);J(a,{code:`// Inside batch(), effect still fires per mutation and calls snapshot() +// per field, but those collapse into ONE snapshot for the whole batch, +// titled after the first field it touched (shouldReplace is ignored). +batch((draft) => { + draft.firstName = 'John'; + draft.lastName = 'Doe'; + draft.email = 'john.doe@example.com'; +}); +// Result: exactly one new snapshot, e.g. "Changed First Name" +// (previously: five separate snapshots, one per field)`,title:`Batching Collapses Multiple Snapshots into One`}),J(L(a,2),{code:`// Undo last change +rollback(); + +// Undo 3 changes at once +rollback(3); + +// Roll back to a named snapshot (returns true if found) +rollbackTo('Changed First Name'); + +// Roll back to initial state +rollbackTo('Initial'); + +// Reset to initial state (clears all snapshots) +reset();`,title:`Rollback, RollbackTo & Reset Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var Vs;function Z(e,t,n){function r(n,r){if(n._zod||Object.defineProperty(n,"_zod",{value:{def:r,constr:o,traits:new Set},enumerable:!1}),n._zod.traits.has(e))return;n._zod.traits.add(e),t(n,r);let i=o.prototype,a=Object.keys(i);for(let e=0;en?.Parent&&t instanceof n.Parent?!0:t?._zod?.traits?.has(e)}),Object.defineProperty(o,"name",{value:e}),o}var Hs=class extends Error{constructor(){super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`)}},Us=class extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name=`ZodEncodeError`}};(Vs=globalThis).__zod_globalConfig??(Vs.__zod_globalConfig={});var Ws=globalThis.__zod_globalConfig;function Gs(e){return e&&Object.assign(Ws,e),Ws}function Ks(e){let t=Object.values(e).filter(e=>typeof e==`number`);return Object.entries(e).filter(([e,n])=>t.indexOf(+e)===-1).map(([e,t])=>t)}function qs(e,t){return typeof t==`bigint`?t.toString():t}function Js(e){return{get value(){{let t=e();return Object.defineProperty(this,"value",{value:t}),t}}}}function Ys(e){return e==null}function Xs(e){let t=+!!e.startsWith(`^`),n=e.endsWith(`$`)?e.length-1:e.length;return e.slice(t,n)}function Zs(e,t){let n=e/t,r=Math.round(n),i=2**-52*Math.max(Math.abs(n),1);return Math.abs(n-r){};function ic(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var ac=Js(()=>{if(Ws.jitless||typeof navigator<`u`&&navigator?.userAgent?.includes(`Cloudflare`))return!1;try{return Function(``),!0}catch{return!1}});function oc(e){if(ic(e)===!1)return!1;let t=e.constructor;if(t===void 0||typeof t!=`function`)return!0;let n=t.prototype;return ic(n)!==!1&&Object.prototype.hasOwnProperty.call(n,`isPrototypeOf`)!==!1}function sc(e){return oc(e)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e}var cc=new Set([`string`,`number`,`symbol`]);function lc(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function uc(e,t,n){let r=new e._zod.constr(t??e._zod.def);return(!t||n?.parent)&&(r._zod.parent=e),r}function $(e){let t=e;if(!t)return{};if(typeof t==`string`)return{error:()=>t};if(t?.message!==void 0){if(t?.error!==void 0)throw Error("Cannot specify both `message` and `error` params");t.error=t.message}return delete t.message,typeof t.error==`string`?{...t,error:()=>t.error}:t}function dc(e){return Object.keys(e).filter(t=>e[t]._zod.optin===`optional`&&e[t]._zod.optout===`optional`)}var fc={safeint:[-(2**53-1),2**53-1],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function pc(e,t){let n=e._zod.def,r=n.checks;if(r&&r.length>0)throw Error(`.pick() cannot be used on object schemas containing refinements`);return uc(e,ec(e._zod.def,{get shape(){let e={};for(let r in t){if(!(r in n.shape))throw Error(`Unrecognized key: "${r}"`);t[r]&&(e[r]=n.shape[r])}return $s(this,`shape`,e),e},checks:[]}))}function mc(e,t){let n=e._zod.def,r=n.checks;if(r&&r.length>0)throw Error(`.omit() cannot be used on object schemas containing refinements`);return uc(e,ec(e._zod.def,{get shape(){let r={...e._zod.def.shape};for(let e in t){if(!(e in n.shape))throw Error(`Unrecognized key: "${e}"`);t[e]&&delete r[e]}return $s(this,`shape`,r),r},checks:[]}))}function hc(e,t){if(!oc(t))throw Error(`Invalid input to extend: expected a plain object`);let n=e._zod.def.checks;if(n&&n.length>0){let n=e._zod.def.shape;for(let e in t)if(Object.getOwnPropertyDescriptor(n,e)!==void 0)throw Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}return uc(e,ec(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t};return $s(this,`shape`,n),n}}))}function gc(e,t){if(!oc(t))throw Error(`Invalid input to safeExtend: expected a plain object`);return uc(e,ec(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t};return $s(this,`shape`,n),n}}))}function _c(e,t){if(e._zod.def.checks?.length)throw Error(`.merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.`);return uc(e,ec(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t._zod.def.shape};return $s(this,`shape`,n),n},get catchall(){return t._zod.def.catchall},checks:t._zod.def.checks??[]}))}function vc(e,t,n){let r=t._zod.def.checks;if(r&&r.length>0)throw Error(`.partial() cannot be used on object schemas containing refinements`);return uc(t,ec(t._zod.def,{get shape(){let r=t._zod.def.shape,i={...r};if(n)for(let t in n){if(!(t in r))throw Error(`Unrecognized key: "${t}"`);n[t]&&(i[t]=e?new e({type:`optional`,innerType:r[t]}):r[t])}else for(let t in r)i[t]=e?new e({type:`optional`,innerType:r[t]}):r[t];return $s(this,`shape`,i),i},checks:[]}))}function yc(e,t,n){return uc(t,ec(t._zod.def,{get shape(){let r=t._zod.def.shape,i={...r};if(n)for(let t in n){if(!(t in i))throw Error(`Unrecognized key: "${t}"`);n[t]&&(i[t]=new e({type:`nonoptional`,innerType:r[t]}))}else for(let t in r)i[t]=new e({type:`nonoptional`,innerType:r[t]});return $s(this,`shape`,i),i}}))}function bc(e,t=0){if(e.aborted===!0)return!0;for(let n=t;n{var n;return(n=t).path??(n.path=[]),t.path.unshift(e),t})}function Cc(e){return typeof e==`string`?e:e?.message}function wc(e,t,n){let r=e.message?e.message:Cc(e.inst?._zod.def?.error?.(e))??Cc(t?.error?.(e))??Cc(n.customError?.(e))??Cc(n.localeError?.(e))??`Invalid input`,{inst:i,continue:a,input:o,...s}=e;return s.path??=[],s.message=r,t?.reportInput&&(s.input=o),s}function Tc(e){return Array.isArray(e)?`array`:typeof e==`string`?`string`:`unknown`}function Ec(...e){let[t,n,r]=e;return typeof t==`string`?{message:t,code:`custom`,input:n,inst:r}:{...t}}var Dc=(e,t)=>{e.name=`$ZodError`,Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:t,enumerable:!1}),e.message=JSON.stringify(t,qs,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},Oc=Z(`$ZodError`,Dc),kc=Z(`$ZodError`,Dc,{Parent:Error});function Ac(e,t=e=>e.message){let n={},r=[];for(let i of e.issues)i.path.length>0?(n[i.path[0]]=n[i.path[0]]||[],n[i.path[0]].push(t(i))):r.push(t(i));return{formErrors:r,fieldErrors:n}}function jc(e,t=e=>e.message){let n={_errors:[]},r=(e,i=[])=>{for(let a of e.issues)if(a.code===`invalid_union`&&a.errors.length)a.errors.map(e=>r({issues:e},[...i,...a.path]));else if(a.code===`invalid_key`)r({issues:a.issues},[...i,...a.path]);else if(a.code===`invalid_element`)r({issues:a.issues},[...i,...a.path]);else{let e=[...i,...a.path];if(e.length===0)n._errors.push(t(a));else{let r=n,i=0;for(;i(t,n,r,i)=>{let a=r?{...r,async:!1}:{async:!1},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise)throw new Hs;if(o.issues.length){let t=new((i?.Err)??e)(o.issues.map(e=>wc(e,a,Gs())));throw rc(t,i?.callee),t}return o.value},Nc=e=>async(t,n,r,i)=>{let a=r?{...r,async:!0}:{async:!0},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise&&(o=await o),o.issues.length){let t=new((i?.Err)??e)(o.issues.map(e=>wc(e,a,Gs())));throw rc(t,i?.callee),t}return o.value},Pc=e=>(t,n,r)=>{let i=r?{...r,async:!1}:{async:!1},a=t._zod.run({value:n,issues:[]},i);if(a instanceof Promise)throw new Hs;return a.issues.length?{success:!1,error:new(e??Oc)(a.issues.map(e=>wc(e,i,Gs())))}:{success:!0,data:a.value}},Fc=Pc(kc),Ic=e=>async(t,n,r)=>{let i=r?{...r,async:!0}:{async:!0},a=t._zod.run({value:n,issues:[]},i);return a instanceof Promise&&(a=await a),a.issues.length?{success:!1,error:new e(a.issues.map(e=>wc(e,i,Gs())))}:{success:!0,data:a.value}},Lc=Ic(kc),Rc=e=>(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return Mc(e)(t,n,i)},zc=e=>(t,n,r)=>Mc(e)(t,n,r),Bc=e=>async(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return Nc(e)(t,n,i)},Vc=e=>async(t,n,r)=>Nc(e)(t,n,r),Hc=e=>(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return Pc(e)(t,n,i)},Uc=e=>(t,n,r)=>Pc(e)(t,n,r),Wc=e=>async(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return Ic(e)(t,n,i)},Gc=e=>async(t,n,r)=>Ic(e)(t,n,r),Kc=/^[cC][0-9a-z]{6,}$/,qc=/^[0-9a-z]+$/,Jc=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Yc=/^[0-9a-vA-V]{20}$/,Xc=/^[A-Za-z0-9]{27}$/,Zc=/^[a-zA-Z0-9_-]{21}$/,Qc=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,$c=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,el=e=>e?RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,tl=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,nl=`^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;function rl(){return new RegExp(nl,`u`)}var il=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,al=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,ol=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,sl=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,cl=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,ll=/^[A-Za-z0-9_-]*$/,ul=/^https?$/,dl=/^\+[1-9]\d{6,14}$/,fl=`(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`,pl=RegExp(`^${fl}$`);function ml(e){let t=`(?:[01]\\d|2[0-3]):[0-5]\\d`;return typeof e.precision==`number`?e.precision===-1?`${t}`:e.precision===0?`${t}:[0-5]\\d`:`${t}:[0-5]\\d\\.\\d{${e.precision}}`:`${t}(?::[0-5]\\d(?:\\.\\d+)?)?`}function hl(e){return RegExp(`^${ml(e)}$`)}function gl(e){let t=ml({precision:e.precision}),n=[`Z`];e.local&&n.push(``),e.offset&&n.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);let r=`${t}(?:${n.join(`|`)})`;return RegExp(`^${fl}T(?:${r})$`)}var _l=e=>{let t=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??``}}`:`[\\s\\S]*`;return RegExp(`^${t}$`)},vl=/^-?\d+$/,yl=/^-?\d+(?:\.\d+)?$/,bl=/^[^A-Z]*$/,xl=/^[^a-z]*$/,Sl=Z(`$ZodCheck`,(e,t)=>{var n;e._zod??={},e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),Cl={number:`number`,bigint:`bigint`,object:`date`},wl=Z(`$ZodCheckLessThan`,(e,t)=>{Sl.init(e,t);let n=Cl[typeof t.value];e._zod.onattach.push(e=>{let n=e._zod.bag,r=(t.inclusive?n.maximum:n.exclusiveMaximum)??1/0;t.value{(t.inclusive?r.value<=t.value:r.value{Sl.init(e,t);let n=Cl[typeof t.value];e._zod.onattach.push(e=>{let n=e._zod.bag,r=(t.inclusive?n.minimum:n.exclusiveMinimum)??-1/0;t.value>r&&(t.inclusive?n.minimum=t.value:n.exclusiveMinimum=t.value)}),e._zod.check=r=>{(t.inclusive?r.value>=t.value:r.value>t.value)||r.issues.push({origin:n,code:`too_small`,minimum:typeof t.value==`object`?t.value.getTime():t.value,input:r.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),El=Z(`$ZodCheckMultipleOf`,(e,t)=>{Sl.init(e,t),e._zod.onattach.push(e=>{var n;(n=e._zod.bag).multipleOf??(n.multipleOf=t.value)}),e._zod.check=n=>{if(typeof n.value!=typeof t.value)throw Error(`Cannot mix number and bigint in multiple_of check.`);(typeof n.value==`bigint`?n.value%t.value===BigInt(0):Zs(n.value,t.value)===0)||n.issues.push({origin:typeof n.value,code:`not_multiple_of`,divisor:t.value,input:n.value,inst:e,continue:!t.abort})}}),Dl=Z(`$ZodCheckNumberFormat`,(e,t)=>{Sl.init(e,t),t.format=t.format||`float64`;let n=t.format?.includes(`int`),r=n?`int`:`number`,[i,a]=fc[t.format];e._zod.onattach.push(e=>{let r=e._zod.bag;r.format=t.format,r.minimum=i,r.maximum=a,n&&(r.pattern=vl)}),e._zod.check=o=>{let s=o.value;if(n){if(!Number.isInteger(s)){o.issues.push({expected:r,format:t.format,code:`invalid_type`,continue:!1,input:s,inst:e});return}if(!Number.isSafeInteger(s)){s>0?o.issues.push({input:s,code:`too_big`,maximum:2**53-1,note:`Integers must be within the safe integer range.`,inst:e,origin:r,inclusive:!0,continue:!t.abort}):o.issues.push({input:s,code:`too_small`,minimum:-(2**53-1),note:`Integers must be within the safe integer range.`,inst:e,origin:r,inclusive:!0,continue:!t.abort});return}}sa&&o.issues.push({origin:`number`,input:s,code:`too_big`,maximum:a,inclusive:!0,inst:e,continue:!t.abort})}}),Ol=Z(`$ZodCheckMaxLength`,(e,t)=>{var n;Sl.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!Ys(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag.maximum??1/0;t.maximum{let r=n.value;if(r.length<=t.maximum)return;let i=Tc(r);n.issues.push({origin:i,code:`too_big`,maximum:t.maximum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),kl=Z(`$ZodCheckMinLength`,(e,t)=>{var n;Sl.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!Ys(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag.minimum??-1/0;t.minimum>n&&(e._zod.bag.minimum=t.minimum)}),e._zod.check=n=>{let r=n.value;if(r.length>=t.minimum)return;let i=Tc(r);n.issues.push({origin:i,code:`too_small`,minimum:t.minimum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),Al=Z(`$ZodCheckLengthEquals`,(e,t)=>{var n;Sl.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!Ys(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag;n.minimum=t.length,n.maximum=t.length,n.length=t.length}),e._zod.check=n=>{let r=n.value,i=r.length;if(i===t.length)return;let a=Tc(r),o=i>t.length;n.issues.push({origin:a,...o?{code:`too_big`,maximum:t.length}:{code:`too_small`,minimum:t.length},inclusive:!0,exact:!0,input:n.value,inst:e,continue:!t.abort})}}),jl=Z(`$ZodCheckStringFormat`,(e,t)=>{var n,r;Sl.init(e,t),e._zod.onattach.push(e=>{let n=e._zod.bag;n.format=t.format,t.pattern&&(n.patterns??=new Set,n.patterns.add(t.pattern))}),t.pattern?(n=e._zod).check??(n.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:t.format,input:n.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})}):(r=e._zod).check??(r.check=()=>{})}),Ml=Z(`$ZodCheckRegex`,(e,t)=>{jl.init(e,t),e._zod.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:`regex`,input:n.value,pattern:t.pattern.toString(),inst:e,continue:!t.abort})}}),Nl=Z(`$ZodCheckLowerCase`,(e,t)=>{t.pattern??=bl,jl.init(e,t)}),Pl=Z(`$ZodCheckUpperCase`,(e,t)=>{t.pattern??=xl,jl.init(e,t)}),Fl=Z(`$ZodCheckIncludes`,(e,t)=>{Sl.init(e,t);let n=lc(t.includes),r=new RegExp(typeof t.position==`number`?`^.{${t.position}}${n}`:n);t.pattern=r,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(r)}),e._zod.check=n=>{n.value.includes(t.includes,t.position)||n.issues.push({origin:`string`,code:`invalid_format`,format:`includes`,includes:t.includes,input:n.value,inst:e,continue:!t.abort})}}),Il=Z(`$ZodCheckStartsWith`,(e,t)=>{Sl.init(e,t);let n=RegExp(`^${lc(t.prefix)}.*`);t.pattern??=n,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(n)}),e._zod.check=n=>{n.value.startsWith(t.prefix)||n.issues.push({origin:`string`,code:`invalid_format`,format:`starts_with`,prefix:t.prefix,input:n.value,inst:e,continue:!t.abort})}}),Ll=Z(`$ZodCheckEndsWith`,(e,t)=>{Sl.init(e,t);let n=RegExp(`.*${lc(t.suffix)}$`);t.pattern??=n,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(n)}),e._zod.check=n=>{n.value.endsWith(t.suffix)||n.issues.push({origin:`string`,code:`invalid_format`,format:`ends_with`,suffix:t.suffix,input:n.value,inst:e,continue:!t.abort})}}),Rl=Z(`$ZodCheckOverwrite`,(e,t)=>{Sl.init(e,t),e._zod.check=e=>{e.value=t.tx(e.value)}}),zl=class{constructor(e=[]){this.content=[],this.indent=0,this&&(this.args=e)}indented(e){this.indent+=1,e(this),--this.indent}write(e){if(typeof e==`function`){e(this,{execution:`sync`}),e(this,{execution:`async`});return}let t=e.split(` +`).filter(e=>e),n=Math.min(...t.map(e=>e.length-e.trimStart().length)),r=t.map(e=>e.slice(n)).map(e=>` `.repeat(this.indent*2)+e);for(let e of r)this.content.push(e)}compile(){let e=Function,t=this?.args,n=[...(this?.content??[``]).map(e=>` ${e}`)];return new e(...t,n.join(` +`))}},Bl={major:4,minor:4,patch:3},Vl=Z(`$ZodType`,(e,t)=>{var n;e??={},e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=Bl;let r=[...e._zod.def.checks??[]];e._zod.traits.has(`$ZodCheck`)&&r.unshift(e);for(let t of r)for(let n of t._zod.onattach)n(e);if(r.length===0)(n=e._zod).deferred??(n.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{let t=(e,t,n)=>{let r=bc(e),i;for(let a of t){if(a._zod.def.when){if(xc(e)||!a._zod.def.when(e))continue}else if(r)continue;let t=e.issues.length,o=a._zod.check(e);if(o instanceof Promise&&n?.async===!1)throw new Hs;if(i||o instanceof Promise)i=(i??Promise.resolve()).then(async()=>{await o,e.issues.length!==t&&(r||=bc(e,t))});else{if(e.issues.length===t)continue;r||=bc(e,t)}}return i?i.then(()=>e):e},n=(n,i,a)=>{if(bc(n))return n.aborted=!0,n;let o=t(i,r,a);if(o instanceof Promise){if(a.async===!1)throw new Hs;return o.then(t=>e._zod.parse(t,a))}return e._zod.parse(o,a)};e._zod.run=(i,a)=>{if(a.skipChecks)return e._zod.parse(i,a);if(a.direction===`backward`){let t=e._zod.parse({value:i.value,issues:[]},{...a,skipChecks:!0});return t instanceof Promise?t.then(e=>n(e,i,a)):n(t,i,a)}let o=e._zod.parse(i,a);if(o instanceof Promise){if(a.async===!1)throw new Hs;return o.then(e=>t(e,r,a))}return t(o,r,a)}}Q(e,`~standard`,()=>({validate:t=>{try{let n=Fc(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch{return Lc(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:`zod`,version:1}))}),Hl=Z(`$ZodString`,(e,t)=>{Vl.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??_l(e._zod.bag),e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=String(n.value)}catch{}return typeof n.value==`string`||n.issues.push({expected:`string`,code:`invalid_type`,input:n.value,inst:e}),n}}),Ul=Z(`$ZodStringFormat`,(e,t)=>{jl.init(e,t),Hl.init(e,t)}),Wl=Z(`$ZodGUID`,(e,t)=>{t.pattern??=$c,Ul.init(e,t)}),Gl=Z(`$ZodUUID`,(e,t)=>{if(t.version){let e={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[t.version];if(e===void 0)throw Error(`Invalid UUID version: "${t.version}"`);t.pattern??=el(e)}else t.pattern??=el();Ul.init(e,t)}),Kl=Z(`$ZodEmail`,(e,t)=>{t.pattern??=tl,Ul.init(e,t)}),ql=Z(`$ZodURL`,(e,t)=>{Ul.init(e,t),e._zod.check=n=>{try{let r=n.value.trim();if(!t.normalize&&t.protocol?.source===ul.source&&!/^https?:\/\//i.test(r)){n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid URL format`,input:n.value,inst:e,continue:!t.abort});return}let i=new URL(r);t.hostname&&(t.hostname.lastIndex=0,t.hostname.test(i.hostname)||n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid hostname`,pattern:t.hostname.source,input:n.value,inst:e,continue:!t.abort})),t.protocol&&(t.protocol.lastIndex=0,t.protocol.test(i.protocol.endsWith(`:`)?i.protocol.slice(0,-1):i.protocol)||n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid protocol`,pattern:t.protocol.source,input:n.value,inst:e,continue:!t.abort})),n.value=t.normalize?i.href:r;return}catch{n.issues.push({code:`invalid_format`,format:`url`,input:n.value,inst:e,continue:!t.abort})}}}),Jl=Z(`$ZodEmoji`,(e,t)=>{t.pattern??=rl(),Ul.init(e,t)}),Yl=Z(`$ZodNanoID`,(e,t)=>{t.pattern??=Zc,Ul.init(e,t)}),Xl=Z(`$ZodCUID`,(e,t)=>{t.pattern??=Kc,Ul.init(e,t)}),Zl=Z(`$ZodCUID2`,(e,t)=>{t.pattern??=qc,Ul.init(e,t)}),Ql=Z(`$ZodULID`,(e,t)=>{t.pattern??=Jc,Ul.init(e,t)}),$l=Z(`$ZodXID`,(e,t)=>{t.pattern??=Yc,Ul.init(e,t)}),eu=Z(`$ZodKSUID`,(e,t)=>{t.pattern??=Xc,Ul.init(e,t)}),tu=Z(`$ZodISODateTime`,(e,t)=>{t.pattern??=gl(t),Ul.init(e,t)}),nu=Z(`$ZodISODate`,(e,t)=>{t.pattern??=pl,Ul.init(e,t)}),ru=Z(`$ZodISOTime`,(e,t)=>{t.pattern??=hl(t),Ul.init(e,t)}),iu=Z(`$ZodISODuration`,(e,t)=>{t.pattern??=Qc,Ul.init(e,t)}),au=Z(`$ZodIPv4`,(e,t)=>{t.pattern??=il,Ul.init(e,t),e._zod.bag.format=`ipv4`}),ou=Z(`$ZodIPv6`,(e,t)=>{t.pattern??=al,Ul.init(e,t),e._zod.bag.format=`ipv6`,e._zod.check=n=>{try{new URL(`http://[${n.value}]`)}catch{n.issues.push({code:`invalid_format`,format:`ipv6`,input:n.value,inst:e,continue:!t.abort})}}}),su=Z(`$ZodCIDRv4`,(e,t)=>{t.pattern??=ol,Ul.init(e,t)}),cu=Z(`$ZodCIDRv6`,(e,t)=>{t.pattern??=sl,Ul.init(e,t),e._zod.check=n=>{let r=n.value.split(`/`);try{if(r.length!==2)throw Error();let[e,t]=r;if(!t)throw Error();let n=Number(t);if(`${n}`!==t||n<0||n>128)throw Error();new URL(`http://[${e}]`)}catch{n.issues.push({code:`invalid_format`,format:`cidrv6`,input:n.value,inst:e,continue:!t.abort})}}});function lu(e){if(e===``)return!0;if(/\s/.test(e)||e.length%4!=0)return!1;try{return atob(e),!0}catch{return!1}}var uu=Z(`$ZodBase64`,(e,t)=>{t.pattern??=cl,Ul.init(e,t),e._zod.bag.contentEncoding=`base64`,e._zod.check=n=>{lu(n.value)||n.issues.push({code:`invalid_format`,format:`base64`,input:n.value,inst:e,continue:!t.abort})}});function du(e){if(!ll.test(e))return!1;let t=e.replace(/[-_]/g,e=>e===`-`?`+`:`/`);return lu(t.padEnd(Math.ceil(t.length/4)*4,`=`))}var fu=Z(`$ZodBase64URL`,(e,t)=>{t.pattern??=ll,Ul.init(e,t),e._zod.bag.contentEncoding=`base64url`,e._zod.check=n=>{du(n.value)||n.issues.push({code:`invalid_format`,format:`base64url`,input:n.value,inst:e,continue:!t.abort})}}),pu=Z(`$ZodE164`,(e,t)=>{t.pattern??=dl,Ul.init(e,t)});function mu(e,t=null){try{let n=e.split(`.`);if(n.length!==3)return!1;let[r]=n;if(!r)return!1;let i=JSON.parse(atob(r));return!(`typ`in i&&i?.typ!==`JWT`||!i.alg||t&&(!(`alg`in i)||i.alg!==t))}catch{return!1}}var hu=Z(`$ZodJWT`,(e,t)=>{Ul.init(e,t),e._zod.check=n=>{mu(n.value,t.alg)||n.issues.push({code:`invalid_format`,format:`jwt`,input:n.value,inst:e,continue:!t.abort})}}),gu=Z(`$ZodNumber`,(e,t)=>{Vl.init(e,t),e._zod.pattern=e._zod.bag.pattern??yl,e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=Number(n.value)}catch{}let i=n.value;if(typeof i==`number`&&!Number.isNaN(i)&&Number.isFinite(i))return n;let a=typeof i==`number`?Number.isNaN(i)?`NaN`:Number.isFinite(i)?void 0:`Infinity`:void 0;return n.issues.push({expected:`number`,code:`invalid_type`,input:i,inst:e,...a?{received:a}:{}}),n}}),_u=Z(`$ZodNumberFormat`,(e,t)=>{Dl.init(e,t),gu.init(e,t)}),vu=Z(`$ZodUnknown`,(e,t)=>{Vl.init(e,t),e._zod.parse=e=>e}),yu=Z(`$ZodNever`,(e,t)=>{Vl.init(e,t),e._zod.parse=(t,n)=>(t.issues.push({expected:`never`,code:`invalid_type`,input:t.value,inst:e}),t)});function bu(e,t,n){e.issues.length&&t.issues.push(...Sc(n,e.issues)),t.value[n]=e.value}var xu=Z(`$ZodArray`,(e,t)=>{Vl.init(e,t),e._zod.parse=(n,r)=>{let i=n.value;if(!Array.isArray(i))return n.issues.push({expected:`array`,code:`invalid_type`,input:i,inst:e}),n;n.value=Array(i.length);let a=[];for(let e=0;ebu(t,n,e))):bu(s,n,e)}return a.length?Promise.all(a).then(()=>n):n}});function Su(e,t,n,r,i,a){let o=n in r;if(e.issues.length){if(i&&a&&!o)return;t.issues.push(...Sc(n,e.issues))}if(!o&&!i){e.issues.length||t.issues.push({code:`invalid_type`,expected:`nonoptional`,input:void 0,path:[n]});return}e.value===void 0?o&&(t.value[n]=void 0):t.value[n]=e.value}function Cu(e){let t=Object.keys(e.shape);for(let n of t)if(!e.shape?.[n]?._zod?.traits?.has(`$ZodType`))throw Error(`Invalid element at key "${n}": expected a Zod schema`);let n=dc(e.shape);return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}function wu(e,t,n,r,i,a){let o=[],s=i.keySet,c=i.catchall._zod,l=c.def.type,u=c.optin===`optional`,d=c.optout===`optional`;for(let i in t){if(i===`__proto__`||s.has(i))continue;if(l===`never`){o.push(i);continue}let a=c.run({value:t[i],issues:[]},r);a instanceof Promise?e.push(a.then(e=>Su(e,n,i,t,u,d))):Su(a,n,i,t,u,d)}return o.length&&n.issues.push({code:`unrecognized_keys`,keys:o,input:t,inst:a}),e.length?Promise.all(e).then(()=>n):n}var Tu=Z(`$ZodObject`,(e,t)=>{if(Vl.init(e,t),!Object.getOwnPropertyDescriptor(t,`shape`)?.get){let e=t.shape;Object.defineProperty(t,"shape",{get:()=>{let n={...e};return Object.defineProperty(t,"shape",{value:n}),n}})}let n=Js(()=>Cu(t));Q(e._zod,`propValues`,()=>{let e=t.shape,n={};for(let t in e){let r=e[t]._zod;if(r.values){n[t]??(n[t]=new Set);for(let e of r.values)n[t].add(e)}}return n});let r=ic,i=t.catchall,a;e._zod.parse=(t,o)=>{a??=n.value;let s=t.value;if(!r(s))return t.issues.push({expected:`object`,code:`invalid_type`,input:s,inst:e}),t;t.value={};let c=[],l=a.shape;for(let e of a.keys){let n=l[e],r=n._zod.optin===`optional`,i=n._zod.optout===`optional`,a=n._zod.run({value:s[e],issues:[]},o);a instanceof Promise?c.push(a.then(n=>Su(n,t,e,s,r,i))):Su(a,t,e,s,r,i)}return i?wu(c,s,t,o,n.value,e):c.length?Promise.all(c).then(()=>t):t}}),Eu=Z(`$ZodObjectJIT`,(e,t)=>{Tu.init(e,t);let n=e._zod.parse,r=Js(()=>Cu(t)),i=e=>{let t=new zl([`shape`,`payload`,`ctx`]),n=r.value,i=e=>{let t=tc(e);return`shape[${t}]._zod.run({ value: input[${t}], issues: [] }, ctx)`};t.write(`const input = payload.value;`);let a=Object.create(null),o=0;for(let e of n.keys)a[e]=`key_${o++}`;t.write(`const newResult = {};`);for(let r of n.keys){let n=a[r],o=tc(r),s=e[r],c=s?._zod?.optin===`optional`,l=s?._zod?.optout===`optional`;t.write(`const ${n} = ${i(r)};`),c&&l?t.write(` + if (${n}.issues.length) { + if (${o} in input) { + payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ + ...iss, + path: iss.path ? [${o}, ...iss.path] : [${o}] + }))); + } + } + + if (${n}.value === undefined) { + if (${o} in input) { + newResult[${o}] = undefined; + } + } else { + newResult[${o}] = ${n}.value; + } + + `):c?t.write(` + if (${n}.issues.length) { + payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ + ...iss, + path: iss.path ? [${o}, ...iss.path] : [${o}] + }))); + } + + if (${n}.value === undefined) { + if (${o} in input) { + newResult[${o}] = undefined; + } + } else { + newResult[${o}] = ${n}.value; + } + + `):t.write(` + const ${n}_present = ${o} in input; + if (${n}.issues.length) { + payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ + ...iss, + path: iss.path ? [${o}, ...iss.path] : [${o}] + }))); + } + if (!${n}_present && !${n}.issues.length) { + payload.issues.push({ + code: "invalid_type", + expected: "nonoptional", + input: undefined, + path: [${o}] + }); + } + + if (${n}_present) { + if (${n}.value === undefined) { + newResult[${o}] = undefined; + } else { + newResult[${o}] = ${n}.value; + } + } + + `)}t.write(`payload.value = newResult;`),t.write(`return payload;`);let s=t.compile();return(t,n)=>s(e,t,n)},a,o=ic,s=!Ws.jitless,c=s&&ac.value,l=t.catchall,u;e._zod.parse=(d,f)=>{u??=r.value;let p=d.value;return o(p)?s&&c&&f?.async===!1&&f.jitless!==!0?(a||=i(t.shape),d=a(d,f),l?wu([],p,d,f,u,e):d):n(d,f):(d.issues.push({expected:`object`,code:`invalid_type`,input:p,inst:e}),d)}});function Du(e,t,n,r){for(let n of e)if(n.issues.length===0)return t.value=n.value,t;let i=e.filter(e=>!bc(e));return i.length===1?(t.value=i[0].value,i[0]):(t.issues.push({code:`invalid_union`,input:t.value,inst:n,errors:e.map(e=>e.issues.map(e=>wc(e,r,Gs())))}),t)}var Ou=Z(`$ZodUnion`,(e,t)=>{Vl.init(e,t),Q(e._zod,`optin`,()=>t.options.some(e=>e._zod.optin===`optional`)?`optional`:void 0),Q(e._zod,`optout`,()=>t.options.some(e=>e._zod.optout===`optional`)?`optional`:void 0),Q(e._zod,`values`,()=>{if(t.options.every(e=>e._zod.values))return new Set(t.options.flatMap(e=>Array.from(e._zod.values)))}),Q(e._zod,`pattern`,()=>{if(t.options.every(e=>e._zod.pattern)){let e=t.options.map(e=>e._zod.pattern);return RegExp(`^(${e.map(e=>Xs(e.source)).join(`|`)})$`)}});let n=t.options.length===1?t.options[0]._zod.run:null;e._zod.parse=(r,i)=>{if(n)return n(r,i);let a=!1,o=[];for(let e of t.options){let t=e._zod.run({value:r.value,issues:[]},i);if(t instanceof Promise)o.push(t),a=!0;else{if(t.issues.length===0)return t;o.push(t)}}return a?Promise.all(o).then(t=>Du(t,r,e,i)):Du(o,r,e,i)}}),ku=Z(`$ZodIntersection`,(e,t)=>{Vl.init(e,t),e._zod.parse=(e,n)=>{let r=e.value,i=t.left._zod.run({value:r,issues:[]},n),a=t.right._zod.run({value:r,issues:[]},n);return i instanceof Promise||a instanceof Promise?Promise.all([i,a]).then(([t,n])=>ju(e,t,n)):ju(e,i,a)}});function Au(e,t){if(e===t||e instanceof Date&&t instanceof Date&&+e==+t)return{valid:!0,data:e};if(oc(e)&&oc(t)){let n=Object.keys(t),r=Object.keys(e).filter(e=>n.indexOf(e)!==-1),i={...e,...t};for(let n of r){let r=Au(e[n],t[n]);if(!r.valid)return{valid:!1,mergeErrorPath:[n,...r.mergeErrorPath]};i[n]=r.data}return{valid:!0,data:i}}if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return{valid:!1,mergeErrorPath:[]};let n=[];for(let r=0;re.l&&e.r).map(([e])=>e);if(a.length&&i&&e.issues.push({...i,keys:a}),bc(e))return e;let o=Au(t.value,n.value);if(!o.valid)throw Error(`Unmergable intersection. Error path: ${JSON.stringify(o.mergeErrorPath)}`);return e.value=o.data,e}var Mu=Z(`$ZodEnum`,(e,t)=>{Vl.init(e,t);let n=Ks(t.entries),r=new Set(n);e._zod.values=r,e._zod.pattern=RegExp(`^(${n.filter(e=>cc.has(typeof e)).map(e=>typeof e==`string`?lc(e):e.toString()).join(`|`)})$`),e._zod.parse=(t,i)=>{let a=t.value;return r.has(a)||t.issues.push({code:`invalid_value`,values:n,input:a,inst:e}),t}}),Nu=Z(`$ZodLiteral`,(e,t)=>{if(Vl.init(e,t),t.values.length===0)throw Error(`Cannot create literal schema with no valid values`);let n=new Set(t.values);e._zod.values=n,e._zod.pattern=RegExp(`^(${t.values.map(e=>typeof e==`string`?lc(e):e?lc(e.toString()):String(e)).join(`|`)})$`),e._zod.parse=(r,i)=>{let a=r.value;return n.has(a)||r.issues.push({code:`invalid_value`,values:t.values,input:a,inst:e}),r}}),Pu=Z(`$ZodTransform`,(e,t)=>{Vl.init(e,t),e._zod.optin=`optional`,e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new Us(e.constructor.name);let i=t.transform(n.value,n);if(r.async)return(i instanceof Promise?i:Promise.resolve(i)).then(e=>(n.value=e,n.fallback=!0,n));if(i instanceof Promise)throw new Hs;return n.value=i,n.fallback=!0,n}});function Fu(e,t){return t===void 0&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}var Iu=Z(`$ZodOptional`,(e,t)=>{Vl.init(e,t),e._zod.optin=`optional`,e._zod.optout=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),Q(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${Xs(e.source)})?$`):void 0}),e._zod.parse=(e,n)=>{if(t.innerType._zod.optin===`optional`){let r=e.value,i=t.innerType._zod.run(e,n);return i instanceof Promise?i.then(e=>Fu(e,r)):Fu(i,r)}return e.value===void 0?e:t.innerType._zod.run(e,n)}}),Lu=Z(`$ZodExactOptional`,(e,t)=>{Iu.init(e,t),Q(e._zod,`values`,()=>t.innerType._zod.values),Q(e._zod,`pattern`,()=>t.innerType._zod.pattern),e._zod.parse=(e,n)=>t.innerType._zod.run(e,n)}),Ru=Z(`$ZodNullable`,(e,t)=>{Vl.init(e,t),Q(e._zod,`optin`,()=>t.innerType._zod.optin),Q(e._zod,`optout`,()=>t.innerType._zod.optout),Q(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${Xs(e.source)}|null)$`):void 0}),Q(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,null]):void 0),e._zod.parse=(e,n)=>e.value===null?e:t.innerType._zod.run(e,n)}),zu=Z(`$ZodDefault`,(e,t)=>{Vl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);if(e.value===void 0)return e.value=t.defaultValue,e;let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(e=>Bu(e,t)):Bu(r,t)}});function Bu(e,t){return e.value===void 0&&(e.value=t.defaultValue),e}var Vu=Z(`$ZodPrefault`,(e,t)=>{Vl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>(n.direction===`backward`||e.value===void 0&&(e.value=t.defaultValue),t.innerType._zod.run(e,n))}),Hu=Z(`$ZodNonOptional`,(e,t)=>{Vl.init(e,t),Q(e._zod,`values`,()=>{let e=t.innerType._zod.values;return e?new Set([...e].filter(e=>e!==void 0)):void 0}),e._zod.parse=(n,r)=>{let i=t.innerType._zod.run(n,r);return i instanceof Promise?i.then(t=>Uu(t,e)):Uu(i,e)}});function Uu(e,t){return!e.issues.length&&e.value===void 0&&e.issues.push({code:`invalid_type`,expected:`nonoptional`,input:e.value,inst:t}),e}var Wu=Z(`$ZodCatch`,(e,t)=>{Vl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`optout`,()=>t.innerType._zod.optout),Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(r=>(e.value=r.value,r.issues.length&&(e.value=t.catchValue({...e,error:{issues:r.issues.map(e=>wc(e,n,Gs()))},input:e.value}),e.issues=[],e.fallback=!0),e)):(e.value=r.value,r.issues.length&&(e.value=t.catchValue({...e,error:{issues:r.issues.map(e=>wc(e,n,Gs()))},input:e.value}),e.issues=[],e.fallback=!0),e)}}),Gu=Z(`$ZodPipe`,(e,t)=>{Vl.init(e,t),Q(e._zod,`values`,()=>t.in._zod.values),Q(e._zod,`optin`,()=>t.in._zod.optin),Q(e._zod,`optout`,()=>t.out._zod.optout),Q(e._zod,`propValues`,()=>t.in._zod.propValues),e._zod.parse=(e,n)=>{if(n.direction===`backward`){let r=t.out._zod.run(e,n);return r instanceof Promise?r.then(e=>Ku(e,t.in,n)):Ku(r,t.in,n)}let r=t.in._zod.run(e,n);return r instanceof Promise?r.then(e=>Ku(e,t.out,n)):Ku(r,t.out,n)}});function Ku(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues,fallback:e.fallback},n)}var qu=Z(`$ZodReadonly`,(e,t)=>{Vl.init(e,t),Q(e._zod,`propValues`,()=>t.innerType._zod.propValues),Q(e._zod,`values`,()=>t.innerType._zod.values),Q(e._zod,`optin`,()=>t.innerType?._zod?.optin),Q(e._zod,`optout`,()=>t.innerType?._zod?.optout),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(Ju):Ju(r)}});function Ju(e){return e.value=Object.freeze(e.value),e}var Yu=Z(`$ZodCustom`,(e,t)=>{Sl.init(e,t),Vl.init(e,t),e._zod.parse=(e,t)=>e,e._zod.check=n=>{let r=n.value,i=t.fn(r);if(i instanceof Promise)return i.then(t=>Xu(t,n,r,e));Xu(i,n,r,e)}});function Xu(e,t,n,r){if(!e){let e={code:`custom`,input:n,inst:r,path:[...r._zod.def.path??[]],continue:!r._zod.def.abort};r._zod.def.params&&(e.params=r._zod.def.params),t.issues.push(Ec(e))}}var Zu,Qu=class{constructor(){this._map=new WeakMap,this._idmap=new Map}add(e,...t){let n=t[0];return this._map.set(e,n),n&&typeof n==`object`&&`id`in n&&this._idmap.set(n.id,e),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(e){let t=this._map.get(e);return t&&typeof t==`object`&&`id`in t&&this._idmap.delete(t.id),this._map.delete(e),this}get(e){let t=e._zod.parent;if(t){let n={...this.get(t)??{}};delete n.id;let r={...n,...this._map.get(e)};return Object.keys(r).length?r:void 0}return this._map.get(e)}has(e){return this._map.has(e)}};function $u(){return new Qu}(Zu=globalThis).__zod_globalRegistry??(Zu.__zod_globalRegistry=$u());var ed=globalThis.__zod_globalRegistry;function td(e,t){return new e({type:`string`,...$(t)})}function nd(e,t){return new e({type:`string`,format:`email`,check:`string_format`,abort:!1,...$(t)})}function rd(e,t){return new e({type:`string`,format:`guid`,check:`string_format`,abort:!1,...$(t)})}function id(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,...$(t)})}function ad(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v4`,...$(t)})}function od(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v6`,...$(t)})}function sd(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v7`,...$(t)})}function cd(e,t){return new e({type:`string`,format:`url`,check:`string_format`,abort:!1,...$(t)})}function ld(e,t){return new e({type:`string`,format:`emoji`,check:`string_format`,abort:!1,...$(t)})}function ud(e,t){return new e({type:`string`,format:`nanoid`,check:`string_format`,abort:!1,...$(t)})}function dd(e,t){return new e({type:`string`,format:`cuid`,check:`string_format`,abort:!1,...$(t)})}function fd(e,t){return new e({type:`string`,format:`cuid2`,check:`string_format`,abort:!1,...$(t)})}function pd(e,t){return new e({type:`string`,format:`ulid`,check:`string_format`,abort:!1,...$(t)})}function md(e,t){return new e({type:`string`,format:`xid`,check:`string_format`,abort:!1,...$(t)})}function hd(e,t){return new e({type:`string`,format:`ksuid`,check:`string_format`,abort:!1,...$(t)})}function gd(e,t){return new e({type:`string`,format:`ipv4`,check:`string_format`,abort:!1,...$(t)})}function _d(e,t){return new e({type:`string`,format:`ipv6`,check:`string_format`,abort:!1,...$(t)})}function vd(e,t){return new e({type:`string`,format:`cidrv4`,check:`string_format`,abort:!1,...$(t)})}function yd(e,t){return new e({type:`string`,format:`cidrv6`,check:`string_format`,abort:!1,...$(t)})}function bd(e,t){return new e({type:`string`,format:`base64`,check:`string_format`,abort:!1,...$(t)})}function xd(e,t){return new e({type:`string`,format:`base64url`,check:`string_format`,abort:!1,...$(t)})}function Sd(e,t){return new e({type:`string`,format:`e164`,check:`string_format`,abort:!1,...$(t)})}function Cd(e,t){return new e({type:`string`,format:`jwt`,check:`string_format`,abort:!1,...$(t)})}function wd(e,t){return new e({type:`string`,format:`datetime`,check:`string_format`,offset:!1,local:!1,precision:null,...$(t)})}function Td(e,t){return new e({type:`string`,format:`date`,check:`string_format`,...$(t)})}function Ed(e,t){return new e({type:`string`,format:`time`,check:`string_format`,precision:null,...$(t)})}function Dd(e,t){return new e({type:`string`,format:`duration`,check:`string_format`,...$(t)})}function Od(e,t){return new e({type:`number`,checks:[],...$(t)})}function kd(e,t){return new e({type:`number`,check:`number_format`,abort:!1,format:`safeint`,...$(t)})}function Ad(e){return new e({type:`unknown`})}function jd(e,t){return new e({type:`never`,...$(t)})}function Md(e,t){return new wl({check:`less_than`,...$(t),value:e,inclusive:!1})}function Nd(e,t){return new wl({check:`less_than`,...$(t),value:e,inclusive:!0})}function Pd(e,t){return new Tl({check:`greater_than`,...$(t),value:e,inclusive:!1})}function Fd(e,t){return new Tl({check:`greater_than`,...$(t),value:e,inclusive:!0})}function Id(e,t){return new El({check:`multiple_of`,...$(t),value:e})}function Ld(e,t){return new Ol({check:`max_length`,...$(t),maximum:e})}function Rd(e,t){return new kl({check:`min_length`,...$(t),minimum:e})}function zd(e,t){return new Al({check:`length_equals`,...$(t),length:e})}function Bd(e,t){return new Ml({check:`string_format`,format:`regex`,...$(t),pattern:e})}function Vd(e){return new Nl({check:`string_format`,format:`lowercase`,...$(e)})}function Hd(e){return new Pl({check:`string_format`,format:`uppercase`,...$(e)})}function Ud(e,t){return new Fl({check:`string_format`,format:`includes`,...$(t),includes:e})}function Wd(e,t){return new Il({check:`string_format`,format:`starts_with`,...$(t),prefix:e})}function Gd(e,t){return new Ll({check:`string_format`,format:`ends_with`,...$(t),suffix:e})}function Kd(e){return new Rl({check:`overwrite`,tx:e})}function qd(e){return Kd(t=>t.normalize(e))}function Jd(){return Kd(e=>e.trim())}function Yd(){return Kd(e=>e.toLowerCase())}function Xd(){return Kd(e=>e.toUpperCase())}function Zd(){return Kd(e=>nc(e))}function Qd(e,t,n){return new e({type:`array`,element:t,...$(n)})}function $d(e,t,n){return new e({type:`custom`,check:`custom`,fn:t,...$(n)})}function ef(e,t){let n=tf(t=>(t.addIssue=e=>{if(typeof e==`string`)t.issues.push(Ec(e,t.value,n._zod.def));else{let r=e;r.fatal&&(r.continue=!1),r.code??=`custom`,r.input??=t.value,r.inst??=n,r.continue??=!n._zod.def.abort,t.issues.push(Ec(r))}},e(t.value,t)),t);return n}function tf(e,t){let n=new Sl({check:`custom`,...$(t)});return n._zod.check=e,n}function nf(e){let t=e?.target??`draft-2020-12`;return t===`draft-4`&&(t=`draft-04`),t===`draft-7`&&(t=`draft-07`),{processors:e.processors??{},metadataRegistry:e?.metadata??ed,target:t,unrepresentable:e?.unrepresentable??`throw`,override:e?.override??(()=>{}),io:e?.io??`output`,counter:0,seen:new Map,cycles:e?.cycles??`ref`,reused:e?.reused??`inline`,external:e?.external??void 0}}function rf(e,t,n={path:[],schemaPath:[]}){var r;let i=e._zod.def,a=t.seen.get(e);if(a)return a.count++,n.schemaPath.includes(e)&&(a.cycle=n.path),a.schema;let o={schema:{},count:1,cycle:void 0,path:n.path};t.seen.set(e,o);let s=e._zod.toJSONSchema?.();if(s)o.schema=s;else{let r={...n,schemaPath:[...n.schemaPath,e],path:n.path};if(e._zod.processJSONSchema)e._zod.processJSONSchema(t,o.schema,r);else{let n=o.schema,a=t.processors[i.type];if(!a)throw Error(`[toJSONSchema]: Non-representable type encountered: ${i.type}`);a(e,t,n,r)}let a=e._zod.parent;a&&(o.ref||=a,rf(a,t,r),t.seen.get(a).isParent=!0)}let c=t.metadataRegistry.get(e);return c&&Object.assign(o.schema,c),t.io===`input`&&sf(e)&&(delete o.schema.examples,delete o.schema.default),t.io===`input`&&`_prefault`in o.schema&&((r=o.schema).default??(r.default=o.schema._prefault)),delete o.schema._prefault,t.seen.get(e).schema}function af(e,t){let n=e.seen.get(t);if(!n)throw Error(`Unprocessed schema. This is a bug in Zod.`);let r=new Map;for(let t of e.seen.entries()){let n=e.metadataRegistry.get(t[0])?.id;if(n){let e=r.get(n);if(e&&e!==t[0])throw Error(`Duplicate schema id "${n}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);r.set(n,t[0])}}let i=t=>{let r=e.target===`draft-2020-12`?`$defs`:`definitions`;if(e.external){let n=e.external.registry.get(t[0])?.id,i=e.external.uri??(e=>e);if(n)return{ref:i(n)};let a=t[1].defId??t[1].schema.id??`schema${e.counter++}`;return t[1].defId=a,{defId:a,ref:`${i(`__shared`)}#/${r}/${a}`}}if(t[1]===n)return{ref:`#`};let i=`#/${r}/`,a=t[1].schema.id??`__schema${e.counter++}`;return{defId:a,ref:i+a}},a=e=>{if(e[1].schema.$ref)return;let t=e[1],{ref:n,defId:r}=i(e);t.def={...t.schema},r&&(t.defId=r);let a=t.schema;for(let e in a)delete a[e];a.$ref=n};if(e.cycles===`throw`)for(let t of e.seen.entries()){let e=t[1];if(e.cycle)throw Error(`Cycle detected: #/${e.cycle?.join(`/`)}/ + +Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let n of e.seen.entries()){let r=n[1];if(t===n[0]){a(n);continue}if(e.external){let r=e.external.registry.get(n[0])?.id;if(t!==n[0]&&r){a(n);continue}}if(e.metadataRegistry.get(n[0])?.id){a(n);continue}if(r.cycle){a(n);continue}if(r.count>1&&e.reused===`ref`){a(n);continue}}}function of(e,t){let n=e.seen.get(t);if(!n)throw Error(`Unprocessed schema. This is a bug in Zod.`);let r=t=>{let n=e.seen.get(t);if(n.ref===null)return;let i=n.def??n.schema,a={...i},o=n.ref;if(n.ref=null,o){r(o);let n=e.seen.get(o),s=n.schema;if(s.$ref&&(e.target===`draft-07`||e.target===`draft-04`||e.target===`openapi-3.0`)?(i.allOf=i.allOf??[],i.allOf.push(s)):Object.assign(i,s),Object.assign(i,a),t._zod.parent===o)for(let e in i)e!==`$ref`&&e!==`allOf`&&(e in a||delete i[e]);if(s.$ref&&n.def)for(let e in i)e!==`$ref`&&e!==`allOf`&&e in n.def&&JSON.stringify(i[e])===JSON.stringify(n.def[e])&&delete i[e]}let s=t._zod.parent;if(s&&s!==o){r(s);let t=e.seen.get(s);if(t?.schema.$ref&&(i.$ref=t.schema.$ref,t.def))for(let e in i)e!==`$ref`&&e!==`allOf`&&e in t.def&&JSON.stringify(i[e])===JSON.stringify(t.def[e])&&delete i[e]}e.override({zodSchema:t,jsonSchema:i,path:n.path??[]})};for(let t of[...e.seen.entries()].reverse())r(t[0]);let i={};if(e.target===`draft-2020-12`?i.$schema=`https://json-schema.org/draft/2020-12/schema`:e.target===`draft-07`?i.$schema=`http://json-schema.org/draft-07/schema#`:e.target===`draft-04`?i.$schema=`http://json-schema.org/draft-04/schema#`:e.target,e.external?.uri){let n=e.external.registry.get(t)?.id;if(!n)throw Error("Schema is missing an `id` property");i.$id=e.external.uri(n)}Object.assign(i,n.def??n.schema);let a=e.metadataRegistry.get(t)?.id;a!==void 0&&i.id===a&&delete i.id;let o=e.external?.defs??{};for(let t of e.seen.entries()){let e=t[1];e.def&&e.defId&&(e.def.id===e.defId&&delete e.def.id,o[e.defId]=e.def)}e.external||Object.keys(o).length>0&&(e.target===`draft-2020-12`?i.$defs=o:i.definitions=o);try{let n=JSON.parse(JSON.stringify(i));return Object.defineProperty(n,"~standard",{value:{...t[`~standard`],jsonSchema:{input:lf(t,`input`,e.processors),output:lf(t,`output`,e.processors)}},enumerable:!1,writable:!1}),n}catch{throw Error(`Error converting schema to JSON.`)}}function sf(e,t){let n=t??{seen:new Set};if(n.seen.has(e))return!1;n.seen.add(e);let r=e._zod.def;if(r.type===`transform`)return!0;if(r.type===`array`)return sf(r.element,n);if(r.type===`set`)return sf(r.valueType,n);if(r.type===`lazy`)return sf(r.getter(),n);if(r.type===`promise`||r.type===`optional`||r.type===`nonoptional`||r.type===`nullable`||r.type===`readonly`||r.type==="default"||r.type===`prefault`)return sf(r.innerType,n);if(r.type===`intersection`)return sf(r.left,n)||sf(r.right,n);if(r.type===`record`||r.type===`map`)return sf(r.keyType,n)||sf(r.valueType,n);if(r.type===`pipe`)return e._zod.traits.has(`$ZodCodec`)?!0:sf(r.in,n)||sf(r.out,n);if(r.type===`object`){for(let e in r.shape)if(sf(r.shape[e],n))return!0;return!1}if(r.type===`union`){for(let e of r.options)if(sf(e,n))return!0;return!1}if(r.type===`tuple`){for(let e of r.items)if(sf(e,n))return!0;return!!(r.rest&&sf(r.rest,n))}return!1}var cf=(e,t={})=>n=>{let r=nf({...n,processors:t});return rf(e,r),af(r,e),of(r,e)},lf=(e,t,n={})=>r=>{let{libraryOptions:i,target:a}=r??{},o=nf({...i??{},target:a,io:t,processors:n});return rf(e,o),af(o,e),of(o,e)},uf={guid:`uuid`,url:`uri`,datetime:`date-time`,json_string:`json-string`,regex:``},df=(e,t,n,r)=>{let i=n;i.type=`string`;let{minimum:a,maximum:o,format:s,patterns:c,contentEncoding:l}=e._zod.bag;if(typeof a==`number`&&(i.minLength=a),typeof o==`number`&&(i.maxLength=o),s&&(i.format=uf[s]??s,i.format===``&&delete i.format,s===`time`&&delete i.format),l&&(i.contentEncoding=l),c&&c.size>0){let e=[...c];e.length===1?i.pattern=e[0].source:e.length>1&&(i.allOf=[...e.map(e=>({...t.target===`draft-07`||t.target===`draft-04`||t.target===`openapi-3.0`?{type:`string`}:{},pattern:e.source}))])}},ff=(e,t,n,r)=>{let i=n,{minimum:a,maximum:o,format:s,multipleOf:c,exclusiveMaximum:l,exclusiveMinimum:u}=e._zod.bag;i.type=typeof s==`string`&&s.includes(`int`)?`integer`:`number`;let d=typeof u==`number`&&u>=(a??-1/0),f=typeof l==`number`&&l<=(o??1/0),p=t.target===`draft-04`||t.target===`openapi-3.0`;d?p?(i.minimum=u,i.exclusiveMinimum=!0):i.exclusiveMinimum=u:typeof a==`number`&&(i.minimum=a),f?p?(i.maximum=l,i.exclusiveMaximum=!0):i.exclusiveMaximum=l:typeof o==`number`&&(i.maximum=o),typeof c==`number`&&(i.multipleOf=c)},pf=(e,t,n,r)=>{n.not={}},mf=(e,t,n,r)=>{let i=e._zod.def,a=Ks(i.entries);a.every(e=>typeof e==`number`)&&(n.type=`number`),a.every(e=>typeof e==`string`)&&(n.type=`string`),n.enum=a},hf=(e,t,n,r)=>{let i=e._zod.def,a=[];for(let e of i.values)if(e===void 0){if(t.unrepresentable===`throw`)throw Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof e==`bigint`){if(t.unrepresentable===`throw`)throw Error(`BigInt literals cannot be represented in JSON Schema`);a.push(Number(e))}else a.push(e);if(a.length!==0)if(a.length===1){let e=a[0];n.type=e===null?`null`:typeof e,t.target===`draft-04`||t.target===`openapi-3.0`?n.enum=[e]:n.const=e}else a.every(e=>typeof e==`number`)&&(n.type=`number`),a.every(e=>typeof e==`string`)&&(n.type=`string`),a.every(e=>typeof e==`boolean`)&&(n.type=`boolean`),a.every(e=>e===null)&&(n.type=`null`),n.enum=a},gf=(e,t,n,r)=>{if(t.unrepresentable===`throw`)throw Error(`Custom types cannot be represented in JSON Schema`)},_f=(e,t,n,r)=>{if(t.unrepresentable===`throw`)throw Error(`Transforms cannot be represented in JSON Schema`)},vf=(e,t,n,r)=>{let i=n,a=e._zod.def,{minimum:o,maximum:s}=e._zod.bag;typeof o==`number`&&(i.minItems=o),typeof s==`number`&&(i.maxItems=s),i.type=`array`,i.items=rf(a.element,t,{...r,path:[...r.path,`items`]})},yf=(e,t,n,r)=>{let i=n,a=e._zod.def;i.type=`object`,i.properties={};let o=a.shape;for(let e in o)i.properties[e]=rf(o[e],t,{...r,path:[...r.path,`properties`,e]});let s=new Set(Object.keys(o)),c=new Set([...s].filter(e=>{let n=a.shape[e]._zod;return t.io===`input`?n.optin===void 0:n.optout===void 0}));c.size>0&&(i.required=Array.from(c)),a.catchall?._zod.def.type===`never`?i.additionalProperties=!1:a.catchall?a.catchall&&(i.additionalProperties=rf(a.catchall,t,{...r,path:[...r.path,`additionalProperties`]})):t.io===`output`&&(i.additionalProperties=!1)},bf=(e,t,n,r)=>{let i=e._zod.def,a=i.inclusive===!1,o=i.options.map((e,n)=>rf(e,t,{...r,path:[...r.path,a?`oneOf`:`anyOf`,n]}));a?n.oneOf=o:n.anyOf=o},xf=(e,t,n,r)=>{let i=e._zod.def,a=rf(i.left,t,{...r,path:[...r.path,`allOf`,0]}),o=rf(i.right,t,{...r,path:[...r.path,`allOf`,1]}),s=e=>`allOf`in e&&Object.keys(e).length===1;n.allOf=[...s(a)?a.allOf:[a],...s(o)?o.allOf:[o]]},Sf=(e,t,n,r)=>{let i=e._zod.def,a=rf(i.innerType,t,r),o=t.seen.get(e);t.target===`openapi-3.0`?(o.ref=i.innerType,n.nullable=!0):n.anyOf=[a,{type:`null`}]},Cf=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType},wf=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,n.default=JSON.parse(JSON.stringify(i.defaultValue))},Tf=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,t.io===`input`&&(n._prefault=JSON.parse(JSON.stringify(i.defaultValue)))},Ef=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType;let o;try{o=i.catchValue(void 0)}catch{throw Error(`Dynamic catch values are not supported in JSON Schema`)}n.default=o},Df=(e,t,n,r)=>{let i=e._zod.def,a=i.in._zod.traits.has(`$ZodTransform`),o=t.io===`input`?a?i.out:i.in:i.out;rf(o,t,r);let s=t.seen.get(e);s.ref=o},Of=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,n.readOnly=!0},kf=(e,t,n,r)=>{let i=e._zod.def;rf(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType},Af=Z(`ZodISODateTime`,(e,t)=>{tu.init(e,t),rp.init(e,t)});function jf(e){return wd(Af,e)}var Mf=Z(`ZodISODate`,(e,t)=>{nu.init(e,t),rp.init(e,t)});function Nf(e){return Td(Mf,e)}var Pf=Z(`ZodISOTime`,(e,t)=>{ru.init(e,t),rp.init(e,t)});function Ff(e){return Ed(Pf,e)}var If=Z(`ZodISODuration`,(e,t)=>{iu.init(e,t),rp.init(e,t)});function Lf(e){return Dd(If,e)}var Rf=Z(`ZodError`,(e,t)=>{Oc.init(e,t),e.name=`ZodError`,Object.defineProperties(e,{format:{value:t=>jc(e,t)},flatten:{value:t=>Ac(e,t)},addIssue:{value:t=>{e.issues.push(t),e.message=JSON.stringify(e.issues,qs,2)}},addIssues:{value:t=>{e.issues.push(...t),e.message=JSON.stringify(e.issues,qs,2)}},isEmpty:{get(){return e.issues.length===0}}})},{Parent:Error}),zf=Mc(Rf),Bf=Nc(Rf),Vf=Pc(Rf),Hf=Ic(Rf),Uf=Rc(Rf),Wf=zc(Rf),Gf=Bc(Rf),Kf=Vc(Rf),qf=Hc(Rf),Jf=Uc(Rf),Yf=Wc(Rf),Xf=Gc(Rf),Zf=new WeakMap;function Qf(e,t,n){let r=Object.getPrototypeOf(e),i=Zf.get(r);if(i||(i=new Set,Zf.set(r,i)),!i.has(t)){i.add(t);for(let e in n){let t=n[e];Object.defineProperty(r,e,{configurable:!0,enumerable:!1,get(){let n=t.bind(this);return Object.defineProperty(this,e,{configurable:!0,writable:!0,enumerable:!0,value:n}),n},set(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,enumerable:!0,value:t})}})}}}var $f=Z(`ZodType`,(e,t)=>(Vl.init(e,t),Object.assign(e[`~standard`],{jsonSchema:{input:lf(e,`input`),output:lf(e,`output`)}}),e.toJSONSchema=cf(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.parse=(t,n)=>zf(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>Vf(e,t,n),e.parseAsync=async(t,n)=>Bf(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>Hf(e,t,n),e.spa=e.safeParseAsync,e.encode=(t,n)=>Uf(e,t,n),e.decode=(t,n)=>Wf(e,t,n),e.encodeAsync=async(t,n)=>Gf(e,t,n),e.decodeAsync=async(t,n)=>Kf(e,t,n),e.safeEncode=(t,n)=>qf(e,t,n),e.safeDecode=(t,n)=>Jf(e,t,n),e.safeEncodeAsync=async(t,n)=>Yf(e,t,n),e.safeDecodeAsync=async(t,n)=>Xf(e,t,n),Qf(e,`ZodType`,{check(...e){let t=this.def;return this.clone(ec(t,{checks:[...t.checks??[],...e.map(e=>typeof e==`function`?{_zod:{check:e,def:{check:`custom`},onattach:[]}}:e)]}),{parent:!0})},with(...e){return this.check(...e)},clone(e,t){return uc(this,e,t)},brand(){return this},register(e,t){return e.add(this,t),this},refine(e,t){return this.check(um(e,t))},superRefine(e,t){return this.check(dm(e,t))},overwrite(e){return this.check(Kd(e))},optional(){return Kp(this)},exactOptional(){return Jp(this)},nullable(){return Xp(this)},nullish(){return Kp(Xp(this))},nonoptional(e){return nm(this,e)},array(){return Mp(this)},or(e){return Ip([this,e])},and(e){return Rp(this,e)},transform(e){return om(this,Wp(e))},default(e){return Qp(this,e)},prefault(e){return em(this,e)},catch(e){return im(this,e)},pipe(e){return om(this,e)},readonly(){return cm(this)},describe(e){let t=this.clone();return ed.add(t,{description:e}),t},meta(...e){if(e.length===0)return ed.get(this);let t=this.clone();return ed.add(t,e[0]),t},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(e){return e(this)}}),Object.defineProperty(e,"description",{get(){return ed.get(e)?.description},configurable:!0}),e)),ep=Z(`_ZodString`,(e,t)=>{Hl.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>df(e,t,n,r);let n=e._zod.bag;e.format=n.format??null,e.minLength=n.minimum??null,e.maxLength=n.maximum??null,Qf(e,`_ZodString`,{regex(...e){return this.check(Bd(...e))},includes(...e){return this.check(Ud(...e))},startsWith(...e){return this.check(Wd(...e))},endsWith(...e){return this.check(Gd(...e))},min(...e){return this.check(Rd(...e))},max(...e){return this.check(Ld(...e))},length(...e){return this.check(zd(...e))},nonempty(...e){return this.check(Rd(1,...e))},lowercase(e){return this.check(Vd(e))},uppercase(e){return this.check(Hd(e))},trim(){return this.check(Jd())},normalize(...e){return this.check(qd(...e))},toLowerCase(){return this.check(Yd())},toUpperCase(){return this.check(Xd())},slugify(){return this.check(Zd())}})}),tp=Z(`ZodString`,(e,t)=>{Hl.init(e,t),ep.init(e,t),e.email=t=>e.check(nd(ip,t)),e.url=t=>e.check(cd(sp,t)),e.jwt=t=>e.check(Cd(Sp,t)),e.emoji=t=>e.check(ld(cp,t)),e.guid=t=>e.check(rd(ap,t)),e.uuid=t=>e.check(id(op,t)),e.uuidv4=t=>e.check(ad(op,t)),e.uuidv6=t=>e.check(od(op,t)),e.uuidv7=t=>e.check(sd(op,t)),e.nanoid=t=>e.check(ud(lp,t)),e.guid=t=>e.check(rd(ap,t)),e.cuid=t=>e.check(dd(up,t)),e.cuid2=t=>e.check(fd(dp,t)),e.ulid=t=>e.check(pd(fp,t)),e.base64=t=>e.check(bd(yp,t)),e.base64url=t=>e.check(xd(bp,t)),e.xid=t=>e.check(md(pp,t)),e.ksuid=t=>e.check(hd(mp,t)),e.ipv4=t=>e.check(gd(hp,t)),e.ipv6=t=>e.check(_d(gp,t)),e.cidrv4=t=>e.check(vd(_p,t)),e.cidrv6=t=>e.check(yd(vp,t)),e.e164=t=>e.check(Sd(xp,t)),e.datetime=t=>e.check(jf(t)),e.date=t=>e.check(Nf(t)),e.time=t=>e.check(Ff(t)),e.duration=t=>e.check(Lf(t))});function np(e){return td(tp,e)}var rp=Z(`ZodStringFormat`,(e,t)=>{Ul.init(e,t),ep.init(e,t)}),ip=Z(`ZodEmail`,(e,t)=>{Kl.init(e,t),rp.init(e,t)}),ap=Z(`ZodGUID`,(e,t)=>{Wl.init(e,t),rp.init(e,t)}),op=Z(`ZodUUID`,(e,t)=>{Gl.init(e,t),rp.init(e,t)}),sp=Z(`ZodURL`,(e,t)=>{ql.init(e,t),rp.init(e,t)}),cp=Z(`ZodEmoji`,(e,t)=>{Jl.init(e,t),rp.init(e,t)}),lp=Z(`ZodNanoID`,(e,t)=>{Yl.init(e,t),rp.init(e,t)}),up=Z(`ZodCUID`,(e,t)=>{Xl.init(e,t),rp.init(e,t)}),dp=Z(`ZodCUID2`,(e,t)=>{Zl.init(e,t),rp.init(e,t)}),fp=Z(`ZodULID`,(e,t)=>{Ql.init(e,t),rp.init(e,t)}),pp=Z(`ZodXID`,(e,t)=>{$l.init(e,t),rp.init(e,t)}),mp=Z(`ZodKSUID`,(e,t)=>{eu.init(e,t),rp.init(e,t)}),hp=Z(`ZodIPv4`,(e,t)=>{au.init(e,t),rp.init(e,t)}),gp=Z(`ZodIPv6`,(e,t)=>{ou.init(e,t),rp.init(e,t)}),_p=Z(`ZodCIDRv4`,(e,t)=>{su.init(e,t),rp.init(e,t)}),vp=Z(`ZodCIDRv6`,(e,t)=>{cu.init(e,t),rp.init(e,t)}),yp=Z(`ZodBase64`,(e,t)=>{uu.init(e,t),rp.init(e,t)}),bp=Z(`ZodBase64URL`,(e,t)=>{fu.init(e,t),rp.init(e,t)}),xp=Z(`ZodE164`,(e,t)=>{pu.init(e,t),rp.init(e,t)}),Sp=Z(`ZodJWT`,(e,t)=>{hu.init(e,t),rp.init(e,t)}),Cp=Z(`ZodNumber`,(e,t)=>{gu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>ff(e,t,n,r),Qf(e,`ZodNumber`,{gt(e,t){return this.check(Pd(e,t))},gte(e,t){return this.check(Fd(e,t))},min(e,t){return this.check(Fd(e,t))},lt(e,t){return this.check(Md(e,t))},lte(e,t){return this.check(Nd(e,t))},max(e,t){return this.check(Nd(e,t))},int(e){return this.check(Ep(e))},safe(e){return this.check(Ep(e))},positive(e){return this.check(Pd(0,e))},nonnegative(e){return this.check(Fd(0,e))},negative(e){return this.check(Md(0,e))},nonpositive(e){return this.check(Nd(0,e))},multipleOf(e,t){return this.check(Id(e,t))},step(e,t){return this.check(Id(e,t))},finite(){return this}});let n=e._zod.bag;e.minValue=Math.max(n.minimum??-1/0,n.exclusiveMinimum??-1/0)??null,e.maxValue=Math.min(n.maximum??1/0,n.exclusiveMaximum??1/0)??null,e.isInt=(n.format??``).includes(`int`)||Number.isSafeInteger(n.multipleOf??.5),e.isFinite=!0,e.format=n.format??null});function wp(e){return Od(Cp,e)}var Tp=Z(`ZodNumberFormat`,(e,t)=>{_u.init(e,t),Cp.init(e,t)});function Ep(e){return kd(Tp,e)}var Dp=Z(`ZodUnknown`,(e,t)=>{vu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(e,t,n)=>void 0});function Op(){return Ad(Dp)}var kp=Z(`ZodNever`,(e,t)=>{yu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>pf(e,t,n,r)});function Ap(e){return jd(kp,e)}var jp=Z(`ZodArray`,(e,t)=>{xu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>vf(e,t,n,r),e.element=t.element,Qf(e,`ZodArray`,{min(e,t){return this.check(Rd(e,t))},nonempty(e){return this.check(Rd(1,e))},max(e,t){return this.check(Ld(e,t))},length(e,t){return this.check(zd(e,t))},unwrap(){return this.element}})});function Mp(e,t){return Qd(jp,e,t)}var Np=Z(`ZodObject`,(e,t)=>{Eu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>yf(e,t,n,r),Q(e,`shape`,()=>t.shape),Qf(e,`ZodObject`,{keyof(){return Bp(Object.keys(this._zod.def.shape))},catchall(e){return this.clone({...this._zod.def,catchall:e})},passthrough(){return this.clone({...this._zod.def,catchall:Op()})},loose(){return this.clone({...this._zod.def,catchall:Op()})},strict(){return this.clone({...this._zod.def,catchall:Ap()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(e){return hc(this,e)},safeExtend(e){return gc(this,e)},merge(e){return _c(this,e)},pick(e){return pc(this,e)},omit(e){return mc(this,e)},partial(...e){return vc(Gp,this,e[0])},required(...e){return yc(tm,this,e[0])}})});function Pp(e,t){return new Np({type:`object`,shape:e??{},...$(t)})}var Fp=Z(`ZodUnion`,(e,t)=>{Ou.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>bf(e,t,n,r),e.options=t.options});function Ip(e,t){return new Fp({type:`union`,options:e,...$(t)})}var Lp=Z(`ZodIntersection`,(e,t)=>{ku.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>xf(e,t,n,r)});function Rp(e,t){return new Lp({type:`intersection`,left:e,right:t})}var zp=Z(`ZodEnum`,(e,t)=>{Mu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>mf(e,t,n,r),e.enum=t.entries,e.options=Object.values(t.entries);let n=new Set(Object.keys(t.entries));e.extract=(e,r)=>{let i={};for(let r of e)if(n.has(r))i[r]=t.entries[r];else throw Error(`Key ${r} not found in enum`);return new zp({...t,checks:[],...$(r),entries:i})},e.exclude=(e,r)=>{let i={...t.entries};for(let t of e)if(n.has(t))delete i[t];else throw Error(`Key ${t} not found in enum`);return new zp({...t,checks:[],...$(r),entries:i})}});function Bp(e,t){return new zp({type:`enum`,entries:Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e,...$(t)})}var Vp=Z(`ZodLiteral`,(e,t)=>{Nu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>hf(e,t,n,r),e.values=new Set(t.values),Object.defineProperty(e,"value",{get(){if(t.values.length>1)throw Error("This schema contains multiple valid literal values. Use `.values` instead.");return t.values[0]}})});function Hp(e,t){return new Vp({type:`literal`,values:Array.isArray(e)?e:[e],...$(t)})}var Up=Z(`ZodTransform`,(e,t)=>{Pu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>_f(e,t,n,r),e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new Us(e.constructor.name);n.addIssue=r=>{if(typeof r==`string`)n.issues.push(Ec(r,n.value,t));else{let t=r;t.fatal&&(t.continue=!1),t.code??=`custom`,t.input??=n.value,t.inst??=e,n.issues.push(Ec(t))}};let i=t.transform(n.value,n);return i instanceof Promise?i.then(e=>(n.value=e,n.fallback=!0,n)):(n.value=i,n.fallback=!0,n)}});function Wp(e){return new Up({type:`transform`,transform:e})}var Gp=Z(`ZodOptional`,(e,t)=>{Iu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>kf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Kp(e){return new Gp({type:`optional`,innerType:e})}var qp=Z(`ZodExactOptional`,(e,t)=>{Lu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>kf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Jp(e){return new qp({type:`optional`,innerType:e})}var Yp=Z(`ZodNullable`,(e,t)=>{Ru.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Sf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Xp(e){return new Yp({type:`nullable`,innerType:e})}var Zp=Z(`ZodDefault`,(e,t)=>{zu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>wf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function Qp(e,t){return new Zp({type:`default`,innerType:e,get defaultValue(){return typeof t==`function`?t():sc(t)}})}var $p=Z(`ZodPrefault`,(e,t)=>{Vu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Tf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function em(e,t){return new $p({type:`prefault`,innerType:e,get defaultValue(){return typeof t==`function`?t():sc(t)}})}var tm=Z(`ZodNonOptional`,(e,t)=>{Hu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Cf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function nm(e,t){return new tm({type:`nonoptional`,innerType:e,...$(t)})}var rm=Z(`ZodCatch`,(e,t)=>{Wu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Ef(e,t,n,r),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function im(e,t){return new rm({type:`catch`,innerType:e,catchValue:typeof t==`function`?t:()=>t})}var am=Z(`ZodPipe`,(e,t)=>{Gu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Df(e,t,n,r),e.in=t.in,e.out=t.out});function om(e,t){return new am({type:`pipe`,in:e,out:t})}var sm=Z(`ZodReadonly`,(e,t)=>{qu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Of(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function cm(e){return new sm({type:`readonly`,innerType:e})}var lm=Z(`ZodCustom`,(e,t)=>{Yu.init(e,t),$f.init(e,t),e._zod.processJSONSchema=(t,n,r)=>gf(e,t,n,r)});function um(e,t={}){return $d(lm,e,t)}function dm(e,t){return ef(e,t)}var fm=U(`
            `,1),pm=U(` `,1);function mm(e,t){We(t,!0);let n=()=>A(_,`$hasErrors`,o),r=()=>A(v,`$isDirty`,o),i=()=>A(g,`$errors`,o),a=()=>A(y,`$isDirtyByField`,o),[o,s]=ft(),c=Pp({username:np().min(3).max(20).regex(/^\S+$/,`Must not contain spaces`),email:np().min(1,`Required`).email(),age:wp().int().min(18).max(120),website:np().url().optional().or(Hp(``)),bio:np().max(200).optional()});function l(e,t,n){let r=e.safeParse(t);if(r.success)return Object.fromEntries(n.map(e=>[e,``]));let i={};for(let e of r.error.issues){let t=String(e.path[0]);Object.hasOwn(i,t)||(i[t]=e.message)}return Object.fromEntries(n.map(e=>[e,i[e]??``]))}let u=c.pick({username:!0,email:!0,age:!0,website:!0}),d=Object.keys(u.shape),f=[...d,`bio`],p={username:{label:`Username`,placeholder:`Enter username`,type:`text`},email:{label:`Email`,placeholder:`Enter email`,type:`email`},age:{label:`Age`,placeholder:`Enter age`,type:`number`},website:{label:`Website`,placeholder:`https://example.com`,type:`text`}},{data:m,batch:h,state:{errors:g,hasErrors:_,isDirty:v,isDirtyByField:y}}=ua({username:``,email:``,age:0,website:``,bio:``},{validator:e=>l(c,e,f)}),b=()=>{h(e=>{e.username=`user${X()}`,e.email=`${X()}@example.com`,e.age=Ba(18,65),e.bio=`Hello, I am a demo user!`,e.website=`https://${X()}.com`})},x=String.raw`import { z } from 'zod'; + +const userSchema = z.object({ + username: z.string().min(3).max(20).regex(/^\S+$/, 'Must not contain spaces'), + email: z.string().min(1, 'Required').email(), + age: z.number().int().min(18).max(120), + website: z.string().url().optional().or(z.literal('')), + bio: z.string().max(200).optional() +});`;Ma(e,{description:`Demonstrates using Zod schemas for validation with svstate, including dynamic form rendering via z.pick() shape keys.`,title:`Zod Integration Demo`,main:e=>{var t=fm(),o=I(t);za(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),c=F(s);ti(c,16,()=>d,e=>e,(e,t)=>{let n=j(()=>p[t]);{let r=j(()=>i()?.[t]),o=j(()=>t!==`website`);Y(e,{get id(){return t},get error(){return V(r)},get isDirty(){return a()[t]},get label(){return V(n).label},get placeholder(){return V(n).placeholder},get required(){return V(o)},get type(){return V(n).type},get value(){return m[t]},set value(e){m[t]=e}})}});var l=L(c,2);{let e=j(()=>i()?.bio);mo(l,{id:`bio`,get error(){return V(e)},get isDirty(){return a().bio},label:`Bio`,placeholder:`Tell us about yourself (not in pick subset)`,get value(){return m.bio},set value(e){m.bio=e}})}k(s),W(e,t)},sidebar:e=>{wa(e,{get data(){return m},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return a()},onFill:b})},sourceCode:e=>{Fa(e,{children:(e,t)=>{var n=pm(),r=I(n);J(r,{get code(){return x},title:`Zod Schema Definition`});var i=L(r,2);J(i,{code:`function zodToSvstateErrors(schema, source, fields) { + const result = schema.safeParse(source); + if (result.success) + return Object.fromEntries(fields.map(f => [f, ''])); + + const errorMap = {}; + for (const issue of result.error.issues) { + const key = String(issue.path[0]); + if (!errorMap[key]) errorMap[key] = issue.message; + } + return Object.fromEntries( + fields.map(f => [f, errorMap[f] ?? '']) + ); +} + +const { data, batch, state: { errors, hasErrors } } = createSvState(sourceData, { + validator: (source) => zodToSvstateErrors(userSchema, source, allFields) +}); + +// batch() runs the Zod schema once for the whole fill, not once per field +batch((draft) => { + draft.username = 'user123'; + draft.email = 'user123@example.com'; +});`,title:`Bridge Function (Zod → svstate)`}),J(L(i,2),{code:`// Pick a subset of fields for dynamic rendering +const pickedSchema = userSchema.pick({ username: true, email: true, age: true, website: true }); +const dynamicFields = Object.keys(pickedSchema.shape); + +const fieldMeta = { + username: { label: 'Username', placeholder: 'Enter username', type: 'text' }, + email: { label: 'Email', placeholder: 'Enter email', type: 'email' }, + age: { label: 'Age', placeholder: 'Enter age', type: 'number' }, + website: { label: 'Website', placeholder: 'https://...', type: 'text' }, +}; + +// In template: +{#each dynamicFields as field} + +{/each} + + +`,title:`Dynamic Rendering via z.pick()`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var hm=U(``),gm=U(`
            svstate logo

            svstate

            A Svelte 5 library that provides a supercharged $state() with deep reactive proxies, validation, snapshot/undo, + and side effects — built for complex, real-world applications.

            $ npm i svstate
            `);function _m(e){let t=[{value:`basic-validation`,name:`Basic Validation`},{value:`nested-objects`,name:`Nested Objects`},{value:`array-property`,name:`Array Property`},{value:`calculated-fields`,name:`Calculated Fields`},{value:`calculated-class`,name:`State with Methods`},{value:`reset-demo`,name:`Reset`},{value:`snapshot-demo`,name:`Snapshot & Rollback`},{value:`action-demo`,name:`Action & Error`},{value:`async-validation`,name:`Async Validation`},{value:`options-demo`,name:`Options`},{value:`zod-validation`,name:`Zod Integration`},{value:`plugin-devtools`,name:`Plugin: Devtools`},{value:`plugin-persist-sync`,name:`Plugin: Persist & Sync`},{value:`plugin-undo-redo`,name:`Plugin: Undo/Redo`},{value:`plugin-autosave-analytics`,name:`Plugin: Autosave & Analytics`}],n=N(`basic-validation`),r=`2.0.0`,i=`/svstate`;var a=gm(),o=F(a),s=F(o),c=L(s,2),l=F(c),u=L(F(l),2),d=F(u);k(u),k(l);var f=L(l,4),p=L(F(f),4);k(f);var m=L(f,2);k(c),k(o);var h=L(o,2),g=F(h),_=F(g),v=L(F(_),2);ti(v,21,()=>t,Zr,(e,t)=>{var n=hm(),r=F(n,!0);k(n);var i={};R(()=>{G(r,V(t).name),i!==(i=V(t).value)&&(n.value=(n.__value=V(t).value)??``)}),W(e,n)}),k(v),k(_),k(g);var y=L(g,2),b=F(y),x=e=>{_o(e,{})},S=e=>{Fo(e,{})},C=e=>{io(e,{})},w=e=>{Eo(e,{})},T=e=>{Co(e,{})},E=e=>{Ms(e,{})},ee=e=>{Bs(e,{})},te=e=>{Ja(e,{})},ne=e=>{uo(e,{})},re=e=>{Wo(e,{})},ie=e=>{mm(e,{})},ae=e=>{ds(e,{})},oe=e=>{vs(e,{})},se=e=>{Os(e,{})},ce=e=>{ts(e,{})};K(b,e=>{V(n)===`basic-validation`?e(x):V(n)===`nested-objects`?e(S,1):V(n)===`array-property`?e(C,2):V(n)===`calculated-fields`?e(w,3):V(n)===`calculated-class`?e(T,4):V(n)===`reset-demo`?e(E,5):V(n)===`snapshot-demo`?e(ee,6):V(n)===`action-demo`?e(te,7):V(n)===`async-validation`?e(ne,8):V(n)===`options-demo`?e(re,9):V(n)===`zod-validation`?e(ie,10):V(n)===`plugin-devtools`?e(ae,11):V(n)===`plugin-persist-sync`?e(oe,12):V(n)===`plugin-undo-redo`?e(se,13):V(n)===`plugin-autosave-analytics`&&e(ce,14)}),k(y),k(h),k(a),R(()=>{yi(s,`src`,`${i}/favicon.png`),G(d,`v${r}`),yi(m,`href`,`${i}/llms.txt`)}),H(`click`,p,()=>navigator.clipboard.writeText(`npm i svstate@${r}`)),pi(v,()=>V(n),e=>P(n,e)),W(e,a)}Nr([`click`]),Wr(_m,{target:document.querySelector(`#app`)}); \ No newline at end of file diff --git a/docs/assets/index-HzneZOQz.js b/docs/assets/index-HzneZOQz.js deleted file mode 100644 index 591c9a6..0000000 --- a/docs/assets/index-HzneZOQz.js +++ /dev/null @@ -1,537 +0,0 @@ -(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible,d=()=>{};function f(e){return e()}function p(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}var h=1024,g=2048,_=4096,v=8192,y=16384,b=32768,x=1<<25,S=65536,C=1<<19,w=1<<20,T=1<<25,E=65536,ee=1<<21,te=1<<22,ne=1<<23,re=Symbol(`$state`),ie=Symbol(`legacy props`),ae=Symbol(``),oe=Symbol(`attributes`),se=Symbol(`class`),ce=Symbol(`style`),le=Symbol(`text`),ue=Symbol(`form reset`),de=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},fe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`);function pe(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function me(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function he(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function ge(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function _e(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function ve(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function ye(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function be(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function xe(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Se(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Ce(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var we={},Te=Symbol(`uninitialized`),Ee=`http://www.w3.org/1999/xhtml`;function De(){console.warn(`https://svelte.dev/e/derived_inert`)}function Oe(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ke(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function Ae(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var D=!1;function je(e){D=e}var O;function Me(e){if(e===null)throw Oe(),we;return O=e}function Ne(){return Me(Sn(O))}function k(e){if(D){if(Sn(O)!==null)throw Oe(),we;O=e}}function Pe(e=1){if(D){for(var t=e,n=O;t--;)n=Sn(n);O=n}}function Fe(e=!0){for(var t=0,n=O;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=Sn(n);e&&n.remove(),n=i}}function Ie(e){if(!e||e.nodeType!==8)throw Oe(),we;return e.data}function Le(e){return e===this.v}function Re(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function ze(e){return!Re(e,this.v)}var Be=!1;function Ve(){Be=!0}var He=null;function Ue(e){He=e}function We(e,t=!1,n){He={p:He,i:!1,c:null,e:null,s:e,x:null,r:B,l:Be&&!t?{s:null,u:null,$:[]}:null}}function Ge(e){var t=He,n=t.e;if(n!==null){t.e=null;for(var r of n)Nn(r)}return e!==void 0&&(t.x=e),t.i=!0,He=t.p,e??{}}function Ke(){return!Be||He!==null&&He.l===null}var qe=[];function Je(){var e=qe;qe=[],p(e)}function Ye(e){if(qe.length===0&&!Bt){var t=qe;queueMicrotask(()=>{t===qe&&Je()})}qe.push(e)}function Xe(){for(;qe.length>0;)Je()}function Ze(e){var t=B;if(t===null)return z.f|=ne,e;if(!(t.f&32768)&&!(t.f&4))throw e;Qe(e,t)}function Qe(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}var $e=~(g|_|h);function et(e,t){e.f=e.f&$e|t}function tt(e){e.f&512||e.deps===null?et(e,h):et(e,_)}function nt(e){if(e!==null)for(let t of e)!(t.f&2)||!(t.f&65536)||(t.f^=E,nt(t.deps))}function rt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),nt(e.deps),et(e,h)}function it(e,t,n){if(e==null)return t(void 0),n&&n(void 0),d;let r=Tr(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}var at=[];function ot(e,t){return{subscribe:st(e,t).subscribe}}function st(e,t=d){let n=null,r=new Set;function i(t){if(Re(e,t)&&(e=t,n)){let t=!at.length;for(let t of r)t[1](),at.push(t,e);if(t){for(let e=0;e{r.delete(c),r.size===0&&n&&(n(),n=null)}}return{set:i,update:a,subscribe:o}}function ct(e,t,n){let r=!Array.isArray(e),i=r?[e]:e;if(!i.every(Boolean))throw Error(`derived() expects stores as input, got a falsy value`);let a=t.length<2;return ot(n,(e,n)=>{let o=!1,s=[],c=0,l=d,u=()=>{if(c)return;l();let i=t(r?s[0]:s,e,n);a?e(i):l=typeof i==`function`?i:d},f=i.map((e,t)=>it(e,e=>{s[t]=e,c&=~(1<{c|=1<t=e)(),t}var ut=!1,dt=Symbol(`unmounted`);function A(e,t,n){let r=n[t]??={store:null,source:an(void 0),unsubscribe:d};if(r.store!==e&&!(dt in n))if(r.unsubscribe(),r.store=e??null,e==null)r.source.v=void 0,r.unsubscribe=d;else{var i=!0;r.unsubscribe=it(e,e=>{i?r.source.v=e:P(r.source,e)}),i=!1}return e&&dt in n?lt(e):V(r.source)}function ft(){let e={};function t(){jn(()=>{for(var t in e)e[t].unsubscribe();i(e,dt,{enumerable:!1,value:!0})})}return[e,t]}function pt(e){var t=ut;try{return ut=!1,[e(),ut]}finally{ut=t}}function mt(e){D&&xn(e)!==null&&Cn(e)}var ht=!1;function gt(){ht||(ht=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[ue]?.()})},{capture:!0}))}function _t(e){var t=z,n=B;rr(null),ir(null);try{return e()}finally{rr(t),ir(n)}}function vt(e,t,n,r=n){e.addEventListener(t,()=>_t(n));let i=e[ue];e[ue]=i?()=>{i(),r(!0)}:()=>r(!0),gt()}function yt(e){let t=0,n=rn(0),r;return()=>{An()&&(V(n),Rn(()=>(t===0&&(r=Tr(()=>e(()=>un(n)))),t+=1,()=>{Ye(()=>{--t,t===0&&(r?.(),r=void 0,un(n))})})))}}var bt=S|C;function xt(e,t,n,r){new St(e,t,n,r)}var St=class{parent;is_pending=!1;transform_error;#e;#t=D?O:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=yt(()=>(this.#m=rn(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=B;t.b=this,t.f|=128,n(e)},this.parent=B.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=zn(()=>{if(D){let e=this.#t;Ne();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},bt),D&&(this.#e=O)}#g(){try{this.#a=Bn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Ye(r),t&&(this.#s=Bn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){Ae();return}t=!0,n&&Ce(),this.#s!==null&&qn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){Qe(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=Bn(()=>e(this.#e)),Ye(()=>{var e=this.#c=document.createDocumentFragment(),t=bn();e.append(t),this.#a=this.#S(()=>Bn(()=>this.#r(t))),this.#u===0&&(this.#e.before(e),this.#c=null,qn(this.#o,()=>{this.#o=null}),this.#x(M))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=Bn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();Zn(this.#a,e);let t=this.#n.pending;this.#o=Bn(()=>t(this.#e))}else this.#x(M)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){rt(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=B,n=z,r=He;ir(this.#i),rr(this.#i),Ue(this.#i.ctx);try{return Kt.ensure(),e()}catch(e){return Ze(e),null}finally{ir(t),rr(n),Ue(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&qn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Ye(()=>{this.#d=!1,this.#m&&sn(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),V(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;M?.is_fork?(this.#a&&M.skip_effect(this.#a),this.#o&&M.skip_effect(this.#o),this.#s&&M.skip_effect(this.#s),M.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(Wn(this.#a),null),this.#o&&=(Wn(this.#o),null),this.#s&&=(Wn(this.#s),null),D&&(Me(this.#t),Pe(),Me(Fe()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return Bn(()=>{var r=B;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return Qe(e,this.#i.parent),null}}))};Ye(()=>{var t;try{t=this.transform_error(e)}catch(e){Qe(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>Qe(e,this.#i&&this.#i.parent)):n(t)})}};function Ct(e,t,n,r){let i=Ke()?Dt:At;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=B,c=wt(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){Qe(e,s)}Tt()}}var d=Et();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>kt(e))).then(u).catch(e=>Qe(e,s)).finally(d)}l?l.then(()=>{c(),f(),Tt()}):f()}function wt(){var e=B,t=z,n=He,r=M;return function(i=!0){ir(e),rr(t),Ue(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function Tt(e=!0){ir(null),rr(null),Ue(null),e&&M?.deactivate()}function Et(){var e=B,t=e.b,n=M,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function Dt(e){var t=2|g;return B!==null&&(B.f|=C),{ctx:He,deps:null,effects:null,equals:Le,f:t,fn:e,reactions:null,rv:0,v:Te,wv:0,parent:B,ac:null}}var Ot=Symbol(`obsolete`);function kt(e,t,n){let r=B;r===null&&pe();var i=void 0,a=rn(Te),o=!z,s=new Set;return Ln(()=>{var t=B,n=m();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==de&&n.reject(e)}).finally(Tt)}catch(e){n.reject(e),Tt()}var c=M;if(o){if(t.f&32768)var l=Et();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(Ot);else for(let e of s.values())e.reject(Ot);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==Ot&&(c.activate(),t?(a.f|=ne,sn(a,t)):(a.f&8388608&&(a.f^=ne),sn(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),jn(()=>{for(let e of s)e.reject(Ot)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function j(e){let t=Dt(e);return or(t),t}function At(e){let t=Dt(e);return t.equals=ze,t}function jt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(de),t.ac=null}),t.fn!==null&&(t.teardown=d),br(t,0),Hn(t))}function Ft(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&xr(t)}var It=null,M=null,Lt=null,Rt=null,zt=null,Bt=!1,Vt=!1,Ht=null,Ut=null,Wt=0,Gt=1,Kt=class e{id=Gt++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){It===null?It=this:(It.#n=this,this.#t=It),It=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)et(r,g),t(r);for(r of n.m)et(r,_),t(r)}this.#p.add(e)}#g(){this.#e=!0,Wt++>1e3&&(this.#x(),Jt());for(let e of this.#u)this.#d.delete(e),et(e,g),this.schedule(e);for(let e of this.#d)et(e,_),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=Ht=[],r=[],i=Ut=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw $t(e),this.#h()||this.discard(),t}if(M=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(Ht=null,Ut=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Qt(e,t);i.length>0&&M.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),Lt=this,Xt(r),Xt(n),Lt=null,this.#s?.resolve();var s=M;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0)if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this;s!==null&&s.#g()}#_(e,t,n){e.f^=h;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=h:i&4?t.push(r):gr(r)&&(i&16&&this.#d.add(r),xr(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),et(i,g),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),M=this,this.#g()}#b(e){for(var t=0;t{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=m()).promise}static ensure(){if(M===null){let t=M=new e;!Vt&&!Bt&&Ye(()=>{t.#e||t.flush()})}return M}apply(){Rt=null}schedule(e){if(zt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(Ht!==null&&t===B&&(z===null||!(z.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=h}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?It=e:t.#t=e,this.linked=!1}}};function qt(e){var t=Bt;Bt=!0;try{var n;for(e&&(M!==null&&!M.is_fork&&M.flush(),n=e());;){if(Xe(),M===null)return n;M.flush()}}finally{Bt=t}}function Jt(){try{ve()}catch(e){Qe(e,zt)}}var Yt=null;function Xt(e){var t=e.length;if(t!==0){for(var n=0;n0)){tn.clear();for(let e of Yt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Yt.has(n)&&(Yt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||xr(n)}}Yt.clear()}}Yt=null}}function Zt(e){M.schedule(e)}function Qt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),et(e,h);for(var n=e.first;n!==null;)Qt(n,t),n=n.next}}function $t(e){et(e,h);for(var t=e.first;t!==null;)$t(t),t=t.next}var en=new Set,tn=new Map,nn=!1;function rn(e,t){return{f:0,v:e,reactions:null,equals:Le,rv:0,wv:0}}function N(e,t){let n=rn(e,t);return or(n),n}function an(e,t=!1,n=!0){let r=rn(e);return t||(r.equals=ze),Be&&n&&He!==null&&He.l!==null&&(He.l.s??=[]).push(r),r}function on(e,t){return P(e,Tr(()=>V(e))),t}function P(e,t,n=!1){return z!==null&&(!nr||z.f&131072)&&Ke()&&z.f&4325394&&(ar===null||!ar.has(e))&&Se(),sn(e,n?fn(t):t,Ut)}function sn(e,t,n=null){if(!e.equals(t)){tn.set(e,er?t:e.v);var r=Kt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&Mt(t),Rt===null&&tt(t)}e.wv=hr(),dn(e,g,n),Ke()&&B!==null&&B.f&1024&&!(B.f&96)&&(lr===null?ur([e]):lr.push(e)),!r.is_fork&&en.size>0&&!nn&&cn()}return t}function cn(){nn=!1;for(let e of en){e.f&1024&&et(e,_);let t;try{t=gr(e)}catch{t=!0}t&&xr(e)}en.clear()}function ln(e,t=1){var n=V(e),r=t===1?n++:n--;return P(e,n),r}function un(e){P(e,e.v+1)}function dn(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ke(),a=r.length,o=0;o{if(pr===d)return e();var t=z,n=pr;rr(null),mr(d);var r=e();return rr(t),mr(n),r};return i&&r.set(`length`,N(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&be();var i=r.get(t);return i===void 0?f(()=>{var e=N(n.value,u);return r.set(t,e),e}):P(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>N(Te,u));r.set(t,e),un(o)}}else P(n,Te),un(o);return!0},get(e,n,i){if(n===re)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>N(fn(s?e[n]:Te),u)),r.set(n,o)),o!==void 0){var c=V(o);return c===Te?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=V(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==Te)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===re)return!0;var n=r.get(t),i=n!==void 0&&n.v!==Te||Reflect.has(e,t);return(n!==void 0||B!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>N(i?fn(e[t]):Te,u)),r.set(t,n)),V(n)===Te)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dN(Te,u)),r.set(d+``,p)):P(p,Te)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>N(void 0,u)),P(c,fn(n)),r.set(t,c));else{l=c.v!==Te;var m=f(()=>fn(n));P(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&P(g,_+1)}un(o)}return!0},ownKeys(e){V(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==Te});for(var[n,i]of r)i.v!==Te&&!(n in e)&&t.push(n);return t},setPrototypeOf(){xe()}})}function pn(e){try{if(typeof e==`object`&&e&&re in e)return e[re]}catch{}return e}function mn(e,t){return Object.is(pn(e),pn(t))}var hn,gn,_n,vn;function yn(){if(hn===void 0){hn=window,gn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;_n=a(t,`firstChild`).get,vn=a(t,`nextSibling`).get,u(e)&&(e[se]=void 0,e[oe]=null,e[ce]=void 0,e.__e=void 0),u(n)&&(n[le]=void 0)}}function bn(e=``){return document.createTextNode(e)}function xn(e){return _n.call(e)}function Sn(e){return vn.call(e)}function F(e,t){if(!D)return xn(e);var n=xn(O);if(n===null)n=O.appendChild(bn());else if(t&&n.nodeType!==3){var r=bn();return n?.before(r),Me(r),r}return t&&En(n),Me(n),n}function I(e,t=!1){if(!D){var n=xn(e);return n instanceof Comment&&n.data===``?Sn(n):n}if(t){if(O?.nodeType!==3){var r=bn();return O?.before(r),Me(r),r}En(O)}return O}function L(e,t=1,n=!1){let r=D?O:e;for(var i;t--;)i=r,r=Sn(r);if(!D)return r;if(n){if(r?.nodeType!==3){var a=bn();return r===null?i?.after(a):r.before(a),Me(a),a}En(r)}return Me(r),r}function Cn(e){e.textContent=``}function wn(){return!1}function Tn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function En(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function Dn(e){B===null&&(z===null&&_e(e),ge()),er&&he(e)}function On(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function kn(e,t){var n=B;n!==null&&n.f&8192&&(e|=v);var r={ctx:He,deps:null,nodes:null,f:e|g|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};M?.register_created_effect(r);var i=r;if(e&4)Ht===null?Kt.ensure().schedule(r):Ht.push(r);else if(t!==null){try{xr(r)}catch(e){throw Wn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=S))}if(i!==null&&(i.parent=n,n!==null&&On(i,n),z!==null&&z.f&2&&!(e&64))){var a=z;(a.effects??=[]).push(i)}return r}function An(){return z!==null&&!nr}function jn(e){let t=kn(8,null);return et(t,h),t.teardown=e,t}function Mn(e){Dn(`$effect`);var t=B.f;if(!z&&t&32&&He!==null&&!He.i){var n=He;(n.e??=[]).push(e)}else return Nn(e)}function Nn(e){return kn(4|w,e)}function Pn(e){return Dn(`$effect.pre`),kn(8|w,e)}function Fn(e){Kt.ensure();let t=kn(64|C,e);return(e={})=>new Promise(n=>{e.outro?qn(t,()=>{Wn(t),n(void 0)}):(Wn(t),n(void 0))})}function In(e){return kn(4,e)}function Ln(e){return kn(te|C,e)}function Rn(e,t=0){return kn(8|t,e)}function R(e,t=[],n=[],r=[]){Ct(r,t,n,t=>{kn(8,()=>{e(...t.map(V))})})}function zn(e,t=0){return kn(16|t,e)}function Bn(e){return kn(32|C,e)}function Vn(e){var t=e.teardown;if(t!==null){let e=er,n=z;tr(!0),rr(null);try{t.call(null)}finally{tr(e),rr(n)}}}function Hn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&_t(()=>{e.abort(de)});var r=n.next;n.f&64?n.parent=null:Wn(n,t),n=r}}function Un(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||Wn(t),t=n}}function Wn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Gn(e.nodes.start,e.nodes.end),n=!0),e.f|=x,Hn(e,t&&!n),br(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();Vn(e),e.f^=x,e.f|=y;var i=e.parent;i!==null&&i.first!==null&&Kn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Gn(e,t){for(;e!==null;){var n=e===t?null:Sn(e);e.remove(),e=n}}function Kn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function qn(e,t,n=!0){var r=[];Jn(e,r,!0);var i=()=>{n&&Wn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Jn(e,t,n){if(!(e.f&8192)){e.f^=v;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);Jn(i,t,o?n:!1)}i=a}}}function Yn(e){Xn(e,!0)}function Xn(e,t){if(e.f&8192){e.f^=v,e.f&1024||(et(e,g),Kt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Xn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function Zn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:Sn(n);t.append(n),n=i}}var Qn=null,$n=!1,er=!1;function tr(e){er=e}var z=null,nr=!1;function rr(e){z=e}var B=null;function ir(e){B=e}var ar=null;function or(e){z!==null&&(ar??=new Set).add(e)}var sr=null,cr=0,lr=null;function ur(e){lr=e}var dr=1,fr=0,pr=fr;function mr(e){pr=e}function hr(){return++dr}function gr(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~E),t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&Rt===null&&et(e,h)}return!1}function _r(e,t,n=!0){var r=e.reactions;if(r!==null&&!(ar!==null&&ar.has(e)))for(var i=0;i{e.ac.abort(de)}),e.ac=null);try{e.f|=ee;var u=e.fn,d=u();e.f|=b;var f=e.deps,p=M?.is_fork;if(sr!==null){var m;if(p||br(e,cr),f!==null&&cr>0)for(f.length=cr+sr.length,m=0;m{s.ac.abort(de),s.ac=null,et(s,g)}),Pt(s),br(s,0)}}function br(e,t){var n=e.deps;if(n!==null)for(var r=t;r{throw e});throw p}}finally{e[Ar]=t,delete e.currentTarget,rr(d),ir(f)}}}var Ir=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function Lr(e){return Ir?.createHTML(e)??e}function Rr(e){var t=Tn(`template`);return t.innerHTML=Lr(e.replaceAll(``,``)),t.content}function zr(e,t){var n=B;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function U(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(D)return zr(O,null),O;i===void 0&&(i=Rr(a?e:``+e),n||(i=xn(i)));var t=r||gn?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=xn(t),s=t.lastChild;zr(o,s)}else zr(t,t);return t}}function Br(e=``){if(!D){var t=bn(e+``);return zr(t,t),t}var n=O;return n.nodeType===3?En(n):(n.before(n=bn()),Me(n)),zr(n,n),n}function Vr(){if(D)return zr(O,null),O;var e=document.createDocumentFragment(),t=document.createComment(``),n=bn();return e.append(t,n),zr(t,n),e}function W(e,t){if(D){var n=B;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=O),Ne();return}e!==null&&e.before(t)}function G(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[le]??=e.nodeValue)&&(e[le]=n,e.nodeValue=`${n}`)}function Hr(e,t){return Wr(e,t)}var Ur=new Map;function Wr(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){yn();var l=void 0,u=Fn(()=>{var s=n??t.appendChild(bn());xt(s,{pending:()=>{}},t=>{We({});var n=He;if(o&&(n.c=o),a&&(i.$$events=a),D&&zr(t,null),l=e(t,i)||{},D&&(B.nodes.end=O,O===null||O.nodeType!==8||O.data!==`]`))throw Oe(),we;Ge()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=Ur.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,Fr),r.delete(e),r.size===0&&Ur.delete(n)):r.set(e,i)}Mr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Gr.set(l,u),l}var Gr=new WeakMap,Kr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)Yn(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(Yn(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(Wn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();Zn(r,t),t.append(bn()),this.#n.set(e,{effect:r,fragment:t})}else Wn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),qn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(Wn(n.effect),this.#n.delete(e))};ensure(e,t){var n=M,r=wn();if(t&&!this.#t.has(e)&&!this.#n.has(e))if(r){var i=document.createDocumentFragment(),a=bn();i.append(a),this.#n.set(e,{effect:Bn(()=>t(a)),fragment:i})}else this.#t.set(e,Bn(()=>t(this.anchor)));if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else D&&(this.anchor=O),this.#a(n)}};function K(e,t,n=!1){var r;D&&(r=O,Ne());var i=new Kr(e),a=n?S:0;function o(e,t){if(D){var n=Ie(r);if(e!==parseInt(n.substring(1))){var a=Fe();Me(a),i.anchor=a,je(!1),i.ensure(e,t),je(!0);return}}i.ensure(e,t)}zn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var qr=Symbol(`NaN`);function Jr(e,t,n){D&&Ne();var r=new Kr(e),i=!Ke();zn(()=>{var e=t();e!==e&&(e=qr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function Yr(e,t){return t}function Xr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Zr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null;if(l){var u=n,d=u.parentNode;Cn(d),d.append(u),e.items.clear()}Zr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Zr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,ti(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=T,ri(d,null,c)):Yn(d):qn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:zn(()=>{p=V(f);var e=p.length;let t=!1;D&&Ie(c)===`[!`!=(e===0)&&(c=Fe(),Me(c),je(!1),t=!0);for(var r=new Set,u=M,v=wn(),y=0;ys(c)):(d=Bn(()=>s(Qr??=bn())),d.f|=T)),e>r.size&&me(``,``,``),D&&e>0&&Me(Fe()),!h)if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u);t&&je(!0),V(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,D&&(c=O)}function ei(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function ti(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=ei(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var ee=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function ni(e,t,n,r,i,a,o,s){var c=o&1?o&16?rn(n):an(n,!1,!1):null,l=o&2?rn(i):null;return{v:c,i:l,e:Bn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function ri(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=Sn(r);if(a.before(r),r===i)return;r=o}}function ii(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function ai(e,t,...n){var r=new Kr(e);zn(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},S)}var oi=[...` -\r\f\xA0\v`];function si(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||oi.includes(r[o-1]))&&(s===r.length||oi.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ci(e,t,n,r,i,a){var o=e[se];if(D||o!==n||o===void 0){var s=si(n,r,a);(!D||s!==e.getAttribute(`class`))&&(s==null?e.removeAttribute(`class`):t?e.className=s:e.setAttribute(`class`,s)),e[se]=n}else if(a&&i!==a)for(var c in a){var l=!!a[c];(i==null||l!==!!i[c])&&e.classList.toggle(c,l)}return a}function li(t,n,r=!1){if(t.multiple){if(n==null)return;if(!e(n))return ke();for(var i of t.options)i.selected=n.includes(fi(i));return}for(i of t.options)if(mn(fi(i),n)){i.selected=!0;return}(!r||n!==void 0)&&(t.selectedIndex=-1)}function ui(e){var t=new MutationObserver(()=>{`__value`in e&&li(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),jn(()=>{t.disconnect()})}function di(e,t,n=t){var r=new WeakSet,i=!0;vt(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),fi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&fi(o)}n(a),e.__value=a,M!==null&&r.add(M)}),In(()=>{var a=t();if(e===document.activeElement){var o=M;if(r.has(o))return}if(li(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=fi(s),n(a))}e.__value=a,i=!1}),ui(e)}function fi(e){return`__value`in e?e.__value:e.value}var pi=Symbol(`is custom element`),mi=Symbol(`is html`),hi=fe?`link`:`LINK`;function gi(e){if(D){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;_i(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;_i(e,`checked`,null),e.checked=r}}};e[ue]=n,Ye(n),gt()}}function _i(e,t,n,r){var i=vi(e);D&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===hi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[ae]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&bi(e).includes(t)?e[t]=n:e.setAttribute(t,n))}function vi(e){return e[oe]??={[pi]:e.nodeName.includes(`-`),[mi]:e.namespaceURI===Ee}}var yi=new Map;function bi(e){var t=e.getAttribute(`is`)||e.nodeName,n=yi.get(t);if(n)return n;yi.set(t,n=[]);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.push(s);i=l(i)}return n}function xi(e,t,n=t){var r=new WeakSet;vt(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Ci(e)?wi(a):a,n(a),M!==null&&r.add(M),await Sr(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(D&&e.defaultValue!==e.value||Tr(t)==null&&e.value)&&(n(Ci(e)?wi(e.value):e.value),M!==null&&r.add(M)),Rn(()=>{var n=t();if(e===document.activeElement){var i=M;if(r.has(i))return}Ci(e)&&n===wi(e.value)||e.type===`date`&&!n&&!e.value||n!==e.value&&(e.value=n??``)})}function Si(e,t,n=t){vt(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(D&&e.defaultChecked!==e.checked||Tr(t)==null)&&n(e.checked),Rn(()=>{e.checked=!!t()})}function Ci(e){var t=e.type;return t===`number`||t===`range`}function wi(e){return e===``?null:+e}function Ti(e=!1){let t=He,n=t.l.u;if(!n)return;let r=()=>Er(t.s);if(e){let e=0,n={},i=Dt(()=>{let r=!1,i=t.s;for(let e in i)i[e]!==n[e]&&(n[e]=i[e],r=!0);return r&&e++,e});r=()=>V(i)}n.b.length&&Pn(()=>{Ei(t,r),p(n.b)}),Mn(()=>{let e=Tr(()=>n.m.map(f));return()=>{for(let t of e)typeof t==`function`&&t()}}),n.a.length&&Mn(()=>{Ei(t,r),p(n.a)})}function Ei(e,t){if(e.l.s)for(let t of e.l.s)V(t);t()}function Di(e,t,n,r){var i=!Be||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=Dt(r),V(u)):(l&&(l=!1,c=s?Tr(r):r),c);let f;if(o){var p=re in e||ie in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=pt(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&ye(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?Dt:At)(()=>(v=!1,g()));o&&V(y);var b=B;return(function(e,t){if(arguments.length>0){let n=t?V(y):i&&o?fn(e):e;return P(y,n),v=!0,c!==void 0&&(c=n),e}return er&&v||b.f&16384?y.v:V(y)})}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Oi(e){let t=e.batchSize??20,n=e.flushInterval??5e3,r=e.include,i=[],a,o=e=>!r||r.includes(e),s=(e,n)=>{o(e)&&(i.push({type:e,timestamp:Date.now(),detail:n}),i.length>=t&&c())},c=()=>{if(i.length===0)return;let t=i.slice();i.length=0,e.onFlush(t)};return{name:`analytics`,onInit(){n>0&&(a=setInterval(c,n))},onChange(t){let n=e.redact?.includes(t.property);s(`change`,{property:t.property,currentValue:n?`[redacted]`:t.currentValue,oldValue:n?`[redacted]`:t.oldValue})},onValidation(e){s(`validation`,{hasErrors:e!==void 0})},onSnapshot(e){s(`snapshot`,{title:e.title})},onAction(e){s(`action`,{phase:e.phase,error:e.error?.message})},onRollback(e){s(`rollback`,{title:e.title})},onReset(){s(`reset`,{})},destroy(){a!==void 0&&clearInterval(a),c()},flush(){c()},eventCount(){return i.length}}}function ki(e){let t=e.idle??1e3,n=e.interval??0,r=e.saveOnDestroy??!0,i=e.onlyWhenDirty??!0,a,o,s,c=!1,l=!1,u=async()=>{if(a&&!(i&&!lt(a.state.isDirty))&&!c){c=!0;try{await e.save(a.data)}catch(t){e.onError?.(t)}finally{c=!1}}},d=()=>{clearTimeout(o),o=setTimeout(u,t)},f=()=>{typeof document<`u`&&document.visibilityState===`hidden`&&u()};return{name:`autosave`,onInit(t){a=t,n>0&&(s=setInterval(u,n)),typeof document<`u`&&e.onVisibilityHidden&&document.addEventListener(`visibilitychange`,f)},onChange(){d()},onAction(e){e.phase===`after`&&!e.error&&clearTimeout(o)},destroy(){if(l=!0,clearTimeout(o),s!==void 0&&clearInterval(s),typeof document<`u`&&document.removeEventListener(`visibilitychange`,f),r&&a){c=!1;let t=a;(!i||lt(t.state.isDirty))&&(async()=>{try{await e.save(t.data)}catch(t){e.onError?.(t)}})()}},async saveNow(){l||(clearTimeout(o),c=!1,await u())},isSaving(){return c}}}var Ai=()=>{try{return import.meta.env?.PROD===!0}catch{return!1}};function ji(e){let t=e?.name??`svstate`,n=e?.collapsed??!0,r=e?.logValidation??!1,i=e?.logValues??!1,a=e?.enabled??!Ai(),o=(e,...r)=>{if(!a)return;let i=new Date().toISOString().slice(11,23);(n?console.groupCollapsed:console.group)(`[${t}] ${e} (${i})`);for(let e of r)console.log(e);console.groupEnd()};return{name:`devtools`,onChange(e){i?o(`change`,{property:e.property,from:e.oldValue,to:e.currentValue}):o(`change`,{property:e.property})},onValidation(e){r&&o(`validation`,e)},onSnapshot(e){o(`snapshot`,{title:e.title})},onAction(e){e.error?o(`action:${e.phase}`,{params:e.params,error:e.error.message}):o(`action:${e.phase}`,{params:e.params})},onRollback(e){o(`rollback`,{title:e.title})},onReset(){o(`reset`)}}}var Mi=new Set([`__proto__`,`constructor`,`prototype`]),Ni=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Pi=e=>Ni(e)&&typeof e.version==`number`&&Ni(e.data),Fi=(e,t)=>{for(let[n,r]of Object.entries(t))Mi.has(n)||(e[n]=r)},Ii=(e,t)=>{let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},Li=(e,t,n)=>{let r=t.split(`.`),i=e;for(let e=0;e{let n=t.split(`.`);if(n.length===1){delete e[t];return}let r=e;for(let e=0;e{if(t){let n={};for(let r of t){let t=Ii(e,r);t!==void 0&&Li(n,r,t)}return n}if(n){let t={...e};for(let e of n)Ri(t,e);return t}return e};function Bi(e){let t=e.storage??(typeof localStorage>`u`?void 0:localStorage),n=e.throttle??300,r=e.version??1,i=!1,a,o,s=()=>{if(!t||!o)return;let n=zi(o,e.include,e.exclude),i={version:r,data:n};t.setItem(e.key,JSON.stringify(i))},c=()=>{clearTimeout(a),a=setTimeout(s,n)};return{name:`persist`,onInit(n){if(o=n.data,!t)return;let a=t.getItem(e.key);if(a)try{let t=JSON.parse(a);if(!Pi(t))return;let o=t;if(e.migrate&&o.version!==r){let t=e.migrate(o.data,o.version);if(!Ni(t))return;o={version:r,data:t}}Fi(n.data,o.data),i=!0}catch{}},onChange(){c()},onReset(){s()},destroy(){a!==void 0&&(clearTimeout(a),s())},clearPersistedState(){t?.removeItem(e.key)},isRestored(){return i}}}var Vi=new Set([`__proto__`,`constructor`,`prototype`]),Hi=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Ui=10,Wi=(e,t=0)=>t>Ui?!1:!Hi(e)||Object.values(e).every(e=>Wi(e,t+1)),Gi=(e,t)=>{for(let[n,r]of Object.entries(t))Vi.has(n)||(e[n]=r)};function Ki(e){let t=e.throttle??100,n=e.merge??`overwrite`,r,i,a=!1,o,s=0,c=()=>{if(!r||!i)return;let e=JSON.parse(JSON.stringify(i.data));r.postMessage({type:`sync`,data:e})},l=()=>{clearTimeout(o),o=setTimeout(c,t)},u=()=>{clearTimeout(o),r&&=(r.close(),void 0)};return{name:`sync`,onInit(o){i=o,!(typeof BroadcastChannel>`u`)&&(r=new BroadcastChannel(e.key),r.addEventListener(`message`,e=>{if(!i||n===`ignore`||e.data?.type!==`sync`)return;let r=Date.now();r-s{if(typeof e!=`object`||!e)return e;if(e instanceof Date)return new Date(e);if(Array.isArray(e))return e.map(e=>o(e));let t=Object.create(Object.getPrototypeOf(e));for(let n of Object.keys(e))t[n]=o(e[n]);return t};return{name:`undo-redo`,redoStack:{subscribe:t.subscribe},onInit(e){r=e,i=e.state.snapshots.subscribe(e=>{e.length0&&(a=n.at(-1)),n=e})},onRollback(){a&&=(t.update(t=>{let n=[...t,a],r=e?.maxRedoStack;return r&&r>0?n.slice(-r):n}),void 0)},onChange(){t.set([])},onReset(){t.set([])},redo(){if(!r)return;let e=lt(t);if(e.length===0)return;let n=e.at(-1);t.set(e.slice(0,-1)),r.snapshot(`Undo`),Object.assign(r.data,o(n.data))},canRedo(){return lt(t).length>0},destroy(){i?.()}}}var Ji=e=>typeof e==`object`&&!!e&&!(e instanceof Date)&&!(e instanceof Map)&&!(e instanceof Set)&&!(e instanceof WeakMap)&&!(e instanceof WeakSet)&&!(e instanceof RegExp)&&!(e instanceof Error)&&!(e instanceof Promise),Yi=(e,t)=>{let n=(e,i)=>new Proxy(e,{get(e,t){if(typeof t==`symbol`)return e[t];let r=e[t];if(Ji(r)){let e=Number.isSafeInteger(Number(t))?``:String(t),a=e?i?`${i}.${e}`:e:i;return n(r,a)}return r},set(e,n,a){if(typeof n==`symbol`)return e[n]=a,!0;let o=e[n];if(o!==a){e[n]=a;let s=Number.isSafeInteger(Number(n))?``:String(n),c=s?i?`${i}.${s}`:s:i;t(r,c,a,o)}return!0}}),r=n(e,``);return r},Xi=e=>Object.values(e).some(e=>typeof e==`string`?!!e:Xi(e)),Zi=e=>!!e&&Xi(e),Qi=new Set([`__proto__`,`constructor`,`prototype`]),$i=e=>{if(typeof e!=`object`||!e)return e;if(e instanceof Date)return new Date(e);if(Array.isArray(e))return e.map(e=>$i(e));let t=Object.create(Object.getPrototypeOf(e));for(let n of Object.keys(e))Qi.has(n)||(t[n]=$i(e[n]));return t},ea=(e,t)=>{let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},ta=(e,t)=>{if(!e)return``;let n=t.split(`.`),r=e;for(let e of n){if(typeof r==`string`||r[e]===void 0)return``;r=r[e]}return typeof r==`string`?r:``},na=(e,t)=>{let n=[];for(let r of Object.keys(e))(r===t||r.startsWith(t+`.`)||t.startsWith(r+`.`))&&n.push(r);return n},ra={resetDirtyOnAction:!0,debounceValidation:0,allowConcurrentActions:!1,persistActionError:!1,debounceAsyncValidation:300,runAsyncValidationOnInit:!1,clearAsyncErrorsOnChange:!0,maxConcurrentAsyncValidations:4,maxSnapshots:50,plugins:[]};function ia(e,t,n){let r={...ra,...n},{validator:i,effect:a,asyncValidator:o}=t??{},s=st(),c=ct(s,Zi),l=st({}),u=ct(l,e=>Object.keys(e).length>0),d=st(!1),f=st(),p=st([{title:`Initial`,data:$i(e)}]),m=st({}),h=st(new Set),g=ct(h,e=>[...e]),_=ct(m,e=>Object.values(e).some(e=>!!e)),v=ct([c,_],([e,t])=>e||t),y=new Map,b=[],x=e=>{l.update(t=>{let n={...t,[e]:!0},r=e.split(`.`);for(let e=1;e{for(let n of C){let r=n[e];typeof r==`function`&&r.call(n,...t)}},T=()=>{if(!i)return;let e=i(ue);s.set(e),w(`onValidation`,e)},E=(e,t=!0)=>{let n=lt(p),i={title:e,data:$i(S)},a=n.at(-1),o=t&&a&&a.title===e?[...n.slice(0,-1),i]:[...n,i];if(r.maxSnapshots>0&&o.length>r.maxSnapshots){let e=o.length-r.maxSnapshots;o=[o[0],...o.slice(1+e)]}p.set(o),w(`onSnapshot`,i)},ee=!1,te,ne=()=>{if(i)if(r.debounceValidation>0)clearTimeout(te),te=setTimeout(()=>{T()},r.debounceValidation);else{if(ee)return;ee=!0,queueMicrotask(()=>{T(),ee=!1})}},re=e=>{let t=b.indexOf(e);t!==-1&&b.splice(t,1)},ie=e=>{re(e);let t=y.get(e);t&&(clearTimeout(t.timeoutId),t.controller.abort(),y.delete(e),h.update(t=>(t.delete(e),new Set(t))))},ae=()=>{b.length=0;for(let e of y.keys())ie(e);m.set({})},oe=async(e,t)=>{if(!o){t();return}let n=o[e];if(!n){t();return}if(ta(lt(s),e)){t();return}let r=new AbortController;y.set(e,{controller:r,timeoutId:0}),h.update(t=>new Set([...t,e]));try{let t=await n(ea(ue,e),ue,r.signal);r.signal.aborted||m.update(n=>({...n,[e]:t}))}catch(t){if(t instanceof Error&&t.name===`AbortError`)return;if(!r.signal.aborted){let n=t instanceof Error?t.message:`Async validation error`;m.update(t=>({...t,[e]:n}))}}finally{y.delete(e),h.update(t=>(t.delete(e),new Set(t))),t()}},se=()=>{for(;b.length>0&&!(lt(h).size>=r.maxConcurrentAsyncValidations);){let e=b.shift();e&&oe(e,se)}},ce=e=>{if(!o||!Object.hasOwn(o,e))return;ie(e),r.clearAsyncErrorsOnChange&&m.update(t=>{let n={...t};return delete n[e],n});let t=new AbortController,n=setTimeout(()=>{y.delete(e),lt(h).size{if(!o)return;let t=na(o,e);for(let e of t)ce(e)},ue=Yi(S,(e,t,n,i)=>{if(r.persistActionError||f.set(void 0),x(t),a?.({snapshot:E,target:e,property:t,currentValue:n,oldValue:i})instanceof Promise)throw Error(`svstate: effect callback must be synchronous. Use action for async operations.`);w(`onChange`,{target:e,property:t,currentValue:n,oldValue:i}),ne(),le(t)});if(T(),o&&r.runAsyncValidationOnInit)for(let e of Object.keys(o))ce(e);let de=async e=>{if(!(!r.allowConcurrentActions&<(d))){w(`onAction`,{phase:`before`,params:e}),f.set(void 0),d.set(!0);try{await t?.action?.(e),r.resetDirtyOnAction&&l.set({}),p.set([{title:`Initial`,data:$i(S)}]),await t?.actionCompleted?.(),w(`onAction`,{phase:`after`,params:e})}catch(n){await t?.actionCompleted?.(n);let r=n instanceof Error?n:n&&typeof n==`object`?Error(String(n.message??n.body?.message??n)):void 0;f.set(r),w(`onAction`,{phase:`after`,params:e,error:r})}finally{d.set(!1)}}},fe=(e,t)=>{let n=t[e];if(n)return ae(),l.set({}),Object.assign(S,$i(n.data)),p.set(t.slice(0,e+1)),T(),n},pe=(e=1)=>{let t=lt(p);if(t.length<=1)return;let n=Math.max(0,t.length-1-e),r=fe(n,t);r&&w(`onRollback`,r)},me=e=>{let t=lt(p);if(t.length<=1)return!1;for(let n=t.length-1;n>=0;n--)if(t[n].title===e){let e=fe(n,t);return e&&w(`onRollback`,e),!0}return!1},he=()=>{let e=lt(p);e[0]&&(fe(0,e),w(`onReset`))},ge={errors:s,hasErrors:c,isDirty:u,isDirtyByField:l,actionInProgress:d,actionError:f,snapshots:p,asyncErrors:m,hasAsyncErrors:_,asyncValidating:g,hasCombinedErrors:v};return w(`onInit`,{data:ue,state:ge,options:r,snapshot:E}),{data:ue,execute:de,state:ge,rollback:pe,rollbackTo:me,reset:he,destroy:()=>{for(let e=C.length-1;e>=0;e--)C[e]?.destroy?.()}}}var aa={trim:e=>e.trim(),normalize:e=>e.replaceAll(/\s{2,}/g,` `),upper:e=>e.toUpperCase(),lower:e=>e.toLowerCase(),localeUpper:e=>e.toLocaleUpperCase(),localeLower:e=>e.toLocaleLowerCase()};function q(e){let t=``,n=e==null,r=e??``,i=e=>{t||=e},a={prepare(...e){return r=e.reduce((e,t)=>aa[t](e),r),a},required(){return!t&&(n||!r)&&i(`Required`),a},requiredIf(e){return e&&!t&&(n||!r)&&i(`Required`),a},noSpace(){return n||!t&&r.includes(` `)&&i(`No space allowed`),a},notBlank(){return n||!t&&r.length>0&&r.trim().length===0&&i(`Must not be blank`),a},minLength(e){return n||!t&&r.lengthe&&i(`Max length ${e}`),a},uppercase(){return n||!t&&r!==r.toUpperCase()&&i(`Uppercase only`),a},lowercase(){return n||!t&&r!==r.toLowerCase()&&i(`Lowercase only`),a},startsWith(e){if(t)return a;let n=Array.isArray(e)?e:[e];return r&&n.every(e=>!r.startsWith(e))&&i(`Must start with ${n.join(`, `)}`),a},regexp(e,n){return!t&&r&&!e.test(r)&&i(n??`Not allowed chars`),a},in(e){if(t)return a;let n=Array.isArray(e)?e:Object.keys(e);return r&&!n.includes(r)&&i(`Must be one of: ${n.join(`, `)}`),a},notIn(e){if(t)return a;let n=Array.isArray(e)?e:Object.keys(e);return r&&n.includes(r)&&i(`Must not be one of: ${n.join(`, `)}`),a},email(){return!t&&r&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r)&&i(`Invalid email format`),a},website(e=`optional`){if(t||!r||e===`optional`)return a;let n=/^https?:\/\//.test(r);return e===`required`&&!n?i(`Must start with http:// or https://`):e===`forbidden`&&n&&i(`Must not start with http:// or https://`),a},endsWith(e){if(t||!r)return a;let n=Array.isArray(e)?e:[e];return n.every(e=>!r.endsWith(e))&&i(`Must end with ${n.join(`, `)}`),a},contains(e){return!t&&r&&!r.includes(e)&&i(`Must contain "${e}"`),a},alphanumeric(){return!t&&r&&!/^[\dA-Za-z]+$/.test(r)&&i(`Only letters and numbers allowed`),a},numeric(){return!t&&r&&!/^\d+$/.test(r)&&i(`Only numbers allowed`),a},slug(){return!t&&r&&!/^[\da-z-]+$/.test(r)&&i(`Invalid slug format`),a},identifier(){return!t&&r&&!/^[A-Z_a-z]\w*$/.test(r)&&i(`Invalid identifier format`),a},getError(){return t}};return a}function oa(e){let t=``,n=e==null,r=e=>{t||=e},i={required(){return!t&&(n||Number.isNaN(e))&&r(`Required`),i},requiredIf(a){return a&&!t&&(n||Number.isNaN(e))&&r(`Required`),i},min(a){return n||!t&&ea&&r(`Maximum ${a}`),i},between(a,o){return n||!t&&(eo)&&r(`Must be between ${a} and ${o}`),i},integer(){return n||!t&&!Number.isSafeInteger(e)&&r(`Must be an integer`),i},positive(){return n||!t&&e<=0&&r(`Must be positive`),i},negative(){return n||!t&&e>=0&&r(`Must be negative`),i},nonNegative(){return n||!t&&e<0&&r(`Must be non-negative`),i},notZero(){return n||!t&&e===0&&r(`Must not be zero`),i},multipleOf(a){return n||!t&&e%a!==0&&r(`Must be a multiple of ${a}`),i},step(a){return n||!t&&e%a!==0&&r(`Must be a multiple of ${a}`),i},decimal(a){return n||t||Number.isNaN(e)||(String(e).split(`.`)[1]?.length??0)>a&&r(`Maximum ${a} decimal places`),i},percentage(){return n||!t&&(e<0||e>100)&&r(`Must be between 0 and 100`),i},getError(){return t}};return i}function sa(e){let t=``,n=e==null,r=e??[],i=e=>{t||=e},a={required(){return!t&&(n||r.length===0)&&i(`Required`),a},requiredIf(e){return e&&!t&&(n||r.length===0)&&i(`Required`),a},minLength(e){return n||!t&&r.lengthe&&i(`Maximum ${e} items`),a},unique(){if(n||t)return a;let e=new Set;for(let t of r){let n=typeof t==`object`?JSON.stringify(t):String(t);if(e.has(n)){i(`Items must be unique`);break}e.add(n)}return a},ofLength(e){return n||!t&&r.length!==e&&i(`Must have exactly ${e} items`),a},includes(e){if(n||t)return a;let o=typeof e==`object`?JSON.stringify(e):String(e);return r.some(e=>(typeof e==`object`?JSON.stringify(e):String(e))===o)||i(`Must include ${o}`),a},includesAny(e){if(n||t)return a;let o=e.map(e=>typeof e==`object`?JSON.stringify(e):String(e));return r.some(e=>{let t=typeof e==`object`?JSON.stringify(e):String(e);return o.includes(t)})||i(`Must include at least one of: ${o.join(`, `)}`),a},includesAll(e){if(n||t)return a;let o=new Set(r.map(e=>typeof e==`object`?JSON.stringify(e):String(e))),s=e.filter(e=>{let t=typeof e==`object`?JSON.stringify(e):String(e);return!o.has(t)});if(s.length>0){let e=s.map(e=>typeof e==`object`?JSON.stringify(e):String(e));i(`Missing required items: ${e.join(`, `)}`)}return a},getError(){return t}};return a}var ca=U(`
            `),la=U(`
             
            `);function J(e,t){var n=la(),r=F(n),i=e=>{var n=ca(),r=F(n,!0);k(n),R(()=>G(r,t.title)),W(e,n)};K(r,e=>{t.title&&e(i)});var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>G(o,t.code)),W(e,n)}var ua=U(`
            Dirty Fields
             
            `),da=U(`
            State Object
             
            State Info
            isDirty:
            hasErrors:
            Errors
             
            `);function fa(e,t){We(t,!0);let n=Di(t,`width`,3,`xl:w-80`);var r=da(),i=F(r),a=L(F(i),2),o=F(a,!0);k(a),k(i);var s=L(i,2),c=L(F(s),2),l=F(c),u=L(F(l));k(l);var d=L(l,2),f=L(F(d));k(d),k(c),k(s);var p=L(s,2),m=e=>{var n=ua(),r=L(F(n),2),i=F(r,!0);k(r),k(n),R(e=>G(i,e),[()=>JSON.stringify(t.isDirtyByField,Object.keys(t.isDirtyByField).toSorted((e,t)=>e.localeCompare(t)),2)]),W(e,n)};K(p,e=>{t.isDirtyByField&&e(m)});var h=L(p,2),g=L(F(h),2),_=F(g,!0);k(g),k(h);var v=L(h,2);k(r),R((e,i)=>{ci(r,1,`w-full ${n()??``} flex-shrink-0 space-y-4`),G(o,e),G(u,` ${t.isDirty??``}`),G(f,` ${t.hasErrors??``}`),G(_,i)},[()=>JSON.stringify(t.data,void 0,2),()=>JSON.stringify(t.errors,void 0,2)]),H(`click`,v,function(...e){t.onFill?.apply(this,e)}),W(e,r),Ge()}Nr([`click`]);var pa=U(`

            `);function ma(e,t){var n=Vr(),r=I(n),i=e=>{var n=pa(),r=F(n,!0);k(n),R(()=>G(r,t.error)),W(e,n)};K(r,e=>{t.error&&e(i)}),W(e,n)}var ha=U(``),ga=U(`
            `);function Y(e,t){We(t,!0);let n=Di(t,`type`,3,`text`),r=Di(t,`placeholder`,3,``),i=Di(t,`value`,15),a=Di(t,`error`,3,``),o=Di(t,`required`,3,!0),s=Di(t,`disabled`,3,!1),c=Di(t,`variant`,3,`default`),l=j(()=>c()===`nested`?`bg-white`:`bg-gray-50`);var u=ga(),d=F(u),f=F(d),p=L(f),m=e=>{W(e,ha())};K(p,e=>{t.isDirty&&e(m)}),k(d);var h=L(d,2);gi(h);var g=L(h,2);{let e=j(()=>a()??``);ma(g,{get error(){return V(e)}})}k(u),R(()=>{ci(d,1,`mb-2 block text-sm text-gray-900 ${o()?`font-bold`:``}`),_i(d,`for`,t.id),G(f,`${t.label??``} `),_i(h,`id`,t.id),ci(h,1,`block w-full rounded-lg border p-2.5 text-sm ${a()?`border-red-500 bg-red-50 text-red-900 placeholder-red-400 focus:border-red-500 focus:ring-red-500`:`border-gray-300 ${V(l)} text-gray-900 focus:border-blue-500 focus:ring-blue-500`} ${s()?`cursor-not-allowed opacity-50`:``}`),h.disabled=s(),_i(h,`max`,t.max),_i(h,`min`,t.min),_i(h,`placeholder`,r()),_i(h,`step`,t.step),_i(h,`type`,n())}),xi(h,i),W(e,u),Ge()}var _a=U(`

            `),va=U(`
            `),ya=U(`
            `,1);function ba(e,t){var n=ya(),r=I(n),i=F(r),a=F(i),o=F(a,!0);k(a);var s=L(a,2),c=e=>{var n=_a(),r=F(n,!0);k(n),R(()=>G(r,t.description)),W(e,n)},l=e=>{W(e,va())};K(s,e=>{t.description?e(c):e(l,-1)}),ai(L(s,2),()=>t.main),k(i),ai(L(i,2),()=>t.sidebar),k(r);var u=L(r,2),d=e=>{var n=Vr();ai(I(n),()=>t.sourceCode),W(e,n)};K(u,e=>{t.sourceCode&&e(d)}),R(()=>G(o,t.title)),W(e,n)}var xa=U(`
            `),Sa=U(`
            `);function Ca(e,t){let n=N(!1);var r=Sa(),i=F(r),a=L(F(i),2);k(i);var o=L(i,2),s=e=>{var n=xa();ai(F(n),()=>t.children),k(n),W(e,n)};K(o,e=>{V(n)&&e(s)}),k(r),R(()=>{ci(i,1,`flex w-full cursor-pointer items-center justify-between px-4 py-3 text-left text-sm font-medium text-gray-900 hover:bg-gray-50 ${V(n)?`border-b border-gray-200`:``}`),ci(a,0,`h-5 w-5 transform transition-transform ${V(n)?`rotate-180`:``}`)}),H(`click`,i,()=>P(n,!V(n))),W(e,r)}Nr([`click`]);var wa=U(`
            `);function Ta(e,t){var n=wa(),r=F(n),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{ci(r,1,`rounded px-2.5 py-0.5 text-xs font-medium ${t.hasErrors?`bg-red-100 text-red-800`:`bg-green-100 text-green-800`}`),G(i,t.hasErrors?`Has Errors`:`Valid`),ci(a,1,`rounded px-2.5 py-0.5 text-xs font-medium ${t.isDirty?`bg-yellow-100 text-yellow-800`:`bg-gray-100 text-gray-800`}`),G(o,t.isDirty?`Modified`:`Clean`)}),W(e,n)}var X=()=>Math.random().toString(36).slice(2,8),Ea=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,Da=U(`
            `),Oa=U(`
            `),ka=U(` Submitting...`),Aa=U(`
            `,1),ja=U(`
            Action State
            actionInProgress:
            actionError:
            `),Ma=U(` `,1);function Na(e,t){We(t,!0);let n=()=>A(h,`$hasErrors`,s),r=()=>A(g,`$isDirty`,s),i=()=>A(_,`$actionInProgress`,s),a=()=>A(m,`$errors`,s),o=()=>A(v,`$actionError`,s),[s,c]=ft(),l={title:`Task ${X()}`,description:`This is a sample task description with ID ${X()}`},u=N(!1),d=N(void 0),{data:f,execute:p,state:{errors:m,hasErrors:h,isDirty:g,actionInProgress:_,actionError:v}}=ia(l,{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(3).maxLength(50).getError(),description:q(e.description).prepare(`trim`).required().minLength(10).maxLength(200).getError()}),action:async()=>{let e=Ea(100,1e3);if(await new Promise(t=>setTimeout(t,e)),V(u))throw Error(`Simulated server error after ${e}ms`);P(d,`Submitted successfully in ${e}ms!`)},actionCompleted:e=>{e&&P(d,void 0)}}),y=()=>{f.title=`Task ${X()}`,f.description=`This is a sample task description with ID ${X()}`},b=()=>{P(d,void 0),p()};ba(e,{description:`Demonstrates async action execution with loading states and error handling.`,title:`Action Demo`,main:e=>{var t=Aa(),s=I(t);Ta(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=F(c),p=F(l,!0);k(l),k(c);var m=L(c,2),h=F(m);{let e=j(()=>a()?.title);Y(h,{id:`title`,get disabled(){return i()},get error(){return V(e)},label:`Title`,placeholder:`Enter task title`,get value(){return f.title},set value(e){f.title=e}})}var g=L(h,2);{let e=j(()=>a()?.description);Y(g,{id:`description`,get disabled(){return i()},get error(){return V(e)},label:`Description`,placeholder:`Enter task description (min 10 characters)`,get value(){return f.description},set value(e){f.description=e}})}var _=L(g,2),v=F(_);gi(v),Pe(2),k(_),k(m);var y=L(m,2),x=e=>{var t=Da(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,o().message)),W(e,t)};K(y,e=>{o()&&e(x)});var S=L(y,2),C=e=>{var t=Oa(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,V(d))),W(e,t)};K(S,e=>{V(d)&&e(C)});var w=L(S,2),T=F(w),E=F(T),ee=e=>{W(e,ka())},te=e=>{W(e,Br(`Submit`))};K(E,e=>{i()?e(ee):e(te,-1)}),k(T),k(w),R(()=>{ci(l,1,`rounded px-2.5 py-0.5 text-xs font-medium ${i()?`bg-blue-100 text-blue-800`:`bg-gray-100 text-gray-800`}`),G(p,i()?`In Progress`:`Idle`),v.disabled=i(),T.disabled=n()||i()}),Si(v,()=>V(u),e=>P(u,e)),H(`click`,T,b),W(e,t)},sidebar:e=>{var t=ja(),s=F(t);fa(s,{get data(){return f},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:y});var c=L(s,2),l=L(F(c),2),u=F(l),d=L(F(u));k(u);var p=L(u,2),m=L(F(p));k(p),k(l),k(c),k(t),R(()=>{G(d,` ${i()??``}`),G(m,` ${o()?.message??`none`??``}`)}),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Ma(),r=I(n);J(r,{code:`const { data, execute, state: { errors, hasErrors, isDirty, actionInProgress, actionError } } = - createSvState(sourceData, { - validator: (source) => ({ - title: stringValidator(source.title).prepare('trim').required().minLength(3).maxLength(50).getError(), - description: stringValidator(source.description).prepare('trim').required().minLength(10).getError() - }), - action: async () => { - // Simulate API call with 100-1000ms delay - const delay = randomInt(100, 1000); - await new Promise((resolve) => setTimeout(resolve, delay)); - - if (shouldFail) { - throw new Error('Simulated server error'); - } - }, - actionCompleted: (error) => { - // Called after action completes (success or failure) - console.log(error ? 'Action failed' : 'Action succeeded'); - } - });`,title:`State Setup with Action`});var i=L(r,2);J(i,{code:`// Execute the action - - -// With parameters (if action accepts them) -execute({ userId: 123 });`,title:`Execute Action`}),J(L(i,2),{code:`// Display action error -{#if $actionError} -
            - {$actionError.message} -
            -{/if} - -// Check if action is in progress -{#if $actionInProgress} -
            Submitting...
            -{/if}`,title:`Error & Loading States`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var Pa=U(`
            `);function Fa(e,t){let n=Di(t,`label`,3,`Item`);var r=Pa(),i=F(r),a=F(i),o=F(a);k(a);var s=L(a,2);k(i),ai(L(i,2),()=>t.children),k(r),R(()=>G(o,`${n()??``} #${t.index+1}`)),H(`click`,s,function(...e){t.onRemove?.apply(this,e)}),W(e,r)}Nr([`click`]);var Ia=U(`

            `);function La(e,t){var n=Ia(),r=F(n),i=F(r,!0);k(r),k(n),R(()=>G(i,t.message)),W(e,n)}var Ra=U(`
            `),za=U(`
            `),Ba=U(`
            `),Va=U(`
            Contacts
            `,1),Ha=U(` `,1);function Ua(e,t){We(t,!0);let n=()=>A(l,`$hasErrors`,a),r=()=>A(u,`$isDirty`,a),i=()=>A(c,`$errors`,a),[a,o]=ft(),{data:s,state:{errors:c,hasErrors:l,isDirty:u}}=ia({listName:``,items:[]},{validator:e=>({listName:q(e.listName).prepare(`trim`).required().minLength(2).getError(),items:sa(e.items).required().minLength(1).getError(),...Object.fromEntries(e.items.map((e,t)=>[`item_${t}`,{name:q(e.name).prepare(`trim`).required().minLength(2).getError(),email:q(e.email).prepare(`trim`).required().email().getError()}]))})}),d=()=>{s.items=[...s.items,{name:``,email:``}]},f=e=>{s.items=s.items.filter((t,n)=>n!==e)},p=()=>{s.listName=`Contact List ${X()}`,s.items=[{name:`John Doe`,email:`john@example.com`},{name:`Jane Smith`,email:`jane@example.com`},{name:`Bob Wilson`,email:`bob@example.com`}]};ba(e,{description:`Shows how to validate dynamic arrays with per-item validation using indexed error keys.`,title:`Array Property Demo`,main:e=>{var t=Va(),a=I(t);Ta(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.listName);Y(c,{id:`listName`,get error(){return V(e)},label:`List Name`,placeholder:`Enter list name`,get value(){return s.listName},set value(e){s.listName=e}})}var l=L(c,2),u=F(l),p=F(u),m=L(F(p)),h=F(m);k(m),k(p);var g=L(p,2);k(u);var _=L(u,2),v=e=>{var t=Ra();ma(F(t),{get error(){return i().items}}),k(t),W(e,t)};K(_,e=>{i()?.items&&e(v)});var y=L(_,2),b=e=>{La(e,{message:`No contacts yet. Click "Add Contact" to get started.`})},x=e=>{var t=Ba();$r(t,21,()=>s.items,Yr,(e,t,n)=>{Fa(e,{index:n,label:`Contact`,onRemove:()=>f(n),children:(e,r)=>{var a=za(),o=F(a),s=F(o);_i(s,`for`,`item-name-${n}`);var c=L(s,2);gi(c),_i(c,`id`,`item-name-${n}`);var l=L(c,2);{let e=j(()=>i()?.[`item_${n}`]?.name??``);ma(l,{get error(){return V(e)}})}k(o);var u=L(o,2),d=F(u);_i(d,`for`,`item-email-${n}`);var f=L(d,2);gi(f),_i(f,`id`,`item-email-${n}`);var p=L(f,2);{let e=j(()=>i()?.[`item_${n}`]?.email??``);ma(p,{get error(){return V(e)}})}k(u),k(a),R(()=>{ci(c,1,`block w-full rounded-lg border p-2 text-sm ${i()?.[`item_${n}`]?.name?`border-red-500 bg-red-50 text-red-900 placeholder-red-400`:`border-gray-300 bg-white text-gray-900`}`),ci(f,1,`block w-full rounded-lg border p-2 text-sm ${i()?.[`item_${n}`]?.email?`border-red-500 bg-red-50 text-red-900 placeholder-red-400`:`border-gray-300 bg-white text-gray-900`}`)}),xi(c,()=>V(t).name,e=>V(t).name=e),xi(f,()=>V(t).email,e=>V(t).email=e),W(e,a)},$$slots:{default:!0}})}),k(t),W(e,t)};K(y,e=>{s.items.length===0?e(b):e(x,-1)}),k(l),k(o),R(()=>G(h,`${s.items.length??``} items`)),H(`click`,g,d),W(e,t)},sidebar:e=>{fa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:p,width:`xl:w-96`})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Ha(),r=I(n);J(r,{code:`const sourceData = { - listName: '', - items: [] as { name: string; email: string }[] -}; - -const { data, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { - validator: (source) => ({ - listName: stringValidator(source.listName).prepare('trim').required().minLength(2).getError(), - items: arrayValidator(source.items).required().minLength(1).getError(), - // Per-item validation using indexed keys - ...Object.fromEntries( - source.items.map((item, index) => [ - \`item_\${index}\`, - { - name: stringValidator(item.name).prepare('trim').required().minLength(2).getError(), - email: stringValidator(item.email).prepare('trim').required().email().getError() - } - ]) - ) - }) -});`,title:`State Setup with Array Item Validation`}),J(L(r,2),{code:`// Define type for item errors -type ItemErrors = Record; - -{#each data.items as item, index} - - - - - -{/each}`,title:`Array Form Binding Examples`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]),Ve();var Wa=U(`
            `),Ga=U(` Validating...`),Ka=U(`
            Taken usernames:
            Taken emails:
            Taken slugs:
            Concurrency limit: maxConcurrentAsyncValidations = 2
            Only 2 async validations run simultaneously. Try filling all 3 fields at once to see queuing in action.
            `,1),qa=U(`
            Quick Fill
            Async Validation State
            asyncValidating:
            hasAsyncErrors:
            hasCombinedErrors:
            Async Errors
             
            `),Ja=U(` `,1);function Ya(e,t){We(t,!1);let n=()=>A(_,`$hasErrors`,l),r=()=>A(v,`$isDirty`,l),i=()=>A(b,`$hasAsyncErrors`,l),a=()=>A(S,`$hasCombinedErrors`,l),o=()=>A(g,`$errors`,l),s=()=>A(y,`$asyncErrors`,l),c=()=>A(x,`$asyncValidating`,l),[l,u]=ft(),d=[`admin`,`user`,`test`,`demo`,`root`],f=[`admin@example.com`,`test@example.com`,`user@example.com`],p=[`admin`,`about`,`contact`,`help`,`support`],m=ia({username:``,email:``,slug:``},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(3).maxLength(20).noSpace().getError(),email:q(e.email).prepare(`trim`).required().email().getError(),slug:q(e.slug).prepare(`trim`).required().minLength(2).slug().getError()}),asyncValidator:{username:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,500);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return d.includes(r)?`Username is already taken`:``},email:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,400);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return f.includes(r)?`Email is already registered`:``},slug:async(e,t,n)=>{await new Promise((e,t)=>{let r=setTimeout(e,600);n.addEventListener(`abort`,()=>{clearTimeout(r),t(new DOMException(`Aborted`,`AbortError`))})});let r=String(e).toLowerCase();return p.includes(r)?`URL slug is already in use`:``}}},{maxConcurrentAsyncValidations:2}),h=an(m.data),g=m.state.errors,_=m.state.hasErrors,v=m.state.isDirty,y=m.state.asyncErrors,b=m.state.hasAsyncErrors,x=m.state.asyncValidating,S=m.state.hasCombinedErrors,C=()=>{on(h,V(h).username=`newuser${X()}`),on(h,V(h).email=`${X()}@example.com`),on(h,V(h).slug=`my-page-${X()}`)},w=()=>{on(h,V(h).username=`admin`),on(h,V(h).email=`admin@example.com`),on(h,V(h).slug=`about`)};Ti(),ba(e,{description:`Demonstrates async validation with simulated API calls for username and email uniqueness checks.`,title:`Async Validation Demo`,main:e=>{var t=Ka(),l=I(t);Ta(l,{get hasErrors(){return n()},get isDirty(){return r()}});var u=L(l,2),m=F(u),g=F(m);k(m);var _=L(m,2),v=F(_);k(_),k(u);var y=L(u,2),b=F(y),x=F(b);{let e=At(()=>o()?.username||s().username);Y(x,{id:`username`,get error(){return V(e)},label:`Username`,placeholder:`Enter username (try 'admin', 'user', 'test')`,get value(){return V(h).username},set value(e){on(h,V(h).username=e)},$$legacy:!0})}var S=L(x,2),C=e=>{W(e,Wa())},w=j(()=>c().includes(`username`));K(S,e=>{V(w)&&e(C)}),k(b);var T=L(b,2),E=F(T);{let e=At(()=>o()?.email||s().email);Y(E,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email (try 'admin@example.com')`,type:`email`,get value(){return V(h).email},set value(e){on(h,V(h).email=e)},$$legacy:!0})}var ee=L(E,2),te=e=>{W(e,Wa())},ne=j(()=>c().includes(`email`));K(ee,e=>{V(ne)&&e(te)}),k(T);var re=L(T,2),ie=F(re);{let e=At(()=>o()?.slug||s().slug);Y(ie,{id:`slug`,get error(){return V(e)},label:`URL Slug`,placeholder:`Enter slug (try 'admin', 'about', 'contact')`,get value(){return V(h).slug},set value(e){on(h,V(h).slug=e)},$$legacy:!0})}var ae=L(ie,2),oe=e=>{W(e,Wa())},se=j(()=>c().includes(`slug`));K(ae,e=>{V(se)&&e(oe)}),k(re),k(y);var ce=L(y,2),le=F(ce),ue=L(F(le));k(le);var de=L(le,2),fe=L(F(de));k(de);var pe=L(de,2),me=L(F(pe));k(pe),k(ce);var he=L(ce,4),ge=F(he),_e=F(ge),ve=e=>{W(e,Ga())},ye=e=>{W(e,Br(`Submit`))};K(_e,e=>{c().length>0?e(ve):e(ye,-1)}),k(ge),k(he),R((e,t,n)=>{ci(m,1,`rounded px-2.5 py-0.5 text-xs font-medium ${i()?`bg-red-100 text-red-800`:`bg-gray-100 text-gray-800`}`),G(g,`Async Errors: ${i()?`Yes`:`No`}`),ci(_,1,`rounded px-2.5 py-0.5 text-xs font-medium ${a()?`bg-red-100 text-red-800`:`bg-green-100 text-green-800`}`),G(v,`Combined: ${a()?`Has Errors`:`Valid`}`),G(ue,` ${e??``}`),G(fe,` ${t??``}`),G(me,` ${n??``}`),ge.disabled=a()||c().length>0},[()=>d.join(`, `),()=>f.join(`, `),()=>p.join(`, `)]),W(e,t)},sidebar:e=>{var t=qa(),l=F(t);fa(l,{get data(){return V(h)},get errors(){return o()},get hasErrors(){return n()},get isDirty(){return r()},onFill:C});var u=L(l,2),d=L(F(u),2);k(u);var f=L(u,2),p=L(F(f),2),m=F(p),g=L(F(m));k(m);var _=L(m,2),v=L(F(_));k(_);var y=L(_,2),b=L(F(y));k(y),k(p),k(f);var x=L(f,2),S=L(F(x),2),T=F(S,!0);k(S),k(x),k(t),R((e,t)=>{G(g,` [${e??``}]`),G(v,` ${i()??``}`),G(b,` ${a()??``}`),G(T,t)},[()=>c().join(`, `),()=>JSON.stringify(s(),void 0,2)]),H(`click`,d,w),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Ja(),r=I(n);J(r,{code:`const { data, state: { errors, asyncErrors, asyncValidating, hasCombinedErrors } } = - createSvState(sourceData, { - validator: (source) => ({ - username: stringValidator(source.username).required().minLength(3).noSpace().getError(), - email: stringValidator(source.email).required().email().getError(), - slug: stringValidator(source.slug).required().minLength(2).slug().getError() - }), - asyncValidator: { - username: async (value, source, signal) => { - const res = await fetch(\`/api/check-username?u=\${value}\`, { signal }); - return (await res.json()).available ? '' : 'Username already taken'; - }, - email: async (value, source, signal) => { - const res = await fetch(\`/api/check-email?e=\${value}\`, { signal }); - return (await res.json()).available ? '' : 'Email already registered'; - }, - slug: async (value, source, signal) => { - const res = await fetch(\`/api/check-slug?s=\${value}\`, { signal }); - return (await res.json()).available ? '' : 'URL slug already in use'; - } - } - }, - { maxConcurrentAsyncValidations: 2 } // Only 2 async validations run at a time -);`,title:`State Setup with Async Validators`});var i=L(r,2);J(i,{code:` -{#if $asyncValidating.includes('username')} - ... -{/if} - - -{#if $asyncErrors.username} - {$asyncErrors.username} -{/if} - - -`,title:`Template Usage`}),J(L(i,2),{code:`// Available stores for async validation: -$errors // Sync validation errors (nested object) -$hasErrors // true if any sync errors - -$asyncErrors // Async validation errors (flat map by path) -$hasAsyncErrors // true if any async errors - -$asyncValidating // Array of paths currently being validated -$hasCombinedErrors // hasErrors || hasAsyncErrors`,title:`Available Stores`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),u()}Nr([`click`]);var Xa=U(``),Za=U(`
            `);function Qa(e,t){We(t,!0);let n=Di(t,`placeholder`,3,``),r=Di(t,`value`,15),i=Di(t,`error`,3,``),a=Di(t,`required`,3,!1),o=Di(t,`rows`,3,3);var s=Za(),c=F(s),l=F(c),u=L(l),d=e=>{W(e,Xa())};K(u,e=>{t.isDirty&&e(d)}),k(c);var f=L(c,2);mt(f);var p=L(f,2);{let e=j(()=>i()??``);ma(p,{get error(){return V(e)}})}k(s),R(()=>{ci(c,1,`mb-2 block text-sm text-gray-900 ${a()?`font-bold`:``}`),_i(c,`for`,t.id),G(l,`${t.label??``} `),_i(f,`id`,t.id),ci(f,1,`block w-full rounded-lg border p-2.5 text-sm ${i()?`border-red-500 bg-red-50 text-red-900 placeholder-red-400 focus:border-red-500 focus:ring-red-500`:`border-gray-300 bg-gray-50 text-gray-900 focus:border-blue-500 focus:ring-blue-500`}`),_i(f,`placeholder`,n()),_i(f,`rows`,o())}),xi(f,r),W(e,s),Ge()}var $a=U(`
            `,1),eo=U(` `,1);function to(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,o),r=()=>A(d,`$isDirty`,o),i=()=>A(l,`$errors`,o),a=()=>A(f,`$isDirtyByField`,o),[o,s]=ft(),{data:c,state:{errors:l,hasErrors:u,isDirty:d,isDirtyByField:f}}=ia({username:``,email:``,age:0,bio:``,website:``},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(3).maxLength(20).noSpace().getError(),email:q(e.email).prepare(`trim`).required().email().getError(),age:oa(e.age).required().min(18).max(120).integer().getError(),bio:q(e.bio).maxLength(200).getError(),website:q(e.website).prepare(`trim`).website(`required`).getError()})}),p=()=>{c.username=`user${X()}`,c.email=`${X()}@example.com`,c.age=Ea(18,65),c.bio=`Hello, I am a demo user!`,c.website=`https://${X()}.com`};ba(e,{description:`Demonstrates form validation with string, number, and email validators using the fluent API.`,title:`Basic Validation Demo`,main:e=>{var t=$a(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s);{let e=j(()=>i()?.username);Y(l,{id:`username`,get error(){return V(e)},get isDirty(){return a().username},label:`Username`,placeholder:`Enter username`,get value(){return c.username},set value(e){c.username=e}})}var u=L(l,2);{let e=j(()=>i()?.email);Y(u,{id:`email`,get error(){return V(e)},get isDirty(){return a().email},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return c.email},set value(e){c.email=e}})}var d=L(u,2);{let e=j(()=>i()?.age);Y(d,{id:`age`,get error(){return V(e)},get isDirty(){return a().age},label:`Age`,placeholder:`Enter age`,type:`number`,get value(){return c.age},set value(e){c.age=e}})}var f=L(d,2);{let e=j(()=>i()?.bio);Qa(f,{id:`bio`,get error(){return V(e)},get isDirty(){return a().bio},label:`Bio`,placeholder:`Tell us about yourself`,get value(){return c.bio},set value(e){c.bio=e}})}var p=L(f,2);{let e=j(()=>i()?.website);Y(p,{id:`website`,get error(){return V(e)},get isDirty(){return a().website},label:`Website`,placeholder:`https://example.com`,required:!1,get value(){return c.website},set value(e){c.website=e}})}k(s),W(e,t)},sidebar:e=>{fa(e,{get data(){return c},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return a()},onFill:p})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=eo(),r=I(n);J(r,{code:`const sourceData = { - username: '', - email: '', - age: 0, - bio: '', - website: '' -}; - -const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { - validator: (source) => ({ - username: stringValidator(source.username).prepare('trim').required().minLength(3).maxLength(20).noSpace().getError(), - email: stringValidator(source.email).prepare('trim').required().email().getError(), - age: numberValidator(source.age).required().min(18).max(120).integer().getError(), - bio: stringValidator(source.bio).maxLength(200).getError(), - website: stringValidator(source.website).prepare('trim').website('required').getError() - }) -});`,title:`State Setup`}),J(L(r,2),{code:` -`,title:`Form Binding Example`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var no=U(` `),ro=U(`
            `);function io(e,t){var n=ro(),r=F(n),i=L(r),a=e=>{var n=no(),r=F(n);k(n),R(()=>G(r,`(${t.subtitle??``})`)),W(e,n)};K(i,e=>{t.subtitle&&e(a)});var o=L(i,2),s=e=>{var n=Vr();ai(I(n),()=>t.children),W(e,n)};K(o,e=>{t.children&&e(s)}),k(n),R(()=>G(r,`${t.title??``} `)),W(e,n)}var ao=U(`
            Subtotal:
            Tax (8%):
            Total:

            Values formatted using methods on state: data.formatCurrency() and data.formatTotal()

            `,1),oo=U(` `,1);function so(e,t){We(t,!0);let n=()=>A(l,`$hasErrors`,a),r=()=>A(u,`$isDirty`,a),i=()=>A(c,`$errors`,a),[a,o]=ft(),{data:s,state:{errors:c,hasErrors:l,isDirty:u}}=ia({productName:`Widget ${X()}`,item:{unitPrice:0,quantity:1},subtotal:0,tax:0,total:0,formatTotal(){return`$${this.total.toFixed(2)}`},formatCurrency(e){return`$${e.toFixed(2)}`},calculateTotals(e=.08){this.subtotal=this.item.unitPrice*this.item.quantity,this.tax=this.subtotal*e,this.total=this.subtotal+this.tax}},{validator:e=>({productName:q(e.productName).prepare(`trim`).required().minLength(2).getError(),item:{unitPrice:oa(e.item.unitPrice).required().positive().getError(),quantity:oa(e.item.quantity).required().integer().min(1).max(100).getError()}}),effect:({property:e})=>{(e===`item.unitPrice`||e===`item.quantity`)&&s.calculateTotals()}}),d=()=>{s.productName=`Widget ${X()}`,s.item.unitPrice=Ea(10,100),s.item.quantity=Ea(1,10)};ba(e,{description:`Demonstrates using objects with methods as state. The effect callback can call methods directly on the state object.`,title:`State with Methods Demo`,main:e=>{var t=ao(),a=I(t);Ta(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.productName);Y(c,{id:`productName`,get error(){return V(e)},label:`Product Name`,placeholder:`Enter product name`,get value(){return s.productName},set value(e){s.productName=e}})}var l=L(c,2),u=F(l);io(u,{subtitle:`nested object`,title:`Item Details`});var d=L(u,2),f=F(d);{let e=j(()=>i()?.item?.unitPrice);Y(f,{id:`unitPrice`,get error(){return V(e)},label:`Unit Price ($)`,min:0,placeholder:`0.00`,step:.01,type:`number`,get value(){return s.item.unitPrice},set value(e){s.item.unitPrice=e}})}var p=L(f,2);{let e=j(()=>i()?.item?.quantity);Y(p,{id:`quantity`,get error(){return V(e)},label:`Quantity`,max:100,min:1,placeholder:`1`,type:`number`,get value(){return s.item.quantity},set value(e){s.item.quantity=e}})}k(d),k(l);var m=L(l,2),h=F(m);io(h,{subtitle:`computed by method`,title:`Calculated Totals`});var g=L(h,2),_=F(g),v=F(_),y=L(F(v),2),b=F(y,!0);k(y),k(v);var x=L(v,2),S=L(F(x),2),C=F(S,!0);k(S),k(x);var w=L(x,2),T=L(F(w),2),E=F(T,!0);k(T),k(w),k(_),k(g),Pe(2),k(m),k(o),R((e,t,n)=>{G(b,e),G(C,t),G(E,n)},[()=>s.formatCurrency(s.subtotal),()=>s.formatCurrency(s.tax),()=>s.formatTotal()]),W(e,t)},sidebar:e=>{fa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:d})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=oo(),r=I(n);J(r,{code:`// Define state type with methods -type SourceData = { - productName: string; - item: { unitPrice: number; quantity: number }; - subtotal: number; - tax: number; - total: number; - formatTotal: () => string; - formatCurrency: (value: number) => string; - calculateTotals: (taxRate?: number) => void; -}; - -// Create initial state as object with methods -const createSourceData = (): SourceData => ({ - productName: '', - item: { unitPrice: 0, quantity: 1 }, - subtotal: 0, - tax: 0, - total: 0, - formatTotal() { - return \`$\${this.total.toFixed(2)}\`; - }, - formatCurrency(value: number) { - return \`$\${value.toFixed(2)}\`; - }, - calculateTotals(taxRate: number = 0.08) { - this.subtotal = this.item.unitPrice * this.item.quantity; - this.tax = this.subtotal * taxRate; - this.total = this.subtotal + this.tax; - } -});`,title:`Class Definition`});var i=L(r,2);J(i,{code:`const { data, state: { errors, hasErrors, isDirty } } = createSvState(createSourceData(), { - validator: (source) => ({ - productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), - item: { - unitPrice: numberValidator(source.item.unitPrice).required().positive().getError(), - quantity: numberValidator(source.item.quantity).required().integer().min(1).max(100).getError() - } - }), - effect: ({ property }) => { - if (property === 'item.unitPrice' || property === 'item.quantity') { - data.calculateTotals(); // Call method on state object! - } - } -});`,title:`State Setup with Class Instance`}),J(L(i,2),{code:` -{data.formatCurrency(data.subtotal)} -{data.formatTotal()}`,title:`Template Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}var co=U(`
            Subtotal:
            Tax (8%):
            Total:
            `,1),lo=U(` `,1);function uo(e,t){We(t,!0);let n=()=>A(l,`$hasErrors`,a),r=()=>A(u,`$isDirty`,a),i=()=>A(c,`$errors`,a),[a,o]=ft(),{data:s,state:{errors:c,hasErrors:l,isDirty:u}}=ia({productName:`Widget ${X()}`,item:{unitPrice:0,quantity:1},subtotal:0,tax:0,total:0},{validator:e=>({productName:q(e.productName).prepare(`trim`).required().minLength(2).getError(),item:{unitPrice:oa(e.item.unitPrice).required().positive().getError(),quantity:oa(e.item.quantity).required().integer().min(1).max(100).getError()}}),effect:({property:e})=>{(e===`item.unitPrice`||e===`item.quantity`)&&(s.subtotal=s.item.unitPrice*s.item.quantity,s.tax=s.subtotal*.08,s.total=s.subtotal+s.tax)}}),d=()=>{s.productName=`Widget ${X()}`,s.item.unitPrice=Ea(10,100),s.item.quantity=Ea(1,10)},f=e=>`$${e.toFixed(2)}`;ba(e,{description:`Uses the effect callback to automatically compute derived values like subtotals, taxes, and totals.`,title:`Calculated Fields Demo`,main:e=>{var t=co(),a=I(t);Ta(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),c=F(o);{let e=j(()=>i()?.productName);Y(c,{id:`productName`,get error(){return V(e)},label:`Product Name`,placeholder:`Enter product name`,get value(){return s.productName},set value(e){s.productName=e}})}var l=L(c,2),u=F(l);io(u,{subtitle:`nested object`,title:`Item Details`});var d=L(u,2),p=F(d);{let e=j(()=>i()?.item?.unitPrice);Y(p,{id:`unitPrice`,get error(){return V(e)},label:`Unit Price ($)`,min:0,placeholder:`0.00`,step:.01,type:`number`,get value(){return s.item.unitPrice},set value(e){s.item.unitPrice=e}})}var m=L(p,2);{let e=j(()=>i()?.item?.quantity);Y(m,{id:`quantity`,get error(){return V(e)},label:`Quantity`,max:100,min:1,placeholder:`1`,type:`number`,get value(){return s.item.quantity},set value(e){s.item.quantity=e}})}k(d),k(l);var h=L(l,2),g=F(h);io(g,{subtitle:`computed by effect`,title:`Calculated Totals`});var _=L(g,2),v=F(_),y=F(v),b=L(F(y),2),x=F(b,!0);k(b),k(y);var S=L(y,2),C=L(F(S),2),w=F(C,!0);k(C),k(S);var T=L(S,2),E=L(F(T),2),ee=F(E,!0);k(E),k(T),k(v),k(_),k(h),k(o),R((e,t,n)=>{G(x,e),G(w,t),G(ee,n)},[()=>f(s.subtotal),()=>f(s.tax),()=>f(s.total)]),W(e,t)},sidebar:e=>{fa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:d})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=lo(),r=I(n);J(r,{code:`const sourceData = { - productName: '', - item: { unitPrice: 0, quantity: 1 }, - subtotal: 0, tax: 0, total: 0 // Calculated fields (set by effect) -}; - -const TAX_RATE = 0.08; - -const { data, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { - validator: (source) => ({ - productName: stringValidator(source.productName).prepare('trim').required().minLength(2).getError(), - item: { - unitPrice: numberValidator(source.item.unitPrice).required().positive().getError(), - quantity: numberValidator(source.item.quantity).required().integer().min(1).max(100).getError() - } - }), - effect: ({ property }) => { - if (property === 'item.unitPrice' || property === 'item.quantity') { - data.subtotal = data.item.unitPrice * data.item.quantity; - data.tax = data.subtotal * TAX_RATE; - data.total = data.subtotal + data.tax; - } - } -});`,title:`State Setup with Effect`}),J(L(r,2),{code:`effect: ({ property }) => { - if (property === 'item.unitPrice' || property === 'item.quantity') { - data.subtotal = data.item.unitPrice * data.item.quantity; - data.tax = data.subtotal * TAX_RATE; - data.total = data.subtotal + data.tax; - } -}`,title:`Effect Function`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}var fo=U(` `),po=U(``),mo=U(`
            `);function ho(e,t){var n=mo(),r=F(n),i=F(r),a=L(i),o=e=>{var n=fo(),r=F(n);k(n),R(()=>G(r,`(${t.subtitle??``})`)),W(e,n)};K(a,e=>{t.subtitle&&e(o)});var s=L(a,2),c=e=>{W(e,po())};K(s,e=>{t.isDirty&&e(c)}),k(r),ai(L(r,2),()=>t.children),k(n),R(()=>G(i,`${t.title??``} `)),W(e,n)}var go=U(``),_o=U(`
            `),vo=U(`
            `,1),yo=U(` `,1);function bo(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,o),r=()=>A(d,`$isDirty`,o),i=()=>A(f,`$isDirtyByField`,o),a=()=>A(l,`$errors`,o),[o,s]=ft(),{data:c,state:{errors:l,hasErrors:u,isDirty:d,isDirtyByField:f}}=ia({name:``,address:{street:``,city:``,zip:``},company:{name:``,department:``,contact:{phone:``,email:``}}},{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),address:{street:q(e.address.street).prepare(`trim`).required().minLength(5).getError(),city:q(e.address.city).prepare(`trim`).required().minLength(2).getError(),zip:q(e.address.zip).prepare(`trim`).required().minLength(5).maxLength(10).getError()},company:{name:q(e.company.name).prepare(`trim`).required().minLength(2).getError(),department:q(e.company.department).prepare(`trim`).maxLength(50).getError(),contact:{phone:q(e.company.contact.phone).prepare(`trim`).required().minLength(10).getError(),email:q(e.company.contact.email).prepare(`trim`).required().email().getError()}}})}),p=()=>{c.name=`John ${X()}`,c.address.street=`${Ea(100,9999)} Main Street`,c.address.city=`New York`,c.address.zip=String(Ea(1e4,99999)),c.company.name=`Acme ${X()} Inc`,c.company.department=`Engineering`,c.company.contact.phone=`555-${Ea(100,999)}-${Ea(1e3,9999)}`,c.company.contact.email=`contact@${X()}.com`};ba(e,{description:`Illustrates validating deeply nested object structures with multi-level property paths.`,title:`Nested Objects Demo`,main:e=>{var t=vo(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),u=F(l);io(u,{title:`Personal Info`,children:(e,t)=>{var n=Vr(),r=I(n),a=e=>{W(e,go())};K(r,e=>{i().name&&e(a)}),W(e,n)},$$slots:{default:!0}});var d=L(u,2);{let e=j(()=>a()?.name);Y(d,{id:`name`,get error(){return V(e)},label:`Full Name`,placeholder:`Enter your full name`,get value(){return c.name},set value(e){c.name=e}})}k(l);var f=L(l,2),p=F(f);io(p,{subtitle:`2-level nested`,title:`Address`,children:(e,t)=>{var n=Vr(),r=I(n),a=e=>{W(e,go())};K(r,e=>{i().address&&e(a)}),W(e,n)},$$slots:{default:!0}});var m=L(p,2),h=F(m);{let e=j(()=>a()?.address?.street);Y(h,{id:`street`,get error(){return V(e)},label:`Street`,placeholder:`Enter street address`,get value(){return c.address.street},set value(e){c.address.street=e}})}var g=L(h,2),_=F(g);{let e=j(()=>a()?.address?.city);Y(_,{id:`city`,get error(){return V(e)},label:`City`,placeholder:`Enter city`,get value(){return c.address.city},set value(e){c.address.city=e}})}var v=L(_,2);{let e=j(()=>a()?.address?.zip);Y(v,{id:`zip`,get error(){return V(e)},label:`ZIP Code`,placeholder:`Enter ZIP`,get value(){return c.address.zip},set value(e){c.address.zip=e}})}k(g),k(m),k(f);var y=L(f,2),b=F(y);io(b,{subtitle:`3-level nested`,title:`Company`,children:(e,t)=>{var n=Vr(),r=I(n),a=e=>{W(e,go())};K(r,e=>{i().company&&e(a)}),W(e,n)},$$slots:{default:!0}});var x=L(b,2),S=F(x),C=F(S);{let e=j(()=>a()?.company?.name);Y(C,{id:`company-name`,get error(){return V(e)},label:`Company Name`,placeholder:`Enter company name`,get value(){return c.company.name},set value(e){c.company.name=e}})}var w=L(C,2);{let e=j(()=>a()?.company?.department);Y(w,{id:`department`,get error(){return V(e)},label:`Department`,placeholder:`Enter department`,required:!1,get value(){return c.company.department},set value(e){c.company.department=e}})}k(S),ho(L(S,2),{get isDirty(){return i()[`company.contact`]},subtitle:`3rd level`,title:`Contact Info`,children:(e,t)=>{var n=_o(),r=F(n);{let e=j(()=>a()?.company?.contact?.phone);Y(r,{id:`contact-phone`,get error(){return V(e)},label:`Phone`,placeholder:`Enter phone number`,variant:`nested`,get value(){return c.company.contact.phone},set value(e){c.company.contact.phone=e}})}var i=L(r,2);{let e=j(()=>a()?.company?.contact?.email);Y(i,{id:`contact-email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email address`,type:`email`,variant:`nested`,get value(){return c.company.contact.email},set value(e){c.company.contact.email=e}})}k(n),W(e,n)},$$slots:{default:!0}}),k(x),k(y),k(s),W(e,t)},sidebar:e=>{fa(e,{get data(){return c},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return i()},onFill:p,width:`xl:w-96`})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=yo(),r=I(n);J(r,{code:`const sourceData = { - name: '', - address: { street: '', city: '', zip: '' }, // 2-level nested - company: { // 3-level nested - name: '', - department: '', - contact: { phone: '', email: '' } - } -}; - -const { data, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { - validator: (source) => ({ - name: stringValidator(source.name).prepare('trim').required().minLength(2).maxLength(50).getError(), - address: { - street: stringValidator(source.address.street).prepare('trim').required().minLength(5).getError(), - city: stringValidator(source.address.city).prepare('trim').required().minLength(2).getError(), - zip: stringValidator(source.address.zip).prepare('trim').required().minLength(5).maxLength(10).getError() - }, - company: { - name: stringValidator(source.company.name).prepare('trim').required().minLength(2).getError(), - department: stringValidator(source.company.department).prepare('trim').maxLength(50).getError(), - contact: { - phone: stringValidator(source.company.contact.phone).prepare('trim').required().minLength(10).getError(), - email: stringValidator(source.company.contact.email).prepare('trim').required().email().getError() - } - } - }) -});`,title:`State Setup with Nested Validation`}),J(L(r,2),{code:` - - - - - -`,title:`Nested Form Binding Examples`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var xo=U(`
            Effect triggered:
            `),So=U(`
            `),Co=U(`
            `),wo=U(` Submitting...`),To=U(`
            `,1),Eo=U(`
            Options

            Reset isDirty after successful action

            Try 500ms and type quickly

            Keep errors until next action

            Current Options
            `),Do=U(` `,1);function Oo(e,t){We(t,!0);let n=()=>A(V(x),`$hasErrors`,s),r=()=>A(V(S),`$isDirty`,s),i=()=>A(V(C),`$actionInProgress`,s),a=()=>A(V(b),`$errors`,s),o=()=>A(V(w),`$actionError`,s),[s,c]=ft(),l=N(!0),u=N(0),d=N(!1),f=N(0),p=N(!1),m=N(void 0),h=N(void 0),g=()=>({name:`User ${X()}`,email:`${X()}@example.com`}),_=e=>ia(g(),{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),email:q(e.email).prepare(`trim`).required().email().getError()}),effect:({property:e})=>{P(h,e,!0)},action:async()=>{let e=Ea(100,800);if(await new Promise(t=>setTimeout(t,e)),V(p))throw Error(`Simulated error after ${e}ms`);P(m,`Submitted successfully in ${e}ms!`)},actionCompleted:e=>{e&&P(m,void 0)}},e),v=N(fn(_({resetDirtyOnAction:!0,debounceValidation:0,persistActionError:!1}))),y=()=>{P(h,void 0),P(m,void 0),P(v,_({resetDirtyOnAction:V(l),debounceValidation:V(u),persistActionError:V(d)}),!0),ln(f)},b=j(()=>V(v).state.errors),x=j(()=>V(v).state.hasErrors),S=j(()=>V(v).state.isDirty),C=j(()=>V(v).state.actionInProgress),w=j(()=>V(v).state.actionError),T=()=>{V(v).data.name=`User ${X()}`,V(v).data.email=`${X()}@example.com`},E=()=>{P(m,void 0),V(v).execute()};ba(e,{description:`Interactive playground for configuring createSvState options like debouncing and error persistence.`,title:`Options Demo`,main:e=>{var t=Vr();Jr(I(t),()=>V(f),e=>{var t=To(),s=I(t);Ta(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=e=>{var t=xo(),n=F(t),r=L(F(n));k(n),k(t),R(()=>G(r,` property "${V(h)??``}" changed`)),W(e,t)};K(c,e=>{V(h)&&e(l)});var u=L(c,2),d=F(u);{let e=j(()=>a()?.name);Y(d,{id:`name`,get disabled(){return i()},get error(){return V(e)},label:`Name`,placeholder:`Enter name`,get value(){return V(v).data.name},set value(e){V(v).data.name=e}})}var f=L(d,2);{let e=j(()=>a()?.email);Y(f,{id:`email`,get disabled(){return i()},get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return V(v).data.email},set value(e){V(v).data.email=e}})}var g=L(f,2),_=F(g);gi(_),Pe(2),k(g),k(u);var y=L(u,2),b=e=>{var t=So(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,o().message)),W(e,t)};K(y,e=>{o()&&e(b)});var x=L(y,2),S=e=>{var t=Co(),n=F(t),r=L(F(n),2),i=F(r,!0);k(r),k(n),k(t),R(()=>G(i,V(m))),W(e,t)};K(x,e=>{V(m)&&e(S)});var C=L(x,2),w=F(C),T=F(w),ee=e=>{W(e,wo())},te=e=>{W(e,Br(`Submit`))};K(T,e=>{i()?e(ee):e(te,-1)}),k(w),k(C),R(()=>{_.disabled=i(),w.disabled=n()||i()}),Si(_,()=>V(p),e=>P(p,e)),H(`click`,w,E),W(e,t)}),W(e,t)},sidebar:e=>{var t=Eo(),i=F(t);fa(i,{get data(){return V(v).data},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:T});var o=L(i,2),s=L(F(o),2),c=F(s),f=F(c),p=F(f);gi(p),Pe(2),k(f),Pe(2),k(c);var m=L(c,2),h=L(F(m),2);gi(h),Pe(2),k(m);var g=L(m,2),_=F(g),b=F(_);gi(b),Pe(2),k(_),Pe(2),k(g);var x=L(g,2);k(s),k(o);var S=L(o,2),C=L(F(S),2),w=F(C),E=F(w);k(w);var ee=L(w,2),te=F(ee);k(ee);var ne=L(ee,2),re=F(ne);k(ne),k(C),k(S),k(t),R(()=>{G(E,`resetDirtyOnAction: ${V(l)??``}`),G(te,`debounceValidation: ${V(u)??``}`),G(re,`persistActionError: ${V(d)??``}`)}),Si(p,()=>V(l),e=>P(l,e)),xi(h,()=>V(u),e=>P(u,e)),Si(b,()=>V(d),e=>P(d,e)),H(`click`,x,y),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Do(),r=I(n);J(r,{code:`const { data, execute, state } = createSvState( - sourceData, - { validator, effect, action }, - { - // Reset isDirty to false after successful action - resetDirtyOnAction: true, // default: true - - // Debounce validation by N milliseconds - debounceValidation: 0, // default: 0 (uses queueMicrotask) - - // Keep action errors until next action (not cleared on data change) - persistActionError: false // default: false - } -);`,title:`Options Overview`});var i=L(r,2);J(i,{code:`// With resetDirtyOnAction: true (default) -await execute(); -// isDirty is now false - -// With resetDirtyOnAction: false -await execute(); -// isDirty remains true`,title:`resetDirtyOnAction`});var a=L(i,2);J(a,{code:`// With debounceValidation: 0 (default) -// Validation runs via queueMicrotask after each change - -// With debounceValidation: 500 -// Validation runs 500ms after the last change -// Useful for expensive validators or rapid typing`,title:`debounceValidation`}),J(L(a,2),{code:`// With persistActionError: false (default) -data.name = 'new value'; -// actionError is cleared immediately - -// With persistActionError: true -data.name = 'new value'; -// actionError remains until next execute() call`,title:`persistActionError`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var ko=U(`Saving...`),Ao=U(``),jo=U(`
            Auto-save triggers 2 seconds after the last change. Analytics events buffer and flush at 10 events or every 10 - seconds.
            `,1),Mo=U(`

            No saves yet — edit the form and wait 2s

            `),No=U(`
          • save
          • `),Po=U(`
              `),Fo=U(`

              No flushes yet

              `),Io=U(`
            • flush
            • `),Lo=U(`
              Autosave Log
              Analytics Buffer
              Buffered:
              Batch size: 10
              Flush interval: 10s
              Tracked: change, action, snapshot
              Flush History
              `),Ro=U(` `,1);function zo(e,t){We(t,!0);let n=()=>A(_,`$hasErrors`,o),r=()=>A(v,`$isDirty`,o),i=()=>A(g,`$errors`,o),a=()=>A(y,`$actionInProgress`,o),[o,s]=ft(),c=N(fn([])),l=N(fn([])),u=N(0),d=ki({save:async e=>{await new Promise(e=>setTimeout(e,300));let t=new Date().toISOString().slice(11,23);P(c,[...V(c),{id:X(),timestamp:t,data:`${e.title} (${e.category})`}],!0)},idle:2e3,onlyWhenDirty:!0}),f=Oi({onFlush:e=>{let t=new Date().toISOString().slice(11,23),n={};for(let t of e)n[t.type]=(n[t.type]??0)+1;let r=Object.entries(n).map(([e,t])=>`${e}:${t}`).join(`, `);P(l,[...V(l),{id:X(),timestamp:t,eventCount:e.length,types:r}],!0)},batchSize:10,flushInterval:1e4,include:[`change`,`action`,`snapshot`]}),{data:p,execute:m,reset:h,state:{errors:g,hasErrors:_,isDirty:v,actionInProgress:y}}=ia({title:``,category:`general`,notes:``},{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(2).maxLength(100).getError(),category:``,notes:q(e.notes).maxLength(500).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${t.charAt(0).toUpperCase()+t.slice(1)}`)},action:async()=>{await new Promise(e=>setTimeout(e,500))}},{plugins:[d,f]}),b=()=>{p.title=`Article ${X()}`,p.category=`tech`,p.notes=`Some interesting notes about the topic that should pass validation.`};Mn(()=>{let e=setInterval(()=>{P(u,f.eventCount(),!0)},500);return()=>clearInterval(e)}),ba(e,{description:`Auto-save with idle timer (autosavePlugin) and batched event analytics (analyticsPlugin).`,title:`Plugin: Autosave & Analytics`,main:e=>{var t=jo(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),g=F(l);k(l);var _=L(l,2),v=F(_);k(_);var y=L(_,2),b=e=>{W(e,ko())},x=j(()=>d.isSaving());K(y,e=>{V(x)&&e(b)}),k(s);var S=L(s,4),C=F(S);{let e=j(()=>i()?.title);Y(C,{id:`title`,get error(){return V(e)},label:`Title`,placeholder:`Enter article title`,get value(){return p.title},set value(e){p.title=e}})}var w=L(C,2),T=L(F(w),2),E=F(T);E.value=E.__value=`general`;var ee=L(E);ee.value=ee.__value=`tech`;var te=L(ee);te.value=te.__value=`science`;var ne=L(te);ne.value=ne.__value=`culture`,k(T),k(w);var re=L(w,2);{let e=j(()=>i()?.notes);Qa(re,{id:`notes`,get error(){return V(e)},label:`Notes`,placeholder:`Write your notes (max 500 chars)`,rows:4,get value(){return p.notes},set value(e){p.notes=e}})}k(S);var ie=L(S,2),ae=F(ie),oe=F(ae,!0);k(ae);var se=L(ae,2),ce=L(se,2),le=L(ce,2),ue=e=>{var t=Ao();H(`click`,t,h),W(e,t)};K(le,e=>{r()&&e(ue)}),k(ie),R(()=>{G(g,`${V(c).length??``} Save${V(c).length===1?``:`s`}`),G(v,`${V(u)??``} Buffered Event${V(u)===1?``:`s`}`),ae.disabled=n()||a(),G(oe,a()?`Submitting...`:`Submit`)}),di(T,()=>p.category,e=>p.category=e),H(`click`,ae,()=>m()),H(`click`,se,()=>d.saveNow()),H(`click`,ce,()=>f.flush()),W(e,t)},sidebar:e=>{var t=Lo(),a=F(t);fa(a,{get data(){return p},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:b,width:`xl:w-96`});var o=L(a,2),s=L(F(o),2),d=e=>{W(e,Mo())},f=e=>{var t=Po();$r(t,21,()=>V(c),e=>e.id,(e,t)=>{var n=No(),r=L(F(n),2),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{G(i,V(t).data),G(o,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(s,e=>{V(c).length===0?e(d):e(f,-1)}),k(o);var m=L(o,2),h=L(F(m),2),g=F(h),_=L(F(g));k(g),Pe(6),k(h),k(m);var v=L(m,2),y=L(F(v),2),x=e=>{W(e,Fo())},S=e=>{var t=Po();$r(t,21,()=>V(l),e=>e.id,(e,t)=>{var n=Io(),r=L(F(n),2),i=F(r);k(r);var a=L(r,2),o=F(a,!0);k(a),k(n),R(()=>{G(i,`${V(t).eventCount??``} event${V(t).eventCount===1?``:`s`} (${V(t).types??``})`),G(o,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(y,e=>{V(l).length===0?e(x):e(S,-1)}),k(v),k(t),R(()=>G(_,` ${V(u)??``} event${V(u)===1?``:`s`}`)),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Ro(),r=I(n);J(r,{code:`import { createSvState, autosavePlugin, analyticsPlugin } from 'svstate'; - -const autosave = autosavePlugin({ - save: async (data) => { - await fetch('/api/save', { - method: 'POST', - body: JSON.stringify(data) - }); - }, - idle: 2000, // Save 2s after last change - onlyWhenDirty: true // Skip save if nothing changed -}); - -const analytics = analyticsPlugin({ - onFlush: (events) => { - sendToAnalytics(events); // Your analytics endpoint - }, - batchSize: 10, // Flush after 10 events - flushInterval: 10000, // Or every 10 seconds - include: ['change', 'action', 'snapshot'] // Filter event types -}); - -const { data, execute, state } = createSvState( - initialData, actuators, - { plugins: [autosave, analytics] } -);`,title:`autosavePlugin + analyticsPlugin Setup`}),J(L(r,2),{code:`// autosavePlugin API -autosave.saveNow(); // Force immediate save -autosave.isSaving(); // Check if currently saving - -// analyticsPlugin API -analytics.flush(); // Force flush buffered events -analytics.eventCount(); // Number of buffered events`,title:`Plugin API`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var Bo=U(``),Vo=U(`
              `,1),Ho=U(`

              No events yet — interact with the form

              `),Uo=U(`
            • `),Wo=U(`
                `),Go=U(`
                Event Log
                `),Ko=U(` `,1);function qo(e,t){We(t,!0);let n=()=>A(g,`$hasErrors`,s),r=()=>A(_,`$isDirty`,s),i=()=>A(h,`$errors`,s),a=()=>A(y,`$actionInProgress`,s),o=()=>A(v,`$snapshots`,s),[s,c]=ft(),l=N(fn([])),u=(e,t)=>{let n=new Date().toISOString().slice(11,23);P(l,[...V(l),{id:X(),type:e,message:t,timestamp:n}],!0)},{data:d,execute:f,reset:p,rollback:m,state:{errors:h,hasErrors:g,isDirty:_,snapshots:v,actionInProgress:y}}=ia({name:``,email:``,message:``},{validator:e=>({name:q(e.name).prepare(`trim`).required().minLength(2).maxLength(50).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),message:q(e.message).prepare(`trim`).required().minLength(5).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${t.charAt(0).toUpperCase()+t.slice(1)}`)},action:async()=>{await new Promise(e=>setTimeout(e,500))}},{plugins:[ji({name:`demo-devtools`,enabled:!0,logValidation:!0}),{name:`log-mirror`,onChange(e){u(`change`,`${e.property}: "${e.oldValue}" → "${e.currentValue}"`)},onValidation(e){u(`validation`,e?`Has errors`:`Valid`)},onSnapshot(e){u(`snapshot`,e.title)},onAction(e){e.phase===`before`?u(`action`,`Action started`):u(`action`,e.error?`Action failed: ${e.error.message}`:`Action completed`)},onRollback(e){u(`rollback`,`Rolled back to: ${e.title}`)},onReset(){u(`reset`,`State reset to initial`)}}]}),b=()=>{d.name=`John Doe ${X()}`,d.email=`john.${X()}@example.com`,d.message=`Hello, this is a test message for the devtools demo.`},x=()=>{P(l,[],!0)},S={change:`bg-blue-100 text-blue-800`,validation:`bg-yellow-100 text-yellow-800`,snapshot:`bg-purple-100 text-purple-800`,action:`bg-green-100 text-green-800`,rollback:`bg-amber-100 text-amber-800`,reset:`bg-red-100 text-red-800`};ba(e,{description:`Shows devtoolsPlugin console logging and a custom log-mirror plugin that captures all events in-page.`,title:`Plugin: Devtools`,main:e=>{var t=Vo(),s=I(t);Ta(s,{get hasErrors(){return n()},get isDirty(){return r()}});var c=L(s,2),l=F(c);{let e=j(()=>i()?.name);Y(l,{id:`name`,get error(){return V(e)},label:`Name`,placeholder:`Enter your name`,get value(){return d.name},set value(e){d.name=e}})}var u=L(l,2);{let e=j(()=>i()?.email);Y(u,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter your email`,type:`email`,get value(){return d.email},set value(e){d.email=e}})}var h=L(u,2);{let e=j(()=>i()?.message);Qa(h,{id:`message`,get error(){return V(e)},label:`Message`,placeholder:`Enter a message (min 5 chars)`,required:!0,get value(){return d.message},set value(e){d.message=e}})}k(c);var g=L(c,2),_=F(g),v=F(_,!0);k(_);var y=L(_,2),b=L(y,2),x=e=>{var t=Bo();H(`click`,t,p),W(e,t)};K(b,e=>{r()&&e(x)}),k(g),R(()=>{_.disabled=n()||a(),G(v,a()?`Submitting...`:`Submit`),y.disabled=o().length<=1}),H(`click`,_,()=>f()),H(`click`,y,()=>m()),W(e,t)},sidebar:e=>{var t=Go(),a=F(t);fa(a,{get data(){return d},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:b,width:`xl:w-96`});var o=L(a,2),s=F(o),c=L(F(s),2);k(s);var u=L(s,2),f=e=>{W(e,Ho())},p=e=>{var t=Wo();$r(t,21,()=>V(l),e=>e.id,(e,t)=>{var n=Uo(),r=F(n),i=F(r,!0);k(r);var a=L(r,2),o=F(a,!0);k(a);var s=L(a,2),c=F(s,!0);k(s),k(n),R(()=>{ci(r,1,`mt-0.5 flex-shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium ${S[V(t).type]??``}`),G(i,V(t).type),G(o,V(t).message),G(c,V(t).timestamp)}),W(e,n)}),k(t),W(e,t)};K(u,e=>{V(l).length===0?e(f):e(p,-1)}),k(o),k(t),H(`click`,c,x),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Ko(),r=I(n);J(r,{code:`import { createSvState, devtoolsPlugin } from 'svstate'; - -const { data, execute, reset, rollback, state } = createSvState( - { name: '', email: '', message: '' }, - { - validator: (source) => ({ /* ... */ }), - effect: ({ snapshot, property }) => { - snapshot(\`Changed \${property}\`); - }, - action: async () => { await saveToServer(); } - }, - { - plugins: [ - devtoolsPlugin({ - name: 'my-form', // Label in console - enabled: true, // Auto-disabled in production - collapsed: true, // Console groups collapsed - logValidation: true // Also log validation events - }) - ] - } -);`,title:`devtoolsPlugin Setup`}),J(L(r,2),{code:`// devtoolsPlugin logs these events to the console: -// - onChange: property changes with old/new values -// - onValidation: validation results (if logValidation: true) -// - onSnapshot: snapshot creation with title -// - onAction: action start/complete/error -// - onRollback: rollback with target snapshot title -// - onReset: state reset events`,title:`What Gets Logged`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),c()}Nr([`click`]);var Jo=U(`Restored from storage`),Yo=U(`Fresh state`),Xo=U(``),Zo=U(`
                Try: Reload the page to see persistence. Open this page in another tab to see cross-tab sync.
                `,1),Qo=U(`
                Persistence Info
                Restored:
                Key: svstate-demo-settings
                Excluded: notifications
                Raw localStorage
                 
                Sync Info
                Channel: svstate-demo-sync
                Throttle: 200ms
                Merge: overwrite (default)
                `),$o=U(` `,1);function es(e,t){We(t,!0);let n=()=>A(d,`$hasErrors`,a),r=()=>A(f,`$isDirty`,a),i=()=>A(u,`$errors`,a),[a,o]=ft(),s=Bi({key:`svstate-demo-settings`,throttle:300,exclude:[`notifications`]}),{data:c,reset:l,state:{errors:u,hasErrors:d,isDirty:f}}=ia({username:``,theme:`light`,fontSize:14,notifications:!0},{validator:e=>({username:q(e.username).prepare(`trim`).required().minLength(2).maxLength(30).getError(),theme:``,fontSize:``,notifications:``})},{plugins:[s,Ki({key:`svstate-demo-sync`,throttle:200})]}),p=s.isRestored(),m=()=>{s.clearPersistedState(),l()},h=()=>{c.username=`demo_user`,c.theme=`dark`,c.fontSize=16,c.notifications=!1},g=N(``);Mn(()=>{c.username,c.theme,c.fontSize,c.notifications;let e=setTimeout(()=>{P(g,localStorage.getItem(`svstate-demo-settings`)??`(empty)`,!0)},500);return()=>clearTimeout(e)}),ba(e,{description:`Settings form with persistPlugin (localStorage) and syncPlugin (cross-tab sync via BroadcastChannel).`,title:`Plugin: Persist & Sync`,main:e=>{var t=Zo(),a=I(t);Ta(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),s=F(o),u=e=>{W(e,Jo())},d=e=>{W(e,Yo())};K(s,e=>{p?e(u):e(d,-1)}),k(o);var f=L(o,4),h=F(f);{let e=j(()=>i()?.username);Y(h,{id:`username`,get error(){return V(e)},label:`Username`,placeholder:`Enter username`,get value(){return c.username},set value(e){c.username=e}})}var g=L(h,2),_=L(F(g),2),v=F(_);v.value=v.__value=`light`;var y=L(v);y.value=y.__value=`dark`;var b=L(y);b.value=b.__value=`system`,k(_),k(g);var x=L(g,2);Y(x,{id:`fontSize`,label:`Font Size`,max:32,min:8,step:1,type:`number`,get value(){return c.fontSize},set value(e){c.fontSize=e}});var S=L(x,2),C=F(S),w=F(C);gi(w),Pe(4),k(C),k(S),k(f);var T=L(f,2),E=F(T),ee=L(E,2),te=e=>{var t=Xo();H(`click`,t,l),W(e,t)};K(ee,e=>{r()&&e(te)}),k(T),di(_,()=>c.theme,e=>c.theme=e),Si(w,()=>c.notifications,e=>c.notifications=e),H(`click`,E,m),W(e,t)},sidebar:e=>{var t=Qo(),a=F(t);fa(a,{get data(){return c},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:h,width:`xl:w-96`});var o=L(a,2),s=L(F(o),2),l=F(s),u=L(F(l));k(l),Pe(4),k(s),k(o);var d=L(o,2),f=L(F(d),2),m=F(f,!0);k(f),k(d),Pe(2),k(t),R(()=>{G(u,` ${p??``}`),G(m,V(g))}),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=$o(),r=I(n);J(r,{code:`import { createSvState, persistPlugin, syncPlugin } from 'svstate'; - -const persist = persistPlugin({ - key: 'svstate-demo-settings', - throttle: 300, - exclude: ['notifications'] // Don't persist this field -}); - -const sync = syncPlugin({ - key: 'svstate-demo-sync', - throttle: 200 -}); - -const { data, reset, state } = createSvState( - { username: '', theme: 'light', fontSize: 14, notifications: true }, - { validator: (source) => ({ /* ... */ }) }, - { plugins: [persist, sync] } -);`,title:`persistPlugin + syncPlugin Setup`}),J(L(r,2),{code:`// persistPlugin API -persist.isRestored(); // true if data was loaded from storage -persist.clearPersistedState(); // Remove stored data - -// syncPlugin: automatic cross-tab sync via BroadcastChannel -// Changes in one tab appear in all other tabs with same key`,title:`Plugin API`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]);var ts=U(``),ns=U(`
                Max: 10
                `,1),rs=U(`

                No snapshots yet

                `),is=U(`
              • `),as=U(`
                  `),os=U(`

                  No redo entries — undo something first

                  `),ss=U(`
                • `),cs=U(`
                  Snapshot History
                  Redo Stack
                  `),ls=U(` `,1);function us(e,t){We(t,!0);let n=()=>A(m,`$hasErrors`,o),r=()=>A(h,`$isDirty`,o),i=()=>A(g,`$snapshots`,o),a=()=>A(p,`$errors`,o),[o,s]=ft(),c=qi(),l=e=>e.charAt(0).toUpperCase()+e.slice(1).replaceAll(/([A-Z])/g,` $1`),{data:u,reset:d,rollback:f,state:{errors:p,hasErrors:m,isDirty:h,snapshots:g}}=ia({title:`My Document`,content:``,priority:`medium`},{validator:e=>({title:q(e.title).prepare(`trim`).required().minLength(2).maxLength(100).getError(),content:q(e.content).prepare(`trim`).required().minLength(10).getError(),priority:``}),effect:({snapshot:e,property:t})=>{e(`Changed ${l(t)}`)}},{maxSnapshots:10,plugins:[c]}),_=()=>{u.title=`Project Report ${X()}`,u.content=`This is a detailed document with enough content to pass validation requirements.`,u.priority=`high`},v=N(fn(lt(c.redoStack)));Mn(()=>c.redoStack.subscribe(e=>{P(v,e,!0)})),ba(e,{description:`Combines the built-in snapshot/rollback system with the undoRedoPlugin for full undo/redo support.`,title:`Plugin: Undo/Redo`,main:e=>{var t=ns(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),l=F(s),p=F(l);k(l);var m=L(l,2),h=F(m);k(m),Pe(2),k(s);var g=L(s,2),_=F(g);{let e=j(()=>a()?.title);Y(_,{id:`title`,get error(){return V(e)},label:`Title`,placeholder:`Enter document title`,get value(){return u.title},set value(e){u.title=e}})}var y=L(_,2);{let e=j(()=>a()?.content);Qa(y,{id:`content`,get error(){return V(e)},label:`Content`,placeholder:`Write your document content (min 10 chars)`,required:!0,rows:4,get value(){return u.content},set value(e){u.content=e}})}var b=L(y,2),x=L(F(b),2),S=F(x);S.value=S.__value=`low`;var C=L(S);C.value=C.__value=`medium`;var w=L(C);w.value=w.__value=`high`;var T=L(w);T.value=T.__value=`critical`,k(x),k(b),k(g);var E=L(g,2),ee=F(E),te=L(ee,2),ne=L(te,2),re=e=>{var t=ts();H(`click`,t,d),W(e,t)};K(ne,e=>{r()&&e(re)}),k(E),R(()=>{G(p,`${i().length??``} Snapshot${i().length===1?``:`s`}`),G(h,`${V(v).length??``} Redo${V(v).length===1?``:`s`}`),ee.disabled=i().length<=1,te.disabled=V(v).length===0}),di(x,()=>u.priority,e=>u.priority=e),H(`click`,ee,()=>f()),H(`click`,te,()=>c.redo()),W(e,t)},sidebar:e=>{var t=cs(),o=F(t);fa(o,{get data(){return u},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:_,width:`xl:w-96`});var s=L(o,2),c=L(F(s),2),l=e=>{W(e,rs())},d=e=>{var t=as();$r(t,5,i,Yr,(e,t,n)=>{var r=is(),i=F(r);i.textContent=n+1;var a=L(i,2),o=F(a,!0);k(a),k(r),R(()=>G(o,V(t).title)),W(e,r)}),k(t),W(e,t)};K(c,e=>{i().length===0?e(l):e(d,-1)}),k(s);var f=L(s,2),p=L(F(f),2),m=e=>{W(e,os())},h=e=>{var t=as();$r(t,21,()=>V(v),Yr,(e,t,n)=>{var r=ss(),i=F(r);i.textContent=n+1;var a=L(i,2),o=F(a,!0);k(a),k(r),R(()=>G(o,V(t).title)),W(e,r)}),k(t),W(e,t)};K(p,e=>{V(v).length===0?e(m):e(h,-1)}),k(f),k(t),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=ls(),r=I(n);J(r,{code:`import { createSvState, undoRedoPlugin } from 'svstate'; - -const undoRedo = undoRedoPlugin(); - -const { data, reset, rollback, state } = createSvState( - { title: 'My Document', content: '', priority: 'medium' }, - { - validator: (source) => ({ /* ... */ }), - effect: ({ snapshot, property }) => { - snapshot(\`Changed \${property}\`); - } - }, - { maxSnapshots: 10, plugins: [undoRedo] } -);`,title:`Setup with undoRedoPlugin`}),J(L(r,2),{code:`// Undo (built-in rollback) -rollback(); - -// Redo (from undoRedoPlugin) -undoRedo.redo(); - -// Check if redo is available -undoRedo.canRedo(); // boolean - -// Subscribe to redo stack -undoRedo.redoStack; // Readable`,title:`Undo/Redo Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var ds=U(`
                  `),fs=U(`
                  `,1),ps=U(` `,1);function ms(e,t){We(t,!0);let n=()=>A(u,`$hasErrors`,a),r=()=>A(d,`$isDirty`,a),i=()=>A(l,`$errors`,a),[a,o]=ft(),{data:s,reset:c,state:{errors:l,hasErrors:u,isDirty:d}}=ia({firstName:`Alice`,lastName:`Smith`,email:`alice.smith@example.com`,phone:``,bio:``},{validator:e=>({firstName:q(e.firstName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),lastName:q(e.lastName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),phone:q(e.phone).prepare(`trim`).required().minLength(10).getError(),bio:q(e.bio).maxLength(200).getError()})}),f=()=>{s.firstName=`John`,s.lastName=`Doe${X()}`,s.email=`john.doe.${X()}@example.com`,s.phone=`555-${X().slice(0,3)}-${X().slice(0,4)}`,s.bio=`Software developer with a passion for clean code.`};ba(e,{description:`Demonstrates the reset() function to restore state back to its initial values.`,title:`Reset Demo`,main:e=>{var t=fs(),a=I(t);Ta(a,{get hasErrors(){return n()},get isDirty(){return r()}});var o=L(a,2),l=F(o);{let e=j(()=>i()?.firstName);Y(l,{id:`firstName`,get error(){return V(e)},label:`First Name`,placeholder:`Enter first name`,get value(){return s.firstName},set value(e){s.firstName=e}})}var u=L(l,2);{let e=j(()=>i()?.lastName);Y(u,{id:`lastName`,get error(){return V(e)},label:`Last Name`,placeholder:`Enter last name`,get value(){return s.lastName},set value(e){s.lastName=e}})}var d=L(u,2);{let e=j(()=>i()?.email);Y(d,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return s.email},set value(e){s.email=e}})}var f=L(d,2);{let e=j(()=>i()?.phone);Y(f,{id:`phone`,get error(){return V(e)},label:`Phone`,placeholder:`555-123-4567`,get value(){return s.phone},set value(e){s.phone=e}})}var p=L(f,2);{let e=j(()=>i()?.bio);Qa(p,{id:`bio`,get error(){return V(e)},label:`Bio`,placeholder:`Tell us about yourself`,required:!1,get value(){return s.bio},set value(e){s.bio=e}})}k(o);var m=L(o,2),h=e=>{var t=ds(),n=F(t);k(t),H(`click`,n,c),W(e,t)};K(m,e=>{r()&&e(h)}),W(e,t)},sidebar:e=>{fa(e,{get data(){return s},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},onFill:f})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=ps(),r=I(n);J(r,{code:`const sourceData = { - firstName: 'Alice', - lastName: 'Smith', - email: 'alice.smith@example.com', - phone: '', - bio: '' -}; - -const { data, reset, state: { errors, hasErrors, isDirty } } = createSvState(sourceData, { - validator: (source) => ({ - firstName: stringValidator(source.firstName).prepare('trim').required().minLength(2).maxLength(30).getError(), - lastName: stringValidator(source.lastName).prepare('trim').required().minLength(2).maxLength(30).getError(), - email: stringValidator(source.email).prepare('trim').required().email().getError(), - phone: stringValidator(source.phone).prepare('trim').required().minLength(10).getError(), - bio: stringValidator(source.bio).maxLength(200).getError() - }) -});`,title:`State Setup with Reset`}),J(L(r,2),{code:` -{#if $isDirty} - -{/if} - - -`,title:`Conditional Reset Button`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),o()}Nr([`click`]);var hs=U(``),gs=U(`
                  Max: 5
                  `,1),_s=U(`

                  No snapshots yet

                  `),vs=U(`
                • `),ys=U(`
                    `),bs=U(`
                    Snapshot History
                    `),xs=U(` `,1);function Ss(e,t){We(t,!0);let n=()=>A(h,`$hasErrors`,o),r=()=>A(g,`$isDirty`,o),i=()=>A(_,`$snapshots`,o),a=()=>A(m,`$errors`,o),[o,s]=ft(),c={firstName:`Alice`,lastName:`Smith`,email:`alice.smith@example.com`,phone:``,bio:``},l=e=>e.charAt(0).toUpperCase()+e.slice(1).replaceAll(/([A-Z])/g,` $1`),{data:u,reset:d,rollback:f,rollbackTo:p,state:{errors:m,hasErrors:h,isDirty:g,snapshots:_}}=ia(c,{validator:e=>({firstName:q(e.firstName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),lastName:q(e.lastName).prepare(`trim`).required().minLength(2).maxLength(30).getError(),email:q(e.email).prepare(`trim`).required().email().getError(),phone:q(e.phone).prepare(`trim`).required().minLength(10).getError(),bio:q(e.bio).maxLength(200).getError()}),effect:({snapshot:e,property:t})=>{e(`Changed ${l(t)}`)}},{maxSnapshots:5}),v=()=>{u.firstName=`John`,u.lastName=`Doe${X()}`,u.email=`john.doe.${X()}@example.com`,u.phone=`555-${X().slice(0,3)}-${X().slice(0,4)}`,u.bio=`Software developer with a passion for clean code.`};ba(e,{description:`Shows snapshot creation for undo functionality with rollback(), rollbackTo(), and maxSnapshots support.`,title:`Snapshot & Rollback Demo`,main:e=>{var t=gs(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),c=F(s),l=F(c);k(c),Pe(2),k(s);var m=L(s,2),h=F(m);{let e=j(()=>a()?.firstName);Y(h,{id:`firstName`,get error(){return V(e)},label:`First Name`,placeholder:`Enter first name`,get value(){return u.firstName},set value(e){u.firstName=e}})}var g=L(h,2);{let e=j(()=>a()?.lastName);Y(g,{id:`lastName`,get error(){return V(e)},label:`Last Name`,placeholder:`Enter last name`,get value(){return u.lastName},set value(e){u.lastName=e}})}var _=L(g,2);{let e=j(()=>a()?.email);Y(_,{id:`email`,get error(){return V(e)},label:`Email`,placeholder:`Enter email`,type:`email`,get value(){return u.email},set value(e){u.email=e}})}var v=L(_,2);{let e=j(()=>a()?.phone);Y(v,{id:`phone`,get error(){return V(e)},label:`Phone`,placeholder:`555-123-4567`,get value(){return u.phone},set value(e){u.phone=e}})}var y=L(v,2);{let e=j(()=>a()?.bio);Qa(y,{id:`bio`,get error(){return V(e)},label:`Bio`,placeholder:`Tell us about yourself`,required:!1,get value(){return u.bio},set value(e){u.bio=e}})}k(m);var b=L(m,2),x=F(b),S=L(x,2),C=L(S,2),w=e=>{var t=hs();H(`click`,t,d),W(e,t)};K(C,e=>{r()&&e(w)}),k(b),R(()=>{G(l,`${i().length??``} Snapshot${i().length===1?``:`s`}`),x.disabled=i().length<=1,S.disabled=i().length<=1}),H(`click`,x,()=>f()),H(`click`,S,()=>p(`Initial`)),W(e,t)},sidebar:e=>{var t=bs(),o=F(t);fa(o,{get data(){return u},get errors(){return a()},get hasErrors(){return n()},get isDirty(){return r()},onFill:v,width:`xl:w-96`});var s=L(o,2),c=L(F(s),2),l=e=>{W(e,_s())},d=e=>{var t=ys();$r(t,5,i,Yr,(e,t,n)=>{var r=vs(),a=F(r);a.textContent=n+1;var o=L(a,2),s=F(o,!0);k(o),k(r),R(()=>{o.disabled=i().length<=1,G(s,V(t).title)}),H(`click`,o,()=>p(V(t).title)),W(e,r)}),k(t),W(e,t)};K(c,e=>{i().length===0?e(l):e(d,-1)}),k(s),k(t),W(e,t)},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=xs(),r=I(n);J(r,{code:`const sourceData = { - firstName: 'Alice', lastName: 'Smith', email: 'alice.smith@example.com', phone: '', bio: '' -}; - -const { data, reset, rollback, rollbackTo, state: { errors, hasErrors, isDirty, snapshots } } = - createSvState(sourceData, { - validator: (source) => ({ /* validation rules */ }), - effect: ({ snapshot, property }) => { - snapshot(\`Changed \${formatFieldName(property)}\`); - } - }, { maxSnapshots: 5 });`,title:`State Setup with Snapshots & maxSnapshots`});var i=L(r,2);J(i,{code:`// Effect callback creates snapshots on each change -effect: ({ snapshot, property }) => { - snapshot(\`Changed \${property}\`); // Creates undo point - // If same title, replaces last snapshot (debouncing) - // Use snapshot(title, false) to always create new -}`,title:`Effect with Snapshot Creation`}),J(L(i,2),{code:`// Undo last change -rollback(); - -// Undo 3 changes at once -rollback(3); - -// Roll back to a named snapshot (returns true if found) -rollbackTo('Changed First Name'); - -// Roll back to initial state -rollbackTo('Initial'); - -// Reset to initial state (clears all snapshots) -reset();`,title:`Rollback, RollbackTo & Reset Usage`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}Nr([`click`]);var Cs;function Z(e,t,n){function r(n,r){if(n._zod||Object.defineProperty(n,"_zod",{value:{def:r,constr:o,traits:new Set},enumerable:!1}),n._zod.traits.has(e))return;n._zod.traits.add(e),t(n,r);let i=o.prototype,a=Object.keys(i);for(let e=0;en?.Parent&&t instanceof n.Parent?!0:t?._zod?.traits?.has(e)}),Object.defineProperty(o,"name",{value:e}),o}var ws=class extends Error{constructor(){super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`)}},Ts=class extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name=`ZodEncodeError`}};(Cs=globalThis).__zod_globalConfig??(Cs.__zod_globalConfig={});var Es=globalThis.__zod_globalConfig;function Ds(e){return e&&Object.assign(Es,e),Es}function Os(e){let t=Object.values(e).filter(e=>typeof e==`number`);return Object.entries(e).filter(([e,n])=>t.indexOf(+e)===-1).map(([e,t])=>t)}function ks(e,t){return typeof t==`bigint`?t.toString():t}function As(e){return{get value(){{let t=e();return Object.defineProperty(this,"value",{value:t}),t}}}}function js(e){return e==null}function Ms(e){let t=+!!e.startsWith(`^`),n=e.endsWith(`$`)?e.length-1:e.length;return e.slice(t,n)}function Ns(e,t){let n=e/t,r=Math.round(n),i=2**-52*Math.max(Math.abs(n),1);return Math.abs(n-r){};function Bs(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var Vs=As(()=>{if(Es.jitless||typeof navigator<`u`&&navigator?.userAgent?.includes(`Cloudflare`))return!1;try{return Function(``),!0}catch{return!1}});function Hs(e){if(Bs(e)===!1)return!1;let t=e.constructor;if(t===void 0||typeof t!=`function`)return!0;let n=t.prototype;return Bs(n)!==!1&&Object.prototype.hasOwnProperty.call(n,`isPrototypeOf`)!==!1}function Us(e){return Hs(e)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e}var Ws=new Set([`string`,`number`,`symbol`]);function Gs(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Ks(e,t,n){let r=new e._zod.constr(t??e._zod.def);return(!t||n?.parent)&&(r._zod.parent=e),r}function $(e){let t=e;if(!t)return{};if(typeof t==`string`)return{error:()=>t};if(t?.message!==void 0){if(t?.error!==void 0)throw Error("Cannot specify both `message` and `error` params");t.error=t.message}return delete t.message,typeof t.error==`string`?{...t,error:()=>t.error}:t}function qs(e){return Object.keys(e).filter(t=>e[t]._zod.optin===`optional`&&e[t]._zod.optout===`optional`)}var Js={safeint:[-(2**53-1),2**53-1],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function Ys(e,t){let n=e._zod.def,r=n.checks;if(r&&r.length>0)throw Error(`.pick() cannot be used on object schemas containing refinements`);return Ks(e,Is(e._zod.def,{get shape(){let e={};for(let r in t){if(!(r in n.shape))throw Error(`Unrecognized key: "${r}"`);t[r]&&(e[r]=n.shape[r])}return Fs(this,`shape`,e),e},checks:[]}))}function Xs(e,t){let n=e._zod.def,r=n.checks;if(r&&r.length>0)throw Error(`.omit() cannot be used on object schemas containing refinements`);return Ks(e,Is(e._zod.def,{get shape(){let r={...e._zod.def.shape};for(let e in t){if(!(e in n.shape))throw Error(`Unrecognized key: "${e}"`);t[e]&&delete r[e]}return Fs(this,`shape`,r),r},checks:[]}))}function Zs(e,t){if(!Hs(t))throw Error(`Invalid input to extend: expected a plain object`);let n=e._zod.def.checks;if(n&&n.length>0){let n=e._zod.def.shape;for(let e in t)if(Object.getOwnPropertyDescriptor(n,e)!==void 0)throw Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}return Ks(e,Is(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t};return Fs(this,`shape`,n),n}}))}function Qs(e,t){if(!Hs(t))throw Error(`Invalid input to safeExtend: expected a plain object`);return Ks(e,Is(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t};return Fs(this,`shape`,n),n}}))}function $s(e,t){if(e._zod.def.checks?.length)throw Error(`.merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.`);return Ks(e,Is(e._zod.def,{get shape(){let n={...e._zod.def.shape,...t._zod.def.shape};return Fs(this,`shape`,n),n},get catchall(){return t._zod.def.catchall},checks:t._zod.def.checks??[]}))}function ec(e,t,n){let r=t._zod.def.checks;if(r&&r.length>0)throw Error(`.partial() cannot be used on object schemas containing refinements`);return Ks(t,Is(t._zod.def,{get shape(){let r=t._zod.def.shape,i={...r};if(n)for(let t in n){if(!(t in r))throw Error(`Unrecognized key: "${t}"`);n[t]&&(i[t]=e?new e({type:`optional`,innerType:r[t]}):r[t])}else for(let t in r)i[t]=e?new e({type:`optional`,innerType:r[t]}):r[t];return Fs(this,`shape`,i),i},checks:[]}))}function tc(e,t,n){return Ks(t,Is(t._zod.def,{get shape(){let r=t._zod.def.shape,i={...r};if(n)for(let t in n){if(!(t in i))throw Error(`Unrecognized key: "${t}"`);n[t]&&(i[t]=new e({type:`nonoptional`,innerType:r[t]}))}else for(let t in r)i[t]=new e({type:`nonoptional`,innerType:r[t]});return Fs(this,`shape`,i),i}}))}function nc(e,t=0){if(e.aborted===!0)return!0;for(let n=t;n{var n;return(n=t).path??(n.path=[]),t.path.unshift(e),t})}function ac(e){return typeof e==`string`?e:e?.message}function oc(e,t,n){let r=e.message?e.message:ac(e.inst?._zod.def?.error?.(e))??ac(t?.error?.(e))??ac(n.customError?.(e))??ac(n.localeError?.(e))??`Invalid input`,{inst:i,continue:a,input:o,...s}=e;return s.path??=[],s.message=r,t?.reportInput&&(s.input=o),s}function sc(e){return Array.isArray(e)?`array`:typeof e==`string`?`string`:`unknown`}function cc(...e){let[t,n,r]=e;return typeof t==`string`?{message:t,code:`custom`,input:n,inst:r}:{...t}}var lc=(e,t)=>{e.name=`$ZodError`,Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:t,enumerable:!1}),e.message=JSON.stringify(t,ks,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},uc=Z(`$ZodError`,lc),dc=Z(`$ZodError`,lc,{Parent:Error});function fc(e,t=e=>e.message){let n={},r=[];for(let i of e.issues)i.path.length>0?(n[i.path[0]]=n[i.path[0]]||[],n[i.path[0]].push(t(i))):r.push(t(i));return{formErrors:r,fieldErrors:n}}function pc(e,t=e=>e.message){let n={_errors:[]},r=(e,i=[])=>{for(let a of e.issues)if(a.code===`invalid_union`&&a.errors.length)a.errors.map(e=>r({issues:e},[...i,...a.path]));else if(a.code===`invalid_key`)r({issues:a.issues},[...i,...a.path]);else if(a.code===`invalid_element`)r({issues:a.issues},[...i,...a.path]);else{let e=[...i,...a.path];if(e.length===0)n._errors.push(t(a));else{let r=n,i=0;for(;i(t,n,r,i)=>{let a=r?{...r,async:!1}:{async:!1},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise)throw new ws;if(o.issues.length){let t=new((i?.Err)??e)(o.issues.map(e=>oc(e,a,Ds())));throw zs(t,i?.callee),t}return o.value},hc=e=>async(t,n,r,i)=>{let a=r?{...r,async:!0}:{async:!0},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise&&(o=await o),o.issues.length){let t=new((i?.Err)??e)(o.issues.map(e=>oc(e,a,Ds())));throw zs(t,i?.callee),t}return o.value},gc=e=>(t,n,r)=>{let i=r?{...r,async:!1}:{async:!1},a=t._zod.run({value:n,issues:[]},i);if(a instanceof Promise)throw new ws;return a.issues.length?{success:!1,error:new(e??uc)(a.issues.map(e=>oc(e,i,Ds())))}:{success:!0,data:a.value}},_c=gc(dc),vc=e=>async(t,n,r)=>{let i=r?{...r,async:!0}:{async:!0},a=t._zod.run({value:n,issues:[]},i);return a instanceof Promise&&(a=await a),a.issues.length?{success:!1,error:new e(a.issues.map(e=>oc(e,i,Ds())))}:{success:!0,data:a.value}},yc=vc(dc),bc=e=>(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return mc(e)(t,n,i)},xc=e=>(t,n,r)=>mc(e)(t,n,r),Sc=e=>async(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return hc(e)(t,n,i)},Cc=e=>async(t,n,r)=>hc(e)(t,n,r),wc=e=>(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return gc(e)(t,n,i)},Tc=e=>(t,n,r)=>gc(e)(t,n,r),Ec=e=>async(t,n,r)=>{let i=r?{...r,direction:`backward`}:{direction:`backward`};return vc(e)(t,n,i)},Dc=e=>async(t,n,r)=>vc(e)(t,n,r),Oc=/^[cC][0-9a-z]{6,}$/,kc=/^[0-9a-z]+$/,Ac=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,jc=/^[0-9a-vA-V]{20}$/,Mc=/^[A-Za-z0-9]{27}$/,Nc=/^[a-zA-Z0-9_-]{21}$/,Pc=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,Fc=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,Ic=e=>e?RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,Lc=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,Rc=`^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;function zc(){return new RegExp(Rc,`u`)}var Bc=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,Vc=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,Hc=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,Uc=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,Wc=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,Gc=/^[A-Za-z0-9_-]*$/,Kc=/^https?$/,qc=/^\+[1-9]\d{6,14}$/,Jc=`(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`,Yc=RegExp(`^${Jc}$`);function Xc(e){let t=`(?:[01]\\d|2[0-3]):[0-5]\\d`;return typeof e.precision==`number`?e.precision===-1?`${t}`:e.precision===0?`${t}:[0-5]\\d`:`${t}:[0-5]\\d\\.\\d{${e.precision}}`:`${t}(?::[0-5]\\d(?:\\.\\d+)?)?`}function Zc(e){return RegExp(`^${Xc(e)}$`)}function Qc(e){let t=Xc({precision:e.precision}),n=[`Z`];e.local&&n.push(``),e.offset&&n.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);let r=`${t}(?:${n.join(`|`)})`;return RegExp(`^${Jc}T(?:${r})$`)}var $c=e=>{let t=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??``}}`:`[\\s\\S]*`;return RegExp(`^${t}$`)},el=/^-?\d+$/,tl=/^-?\d+(?:\.\d+)?$/,nl=/^[^A-Z]*$/,rl=/^[^a-z]*$/,il=Z(`$ZodCheck`,(e,t)=>{var n;e._zod??={},e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),al={number:`number`,bigint:`bigint`,object:`date`},ol=Z(`$ZodCheckLessThan`,(e,t)=>{il.init(e,t);let n=al[typeof t.value];e._zod.onattach.push(e=>{let n=e._zod.bag,r=(t.inclusive?n.maximum:n.exclusiveMaximum)??1/0;t.value{(t.inclusive?r.value<=t.value:r.value{il.init(e,t);let n=al[typeof t.value];e._zod.onattach.push(e=>{let n=e._zod.bag,r=(t.inclusive?n.minimum:n.exclusiveMinimum)??-1/0;t.value>r&&(t.inclusive?n.minimum=t.value:n.exclusiveMinimum=t.value)}),e._zod.check=r=>{(t.inclusive?r.value>=t.value:r.value>t.value)||r.issues.push({origin:n,code:`too_small`,minimum:typeof t.value==`object`?t.value.getTime():t.value,input:r.value,inclusive:t.inclusive,inst:e,continue:!t.abort})}}),cl=Z(`$ZodCheckMultipleOf`,(e,t)=>{il.init(e,t),e._zod.onattach.push(e=>{var n;(n=e._zod.bag).multipleOf??(n.multipleOf=t.value)}),e._zod.check=n=>{if(typeof n.value!=typeof t.value)throw Error(`Cannot mix number and bigint in multiple_of check.`);(typeof n.value==`bigint`?n.value%t.value===BigInt(0):Ns(n.value,t.value)===0)||n.issues.push({origin:typeof n.value,code:`not_multiple_of`,divisor:t.value,input:n.value,inst:e,continue:!t.abort})}}),ll=Z(`$ZodCheckNumberFormat`,(e,t)=>{il.init(e,t),t.format=t.format||`float64`;let n=t.format?.includes(`int`),r=n?`int`:`number`,[i,a]=Js[t.format];e._zod.onattach.push(e=>{let r=e._zod.bag;r.format=t.format,r.minimum=i,r.maximum=a,n&&(r.pattern=el)}),e._zod.check=o=>{let s=o.value;if(n){if(!Number.isInteger(s)){o.issues.push({expected:r,format:t.format,code:`invalid_type`,continue:!1,input:s,inst:e});return}if(!Number.isSafeInteger(s)){s>0?o.issues.push({input:s,code:`too_big`,maximum:2**53-1,note:`Integers must be within the safe integer range.`,inst:e,origin:r,inclusive:!0,continue:!t.abort}):o.issues.push({input:s,code:`too_small`,minimum:-(2**53-1),note:`Integers must be within the safe integer range.`,inst:e,origin:r,inclusive:!0,continue:!t.abort});return}}sa&&o.issues.push({origin:`number`,input:s,code:`too_big`,maximum:a,inclusive:!0,inst:e,continue:!t.abort})}}),ul=Z(`$ZodCheckMaxLength`,(e,t)=>{var n;il.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!js(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag.maximum??1/0;t.maximum{let r=n.value;if(r.length<=t.maximum)return;let i=sc(r);n.issues.push({origin:i,code:`too_big`,maximum:t.maximum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),dl=Z(`$ZodCheckMinLength`,(e,t)=>{var n;il.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!js(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag.minimum??-1/0;t.minimum>n&&(e._zod.bag.minimum=t.minimum)}),e._zod.check=n=>{let r=n.value;if(r.length>=t.minimum)return;let i=sc(r);n.issues.push({origin:i,code:`too_small`,minimum:t.minimum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),fl=Z(`$ZodCheckLengthEquals`,(e,t)=>{var n;il.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!js(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag;n.minimum=t.length,n.maximum=t.length,n.length=t.length}),e._zod.check=n=>{let r=n.value,i=r.length;if(i===t.length)return;let a=sc(r),o=i>t.length;n.issues.push({origin:a,...o?{code:`too_big`,maximum:t.length}:{code:`too_small`,minimum:t.length},inclusive:!0,exact:!0,input:n.value,inst:e,continue:!t.abort})}}),pl=Z(`$ZodCheckStringFormat`,(e,t)=>{var n,r;il.init(e,t),e._zod.onattach.push(e=>{let n=e._zod.bag;n.format=t.format,t.pattern&&(n.patterns??=new Set,n.patterns.add(t.pattern))}),t.pattern?(n=e._zod).check??(n.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:t.format,input:n.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})}):(r=e._zod).check??(r.check=()=>{})}),ml=Z(`$ZodCheckRegex`,(e,t)=>{pl.init(e,t),e._zod.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:`regex`,input:n.value,pattern:t.pattern.toString(),inst:e,continue:!t.abort})}}),hl=Z(`$ZodCheckLowerCase`,(e,t)=>{t.pattern??=nl,pl.init(e,t)}),gl=Z(`$ZodCheckUpperCase`,(e,t)=>{t.pattern??=rl,pl.init(e,t)}),_l=Z(`$ZodCheckIncludes`,(e,t)=>{il.init(e,t);let n=Gs(t.includes),r=new RegExp(typeof t.position==`number`?`^.{${t.position}}${n}`:n);t.pattern=r,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(r)}),e._zod.check=n=>{n.value.includes(t.includes,t.position)||n.issues.push({origin:`string`,code:`invalid_format`,format:`includes`,includes:t.includes,input:n.value,inst:e,continue:!t.abort})}}),vl=Z(`$ZodCheckStartsWith`,(e,t)=>{il.init(e,t);let n=RegExp(`^${Gs(t.prefix)}.*`);t.pattern??=n,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(n)}),e._zod.check=n=>{n.value.startsWith(t.prefix)||n.issues.push({origin:`string`,code:`invalid_format`,format:`starts_with`,prefix:t.prefix,input:n.value,inst:e,continue:!t.abort})}}),yl=Z(`$ZodCheckEndsWith`,(e,t)=>{il.init(e,t);let n=RegExp(`.*${Gs(t.suffix)}$`);t.pattern??=n,e._zod.onattach.push(e=>{let t=e._zod.bag;t.patterns??=new Set,t.patterns.add(n)}),e._zod.check=n=>{n.value.endsWith(t.suffix)||n.issues.push({origin:`string`,code:`invalid_format`,format:`ends_with`,suffix:t.suffix,input:n.value,inst:e,continue:!t.abort})}}),bl=Z(`$ZodCheckOverwrite`,(e,t)=>{il.init(e,t),e._zod.check=e=>{e.value=t.tx(e.value)}}),xl=class{constructor(e=[]){this.content=[],this.indent=0,this&&(this.args=e)}indented(e){this.indent+=1,e(this),--this.indent}write(e){if(typeof e==`function`){e(this,{execution:`sync`}),e(this,{execution:`async`});return}let t=e.split(` -`).filter(e=>e),n=Math.min(...t.map(e=>e.length-e.trimStart().length)),r=t.map(e=>e.slice(n)).map(e=>` `.repeat(this.indent*2)+e);for(let e of r)this.content.push(e)}compile(){let e=Function,t=this?.args,n=[...(this?.content??[``]).map(e=>` ${e}`)];return new e(...t,n.join(` -`))}},Sl={major:4,minor:4,patch:3},Cl=Z(`$ZodType`,(e,t)=>{var n;e??={},e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=Sl;let r=[...e._zod.def.checks??[]];e._zod.traits.has(`$ZodCheck`)&&r.unshift(e);for(let t of r)for(let n of t._zod.onattach)n(e);if(r.length===0)(n=e._zod).deferred??(n.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{let t=(e,t,n)=>{let r=nc(e),i;for(let a of t){if(a._zod.def.when){if(rc(e)||!a._zod.def.when(e))continue}else if(r)continue;let t=e.issues.length,o=a._zod.check(e);if(o instanceof Promise&&n?.async===!1)throw new ws;if(i||o instanceof Promise)i=(i??Promise.resolve()).then(async()=>{await o,e.issues.length!==t&&(r||=nc(e,t))});else{if(e.issues.length===t)continue;r||=nc(e,t)}}return i?i.then(()=>e):e},n=(n,i,a)=>{if(nc(n))return n.aborted=!0,n;let o=t(i,r,a);if(o instanceof Promise){if(a.async===!1)throw new ws;return o.then(t=>e._zod.parse(t,a))}return e._zod.parse(o,a)};e._zod.run=(i,a)=>{if(a.skipChecks)return e._zod.parse(i,a);if(a.direction===`backward`){let t=e._zod.parse({value:i.value,issues:[]},{...a,skipChecks:!0});return t instanceof Promise?t.then(e=>n(e,i,a)):n(t,i,a)}let o=e._zod.parse(i,a);if(o instanceof Promise){if(a.async===!1)throw new ws;return o.then(e=>t(e,r,a))}return t(o,r,a)}}Q(e,`~standard`,()=>({validate:t=>{try{let n=_c(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch{return yc(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:`zod`,version:1}))}),wl=Z(`$ZodString`,(e,t)=>{Cl.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??$c(e._zod.bag),e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=String(n.value)}catch{}return typeof n.value==`string`||n.issues.push({expected:`string`,code:`invalid_type`,input:n.value,inst:e}),n}}),Tl=Z(`$ZodStringFormat`,(e,t)=>{pl.init(e,t),wl.init(e,t)}),El=Z(`$ZodGUID`,(e,t)=>{t.pattern??=Fc,Tl.init(e,t)}),Dl=Z(`$ZodUUID`,(e,t)=>{if(t.version){let e={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[t.version];if(e===void 0)throw Error(`Invalid UUID version: "${t.version}"`);t.pattern??=Ic(e)}else t.pattern??=Ic();Tl.init(e,t)}),Ol=Z(`$ZodEmail`,(e,t)=>{t.pattern??=Lc,Tl.init(e,t)}),kl=Z(`$ZodURL`,(e,t)=>{Tl.init(e,t),e._zod.check=n=>{try{let r=n.value.trim();if(!t.normalize&&t.protocol?.source===Kc.source&&!/^https?:\/\//i.test(r)){n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid URL format`,input:n.value,inst:e,continue:!t.abort});return}let i=new URL(r);t.hostname&&(t.hostname.lastIndex=0,t.hostname.test(i.hostname)||n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid hostname`,pattern:t.hostname.source,input:n.value,inst:e,continue:!t.abort})),t.protocol&&(t.protocol.lastIndex=0,t.protocol.test(i.protocol.endsWith(`:`)?i.protocol.slice(0,-1):i.protocol)||n.issues.push({code:`invalid_format`,format:`url`,note:`Invalid protocol`,pattern:t.protocol.source,input:n.value,inst:e,continue:!t.abort})),n.value=t.normalize?i.href:r;return}catch{n.issues.push({code:`invalid_format`,format:`url`,input:n.value,inst:e,continue:!t.abort})}}}),Al=Z(`$ZodEmoji`,(e,t)=>{t.pattern??=zc(),Tl.init(e,t)}),jl=Z(`$ZodNanoID`,(e,t)=>{t.pattern??=Nc,Tl.init(e,t)}),Ml=Z(`$ZodCUID`,(e,t)=>{t.pattern??=Oc,Tl.init(e,t)}),Nl=Z(`$ZodCUID2`,(e,t)=>{t.pattern??=kc,Tl.init(e,t)}),Pl=Z(`$ZodULID`,(e,t)=>{t.pattern??=Ac,Tl.init(e,t)}),Fl=Z(`$ZodXID`,(e,t)=>{t.pattern??=jc,Tl.init(e,t)}),Il=Z(`$ZodKSUID`,(e,t)=>{t.pattern??=Mc,Tl.init(e,t)}),Ll=Z(`$ZodISODateTime`,(e,t)=>{t.pattern??=Qc(t),Tl.init(e,t)}),Rl=Z(`$ZodISODate`,(e,t)=>{t.pattern??=Yc,Tl.init(e,t)}),zl=Z(`$ZodISOTime`,(e,t)=>{t.pattern??=Zc(t),Tl.init(e,t)}),Bl=Z(`$ZodISODuration`,(e,t)=>{t.pattern??=Pc,Tl.init(e,t)}),Vl=Z(`$ZodIPv4`,(e,t)=>{t.pattern??=Bc,Tl.init(e,t),e._zod.bag.format=`ipv4`}),Hl=Z(`$ZodIPv6`,(e,t)=>{t.pattern??=Vc,Tl.init(e,t),e._zod.bag.format=`ipv6`,e._zod.check=n=>{try{new URL(`http://[${n.value}]`)}catch{n.issues.push({code:`invalid_format`,format:`ipv6`,input:n.value,inst:e,continue:!t.abort})}}}),Ul=Z(`$ZodCIDRv4`,(e,t)=>{t.pattern??=Hc,Tl.init(e,t)}),Wl=Z(`$ZodCIDRv6`,(e,t)=>{t.pattern??=Uc,Tl.init(e,t),e._zod.check=n=>{let r=n.value.split(`/`);try{if(r.length!==2)throw Error();let[e,t]=r;if(!t)throw Error();let n=Number(t);if(`${n}`!==t||n<0||n>128)throw Error();new URL(`http://[${e}]`)}catch{n.issues.push({code:`invalid_format`,format:`cidrv6`,input:n.value,inst:e,continue:!t.abort})}}});function Gl(e){if(e===``)return!0;if(/\s/.test(e)||e.length%4!=0)return!1;try{return atob(e),!0}catch{return!1}}var Kl=Z(`$ZodBase64`,(e,t)=>{t.pattern??=Wc,Tl.init(e,t),e._zod.bag.contentEncoding=`base64`,e._zod.check=n=>{Gl(n.value)||n.issues.push({code:`invalid_format`,format:`base64`,input:n.value,inst:e,continue:!t.abort})}});function ql(e){if(!Gc.test(e))return!1;let t=e.replace(/[-_]/g,e=>e===`-`?`+`:`/`);return Gl(t.padEnd(Math.ceil(t.length/4)*4,`=`))}var Jl=Z(`$ZodBase64URL`,(e,t)=>{t.pattern??=Gc,Tl.init(e,t),e._zod.bag.contentEncoding=`base64url`,e._zod.check=n=>{ql(n.value)||n.issues.push({code:`invalid_format`,format:`base64url`,input:n.value,inst:e,continue:!t.abort})}}),Yl=Z(`$ZodE164`,(e,t)=>{t.pattern??=qc,Tl.init(e,t)});function Xl(e,t=null){try{let n=e.split(`.`);if(n.length!==3)return!1;let[r]=n;if(!r)return!1;let i=JSON.parse(atob(r));return!(`typ`in i&&i?.typ!==`JWT`||!i.alg||t&&(!(`alg`in i)||i.alg!==t))}catch{return!1}}var Zl=Z(`$ZodJWT`,(e,t)=>{Tl.init(e,t),e._zod.check=n=>{Xl(n.value,t.alg)||n.issues.push({code:`invalid_format`,format:`jwt`,input:n.value,inst:e,continue:!t.abort})}}),Ql=Z(`$ZodNumber`,(e,t)=>{Cl.init(e,t),e._zod.pattern=e._zod.bag.pattern??tl,e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=Number(n.value)}catch{}let i=n.value;if(typeof i==`number`&&!Number.isNaN(i)&&Number.isFinite(i))return n;let a=typeof i==`number`?Number.isNaN(i)?`NaN`:Number.isFinite(i)?void 0:`Infinity`:void 0;return n.issues.push({expected:`number`,code:`invalid_type`,input:i,inst:e,...a?{received:a}:{}}),n}}),$l=Z(`$ZodNumberFormat`,(e,t)=>{ll.init(e,t),Ql.init(e,t)}),eu=Z(`$ZodUnknown`,(e,t)=>{Cl.init(e,t),e._zod.parse=e=>e}),tu=Z(`$ZodNever`,(e,t)=>{Cl.init(e,t),e._zod.parse=(t,n)=>(t.issues.push({expected:`never`,code:`invalid_type`,input:t.value,inst:e}),t)});function nu(e,t,n){e.issues.length&&t.issues.push(...ic(n,e.issues)),t.value[n]=e.value}var ru=Z(`$ZodArray`,(e,t)=>{Cl.init(e,t),e._zod.parse=(n,r)=>{let i=n.value;if(!Array.isArray(i))return n.issues.push({expected:`array`,code:`invalid_type`,input:i,inst:e}),n;n.value=Array(i.length);let a=[];for(let e=0;enu(t,n,e))):nu(s,n,e)}return a.length?Promise.all(a).then(()=>n):n}});function iu(e,t,n,r,i,a){let o=n in r;if(e.issues.length){if(i&&a&&!o)return;t.issues.push(...ic(n,e.issues))}if(!o&&!i){e.issues.length||t.issues.push({code:`invalid_type`,expected:`nonoptional`,input:void 0,path:[n]});return}e.value===void 0?o&&(t.value[n]=void 0):t.value[n]=e.value}function au(e){let t=Object.keys(e.shape);for(let n of t)if(!e.shape?.[n]?._zod?.traits?.has(`$ZodType`))throw Error(`Invalid element at key "${n}": expected a Zod schema`);let n=qs(e.shape);return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}function ou(e,t,n,r,i,a){let o=[],s=i.keySet,c=i.catchall._zod,l=c.def.type,u=c.optin===`optional`,d=c.optout===`optional`;for(let i in t){if(i===`__proto__`||s.has(i))continue;if(l===`never`){o.push(i);continue}let a=c.run({value:t[i],issues:[]},r);a instanceof Promise?e.push(a.then(e=>iu(e,n,i,t,u,d))):iu(a,n,i,t,u,d)}return o.length&&n.issues.push({code:`unrecognized_keys`,keys:o,input:t,inst:a}),e.length?Promise.all(e).then(()=>n):n}var su=Z(`$ZodObject`,(e,t)=>{if(Cl.init(e,t),!Object.getOwnPropertyDescriptor(t,`shape`)?.get){let e=t.shape;Object.defineProperty(t,"shape",{get:()=>{let n={...e};return Object.defineProperty(t,"shape",{value:n}),n}})}let n=As(()=>au(t));Q(e._zod,`propValues`,()=>{let e=t.shape,n={};for(let t in e){let r=e[t]._zod;if(r.values){n[t]??(n[t]=new Set);for(let e of r.values)n[t].add(e)}}return n});let r=Bs,i=t.catchall,a;e._zod.parse=(t,o)=>{a??=n.value;let s=t.value;if(!r(s))return t.issues.push({expected:`object`,code:`invalid_type`,input:s,inst:e}),t;t.value={};let c=[],l=a.shape;for(let e of a.keys){let n=l[e],r=n._zod.optin===`optional`,i=n._zod.optout===`optional`,a=n._zod.run({value:s[e],issues:[]},o);a instanceof Promise?c.push(a.then(n=>iu(n,t,e,s,r,i))):iu(a,t,e,s,r,i)}return i?ou(c,s,t,o,n.value,e):c.length?Promise.all(c).then(()=>t):t}}),cu=Z(`$ZodObjectJIT`,(e,t)=>{su.init(e,t);let n=e._zod.parse,r=As(()=>au(t)),i=e=>{let t=new xl([`shape`,`payload`,`ctx`]),n=r.value,i=e=>{let t=Ls(e);return`shape[${t}]._zod.run({ value: input[${t}], issues: [] }, ctx)`};t.write(`const input = payload.value;`);let a=Object.create(null),o=0;for(let e of n.keys)a[e]=`key_${o++}`;t.write(`const newResult = {};`);for(let r of n.keys){let n=a[r],o=Ls(r),s=e[r],c=s?._zod?.optin===`optional`,l=s?._zod?.optout===`optional`;t.write(`const ${n} = ${i(r)};`),c&&l?t.write(` - if (${n}.issues.length) { - if (${o} in input) { - payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ - ...iss, - path: iss.path ? [${o}, ...iss.path] : [${o}] - }))); - } - } - - if (${n}.value === undefined) { - if (${o} in input) { - newResult[${o}] = undefined; - } - } else { - newResult[${o}] = ${n}.value; - } - - `):c?t.write(` - if (${n}.issues.length) { - payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ - ...iss, - path: iss.path ? [${o}, ...iss.path] : [${o}] - }))); - } - - if (${n}.value === undefined) { - if (${o} in input) { - newResult[${o}] = undefined; - } - } else { - newResult[${o}] = ${n}.value; - } - - `):t.write(` - const ${n}_present = ${o} in input; - if (${n}.issues.length) { - payload.issues = payload.issues.concat(${n}.issues.map(iss => ({ - ...iss, - path: iss.path ? [${o}, ...iss.path] : [${o}] - }))); - } - if (!${n}_present && !${n}.issues.length) { - payload.issues.push({ - code: "invalid_type", - expected: "nonoptional", - input: undefined, - path: [${o}] - }); - } - - if (${n}_present) { - if (${n}.value === undefined) { - newResult[${o}] = undefined; - } else { - newResult[${o}] = ${n}.value; - } - } - - `)}t.write(`payload.value = newResult;`),t.write(`return payload;`);let s=t.compile();return(t,n)=>s(e,t,n)},a,o=Bs,s=!Es.jitless,c=s&&Vs.value,l=t.catchall,u;e._zod.parse=(d,f)=>{u??=r.value;let p=d.value;return o(p)?s&&c&&f?.async===!1&&f.jitless!==!0?(a||=i(t.shape),d=a(d,f),l?ou([],p,d,f,u,e):d):n(d,f):(d.issues.push({expected:`object`,code:`invalid_type`,input:p,inst:e}),d)}});function lu(e,t,n,r){for(let n of e)if(n.issues.length===0)return t.value=n.value,t;let i=e.filter(e=>!nc(e));return i.length===1?(t.value=i[0].value,i[0]):(t.issues.push({code:`invalid_union`,input:t.value,inst:n,errors:e.map(e=>e.issues.map(e=>oc(e,r,Ds())))}),t)}var uu=Z(`$ZodUnion`,(e,t)=>{Cl.init(e,t),Q(e._zod,`optin`,()=>t.options.some(e=>e._zod.optin===`optional`)?`optional`:void 0),Q(e._zod,`optout`,()=>t.options.some(e=>e._zod.optout===`optional`)?`optional`:void 0),Q(e._zod,`values`,()=>{if(t.options.every(e=>e._zod.values))return new Set(t.options.flatMap(e=>Array.from(e._zod.values)))}),Q(e._zod,`pattern`,()=>{if(t.options.every(e=>e._zod.pattern)){let e=t.options.map(e=>e._zod.pattern);return RegExp(`^(${e.map(e=>Ms(e.source)).join(`|`)})$`)}});let n=t.options.length===1?t.options[0]._zod.run:null;e._zod.parse=(r,i)=>{if(n)return n(r,i);let a=!1,o=[];for(let e of t.options){let t=e._zod.run({value:r.value,issues:[]},i);if(t instanceof Promise)o.push(t),a=!0;else{if(t.issues.length===0)return t;o.push(t)}}return a?Promise.all(o).then(t=>lu(t,r,e,i)):lu(o,r,e,i)}}),du=Z(`$ZodIntersection`,(e,t)=>{Cl.init(e,t),e._zod.parse=(e,n)=>{let r=e.value,i=t.left._zod.run({value:r,issues:[]},n),a=t.right._zod.run({value:r,issues:[]},n);return i instanceof Promise||a instanceof Promise?Promise.all([i,a]).then(([t,n])=>pu(e,t,n)):pu(e,i,a)}});function fu(e,t){if(e===t||e instanceof Date&&t instanceof Date&&+e==+t)return{valid:!0,data:e};if(Hs(e)&&Hs(t)){let n=Object.keys(t),r=Object.keys(e).filter(e=>n.indexOf(e)!==-1),i={...e,...t};for(let n of r){let r=fu(e[n],t[n]);if(!r.valid)return{valid:!1,mergeErrorPath:[n,...r.mergeErrorPath]};i[n]=r.data}return{valid:!0,data:i}}if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return{valid:!1,mergeErrorPath:[]};let n=[];for(let r=0;re.l&&e.r).map(([e])=>e);if(a.length&&i&&e.issues.push({...i,keys:a}),nc(e))return e;let o=fu(t.value,n.value);if(!o.valid)throw Error(`Unmergable intersection. Error path: ${JSON.stringify(o.mergeErrorPath)}`);return e.value=o.data,e}var mu=Z(`$ZodEnum`,(e,t)=>{Cl.init(e,t);let n=Os(t.entries),r=new Set(n);e._zod.values=r,e._zod.pattern=RegExp(`^(${n.filter(e=>Ws.has(typeof e)).map(e=>typeof e==`string`?Gs(e):e.toString()).join(`|`)})$`),e._zod.parse=(t,i)=>{let a=t.value;return r.has(a)||t.issues.push({code:`invalid_value`,values:n,input:a,inst:e}),t}}),hu=Z(`$ZodLiteral`,(e,t)=>{if(Cl.init(e,t),t.values.length===0)throw Error(`Cannot create literal schema with no valid values`);let n=new Set(t.values);e._zod.values=n,e._zod.pattern=RegExp(`^(${t.values.map(e=>typeof e==`string`?Gs(e):e?Gs(e.toString()):String(e)).join(`|`)})$`),e._zod.parse=(r,i)=>{let a=r.value;return n.has(a)||r.issues.push({code:`invalid_value`,values:t.values,input:a,inst:e}),r}}),gu=Z(`$ZodTransform`,(e,t)=>{Cl.init(e,t),e._zod.optin=`optional`,e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new Ts(e.constructor.name);let i=t.transform(n.value,n);if(r.async)return(i instanceof Promise?i:Promise.resolve(i)).then(e=>(n.value=e,n.fallback=!0,n));if(i instanceof Promise)throw new ws;return n.value=i,n.fallback=!0,n}});function _u(e,t){return t===void 0&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}var vu=Z(`$ZodOptional`,(e,t)=>{Cl.init(e,t),e._zod.optin=`optional`,e._zod.optout=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),Q(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${Ms(e.source)})?$`):void 0}),e._zod.parse=(e,n)=>{if(t.innerType._zod.optin===`optional`){let r=e.value,i=t.innerType._zod.run(e,n);return i instanceof Promise?i.then(e=>_u(e,r)):_u(i,r)}return e.value===void 0?e:t.innerType._zod.run(e,n)}}),yu=Z(`$ZodExactOptional`,(e,t)=>{vu.init(e,t),Q(e._zod,`values`,()=>t.innerType._zod.values),Q(e._zod,`pattern`,()=>t.innerType._zod.pattern),e._zod.parse=(e,n)=>t.innerType._zod.run(e,n)}),bu=Z(`$ZodNullable`,(e,t)=>{Cl.init(e,t),Q(e._zod,`optin`,()=>t.innerType._zod.optin),Q(e._zod,`optout`,()=>t.innerType._zod.optout),Q(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${Ms(e.source)}|null)$`):void 0}),Q(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,null]):void 0),e._zod.parse=(e,n)=>e.value===null?e:t.innerType._zod.run(e,n)}),xu=Z(`$ZodDefault`,(e,t)=>{Cl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);if(e.value===void 0)return e.value=t.defaultValue,e;let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(e=>Su(e,t)):Su(r,t)}});function Su(e,t){return e.value===void 0&&(e.value=t.defaultValue),e}var Cu=Z(`$ZodPrefault`,(e,t)=>{Cl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>(n.direction===`backward`||e.value===void 0&&(e.value=t.defaultValue),t.innerType._zod.run(e,n))}),wu=Z(`$ZodNonOptional`,(e,t)=>{Cl.init(e,t),Q(e._zod,`values`,()=>{let e=t.innerType._zod.values;return e?new Set([...e].filter(e=>e!==void 0)):void 0}),e._zod.parse=(n,r)=>{let i=t.innerType._zod.run(n,r);return i instanceof Promise?i.then(t=>Tu(t,e)):Tu(i,e)}});function Tu(e,t){return!e.issues.length&&e.value===void 0&&e.issues.push({code:`invalid_type`,expected:`nonoptional`,input:e.value,inst:t}),e}var Eu=Z(`$ZodCatch`,(e,t)=>{Cl.init(e,t),e._zod.optin=`optional`,Q(e._zod,`optout`,()=>t.innerType._zod.optout),Q(e._zod,`values`,()=>t.innerType._zod.values),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(r=>(e.value=r.value,r.issues.length&&(e.value=t.catchValue({...e,error:{issues:r.issues.map(e=>oc(e,n,Ds()))},input:e.value}),e.issues=[],e.fallback=!0),e)):(e.value=r.value,r.issues.length&&(e.value=t.catchValue({...e,error:{issues:r.issues.map(e=>oc(e,n,Ds()))},input:e.value}),e.issues=[],e.fallback=!0),e)}}),Du=Z(`$ZodPipe`,(e,t)=>{Cl.init(e,t),Q(e._zod,`values`,()=>t.in._zod.values),Q(e._zod,`optin`,()=>t.in._zod.optin),Q(e._zod,`optout`,()=>t.out._zod.optout),Q(e._zod,`propValues`,()=>t.in._zod.propValues),e._zod.parse=(e,n)=>{if(n.direction===`backward`){let r=t.out._zod.run(e,n);return r instanceof Promise?r.then(e=>Ou(e,t.in,n)):Ou(r,t.in,n)}let r=t.in._zod.run(e,n);return r instanceof Promise?r.then(e=>Ou(e,t.out,n)):Ou(r,t.out,n)}});function Ou(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues,fallback:e.fallback},n)}var ku=Z(`$ZodReadonly`,(e,t)=>{Cl.init(e,t),Q(e._zod,`propValues`,()=>t.innerType._zod.propValues),Q(e._zod,`values`,()=>t.innerType._zod.values),Q(e._zod,`optin`,()=>t.innerType?._zod?.optin),Q(e._zod,`optout`,()=>t.innerType?._zod?.optout),e._zod.parse=(e,n)=>{if(n.direction===`backward`)return t.innerType._zod.run(e,n);let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(Au):Au(r)}});function Au(e){return e.value=Object.freeze(e.value),e}var ju=Z(`$ZodCustom`,(e,t)=>{il.init(e,t),Cl.init(e,t),e._zod.parse=(e,t)=>e,e._zod.check=n=>{let r=n.value,i=t.fn(r);if(i instanceof Promise)return i.then(t=>Mu(t,n,r,e));Mu(i,n,r,e)}});function Mu(e,t,n,r){if(!e){let e={code:`custom`,input:n,inst:r,path:[...r._zod.def.path??[]],continue:!r._zod.def.abort};r._zod.def.params&&(e.params=r._zod.def.params),t.issues.push(cc(e))}}var Nu,Pu=class{constructor(){this._map=new WeakMap,this._idmap=new Map}add(e,...t){let n=t[0];return this._map.set(e,n),n&&typeof n==`object`&&`id`in n&&this._idmap.set(n.id,e),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(e){let t=this._map.get(e);return t&&typeof t==`object`&&`id`in t&&this._idmap.delete(t.id),this._map.delete(e),this}get(e){let t=e._zod.parent;if(t){let n={...this.get(t)??{}};delete n.id;let r={...n,...this._map.get(e)};return Object.keys(r).length?r:void 0}return this._map.get(e)}has(e){return this._map.has(e)}};function Fu(){return new Pu}(Nu=globalThis).__zod_globalRegistry??(Nu.__zod_globalRegistry=Fu());var Iu=globalThis.__zod_globalRegistry;function Lu(e,t){return new e({type:`string`,...$(t)})}function Ru(e,t){return new e({type:`string`,format:`email`,check:`string_format`,abort:!1,...$(t)})}function zu(e,t){return new e({type:`string`,format:`guid`,check:`string_format`,abort:!1,...$(t)})}function Bu(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,...$(t)})}function Vu(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v4`,...$(t)})}function Hu(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v6`,...$(t)})}function Uu(e,t){return new e({type:`string`,format:`uuid`,check:`string_format`,abort:!1,version:`v7`,...$(t)})}function Wu(e,t){return new e({type:`string`,format:`url`,check:`string_format`,abort:!1,...$(t)})}function Gu(e,t){return new e({type:`string`,format:`emoji`,check:`string_format`,abort:!1,...$(t)})}function Ku(e,t){return new e({type:`string`,format:`nanoid`,check:`string_format`,abort:!1,...$(t)})}function qu(e,t){return new e({type:`string`,format:`cuid`,check:`string_format`,abort:!1,...$(t)})}function Ju(e,t){return new e({type:`string`,format:`cuid2`,check:`string_format`,abort:!1,...$(t)})}function Yu(e,t){return new e({type:`string`,format:`ulid`,check:`string_format`,abort:!1,...$(t)})}function Xu(e,t){return new e({type:`string`,format:`xid`,check:`string_format`,abort:!1,...$(t)})}function Zu(e,t){return new e({type:`string`,format:`ksuid`,check:`string_format`,abort:!1,...$(t)})}function Qu(e,t){return new e({type:`string`,format:`ipv4`,check:`string_format`,abort:!1,...$(t)})}function $u(e,t){return new e({type:`string`,format:`ipv6`,check:`string_format`,abort:!1,...$(t)})}function ed(e,t){return new e({type:`string`,format:`cidrv4`,check:`string_format`,abort:!1,...$(t)})}function td(e,t){return new e({type:`string`,format:`cidrv6`,check:`string_format`,abort:!1,...$(t)})}function nd(e,t){return new e({type:`string`,format:`base64`,check:`string_format`,abort:!1,...$(t)})}function rd(e,t){return new e({type:`string`,format:`base64url`,check:`string_format`,abort:!1,...$(t)})}function id(e,t){return new e({type:`string`,format:`e164`,check:`string_format`,abort:!1,...$(t)})}function ad(e,t){return new e({type:`string`,format:`jwt`,check:`string_format`,abort:!1,...$(t)})}function od(e,t){return new e({type:`string`,format:`datetime`,check:`string_format`,offset:!1,local:!1,precision:null,...$(t)})}function sd(e,t){return new e({type:`string`,format:`date`,check:`string_format`,...$(t)})}function cd(e,t){return new e({type:`string`,format:`time`,check:`string_format`,precision:null,...$(t)})}function ld(e,t){return new e({type:`string`,format:`duration`,check:`string_format`,...$(t)})}function ud(e,t){return new e({type:`number`,checks:[],...$(t)})}function dd(e,t){return new e({type:`number`,check:`number_format`,abort:!1,format:`safeint`,...$(t)})}function fd(e){return new e({type:`unknown`})}function pd(e,t){return new e({type:`never`,...$(t)})}function md(e,t){return new ol({check:`less_than`,...$(t),value:e,inclusive:!1})}function hd(e,t){return new ol({check:`less_than`,...$(t),value:e,inclusive:!0})}function gd(e,t){return new sl({check:`greater_than`,...$(t),value:e,inclusive:!1})}function _d(e,t){return new sl({check:`greater_than`,...$(t),value:e,inclusive:!0})}function vd(e,t){return new cl({check:`multiple_of`,...$(t),value:e})}function yd(e,t){return new ul({check:`max_length`,...$(t),maximum:e})}function bd(e,t){return new dl({check:`min_length`,...$(t),minimum:e})}function xd(e,t){return new fl({check:`length_equals`,...$(t),length:e})}function Sd(e,t){return new ml({check:`string_format`,format:`regex`,...$(t),pattern:e})}function Cd(e){return new hl({check:`string_format`,format:`lowercase`,...$(e)})}function wd(e){return new gl({check:`string_format`,format:`uppercase`,...$(e)})}function Td(e,t){return new _l({check:`string_format`,format:`includes`,...$(t),includes:e})}function Ed(e,t){return new vl({check:`string_format`,format:`starts_with`,...$(t),prefix:e})}function Dd(e,t){return new yl({check:`string_format`,format:`ends_with`,...$(t),suffix:e})}function Od(e){return new bl({check:`overwrite`,tx:e})}function kd(e){return Od(t=>t.normalize(e))}function Ad(){return Od(e=>e.trim())}function jd(){return Od(e=>e.toLowerCase())}function Md(){return Od(e=>e.toUpperCase())}function Nd(){return Od(e=>Rs(e))}function Pd(e,t,n){return new e({type:`array`,element:t,...$(n)})}function Fd(e,t,n){return new e({type:`custom`,check:`custom`,fn:t,...$(n)})}function Id(e,t){let n=Ld(t=>(t.addIssue=e=>{if(typeof e==`string`)t.issues.push(cc(e,t.value,n._zod.def));else{let r=e;r.fatal&&(r.continue=!1),r.code??=`custom`,r.input??=t.value,r.inst??=n,r.continue??=!n._zod.def.abort,t.issues.push(cc(r))}},e(t.value,t)),t);return n}function Ld(e,t){let n=new il({check:`custom`,...$(t)});return n._zod.check=e,n}function Rd(e){let t=e?.target??`draft-2020-12`;return t===`draft-4`&&(t=`draft-04`),t===`draft-7`&&(t=`draft-07`),{processors:e.processors??{},metadataRegistry:e?.metadata??Iu,target:t,unrepresentable:e?.unrepresentable??`throw`,override:e?.override??(()=>{}),io:e?.io??`output`,counter:0,seen:new Map,cycles:e?.cycles??`ref`,reused:e?.reused??`inline`,external:e?.external??void 0}}function zd(e,t,n={path:[],schemaPath:[]}){var r;let i=e._zod.def,a=t.seen.get(e);if(a)return a.count++,n.schemaPath.includes(e)&&(a.cycle=n.path),a.schema;let o={schema:{},count:1,cycle:void 0,path:n.path};t.seen.set(e,o);let s=e._zod.toJSONSchema?.();if(s)o.schema=s;else{let r={...n,schemaPath:[...n.schemaPath,e],path:n.path};if(e._zod.processJSONSchema)e._zod.processJSONSchema(t,o.schema,r);else{let n=o.schema,a=t.processors[i.type];if(!a)throw Error(`[toJSONSchema]: Non-representable type encountered: ${i.type}`);a(e,t,n,r)}let a=e._zod.parent;a&&(o.ref||=a,zd(a,t,r),t.seen.get(a).isParent=!0)}let c=t.metadataRegistry.get(e);return c&&Object.assign(o.schema,c),t.io===`input`&&Hd(e)&&(delete o.schema.examples,delete o.schema.default),t.io===`input`&&`_prefault`in o.schema&&((r=o.schema).default??(r.default=o.schema._prefault)),delete o.schema._prefault,t.seen.get(e).schema}function Bd(e,t){let n=e.seen.get(t);if(!n)throw Error(`Unprocessed schema. This is a bug in Zod.`);let r=new Map;for(let t of e.seen.entries()){let n=e.metadataRegistry.get(t[0])?.id;if(n){let e=r.get(n);if(e&&e!==t[0])throw Error(`Duplicate schema id "${n}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);r.set(n,t[0])}}let i=t=>{let r=e.target===`draft-2020-12`?`$defs`:`definitions`;if(e.external){let n=e.external.registry.get(t[0])?.id,i=e.external.uri??(e=>e);if(n)return{ref:i(n)};let a=t[1].defId??t[1].schema.id??`schema${e.counter++}`;return t[1].defId=a,{defId:a,ref:`${i(`__shared`)}#/${r}/${a}`}}if(t[1]===n)return{ref:`#`};let i=`#/${r}/`,a=t[1].schema.id??`__schema${e.counter++}`;return{defId:a,ref:i+a}},a=e=>{if(e[1].schema.$ref)return;let t=e[1],{ref:n,defId:r}=i(e);t.def={...t.schema},r&&(t.defId=r);let a=t.schema;for(let e in a)delete a[e];a.$ref=n};if(e.cycles===`throw`)for(let t of e.seen.entries()){let e=t[1];if(e.cycle)throw Error(`Cycle detected: #/${e.cycle?.join(`/`)}/ - -Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let n of e.seen.entries()){let r=n[1];if(t===n[0]){a(n);continue}if(e.external){let r=e.external.registry.get(n[0])?.id;if(t!==n[0]&&r){a(n);continue}}if(e.metadataRegistry.get(n[0])?.id){a(n);continue}if(r.cycle){a(n);continue}if(r.count>1&&e.reused===`ref`){a(n);continue}}}function Vd(e,t){let n=e.seen.get(t);if(!n)throw Error(`Unprocessed schema. This is a bug in Zod.`);let r=t=>{let n=e.seen.get(t);if(n.ref===null)return;let i=n.def??n.schema,a={...i},o=n.ref;if(n.ref=null,o){r(o);let n=e.seen.get(o),s=n.schema;if(s.$ref&&(e.target===`draft-07`||e.target===`draft-04`||e.target===`openapi-3.0`)?(i.allOf=i.allOf??[],i.allOf.push(s)):Object.assign(i,s),Object.assign(i,a),t._zod.parent===o)for(let e in i)e!==`$ref`&&e!==`allOf`&&(e in a||delete i[e]);if(s.$ref&&n.def)for(let e in i)e!==`$ref`&&e!==`allOf`&&e in n.def&&JSON.stringify(i[e])===JSON.stringify(n.def[e])&&delete i[e]}let s=t._zod.parent;if(s&&s!==o){r(s);let t=e.seen.get(s);if(t?.schema.$ref&&(i.$ref=t.schema.$ref,t.def))for(let e in i)e!==`$ref`&&e!==`allOf`&&e in t.def&&JSON.stringify(i[e])===JSON.stringify(t.def[e])&&delete i[e]}e.override({zodSchema:t,jsonSchema:i,path:n.path??[]})};for(let t of[...e.seen.entries()].reverse())r(t[0]);let i={};if(e.target===`draft-2020-12`?i.$schema=`https://json-schema.org/draft/2020-12/schema`:e.target===`draft-07`?i.$schema=`http://json-schema.org/draft-07/schema#`:e.target===`draft-04`?i.$schema=`http://json-schema.org/draft-04/schema#`:e.target,e.external?.uri){let n=e.external.registry.get(t)?.id;if(!n)throw Error("Schema is missing an `id` property");i.$id=e.external.uri(n)}Object.assign(i,n.def??n.schema);let a=e.metadataRegistry.get(t)?.id;a!==void 0&&i.id===a&&delete i.id;let o=e.external?.defs??{};for(let t of e.seen.entries()){let e=t[1];e.def&&e.defId&&(e.def.id===e.defId&&delete e.def.id,o[e.defId]=e.def)}e.external||Object.keys(o).length>0&&(e.target===`draft-2020-12`?i.$defs=o:i.definitions=o);try{let n=JSON.parse(JSON.stringify(i));return Object.defineProperty(n,"~standard",{value:{...t[`~standard`],jsonSchema:{input:Wd(t,`input`,e.processors),output:Wd(t,`output`,e.processors)}},enumerable:!1,writable:!1}),n}catch{throw Error(`Error converting schema to JSON.`)}}function Hd(e,t){let n=t??{seen:new Set};if(n.seen.has(e))return!1;n.seen.add(e);let r=e._zod.def;if(r.type===`transform`)return!0;if(r.type===`array`)return Hd(r.element,n);if(r.type===`set`)return Hd(r.valueType,n);if(r.type===`lazy`)return Hd(r.getter(),n);if(r.type===`promise`||r.type===`optional`||r.type===`nonoptional`||r.type===`nullable`||r.type===`readonly`||r.type==="default"||r.type===`prefault`)return Hd(r.innerType,n);if(r.type===`intersection`)return Hd(r.left,n)||Hd(r.right,n);if(r.type===`record`||r.type===`map`)return Hd(r.keyType,n)||Hd(r.valueType,n);if(r.type===`pipe`)return e._zod.traits.has(`$ZodCodec`)?!0:Hd(r.in,n)||Hd(r.out,n);if(r.type===`object`){for(let e in r.shape)if(Hd(r.shape[e],n))return!0;return!1}if(r.type===`union`){for(let e of r.options)if(Hd(e,n))return!0;return!1}if(r.type===`tuple`){for(let e of r.items)if(Hd(e,n))return!0;return!!(r.rest&&Hd(r.rest,n))}return!1}var Ud=(e,t={})=>n=>{let r=Rd({...n,processors:t});return zd(e,r),Bd(r,e),Vd(r,e)},Wd=(e,t,n={})=>r=>{let{libraryOptions:i,target:a}=r??{},o=Rd({...i??{},target:a,io:t,processors:n});return zd(e,o),Bd(o,e),Vd(o,e)},Gd={guid:`uuid`,url:`uri`,datetime:`date-time`,json_string:`json-string`,regex:``},Kd=(e,t,n,r)=>{let i=n;i.type=`string`;let{minimum:a,maximum:o,format:s,patterns:c,contentEncoding:l}=e._zod.bag;if(typeof a==`number`&&(i.minLength=a),typeof o==`number`&&(i.maxLength=o),s&&(i.format=Gd[s]??s,i.format===``&&delete i.format,s===`time`&&delete i.format),l&&(i.contentEncoding=l),c&&c.size>0){let e=[...c];e.length===1?i.pattern=e[0].source:e.length>1&&(i.allOf=[...e.map(e=>({...t.target===`draft-07`||t.target===`draft-04`||t.target===`openapi-3.0`?{type:`string`}:{},pattern:e.source}))])}},qd=(e,t,n,r)=>{let i=n,{minimum:a,maximum:o,format:s,multipleOf:c,exclusiveMaximum:l,exclusiveMinimum:u}=e._zod.bag;i.type=typeof s==`string`&&s.includes(`int`)?`integer`:`number`;let d=typeof u==`number`&&u>=(a??-1/0),f=typeof l==`number`&&l<=(o??1/0),p=t.target===`draft-04`||t.target===`openapi-3.0`;d?p?(i.minimum=u,i.exclusiveMinimum=!0):i.exclusiveMinimum=u:typeof a==`number`&&(i.minimum=a),f?p?(i.maximum=l,i.exclusiveMaximum=!0):i.exclusiveMaximum=l:typeof o==`number`&&(i.maximum=o),typeof c==`number`&&(i.multipleOf=c)},Jd=(e,t,n,r)=>{n.not={}},Yd=(e,t,n,r)=>{let i=e._zod.def,a=Os(i.entries);a.every(e=>typeof e==`number`)&&(n.type=`number`),a.every(e=>typeof e==`string`)&&(n.type=`string`),n.enum=a},Xd=(e,t,n,r)=>{let i=e._zod.def,a=[];for(let e of i.values)if(e===void 0){if(t.unrepresentable===`throw`)throw Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof e==`bigint`){if(t.unrepresentable===`throw`)throw Error(`BigInt literals cannot be represented in JSON Schema`);a.push(Number(e))}else a.push(e);if(a.length!==0)if(a.length===1){let e=a[0];n.type=e===null?`null`:typeof e,t.target===`draft-04`||t.target===`openapi-3.0`?n.enum=[e]:n.const=e}else a.every(e=>typeof e==`number`)&&(n.type=`number`),a.every(e=>typeof e==`string`)&&(n.type=`string`),a.every(e=>typeof e==`boolean`)&&(n.type=`boolean`),a.every(e=>e===null)&&(n.type=`null`),n.enum=a},Zd=(e,t,n,r)=>{if(t.unrepresentable===`throw`)throw Error(`Custom types cannot be represented in JSON Schema`)},Qd=(e,t,n,r)=>{if(t.unrepresentable===`throw`)throw Error(`Transforms cannot be represented in JSON Schema`)},$d=(e,t,n,r)=>{let i=n,a=e._zod.def,{minimum:o,maximum:s}=e._zod.bag;typeof o==`number`&&(i.minItems=o),typeof s==`number`&&(i.maxItems=s),i.type=`array`,i.items=zd(a.element,t,{...r,path:[...r.path,`items`]})},ef=(e,t,n,r)=>{let i=n,a=e._zod.def;i.type=`object`,i.properties={};let o=a.shape;for(let e in o)i.properties[e]=zd(o[e],t,{...r,path:[...r.path,`properties`,e]});let s=new Set(Object.keys(o)),c=new Set([...s].filter(e=>{let n=a.shape[e]._zod;return t.io===`input`?n.optin===void 0:n.optout===void 0}));c.size>0&&(i.required=Array.from(c)),a.catchall?._zod.def.type===`never`?i.additionalProperties=!1:a.catchall?a.catchall&&(i.additionalProperties=zd(a.catchall,t,{...r,path:[...r.path,`additionalProperties`]})):t.io===`output`&&(i.additionalProperties=!1)},tf=(e,t,n,r)=>{let i=e._zod.def,a=i.inclusive===!1,o=i.options.map((e,n)=>zd(e,t,{...r,path:[...r.path,a?`oneOf`:`anyOf`,n]}));a?n.oneOf=o:n.anyOf=o},nf=(e,t,n,r)=>{let i=e._zod.def,a=zd(i.left,t,{...r,path:[...r.path,`allOf`,0]}),o=zd(i.right,t,{...r,path:[...r.path,`allOf`,1]}),s=e=>`allOf`in e&&Object.keys(e).length===1;n.allOf=[...s(a)?a.allOf:[a],...s(o)?o.allOf:[o]]},rf=(e,t,n,r)=>{let i=e._zod.def,a=zd(i.innerType,t,r),o=t.seen.get(e);t.target===`openapi-3.0`?(o.ref=i.innerType,n.nullable=!0):n.anyOf=[a,{type:`null`}]},af=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType},of=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,n.default=JSON.parse(JSON.stringify(i.defaultValue))},sf=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,t.io===`input`&&(n._prefault=JSON.parse(JSON.stringify(i.defaultValue)))},cf=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType;let o;try{o=i.catchValue(void 0)}catch{throw Error(`Dynamic catch values are not supported in JSON Schema`)}n.default=o},lf=(e,t,n,r)=>{let i=e._zod.def,a=i.in._zod.traits.has(`$ZodTransform`),o=t.io===`input`?a?i.out:i.in:i.out;zd(o,t,r);let s=t.seen.get(e);s.ref=o},uf=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType,n.readOnly=!0},df=(e,t,n,r)=>{let i=e._zod.def;zd(i.innerType,t,r);let a=t.seen.get(e);a.ref=i.innerType},ff=Z(`ZodISODateTime`,(e,t)=>{Ll.init(e,t),zf.init(e,t)});function pf(e){return od(ff,e)}var mf=Z(`ZodISODate`,(e,t)=>{Rl.init(e,t),zf.init(e,t)});function hf(e){return sd(mf,e)}var gf=Z(`ZodISOTime`,(e,t)=>{zl.init(e,t),zf.init(e,t)});function _f(e){return cd(gf,e)}var vf=Z(`ZodISODuration`,(e,t)=>{Bl.init(e,t),zf.init(e,t)});function yf(e){return ld(vf,e)}var bf=Z(`ZodError`,(e,t)=>{uc.init(e,t),e.name=`ZodError`,Object.defineProperties(e,{format:{value:t=>pc(e,t)},flatten:{value:t=>fc(e,t)},addIssue:{value:t=>{e.issues.push(t),e.message=JSON.stringify(e.issues,ks,2)}},addIssues:{value:t=>{e.issues.push(...t),e.message=JSON.stringify(e.issues,ks,2)}},isEmpty:{get(){return e.issues.length===0}}})},{Parent:Error}),xf=mc(bf),Sf=hc(bf),Cf=gc(bf),wf=vc(bf),Tf=bc(bf),Ef=xc(bf),Df=Sc(bf),Of=Cc(bf),kf=wc(bf),Af=Tc(bf),jf=Ec(bf),Mf=Dc(bf),Nf=new WeakMap;function Pf(e,t,n){let r=Object.getPrototypeOf(e),i=Nf.get(r);if(i||(i=new Set,Nf.set(r,i)),!i.has(t)){i.add(t);for(let e in n){let t=n[e];Object.defineProperty(r,e,{configurable:!0,enumerable:!1,get(){let n=t.bind(this);return Object.defineProperty(this,e,{configurable:!0,writable:!0,enumerable:!0,value:n}),n},set(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,enumerable:!0,value:t})}})}}}var Ff=Z(`ZodType`,(e,t)=>(Cl.init(e,t),Object.assign(e[`~standard`],{jsonSchema:{input:Wd(e,`input`),output:Wd(e,`output`)}}),e.toJSONSchema=Ud(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.parse=(t,n)=>xf(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>Cf(e,t,n),e.parseAsync=async(t,n)=>Sf(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>wf(e,t,n),e.spa=e.safeParseAsync,e.encode=(t,n)=>Tf(e,t,n),e.decode=(t,n)=>Ef(e,t,n),e.encodeAsync=async(t,n)=>Df(e,t,n),e.decodeAsync=async(t,n)=>Of(e,t,n),e.safeEncode=(t,n)=>kf(e,t,n),e.safeDecode=(t,n)=>Af(e,t,n),e.safeEncodeAsync=async(t,n)=>jf(e,t,n),e.safeDecodeAsync=async(t,n)=>Mf(e,t,n),Pf(e,`ZodType`,{check(...e){let t=this.def;return this.clone(Is(t,{checks:[...t.checks??[],...e.map(e=>typeof e==`function`?{_zod:{check:e,def:{check:`custom`},onattach:[]}}:e)]}),{parent:!0})},with(...e){return this.check(...e)},clone(e,t){return Ks(this,e,t)},brand(){return this},register(e,t){return e.add(this,t),this},refine(e,t){return this.check(Kp(e,t))},superRefine(e,t){return this.check(qp(e,t))},overwrite(e){return this.check(Od(e))},optional(){return Op(this)},exactOptional(){return Ap(this)},nullable(){return Mp(this)},nullish(){return Op(Mp(this))},nonoptional(e){return Rp(this,e)},array(){return mp(this)},or(e){return vp([this,e])},and(e){return bp(this,e)},transform(e){return Hp(this,Ep(e))},default(e){return Pp(this,e)},prefault(e){return Ip(this,e)},catch(e){return Bp(this,e)},pipe(e){return Hp(this,e)},readonly(){return Wp(this)},describe(e){let t=this.clone();return Iu.add(t,{description:e}),t},meta(...e){if(e.length===0)return Iu.get(this);let t=this.clone();return Iu.add(t,e[0]),t},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(e){return e(this)}}),Object.defineProperty(e,"description",{get(){return Iu.get(e)?.description},configurable:!0}),e)),If=Z(`_ZodString`,(e,t)=>{wl.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Kd(e,t,n,r);let n=e._zod.bag;e.format=n.format??null,e.minLength=n.minimum??null,e.maxLength=n.maximum??null,Pf(e,`_ZodString`,{regex(...e){return this.check(Sd(...e))},includes(...e){return this.check(Td(...e))},startsWith(...e){return this.check(Ed(...e))},endsWith(...e){return this.check(Dd(...e))},min(...e){return this.check(bd(...e))},max(...e){return this.check(yd(...e))},length(...e){return this.check(xd(...e))},nonempty(...e){return this.check(bd(1,...e))},lowercase(e){return this.check(Cd(e))},uppercase(e){return this.check(wd(e))},trim(){return this.check(Ad())},normalize(...e){return this.check(kd(...e))},toLowerCase(){return this.check(jd())},toUpperCase(){return this.check(Md())},slugify(){return this.check(Nd())}})}),Lf=Z(`ZodString`,(e,t)=>{wl.init(e,t),If.init(e,t),e.email=t=>e.check(Ru(Bf,t)),e.url=t=>e.check(Wu(Uf,t)),e.jwt=t=>e.check(ad(ip,t)),e.emoji=t=>e.check(Gu(Wf,t)),e.guid=t=>e.check(zu(Vf,t)),e.uuid=t=>e.check(Bu(Hf,t)),e.uuidv4=t=>e.check(Vu(Hf,t)),e.uuidv6=t=>e.check(Hu(Hf,t)),e.uuidv7=t=>e.check(Uu(Hf,t)),e.nanoid=t=>e.check(Ku(Gf,t)),e.guid=t=>e.check(zu(Vf,t)),e.cuid=t=>e.check(qu(Kf,t)),e.cuid2=t=>e.check(Ju(qf,t)),e.ulid=t=>e.check(Yu(Jf,t)),e.base64=t=>e.check(nd(tp,t)),e.base64url=t=>e.check(rd(np,t)),e.xid=t=>e.check(Xu(Yf,t)),e.ksuid=t=>e.check(Zu(Xf,t)),e.ipv4=t=>e.check(Qu(Zf,t)),e.ipv6=t=>e.check($u(Qf,t)),e.cidrv4=t=>e.check(ed($f,t)),e.cidrv6=t=>e.check(td(ep,t)),e.e164=t=>e.check(id(rp,t)),e.datetime=t=>e.check(pf(t)),e.date=t=>e.check(hf(t)),e.time=t=>e.check(_f(t)),e.duration=t=>e.check(yf(t))});function Rf(e){return Lu(Lf,e)}var zf=Z(`ZodStringFormat`,(e,t)=>{Tl.init(e,t),If.init(e,t)}),Bf=Z(`ZodEmail`,(e,t)=>{Ol.init(e,t),zf.init(e,t)}),Vf=Z(`ZodGUID`,(e,t)=>{El.init(e,t),zf.init(e,t)}),Hf=Z(`ZodUUID`,(e,t)=>{Dl.init(e,t),zf.init(e,t)}),Uf=Z(`ZodURL`,(e,t)=>{kl.init(e,t),zf.init(e,t)}),Wf=Z(`ZodEmoji`,(e,t)=>{Al.init(e,t),zf.init(e,t)}),Gf=Z(`ZodNanoID`,(e,t)=>{jl.init(e,t),zf.init(e,t)}),Kf=Z(`ZodCUID`,(e,t)=>{Ml.init(e,t),zf.init(e,t)}),qf=Z(`ZodCUID2`,(e,t)=>{Nl.init(e,t),zf.init(e,t)}),Jf=Z(`ZodULID`,(e,t)=>{Pl.init(e,t),zf.init(e,t)}),Yf=Z(`ZodXID`,(e,t)=>{Fl.init(e,t),zf.init(e,t)}),Xf=Z(`ZodKSUID`,(e,t)=>{Il.init(e,t),zf.init(e,t)}),Zf=Z(`ZodIPv4`,(e,t)=>{Vl.init(e,t),zf.init(e,t)}),Qf=Z(`ZodIPv6`,(e,t)=>{Hl.init(e,t),zf.init(e,t)}),$f=Z(`ZodCIDRv4`,(e,t)=>{Ul.init(e,t),zf.init(e,t)}),ep=Z(`ZodCIDRv6`,(e,t)=>{Wl.init(e,t),zf.init(e,t)}),tp=Z(`ZodBase64`,(e,t)=>{Kl.init(e,t),zf.init(e,t)}),np=Z(`ZodBase64URL`,(e,t)=>{Jl.init(e,t),zf.init(e,t)}),rp=Z(`ZodE164`,(e,t)=>{Yl.init(e,t),zf.init(e,t)}),ip=Z(`ZodJWT`,(e,t)=>{Zl.init(e,t),zf.init(e,t)}),ap=Z(`ZodNumber`,(e,t)=>{Ql.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>qd(e,t,n,r),Pf(e,`ZodNumber`,{gt(e,t){return this.check(gd(e,t))},gte(e,t){return this.check(_d(e,t))},min(e,t){return this.check(_d(e,t))},lt(e,t){return this.check(md(e,t))},lte(e,t){return this.check(hd(e,t))},max(e,t){return this.check(hd(e,t))},int(e){return this.check(cp(e))},safe(e){return this.check(cp(e))},positive(e){return this.check(gd(0,e))},nonnegative(e){return this.check(_d(0,e))},negative(e){return this.check(md(0,e))},nonpositive(e){return this.check(hd(0,e))},multipleOf(e,t){return this.check(vd(e,t))},step(e,t){return this.check(vd(e,t))},finite(){return this}});let n=e._zod.bag;e.minValue=Math.max(n.minimum??-1/0,n.exclusiveMinimum??-1/0)??null,e.maxValue=Math.min(n.maximum??1/0,n.exclusiveMaximum??1/0)??null,e.isInt=(n.format??``).includes(`int`)||Number.isSafeInteger(n.multipleOf??.5),e.isFinite=!0,e.format=n.format??null});function op(e){return ud(ap,e)}var sp=Z(`ZodNumberFormat`,(e,t)=>{$l.init(e,t),ap.init(e,t)});function cp(e){return dd(sp,e)}var lp=Z(`ZodUnknown`,(e,t)=>{eu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(e,t,n)=>void 0});function up(){return fd(lp)}var dp=Z(`ZodNever`,(e,t)=>{tu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Jd(e,t,n,r)});function fp(e){return pd(dp,e)}var pp=Z(`ZodArray`,(e,t)=>{ru.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>$d(e,t,n,r),e.element=t.element,Pf(e,`ZodArray`,{min(e,t){return this.check(bd(e,t))},nonempty(e){return this.check(bd(1,e))},max(e,t){return this.check(yd(e,t))},length(e,t){return this.check(xd(e,t))},unwrap(){return this.element}})});function mp(e,t){return Pd(pp,e,t)}var hp=Z(`ZodObject`,(e,t)=>{cu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>ef(e,t,n,r),Q(e,`shape`,()=>t.shape),Pf(e,`ZodObject`,{keyof(){return Sp(Object.keys(this._zod.def.shape))},catchall(e){return this.clone({...this._zod.def,catchall:e})},passthrough(){return this.clone({...this._zod.def,catchall:up()})},loose(){return this.clone({...this._zod.def,catchall:up()})},strict(){return this.clone({...this._zod.def,catchall:fp()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(e){return Zs(this,e)},safeExtend(e){return Qs(this,e)},merge(e){return $s(this,e)},pick(e){return Ys(this,e)},omit(e){return Xs(this,e)},partial(...e){return ec(Dp,this,e[0])},required(...e){return tc(Lp,this,e[0])}})});function gp(e,t){return new hp({type:`object`,shape:e??{},...$(t)})}var _p=Z(`ZodUnion`,(e,t)=>{uu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>tf(e,t,n,r),e.options=t.options});function vp(e,t){return new _p({type:`union`,options:e,...$(t)})}var yp=Z(`ZodIntersection`,(e,t)=>{du.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>nf(e,t,n,r)});function bp(e,t){return new yp({type:`intersection`,left:e,right:t})}var xp=Z(`ZodEnum`,(e,t)=>{mu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Yd(e,t,n,r),e.enum=t.entries,e.options=Object.values(t.entries);let n=new Set(Object.keys(t.entries));e.extract=(e,r)=>{let i={};for(let r of e)if(n.has(r))i[r]=t.entries[r];else throw Error(`Key ${r} not found in enum`);return new xp({...t,checks:[],...$(r),entries:i})},e.exclude=(e,r)=>{let i={...t.entries};for(let t of e)if(n.has(t))delete i[t];else throw Error(`Key ${t} not found in enum`);return new xp({...t,checks:[],...$(r),entries:i})}});function Sp(e,t){return new xp({type:`enum`,entries:Array.isArray(e)?Object.fromEntries(e.map(e=>[e,e])):e,...$(t)})}var Cp=Z(`ZodLiteral`,(e,t)=>{hu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Xd(e,t,n,r),e.values=new Set(t.values),Object.defineProperty(e,"value",{get(){if(t.values.length>1)throw Error("This schema contains multiple valid literal values. Use `.values` instead.");return t.values[0]}})});function wp(e,t){return new Cp({type:`literal`,values:Array.isArray(e)?e:[e],...$(t)})}var Tp=Z(`ZodTransform`,(e,t)=>{gu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Qd(e,t,n,r),e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new Ts(e.constructor.name);n.addIssue=r=>{if(typeof r==`string`)n.issues.push(cc(r,n.value,t));else{let t=r;t.fatal&&(t.continue=!1),t.code??=`custom`,t.input??=n.value,t.inst??=e,n.issues.push(cc(t))}};let i=t.transform(n.value,n);return i instanceof Promise?i.then(e=>(n.value=e,n.fallback=!0,n)):(n.value=i,n.fallback=!0,n)}});function Ep(e){return new Tp({type:`transform`,transform:e})}var Dp=Z(`ZodOptional`,(e,t)=>{vu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>df(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Op(e){return new Dp({type:`optional`,innerType:e})}var kp=Z(`ZodExactOptional`,(e,t)=>{yu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>df(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Ap(e){return new kp({type:`optional`,innerType:e})}var jp=Z(`ZodNullable`,(e,t)=>{bu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>rf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Mp(e){return new jp({type:`nullable`,innerType:e})}var Np=Z(`ZodDefault`,(e,t)=>{xu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>of(e,t,n,r),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function Pp(e,t){return new Np({type:`default`,innerType:e,get defaultValue(){return typeof t==`function`?t():Us(t)}})}var Fp=Z(`ZodPrefault`,(e,t)=>{Cu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>sf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Ip(e,t){return new Fp({type:`prefault`,innerType:e,get defaultValue(){return typeof t==`function`?t():Us(t)}})}var Lp=Z(`ZodNonOptional`,(e,t)=>{wu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>af(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Rp(e,t){return new Lp({type:`nonoptional`,innerType:e,...$(t)})}var zp=Z(`ZodCatch`,(e,t)=>{Eu.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>cf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function Bp(e,t){return new zp({type:`catch`,innerType:e,catchValue:typeof t==`function`?t:()=>t})}var Vp=Z(`ZodPipe`,(e,t)=>{Du.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>lf(e,t,n,r),e.in=t.in,e.out=t.out});function Hp(e,t){return new Vp({type:`pipe`,in:e,out:t})}var Up=Z(`ZodReadonly`,(e,t)=>{ku.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>uf(e,t,n,r),e.unwrap=()=>e._zod.def.innerType});function Wp(e){return new Up({type:`readonly`,innerType:e})}var Gp=Z(`ZodCustom`,(e,t)=>{ju.init(e,t),Ff.init(e,t),e._zod.processJSONSchema=(t,n,r)=>Zd(e,t,n,r)});function Kp(e,t={}){return Fd(Gp,e,t)}function qp(e,t){return Id(e,t)}var Jp=U(`
                    `,1),Yp=U(` `,1);function Xp(e,t){We(t,!0);let n=()=>A(g,`$hasErrors`,o),r=()=>A(_,`$isDirty`,o),i=()=>A(h,`$errors`,o),a=()=>A(v,`$isDirtyByField`,o),[o,s]=ft(),c=gp({username:Rf().min(3).max(20).regex(/^\S+$/,`Must not contain spaces`),email:Rf().min(1,`Required`).email(),age:op().int().min(18).max(120),website:Rf().url().optional().or(wp(``)),bio:Rf().max(200).optional()});function l(e,t,n){let r=e.safeParse(t);if(r.success)return Object.fromEntries(n.map(e=>[e,``]));let i={};for(let e of r.error.issues){let t=String(e.path[0]);Object.hasOwn(i,t)||(i[t]=e.message)}return Object.fromEntries(n.map(e=>[e,i[e]??``]))}let u=c.pick({username:!0,email:!0,age:!0,website:!0}),d=Object.keys(u.shape),f=[...d,`bio`],p={username:{label:`Username`,placeholder:`Enter username`,type:`text`},email:{label:`Email`,placeholder:`Enter email`,type:`email`},age:{label:`Age`,placeholder:`Enter age`,type:`number`},website:{label:`Website`,placeholder:`https://example.com`,type:`text`}},{data:m,state:{errors:h,hasErrors:g,isDirty:_,isDirtyByField:v}}=ia({username:``,email:``,age:0,website:``,bio:``},{validator:e=>l(c,e,f)}),y=()=>{m.username=`user${X()}`,m.email=`${X()}@example.com`,m.age=Ea(18,65),m.bio=`Hello, I am a demo user!`,m.website=`https://${X()}.com`},b=String.raw`import { z } from 'zod'; - -const userSchema = z.object({ - username: z.string().min(3).max(20).regex(/^\S+$/, 'Must not contain spaces'), - email: z.string().min(1, 'Required').email(), - age: z.number().int().min(18).max(120), - website: z.string().url().optional().or(z.literal('')), - bio: z.string().max(200).optional() -});`;ba(e,{description:`Demonstrates using Zod schemas for validation with svstate, including dynamic form rendering via z.pick() shape keys.`,title:`Zod Integration Demo`,main:e=>{var t=Jp(),o=I(t);Ta(o,{get hasErrors(){return n()},get isDirty(){return r()}});var s=L(o,2),c=F(s);$r(c,16,()=>d,e=>e,(e,t)=>{let n=j(()=>p[t]);{let r=j(()=>i()?.[t]),o=j(()=>t!==`website`);Y(e,{get id(){return t},get error(){return V(r)},get isDirty(){return a()[t]},get label(){return V(n).label},get placeholder(){return V(n).placeholder},get required(){return V(o)},get type(){return V(n).type},get value(){return m[t]},set value(e){m[t]=e}})}});var l=L(c,2);{let e=j(()=>i()?.bio);Qa(l,{id:`bio`,get error(){return V(e)},get isDirty(){return a().bio},label:`Bio`,placeholder:`Tell us about yourself (not in pick subset)`,get value(){return m.bio},set value(e){m.bio=e}})}k(s),W(e,t)},sidebar:e=>{fa(e,{get data(){return m},get errors(){return i()},get hasErrors(){return n()},get isDirty(){return r()},get isDirtyByField(){return a()},onFill:y})},sourceCode:e=>{Ca(e,{children:(e,t)=>{var n=Yp(),r=I(n);J(r,{get code(){return b},title:`Zod Schema Definition`});var i=L(r,2);J(i,{code:`function zodToSvstateErrors(schema, source, fields) { - const result = schema.safeParse(source); - if (result.success) - return Object.fromEntries(fields.map(f => [f, ''])); - - const errorMap = {}; - for (const issue of result.error.issues) { - const key = String(issue.path[0]); - if (!errorMap[key]) errorMap[key] = issue.message; - } - return Object.fromEntries( - fields.map(f => [f, errorMap[f] ?? '']) - ); -} - -const { data, state: { errors, hasErrors } } = createSvState(sourceData, { - validator: (source) => zodToSvstateErrors(userSchema, source, allFields) -});`,title:`Bridge Function (Zod → svstate)`}),J(L(i,2),{code:`// Pick a subset of fields for dynamic rendering -const pickedSchema = userSchema.pick({ username: true, email: true, age: true, website: true }); -const dynamicFields = Object.keys(pickedSchema.shape); - -const fieldMeta = { - username: { label: 'Username', placeholder: 'Enter username', type: 'text' }, - email: { label: 'Email', placeholder: 'Enter email', type: 'email' }, - age: { label: 'Age', placeholder: 'Enter age', type: 'number' }, - website: { label: 'Website', placeholder: 'https://...', type: 'text' }, -}; - -// In template: -{#each dynamicFields as field} - -{/each} - - -`,title:`Dynamic Rendering via z.pick()`}),W(e,n)},$$slots:{default:!0}})},$$slots:{main:!0,sidebar:!0,sourceCode:!0}}),Ge(),s()}var Zp=U(``),Qp=U(`
                    svstate logo

                    svstate

                    A Svelte 5 library that provides a supercharged $state() with deep reactive proxies, validation, snapshot/undo, - and side effects — built for complex, real-world applications.

                    $ npm i svstate
                    `);function $p(e){let t=[{value:`basic-validation`,name:`Basic Validation`},{value:`nested-objects`,name:`Nested Objects`},{value:`array-property`,name:`Array Property`},{value:`calculated-fields`,name:`Calculated Fields`},{value:`calculated-class`,name:`State with Methods`},{value:`reset-demo`,name:`Reset`},{value:`snapshot-demo`,name:`Snapshot & Rollback`},{value:`action-demo`,name:`Action & Error`},{value:`async-validation`,name:`Async Validation`},{value:`options-demo`,name:`Options`},{value:`zod-validation`,name:`Zod Integration`},{value:`plugin-devtools`,name:`Plugin: Devtools`},{value:`plugin-persist-sync`,name:`Plugin: Persist & Sync`},{value:`plugin-undo-redo`,name:`Plugin: Undo/Redo`},{value:`plugin-autosave-analytics`,name:`Plugin: Autosave & Analytics`}],n=N(`basic-validation`),r=`1.5.6`,i=`/svstate`;var a=Qp(),o=F(a),s=F(o),c=L(s,2),l=F(c),u=L(F(l),2),d=F(u);k(u),k(l);var f=L(l,4),p=L(F(f),4);k(f);var m=L(f,2);k(c),k(o);var h=L(o,2),g=F(h),_=F(g),v=L(F(_),2);$r(v,21,()=>t,Yr,(e,t)=>{var n=Zp(),r=F(n,!0);k(n);var i={};R(()=>{G(r,V(t).name),i!==(i=V(t).value)&&(n.value=(n.__value=V(t).value)??``)}),W(e,n)}),k(v),k(_),k(g);var y=L(g,2),b=F(y),x=e=>{to(e,{})},S=e=>{bo(e,{})},C=e=>{Ua(e,{})},w=e=>{uo(e,{})},T=e=>{so(e,{})},E=e=>{ms(e,{})},ee=e=>{Ss(e,{})},te=e=>{Na(e,{})},ne=e=>{Ya(e,{})},re=e=>{Oo(e,{})},ie=e=>{Xp(e,{})},ae=e=>{qo(e,{})},oe=e=>{es(e,{})},se=e=>{us(e,{})},ce=e=>{zo(e,{})};K(b,e=>{V(n)===`basic-validation`?e(x):V(n)===`nested-objects`?e(S,1):V(n)===`array-property`?e(C,2):V(n)===`calculated-fields`?e(w,3):V(n)===`calculated-class`?e(T,4):V(n)===`reset-demo`?e(E,5):V(n)===`snapshot-demo`?e(ee,6):V(n)===`action-demo`?e(te,7):V(n)===`async-validation`?e(ne,8):V(n)===`options-demo`?e(re,9):V(n)===`zod-validation`?e(ie,10):V(n)===`plugin-devtools`?e(ae,11):V(n)===`plugin-persist-sync`?e(oe,12):V(n)===`plugin-undo-redo`?e(se,13):V(n)===`plugin-autosave-analytics`&&e(ce,14)}),k(y),k(h),k(a),R(()=>{_i(s,`src`,`${i}/favicon.png`),G(d,`v${r}`),_i(m,`href`,`${i}/llms.txt`)}),H(`click`,p,()=>navigator.clipboard.writeText(`npm i svstate@${r}`)),di(v,()=>V(n),e=>P(n,e)),W(e,a)}Nr([`click`]),Hr($p,{target:document.querySelector(`#app`)}); \ No newline at end of file diff --git a/docs/assets/index-PZgML0IF.css b/docs/assets/index-PZgML0IF.css new file mode 100644 index 0000000..de49aa1 --- /dev/null +++ b/docs/assets/index-PZgML0IF.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.absolute{position:absolute}.relative{position:relative}.top-9{top:calc(var(--spacing) * 9)}.right-3{right:calc(var(--spacing) * 3)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-2{height:calc(var(--spacing) * 2)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-20{height:calc(var(--spacing) * 20)}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-20{width:calc(var(--spacing) * 20)}.w-full{width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-200{border-color:var(--color-amber-200)}.border-blue-200{border-color:var(--color-blue-200)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-green-200{border-color:var(--color-green-200)}.border-purple-200{border-color:var(--color-purple-200)}.border-red-200{border-color:var(--color-red-200)}.border-red-500{border-color:var(--color-red-500)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-200{background-color:var(--color-blue-200)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-orange-600{background-color:var(--color-orange-600)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-purple-100{background-color:var(--color-purple-100)}.bg-purple-200{background-color:var(--color-purple-200)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-600{background-color:var(--color-red-600)}.bg-white{background-color:var(--color-white)}.bg-yellow-100{background-color:var(--color-yellow-100)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-800{color:var(--color-blue-800)}.text-blue-900{color:var(--color-blue-900)}.text-emerald-800{color:var(--color-emerald-800)}.text-gray-100{color:var(--color-gray-100)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-green-800{color:var(--color-green-800)}.text-indigo-700{color:var(--color-indigo-700)}.text-indigo-800{color:var(--color-indigo-800)}.text-orange-800{color:var(--color-orange-800)}.text-purple-600{color:var(--color-purple-600)}.text-purple-800{color:var(--color-purple-800)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-800{color:var(--color-red-800)}.text-red-900{color:var(--color-red-900)}.text-white{color:var(--color-white)}.text-yellow-800{color:var(--color-yellow-800)}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.placeholder-red-400::placeholder{color:var(--color-red-400)}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-emerald-700:hover{background-color:var(--color-emerald-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-300:hover{background-color:var(--color-gray-300)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-indigo-200:hover{background-color:var(--color-indigo-200)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-orange-200:hover{background-color:var(--color-orange-200)}.hover\:bg-orange-700:hover{background-color:var(--color-orange-700)}.hover\:bg-purple-700:hover{background-color:var(--color-purple-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-purple-700:hover{color:var(--color-purple-700)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-red-500:focus{border-color:var(--color-red-500)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-amber-500:focus{--tw-ring-color:var(--color-amber-500)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-emerald-500:focus{--tw-ring-color:var(--color-emerald-500)}.focus\:ring-green-500:focus{--tw-ring-color:var(--color-green-500)}.focus\:ring-indigo-500:focus{--tw-ring-color:var(--color-indigo-500)}.focus\:ring-orange-500:focus{--tw-ring-color:var(--color-orange-500)}.focus\:ring-purple-500:focus{--tw-ring-color:var(--color-purple-500)}.focus\:ring-red-500:focus{--tw-ring-color:var(--color-red-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:no-underline:disabled{text-decoration-line:none}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:text-gray-600:disabled:hover{color:var(--color-gray-600)}}@media (width>=40rem){.sm\:mb-8{margin-bottom:calc(var(--spacing) * 8)}.sm\:inline-flex{display:inline-flex}.sm\:h-5{height:calc(var(--spacing) * 5)}.sm\:h-32{height:calc(var(--spacing) * 32)}.sm\:w-5{width:calc(var(--spacing) * 5)}.sm\:w-32{width:calc(var(--spacing) * 32)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:text-left{text-align:left}.sm\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.sm\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media (width>=48rem){.md\:p-8{padding:calc(var(--spacing) * 8)}}@media (width>=64rem){.lg\:w-64{width:calc(var(--spacing) * 64)}.lg\:flex-shrink-0{flex-shrink:0}.lg\:flex-row{flex-direction:row}.lg\:gap-6{gap:calc(var(--spacing) * 6)}}@media (width>=80rem){.xl\:w-80{width:calc(var(--spacing) * 80)}.xl\:w-96{width:calc(var(--spacing) * 96)}.xl\:flex-row{flex-direction:row}.xl\:gap-6{gap:calc(var(--spacing) * 6)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes spin{to{transform:rotate(360deg)}} diff --git a/docs/assets/index-RzZBKdI5.css b/docs/assets/index-RzZBKdI5.css deleted file mode 100644 index 929912e..0000000 --- a/docs/assets/index-RzZBKdI5.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-800:oklch(43.2% .095 166.913);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-700:oklch(49.6% .265 301.924);--color-purple-800:oklch(43.8% .218 303.724);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.top-9{top:calc(var(--spacing) * 9)}.right-3{right:calc(var(--spacing) * 3)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-2{height:calc(var(--spacing) * 2)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-20{height:calc(var(--spacing) * 20)}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-20{width:calc(var(--spacing) * 20)}.w-full{width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-200{border-color:var(--color-amber-200)}.border-blue-200{border-color:var(--color-blue-200)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-green-200{border-color:var(--color-green-200)}.border-purple-200{border-color:var(--color-purple-200)}.border-red-200{border-color:var(--color-red-200)}.border-red-500{border-color:var(--color-red-500)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-200{background-color:var(--color-blue-200)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-orange-600{background-color:var(--color-orange-600)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-purple-100{background-color:var(--color-purple-100)}.bg-purple-200{background-color:var(--color-purple-200)}.bg-purple-600{background-color:var(--color-purple-600)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-600{background-color:var(--color-red-600)}.bg-white{background-color:var(--color-white)}.bg-yellow-100{background-color:var(--color-yellow-100)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-800{color:var(--color-blue-800)}.text-blue-900{color:var(--color-blue-900)}.text-emerald-800{color:var(--color-emerald-800)}.text-gray-100{color:var(--color-gray-100)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-green-800{color:var(--color-green-800)}.text-indigo-800{color:var(--color-indigo-800)}.text-orange-800{color:var(--color-orange-800)}.text-purple-600{color:var(--color-purple-600)}.text-purple-800{color:var(--color-purple-800)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-800{color:var(--color-red-800)}.text-red-900{color:var(--color-red-900)}.text-white{color:var(--color-white)}.text-yellow-800{color:var(--color-yellow-800)}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.placeholder-red-400::placeholder{color:var(--color-red-400)}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-emerald-700:hover{background-color:var(--color-emerald-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-300:hover{background-color:var(--color-gray-300)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-orange-200:hover{background-color:var(--color-orange-200)}.hover\:bg-orange-700:hover{background-color:var(--color-orange-700)}.hover\:bg-purple-700:hover{background-color:var(--color-purple-700)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-purple-700:hover{color:var(--color-purple-700)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-red-500:focus{border-color:var(--color-red-500)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-amber-500:focus{--tw-ring-color:var(--color-amber-500)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-emerald-500:focus{--tw-ring-color:var(--color-emerald-500)}.focus\:ring-green-500:focus{--tw-ring-color:var(--color-green-500)}.focus\:ring-indigo-500:focus{--tw-ring-color:var(--color-indigo-500)}.focus\:ring-orange-500:focus{--tw-ring-color:var(--color-orange-500)}.focus\:ring-purple-500:focus{--tw-ring-color:var(--color-purple-500)}.focus\:ring-red-500:focus{--tw-ring-color:var(--color-red-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:no-underline:disabled{text-decoration-line:none}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:text-gray-600:disabled:hover{color:var(--color-gray-600)}}@media (width>=40rem){.sm\:mb-8{margin-bottom:calc(var(--spacing) * 8)}.sm\:inline-flex{display:inline-flex}.sm\:h-5{height:calc(var(--spacing) * 5)}.sm\:h-32{height:calc(var(--spacing) * 32)}.sm\:w-5{width:calc(var(--spacing) * 5)}.sm\:w-32{width:calc(var(--spacing) * 32)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:text-left{text-align:left}.sm\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.sm\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media (width>=48rem){.md\:p-8{padding:calc(var(--spacing) * 8)}}@media (width>=64rem){.lg\:w-64{width:calc(var(--spacing) * 64)}.lg\:flex-shrink-0{flex-shrink:0}.lg\:flex-row{flex-direction:row}.lg\:gap-6{gap:calc(var(--spacing) * 6)}}@media (width>=80rem){.xl\:w-80{width:calc(var(--spacing) * 80)}.xl\:w-96{width:calc(var(--spacing) * 96)}.xl\:flex-row{flex-direction:row}.xl\:gap-6{gap:calc(var(--spacing) * 6)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes spin{to{transform:rotate(360deg)}} diff --git a/docs/index.html b/docs/index.html index a331d8d..8de7780 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,8 +5,8 @@ svstate demo - - + + diff --git a/package-lock.json b/package-lock.json index 3269517..98bf2e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "svstate", - "version": "1.5.6", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "svstate", - "version": "1.5.6", + "version": "2.0.0", "license": "ISC", "devDependencies": { "@eslint/eslintrc": "^3.3.6", diff --git a/package.json b/package.json index 4f6e766..0e05805 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svstate", - "version": "1.5.6", + "version": "2.0.0", "description": "Supercharged $state() for Svelte 5: deep reactive proxy with validation, cross-field rules, computed & side-effects", "author": "BCsabaEngine", "license": "ISC", @@ -37,7 +37,7 @@ "clean": "tsc --build --clean", "build": "tsc --build --clean && tsc --build --force", "format:check": "prettier --check .", - "format:fix": "prettier --write . | grep -v 'unchanged' | sed G", + "format:fix": "prettier --write --list-different .", "lint:check": "eslint .", "lint:fix": "eslint --fix .", "fix": "node --run format:fix && node --run lint:fix && node --run format:fix", diff --git a/src/index.ts b/src/index.ts index fa1ee27..2a4ab23 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,13 +5,18 @@ export { type PluginStores, type SvStatePlugin } from './plugin'; -export { type AnalyticsEvent, type AnalyticsOptions, analyticsPlugin } from './plugins/analytics'; -export { type AutosaveOptions, autosavePlugin } from './plugins/autosave'; +export { + type AnalyticsEvent, + type AnalyticsOptions, + analyticsPlugin, + type AnalyticsPluginInstance +} from './plugins/analytics'; +export { type AutosaveOptions, autosavePlugin, type AutosavePluginInstance } from './plugins/autosave'; export { type DevtoolsOptions, devtoolsPlugin } from './plugins/devtools'; export { type HistoryOptions, historyPlugin, type HistoryPluginInstance } from './plugins/history'; -export { type PersistOptions, persistPlugin } from './plugins/persist'; +export { type PersistOptions, persistPlugin, type PersistPluginInstance } from './plugins/persist'; export { type SyncOptions, syncPlugin, type SyncPluginInstance } from './plugins/sync'; -export { undoRedoPlugin, type UndoRedoPluginInstance } from './plugins/undo-redo'; +export { type UndoRedoOptions, undoRedoPlugin, type UndoRedoPluginInstance } from './plugins/undo-redo'; export { type AsyncErrors, type AsyncValidator, @@ -19,9 +24,11 @@ export { createSvState, type DirtyFields, type EffectContext, + type PluginHook, type Snapshot, type SnapshotFunction, type SvStateOptions, + type ValidationResult, type Validator } from './state.svelte'; export { arrayValidator, dateValidator, numberValidator, stringValidator } from './validators'; diff --git a/src/internal/clone.ts b/src/internal/clone.ts new file mode 100644 index 0000000..fb671de --- /dev/null +++ b/src/internal/clone.ts @@ -0,0 +1,64 @@ +import { DANGEROUS_KEYS } from './paths'; + +// Values that cannot be meaningfully reconstructed by copying own keys. +// They are carried over by reference rather than being turned into broken look-alikes. +const isCarriedByReference = (value: object): boolean => + value instanceof Promise || + value instanceof WeakMap || + value instanceof WeakSet || + value instanceof WeakRef || + value instanceof Error || + value instanceof ArrayBuffer || + ArrayBuffer.isView(value); + +/** + * Structural clone that preserves prototypes (so methods on the state object keep working) + * and reconstructs Map/Set/RegExp instead of producing empty look-alikes. Circular references + * resolve to the already-cloned instance. + */ +export const deepClone = (object: T, seen: WeakMap = new WeakMap()): T => { + if (object === null || typeof object !== 'object') return object; + + const reference = object as object; + if (seen.has(reference)) return seen.get(reference) as T; + + if (object instanceof Date) return new Date(object) as T; + if (object instanceof RegExp) { + const clonedRegexp = new RegExp(object.source, object.flags); + clonedRegexp.lastIndex = object.lastIndex; + return clonedRegexp as T; + } + if (isCarriedByReference(reference)) return object; + + if (Array.isArray(object)) { + const cloned: unknown[] = []; + seen.set(reference, cloned); + for (const item of object) cloned.push(deepClone(item, seen)); + return cloned as T; + } + + if (object instanceof Map) { + const cloned = new Map(); + seen.set(reference, cloned); + for (const [key, value] of object) cloned.set(deepClone(key, seen), deepClone(value, seen)); + return cloned as T; + } + + if (object instanceof Set) { + const cloned = new Set(); + seen.set(reference, cloned); + for (const value of object) cloned.add(deepClone(value, seen)); + return cloned as T; + } + + const cloned = Object.create(Object.getPrototypeOf(reference)) as Record; + seen.set(reference, cloned); + for (const [key, value] of Object.entries(reference)) { + if (DANGEROUS_KEYS.has(key)) continue; + const descriptor = Object.getOwnPropertyDescriptor(reference, key); + // Keep getters/setters as accessors rather than freezing them into a value + if (descriptor && (descriptor.get || descriptor.set)) Object.defineProperty(cloned, key, descriptor); + else cloned[key] = deepClone(value, seen); + } + return cloned as T; +}; diff --git a/src/internal/errors.ts b/src/internal/errors.ts new file mode 100644 index 0000000..ca51747 --- /dev/null +++ b/src/internal/errors.ts @@ -0,0 +1,20 @@ +import type { Validator } from '../state.svelte'; + +/** True when any leaf of the (possibly nested) validator result is a non-empty string. */ +const hasValidatorErrors = (validator: Validator): boolean => + Object.values(validator).some((item) => (typeof item === 'string' ? !!item : hasValidatorErrors(item))); + +export const hasAnyErrors = ($errors: Validator | undefined): boolean => !!$errors && hasValidatorErrors($errors); + +/** + * Normalizes anything thrown into an Error. Non-Error objects are unwrapped by reading + * `.message`, then `.body.message`, before falling back to `String()`. + */ +export const toError = (thrown: unknown): Error => { + if (thrown instanceof Error) return thrown; + if (thrown !== null && typeof thrown === 'object') { + const candidate = thrown as { message?: unknown; body?: { message?: unknown } }; + return new Error(String(candidate.message ?? candidate.body?.message ?? thrown)); + } + return new Error(String(thrown)); +}; diff --git a/src/internal/paths.ts b/src/internal/paths.ts new file mode 100644 index 0000000..a80d0d6 --- /dev/null +++ b/src/internal/paths.ts @@ -0,0 +1,50 @@ +// Shared path/merge helpers used by the core state and by plugins. +// Internal module — not part of the public API surface. + +export const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']); + +export const isPlainObject = (value: unknown): value is Record => + value !== null && typeof value === 'object' && !Array.isArray(value); + +/** Views a typed state object as an indexable record for path walking. */ +export const asRecord = (value: object): Record => value as Record; + +/** + * Selects the registered dot-notation paths affected by a change at `changedPath`. + * A path matches when it is the changed path itself, a descendant of it (changing + * `user` affects `user.email`), or an ancestor of it (changing `user.email` affects `user`). + */ +export const getMatchingPaths = (registeredPaths: string[], changedPath: string): string[] => + registeredPaths.filter( + (registeredPath) => + registeredPath === changedPath || + registeredPath.startsWith(changedPath + '.') || + changedPath.startsWith(registeredPath + '.') + ); + +export const getValueAtPath = (source: unknown, path: string): unknown => { + const parts = path.split('.'); + let current: unknown = source; + for (const part of parts) { + if (current === null || current === undefined) return undefined; + current = (current as Record)[part]; + } + return current; +}; + +export const setValueAtPath = (target: Record, path: string, value: unknown): void => { + const parts = path.split('.'); + let current: Record = target; + for (let index = 0; index < parts.length - 1; index++) { + const part = parts[index]!; + if (DANGEROUS_KEYS.has(part)) return; + if (current[part] === undefined || current[part] === null) current[part] = {}; + current = current[part] as Record; + } + const lastPart = parts.at(-1)!; + if (!DANGEROUS_KEYS.has(lastPart)) current[lastPart] = value; +}; + +export const safeMerge = (target: Record, source: Record): void => { + for (const [key, value] of Object.entries(source)) if (!DANGEROUS_KEYS.has(key)) target[key] = value; +}; diff --git a/src/internal/timers.ts b/src/internal/timers.ts new file mode 100644 index 0000000..d112a12 --- /dev/null +++ b/src/internal/timers.ts @@ -0,0 +1,43 @@ +// Shared timer helpers used by the plugins. +// Internal module — not part of the public API surface. + +export type Debouncer = { + /** (Re)starts the delay; `run` fires once the delay elapses without another call. */ + schedule(): void; + /** Drops a pending run without executing it. */ + cancel(): void; + /** Runs `run` immediately if one is pending, otherwise does nothing. */ + flush(): void; + isPending(): boolean; +}; + +/** + * Trailing-edge debounce: a burst of `schedule()` calls collapses into a single `run` + * fired `delayMs` after the last one. + */ +export const createDebouncer = (run: () => void, delayMs: number): Debouncer => { + let timeoutId: ReturnType | undefined; + + const cancel = () => { + if (timeoutId === undefined) return; + clearTimeout(timeoutId); + timeoutId = undefined; + }; + + return { + schedule() { + cancel(); + timeoutId = setTimeout(() => { + timeoutId = undefined; + run(); + }, delayMs); + }, + cancel, + flush() { + if (timeoutId === undefined) return; + cancel(); + run(); + }, + isPending: () => timeoutId !== undefined + }; +}; diff --git a/src/plugin.ts b/src/plugin.ts index 1a1387e..01267fa 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,20 +1,7 @@ -import type { Readable } from 'svelte/store'; +import type { Snapshot, SnapshotFunction, StateResult, SvStateOptions, Validator } from './state.svelte'; -import type { AsyncErrors, DirtyFields, Snapshot, SnapshotFunction, SvStateOptions, Validator } from './state.svelte'; - -export type PluginStores = { - errors: Readable; - hasErrors: Readable; - isDirty: Readable; - isDirtyByField: Readable; - actionInProgress: Readable; - actionError: Readable; - snapshots: Readable[]>; - asyncErrors: Readable; - hasAsyncErrors: Readable; - asyncValidating: Readable; - hasCombinedErrors: Readable; -}; +/** The same stores `createSvState` returns, with errors widened to the untyped shape. */ +export type PluginStores = StateResult; export type PluginContext> = { data: T; diff --git a/src/plugins/analytics.ts b/src/plugins/analytics.ts index 5436de4..53d12e0 100644 --- a/src/plugins/analytics.ts +++ b/src/plugins/analytics.ts @@ -1,3 +1,4 @@ +import { hasAnyErrors } from '../internal/errors'; import type { SvStatePlugin } from '../plugin'; export type AnalyticsEvent = { @@ -12,11 +13,17 @@ export type AnalyticsOptions = { flushInterval?: number; include?: AnalyticsEvent['type'][]; redact?: string[]; + onError?: (error: unknown) => void; +}; + +export type AnalyticsPluginInstance> = SvStatePlugin & { + flush(): void; + eventCount(): number; }; export function analyticsPlugin>( options: AnalyticsOptions -): SvStatePlugin & { flush(): void; eventCount(): number } { +): AnalyticsPluginInstance { const batchSize = options.batchSize ?? 20; const flushInterval = options.flushInterval ?? 5000; const include = options.include; @@ -26,20 +33,33 @@ export function analyticsPlugin>( const shouldTrack = (type: AnalyticsEvent['type']) => !include || include.includes(type); + // A redacted path covers everything below it: redact 'user' also redacts 'user.ssn' + const isRedacted = (property: string) => + options.redact?.some((path) => property === path || property.startsWith(path + '.')) ?? false; + const addEvent = (type: AnalyticsEvent['type'], detail: Record) => { if (!shouldTrack(type)) return; buffer.push({ type, timestamp: Date.now(), detail }); if (buffer.length >= batchSize) doFlush(); }; + // A failing sink must never take down the state it is observing + const flushEvents = async (events: AnalyticsEvent[]) => { + try { + await options.onFlush(events); + } catch (error) { + options.onError?.(error); + } + }; + const doFlush = () => { if (buffer.length === 0) return; const events = buffer.slice(); buffer.length = 0; - options.onFlush(events); + void flushEvents(events); }; - const plugin: SvStatePlugin & { flush(): void; eventCount(): number } = { + const plugin: AnalyticsPluginInstance = { name: 'analytics', onInit() { @@ -47,16 +67,16 @@ export function analyticsPlugin>( }, onChange(event) { - const isRedacted = options.redact?.includes(event.property); + const redacted = isRedacted(event.property); addEvent('change', { property: event.property, - currentValue: isRedacted ? '[redacted]' : event.currentValue, - oldValue: isRedacted ? '[redacted]' : event.oldValue + currentValue: redacted ? '[redacted]' : event.currentValue, + oldValue: redacted ? '[redacted]' : event.oldValue }); }, onValidation(errors) { - addEvent('validation', { hasErrors: errors !== undefined }); + addEvent('validation', { hasErrors: hasAnyErrors(errors) }); }, onSnapshot(snapshot) { diff --git a/src/plugins/autosave.ts b/src/plugins/autosave.ts index 6d12d22..4162ac3 100644 --- a/src/plugins/autosave.ts +++ b/src/plugins/autosave.ts @@ -1,5 +1,6 @@ import { get } from 'svelte/store'; +import { createDebouncer } from '../internal/timers'; import type { PluginContext, SvStatePlugin } from '../plugin'; export type AutosaveOptions = { @@ -12,24 +13,34 @@ export type AutosaveOptions = { onError?: (error: unknown) => void; }; +export type AutosavePluginInstance> = SvStatePlugin & { + saveNow(): Promise; + isSaving(): boolean; +}; + export function autosavePlugin>( options: AutosaveOptions -): SvStatePlugin & { saveNow(): Promise; isSaving(): boolean } { +): AutosavePluginInstance { const idleMs = options.idle ?? 1000; const intervalMs = options.interval ?? 0; const saveOnDestroy = options.saveOnDestroy ?? true; const onlyWhenDirty = options.onlyWhenDirty ?? true; let context: PluginContext | undefined; - let idleTimeout: ReturnType | undefined; let intervalTimer: ReturnType | undefined; + let hasVisibilityListener = false; let isSaving = false; let isDestroyed = false; + let hasPendingSave = false; const doSave = async () => { if (!context) return; if (onlyWhenDirty && !get(context.state.isDirty)) return; - if (isSaving) return; + // A save requested mid-flight is not dropped — it runs once the current one settles + if (isSaving) { + hasPendingSave = true; + return; + } isSaving = true; try { @@ -39,18 +50,20 @@ export function autosavePlugin>( } finally { isSaving = false; } - }; - const scheduleIdleSave = () => { - clearTimeout(idleTimeout); - idleTimeout = setTimeout(doSave, idleMs); + if (hasPendingSave && !isDestroyed) { + hasPendingSave = false; + await doSave(); + } }; + const idleSaver = createDebouncer(() => void doSave(), idleMs); + const handleVisibility = () => { if (typeof document !== 'undefined' && document.visibilityState === 'hidden') doSave(); }; - const plugin: SvStatePlugin & { saveNow(): Promise; isSaving(): boolean } = { + const plugin: AutosavePluginInstance = { name: 'autosave', onInit(context_) { @@ -58,47 +71,43 @@ export function autosavePlugin>( if (intervalMs > 0) intervalTimer = setInterval(doSave, intervalMs); - if (typeof document !== 'undefined' && options.onVisibilityHidden) + if (typeof document !== 'undefined' && options.onVisibilityHidden) { document.addEventListener('visibilitychange', handleVisibility); + hasVisibilityListener = true; + } }, onChange() { - scheduleIdleSave(); + idleSaver.schedule(); }, onAction(event) { - if (event.phase === 'after' && !event.error) clearTimeout(idleTimeout); + if (event.phase === 'after' && !event.error) idleSaver.cancel(); }, destroy() { isDestroyed = true; - clearTimeout(idleTimeout); + hasPendingSave = false; + idleSaver.cancel(); if (intervalTimer !== undefined) clearInterval(intervalTimer); - if (typeof document !== 'undefined') document.removeEventListener('visibilitychange', handleVisibility); + if (hasVisibilityListener) { + document.removeEventListener('visibilitychange', handleVisibility); + hasVisibilityListener = false; + } + // Fire-and-forget: doSave already applies the onlyWhenDirty check and the error guard if (saveOnDestroy && context) { isSaving = false; - const activeContext = context; - // Fire-and-forget save on destroy - const shouldSave = !onlyWhenDirty || get(activeContext.state.isDirty); - if (shouldSave) { - const trySave = async () => { - try { - await options.save(activeContext.data); - } catch (error) { - options.onError?.(error); - } - }; - void trySave(); - } + void doSave(); } }, async saveNow() { if (isDestroyed) return; - clearTimeout(idleTimeout); + idleSaver.cancel(); isSaving = false; + hasPendingSave = false; await doSave(); }, diff --git a/src/plugins/history.ts b/src/plugins/history.ts index 4e0e32d..1db7854 100644 --- a/src/plugins/history.ts +++ b/src/plugins/history.ts @@ -1,46 +1,21 @@ +import { asRecord, DANGEROUS_KEYS, getMatchingPaths, getValueAtPath, setValueAtPath } from '../internal/paths'; import type { PluginContext, SvStatePlugin } from '../plugin'; -const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']); - export type HistoryOptions = { fields: Record; mode?: 'push' | 'replace'; deserialize?: (parameter: string, field: string) => unknown; serialize?: (value: unknown, field: string) => string; + onError?: (error: unknown) => void; }; export type HistoryPluginInstance> = SvStatePlugin & { syncFromUrl(): void; }; -const isNullOrUndefined = (value: unknown): boolean => value === undefined || value === null; - const defaultSerialize: (value: unknown, field: string) => string = String; const defaultDeserialize: (parameter: string, field: string) => unknown = (parameter) => parameter; -const getValueAtPath = (source: Record, path: string): unknown => { - const parts = path.split('.'); - let current: unknown = source; - for (const part of parts) { - if (current === null || current === undefined) return undefined; - current = (current as Record)[part]; - } - return current; -}; - -const setValueAtPath = (target: Record, path: string, value: unknown): void => { - const parts = path.split('.'); - let current: Record = target; - for (let index = 0; index < parts.length - 1; index++) { - const part = parts[index]!; - if (DANGEROUS_KEYS.has(part)) return; - if (current[part] === undefined || current[part] === null) current[part] = {}; - current = current[part] as Record; - } - const lastPart = parts.at(-1)!; - if (!DANGEROUS_KEYS.has(lastPart)) current[lastPart] = value; -}; - export function historyPlugin>(options: HistoryOptions): HistoryPluginInstance { const mode = options.mode ?? 'replace'; const serialize = options.serialize ?? defaultSerialize; @@ -55,9 +30,12 @@ export function historyPlugin>(options: Histor for (const [stateField, urlParameter] of Object.entries(options.fields)) { if (stateField.split('.').some((part) => DANGEROUS_KEYS.has(part))) continue; const parameterValue = parameters.get(urlParameter); - if (parameterValue !== null) { - const value = deserialize(parameterValue, stateField); - setValueAtPath(context.data as unknown as Record, stateField, value); + if (parameterValue === null) continue; + try { + setValueAtPath(asRecord(context.data), stateField, deserialize(parameterValue, stateField)); + } catch (error) { + // A throwing user deserializer must not break the remaining fields, nor escape popstate + options.onError?.(error); } } }; @@ -67,11 +45,16 @@ export function historyPlugin>(options: Histor const urlParameter = options.fields[stateField]; if (!urlParameter) return; - const value = getValueAtPath(context.data as unknown as Record, stateField); + const value = getValueAtPath(asRecord(context.data), stateField); const url = new URL(window.location.href); - if (value === '' || isNullOrUndefined(value)) url.searchParams.delete(urlParameter); - else url.searchParams.set(urlParameter, serialize(value, stateField)); + try { + if (value === '' || value == undefined) url.searchParams.delete(urlParameter); + else url.searchParams.set(urlParameter, serialize(value, stateField)); + } catch (error) { + options.onError?.(error); + return; + } if (mode === 'push') window.history.pushState({}, '', url.href); else window.history.replaceState({}, '', url.href); @@ -91,7 +74,10 @@ export function historyPlugin>(options: Histor }, onChange(event) { - if (Object.hasOwn(options.fields, event.property)) updateUrl(event.property); + // Dotted fields must react both ways: replacing `filters` affects the registered + // `filters.q`, and mutating `filters.q` affects a registered `filters`. + const affectedFields = getMatchingPaths(Object.keys(options.fields), event.property); + for (const stateField of affectedFields) updateUrl(stateField); }, destroy() { diff --git a/src/plugins/persist.ts b/src/plugins/persist.ts index ad781e2..882558d 100644 --- a/src/plugins/persist.ts +++ b/src/plugins/persist.ts @@ -1,19 +1,12 @@ +import { asRecord, getValueAtPath, isPlainObject, safeMerge, setValueAtPath } from '../internal/paths'; +import { createDebouncer } from '../internal/timers'; import type { SvStatePlugin } from '../plugin'; -const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']); - -const isPlainObject = (value: unknown): value is Record => - value !== null && typeof value === 'object' && !Array.isArray(value); - const isValidStorageFormat = (value: unknown): value is StorageFormat => isPlainObject(value) && typeof (value as StorageFormat).version === 'number' && isPlainObject((value as StorageFormat).data); -const safeMerge = (target: Record, source: Record): void => { - for (const [key, value] of Object.entries(source)) if (!DANGEROUS_KEYS.has(key)) target[key] = value; -}; - export type PersistOptions = { key: string; storage?: { @@ -26,6 +19,7 @@ export type PersistOptions = { migrate?: (persisted: unknown, version: number) => unknown; include?: string[]; exclude?: string[]; + onError?: (error: unknown) => void; }; type StorageFormat = { @@ -33,29 +27,6 @@ type StorageFormat = { data: Record; }; -const getValueAtPath = (source: Record, path: string): unknown => { - const parts = path.split('.'); - let current: unknown = source; - for (const part of parts) { - if (current === null || current === undefined) return undefined; - current = (current as Record)[part]; - } - return current; -}; - -const setValueAtPath = (target: Record, path: string, value: unknown): void => { - const parts = path.split('.'); - let current: Record = target; - for (let index = 0; index < parts.length - 1; index++) { - const part = parts[index]!; - if (DANGEROUS_KEYS.has(part)) return; - if (current[part] === undefined || current[part] === null) current[part] = {}; - current = current[part] as Record; - } - const lastPart = parts.at(-1)!; - if (!DANGEROUS_KEYS.has(lastPart)) current[lastPart] = value; -}; - const excludePath = (filtered: Record, path: string): void => { const parts = path.split('.'); if (parts.length === 1) { @@ -94,30 +65,34 @@ const filterData = (data: Record, include?: string[], exclude?: return data; }; -export function persistPlugin>( - options: PersistOptions -): SvStatePlugin & { clearPersistedState(): void; isRestored(): boolean } { +export type PersistPluginInstance> = SvStatePlugin & { + clearPersistedState(): void; + isRestored(): boolean; +}; + +export function persistPlugin>(options: PersistOptions): PersistPluginInstance { const storage = options.storage ?? (typeof localStorage === 'undefined' ? undefined : localStorage); const throttleMs = options.throttle ?? 300; const version = options.version ?? 1; let isRestored = false; - let pendingTimeout: ReturnType | undefined; let contextData: T | undefined; const writeToStorage = () => { if (!storage || !contextData) return; - const filtered = filterData(contextData as unknown as Record, options.include, options.exclude); - const payload: StorageFormat = { version, data: filtered }; - storage.setItem(options.key, JSON.stringify(payload)); + try { + const filtered = filterData(asRecord(contextData), options.include, options.exclude); + const payload: StorageFormat = { version, data: filtered }; + storage.setItem(options.key, JSON.stringify(payload)); + } catch (error) { + // Quota exceeded, unserializable state, blocked storage — never throw out of a timer + options.onError?.(error); + } }; - const scheduleWrite = () => { - clearTimeout(pendingTimeout); - pendingTimeout = setTimeout(writeToStorage, throttleMs); - }; + const writer = createDebouncer(writeToStorage, throttleMs); - const plugin: SvStatePlugin & { clearPersistedState(): void; isRestored(): boolean } = { + const plugin: PersistPluginInstance = { name: 'persist', onInit(context) { @@ -138,7 +113,7 @@ export function persistPlugin>( parsed = { version, data: migrated }; } - safeMerge(context.data as unknown as Record, parsed.data); + safeMerge(asRecord(context.data), parsed.data); isRestored = true; } catch { // Invalid stored data — ignore @@ -146,18 +121,16 @@ export function persistPlugin>( }, onChange() { - scheduleWrite(); + writer.schedule(); }, onReset() { writeToStorage(); }, + // Idempotent: only a still-pending write is flushed, so a second destroy() is a no-op destroy() { - if (pendingTimeout === undefined) return; - - clearTimeout(pendingTimeout); - writeToStorage(); + writer.flush(); }, clearPersistedState() { diff --git a/src/plugins/sync.ts b/src/plugins/sync.ts index e765410..b59362d 100644 --- a/src/plugins/sync.ts +++ b/src/plugins/sync.ts @@ -1,10 +1,7 @@ +import { asRecord, isPlainObject, safeMerge } from '../internal/paths'; +import { createDebouncer } from '../internal/timers'; import type { PluginContext, SvStatePlugin } from '../plugin'; -const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']); - -const isPlainObject = (value: unknown): value is Record => - value !== null && typeof value === 'object' && !Array.isArray(value); - const MAX_SYNC_DEPTH = 10; const isWithinDepthLimit = (value: unknown, depth = 0): boolean => { @@ -13,14 +10,11 @@ const isWithinDepthLimit = (value: unknown, depth = 0): boolean => { return Object.values(value).every((v) => isWithinDepthLimit(v, depth + 1)); }; -const safeMerge = (target: Record, source: Record): void => { - for (const [key, value] of Object.entries(source)) if (!DANGEROUS_KEYS.has(key)) target[key] = value; -}; - export type SyncOptions = { key: string; throttle?: number; merge?: 'overwrite' | 'ignore'; + onError?: (error: unknown) => void; }; export type SyncPluginInstance> = SvStatePlugin & { @@ -34,24 +28,62 @@ export function syncPlugin>(options: SyncOptio let channel: BroadcastChannel | undefined; let context: PluginContext | undefined; let isReceiving = false; - let pendingTimeout: ReturnType | undefined; let lastReceivedAt = 0; + let pendingIncoming: Record | undefined; + let incomingTimeout: ReturnType | undefined; const broadcast = () => { if (!channel || !context) return; - // eslint-disable-next-line unicorn/prefer-structured-clone -- structuredClone fails on Svelte reactive proxies - const cloned = JSON.parse(JSON.stringify(context.data)) as T; + try { + // eslint-disable-next-line unicorn/prefer-structured-clone -- structuredClone fails on Svelte reactive proxies + const cloned = JSON.parse(JSON.stringify(context.data)) as T; + + channel.postMessage({ type: 'sync', data: cloned }); + } catch (error) { + // Circular structures, BigInt, a closed channel — never throw out of a timer + options.onError?.(error); + } + }; - channel.postMessage({ type: 'sync', data: cloned }); + const broadcaster = createDebouncer(broadcast, throttleMs); + + const applyIncoming = (payload: Record) => { + if (!context) return; + isReceiving = true; + try { + safeMerge(asRecord(context.data), payload); + } finally { + isReceiving = false; + } }; - const scheduleBroadcast = () => { - clearTimeout(pendingTimeout); - pendingTimeout = setTimeout(broadcast, throttleMs); + // Throttle inbound messages without dropping the newest one: bursts collapse to the last payload, + // which is applied when the window closes. + const queueIncoming = (payload: Record) => { + const elapsed = Date.now() - lastReceivedAt; + if (elapsed >= throttleMs) { + lastReceivedAt = Date.now(); + applyIncoming(payload); + return; + } + + pendingIncoming = payload; + if (incomingTimeout !== undefined) return; + incomingTimeout = setTimeout(() => { + incomingTimeout = undefined; + const next = pendingIncoming; + pendingIncoming = undefined; + if (!next) return; + lastReceivedAt = Date.now(); + applyIncoming(next); + }, throttleMs - elapsed); }; const closeChannel = () => { - clearTimeout(pendingTimeout); + broadcaster.cancel(); + clearTimeout(incomingTimeout); + incomingTimeout = undefined; + pendingIncoming = undefined; if (channel) { channel.close(); channel = undefined; @@ -70,22 +102,16 @@ export function syncPlugin>(options: SyncOptio if (!context || merge === 'ignore') return; if (event.data?.type !== 'sync') return; - const now = Date.now(); - if (now - lastReceivedAt < throttleMs) return; - lastReceivedAt = now; - if (!isPlainObject(event.data.data)) return; if (!isWithinDepthLimit(event.data.data)) return; - isReceiving = true; - safeMerge(context.data as unknown as Record, event.data.data); - isReceiving = false; + queueIncoming(event.data.data); }); }, onChange() { if (isReceiving) return; - scheduleBroadcast(); + broadcaster.schedule(); }, destroy() { diff --git a/src/plugins/undo-redo.ts b/src/plugins/undo-redo.ts index 860a7dd..5b1c52c 100644 --- a/src/plugins/undo-redo.ts +++ b/src/plugins/undo-redo.ts @@ -1,5 +1,6 @@ import { get, type Readable, writable } from 'svelte/store'; +import { deepClone } from '../internal/clone'; import type { PluginContext, SvStatePlugin } from '../plugin'; import type { Snapshot } from '../state.svelte'; @@ -21,15 +22,7 @@ export function undoRedoPlugin>( let context: PluginContext | undefined; let unsubscribe: (() => void) | undefined; let previousTipSnapshot: Snapshot | undefined; - - const deepClone = (object: U): U => { - if (object === null || typeof object !== 'object') return object; - if (object instanceof Date) return new Date(object) as U; - if (Array.isArray(object)) return object.map((item) => deepClone(item)) as U; - const cloned = Object.create(Object.getPrototypeOf(object)) as U; - for (const key of Object.keys(object)) cloned[key as keyof U] = deepClone(object[key as keyof U]); - return cloned; - }; + let isApplyingRedo = false; const plugin: UndoRedoPluginInstance = { name: 'undo-redo', @@ -60,6 +53,8 @@ export function undoRedoPlugin>( }, onChange() { + // Applying a redo mutates state; that must not wipe the rest of the redo stack. + if (isApplyingRedo) return; redoStore.set([]); }, @@ -75,11 +70,16 @@ export function undoRedoPlugin>( const targetSnapshot = stack.at(-1)!; redoStore.set(stack.slice(0, -1)); - // Create a snapshot of current state before redo - context.snapshot('Undo'); - - // Apply the redo target data - Object.assign(context.data, deepClone(targetSnapshot.data)); + isApplyingRedo = true; + try { + // Create a snapshot of current state before redo. Each redo step keeps its own + // snapshot, so a later rollback undoes one step at a time. + context.snapshot('Undo', false); + // Apply the redo target data + Object.assign(context.data, deepClone(targetSnapshot.data)); + } finally { + isApplyingRedo = false; + } }, canRedo() { diff --git a/src/proxy.ts b/src/proxy.ts index 44de3c3..2c76fc0 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -5,6 +5,12 @@ export type ProxyChanged = ( oldValue: unknown ) => void; +/** Reading this symbol off a change proxy yields the underlying raw object. */ +const RAW = Symbol('svstate.raw'); + +/** Canonical array index (no leading zeros, no sign, no whitespace). */ +const ARRAY_INDEX = /^(?:0|[1-9]\d*)$/; + const isProxiable = (value: unknown): boolean => typeof value === 'object' && value !== null && @@ -17,35 +23,74 @@ const isProxiable = (value: unknown): boolean => !(value instanceof Error) && !(value instanceof Promise); +const unwrap = (value: unknown): unknown => { + if (typeof value !== 'object' || value === null) return value; + return (value as Record)[RAW] ?? value; +}; + +// Array element and length writes are reported on the array itself; every other key — +// including numeric-looking keys on plain objects — keeps its own path segment. +const resolvePath = (object: object, property: string, parentPath: string): string => { + if (Array.isArray(object) && (property === 'length' || ARRAY_INDEX.test(property))) return parentPath; + return parentPath ? `${parentPath}.${property}` : property; +}; + export const ChangeProxy = (source: T, changed: ProxyChanged): T => { - const createProxy = (target: object, parentPath: string): object => - new Proxy(target, { + // raw object -> path -> proxy. The same object can be reachable through several paths, so the + // path is part of the key. WeakRef values keep the cache from pinning raw objects in memory. + const proxyCache = new WeakMap>>(); + + const createProxy = (target: object, parentPath: string): object => { + let byPath = proxyCache.get(target); + if (byPath) { + const cached = byPath.get(parentPath)?.deref(); + if (cached) return cached; + } else { + byPath = new Map(); + proxyCache.set(target, byPath); + } + + const proxy = new Proxy(target, { get(object, property) { + if (property === RAW) return object; if (typeof property === 'symbol') return (object as Record)[property]; const value = (object as Record)[property]; - if (isProxiable(value)) { - const pathSegment = Number.isSafeInteger(Number(property)) ? '' : String(property); - const childPath = pathSegment ? (parentPath ? `${parentPath}.${pathSegment}` : pathSegment) : parentPath; - return createProxy(value as object, childPath); - } + if (isProxiable(value)) return createProxy(value as object, resolvePath(object, property, parentPath)); return value; }, + set(object, property, incomingValue) { if (typeof property === 'symbol') { (object as Record)[property] = incomingValue; return true; } + // Storing a proxy inside the raw tree would make later mutations report the path the + // value was read from rather than the one it was written to. + const nextValue = unwrap(incomingValue); const oldValue = (object as Record)[property]; - if (oldValue !== incomingValue) { - (object as Record)[property] = incomingValue; - const pathSegment = Number.isSafeInteger(Number(property)) ? '' : String(property); - const fullPath = pathSegment ? (parentPath ? `${parentPath}.${pathSegment}` : pathSegment) : parentPath; - changed(data as T, fullPath, incomingValue, oldValue); - } + if (Object.is(oldValue, nextValue)) return true; + + (object as Record)[property] = nextValue; + changed(data as T, resolvePath(object, property, parentPath), nextValue, oldValue); + return true; + }, + + deleteProperty(object, property) { + if (typeof property === 'symbol') return Reflect.deleteProperty(object, property); + if (!Object.hasOwn(object, property)) return true; + + const oldValue = (object as Record)[property]; + if (!Reflect.deleteProperty(object, property)) return false; + + changed(data as T, resolvePath(object, property, parentPath), undefined, oldValue); return true; } }); + byPath.set(parentPath, new WeakRef(proxy)); + return proxy; + }; + const data = createProxy(source, ''); return data as T; }; diff --git a/src/state.svelte.ts b/src/state.svelte.ts index 159d666..85b3726 100644 --- a/src/state.svelte.ts +++ b/src/state.svelte.ts @@ -1,5 +1,8 @@ import { derived, get, type Readable, writable } from 'svelte/store'; +import { deepClone } from './internal/clone'; +import { hasAnyErrors, toError } from './internal/errors'; +import { getMatchingPaths, getValueAtPath, isPlainObject } from './internal/paths'; import type { SvStatePlugin } from './plugin'; import { ChangeProxy } from './proxy'; @@ -38,6 +41,11 @@ export type DirtyFields = { [propertyPath: string]: boolean; }; +export type ValidationResult = { + errors: V | undefined; + hasErrors: boolean; +}; + type Actuators, V extends Validator, P extends object> = { validator?: (source: T) => V; effect?: (context: EffectContext) => void; @@ -46,7 +54,7 @@ type Actuators, V extends Validator, P extends asyncValidator?: AsyncValidator; }; -type StateResult = { +export type StateResult = { errors: Readable; hasErrors: Readable; isDirty: Readable; @@ -60,62 +68,23 @@ type StateResult = { hasCombinedErrors: Readable; }; -// Helpers -const hasValidatorErrors = (validator: Validator): boolean => - Object.values(validator).some((item) => (typeof item === 'string' ? !!item : hasValidatorErrors(item))); -const hasAnyErrors = ($errors: Validator | undefined): boolean => !!$errors && hasValidatorErrors($errors); - -const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']); - -const deepClone = (object: T): T => { - if (object === null || typeof object !== 'object') return object; - if (object instanceof Date) return new Date(object) as T; - if (Array.isArray(object)) return object.map((item) => deepClone(item)) as T; - const cloned = Object.create(Object.getPrototypeOf(object)) as T; - for (const key of Object.keys(object)) - if (!DANGEROUS_KEYS.has(key)) cloned[key as keyof T] = deepClone(object[key as keyof T]); - return cloned; -}; - // Async validation helpers -const getValueAtPath = (source: T, path: string): unknown => { - const parts = path.split('.'); - let current: unknown = source; - for (const part of parts) { - if (current === null || current === undefined) return undefined; - current = (current as Record)[part]; - } - return current; -}; - +// Walks only through objects on purpose: a string ancestor means the error sits above this +// path, not on it, and indexing into that string would yield a bogus single-character "error" const getSyncErrorForPath = (errors: Validator | undefined, path: string): string => { - if (!errors) return ''; - const parts = path.split('.'); - let current: string | Validator = errors; - for (const part of parts) { - if (typeof current === 'string') return ''; - if (current[part] === undefined) return ''; + let current: unknown = errors; + for (const part of path.split('.')) { + if (!isPlainObject(current)) return ''; current = current[part]; } return typeof current === 'string' ? current : ''; }; -const getMatchingAsyncValidatorPaths = (asyncValidator: AsyncValidator, changedPath: string): string[] => { - const matches: string[] = []; - for (const registeredPath of Object.keys(asyncValidator)) - // Exact match, changed path is a prefix of registered path, or changed path is nested - // within registered path (e.g., validator for 'user', changed 'user.name') - if ( - registeredPath === changedPath || - registeredPath.startsWith(changedPath + '.') || - changedPath.startsWith(registeredPath + '.') - ) - matches.push(registeredPath); - - return matches; -}; +const INITIAL_SNAPSHOT_TITLE = 'Initial'; // Options +export type PluginHook = Exclude>, 'name'>; + export type SvStateOptions = { resetDirtyOnAction: boolean; debounceValidation: number; @@ -126,6 +95,7 @@ export type SvStateOptions = { clearAsyncErrorsOnChange: boolean; maxConcurrentAsyncValidations: number; maxSnapshots: number; + onPluginError: (error: unknown, pluginName: string, hook: PluginHook) => void; // eslint-disable-next-line @typescript-eslint/no-explicit-any plugins: SvStatePlugin[]; }; @@ -139,6 +109,7 @@ const defaultOptions: SvStateOptions = { clearAsyncErrorsOnChange: true, maxConcurrentAsyncValidations: 4, maxSnapshots: 50, + onPluginError: (error, pluginName, hook) => console.error(`svstate: plugin "${pluginName}" threw in ${hook}`, error), plugins: [] }; @@ -158,7 +129,7 @@ export function createSvState, V extends Valid const isDirty = derived(dirtyFieldsStore, ($fields) => Object.keys($fields).length > 0); const actionInProgress = writable(false); const actionError = writable(); - const snapshots = writable[]>([{ title: 'Initial', data: deepClone(init) }]); + const snapshots = writable[]>([{ title: INITIAL_SNAPSHOT_TITLE, data: deepClone(init) }]); // Async validation stores const asyncErrorsStore = writable({}); @@ -172,15 +143,17 @@ export function createSvState, V extends Valid ([$hasErrors, $hasAsyncErrors]) => $hasErrors || $hasAsyncErrors ); - // Async validation trackers for cancellation - const asyncValidationTrackers = new Map< - string, - { controller: AbortController; timeoutId: ReturnType } - >(); + // Async validation trackers for cancellation. A path is either waiting out its debounce + // delay or already running — never both, so each phase carries only what it can cancel. + type AsyncTracker = + { kind: 'debounced'; timeoutId: ReturnType } | { kind: 'running'; controller: AbortController }; + const asyncValidationTrackers = new Map(); // Queue for async validations waiting to run (when at concurrency limit) const asyncValidationQueue: string[] = []; + let isDestroyed = false; + const markDirtyWithParents = (property: string) => { dirtyFieldsStore.update(($fields) => { const updated = { ...$fields, [property]: true }; @@ -192,15 +165,31 @@ export function createSvState, V extends Valid const stateObject = $state(init); + // Deferral state for batch() and for plugin hydration during onInit + let isBatching = false; + // Nothing can mutate before the onInit hook runs, so this stays false until hydration + let hasChanged = false; + let batchedSnapshotTitle: string | undefined; + const batchedAsyncPaths = new Set(); + // Plugin system const plugins = usedOptions.plugins as SvStatePlugin[]; - const callPlugins = (hook: string, ...arguments_: unknown[]) => { - for (const plugin of plugins) { - const function_ = plugin[hook as keyof SvStatePlugin]; - if (typeof function_ === 'function') (function_ as (...a: unknown[]) => void).call(plugin, ...arguments_); + + // A throwing plugin must not abort the mutation that triggered it, nor block later plugins. + const callPlugin = (plugin: SvStatePlugin, hook: H, arguments_: unknown[]) => { + const function_ = plugin[hook]; + if (typeof function_ !== 'function') return; + try { + (function_ as (...a: unknown[]) => void).apply(plugin, arguments_); + } catch (error) { + usedOptions.onPluginError(error, plugin.name, hook); } }; + const callPlugins = (hook: H, ...arguments_: Parameters[H]>>) => { + for (const plugin of plugins) callPlugin(plugin, hook, arguments_); + }; + const runValidation = () => { if (!validator) return; const result = validator(data); @@ -209,6 +198,12 @@ export function createSvState, V extends Valid }; const createSnapshot: SnapshotFunction = (title: string, shouldReplace = true) => { + // Inside a batch every mutation still runs `effect`, but the batch yields one undo point + if (isBatching) { + batchedSnapshotTitle ??= title; + return; + } + const currentSnapshots = get(snapshots); const createdSnapshot: Snapshot = { title, data: deepClone(stateObject) }; const lastSnapshot = currentSnapshots.at(-1); @@ -230,20 +225,27 @@ export function createSvState, V extends Valid let isValidationScheduled = false; let validationTimeout: ReturnType | undefined; + const clearValidationTimer = () => { + if (validationTimeout === undefined) return; + clearTimeout(validationTimeout); + validationTimeout = undefined; + }; + const scheduleValidation = () => { - if (!validator) return; + if (!validator || isDestroyed) return; if (usedOptions.debounceValidation > 0) { clearTimeout(validationTimeout); validationTimeout = setTimeout(() => { + validationTimeout = undefined; runValidation(); }, usedOptions.debounceValidation); } else { if (isValidationScheduled) return; isValidationScheduled = true; queueMicrotask(() => { - runValidation(); isValidationScheduled = false; + if (!isDestroyed) runValidation(); }); } }; @@ -254,19 +256,24 @@ export function createSvState, V extends Valid if (index !== -1) asyncValidationQueue.splice(index, 1); }; + const markValidating = (path: string) => asyncValidatingSet.update(($set) => new Set([...$set, path])); + + const unmarkValidating = (path: string) => + asyncValidatingSet.update(($set) => { + $set.delete(path); + return new Set($set); + }); + const cancelAsyncValidation = (path: string) => { // Remove from queue if waiting removeFromQueue(path); const tracker = asyncValidationTrackers.get(path); if (tracker) { - clearTimeout(tracker.timeoutId); - tracker.controller.abort(); + if (tracker.kind === 'debounced') clearTimeout(tracker.timeoutId); + else tracker.controller.abort(); asyncValidationTrackers.delete(path); - asyncValidatingSet.update(($set) => { - $set.delete(path); - return new Set($set); - }); + unmarkValidating(path); } }; @@ -277,30 +284,17 @@ export function createSvState, V extends Valid }; const executeAsyncValidation = async (path: string, onComplete: () => void) => { - if (!asyncValidator) { - onComplete(); - return; - } - - const asyncValidatorForPath = asyncValidator[path]; - if (!asyncValidatorForPath) { - onComplete(); - return; - } - - // Check sync error for this path - skip if sync fails - const syncError = getSyncErrorForPath(get(errors), path); - if (syncError) { + const asyncValidatorForPath = asyncValidator?.[path]; + // Nothing to run, torn down, or sync validation already failed for this path + if (!asyncValidatorForPath || isDestroyed || getSyncErrorForPath(get(errors), path)) { onComplete(); return; } const controller = new AbortController(); - // Store controller with a dummy timeoutId (validation already started) - asyncValidationTrackers.set(path, { controller, timeoutId: 0 as unknown as ReturnType }); + asyncValidationTrackers.set(path, { kind: 'running', controller }); - // Mark as validating - asyncValidatingSet.update(($set) => new Set([...$set, path])); + markValidating(path); try { const value = getValueAtPath(data, path); @@ -315,16 +309,11 @@ export function createSvState, V extends Valid } catch (error) { if (error instanceof Error && error.name === 'AbortError') return; // Store unexpected validator errors rather than re-throwing - if (!controller.signal.aborted) { - const message = error instanceof Error ? error.message : 'Async validation error'; - asyncErrorsStore.update(($asyncErrors) => ({ ...$asyncErrors, [path]: message })); - } + if (!controller.signal.aborted) + asyncErrorsStore.update(($asyncErrors) => ({ ...$asyncErrors, [path]: toError(error).message })); } finally { asyncValidationTrackers.delete(path); - asyncValidatingSet.update(($set) => { - $set.delete(path); - return new Set($set); - }); + unmarkValidating(path); onComplete(); } }; @@ -340,7 +329,7 @@ export function createSvState, V extends Valid }; const scheduleAsyncValidation = (path: string) => { - if (!asyncValidator || !Object.hasOwn(asyncValidator, path)) return; + if (isDestroyed || !asyncValidator || !Object.hasOwn(asyncValidator, path)) return; // Cancel any existing validation for this path cancelAsyncValidation(path); @@ -353,7 +342,6 @@ export function createSvState, V extends Valid return updated; }); - const controller = new AbortController(); const timeoutId = setTimeout(() => { // Remove tracker since debounce is done asyncValidationTrackers.delete(path); @@ -362,40 +350,88 @@ export function createSvState, V extends Valid const activeCount = get(asyncValidatingSet).size; if (activeCount < usedOptions.maxConcurrentAsyncValidations) executeAsyncValidation(path, processAsyncValidationQueue); - else { - // Remove any existing entry for this path and add to end of queue - removeFromQueue(path); - asyncValidationQueue.push(path); - } + else asyncValidationQueue.push(path); }, usedOptions.debounceAsyncValidation); - asyncValidationTrackers.set(path, { controller, timeoutId }); + asyncValidationTrackers.set(path, { kind: 'debounced', timeoutId }); + }; + + const flushDeferredValidation = () => { + const pendingPaths = [...batchedAsyncPaths]; + batchedAsyncPaths.clear(); + scheduleValidation(); + for (const path of pendingPaths) scheduleAsyncValidation(path); }; const scheduleAsyncValidationsForPath = (changedPath: string) => { if (!asyncValidator) return; - const matchingPaths = getMatchingAsyncValidatorPaths(asyncValidator, changedPath); + const matchingPaths = getMatchingPaths(Object.keys(asyncValidator), changedPath); + if (isBatching) { + for (const path of matchingPaths) batchedAsyncPaths.add(path); + return; + } for (const path of matchingPaths) scheduleAsyncValidation(path); }; const data = ChangeProxy(stateObject, (target: T, property: string, currentValue: unknown, oldValue: unknown) => { + if (isDestroyed) return; + hasChanged = true; if (!usedOptions.persistActionError) actionError.set(undefined); markDirtyWithParents(property); const effectResult: unknown = effect?.({ snapshot: createSnapshot, target, property, currentValue, oldValue }); if (effectResult instanceof Promise) throw new Error('svstate: effect callback must be synchronous. Use action for async operations.'); callPlugins('onChange', { target, property, currentValue, oldValue }); - scheduleValidation(); + if (!isBatching) scheduleValidation(); scheduleAsyncValidationsForPath(property); }); runValidation(); + /** Runs sync validation immediately (bypassing debounce) and returns the result. */ + const validate = (): ValidationResult => { + clearValidationTimer(); + runValidation(); + const currentErrors = get(errors); + return { errors: currentErrors, hasErrors: hasAnyErrors(currentErrors) }; + }; + + /** + * Applies many mutations as one unit: validation runs once at the end and each async + * validator is scheduled at most once. `effect` and plugin `onChange` still fire per mutation. + */ + const batch = (mutate: (draft: T) => void) => { + if (isDestroyed) return; + if (isBatching) { + mutate(data); + return; + } + + isBatching = true; + try { + mutate(data); + } finally { + isBatching = false; + if (batchedSnapshotTitle !== undefined) { + const title = batchedSnapshotTitle; + batchedSnapshotTitle = undefined; + createSnapshot(title, false); + } + flushDeferredValidation(); + } + }; + // Run async validation on init if configured if (asyncValidator && usedOptions.runAsyncValidationOnInit) for (const path of Object.keys(asyncValidator)) scheduleAsyncValidation(path); + // Makes the current state the new starting point: one "Initial" snapshot, nothing dirty + const resetBaseline = (shouldClearDirty = true) => { + if (shouldClearDirty) dirtyFieldsStore.set({}); + snapshots.set([{ title: INITIAL_SNAPSHOT_TITLE, data: deepClone(stateObject) }]); + }; + const execute = async (parameters?: P) => { if (!usedOptions.allowConcurrentActions && get(actionInProgress)) return; @@ -404,26 +440,12 @@ export function createSvState, V extends Valid actionInProgress.set(true); try { await actuators?.action?.(parameters); - if (usedOptions.resetDirtyOnAction) dirtyFieldsStore.set({}); - snapshots.set([{ title: 'Initial', data: deepClone(stateObject) }]); + resetBaseline(usedOptions.resetDirtyOnAction); await actuators?.actionCompleted?.(); callPlugins('onAction', { phase: 'after', params: parameters }); } catch (caughtError) { await actuators?.actionCompleted?.(caughtError); - const actionError_ = - caughtError instanceof Error - ? caughtError - : caughtError && typeof caughtError === 'object' - ? new Error( - String( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (caughtError as any).message ?? - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (caughtError as any).body?.message ?? - caughtError - ) - ) - : undefined; + const actionError_ = toError(caughtError); actionError.set(actionError_); callPlugins('onAction', { phase: 'after', params: parameters, error: actionError_ }); } finally { @@ -431,23 +453,34 @@ export function createSvState, V extends Valid } }; + // Replaces the live state with a snapshot, including removing keys added since it was taken + const replaceStateObject = (source: T) => { + const restored = deepClone(source); + for (const key of Object.keys(stateObject)) + if (!Object.hasOwn(restored, key)) delete (stateObject as Record)[key]; + Object.assign(stateObject, restored); + }; + const restoreToSnapshot = (targetIndex: number, currentSnapshots: Snapshot[]) => { const targetSnapshot = currentSnapshots[targetIndex]; if (!targetSnapshot) return; cancelAllAsyncValidations(); dirtyFieldsStore.set({}); - Object.assign(stateObject, deepClone(targetSnapshot.data)); + replaceStateObject(targetSnapshot.data); snapshots.set(currentSnapshots.slice(0, targetIndex + 1)); runValidation(); return targetSnapshot; }; + const restoreAndNotify = (targetIndex: number, currentSnapshots: Snapshot[]) => { + const targetSnapshot = restoreToSnapshot(targetIndex, currentSnapshots); + if (targetSnapshot) callPlugins('onRollback', targetSnapshot); + }; + const rollback = (steps = 1) => { const currentSnapshots = get(snapshots); if (currentSnapshots.length <= 1) return; - const targetIndex = Math.max(0, currentSnapshots.length - 1 - steps); - const targetSnapshot = restoreToSnapshot(targetIndex, currentSnapshots); - if (targetSnapshot) callPlugins('onRollback', targetSnapshot); + restoreAndNotify(Math.max(0, currentSnapshots.length - 1 - steps), currentSnapshots); }; // eslint-disable-next-line unicorn/consistent-boolean-name -- rollbackTo is a public API method name, not a boolean flag @@ -456,8 +489,7 @@ export function createSvState, V extends Valid if (currentSnapshots.length <= 1) return false; for (let index = currentSnapshots.length - 1; index >= 0; index--) if (currentSnapshots[index]!.title === title) { - const targetSnapshot = restoreToSnapshot(index, currentSnapshots); - if (targetSnapshot) callPlugins('onRollback', targetSnapshot); + restoreAndNotify(index, currentSnapshots); return true; } @@ -486,10 +518,35 @@ export function createSvState, V extends Valid }; const destroy = () => { - for (let index = plugins.length - 1; index >= 0; index--) plugins[index]?.destroy?.(); + if (isDestroyed) return; + isDestroyed = true; + + clearValidationTimer(); + cancelAllAsyncValidations(); + + for (let index = plugins.length - 1; index >= 0; index--) { + const plugin = plugins[index]; + if (plugin) callPlugin(plugin, 'destroy', []); + } }; - callPlugins('onInit', { data, state, options: usedOptions, snapshot: createSnapshot }); + // Plugins such as persist/history hydrate state from onInit by writing through the proxy. + // Defer validation across the hook, then re-baseline so hydrated values count as the initial + // state instead of as a dirty change on top of it. + isBatching = true; + try { + callPlugins('onInit', { data, state, options: usedOptions, snapshot: createSnapshot }); + } finally { + isBatching = false; + } + + // Snapshots taken during hydration are superseded by the re-baseline below + batchedSnapshotTitle = undefined; + + if (hasChanged) { + resetBaseline(); + flushDeferredValidation(); + } else batchedAsyncPaths.clear(); - return { data, execute, state, rollback, rollbackTo, reset, destroy }; + return { data, execute, state, rollback, rollbackTo, reset, destroy, validate, batch }; } diff --git a/src/validators.ts b/src/validators.ts index 7b99a2e..40f64ca 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -1,3 +1,52 @@ +const EPSILON = 1e-9; + +// Counts decimal places for exponential notation too — String(1e-7) is '1e-7', not '0.0000001' +const countDecimalPlaces = (value: number): number => { + if (Number.isSafeInteger(value)) return 0; + const text = String(value); + const exponentIndex = text.indexOf('e-'); + if (exponentIndex === -1) return text.split('.', 2)[1]?.length ?? 0; + const mantissa = text.slice(0, exponentIndex); + const exponent = Number(text.slice(exponentIndex + 2)); + return (mantissa.split('.', 2)[1]?.length ?? 0) + exponent; +}; + +// Tolerant divisibility: an exact `%` reports 0.3 as not a multiple of 0.1 +const isMultipleOf = (value: number, divisor: number): boolean => { + if (divisor === 0) return false; + const remainder = Math.abs(value % divisor); + return remainder < EPSILON || Math.abs(remainder - Math.abs(divisor)) < EPSILON; +}; + +const stableStringify = (value: unknown): string => { + if (value === null || typeof value !== 'object') return JSON.stringify(value) ?? String(value); + if (value instanceof Date) return `Date(${value.getTime()})`; + if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(',')}]`; + const entries = Object.entries(value as Record).toSorted(([a], [b]) => (a < b ? -1 : 1)); + return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(',')}}`; +}; + +// Type-tagged so 1 and '1' (or null and 'null') never collide, and key order never matters +const toComparableKey = (value: unknown): string => { + if (value === null) return 'null'; + if (typeof value === 'object') return `object:${stableStringify(value)}`; + return `${typeof value}:${String(value)}`; +}; + +const toDisplay = (value: unknown): string => + value !== null && typeof value === 'object' ? JSON.stringify(value) : String(value); + +const toDate = (value: Date | string | number): Date => (value instanceof Date ? value : new Date(value)); + +const isWeekendDay = (date: Date): boolean => date.getDay() === 0 || date.getDay() === 6; + +// Today shifted back N years — the cut-off an age constraint compares against +const yearsAgo = (years: number): Date => { + const date = new Date(); + date.setFullYear(date.getFullYear() - years); + return date; +}; + type BaseOption = 'trim' | 'normalize'; type PrepareOption = BaseOption | 'upper' | 'lower' | 'localeUpper' | 'localeLower'; @@ -187,93 +236,90 @@ type StringValidatorBuilder = { // Number Validator export function numberValidator(input: number | null | undefined): NumberValidatorBuilder { let error = ''; - const isNullish = input === null || input === undefined; + // NaN carries no comparable value — only required() reports it, every other rule skips it + const isMissing = input === null || input === undefined || Number.isNaN(input); const setError = (message: string) => { if (!error) error = message; }; const builder: NumberValidatorBuilder = { required() { - if (!error && (isNullish || Number.isNaN(input))) setError('Required'); + if (!error && isMissing) setError('Required'); return builder; }, requiredIf(shouldRequire: boolean) { - if (shouldRequire && !error && (isNullish || Number.isNaN(input))) setError('Required'); + if (shouldRequire && !error && isMissing) setError('Required'); return builder; }, min(n: number) { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input < n) setError(`Minimum ${n}`); return builder; }, max(n: number) { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input > n) setError(`Maximum ${n}`); return builder; }, between(min: number, max: number) { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && (input < min || input > max)) setError(`Must be between ${min} and ${max}`); return builder; }, integer() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && !Number.isSafeInteger(input)) setError('Must be an integer'); return builder; }, positive() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input <= 0) setError('Must be positive'); return builder; }, negative() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input >= 0) setError('Must be negative'); return builder; }, nonNegative() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input < 0) setError('Must be non-negative'); return builder; }, notZero() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && input === 0) setError('Must not be zero'); return builder; }, multipleOf(n: number) { - if (isNullish) return builder; - if (!error && input % n !== 0) setError(`Must be a multiple of ${n}`); + if (isMissing) return builder; + if (!error && !isMultipleOf(input, n)) setError(`Must be a multiple of ${n}`); return builder; }, + /** Alias of {@link multipleOf}. */ step(n: number) { - if (isNullish) return builder; - if (!error && input % n !== 0) setError(`Must be a multiple of ${n}`); - return builder; + return builder.multipleOf(n); }, decimal(places: number) { - if (isNullish) return builder; - if (error || Number.isNaN(input)) return builder; - const parts = String(input).split('.'); - const actualPlaces = parts[1]?.length ?? 0; - if (actualPlaces > places) setError(`Maximum ${places} decimal places`); + if (isMissing) return builder; + if (!error && countDecimalPlaces(input) > places) setError(`Maximum ${places} decimal places`); return builder; }, percentage() { - if (isNullish) return builder; + if (isMissing) return builder; if (!error && (input < 0 || input > 100)) setError('Must be between 0 and 100'); return builder; }, @@ -337,11 +383,10 @@ export function arrayValidator(input: T[] | null | undefined): ArrayValidator }, unique() { - if (isNullish) return builder; - if (error) return builder; + if (isNullish || error) return builder; const seen = new Set(); for (const item of array) { - const key = typeof item === 'object' ? JSON.stringify(item) : String(item); + const key = toComparableKey(item); if (seen.has(key)) { setError('Items must be unique'); break; @@ -358,43 +403,27 @@ export function arrayValidator(input: T[] | null | undefined): ArrayValidator }, includes(item: T) { - if (isNullish) return builder; - if (error) return builder; - const itemKey = typeof item === 'object' ? JSON.stringify(item) : String(item); - const found = array.some((element) => { - const elementKey = typeof element === 'object' ? JSON.stringify(element) : String(element); - return elementKey === itemKey; - }); - if (!found) setError(`Must include ${itemKey}`); + if (isNullish || error) return builder; + const itemKey = toComparableKey(item); + const found = array.some((element) => toComparableKey(element) === itemKey); + if (!found) setError(`Must include ${toDisplay(item)}`); return builder; }, includesAny(items: T[]) { - if (isNullish) return builder; - if (error) return builder; - const itemKeys = items.map((entry) => (typeof entry === 'object' ? JSON.stringify(entry) : String(entry))); - const found = array.some((element) => { - const elementKey = typeof element === 'object' ? JSON.stringify(element) : String(element); - return itemKeys.includes(elementKey); - }); - if (!found) setError(`Must include at least one of: ${itemKeys.join(', ')}`); + if (isNullish || error) return builder; + const itemKeys = new Set(items.map((entry) => toComparableKey(entry))); + const found = array.some((element) => itemKeys.has(toComparableKey(element))); + if (!found) setError(`Must include at least one of: ${items.map((entry) => toDisplay(entry)).join(', ')}`); return builder; }, includesAll(items: T[]) { - if (isNullish) return builder; - if (error) return builder; - const arrayKeys = new Set( - array.map((element) => (typeof element === 'object' ? JSON.stringify(element) : String(element))) - ); - const missing = items.filter((entry) => { - const entryKey = typeof entry === 'object' ? JSON.stringify(entry) : String(entry); - return !arrayKeys.has(entryKey); - }); - if (missing.length > 0) { - const missingKeys = missing.map((entry) => (typeof entry === 'object' ? JSON.stringify(entry) : String(entry))); - setError(`Missing required items: ${missingKeys.join(', ')}`); - } + if (isNullish || error) return builder; + const arrayKeys = new Set(array.map((element) => toComparableKey(element))); + const missing = items.filter((entry) => !arrayKeys.has(toComparableKey(entry))); + if (missing.length > 0) + setError(`Missing required items: ${missing.map((entry) => toDisplay(entry)).join(', ')}`); return builder; }, @@ -427,7 +456,7 @@ export function dateValidator(input: Date | string | number | null | undefined): if (!error) error = message; }; - const date = isNullish ? new Date(NaN) : input instanceof Date ? input : new Date(input); + const date = isNullish ? new Date(NaN) : toDate(input); const isValid = !isNullish && !Number.isNaN(date.getTime()); const builder: DateValidatorBuilder = { @@ -443,7 +472,7 @@ export function dateValidator(input: Date | string | number | null | undefined): before(target: Date | string | number) { if (!error && isValid) { - const targetDate = target instanceof Date ? target : new Date(target); + const targetDate = toDate(target); if (date >= targetDate) setError(`Must be before ${targetDate.toISOString()}`); } return builder; @@ -451,7 +480,7 @@ export function dateValidator(input: Date | string | number | null | undefined): after(target: Date | string | number) { if (!error && isValid) { - const targetDate = target instanceof Date ? target : new Date(target); + const targetDate = toDate(target); if (date <= targetDate) setError(`Must be after ${targetDate.toISOString()}`); } return builder; @@ -459,8 +488,8 @@ export function dateValidator(input: Date | string | number | null | undefined): between(start: Date | string | number, end: Date | string | number) { if (!error && isValid) { - const startDate = start instanceof Date ? start : new Date(start); - const endDate = end instanceof Date ? end : new Date(end); + const startDate = toDate(start); + const endDate = toDate(end); if (date < startDate || date > endDate) setError(`Must be between ${startDate.toISOString()} and ${endDate.toISOString()}`); } @@ -478,36 +507,22 @@ export function dateValidator(input: Date | string | number | null | undefined): }, weekday() { - if (!error && isValid) { - const day = date.getDay(); - if (day === 0 || day === 6) setError('Must be a weekday'); - } + if (!error && isValid && isWeekendDay(date)) setError('Must be a weekday'); return builder; }, weekend() { - if (!error && isValid) { - const day = date.getDay(); - if (day !== 0 && day !== 6) setError('Must be a weekend'); - } + if (!error && isValid && !isWeekendDay(date)) setError('Must be a weekend'); return builder; }, minAge(years: number) { - if (!error && isValid) { - const minDate = new Date(); - minDate.setFullYear(minDate.getFullYear() - years); - if (date > minDate) setError(`Must be at least ${years} years ago`); - } + if (!error && isValid && date > yearsAgo(years)) setError(`Must be at least ${years} years ago`); return builder; }, maxAge(years: number) { - if (!error && isValid) { - const maxDate = new Date(); - maxDate.setFullYear(maxDate.getFullYear() - years); - if (date < maxDate) setError(`Must be at most ${years} years ago`); - } + if (!error && isValid && date < yearsAgo(years)) setError(`Must be at most ${years} years ago`); return builder; }, diff --git a/test/plugins-analytics.test.svelte.ts b/test/plugins-analytics.test.svelte.ts index 672fc7b..fad5238 100644 --- a/test/plugins-analytics.test.svelte.ts +++ b/test/plugins-analytics.test.svelte.ts @@ -169,3 +169,89 @@ describe('analyticsPlugin', () => { expect(snapshotEvents[0]!.detail.title).toBe('MySnapshot'); }); }); + +describe('analyticsPlugin validation and redaction', () => { + it('should report hasErrors false when validation is clean', () => { + const flushed: AnalyticsEvent[] = []; + const analytics = analyticsPlugin({ + onFlush: (events) => { + flushed.push(...events); + }, + include: ['validation'], + flushInterval: 0 + }); + + createSvState( + { name: 'ok' }, + { validator: (source) => ({ name: source.name ? '' : 'Required' }) }, + { + plugins: [analytics] + } + ); + analytics.flush(); + + expect(flushed).toHaveLength(1); + expect(flushed[0]?.detail['hasErrors']).toBe(false); + }); + + it('should report hasErrors true when validation fails', () => { + const flushed: AnalyticsEvent[] = []; + const analytics = analyticsPlugin({ + onFlush: (events) => { + flushed.push(...events); + }, + include: ['validation'], + flushInterval: 0 + }); + + createSvState( + { name: '' }, + { validator: (source) => ({ name: source.name ? '' : 'Required' }) }, + { + plugins: [analytics] + } + ); + analytics.flush(); + + expect(flushed[0]?.detail['hasErrors']).toBe(true); + }); + + it('should redact nested paths under a redacted parent', () => { + const flushed: AnalyticsEvent[] = []; + const analytics = analyticsPlugin({ + onFlush: (events) => { + flushed.push(...events); + }, + include: ['change'], + redact: ['user'], + flushInterval: 0 + }); + + const { data } = createSvState({ user: { ssn: '', nickname: '' } }, {}, { plugins: [analytics] }); + data.user.ssn = '123-45-6789'; + analytics.flush(); + + expect(flushed[0]?.detail['property']).toBe('user.ssn'); + expect(flushed[0]?.detail['currentValue']).toBe('[redacted]'); + }); + + it('should report a rejected onFlush through onError', async () => { + const errors: unknown[] = []; + const analytics = analyticsPlugin({ + onFlush: () => Promise.reject(new Error('network down')), + onError: (error) => { + errors.push(error); + }, + include: ['change'], + flushInterval: 0 + }); + + const { data } = createSvState({ value: 0 }, {}, { plugins: [analytics] }); + data.value = 1; + analytics.flush(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(errors).toHaveLength(1); + expect((errors[0] as Error).message).toBe('network down'); + }); +}); diff --git a/test/plugins-history.test.svelte.ts b/test/plugins-history.test.svelte.ts index 66a31d9..d9113c4 100644 --- a/test/plugins-history.test.svelte.ts +++ b/test/plugins-history.test.svelte.ts @@ -145,4 +145,92 @@ describe('historyPlugin', () => { destroy(); expect(popstateListeners.length).toBe(0); }); + + describe('nested fields', () => { + it('should update URL when a dotted field is mutated directly', () => { + const history = historyPlugin({ fields: { 'filters.q': 'q' } }); + const { data } = createSvState({ filters: { q: '' } }, undefined, { plugins: [history] }); + + data.filters.q = 'nested'; + + expect(replaceStateCalls.length).toBe(1); + expect((replaceStateCalls[0] as unknown[])[2]).toContain('q=nested'); + }); + + it('should update URL when the parent of a dotted field is replaced', () => { + const history = historyPlugin({ fields: { 'filters.q': 'q' } }); + const { data } = createSvState({ filters: { q: '' } }, undefined, { plugins: [history] }); + + data.filters = { q: 'replaced' }; + + expect(replaceStateCalls.length).toBe(1); + expect((replaceStateCalls[0] as unknown[])[2]).toContain('q=replaced'); + }); + + it('should update URL for a registered parent when a child changes', () => { + const history = historyPlugin({ + fields: { filters: 'f' }, + serialize: (value) => JSON.stringify(value) + }); + const { data } = createSvState({ filters: { q: '' } }, undefined, { plugins: [history] }); + + data.filters.q = 'child'; + + expect(replaceStateCalls.length).toBe(1); + expect((replaceStateCalls[0] as unknown[])[2]).toContain('child'); + }); + + it('should read a dotted field from the URL on init', () => { + mockUrl.search = '?q=fromurl'; + mockUrl.href = 'http://localhost/?q=fromurl'; + + const history = historyPlugin({ fields: { 'filters.q': 'q' } }); + const { data } = createSvState({ filters: { q: '' } }, undefined, { plugins: [history] }); + + expect(data.filters.q).toBe('fromurl'); + }); + }); + + describe('onError', () => { + it('should route a throwing serialize to onError instead of escaping', () => { + const errors: unknown[] = []; + const history = historyPlugin({ + fields: { query: 'q' }, + serialize: () => { + throw new Error('serialize failed'); + }, + onError: (error) => { + errors.push(error); + } + }); + const { data } = createSvState({ query: '' }, undefined, { plugins: [history] }); + + expect(() => (data.query = 'boom')).not.toThrow(); + expect(errors.length).toBe(1); + expect((errors[0] as Error).message).toBe('serialize failed'); + expect(replaceStateCalls.length).toBe(0); + }); + + it('should route a throwing deserialize to onError and keep other fields', () => { + mockUrl.search = '?a=1&b=2'; + mockUrl.href = 'http://localhost/?a=1&b=2'; + + const errors: unknown[] = []; + const history = historyPlugin({ + fields: { alpha: 'a', beta: 'b' }, + deserialize: (parameter, field) => { + if (field === 'alpha') throw new Error('deserialize failed'); + return parameter; + }, + onError: (error) => { + errors.push(error); + } + }); + const { data } = createSvState({ alpha: '', beta: '' }, undefined, { plugins: [history] }); + + expect(errors.length).toBe(1); + expect(data.alpha).toBe(''); + expect(data.beta).toBe('2'); + }); + }); }); diff --git a/test/plugins-persist.test.svelte.ts b/test/plugins-persist.test.svelte.ts index ae62947..fecfe3f 100644 --- a/test/plugins-persist.test.svelte.ts +++ b/test/plugins-persist.test.svelte.ts @@ -1,3 +1,5 @@ +import { get } from 'svelte/store'; + import { persistPlugin } from '../src/plugins/persist'; import { createSvState } from '../src/state.svelte'; @@ -141,3 +143,132 @@ describe('persistPlugin', () => { expect(stored.data.name).toBe('initial'); }); }); + +describe('persistPlugin hydration baseline', () => { + it('should not mark restored fields dirty', () => { + const storage = createMockStorage(); + storage.setItem('form', JSON.stringify({ version: 1, data: { name: 'restored' } })); + + const { data, state } = createSvState( + { name: 'default' }, + {}, + { + plugins: [persistPlugin({ key: 'form', storage })] + } + ); + + expect(data.name).toBe('restored'); + expect(get(state.isDirty)).toBe(false); + expect(get(state.isDirtyByField)).toEqual({}); + }); + + it('should reset to the restored values, not the pre-restore defaults', () => { + const storage = createMockStorage(); + storage.setItem('form', JSON.stringify({ version: 1, data: { name: 'restored' } })); + + const { data, reset, state } = createSvState( + { name: 'default' }, + {}, + { + plugins: [persistPlugin({ key: 'form', storage })] + } + ); + + data.name = 'edited'; + reset(); + + expect(data.name).toBe('restored'); + expect(get(state.snapshots)[0]?.data).toEqual({ name: 'restored' }); + }); + + it('should report storage failures through onError instead of throwing', () => { + const errors: unknown[] = []; + const failingStorage = { + // eslint-disable-next-line unicorn/no-null + getItem: () => null, + setItem: () => { + throw new Error('QuotaExceededError'); + }, + removeItem: () => {} + }; + + const { data, destroy } = createSvState( + { name: 'a' }, + {}, + { + plugins: [ + persistPlugin({ + key: 'form', + storage: failingStorage, + throttle: 0, + onError: (error) => { + errors.push(error); + } + }) + ] + } + ); + + data.name = 'b'; + expect(() => destroy()).not.toThrow(); + expect(errors).toHaveLength(1); + expect((errors[0] as Error).message).toBe('QuotaExceededError'); + }); + + it('should write only once when destroy is called twice', () => { + const storage = createMockStorage(); + let writes = 0; + const countingStorage = { + ...storage, + setItem: (key: string, value: string) => { + writes++; + storage.setItem(key, value); + } + }; + + const persist = persistPlugin({ key: 'test', storage: countingStorage, throttle: 50 }); + const { data } = createSvState({ name: 'a' }, undefined, { plugins: [persist] }); + + data.name = 'b'; + + // createSvState.destroy() is idempotent, so the plugin hook is exercised directly here + persist.destroy?.(); + expect(writes).toBe(1); + + persist.destroy?.(); + expect(writes).toBe(1); + }); + + it('should not write on destroy when nothing changed', () => { + const storage = createMockStorage(); + let writes = 0; + const countingStorage = { + ...storage, + setItem: (key: string, value: string) => { + writes++; + storage.setItem(key, value); + } + }; + + const persist = persistPlugin({ key: 'test', storage: countingStorage, throttle: 50 }); + const { destroy } = createSvState({ name: 'a' }, undefined, { plugins: [persist] }); + + destroy(); + expect(writes).toBe(0); + }); + + it('should keep the pending write when destroy runs before the throttle elapses', async () => { + const storage = createMockStorage(); + const persist = persistPlugin({ key: 'test', storage, throttle: 50 }); + const { data, destroy } = createSvState({ name: 'a' }, undefined, { plugins: [persist] }); + + data.name = 'flushed'; + destroy(); + + expect(JSON.parse(storage.getItem('test')!).data.name).toBe('flushed'); + + // The cancelled timer must not fire a second write afterwards + await new Promise((r) => setTimeout(r, 80)); + expect(JSON.parse(storage.getItem('test')!).data.name).toBe('flushed'); + }); +}); diff --git a/test/plugins-sync.test.svelte.ts b/test/plugins-sync.test.svelte.ts index ede6067..2e04660 100644 --- a/test/plugins-sync.test.svelte.ts +++ b/test/plugins-sync.test.svelte.ts @@ -114,3 +114,76 @@ describe('syncPlugin', () => { expect(channels?.length ?? 0).toBe(0); }); }); + +describe('syncPlugin inbound throttling', () => { + beforeEach(() => { + MockBroadcastChannel.reset(); + vi.stubGlobal('BroadcastChannel', MockBroadcastChannel); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it('should apply the newest payload of a burst instead of dropping it', async () => { + const receiver = syncPlugin({ key: 'burst', throttle: 30 }); + const state = createSvState({ name: 'initial' }, undefined, { plugins: [receiver] }); + + const sender = new MockBroadcastChannel('burst'); + sender.postMessage({ type: 'sync', data: { name: 'first' } }); + sender.postMessage({ type: 'sync', data: { name: 'second' } }); + sender.postMessage({ type: 'sync', data: { name: 'third' } }); + + await new Promise((r) => setTimeout(r, 80)); + + expect(state.data.name).toBe('third'); + }); + + it('should route an unserializable broadcast to onError', async () => { + const errors: unknown[] = []; + const sync = syncPlugin({ + key: 'unserializable', + throttle: 10, + onError: (error) => { + errors.push(error); + } + }); + const { data } = createSvState<{ name: string; big: unknown }, never, never>( + { name: 'a', big: undefined }, + undefined, + { plugins: [sync] } + ); + + // BigInt is not JSON-serializable — JSON.stringify throws inside the debounced broadcast + data.big = 1n; + + await new Promise((r) => setTimeout(r, 40)); + + expect(errors).toHaveLength(1); + expect(errors[0]).toBeInstanceOf(TypeError); + }); + + it('should route a circular structure to onError', async () => { + const errors: unknown[] = []; + const sync = syncPlugin({ + key: 'circular', + throttle: 10, + onError: (error) => { + errors.push(error); + } + }); + const { data } = createSvState<{ name: string; self: unknown }, never, never>( + { name: 'a', self: undefined }, + undefined, + { plugins: [sync] } + ); + + const cycle: Record = {}; + cycle.self = cycle; + data.self = cycle; + + await new Promise((r) => setTimeout(r, 40)); + + expect(errors).toHaveLength(1); + }); +}); diff --git a/test/plugins-undo-redo.test.svelte.ts b/test/plugins-undo-redo.test.svelte.ts index f52510c..10fe3a8 100644 --- a/test/plugins-undo-redo.test.svelte.ts +++ b/test/plugins-undo-redo.test.svelte.ts @@ -106,3 +106,32 @@ describe('undoRedoPlugin', () => { expect(undoRedo.canRedo()).toBe(false); }); }); + +describe('undoRedoPlugin multi-step redo', () => { + it('should redo each rolled-back step in turn', () => { + const undoRedo = undoRedoPlugin<{ name: string; count: number }>(); + const { data, rollback } = createSvState( + { name: 'initial', count: 0 }, + { effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) }, + { plugins: [undoRedo] } + ); + + data.name = 'first'; + data.count = 10; + + rollback(); + rollback(); + + expect(data.name).toBe('initial'); + expect(data.count).toBe(0); + expect(get(undoRedo.redoStack)).toHaveLength(2); + + undoRedo.redo(); + expect(data.name).toBe('first'); + expect(get(undoRedo.redoStack)).toHaveLength(1); + + undoRedo.redo(); + expect(data.count).toBe(10); + expect(undoRedo.canRedo()).toBe(false); + }); +}); diff --git a/test/proxy.test.ts b/test/proxy.test.ts index 4e0063a..fbd3090 100644 --- a/test/proxy.test.ts +++ b/test/proxy.test.ts @@ -372,3 +372,91 @@ describe('ChangeProxy', () => { }); }); }); + +describe('ChangeProxy identity, deletes and paths', () => { + it('should return the same proxy instance for repeated reads', () => { + const proxy = ChangeProxy({ nested: { value: 1 } }, vi.fn()); + + expect(proxy.nested).toBe(proxy.nested); + }); + + it('should report property deletion as a change', () => { + const changed = vi.fn(); + const source: { name?: string; keep: number } = { name: 'test', keep: 1 }; + const proxy = ChangeProxy(source, changed); + + delete proxy.name; + + expect(changed).toHaveBeenCalledWith(expect.any(Object), 'name', undefined, 'test'); + expect(Object.hasOwn(source, 'name')).toBe(false); + }); + + it('should report nested deletion with the full path', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ user: { name: 'a' } as { name?: string } }, changed); + + delete proxy.user.name; + + expect(changed).toHaveBeenCalledWith(expect.any(Object), 'user.name', undefined, 'a'); + }); + + it('should not fire when deleting a missing key', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ name: 'test' } as { name?: string; other?: string }, changed); + + delete proxy.other; + + expect(changed).not.toHaveBeenCalled(); + }); + + it('should not store proxies in the raw tree', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ a: { x: 1 }, b: {} as { x?: number } }, changed); + + proxy.b = proxy.a; + changed.mockClear(); + proxy.b.x = 99; + + expect(changed).toHaveBeenCalledTimes(1); + expect(changed).toHaveBeenCalledWith(expect.any(Object), 'b.x', 99, 1); + }); + + it('should treat self-assignment as a no-op', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ nested: { x: 1 } }, changed); + + const current = proxy.nested; + proxy.nested = current; + + expect(changed).not.toHaveBeenCalled(); + }); + + it('should not fire when NaN replaces NaN', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ value: NaN }, changed); + + proxy.value = NaN; + + expect(changed).not.toHaveBeenCalled(); + }); + + it('should keep numeric-looking object keys in the path', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ users: { '123': { name: 'x' } } }, changed); + + proxy.users['123']!.name = 'y'; + + expect(changed).toHaveBeenCalledWith(expect.any(Object), 'users.123.name', 'y', 'x'); + }); + + it('should report array index and length writes on the array itself', () => { + const changed = vi.fn(); + const proxy = ChangeProxy({ list: [1, 2, 3] }, changed); + + proxy.list[0] = 9; + proxy.list.length = 1; + + expect(changed).toHaveBeenNthCalledWith(1, expect.any(Object), 'list', 9, 1); + expect(changed).toHaveBeenNthCalledWith(2, expect.any(Object), 'list', 1, 3); + }); +}); diff --git a/test/state.test.svelte.ts b/test/state.test.svelte.ts index 1e8ea3a..5e5cc3e 100644 --- a/test/state.test.svelte.ts +++ b/test/state.test.svelte.ts @@ -565,7 +565,7 @@ describe('actionError', () => { expect(get(state.actionError)?.message).toBe('Test error'); }); - it('should set actionError to undefined for non-Error throws', async () => { + it('should wrap thrown primitives into an Error', async () => { const { execute, state } = createSvState( { value: 0 }, { @@ -577,7 +577,8 @@ describe('actionError', () => { await execute(); - expect(get(state.actionError)).toBeUndefined(); + expect(get(state.actionError)).toBeInstanceOf(Error); + expect(get(state.actionError)?.message).toBe('string error'); }); it('should clear actionError on next action by default', async () => { @@ -1584,3 +1585,262 @@ describe('maxSnapshots', () => { expect(snaps[1]!.title).toBe('Same Title'); }); }); + +describe('non-plain values in state', () => { + it('should keep Map, Set and RegExp usable through snapshot and rollback', () => { + const { data, rollback } = createSvState( + { tags: new Set(['a']), meta: new Map([['k', 1]]), pattern: /ab+c/gi, label: 'x' }, + { effect: ({ snapshot }) => snapshot('change') } + ); + + data.label = 'y'; + rollback(); + + expect(data.label).toBe('x'); + expect(data.tags.has('a')).toBe(true); + expect(data.meta.get('k')).toBe(1); + expect(data.pattern.source).toBe('ab+c'); + expect(data.pattern.flags).toBe('gi'); + }); + + it('should keep Map and Set usable through reset', () => { + const { data, reset } = createSvState( + { meta: new Map([['k', 1]]), label: 'x' }, + { effect: ({ snapshot }) => snapshot('change') } + ); + + data.label = 'y'; + reset(); + + expect(data.meta.get('k')).toBe(1); + }); + + it('should clone circular structures without recursing forever', () => { + type Node = { name: string; self?: Node }; + const init: Node = { name: 'a' }; + init.self = init; + + const { data, rollback } = createSvState(init, { effect: ({ snapshot }) => snapshot('change') }); + + data.name = 'b'; + rollback(); + + expect(data.name).toBe('a'); + expect(data.self?.name).toBe('a'); + }); + + it('should remove keys added after a snapshot when rolling back', () => { + const { data, rollback } = createSvState({ a: 1 } as { a: number; b?: number }, { + effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) + }); + + data.b = 2; + rollback(); + + expect(Object.hasOwn(data, 'b')).toBe(false); + }); +}); + +describe('destroy cleanup', () => { + it('should cancel pending async validation', async () => { + let calls = 0; + const { data, destroy, state } = createSvState( + { email: '' }, + { + asyncValidator: { + email: async () => { + calls++; + return 'taken'; + } + } + }, + { debounceAsyncValidation: 10 } + ); + + data.email = 'a@b.c'; + destroy(); + await new Promise((resolve) => setTimeout(resolve, 40)); + + expect(calls).toBe(0); + expect(get(state.asyncErrors)).toEqual({}); + }); + + it('should ignore changes made after destroy', async () => { + let validations = 0; + const { data, destroy } = createSvState( + { value: 0 }, + { + validator: () => { + validations++; + return {}; + } + } + ); + + destroy(); + const before = validations; + data.value = 1; + await Promise.resolve(); + + expect(validations).toBe(before); + }); + + it('should be safe to call twice', () => { + let destroyCalls = 0; + const { destroy } = createSvState( + { value: 0 }, + {}, + { + plugins: [ + { + name: 'counter', + destroy: () => { + destroyCalls++; + } + } + ] + } + ); + + destroy(); + destroy(); + + expect(destroyCalls).toBe(1); + }); +}); + +describe('validate', () => { + it('should run validation synchronously and report a clean result', () => { + const { data, validate, state } = createSvState( + { name: '' }, + { validator: (source) => ({ name: source.name ? '' : 'Required' }) } + ); + + data.name = 'ok'; + const result = validate(); + + expect(result.hasErrors).toBe(false); + expect(result.errors).toEqual({ name: '' }); + expect(get(state.errors)).toEqual({ name: '' }); + }); + + it('should report errors without waiting for the debounce', () => { + const { data, validate } = createSvState( + { name: 'ok' }, + { validator: (source) => ({ name: source.name ? '' : 'Required' }) }, + { debounceValidation: 1000 } + ); + + data.name = ''; + const result = validate(); + + expect(result.hasErrors).toBe(true); + expect(result.errors).toEqual({ name: 'Required' }); + }); + + it('should return no errors when no validator is configured', () => { + const { validate } = createSvState({ value: 0 }); + + expect(validate()).toEqual({ errors: undefined, hasErrors: false }); + }); +}); + +describe('batch', () => { + it('should create a single snapshot for the whole batch', () => { + const { batch, state } = createSvState( + { a: 0, b: 0 }, + { effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) } + ); + + expect(get(state.snapshots)).toHaveLength(1); + + batch((draft) => { + draft.a = 1; + draft.b = 2; + }); + + expect(get(state.snapshots)).toHaveLength(2); + }); + + it('should apply every mutation and mark each field dirty', () => { + const { data, batch, state } = createSvState({ a: 0, b: 0 }); + + batch((draft) => { + draft.a = 1; + draft.b = 2; + }); + + expect(data.a).toBe(1); + expect(data.b).toBe(2); + expect(get(state.isDirtyByField)).toEqual({ a: true, b: true }); + }); + + it('should validate against the final state', async () => { + const { batch, state } = createSvState( + { a: 0, b: 0 }, + { validator: (source) => ({ total: source.a + source.b > 2 ? '' : 'Too small' }) } + ); + + batch((draft) => { + draft.a = 2; + draft.b = 2; + }); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(get(state.errors)).toEqual({ total: '' }); + }); + + it('should support nested batches', () => { + const { data, batch, state } = createSvState( + { a: 0, b: 0 }, + { effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) } + ); + + batch((draft) => { + draft.a = 1; + batch((inner) => { + inner.b = 2; + }); + }); + + expect(data.b).toBe(2); + expect(get(state.snapshots)).toHaveLength(2); + }); +}); + +describe('plugin error isolation', () => { + it('should keep the mutation and later plugins working when a plugin throws', () => { + const seen: string[] = []; + const reported: string[] = []; + + const { data } = createSvState( + { value: 0 }, + {}, + { + onPluginError: (_error, pluginName, hook) => { + reported.push(`${pluginName}:${hook}`); + }, + plugins: [ + { + name: 'thrower', + onChange: () => { + throw new Error('boom'); + } + }, + { + name: 'observer', + onChange: (event) => { + seen.push(event.property); + } + } + ] + } + ); + + data.value = 1; + + expect(data.value).toBe(1); + expect(seen).toEqual(['value']); + expect(reported).toEqual(['thrower:onChange']); + }); +}); diff --git a/test/validators.test.ts b/test/validators.test.ts index 9ffdd70..2906859 100644 --- a/test/validators.test.ts +++ b/test/validators.test.ts @@ -1628,3 +1628,77 @@ describe('dateValidator', () => { /* eslint-enable unicorn/no-null */ }); }); + +describe('numberValidator NaN handling', () => { + it('should report NaN as required', () => { + expect(numberValidator(NaN).required().getError()).toBe('Required'); + }); + + it('should skip comparison rules for NaN', () => { + expect(numberValidator(NaN).min(5).getError()).toBe(''); + expect(numberValidator(NaN).max(5).getError()).toBe(''); + expect(numberValidator(NaN).between(1, 5).getError()).toBe(''); + expect(numberValidator(NaN).positive().getError()).toBe(''); + expect(numberValidator(NaN).integer().getError()).toBe(''); + expect(numberValidator(NaN).percentage().getError()).toBe(''); + expect(numberValidator(NaN).decimal(2).getError()).toBe(''); + }); +}); + +describe('numberValidator precision', () => { + it('should count decimal places in exponential notation', () => { + expect(numberValidator(1e-7).decimal(2).getError()).toBe('Maximum 2 decimal places'); + expect(numberValidator(1e-7).decimal(7).getError()).toBe(''); + }); + + it('should accept float multiples that exact modulo rejects', () => { + expect(numberValidator(0.3).multipleOf(0.1).getError()).toBe(''); + expect(numberValidator(0.3).step(0.1).getError()).toBe(''); + expect(numberValidator(0.35).multipleOf(0.1).getError()).toBe('Must be a multiple of 0.1'); + }); + + it('should reject a zero divisor', () => { + expect(numberValidator(5).multipleOf(0).getError()).toBe('Must be a multiple of 0'); + }); +}); + +describe('arrayValidator comparison keys', () => { + it('should not collide values of different types', () => { + expect(arrayValidator([1, '1']).unique().getError()).toBe(''); + // eslint-disable-next-line unicorn/no-null + expect(arrayValidator([null, 'null']).unique().getError()).toBe(''); + }); + + it('should treat objects with the same entries as equal regardless of key order', () => { + expect( + arrayValidator([ + { a: 1, b: 2 }, + { b: 2, a: 1 } + ]) + .unique() + .getError() + ).toBe('Items must be unique'); + }); + + it('should compare dates by value', () => { + expect( + arrayValidator([new Date('2020-01-01'), new Date('2020-01-01')]) + .unique() + .getError() + ).toBe('Items must be unique'); + expect( + arrayValidator([new Date('2020-01-01'), new Date('2021-01-01')]) + .unique() + .getError() + ).toBe(''); + }); + + it('should match includes by value not by type-coerced string', () => { + expect(arrayValidator([1, 2]).includes(1).getError()).toBe(''); + expect( + arrayValidator(['1', '2']) + .includes(1 as unknown as string) + .getError() + ).toBe('Must include 1'); + }); +});