UNPKG

@zodiac-ui/formula

Version:

Formula is a powerful form generator built for Angular. Inspired by Angular Router, Formula provides a declarative interface for building reactive forms.

1,161 lines (1,145 loc) 33.9 kB
import { Subject } from 'rxjs'; import { startWith, takeUntil } from 'rxjs/operators'; import { InjectionToken, ComponentFactoryResolver, Injector, IterableDiffers, KeyValueDiffers, Renderer2, ViewContainerRef, Directive, EventEmitter, Inject, Input, Optional, Output, SkipSelf, NgModule, ChangeDetectionStrategy, Component, ViewChild } from '@angular/core'; import { FormArray, FormControl, FormGroup, ReactiveFormsModule, NgForm, FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @enum {number} */ const FormulaType = { CONTROL: 0, GROUP: 1, ARRAY: 2, CONTAINER: 3, }; FormulaType[FormulaType.CONTROL] = 'CONTROL'; FormulaType[FormulaType.GROUP] = 'GROUP'; FormulaType[FormulaType.ARRAY] = 'ARRAY'; FormulaType[FormulaType.CONTAINER] = 'CONTAINER'; /** * @abstract */ class FormulaContext { } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const FORMULA = new InjectionToken("FORMULA"); /** @type {?} */ const FORMULA_DIFFER = new InjectionToken("FORMULA_DIFFER"); /** @type {?} */ const FORMULA_OUTLET = new InjectionToken("FORMULA_OUTLET"); /** @type {?} */ const FORMULA_NODE = new InjectionToken("FORMULA_NODE"); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class FormulaRenderer { /** * @param {?} vcr * @param {?} cfr * @param {?} injector */ constructor(vcr, cfr, injector) { this.vcr = vcr; this.cfr = cfr; this.injector = injector; this.refs = new Map(); this.renderer = injector.get(Renderer2); this.destroyed$ = new Subject(); this.destroyed = false; } /** * @param {?} node * @return {?} */ render(node) { /** @type {?} */ const parent = this.injector.get(FORMULA_NODE, null); /** @type {?} */ const resolve = node.formula.resolve; /** @type {?} */ const resolvers = resolve ? Object.getOwnPropertySymbols(resolve) .map((key) => ({ key: key, token: resolve[key], })) .concat(Object.values(resolve).map((key) => ({ key: key, token: resolve[key], }))) : []; /** @type {?} */ const context = { model: node.model, data: node.formula.data, resolve: {}, }; /** @type {?} */ const injector = Injector.create({ parent: this.injector, providers: [ { provide: FormulaContext, useValue: context, }, { provide: FORMULA_NODE, useValue: node, }, ], }); /** @type {?} */ const resolveData = (/** @type {?} */ ({})); if (resolve) { resolvers.forEach(ref => { /** @type {?} */ const resolver = injector.get(ref.token); resolveData[ref.key] = resolver.resolve(context); }); } if (node.formula.component && node !== parent) { /** @type {?} */ const factory = this.cfr.resolveComponentFactory(node.formula.component); /** @type {?} */ const component = this.vcr.createComponent(factory, null, injector); if (node.formula.class) { node.formula.class .split(" ") .forEach(className => this.renderer.addClass(component.location.nativeElement, className)); } this.refs.set(node, component); } else if (node.children) { node.children.forEach(childNode => { /** @type {?} */ const renderer = createRenderer(childNode.formula, injector); renderer.render(childNode); }); } } /** * @return {?} */ destroy() { if (this.destroyed) { throw new Error(`FormulaRenderer was already destroyed.`); } this.refs.forEach(ref => { ref.destroy(); }); this.destroyed$.next(); this.destroyed$.complete(); this.destroyed = true; } } class FormulaArrayRenderer extends FormulaRenderer { /** * @param {?} vcr * @param {?} cfr * @param {?} injector * @param {?} differs */ constructor(vcr, cfr, injector, differs) { super(vcr, cfr, injector); this.differ = differs.find([]).create(); } /** * @param {?} node * @return {?} */ addChild(node) { /** @type {?} */ const renderer = createRenderer(node.formula, this.injector); renderer.render(node); this.refs.set(node, renderer.refs.get(node)); } /** * @param {?} node * @param {?} index * @return {?} */ moveChild(node, index) { /** @type {?} */ const child = this.refs.get(node); this.vcr.move(child.hostView, index); } /** * @param {?} node * @return {?} */ removeChild(node) { /** @type {?} */ const child = this.refs.get(node); child.destroy(); this.refs.delete(node); } /** * @param {?} node * @return {?} */ render(node) { /** @type {?} */ const parent = this.injector.get(FORMULA_NODE, null); /** @type {?} */ const injector = Injector.create({ parent: this.injector, providers: [ { provide: FormulaContext, useValue: { model: node.model, data: node.formula.data, resolve: {}, }, }, { provide: FORMULA, useValue: node.formula, }, { provide: FORMULA_NODE, useValue: node, }, ], }); if (node.formula.component && node !== parent) { /** @type {?} */ const factory = this.cfr.resolveComponentFactory(node.formula.component); /** @type {?} */ const component = this.vcr.createComponent(factory, null, injector); if (node.formula.class) { node.formula.class .split(" ") .forEach(className => this.renderer.addClass(component.location.nativeElement, className)); } this.refs.set(node, component); } else { node.model.valueChanges.pipe(startWith(null)).subscribe(() => { /** @type {?} */ const diff = this.differ.diff(node.children); if (diff) { diff.forEachRemovedItem(record => { this.removeChild(record.item); }); diff.forEachMovedItem(record => { this.moveChild(record.item, record.currentIndex); }); diff.forEachAddedItem(record => { this.addChild(record.item); }); } }); } } } class FormulaGroupRenderer extends FormulaRenderer { /** * @param {?} vcr * @param {?} cfr * @param {?} injector * @param {?} differs */ constructor(vcr, cfr, injector, differs) { super(vcr, cfr, injector); this.differ = differs.find({}).create(); } } class FormulaContainerRenderer extends FormulaRenderer { /** * @param {?} vcr * @param {?} cfr * @param {?} injector */ constructor(vcr, cfr, injector) { super(vcr, cfr, injector); this.differ = null; } /** * @param {?} node * @return {?} */ render(node) { /** @type {?} */ const parent = this.injector.get(FORMULA_NODE, null); /** @type {?} */ const injector = Injector.create({ parent: this.injector, providers: [ { provide: FormulaContext, useValue: { model: node.model, data: node.formula.data, resolve: {}, }, }, { provide: FORMULA_NODE, useValue: node, }, ], }); if (node.formula.component && node !== parent) { /** @type {?} */ const factory = this.cfr.resolveComponentFactory(node.formula.component); /** @type {?} */ const component = this.vcr.createComponent(factory, null, injector); if (node.formula.class) { node.formula.class .split(" ") .forEach(className => this.renderer.addClass(component.location.nativeElement, className)); } this.refs.set(node, component); } else { node.children.forEach(childNode => { /** @type {?} */ const renderer = createRenderer(childNode.formula, injector); renderer.render(childNode); }); } } } class FormulaDefaultRenderer extends FormulaRenderer { /** * @param {?} vcr * @param {?} cfr * @param {?} injector */ constructor(vcr, cfr, injector) { super(vcr, cfr, injector); this.differ = null; } } /** * @param {?} formula * @return {?} */ function provideRenderer(formula) { /** @type {?} */ const deps = [ViewContainerRef, ComponentFactoryResolver, Injector, FORMULA_DIFFER]; switch (formula.type) { case FormulaType.GROUP: { return { provide: FormulaGroupRenderer, useClass: FormulaGroupRenderer, deps: deps, }; } case FormulaType.ARRAY: { return { provide: FormulaArrayRenderer, useClass: FormulaArrayRenderer, deps: deps, }; } case FormulaType.CONTAINER: { return { provide: FormulaContainerRenderer, useClass: FormulaContainerRenderer, deps: deps, }; } default: { return { provide: FormulaDefaultRenderer, useClass: FormulaDefaultRenderer, deps: deps, }; } } } /** * @param {?} formula * @param {?} injector * @return {?} */ function provideDiffer(formula, injector) { if (formula.type === FormulaType.ARRAY) { return { provide: FORMULA_DIFFER, useValue: injector.get(IterableDiffers), }; } if (formula.type === FormulaType.GROUP) { return { provide: FORMULA_DIFFER, useValue: injector.get(KeyValueDiffers), }; } return { provide: FORMULA_DIFFER, useValue: null, }; } /** * @param {?} formula * @param {?} parentInjector * @return {?} */ function createRenderer(formula, parentInjector) { /** @type {?} */ const DIFFER = provideDiffer(formula, parentInjector); /** @type {?} */ const RENDERER = provideRenderer(formula); /** @type {?} */ const injector = Injector.create({ parent: parentInjector, providers: [ RENDERER, DIFFER, { provide: FORMULA, useValue: formula, }, ], }); if (formula.type === FormulaType.ARRAY) { return injector.get(FormulaArrayRenderer); } if (formula.type === FormulaType.GROUP) { return injector.get(FormulaGroupRenderer); } if (formula.type === FormulaType.CONTAINER) { return injector.get(FormulaContainerRenderer); } return injector.get(FormulaDefaultRenderer); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @param {?} model * @return {?} */ function isFormArray(model) { return model && model["removeAt"]; } /** * @param {?} model * @return {?} */ function isFormGroup(model) { return model && model["removeControl"]; } /** * @param {?} model * @return {?} */ function isFormControl(model) { return model && !isFormGroup(model) && !isFormArray(model); } /** * @param {?} formula * @param {?} parent * @param {?} control * @return {?} */ function setParentControl(formula, parent, control) { control.setParent(parent); if (isFormArray(parent)) { parent.push(control); } if (isFormGroup(parent)) { parent.setControl(formula.name, control); } } /** * @param {?} formula * @param {?} parent * @return {?} */ function createModel(formula, parent) { /** @type {?} */ let model; if (isFormControl(parent)) { return parent; } switch (formula.type) { case FormulaType.CONTROL: { model = new FormControl(); break; } case FormulaType.GROUP: { model = new FormGroup({}); break; } case FormulaType.ARRAY: { model = new FormArray([]); break; } default: { return parent; } } if (isFormGroup(parent) || isFormArray(parent)) { setParentControl(formula, parent, model); } return model; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class FormulaNode { } class FormulaArrayNode { /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children */ constructor(formula, model, parent, children) { this.parent = parent; this.model = model; this.formula = formula; this.children = children; } /** * @param {?} values * @return {?} */ setValue(values) { /** @type {?} */ const len = this.model.controls.length; values.forEach((value, index) => { if (index < len) { this.children[index].setValue(value); } else { /** @type {?} */ const formula = this.formula.children[index % this.formula.children.length]; /** @type {?} */ const model = createModel(formula, this.model); /** @type {?} */ const node = createFormulaNode(formula, model, this); node.setValue(value); this.children.push(node); } }); /** @type {?} */ const valLen = values.length; this.children.forEach((child, index) => { if (index >= valLen) { this.model.removeAt(index); } }); } } class FormulaControlNode { /** * @param {?} formula * @param {?} model * @param {?} parent */ constructor(formula, model, parent) { this.formula = formula; this.model = model; this.parent = parent; this.children = null; } /** * @param {?} value * @return {?} */ setValue(value) { this.model.setValue(value); } } class FormulaContainerNode { /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children */ constructor(formula, model, parent, children) { this.parent = parent; this.model = model; this.formula = formula; this.children = children; if (!parent) { throw new Error("Containers can not be used as a root node"); } if (children.length > 1) { throw new Error(`Containers can only have one child`); } } /** * @param {?} value * @return {?} */ setValue(value) { if (this.children) { this.children[0].setValue(value); } } } class FormulaGroupNode { /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children */ constructor(formula, model, parent, children) { this.parent = parent; this.model = model; this.formula = formula; this.children = children; } /** * @param {?} value * @return {?} */ setValue(value) { this.children.forEach(child => { child.setValue(value[child.formula.name]); }); } } /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children * @return {?} */ function createGroupNode(formula, model, parent, children) { return new FormulaGroupNode(formula, model, parent, children); } /** * @param {?} formula * @param {?} model * @param {?} parent * @return {?} */ function createControlNode(formula, model, parent) { return new FormulaControlNode(formula, model, parent); } /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children * @return {?} */ function createArrayNode(formula, model, parent, children) { return new FormulaArrayNode(formula, model, parent, children); } /** * @param {?} formula * @param {?} model * @param {?} parent * @param {?} children * @return {?} */ function createContainerNode(formula, model, parent, children) { return new FormulaContainerNode(formula, model, parent, children); } /** * @param {?} formula * @param {?} model * @param {?} parent * @return {?} */ function createFormulaNode(formula, model, parent) { /** @type {?} */ let children = []; switch (formula.type) { case FormulaType.CONTROL: { return createControlNode(formula, model, parent); } case FormulaType.GROUP: { children = formula.children.map(childFormula => { /** @type {?} */ const childModel = createModel(childFormula, model); return createFormulaNode(childFormula, childModel, parent); }); return createGroupNode(formula, model, parent, children); } case FormulaType.ARRAY: { return createArrayNode(formula, model, parent, children); } default: { children = formula.children.map(childFormula => { /** @type {?} */ const childModel = createModel(childFormula, model); return createFormulaNode(childFormula, childModel, parent); }); return createContainerNode(formula, model, parent, children); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Creates a {link FormulaNode} tree that is used to render a form. `FormulaDirective` provides a declarative * approach for dynamic forms creation * * `FormulaDirective` requires a {link Formula}, if a falsy value is set the view will clear and the * form will get destroyed. * * ### Usage * * The simplest case is a formula with a single field. * * ```ts * \@Component({ * selector: "z-example", * template: ` * <z-formula [formula]="formula" [value]="value"></z-formula> * `, * }) * export class ExampleComponent { * value = { * exampleText: null * } * formula: Formula = { * type: FormulaType.CONTROL, * name: "exampleText", * component: TextFieldComponent, * data: { * label: "Example Text", * placeholder: "Type text here" * }, * } * } * ``` * * In this example we are declaring a `formula` that contains a single form control called * `exampleText`. It is rendered with a component, which is up to the user to implement. The * concept is similar to that of Angular route components. For example, the `TextFieldComponent` * may be as simple as this: * * ```ts * \@Component({ * selector: "z-text-field", * template: ` * <label [innerHTML]="ctx.data.label"></label> * <input [formControl]="ctx.model" /> * `, * }) * export class TextFieldComponent { * constructor(public ctx: FormulaContext) {} * } * ``` * * Every Formula component receives a {link FormulaContext} containing the model, data and resolve * data defined for that node in the `FormulaNode` tree * */ class FormulaDirective { /** * @param {?} injector * @param {?} vcr * @param {?} parent */ constructor(injector, vcr, parent) { this.valueChanges = new EventEmitter(); this.statusChanges = new EventEmitter(); this.submit = new EventEmitter(); this.injector = Injector.create({ parent: injector, providers: [ { provide: ViewContainerRef, useValue: vcr, }, ], }); this.parent = parent; this.root = parent ? parent.root : this; } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes.formula) { if (!changes.formula.isFirstChange()) { this.renderer.destroy(); } if (this.formula) { this.renderer = createRenderer(this.formula, this.injector); this.render(); } } if (changes.value) { this.setValue(this.value); } } /** * @return {?} */ ngOnDestroy() { if (this.renderer) { this.renderer.destroy(); } } /** * @param {?} value * @return {?} */ setValue(value) { if (this.node) { this.node.setValue(value); } } /** * @param {?} form * @return {?} */ setForm(form) { if (this.form) { throw new Error("Only one top level NgForm is allowed"); } this.form = form; form.ngSubmit.subscribe(this.submit); } /** * @private * @return {?} */ render() { this.model = createModel(this.formula, this.parent ? this.parent.node.model : null); this.node = createFormulaNode(this.formula, this.model, this.parent ? this.parent.node : null); this.renderer.render(this.node); this.model.valueChanges .pipe(takeUntil(this.renderer.destroyed$)) .subscribe(this.valueChanges); this.model.statusChanges .pipe(takeUntil(this.renderer.destroyed$)) .subscribe(this.statusChanges); } } FormulaDirective.decorators = [ { type: Directive, args: [{ selector: "z-formula, [zFormula]", providers: [ { provide: FORMULA_OUTLET, useExisting: FormulaDirective, }, ], },] } ]; /** @nocollapse */ FormulaDirective.ctorParameters = () => [ { type: Injector }, { type: ViewContainerRef }, { type: undefined, decorators: [{ type: SkipSelf }, { type: Optional }, { type: Inject, args: [FORMULA_OUTLET,] }] } ]; FormulaDirective.propDecorators = { formula: [{ type: Input }], value: [{ type: Input }], valueChanges: [{ type: Output }], statusChanges: [{ type: Output }], submit: [{ type: Output }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const mapChildren = child => (typeof child === "function" ? child() : child); /** * @param {?} config * @return {?} */ function group(config) { return function (...children) { return Object.assign({ type: FormulaType.GROUP, children: children.map(mapChildren) }, config, { data: config.data || {} }); }; } /** * @param {?=} config * @return {?} */ function control(config) { return function () { return Object.assign({ type: FormulaType.CONTROL }, config, { data: config.data || {} }); }; } /** * @param {?} config * @return {?} */ function array(config) { return function (...children) { return Object.assign({ type: FormulaType.ARRAY, children: children.map(mapChildren) }, config, { data: config.data || {} }); }; } /** * @param {?} config * @return {?} */ function container(config) { return function (...children) { return Object.assign({ type: FormulaType.CONTAINER, children: children.map(mapChildren) }, config, { data: config.data || {} }); }; } /** * @template T * @param {?} buildFn * @param {?} opts * @return {?} */ function extend(buildFn, opts) { return function (...args) { /** @type {?} */ const formula = buildFn(...args); Object.getOwnPropertyNames(opts).forEach(key => { /** @type {?} */ const source = formula[key]; /** @type {?} */ const value = opts[key]; if (Array.isArray(value)) { formula[key] = [...source, ...value]; } else if (typeof value === "object" && value !== null) { formula[key] = Object.assign({}, source, value); } else { formula[key] = value; } }); return formula; }; } class FormulaBuilder { constructor() { this.group = group; this.array = array; this.container = container; this.control = control; this.extend = extend; } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class FormulaModule { } FormulaModule.decorators = [ { type: NgModule, args: [{ imports: [ReactiveFormsModule], declarations: [FormulaDirective], exports: [FormulaDirective], providers: [FormulaBuilder], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Renders the current {link FormulaNode} in the tree. Being functionally similar to `router-outlet`, * use this directive inside Formula components to continue rendering child nodes of the current * branch in the node tree. * * ### Usage * * Anywhere in your Formula component template, place a single `z-formula-outlet` tag. * * ```ts * \@Component({ * selector: 'z-form-container', * template: ` * <form> * <z-formula-outlet></z-formula-outlet> * </form> * `, * }) * export class FormContainerComponent {} * ``` * f * In many cases you probably want a native `form` element as the top level component in your form. * This is a minimal way to achieve that. All child nodes will now be rendered between the `<form>` * tags. */ class FormulaOutletDirective { /** * @param {?} injector * @param {?} vcr * @param {?} formula * @param {?} node * @param {?} parent */ constructor(injector, vcr, formula, node, parent) { this.injector = Injector.create({ parent: injector, providers: [ { provide: ViewContainerRef, useValue: vcr, }, ], }); this.parent = parent; this.root = parent.root; this.node = node; this.renderer = createRenderer(formula, injector); } /** * @return {?} */ ngOnInit() { this.render(); } /** * @return {?} */ ngOnDestroy() { this.renderer.destroy(); } /** * @param {?} value * @return {?} */ setValue(value) { this.node.setValue(value); } /** * @private * @return {?} */ render() { this.renderer.render(this.node); } } FormulaOutletDirective.decorators = [ { type: Directive, args: [{ selector: "z-formula-outlet, [zFormulaOutlet]", providers: [ { provide: FORMULA_OUTLET, useExisting: FormulaOutletDirective, }, ], },] } ]; /** @nocollapse */ FormulaOutletDirective.ctorParameters = () => [ { type: Injector }, { type: ViewContainerRef }, { type: undefined, decorators: [{ type: Inject, args: [FORMULA,] }] }, { type: FormulaNode, decorators: [{ type: Inject, args: [FORMULA_NODE,] }] }, { type: undefined, decorators: [{ type: SkipSelf }, { type: Inject, args: [FORMULA_OUTLET,] }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class FormulaOutletModule { } FormulaOutletModule.decorators = [ { type: NgModule, args: [{ imports: [], declarations: [FormulaOutletDirective], exports: [FormulaOutletDirective], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class FormComponent { /** * @param {?} ctx * @param {?} outlet * @param {?} parent */ constructor(ctx, outlet, parent) { if (isFormGroup(ctx.model) || isFormArray(ctx.model)) { this.model = ctx.model; } else { throw new Error("<z-form> only accepts FormGroup or FormArray"); } this.ngFormOptions = ctx.data.ngFormOptions || {}; this.outlet = outlet.root; this.parent = parent; } /** * @return {?} */ ngAfterViewInit() { if (!this.parent) { this.outlet.setForm(this.form); } } } FormComponent.decorators = [ { type: Component, args: [{ selector: "z-form", template: ` <ng-container *ngIf="parent; then: ngForm; else: form"></ng-container> <ng-template #form> <form [ngFormOptions]="ngFormOptions"> <ng-container [ngTemplateOutlet]="content"></ng-container> </form> </ng-template> <ng-template #ngForm> <ng-form [ngFormOptions]="ngFormOptions"> <ng-container [ngTemplateOutlet]="content"></ng-container> </ng-form> </ng-template> <ng-template #content> <ng-content></ng-content> </ng-template> `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%}"] }] } ]; /** @nocollapse */ FormComponent.ctorParameters = () => [ { type: FormulaContext }, { type: undefined, decorators: [{ type: Inject, args: [FORMULA_OUTLET,] }] }, { type: FormComponent, decorators: [{ type: Optional }, { type: SkipSelf }] } ]; FormComponent.propDecorators = { form: [{ type: ViewChild, args: [NgForm,] }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class FormModule { } FormModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, FormsModule], declarations: [FormComponent], entryComponents: [FormComponent], exports: [FormComponent], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { FormulaModule, FORMULA, FORMULA_DIFFER, FORMULA_OUTLET, FORMULA_NODE, FormulaDirective, FormulaType, FormulaContext, FormulaOutletModule, FormulaOutletDirective, FormModule, FormComponent, group, control, array, container, extend, FormulaBuilder, FormulaNode as ɵa }; //# sourceMappingURL=zodiac-ui-formula.js.map