@piying/view-angular 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.mjs +1215 -1
- package/fesm2022/piying-view-angular.mjs.map +1 -0
- package/index.d.ts +2 -2
- package/package.json +35 -2
- package/readme.md +1 -0
|
@@ -1 +1,1215 @@
|
|
|
1
|
-
var SelectorRegexp,SelectorFlags,SelectorRegexp1,SelectorFlags1;import*as i0 from"@angular/core";import{input,Directive,ChangeDetectionStrategy,Component,InjectionToken,reflectComponentType,ɵɵelementStart as __elementStart,ɵɵlistener as __listener,ɵɵtwoWayBindingSet as __twoWayBindingSet,ɵɵprojection as __projection,ɵɵtext as __text,ɵɵtextInterpolate as __textInterpolate,ɵɵelementEnd as __elementEnd,ɵɵproperty as __property,ɵɵtwoWayProperty as __twoWayProperty,viewChild,TemplateRef,ElementRef,ɵɵdefineComponent as __defineComponent,ɵɵviewQuerySignal as __viewQuerySignal,ɵɵqueryAdvance as __queryAdvance,ɵɵprojectionDef as __projectionDef,ɵɵtemplate as __template,inject,computed,untracked,signal,EventEmitter,Injector,createComponent,EnvironmentInjector,ViewContainerRef,createNgModule,resource,effect,Injectable,Pipe,output,createEnvironmentInjector,DestroyRef,linkedSignal}from"@angular/core";import{NgTemplateOutlet}from"@angular/common";import{deepEqual}from"fast-equals";import{NgControl,Validators,NG_VALUE_ACCESSOR}from"@angular/forms";import{createViewControlLink,FormBuilder,PI_VIEW_CONFIG_TOKEN,CoreSchemaHandle,convert,rawConfig as rawConfig$1,mergeHooksFn,asyncInputMerge}from"@piying/view-angular-core";export{asControl,asVirtualGroup,condition,layout}from"@piying/view-angular-core";class PiyingViewGroupBase{fields=input.required();fieldTemplateRef=input.required();static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingViewGroupBase,deps:[],target:i0.ɵɵFactoryTarget.Directive});static ɵdir=i0.ɵɵngDeclareDirective({minVersion:"17.1.0",version:"20.0.3",type:PiyingViewGroupBase,isStandalone:!0,inputs:{fields:{classPropertyName:"fields",publicName:"fields",isSignal:!0,isRequired:!0,transformFunction:null},fieldTemplateRef:{classPropertyName:"fieldTemplateRef",publicName:"fieldTemplateRef",isSignal:!0,isRequired:!0,transformFunction:null}},ngImport:i0})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingViewGroupBase,decorators:[{type:Directive}]});class PiyingViewGroup extends PiyingViewGroupBase{static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingViewGroup,deps:null,target:i0.ɵɵFactoryTarget.Component});static ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"20.0.3",type:PiyingViewGroup,isStandalone:!0,selector:"piying-view-group",usesInheritance:!0,ngImport:i0,template:'@for (field of fields(); track field.id || $index) {\n <ng-container\n *ngTemplateOutlet="fieldTemplateRef(); context: { $implicit: field }"\n ></ng-container>\n}\n',dependencies:[{kind:"directive",type:NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]}],changeDetection:i0.ChangeDetectionStrategy.OnPush})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingViewGroup,decorators:[{type:Component,args:[{selector:"piying-view-group",imports:[NgTemplateOutlet],standalone:!0,changeDetection:ChangeDetectionStrategy.OnPush,template:'@for (field of fields(); track field.id || $index) {\n <ng-container\n *ngTemplateOutlet="fieldTemplateRef(); context: { $implicit: field }"\n ></ng-container>\n}\n'}]}]});let PI_VIEW_FIELD_TOKEN=new InjectionToken("PI_VIEW_FIELD_TOKEN"),PI_COMPONENT_LIST=new InjectionToken("PI_COMPONENT_LIST"),PI_COMPONENT_INDEX=new InjectionToken("PI_COMPONENT_INDEX"),PI_COMPONENT_LIST_LISTEN=new InjectionToken("PI_COMPONENT_LIST_LISTEN"),EMPTY_ARRAY=[];function getComponentCheckConfig(a){return{...a,inputs:Object.keys(a.inputs()??{}).join(","),attributes:Object.entries(a.attributes()??{}).map((key,value)=>`${key}:${value}`).join(","),directives:a.directives?a.directives.map(config=>({...config,inputs:`${config.inputs?Object.keys(config.inputs()).join(","):""}`})):void 0,contents:a.contents?.map(item=>({...item,text:!!item.text}))}}let _SELECTOR_REGEXP=RegExp("(\\:not\\()|(([\\.\\#]?)[-\\w]+)|(?:\\[([-.\\w*\\\\$]+)(?:=([\"']?)([^\\]\"']*)\\5)?\\])|(\\))|(\\s*,\\s*)","g");(SelectorRegexp1=SelectorRegexp||(SelectorRegexp={}))[SelectorRegexp1.ALL=0]="ALL",SelectorRegexp1[SelectorRegexp1.NOT=1]="NOT",SelectorRegexp1[SelectorRegexp1.TAG=2]="TAG",SelectorRegexp1[SelectorRegexp1.PREFIX=3]="PREFIX",SelectorRegexp1[SelectorRegexp1.ATTRIBUTE=4]="ATTRIBUTE",SelectorRegexp1[SelectorRegexp1.ATTRIBUTE_STRING=5]="ATTRIBUTE_STRING",SelectorRegexp1[SelectorRegexp1.ATTRIBUTE_VALUE=6]="ATTRIBUTE_VALUE",SelectorRegexp1[SelectorRegexp1.NOT_END=7]="NOT_END",SelectorRegexp1[SelectorRegexp1.SEPARATOR=8]="SEPARATOR";class CssSelector{element=null;classNames=[];attrs=[];notSelectors=[];static parse(selector){let match,results=[],_addResult=(res,cssSel)=>{cssSel.notSelectors.length>0&&!cssSel.element&&0==cssSel.classNames.length&&0==cssSel.attrs.length&&(cssSel.element="*"),res.push(cssSel)},cssSelector=new CssSelector,current=cssSelector,inNot=!1;for(_SELECTOR_REGEXP.lastIndex=0;match=_SELECTOR_REGEXP.exec(selector);){if(match[SelectorRegexp.NOT]){if(inNot)throw Error("Nesting :not in a selector is not allowed");inNot=!0,current=new CssSelector,cssSelector.notSelectors.push(current)}let tag=match[SelectorRegexp.TAG];if(tag){let prefix=match[SelectorRegexp.PREFIX];"#"===prefix?current.addAttribute("id",tag.slice(1)):"."===prefix?current.addClassName(tag.slice(1)):current.setElement(tag)}let attribute=match[SelectorRegexp.ATTRIBUTE];if(attribute&¤t.addAttribute(current.unescapeAttribute(attribute),match[SelectorRegexp.ATTRIBUTE_VALUE]),match[SelectorRegexp.NOT_END]&&(inNot=!1,current=cssSelector),match[SelectorRegexp.SEPARATOR]){if(inNot)throw Error("Multiple selectors in :not are not supported");_addResult(results,cssSelector),cssSelector=current=new CssSelector}}return _addResult(results,cssSelector),results}unescapeAttribute(attr){let result="",escaping=!1;for(let i=0;i<attr.length;i++){let char=attr.charAt(i);if("\\"===char){escaping=!0;continue}if("$"===char&&!escaping)throw Error(`Error in attribute selector "${attr}". Unescaped "$" is not supported. Please escape with "\\$".`);escaping=!1,result+=char}return result}escapeAttribute(attr){return attr.replace(/\\/g,"\\\\").replace(/\$/g,"\\$")}setElement(element=null){this.element=element}addAttribute(name,value=""){this.attrs.push(name,value&&value.toLowerCase()||"")}addClassName(name){this.classNames.push(name.toLowerCase())}toString(){let res=this.element||"";if(this.classNames&&this.classNames.forEach(klass=>res+=`.${klass}`),this.attrs)for(let i=0;i<this.attrs.length;i+=2){let name=this.escapeAttribute(this.attrs[i]),value=this.attrs[i+1];res+=`[${name}${value?"="+value:""}]`}return this.notSelectors.forEach(notSelector=>res+=`:not(${notSelector})`),res}}function parserSelectorToR3Selector(selector){let positive=function(selector){let classes=selector.classNames&&selector.classNames.length?[SelectorFlags.CLASS,...selector.classNames]:[];return[selector.element&&"*"!==selector.element?selector.element:"",...selector.attrs,...classes]}(selector),negative=selector.notSelectors&&selector.notSelectors.length?selector.notSelectors.map(notSelector=>(function(selector){let classes=selector.classNames&&selector.classNames.length?[SelectorFlags.CLASS,...selector.classNames]:[];return selector.element?[SelectorFlags.NOT|SelectorFlags.ELEMENT,selector.element,...selector.attrs,...classes]:selector.attrs.length?[SelectorFlags.NOT|SelectorFlags.ATTRIBUTE,...selector.attrs,...classes]:selector.classNames&&selector.classNames.length?[SelectorFlags.NOT|SelectorFlags.CLASS,...selector.classNames]:[]})(notSelector)):[];return positive.concat(...negative)}(SelectorFlags1=SelectorFlags||(SelectorFlags={}))[SelectorFlags1.NOT=1]="NOT",SelectorFlags1[SelectorFlags1.ATTRIBUTE=2]="ATTRIBUTE",SelectorFlags1[SelectorFlags1.ELEMENT=4]="ELEMENT",SelectorFlags1[SelectorFlags1.CLASS=8]="CLASS";let EL_QUERY=["el"],index=0,EmptyOBJ={};class BaseComponent{#index=inject(PI_COMPONENT_INDEX,{optional:!0});#eventEmitter;#componentConfig;#viewContainerRef;destroyComponentFn;fieldComponentInstance;fieldElementRef;fieldDirectiveRefList;#componentCheckConfig$$;#setComponentCheck(config){this.#componentCheckConfig$$=computed(()=>untracked(()=>getComponentCheckConfig(config)))}setFieldData(field,index){this.#index=index}#inputCache;#contentCache;#configUpdate$=signal(0);createComponent(list,viewContainerRef){this.destroyComponentFn?.(),this.#viewContainerRef=viewContainerRef,this.#eventEmitter=new EventEmitter;let componentConfig=list[this.#index];this.#componentConfig=componentConfig,this.#inputCache={inputs:computed(()=>(this.#configUpdate$(),this.#componentConfig.inputs()??EmptyOBJ)),attributes:computed(()=>(this.#configUpdate$(),this.#componentConfig.attributes()??EmptyOBJ)),directiveList:this.#componentConfig?.directives?.map((config,index)=>config.inputs?computed(()=>(this.#configUpdate$(),this.#componentConfig.directives[index].inputs())):void 0)},this.#contentCache=componentConfig.contents?.map((item,index)=>item.text?{...item,text:computed(()=>(this.#configUpdate$(),this.#componentConfig.contents[index].text()))}:item),this.#setComponentCheck(componentConfig);let SidecarComponent=function(component,directives){let contentArray,result=function(component,list){let elementTag,vars=0,consts=[],directiveList=[],propertyList=[],listenerList=[],modelList=[];if("string"==typeof component.type)elementTag=component.type;else{let componentDefine=reflectComponentType(component.type);elementTag=component.selector??componentDefine.selector,directiveList.push(component.type)}if(!elementTag)throw Error("未找到元素对应的选择器");let attributes=component.attributes?.();if(attributes)for(let key in attributes)consts.push(key,attributes[key]);let mergedList=[component,...list];for(let i=0;i<mergedList.length;i++){let item=mergedList[i];if(i>0){directiveList.push(item.type);let selectors=item.type["ɵdir"].selectors,selector=item.selector??selectors.find(selectorList=>3===selectorList.length&&""===selectorList[0]&&""===selectorList[2])[1];(!item.inputs||selector in item.inputs())&&item.inputs||(!item.model||selector in item.model)&&item.model||consts.push(selector,"")}if(item.inputs)for(let key in propertyList[i]={signal:item.inputs,keyList:[]},item.inputs())vars++,propertyList[i].keyList.push(key);for(let key in item.outputs)listenerList.push({eventName:key,listenerFn:item.outputs[key]});for(let key in item.model)vars++,modelList.push({key:key,eventName:`${key}Change`,signal:item.model[key]})}return consts.push(3),consts.push(...new Set([...listenerList.map(({eventName})=>eventName),...modelList.map(({eventName})=>eventName)])),consts.push(...new Set([...propertyList.flatMap(item=>item.keyList),...modelList.map(({key})=>key)])),{vars,consts:[["el",""],consts],directiveList,propertyList:propertyList,listenerList:listenerList,modelList,elementTag}}(component,directives);function templateFn(rf,ctx){1&rf&&(__elementStart(0,result.elementTag,1,0),result.listenerList.reduce((fn,item)=>fn(item.eventName,item.listenerFn),__listener),result.modelList.reduce((fn,item)=>fn(item.eventName,value=>{__twoWayBindingSet(item.signal,value)}),__listener),component.contents?.length&&component.contents.forEach((item,index)=>{if(item.select){var selector;__projection(index+2,index,["ngProjectAs",item.select,5,((selector=item.select)?CssSelector.parse(selector).map(parserSelectorToR3Selector):[])[0]],item.text?(rf,ctx)=>{1&rf&&__text(0),2&rf&&__textInterpolate(item.text())}:void 0,item.text?1:void 0,item.text?1:void 0)}else __projection(index+1,index)}),__elementEnd()),2&rf&&(result.propertyList.reduce((fn,{signal,keyList})=>{let value=signal();return keyList.reduce((fn,key)=>fn(key,value[key]),fn)},__property),result.modelList.reduce((fn,item)=>fn(item.key,item.signal),__twoWayProperty))}return component.contents?.length&&(contentArray=Array(component.contents.length).fill("*")),class D{templateRef=viewChild.required(TemplateRef);componentInstance=viewChild("el");elementRef=viewChild("el",{read:ElementRef});directiveRefList=directives.map(({type})=>viewChild("el",{read:type}));static ɵfac=_=>new(_||D);static ɵcmp=__defineComponent({type:D,selectors:[[`d-${index++}`]],ngContentSelectors:contentArray,decls:1,vars:0,consts:result.consts,template:(rf,ctx)=>{1&rf&&(contentArray&&__projectionDef(contentArray),__template(0,templateFn,2+(component.contents?.length??0),result.vars,"ng-template"))},viewQuery:(rf,ctx)=>{1&rf&&(__viewQuerySignal(ctx.templateRef,TemplateRef,5),__viewQuerySignal(ctx.componentInstance,EL_QUERY,5),__viewQuerySignal(ctx.elementRef,EL_QUERY,5,ElementRef),directives.forEach(({type},index)=>{__viewQuerySignal(ctx.directiveRefList[index],EL_QUERY,5,type)})),2&rf&&__queryAdvance(3+directives.length)},dependencies:result.directiveList,encapsulation:2,changeDetection:0})}}({...componentConfig,inputs:this.#inputCache.inputs,attributes:this.#inputCache.attributes,contents:this.#contentCache},componentConfig.directives?.map((config,index)=>({...config,inputs:this.#inputCache.directiveList[index]}))??[]),componentInjector=Injector.create({providers:[{provide:PI_COMPONENT_LIST,useValue:list},{provide:PI_COMPONENT_INDEX,useValue:this.#index+1},{provide:PI_COMPONENT_LIST_LISTEN,useValue:this.#eventEmitter}],parent:componentConfig.injector??viewContainerRef.injector}),componentRef=createComponent(SidecarComponent,{elementInjector:componentInjector,environmentInjector:componentInjector.get(EnvironmentInjector),projectableNodes:componentConfig.contents?.map(({nodes})=>nodes).filter(Boolean)});if(viewContainerRef.createEmbeddedView(componentRef.instance.templateRef()),this.fieldComponentInstance=componentRef.instance.componentInstance(),this.fieldElementRef=componentRef.instance.elementRef(),this.fieldDirectiveRefList=componentRef.instance.directiveRefList.map(item=>item()),this.destroyComponentFn=()=>{viewContainerRef.clear(),componentRef.destroy(),this.#eventEmitter.unsubscribe()},list.length===this.#index+1){let field=componentInjector.get(PI_VIEW_FIELD_TOKEN)();field.hooks?.afterCreateComponent?.(field)}}update(list){let item=list[this.#index];deepEqual(getComponentCheckConfig(item),this.#componentCheckConfig$$())?(this.#componentConfig=item,this.#configUpdate$.update(a=>a+1),this.#eventEmitter.next(list)):this.createComponent(list,this.#viewContainerRef)}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:BaseComponent,deps:[],target:i0.ɵɵFactoryTarget.Directive});static ɵdir=i0.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"20.0.3",type:BaseComponent,isStandalone:!0,ngImport:i0})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:BaseComponent,decorators:[{type:Directive}]});class InteropNgControl extends NgControl{field;constructor(field){super(),this.field=field}control=this;get value(){return this.field().value}get valid(){return this.field().valid}get invalid(){return!this.field().valid}get pending(){return!1}get disabled(){return this.field().disabled}get enabled(){return!this.field().disabled}get errors(){return this.field().errors??null}get pristine(){return!0}get dirty(){return!1}get touched(){return this.field().touched}get untouched(){return!this.field().touched}get submitted(){return!1}viewToModelUpdate(newValue){}get valueChanges(){return this.field().valueChanges}get statusChanges(){return this.field().statusChanges}hasValidator(input){return Validators.required===input&&this.field().required$$()}}let formControlBinding={provide:NgControl,useFactory:()=>inject(FieldControlDirective).ngControl};class FieldControlDirective{fieldControl=input.required();cvaArray=inject(NG_VALUE_ACCESSOR);injector=inject(Injector);get cva(){return this.cvaArray[0]}#_ngControl;get ngControl(){return this.#_ngControl??=new InteropNgControl(()=>this.fieldControl())}ngOnInit(){this.disposeList.push(createViewControlLink(this.fieldControl,this.cva,this.injector))}disposeList=[];clear(){this.disposeList.forEach(fn=>fn()),this.disposeList=[]}ngOnDestroy(){this.clear()}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:FieldControlDirective,deps:[],target:i0.ɵɵFactoryTarget.Directive});static ɵdir=i0.ɵɵngDeclareDirective({minVersion:"17.1.0",version:"20.0.3",type:FieldControlDirective,isStandalone:!1,selector:"[fieldControl]",inputs:{fieldControl:{classPropertyName:"fieldControl",publicName:"fieldControl",isSignal:!0,isRequired:!0,transformFunction:null}},providers:[formControlBinding],ngImport:i0})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:FieldControlDirective,decorators:[{type:Directive,args:[{selector:"[fieldControl]",providers:[formControlBinding],standalone:!1}]}]});class NgComponentOutlet extends BaseComponent{ngComponentOutlet=input();ngComponentOutletInputs=input();ngComponentOutletOutputs=input();ngComponentOutletInjector=input();ngComponentOutletContent=input();ngComponentOutletFormControl=input();ngComponentOutletWrappers=input();ngComponentOutletTopDirectives=input();ngComponentOutletDirectives=input();ngComponentOutletField=input.required();#viewContainerRef=inject(ViewContainerRef);#wrappers=computed(()=>this.ngComponentOutletWrappers()?.map(item=>({...item,type:item.type.component,module:item.type.module})));#onputEqual$$=computed(()=>this.ngComponentOutletOutputs(),{equal:deepEqual});#moduleDestroy;#moduleRef$$=computed(()=>{this.#moduleDestroy?.();let injector=this.ngComponentOutletInjector()||this.#injector,module=this.ngComponentOutlet()?.type.module;if(!module)return;let moduleRef=createNgModule(module,injector);return this.#moduleDestroy=()=>{moduleRef.destroy(),this.#moduleDestroy=void 0},moduleRef});#usedEnvInjector$$=computed(()=>{let injector=this.#moduleRef$$()?.injector??(this.ngComponentOutletInjector()||this.#injector);return Injector.create({providers:[{provide:PI_VIEW_FIELD_TOKEN,useValue:this.ngComponentOutletField},{provide:PI_COMPONENT_INDEX,useValue:0}],parent:injector}).get(Injector)});#injector=inject(Injector);#formControlDirectiveConfig$$=computed(()=>{let fieldControl=this.ngComponentOutletFormControl();return fieldControl?{type:FieldControlDirective,inputs:computed(()=>({fieldControl:fieldControl}))}:void 0});#directiveConfigList$$=computed(()=>{let directivesInputs=this.ngComponentOutletDirectives(),formConfig=this.#formControlDirectiveConfig$$();return formConfig?[...directivesInputs?.()??[],formConfig]:directivesInputs?.()});#componentConfig$$=computed(()=>{let define=this.ngComponentOutlet();if(!define)return;let directives=this.#directiveConfigList$$();return{...define,type:define.type.component,module:define.type.module,inputs:this.ngComponentOutletInputs,directives:directives?directives.map(item=>{let outputs=item.outputs;return outputs?{...item,outputs:outputs}:item}):void 0,outputs:this.#onputEqual$$(),contents:this.ngComponentOutletContent()}});#componentList$$=computed(()=>{let componentConfig=this.#componentConfig$$();if(!componentConfig)return EMPTY_ARRAY;let injector=this.#usedEnvInjector$$(),list=[...this.#wrappers()??[],componentConfig];return list[0]={...list[0],injector},list});#lastList;ngOnChanges(){let list=this.#componentList$$();if(!list.length)return this.destroyComponentFn?.();if(this.#lastList)this.#lastList!==list&&this.update(list);else{let field=this.ngComponentOutletField();field.hooks?.beforeCreateComponent?.(field),this.setFieldData(this.ngComponentOutletField,0),this.createComponent(list,this.#viewContainerRef)}this.#lastList=list}ngOnDestroy(){this.#moduleDestroy?.(),this.destroyComponentFn?.()}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:NgComponentOutlet,deps:null,target:i0.ɵɵFactoryTarget.Directive});static ɵdir=i0.ɵɵngDeclareDirective({minVersion:"17.1.0",version:"20.0.3",type:NgComponentOutlet,isStandalone:!0,selector:"[ngComponentOutlet]",inputs:{ngComponentOutlet:{classPropertyName:"ngComponentOutlet",publicName:"ngComponentOutlet",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletInputs:{classPropertyName:"ngComponentOutletInputs",publicName:"ngComponentOutletInputs",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletOutputs:{classPropertyName:"ngComponentOutletOutputs",publicName:"ngComponentOutletOutputs",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletInjector:{classPropertyName:"ngComponentOutletInjector",publicName:"ngComponentOutletInjector",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletContent:{classPropertyName:"ngComponentOutletContent",publicName:"ngComponentOutletContent",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletFormControl:{classPropertyName:"ngComponentOutletFormControl",publicName:"ngComponentOutletFormControl",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletWrappers:{classPropertyName:"ngComponentOutletWrappers",publicName:"ngComponentOutletWrappers",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletTopDirectives:{classPropertyName:"ngComponentOutletTopDirectives",publicName:"ngComponentOutletTopDirectives",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletDirectives:{classPropertyName:"ngComponentOutletDirectives",publicName:"ngComponentOutletDirectives",isSignal:!0,isRequired:!1,transformFunction:null},ngComponentOutletField:{classPropertyName:"ngComponentOutletField",publicName:"ngComponentOutletField",isSignal:!0,isRequired:!0,transformFunction:null}},exportAs:["ngComponentOutlet"],usesInheritance:!0,usesOnChanges:!0,ngImport:i0})}function createAsyncCache(one,injector){let loading=new Map,cached=new Map;return list=>untracked(()=>{if(!list)return{value:computed(()=>void 0)};let hasPromise=!1,result=(one?[list]:list).map(item=>{if(cached.has(item))return cached.get(item);if(loading.has(item))return hasPromise=!0,loading.get(item);let type=item.type;if("string"!=typeof type&&!reflectComponentType(type))if("function"!=typeof type)return item;else{hasPromise=!0;let result$$=type().then(value=>{let result={...item,type:reflectComponentType(value)?{component:value}:value};return cached.set(item,result),loading.delete(item),result});return loading.set(item,result$$),result$$}{let result={...item,type:{component:type}};return cached.set(item,result),result}});return hasPromise?resource({loader:async()=>one?result[0]:Promise.all(result),injector:injector}):{value:computed(()=>one?result[0]:result)}})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:NgComponentOutlet,decorators:[{type:Directive,args:[{selector:"[ngComponentOutlet]",exportAs:"ngComponentOutlet",standalone:!0}]}]});class AngularFormBuilder extends FormBuilder{#globalConfig=inject(PI_VIEW_CONFIG_TOKEN,{optional:!0})??void 0;afterResolveConfig(rawConfig,config){let componentDefaultConfig,type=rawConfig.type,mergeStrategy=this.#globalConfig?.defaultConfigMergeStrategy;if(type){let result=this.#resolveComponent(type);result.define,componentDefaultConfig=result.defaultConfig}let directives=this.configMerge([componentDefaultConfig?.directives,rawConfig.directives],!0,"string"==typeof mergeStrategy?mergeStrategy:mergeStrategy?.directives??"merge");return{...config,contents:rawConfig.contents?.sort((a,b)=>a.nodes&&b.nodes?0:a.nodes?-1:1),directives:directives}}#resolveComponent(type){let define,defaultConfig;if("string"==typeof type){let config=this.#globalConfig?.types?.[type];if(!config)throw Error(`未注册${type}`);defaultConfig=config,Object.keys(config).length&&(define={...config})}else define={type};return{define,defaultConfig}}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:AngularFormBuilder,deps:null,target:i0.ɵɵFactoryTarget.Injectable});static ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:AngularFormBuilder})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:AngularFormBuilder,decorators:[{type:Injectable}]});class NgSchemaHandle extends CoreSchemaHandle{contents;directives}class PurePipe{transform(fn,...args){return fn(...args)}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PurePipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe});static ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"20.0.3",ngImport:i0,type:PurePipe,isStandalone:!0,name:"pure"})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PurePipe,decorators:[{type:Pipe,args:[{name:"pure",standalone:!0}]}]});let DefaultConvertOptions={builder:AngularFormBuilder,handle:NgSchemaHandle};class PiyingView{schema=input.required();model=input(void 0);modelChange=output();options=input();form$$=computed(()=>this.resolvedField$()?.form.control);#lastRF;ngOnChanges(changes){let rFields=this.#resolvedFields$$();(this.#lastRF!==rFields||"model"in changes)&&this.#modelChange$$(),this.#lastRF=rFields}#modelChange$$=computed(()=>{let model=this.model();untracked(()=>this.#updateField(model))});#resolvedFields$$=computed(()=>(this.schema(),untracked(()=>this.#updateForm())));#injector=inject(Injector);#envInjector=inject(EnvironmentInjector);#builderEnvInjector;resolvedField$=signal(void 0);#disposeList=[];#updateForm(){this.#clean();let envInjector=createEnvironmentInjector([],this.#envInjector);this.#builderEnvInjector=envInjector;let result=convert(this.schema(),{...DefaultConvertOptions,...this.options(),injector:envInjector,registerOnDestroy:fn=>{envInjector.get(DestroyRef).onDestroy(()=>{fn()})}});if(this.resolvedField$.set(result),result.form.control){var input,control,injector,fn;let init,ref=(input=this.model(),control=result.form.control,injector=this.#injector,fn=value=>{untracked(()=>{result.form.control?.valueNoError$$()&&this.modelChange.emit(value)})},init=!0,effect(()=>{let modelValue=control.value$$();init?(deepEqual(modelValue,input)||fn(modelValue),init=!1):fn(modelValue)},{injector}));this.#disposeList.push(()=>ref.destroy())}return result}#clean(isDestoryed=!1){this.#disposeList.forEach(item=>item()),this.#disposeList=[],!isDestoryed&&this.#builderEnvInjector&&(this.#builderEnvInjector.destroy(),this.#builderEnvInjector=void 0)}#updateField(model){if(!this.resolvedField$())return;let field=this.resolvedField$();field.form.control?.updateValue(model)}groupInputsValue=(inputs,fields,fieldTemplateRef)=>computed(()=>({...inputs(),fields,fieldTemplateRef}));resolvedComponent=createAsyncCache(!0,this.#injector);resolvedWrapper=createAsyncCache(!1,this.#injector);groupHidden=field=>computed(()=>this.#groupHidden(field));#groupHidden(field){return field.fieldGroup?!field.fieldGroup().length||field.fieldGroup().every(field=>this.#groupHidden(field)):!field.define||!!field.renderConfig().hidden}ngOnDestroy(){this.#clean(!0)}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingView,deps:[],target:i0.ɵɵFactoryTarget.Component});static ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"20.0.3",type:PiyingView,isStandalone:!0,selector:"piying-view",inputs:{schema:{classPropertyName:"schema",publicName:"schema",isSignal:!0,isRequired:!0,transformFunction:null},model:{classPropertyName:"model",publicName:"model",isSignal:!0,isRequired:!1,transformFunction:null},options:{classPropertyName:"options",publicName:"options",isSignal:!0,isRequired:!1,transformFunction:null}},outputs:{modelChange:"modelChange"},usesOnChanges:!0,ngImport:i0,template:'<ng-template #dynamicComponent let-field>\n @let renderConfig = field.renderConfig();\n @if (!renderConfig?.hidden) {\n @let typeResource = resolvedComponent | pure: field.define;\n @let type = typeResource.value();\n @let wrappersResource = resolvedWrapper | pure: field.wrappers();\n @let wrappers = wrappersResource.value();\n @if (type) {\n @if (field.fieldGroup) {\n @if (!(groupHidden | pure: field)()) {\n \x3c!-- 自定义group --\x3e\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="\n (\n groupInputsValue\n | pure: field.inputs : field.fieldGroup() : dynamicComponent\n )?.()\n "\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n ></ng-container>\n }\n } @else if (field.fieldArray) {\n \x3c!-- 自定义array --\x3e\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="\n (\n groupInputsValue\n | pure: field.inputs : field.fieldArray() : dynamicComponent\n )?.()\n "\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n ></ng-container>\n } @else {\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="field.inputs()"\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletFormControl]="$any(field.form.control)"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n [ngComponentOutletContent]="field.contents"\n ></ng-container>\n }\n }\n }\n</ng-template>\n\n@if (resolvedField$(); as field) {\n <ng-container\n *ngTemplateOutlet="dynamicComponent; context: { $implicit: field }"\n ></ng-container>\n}\n',dependencies:[{kind:"directive",type:NgComponentOutlet,selector:"[ngComponentOutlet]",inputs:["ngComponentOutlet","ngComponentOutletInputs","ngComponentOutletOutputs","ngComponentOutletInjector","ngComponentOutletContent","ngComponentOutletFormControl","ngComponentOutletWrappers","ngComponentOutletTopDirectives","ngComponentOutletDirectives","ngComponentOutletField"],exportAs:["ngComponentOutlet"]},{kind:"pipe",type:PurePipe,name:"pure"},{kind:"directive",type:NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]}],changeDetection:i0.ChangeDetectionStrategy.OnPush})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiyingView,decorators:[{type:Component,args:[{selector:"piying-view",imports:[NgComponentOutlet,PurePipe,NgTemplateOutlet],standalone:!0,changeDetection:ChangeDetectionStrategy.OnPush,template:'<ng-template #dynamicComponent let-field>\n @let renderConfig = field.renderConfig();\n @if (!renderConfig?.hidden) {\n @let typeResource = resolvedComponent | pure: field.define;\n @let type = typeResource.value();\n @let wrappersResource = resolvedWrapper | pure: field.wrappers();\n @let wrappers = wrappersResource.value();\n @if (type) {\n @if (field.fieldGroup) {\n @if (!(groupHidden | pure: field)()) {\n \x3c!-- 自定义group --\x3e\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="\n (\n groupInputsValue\n | pure: field.inputs : field.fieldGroup() : dynamicComponent\n )?.()\n "\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n ></ng-container>\n }\n } @else if (field.fieldArray) {\n \x3c!-- 自定义array --\x3e\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="\n (\n groupInputsValue\n | pure: field.inputs : field.fieldArray() : dynamicComponent\n )?.()\n "\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n ></ng-container>\n } @else {\n <ng-container\n [ngComponentOutlet]="type"\n [ngComponentOutletInputs]="field.inputs()"\n [ngComponentOutletOutputs]="field.outputs()"\n [ngComponentOutletFormControl]="$any(field.form.control)"\n [ngComponentOutletWrappers]="wrappers"\n [ngComponentOutletField]="field"\n [ngComponentOutletDirectives]="field.directives"\n [ngComponentOutletContent]="field.contents"\n ></ng-container>\n }\n }\n }\n</ng-template>\n\n@if (resolvedField$(); as field) {\n <ng-container\n *ngTemplateOutlet="dynamicComponent; context: { $implicit: field }"\n ></ng-container>\n}\n'}]}]});class PiWrapperBaseComponent extends BaseComponent{fieldComponentAnchor=viewChild("fieldComponent",{read:ViewContainerRef});field$$=inject(PI_VIEW_FIELD_TOKEN);props$$=computed(()=>this.field$$().props());#listen=inject(PI_COMPONENT_LIST_LISTEN);#list=inject(PI_COMPONENT_LIST);createComponent(){let result=super.createComponent(this.#list,this.fieldComponentAnchor());return this.#listen.subscribe(list=>{this.update(list)}),result}ngOnInit(){this.createComponent()}static ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiWrapperBaseComponent,deps:null,target:i0.ɵɵFactoryTarget.Directive});static ɵdir=i0.ɵɵngDeclareDirective({minVersion:"17.2.0",version:"20.0.3",type:PiWrapperBaseComponent,isStandalone:!0,viewQueries:[{propertyName:"fieldComponentAnchor",first:!0,predicate:["fieldComponent"],descendants:!0,read:ViewContainerRef,isSignal:!0}],usesInheritance:!0,ngImport:i0})}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"20.0.3",ngImport:i0,type:PiWrapperBaseComponent,decorators:[{type:Directive}]});let rawConfig=rawConfig$1;function setDirectives(items){return rawConfig(field=>{field.directives=items})}function patchDirectives(items){return rawConfig(field=>{field.directives??=[],field.directives.push(...items)})}function patchAsyncDirective(fn){return rawConfig(field=>{mergeHooksFn({fieldResolved:field=>{field.directives??=signal([]);let directive=fn(field),inputs=directive.inputs,inputs$=signal({});inputs&&(inputs$.set(Object.keys(inputs).reduce((obj,key)=>(obj[key]=void 0,obj),{})),inputs$=asyncInputMerge(inputs,inputs$));let oldDirectives=field.directives;field.directives=linkedSignal(()=>[...oldDirectives(),{...directive,inputs:inputs$}])}},{position:"bottom"},field)})}class BaseControl{value$=signal(void 0);emitValue;registerOnChange(fn){this.emitValue=fn}valueChange(value){this.emitValue?.(value),this.value$.set(value)}writeValue(obj){this.value$.set(obj??void 0)}#touched;registerOnTouched(fn){this.#touched=fn}touchedChange(){this.#touched()}disabled$=signal(!1);setDisabledState(isDisabled){this.disabled$.set(isDisabled)}}export{AngularFormBuilder,BaseControl,NgSchemaHandle,PI_COMPONENT_INDEX,PI_COMPONENT_LIST,PI_COMPONENT_LIST_LISTEN,PI_VIEW_FIELD_TOKEN,PiWrapperBaseComponent,PiyingView,PiyingViewGroup,PiyingViewGroupBase,patchAsyncDirective,patchDirectives,rawConfig,setDirectives};
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, Directive, ChangeDetectionStrategy, Component, InjectionToken, reflectComponentType, ɵɵelementStart as __elementStart, ɵɵlistener as __listener, ɵɵtwoWayBindingSet as __twoWayBindingSet, ɵɵprojection as __projection, ɵɵtext as __text, ɵɵtextInterpolate as __textInterpolate, ɵɵelementEnd as __elementEnd, ɵɵproperty as __property, ɵɵtwoWayProperty as __twoWayProperty, viewChild, TemplateRef, ElementRef, ɵɵdefineComponent as __defineComponent, ɵɵviewQuerySignal as __viewQuerySignal, ɵɵqueryAdvance as __queryAdvance, ɵɵprojectionDef as __projectionDef, ɵɵtemplate as __template, inject, computed, untracked, signal, EventEmitter, Injector, createComponent, EnvironmentInjector, ViewContainerRef, createNgModule, resource, effect, Injectable, Pipe, output, createEnvironmentInjector, DestroyRef, linkedSignal } from '@angular/core';
|
|
3
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
4
|
+
import { deepEqual } from 'fast-equals';
|
|
5
|
+
import { NgControl, Validators, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
|
+
import { createViewControlLink, FormBuilder, PI_VIEW_CONFIG_TOKEN, CoreSchemaHandle, convert, rawConfig as rawConfig$1, mergeHooksFn, asyncInputMerge } from '@piying/view-angular-core';
|
|
7
|
+
export { asControl, asVirtualGroup, condition, layout } from '@piying/view-angular-core';
|
|
8
|
+
|
|
9
|
+
class PiyingViewGroupBase {
|
|
10
|
+
fields = input.required();
|
|
11
|
+
fieldTemplateRef = input.required();
|
|
12
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingViewGroupBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
13
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: PiyingViewGroupBase, isStandalone: true, inputs: { fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, fieldTemplateRef: { classPropertyName: "fieldTemplateRef", publicName: "fieldTemplateRef", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
14
|
+
}
|
|
15
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingViewGroupBase, decorators: [{
|
|
16
|
+
type: Directive
|
|
17
|
+
}] });
|
|
18
|
+
|
|
19
|
+
class PiyingViewGroup extends PiyingViewGroupBase {
|
|
20
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingViewGroup, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
21
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: PiyingViewGroup, isStandalone: true, selector: "piying-view-group", usesInheritance: true, ngImport: i0, template: "@for (field of fields(); track field.id || $index) {\n <ng-container\n *ngTemplateOutlet=\"fieldTemplateRef(); context: { $implicit: field }\"\n ></ng-container>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
22
|
+
}
|
|
23
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingViewGroup, decorators: [{
|
|
24
|
+
type: Component,
|
|
25
|
+
args: [{ selector: 'piying-view-group', imports: [NgTemplateOutlet], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (field of fields(); track field.id || $index) {\n <ng-container\n *ngTemplateOutlet=\"fieldTemplateRef(); context: { $implicit: field }\"\n ></ng-container>\n}\n" }]
|
|
26
|
+
}] });
|
|
27
|
+
|
|
28
|
+
/** component */
|
|
29
|
+
/** wrapper中可以使用,已解析的配置 */
|
|
30
|
+
const PI_VIEW_FIELD_TOKEN = new InjectionToken('PI_VIEW_FIELD_TOKEN');
|
|
31
|
+
/**
|
|
32
|
+
* @internal
|
|
33
|
+
* 内部传参用
|
|
34
|
+
*/
|
|
35
|
+
const PI_COMPONENT_LIST = new InjectionToken('PI_COMPONENT_LIST');
|
|
36
|
+
const PI_COMPONENT_INDEX = new InjectionToken('PI_COMPONENT_INDEX');
|
|
37
|
+
const PI_COMPONENT_LIST_LISTEN = new InjectionToken('PI_COMPONENT_LIST_LISTEN');
|
|
38
|
+
|
|
39
|
+
const EMPTY_ARRAY = [];
|
|
40
|
+
const NG_CONFIG_DEFAULT_MERGE_STRAGEGY = {
|
|
41
|
+
directives: 'merge',
|
|
42
|
+
formConfig: 'merge',
|
|
43
|
+
inputs: 'merge',
|
|
44
|
+
outputs: 'merge',
|
|
45
|
+
props: 'merge',
|
|
46
|
+
renderConfig: 'merge',
|
|
47
|
+
wrappers: 'replace',
|
|
48
|
+
attributes: 'merge',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function getComponentCheckConfig(a) {
|
|
52
|
+
return {
|
|
53
|
+
...a,
|
|
54
|
+
inputs: Object.keys(a.inputs() ?? {}).join(','),
|
|
55
|
+
// todo 需要等修改为动态的再比较key
|
|
56
|
+
attributes: Object.entries(a.attributes() ?? {})
|
|
57
|
+
.map((key, value) => `${key}:${value}`)
|
|
58
|
+
.join(','),
|
|
59
|
+
directives: a.directives
|
|
60
|
+
? a.directives.map((config) => ({
|
|
61
|
+
...config,
|
|
62
|
+
inputs: `${config.inputs ? Object.keys(config.inputs()).join(',') : ''}`,
|
|
63
|
+
}))
|
|
64
|
+
: undefined,
|
|
65
|
+
contents: a.contents?.map((item) => ({ ...item, text: !!item.text })),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//packages/compiler/src/directive_matching.ts
|
|
70
|
+
/**
|
|
71
|
+
* @license
|
|
72
|
+
* Copyright Google LLC All Rights Reserved.
|
|
73
|
+
*
|
|
74
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
75
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
76
|
+
*/
|
|
77
|
+
const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not("
|
|
78
|
+
'(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#";
|
|
79
|
+
// "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range
|
|
80
|
+
// 4: attribute; 5: attribute_string; 6: attribute_value
|
|
81
|
+
'(?:\\[([-.\\w*\\\\$]+)(?:=(["\']?)([^\\]"\']*)\\5)?\\])|' + // "[name]", "[name=value]",
|
|
82
|
+
// "[name="value"]",
|
|
83
|
+
// "[name='value']"
|
|
84
|
+
'(\\))|' + // 7: ")"
|
|
85
|
+
'(\\s*,\\s*)', // 8: ","
|
|
86
|
+
'g');
|
|
87
|
+
/**
|
|
88
|
+
* These offsets should match the match-groups in `_SELECTOR_REGEXP` offsets.
|
|
89
|
+
*/
|
|
90
|
+
var SelectorRegexp;
|
|
91
|
+
(function (SelectorRegexp) {
|
|
92
|
+
SelectorRegexp[SelectorRegexp["ALL"] = 0] = "ALL";
|
|
93
|
+
SelectorRegexp[SelectorRegexp["NOT"] = 1] = "NOT";
|
|
94
|
+
SelectorRegexp[SelectorRegexp["TAG"] = 2] = "TAG";
|
|
95
|
+
SelectorRegexp[SelectorRegexp["PREFIX"] = 3] = "PREFIX";
|
|
96
|
+
SelectorRegexp[SelectorRegexp["ATTRIBUTE"] = 4] = "ATTRIBUTE";
|
|
97
|
+
SelectorRegexp[SelectorRegexp["ATTRIBUTE_STRING"] = 5] = "ATTRIBUTE_STRING";
|
|
98
|
+
SelectorRegexp[SelectorRegexp["ATTRIBUTE_VALUE"] = 6] = "ATTRIBUTE_VALUE";
|
|
99
|
+
SelectorRegexp[SelectorRegexp["NOT_END"] = 7] = "NOT_END";
|
|
100
|
+
SelectorRegexp[SelectorRegexp["SEPARATOR"] = 8] = "SEPARATOR";
|
|
101
|
+
})(SelectorRegexp || (SelectorRegexp = {}));
|
|
102
|
+
/**
|
|
103
|
+
* A css selector contains an element name,
|
|
104
|
+
* css classes and attribute/value pairs with the purpose
|
|
105
|
+
* of selecting subsets out of them.
|
|
106
|
+
*/
|
|
107
|
+
class CssSelector {
|
|
108
|
+
element = null;
|
|
109
|
+
classNames = [];
|
|
110
|
+
/**
|
|
111
|
+
* The selectors are encoded in pairs where:
|
|
112
|
+
* - even locations are attribute names
|
|
113
|
+
* - odd locations are attribute values.
|
|
114
|
+
*
|
|
115
|
+
* Example:
|
|
116
|
+
* Selector: `[key1=value1][key2]` would parse to:
|
|
117
|
+
* ```
|
|
118
|
+
* ['key1', 'value1', 'key2', '']
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
attrs = [];
|
|
122
|
+
notSelectors = [];
|
|
123
|
+
static parse(selector) {
|
|
124
|
+
const results = [];
|
|
125
|
+
const _addResult = (res, cssSel) => {
|
|
126
|
+
if (cssSel.notSelectors.length > 0 &&
|
|
127
|
+
!cssSel.element &&
|
|
128
|
+
cssSel.classNames.length == 0 &&
|
|
129
|
+
cssSel.attrs.length == 0) {
|
|
130
|
+
cssSel.element = '*';
|
|
131
|
+
}
|
|
132
|
+
res.push(cssSel);
|
|
133
|
+
};
|
|
134
|
+
let cssSelector = new CssSelector();
|
|
135
|
+
let match;
|
|
136
|
+
let current = cssSelector;
|
|
137
|
+
let inNot = false;
|
|
138
|
+
_SELECTOR_REGEXP.lastIndex = 0;
|
|
139
|
+
while ((match = _SELECTOR_REGEXP.exec(selector))) {
|
|
140
|
+
if (match[SelectorRegexp.NOT]) {
|
|
141
|
+
if (inNot) {
|
|
142
|
+
throw new Error('Nesting :not in a selector is not allowed');
|
|
143
|
+
}
|
|
144
|
+
inNot = true;
|
|
145
|
+
current = new CssSelector();
|
|
146
|
+
cssSelector.notSelectors.push(current);
|
|
147
|
+
}
|
|
148
|
+
const tag = match[SelectorRegexp.TAG];
|
|
149
|
+
if (tag) {
|
|
150
|
+
const prefix = match[SelectorRegexp.PREFIX];
|
|
151
|
+
if (prefix === '#') {
|
|
152
|
+
// #hash
|
|
153
|
+
current.addAttribute('id', tag.slice(1));
|
|
154
|
+
}
|
|
155
|
+
else if (prefix === '.') {
|
|
156
|
+
// Class
|
|
157
|
+
current.addClassName(tag.slice(1));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Element
|
|
161
|
+
current.setElement(tag);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const attribute = match[SelectorRegexp.ATTRIBUTE];
|
|
165
|
+
if (attribute) {
|
|
166
|
+
current.addAttribute(current.unescapeAttribute(attribute), match[SelectorRegexp.ATTRIBUTE_VALUE]);
|
|
167
|
+
}
|
|
168
|
+
if (match[SelectorRegexp.NOT_END]) {
|
|
169
|
+
inNot = false;
|
|
170
|
+
current = cssSelector;
|
|
171
|
+
}
|
|
172
|
+
if (match[SelectorRegexp.SEPARATOR]) {
|
|
173
|
+
if (inNot) {
|
|
174
|
+
throw new Error('Multiple selectors in :not are not supported');
|
|
175
|
+
}
|
|
176
|
+
_addResult(results, cssSelector);
|
|
177
|
+
cssSelector = current = new CssSelector();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
_addResult(results, cssSelector);
|
|
181
|
+
return results;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Unescape `\$` sequences from the CSS attribute selector.
|
|
185
|
+
*
|
|
186
|
+
* This is needed because `$` can have a special meaning in CSS selectors,
|
|
187
|
+
* but we might want to match an attribute that contains `$`.
|
|
188
|
+
* [MDN web link for more
|
|
189
|
+
* info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
|
|
190
|
+
* @param attr the attribute to unescape.
|
|
191
|
+
* @returns the unescaped string.
|
|
192
|
+
*/
|
|
193
|
+
unescapeAttribute(attr) {
|
|
194
|
+
let result = '';
|
|
195
|
+
let escaping = false;
|
|
196
|
+
for (let i = 0; i < attr.length; i++) {
|
|
197
|
+
const char = attr.charAt(i);
|
|
198
|
+
if (char === '\\') {
|
|
199
|
+
escaping = true;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (char === '$' && !escaping) {
|
|
203
|
+
throw new Error(`Error in attribute selector "${attr}". ` +
|
|
204
|
+
`Unescaped "$" is not supported. Please escape with "\\$".`);
|
|
205
|
+
}
|
|
206
|
+
escaping = false;
|
|
207
|
+
result += char;
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Escape `$` sequences from the CSS attribute selector.
|
|
213
|
+
*
|
|
214
|
+
* This is needed because `$` can have a special meaning in CSS selectors,
|
|
215
|
+
* with this method we are escaping `$` with `\$'.
|
|
216
|
+
* [MDN web link for more
|
|
217
|
+
* info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
|
|
218
|
+
* @param attr the attribute to escape.
|
|
219
|
+
* @returns the escaped string.
|
|
220
|
+
*/
|
|
221
|
+
escapeAttribute(attr) {
|
|
222
|
+
return attr.replace(/\\/g, '\\\\').replace(/\$/g, '\\$');
|
|
223
|
+
}
|
|
224
|
+
setElement(element = null) {
|
|
225
|
+
this.element = element;
|
|
226
|
+
}
|
|
227
|
+
addAttribute(name, value = '') {
|
|
228
|
+
this.attrs.push(name, (value && value.toLowerCase()) || '');
|
|
229
|
+
}
|
|
230
|
+
addClassName(name) {
|
|
231
|
+
this.classNames.push(name.toLowerCase());
|
|
232
|
+
}
|
|
233
|
+
toString() {
|
|
234
|
+
let res = this.element || '';
|
|
235
|
+
if (this.classNames) {
|
|
236
|
+
this.classNames.forEach((klass) => (res += `.${klass}`));
|
|
237
|
+
}
|
|
238
|
+
if (this.attrs) {
|
|
239
|
+
for (let i = 0; i < this.attrs.length; i += 2) {
|
|
240
|
+
const name = this.escapeAttribute(this.attrs[i]);
|
|
241
|
+
const value = this.attrs[i + 1];
|
|
242
|
+
res += `[${name}${value ? '=' + value : ''}]`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
this.notSelectors.forEach((notSelector) => (res += `:not(${notSelector})`));
|
|
246
|
+
return res;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// packages/compiler/src/core.ts
|
|
251
|
+
/**
|
|
252
|
+
* Flags used to generate R3-style CSS Selectors. They are pasted from
|
|
253
|
+
* core/src/render3/projection.ts because they cannot be referenced directly.
|
|
254
|
+
*/
|
|
255
|
+
var SelectorFlags;
|
|
256
|
+
(function (SelectorFlags) {
|
|
257
|
+
/** Indicates this is the beginning of a new negative selector */
|
|
258
|
+
SelectorFlags[SelectorFlags["NOT"] = 1] = "NOT";
|
|
259
|
+
/** Mode for matching attributes */
|
|
260
|
+
SelectorFlags[SelectorFlags["ATTRIBUTE"] = 2] = "ATTRIBUTE";
|
|
261
|
+
/** Mode for matching tag names */
|
|
262
|
+
SelectorFlags[SelectorFlags["ELEMENT"] = 4] = "ELEMENT";
|
|
263
|
+
/** Mode for matching class names */
|
|
264
|
+
SelectorFlags[SelectorFlags["CLASS"] = 8] = "CLASS";
|
|
265
|
+
})(SelectorFlags || (SelectorFlags = {}));
|
|
266
|
+
function parserSelectorToSimpleSelector(selector) {
|
|
267
|
+
const classes = selector.classNames && selector.classNames.length
|
|
268
|
+
? [SelectorFlags.CLASS, ...selector.classNames]
|
|
269
|
+
: [];
|
|
270
|
+
const elementName = selector.element && selector.element !== '*' ? selector.element : '';
|
|
271
|
+
return [elementName, ...selector.attrs, ...classes];
|
|
272
|
+
}
|
|
273
|
+
function parserSelectorToNegativeSelector(selector) {
|
|
274
|
+
const classes = selector.classNames && selector.classNames.length
|
|
275
|
+
? [SelectorFlags.CLASS, ...selector.classNames]
|
|
276
|
+
: [];
|
|
277
|
+
if (selector.element) {
|
|
278
|
+
return [
|
|
279
|
+
SelectorFlags.NOT | SelectorFlags.ELEMENT,
|
|
280
|
+
selector.element,
|
|
281
|
+
...selector.attrs,
|
|
282
|
+
...classes,
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
else if (selector.attrs.length) {
|
|
286
|
+
return [
|
|
287
|
+
SelectorFlags.NOT | SelectorFlags.ATTRIBUTE,
|
|
288
|
+
...selector.attrs,
|
|
289
|
+
...classes,
|
|
290
|
+
];
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
return selector.classNames && selector.classNames.length
|
|
294
|
+
? [SelectorFlags.NOT | SelectorFlags.CLASS, ...selector.classNames]
|
|
295
|
+
: [];
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function parserSelectorToR3Selector(selector) {
|
|
299
|
+
const positive = parserSelectorToSimpleSelector(selector);
|
|
300
|
+
const negative = selector.notSelectors && selector.notSelectors.length
|
|
301
|
+
? selector.notSelectors.map((notSelector) => parserSelectorToNegativeSelector(notSelector))
|
|
302
|
+
: [];
|
|
303
|
+
return positive.concat(...negative);
|
|
304
|
+
}
|
|
305
|
+
function parseSelectorToR3Selector(selector) {
|
|
306
|
+
return selector
|
|
307
|
+
? CssSelector.parse(selector).map(parserSelectorToR3Selector)
|
|
308
|
+
: [];
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function parseDirectives(component, list) {
|
|
312
|
+
let vars = 0;
|
|
313
|
+
const consts = [];
|
|
314
|
+
const directiveList = [];
|
|
315
|
+
const propertyList = [];
|
|
316
|
+
const listenerList = [];
|
|
317
|
+
const modelList = [];
|
|
318
|
+
let elementTag;
|
|
319
|
+
if (typeof component.type === 'string') {
|
|
320
|
+
elementTag = component.type;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
const componentDefine = reflectComponentType(component.type);
|
|
324
|
+
elementTag = component.selector ?? componentDefine.selector;
|
|
325
|
+
directiveList.push(component.type);
|
|
326
|
+
}
|
|
327
|
+
if (!elementTag) {
|
|
328
|
+
throw new Error('未找到元素对应的选择器');
|
|
329
|
+
}
|
|
330
|
+
// todo 静态attr应该改为动态的
|
|
331
|
+
const attributes = component.attributes?.();
|
|
332
|
+
if (attributes) {
|
|
333
|
+
for (const key in attributes) {
|
|
334
|
+
consts.push(key, attributes[key]);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const mergedList = [component, ...list];
|
|
338
|
+
for (let i = 0; i < mergedList.length; i++) {
|
|
339
|
+
const item = mergedList[i];
|
|
340
|
+
if (i > 0) {
|
|
341
|
+
directiveList.push(item.type);
|
|
342
|
+
const define = item.type['ɵdir'];
|
|
343
|
+
const selectors = define.selectors;
|
|
344
|
+
const selector = item.selector ??
|
|
345
|
+
selectors.find((selectorList) => selectorList.length === 3 &&
|
|
346
|
+
selectorList[0] === '' &&
|
|
347
|
+
selectorList[2] === '')[1];
|
|
348
|
+
if (((item.inputs && !(selector in item.inputs())) || !item.inputs) &&
|
|
349
|
+
((item.model && !(selector in item.model)) || !item.model)) {
|
|
350
|
+
consts.push(selector, '');
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (item.inputs) {
|
|
354
|
+
propertyList[i] = { signal: item.inputs, keyList: [] };
|
|
355
|
+
for (const key in item.inputs()) {
|
|
356
|
+
vars++;
|
|
357
|
+
propertyList[i].keyList.push(key);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
for (const key in item.outputs) {
|
|
361
|
+
listenerList.push({
|
|
362
|
+
eventName: key,
|
|
363
|
+
listenerFn: item.outputs[key],
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
for (const key in item.model) {
|
|
367
|
+
vars++;
|
|
368
|
+
modelList.push({
|
|
369
|
+
key: key,
|
|
370
|
+
eventName: `${key}Change`,
|
|
371
|
+
signal: item.model[key],
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// packages/core/src/render3/interfaces/attribute_marker.ts
|
|
376
|
+
consts.push(3);
|
|
377
|
+
consts.push(...new Set([
|
|
378
|
+
...listenerList.map(({ eventName }) => eventName),
|
|
379
|
+
...modelList.map(({ eventName }) => eventName),
|
|
380
|
+
]));
|
|
381
|
+
consts.push(...new Set([
|
|
382
|
+
...propertyList.flatMap((item) => item.keyList),
|
|
383
|
+
...modelList.map(({ key }) => key),
|
|
384
|
+
]));
|
|
385
|
+
return {
|
|
386
|
+
vars,
|
|
387
|
+
consts: [['el', ''], consts],
|
|
388
|
+
directiveList,
|
|
389
|
+
propertyList: propertyList,
|
|
390
|
+
listenerList: listenerList,
|
|
391
|
+
modelList,
|
|
392
|
+
elementTag,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/** 常量不变 */
|
|
396
|
+
const EL_QUERY = ['el'];
|
|
397
|
+
let index = 0;
|
|
398
|
+
function createDynamicComponentDefine(component, directives) {
|
|
399
|
+
const result = parseDirectives(component, directives);
|
|
400
|
+
let contentArray;
|
|
401
|
+
let contentData;
|
|
402
|
+
if (component.contents?.length) {
|
|
403
|
+
contentArray = new Array(component.contents.length).fill('*');
|
|
404
|
+
contentData;
|
|
405
|
+
}
|
|
406
|
+
function templateFn(rf, ctx) {
|
|
407
|
+
if (rf & 1) {
|
|
408
|
+
__elementStart(0, result.elementTag, 1, 0);
|
|
409
|
+
result.listenerList.reduce((fn, item) => fn(item.eventName, item.listenerFn), __listener);
|
|
410
|
+
result.modelList.reduce((fn, item) => fn(item.eventName, (value) => {
|
|
411
|
+
__twoWayBindingSet(item.signal, value);
|
|
412
|
+
}), __listener);
|
|
413
|
+
if (component.contents?.length) {
|
|
414
|
+
component.contents.forEach((item, index) => {
|
|
415
|
+
if (item.select) {
|
|
416
|
+
__projection(index + 2, index, [
|
|
417
|
+
'ngProjectAs',
|
|
418
|
+
item.select,
|
|
419
|
+
5,
|
|
420
|
+
parseSelectorToR3Selector(item.select)[0],
|
|
421
|
+
], item.text
|
|
422
|
+
? (rf, ctx) => {
|
|
423
|
+
if (rf & 1) {
|
|
424
|
+
__text(0);
|
|
425
|
+
}
|
|
426
|
+
if (rf & 2) {
|
|
427
|
+
__textInterpolate(item.text());
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
: undefined, item.text ? 1 : undefined, item.text ? 1 : undefined);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
__projection(index + 1, index);
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
__elementEnd();
|
|
438
|
+
}
|
|
439
|
+
if (rf & 2) {
|
|
440
|
+
result.propertyList.reduce((fn, { signal, keyList }) => {
|
|
441
|
+
const value = signal();
|
|
442
|
+
return keyList.reduce((fn, key) => fn(key, value[key]), fn);
|
|
443
|
+
}, __property);
|
|
444
|
+
result.modelList.reduce((fn, item) => fn(item.key, item.signal), __twoWayProperty);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return class D {
|
|
448
|
+
templateRef = viewChild.required(TemplateRef);
|
|
449
|
+
componentInstance = viewChild('el');
|
|
450
|
+
elementRef = viewChild('el', { read: ElementRef });
|
|
451
|
+
directiveRefList = directives.map(({ type }) => viewChild('el', { read: type }));
|
|
452
|
+
static ɵfac = (_) => new (_ || D)();
|
|
453
|
+
static ɵcmp = __defineComponent({
|
|
454
|
+
type: D,
|
|
455
|
+
selectors: [[`d-${index++}`]],
|
|
456
|
+
ngContentSelectors: contentArray,
|
|
457
|
+
decls: 1,
|
|
458
|
+
vars: 0,
|
|
459
|
+
consts: result.consts,
|
|
460
|
+
template: (rf, ctx) => {
|
|
461
|
+
if (rf & 1) {
|
|
462
|
+
if (contentArray) {
|
|
463
|
+
__projectionDef(contentArray);
|
|
464
|
+
}
|
|
465
|
+
__template(0, templateFn, 2 + (component.contents?.length ?? 0), result.vars, 'ng-template');
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
viewQuery: (rf, ctx) => {
|
|
469
|
+
if (rf & 1) {
|
|
470
|
+
__viewQuerySignal(ctx.templateRef, TemplateRef, 5);
|
|
471
|
+
__viewQuerySignal(ctx.componentInstance, EL_QUERY, 5);
|
|
472
|
+
__viewQuerySignal(ctx.elementRef, EL_QUERY, 5, ElementRef);
|
|
473
|
+
directives.forEach(({ type }, index) => {
|
|
474
|
+
__viewQuerySignal(ctx.directiveRefList[index], EL_QUERY, 5, type);
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (rf & 2) {
|
|
478
|
+
__queryAdvance(3 + directives.length);
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
dependencies: result.directiveList,
|
|
482
|
+
encapsulation: 2,
|
|
483
|
+
changeDetection: 0,
|
|
484
|
+
});
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const EmptyOBJ = {};
|
|
489
|
+
class BaseComponent {
|
|
490
|
+
/** 第一次默认为空 */
|
|
491
|
+
#index = inject(PI_COMPONENT_INDEX, { optional: true });
|
|
492
|
+
/** 发射提供到下一级 */
|
|
493
|
+
#eventEmitter;
|
|
494
|
+
#componentConfig;
|
|
495
|
+
#viewContainerRef;
|
|
496
|
+
destroyComponentFn;
|
|
497
|
+
fieldComponentInstance;
|
|
498
|
+
fieldElementRef;
|
|
499
|
+
fieldDirectiveRefList;
|
|
500
|
+
/** 比较时使用 */
|
|
501
|
+
#componentCheckConfig$$;
|
|
502
|
+
#setComponentCheck(config) {
|
|
503
|
+
this.#componentCheckConfig$$ = computed(() => untracked(() => getComponentCheckConfig(config)));
|
|
504
|
+
}
|
|
505
|
+
setFieldData(field, index) {
|
|
506
|
+
this.#index = index;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* 输入引用绑定
|
|
510
|
+
* 1. 上次传入的数据格式和当前一样,只触发更新
|
|
511
|
+
* 2. 上次传入的数据格式和当前不一样,直接重新创建
|
|
512
|
+
*/
|
|
513
|
+
#inputCache;
|
|
514
|
+
#contentCache;
|
|
515
|
+
#configUpdate$ = signal(0);
|
|
516
|
+
createComponent(list, viewContainerRef) {
|
|
517
|
+
// 销毁
|
|
518
|
+
this.destroyComponentFn?.();
|
|
519
|
+
this.#viewContainerRef = viewContainerRef;
|
|
520
|
+
// 取消上一级的定义
|
|
521
|
+
this.#eventEmitter = new EventEmitter();
|
|
522
|
+
const componentConfig = list[this.#index];
|
|
523
|
+
this.#componentConfig = componentConfig;
|
|
524
|
+
this.#inputCache = {
|
|
525
|
+
inputs: computed(() => {
|
|
526
|
+
this.#configUpdate$();
|
|
527
|
+
return this.#componentConfig.inputs() ?? EmptyOBJ;
|
|
528
|
+
}),
|
|
529
|
+
attributes: computed(() => {
|
|
530
|
+
this.#configUpdate$();
|
|
531
|
+
return this.#componentConfig.attributes() ?? EmptyOBJ;
|
|
532
|
+
}),
|
|
533
|
+
directiveList: this.#componentConfig?.directives?.map((config, index) => config.inputs
|
|
534
|
+
? computed(() => {
|
|
535
|
+
this.#configUpdate$();
|
|
536
|
+
return this.#componentConfig.directives[index].inputs();
|
|
537
|
+
})
|
|
538
|
+
: undefined),
|
|
539
|
+
};
|
|
540
|
+
this.#contentCache = componentConfig.contents?.map((item, index) => {
|
|
541
|
+
if (item.text) {
|
|
542
|
+
return {
|
|
543
|
+
...item,
|
|
544
|
+
text: computed(() => {
|
|
545
|
+
this.#configUpdate$();
|
|
546
|
+
return this.#componentConfig.contents[index].text();
|
|
547
|
+
}),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return item;
|
|
551
|
+
});
|
|
552
|
+
this.#setComponentCheck(componentConfig);
|
|
553
|
+
const SidecarComponent = createDynamicComponentDefine({
|
|
554
|
+
...componentConfig,
|
|
555
|
+
inputs: this.#inputCache.inputs,
|
|
556
|
+
attributes: this.#inputCache.attributes,
|
|
557
|
+
contents: this.#contentCache,
|
|
558
|
+
}, componentConfig.directives?.map((config, index) => ({
|
|
559
|
+
...config,
|
|
560
|
+
inputs: this.#inputCache.directiveList[index],
|
|
561
|
+
})) ?? []);
|
|
562
|
+
const componentInjector = Injector.create({
|
|
563
|
+
providers: [
|
|
564
|
+
{ provide: PI_COMPONENT_LIST, useValue: list },
|
|
565
|
+
{ provide: PI_COMPONENT_INDEX, useValue: this.#index + 1 },
|
|
566
|
+
{ provide: PI_COMPONENT_LIST_LISTEN, useValue: this.#eventEmitter },
|
|
567
|
+
],
|
|
568
|
+
parent: componentConfig.injector ?? viewContainerRef.injector,
|
|
569
|
+
});
|
|
570
|
+
const componentRef = createComponent(SidecarComponent, {
|
|
571
|
+
elementInjector: componentInjector,
|
|
572
|
+
environmentInjector: componentInjector.get(EnvironmentInjector),
|
|
573
|
+
projectableNodes: componentConfig.contents
|
|
574
|
+
?.map(({ nodes }) => nodes)
|
|
575
|
+
.filter(Boolean),
|
|
576
|
+
});
|
|
577
|
+
// todo 这里需不需要加注入?
|
|
578
|
+
viewContainerRef.createEmbeddedView(componentRef.instance.templateRef());
|
|
579
|
+
this.fieldComponentInstance = componentRef.instance.componentInstance();
|
|
580
|
+
this.fieldElementRef = componentRef.instance.elementRef();
|
|
581
|
+
this.fieldDirectiveRefList = componentRef.instance.directiveRefList.map((item) => item());
|
|
582
|
+
this.destroyComponentFn = () => {
|
|
583
|
+
viewContainerRef.clear();
|
|
584
|
+
componentRef.destroy();
|
|
585
|
+
this.#eventEmitter.unsubscribe();
|
|
586
|
+
};
|
|
587
|
+
if (list.length === this.#index + 1) {
|
|
588
|
+
const field = componentInjector.get(PI_VIEW_FIELD_TOKEN)();
|
|
589
|
+
field.hooks?.afterCreateComponent?.(field);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
update(list) {
|
|
593
|
+
const item = list[this.#index];
|
|
594
|
+
const currentCheckConfig = getComponentCheckConfig(item);
|
|
595
|
+
const isEqual = deepEqual(currentCheckConfig, this.#componentCheckConfig$$());
|
|
596
|
+
// this.#componentCheckConfig$$ = computed(() => currentCheckConfig);
|
|
597
|
+
if (isEqual) {
|
|
598
|
+
this.#componentConfig = item;
|
|
599
|
+
this.#configUpdate$.update((a) => a + 1);
|
|
600
|
+
// 相等不处理
|
|
601
|
+
this.#eventEmitter.next(list);
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
this.createComponent(list, this.#viewContainerRef);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
608
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.3", type: BaseComponent, isStandalone: true, ngImport: i0 });
|
|
609
|
+
}
|
|
610
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: BaseComponent, decorators: [{
|
|
611
|
+
type: Directive
|
|
612
|
+
}] });
|
|
613
|
+
|
|
614
|
+
class InteropNgControl extends NgControl {
|
|
615
|
+
field;
|
|
616
|
+
constructor(field) {
|
|
617
|
+
super();
|
|
618
|
+
this.field = field;
|
|
619
|
+
}
|
|
620
|
+
control = this;
|
|
621
|
+
get value() {
|
|
622
|
+
return this.field().value;
|
|
623
|
+
}
|
|
624
|
+
get valid() {
|
|
625
|
+
return this.field().valid;
|
|
626
|
+
}
|
|
627
|
+
get invalid() {
|
|
628
|
+
return !this.field().valid;
|
|
629
|
+
}
|
|
630
|
+
get pending() {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
get disabled() {
|
|
634
|
+
return this.field().disabled;
|
|
635
|
+
}
|
|
636
|
+
get enabled() {
|
|
637
|
+
return !this.field().disabled;
|
|
638
|
+
}
|
|
639
|
+
get errors() {
|
|
640
|
+
const errors = this.field().errors;
|
|
641
|
+
return errors ?? null;
|
|
642
|
+
}
|
|
643
|
+
get pristine() {
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
get dirty() {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
get touched() {
|
|
650
|
+
return this.field().touched;
|
|
651
|
+
}
|
|
652
|
+
get untouched() {
|
|
653
|
+
return !this.field().touched;
|
|
654
|
+
}
|
|
655
|
+
get submitted() {
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
viewToModelUpdate(newValue) { }
|
|
659
|
+
get valueChanges() {
|
|
660
|
+
return this.field().valueChanges;
|
|
661
|
+
}
|
|
662
|
+
get statusChanges() {
|
|
663
|
+
return this.field().statusChanges;
|
|
664
|
+
}
|
|
665
|
+
hasValidator(input) {
|
|
666
|
+
if (Validators.required === input) {
|
|
667
|
+
return this.field().required$$();
|
|
668
|
+
}
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const formControlBinding = {
|
|
674
|
+
provide: NgControl,
|
|
675
|
+
useFactory: () => inject(FieldControlDirective).ngControl,
|
|
676
|
+
};
|
|
677
|
+
class FieldControlDirective {
|
|
678
|
+
fieldControl = input.required();
|
|
679
|
+
cvaArray = inject(NG_VALUE_ACCESSOR);
|
|
680
|
+
injector = inject(Injector);
|
|
681
|
+
get cva() {
|
|
682
|
+
return this.cvaArray[0];
|
|
683
|
+
}
|
|
684
|
+
#_ngControl;
|
|
685
|
+
get ngControl() {
|
|
686
|
+
return (this.#_ngControl ??= new InteropNgControl(() => this.fieldControl()));
|
|
687
|
+
}
|
|
688
|
+
ngOnInit() {
|
|
689
|
+
this.disposeList.push(createViewControlLink(this.fieldControl, this.cva, this.injector));
|
|
690
|
+
}
|
|
691
|
+
disposeList = [];
|
|
692
|
+
clear() {
|
|
693
|
+
this.disposeList.forEach((fn) => fn());
|
|
694
|
+
this.disposeList = [];
|
|
695
|
+
}
|
|
696
|
+
/** @docs-private */
|
|
697
|
+
ngOnDestroy() {
|
|
698
|
+
this.clear();
|
|
699
|
+
}
|
|
700
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FieldControlDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
701
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: FieldControlDirective, isStandalone: false, selector: "[fieldControl]", inputs: { fieldControl: { classPropertyName: "fieldControl", publicName: "fieldControl", isSignal: true, isRequired: true, transformFunction: null } }, providers: [formControlBinding], ngImport: i0 });
|
|
702
|
+
}
|
|
703
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: FieldControlDirective, decorators: [{
|
|
704
|
+
type: Directive,
|
|
705
|
+
args: [{
|
|
706
|
+
selector: '[fieldControl]',
|
|
707
|
+
providers: [formControlBinding],
|
|
708
|
+
standalone: false,
|
|
709
|
+
}]
|
|
710
|
+
}] });
|
|
711
|
+
|
|
712
|
+
class NgComponentOutlet extends BaseComponent {
|
|
713
|
+
/** 输入 */
|
|
714
|
+
ngComponentOutlet = input();
|
|
715
|
+
ngComponentOutletInputs = input();
|
|
716
|
+
ngComponentOutletOutputs = input();
|
|
717
|
+
ngComponentOutletInjector = input();
|
|
718
|
+
ngComponentOutletContent = input();
|
|
719
|
+
/** 控件用 */
|
|
720
|
+
ngComponentOutletFormControl = input();
|
|
721
|
+
/** 包裹用 */
|
|
722
|
+
ngComponentOutletWrappers = input();
|
|
723
|
+
ngComponentOutletTopDirectives = input();
|
|
724
|
+
ngComponentOutletDirectives = input();
|
|
725
|
+
ngComponentOutletField = input.required();
|
|
726
|
+
#viewContainerRef = inject(ViewContainerRef);
|
|
727
|
+
// 这里感觉会在非发射时出现多次输入?
|
|
728
|
+
#wrappers = computed(() => this.ngComponentOutletWrappers()?.map((item) => ({
|
|
729
|
+
...item,
|
|
730
|
+
type: item.type.component,
|
|
731
|
+
module: item.type.module,
|
|
732
|
+
})));
|
|
733
|
+
#onputEqual$$ = computed(() => this.ngComponentOutletOutputs(), {
|
|
734
|
+
equal: deepEqual,
|
|
735
|
+
});
|
|
736
|
+
#moduleDestroy;
|
|
737
|
+
#moduleRef$$ = computed(() => {
|
|
738
|
+
this.#moduleDestroy?.();
|
|
739
|
+
const injector = this.ngComponentOutletInjector() || this.#injector;
|
|
740
|
+
const module = this.ngComponentOutlet()?.type.module;
|
|
741
|
+
if (!module) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const moduleRef = createNgModule(module, injector);
|
|
745
|
+
this.#moduleDestroy = () => {
|
|
746
|
+
moduleRef.destroy();
|
|
747
|
+
this.#moduleDestroy = undefined;
|
|
748
|
+
};
|
|
749
|
+
return moduleRef;
|
|
750
|
+
});
|
|
751
|
+
#usedEnvInjector$$ = computed(() => {
|
|
752
|
+
const injector = this.#moduleRef$$()?.injector ??
|
|
753
|
+
(this.ngComponentOutletInjector() || this.#injector);
|
|
754
|
+
return Injector.create({
|
|
755
|
+
providers: [
|
|
756
|
+
{
|
|
757
|
+
provide: PI_VIEW_FIELD_TOKEN,
|
|
758
|
+
useValue: this.ngComponentOutletField,
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
provide: PI_COMPONENT_INDEX,
|
|
762
|
+
useValue: 0,
|
|
763
|
+
},
|
|
764
|
+
],
|
|
765
|
+
parent: injector,
|
|
766
|
+
}).get(Injector);
|
|
767
|
+
});
|
|
768
|
+
#injector = inject(Injector);
|
|
769
|
+
#formControlDirectiveConfig$$ = computed(() => {
|
|
770
|
+
const fieldControl = this.ngComponentOutletFormControl();
|
|
771
|
+
return fieldControl
|
|
772
|
+
? {
|
|
773
|
+
type: FieldControlDirective,
|
|
774
|
+
inputs: computed(() => ({ fieldControl: fieldControl })),
|
|
775
|
+
}
|
|
776
|
+
: undefined;
|
|
777
|
+
});
|
|
778
|
+
#directiveConfigList$$ = computed(() => {
|
|
779
|
+
const directivesInputs = this.ngComponentOutletDirectives();
|
|
780
|
+
const formConfig = this.#formControlDirectiveConfig$$();
|
|
781
|
+
return formConfig
|
|
782
|
+
? [...(directivesInputs?.() ?? []), formConfig]
|
|
783
|
+
: directivesInputs?.();
|
|
784
|
+
});
|
|
785
|
+
#componentConfig$$ = computed(() => {
|
|
786
|
+
const define = this.ngComponentOutlet();
|
|
787
|
+
if (!define) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
const directives = this.#directiveConfigList$$();
|
|
791
|
+
return {
|
|
792
|
+
...define,
|
|
793
|
+
type: define.type.component,
|
|
794
|
+
module: define.type.module,
|
|
795
|
+
inputs: this.ngComponentOutletInputs,
|
|
796
|
+
directives: directives
|
|
797
|
+
? directives.map((item) => {
|
|
798
|
+
const outputs = item.outputs;
|
|
799
|
+
if (outputs) {
|
|
800
|
+
return {
|
|
801
|
+
...item,
|
|
802
|
+
outputs: outputs,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
return item;
|
|
806
|
+
})
|
|
807
|
+
: undefined,
|
|
808
|
+
outputs: this.#onputEqual$$(),
|
|
809
|
+
contents: this.ngComponentOutletContent(),
|
|
810
|
+
};
|
|
811
|
+
});
|
|
812
|
+
#componentList$$ = computed(() => {
|
|
813
|
+
const componentConfig = this.#componentConfig$$();
|
|
814
|
+
if (!componentConfig) {
|
|
815
|
+
return EMPTY_ARRAY;
|
|
816
|
+
}
|
|
817
|
+
const injector = this.#usedEnvInjector$$();
|
|
818
|
+
const list = [
|
|
819
|
+
...(this.#wrappers() ?? []),
|
|
820
|
+
componentConfig,
|
|
821
|
+
];
|
|
822
|
+
list[0] = { ...list[0], injector };
|
|
823
|
+
return list;
|
|
824
|
+
});
|
|
825
|
+
#lastList;
|
|
826
|
+
ngOnChanges() {
|
|
827
|
+
//todo 变更时的一些检测,相同时应该不处理
|
|
828
|
+
const list = this.#componentList$$();
|
|
829
|
+
if (!list.length) {
|
|
830
|
+
return this.destroyComponentFn?.();
|
|
831
|
+
}
|
|
832
|
+
if (!this.#lastList) {
|
|
833
|
+
const field = this.ngComponentOutletField();
|
|
834
|
+
field.hooks?.beforeCreateComponent?.(field);
|
|
835
|
+
this.setFieldData(this.ngComponentOutletField, 0);
|
|
836
|
+
this.createComponent(list, this.#viewContainerRef);
|
|
837
|
+
}
|
|
838
|
+
else if (this.#lastList !== list) {
|
|
839
|
+
this.update(list);
|
|
840
|
+
}
|
|
841
|
+
// 监听输入/输出变更,重新进行赋值
|
|
842
|
+
this.#lastList = list;
|
|
843
|
+
}
|
|
844
|
+
ngOnDestroy() {
|
|
845
|
+
this.#moduleDestroy?.();
|
|
846
|
+
this.destroyComponentFn?.();
|
|
847
|
+
}
|
|
848
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgComponentOutlet, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
849
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: NgComponentOutlet, isStandalone: true, selector: "[ngComponentOutlet]", inputs: { ngComponentOutlet: { classPropertyName: "ngComponentOutlet", publicName: "ngComponentOutlet", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletInputs: { classPropertyName: "ngComponentOutletInputs", publicName: "ngComponentOutletInputs", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletOutputs: { classPropertyName: "ngComponentOutletOutputs", publicName: "ngComponentOutletOutputs", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletInjector: { classPropertyName: "ngComponentOutletInjector", publicName: "ngComponentOutletInjector", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletContent: { classPropertyName: "ngComponentOutletContent", publicName: "ngComponentOutletContent", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletFormControl: { classPropertyName: "ngComponentOutletFormControl", publicName: "ngComponentOutletFormControl", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletWrappers: { classPropertyName: "ngComponentOutletWrappers", publicName: "ngComponentOutletWrappers", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletTopDirectives: { classPropertyName: "ngComponentOutletTopDirectives", publicName: "ngComponentOutletTopDirectives", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletDirectives: { classPropertyName: "ngComponentOutletDirectives", publicName: "ngComponentOutletDirectives", isSignal: true, isRequired: false, transformFunction: null }, ngComponentOutletField: { classPropertyName: "ngComponentOutletField", publicName: "ngComponentOutletField", isSignal: true, isRequired: true, transformFunction: null } }, exportAs: ["ngComponentOutlet"], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
|
|
850
|
+
}
|
|
851
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgComponentOutlet, decorators: [{
|
|
852
|
+
type: Directive,
|
|
853
|
+
args: [{
|
|
854
|
+
selector: '[ngComponentOutlet]',
|
|
855
|
+
exportAs: 'ngComponentOutlet',
|
|
856
|
+
standalone: true,
|
|
857
|
+
}]
|
|
858
|
+
}] });
|
|
859
|
+
|
|
860
|
+
function isComponentType(input) {
|
|
861
|
+
return !!reflectComponentType(input);
|
|
862
|
+
}
|
|
863
|
+
function createAsyncCache(one, injector) {
|
|
864
|
+
const loading = new Map();
|
|
865
|
+
const cached = new Map();
|
|
866
|
+
return (list) => untracked(() => {
|
|
867
|
+
if (!list) {
|
|
868
|
+
return { value: computed(() => undefined) };
|
|
869
|
+
}
|
|
870
|
+
let hasPromise = false;
|
|
871
|
+
const result = (one ? [list] : list).map((item) => {
|
|
872
|
+
if (cached.has(item)) {
|
|
873
|
+
return cached.get(item);
|
|
874
|
+
}
|
|
875
|
+
else if (loading.has(item)) {
|
|
876
|
+
hasPromise = true;
|
|
877
|
+
return loading.get(item);
|
|
878
|
+
}
|
|
879
|
+
const resolved = item;
|
|
880
|
+
const type = resolved.type;
|
|
881
|
+
if (typeof type === 'string' || isComponentType(type)) {
|
|
882
|
+
const result = { ...resolved, type: { component: type } };
|
|
883
|
+
cached.set(item, result);
|
|
884
|
+
return result;
|
|
885
|
+
}
|
|
886
|
+
else if (typeof type === 'function') {
|
|
887
|
+
hasPromise = true;
|
|
888
|
+
const result$$ = type().then((value) => {
|
|
889
|
+
const result = {
|
|
890
|
+
...resolved,
|
|
891
|
+
type: isComponentType(value) ? { component: value } : value,
|
|
892
|
+
};
|
|
893
|
+
cached.set(item, result);
|
|
894
|
+
loading.delete(item);
|
|
895
|
+
return result;
|
|
896
|
+
});
|
|
897
|
+
loading.set(item, result$$);
|
|
898
|
+
return result$$;
|
|
899
|
+
}
|
|
900
|
+
else {
|
|
901
|
+
return resolved;
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
if (hasPromise) {
|
|
905
|
+
return resource({
|
|
906
|
+
loader: async () => (one ? result[0] : Promise.all(result)),
|
|
907
|
+
injector: injector,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
return {
|
|
912
|
+
value: computed(() => (one ? result[0] : result)),
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function initListen(input, control, injector, fn) {
|
|
919
|
+
let init = true;
|
|
920
|
+
return effect(() => {
|
|
921
|
+
const modelValue = control.value$$();
|
|
922
|
+
if (init) {
|
|
923
|
+
if (!deepEqual(modelValue, input)) {
|
|
924
|
+
fn(modelValue);
|
|
925
|
+
}
|
|
926
|
+
init = false;
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
fn(modelValue);
|
|
930
|
+
}
|
|
931
|
+
}, { injector });
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
class AngularFormBuilder extends FormBuilder {
|
|
935
|
+
#globalConfig = inject(PI_VIEW_CONFIG_TOKEN, { optional: true }) ?? undefined;
|
|
936
|
+
afterResolveConfig(rawConfig, config) {
|
|
937
|
+
const field = rawConfig;
|
|
938
|
+
const type = rawConfig.type;
|
|
939
|
+
let componentDefaultConfig;
|
|
940
|
+
let define;
|
|
941
|
+
const mergeStrategy = this.#globalConfig
|
|
942
|
+
?.defaultConfigMergeStrategy;
|
|
943
|
+
if (type) {
|
|
944
|
+
const result = this.#resolveComponent(type);
|
|
945
|
+
define = result.define;
|
|
946
|
+
componentDefaultConfig = result.defaultConfig;
|
|
947
|
+
}
|
|
948
|
+
const directives = this.configMerge([componentDefaultConfig?.directives, field.directives], true, typeof mergeStrategy === 'string'
|
|
949
|
+
? mergeStrategy
|
|
950
|
+
: (mergeStrategy?.directives ??
|
|
951
|
+
NG_CONFIG_DEFAULT_MERGE_STRAGEGY.directives));
|
|
952
|
+
return {
|
|
953
|
+
...config,
|
|
954
|
+
contents: field.contents?.sort((a, b) => a.nodes && b.nodes ? 0 : a.nodes ? -1 : 1),
|
|
955
|
+
directives: directives,
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
#resolveComponent(type) {
|
|
959
|
+
let define;
|
|
960
|
+
let defaultConfig;
|
|
961
|
+
// 查引用
|
|
962
|
+
if (typeof type === 'string') {
|
|
963
|
+
const config = this.#globalConfig?.types?.[type];
|
|
964
|
+
if (!config) {
|
|
965
|
+
throw new Error(`未注册${type}`);
|
|
966
|
+
}
|
|
967
|
+
defaultConfig = config;
|
|
968
|
+
if (Object.keys(config).length) {
|
|
969
|
+
define = {
|
|
970
|
+
...config,
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
// 直接使用视为独立组件,并且selector只有一个
|
|
976
|
+
define = { type };
|
|
977
|
+
}
|
|
978
|
+
return {
|
|
979
|
+
define,
|
|
980
|
+
defaultConfig,
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularFormBuilder, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
984
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularFormBuilder });
|
|
985
|
+
}
|
|
986
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularFormBuilder, decorators: [{
|
|
987
|
+
type: Injectable
|
|
988
|
+
}] });
|
|
989
|
+
|
|
990
|
+
class NgSchemaHandle extends CoreSchemaHandle {
|
|
991
|
+
contents;
|
|
992
|
+
directives;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
class PurePipe {
|
|
996
|
+
transform(fn, ...args) {
|
|
997
|
+
return fn(...args);
|
|
998
|
+
}
|
|
999
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PurePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1000
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: PurePipe, isStandalone: true, name: "pure" });
|
|
1001
|
+
}
|
|
1002
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PurePipe, decorators: [{
|
|
1003
|
+
type: Pipe,
|
|
1004
|
+
args: [{
|
|
1005
|
+
name: 'pure',
|
|
1006
|
+
standalone: true,
|
|
1007
|
+
}]
|
|
1008
|
+
}] });
|
|
1009
|
+
|
|
1010
|
+
const DefaultConvertOptions = {
|
|
1011
|
+
builder: AngularFormBuilder,
|
|
1012
|
+
handle: NgSchemaHandle,
|
|
1013
|
+
};
|
|
1014
|
+
class PiyingView {
|
|
1015
|
+
schema = input.required();
|
|
1016
|
+
model = input(undefined);
|
|
1017
|
+
modelChange = output();
|
|
1018
|
+
options = input();
|
|
1019
|
+
form$$ = computed(() => this.resolvedField$()?.form.control);
|
|
1020
|
+
#lastRF;
|
|
1021
|
+
ngOnChanges(changes) {
|
|
1022
|
+
const rFields = this.#resolvedFields$$();
|
|
1023
|
+
if (this.#lastRF !== rFields || 'model' in changes) {
|
|
1024
|
+
this.#modelChange$$();
|
|
1025
|
+
}
|
|
1026
|
+
this.#lastRF = rFields;
|
|
1027
|
+
}
|
|
1028
|
+
#modelChange$$ = computed(() => {
|
|
1029
|
+
const model = this.model();
|
|
1030
|
+
untracked(() => this.#updateField(model));
|
|
1031
|
+
});
|
|
1032
|
+
#resolvedFields$$ = computed(() => {
|
|
1033
|
+
this.schema();
|
|
1034
|
+
return untracked(() => this.#updateForm());
|
|
1035
|
+
});
|
|
1036
|
+
#injector = inject(Injector);
|
|
1037
|
+
#envInjector = inject(EnvironmentInjector);
|
|
1038
|
+
#builderEnvInjector;
|
|
1039
|
+
resolvedField$ = signal(undefined);
|
|
1040
|
+
#disposeList = [];
|
|
1041
|
+
#updateForm() {
|
|
1042
|
+
this.#clean();
|
|
1043
|
+
// 临时销毁
|
|
1044
|
+
const envInjector = createEnvironmentInjector([], this.#envInjector);
|
|
1045
|
+
this.#builderEnvInjector = envInjector;
|
|
1046
|
+
const result = convert(this.schema(), {
|
|
1047
|
+
...DefaultConvertOptions,
|
|
1048
|
+
...this.options(),
|
|
1049
|
+
injector: envInjector,
|
|
1050
|
+
registerOnDestroy: (fn) => {
|
|
1051
|
+
envInjector.get(DestroyRef).onDestroy(() => {
|
|
1052
|
+
fn();
|
|
1053
|
+
});
|
|
1054
|
+
},
|
|
1055
|
+
});
|
|
1056
|
+
this.resolvedField$.set(result);
|
|
1057
|
+
if (result.form.control) {
|
|
1058
|
+
// 监听初始化,每次field变更会初始化
|
|
1059
|
+
const ref = initListen(this.model(), result.form.control,
|
|
1060
|
+
// 使用envInjector会导致在测试中慢一次检查,生产上可能也会慢一点?
|
|
1061
|
+
this.#injector, (value) => {
|
|
1062
|
+
untracked(() => {
|
|
1063
|
+
if (result.form.control?.valueNoError$$()) {
|
|
1064
|
+
this.modelChange.emit(value);
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
});
|
|
1068
|
+
this.#disposeList.push(() => ref.destroy());
|
|
1069
|
+
}
|
|
1070
|
+
return result;
|
|
1071
|
+
}
|
|
1072
|
+
#clean(isDestoryed = false) {
|
|
1073
|
+
this.#disposeList.forEach((item) => item());
|
|
1074
|
+
this.#disposeList = [];
|
|
1075
|
+
if (!isDestoryed && this.#builderEnvInjector) {
|
|
1076
|
+
this.#builderEnvInjector.destroy();
|
|
1077
|
+
this.#builderEnvInjector = undefined;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
#updateField(model) {
|
|
1081
|
+
if (!this.resolvedField$()) {
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
const field = this.resolvedField$();
|
|
1085
|
+
field.form.control?.updateValue(model);
|
|
1086
|
+
}
|
|
1087
|
+
groupInputsValue = (inputs, fields, fieldTemplateRef) => computed(() => ({
|
|
1088
|
+
...inputs(),
|
|
1089
|
+
fields,
|
|
1090
|
+
fieldTemplateRef,
|
|
1091
|
+
}));
|
|
1092
|
+
resolvedComponent = createAsyncCache(true, this.#injector);
|
|
1093
|
+
// 这里的组件还是不准确,因为type已经改了,
|
|
1094
|
+
resolvedWrapper = createAsyncCache(false, this.#injector);
|
|
1095
|
+
groupHidden = (field) => computed(() => this.#groupHidden(field));
|
|
1096
|
+
#groupHidden(field) {
|
|
1097
|
+
if (field.fieldGroup) {
|
|
1098
|
+
if (!field.fieldGroup().length) {
|
|
1099
|
+
return true;
|
|
1100
|
+
}
|
|
1101
|
+
else {
|
|
1102
|
+
return field.fieldGroup().every((field) => this.#groupHidden(field));
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
else {
|
|
1106
|
+
return !field.define || !!field.renderConfig().hidden;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
ngOnDestroy() {
|
|
1110
|
+
this.#clean(true);
|
|
1111
|
+
}
|
|
1112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingView, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1113
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.3", type: PiyingView, isStandalone: true, selector: "piying-view", inputs: { schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: true, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modelChange: "modelChange" }, usesOnChanges: true, ngImport: i0, template: "<ng-template #dynamicComponent let-field>\n @let renderConfig = field.renderConfig();\n @if (!renderConfig?.hidden) {\n @let typeResource = resolvedComponent | pure: field.define;\n @let type = typeResource.value();\n @let wrappersResource = resolvedWrapper | pure: field.wrappers();\n @let wrappers = wrappersResource.value();\n @if (type) {\n @if (field.fieldGroup) {\n @if (!(groupHidden | pure: field)()) {\n <!-- \u81EA\u5B9A\u4E49group -->\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"\n (\n groupInputsValue\n | pure: field.inputs : field.fieldGroup() : dynamicComponent\n )?.()\n \"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n ></ng-container>\n }\n } @else if (field.fieldArray) {\n <!-- \u81EA\u5B9A\u4E49array -->\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"\n (\n groupInputsValue\n | pure: field.inputs : field.fieldArray() : dynamicComponent\n )?.()\n \"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n ></ng-container>\n } @else {\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"field.inputs()\"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletFormControl]=\"$any(field.form.control)\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n [ngComponentOutletContent]=\"field.contents\"\n ></ng-container>\n }\n }\n }\n</ng-template>\n\n@if (resolvedField$(); as field) {\n <ng-container\n *ngTemplateOutlet=\"dynamicComponent; context: { $implicit: field }\"\n ></ng-container>\n}\n", dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletOutputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletFormControl", "ngComponentOutletWrappers", "ngComponentOutletTopDirectives", "ngComponentOutletDirectives", "ngComponentOutletField"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: PurePipe, name: "pure" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1114
|
+
}
|
|
1115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiyingView, decorators: [{
|
|
1116
|
+
type: Component,
|
|
1117
|
+
args: [{ selector: 'piying-view', imports: [NgComponentOutlet, PurePipe, NgTemplateOutlet], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #dynamicComponent let-field>\n @let renderConfig = field.renderConfig();\n @if (!renderConfig?.hidden) {\n @let typeResource = resolvedComponent | pure: field.define;\n @let type = typeResource.value();\n @let wrappersResource = resolvedWrapper | pure: field.wrappers();\n @let wrappers = wrappersResource.value();\n @if (type) {\n @if (field.fieldGroup) {\n @if (!(groupHidden | pure: field)()) {\n <!-- \u81EA\u5B9A\u4E49group -->\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"\n (\n groupInputsValue\n | pure: field.inputs : field.fieldGroup() : dynamicComponent\n )?.()\n \"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n ></ng-container>\n }\n } @else if (field.fieldArray) {\n <!-- \u81EA\u5B9A\u4E49array -->\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"\n (\n groupInputsValue\n | pure: field.inputs : field.fieldArray() : dynamicComponent\n )?.()\n \"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n ></ng-container>\n } @else {\n <ng-container\n [ngComponentOutlet]=\"type\"\n [ngComponentOutletInputs]=\"field.inputs()\"\n [ngComponentOutletOutputs]=\"field.outputs()\"\n [ngComponentOutletFormControl]=\"$any(field.form.control)\"\n [ngComponentOutletWrappers]=\"wrappers\"\n [ngComponentOutletField]=\"field\"\n [ngComponentOutletDirectives]=\"field.directives\"\n [ngComponentOutletContent]=\"field.contents\"\n ></ng-container>\n }\n }\n }\n</ng-template>\n\n@if (resolvedField$(); as field) {\n <ng-container\n *ngTemplateOutlet=\"dynamicComponent; context: { $implicit: field }\"\n ></ng-container>\n}\n" }]
|
|
1118
|
+
}] });
|
|
1119
|
+
|
|
1120
|
+
class PiWrapperBaseComponent extends BaseComponent {
|
|
1121
|
+
fieldComponentAnchor = viewChild('fieldComponent', {
|
|
1122
|
+
read: ViewContainerRef,
|
|
1123
|
+
});
|
|
1124
|
+
field$$ = inject(PI_VIEW_FIELD_TOKEN);
|
|
1125
|
+
props$$ = computed(() => this.field$$().props());
|
|
1126
|
+
#listen = inject(PI_COMPONENT_LIST_LISTEN);
|
|
1127
|
+
#list = inject(PI_COMPONENT_LIST);
|
|
1128
|
+
createComponent() {
|
|
1129
|
+
const result = super.createComponent(this.#list, this.fieldComponentAnchor());
|
|
1130
|
+
this.#listen.subscribe((list) => {
|
|
1131
|
+
this.update(list);
|
|
1132
|
+
});
|
|
1133
|
+
return result;
|
|
1134
|
+
}
|
|
1135
|
+
ngOnInit() {
|
|
1136
|
+
this.createComponent();
|
|
1137
|
+
}
|
|
1138
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiWrapperBaseComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
1139
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.0.3", type: PiWrapperBaseComponent, isStandalone: true, viewQueries: [{ propertyName: "fieldComponentAnchor", first: true, predicate: ["fieldComponent"], descendants: true, read: ViewContainerRef, isSignal: true }], usesInheritance: true, ngImport: i0 });
|
|
1140
|
+
}
|
|
1141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: PiWrapperBaseComponent, decorators: [{
|
|
1142
|
+
type: Directive
|
|
1143
|
+
}] });
|
|
1144
|
+
|
|
1145
|
+
const rawConfig = rawConfig$1;
|
|
1146
|
+
|
|
1147
|
+
function setDirectives(items) {
|
|
1148
|
+
return rawConfig((field) => {
|
|
1149
|
+
field.directives = items;
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
function patchDirectives(items) {
|
|
1153
|
+
return rawConfig((field) => {
|
|
1154
|
+
field.directives ??= [];
|
|
1155
|
+
field.directives.push(...items);
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
function patchAsyncDirective(fn) {
|
|
1159
|
+
return rawConfig((field) => {
|
|
1160
|
+
mergeHooksFn({
|
|
1161
|
+
fieldResolved: (field) => {
|
|
1162
|
+
field.directives ??= signal([]);
|
|
1163
|
+
const directive = fn(field);
|
|
1164
|
+
const inputs = directive.inputs;
|
|
1165
|
+
let inputs$ = signal({});
|
|
1166
|
+
if (inputs) {
|
|
1167
|
+
inputs$.set(Object.keys(inputs).reduce((obj, key) => {
|
|
1168
|
+
obj[key] = undefined;
|
|
1169
|
+
return obj;
|
|
1170
|
+
}, {}));
|
|
1171
|
+
inputs$ = asyncInputMerge(inputs, inputs$);
|
|
1172
|
+
}
|
|
1173
|
+
const oldDirectives = field.directives;
|
|
1174
|
+
field.directives = linkedSignal(() => [
|
|
1175
|
+
...oldDirectives(),
|
|
1176
|
+
{ ...directive, inputs: inputs$ },
|
|
1177
|
+
]);
|
|
1178
|
+
},
|
|
1179
|
+
}, { position: 'bottom' }, field);
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
class BaseControl {
|
|
1184
|
+
value$ = signal(undefined);
|
|
1185
|
+
emitValue;
|
|
1186
|
+
registerOnChange(fn) {
|
|
1187
|
+
this.emitValue = fn;
|
|
1188
|
+
}
|
|
1189
|
+
/** 同时发射和value变更 */
|
|
1190
|
+
valueChange(value) {
|
|
1191
|
+
this.emitValue?.(value);
|
|
1192
|
+
this.value$.set(value);
|
|
1193
|
+
}
|
|
1194
|
+
writeValue(obj) {
|
|
1195
|
+
this.value$.set(obj ?? undefined);
|
|
1196
|
+
}
|
|
1197
|
+
#touched;
|
|
1198
|
+
registerOnTouched(fn) {
|
|
1199
|
+
this.#touched = fn;
|
|
1200
|
+
}
|
|
1201
|
+
touchedChange() {
|
|
1202
|
+
this.#touched();
|
|
1203
|
+
}
|
|
1204
|
+
disabled$ = signal(false);
|
|
1205
|
+
setDisabledState(isDisabled) {
|
|
1206
|
+
this.disabled$.set(isDisabled);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
* Generated bundle index. Do not edit.
|
|
1212
|
+
*/
|
|
1213
|
+
|
|
1214
|
+
export { AngularFormBuilder, BaseControl, NgSchemaHandle, PI_COMPONENT_INDEX, PI_COMPONENT_LIST, PI_COMPONENT_LIST_LISTEN, PI_VIEW_FIELD_TOKEN, PiWrapperBaseComponent, PiyingView, PiyingViewGroup, PiyingViewGroupBase, patchAsyncDirective, patchDirectives, rawConfig, setDirectives };
|
|
1215
|
+
//# sourceMappingURL=piying-view-angular.mjs.map
|