UNPKG

react-form-with-constraints

Version:
2 lines (1 loc) 17.3 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["exports","react","prop-types"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactFormWithConstraints={},e.React,e.PropTypes)}(this,(function(e,t,i){"use strict";function s(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var s=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,s.get?s:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var n,a,d=s(t);function r(e,t){}class l{constructor(){this.listeners=new Map}emitSync(e,...t){const i=this.getListeners(e),s=new Array;return i.forEach((e=>s.push(e(...t)))),s}async emitAsync(e,...t){const i=this.getListeners(e),s=new Array;for(let e=0;e<i.length;e++)s.push(await i[e](...t));return s}getListeners(e){const t=this.listeners.get(e);return void 0!==t?(r(t.length>0,`No listener for event '${e}'`),t):[]}addListener(e,t){this.listeners.has(e)||this.listeners.set(e,[]);const i=this.listeners.get(e);r(!i.includes(t),`Listener already added for event '${e}'`),i.push(t)}removeListener(e,t){const i=this.listeners.get(e);r(void 0!==i,`Unknown event '${e}'`);const s=i.lastIndexOf(t);r(s>-1,`Listener not found for event '${e}'`),i.splice(s,1),0===i.length&&this.listeners.delete(e)}}e.FieldFeedbackType=void 0,(n=e.FieldFeedbackType||(e.FieldFeedbackType={})).Error="error",n.Warning="warning",n.Info="info",n.WhenValid="whenValid";class o{constructor(e){this.name=e,this.validations=[]}addOrReplaceValidation(e){const t=this.validations.findIndex((t=>t.key===e.key));t>-1?this.validations[t]=e:this.validations.push(e)}clearValidations(){!function(e){for(;e.length>0;)e.pop()}(this.validations)}hasFeedbacksOfType(e,t){return this.validations.some((i=>(void 0===t||i.key.startsWith(`${t}.`))&&i.type===e&&!0===i.show))}hasErrors(t){return this.hasFeedbacksOfType(e.FieldFeedbackType.Error,t)}hasWarnings(t){return this.hasFeedbacksOfType(e.FieldFeedbackType.Warning,t)}hasInfos(t){return this.hasFeedbacksOfType(e.FieldFeedbackType.Info,t)}hasFeedbacks(e){return this.hasErrors(e)||this.hasWarnings(e)||this.hasInfos(e)}isValid(){return!this.hasErrors()}}e.FieldEvent=void 0,(a=e.FieldEvent||(e.FieldEvent={})).Added="FIELD_ADDED",a.Removed="FIELD_REMOVED";class h extends l{constructor(){super(...arguments),this.fields=new Array}getField(e){const t=this.fields.filter((t=>t.name===e));return 1===t.length?t[0]:void 0}addField(t){const i=this.fields.filter((e=>e.name===t));if(r(0===i.length||1===i.length,`Cannot have more than 1 field matching '${t}'`),0===i.length){const i=new o(t);this.fields.push(i),this.emitSync(e.FieldEvent.Added,i)}}removeField(t){const i=this.fields.filter((e=>e.name===t)),s=this.fields.indexOf(i[0]);s>-1&&(this.fields.splice(s,1),this.emitSync(e.FieldEvent.Removed,t))}isValid(){return this.fields.every((e=>e.isValid()))}hasFeedbacks(){return this.fields.some((e=>e.hasFeedbacks()))}}class c{constructor(e){this.badInput=e.badInput,this.customError=e.customError,this.patternMismatch=e.patternMismatch,this.rangeOverflow=e.rangeOverflow,this.rangeUnderflow=e.rangeUnderflow,this.stepMismatch=e.stepMismatch,this.tooLong=e.tooLong,this.tooShort=e.tooShort,this.typeMismatch=e.typeMismatch,this.valid=e.valid,this.valueMissing=e.valueMissing}}function f(e){return void 0===e.props}class u{constructor(e){f(e)?(this.name=e.name,this.type=e.type,this.value=e.value,this.validity=new c(e.validity),this.validationMessage=e.validationMessage):(this.name=e.props.name,this.type=void 0,this.value=e.props.value,this.validity=void 0,this.validationMessage=void 0)}}const p="FIELD_DID_RESET_EVENT";function v(e){return class extends e{constructor(){super(...arguments),this.fieldDidResetEventEmitter=new l}emitFieldDidResetEvent(e){return this.fieldDidResetEventEmitter.emitSync(p,e)}addFieldDidResetEventListener(e){this.fieldDidResetEventEmitter.addListener(p,e)}removeFieldDidResetEventListener(e){this.fieldDidResetEventEmitter.removeListener(p,e)}}}const m="FIELD_DID_VALIDATE_EVENT";function F(e){return class extends e{constructor(){super(...arguments),this.fieldDidValidateEventEmitter=new l}emitFieldDidValidateEvent(e){return this.fieldDidValidateEventEmitter.emitSync(m,e)}addFieldDidValidateEventListener(e){this.fieldDidValidateEventEmitter.addListener(m,e)}removeFieldDidValidateEventListener(e){this.fieldDidValidateEventEmitter.removeListener(m,e)}}}const E="FIELD_WILL_VALIDATE_EVENT";function y(e){return class extends e{constructor(){super(...arguments),this.fieldWillValidateEventEmitter=new l}emitFieldWillValidateEvent(e){return this.fieldWillValidateEventEmitter.emitSync(E,e)}addFieldWillValidateEventListener(e){this.fieldWillValidateEventEmitter.addListener(E,e)}removeFieldWillValidateEventListener(e){this.fieldWillValidateEventEmitter.removeListener(E,e)}}}const k="VALIDATE_FIELD_EVENT";function V(e){return class extends e{constructor(){super(...arguments),this.validateFieldEventEmitter=new l}emitValidateFieldEvent(e){return this.validateFieldEventEmitter.emitAsync(k,e)}addValidateFieldEventListener(e){this.validateFieldEventEmitter.addListener(k,e)}removeValidateFieldEventListener(e){this.validateFieldEventEmitter.removeListener(k,e)}}}class b extends d.PureComponent{}class g extends(v(y(F(V(b))))){constructor(){super(...arguments),this.form=null,this.fieldsStore=new h,this.fieldFeedbacksKeyCounter=0}getChildContext(){return{form:this}}computeFieldFeedbacksKey(){return""+this.fieldFeedbacksKeyCounter++}validateFields(...e){return this._validateFields(!0,...e)}validateForm(){return this.validateFieldsWithoutFeedback()}validateFieldsWithoutFeedback(...e){return this._validateFields(!1,...e)}async _validateFields(e,...t){const i=new Array,s=this.normalizeInputs(...t);for(let t=0;t<s.length;t++){const n=s[t],a=await this.validateField(e,new u(n),n);void 0!==a&&i.push(a)}return i}async validateField(e,t,i){const s=t.name,n=this.fieldsStore.getField(s);if(void 0===n);else if(e||!n.hasFeedbacks()){n.element=i,n.clearValidations(),this.emitFieldWillValidateEvent(s);const e=await this.emitValidateFieldEvent(t);r(JSON.stringify(e.flat(Number.POSITIVE_INFINITY).filter((e=>void 0!==e)))===JSON.stringify(n.validations),"FieldsStore does not match emitValidateFieldEvent() result, did the user changed the input rapidly?"),this.emitFieldDidValidateEvent(n)}return n}normalizeInputs(...e){let t;return 0===e.length?(t=Array.from(this.form.querySelectorAll("[name]")),t=t.filter((e=>void 0!==e.validity)),t.filter((e=>"checkbox"!==e.type&&"radio"!==e.type)).map((e=>e.name)).forEach(((e,t,i)=>{if(i.indexOf(e)!==t)throw new Error(`Multiple elements matching '[name="${e}"]' inside the form`)}))):t=e.map((e=>{if("string"==typeof e){const t=`[name="${e}"]`,i=Array.from(this.form.querySelectorAll(t));if(i.some((e=>void 0===e.validity)))throw new Error(`'${t}' should match an <input>, <select> or <textarea>`);if(i.filter((e=>"checkbox"!==e.type&&"radio"!==e.type)).length>1)throw new Error(`Multiple elements matching '${t}' inside the form`);const s=i[0];if(void 0===s)throw new Error(`Could not find field '${t}' inside the form`);return s}return e})),t}isValid(){return this.fieldsStore.isValid()}hasFeedbacks(){return this.fieldsStore.hasFeedbacks()}reset(){return this.resetFields()}resetFields(...e){const t=new Array;return this.normalizeInputs(...e).forEach((e=>{const i=this.resetField(new u(e));void 0!==i&&t.push(i)})),t}resetField(e){const t=e.name,i=this.fieldsStore.getField(t);return void 0===i||(i.clearValidations(),this.emitFieldDidResetEvent(i)),i}render(){return d.createElement("form",{ref:e=>this.form=e,...this.props})}}g.childContextTypes={form:i.instanceOf(g).isRequired};class w extends d.PureComponent{}class D extends(V(w)){constructor(e,t){super(e,t),this.fieldFeedbackKeyCounter=0,this.validate=async e=>{const{form:t,fieldFeedbacks:i}=this.context;let s;if(e.name===this.fieldName){const n=t.fieldsStore.getField(this.fieldName);i&&("first"===i.props.stop&&n.hasFeedbacks(i.key)||"first-error"===i.props.stop&&n.hasErrors(i.key)||"first-warning"===i.props.stop&&n.hasWarnings(i.key)||"first-info"===i.props.stop&&n.hasInfos(i.key))||(s=await this._validate(e))}return s};const{form:i,fieldFeedbacks:s}=t;if(this.key=s?s.computeFieldFeedbackKey():i.computeFieldFeedbacksKey(),s){if(this.fieldName=s.fieldName,void 0!==e.for)throw new Error("FieldFeedbacks cannot have a parent and a 'for' prop")}else{if(void 0===e.for)throw new Error("FieldFeedbacks cannot be without parent and without 'for' prop");this.fieldName=e.for}}getChildContext(){return{fieldFeedbacks:this}}computeFieldFeedbackKey(){return`${this.key}.${this.fieldFeedbackKeyCounter++}`}addFieldFeedback(){return this.computeFieldFeedbackKey()}componentDidMount(){const{form:e,fieldFeedbacks:t}=this.context;e.fieldsStore.addField(this.fieldName);(null!=t?t:e).addValidateFieldEventListener(this.validate)}componentWillUnmount(){const{form:e,fieldFeedbacks:t}=this.context;e.fieldsStore.removeField(this.fieldName);(null!=t?t:e).removeValidateFieldEventListener(this.validate)}async _validate(e){return(await this.emitValidateFieldEvent(e)).flat(Number.POSITIVE_INFINITY)}render(){const{children:e}=this.props;return void 0!==e?e:null}}var L;D.defaultProps={stop:"first-error"},D.contextTypes={form:i.instanceOf(g).isRequired,fieldFeedbacks:i.instanceOf(D)},D.childContextTypes={fieldFeedbacks:i.instanceOf(D).isRequired},e.Status=void 0,(L=e.Status||(e.Status={}))[L.None=0]="None",L[L.Pending=1]="Pending",L[L.Rejected=2]="Rejected",L[L.Resolved=3]="Resolved";class x extends d.PureComponent{}class S extends(V(x)){constructor(){super(...arguments),this.state={status:e.Status.None},this.validate=t=>{const{form:i,fieldFeedbacks:s}=this.context;let n;const a=i.fieldsStore.getField(t.name);return"first"===s.props.stop&&a.hasFeedbacks(s.key)||"first-error"===s.props.stop&&a.hasErrors(s.key)||"first-warning"===s.props.stop&&a.hasWarnings(s.key)||"first-info"===s.props.stop&&a.hasInfos(s.key)?this.setState({status:e.Status.None}):n=this._validate(t),n}}getChildContext(){return{async:this}}componentDidMount(){this.context.fieldFeedbacks.addValidateFieldEventListener(this.validate)}componentWillUnmount(){this.context.fieldFeedbacks.removeValidateFieldEventListener(this.validate)}async setStateSync(e){return new Promise((t=>{this.setState(e,t)}))}async _validate(t){let i={status:e.Status.Pending};this.setState(i);try{const s=await this.props.promise(t.value);i={status:e.Status.Resolved,value:s}}catch(t){i={status:e.Status.Rejected,value:t}}return await this.setStateSync(i),this.emitValidateFieldEvent(t)}render(){const{props:t,state:i}=this;let s=null;switch(i.status){case e.Status.None:break;case e.Status.Pending:t.pending&&(s=t.pending);break;case e.Status.Resolved:t.then&&(s=t.then(i.value));break;case e.Status.Rejected:t.catch&&(s=t.catch(i.value));break;default:r(!1,`Unknown status: '${i.status}'`)}return s}}S.contextTypes={form:i.instanceOf(g).isRequired,fieldFeedbacks:i.instanceOf(D).isRequired},S.childContextTypes={async:i.instanceOf(S).isRequired};class R extends d.Component{constructor(){super(...arguments),this.state={fieldIsValid:void 0},this.fieldWillValidate=e=>{e===this.context.fieldFeedbacks.fieldName&&this.setState({fieldIsValid:void 0})},this.fieldDidValidate=e=>{e.name===this.context.fieldFeedbacks.fieldName&&this.setState({fieldIsValid:e.isValid()})},this.fieldDidReset=e=>{e.name===this.context.fieldFeedbacks.fieldName&&this.setState({fieldIsValid:void 0})}}componentDidMount(){this.context.form.addFieldWillValidateEventListener(this.fieldWillValidate),this.context.form.addFieldDidValidateEventListener(this.fieldDidValidate),this.context.form.addFieldDidResetEventListener(this.fieldDidReset)}componentWillUnmount(){this.context.form.removeFieldWillValidateEventListener(this.fieldWillValidate),this.context.form.removeFieldDidValidateEventListener(this.fieldDidValidate),this.context.form.removeFieldDidResetEventListener(this.fieldDidReset)}render(){const{style:e,...t}=this.props;return this.state.fieldIsValid?d.createElement("span",{...t,style:{display:"block",...e}}):null}}R.contextTypes={form:i.instanceOf(g).isRequired,fieldFeedbacks:i.instanceOf(D).isRequired};class I extends d.Component{constructor(t,i){var s;super(t,i),this.validate=e=>{const{when:t}=this.props,{form:i,fieldFeedbacks:s}=this.context,n=i.fieldsStore.getField(e.name),a={...this.state.validation};if("first"===s.props.stop&&n.hasFeedbacks(s.key)||"first-error"===s.props.stop&&n.hasErrors(s.key)||"first-warning"===s.props.stop&&n.hasWarnings(s.key)||"first-info"===s.props.stop&&n.hasInfos(s.key))a.show=void 0;else if(a.show=!1,"function"==typeof t)a.show=t(e.value);else{if("string"!=typeof t)throw new TypeError("Invalid FieldFeedback 'when' type: "+typeof t);if("valid"===t)a.show=void 0;else{const{validity:i}=e;i.valid||("*"===t||i.badInput&&"badInput"===t||i.patternMismatch&&"patternMismatch"===t||i.rangeOverflow&&"rangeOverflow"===t||i.rangeUnderflow&&"rangeUnderflow"===t||i.stepMismatch&&"stepMismatch"===t||i.tooLong&&"tooLong"===t||i.tooShort&&"tooShort"===t||i.typeMismatch&&"typeMismatch"===t||i.valueMissing&&"valueMissing"===t)&&(a.show=!0)}}return n.addOrReplaceValidation(a),this.setState({validation:a,validationMessage:e.validationMessage}),a},this.fieldDidReset=e=>{e.name===this.context.fieldFeedbacks.fieldName&&this.setState((e=>({validation:{...e.validation,show:void 0},validationMessage:""})))},this.key=i.fieldFeedbacks.addFieldFeedback();const{error:n,warning:a,info:d,when:r}=t;let l=e.FieldFeedbackType.Error;if("valid"===r?l=e.FieldFeedbackType.WhenValid:a?l=e.FieldFeedbackType.Warning:d&&(l=e.FieldFeedbackType.Info),l===e.FieldFeedbackType.WhenValid&&(null!==(s=null!=n?n:a)&&void 0!==s?s:d))throw new Error('Cannot have an attribute (error, warning...) with FieldFeedback when="valid"');this.state={validation:{key:this.key,type:l,show:void 0},validationMessage:""}}componentDidMount(){const{form:e,fieldFeedbacks:t,async:i}=this.context;i?i.addValidateFieldEventListener(this.validate):t.addValidateFieldEventListener(this.validate),e.addFieldDidResetEventListener(this.fieldDidReset)}componentWillUnmount(){const{form:e,fieldFeedbacks:t,async:i}=this.context;i?i.removeValidateFieldEventListener(this.validate):t.removeValidateFieldEventListener(this.validate),e.removeFieldDidResetEventListener(this.fieldDidReset)}render(){const{when:t,error:i,warning:s,info:n,className:a,classes:r,style:l,children:o,...h}=this.props,{validation:c,validationMessage:f}=this.state,u=r[c.type],p=void 0!==a?`${a} ${u}`:u;if(c.type===e.FieldFeedbackType.WhenValid)return d.createElement(R,{"data-feedback":this.key,style:l,className:p,...h},o);if(c.show){const e=void 0!==o?o:f;return d.createElement("span",{"data-feedback":this.key,className:p,style:{display:"block",...l},...h},e)}return null}}I.defaultProps={when:()=>!0,classes:{error:"error",warning:"warning",info:"info",whenValid:"when-valid"}},I.contextTypes={form:i.instanceOf(g).isRequired,fieldFeedbacks:i.instanceOf(D).isRequired,async:i.instanceOf(S)};class W extends d.Component{constructor(){super(...arguments),this.state={field:void 0},this.fieldWillValidate=e=>{e===this.props.name&&this.setState({field:"pending"})},this.fieldDidValidate=e=>{e.name===this.props.name&&this.setState({field:e})},this.fieldDidReset=e=>{e.name===this.props.name&&this.setState({field:void 0})}}componentDidMount(){this.context.form.addFieldWillValidateEventListener(this.fieldWillValidate),this.context.form.addFieldDidValidateEventListener(this.fieldDidValidate),this.context.form.addFieldDidResetEventListener(this.fieldDidReset)}componentWillUnmount(){this.context.form.removeFieldWillValidateEventListener(this.fieldWillValidate),this.context.form.removeFieldDidValidateEventListener(this.fieldDidValidate),this.context.form.removeFieldDidResetEventListener(this.fieldDidReset)}fieldValidationStates(){const{field:e}=this.state,t=[];return void 0!==e&&("pending"===e?t.push("isPending"):(e.hasErrors()&&t.push("hasErrors"),e.hasWarnings()&&t.push("hasWarnings"),e.hasInfos()&&t.push("hasInfos"),e.isValid()&&t.push("isValid"))),t}render(){const{innerRef:e,className:t,classes:i,...s}=this.props,n=this.fieldValidationStates();let a=t;return n.forEach((e=>{const t=i[e];void 0!==t&&(void 0!==a?a+=` ${t}`:a=t)})),d.createElement("input",{ref:e,...s,className:a})}}W.contextTypes={form:i.instanceOf(g).isRequired},W.defaultProps={classes:{isPending:"is-pending",hasErrors:"has-errors",hasWarnings:"has-warnings",hasInfos:"has-infos",isValid:"is-valid"}},e.Async=S,e.EventEmitter=l,e.Field=o,e.FieldDidResetEvent=p,e.FieldDidValidateEvent=m,e.FieldFeedback=I,e.FieldFeedbackWhenValid=R,e.FieldFeedbacks=D,e.FieldWillValidateEvent=E,e.FieldsStore=h,e.FormWithConstraints=g,e.IValidityState=c,e.Input=W,e.InputElement=u,e.ValidateFieldEvent=k,e.assert=r,e.deepForEach=function e(i,s){t.Children.forEach(i,(t=>{const i=t;i.props&&i.props.children&&"object"==typeof i.props.children&&e(i.props.children,s),s(i)}))},e.isHTMLInput=f,e.withFieldDidResetEventEmitter=v,e.withFieldDidValidateEventEmitter=F,e.withFieldWillValidateEventEmitter=y,e.withValidateFieldEventEmitter=V,Object.defineProperty(e,"__esModule",{value:!0})}));