UNPKG

@uiowa/uiowa-mfk

Version:

mfk, uiowa-mfk, uiowa-favorite-mfk, mfk-string

544 lines (531 loc) 26.4 kB
import * as i0 from '@angular/core'; import { EventEmitter, ViewChildren, Output, Input, ChangeDetectionStrategy, Component, Pipe, NgModule } from '@angular/core'; import * as i3 from '@uiowa/digit-only'; import { DigitOnlyDirective } from '@uiowa/digit-only'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i2 from '@angular/forms'; import { FormsModule } from '@angular/forms'; class MfkFieldName { static FUND = 'fund'; static ORG = 'org'; static DEPT = 'dept'; static SUBDEPT = 'subdept'; static GRANTPGM = 'grantpgm'; static IACT = 'iact'; static OACT = 'oact'; static DACT = 'dact'; static FN = 'fn'; static CCTR = 'cctr'; static BRF = 'brf'; } /** * Options for MFK field. * * allows to set field default value, set readonly attribute, set validation regex pattern. Example usage: * * ```typescript * new MfkFieldOption(MfkFieldName.IACT, '6218') * new MfkFieldOption(MfkFieldName.IACT, '6218', true) * new MfkFieldOption(MfkFieldName.BRF) * ``` */ class MfkFieldOption { name; defaultValue; readonly; valuePattern; label; width; length; numericRegex = '^[0-9]+$'; /** * Options for MFK field. * * allows to set field default value, set readonly attribute, set validation regex pattern. Example usage: * * ```typescript * new MfkFieldOption(MfkFieldName.IACT, '6218') * new MfkFieldOption(MfkFieldName.IACT, '6218', true) * new MfkFieldOption(MfkFieldName.BRF) * ``` * * @param name (Required) the input field name. Use MfkFieldName type to get a proper value. * @param defaultValue (Optional) set a default value for this field. Default: ''. * @param readonly (Optional) set to true if the input field is readonly. Default: false. * @param valuePattern (Optional) set a regex for this field. Default: '^[0-9]+$'. */ constructor(name, defaultValue = '', readonly = false, valuePattern = '^[0-9]+$') { this.name = name; this.defaultValue = defaultValue; this.readonly = readonly; this.valuePattern = valuePattern; switch (name) { case MfkFieldName.FUND: this.label = 'Fund'; this.length = 3; break; case MfkFieldName.ORG: this.label = 'Org'; this.length = 2; break; case MfkFieldName.DEPT: this.label = 'Dept'; this.length = 4; break; case MfkFieldName.SUBDEPT: this.label = 'Subdept'; this.length = 5; break; case MfkFieldName.GRANTPGM: this.label = `Grant/Pgm`; this.length = 8; break; case MfkFieldName.IACT: this.label = 'Iact'; this.length = 4; break; case MfkFieldName.OACT: this.label = 'Oact'; this.length = 3; break; case MfkFieldName.DACT: this.label = 'Dact'; this.length = 5; break; case MfkFieldName.FN: this.label = 'Fn'; this.length = 2; break; case MfkFieldName.CCTR: this.label = 'Cctr'; this.length = 4; break; case MfkFieldName.BRF: this.label = 'Brf'; this.length = 2; break; default: throw new Error(`MFK field name [${name.toUpperCase()}] is invalid.`); } this.width = this.length * 0.65 + 0.75; if (!valuePattern) { valuePattern = this.numericRegex; } if (this.readonly) { if (!this.defaultValue) { throw new Error(`Default value for readonly field [${name.toUpperCase()}] is required.`); } return; // if readonly, then don't validate default value } if (defaultValue) { if (defaultValue.length !== this.length) { throw new Error(`The default value [${defaultValue}] for ${name.toUpperCase()} is not ${this.length} digits long.`); } let reg = new RegExp(this.numericRegex); if (!reg.test(defaultValue)) { throw new Error(`The default value [${defaultValue}] for ${name.toUpperCase()} is not a number.`); } if (valuePattern !== this.numericRegex) { reg = new RegExp(valuePattern); if (!reg.test(defaultValue)) { throw new Error(`The default value [${defaultValue}] for ${name.toUpperCase()} doesn't match RegEx "${valuePattern}".`); } } } } } class MfkString { mfkString; /** * MFK parsed from a string. Default value is an empty object. */ mfk = {}; isValidMfk = false; /** * construct an MFK String and build an MFK object. Default MFK object is an empty object. * @param mfkString string. The constructor will strip out non-digit characters. The string length must be longer than 40. */ constructor(mfkString) { this.mfkString = mfkString; const s = mfkString.replace(/\D/g, ''); if (s && s.length >= 40) { this.mfk.fund = s.substring(0, 3); this.mfk.org = s.substring(3, 5); this.mfk.dept = s.substring(5, 9); this.mfk.subdept = s.substring(9, 14); this.mfk.grantpgm = s.substring(14, 22); this.mfk.iact = s.substring(22, 26); this.mfk.oact = s.substring(26, 29); this.mfk.dact = s.substring(29, 34); this.mfk.fn = s.substring(34, 36); this.mfk.cctr = s.substring(36, 40); if (s.length >= 42) { this.mfk.brf = s.substring(40, 42); } this.isValidMfk = true; } } } /** * checks the equality of two Mfk objects * @param mfk1 an Mfk object * @param mfk2 an Mfk object */ function areEqual(mfk1, mfk2) { if (!mfk1 || !mfk2) { return false; } if (Object.keys(mfk1).length !== Object.keys(mfk2).length) { return false; } for (const k of Object.keys(mfk1)) { if (mfk1[k] !== mfk2[k]) { return false; } } return true; } /** * converts an Mfk object to a string by joining 10 fields with '-' symbol. * @param mfk An Mfk object */ function stringify(mfk) { if (!mfk) { return ''; } const s = Object.keys(mfk) .filter((k) => k !== MfkFieldName.BRF) .map((k) => mfk[k]) .join('-'); return s; } /** * creates an empty Mfk object with all 10 fields being empty string */ function emptyMfk() { return { fund: '', org: '', dept: '', subdept: '', grantpgm: '', iact: '', oact: '', dact: '', fn: '', cctr: '', }; } /** * checks if an Mfk object is in a valid format */ function validFormat(mfk) { var mfkString = stringify(mfk); if (mfkString.length !== 49) { return false; } if (mfk.brf && mfk.brf.length !== 2) { return false; } return true; } /** * checks if each field of an Mfk object is in a valid format * returns an array of error messages * If the format is valid, then the returning array is empty. */ function validateStructure(mfk) { const result = []; if (mfk.fund?.length !== 3) { result.push(`Invalid Fund: Length is incorrect (must be 3 digits)`); } if (mfk.org?.length !== 2) { result.push(`Invalid Org: Length is incorrect (must be 2 digits)`); } if (mfk.dept?.length !== 4) { result.push(`Invalid Dept: Length is incorrect (must be 4 digits)`); } if (mfk.subdept?.length !== 5) { result.push(`Invalid Subdept: Length is incorrect (must be 5 digits)`); } if (mfk.grantpgm?.length !== 8) { result.push(`Invalid Grant/Pgm: Length is incorrect (must be 8 digits)`); } if (mfk.iact?.length !== 4) { result.push(`Invalid Iact: Length is incorrect (must be 4 digits)`); } if (mfk.oact?.length !== 3) { result.push(`Invalid Oact: Length is incorrect (must be 3 digits)`); } if (mfk.dact?.length !== 5) { result.push(`Invalid Dact: Length is incorrect (must be 5 digits)`); } if (mfk.fn?.length !== 2) { result.push(`Invalid Fn: Length is incorrect (must be 2 digits)`); } if (mfk.cctr?.length !== 4) { result.push(`Invalid Cctr: Length is incorrect (must be 4 digits)`); } if (mfk.brf && mfk.brf.length !== 2) { result.push(`Invalid Brf: Length is incorrect (must be 2 digits)`); } return result; } /** * Convert a string to an MFK object * @param mfkString MFK string * @returns MFK object */ function toMfk(mfkString) { var s = new MfkString(mfkString); return s.mfk; } class MfkInputComponent { _mfk = emptyMfk(); set mfk(mfk) { mfk = Object.assign(emptyMfk(), mfk); this.options .filter((o) => o.defaultValue) .forEach((o) => { mfk[o.name] = mfk[o.name] || o.defaultValue; }); this.options .filter((o) => o.readonly) .forEach((o) => { mfk[o.name] = o.defaultValue; }); this._mfk = mfk; } get mfk() { return this._mfk; } options = []; mfkChange = new EventEmitter(); mfkInputFields; elementId = 'mfk-container_'; elementName = 'mfk-container_'; constructor(el) { const rand = Math.random().toString(36).substring(2); this.elementId += el.nativeElement.getAttribute('id') || el.nativeElement.getAttribute('name') || rand; this.elementName += el.nativeElement.getAttribute('name') || el.nativeElement.getAttribute('id') || rand; } ngOnChanges(changes) { if (changes['mfk'] && changes['mfk'].currentValue) { if (!areEqual(changes['mfk'].previousValue, changes['mfk'].currentValue)) { this.mfk = changes['mfk'].currentValue; this.mfkChange.emit(this.mfk); } } if (changes['options'] || !this.options.length) { this.options = this.mergeOptions(changes['options']?.currentValue); this.mfk = this.mfk; this.mfkChange.emit(this.mfk); } } ngOnInit() { } paste(e) { const pastedInput = e.clipboardData?.getData('text/plain').replace(/\D/g, '') ?? ''; // get a digit-only string if (!pastedInput) { return; } if (pastedInput.length >= 40) { const mfkString = new MfkString(pastedInput); if (mfkString.isValidMfk && !areEqual(this.mfk, mfkString.mfk)) { this.mfk = mfkString.mfk; this.originalMfk = stringify(this.mfk); this.mfkChange.emit(this.mfk); } } } onKeyup(e) { if (this.originalMfk !== stringify(this.mfk)) { this.mfkChange.emit(this.mfk); } if (isNaN(Number(e.key))) { return; // only numbers can trigger auto jump feature. } const target = e.target; const fieldName = target.name; if (this.mfk[fieldName]?.length === target.maxLength) { // auto jump to the next input field when current field is full const currentInputFieldIndex = this.options.findIndex((o) => o.name === fieldName); for (let i = currentInputFieldIndex + 1; i < this.options.length; i++) { if (this.options[i].readonly) { continue; } const nextInputField = this.mfkInputFields.find((v) => v.el.nativeElement['name'] === this.options[i].name); nextInputField?.el.nativeElement.focus(); break; } } } originalMfk = ''; onKeydown(e) { this.originalMfk = stringify(this.mfk); const target = e.target; const fieldName = target.name; // handle "tab" key --> auto fill '0's if the input field has not completed if (e.key === 'Tab') { if (target.readOnly) { return; } while (this.mfk[fieldName].length < target.maxLength) { this.mfk[fieldName] = this.mfk[fieldName].concat('0'); } } // handle "backspace" key if ((e.key === 'Backspace' || e.code === 'Backspace') && this.mfk[fieldName]?.length === 0) { const currentInputFieldIndex = this.options.findIndex((o) => o.name === fieldName); // auto jump to the previous input field when current field is empty for (let i = currentInputFieldIndex - 1; i >= 0; i--) { if (this.options[i].readonly) { continue; } const prevInputField = this.mfkInputFields.find((v) => v.el.nativeElement['name'] === this.options[i].name); prevInputField?.el.nativeElement.focus(); break; } } } mergeOptions(options = []) { const result = [ new MfkFieldOption(MfkFieldName.FUND), new MfkFieldOption(MfkFieldName.ORG), new MfkFieldOption(MfkFieldName.DEPT), new MfkFieldOption(MfkFieldName.SUBDEPT), new MfkFieldOption(MfkFieldName.GRANTPGM), new MfkFieldOption(MfkFieldName.IACT), new MfkFieldOption(MfkFieldName.OACT), new MfkFieldOption(MfkFieldName.DACT), new MfkFieldOption(MfkFieldName.FN), new MfkFieldOption(MfkFieldName.CCTR), ]; if (options && options.length > 0) { for (const option of options) { const fieldOption = result.find((o) => o.name === option.name); if (fieldOption) { const index = result.indexOf(fieldOption); result[index] = option; } else { result.push(option); } } } return result; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkInputComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: MfkInputComponent, isStandalone: false, selector: "uiowa-mfk-input", inputs: { mfk: "mfk", options: "options" }, outputs: { mfkChange: "mfkChange" }, viewQueries: [{ propertyName: "mfkInputFields", predicate: DigitOnlyDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<form\r\n id=\"{{ elementId }}\"\r\n name=\"{{ elementName }}\"\r\n [attr.name]=\"elementName\"\r\n class=\"mfk-container\"\r\n>\r\n <div class=\"mfk-field\" *ngFor=\"let option of options\">\r\n <label for=\"{{ elementId + option.name }}\">\r\n {{ option.label }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n id=\"{{ elementId + option.name }}\"\r\n name=\"{{ option.name }}\"\r\n [attr.name]=\"option.name\"\r\n [style.width.rem]=\"option.width\"\r\n [attr.aria-label]=\"option.name\"\r\n [attr.maxlength]=\"option.length\"\r\n [readOnly]=\"option.readonly\"\r\n [(ngModel)]=\"mfk[option.name]\"\r\n (paste)=\"paste($event)\"\r\n (keyup)=\"onKeyup($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n inputmode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n digitOnly\r\n />\r\n </div>\r\n</form>\r\n", styles: [":host{display:inline-flex}.mfk-field{display:inline-flex;flex-direction:column;vertical-align:middle;text-align:center;margin-right:.25rem}.mfk-field label{font-size:.625rem;margin-bottom:0;white-space:nowrap}.mfk-field input{display:block;padding:.375rem!important;font-size:1rem;font-weight:400;font-style:normal;font-variant:normal;text-align:center;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.mfk-field input:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.mfk-field input:disabled,.mfk-field input[readonly]{background-color:#e9ecef;opacity:1}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.DigitOnlyDirective, selector: "[digitOnly]", inputs: ["decimal", "decimalSeparator", "allowNegatives", "allowPaste", "negativeSign", "min", "max", "pattern"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkInputComponent, decorators: [{ type: Component, args: [{ selector: 'uiowa-mfk-input', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<form\r\n id=\"{{ elementId }}\"\r\n name=\"{{ elementName }}\"\r\n [attr.name]=\"elementName\"\r\n class=\"mfk-container\"\r\n>\r\n <div class=\"mfk-field\" *ngFor=\"let option of options\">\r\n <label for=\"{{ elementId + option.name }}\">\r\n {{ option.label }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n id=\"{{ elementId + option.name }}\"\r\n name=\"{{ option.name }}\"\r\n [attr.name]=\"option.name\"\r\n [style.width.rem]=\"option.width\"\r\n [attr.aria-label]=\"option.name\"\r\n [attr.maxlength]=\"option.length\"\r\n [readOnly]=\"option.readonly\"\r\n [(ngModel)]=\"mfk[option.name]\"\r\n (paste)=\"paste($event)\"\r\n (keyup)=\"onKeyup($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n inputmode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n digitOnly\r\n />\r\n </div>\r\n</form>\r\n", styles: [":host{display:inline-flex}.mfk-field{display:inline-flex;flex-direction:column;vertical-align:middle;text-align:center;margin-right:.25rem}.mfk-field label{font-size:.625rem;margin-bottom:0;white-space:nowrap}.mfk-field input{display:block;padding:.375rem!important;font-size:1rem;font-weight:400;font-style:normal;font-variant:normal;text-align:center;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.mfk-field input:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.mfk-field input:disabled,.mfk-field input[readonly]{background-color:#e9ecef;opacity:1}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { mfk: [{ type: Input }], options: [{ type: Input }], mfkChange: [{ type: Output }], mfkInputFields: [{ type: ViewChildren, args: [DigitOnlyDirective] }] } }); class MfkStringComponent { mfk = null; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkStringComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: MfkStringComponent, isStandalone: false, selector: "uiowa-mfk-string", inputs: { mfk: "mfk" }, ngImport: i0, template: "@if(mfk){\r\n<span>\r\n <span>{{ mfk.fund }}</span>\r\n <span>-{{ mfk.org }}</span>\r\n <span>-{{ mfk.dept }}</span>\r\n <span>-{{ mfk.subdept }}</span>\r\n <span>-{{ mfk.grantpgm }}</span>\r\n <span>-{{ mfk.iact }}</span>\r\n <span>-{{ mfk.oact }}</span>\r\n <span>-{{ mfk.dact }}</span>\r\n <span>-{{ mfk.fn }}</span>\r\n <span>-{{ mfk.cctr }}</span>\r\n @if(mfk.brf){ <span>-{{ mfk.brf }}</span> }\r\n</span>\r\n}\r\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkStringComponent, decorators: [{ type: Component, args: [{ selector: 'uiowa-mfk-string', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if(mfk){\r\n<span>\r\n <span>{{ mfk.fund }}</span>\r\n <span>-{{ mfk.org }}</span>\r\n <span>-{{ mfk.dept }}</span>\r\n <span>-{{ mfk.subdept }}</span>\r\n <span>-{{ mfk.grantpgm }}</span>\r\n <span>-{{ mfk.iact }}</span>\r\n <span>-{{ mfk.oact }}</span>\r\n <span>-{{ mfk.dact }}</span>\r\n <span>-{{ mfk.fn }}</span>\r\n <span>-{{ mfk.cctr }}</span>\r\n @if(mfk.brf){ <span>-{{ mfk.brf }}</span> }\r\n</span>\r\n}\r\n" }] }], propDecorators: { mfk: [{ type: Input }] } }); class MfkStringPipePipe { transform(value, ...args) { return stringify(value); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkStringPipePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: MfkStringPipePipe, isStandalone: false, name: "mfkString" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MfkStringPipePipe, decorators: [{ type: Pipe, args: [{ name: 'mfkString', standalone: false, }] }] }); class WhoKeyStringPipePipe { transform(value, ...args) { if (!value) { return ''; } return (value.fund + '-' + value.org + '-' + value.dept + '-' + value.subdept + '-' + value.grantpgm + '-' + value.fn); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: WhoKeyStringPipePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: WhoKeyStringPipePipe, isStandalone: false, name: "whoKeyString" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: WhoKeyStringPipePipe, decorators: [{ type: Pipe, args: [{ name: 'whoKeyString', standalone: false, }] }] }); class UiowaMfkModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: UiowaMfkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: UiowaMfkModule, declarations: [MfkInputComponent, MfkStringComponent, MfkStringPipePipe, WhoKeyStringPipePipe], imports: [CommonModule, FormsModule, DigitOnlyDirective], exports: [MfkInputComponent, MfkStringComponent, MfkStringPipePipe, WhoKeyStringPipePipe, DigitOnlyDirective] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: UiowaMfkModule, imports: [CommonModule, FormsModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: UiowaMfkModule, decorators: [{ type: NgModule, args: [{ declarations: [ MfkInputComponent, MfkStringComponent, MfkStringPipePipe, WhoKeyStringPipePipe, ], imports: [CommonModule, FormsModule, DigitOnlyDirective], exports: [ MfkInputComponent, MfkStringComponent, MfkStringPipePipe, WhoKeyStringPipePipe, DigitOnlyDirective, ], }] }] }); /* * Public API Surface of uiowa-mfk */ /** * Generated bundle index. Do not edit. */ export { MfkFieldName, MfkFieldOption, MfkInputComponent, MfkString, MfkStringComponent, MfkStringPipePipe, UiowaMfkModule, WhoKeyStringPipePipe, areEqual, emptyMfk, stringify, toMfk, validFormat, validateStructure }; //# sourceMappingURL=uiowa-uiowa-mfk.mjs.map