UNPKG

@proangular/pro-form

Version:

A predefined set of reactive and reusable form input components based on Angular Material.

704 lines (691 loc) 78.4 kB
import { __decorate } from 'tslib'; import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy'; import { startWith, interval } from 'rxjs'; import { CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { inject, ElementRef, forwardRef, Input, Directive, EventEmitter, Output, ChangeDetectionStrategy, Component, QueryList, ViewChild, ContentChildren, Pipe, ViewChildren } from '@angular/core'; import * as i3 from '@angular/forms'; import { NgControl, Validators, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms'; import * as i2 from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox'; import * as i1 from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field'; import { coerceElement, coerceBooleanProperty } from '@angular/cdk/coercion'; import * as i2$1 from '@angular/material/chips'; import { MatChip, MatChipsModule, MatChipListbox } from '@angular/material/chips'; import * as i2$2 from '@angular/material/input'; import { MatInputModule } from '@angular/material/input'; import { provideLuxonDateAdapter } from '@angular/material-luxon-adapter'; import * as i1$1 from '@angular/material/datepicker'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { DateTime } from 'luxon'; import * as i3$1 from '@angular/material/select'; import { MatOption as MatOption$1, MatSelectModule, MatSelect } from '@angular/material/select'; import { MatOption } from '@angular/material/core'; import * as i2$3 from '@angular/material/radio'; import { MatRadioModule } from '@angular/material/radio'; import * as i3$2 from '@angular/material/timepicker'; import { MatTimepickerModule } from '@angular/material/timepicker'; import * as i3$3 from '@angular/material/slide-toggle'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; let id = 0; const rF$8 = { required: false }; class InputDirective { constructor() { if (this.ngControl) { this.ngControl.valueAccessor = this; } } elementRef = inject(ElementRef); ngControl = inject(NgControl, { self: true, optional: true }); get formControl() { if (!this.ngControl) { throw new Error('Input requires a NgControl to be provided.'); } return this.ngControl.control; } hint = null; id = `pro-input-${++id}`; placeholder = null; label; get isRequired() { return this.formControl.hasValidator(Validators.required); } onChange = () => undefined; onTouched = () => undefined; writeValue = () => undefined; registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } scrollIntoView(options) { const defaultOptions = { behavior: 'smooth' }; this.elementRef.nativeElement.scrollIntoView({ ...defaultOptions, ...options, }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: InputDirective, isStandalone: true, inputs: { hint: "hint", id: "id", placeholder: "placeholder", label: "label" }, providers: [ { multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDirective), }, ], ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDirective, decorators: [{ type: Directive, args: [{ providers: [ { multi: true, provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDirective), }, ], }] }], ctorParameters: () => [], propDecorators: { hint: [{ type: Input, args: [rF$8] }], id: [{ type: Input, args: [rF$8] }], placeholder: [{ type: Input, args: [rF$8] }], label: [{ type: Input, args: [{ required: true }] }] } }); const rF$7 = { required: false }; let InputCheckboxComponent = class InputCheckboxComponent extends InputDirective { labelPosition = 'after'; // eslint-disable-next-line @angular-eslint/no-output-native change = new EventEmitter(); ngOnInit() { this.formControl.valueChanges .pipe(startWith(this.formControl.value), untilDestroyed(this)) .subscribe((isChecked) => { if (this.formControl.disabled) { return; } if (this.isRequired && !isChecked) { this.formControl.setErrors({ required: true }, { emitEvent: false }); this.formControl.setValue(null, { emitEvent: false }); } else if (this.isRequired && isChecked) { this.formControl.setErrors(null); } if (isChecked !== null) { this.change.emit(isChecked); } }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputCheckboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputCheckboxComponent, isStandalone: true, selector: "pro-input-checkbox", inputs: { labelPosition: "labelPosition" }, outputs: { change: "change" }, usesInheritance: true, ngImport: i0, template: "<mat-checkbox [formControl]=\"formControl\" [labelPosition]=\"labelPosition\">{{\n label + (isRequired ? '*' : '')\n}}</mat-checkbox>\n@if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n }\n </mat-error>\n}\n", styles: [":host>mat-checkbox{margin-top:.5rem}mat-error{font-size:var(--mat-form-field-subscript-text-size, var(--mat-sys-body-small-size));padding:0 1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i2.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.Default }); }; InputCheckboxComponent = __decorate([ UntilDestroy() ], InputCheckboxComponent); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputCheckboxComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-checkbox', standalone: true, imports: [ CommonModule, FormsModule, MatCheckboxModule, MatFormFieldModule, ReactiveFormsModule, ], changeDetection: ChangeDetectionStrategy.Default, template: "<mat-checkbox [formControl]=\"formControl\" [labelPosition]=\"labelPosition\">{{\n label + (isRequired ? '*' : '')\n}}</mat-checkbox>\n@if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n }\n </mat-error>\n}\n", styles: [":host>mat-checkbox{margin-top:.5rem}mat-error{font-size:var(--mat-form-field-subscript-text-size, var(--mat-sys-body-small-size));padding:0 1rem}\n"] }] }], propDecorators: { labelPosition: [{ type: Input, args: [rF$7] }], change: [{ type: Output }] } }); class InputChipComponent extends MatChip { elementRef = inject((ElementRef)); get element() { return coerceElement(this.elementRef); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputChipComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: InputChipComponent, isStandalone: true, selector: "pro-input-chip", usesInheritance: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputChipComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-chip', template: `<ng-content></ng-content>`, standalone: true, }] }] }); const rF$6 = { required: false }; const rFc$1 = { required: false, transform: coerceBooleanProperty }; class InputChipsComponent extends InputDirective { chips = new QueryList(); matChipListbox; max; multiple = false; compareWith = (optionValue, selectedValue) => { return (JSON.stringify(optionValue) === JSON.stringify(selectedValue) || optionValue === selectedValue); }; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputChipsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputChipsComponent, isStandalone: true, selector: "pro-input-chips", inputs: { max: "max", multiple: ["multiple", "multiple", coerceBooleanProperty], compareWith: "compareWith" }, queries: [{ propertyName: "chips", predicate: InputChipComponent }], viewQueries: [{ propertyName: "matChipListbox", first: true, predicate: MatChipListbox, descendants: true }], usesInheritance: true, ngImport: i0, template: "<mat-label>{{ label }}</mat-label>\n<mat-chip-listbox\n [compareWith]=\"compareWith\"\n [formControl]=\"formControl\"\n [multiple]=\"multiple\"\n>\n @for (chip of chips; track chip) {\n <mat-chip-option [disabled]=\"chip.disabled\" [value]=\"chip.value\">{{\n chip.element.textContent\n }}</mat-chip-option>\n }\n</mat-chip-listbox>\n@if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['maxlength'].requiredLength }} selections.\n } @else if (formControl.hasError('minlength')) {\n {{ label }} must have at least\n {{ formControl.errors?.['minlength'].requiredLength }} selections.\n }\n </mat-error>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i2$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputChipsComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-chips', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, FormsModule, MatChipsModule, MatFormFieldModule, ReactiveFormsModule, ], standalone: true, template: "<mat-label>{{ label }}</mat-label>\n<mat-chip-listbox\n [compareWith]=\"compareWith\"\n [formControl]=\"formControl\"\n [multiple]=\"multiple\"\n>\n @for (chip of chips; track chip) {\n <mat-chip-option [disabled]=\"chip.disabled\" [value]=\"chip.value\">{{\n chip.element.textContent\n }}</mat-chip-option>\n }\n</mat-chip-listbox>\n@if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['maxlength'].requiredLength }} selections.\n } @else if (formControl.hasError('minlength')) {\n {{ label }} must have at least\n {{ formControl.errors?.['minlength'].requiredLength }} selections.\n }\n </mat-error>\n}\n" }] }], propDecorators: { chips: [{ type: ContentChildren, args: [InputChipComponent] }], matChipListbox: [{ type: ViewChild, args: [MatChipListbox] }], max: [{ type: Input, args: [rF$6] }], multiple: [{ type: Input, args: [rFc$1] }], compareWith: [{ type: Input, args: [rF$6] }] } }); const rF$5 = { required: false }; let InputLoadingComponent = class InputLoadingComponent { appearance = 'outline'; hint; label; formControl = new FormControl(null); loadingText = 'Loading'; ngOnInit() { this.formControl.disable(); interval(500) .pipe(untilDestroyed(this)) .subscribe(() => { if (this.loadingText === 'Loading') { this.loadingText = this.label ? `Loading "${this.label}".` : 'Loading.'; } else if (this.loadingText.endsWith('...')) { this.loadingText = this.label ? `Loading "${this.label}"` : 'Loading'; } else { this.loadingText = this.loadingText + '.'; } this.formControl.setValue(this.loadingText); }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputLoadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputLoadingComponent, isStandalone: true, selector: "pro-input-loading", inputs: { appearance: "appearance", hint: "hint", label: "label" }, ngImport: i0, template: ` <mat-form-field [appearance]="appearance"> <input [formControl]="formControl" matInput type="text" /> @if (hint) { <mat-hint [title]="hint">{{ hint }}</mat-hint> } </mat-form-field> `, isInline: true, styles: [":host{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }; InputLoadingComponent = __decorate([ UntilDestroy() ], InputLoadingComponent); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputLoadingComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-loading', template: ` <mat-form-field [appearance]="appearance"> <input [formControl]="formControl" matInput type="text" /> @if (hint) { <mat-hint [title]="hint">{{ hint }}</mat-hint> } </mat-form-field> `, imports: [ CommonModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule, ], standalone: true, styles: [":host{width:100%}\n"] }] }], propDecorators: { appearance: [{ type: Input, args: [rF$5] }], hint: [{ type: Input, args: [rF$5] }], label: [{ type: Input, args: [rF$5] }] } }); const rF$4 = { required: false }; class InputComponent extends InputDirective { appearance = 'outline'; autocomplete = 'off'; set max(value) { this.setMax(value); } get max() { return this.getMax(); } #max; set min(value) { this.setMin(value); } get min() { return this.getMin(); } #min; set maxLength(value) { this.setMaxLength(value); } get maxLength() { return this.#maxLength; } #maxLength; set minLength(value) { this.setMinLength(value); } get minLength() { return this.#minLength; } #minLength; name; set step(value) { const stepParsed = Number(value); if (isNaN(stepParsed)) { this.#step = undefined; return; } this.#step = stepParsed; } get step() { if (this.type !== 'number') { return undefined; } return this.#step; } #step; type = 'text'; getMax() { if (this.type !== 'number') { return undefined; } return this.#max; } getMin() { if (this.type !== 'number') { return undefined; } return this.#min; } setMax(value) { const maxParsed = Number(value); if (isNaN(maxParsed)) { this.#max = undefined; return; } this.#max = maxParsed; } setMaxLength(value) { const maxLengthParsed = Number(value); if (isNaN(maxLengthParsed)) { this.#maxLength = undefined; return; } this.#maxLength = maxLengthParsed; } setMin(value) { const minParsed = Number(value); if (isNaN(minParsed)) { this.#min = undefined; return; } this.#min = minParsed; } setMinLength(value) { const minLengthParsed = Number(value); if (isNaN(minLengthParsed)) { this.#minLength = undefined; return; } this.#minLength = minLengthParsed; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputComponent, isStandalone: true, selector: "pro-input", inputs: { appearance: "appearance", autocomplete: "autocomplete", max: "max", min: "min", maxLength: "maxLength", minLength: "minLength", name: "name", step: "step", type: "type" }, usesInheritance: true, ngImport: i0, template: "@if (formControl) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <input\n [attr.step]=\"step\"\n [autocomplete]=\"autocomplete\"\n [formControl]=\"formControl\"\n [id]=\"id\"\n [name]=\"name || id\"\n [placeholder]=\"placeholder || ''\"\n [type]=\"type\"\n matInput\n />\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('min')) {\n {{ label }} must be at least {{ formControl.errors?.['min'].min }}.\n } @else if (formControl.hasError('max')) {\n {{ label }} cannot exceed {{ formControl.errors?.['max'].max }}.\n } @else if (formControl.hasError('minlength')) {\n {{ label }} must be at least\n {{ formControl.errors?.['minlength'].requiredLength }} characters.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['maxlength'].requiredLength }} characters.\n } @else if (formControl.hasError('email')) {\n {{ label }} must be a valid email address.\n } @else if (formControl.hasError('nonNumber')) {\n {{ label }} must be a number.\n } @else if (formControl.hasError('wholeNumber')) {\n {{ label }} must be a whole number.\n }\n </mat-error>\n }\n </mat-form-field>\n} @else {\n <pro-input-loading [label]=\"label\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: InputLoadingComponent, selector: "pro-input-loading", inputs: ["appearance", "hint", "label"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input', standalone: true, imports: [ CommonModule, InputLoadingComponent, MatFormFieldModule, MatInputModule, ReactiveFormsModule, ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (formControl) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <input\n [attr.step]=\"step\"\n [autocomplete]=\"autocomplete\"\n [formControl]=\"formControl\"\n [id]=\"id\"\n [name]=\"name || id\"\n [placeholder]=\"placeholder || ''\"\n [type]=\"type\"\n matInput\n />\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('min')) {\n {{ label }} must be at least {{ formControl.errors?.['min'].min }}.\n } @else if (formControl.hasError('max')) {\n {{ label }} cannot exceed {{ formControl.errors?.['max'].max }}.\n } @else if (formControl.hasError('minlength')) {\n {{ label }} must be at least\n {{ formControl.errors?.['minlength'].requiredLength }} characters.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['maxlength'].requiredLength }} characters.\n } @else if (formControl.hasError('email')) {\n {{ label }} must be a valid email address.\n } @else if (formControl.hasError('nonNumber')) {\n {{ label }} must be a number.\n } @else if (formControl.hasError('wholeNumber')) {\n {{ label }} must be a whole number.\n }\n </mat-error>\n }\n </mat-form-field>\n} @else {\n <pro-input-loading [label]=\"label\" />\n}\n" }] }], propDecorators: { appearance: [{ type: Input, args: [rF$4] }], autocomplete: [{ type: Input, args: [rF$4] }], max: [{ type: Input, args: [rF$4] }], min: [{ type: Input, args: [rF$4] }], maxLength: [{ type: Input, args: [rF$4] }], minLength: [{ type: Input, args: [rF$4] }], name: [{ type: Input, args: [rF$4] }], step: [{ type: Input, args: [rF$4] }], type: [{ type: Input, args: [rF$4] }] } }); /** * Validate that the value is an empty value. * * @param value The value to check. * @returns True if the value is an empty value, false otherwise. */ function isEmptyValue(value) { return value === null || value === undefined; } /** * Validate that the value is a non-empty value. * * @param value The value to check. * @returns True if the value is a non-empty value, false otherwise. */ function isNonEmptyValue(value) { return value !== null && value !== undefined; } /** * Validate that the value is a number. * * @param value The value to check. * @returns True if the value is a number, false otherwise. */ function isNumber(value) { return typeof value === 'number' && !isNaN(value); } /** * Validate that the value is a string. This includes both primitive strings * and string objects. * * @param value The value to check. * @returns True if the value is a string, false otherwise. */ function isString(value) { return typeof value === 'string' || value instanceof String; } /** * Validate that the value is an empty string. An empty string is a string that * contains no characters. * * @param value The value to check. * @returns True if the value is an empty string, false otherwise. */ function isEmptyString(value) { return value === ''; } /** * Validate that the value is a blank string. A blank string is a string that * contains only whitespace characters. * * @param value * @returns */ function isWhitespaceString(value) { return typeof value === 'string' && value.trim() === ''; } /** * Validate that the value is a string that is non-empty. * * @param value The value to check. * @returns True if the value is a string that is non-empty, false otherwise. */ function isNonEmptyString(value) { return isString(value) && !isWhitespaceString(value); } class CustomValidators { /** * Validates that a given DateTime value does not exceed a maximum allowed DateTime. * * @param max The maximum allowed DateTime. * @returns A validator function that checks if the value exceeds the max DateTime. */ static maxDateTime(max) { return (control) => { const value = control.value; return value instanceof DateTime && value.isValid && value > max ? { max: { max, actual: value } } : null; }; } /** * Validates that a given DateTime value is not earlier than a minimum allowed DateTime. * * @param min The minimum allowed DateTime. * @returns A validator function that checks if the value is below the min DateTime. */ static minDateTime(min) { return (control) => { const value = control.value; return value instanceof DateTime && value.isValid && value < min ? { min: { min, actual: value } } : null; }; } /** * Validates that a given value is **not** a string. * * @param control The form control being validated. * @returns A validation error if the value is a string, otherwise null. */ static nonString(control) { return typeof control.value !== 'string' ? null : { nonString: true }; } /** * Validates that a given value is a number. * * @returns A validator function that checks if the value is a number. */ static isNumber() { return (control) => { return isNumber(control.value) ? null : { nonNumber: true }; }; } /** * Validates that a given value is a whole number (integer). * * @returns A validator function that checks if the value is a whole number. */ static wholeNumber() { return (control) => { if (!isNumber(control.value)) { return null; } return Number.isInteger(control.value) ? null : { wholeNumber: true }; }; } } class DateTimePipe { defaultFormat = 'MM/dd/yyyy'; /** Transform DateTime object into a readable string. */ transform(value, format = this.defaultFormat) { if (!isNonEmptyValue(value) || !(value instanceof DateTime)) { return ''; } if (format === 'relative-date') { return this.getRelativeDate(value); } else if (format === 'relative-datetime') { return this.getRelativeDateTime(value); } return value.toFormat(format); } getRelativeDate(value) { const relativeTime = value.toRelative(); if (!relativeTime) { throw new Error(`There was an issue converting the datetime object "${value.toString()}" to a relative time.`); } const now = DateTime.local(); const hoursDiff = now.diff(value).as('hours'); if (hoursDiff < 24) { return 'Today'; } else if (hoursDiff < 48) { return 'Yesterday'; } else if (hoursDiff > 168) { return value.toFormat(this.defaultFormat); } return relativeTime; } getRelativeDateTime(value) { const time = value.toFormat('h:mm a'); return `${this.getRelativeDate(value)}, ${time}`; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DateTimePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: DateTimePipe, isStandalone: true, name: "dateTime" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: DateTimePipe, decorators: [{ type: Pipe, args: [{ name: 'dateTime', standalone: true }] }] }); const rF$3 = { required: false }; class InputDatepickerComponent extends InputDirective { appearance = 'outline'; max; min; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDatepickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputDatepickerComponent, isStandalone: true, selector: "pro-input-datepicker", inputs: { appearance: "appearance", max: "max", min: "min" }, providers: [provideLuxonDateAdapter()], usesInheritance: true, ngImport: i0, template: "@if (formControl) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <input\n [formControl]=\"formControl\"\n [matDatepicker]=\"datepicker\"\n [max]=\"max\"\n [min]=\"min\"\n [placeholder]=\"placeholder ?? ''\"\n matInput\n />\n <mat-datepicker-toggle [for]=\"datepicker\" matSuffix />\n <mat-datepicker #datepicker />\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('min')) {\n {{ label }} must be at least\n {{ formControl.errors?.['min'].min | dateTime: 'MM/dd/yyyy' }}.\n } @else if (formControl.hasError('max')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['max'].max | dateTime: 'MM/dd/yyyy' }}.\n }\n </mat-error>\n }\n </mat-form-field>\n} @else {\n <pro-input-loading [label]=\"label\" />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: InputLoadingComponent, selector: "pro-input-loading", inputs: ["appearance", "hint", "label"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i1$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i1$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i1$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: DateTimePipe, name: "dateTime" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDatepickerComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-datepicker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, DateTimePipe, InputLoadingComponent, MatDatepickerModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule, ], providers: [provideLuxonDateAdapter()], standalone: true, template: "@if (formControl) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <input\n [formControl]=\"formControl\"\n [matDatepicker]=\"datepicker\"\n [max]=\"max\"\n [min]=\"min\"\n [placeholder]=\"placeholder ?? ''\"\n matInput\n />\n <mat-datepicker-toggle [for]=\"datepicker\" matSuffix />\n <mat-datepicker #datepicker />\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('min')) {\n {{ label }} must be at least\n {{ formControl.errors?.['min'].min | dateTime: 'MM/dd/yyyy' }}.\n } @else if (formControl.hasError('max')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['max'].max | dateTime: 'MM/dd/yyyy' }}.\n }\n </mat-error>\n }\n </mat-form-field>\n} @else {\n <pro-input-loading [label]=\"label\" />\n}\n" }] }], propDecorators: { appearance: [{ type: Input, args: [rF$3] }], max: [{ type: Input, args: [rF$3] }], min: [{ type: Input, args: [rF$3] }] } }); class InputDropdownOptionComponent extends MatOption { elementRef = inject((ElementRef)); get element() { return coerceElement(this.elementRef); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownOptionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: InputDropdownOptionComponent, isStandalone: true, selector: "pro-input-dropdown-option", usesInheritance: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownOptionComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-dropdown-option', template: `<ng-content></ng-content>`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, }] }] }); class InputDropdownOptionGroupComponent { label; options = new QueryList(); static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownOptionGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: InputDropdownOptionGroupComponent, isStandalone: true, selector: "pro-input-dropdown-option-group", inputs: { label: "label" }, queries: [{ propertyName: "options", predicate: InputDropdownOptionComponent }], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownOptionGroupComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-dropdown-option-group', template: `<ng-content></ng-content>`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, }] }], propDecorators: { label: [{ type: Input, args: [{ required: true }] }], options: [{ type: ContentChildren, args: [InputDropdownOptionComponent] }] } }); const rF$2 = { required: false }; const rFc = { required: false, transform: coerceBooleanProperty }; class InputDropdownComponent extends InputDirective { options = new QueryList(); optionGroups = new QueryList(); matSelect; appearance = 'outline'; max; get exceedsMax() { return this.max !== undefined && this.selectedOptions.length > this.max; } get selectedOptions() { if (!this.matSelect) { return []; } const allOptions = [ ...this.options.toArray(), ...this.optionGroups .toArray() .flatMap((group) => group.options.toArray()), ]; // Single selection if (this.matSelect.selected instanceof MatOption$1) { const selectedValue = this.matSelect.selected.value; return allOptions.filter((option) => option.value === selectedValue); } // Multi-selection if (Array.isArray(this.matSelect.selected) && this.matSelect.selected.every((s) => s instanceof MatOption$1)) { const selectedValues = this.matSelect.selected.map((selected) => selected.value); return allOptions.filter((option) => selectedValues.includes(option.value)); } // Default: No option is selected. return []; } multiple = false; compareWith = (optionValue, selectedValue) => { return (JSON.stringify(optionValue) === JSON.stringify(selectedValue) || optionValue === selectedValue); }; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: InputDropdownComponent, isStandalone: true, selector: "pro-input-dropdown", inputs: { appearance: "appearance", max: "max", multiple: ["multiple", "multiple", coerceBooleanProperty], compareWith: "compareWith" }, queries: [{ propertyName: "options", predicate: InputDropdownOptionComponent }, { propertyName: "optionGroups", predicate: InputDropdownOptionGroupComponent }], viewQueries: [{ propertyName: "matSelect", first: true, predicate: MatSelect, descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (formControl && (options || optionGroups)) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <mat-select\n [compareWith]=\"compareWith\"\n [formControl]=\"formControl\"\n [multiple]=\"multiple\"\n [placeholder]=\"placeholder || ''\"\n >\n @for (option of options; track option) {\n <mat-option [disabled]=\"option.disabled\" [value]=\"option.value\">{{\n option.element.textContent\n }}</mat-option>\n }\n @for (optionGroup of optionGroups; track optionGroup) {\n <mat-optgroup [label]=\"optionGroup.label\">\n @for (option of optionGroup.options; track option) {\n <mat-option [disabled]=\"option.disabled\" [value]=\"option.value\">{{\n option.element.textContent\n }}</mat-option>\n }\n </mat-optgroup>\n }\n </mat-select>\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n {{ formControl.errors?.['maxlength'].requiredLength }} selections.\n } @else if (formControl.hasError('minlength')) {\n {{ label }} must have at least\n {{ formControl.errors?.['minlength'].requiredLength }} selections.\n }\n </mat-error>\n }\n </mat-form-field>\n} @else {\n <pro-input-loading [label]=\"label\" />\n}\n", styles: ["::ng-deep mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: InputLoadingComponent, selector: "pro-input-loading", inputs: ["appearance", "hint", "label"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3$1.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: InputDropdownComponent, decorators: [{ type: Component, args: [{ selector: 'pro-input-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ CommonModule, FormsModule, InputLoadingComponent, MatFormFieldModule, MatSelectModule, ReactiveFormsModule, ], standalone: true, template: "@if (formControl && (options || optionGroups)) {\n <mat-form-field [appearance]=\"appearance\">\n <mat-label>{{ label }}</mat-label>\n <mat-select\n [compareWith]=\"compareWith\"\n [formControl]=\"formControl\"\n [multiple]=\"multiple\"\n [placeholder]=\"placeholder || ''\"\n >\n @for (option of options; track option) {\n <mat-option [disabled]=\"option.disabled\" [value]=\"option.value\">{{\n option.element.textContent\n }}</mat-option>\n }\n @for (optionGroup of optionGroups; track optionGroup) {\n <mat-optgroup [label]=\"optionGroup.label\">\n @for (option of optionGroup.options; track option) {\n <mat-option [disabled]=\"option.disabled\" [value]=\"option.value\">{{\n option.element.textContent\n }}</mat-option>\n }\n </mat-optgroup>\n }\n </mat-select>\n <mat-hint [title]=\"hint\">{{ hint }}</mat-hint>\n @if (formControl.invalid && formControl.touched) {\n <mat-error>\n @if (formControl.hasError('required')) {\n {{ label }} is required.\n } @else if (formControl.hasError('maxlength')) {\n {{ label }} cannot exceed\n