UNPKG

@mobx-sentinel/form

Version:

MobX library for non-intrusive class-based model enhancement. Acting as a sentinel, it provides change detection, reactive validation, and form integration capabilities without contamination.

2 lines 6.27 kB
var N=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var r=(s,e,n,i)=>{for(var t=i>1?void 0:i?I(e,n):e,d=s.length-1,l;d>=0;d--)(l=s[d])&&(t=(i?l(e,n,t):l(t))||t);return i&&t&&N(e,n,t),t};import{action as h,computed as F,makeObservable as z,observable as K}from"mobx";import{v4 as $}from"uuid";import{Validator as P,Watcher as W,StandardNestedFetcher as q,KeyPath as S}from"@mobx-sentinel/core";import{action as m,comparer as M,computed as p,makeObservable as k,observable as f,reaction as E}from"mobx";import{v4 as R}from"uuid";import{KeyPath as C}from"@mobx-sentinel/core";var O=Symbol("formField.internal"),o=class{id=R();fieldName;validator;#t;#e=f.box(!1);#i=f.box(null);#n=f.box(!1);#o=f.box(!1);#r=null;constructor(e){k(this),this.fieldName=e.fieldName,this.validator=e.validator,this.#t=e.getFinalizationDelayMs,E(()=>[this.#n.get(),this.validator.isValidating],([n,i])=>{i||this.#o.set(n)},{equals:M.shallow})}get isTouched(){return this.#e.get()}get isIntermediate(){return this.#i.get()==="intermediate"}get isChanged(){return!!this.#i.get()}get isErrorReported(){if(this.#o.get())return this.hasErrors}get errors(){return this.validator.getErrorMessages(C.build(this.fieldName))}get hasErrors(){return this.validator.hasErrors(C.build(this.fieldName))}reset(){this.#i.set(null),this.#e.set(!1),this.#n.set(!1),this.#s()}markAsTouched(){this.#e.set(!0)}markAsChanged(e="final"){switch(this.#i.set(e),e){case"final":{this.#s(),this.reportError();break}case"intermediate":{this.#a();break}}}reportError(){this.#n.set(!0)}finalizeChangeIfNeeded(){this.#s(),this.isIntermediate&&this.markAsChanged("final")}#a(){this.#s(),this.#r=+setTimeout(()=>{this.finalizeChangeIfNeeded()},this.#t())}#s(){this.#r&&(clearTimeout(this.#r),this.#r=null)}[O](){return{isReported:this.#n}}};r([p],o.prototype,"isErrorReported",1),r([p.struct],o.prototype,"errors",1),r([p],o.prototype,"hasErrors",1),r([m],o.prototype,"reset",1),r([m],o.prototype,"markAsTouched",1),r([m],o.prototype,"markAsChanged",1),r([m],o.prototype,"reportError",1);import{v4 as j}from"uuid";function c(s){let e=T.get(s);return e||(e=`${s.name}--${j()}`,T.set(s,e)),e}var T=new WeakMap;import{observable as D,runInAction as A}from"mobx";var x=Object.freeze({autoFinalizationDelayMs:3e3,allowSubmitNonDirty:!1,allowSubmitInvalid:!1}),g=D.object(x);function V(s){return A(()=>{s===!0?Object.assign(g,x):Object.assign(g,s)}),g}import{observable as H,runInAction as w}from"mobx";var u=class{#t=H.box(!1);#e={willSubmit:new Set,submit:new Set,didSubmit:new Set};#i=null;get isRunning(){return this.#t.get()}addHandler(e,n){return this.#e[e].add(n),()=>void this.#e[e].delete(n)}async exec(){this.#i?.abort();let e=new AbortController;this.#i=e;let n=!0;w(()=>{this.#t.set(!0)});try{for(let i of this.#e.willSubmit)if(!await i(e.signal)){n=!1;break}}catch(i){n=!1,console.error(i)}if(n)try{for(let i of this.#e.submit)if(!await i(e.signal)){n=!1;break}}catch(i){n=!1,console.error(i)}return this.#i=null,w(()=>{this.#t.set(!1);try{for(let i of this.#e.didSubmit)i(n)}catch(i){console.warn(i)}}),n}};var y=new WeakMap,G=Symbol("form.defaultFormKey"),b=Symbol("form.internalToken"),a=class a{id=$();#t;watcher;validator;#e;#i=new u;#n=new Map;#o=new Map;#r=K.box({});static get(e,n){let i=this.getSafe(e,n);if(!i)throw new TypeError("subject: Expected an object");return i}static getSafe(e,n){if(!e||typeof e!="object")return null;n??=G;let i=y.get(e);i||(i=new Map,y.set(e,i));let t=i.get(n);return t||(t=new this(b,{subject:e,formKey:n}),i.set(n,t)),t}static dispose(e,n){let i=y.get(e);i&&(n?i.delete(n):i.clear())}constructor(e,n){if(e!==b)throw new Error("private constructor");this.#t=n.formKey,this.watcher=W.get(n.subject),this.validator=P.get(n.subject),this.#e=new q(n.subject,i=>a.getSafe(i.data,this.#t)),z(this),this.#i.addHandler("didSubmit",i=>{i&&this.reset()})}get config(){return{...g,...this.#r.get()}}configure=e=>{typeof e=="object"?Object.assign(this.#r.get(),e):this.#r.set({})};get isDirty(){return this.watcher.changed}get isValid(){return this.validator.isValid}get invalidFieldCount(){return this.validator.invalidKeyCount}get invalidFieldPathCount(){return this.validator.invalidKeyPathCount}get isValidating(){return this.validator.isValidating}get isSubmitting(){return this.#i.isRunning}get isBusy(){return this.isSubmitting||this.isValidating}get canSubmit(){return!this.isBusy&&(this.config.allowSubmitInvalid||this.isValid)&&(this.config.allowSubmitNonDirty||this.isDirty)}get subForms(){return this.#e.dataMap}reportError(){for(let e of this.#n.values())e.reportError();for(let e of this.#e)e.data.reportError()}reset(){this.watcher.reset();for(let e of this.#n.values())e.reset();for(let e of this.#e)e.data.reset()}markAsDirty(){this.watcher.assumeChanged()}async submit(e){return!e?.force&&!this.canSubmit?!1:this.#i.exec()}addHandler=(...e)=>this.#i.addHandler(...e);getField(e){let n=this.#n.get(e);return n||(n=new o({fieldName:String(e),validator:this.validator,getFinalizationDelayMs:()=>this.config.autoFinalizationDelayMs}),this.#n.set(e,n)),n}#a(e,n){let i=this.#o.get(e);return i||(i=n(),this.#o.set(e,i)),i}#s=(e,n)=>{let i=`${c(e)}:${n?.cacheKey}`,t=this.#a(i,()=>new e(this,n));return t.config=n,t.props};#d=(e,n,i)=>{let t=`${e}@${c(n)}:${i?.cacheKey}`,d=this.#a(t,()=>{let l=this.getField(e);return new n(l,i)});return d.config=i,d.props};#l=(e,n,i)=>{let t=`${e.join(",")}@${c(n)}:${i?.cacheKey}`,d=this.#a(t,()=>{let l=e.map(v=>this.getField(v));return new n(l,i)});return d.config=i,d.props};bind=(...e)=>typeof e[0]=="string"?this.#d(e[0],e[1],e[2]):Array.isArray(e[0])?this.#l(e[0],e[1],e[2]):this.#s(e[0],e[1]);getErrors(e,n=!1){let i=this.getField(e);return!n&&!i.isErrorReported?new Set:i.errors}getAllErrors(e){return this.validator.getErrorMessages(e?S.build(e):S.Self,!0)}get firstErrorMessage(){return this.validator.firstErrorMessage}[b](){return{fields:this.#n,bindings:this.#o,submission:this.#i}}};r([F.struct],a.prototype,"config",1),r([h.bound],a.prototype,"configure",2),r([F],a.prototype,"isBusy",1),r([F],a.prototype,"canSubmit",1),r([h],a.prototype,"reportError",1),r([h],a.prototype,"reset",1),r([F],a.prototype,"firstErrorMessage",1);var B=a;export{B as Form,o as FormField,V as configureForm}; //# sourceMappingURL=index.mjs.map