diff --git a/CHANGELOG.md b/CHANGELOG.md index a0253e1..f18cc98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ 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.2] - 2026-08-20 + +### Fixed + +- **Reactive proxy could be used to pollute `Object.prototype`** — reading, writing, or deleting `__proto__`, `constructor`, or `prototype` through `data` behaved like any other property, so `data.__proto__ = { isAdmin: true }` (or an unguarded `Object.assign(data, JSON.parse(untrustedInput))`) could reach the shared `Object.prototype` and affect every object in the app. These keys are now blocked at the proxy itself, matching the guard already used for path-based updates and merges. + +### Demo + +- Widened a couple of validators and reactive stores shown in the demo pages, and refreshed the built demo site. + ## [2.0.1] - 2026-08-20 ### Changed diff --git a/demo/src/pages/ActionDemo.svelte b/demo/src/pages/ActionDemo.svelte index 47fbe11..054b858 100644 --- a/demo/src/pages/ActionDemo.svelte +++ b/demo/src/pages/ActionDemo.svelte @@ -65,7 +65,7 @@ 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() + description: stringValidator(source.description).prepare('trim').required().minLength(10).maxLength(200).getError() }), action: async () => { // Simulate API call with 100-1000ms delay diff --git a/demo/src/pages/ArrayProperty.svelte b/demo/src/pages/ArrayProperty.svelte index bd7fff5..adaae50 100644 --- a/demo/src/pages/ArrayProperty.svelte +++ b/demo/src/pages/ArrayProperty.svelte @@ -96,10 +96,10 @@ type ItemErrors = Record; {#each data.items as item, index} - + - + {/each}`; diff --git a/demo/src/pages/AsyncValidation.svelte b/demo/src/pages/AsyncValidation.svelte index 7d6eb92..c73c1b3 100644 --- a/demo/src/pages/AsyncValidation.svelte +++ b/demo/src/pages/AsyncValidation.svelte @@ -103,12 +103,12 @@ // ───────────────────────────────────────────── // Source code examples for the collapsible section // ───────────────────────────────────────────── - const stateSourceCode = `const { data, batch, state: { errors, asyncErrors, asyncValidating, hasCombinedErrors } } = + const stateSourceCode = `const { data, batch, state: { errors, hasErrors, isDirty, 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() + username: stringValidator(source.username).prepare('trim').required().minLength(3).maxLength(20).noSpace().getError(), + email: stringValidator(source.email).prepare('trim').required().email().getError(), + slug: stringValidator(source.slug).prepare('trim').required().minLength(2).slug().getError() }), asyncValidator: { username: async (value, source, signal) => { diff --git a/demo/src/pages/OptionsDemo.svelte b/demo/src/pages/OptionsDemo.svelte index 20a951b..7446724 100644 --- a/demo/src/pages/OptionsDemo.svelte +++ b/demo/src/pages/OptionsDemo.svelte @@ -113,7 +113,7 @@ // ───────────────────────────────────────────── const optionsSourceCode = `const { data, execute, state } = createSvState( sourceData, - { validator, effect, action }, + { validator, effect, action, actionCompleted }, { // Reset isDirty to false after successful action resetDirtyOnAction: true, // default: true diff --git a/demo/src/pages/PluginPersistSync.svelte b/demo/src/pages/PluginPersistSync.svelte index 81e42d8..32ac1c1 100644 --- a/demo/src/pages/PluginPersistSync.svelte +++ b/demo/src/pages/PluginPersistSync.svelte @@ -109,6 +109,7 @@ batch((draft) => { draft.username = 'demo_user'; draft.theme = 'dark'; draft.fontSize = 16; + draft.notifications = false; });`; const apiSourceCode = `// persistPlugin API diff --git a/demo/src/pages/ZodValidation.svelte b/demo/src/pages/ZodValidation.svelte index 64d56f6..ad343ca 100644 --- a/demo/src/pages/ZodValidation.svelte +++ b/demo/src/pages/ZodValidation.svelte @@ -117,7 +117,7 @@ const userSchema = z.object({ ); } -const { data, batch, state: { errors, hasErrors } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => zodToSvstateErrors(userSchema, source, allFields) }); diff --git a/docs/assets/index-DofWQVW3.js b/docs/assets/index-VyZcMzTz.js similarity index 90% rename from docs/assets/index-DofWQVW3.js rename to docs/assets/index-VyZcMzTz.js index c8b9bb4..ae53114 100644 --- a/docs/assets/index-DofWQVW3.js +++ b/docs/assets/index-VyZcMzTz.js @@ -1,9 +1,9 @@ (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&&e.pending.size===0;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 } } = +\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`||Ri.has(t))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;if(Ri.has(n))return!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(Ri.has(n)||!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() + description: stringValidator(source.description).prepare('trim').required().minLength(10).maxLength(200).getError() }), action: async () => { // Simulate API call with 100-1000ms delay @@ -69,16 +69,16 @@ 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 } } = + +{/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, hasErrors, isDirty, 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() + username: stringValidator(source.username).prepare('trim').required().minLength(3).maxLength(20).noSpace().getError(), + email: stringValidator(source.email).prepare('trim').required().email().getError(), + slug: stringValidator(source.slug).prepare('trim').required().minLength(2).slug().getError() }), asyncValidator: { username: async (value, source, signal) => { @@ -282,7 +282,7 @@ batch((draft) => { `,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 }, + { validator, effect, action, actionCompleted }, { // Reset isDirty to false after successful action resetDirtyOnAction: true, // default: true @@ -413,6 +413,7 @@ batch((draft) => { draft.username = 'demo_user'; draft.theme = 'dark'; draft.fontSize = 16; + draft.notifications = false; });`,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 @@ -599,7 +600,7 @@ const userSchema = z.object({ ); } -const { data, batch, state: { errors, hasErrors } } = createSvState(sourceData, { +const { data, batch, state: { errors, hasErrors, isDirty, isDirtyByField } } = createSvState(sourceData, { validator: (source) => zodToSvstateErrors(userSchema, source, allFields) }); @@ -632,4 +633,4 @@ const fieldMeta = { `,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.1`,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 + 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.2`,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/index.html b/docs/index.html index 7b79aa4..21f9a9a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,7 +5,7 @@ svstate demo - + diff --git a/package-lock.json b/package-lock.json index d5b2fa7..5adc149 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "svstate", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "svstate", - "version": "2.0.1", + "version": "2.0.2", "license": "ISC", "devDependencies": { "@eslint/eslintrc": "^3.3.6", diff --git a/package.json b/package.json index 39f485e..dec4a71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svstate", - "version": "2.0.1", + "version": "2.0.2", "description": "Supercharged $state() for Svelte 5: deep reactive proxy with validation, cross-field rules, computed & side-effects", "author": "BCsabaEngine", "license": "ISC", diff --git a/src/proxy.ts b/src/proxy.ts index 25e7da8..372b130 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1,3 +1,5 @@ +import { DANGEROUS_KEYS } from './internal/paths'; + export type ProxyChanged = ( target: T, property: string, @@ -58,6 +60,10 @@ export const ChangeProxy = (source: T, changed: ProxyChanged)[property]; + // Never hand back a reactive wrapper around __proto__/constructor/prototype: for + // __proto__ that value is the real, shared Object.prototype, and wrapping it would let + // a write through the returned proxy pollute every object in the process. + if (DANGEROUS_KEYS.has(property)) return (object as Record)[property]; const value = (object as Record)[property]; if (isProxiable(value)) return createProxy(value as object, resolvePath(object, property, parentPath)); return value; @@ -68,6 +74,10 @@ export const ChangeProxy = (source: T, changed: ProxyChanged)[property] = incomingValue; return true; } + // Silently reject writes to __proto__/constructor/prototype, same as setValueAtPath and + // safeMerge do, so an untrusted payload (e.g. Object.assign(data, JSON.parse(input))) + // can't repoint the state object's prototype. + if (DANGEROUS_KEYS.has(property)) 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); @@ -81,6 +91,7 @@ export const ChangeProxy = (source: T, changed: ProxyChanged)[property]; diff --git a/test/async-validation.test.svelte.ts b/test/async-validation.test.svelte.ts index 7b0e7e7..85619e4 100644 --- a/test/async-validation.test.svelte.ts +++ b/test/async-validation.test.svelte.ts @@ -171,6 +171,48 @@ describe('async validation - cancellation', () => { }); }); +describe('async validation - error handling', () => { + it('should store the error message when the async validator throws', async () => { + const { data, state } = createSvState( + { username: '' }, + { + asyncValidator: { + username: async () => { + throw new Error('Server unreachable'); + } + } + }, + { debounceAsyncValidation: 10 } + ); + + data.username = 'test'; + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(get(state.asyncErrors)).toEqual({ username: 'Server unreachable' }); + expect(get(state.hasAsyncErrors)).toBe(true); + expect(get(state.asyncValidating)).toEqual([]); + }); + + it('should unwrap a non-Error throw into a message', async () => { + const { data, state } = createSvState( + { username: '' }, + { + asyncValidator: { + username: async () => { + throw 'plain string rejection'; + } + } + }, + { debounceAsyncValidation: 10 } + ); + + data.username = 'test'; + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(get(state.asyncErrors)).toEqual({ username: 'plain string rejection' }); + }); +}); + describe('async validation - asyncValidating store', () => { it('should update asyncValidating store during validation', async () => { const { data, state } = createSvState( @@ -561,6 +603,59 @@ describe('async validation - nested paths', () => { expect(isAsyncValidatorCalled).toBe(true); expect(get(state.asyncErrors)).toEqual({ user: 'User invalid' }); }); + + it('should pass undefined to the validator when a path segment resolves through a null ancestor', async () => { + let receivedValue: unknown = 'not called'; + + const { data } = createSvState( + { user: { email: 'x@y.z' } as { email: string } | null }, + { + asyncValidator: { + 'user.email': async (value) => { + receivedValue = value; + return ''; + } + } + }, + { debounceAsyncValidation: 10 } + ); + + // "user" becoming null matches registered "user.email" (parent triggers child), and reading + // through the now-null "user" must not throw + // eslint-disable-next-line unicorn/no-null + data.user = null; + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(receivedValue).toBeUndefined(); + }); + + it('should still run when only a descendant path has a sync error, not the registered path itself', async () => { + let isAsyncValidatorCalled = false; + + const { data, state } = createSvState( + { user: { name: 'x' } }, + { + validator: (source) => ({ + user: { name: source.user.name ? '' : 'Required' } + }), + asyncValidator: { + // "user" itself resolves to a nested object, not a string, so the sync-error check + // (which only looks at the exact registered path) must not block this + user: async () => { + isAsyncValidatorCalled = true; + return ''; + } + } + }, + { debounceAsyncValidation: 10 } + ); + + data.user.name = ''; + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(get(state.errors)).toEqual({ user: { name: 'Required' } }); + expect(isAsyncValidatorCalled).toBe(true); + }); }); describe('async validation - receives full source', () => { diff --git a/test/plugins-analytics.test.svelte.ts b/test/plugins-analytics.test.svelte.ts index fad5238..2dd70cb 100644 --- a/test/plugins-analytics.test.svelte.ts +++ b/test/plugins-analytics.test.svelte.ts @@ -41,6 +41,30 @@ describe('analyticsPlugin', () => { expect(flushed.length).toBeGreaterThanOrEqual(1); }); + it('should use the default 5000ms flush interval when not specified', () => { + vi.useFakeTimers(); + try { + const flushed: AnalyticsEvent[][] = []; + const analytics = analyticsPlugin({ + onFlush: (events) => { + flushed.push([...events]); + }, + batchSize: 100 + }); + const { data, destroy } = createSvState({ name: 'test' }, undefined, { plugins: [analytics] }); + + data.name = 'updated'; + expect(flushed.length).toBe(0); + + vi.advanceTimersByTime(5000); + expect(flushed.length).toBe(1); + + destroy(); + } finally { + vi.useRealTimers(); + } + }); + it('should filter by include types', () => { const flushed: AnalyticsEvent[][] = []; const analytics = analyticsPlugin({ diff --git a/test/plugins-autosave.test.svelte.ts b/test/plugins-autosave.test.svelte.ts index 175d756..fc681bc 100644 --- a/test/plugins-autosave.test.svelte.ts +++ b/test/plugins-autosave.test.svelte.ts @@ -117,6 +117,52 @@ describe('autosavePlugin', () => { expect(saved.length).toBeGreaterThanOrEqual(2); }); + it('should run a save requested while one is already in flight instead of dropping it', async () => { + const saveCalls: string[] = []; + const { promise: inFlight, resolve: resolveInFlight } = Promise.withResolvers(); + const autosave = autosavePlugin({ + save: async (data) => { + saveCalls.push((data as { name: string }).name); + if (saveCalls.length === 1) await inFlight; + }, + idle: 5000, + interval: 15, + onlyWhenDirty: false, + saveOnDestroy: false + }); + const { data, destroy } = createSvState({ name: 'a' }, undefined, { plugins: [autosave] }); + + // First interval tick starts the save and hangs on the unresolved promise + await new Promise((r) => setTimeout(r, 25)); + expect(autosave.isSaving()).toBe(true); + + data.name = 'b'; + // A later interval tick requests a save while the first is still in flight, and must not be + // dropped even though `isSaving` was true at request time + await new Promise((r) => setTimeout(r, 25)); + + resolveInFlight(); + await new Promise((r) => setTimeout(r, 15)); + destroy(); + + expect(saveCalls[0]).toBe('a'); + expect(saveCalls).toContain('b'); + expect(autosave.isSaving()).toBe(false); + }); + + it('should not touch document when onVisibilityHidden is set but document is unavailable', () => { + const autosave = autosavePlugin({ + save: () => {}, + onVisibilityHidden: true, + saveOnDestroy: false + }); + + expect(() => { + const { destroy } = createSvState({ name: 'a' }, undefined, { plugins: [autosave] }); + destroy(); + }).not.toThrow(); + }); + it('should clear idle timer after successful action', async () => { const saved: unknown[] = []; const autosave = autosavePlugin({ diff --git a/test/plugins-devtools.test.svelte.ts b/test/plugins-devtools.test.svelte.ts index e6db039..c213201 100644 --- a/test/plugins-devtools.test.svelte.ts +++ b/test/plugins-devtools.test.svelte.ts @@ -77,6 +77,65 @@ describe('devtoolsPlugin', () => { expect(actionCalls.length).toBe(2); }); + it('should default to enabled outside of production when enabled is not specified', () => { + const devtools = devtoolsPlugin(); + const { data } = createSvState({ name: 'test' }, undefined, { plugins: [devtools] }); + + data.name = 'updated'; + + expect(groupCollapsedSpy).toHaveBeenCalled(); + }); + + it('should include from/to values when logValues is true', () => { + const devtools = devtoolsPlugin({ enabled: true, logValues: true }); + const { data } = createSvState({ name: 'old' }, undefined, { plugins: [devtools] }); + + data.name = 'new'; + + const changeDetail = logSpy.mock.calls.find((c) => (c[0] as { property?: string })?.property === 'name')?.[0] as + { from?: string; to?: string } | undefined; + expect(changeDetail).toEqual({ property: 'name', from: 'old', to: 'new' }); + }); + + it('should log the error message when an action fails', async () => { + const devtools = devtoolsPlugin({ enabled: true }); + const { execute } = createSvState( + { name: 'test' }, + { + action: async () => { + throw new Error('boom'); + } + }, + { plugins: [devtools] } + ); + + await execute(); + + const errorDetail = logSpy.mock.calls.find((c) => (c[0] as { error?: string })?.error === 'boom'); + expect(errorDetail).toBeDefined(); + }); + + it('should log snapshot, rollback and reset events', () => { + const devtools = devtoolsPlugin({ enabled: true }); + const { data, rollback, reset } = createSvState( + { name: 'initial' }, + { effect: ({ snapshot }) => snapshot('Changed') }, + { plugins: [devtools] } + ); + + data.name = 'updated'; + const snapshotCall = groupCollapsedSpy.mock.calls.find((c) => (c[0] as string).includes('snapshot')); + expect(snapshotCall).toBeDefined(); + + rollback(); + const rollbackCall = groupCollapsedSpy.mock.calls.find((c) => (c[0] as string).includes('rollback')); + expect(rollbackCall).toBeDefined(); + + reset(); + const resetCall = groupCollapsedSpy.mock.calls.find((c) => (c[0] as string).includes('reset')); + expect(resetCall).toBeDefined(); + }); + it('should use custom name in log prefix', () => { const devtools = devtoolsPlugin({ enabled: true, name: 'myForm' }); const { data } = createSvState({ name: 'test' }, undefined, { plugins: [devtools] }); diff --git a/test/plugins-history.test.svelte.ts b/test/plugins-history.test.svelte.ts index d9113c4..1e2f332 100644 --- a/test/plugins-history.test.svelte.ts +++ b/test/plugins-history.test.svelte.ts @@ -146,6 +146,23 @@ describe('historyPlugin', () => { expect(popstateListeners.length).toBe(0); }); + it('should stay a safe no-op during SSR, where window is unavailable', () => { + // Undo the beforeEach mock: neither onInit's URL read nor onChange's URL write may touch it + delete (globalThis as Record).window; + + const history = historyPlugin({ fields: { query: 'q' } }); + + expect(() => { + const { data, destroy } = createSvState({ query: 'initial' }, undefined, { plugins: [history] }); + expect(data.query).toBe('initial'); + + data.query = 'changed'; + expect(data.query).toBe('changed'); + + destroy(); + }).not.toThrow(); + }); + describe('nested fields', () => { it('should update URL when a dotted field is mutated directly', () => { const history = historyPlugin({ fields: { 'filters.q': 'q' } }); diff --git a/test/plugins-persist.test.svelte.ts b/test/plugins-persist.test.svelte.ts index fecfe3f..e3bf980 100644 --- a/test/plugins-persist.test.svelte.ts +++ b/test/plugins-persist.test.svelte.ts @@ -15,6 +15,19 @@ function createMockStorage() { } describe('persistPlugin', () => { + it('should stay a safe no-op when no storage option is given and no global localStorage exists', () => { + const persist = persistPlugin({ key: 'test', throttle: 10 }); + + expect(() => { + const { data } = createSvState({ name: 'initial' }, undefined, { plugins: [persist] }); + expect(data.name).toBe('initial'); + expect(persist.isRestored()).toBe(false); + + data.name = 'changed'; + persist.clearPersistedState(); + }).not.toThrow(); + }); + it('should hydrate state from storage on init', () => { const storage = createMockStorage(); storage.setItem('test', JSON.stringify({ version: 1, data: { name: 'stored' } })); @@ -27,6 +40,20 @@ describe('persistPlugin', () => { expect(persist.isRestored()).toBe(true); }); + it('should ignore a __proto__ key in stored data instead of merging it', () => { + const storage = createMockStorage(); + // A raw JSON string (not an object literal) is required: JSON.parse gives "__proto__" a real + // own property, whereas `{ __proto__: ... }` as a literal would just set the prototype. + storage.setItem('test', '{"version":1,"data":{"name":"stored","__proto__":{"polluted":true}}}'); + + const persist = persistPlugin({ key: 'test', storage }); + const { data } = createSvState({ name: 'initial' }, undefined, { plugins: [persist] }); + + expect(data.name).toBe('stored'); + expect(Object.getPrototypeOf(data)).toBe(Object.prototype); + expect(({} as Record).polluted).toBeUndefined(); + }); + it('should not restore if no stored data', () => { const storage = createMockStorage(); const persist = persistPlugin({ key: 'test', storage }); @@ -67,6 +94,40 @@ describe('persistPlugin', () => { expect(stored.data.count).toBeUndefined(); }); + it('should persist a nested include path, creating intermediate objects as needed', async () => { + const storage = createMockStorage(); + const persist = persistPlugin({ key: 'test', storage, throttle: 10, include: ['user.address.city'] }); + const { data } = createSvState({ user: { address: { city: 'Berlin', zip: '10115' } }, count: 0 }, undefined, { + plugins: [persist] + }); + + data.user.address.city = 'Vienna'; + await new Promise((r) => setTimeout(r, 50)); + + const stored = JSON.parse(storage.getItem('test')!); + expect(stored.data).toEqual({ user: { address: { city: 'Vienna' } } }); + }); + + it('should skip include paths that are or traverse through a dangerous key', async () => { + const storage = createMockStorage(); + const persist = persistPlugin({ + key: 'test', + storage, + throttle: 10, + // 'constructor' alone and 'constructor.name' both resolve to a defined value (the real + // Object constructor / its name), so this exercises setValueAtPath's own guard rather + // than being filtered out earlier by "value === undefined". + include: ['name', 'constructor', 'constructor.name'] + }); + const { data } = createSvState({ name: 'test' }, undefined, { plugins: [persist] }); + + data.name = 'updated'; + await new Promise((r) => setTimeout(r, 50)); + + const stored = JSON.parse(storage.getItem('test')!); + expect(stored.data).toEqual({ name: 'updated' }); + }); + it('should respect exclude paths', async () => { const storage = createMockStorage(); const persist = persistPlugin({ key: 'test', storage, throttle: 10, exclude: ['secret'] }); @@ -80,6 +141,47 @@ describe('persistPlugin', () => { expect(stored.data.secret).toBeUndefined(); }); + it('should respect a nested exclude path without disturbing its siblings', async () => { + const storage = createMockStorage(); + const persist = persistPlugin({ key: 'test', storage, throttle: 10, exclude: ['user.secret'] }); + const { data } = createSvState({ user: { name: 'test', secret: 'hidden' }, count: 0 }, undefined, { + plugins: [persist] + }); + + data.count = 1; + await new Promise((r) => setTimeout(r, 50)); + + const stored = JSON.parse(storage.getItem('test')!); + expect(stored.data).toEqual({ user: { name: 'test' }, count: 1 }); + }); + + it('should ignore stored data that is not a valid StorageFormat', () => { + const storage = createMockStorage(); + storage.setItem('test', JSON.stringify({ notAVersion: true })); + + const persist = persistPlugin({ key: 'test', storage }); + const { data } = createSvState({ name: 'initial' }, undefined, { plugins: [persist] }); + + expect(data.name).toBe('initial'); + expect(persist.isRestored()).toBe(false); + }); + + it('should ignore migration output that is not a plain object', () => { + const storage = createMockStorage(); + storage.setItem('test', JSON.stringify({ version: 1, data: { fullName: 'John Doe' } })); + + const persist = persistPlugin({ + key: 'test', + storage, + version: 2, + migrate: () => 'not-an-object' + }); + const { data } = createSvState({ name: 'initial' }, undefined, { plugins: [persist] }); + + expect(data.name).toBe('initial'); + expect(persist.isRestored()).toBe(false); + }); + it('should run migration when version changes', () => { const storage = createMockStorage(); storage.setItem('test', JSON.stringify({ version: 1, data: { fullName: 'John Doe' } })); diff --git a/test/plugins-sync.test.svelte.ts b/test/plugins-sync.test.svelte.ts index 2e04660..f8dc38d 100644 --- a/test/plugins-sync.test.svelte.ts +++ b/test/plugins-sync.test.svelte.ts @@ -62,6 +62,23 @@ describe('syncPlugin', () => { expect(state2.data.name).toBe('updated'); }); + it('should reject an incoming payload nested deeper than the depth limit', async () => { + const sync1 = syncPlugin({ key: 'depth-test', throttle: 10 }); + const sync2 = syncPlugin({ key: 'depth-test', throttle: 10 }); + + const state1 = createSvState({ deep: 'unset' as unknown }, undefined, { plugins: [sync1] }); + const state2 = createSvState({ deep: 'unset' as unknown }, undefined, { plugins: [sync2] }); + + // 12 levels of object nesting inside "deep" pushes the whole payload past the 10-level limit + let tooDeep: unknown = 'leaf'; + for (let index = 0; index < 12; index++) tooDeep = { nested: tooDeep }; + + state1.data.deep = tooDeep; + await new Promise((r) => setTimeout(r, 40)); + + expect(state2.data.deep).toBe('unset'); + }); + it('should not create echo loops', async () => { const sync1 = syncPlugin({ key: 'echo-test', throttle: 10 }); const sync2 = syncPlugin({ key: 'echo-test', throttle: 10 }); @@ -186,4 +203,35 @@ describe('syncPlugin inbound throttling', () => { expect(errors).toHaveLength(1); }); + + it('should stay a safe no-op when BroadcastChannel is unavailable', async () => { + vi.stubGlobal('BroadcastChannel', undefined); + + const sync = syncPlugin({ key: 'no-bc', throttle: 10 }); + const { data, destroy } = createSvState({ name: 'initial' }, undefined, { plugins: [sync] }); + + data.name = 'updated'; + // Let the throttled broadcast actually fire with no channel to post through, instead of + // cancelling it via an immediate destroy() + await new Promise((resolve) => setTimeout(resolve, 30)); + + expect(() => destroy()).not.toThrow(); + }); + + it('should ignore a non-sync message and a non-object payload', async () => { + const sync1 = syncPlugin({ key: 'ignore-test', throttle: 10 }); + const sync2 = syncPlugin({ key: 'ignore-test', throttle: 10 }); + + const state1 = createSvState({ name: 'initial' }, undefined, { plugins: [sync1] }); + const state2 = createSvState({ name: 'initial' }, undefined, { plugins: [sync2] }); + + const channel = MockBroadcastChannel.channels.get('ignore-test')![0]!; + channel.postMessage({ type: 'not-sync', data: { name: 'should-not-apply' } }); + channel.postMessage({ type: 'sync', data: 'not-an-object' }); + + await new Promise((r) => setTimeout(r, 30)); + + expect(state1.data.name).toBe('initial'); + expect(state2.data.name).toBe('initial'); + }); }); diff --git a/test/plugins-undo-redo.test.svelte.ts b/test/plugins-undo-redo.test.svelte.ts index 10fe3a8..99a8b92 100644 --- a/test/plugins-undo-redo.test.svelte.ts +++ b/test/plugins-undo-redo.test.svelte.ts @@ -105,6 +105,43 @@ describe('undoRedoPlugin', () => { destroy(); expect(undoRedo.canRedo()).toBe(false); }); + + it('should not push a redo entry when rollback(0) leaves the snapshot list unchanged', () => { + const { data, rollback, undoRedo } = createTestState(); + + data.name = 'updated'; + // steps=0 targets the current tip, so restoreToSnapshot doesn't shrink the snapshot list + // and the plugin's subscription never captures a "previous tip" to push onto the redo stack + rollback(0); + + expect(data.name).toBe('updated'); + expect(undoRedo.canRedo()).toBe(false); + }); +}); + +describe('undoRedoPlugin maxRedoStack', () => { + it('should drop the oldest redo entry once the configured maximum is exceeded', () => { + const undoRedo = undoRedoPlugin<{ a: number; b: number; c: number }>({ maxRedoStack: 2 }); + const { data, rollback } = createSvState( + { a: 0, b: 0, c: 0 }, + { effect: ({ snapshot, property }) => snapshot(`Changed ${property}`) }, + { plugins: [undoRedo] } + ); + + data.a = 1; // Changed a + data.b = 2; // Changed b + data.c = 3; // Changed c + + // Each rollback undoes the current tip and pushes it onto the redo stack, so the push order + // is the reverse of the change order: "Changed c" first, then "Changed b", then "Changed a" + rollback(); + rollback(); + rollback(); + + const stack = get(undoRedo.redoStack); + // "Changed c" (pushed first) is dropped once the stack exceeds maxRedoStack + expect(stack.map((s) => s.title)).toEqual(['Changed b', 'Changed a']); + }); }); describe('undoRedoPlugin multi-step redo', () => { diff --git a/test/proxy.test.ts b/test/proxy.test.ts index fbd3090..b19c138 100644 --- a/test/proxy.test.ts +++ b/test/proxy.test.ts @@ -370,6 +370,32 @@ describe('ChangeProxy', () => { expect(changed).toHaveBeenCalledWith(expect.any(Object), '123abc', 'updated', 'test'); }); + + it('should set a symbol-keyed property directly on the raw object without reporting a change', () => { + const source: Record = {}; + const changed = vi.fn(); + const proxy = ChangeProxy(source, changed) as Record; + const sym = Symbol('tag'); + + proxy[sym] = 'value'; + + expect(source[sym]).toBe('value'); + expect(proxy[sym]).toBe('value'); + expect(changed).not.toHaveBeenCalled(); + }); + + it('should delete a symbol-keyed property directly on the raw object without reporting a change', () => { + const sym = Symbol('tag'); + const source: Record = { [sym]: 'value' }; + const changed = vi.fn(); + const proxy = ChangeProxy(source, changed) as Record; + + const wasDeleted = delete proxy[sym]; + + expect(wasDeleted).toBe(true); + expect(Object.hasOwn(source, sym)).toBe(false); + expect(changed).not.toHaveBeenCalled(); + }); }); }); @@ -460,3 +486,78 @@ describe('ChangeProxy identity, deletes and paths', () => { expect(changed).toHaveBeenNthCalledWith(2, expect.any(Object), 'list', 1, 3); }); }); + +describe('prototype pollution guard', () => { + it('should not reassign the raw object prototype via __proto__', () => { + const source: Record = { a: 1 }; + const changed = vi.fn(); + const proxy = ChangeProxy(source, changed) as Record; + + proxy.__proto__ = { isAdmin: true }; + + expect(Object.getPrototypeOf(source)).toBe(Object.prototype); + expect((source as { isAdmin?: boolean }).isAdmin).toBeUndefined(); + expect(changed).not.toHaveBeenCalled(); + }); + + it('should not create own constructor/prototype properties', () => { + const source: Record = { a: 1 }; + const changed = vi.fn(); + const proxy = ChangeProxy(source, changed) as Record; + + proxy.constructor = 'hijacked'; + proxy.prototype = 'hijacked'; + + expect(Object.hasOwn(source, 'constructor')).toBe(false); + expect(Object.hasOwn(source, 'prototype')).toBe(false); + expect(changed).not.toHaveBeenCalled(); + }); + + it('should no-op deleting __proto__ without throwing or affecting the prototype', () => { + const source: Record = { a: 1 }; + const proxy = ChangeProxy(source, vi.fn()) as Record; + + expect(() => delete proxy.__proto__).not.toThrow(); + expect(Object.getPrototypeOf(source)).toBe(Object.prototype); + }); + + it('should not pollute the prototype via Object.assign with a __proto__ payload', () => { + const source: Record = { a: 1 }; + const proxy = ChangeProxy(source, vi.fn()) as Record; + + const untrusted = JSON.parse('{"__proto__":{"polluted":"yes"}}') as Record; + Object.assign(proxy, untrusted); + + expect(Object.getPrototypeOf(source)).toBe(Object.prototype); + expect((source as { polluted?: string }).polluted).toBeUndefined(); + }); + + it('should return the real prototype from __proto__, not a reactive wrapper', () => { + const source: Record = { a: 1 }; + const proxy = ChangeProxy(source, vi.fn()) as Record; + + expect(proxy.__proto__).toBe(Object.prototype); + }); + + it('should return the real constructor unwrapped, not a reactive proxy', () => { + const source: Record = { a: 1 }; + const proxy = ChangeProxy(source, vi.fn()) as Record; + + expect(proxy.constructor).toBe(Object); + }); + + it('should guard __proto__/constructor/prototype at any nesting depth, not just the root', () => { + const source = { nested: { a: 1 } as Record }; + const changed = vi.fn(); + const proxy = ChangeProxy(source, changed) as { nested: Record }; + + proxy.nested.__proto__ = { isAdmin: true }; + proxy.nested.constructor = 'hijacked'; + delete proxy.nested.__proto__; + + expect(Object.getPrototypeOf(source.nested)).toBe(Object.prototype); + expect(Object.hasOwn(source.nested, 'constructor')).toBe(false); + expect((source.nested as { isAdmin?: boolean }).isAdmin).toBeUndefined(); + expect(changed).not.toHaveBeenCalled(); + }); +}); diff --git a/test/state.test.svelte.ts b/test/state.test.svelte.ts index 5e5cc3e..785d35d 100644 --- a/test/state.test.svelte.ts +++ b/test/state.test.svelte.ts @@ -49,6 +49,20 @@ class ParentClass { } } +// Plain-object accessors (unlike a class's get/set, which live on the shared prototype) are own +// properties of the instance, so deepClone must special-case them to avoid flattening into a value. +const createAccessorState = (cents = 0) => ({ + cents, + get dollars(): number { + // eslint-disable-next-line unicorn/no-this-outside-of-class -- own-property accessor on a plain object, not a class + return this.cents / 100; + }, + set dollars(value: number) { + // eslint-disable-next-line unicorn/no-this-outside-of-class -- own-property accessor on a plain object, not a class + this.cents = Math.round(value * 100); + } +}); + describe('createSvState basic functionality', () => { it('should create state with initial data', () => { const { data } = createSvState({ name: 'test', count: 5 }); @@ -372,6 +386,26 @@ describe('rollback', () => { expect(get(state.snapshots)).toHaveLength(1); }); + it('should do nothing when steps is negative enough to target a non-existent snapshot', () => { + const { data, rollback, state } = createSvState( + { value: 0 }, + { + effect: ({ snapshot }) => { + snapshot('Changed', false); + } + } + ); + + data.value = 1; + const snapshotsBefore = get(state.snapshots); + + // steps=-5 targets an index past the end of the snapshot history + rollback(-5); + + expect(data.value).toBe(1); + expect(get(state.snapshots)).toEqual(snapshotsBefore); + }); + it('should trigger validation after rollback', () => { const { data, rollback, state } = createSvState( { name: 'initial' }, @@ -617,6 +651,54 @@ describe('actionError', () => { expect(get(state.actionError)).toBeUndefined(); }); + it('should read .message off a thrown non-Error object', async () => { + const { execute, state } = createSvState( + { value: 0 }, + { + action: async () => { + throw { message: 'Object error' }; + } + } + ); + + await execute(); + + expect(get(state.actionError)).toBeInstanceOf(Error); + expect(get(state.actionError)?.message).toBe('Object error'); + }); + + it('should fall back to .body.message when .message is absent', async () => { + const { execute, state } = createSvState( + { value: 0 }, + { + action: async () => { + throw { body: { message: 'Nested body error' } }; + } + } + ); + + await execute(); + + expect(get(state.actionError)).toBeInstanceOf(Error); + expect(get(state.actionError)?.message).toBe('Nested body error'); + }); + + it('should stringify a thrown object with neither .message nor .body.message', async () => { + const { execute, state } = createSvState( + { value: 0 }, + { + action: async () => { + throw { code: 500 }; + } + } + ); + + await execute(); + + expect(get(state.actionError)).toBeInstanceOf(Error); + expect(get(state.actionError)?.message).toBe('[object Object]'); + }); + it('should persist actionError when persistActionError is true', async () => { const { data, execute, state } = createSvState( { value: 0 }, @@ -1639,6 +1721,58 @@ describe('non-plain values in state', () => { expect(Object.hasOwn(data, 'b')).toBe(false); }); + + it('should carry Promise/WeakMap/Error fields by reference through rollback', () => { + const promise = Promise.resolve(1); + const weakMap = new WeakMap(); + const error = new Error('boom'); + + const { data, rollback } = createSvState( + { promise, weakMap, error, label: 'x' }, + { effect: ({ snapshot }) => snapshot('change') } + ); + + data.label = 'y'; + rollback(); + + expect(data.promise).toBe(promise); + expect(data.weakMap).toBe(weakMap); + expect(data.error).toBe(error); + }); + + it('should preserve an own getter/setter through rollback instead of flattening it to a value', () => { + const { data, rollback } = createSvState(createAccessorState(150), { + effect: ({ snapshot }) => snapshot('change') + }); + + expect(data.dollars).toBe(1.5); + + data.dollars = 9.99; + expect(data.cents).toBe(999); + + rollback(); + + expect(data.cents).toBe(150); + expect(data.dollars).toBe(1.5); + + // The setter must still run through the accessor, not a plain flattened value + data.dollars = 2; + expect(data.cents).toBe(200); + }); + + it('should drop an own constructor/prototype key when snapshotting', () => { + const init = { name: 'x', constructor: 'hijacked', prototype: 'hijacked' } as unknown as { name: string }; + const { data, rollback } = createSvState(init, { effect: ({ snapshot }) => snapshot('change') }); + + expect(Object.hasOwn(data, 'constructor')).toBe(true); + + data.name = 'y'; + rollback(); + + expect(data.name).toBe('x'); + expect(Object.hasOwn(data, 'constructor')).toBe(false); + expect(Object.hasOwn(data, 'prototype')).toBe(false); + }); }); describe('destroy cleanup', () => { @@ -1685,6 +1819,28 @@ describe('destroy cleanup', () => { expect(validations).toBe(before); }); + it('should skip a validation microtask scheduled before destroy runs before it fires', async () => { + let validations = 0; + const { data, destroy } = createSvState( + { value: 0 }, + { + validator: () => { + validations++; + return {}; + } + } + ); + + const before = validations; + // debounceValidation defaults to 0, so this schedules the pending run via queueMicrotask + data.value = 1; + destroy(); + await Promise.resolve(); + await Promise.resolve(); + + expect(validations).toBe(before); + }); + it('should be safe to call twice', () => { let destroyCalls = 0; const { destroy } = createSvState( @@ -1806,6 +1962,44 @@ describe('batch', () => { expect(data.b).toBe(2); expect(get(state.snapshots)).toHaveLength(2); }); + + it('should schedule each async validator at most once for the whole batch', async () => { + let callCount = 0; + const { batch, state } = createSvState( + { a: '', b: '' }, + { + asyncValidator: { + a: async () => { + callCount++; + return ''; + } + } + }, + { debounceAsyncValidation: 10 } + ); + + batch((draft) => { + draft.a = 'one'; + draft.a = 'two'; + draft.a = 'three'; + }); + + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(callCount).toBe(1); + expect(get(state.asyncErrors)).toEqual({ a: '' }); + }); + + it('should do nothing when called after destroy', () => { + const { data, batch, destroy } = createSvState({ a: 0 }); + + destroy(); + batch((draft) => { + draft.a = 1; + }); + + expect(data.a).toBe(0); + }); }); describe('plugin error isolation', () => { @@ -1843,4 +2037,29 @@ describe('plugin error isolation', () => { expect(seen).toEqual(['value']); expect(reported).toEqual(['thrower:onChange']); }); + + it('should log through console.error by default when onPluginError is not provided', () => { + const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); + + const { data } = createSvState( + { value: 0 }, + {}, + { + plugins: [ + { + name: 'thrower', + onChange: () => { + throw new Error('boom'); + } + } + ] + } + ); + + data.value = 1; + + expect(consoleErrorSpy).toHaveBeenCalledWith('svstate: plugin "thrower" threw in onChange', expect.any(Error)); + + consoleErrorSpy.mockRestore(); + }); }); diff --git a/test/validators.test.ts b/test/validators.test.ts index 2906859..c4a439c 100644 --- a/test/validators.test.ts +++ b/test/validators.test.ts @@ -185,6 +185,13 @@ describe('stringValidator', () => { it('should fail for mixed case string', () => { expect(stringValidator('Hello').lowercase().getError()).toBe('Lowercase only'); }); + + it('should skip validation for nullish values', () => { + /* eslint-disable unicorn/no-null */ + expect(stringValidator(null).lowercase().getError()).toBe(''); + expect(stringValidator().lowercase().getError()).toBe(''); + /* eslint-enable unicorn/no-null */ + }); }); describe('startsWith', () => { @@ -207,6 +214,10 @@ describe('stringValidator', () => { it('should skip validation for empty string', () => { expect(stringValidator('').startsWith('hello').getError()).toBe(''); }); + + it('should keep the earlier error instead of overwriting it', () => { + expect(stringValidator('bye world').minLength(20).startsWith('hello').getError()).toBe('Min length 20'); + }); }); describe('regexp', () => { @@ -270,6 +281,10 @@ describe('stringValidator', () => { expect(stringValidator().in(['apple', 'banana']).getError()).toBe(''); /* eslint-enable unicorn/no-null */ }); + + it('should keep the earlier error instead of overwriting it', () => { + expect(stringValidator('orange').minLength(20).in(['apple', 'banana']).getError()).toBe('Min length 20'); + }); }); describe('notIn', () => { @@ -301,6 +316,10 @@ describe('stringValidator', () => { expect(stringValidator().notIn(['apple', 'banana']).getError()).toBe(''); /* eslint-enable unicorn/no-null */ }); + + it('should keep the earlier error instead of overwriting it', () => { + expect(stringValidator('apple').minLength(20).notIn(['apple', 'banana']).getError()).toBe('Min length 20'); + }); }); describe('email', () => { @@ -765,6 +784,14 @@ describe('numberValidator', () => { it('should fail for positive number', () => { expect(numberValidator(5).negative().getError()).toBe('Must be negative'); }); + + it('should skip validation for null/undefined/NaN', () => { + /* eslint-disable unicorn/no-null */ + expect(numberValidator(null).negative().getError()).toBe(''); + expect(numberValidator().negative().getError()).toBe(''); + /* eslint-enable unicorn/no-null */ + expect(numberValidator(NaN).negative().getError()).toBe(''); + }); }); describe('nonNegative', () => { @@ -779,6 +806,14 @@ describe('numberValidator', () => { it('should fail for negative number', () => { expect(numberValidator(-5).nonNegative().getError()).toBe('Must be non-negative'); }); + + it('should skip validation for null/undefined/NaN', () => { + /* eslint-disable unicorn/no-null */ + expect(numberValidator(null).nonNegative().getError()).toBe(''); + expect(numberValidator().nonNegative().getError()).toBe(''); + /* eslint-enable unicorn/no-null */ + expect(numberValidator(NaN).nonNegative().getError()).toBe(''); + }); }); describe('notZero', () => { @@ -1660,6 +1695,15 @@ describe('numberValidator precision', () => { it('should reject a zero divisor', () => { expect(numberValidator(5).multipleOf(0).getError()).toBe('Must be a multiple of 0'); }); + + it('should treat an unsafe integer with no decimal point as having zero decimal places', () => { + // Beyond Number.MAX_SAFE_INTEGER, isSafeInteger() is false but String() still has no '.' or 'e' + expect( + numberValidator(2 ** 60) + .decimal(2) + .getError() + ).toBe(''); + }); }); describe('arrayValidator comparison keys', () => { @@ -1701,4 +1745,34 @@ describe('arrayValidator comparison keys', () => { .getError() ).toBe('Must include 1'); }); + + it('should compare nested arrays by structure', () => { + expect( + arrayValidator([ + [1, 2], + [1, 2] + ]) + .unique() + .getError() + ).toBe('Items must be unique'); + expect( + arrayValidator([ + [1, 2], + [1, 3] + ]) + .unique() + .getError() + ).toBe(''); + }); + + it('should treat undefined entries inside nested structures as equal', () => { + expect( + arrayValidator([ + [1, undefined], + [1, undefined] + ]) + .unique() + .getError() + ).toBe('Items must be unique'); + }); });