@piying/view-angular-core 0.6.30 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/piying-view-angular-core-test.mjs +102 -1
- package/fesm2022/piying-view-angular-core-test.mjs.map +1 -0
- package/fesm2022/piying-view-angular-core.mjs +2111 -1
- package/fesm2022/piying-view-angular-core.mjs.map +1 -0
- package/index.d.ts +4 -4
- package/package.json +31 -2
- package/readme.md +1 -0
|
@@ -1 +1,2111 @@
|
|
|
1
|
-
import{effect,inject,Injector,untracked,DestroyRef,isSignal,signal,InjectionToken,computed,EnvironmentInjector,linkedSignal}from"@angular/core";import*as v from"valibot";import{deepEqual}from"fast-equals";import{BehaviorSubject,isObservable,Subject,combineLatest,startWith,skip,map}from"rxjs";import rfdc from"rfdc";import{createRawConfig,BaseSchemaHandle,convertSchema,convertCore}from"@piying/valibot-visit";export{asControl,asVirtualGroup,changeObject,condition,getDefaults,getSchemaByIssuePath,getSchemaMetadata}from"@piying/valibot-visit";import clsx from"clsx";function arrayStartsWith(list,parts){return(Array.isArray(parts)?parts:[parts]).every((item,index)=>item===list[index])}function effectListen(listen,fn,options){let first=!0,oldValue=listen();return effect(()=>{let currentValue=listen();if(first){first=!1,deepEqual(oldValue,currentValue)||fn();return}return fn()},options)}function toObservable(listen,source,options){let injector=options?.injector??inject(Injector),subject=new BehaviorSubject(source()),watcher=effectListen(listen,()=>{let value;try{value=source()}catch(err){untracked(()=>subject.error(err));return}untracked(()=>subject.next(value))},{injector,manualCleanup:!0});return injector.get(DestroyRef).onDestroy(()=>{watcher.destroy(),subject.complete()}),subject.asObservable()}let clone=rfdc({proto:!1,circles:!1});function unWrapSignal$1(value){return isSignal(value)?value():value}function toArray(input){return void 0===input||Array.isArray(input)?input:[input]}class SortedArray extends Array{#compareFn;constructor(compareFn){super(),this.#compareFn=compareFn}push(...items){let result=super.push(...items);return this.sort(this.#compareFn),result}}function createViewControlLink(fieldControl,cva,injector){cva.registerOnChange(value=>{fieldControl().disabled$$()||(fieldControl().pendingStatus.update(status=>({...status,value:value,change:!0})),"change"===fieldControl().updateOn$$()&&fieldControl().viewValueChange(value))}),cva.registerOnTouched(()=>{if(fieldControl().disabled$$())return;let updateOn=fieldControl().updateOn$$(),pendingStatus=fieldControl().pendingStatus();"submit"===updateOn?fieldControl().pendingStatus.update(status=>({...status,touched:!0})):(fieldControl().markAsTouched(),pendingStatus.change&&"blur"===updateOn&&(fieldControl().viewValueChange(pendingStatus.value),fieldControl().pendingStatus.update(status=>({...status,change:!1,value:void 0}))))});let disposeList=[],ref=effect(()=>{let value=fieldControl().modelValueToViewValue$$();untracked(()=>{cva.writeValue(value)})},{injector:injector});if(cva.writeValue(fieldControl().modelValueToViewValue$$()),disposeList.push(()=>ref.destroy()),cva.setDisabledState){let disabledRef=effect(()=>{let value=fieldControl().disabled$$();untracked(()=>{cva.setDisabledState(value)})},{injector:injector});cva.setDisabledState(fieldControl().disabled$$()),disposeList.push(()=>disabledRef.destroy())}return()=>{disposeList.forEach(fn=>fn()),untracked(()=>{fieldControl().updateValue(fieldControl().value$$(),!0)})}}function controlStatusList(fieldControl,skipDisabled){if(!fieldControl)return[];let statusList=[];switch(!skipDisabled&&fieldControl.disabled$$()&&statusList.push("disabled"),fieldControl.touched$$()?statusList.push("touched"):statusList.push("untouched"),fieldControl.dirty$$()?statusList.push("dirty"):statusList.push("pristine"),fieldControl.status$$()){case"VALID":statusList.push("valid");break;case"INVALID":statusList.push("invalid");break;case"PENDING":statusList.push("pending")}return statusList}function fieldControlStatusClass(fieldControl,skipDisabled){return controlStatusList(fieldControl,skipDisabled).map(item=>`pi-${item}`).join(" ")}function isPromise(obj){return!!obj&&"function"==typeof obj.then}let ValidatorPending=Symbol("PENDING"),PI_VIEW_CONFIG_TOKEN=new InjectionToken("PI_VIEW_CONFIG"),PI_FORM_BUILDER_OPTIONS_TOKEN=new InjectionToken("PI_FORM_BUILDER_OPTIONS"),PI_FORM_BUILDER_ALIAS_MAP=new InjectionToken("PI_FORM_BUILDER_ALIAS_MAP"),PI_CONTEXT_TOKEN=new InjectionToken("PI_CONTEXT");class FieldArray extends AbstractControl{#deletionMode$$=computed(()=>this.config$().deletionMode??"shrink");value$$=computed(()=>{let list=[];for(let control of this.controls$())if(control&&control.shouldInclude$$())list.push(control.value$$());else{if("shrink"===this.#deletionMode$$())continue;"mark"===this.#deletionMode$$()&&list.push(void 0)}let returnResult=0===list.length?this.emptyValue$$():list;return this.config$().transfomer?.toModel?.(returnResult,this)??returnResult});children$$=computed(()=>this.controls$());controls$=signal([]);get controls(){return this.controls$()}removeAt(index){let adjustedIndex=this._adjustIndex(index);this.controls$()[adjustedIndex]&&this.controls$.update(list=>((list=list.slice()).splice(adjustedIndex,1),list))}setControl(index,control){let adjustedIndex=this._adjustIndex(index);this.controls$.update(list=>((list=list.slice())[adjustedIndex]=control,list)),control.setParent(this)}get length(){return this.controls$().length}reset(value=[]){this._forEachChild((control,index)=>{control.reset(value[index])})}getRawValue(){return this.controls$().map(control=>control.getRawValue())}clear(){this.controls$().length<1||this.controls$.update(()=>[])}_adjustIndex(index){return index<0?Math.max(index+this.length,0):index}_forEachChild(cb){this.controls$().forEach((control,index)=>{control&&cb(control,index)})}find(name){return this.controls$()[this._adjustIndex(name)]}beforeUpdateList=[];updateValue(value=[]){if(deepEqual(value,this.value$$()))return;let viewValue=this.config$().transfomer?.toView?.(value,this)??value;this.beforeUpdateList.forEach(item=>item(viewValue)),this.controls$().forEach((control,i)=>{control.updateValue(viewValue[i])})}}let InitPendingValue={touched:!1,change:!1,value:void 0};class FieldControl extends AbstractControl{pendingStatus=signal(InitPendingValue);children$$;#viewIndex=0;viewIndex$=signal(0);modelValue$=signal(void 0);modelValueToViewValueOrigin$$=computed(()=>{let viewValue=this.modelValue$(),toView=this.config$?.().transfomer?.toView;return toView?toView(viewValue,this):viewValue});modelValueToViewValue$$=computed(()=>(this.viewIndex$(),this.modelValueToViewValueOrigin$$()),{equal:()=>!1});value$$=signal(void 0);reset(formState=this.config$().defaultValue){this.updateValue(formState,!0),this.markAsPristine(),this.markAsUntouched()}_forEachChild(cb){}#initInput=!0;#viewSubject$$=computed(()=>{let subject=new Subject;return this.injector.get(DestroyRef).onDestroy(()=>{subject.complete()}),subject.pipe(this.config$().pipe.toModel).subscribe(value=>{untracked(()=>{this.#viewValueChange(value)})}),subject});#viewValueChange(value){this.markAllAsDirty(),this.#viewIndex++;let toModel=this.config$?.().transfomer?.toModel,originValue=toModel?toModel(value,this):value,transfomered=this.schemaParser(originValue);transfomered.success?(this.value$$.set(transfomered.output),this.syncError$.update(data=>(data&&delete data.valibot,data&&Object.keys(data).length?data:void 0))):this.syncError$.update(data=>({...data,valibot:transfomered.issues}))}viewValueChange(value){this.config$().pipe?.toModel?this.#viewSubject$$().next(value):this.#viewValueChange(value)}updateValue(value,force){if(force&&(this.#viewIndex++,this.viewIndex$.set(this.#viewIndex),this.resetIndex$.update(a=>a+1),this.#initInput=!0),this.#initInput){this.#initInput=!1,(void 0!==value&&!deepEqual(value,this.value$$())||force)&&(this.modelValue$.set(value),this.value$$.set(value));return}deepEqual(value,this.value$$())||(this.viewIndex$.set(this.#viewIndex),this.modelValue$.set(value),this.value$$.set(value))}initConfig(config){super.initConfig(config),"defaultValue"in this.config$()&&(this.modelValue$.set(this.config$().defaultValue),this.value$$.set(this.config$().defaultValue))}emitSubmit(){let pendingStatus=this.pendingStatus();pendingStatus.touched&&this.markAsTouched(),pendingStatus.change&&this.viewValueChange(pendingStatus.value),this.pendingStatus.set(InitPendingValue)}}class FieldLogicGroup extends FieldArray{activateIndex$=signal(0);type=signal("and");activateControl$=signal(void 0);value$$=computed(()=>{let returnResult=this.getValue(!1);return this.config$().transfomer?.toModel?.(returnResult,this)??returnResult});getActivateControls(){let list;if(this.activateControl$())list=this.activateControl$();else if("and"===this.type())list=this.controls$();else if("or"===this.type())list=[this.controls$()[this.activateIndex$()]];else throw Error("");return list}getValue(rawData){let controls=rawData?this.getActivateControls():this.getActivateControls().filter(control=>control.shouldInclude$$()),control=controls[0];if(0===controls.length)return this.emptyValue$$();if(1===controls.length)return control.value;let result=controls.reduce((obj,control)=>({...obj,...control.value$$()}),{});return Object.keys(result).length?result:this.emptyValue$$()}getRawValue(){return this.getValue(!0)}updateValue(value){if(deepEqual(value,this.value$$()))return;let viewValue=this.config$().transfomer?.toView?.(value,this)??value;this.controls$().forEach((control,i)=>{control.updateValue(viewValue)})}}function isFieldGroup(input){return input instanceof FieldGroup}function isFieldArray(input){return input instanceof FieldArray}function isFieldControl(input){return input instanceof FieldControl}function isFieldLogicGroup(input){return input instanceof FieldLogicGroup}function isGroup(schema){return schema.isGroup}function isArray(schema){return schema.isArray}function unWrapSignal(value){return isSignal(value)?value():value}class ParentMap extends Map{parent;constructor(parent){super(),this.parent=parent}get(key){let result=super.get(key);return void 0===result?this.parent?.get(key):result}}function fieldQuery(key,field,aliasMap,root,aliasNotFoundFn){let list,keyPath=Array.isArray(key)?key:"number"==typeof key?[key]:key.split("."),firstPath=keyPath[0];if("#"===firstPath)field=root,list=[{field:root,level:1}];else if(".."===firstPath)list=[{field:field.parent,level:1}];else if("string"==typeof firstPath&&firstPath.startsWith("@")){let queryField=aliasMap.get(firstPath.slice(1));!queryField&&aliasNotFoundFn&&(queryField=aliasNotFoundFn(firstPath.slice(1),field)),list=[{field:queryField,level:1}]}else field.fieldGroup?list=(function* groupGenerator(list){for(let item of list)!item.keyPath?.length&&item.fieldGroup?.().length?yield*groupGenerator(item.fieldGroup()):item.keyPath?.length&&(yield item)})(field.fieldGroup()).filter(field=>field.keyPath&&arrayStartsWith(keyPath,field.keyPath)).map(field=>({field:field,level:field.keyPath?.length})):field.fieldArray&&(list=field.fieldArray().filter(field=>field.keyPath&&arrayStartsWith(keyPath,field.keyPath)).map(field=>({field:field,level:field.keyPath?.length})));if(list)for(let item of list){if(keyPath.length===item.level)return item.field;let res=item.field.get(keyPath.slice(item.level),aliasNotFoundFn);if(res)return res}}class FormBuilder{#scopeMap=inject(PI_FORM_BUILDER_ALIAS_MAP,{optional:!0})??new ParentMap;#options=inject(PI_FORM_BUILDER_OPTIONS_TOKEN);#injector=inject(Injector);#envInjector=inject(EnvironmentInjector);#globalConfig=inject(PI_VIEW_CONFIG_TOKEN,{optional:!0})??void 0;#allFieldInitHookList=[];buildRoot(item){this.#buildControl({type:"root",field:{fullPath:[]},form:void 0,resolvedField$:item.resolvedField$,append:()=>{}},item.field,0),this.allFieldInitHookCall()}allFieldInitHookCall(){let list=this.#allFieldInitHookList;this.#allFieldInitHookList=[],list.forEach(fn=>fn())}#buildField(item){"group"===item.type?this.#buildGroup(item):this.#buildArray(item)}afterResolveConfig(rawConfig,config){}#buildControl(parent,field,index){var parentForm,key,injector;let viewDefaultConfig,define,control,FieldClass,control1,type=field.type;if(type){let result=this.#resolveComponent(type);viewDefaultConfig=result.defaultConfig,define=result.define}let mergeStrategy=this.#globalConfig?.defaultConfigMergeStrategy,inputs=this.configMerge([this.#globalConfig?.defaultConfig?.inputs,viewDefaultConfig?.inputs,field.inputs],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.inputs??"merge"),outputs=this.configMerge([this.#globalConfig?.defaultConfig?.outputs,viewDefaultConfig?.outputs,field.outputs],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.outputs??"merge"),attributes=this.configMerge([this.#globalConfig?.defaultConfig?.attributes,viewDefaultConfig?.attributes,field.attributes],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.attributes??"merge"),wrappers1=this.configMergeRaw([this.#globalConfig?.defaultConfig?.wrappers,viewDefaultConfig?.wrappers,field.wrappers],!0,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.wrappers??"replace"),wrappers=this.#resolveWrappers(wrappers1),props=this.configMerge([this.#globalConfig?.defaultConfig?.props,viewDefaultConfig?.props,field.props],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.props??"merge"),formConfig$=this.configMerge([this.#globalConfig?.defaultConfig?.formConfig,viewDefaultConfig?.formConfig,field.formConfig],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.formConfig??"merge"),renderConfig=this.configMerge([this.#globalConfig?.defaultConfig?.renderConfig,viewDefaultConfig?.renderConfig,field.renderConfig],!1,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.renderConfig??"merge"),keyPath=field.key;isFieldLogicGroup(parent.form)?keyPath??=parent.form.controls$().length:isFieldArray(parent.form)&&(keyPath??=index);let isRoot="root"===parent.type;!field.nonFieldControl&&(void 0!==keyPath||isRoot)&&(parentForm=parent.form,key=keyPath,injector=this.#injector,FieldClass=field.isLogicAnd||field.isLogicOr?FieldLogicGroup:isGroup(field)?FieldGroup:isArray(field)||field.isTuple?FieldArray:FieldControl,isRoot?(isFieldLogicGroup(control1=new FieldClass(field.sourceSchema,injector))&&control1.type.set(field.isLogicAnd?"and":"or"),control1.initConfig(formConfig$)):(control1=parentForm.get([key]))||(isFieldLogicGroup(control1=new FieldClass(field.sourceSchema,injector))&&control1.type.set(field.isLogicAnd?"and":"or"),parentForm.setControl?.(key,control1),control1.initConfig(formConfig$)),control=control1);let rootForm=this.#options.form$$,resolvedConfig={id:field.id,keyPath:toArray(keyPath),get fullPath(){return[...resolvedConfig.parent.fullPath,...resolvedConfig.keyPath??[]]},form:{parent:parent.form,control:control??(isGroup(field)?parent.form:void 0),get root(){return rootForm()}},get:(keyPath,aliasNotFoundFn)=>untracked(()=>fieldQuery(keyPath,resolvedConfig,this.#scopeMap,this.#options.resolvedField$(),aliasNotFoundFn)),parent:parent.field,origin:field,renderConfig:renderConfig,formConfig:formConfig$,props,context:this.#options.context,priority:field.priority,hooks:field.hooks,alias:field.alias,inputs:inputs,outputs:outputs,attributes,define:define?{...define,inputs,outputs,attributes}:void 0,wrappers};return resolvedConfig=this.afterResolveConfig(field,resolvedConfig)??resolvedConfig,field.movePath?this.#moveViewField(field.movePath,resolvedConfig):parent.append(resolvedConfig),field.alias&&this.#scopeMap.set(field.alias,resolvedConfig),resolvedConfig.hooks?.fieldResolved?.(resolvedConfig),isRoot&&parent.resolvedField$.set(resolvedConfig),isGroup(field)||field.isLogicAnd||field.isLogicOr||field.isTuple?(resolvedConfig.fieldGroup=signal(new SortedArray((a,b)=>a.priority-b.priority)),this.#buildField({type:"group",fields:field.children,field:resolvedConfig,form:control||parent.form,append:field=>{resolvedConfig.fieldGroup().push(field)}})):isArray(field)&&this.#buildField({type:"array",templateField:field.arrayChild,field:resolvedConfig,form:control,append:field=>{}}),resolvedConfig.hooks?.allFieldsResolved&&this.#allFieldInitHookList.push(()=>{resolvedConfig.hooks.allFieldsResolved(resolvedConfig)}),resolvedConfig}#buildGroup(groupItem){for(let index=0;index<groupItem.fields.length;index++){let field=groupItem.fields[index];this.#buildControl(groupItem,field,index)}let field=groupItem.field;field.hooks?.afterChildrenInit?.(field)}createArrayItem(parent,field,index){let Builder=this.constructor,injector=Injector.create({providers:[Builder,{provide:PI_FORM_BUILDER_ALIAS_MAP,useValue:new ParentMap(this.#scopeMap)},{provide:EnvironmentInjector,useFactory:()=>injector}],parent:this.#envInjector});this.#envInjector.get(DestroyRef).onDestroy(()=>{result.injector?.destroy()});let instance=injector.get(Builder),result=instance.#buildControl(parent,field,index);return this.#allFieldInitHookList.push(()=>instance.allFieldInitHookCall()),result.injector=injector.get(EnvironmentInjector),result}#buildArray(arrayItem){let{templateField,form}=arrayItem;arrayItem.field.action={set:(value,index)=>{untracked(()=>{index="number"==typeof index?index:arrayItem.field.fieldArray?.().length??0;let result=this.createArrayItem(arrayItem,templateField,index),list=[...arrayItem.field.fieldArray()];list[index]=result,arrayItem.field.fieldArray.set(list),this.allFieldInitHookCall(),result.form.control.updateValue(value)})},remove:index=>{untracked(()=>{let list=[...arrayItem.field.fieldArray()],[deletedItem]=list.splice(index,1);arrayItem.field.fieldArray.set(list),form.removeAt(index),deletedItem&&(deletedItem.injector.destroy(),deletedItem.injector=void 0)})}},arrayItem.field.fieldArray=signal([]),arrayItem.field.hooks?.afterChildrenInit?.(arrayItem.field),form.beforeUpdateList.push(input=>{let controlLength=form.controls$().length;if(controlLength<input.length){let list=arrayItem.field.fieldArray().slice();for(let index=controlLength;index<input.length;index++){let result=this.createArrayItem(arrayItem,arrayItem.templateField,index);list[index]=result}arrayItem.field.fieldArray.set(list)}else if(input.length<controlLength){let list=arrayItem.field.fieldArray().slice();for(let index=arrayItem.field.fieldArray().length-1;index>=input.length;index--){let[deletedItem]=list.splice(index,1);form.removeAt(index),deletedItem&&(deletedItem.injector?.destroy(),deletedItem.injector=void 0)}arrayItem.field.fieldArray.set(list)}this.allFieldInitHookCall()})}#resolveComponent(type){let define,defaultConfig;if("string"!=typeof type)return{define:{type:type}};{let config=this.#globalConfig?.types?.[type];if(!config)throw Error(`define:未注册[${type}]`);if(defaultConfig=config,Object.keys(config).length)return define={...config},{define:{...config},defaultConfig}}return{define,defaultConfig}}configMergeRaw(list,isArray,strategy){return clone(isArray?"merge"===strategy?list.filter(Boolean).flat().map(item=>unWrapSignal(item)):list.reduce((data,item)=>unWrapSignal(item)??data,[]):"merge"===strategy?list.reduce((obj,item)=>({...obj,...unWrapSignal(item)}),{}):list.reduce((data,item)=>unWrapSignal(item)??data,{}))}configMerge(list,isArray,strategy){return signal(this.configMergeRaw(list,isArray,strategy))}#moveViewField(key,inputField){let parent=fieldQuery(key,inputField,this.#scopeMap,this.#options.resolvedField$(),(name,field)=>{let rootForm=this.#options.form$$,aliasField={alias:name,parent:field,get fullPath(){return field.fullPath},form:{parent:field.form.control??field.form.parent,control:void 0,get root(){return rootForm()}},get:(keyPath,fn)=>fieldQuery(keyPath,aliasField,this.#scopeMap,this.#options.resolvedField$(),fn),fieldGroup:signal(new SortedArray((a,b)=>a.priority-b.priority)),priority:0,renderConfig:signal({}),wrappers:signal([])};if(this.#scopeMap.set(name,aliasField),inputField===field)throw Error(`添加位置不可为自身`);return field.fieldGroup().push(aliasField),aliasField});if(!parent)throw Error("移动视图项失败");let index=inputField.parent.fieldGroup?.().findIndex(item=>item===inputField);"number"==typeof index&&-1!==index&&inputField.parent.fieldGroup?.().splice(index,1);let newKeyPath=inputField.fullPath.slice(parent.fullPath.length);inputField.keyPath=newKeyPath,inputField.parent=parent,parent.fieldGroup().push(inputField)}#resolveWrappers(wrappers){let result=(wrappers??[]).map(wrapper=>{if("string"==typeof wrapper){let config=this.#globalConfig?.wrappers?.[wrapper];if(!config)throw Error(`wrapper:未注册[${wrapper}]`);return{...config,inputs:signal(config.inputs),attributes:signal(config.attributes)}}if("string"!=typeof wrapper.type)return{...wrapper,inputs:signal(wrapper.inputs),attributes:signal(wrapper.attributes)};{let config=this.#globalConfig?.wrappers?.[wrapper.type];if(!config)throw Error(`wrapper:未注册[${wrapper.type}]`);return{inputs:signal({...config.inputs,...wrapper.inputs}),outputs:{...config.outputs,...wrapper.outputs},attributes:signal({...config.attributes,...wrapper.attributes}),type:config.type}}});return signal(result)}}function shortCircuitTrue(value){return value}let VALID="VALID",INVALID="INVALID",PENDING="PENDING";class AbstractControl{emptyValue$$=computed(()=>clone(this.config$().emptyValue));shouldInclude$$=computed(()=>this.valueNoError$$()&&(!this.selfDisabled$$()||this.selfDisabled$$()&&"reserve"===this.config$().disabledValue));injector;selfDisabled$$=computed(()=>this.config$?.().disabled??!1);selfEnabled$$=computed(()=>!this.selfDisabled$$());disabled$$=computed(()=>(this.parent?.disabled$$()||this.selfDisabled$$())??!1);enabled$$=computed(()=>!this.disabled$$());get disabled(){return this.disabled$$()}get enabled(){return!this.disabled$$()}enable(){this.config$.update(config=>({...config,disabled:!1}))}disable(){this.config$.update(config=>({...config,disabled:!0}))}selfTouched$=signal(!1);touched$$=computed(()=>this.reduceChildren(this.selfTouched$(),(child,value)=>value||child.touched$$(),shortCircuitTrue));get touched(){return untracked(this.touched$$)}get untouched(){return!untracked(this.touched$$)}selfDirty$=signal(!1);dirty$$=computed(()=>this.reduceChildren(this.selfDirty$(),(child,value)=>value||child.dirty$$(),shortCircuitTrue));get dirty(){return untracked(this.dirty$$)}get pristine(){return!untracked(this.dirty$$)}#validators$$=computed(()=>this.config$().validators??[]);#asyncValidators$$=computed(()=>this.config$().asyncValidators??[]);resetIndex$=signal(0);syncError$=linkedSignal(computed(()=>{if(this.disabled$$())return;this.resetIndex$(),this.value$$();let result=this.#validators$$().reduce((obj,item)=>{let result=untracked(()=>item(this));return result&&(obj={...obj,...result}),obj},{}),schemaResult=this.#schemaCheck$$();return schemaResult.success?Object.keys(result).length?result:void 0:{...result,valibot:schemaResult.issues}},{equal:()=>!1}));asyncErrorRes$$=computed(()=>{let result=this.#asyncValidators$$();if(0===result.length)return;this.resetIndex$(),this.value$$();let dataList=result.map(item=>untracked(()=>(function(input){if(isPromise(input)){let value$=signal(ValidatorPending);return input.then(value=>{value$.set({value})}),value$}if(!isObservable(input))return input;let value$=signal(ValidatorPending);return input.subscribe({next:value=>{value$.set({value})},error:error=>{value$.set({error})}}),value$})(item(this))));return computed(()=>{let params=dataList.map(item=>item()),pendingCount=0,errorResult=params.reduce((obj,item)=>item===ValidatorPending?(pendingCount++,obj):"value"in item?{...obj,...item.value}:{...obj,error:item.error},{});return Object.keys(errorResult).length?errorResult:pendingCount?ValidatorPending:void 0})});asyncError$$=computed(()=>{if(this.disabled$$())return;let ref=this.asyncErrorRes$$();if(ref){let result=ref();return result===ValidatorPending?PENDING:result}});rawError$$=computed(()=>{if(this.disabled$$())return;let syncError=this.syncError$(),asyncError=this.asyncError$$();return asyncError===PENDING?PENDING:syncError&&asyncError?{...syncError,...asyncError}:syncError||asyncError?syncError||asyncError:void 0});valueNoError$$=computed(()=>void 0===this.rawError$$());get errors(){let error=this.rawError$$();return error===PENDING?void 0:error}_parent;get parent(){return this._parent}get value(){return this.value$$()}required$$=computed(()=>this.config$().required);schemaParser;context;constructor(rawSchema,injector){this.injector=injector,this.schemaParser=v.safeParser(rawSchema),this.context=this.injector.get(PI_CONTEXT_TOKEN)}#schemaCheck$$=computed(()=>this.schemaParser(this.value$$()));setParent(parent){this._parent=parent}get valid(){return this.status$$()===VALID}get invalid(){return this.status$$()===INVALID}get pending(){return this.status$$()===PENDING}selfUpdateOn$$=computed(()=>this.config$?.().updateOn);updateOn$$=computed(()=>(this.selfUpdateOn$$()||this.parent?.updateOn$$())??"change");markAsTouched(){this.selfTouched$.set(!0)}markAllAsDirty(){this.markAsDirty(),this._forEachChild(control=>control.markAllAsDirty())}markAllAsTouched(){this.markAsTouched(),this._forEachChild(control=>control.markAllAsTouched())}markAsUntouched(){this.selfTouched$.set(!1)}markAsDirty(){this.selfDirty$.set(!0)}markAsPristine(){this.selfDirty$.set(!1)}getRawValue(){return this.value}get(path){let currPath=path;return null==currPath||(Array.isArray(currPath)||(currPath=currPath.split(".")),0===currPath.length)?null:currPath.reduce((control,name)=>control&&control.find(name),this)}get root(){let x=this;for(;x._parent;)x=x._parent;return x}config$=signal({});initConfig(config){this.config$=config}find(name){return null}setControl(name,control){}reduceChildren(initialValue,fn,shortCircuit){let childrenMap=this.children$$?.();if(!childrenMap)return initialValue;let value=initialValue;for(let child of childrenMap){if(shortCircuit?.(value))break;value=fn(child,value)}return value}#valueChange;get valueChanges(){return this.#valueChange??(this.#valueChange=toObservable(computed(()=>({value:this.value$$(),disabled:this.disabled$$()})),this.value$$,{injector:this.injector}))}status$$=computed(()=>{if(this.disabled$$())return VALID;let childStatus=this.reduceChildren(VALID,(child,value)=>value===INVALID||child.status$$()===INVALID?INVALID:value===PENDING||child.status$$()===PENDING?PENDING:VALID,v=>v===INVALID||v===PENDING);if(childStatus===VALID&&this.rawError$$())if(this.rawError$$()!==PENDING)return INVALID;else return PENDING;return childStatus});#statusChange;get statusChanges(){return this.#statusChange??(this.#statusChange=toObservable(this.status$$,this.status$$,{injector:this.injector}))}emitSubmit(){this.children$$&&this.children$$().forEach(child=>{child.emitSubmit()})}}class FieldGroup extends AbstractControl{value$$=computed(()=>{let result={...this._reduceChildren({},(acc,control,name)=>(control.shouldInclude$$()&&(acc[name]=control.value),acc)),...this.looseValue$$()},returnResult=Object.keys(result).length?result:this.emptyValue$$();return this.config$().transfomer?.toModel?.(returnResult,this)??returnResult});children$$=computed(()=>Object.values(this.controls$()));controls$=signal({});get controls(){return this.controls$()}registerControl(name,control){return this.controls$()[name]?this.controls$()[name]:(this.controls$.update(controls=>({...controls,[name]:control})),control.setParent(this),control)}removeControl(name){this.controls$()[name]&&this.controls$.update(controls=>(controls={...controls},delete controls[name],controls))}setControl(name,control){this.controls$.update(controls=>(controls={...controls},delete controls[name],controls)),control&&this.registerControl(name,control)}reset(value={}){this._forEachChild((control,name)=>{control.reset(value?value[name]:void 0)})}getRawValue(){return this._reduceChildren({},(acc,control,name)=>(acc[name]=control.getRawValue(),acc))}_forEachChild(cb){Object.keys(this.controls$()).forEach(key=>{let control=this.controls$()[key];control&&cb(control,key)})}_reduceChildren(initValue,fn){let res=initValue;return this._forEachChild((control,name)=>{res=fn(res,control,name)}),res}find(name){return this.controls$()[name]}looseValue$$=computed(()=>{let resetValue=this.#inputValue$();if(!resetValue||isFieldLogicGroup(this.parent))return{};let controls=this.controls$(),looseValue={};for(let key in resetValue)key in controls||(looseValue[key]=resetValue[key]);return looseValue});#inputValue$=signal({});#setInputValue(obj){this.#inputValue$.set(obj)}updateValue(value){if(deepEqual(value,this.value$$()))return;deepEqual(value,this.#inputValue$())||this.#setInputValue(value);let viewValue=this.config$().transfomer?.toView?.(value,this)??value;for(let key in this.controls$())this.controls$()[key].updateValue(viewValue?.[key])}}function layout(value){return{kind:"metadata",type:"layout",reference:layout,value:value}}let rawConfig=createRawConfig("viewRawConfig");function setComponent(type){return rawConfig(field=>{field.type=type})}let setHooks=hooks=>rawConfig(field=>{field.hooks=hooks}),patchHooks=hooks=>rawConfig(field=>{field.hooks={...field.hooks,...hooks}}),DefaultOptions$1={position:"bottom"};function mergeHooksFn(hooks,options,field){for(let key in field.hooks??={},hooks){let oldFn=field.hooks[key];field.hooks[key]=(...args)=>{"top"===options.position&&hooks[key](...args),oldFn?.(...args),"bottom"===options.position&&hooks[key](...args)}}}let mergeHooks=(hooks,options=DefaultOptions$1)=>rawConfig(field=>mergeHooksFn(hooks,options,field));function removeHooks(list){return rawConfig(field=>{let oldValue=field.hooks;oldValue&&(list.forEach(item=>{delete oldValue[item]}),field.hooks=oldValue)})}function setInputs(inputs){return rawConfig(field=>{field.inputs=inputs})}function patchInputs(inputs){return rawConfig(field=>{field.inputs={...field.inputs,...inputs}})}function removeInputs(list){return rawConfig(field=>{let oldValue=unWrapSignal$1(field.inputs);oldValue&&(list.forEach(item=>{delete oldValue[item]}),field.inputs=oldValue)})}function asyncInputMerge(dataObj,data$){let signalObj={};Object.keys(dataObj).forEach(key=>{let result=dataObj[key];isPromise(result)?result.then(value=>{data$.update(lastData=>((lastData={...lastData})[key]=value,lastData))}):result&&"function"==typeof result.subscribe?result.subscribe({next:value=>{data$.update(lastData=>((lastData={...lastData})[key]=value,lastData))}}):isSignal(result)?signalObj[key]=result:data$.update(lastData=>((lastData={...lastData})[key]=result,lastData))});let signalKeyList=Object.keys(signalObj);return signalKeyList.length?linkedSignal(computed(()=>({...data$(),...signalKeyList.reduce((obj,key)=>({...obj,[key]:signalObj[key]()}),{})}))):data$}function patchAsyncFn(patchKey){return(dataObj,options)=>rawConfig(rawField=>{let inputList=Object.keys(dataObj),hookName=options?.hookName??"allFieldsResolved";return rawField[patchKey]={...rawField[patchKey],...inputList.reduce((obj,item)=>(obj[item]=rawField[patchKey]?.[item]??void 0,obj),{})},mergeHooksFn({[hookName]:field=>{field[patchKey]=asyncInputMerge(Object.entries(dataObj).reduce((obj,[key,value])=>(obj[key]=value(field),obj),{}),field[patchKey])}},{position:options?.addPosition??"bottom"},rawField)})}let patchAsyncInputs=patchAsyncFn("inputs");function setAttributes(attributes){return rawConfig(field=>{field.attributes=attributes})}function patchAttributes(attributes){return rawConfig(field=>{field.attributes={...field.attributes,...attributes}})}function removeAttributes(list){return rawConfig(field=>{let oldValue=unWrapSignal$1(field.attributes);oldValue&&(list.forEach(item=>{delete oldValue[item]}),field.attributes=oldValue)})}let patchAsyncAttributes=patchAsyncFn("attributes");function setProps(props){return rawConfig(field=>{field.props=props})}function patchProps(props){return rawConfig(field=>{field.props={...field.props,...props}})}function removeProps(list){return rawConfig(field=>{let oldValue=unWrapSignal$1(field.props);oldValue&&(list.forEach(item=>{delete oldValue[item]}),field.props=oldValue)})}let patchAsyncProps=patchAsyncFn("props");function setOutputs(outputs){return rawConfig(field=>{field.outputs=outputs})}function patchOutputs(outputs){return rawConfig(field=>{let oldValue=field.outputs;field.outputs={...oldValue,...outputs}})}function removeOutputs(list){return rawConfig(field=>{let oldValue=field.outputs;oldValue&&(list.forEach(item=>{delete oldValue[item]}),field.outputs=oldValue)})}function mergeOutputFn(field,outputs,options){field.outputs.update(originOutputs=>{for(let key in originOutputs={...originOutputs},outputs){let oldFn=originOutputs[key];originOutputs[key]=(...args)=>{"top"===options.position&&outputs[key](...args,field),oldFn?.(...args,field),"bottom"===options.position&&outputs[key](...args,field)}}return originOutputs})}let DefaultOptions={position:"bottom"},mergeOutputs=(outputs,options=DefaultOptions)=>rawConfig(field=>{mergeHooksFn({allFieldsResolved:field=>{mergeOutputFn(field,outputs,options)}},{position:"bottom"},field)});function outputChangeFn(rawField,fn){mergeHooksFn({allFieldsResolved:field=>fn(list=>{let resultList=[];for(let item of list){let emitField=item.list?field.get(item.list):field,subject=new Subject;mergeOutputFn(field,{[item.output]:(...args)=>{subject.next(args)}},{position:"bottom"}),resultList.push({subject,field:emitField})}return combineLatest(resultList.map(({subject})=>subject.pipe(startWith(void 0)))).pipe(skip(1),map(list=>({list,field,listenFields:resultList.map(item=>item.field)})))})},{position:"bottom"},rawField)}function outputChange(fn){return rawConfig(field=>outputChangeFn(field,fn))}function setWrappers(wrappers){return rawConfig(field=>{field.wrappers=wrappers})}let defaultValue={position:"tail"};function patchWrappers(wrappers,options=defaultValue){return rawConfig(field=>{let list=toArray(wrappers);field.wrappers??=[],"tail"===options.position?field.wrappers.push(...list):field.wrappers.unshift(...list)})}function removeWrappers(list){return rawConfig(field=>{if(!field.wrappers)return;let wrappers=field.wrappers;for(let i=0;i<list.length;i++){let name=list[i];for(let j=0;j<wrappers.length;j++){let config=wrappers[j];if(("string"==typeof config?config:config.type)===name){wrappers.splice(j,1);break}}}field.wrappers=wrappers})}function setAlias(alias){return rawConfig(field=>{field.alias=alias})}function renderConfig(type){return rawConfig(field=>{field.renderConfig=type})}function formConfig(config){return rawConfig(field=>{field.formConfig={...field.formConfig,...config}})}let DefaultSelfList=[void 0];function valueChangeFn(field,input={}){return combineLatest((input.list??DefaultSelfList).map(keyPath=>keyPath?field.get(keyPath).form.control:field.form.control).map(control=>input.skipInitValue?control.valueChanges.pipe(skip(1)):control.valueChanges)).pipe(map(list=>({list,field,listenFields:list})))}function valueChange(listenFn){return rawConfig(field=>{mergeHooksFn({allFieldsResolved:field=>{listenFn(options=>valueChangeFn(field,options),field)}},{position:"bottom"},field)})}function hideWhen(options){return rawConfig(field=>(mergeHooksFn({allFieldsResolved:field=>{options.listen(options=>valueChangeFn(field,options),field).subscribe(hidden=>{field.renderConfig.update(value=>!!value.hidden!==hidden?{...value,hidden:hidden}:value),void 0!==options.disabled&&field.formConfig&&field.formConfig.update(value=>((value={...value}).disabled=!!hidden&&options.disabled,value))})}},{position:"bottom"},field),field))}function disableWhen(options){return rawConfig(field=>(mergeHooksFn({allFieldsResolved:field=>{options.listen(options=>valueChangeFn(field,options),field).subscribe(disabled=>{field.formConfig().disabled!==disabled&&field.formConfig.update(value=>({...value,disabled:disabled}))})}},{position:"bottom"},field),field))}function topClass(className,merge){return rawConfig(rawField=>{mergeHooksFn({fieldResolved:field=>{let wrappers=field.wrappers();wrappers?.length?wrappers[0].attributes.update(attributes=>({...attributes,class:merge?clsx(attributes?.class,className):clsx(className)})):field.attributes.update(attributes=>({...attributes,class:merge?clsx(attributes?.class,className):clsx(className)}))}},{position:"bottom"},rawField)})}function componentClass(className,merge){return rawConfig(field=>{field.attributes={...field.attributes,class:merge?clsx(field.attributes?.class,className):clsx(className)}})}function nonFieldControl(value=!0){return{kind:"metadata",type:"nonFieldControl",reference:nonFieldControl,value:value}}class CoreSchemaHandle extends BaseSchemaHandle{inputs;outputs;wrappers;attributes;alias;movePath;renderConfig;formConfig={};id;isLogicAnd=!1;isLogicOr=!1;isArray=!1;isTuple=!1;nonFieldControl=!1;hooks;lazySchema(schema){if(super.lazySchema(schema),this.parent){let wrappered=this.lazyWrapped;if(this.parent.isArray)this.parent.arrayChild=wrappered;else{let index=this.parent.children.findIndex(item=>item===this);this.parent.children[index]=wrappered}wrappered.parent=this.parent,wrappered.key=this.key}}arraySchema(schema){if(!this.isObjectControl){this.isArray=!0;let sh=new this.globalConfig.handle(this.globalConfig,this,schema);sh.parent=this,this.arrayChild=sh,convertSchema(schema.item,sh)}}defaultSchema(schema){this.defaultValue=schema.literal}tupleDefault(schema){super.tupleDefault(schema),this.isTuple=!0}enumSchema(schema){this.props??={},this.props.options??=schema.options}intersectBefore(schema){this.childrenAsVirtualGroup?"intersect"===this.type&&(this.type="intersect-group"):this.isLogicAnd=!0}logicItemSchema(schema,index,type){let sh=new this.globalConfig.handle(this.globalConfig,this,schema);this.childrenAsVirtualGroup||(sh.key=index),sh.setParent(this),convertSchema(schema,sh)}unionBefore(schema){this.childrenAsVirtualGroup||(this.isLogicOr=!0)}beforeSchemaType(schema){super.beforeSchemaType(schema),this.formConfig.required=!this.undefinedable&&!this.nullable}voidSchema(schema){this.nonFieldControl=!0}metadataDefaulthandle(metadata,environments){switch(metadata.type){case"viewRawConfig":metadata.value(this,this.globalConfig.context);break;case"layout":this.movePath=metadata.value.keyPath,this.priority=metadata.value.priority;break;case"nonFieldControl":this.nonFieldControl=metadata.value}}end(schema){super.end(schema),this.formConfig.defaultValue=this.defaultValue}}function convert(obj,options){let buildOptions={form$$:computed(()=>buildOptions.resolvedField$()?.form.control),resolvedField$:signal(void 0),context:options.context},injector=Injector.create({providers:[{provide:PI_FORM_BUILDER_OPTIONS_TOKEN,useValue:buildOptions},{provide:PI_VIEW_CONFIG_TOKEN,useValue:options.fieldGlobalConfig},{provide:PI_CONTEXT_TOKEN,useValue:options.context},options.builder,{provide:EnvironmentInjector,useFactory:()=>injector}],parent:options.injector});return options.registerOnDestroy?.(()=>{injector.get(EnvironmentInjector).destroy()}),convertCore(obj,item=>(injector.get(options.builder).buildRoot({field:item,resolvedField$:buildOptions.resolvedField$}),buildOptions.resolvedField$()),{...options,handle:options?.handle??CoreSchemaHandle})}let NFCSchema=v.optional(v.void());export{AbstractControl,CoreSchemaHandle,FieldArray,FieldControl,FieldGroup,FieldLogicGroup,FormBuilder,INVALID,NFCSchema,PENDING,PI_CONTEXT_TOKEN,PI_FORM_BUILDER_ALIAS_MAP,PI_FORM_BUILDER_OPTIONS_TOKEN,PI_VIEW_CONFIG_TOKEN,SortedArray,VALID,arrayStartsWith,asyncInputMerge,clone,componentClass,controlStatusList,convert,createViewControlLink,disableWhen,effectListen,fieldControlStatusClass,formConfig,hideWhen,isArray,isFieldArray,isFieldControl,isFieldGroup,isFieldLogicGroup,isGroup,layout,mergeHooks,mergeHooksFn,mergeOutputFn,mergeOutputs,nonFieldControl,outputChange,outputChangeFn,patchAsyncAttributes,patchAsyncFn,patchAsyncInputs,patchAsyncProps,patchAttributes,patchHooks,patchInputs,patchOutputs,patchProps,patchWrappers,rawConfig,removeAttributes,removeHooks,removeInputs,removeOutputs,removeProps,removeWrappers,renderConfig,setAlias,setAttributes,setComponent,setHooks,setInputs,setOutputs,setProps,setWrappers,toArray,toObservable,topClass,unWrapSignal$1 as unWrapSignal,valueChange,valueChangeFn};
|
|
1
|
+
import { effect, inject, Injector, untracked, DestroyRef, isSignal, signal, InjectionToken, computed, linkedSignal, EnvironmentInjector } from '@angular/core';
|
|
2
|
+
import * as v from 'valibot';
|
|
3
|
+
import { deepEqual } from 'fast-equals';
|
|
4
|
+
import { BehaviorSubject, isObservable, Subject, combineLatest, startWith, skip, map } from 'rxjs';
|
|
5
|
+
import rfdc from 'rfdc';
|
|
6
|
+
import { createRawConfig, BaseSchemaHandle, convertSchema, convertCore } from '@piying/valibot-visit';
|
|
7
|
+
export { asControl, asVirtualGroup, changeObject, condition, getDefaults, getSchemaByIssuePath, getSchemaMetadata } from '@piying/valibot-visit';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
|
|
10
|
+
function arrayStartsWith(list, parts) {
|
|
11
|
+
return (Array.isArray(parts) ? parts : [parts]).every((item, index) => item === list[index]);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** 跳过第一个值,假如发射时和初始值不同 */
|
|
15
|
+
function effectListen(listen, fn, options) {
|
|
16
|
+
let first = true;
|
|
17
|
+
const oldValue = listen();
|
|
18
|
+
return effect(() => {
|
|
19
|
+
const currentValue = listen();
|
|
20
|
+
if (first) {
|
|
21
|
+
first = false;
|
|
22
|
+
if (!deepEqual(oldValue, currentValue)) {
|
|
23
|
+
fn();
|
|
24
|
+
}
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return fn();
|
|
28
|
+
}, options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Exposes the value of an Angular `Signal` as an RxJS `Observable`.
|
|
33
|
+
*
|
|
34
|
+
* The signal's value will be propagated into the `Observable`'s subscribers using an `effect`.
|
|
35
|
+
*
|
|
36
|
+
* `toObservable` must be called in an injection context unless an injector is provided via options.
|
|
37
|
+
*
|
|
38
|
+
* @publicApi 20.0
|
|
39
|
+
*/
|
|
40
|
+
function toObservable(listen, source, options) {
|
|
41
|
+
const injector = options?.injector ?? inject(Injector);
|
|
42
|
+
const subject = new BehaviorSubject(source());
|
|
43
|
+
const watcher = effectListen(listen, () => {
|
|
44
|
+
let value;
|
|
45
|
+
try {
|
|
46
|
+
value = source();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
untracked(() => subject.error(err));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
untracked(() => subject.next(value));
|
|
53
|
+
}, { injector, manualCleanup: true });
|
|
54
|
+
injector.get(DestroyRef).onDestroy(() => {
|
|
55
|
+
watcher.destroy();
|
|
56
|
+
subject.complete();
|
|
57
|
+
});
|
|
58
|
+
return subject.asObservable();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const clone = rfdc({ proto: false, circles: false });
|
|
62
|
+
|
|
63
|
+
function unWrapSignal$1(value) {
|
|
64
|
+
return isSignal(value) ? value() : value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function toArray(input) {
|
|
68
|
+
return input === undefined
|
|
69
|
+
? input
|
|
70
|
+
: Array.isArray(input)
|
|
71
|
+
? input
|
|
72
|
+
: [input];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class SortedArray extends Array {
|
|
76
|
+
#compareFn;
|
|
77
|
+
constructor(compareFn) {
|
|
78
|
+
super();
|
|
79
|
+
this.#compareFn = compareFn;
|
|
80
|
+
}
|
|
81
|
+
push(...items) {
|
|
82
|
+
const result = super.push(...items);
|
|
83
|
+
this.sort(this.#compareFn);
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function createViewControlLink(fieldControl, cva, injector) {
|
|
89
|
+
cva.registerOnChange((value) => {
|
|
90
|
+
if (fieldControl().disabled$$()) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
fieldControl().pendingStatus.update((status) => ({
|
|
94
|
+
...status,
|
|
95
|
+
value: value,
|
|
96
|
+
change: true,
|
|
97
|
+
}));
|
|
98
|
+
if (fieldControl().updateOn$$() === 'change') {
|
|
99
|
+
fieldControl().viewValueChange(value);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
cva.registerOnTouched(() => {
|
|
103
|
+
if (fieldControl().disabled$$()) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const updateOn = fieldControl().updateOn$$();
|
|
107
|
+
const pendingStatus = fieldControl().pendingStatus();
|
|
108
|
+
if (updateOn === 'submit') {
|
|
109
|
+
fieldControl().pendingStatus.update((status) => ({
|
|
110
|
+
...status,
|
|
111
|
+
touched: true,
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
fieldControl().markAsTouched();
|
|
116
|
+
if (pendingStatus.change && updateOn === 'blur') {
|
|
117
|
+
fieldControl().viewValueChange(pendingStatus.value);
|
|
118
|
+
fieldControl().pendingStatus.update((status) => ({
|
|
119
|
+
...status,
|
|
120
|
+
change: false,
|
|
121
|
+
value: undefined,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
const disposeList = [];
|
|
127
|
+
const ref = effect(() => {
|
|
128
|
+
const value = fieldControl().modelValueToViewValue$$();
|
|
129
|
+
untracked(() => {
|
|
130
|
+
cva.writeValue(value);
|
|
131
|
+
});
|
|
132
|
+
}, { injector: injector });
|
|
133
|
+
cva.writeValue(fieldControl().modelValueToViewValue$$());
|
|
134
|
+
disposeList.push(() => ref.destroy());
|
|
135
|
+
if (cva.setDisabledState) {
|
|
136
|
+
const disabledRef = effect(() => {
|
|
137
|
+
const value = fieldControl().disabled$$();
|
|
138
|
+
untracked(() => {
|
|
139
|
+
cva.setDisabledState(value);
|
|
140
|
+
});
|
|
141
|
+
}, { injector: injector });
|
|
142
|
+
cva.setDisabledState(fieldControl().disabled$$());
|
|
143
|
+
disposeList.push(() => disabledRef.destroy());
|
|
144
|
+
}
|
|
145
|
+
return () => {
|
|
146
|
+
disposeList.forEach((fn) => fn());
|
|
147
|
+
untracked(() => {
|
|
148
|
+
fieldControl().updateValue(fieldControl().value$$(), true);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function controlStatusList(fieldControl, skipDisabled) {
|
|
154
|
+
if (!fieldControl) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const statusList = [];
|
|
158
|
+
if (!skipDisabled && fieldControl.disabled$$()) {
|
|
159
|
+
statusList.push('disabled');
|
|
160
|
+
}
|
|
161
|
+
if (fieldControl.touched$$()) {
|
|
162
|
+
statusList.push('touched');
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
statusList.push('untouched');
|
|
166
|
+
}
|
|
167
|
+
if (fieldControl.dirty$$()) {
|
|
168
|
+
statusList.push('dirty');
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
statusList.push('pristine');
|
|
172
|
+
}
|
|
173
|
+
switch (fieldControl.status$$()) {
|
|
174
|
+
case 'VALID':
|
|
175
|
+
statusList.push('valid');
|
|
176
|
+
break;
|
|
177
|
+
case 'INVALID':
|
|
178
|
+
statusList.push('invalid');
|
|
179
|
+
break;
|
|
180
|
+
case 'PENDING':
|
|
181
|
+
statusList.push('pending');
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
return statusList;
|
|
187
|
+
}
|
|
188
|
+
function fieldControlStatusClass(fieldControl, skipDisabled) {
|
|
189
|
+
return controlStatusList(fieldControl, skipDisabled)
|
|
190
|
+
.map((item) => `pi-${item}`)
|
|
191
|
+
.join(' ');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function isPromise(obj) {
|
|
195
|
+
return !!obj && typeof obj.then === 'function';
|
|
196
|
+
}
|
|
197
|
+
function isSubscribable(obj) {
|
|
198
|
+
return !!obj && typeof obj.subscribe === 'function';
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const ValidatorPending = Symbol('PENDING');
|
|
202
|
+
function promiseToSignal(input) {
|
|
203
|
+
const value$ = signal(ValidatorPending);
|
|
204
|
+
input.then((value) => {
|
|
205
|
+
value$.set({ value });
|
|
206
|
+
});
|
|
207
|
+
return value$;
|
|
208
|
+
}
|
|
209
|
+
function observableToSignal(input) {
|
|
210
|
+
const value$ = signal(ValidatorPending);
|
|
211
|
+
input.subscribe({
|
|
212
|
+
next: (value) => {
|
|
213
|
+
value$.set({ value });
|
|
214
|
+
},
|
|
215
|
+
error: (error) => {
|
|
216
|
+
value$.set({ error });
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
return value$;
|
|
220
|
+
}
|
|
221
|
+
function asyncValidatorToSignal(input) {
|
|
222
|
+
if (isPromise(input)) {
|
|
223
|
+
return promiseToSignal(input);
|
|
224
|
+
}
|
|
225
|
+
else if (isObservable(input)) {
|
|
226
|
+
return observableToSignal(input);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
return input;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** 一些默认配置 */
|
|
234
|
+
const PI_VIEW_CONFIG_TOKEN = new InjectionToken('PI_VIEW_CONFIG');
|
|
235
|
+
/**
|
|
236
|
+
* @internal
|
|
237
|
+
* 内部传参用
|
|
238
|
+
*/
|
|
239
|
+
const PI_FORM_BUILDER_OPTIONS_TOKEN = new InjectionToken('PI_FORM_BUILDER_OPTIONS');
|
|
240
|
+
/**
|
|
241
|
+
* @internal
|
|
242
|
+
* 内部传参用
|
|
243
|
+
*/
|
|
244
|
+
const PI_FORM_BUILDER_ALIAS_MAP = new InjectionToken('PI_FORM_BUILDER_ALIAS_MAP');
|
|
245
|
+
/** 上下文注入 */
|
|
246
|
+
const PI_CONTEXT_TOKEN = new InjectionToken('PI_CONTEXT');
|
|
247
|
+
|
|
248
|
+
function shortCircuitFalse(value) {
|
|
249
|
+
return !value;
|
|
250
|
+
}
|
|
251
|
+
function shortCircuitTrue(value) {
|
|
252
|
+
return value;
|
|
253
|
+
}
|
|
254
|
+
const VALID = 'VALID';
|
|
255
|
+
const INVALID = 'INVALID';
|
|
256
|
+
const PENDING = 'PENDING';
|
|
257
|
+
class AbstractControl {
|
|
258
|
+
emptyValue$$ = computed(() => clone(this.config$().emptyValue));
|
|
259
|
+
/** 父级取值时,当前子级是否包含在内 */
|
|
260
|
+
shouldInclude$$ = computed(() => this.valueNoError$$() &&
|
|
261
|
+
(!this.selfDisabled$$() ||
|
|
262
|
+
(this.selfDisabled$$() && this.config$().disabledValue === 'reserve')));
|
|
263
|
+
injector;
|
|
264
|
+
/** disabled */
|
|
265
|
+
selfDisabled$$ = computed(() => this.config$?.().disabled ?? false);
|
|
266
|
+
selfEnabled$$ = computed(() => !this.selfDisabled$$());
|
|
267
|
+
/** `self` || `parent` */
|
|
268
|
+
disabled$$ = computed(() => (this.parent?.disabled$$() || this.selfDisabled$$()) ?? false);
|
|
269
|
+
enabled$$ = computed(() => !this.disabled$$());
|
|
270
|
+
get disabled() {
|
|
271
|
+
return this.disabled$$();
|
|
272
|
+
}
|
|
273
|
+
get enabled() {
|
|
274
|
+
return !this.disabled$$();
|
|
275
|
+
}
|
|
276
|
+
enable() {
|
|
277
|
+
this.config$.update((config) => ({ ...config, disabled: false }));
|
|
278
|
+
}
|
|
279
|
+
disable() {
|
|
280
|
+
this.config$.update((config) => ({ ...config, disabled: true }));
|
|
281
|
+
}
|
|
282
|
+
/** touched */
|
|
283
|
+
selfTouched$ = signal(false);
|
|
284
|
+
touched$$ = computed(() => this.reduceChildren(this.selfTouched$(), (child, value) => value || child.touched$$(), shortCircuitTrue));
|
|
285
|
+
get touched() {
|
|
286
|
+
return untracked(this.touched$$);
|
|
287
|
+
}
|
|
288
|
+
get untouched() {
|
|
289
|
+
return !untracked(this.touched$$);
|
|
290
|
+
}
|
|
291
|
+
/** dirty */
|
|
292
|
+
selfDirty$ = signal(false);
|
|
293
|
+
dirty$$ = computed(() => this.reduceChildren(this.selfDirty$(), (child, value) => value || child.dirty$$(), shortCircuitTrue));
|
|
294
|
+
get dirty() {
|
|
295
|
+
return untracked(this.dirty$$);
|
|
296
|
+
}
|
|
297
|
+
get pristine() {
|
|
298
|
+
return !untracked(this.dirty$$);
|
|
299
|
+
}
|
|
300
|
+
/** validator */
|
|
301
|
+
#validators$$ = computed(() => this.config$().validators ?? []);
|
|
302
|
+
#asyncValidators$$ = computed(() => this.config$().asyncValidators ?? []);
|
|
303
|
+
resetIndex$ = signal(0);
|
|
304
|
+
syncError$ = linkedSignal(computed(() => {
|
|
305
|
+
const disabled = this.disabled$$();
|
|
306
|
+
if (disabled) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
this.resetIndex$();
|
|
310
|
+
this.value$$();
|
|
311
|
+
const result = this.#validators$$().reduce((obj, item) => {
|
|
312
|
+
const result = untracked(() => item(this));
|
|
313
|
+
if (result) {
|
|
314
|
+
obj = { ...obj, ...result };
|
|
315
|
+
}
|
|
316
|
+
return obj;
|
|
317
|
+
}, {});
|
|
318
|
+
const schemaResult = this.#schemaCheck$$();
|
|
319
|
+
if (!schemaResult.success) {
|
|
320
|
+
return { ...result, valibot: schemaResult.issues };
|
|
321
|
+
}
|
|
322
|
+
return Object.keys(result).length
|
|
323
|
+
? result
|
|
324
|
+
: undefined;
|
|
325
|
+
}, { equal: () => false }));
|
|
326
|
+
asyncErrorRes$$ = computed(() => {
|
|
327
|
+
const result = this.#asyncValidators$$();
|
|
328
|
+
if (result.length === 0) {
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
this.resetIndex$();
|
|
332
|
+
this.value$$();
|
|
333
|
+
const dataList = result.map((item) => untracked(() => asyncValidatorToSignal(item(this))));
|
|
334
|
+
return computed(() => {
|
|
335
|
+
const params = dataList.map((item) => item());
|
|
336
|
+
let pendingCount = 0;
|
|
337
|
+
const errorResult = params.reduce((obj, item) => {
|
|
338
|
+
if (item === ValidatorPending) {
|
|
339
|
+
pendingCount++;
|
|
340
|
+
return obj;
|
|
341
|
+
}
|
|
342
|
+
else if ('value' in item) {
|
|
343
|
+
return { ...obj, ...item.value };
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
return { ...obj, error: item.error };
|
|
347
|
+
}
|
|
348
|
+
}, {});
|
|
349
|
+
if (!Object.keys(errorResult).length) {
|
|
350
|
+
if (pendingCount) {
|
|
351
|
+
return ValidatorPending;
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
return errorResult;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
asyncError$$ = computed(() => {
|
|
361
|
+
const disabled = this.disabled$$();
|
|
362
|
+
if (disabled) {
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
const ref = this.asyncErrorRes$$();
|
|
366
|
+
if (ref) {
|
|
367
|
+
const result = ref();
|
|
368
|
+
if (result === ValidatorPending) {
|
|
369
|
+
return PENDING;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return undefined;
|
|
376
|
+
});
|
|
377
|
+
rawError$$ = computed(() => {
|
|
378
|
+
const disabled = this.disabled$$();
|
|
379
|
+
if (disabled) {
|
|
380
|
+
return undefined;
|
|
381
|
+
}
|
|
382
|
+
const syncError = this.syncError$();
|
|
383
|
+
const asyncError = this.asyncError$$();
|
|
384
|
+
if (asyncError === PENDING) {
|
|
385
|
+
return PENDING;
|
|
386
|
+
}
|
|
387
|
+
if (syncError && asyncError) {
|
|
388
|
+
return { ...syncError, ...asyncError };
|
|
389
|
+
}
|
|
390
|
+
else if (syncError || asyncError) {
|
|
391
|
+
return syncError || asyncError;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
valueNoError$$ = computed(() => this.rawError$$() === undefined);
|
|
398
|
+
get errors() {
|
|
399
|
+
const error = this.rawError$$();
|
|
400
|
+
return error === PENDING ? undefined : error;
|
|
401
|
+
}
|
|
402
|
+
/** parent */
|
|
403
|
+
_parent;
|
|
404
|
+
get parent() {
|
|
405
|
+
return this._parent;
|
|
406
|
+
}
|
|
407
|
+
get value() {
|
|
408
|
+
return this.value$$();
|
|
409
|
+
}
|
|
410
|
+
required$$ = computed(() => this.config$().required);
|
|
411
|
+
schemaParser;
|
|
412
|
+
context;
|
|
413
|
+
constructor(rawSchema, injector) {
|
|
414
|
+
this.injector = injector;
|
|
415
|
+
this.schemaParser = v.safeParser(rawSchema);
|
|
416
|
+
this.context = this.injector.get(PI_CONTEXT_TOKEN);
|
|
417
|
+
}
|
|
418
|
+
#schemaCheck$$ = computed(() => this.schemaParser(this.value$$()));
|
|
419
|
+
setParent(parent) {
|
|
420
|
+
this._parent = parent;
|
|
421
|
+
}
|
|
422
|
+
get valid() {
|
|
423
|
+
return this.status$$() === VALID;
|
|
424
|
+
}
|
|
425
|
+
get invalid() {
|
|
426
|
+
return this.status$$() === INVALID;
|
|
427
|
+
}
|
|
428
|
+
get pending() {
|
|
429
|
+
return this.status$$() === PENDING;
|
|
430
|
+
}
|
|
431
|
+
selfUpdateOn$$ = computed(() => this.config$?.().updateOn);
|
|
432
|
+
updateOn$$ = computed(() => (this.selfUpdateOn$$() || this.parent?.updateOn$$()) ?? 'change');
|
|
433
|
+
markAsTouched() {
|
|
434
|
+
this.selfTouched$.set(true);
|
|
435
|
+
}
|
|
436
|
+
markAllAsDirty() {
|
|
437
|
+
this.markAsDirty();
|
|
438
|
+
this._forEachChild((control) => control.markAllAsDirty());
|
|
439
|
+
}
|
|
440
|
+
markAllAsTouched() {
|
|
441
|
+
this.markAsTouched();
|
|
442
|
+
this._forEachChild((control) => control.markAllAsTouched());
|
|
443
|
+
}
|
|
444
|
+
markAsUntouched() {
|
|
445
|
+
this.selfTouched$.set(false);
|
|
446
|
+
}
|
|
447
|
+
markAsDirty() {
|
|
448
|
+
this.selfDirty$.set(true);
|
|
449
|
+
}
|
|
450
|
+
markAsPristine() {
|
|
451
|
+
this.selfDirty$.set(false);
|
|
452
|
+
}
|
|
453
|
+
getRawValue() {
|
|
454
|
+
return this.value;
|
|
455
|
+
}
|
|
456
|
+
get(path) {
|
|
457
|
+
let currPath = path;
|
|
458
|
+
if (currPath == null)
|
|
459
|
+
return null;
|
|
460
|
+
if (!Array.isArray(currPath))
|
|
461
|
+
currPath = currPath.split('.');
|
|
462
|
+
if (currPath.length === 0)
|
|
463
|
+
return null;
|
|
464
|
+
return currPath.reduce((control, name) => control && control.find(name), this);
|
|
465
|
+
}
|
|
466
|
+
get root() {
|
|
467
|
+
let x = this;
|
|
468
|
+
while (x._parent) {
|
|
469
|
+
x = x._parent;
|
|
470
|
+
}
|
|
471
|
+
return x;
|
|
472
|
+
}
|
|
473
|
+
config$ = signal({});
|
|
474
|
+
initConfig(config) {
|
|
475
|
+
this.config$ = config;
|
|
476
|
+
}
|
|
477
|
+
find(name) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
setControl(name, control) { }
|
|
481
|
+
reduceChildren(initialValue, fn, shortCircuit) {
|
|
482
|
+
const childrenMap = this.children$$?.();
|
|
483
|
+
if (!childrenMap) {
|
|
484
|
+
return initialValue;
|
|
485
|
+
}
|
|
486
|
+
let value = initialValue;
|
|
487
|
+
for (const child of childrenMap) {
|
|
488
|
+
if (shortCircuit?.(value)) {
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
value = fn(child, value);
|
|
492
|
+
}
|
|
493
|
+
return value;
|
|
494
|
+
}
|
|
495
|
+
#valueChange;
|
|
496
|
+
get valueChanges() {
|
|
497
|
+
return (this.#valueChange ??
|
|
498
|
+
(this.#valueChange = toObservable(computed(() => ({
|
|
499
|
+
value: this.value$$(),
|
|
500
|
+
disabled: this.disabled$$(),
|
|
501
|
+
})), this.value$$, {
|
|
502
|
+
injector: this.injector,
|
|
503
|
+
})));
|
|
504
|
+
}
|
|
505
|
+
status$$ = computed(() => {
|
|
506
|
+
if (this.disabled$$()) {
|
|
507
|
+
return VALID;
|
|
508
|
+
}
|
|
509
|
+
const childStatus = this.reduceChildren(VALID, (child, value) => {
|
|
510
|
+
if (value === INVALID || child.status$$() === INVALID) {
|
|
511
|
+
return INVALID;
|
|
512
|
+
}
|
|
513
|
+
else if (value === PENDING || child.status$$() === PENDING) {
|
|
514
|
+
return PENDING;
|
|
515
|
+
}
|
|
516
|
+
return VALID;
|
|
517
|
+
}, (v) => v === INVALID || v === PENDING);
|
|
518
|
+
if (childStatus === VALID) {
|
|
519
|
+
if (this.rawError$$()) {
|
|
520
|
+
if (this.rawError$$() !== PENDING) {
|
|
521
|
+
return INVALID;
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
return PENDING;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return childStatus;
|
|
529
|
+
});
|
|
530
|
+
#statusChange;
|
|
531
|
+
get statusChanges() {
|
|
532
|
+
return (this.#statusChange ??
|
|
533
|
+
(this.#statusChange = toObservable(this.status$$, this.status$$, {
|
|
534
|
+
injector: this.injector,
|
|
535
|
+
})));
|
|
536
|
+
}
|
|
537
|
+
/** 仅触发 updateOn: submit 时使用 */
|
|
538
|
+
emitSubmit() {
|
|
539
|
+
if (this.children$$) {
|
|
540
|
+
this.children$$().forEach((child) => {
|
|
541
|
+
child.emitSubmit();
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
class FieldArray extends AbstractControl {
|
|
548
|
+
#deletionMode$$ = computed(() => this.config$().deletionMode ?? 'shrink');
|
|
549
|
+
value$$ = computed(() => {
|
|
550
|
+
const list = [];
|
|
551
|
+
for (const control of this.controls$()) {
|
|
552
|
+
if (control && control.shouldInclude$$()) {
|
|
553
|
+
list.push(control.value$$());
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
if (this.#deletionMode$$() === 'shrink') {
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
else if (this.#deletionMode$$() === 'mark') {
|
|
560
|
+
list.push(undefined);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
const returnResult = list.length === 0 ? this.emptyValue$$() : list;
|
|
565
|
+
return (this.config$().transfomer?.toModel?.(returnResult, this) ?? returnResult);
|
|
566
|
+
});
|
|
567
|
+
children$$ = computed(() => this.controls$());
|
|
568
|
+
controls$ = signal([]);
|
|
569
|
+
get controls() {
|
|
570
|
+
return this.controls$();
|
|
571
|
+
}
|
|
572
|
+
removeAt(index) {
|
|
573
|
+
const adjustedIndex = this._adjustIndex(index);
|
|
574
|
+
if (this.controls$()[adjustedIndex]) {
|
|
575
|
+
this.controls$.update((list) => {
|
|
576
|
+
list = list.slice();
|
|
577
|
+
list.splice(adjustedIndex, 1);
|
|
578
|
+
return list;
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
setControl(index, control) {
|
|
583
|
+
const adjustedIndex = this._adjustIndex(index);
|
|
584
|
+
this.controls$.update((list) => {
|
|
585
|
+
list = list.slice();
|
|
586
|
+
list[adjustedIndex] = control;
|
|
587
|
+
return list;
|
|
588
|
+
});
|
|
589
|
+
control.setParent(this);
|
|
590
|
+
}
|
|
591
|
+
get length() {
|
|
592
|
+
return this.controls$().length;
|
|
593
|
+
}
|
|
594
|
+
reset(value = []) {
|
|
595
|
+
this._forEachChild((control, index) => {
|
|
596
|
+
control.reset(value[index]);
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
getRawValue() {
|
|
600
|
+
return this.controls$().map((control) => control.getRawValue());
|
|
601
|
+
}
|
|
602
|
+
clear() {
|
|
603
|
+
if (this.controls$().length < 1)
|
|
604
|
+
return;
|
|
605
|
+
this.controls$.update(() => []);
|
|
606
|
+
}
|
|
607
|
+
_adjustIndex(index) {
|
|
608
|
+
return index < 0 ? Math.max(index + this.length, 0) : index;
|
|
609
|
+
}
|
|
610
|
+
/** @internal */
|
|
611
|
+
_forEachChild(cb) {
|
|
612
|
+
this.controls$().forEach((control, index) => {
|
|
613
|
+
if (control) {
|
|
614
|
+
cb(control, index);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
find(name) {
|
|
619
|
+
return this.controls$()[this._adjustIndex(name)];
|
|
620
|
+
}
|
|
621
|
+
beforeUpdateList = [];
|
|
622
|
+
updateValue(value = []) {
|
|
623
|
+
if (deepEqual(value, this.value$$())) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
const viewValue = this.config$().transfomer?.toView?.(value, this) ?? value;
|
|
627
|
+
this.beforeUpdateList.forEach((item) => item(viewValue));
|
|
628
|
+
this.controls$().forEach((control, i) => {
|
|
629
|
+
control.updateValue(viewValue[i]);
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const InitPendingValue = {
|
|
635
|
+
touched: false,
|
|
636
|
+
change: false,
|
|
637
|
+
value: undefined,
|
|
638
|
+
};
|
|
639
|
+
class FieldControl extends AbstractControl {
|
|
640
|
+
pendingStatus = signal(InitPendingValue);
|
|
641
|
+
children$$;
|
|
642
|
+
#viewIndex = 0;
|
|
643
|
+
/** 视图变化时model值不变也要更新view */
|
|
644
|
+
viewIndex$ = signal(0);
|
|
645
|
+
/** model输入值 */
|
|
646
|
+
modelValue$ = signal(undefined);
|
|
647
|
+
modelValueToViewValueOrigin$$ = computed(() => {
|
|
648
|
+
const viewValue = this.modelValue$();
|
|
649
|
+
const toView = this.config$?.().transfomer?.toView;
|
|
650
|
+
if (toView) {
|
|
651
|
+
return toView(viewValue, this);
|
|
652
|
+
}
|
|
653
|
+
return viewValue;
|
|
654
|
+
});
|
|
655
|
+
/** 传入到view中的值 */
|
|
656
|
+
modelValueToViewValue$$ = computed(() => {
|
|
657
|
+
this.viewIndex$();
|
|
658
|
+
return this.modelValueToViewValueOrigin$$();
|
|
659
|
+
}, { equal: () => false });
|
|
660
|
+
/** modelValue + viewValue => modelValue */
|
|
661
|
+
value$$ = signal(undefined);
|
|
662
|
+
reset(formState = this.config$().defaultValue) {
|
|
663
|
+
this.updateValue(formState, true);
|
|
664
|
+
this.markAsPristine();
|
|
665
|
+
this.markAsUntouched();
|
|
666
|
+
}
|
|
667
|
+
/** @internal */
|
|
668
|
+
_forEachChild(cb) { }
|
|
669
|
+
#initInput = true;
|
|
670
|
+
#viewSubject$$ = computed(() => {
|
|
671
|
+
const subject = new Subject();
|
|
672
|
+
this.injector.get(DestroyRef).onDestroy(() => {
|
|
673
|
+
subject.complete();
|
|
674
|
+
});
|
|
675
|
+
subject.pipe(this.config$().pipe.toModel).subscribe((value) => {
|
|
676
|
+
untracked(() => {
|
|
677
|
+
this.#viewValueChange(value);
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
return subject;
|
|
681
|
+
});
|
|
682
|
+
#viewValueChange(value) {
|
|
683
|
+
this.markAllAsDirty();
|
|
684
|
+
this.#viewIndex++;
|
|
685
|
+
const toModel = this.config$?.().transfomer?.toModel;
|
|
686
|
+
const originValue = toModel ? toModel(value, this) : value;
|
|
687
|
+
const transfomered = this.schemaParser(originValue);
|
|
688
|
+
if (transfomered.success) {
|
|
689
|
+
this.value$$.set(transfomered.output);
|
|
690
|
+
this.syncError$.update((data) => {
|
|
691
|
+
if (data) {
|
|
692
|
+
delete data['valibot'];
|
|
693
|
+
}
|
|
694
|
+
return data && Object.keys(data).length ? data : undefined;
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
this.syncError$.update((data) => ({
|
|
699
|
+
...data,
|
|
700
|
+
valibot: transfomered.issues,
|
|
701
|
+
}));
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/** view变更 */
|
|
705
|
+
viewValueChange(value) {
|
|
706
|
+
if (this.config$().pipe?.toModel) {
|
|
707
|
+
this.#viewSubject$$().next(value);
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
this.#viewValueChange(value);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
updateValue(value, force) {
|
|
714
|
+
if (force) {
|
|
715
|
+
this.#viewIndex++;
|
|
716
|
+
this.viewIndex$.set(this.#viewIndex);
|
|
717
|
+
this.resetIndex$.update((a) => a + 1);
|
|
718
|
+
this.#initInput = true;
|
|
719
|
+
}
|
|
720
|
+
if (this.#initInput) {
|
|
721
|
+
this.#initInput = false;
|
|
722
|
+
if ((value !== undefined && !deepEqual(value, this.value$$())) || force) {
|
|
723
|
+
this.modelValue$.set(value);
|
|
724
|
+
this.value$$.set(value);
|
|
725
|
+
}
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
if (deepEqual(value, this.value$$())) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
this.viewIndex$.set(this.#viewIndex);
|
|
732
|
+
this.modelValue$.set(value);
|
|
733
|
+
this.value$$.set(value);
|
|
734
|
+
}
|
|
735
|
+
initConfig(config) {
|
|
736
|
+
super.initConfig(config);
|
|
737
|
+
if ('defaultValue' in this.config$()) {
|
|
738
|
+
this.modelValue$.set(this.config$().defaultValue);
|
|
739
|
+
this.value$$.set(this.config$().defaultValue);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
emitSubmit() {
|
|
743
|
+
const pendingStatus = this.pendingStatus();
|
|
744
|
+
if (pendingStatus.touched) {
|
|
745
|
+
this.markAsTouched();
|
|
746
|
+
}
|
|
747
|
+
if (pendingStatus.change) {
|
|
748
|
+
this.viewValueChange(pendingStatus.value);
|
|
749
|
+
}
|
|
750
|
+
this.pendingStatus.set(InitPendingValue);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// 切换索引后,理论上应该触发下值变更,否则不知道值是什么
|
|
755
|
+
class FieldLogicGroup extends FieldArray {
|
|
756
|
+
/** 待定参数 */
|
|
757
|
+
activateIndex$ = signal(0);
|
|
758
|
+
type = signal('and');
|
|
759
|
+
activateControl$ = signal(undefined);
|
|
760
|
+
value$$ = computed(() => {
|
|
761
|
+
const returnResult = this.getValue(false);
|
|
762
|
+
return (this.config$().transfomer?.toModel?.(returnResult, this) ?? returnResult);
|
|
763
|
+
});
|
|
764
|
+
getActivateControls() {
|
|
765
|
+
let list;
|
|
766
|
+
if (this.activateControl$()) {
|
|
767
|
+
list = this.activateControl$();
|
|
768
|
+
}
|
|
769
|
+
else if (this.type() === 'and') {
|
|
770
|
+
list = this.controls$();
|
|
771
|
+
}
|
|
772
|
+
else if (this.type() === 'or') {
|
|
773
|
+
list = [this.controls$()[this.activateIndex$()]];
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
throw new Error('');
|
|
777
|
+
}
|
|
778
|
+
return list;
|
|
779
|
+
}
|
|
780
|
+
getValue(rawData) {
|
|
781
|
+
const controls = rawData
|
|
782
|
+
? this.getActivateControls()
|
|
783
|
+
: this.getActivateControls().filter((control) => control.shouldInclude$$());
|
|
784
|
+
const control = controls[0];
|
|
785
|
+
if (controls.length === 0) {
|
|
786
|
+
return this.emptyValue$$();
|
|
787
|
+
}
|
|
788
|
+
if (controls.length === 1) {
|
|
789
|
+
return control.value;
|
|
790
|
+
}
|
|
791
|
+
const result = controls.reduce((obj, control) => ({ ...obj, ...control.value$$() }), {});
|
|
792
|
+
return Object.keys(result).length ? result : this.emptyValue$$();
|
|
793
|
+
}
|
|
794
|
+
getRawValue() {
|
|
795
|
+
return this.getValue(true);
|
|
796
|
+
}
|
|
797
|
+
updateValue(value) {
|
|
798
|
+
if (deepEqual(value, this.value$$())) {
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
const viewValue = this.config$().transfomer?.toView?.(value, this) ?? value;
|
|
802
|
+
this.controls$().forEach((control, i) => {
|
|
803
|
+
control.updateValue(viewValue);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function isFieldGroup(input) {
|
|
809
|
+
return input instanceof FieldGroup;
|
|
810
|
+
}
|
|
811
|
+
function isFieldArray(input) {
|
|
812
|
+
return input instanceof FieldArray;
|
|
813
|
+
}
|
|
814
|
+
function isFieldControl(input) {
|
|
815
|
+
return input instanceof FieldControl;
|
|
816
|
+
}
|
|
817
|
+
function isFieldLogicGroup(input) {
|
|
818
|
+
return input instanceof FieldLogicGroup;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
class FieldGroup extends AbstractControl {
|
|
822
|
+
value$$ = computed(() => {
|
|
823
|
+
const acc = {};
|
|
824
|
+
const value = this._reduceChildren(acc, (acc, control, name) => {
|
|
825
|
+
if (control.shouldInclude$$()) {
|
|
826
|
+
acc[name] = control.value;
|
|
827
|
+
}
|
|
828
|
+
return acc;
|
|
829
|
+
});
|
|
830
|
+
const result = { ...value, ...this.looseValue$$() };
|
|
831
|
+
const returnResult = Object.keys(result).length
|
|
832
|
+
? result
|
|
833
|
+
: this.emptyValue$$();
|
|
834
|
+
return (this.config$().transfomer?.toModel?.(returnResult, this) ?? returnResult);
|
|
835
|
+
});
|
|
836
|
+
children$$ = computed(() => Object.values(this.controls$()));
|
|
837
|
+
controls$ = signal({});
|
|
838
|
+
get controls() {
|
|
839
|
+
return this.controls$();
|
|
840
|
+
}
|
|
841
|
+
registerControl(name, control) {
|
|
842
|
+
if (this.controls$()[name])
|
|
843
|
+
return this.controls$()[name];
|
|
844
|
+
this.controls$.update((controls) => ({ ...controls, [name]: control }));
|
|
845
|
+
control.setParent(this);
|
|
846
|
+
return control;
|
|
847
|
+
}
|
|
848
|
+
removeControl(name) {
|
|
849
|
+
if (this.controls$()[name]) {
|
|
850
|
+
this.controls$.update((controls) => {
|
|
851
|
+
controls = { ...controls };
|
|
852
|
+
delete controls[name];
|
|
853
|
+
return controls;
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
setControl(name, control) {
|
|
858
|
+
this.controls$.update((controls) => {
|
|
859
|
+
controls = { ...controls };
|
|
860
|
+
delete controls[name];
|
|
861
|
+
return controls;
|
|
862
|
+
});
|
|
863
|
+
if (control)
|
|
864
|
+
this.registerControl(name, control);
|
|
865
|
+
}
|
|
866
|
+
reset(value = {}) {
|
|
867
|
+
this._forEachChild((control, name) => {
|
|
868
|
+
control.reset(value ? value[name] : undefined);
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
getRawValue() {
|
|
872
|
+
return this._reduceChildren({}, (acc, control, name) => {
|
|
873
|
+
acc[name] = control.getRawValue();
|
|
874
|
+
return acc;
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
/** @internal */
|
|
878
|
+
_forEachChild(cb) {
|
|
879
|
+
Object.keys(this.controls$()).forEach((key) => {
|
|
880
|
+
const control = this.controls$()[key];
|
|
881
|
+
control && cb(control, key);
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
/** @internal */
|
|
885
|
+
_reduceChildren(initValue, fn) {
|
|
886
|
+
let res = initValue;
|
|
887
|
+
this._forEachChild((control, name) => {
|
|
888
|
+
res = fn(res, control, name);
|
|
889
|
+
});
|
|
890
|
+
return res;
|
|
891
|
+
}
|
|
892
|
+
find(name) {
|
|
893
|
+
return this.controls$()[name];
|
|
894
|
+
}
|
|
895
|
+
looseValue$$ = computed(() => {
|
|
896
|
+
const resetValue = this.#inputValue$();
|
|
897
|
+
if (!resetValue || isFieldLogicGroup(this.parent)) {
|
|
898
|
+
return {};
|
|
899
|
+
}
|
|
900
|
+
const controls = this.controls$();
|
|
901
|
+
const looseValue = {};
|
|
902
|
+
for (const key in resetValue) {
|
|
903
|
+
if (!(key in controls)) {
|
|
904
|
+
looseValue[key] = resetValue[key];
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return looseValue;
|
|
908
|
+
});
|
|
909
|
+
/**
|
|
910
|
+
* loose object
|
|
911
|
+
* todo 动态添加
|
|
912
|
+
* */
|
|
913
|
+
#inputValue$ = signal({});
|
|
914
|
+
#setInputValue(obj) {
|
|
915
|
+
this.#inputValue$.set(obj);
|
|
916
|
+
}
|
|
917
|
+
updateValue(value) {
|
|
918
|
+
if (deepEqual(value, this.value$$())) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
if (!deepEqual(value, this.#inputValue$())) {
|
|
922
|
+
this.#setInputValue(value);
|
|
923
|
+
}
|
|
924
|
+
const viewValue = this.config$().transfomer?.toView?.(value, this) ?? value;
|
|
925
|
+
for (const key in this.controls$()) {
|
|
926
|
+
const control = this.controls$()[key];
|
|
927
|
+
control.updateValue(viewValue?.[key]);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function isGroup(schema) {
|
|
933
|
+
return schema.isGroup;
|
|
934
|
+
}
|
|
935
|
+
function isArray(schema) {
|
|
936
|
+
return schema.isArray;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function createField(parentForm, field,
|
|
940
|
+
/** 创建用 */
|
|
941
|
+
key, formConfig$$, isRoot, injector) {
|
|
942
|
+
let FieldClass;
|
|
943
|
+
if (field.isLogicAnd || field.isLogicOr) {
|
|
944
|
+
FieldClass = FieldLogicGroup;
|
|
945
|
+
}
|
|
946
|
+
else if (isGroup(field)) {
|
|
947
|
+
FieldClass = FieldGroup;
|
|
948
|
+
}
|
|
949
|
+
else if (isArray(field) || field.isTuple) {
|
|
950
|
+
FieldClass = FieldArray;
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
FieldClass = FieldControl;
|
|
954
|
+
}
|
|
955
|
+
let control;
|
|
956
|
+
if (isRoot) {
|
|
957
|
+
control = new FieldClass(field.sourceSchema, injector);
|
|
958
|
+
if (isFieldLogicGroup(control)) {
|
|
959
|
+
control.type.set(field.isLogicAnd ? 'and' : 'or');
|
|
960
|
+
}
|
|
961
|
+
control.initConfig(formConfig$$);
|
|
962
|
+
}
|
|
963
|
+
else {
|
|
964
|
+
control = parentForm.get([key]);
|
|
965
|
+
if (!control) {
|
|
966
|
+
control = new FieldClass(field.sourceSchema, injector);
|
|
967
|
+
if (isFieldLogicGroup(control)) {
|
|
968
|
+
control.type.set(field.isLogicAnd ? 'and' : 'or');
|
|
969
|
+
}
|
|
970
|
+
parentForm.setControl?.(key, control);
|
|
971
|
+
control.initConfig(formConfig$$);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return control;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
function unWrapSignal(value) {
|
|
978
|
+
return isSignal(value) ? value() : value;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const DCONFIG_EFAULT_MERGE_STRAGEGY = {
|
|
982
|
+
props: 'merge',
|
|
983
|
+
formConfig: 'merge',
|
|
984
|
+
renderConfig: 'merge',
|
|
985
|
+
inputs: 'merge',
|
|
986
|
+
outputs: 'merge',
|
|
987
|
+
wrappers: 'replace',
|
|
988
|
+
attributes: 'merge',
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
class ParentMap extends Map {
|
|
992
|
+
parent;
|
|
993
|
+
constructor(parent) {
|
|
994
|
+
super();
|
|
995
|
+
this.parent = parent;
|
|
996
|
+
}
|
|
997
|
+
get(key) {
|
|
998
|
+
const result = super.get(key);
|
|
999
|
+
if (result === undefined) {
|
|
1000
|
+
return this.parent?.get(key);
|
|
1001
|
+
}
|
|
1002
|
+
return result;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
function* groupGenerator(list) {
|
|
1007
|
+
for (const item of list) {
|
|
1008
|
+
if (!item.keyPath?.length && item.fieldGroup?.().length) {
|
|
1009
|
+
yield* groupGenerator(item.fieldGroup());
|
|
1010
|
+
}
|
|
1011
|
+
else if (item.keyPath?.length) {
|
|
1012
|
+
yield item;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
function fieldQuery(key, field, aliasMap, root, aliasNotFoundFn) {
|
|
1018
|
+
const keyPath = Array.isArray(key)
|
|
1019
|
+
? key
|
|
1020
|
+
: typeof key === 'number'
|
|
1021
|
+
? [key]
|
|
1022
|
+
: key.split('.');
|
|
1023
|
+
const firstPath = keyPath[0];
|
|
1024
|
+
let list;
|
|
1025
|
+
if (firstPath === '#') {
|
|
1026
|
+
field = root;
|
|
1027
|
+
list = [{ field: root, level: 1 }];
|
|
1028
|
+
}
|
|
1029
|
+
else if (firstPath === '..') {
|
|
1030
|
+
list = [{ field: field.parent, level: 1 }];
|
|
1031
|
+
}
|
|
1032
|
+
else if (typeof firstPath === 'string' && firstPath.startsWith('@')) {
|
|
1033
|
+
let queryField = aliasMap.get(firstPath.slice(1));
|
|
1034
|
+
if (!queryField && aliasNotFoundFn) {
|
|
1035
|
+
queryField = aliasNotFoundFn(firstPath.slice(1), field);
|
|
1036
|
+
}
|
|
1037
|
+
list = [{ field: queryField, level: 1 }];
|
|
1038
|
+
}
|
|
1039
|
+
else if (field.fieldGroup) {
|
|
1040
|
+
list = groupGenerator(field.fieldGroup())
|
|
1041
|
+
.filter((field) => field.keyPath && arrayStartsWith(keyPath, field.keyPath))
|
|
1042
|
+
.map((field) => ({ field: field, level: field.keyPath?.length }));
|
|
1043
|
+
}
|
|
1044
|
+
else if (field.fieldArray) {
|
|
1045
|
+
list = field
|
|
1046
|
+
.fieldArray()
|
|
1047
|
+
.filter((field) => field.keyPath && arrayStartsWith(keyPath, field.keyPath))
|
|
1048
|
+
.map((field) => ({ field: field, level: field.keyPath?.length }));
|
|
1049
|
+
}
|
|
1050
|
+
if (!list) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
for (const item of list) {
|
|
1054
|
+
if (keyPath.length === item.level) {
|
|
1055
|
+
return item.field;
|
|
1056
|
+
}
|
|
1057
|
+
const res = item.field.get(keyPath.slice(item.level), aliasNotFoundFn);
|
|
1058
|
+
if (res) {
|
|
1059
|
+
return res;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return undefined;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
class FormBuilder {
|
|
1066
|
+
#scopeMap = inject(PI_FORM_BUILDER_ALIAS_MAP, { optional: true }) ??
|
|
1067
|
+
new ParentMap();
|
|
1068
|
+
#options = inject(PI_FORM_BUILDER_OPTIONS_TOKEN);
|
|
1069
|
+
#injector = inject(Injector);
|
|
1070
|
+
#envInjector = inject(EnvironmentInjector);
|
|
1071
|
+
#globalConfig = inject(PI_VIEW_CONFIG_TOKEN, { optional: true }) ?? undefined;
|
|
1072
|
+
#allFieldInitHookList = [];
|
|
1073
|
+
buildRoot(item) {
|
|
1074
|
+
const field = this.#buildControl({
|
|
1075
|
+
type: 'root',
|
|
1076
|
+
field: { fullPath: [] },
|
|
1077
|
+
form: undefined,
|
|
1078
|
+
resolvedField$: item.resolvedField$,
|
|
1079
|
+
append: () => { },
|
|
1080
|
+
}, item.field, 0);
|
|
1081
|
+
this.allFieldInitHookCall();
|
|
1082
|
+
}
|
|
1083
|
+
allFieldInitHookCall() {
|
|
1084
|
+
const list = this.#allFieldInitHookList;
|
|
1085
|
+
this.#allFieldInitHookList = [];
|
|
1086
|
+
list.forEach((fn) => fn());
|
|
1087
|
+
}
|
|
1088
|
+
#buildField(item) {
|
|
1089
|
+
if (item.type === 'group') {
|
|
1090
|
+
this.#buildGroup(item);
|
|
1091
|
+
}
|
|
1092
|
+
else {
|
|
1093
|
+
this.#buildArray(item);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
afterResolveConfig(rawConfig, config) {
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
#buildControl(parent,
|
|
1100
|
+
// 单独一项
|
|
1101
|
+
field, index) {
|
|
1102
|
+
// 利用类型查引用,
|
|
1103
|
+
let viewDefaultConfig;
|
|
1104
|
+
const type = field.type;
|
|
1105
|
+
let define;
|
|
1106
|
+
if (type) {
|
|
1107
|
+
const result = this.#resolveComponent(type);
|
|
1108
|
+
viewDefaultConfig = result.defaultConfig;
|
|
1109
|
+
define = result.define;
|
|
1110
|
+
}
|
|
1111
|
+
const mergeStrategy = this.#globalConfig?.defaultConfigMergeStrategy;
|
|
1112
|
+
const inputs = this.configMerge([
|
|
1113
|
+
this.#globalConfig?.defaultConfig?.inputs,
|
|
1114
|
+
viewDefaultConfig?.inputs,
|
|
1115
|
+
field.inputs,
|
|
1116
|
+
], false, typeof mergeStrategy === 'string'
|
|
1117
|
+
? mergeStrategy
|
|
1118
|
+
: (mergeStrategy?.inputs ?? DCONFIG_EFAULT_MERGE_STRAGEGY.inputs));
|
|
1119
|
+
const outputs = this.configMerge([
|
|
1120
|
+
this.#globalConfig?.defaultConfig?.outputs,
|
|
1121
|
+
viewDefaultConfig?.outputs,
|
|
1122
|
+
field.outputs,
|
|
1123
|
+
], false, typeof mergeStrategy === 'string'
|
|
1124
|
+
? mergeStrategy
|
|
1125
|
+
: (mergeStrategy?.outputs ?? DCONFIG_EFAULT_MERGE_STRAGEGY.outputs));
|
|
1126
|
+
const attributes = this.configMerge([
|
|
1127
|
+
this.#globalConfig?.defaultConfig?.attributes,
|
|
1128
|
+
viewDefaultConfig?.attributes,
|
|
1129
|
+
field.attributes,
|
|
1130
|
+
], false, typeof mergeStrategy === 'string'
|
|
1131
|
+
? mergeStrategy
|
|
1132
|
+
: (mergeStrategy?.attributes ??
|
|
1133
|
+
DCONFIG_EFAULT_MERGE_STRAGEGY.attributes));
|
|
1134
|
+
const wrappers1 = this.configMergeRaw([
|
|
1135
|
+
this.#globalConfig?.defaultConfig?.wrappers,
|
|
1136
|
+
viewDefaultConfig?.wrappers,
|
|
1137
|
+
field.wrappers,
|
|
1138
|
+
], true, typeof mergeStrategy === 'string'
|
|
1139
|
+
? mergeStrategy
|
|
1140
|
+
: (mergeStrategy?.wrappers ?? DCONFIG_EFAULT_MERGE_STRAGEGY.wrappers));
|
|
1141
|
+
const wrappers = this.#resolveWrappers(wrappers1);
|
|
1142
|
+
const props = this.configMerge([
|
|
1143
|
+
this.#globalConfig?.defaultConfig?.props,
|
|
1144
|
+
viewDefaultConfig?.props,
|
|
1145
|
+
field.props,
|
|
1146
|
+
], false, typeof mergeStrategy === 'string'
|
|
1147
|
+
? mergeStrategy
|
|
1148
|
+
: (mergeStrategy?.props ?? DCONFIG_EFAULT_MERGE_STRAGEGY.props));
|
|
1149
|
+
const formConfig$ = this.configMerge([
|
|
1150
|
+
this.#globalConfig?.defaultConfig?.formConfig,
|
|
1151
|
+
viewDefaultConfig?.formConfig,
|
|
1152
|
+
field.formConfig,
|
|
1153
|
+
], false, typeof mergeStrategy === 'string'
|
|
1154
|
+
? mergeStrategy
|
|
1155
|
+
: (mergeStrategy?.formConfig ??
|
|
1156
|
+
DCONFIG_EFAULT_MERGE_STRAGEGY.formConfig));
|
|
1157
|
+
const renderConfig = this.configMerge([
|
|
1158
|
+
this.#globalConfig?.defaultConfig?.renderConfig,
|
|
1159
|
+
viewDefaultConfig?.renderConfig,
|
|
1160
|
+
field.renderConfig,
|
|
1161
|
+
], false, typeof mergeStrategy === 'string'
|
|
1162
|
+
? mergeStrategy
|
|
1163
|
+
: (mergeStrategy?.renderConfig ??
|
|
1164
|
+
DCONFIG_EFAULT_MERGE_STRAGEGY.renderConfig));
|
|
1165
|
+
let control;
|
|
1166
|
+
let keyPath = field.key;
|
|
1167
|
+
if (isFieldLogicGroup(parent.form)) {
|
|
1168
|
+
keyPath ??= parent.form.controls$().length;
|
|
1169
|
+
}
|
|
1170
|
+
else if (isFieldArray(parent.form)) {
|
|
1171
|
+
keyPath ??= index;
|
|
1172
|
+
}
|
|
1173
|
+
const isRoot = parent.type === 'root';
|
|
1174
|
+
if (!field.nonFieldControl && (keyPath !== undefined || isRoot)) {
|
|
1175
|
+
control = createField(parent.form, field, keyPath,
|
|
1176
|
+
// 这里也是fullPath
|
|
1177
|
+
formConfig$, isRoot, this.#injector);
|
|
1178
|
+
}
|
|
1179
|
+
const rootForm = this.#options.form$$;
|
|
1180
|
+
let resolvedConfig = {
|
|
1181
|
+
id: field.id,
|
|
1182
|
+
keyPath: toArray(keyPath),
|
|
1183
|
+
get fullPath() {
|
|
1184
|
+
return [
|
|
1185
|
+
...resolvedConfig.parent.fullPath,
|
|
1186
|
+
...(resolvedConfig.keyPath ?? []),
|
|
1187
|
+
];
|
|
1188
|
+
},
|
|
1189
|
+
form: {
|
|
1190
|
+
parent: parent.form,
|
|
1191
|
+
control: control ?? (isGroup(field) ? parent.form : undefined),
|
|
1192
|
+
get root() {
|
|
1193
|
+
return rootForm();
|
|
1194
|
+
},
|
|
1195
|
+
},
|
|
1196
|
+
get: (keyPath, aliasNotFoundFn) => untracked(() => fieldQuery(keyPath, resolvedConfig, this.#scopeMap, this.#options.resolvedField$(), aliasNotFoundFn)),
|
|
1197
|
+
parent: parent.field,
|
|
1198
|
+
origin: field,
|
|
1199
|
+
renderConfig: renderConfig,
|
|
1200
|
+
formConfig: formConfig$,
|
|
1201
|
+
props,
|
|
1202
|
+
context: this.#options.context,
|
|
1203
|
+
priority: field.priority,
|
|
1204
|
+
hooks: field.hooks,
|
|
1205
|
+
alias: field.alias,
|
|
1206
|
+
inputs: inputs,
|
|
1207
|
+
outputs: outputs,
|
|
1208
|
+
attributes,
|
|
1209
|
+
define: define ? { ...define, inputs, outputs, attributes } : undefined,
|
|
1210
|
+
wrappers,
|
|
1211
|
+
};
|
|
1212
|
+
resolvedConfig =
|
|
1213
|
+
this.afterResolveConfig(field, resolvedConfig) ?? resolvedConfig;
|
|
1214
|
+
if (field.movePath) {
|
|
1215
|
+
this.#moveViewField(field.movePath, resolvedConfig);
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
parent.append(resolvedConfig);
|
|
1219
|
+
}
|
|
1220
|
+
if (field.alias) {
|
|
1221
|
+
this.#scopeMap.set(field.alias, resolvedConfig);
|
|
1222
|
+
}
|
|
1223
|
+
resolvedConfig.hooks?.fieldResolved?.(resolvedConfig);
|
|
1224
|
+
if (isRoot) {
|
|
1225
|
+
parent.resolvedField$.set(resolvedConfig);
|
|
1226
|
+
}
|
|
1227
|
+
// 递归进行解析
|
|
1228
|
+
if (isGroup(field) ||
|
|
1229
|
+
field.isLogicAnd ||
|
|
1230
|
+
field.isLogicOr ||
|
|
1231
|
+
field.isTuple) {
|
|
1232
|
+
resolvedConfig.fieldGroup = signal(new SortedArray((a, b) => a.priority - b.priority));
|
|
1233
|
+
this.#buildField({
|
|
1234
|
+
type: 'group',
|
|
1235
|
+
fields: field.children,
|
|
1236
|
+
field: resolvedConfig,
|
|
1237
|
+
form: (control || parent.form),
|
|
1238
|
+
append: (field) => {
|
|
1239
|
+
resolvedConfig.fieldGroup().push(field);
|
|
1240
|
+
},
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
else if (isArray(field)) {
|
|
1244
|
+
this.#buildField({
|
|
1245
|
+
type: 'array',
|
|
1246
|
+
templateField: field.arrayChild,
|
|
1247
|
+
field: resolvedConfig,
|
|
1248
|
+
form: control,
|
|
1249
|
+
append: (field) => { },
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
if (resolvedConfig.hooks?.allFieldsResolved) {
|
|
1253
|
+
this.#allFieldInitHookList.push(() => {
|
|
1254
|
+
resolvedConfig.hooks.allFieldsResolved(resolvedConfig);
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
return resolvedConfig;
|
|
1258
|
+
}
|
|
1259
|
+
#buildGroup(groupItem) {
|
|
1260
|
+
for (let index = 0; index < groupItem.fields.length; index++) {
|
|
1261
|
+
const field = groupItem.fields[index];
|
|
1262
|
+
this.#buildControl(groupItem, field, index);
|
|
1263
|
+
}
|
|
1264
|
+
/** 虚拟group不存在hooks */
|
|
1265
|
+
const field = groupItem.field;
|
|
1266
|
+
field.hooks?.afterChildrenInit?.(field);
|
|
1267
|
+
}
|
|
1268
|
+
createArrayItem(parent,
|
|
1269
|
+
// 单独一项
|
|
1270
|
+
field, index) {
|
|
1271
|
+
const Builder = this.constructor;
|
|
1272
|
+
const injector = Injector.create({
|
|
1273
|
+
providers: [
|
|
1274
|
+
Builder,
|
|
1275
|
+
{
|
|
1276
|
+
provide: PI_FORM_BUILDER_ALIAS_MAP,
|
|
1277
|
+
useValue: new ParentMap(this.#scopeMap),
|
|
1278
|
+
},
|
|
1279
|
+
{ provide: EnvironmentInjector, useFactory: () => injector },
|
|
1280
|
+
],
|
|
1281
|
+
parent: this.#envInjector,
|
|
1282
|
+
});
|
|
1283
|
+
this.#envInjector.get(DestroyRef).onDestroy(() => {
|
|
1284
|
+
result.injector?.destroy();
|
|
1285
|
+
});
|
|
1286
|
+
const instance = injector.get(Builder);
|
|
1287
|
+
const result = instance.#buildControl(parent, field, index);
|
|
1288
|
+
this.#allFieldInitHookList.push(() => instance.allFieldInitHookCall());
|
|
1289
|
+
result.injector = injector.get(EnvironmentInjector);
|
|
1290
|
+
return result;
|
|
1291
|
+
}
|
|
1292
|
+
#buildArray(arrayItem) {
|
|
1293
|
+
const { templateField, form } = arrayItem;
|
|
1294
|
+
arrayItem.field.action = {
|
|
1295
|
+
// 因为数组需要有动态添加的能力,所以才加上,group不需要
|
|
1296
|
+
set: (value, index) => {
|
|
1297
|
+
untracked(() => {
|
|
1298
|
+
index = (typeof index === 'number'
|
|
1299
|
+
? index
|
|
1300
|
+
: (arrayItem.field.fieldArray?.().length ?? 0));
|
|
1301
|
+
const result = this.createArrayItem(arrayItem, templateField, index);
|
|
1302
|
+
const list = [...arrayItem.field.fieldArray()];
|
|
1303
|
+
list[index] = result;
|
|
1304
|
+
arrayItem.field.fieldArray.set(list);
|
|
1305
|
+
this.allFieldInitHookCall();
|
|
1306
|
+
result.form.control.updateValue(value);
|
|
1307
|
+
});
|
|
1308
|
+
},
|
|
1309
|
+
remove: (index) => {
|
|
1310
|
+
untracked(() => {
|
|
1311
|
+
const list = [...arrayItem.field.fieldArray()];
|
|
1312
|
+
const [deletedItem] = list.splice(index, 1);
|
|
1313
|
+
arrayItem.field.fieldArray.set(list);
|
|
1314
|
+
form.removeAt(index);
|
|
1315
|
+
if (deletedItem) {
|
|
1316
|
+
deletedItem.injector.destroy();
|
|
1317
|
+
deletedItem.injector = undefined;
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
},
|
|
1321
|
+
};
|
|
1322
|
+
arrayItem.field.fieldArray = signal([]);
|
|
1323
|
+
arrayItem.field.hooks?.afterChildrenInit?.(arrayItem.field);
|
|
1324
|
+
form.beforeUpdateList.push((input) => {
|
|
1325
|
+
const controlLength = form.controls$().length;
|
|
1326
|
+
if (controlLength < input.length) {
|
|
1327
|
+
const list = arrayItem.field.fieldArray().slice();
|
|
1328
|
+
for (let index = controlLength; index < input.length; index++) {
|
|
1329
|
+
const result = this.createArrayItem(arrayItem, arrayItem.templateField, index);
|
|
1330
|
+
list[index] = result;
|
|
1331
|
+
}
|
|
1332
|
+
arrayItem.field.fieldArray.set(list);
|
|
1333
|
+
}
|
|
1334
|
+
else if (input.length < controlLength) {
|
|
1335
|
+
const list = arrayItem.field.fieldArray().slice();
|
|
1336
|
+
for (let index = arrayItem.field.fieldArray().length - 1; index >= input.length; index--) {
|
|
1337
|
+
const [deletedItem] = list.splice(index, 1);
|
|
1338
|
+
form.removeAt(index);
|
|
1339
|
+
if (deletedItem) {
|
|
1340
|
+
deletedItem.injector?.destroy();
|
|
1341
|
+
deletedItem.injector = undefined;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
arrayItem.field.fieldArray.set(list);
|
|
1345
|
+
}
|
|
1346
|
+
this.allFieldInitHookCall();
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
#resolveComponent(type) {
|
|
1350
|
+
let define;
|
|
1351
|
+
let defaultConfig;
|
|
1352
|
+
// 查引用
|
|
1353
|
+
if (typeof type === 'string') {
|
|
1354
|
+
const config = this.#globalConfig?.types?.[type];
|
|
1355
|
+
if (!config) {
|
|
1356
|
+
throw new Error(`define:未注册[${type}]`);
|
|
1357
|
+
}
|
|
1358
|
+
defaultConfig = config;
|
|
1359
|
+
if (Object.keys(config).length) {
|
|
1360
|
+
define = {
|
|
1361
|
+
...config,
|
|
1362
|
+
};
|
|
1363
|
+
return {
|
|
1364
|
+
define: { ...config },
|
|
1365
|
+
defaultConfig,
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
return { define: { type: type } };
|
|
1371
|
+
}
|
|
1372
|
+
return {
|
|
1373
|
+
define,
|
|
1374
|
+
defaultConfig,
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
configMergeRaw(list, isArray, strategy) {
|
|
1378
|
+
let value;
|
|
1379
|
+
if (isArray) {
|
|
1380
|
+
if (strategy === 'merge') {
|
|
1381
|
+
value = list
|
|
1382
|
+
.filter(Boolean)
|
|
1383
|
+
.flat()
|
|
1384
|
+
.map((item) => unWrapSignal(item));
|
|
1385
|
+
}
|
|
1386
|
+
else {
|
|
1387
|
+
value = list.reduce((data, item) => unWrapSignal(item) ?? data, []);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
if (strategy === 'merge') {
|
|
1392
|
+
value = list.reduce((obj, item) => ({
|
|
1393
|
+
...obj,
|
|
1394
|
+
...unWrapSignal(item),
|
|
1395
|
+
}), {});
|
|
1396
|
+
}
|
|
1397
|
+
else {
|
|
1398
|
+
value = list.reduce((data, item) => unWrapSignal(item) ?? data, {});
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
return clone(value);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* 后面覆盖前面
|
|
1405
|
+
* */
|
|
1406
|
+
configMerge(list, isArray, strategy) {
|
|
1407
|
+
return signal(this.configMergeRaw(list, isArray, strategy));
|
|
1408
|
+
}
|
|
1409
|
+
#moveViewField(key, inputField) {
|
|
1410
|
+
const parent = fieldQuery(key, inputField, this.#scopeMap, this.#options.resolvedField$(), (name, field) => {
|
|
1411
|
+
const rootForm = this.#options.form$$;
|
|
1412
|
+
const aliasField = {
|
|
1413
|
+
alias: name,
|
|
1414
|
+
parent: field,
|
|
1415
|
+
get fullPath() {
|
|
1416
|
+
return field.fullPath;
|
|
1417
|
+
},
|
|
1418
|
+
form: {
|
|
1419
|
+
parent: field.form.control ?? field.form.parent,
|
|
1420
|
+
control: undefined,
|
|
1421
|
+
get root() {
|
|
1422
|
+
return rootForm();
|
|
1423
|
+
},
|
|
1424
|
+
},
|
|
1425
|
+
get: (keyPath, fn) => fieldQuery(keyPath, aliasField, this.#scopeMap, this.#options.resolvedField$(), fn),
|
|
1426
|
+
fieldGroup: signal(new SortedArray((a, b) => a.priority - b.priority)),
|
|
1427
|
+
priority: 0,
|
|
1428
|
+
renderConfig: signal({}),
|
|
1429
|
+
wrappers: signal([]),
|
|
1430
|
+
};
|
|
1431
|
+
this.#scopeMap.set(name, aliasField);
|
|
1432
|
+
if (inputField === field) {
|
|
1433
|
+
throw new Error(`添加位置不可为自身`);
|
|
1434
|
+
}
|
|
1435
|
+
field.fieldGroup().push(aliasField);
|
|
1436
|
+
return aliasField;
|
|
1437
|
+
});
|
|
1438
|
+
if (!parent) {
|
|
1439
|
+
throw new Error('移动视图项失败');
|
|
1440
|
+
}
|
|
1441
|
+
const index = inputField.parent
|
|
1442
|
+
.fieldGroup?.()
|
|
1443
|
+
.findIndex((item) => item === inputField);
|
|
1444
|
+
if (typeof index === 'number' && index !== -1) {
|
|
1445
|
+
inputField.parent.fieldGroup?.().splice(index, 1);
|
|
1446
|
+
}
|
|
1447
|
+
const newKeyPath = inputField.fullPath.slice(parent.fullPath.length);
|
|
1448
|
+
inputField.keyPath = newKeyPath;
|
|
1449
|
+
inputField.parent = parent;
|
|
1450
|
+
parent.fieldGroup().push(inputField);
|
|
1451
|
+
}
|
|
1452
|
+
#resolveWrappers(wrappers) {
|
|
1453
|
+
const result = (wrappers ?? []).map((wrapper) => {
|
|
1454
|
+
// 查引用1
|
|
1455
|
+
if (typeof wrapper === 'string') {
|
|
1456
|
+
const config = this.#globalConfig?.wrappers?.[wrapper];
|
|
1457
|
+
if (!config) {
|
|
1458
|
+
throw new Error(`wrapper:未注册[${wrapper}]`);
|
|
1459
|
+
}
|
|
1460
|
+
return {
|
|
1461
|
+
...config,
|
|
1462
|
+
inputs: signal(config.inputs),
|
|
1463
|
+
attributes: signal(config.attributes),
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
else if (typeof wrapper.type === 'string') {
|
|
1467
|
+
// 查引用2
|
|
1468
|
+
const config = this.#globalConfig?.wrappers?.[wrapper.type];
|
|
1469
|
+
if (!config) {
|
|
1470
|
+
throw new Error(`wrapper:未注册[${wrapper.type}]`);
|
|
1471
|
+
}
|
|
1472
|
+
return {
|
|
1473
|
+
inputs: signal({ ...config.inputs, ...wrapper.inputs }),
|
|
1474
|
+
outputs: { ...config.outputs, ...wrapper.outputs },
|
|
1475
|
+
attributes: signal({ ...config.attributes, ...wrapper.attributes }),
|
|
1476
|
+
type: config.type,
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
else {
|
|
1480
|
+
return {
|
|
1481
|
+
...wrapper,
|
|
1482
|
+
inputs: signal(wrapper.inputs),
|
|
1483
|
+
attributes: signal(wrapper.attributes),
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
});
|
|
1487
|
+
return signal(result);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
function layout(value) {
|
|
1492
|
+
return {
|
|
1493
|
+
kind: 'metadata',
|
|
1494
|
+
type: 'layout',
|
|
1495
|
+
reference: layout,
|
|
1496
|
+
value: value,
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
const rawConfig = createRawConfig('viewRawConfig');
|
|
1501
|
+
|
|
1502
|
+
function setComponent(type) {
|
|
1503
|
+
return rawConfig((field) => {
|
|
1504
|
+
field.type = type;
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
const setHooks = (hooks) => rawConfig((field) => {
|
|
1509
|
+
field.hooks = hooks;
|
|
1510
|
+
});
|
|
1511
|
+
const patchHooks = (hooks) => rawConfig((field) => {
|
|
1512
|
+
field.hooks = { ...field.hooks, ...hooks };
|
|
1513
|
+
});
|
|
1514
|
+
const DefaultOptions$1 = { position: 'bottom' };
|
|
1515
|
+
function mergeHooksFn(hooks, options, field) {
|
|
1516
|
+
field.hooks ??= {};
|
|
1517
|
+
for (const key in hooks) {
|
|
1518
|
+
const oldFn = field.hooks[key];
|
|
1519
|
+
field.hooks[key] = (...args) => {
|
|
1520
|
+
if (options.position === 'top') {
|
|
1521
|
+
hooks[key](...args);
|
|
1522
|
+
}
|
|
1523
|
+
oldFn?.(...args);
|
|
1524
|
+
if (options.position === 'bottom') {
|
|
1525
|
+
hooks[key](...args);
|
|
1526
|
+
}
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
const mergeHooks = (hooks, options = DefaultOptions$1) => rawConfig((field) => mergeHooksFn(hooks, options, field));
|
|
1531
|
+
function removeHooks(list) {
|
|
1532
|
+
return rawConfig((field) => {
|
|
1533
|
+
const oldValue = field.hooks;
|
|
1534
|
+
if (!oldValue) {
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
list.forEach((item) => {
|
|
1538
|
+
delete oldValue[item];
|
|
1539
|
+
});
|
|
1540
|
+
field.hooks = oldValue;
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
function setInputs(inputs) {
|
|
1545
|
+
return rawConfig((field) => {
|
|
1546
|
+
field.inputs = inputs;
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
function patchInputs(inputs) {
|
|
1550
|
+
return rawConfig((field) => {
|
|
1551
|
+
field.inputs = {
|
|
1552
|
+
...field.inputs,
|
|
1553
|
+
...inputs,
|
|
1554
|
+
};
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
function removeInputs(list) {
|
|
1558
|
+
return rawConfig((field) => {
|
|
1559
|
+
const oldValue = unWrapSignal$1(field.inputs);
|
|
1560
|
+
if (!oldValue) {
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
list.forEach((item) => {
|
|
1564
|
+
delete oldValue[item];
|
|
1565
|
+
});
|
|
1566
|
+
field.inputs = oldValue;
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
function asyncInputMerge(dataObj, data$) {
|
|
1570
|
+
const signalObj = {};
|
|
1571
|
+
const inputList = Object.keys(dataObj);
|
|
1572
|
+
inputList.forEach((key) => {
|
|
1573
|
+
const result = dataObj[key];
|
|
1574
|
+
if (isPromise(result)) {
|
|
1575
|
+
// promise
|
|
1576
|
+
result.then((value) => {
|
|
1577
|
+
data$.update((lastData) => {
|
|
1578
|
+
lastData = { ...lastData };
|
|
1579
|
+
lastData[key] = value;
|
|
1580
|
+
return lastData;
|
|
1581
|
+
});
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
else if (isSubscribable(result)) {
|
|
1585
|
+
// rxjs
|
|
1586
|
+
result.subscribe({
|
|
1587
|
+
next: (value) => {
|
|
1588
|
+
data$.update((lastData) => {
|
|
1589
|
+
lastData = { ...lastData };
|
|
1590
|
+
lastData[key] = value;
|
|
1591
|
+
return lastData;
|
|
1592
|
+
});
|
|
1593
|
+
},
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
else if (isSignal(result)) {
|
|
1597
|
+
signalObj[key] = result;
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
// 普通类型
|
|
1601
|
+
data$.update((lastData) => {
|
|
1602
|
+
lastData = { ...lastData };
|
|
1603
|
+
lastData[key] = result;
|
|
1604
|
+
return lastData;
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
});
|
|
1608
|
+
const signalKeyList = Object.keys(signalObj);
|
|
1609
|
+
if (signalKeyList.length) {
|
|
1610
|
+
return linkedSignal(computed(() => ({
|
|
1611
|
+
...data$(),
|
|
1612
|
+
...signalKeyList.reduce((obj, key) => ({ ...obj, [key]: signalObj[key]() }), {}),
|
|
1613
|
+
})));
|
|
1614
|
+
}
|
|
1615
|
+
return data$;
|
|
1616
|
+
}
|
|
1617
|
+
function patchAsyncFn(patchKey) {
|
|
1618
|
+
return (dataObj, options) => rawConfig((rawField) => {
|
|
1619
|
+
const inputList = Object.keys(dataObj);
|
|
1620
|
+
const hookName = options?.hookName ?? 'allFieldsResolved';
|
|
1621
|
+
// 设置初始值
|
|
1622
|
+
rawField[patchKey] = {
|
|
1623
|
+
...rawField[patchKey],
|
|
1624
|
+
...inputList.reduce((obj, item) => {
|
|
1625
|
+
obj[item] = rawField[patchKey]?.[item] ?? undefined;
|
|
1626
|
+
return obj;
|
|
1627
|
+
}, {}),
|
|
1628
|
+
};
|
|
1629
|
+
return mergeHooksFn({
|
|
1630
|
+
[hookName]: (field) => {
|
|
1631
|
+
field[patchKey] =
|
|
1632
|
+
asyncInputMerge(Object.entries(dataObj).reduce((obj, [key, value]) => {
|
|
1633
|
+
obj[key] = value(field);
|
|
1634
|
+
return obj;
|
|
1635
|
+
}, {}), field[patchKey]);
|
|
1636
|
+
},
|
|
1637
|
+
}, { position: options?.addPosition ?? 'bottom' }, rawField);
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
const patchAsyncInputs = patchAsyncFn('inputs');
|
|
1641
|
+
|
|
1642
|
+
function setAttributes(attributes) {
|
|
1643
|
+
return rawConfig((field) => {
|
|
1644
|
+
field.attributes = attributes;
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1647
|
+
function patchAttributes(attributes) {
|
|
1648
|
+
return rawConfig((field) => {
|
|
1649
|
+
field.attributes = {
|
|
1650
|
+
...field.attributes,
|
|
1651
|
+
...attributes,
|
|
1652
|
+
};
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
function removeAttributes(list) {
|
|
1656
|
+
return rawConfig((field) => {
|
|
1657
|
+
const oldValue = unWrapSignal$1(field.attributes);
|
|
1658
|
+
if (!oldValue) {
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
list.forEach((item) => {
|
|
1662
|
+
delete oldValue[item];
|
|
1663
|
+
});
|
|
1664
|
+
field.attributes = oldValue;
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
const patchAsyncAttributes = patchAsyncFn('attributes');
|
|
1668
|
+
|
|
1669
|
+
function setProps(props) {
|
|
1670
|
+
return rawConfig((field) => {
|
|
1671
|
+
field.props = props;
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
function patchProps(props) {
|
|
1675
|
+
return rawConfig((field) => {
|
|
1676
|
+
field.props = {
|
|
1677
|
+
...field.props,
|
|
1678
|
+
...props,
|
|
1679
|
+
};
|
|
1680
|
+
});
|
|
1681
|
+
}
|
|
1682
|
+
function removeProps(list) {
|
|
1683
|
+
return rawConfig((field) => {
|
|
1684
|
+
const oldValue = unWrapSignal$1(field.props);
|
|
1685
|
+
if (!oldValue) {
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
list.forEach((item) => {
|
|
1689
|
+
delete oldValue[item];
|
|
1690
|
+
});
|
|
1691
|
+
field.props = oldValue;
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
const patchAsyncProps = patchAsyncFn('props');
|
|
1695
|
+
|
|
1696
|
+
function setOutputs(outputs) {
|
|
1697
|
+
return rawConfig((field) => {
|
|
1698
|
+
field.outputs = outputs;
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
function patchOutputs(outputs) {
|
|
1702
|
+
return rawConfig((field) => {
|
|
1703
|
+
const oldValue = field.outputs;
|
|
1704
|
+
field.outputs = {
|
|
1705
|
+
...oldValue,
|
|
1706
|
+
...outputs,
|
|
1707
|
+
};
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
function removeOutputs(list) {
|
|
1711
|
+
return rawConfig((field) => {
|
|
1712
|
+
const oldValue = field.outputs;
|
|
1713
|
+
if (!oldValue) {
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
list.forEach((item) => {
|
|
1717
|
+
delete oldValue[item];
|
|
1718
|
+
});
|
|
1719
|
+
field.outputs = oldValue;
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
function mergeOutputFn(field, outputs, options) {
|
|
1723
|
+
field.outputs.update((originOutputs) => {
|
|
1724
|
+
originOutputs = { ...originOutputs };
|
|
1725
|
+
for (const key in outputs) {
|
|
1726
|
+
const oldFn = originOutputs[key];
|
|
1727
|
+
originOutputs[key] = (...args) => {
|
|
1728
|
+
if (options.position === 'top') {
|
|
1729
|
+
outputs[key](...args, field);
|
|
1730
|
+
}
|
|
1731
|
+
oldFn?.(...args, field);
|
|
1732
|
+
if (options.position === 'bottom') {
|
|
1733
|
+
outputs[key](...args, field);
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
return originOutputs;
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
const DefaultOptions = { position: 'bottom' };
|
|
1741
|
+
const mergeOutputs = (outputs, options = DefaultOptions) => rawConfig((field) => {
|
|
1742
|
+
mergeHooksFn({
|
|
1743
|
+
allFieldsResolved: (field) => {
|
|
1744
|
+
mergeOutputFn(field, outputs, options);
|
|
1745
|
+
},
|
|
1746
|
+
}, { position: 'bottom' }, field);
|
|
1747
|
+
});
|
|
1748
|
+
function outputChangeFn(rawField, fn) {
|
|
1749
|
+
mergeHooksFn({
|
|
1750
|
+
allFieldsResolved: (field) => fn((list) => {
|
|
1751
|
+
const resultList = [];
|
|
1752
|
+
for (const item of list) {
|
|
1753
|
+
const emitField = !item.list ? field : field.get(item.list);
|
|
1754
|
+
const subject = new Subject();
|
|
1755
|
+
mergeOutputFn(field, {
|
|
1756
|
+
[item.output]: (...args) => {
|
|
1757
|
+
subject.next(args);
|
|
1758
|
+
},
|
|
1759
|
+
}, { position: 'bottom' });
|
|
1760
|
+
resultList.push({
|
|
1761
|
+
subject,
|
|
1762
|
+
field: emitField,
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
return combineLatest(resultList.map(({ subject }) => subject.pipe(startWith(undefined)))).pipe(skip(1), map((list) => ({
|
|
1766
|
+
list,
|
|
1767
|
+
field,
|
|
1768
|
+
listenFields: resultList.map((item) => item.field),
|
|
1769
|
+
})));
|
|
1770
|
+
}),
|
|
1771
|
+
}, { position: 'bottom' }, rawField);
|
|
1772
|
+
}
|
|
1773
|
+
function outputChange(fn) {
|
|
1774
|
+
return rawConfig((field) => outputChangeFn(field, fn));
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
function setWrappers(wrappers) {
|
|
1778
|
+
return rawConfig((field) => {
|
|
1779
|
+
field.wrappers = wrappers;
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
const defaultValue = {
|
|
1783
|
+
position: 'tail',
|
|
1784
|
+
};
|
|
1785
|
+
function patchWrappers(wrappers, options = defaultValue) {
|
|
1786
|
+
return rawConfig((field) => {
|
|
1787
|
+
const list = toArray(wrappers);
|
|
1788
|
+
field.wrappers ??= [];
|
|
1789
|
+
if (options.position === 'tail') {
|
|
1790
|
+
field.wrappers.push(...list);
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
field.wrappers.unshift(...list);
|
|
1794
|
+
}
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
function removeWrappers(list) {
|
|
1798
|
+
return rawConfig((field) => {
|
|
1799
|
+
if (!field.wrappers) {
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
const wrappers = field.wrappers;
|
|
1803
|
+
for (let i = 0; i < list.length; i++) {
|
|
1804
|
+
const name = list[i];
|
|
1805
|
+
for (let j = 0; j < wrappers.length; j++) {
|
|
1806
|
+
const config = wrappers[j];
|
|
1807
|
+
const name2 = typeof config === 'string' ? config : config.type;
|
|
1808
|
+
if (name2 === name) {
|
|
1809
|
+
wrappers.splice(j, 1);
|
|
1810
|
+
break;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
field.wrappers = wrappers;
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
function setAlias(alias) {
|
|
1819
|
+
return rawConfig((field) => {
|
|
1820
|
+
field.alias = alias;
|
|
1821
|
+
});
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
function renderConfig(type) {
|
|
1825
|
+
return rawConfig((field) => {
|
|
1826
|
+
field.renderConfig = type;
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
function formConfig(config) {
|
|
1830
|
+
return rawConfig((field) => {
|
|
1831
|
+
field.formConfig = { ...field.formConfig, ...config };
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
const DefaultSelfList = [undefined];
|
|
1836
|
+
function valueChangeFn(field, input = {}) {
|
|
1837
|
+
const list = (input.list ?? DefaultSelfList).map((keyPath) => !keyPath ? field.form.control : field.get(keyPath).form.control);
|
|
1838
|
+
return combineLatest(list.map((control) => input.skipInitValue
|
|
1839
|
+
? control.valueChanges.pipe(skip(1))
|
|
1840
|
+
: control.valueChanges)).pipe(map((list) => ({ list, field, listenFields: list })));
|
|
1841
|
+
}
|
|
1842
|
+
function valueChange(listenFn) {
|
|
1843
|
+
return rawConfig((field) => {
|
|
1844
|
+
mergeHooksFn({
|
|
1845
|
+
allFieldsResolved: (field) => {
|
|
1846
|
+
listenFn((options) => valueChangeFn(field, options), field);
|
|
1847
|
+
},
|
|
1848
|
+
}, { position: 'bottom' }, field);
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
function hideWhen(options) {
|
|
1853
|
+
return rawConfig((field) => {
|
|
1854
|
+
mergeHooksFn({
|
|
1855
|
+
allFieldsResolved: (field) => {
|
|
1856
|
+
options
|
|
1857
|
+
.listen((options) => valueChangeFn(field, options), field)
|
|
1858
|
+
.subscribe((hidden) => {
|
|
1859
|
+
field.renderConfig.update((value) => !!value.hidden !== hidden
|
|
1860
|
+
? { ...value, hidden: hidden }
|
|
1861
|
+
: value);
|
|
1862
|
+
if (options.disabled !== undefined && field.formConfig) {
|
|
1863
|
+
field.formConfig.update((value) => {
|
|
1864
|
+
value = { ...value };
|
|
1865
|
+
value.disabled = hidden ? options.disabled : false;
|
|
1866
|
+
return value;
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
});
|
|
1870
|
+
},
|
|
1871
|
+
}, { position: 'bottom' }, field);
|
|
1872
|
+
return field;
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
function disableWhen(options) {
|
|
1877
|
+
return rawConfig((field) => {
|
|
1878
|
+
mergeHooksFn({
|
|
1879
|
+
allFieldsResolved: (field) => {
|
|
1880
|
+
options
|
|
1881
|
+
.listen((options) => valueChangeFn(field, options), field)
|
|
1882
|
+
.subscribe((disabled) => {
|
|
1883
|
+
if (field.formConfig().disabled !== disabled) {
|
|
1884
|
+
field.formConfig.update((value) => ({
|
|
1885
|
+
...value,
|
|
1886
|
+
disabled: disabled,
|
|
1887
|
+
}));
|
|
1888
|
+
}
|
|
1889
|
+
});
|
|
1890
|
+
},
|
|
1891
|
+
}, { position: 'bottom' }, field);
|
|
1892
|
+
return field;
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
/** 必须防止到所有wrappers操作后面,防止设置错误
|
|
1897
|
+
* 设置到顶层,可能是wrapper,也可能是component
|
|
1898
|
+
*
|
|
1899
|
+
*/
|
|
1900
|
+
function topClass(className, merge) {
|
|
1901
|
+
return rawConfig((rawField) => {
|
|
1902
|
+
mergeHooksFn({
|
|
1903
|
+
fieldResolved: (field) => {
|
|
1904
|
+
const wrappers = field.wrappers();
|
|
1905
|
+
if (wrappers?.length) {
|
|
1906
|
+
wrappers[0].attributes.update((attributes) => ({
|
|
1907
|
+
...attributes,
|
|
1908
|
+
class: merge
|
|
1909
|
+
? clsx(attributes?.['class'], className)
|
|
1910
|
+
: clsx(className),
|
|
1911
|
+
}));
|
|
1912
|
+
}
|
|
1913
|
+
else {
|
|
1914
|
+
field.attributes.update((attributes) => ({
|
|
1915
|
+
...attributes,
|
|
1916
|
+
class: merge
|
|
1917
|
+
? clsx(attributes?.['class'], className)
|
|
1918
|
+
: clsx(className),
|
|
1919
|
+
}));
|
|
1920
|
+
}
|
|
1921
|
+
},
|
|
1922
|
+
}, { position: 'bottom' }, rawField);
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
/** 仅设置在组件上 */
|
|
1926
|
+
function componentClass(className, merge) {
|
|
1927
|
+
return rawConfig((field) => {
|
|
1928
|
+
field.attributes = {
|
|
1929
|
+
...field.attributes,
|
|
1930
|
+
class: merge
|
|
1931
|
+
? clsx(field.attributes?.['class'], className)
|
|
1932
|
+
: clsx(className),
|
|
1933
|
+
};
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
function nonFieldControl(value = true) {
|
|
1938
|
+
return {
|
|
1939
|
+
kind: 'metadata',
|
|
1940
|
+
type: 'nonFieldControl',
|
|
1941
|
+
reference: nonFieldControl,
|
|
1942
|
+
value: value,
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
class CoreSchemaHandle extends BaseSchemaHandle {
|
|
1947
|
+
inputs;
|
|
1948
|
+
outputs;
|
|
1949
|
+
wrappers;
|
|
1950
|
+
attributes;
|
|
1951
|
+
alias;
|
|
1952
|
+
movePath;
|
|
1953
|
+
renderConfig;
|
|
1954
|
+
/** todo 非表单应该可选 */
|
|
1955
|
+
formConfig = {};
|
|
1956
|
+
id;
|
|
1957
|
+
isLogicAnd = false;
|
|
1958
|
+
isLogicOr = false;
|
|
1959
|
+
isArray = false;
|
|
1960
|
+
isTuple = false;
|
|
1961
|
+
nonFieldControl = false;
|
|
1962
|
+
hooks;
|
|
1963
|
+
lazySchema(schema) {
|
|
1964
|
+
super.lazySchema(schema);
|
|
1965
|
+
if (this.parent) {
|
|
1966
|
+
const wrappered = this.lazyWrapped;
|
|
1967
|
+
if (this.parent.isArray) {
|
|
1968
|
+
this.parent.arrayChild = wrappered;
|
|
1969
|
+
}
|
|
1970
|
+
else {
|
|
1971
|
+
const index = this.parent.children.findIndex((item) => item === this);
|
|
1972
|
+
this.parent.children[index] = wrappered;
|
|
1973
|
+
}
|
|
1974
|
+
wrappered.parent = this.parent;
|
|
1975
|
+
wrappered.key = this.key;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
arraySchema(schema) {
|
|
1979
|
+
if (this.isObjectControl) {
|
|
1980
|
+
// 不需要设置默认值,因为item属于模板
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
else {
|
|
1984
|
+
this.isArray = true;
|
|
1985
|
+
const sh = new this.globalConfig.handle(this.globalConfig, this, schema);
|
|
1986
|
+
sh.parent = this;
|
|
1987
|
+
this.arrayChild = sh;
|
|
1988
|
+
convertSchema(schema.item, sh);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
defaultSchema(schema) {
|
|
1992
|
+
this.defaultValue = schema.literal;
|
|
1993
|
+
}
|
|
1994
|
+
tupleDefault(schema) {
|
|
1995
|
+
super.tupleDefault(schema);
|
|
1996
|
+
this.isTuple = true;
|
|
1997
|
+
}
|
|
1998
|
+
enumSchema(schema) {
|
|
1999
|
+
this.props ??= {};
|
|
2000
|
+
this.props['options'] ??= schema.options;
|
|
2001
|
+
}
|
|
2002
|
+
intersectBefore(schema) {
|
|
2003
|
+
if (this.childrenAsVirtualGroup) {
|
|
2004
|
+
// 临时修复,需要把action分为前后两个部分
|
|
2005
|
+
if (this.type === 'intersect') {
|
|
2006
|
+
this.type = 'intersect-group';
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
else {
|
|
2010
|
+
this.isLogicAnd = true;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
logicItemSchema(schema, index, type) {
|
|
2014
|
+
const sh = new this.globalConfig.handle(this.globalConfig, this, schema);
|
|
2015
|
+
if (this.childrenAsVirtualGroup) {
|
|
2016
|
+
}
|
|
2017
|
+
else {
|
|
2018
|
+
sh.key = index;
|
|
2019
|
+
}
|
|
2020
|
+
sh.setParent(this);
|
|
2021
|
+
convertSchema(schema, sh);
|
|
2022
|
+
}
|
|
2023
|
+
unionBefore(schema) {
|
|
2024
|
+
if (this.childrenAsVirtualGroup) {
|
|
2025
|
+
// 这个参数并不应该出现到这里,因为是专门为intersect设计
|
|
2026
|
+
}
|
|
2027
|
+
else {
|
|
2028
|
+
this.isLogicOr = true;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
beforeSchemaType(schema) {
|
|
2032
|
+
super.beforeSchemaType(schema);
|
|
2033
|
+
this.formConfig.required = !this.undefinedable && !this.nullable;
|
|
2034
|
+
}
|
|
2035
|
+
voidSchema(schema) {
|
|
2036
|
+
this.nonFieldControl = true;
|
|
2037
|
+
}
|
|
2038
|
+
metadataDefaulthandle(metadata, environments) {
|
|
2039
|
+
switch (metadata.type) {
|
|
2040
|
+
case 'viewRawConfig': {
|
|
2041
|
+
metadata.value(this, this.globalConfig.context);
|
|
2042
|
+
break;
|
|
2043
|
+
}
|
|
2044
|
+
case 'layout': {
|
|
2045
|
+
this.movePath = metadata.value.keyPath;
|
|
2046
|
+
this.priority = metadata.value.priority;
|
|
2047
|
+
break;
|
|
2048
|
+
}
|
|
2049
|
+
case 'nonFieldControl': {
|
|
2050
|
+
this.nonFieldControl = metadata.value;
|
|
2051
|
+
break;
|
|
2052
|
+
}
|
|
2053
|
+
default:
|
|
2054
|
+
break;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
end(schema) {
|
|
2058
|
+
super.end(schema);
|
|
2059
|
+
this.formConfig.defaultValue = this.defaultValue;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
function convert(obj, options) {
|
|
2064
|
+
const buildOptions = {
|
|
2065
|
+
form$$: computed(() => buildOptions.resolvedField$()?.form.control),
|
|
2066
|
+
resolvedField$: signal(undefined),
|
|
2067
|
+
context: options.context,
|
|
2068
|
+
};
|
|
2069
|
+
const injector = Injector.create({
|
|
2070
|
+
providers: [
|
|
2071
|
+
{
|
|
2072
|
+
provide: PI_FORM_BUILDER_OPTIONS_TOKEN,
|
|
2073
|
+
useValue: buildOptions,
|
|
2074
|
+
},
|
|
2075
|
+
{
|
|
2076
|
+
provide: PI_VIEW_CONFIG_TOKEN,
|
|
2077
|
+
useValue: options.fieldGlobalConfig,
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
provide: PI_CONTEXT_TOKEN,
|
|
2081
|
+
useValue: options.context,
|
|
2082
|
+
},
|
|
2083
|
+
options.builder,
|
|
2084
|
+
{ provide: EnvironmentInjector, useFactory: () => injector },
|
|
2085
|
+
],
|
|
2086
|
+
parent: options.injector,
|
|
2087
|
+
});
|
|
2088
|
+
options.registerOnDestroy?.(() => {
|
|
2089
|
+
injector.get(EnvironmentInjector).destroy();
|
|
2090
|
+
});
|
|
2091
|
+
return convertCore(obj, (item) => {
|
|
2092
|
+
// todo
|
|
2093
|
+
injector.get(options.builder).buildRoot({
|
|
2094
|
+
field: item,
|
|
2095
|
+
resolvedField$: buildOptions.resolvedField$,
|
|
2096
|
+
});
|
|
2097
|
+
return buildOptions.resolvedField$();
|
|
2098
|
+
}, {
|
|
2099
|
+
...options,
|
|
2100
|
+
handle: options?.handle ?? CoreSchemaHandle,
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
const NFCSchema = v.optional(v.void());
|
|
2105
|
+
|
|
2106
|
+
/**
|
|
2107
|
+
* Generated bundle index. Do not edit.
|
|
2108
|
+
*/
|
|
2109
|
+
|
|
2110
|
+
export { AbstractControl, CoreSchemaHandle, FieldArray, FieldControl, FieldGroup, FieldLogicGroup, FormBuilder, INVALID, NFCSchema, PENDING, PI_CONTEXT_TOKEN, PI_FORM_BUILDER_ALIAS_MAP, PI_FORM_BUILDER_OPTIONS_TOKEN, PI_VIEW_CONFIG_TOKEN, SortedArray, VALID, arrayStartsWith, asyncInputMerge, clone, componentClass, controlStatusList, convert, createViewControlLink, disableWhen, effectListen, fieldControlStatusClass, formConfig, hideWhen, isArray, isFieldArray, isFieldControl, isFieldGroup, isFieldLogicGroup, isGroup, layout, mergeHooks, mergeHooksFn, mergeOutputFn, mergeOutputs, nonFieldControl, outputChange, outputChangeFn, patchAsyncAttributes, patchAsyncFn, patchAsyncInputs, patchAsyncProps, patchAttributes, patchHooks, patchInputs, patchOutputs, patchProps, patchWrappers, rawConfig, removeAttributes, removeHooks, removeInputs, removeOutputs, removeProps, removeWrappers, renderConfig, setAlias, setAttributes, setComponent, setHooks, setInputs, setOutputs, setProps, setWrappers, toArray, toObservable, topClass, unWrapSignal$1 as unWrapSignal, valueChange, valueChangeFn };
|
|
2111
|
+
//# sourceMappingURL=piying-view-angular-core.mjs.map
|