@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
JavaScript
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