UNPKG

@uplink-protocol/form-controller

Version:

Reactive multi-step form controller with dynamic validation and state management

2 lines 32.2 kB
var e={473:(e,t,r)=>{r.r(t),r.d(t,{getValidator:()=>o,predefinedValidators:()=>c,registerValidator:()=>n,runValidator:()=>a,unregisterValidator:()=>s});const i={},n=(e,t)=>{i[e]&&console.warn(`Validator '${e}' already exists and will be overwritten.`),i[e]=t},s=e=>!!i[e]&&(delete i[e],!0),o=e=>i[e],a=(e,t,r,n)=>{const s=i[e];return s?(n&&(r={...r,field:{...r.field,validation:{...r.field.validation,dynamicValidatorParams:n}}}),s(t,r)):(console.warn(`Validator '${e}' not found.`),!0)};n("requiredIf",((e,t)=>{const{condition:r,fields:i,errorMessage:n}=t.field.validation?.dynamicValidatorParams||{};if(!r||!i||!i.length)return!0;const s=i.map((e=>t.formData[e]));let o=!1;switch(r){case"equals":const e=t.field.validation?.dynamicValidatorParams?.value;o=s.some((t=>t===e));break;case"notEmpty":o=s.every((e=>null!=e&&""!==e));break;case"notEquals":const r=t.field.validation?.dynamicValidatorParams?.value;o=s.every((e=>e!==r));break;default:return!0}return!o||("checkbox"===t.field.type?!1!==e:null!=e&&""!==e)||(n||`${t.field.label} is required`)})),n("equals",((e,t)=>{const{targetValue:r,targetField:i,errorMessage:n}=t.field.validation?.dynamicValidatorParams||{};let s;if(i)s=t.formData[i];else{if(void 0===r)return!0;s=r}return e===s||n||`${t.field.label} must equal ${i?"the other field":r}`}));const c={requiredIf:"requiredIf",equals:"equals"}}},t={};function r(i){var n=t[i];if(void 0!==n)return n.exports;var s=t[i]={exports:{}};return e[i](s,s.exports,r),s.exports}r.d=(e,t)=>{for(var i in t)r.o(t,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};class i{constructor(e){Object.defineProperty(this,"current",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_callbacks",{enumerable:!0,configurable:!0,writable:!0,value:[]}),this.current=e}subscribe(e){return this._callbacks.push(e),e(this.current),()=>{this._callbacks=this._callbacks.filter((t=>t!==e))}}set(e){this.current=e,this._callbacks&&this._callbacks.length&&this._callbacks.forEach((t=>t(e)))}get(){return this.current}}class n extends i{constructor(e){super(e)}updateConfig(e){this.set(e)}updateConfigAndReset(e,t){this.updateConfig(e),t()}addStep(e,t){const r={...this.current},i=[...r.steps],n=void 0!==t?t:i.length;return i.splice(n,0,e),r.steps=i,this.set(r),i.length}removeStep(e){const t={...this.current},r=t.steps.findIndex((t=>t.id===e));return-1!==r&&(t.steps=t.steps.filter((t=>t.id!==e)),this.set(t),!0)}getStepById(e){return this.current.steps.find((t=>t.id===e))}getStepByIndex(e){return this.current.steps[e]}get totalSteps(){return this.current.steps.length}}var s=r(473);const o=(e,t,r,i=!1)=>{if(e.disabled)return{isValid:!0};const n=[],o=!0===e.required||e.validation&&!0===e.validation.required,a="checkbox"===e.type||"boolean"==typeof t?!1===t:null==t||""===t;if(o&&a){const t=e.validation?.errorMessages?.required||e.validation?.errorMessage||`${e.label} is required`;if(!i)return{isValid:!1,error:t,errors:[t]};n.push(t)}if(!e.validation)return n.length?{isValid:!1,error:n[0],errors:n}:{isValid:!0};const c=e.validation;if(null==t||""===t)return n.length?{isValid:!1,error:n[0],errors:n}:{isValid:!0};switch(e.type){case"email":if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(t))){const e=c.errorMessages?.email||c.errorMessage||"Please enter a valid email address";if(n.push(e),!i)return{isValid:!1,error:e,errors:n}}break;case"text":case"textarea":case"password":if(void 0!==c.minLength&&String(t).length<c.minLength){const t=c.errorMessages?.minLength||c.errorMessage||`${e.label} must be at least ${c.minLength} characters`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}if(void 0!==c.maxLength&&String(t).length>c.maxLength){const t=c.errorMessages?.maxLength||c.errorMessage||`${e.label} cannot exceed ${c.maxLength} characters`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}if(c.pattern&&!(c.pattern instanceof RegExp?c.pattern:new RegExp(c.pattern)).test(String(t))){const t=c.errorMessages?.pattern||c.errorMessage||`${e.label} format is invalid`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}break;case"number":case"tel":if(void 0!==c.min&&Number(t)<c.min){const t=c.errorMessages?.min||c.errorMessage||`${e.label} must be at least ${c.min}`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}if(void 0!==c.max&&Number(t)>c.max){const t=c.errorMessages?.max||c.errorMessage||`${e.label} cannot exceed ${c.max}`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}}if(c.custom){const r=c.custom(t);if(!1===r){const t=c.errorMessages?.custom||c.errorMessage||`${e.label} is invalid`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}else if("string"==typeof r&&(n.push(r),!i))return{isValid:!1,error:r,errors:n}}const l={field:e,formData:r?.formData||{},stepId:r?.stepId||"",fieldId:r?.fieldId||""};if(c.dynamicValidator&&r){const r=(0,s.runValidator)(c.dynamicValidator,t,l,c.dynamicValidatorParams);if(!1===r){const t=c.errorMessage||`${e.label} is invalid`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}else if("string"==typeof r&&(n.push(r),!i))return{isValid:!1,error:r,errors:n}}if(c.dynamicValidators&&c.dynamicValidators.length>0&&r)for(const r of c.dynamicValidators){const o=(0,s.runValidator)(r.name,t,l,r.params);if(!1===o){const t=r.errorMessage||c.errorMessage||`${e.label} is invalid`;if(n.push(t),!i)return{isValid:!1,error:t,errors:n}}else if("string"==typeof o&&(n.push(o),!i))return{isValid:!1,error:o,errors:n}}return n.length>0?{isValid:!1,error:n[0],errors:n}:{isValid:!0}};class a{constructor(e,t,r,i){Object.defineProperty(this,"configService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"formService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"fieldErrorsService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"stepsValidityService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.configService=e,this.formService=t,this.fieldErrorsService=r,this.stepsValidityService=i}validateField(e,t,r,i=!0){const n=this.configService.getStepById(e);if(!n)return!1;const s=n.fields[t];if(!s)return!1;const a=void 0!==r?r:this.formService.get()[e]?.[t],c={field:s,fieldId:t,stepId:e,formData:this.formService.get()[e]||{}},l=!0===s.validation?.collectAllErrors,d=o(s,a,c,l);if(i){const r={...this.fieldErrorsService.get()};r[e]||(r[e]={}),d.isValid?delete r[e][t]:d.errors&&d.errors.length>1&&l?r[e][t]=d.errors.join(" | "):r[e][t]=d.error||"Invalid field",this.fieldErrorsService.set(r)}else if(d.isValid){const r={...this.fieldErrorsService.get()};r[e]&&r[e][t]&&(delete r[e][t],this.fieldErrorsService.set(r))}return d.isValid}validateStep(e,t=!0){const r=this.configService.getStepById(e);if(!r)return!1;let i=!0;const n=this.formService.getStepData(e);if(Object.keys(r.fields).forEach((r=>{this.validateField(e,r,n[r],t)||(i=!1)})),i&&r.validation){const s=r.validation(n);if(!0!==s&&(i=!1,t)){const t={...this.fieldErrorsService.get()};t[e]||(t[e]={}),t[e].__step__="string"==typeof s?s:"Invalid step data",this.fieldErrorsService.set(t)}}const s={...this.stepsValidityService.get()};return s[e]=i,this.stepsValidityService.set(s),i}validateForm(e=!0){const t=this.configService.get();let r=!0;return t.steps.forEach((t=>{this.validateStep(t.id,e)||(r=!1)})),r}getFieldErrorsService(){return this.fieldErrorsService}getStepsValidityService(){return this.stepsValidityService}}class c extends i{constructor(e,t,r,i){super(e),Object.defineProperty(this,"configService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"fieldErrorsService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.configService=t,this.fieldErrorsService=r}updateField(e,t,r){const i=this.configService.getStepById(e);if(!i||!i.fields[t])return void console.error(`Step "${e}" or field "${t}" doesn't exist`);const n=JSON.parse(JSON.stringify(this.current));n[e]||(n[e]={}),n[e][t]=r,this.set(n)}getStepData(e){return this.current[e]||{}}getAllData(){return this.current}getFlatData(){const e={};return Object.values(this.current).forEach((t=>{Object.entries(t).forEach((([t,r])=>{e[t]=r}))})),e}resetForm(e){const t=this.configService.get(),r={};t.steps.forEach((i=>{r[i.id]={},Object.entries(i.fields).forEach((([n,s])=>{const o=e?.[n]??t.defaultValues?.[n]??s.value??"";r[i.id][n]=o}))})),this.set(r),this.fieldErrorsService.set({})}submitForm(e,t,r){if(e()){const e=this.getAllData();return console.log("Form submitted:",JSON.stringify(e,null,2)),{success:!0,data:e}}{console.warn("Cannot submit form: validation failed");const e=t();return-1!==e&&r(e),{success:!1,errors:this.fieldErrorsService.get()}}}completeReset(e,t){this.resetForm(),e(),t()}}class l{constructor(e,t){Object.defineProperty(this,"touchedFields",{enumerable:!0,configurable:!0,writable:!0,value:{}}),Object.defineProperty(this,"configService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"fieldService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.configService=e,this.fieldService=t,this.initTouchTracking()}initTouchTracking(){this.configService.get().steps.forEach((e=>{this.touchedFields[e.id]={},Object.keys(e.fields).forEach((t=>{this.touchedFields[e.id][t]=!1}))}))}markFieldTouched(e,t,r=!0){this.touchedFields[e]||(this.touchedFields[e]={}),this.touchedFields[e][t]=r}markAllFieldsInStepTouched(e,t=!0){const r=this.configService.getStepById(e);r&&(this.touchedFields[e]||(this.touchedFields[e]={}),Object.keys(r.fields).forEach((r=>{this.touchedFields[e][r]=t})))}markAllFieldsTouched(e=!0){this.configService.get().steps.forEach((t=>{this.touchedFields[t.id]||(this.touchedFields[t.id]={}),Object.keys(t.fields).forEach((r=>{this.touchedFields[t.id][r]=e}))}))}isFieldTouched(e,t){return!0===this.touchedFields[e]?.[t]}validateStepWithTouchedErrors(e){const t=this.configService.getStepById(e);if(!t)return!1;let r=!0;return Object.keys(t.fields).forEach((t=>{const i=!0===this.touchedFields[e]?.[t];this.fieldService.validateField(e,t,void 0,i)||(r=!1)})),r}resetTouchTracking(){this.initTouchTracking()}getTouchState(){return this.touchedFields}}class d extends i{constructor(e,t){super(e),Object.defineProperty(this,"configService",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.configService=t}nextStep(e){if(this.current<this.configService.totalSteps-1){if(e&&!e())return this.current;const t=this.current+1;return this.set(t),t}return this.current}validateAndNext(e,t,r){if(t(e,!0),r(!0)){const e=this.current+1;if(e<this.configService.totalSteps)return this.set(e),e}return this.get()}prevStep(){if(this.current>0){const e=this.current-1;return this.set(e),e}return 0}goToStep(e){return e>=0&&e<this.configService.totalSteps&&(this.set(e),this.current=e,!0)}get isFirstStep(){return 0===this.current}get isLastStep(){return this.current===this.configService.totalSteps-1}}class u{constructor(){}registerValidator(e,t){const{registerValidator:i}=r(473);i(e,t)}unregisterValidator(e){const{unregisterValidator:t}=r(473);return t(e)}getAvailableValidators(){const{predefinedValidators:e}=r(473);return e}}var h={d:(e,t)=>{for(var r in t)h.o(t,r)&&!h.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},f={};h.d(f,{o8:()=>k,T6:()=>p,Dy:()=>b,ai:()=>v,RW:()=>F,bk:()=>y,Xu:()=>A,Nw:()=>S,_t:()=>V,f:()=>U,op:()=>M,BV:()=>g,Pq:()=>T,vA:()=>_,Kj:()=>E,hq:()=>w,XG:()=>L,tt:()=>P,gT:()=>N,Ay:()=>R,y9:()=>B,yl:()=>D,fO:()=>C,vB:()=>m,Ly:()=>I,nj:()=>$,ZZ:()=>O,hh:()=>j,Xr:()=>q});class p{constructor(){Object.defineProperty(this,"adapters",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"defaultAdapter",{enumerable:!0,configurable:!0,writable:!0,value:null})}static getInstance(){return p.instance||(p.instance=new p),p.instance}registerAdapter(e){this.adapters.set(e.name,e),e.initialize(),this.defaultAdapter||this.setDefaultAdapter(e.name)}getAdapter(e){return this.adapters.get(e)}getAllAdapters(){return Array.from(this.adapters.values())}hasAdapter(e){return this.adapters.has(e)}removeAdapter(e){return this.adapters.delete(e)}setDefaultAdapter(e){if(!this.hasAdapter(e))throw new Error(`Cannot set default adapter: adapter '${e}' is not registered`);this.defaultAdapter=e}getDefaultAdapter(){return this.defaultAdapter?this.adapters.get(this.defaultAdapter):void 0}setAutoDetect(e){}getAppropriateAdapter(){return this.getDefaultAdapter()}}class b{constructor(){Object.defineProperty(this,"controllerMap",{enumerable:!0,configurable:!0,writable:!0,value:new Map})}initialize(e){console.log(`${this.name} adapter initialized (v${this.version})`)}connectController(e,t){this.controllerMap.set(e,t),this.onControllerConnected(e,t)}disconnectController(e){if(this.controllerMap.has(e)){const t=this.controllerMap.get(e);this.onControllerDisconnected(e,t),this.controllerMap.delete(e)}}handleEvent(e,t,r){const i=this.controllerMap.get(e);i&&this.dispatchDOMEvent(i,t,r),this.onControllerEvent(e,t,r)}dispatchDOMEvent(e,t,r){const i=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:r});e.dispatchEvent(i)}onControllerConnected(e,t){}onControllerDisconnected(e,t){}onControllerEvent(e,t,r){}}class g extends b{constructor(){super(...arguments),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:"vanilla"}),Object.defineProperty(this,"version",{enumerable:!0,configurable:!0,writable:!0,value:"1.0.0"})}watchProperty(e,t,r){if(e.bindings&&e.bindings[t])if("function"==typeof e.bindings[t].subscribe)e.bindings[t].subscribe(r);else if(null!==e.bindings[t]){let i=e.bindings[t].current;Object.defineProperty(e.bindings,t,{get:()=>i,set:e=>{const t=i;i=e,t!==e&&r(e)},enumerable:!0,configurable:!0})}}updateProperty(e,t,r){e.bindings&&e.bindings[t]&&("function"==typeof e.bindings[t].set?e.bindings[t].set(r):null!==e.bindings[t]&&(e.bindings[t]=r))}callMethod(e,t,r=[]){if(e.methods&&"function"==typeof e.methods[t])return e.methods[t](...r);if("function"==typeof e[t])return e[t](...r);throw new Error(`Method '${t}' not found on controller`)}onControllerConnected(e,t){e.meta&&e.meta.events&&Object.keys(e.meta.events).forEach((r=>{t.addEventListener(r,(t=>{if(e.events&&e.events[r]){const i=t.detail;e.events[r].emit(i)}}))}))}}class v{constructor(e,t){if(Object.defineProperty(this,"registry",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"adapter",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"element",{enumerable:!0,configurable:!0,writable:!0,value:null}),this.controller=e,this.registry=p.getInstance(),t&&this.registry.hasAdapter(t))this.adapter=this.registry.getAdapter(t);else{const e=this.registry.getAppropriateAdapter();if(e)this.adapter=e;else{const e=new g;this.registry.registerAdapter(e),this.adapter=e}}}connect(e){this.element=e,this.adapter.connectController(this.controller,e)}disconnect(){this.element&&(this.adapter.disconnectController(this.controller),this.element=null)}emitEvent(e,t){this.adapter.handleEvent(this.controller,e,t)}watchProperty(e,t){this.adapter.watchProperty(this.controller,e,t)}updateProperty(e,t){this.adapter.updateProperty(this.controller,e,t)}callMethod(e,t){return this.adapter.callMethod(this.controller,e,t)}getAdapter(){return this.adapter}setAdapter(e){if(this.registry.hasAdapter(e)){const t=this.registry.getAdapter(e);return this.element&&this.adapter.disconnectController(this.controller),this.adapter=t,this.element&&this.adapter.connectController(this.controller,this.element),!0}return!1}}function m(){return p.getInstance()}class y{constructor(e){Object.defineProperty(this,"listeners",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"adapter",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"eventName",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.eventName=e}connectToAdapter(e,t){this.eventName=t,this.adapter=e.__adapter}emit(e){this.listeners.forEach((t=>t(e))),this.adapter&&this.eventName&&this.adapter.emitEvent(this.eventName,e)}subscribe(e){return this.listeners.push(e),()=>{this.listeners=this.listeners.filter((t=>t!==e))}}}class S{constructor(e){Object.defineProperty(this,"current",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_callbacks",{enumerable:!0,configurable:!0,writable:!0,value:[]}),this.current=e}set(e){this.current=e;const t=this._callbacks.slice();for(let r=0;r<t.length;r++)try{t[r](e)}catch(e){console.error("Error in binding subscriber:",e)}}subscribe(e){if("function"!=typeof e)return console.error("Attempted to subscribe with non-function:",e),()=>{};this._callbacks.push(e);let t=!1;return()=>{t||(t=!0,this._callbacks=this._callbacks.filter((t=>t!==e)))}}}function w(e,t,r){const i=new v(e,r);e.__adapter=i,"initialize"in e&&"function"==typeof e.initialize?Promise.resolve(e.initialize()).then((()=>{x(e,t,i)})).catch((r=>{console.error("Error initializing controller:",r),x(e,t,i)})):x(e,t,i)}function x(e,t,r){if(r.connect(t),e.events&&Object.entries(e.events).forEach((([t,r])=>{r instanceof y&&r.connectToAdapter(e,t)})),"connect"in e&&"function"==typeof e.connect)try{e.connect(t)}catch(e){console.error("Error in controller.connect():",e)}if("registerUI"in e&&"function"==typeof e.registerUI)try{if(1===e.registerUI.length){if("connect"in e&&"function"==typeof e.connect){const r=e.connect(t);r&&e.registerUI(r)}}else 2===e.registerUI.length&&e.registerUI(t)}catch(e){console.error("Error in controller.registerUI():",e)}}function C(e){e.__adapter&&(e.__adapter.disconnect(),delete e.__adapter)}function E(e,t,r){const i=new S(t(...e.map((e=>r.bindings[e].current)))),n=e.map((n=>r.bindings[n].subscribe((()=>{i.set(t(...e.map((e=>r.bindings[e].current))))}))));return i.cleanup=()=>{n.forEach((e=>e()))},i}function _(e){e()}function O(e){m().registerAdapter(e)}function j(e){m().setDefaultAdapter(e)}class V{constructor(e,t){Object.defineProperty(this,"_state",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_frameworkContext",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_subscriptions",{enumerable:!0,configurable:!0,writable:!0,value:[]}),this._state=e,this._frameworkContext=t}get frameworkContext(){return this._frameworkContext}get element(){return this._frameworkContext.element||this._frameworkContext.getElement&&this._frameworkContext.getElement()||document.createElement("div")}get state(){return this._state}setState(e){this._state={...this._state,...e},this._frameworkContext.render&&this._frameworkContext.render()}addSubscription(e){this._subscriptions.push(e)}cleanup(){this._frameworkContext.cleanup&&this._frameworkContext.cleanup(),this._subscriptions.forEach((e=>e())),this._subscriptions=[]}}class A{constructor(){Object.defineProperty(this,"bindings",{enumerable:!0,configurable:!0,writable:!0,value:{}}),Object.defineProperty(this,"methods",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"events",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"meta",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"__adapter",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"_uiContexts",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"_activeContext",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_globalSubscriptions",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"_isSyncingState",{enumerable:!0,configurable:!0,writable:!0,value:!1})}getActiveContext(){if(!this._activeContext&&this._uiContexts.size>0&&(this._activeContext=this._uiContexts.values().next().value),!this._activeContext)throw new Error("No active UI context - Controller must be connected to a UI before using methods");return this._activeContext}setActiveContext(e){this._uiContexts.has(e.frameworkContext.id)&&this._activeContext!==e&&(this._activeContext=e,this.syncStateFromContext(e))}syncStateFromContext(e){this._isSyncingState?console.warn("Preventing recursive syncStateFromContext call"):(this._isSyncingState=!0,this._isSyncingState=!1)}connect(e){return this.connectWithContext({id:e.id||`element-${Date.now()}`,element:e,getElement:()=>e})}connectWithContext(e){const t=new V({},e);return this._uiContexts.set(e.id,t),this._activeContext=t,this.syncStateFromContext(t),t}disconnect(e){e.cleanup(),this._uiContexts.delete(e.frameworkContext.id),this._activeContext===e&&(this._activeContext=null,this._uiContexts.size>0&&(this._activeContext=this._uiContexts.values().next().value,this.syncStateFromContext(this._activeContext)))}dispose(){for(const e of this._uiContexts.values())e.cleanup();this._uiContexts.clear(),this._globalSubscriptions.forEach((e=>e())),this._globalSubscriptions=[]}registerUI(e){const t=this._activeContext;this._activeContext=e;try{if(e.frameworkContext.element){const t=P(this,e.frameworkContext.element);return e.addSubscription(t),t}return()=>{}}finally{this._activeContext=t}}batchUpdates(e){const t=new Map,r=new Map;Object.keys(this.bindings).forEach((e=>{const i=this.bindings[e];t.set(e,i.set.bind(i)),i.set=t=>{r.set(e,t)}}));try{e(),r.forEach(((e,r)=>{t.get(r)?.(e)}))}finally{Object.keys(this.bindings).forEach((e=>{const r=this.bindings[e],i=t.get(e);i&&(r.set=i)}))}}}function P(e,t){const r=[];return t.querySelectorAll("[data-uplink]").forEach((t=>{const i=t.getAttribute("data-uplink");if(!i||!e.bindings[i])return;const n=e.bindings[i];if(t instanceof HTMLInputElement){if(n.current instanceof Date&&e.methods?.formatDate){const r=e.methods.formatDate,i=e.bindings.format?.current||"yyyy-MM-dd";t.value=r(n.current,i)}else t.value=n.current?.toString()||"";t.addEventListener("input",(()=>{if("selectedDate"===i&&e.methods?.setDate)try{const r=new Date(t.value);isNaN(r.getTime())||(0,e.methods.setDate)(r)}catch(e){console.error("Invalid date input:",e)}else n.set(t.value)})),r.push(n.subscribe((r=>{if(r instanceof Date&&e.methods?.formatDate){const i=e.methods.formatDate,n=e.bindings.format?.current||"yyyy-MM-dd";t.value=i(r,n)}else t.value=r?.toString()||""})))}else t.textContent=n.current?.toString()||"",r.push(n.subscribe((e=>{t.textContent=e?.toString()||""})))})),()=>{r.forEach((e=>e()))}}class k extends A{connect(e){const t={id:e.id||`element-${Date.now()}`,element:e,getElement:()=>e};return this.connectWithContext(t)}connectWithContext(e){const t=this.createInitialUIState(),r=new V(t,e);return this._uiContexts.set(e.id,r),this._activeContext=r,this.registerUI(r),this.setupBindingSyncToActiveContext(),this.syncStateFromContext(r),r}setupBindingSyncToActiveContext(){const e=Object.keys(this.bindings).reduce(((e,t)=>(t in this.createInitialUIState()&&(e[t]=t),e)),{});Object.entries(e).forEach((([e,t])=>{const r=this.bindings[e];r&&"function"==typeof r.subscribe&&this._globalSubscriptions.push(r.subscribe((e=>{const r=this.getActiveContext();if(r&&!this._isSyncingState){const i={[t]:e};r.setState(i)}})))}))}updateActiveContext(e){const t=this.getActiveContext();t.setState(e),this.syncStateFromContext(t)}batchUpdateActiveContext(e){this._isSyncingState=!0;try{const t=this.getActiveContext();t.setState(e),this.batchUpdates((()=>{this.syncStateFromContext(t)}))}finally{this._isSyncingState=!1}}}class F{constructor(){Object.defineProperty(this,"factories",{enumerable:!0,configurable:!0,writable:!0,value:new Map})}static getInstance(){return F.instance||(F.instance=new F),F.instance}register(e,t){this.factories.set(e,t)}create(e){const t=this.factories.get(e);if(!t)throw new Error(`Controller factory not registered for '${e}'`);return t()}has(e){return this.factories.has(e)}unregister(e){return this.factories.delete(e)}}function I(){return F.getInstance()}function M(e){return function(t){return F.getInstance().register(e,(()=>new t)),t}}function D(){return"vanilla"}function T(){const e=m();if(e.getAllAdapters().length>0)return void console.log("Uplink Protocol adapters are already registered");const t=new g;e.registerAdapter(t),e.setDefaultAdapter("vanilla"),console.log("Uplink Protocol initialized with vanilla adapter")}function $(){T()}"undefined"!=typeof window&&setTimeout((()=>{T()}),0);class U{constructor(e){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"element",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"_eventUnsubscribes",{enumerable:!0,configurable:!0,writable:!0,value:[]}),this.controller=e}connect(e,t={}){if(this.element=e,this.element.setAttribute("data-uplink-controller",""),this.controller.events)for(const[e,r]of Object.entries(this.controller.events)){const i=t[`on${e.charAt(0).toUpperCase()+e.slice(1)}`];if("function"==typeof i){const e=r.subscribe((e=>{i(e)}));this._eventUnsubscribes.push(e)}}return w(this.controller,this.element,"vanilla"),()=>this.disconnect()}disconnect(){this._eventUnsubscribes.forEach((e=>e())),this._eventUnsubscribes=[],C(this.controller),this.element=null}}function q(e,t={}){let r;r="string"==typeof e?I().create(e):"function"==typeof e?e():e;const i={},n="all"===t.trackBindings?Object.keys(r.bindings||{}):t.trackBindings||[];n.forEach((e=>{r.bindings&&r.bindings[e]&&(i[e]=r.bindings[e].current)}));const s=[];n.forEach((e=>{if(r.bindings&&r.bindings[e]){const t=r.bindings[e].subscribe((t=>{i[e]=t}));s.push(t)}}));const o=new U(r);return{controller:r,state:i,methods:r.methods||{},events:r.events||{},connect:(e,t={})=>o.connect(e,t),disconnect:()=>{s.forEach((e=>e())),o.disconnect()}}}function B(e,t,r={}){"undefined"!=typeof customElements?customElements.define(e,class extends HTMLElement{constructor(){if(super(),Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"cleanup",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"eventHandlers",{enumerable:!0,configurable:!0,writable:!0,value:{}}),this.controller="string"==typeof t?I().create(t):"function"==typeof t?t():t,r.onEvent&&this.controller.events)for(const[e,t]of Object.entries(r.onEvent))this.controller.events[e]&&(this.eventHandlers[`on${e.charAt(0).toUpperCase()+e.slice(1)}`]=e=>t(e,this));r.shadow&&this.attachShadow({mode:"open"})}connectedCallback(){r.template&&(this.shadowRoot?this.shadowRoot.innerHTML=r.template:this.innerHTML=r.template);const e=new U(this.controller);this.cleanup=e.connect(this.shadowRoot?this.shadowRoot:this,this.eventHandlers),r.onConnected&&r.onConnected(this.shadowRoot?this.shadowRoot:this,this.controller)}disconnectedCallback(){r.onDisconnected&&r.onDisconnected(this.shadowRoot?this.shadowRoot:this,this.controller),this.cleanup&&(this.cleanup(),this.cleanup=null)}}):console.error("Custom Elements are not supported in this browser")}function L(e){const t={};return Object.keys(e).forEach((r=>{t[r]=new S(e[r])})),t}function N(e){const t={};if(Array.isArray(e))e.forEach((e=>{t[e]=new y}));else for(const r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=new y);return t}const R={connectController:w,disconnectController:C,createBindings:L,createEventEmitters:N,StandardBinding:S,EventEmitter:y,ControllerAdapter:v};var W=f.XG;const z=e=>{const t={},r={};e.steps.forEach((i=>{t[i.id]={},Object.entries(i.fields).forEach((([r,n])=>{const s=e.defaultValues?.[r]??n.value??"";t[i.id][r]=s}));const n=Object.values(i.fields).some((e=>!0===e.required));r[i.id]=!n}));const s=new i({}),o=new i(r),h=new n(e),f=new d(0,h),p=new c(t,h,s,o),b=new a(h,p,s,o),g=new l(h,b),v=new u,m={bindings:W({config:e,currentStepIndex:0,currentStep:e.steps[0],formData:t,stepsValidity:r,fieldErrors:{},totalSteps:e.steps.length,isLastStep:1===e.steps.length,isFirstStep:!0,isFormValid:!1}),methods:{nextStep:()=>{const e=m.bindings.currentStep.current;if(g.markAllFieldsInStepTouched(e.id,!0),m.methods.validateCurrentStep(!0)){const e=m.bindings.currentStepIndex.current+1;if(e<h.get().steps.length){f.set(e),m.bindings.currentStepIndex.current=e;const t=h.getStepByIndex(e);return t&&(m.bindings.currentStep.current=t),e}}return m.bindings.currentStepIndex.current},prevStep:()=>{const e=m.bindings.currentStepIndex.current;if(e>0){const t=e-1;f.set(t),m.bindings.currentStepIndex.current=t;const r=h.getStepByIndex(t);return r&&(m.bindings.currentStep.current=r),t}return e},goToStep:e=>{const t=f.goToStep(e);if(t){m.bindings.currentStepIndex.current=e;const t=h.getStepByIndex(e);t&&(m.bindings.currentStep.current=t)}return t},updateField:(e,t,r)=>{const i={...p.get()};i[e]||(i[e]={}),i[e][t]=r,p.set(i),m.bindings.formData.current=i,g.markFieldTouched(e,t,!0),b.validateField(e,t,r,!0),g.validateStepWithTouchedErrors(e)},validateField:(e,t,r,i=!0)=>{const n=h.getStepById(e),o=n?.fields[t];if(!n||!o)return!1;const a=b.validateField(e,t,r,i);if(!a&&i){const r=s.get();r[e]||(r[e]={}),r[e][t]||(r[e][t]=`${o.label} is required`),m.bindings.fieldErrors.current={...r}}return a},validateStep:(e,t=!0)=>b.validateStep(e,t),validateCurrentStep:(e=!0)=>{const t=m.bindings.currentStep.current;return b.validateStep(t.id,e)},validateCurrentStepWithTouchedErrors:()=>{const e=m.bindings.currentStep.current;return g.validateStepWithTouchedErrors(e.id)},validateStepWithTouchedErrors:e=>g.validateStepWithTouchedErrors(e),validateForm:(e=!0)=>b.validateForm(e),submitForm:()=>p.submitForm((()=>(g.markAllFieldsTouched(!0),m.methods.validateForm(!0))),(()=>{const e=o.get();return h.get().steps.findIndex((t=>!e[t.id]))}),(e=>{-1!==e&&e!==f.get()&&f.set(e)})),resetForm:()=>{g.resetTouchTracking();const e=h.get(),t={};e.steps.forEach((r=>{t[r.id]={},Object.entries(r.fields).forEach((([i,n])=>{const s=e.defaultValues?.[i]??n.value??"";t[r.id][i]=s}))})),p.set(t),m.bindings.formData.current=t,m.methods.validateForm(!1)},updateConfig:e=>{h.set(e),m.bindings.config.current=e,m.bindings.totalSteps.current=e.steps.length,g.resetTouchTracking(),p.resetForm(),m.methods.validateForm(!1)},getStepData:e=>p.getStepData(e),getAllData:()=>p.getAllData(),getFlatData:()=>p.getFlatData(),addStep:(e,t)=>{const r=h.get(),i=[...r.steps];void 0!==t&&t>=0&&t<=i.length?i.splice(t,0,e):i.push(e);const n={...r,steps:i};h.set(n),m.bindings.config.current=n,m.bindings.totalSteps.current=i.length;const s={...p.get()};return s[e.id]={},Object.entries(e.fields).forEach((([t,i])=>{const n=r.defaultValues?.[t]??i.value??"";s[e.id][t]=n})),p.set(s),m.bindings.formData.current=s,b.validateStep(e.id,!1),i.length},removeStep:e=>{const t=h.get();if(-1===t.steps.findIndex((t=>t.id===e)))return!1;const r=t.steps.filter((t=>t.id!==e)),i={...t,steps:r};h.set(i),m.bindings.config.current=i,m.bindings.totalSteps.current=r.length;const n={...p.get()};delete n[e],p.set(n),m.bindings.formData.current=n;const a={...o.get()};delete a[e],o.set(a);const c={...s.get()};return delete c[e],s.set(c),m.bindings.fieldErrors.current=c,f.get()>=r.length&&f.set(Math.max(0,r.length-1)),!0},registerValidator:(e,t)=>{v.registerValidator(e,t)},unregisterValidator:e=>v.unregisterValidator(e),getAvailableValidators:()=>v.getAvailableValidators()}};return e.steps.forEach((e=>{if(Object.entries(e.fields).some((([r,i])=>{if(i.required||i.validation&&i.validation.required){const n=t[e.id]?.[r];return"checkbox"===i.type?!1===n:!n}return!1}))){const t={...o.get()};t[e.id]=!1,o.set(t)}})),m},H=s.registerValidator,X=s.unregisterValidator,J=()=>s.predefinedValidators;export{i as BaseService,n as ConfigService,a as FieldService,z as FormController,c as FormService,l as InteractionService,d as StepperService,u as ValidatorService,J as getAvailableValidators,H as registerValidator,X as unregisterValidator,o as validateField}; //# sourceMappingURL=index.js.map