@m1z23r/ngx-ui 1.1.22 → 1.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,144 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, Pipe, contentChildren, ViewChild, TemplateRef, contentChild, viewChild, DestroyRef } from '@angular/core';
2
+ import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, Pipe, contentChildren, ViewChild, TemplateRef, contentChild, viewChild, afterRenderEffect, DestroyRef } from '@angular/core';
3
3
  import { isPlatformBrowser, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, DecimalPipe } from '@angular/common';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { FormsModule } from '@angular/forms';
6
6
 
7
+ /**
8
+ * Collection of built-in validators for form inputs
9
+ *
10
+ * @example
11
+ * // Using predefined validators
12
+ * <ui-input [validators]="[Validators.required, Validators.email]" />
13
+ *
14
+ * @example
15
+ * // Using validators with parameters
16
+ * <ui-input [validators]="[Validators.required, Validators.minLength(3), Validators.maxLength(50)]" />
17
+ *
18
+ * @example
19
+ * // Custom validator function
20
+ * const noSpaces: ValidatorFn = (value) =>
21
+ * typeof value === 'string' && value.includes(' ')
22
+ * ? { key: 'noSpaces', message: 'Spaces are not allowed' }
23
+ * : null;
24
+ * <ui-input [validatorFn]="noSpaces" />
25
+ */
26
+ class Validators {
27
+ /**
28
+ * Validates that the value is not empty
29
+ */
30
+ static required = (value) => {
31
+ const isEmpty = value === null ||
32
+ value === undefined ||
33
+ value === '' ||
34
+ (Array.isArray(value) && value.length === 0);
35
+ return isEmpty ? { key: 'required', message: 'This field is required' } : null;
36
+ };
37
+ /**
38
+ * Validates email format
39
+ */
40
+ static email = (value) => {
41
+ if (!value || typeof value !== 'string')
42
+ return null;
43
+ const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
44
+ return emailRegex.test(value) ? null : { key: 'email', message: 'Please enter a valid email address' };
45
+ };
46
+ /**
47
+ * Validates minimum string length
48
+ */
49
+ static minLength(min) {
50
+ return (value) => {
51
+ if (!value || typeof value !== 'string')
52
+ return null;
53
+ return value.length >= min
54
+ ? null
55
+ : { key: 'minLength', message: `Minimum ${min} characters required` };
56
+ };
57
+ }
58
+ /**
59
+ * Validates maximum string length
60
+ */
61
+ static maxLength(max) {
62
+ return (value) => {
63
+ if (!value || typeof value !== 'string')
64
+ return null;
65
+ return value.length <= max
66
+ ? null
67
+ : { key: 'maxLength', message: `Maximum ${max} characters allowed` };
68
+ };
69
+ }
70
+ /**
71
+ * Validates minimum numeric value
72
+ */
73
+ static min(min) {
74
+ return (value) => {
75
+ if (value === '' || value === null || value === undefined)
76
+ return null;
77
+ const numValue = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : NaN;
78
+ if (isNaN(numValue))
79
+ return null;
80
+ return numValue >= min
81
+ ? null
82
+ : { key: 'min', message: `Value must be at least ${min}` };
83
+ };
84
+ }
85
+ /**
86
+ * Validates maximum numeric value
87
+ */
88
+ static max(max) {
89
+ return (value) => {
90
+ if (value === '' || value === null || value === undefined)
91
+ return null;
92
+ const numValue = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : NaN;
93
+ if (isNaN(numValue))
94
+ return null;
95
+ return numValue <= max
96
+ ? null
97
+ : { key: 'max', message: `Value must be at most ${max}` };
98
+ };
99
+ }
100
+ /**
101
+ * Validates against a regex pattern
102
+ */
103
+ static pattern(pattern, message) {
104
+ return (value) => {
105
+ if (!value || typeof value !== 'string')
106
+ return null;
107
+ return pattern.test(value)
108
+ ? null
109
+ : { key: 'pattern', message: message ?? 'Invalid format' };
110
+ };
111
+ }
112
+ /**
113
+ * Validates URL format
114
+ */
115
+ static url = (value) => {
116
+ if (!value || typeof value !== 'string')
117
+ return null;
118
+ // Stricter URL regex: requires protocol, valid domain with TLD, no spaces
119
+ const urlRegex = /^https?:\/\/[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+([/?#].*)?$/;
120
+ return urlRegex.test(value) ? null : { key: 'url', message: 'Please enter a valid URL' };
121
+ };
122
+ /**
123
+ * Validates that value contains only numeric characters
124
+ */
125
+ static numeric = (value) => {
126
+ if (!value || typeof value !== 'string')
127
+ return null;
128
+ return /^\d+$/.test(value) ? null : { key: 'numeric', message: 'Only numbers are allowed' };
129
+ };
130
+ /**
131
+ * Validates that value contains only alphanumeric characters
132
+ */
133
+ static alphanumeric = (value) => {
134
+ if (!value || typeof value !== 'string')
135
+ return null;
136
+ return /^[a-zA-Z0-9]+$/.test(value)
137
+ ? null
138
+ : { key: 'alphanumeric', message: 'Only letters and numbers are allowed' };
139
+ };
140
+ }
141
+
7
142
  class SidebarService {
8
143
  platformId = inject(PLATFORM_ID);
9
144
  MOBILE_BREAKPOINT = 768;
@@ -940,17 +1075,140 @@ class InputComponent {
940
1075
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
941
1076
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
942
1077
  id = input('', ...(ngDevMode ? [{ debugName: "id" }] : []));
1078
+ /** Array of validator functions to run against the value */
1079
+ validators = input([], ...(ngDevMode ? [{ debugName: "validators" }] : []));
1080
+ /** Single custom validator function */
1081
+ validatorFn = input(null, ...(ngDevMode ? [{ debugName: "validatorFn" }] : []));
1082
+ /** When to show validation errors: 'touched' (default), 'dirty', or 'always' */
1083
+ showErrorsOn = input('touched', ...(ngDevMode ? [{ debugName: "showErrorsOn" }] : []));
943
1084
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
944
1085
  static nextId = 0;
945
1086
  generatedId = `ui-input-${++InputComponent.nextId}`;
946
1087
  inputId = computed(() => this.id() || this.generatedId, ...(ngDevMode ? [{ debugName: "inputId" }] : []));
1088
+ /** Whether the input has been blurred at least once */
1089
+ touched = signal(false, ...(ngDevMode ? [{ debugName: "touched" }] : []));
1090
+ /** Whether the input value has been modified */
1091
+ dirty = signal(false, ...(ngDevMode ? [{ debugName: "dirty" }] : []));
1092
+ initialValue = signal('', ...(ngDevMode ? [{ debugName: "initialValue" }] : []));
1093
+ initialized = false;
1094
+ constructor() {
1095
+ effect(() => {
1096
+ const val = this.value();
1097
+ if (!this.initialized) {
1098
+ this.initialValue.set(val);
1099
+ this.initialized = true;
1100
+ }
1101
+ });
1102
+ }
1103
+ /** All validation errors from validators and validatorFn */
1104
+ errors = computed(() => {
1105
+ const value = this.value();
1106
+ const errors = [];
1107
+ // Run array validators
1108
+ for (const validator of this.validators()) {
1109
+ const error = validator(value);
1110
+ if (error)
1111
+ errors.push(error);
1112
+ }
1113
+ // Run single validatorFn
1114
+ const customValidator = this.validatorFn();
1115
+ if (customValidator) {
1116
+ const error = customValidator(value);
1117
+ if (error)
1118
+ errors.push(error);
1119
+ }
1120
+ return errors;
1121
+ }, ...(ngDevMode ? [{ debugName: "errors" }] : []));
1122
+ /** Whether the input passes all validations */
1123
+ isValid = computed(() => this.errors().length === 0, ...(ngDevMode ? [{ debugName: "isValid" }] : []));
1124
+ /** Whether the input has validation errors */
1125
+ isInvalid = computed(() => this.errors().length > 0, ...(ngDevMode ? [{ debugName: "isInvalid" }] : []));
1126
+ /** First error message from validators */
1127
+ errorMessage = computed(() => this.errors()[0]?.message ?? null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
1128
+ /** Whether to display the error based on showErrorsOn setting */
1129
+ shouldShowError = computed(() => {
1130
+ if (!this.isInvalid())
1131
+ return false;
1132
+ switch (this.showErrorsOn()) {
1133
+ case 'always':
1134
+ return true;
1135
+ case 'dirty':
1136
+ return this.dirty();
1137
+ case 'touched':
1138
+ default:
1139
+ return this.touched();
1140
+ }
1141
+ }, ...(ngDevMode ? [{ debugName: "shouldShowError" }] : []));
1142
+ /** Combined error - either from error input or from validation */
1143
+ displayError = computed(() => {
1144
+ const manualError = this.error();
1145
+ if (manualError)
1146
+ return manualError;
1147
+ return this.shouldShowError() ? this.errorMessage() : null;
1148
+ }, ...(ngDevMode ? [{ debugName: "displayError" }] : []));
1149
+ /** Full validation state object for external consumption */
1150
+ validationState = computed(() => ({
1151
+ touched: this.touched(),
1152
+ dirty: this.dirty(),
1153
+ valid: this.isValid(),
1154
+ invalid: this.isInvalid(),
1155
+ errors: this.errors(),
1156
+ errorMessage: this.errorMessage(),
1157
+ classes: {
1158
+ touched: this.touched(),
1159
+ untouched: !this.touched(),
1160
+ dirty: this.dirty(),
1161
+ pristine: !this.dirty(),
1162
+ valid: this.isValid(),
1163
+ invalid: this.isInvalid(),
1164
+ },
1165
+ }), ...(ngDevMode ? [{ debugName: "validationState" }] : []));
1166
+ /** Marks the input as touched (called on blur) */
1167
+ onBlur() {
1168
+ this.touched.set(true);
1169
+ }
1170
+ /** Marks the input as dirty when value changes */
1171
+ onInput() {
1172
+ if (!this.dirty()) {
1173
+ this.dirty.set(true);
1174
+ }
1175
+ }
1176
+ /** Reset validation state */
1177
+ reset() {
1178
+ this.touched.set(false);
1179
+ this.dirty.set(false);
1180
+ this.value.set(this.initialValue());
1181
+ }
1182
+ /** Mark as touched programmatically */
1183
+ markAsTouched() {
1184
+ this.touched.set(true);
1185
+ }
1186
+ /** Mark as dirty programmatically */
1187
+ markAsDirty() {
1188
+ this.dirty.set(true);
1189
+ }
1190
+ /** Check if a specific error exists by key */
1191
+ hasError(key) {
1192
+ return this.errors().some((e) => e.key === key);
1193
+ }
1194
+ /** Get error by key */
1195
+ getError(key) {
1196
+ return this.errors().find((e) => e.key === key);
1197
+ }
947
1198
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
948
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: InputComponent, isStandalone: true, selector: "ui-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "<div class=\"ui-input-wrapper\" [class.ui-input-wrapper--error]=\"error()\" [class.ui-input-wrapper--disabled]=\"disabled()\">\n @if (label()) {\n <label class=\"ui-input__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ui-input__required\">*</span>\n }\n </label>\n }\n <div class=\"ui-input__container\">\n <input\n class=\"ui-input\"\n [id]=\"inputId()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [(ngModel)]=\"value\"\n />\n </div>\n @if (error()) {\n <span class=\"ui-input__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block}.ui-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-input__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-input__required{color:var(--ui-danger);margin-left:2px}.ui-input__container{position:relative}.ui-input{width:100%;padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-family:inherit;font-size:var(--ui-font-md);color:var(--ui-text);background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-input::placeholder{color:var(--ui-text-muted)}.ui-input:hover:not(:disabled):not(:read-only){border-color:var(--ui-border-hover)}.ui-input:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-input:disabled{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-input:read-only{background-color:var(--ui-bg-secondary)}.ui-input-wrapper--error .ui-input{border-color:var(--ui-danger)}.ui-input-wrapper--error .ui-input:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-input__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-input__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1199
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: InputComponent, isStandalone: true, selector: "ui-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, validators: { classPropertyName: "validators", publicName: "validators", isSignal: true, isRequired: false, transformFunction: null }, validatorFn: { classPropertyName: "validatorFn", publicName: "validatorFn", isSignal: true, isRequired: false, transformFunction: null }, showErrorsOn: { classPropertyName: "showErrorsOn", publicName: "showErrorsOn", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.ui-input--touched": "touched()", "class.ui-input--untouched": "!touched()", "class.ui-input--dirty": "dirty()", "class.ui-input--pristine": "!dirty()", "class.ui-input--valid": "isValid()", "class.ui-input--invalid": "isInvalid()" } }, ngImport: i0, template: "<div\n class=\"ui-input-wrapper\"\n [class.ui-input-wrapper--error]=\"displayError()\"\n [class.ui-input-wrapper--disabled]=\"disabled()\"\n>\n @if (label()) {\n <label class=\"ui-input__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ui-input__required\">*</span>\n }\n </label>\n }\n <div class=\"ui-input__container\">\n <input\n class=\"ui-input\"\n [id]=\"inputId()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [(ngModel)]=\"value\"\n (blur)=\"onBlur()\"\n (input)=\"onInput()\"\n />\n </div>\n @if (displayError()) {\n <span class=\"ui-input__error\">{{ displayError() }}</span>\n }\n @if (hint() && !displayError()) {\n <span class=\"ui-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block}.ui-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-input__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-input__required{color:var(--ui-danger);margin-left:2px}.ui-input__container{position:relative}.ui-input{width:100%;padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-family:inherit;font-size:var(--ui-font-md);color:var(--ui-text);background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-input::placeholder{color:var(--ui-text-muted)}.ui-input:hover:not(:disabled):not(:read-only){border-color:var(--ui-border-hover)}.ui-input:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-input:disabled{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-input:read-only{background-color:var(--ui-bg-secondary)}.ui-input-wrapper--error .ui-input{border-color:var(--ui-danger)}.ui-input-wrapper--error .ui-input:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-input__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-input__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
949
1200
  }
950
1201
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: InputComponent, decorators: [{
951
1202
  type: Component,
952
- args: [{ selector: 'ui-input', standalone: true, imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-input-wrapper\" [class.ui-input-wrapper--error]=\"error()\" [class.ui-input-wrapper--disabled]=\"disabled()\">\n @if (label()) {\n <label class=\"ui-input__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ui-input__required\">*</span>\n }\n </label>\n }\n <div class=\"ui-input__container\">\n <input\n class=\"ui-input\"\n [id]=\"inputId()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [(ngModel)]=\"value\"\n />\n </div>\n @if (error()) {\n <span class=\"ui-input__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block}.ui-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-input__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-input__required{color:var(--ui-danger);margin-left:2px}.ui-input__container{position:relative}.ui-input{width:100%;padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-family:inherit;font-size:var(--ui-font-md);color:var(--ui-text);background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-input::placeholder{color:var(--ui-text-muted)}.ui-input:hover:not(:disabled):not(:read-only){border-color:var(--ui-border-hover)}.ui-input:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-input:disabled{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-input:read-only{background-color:var(--ui-bg-secondary)}.ui-input-wrapper--error .ui-input{border-color:var(--ui-danger)}.ui-input-wrapper--error .ui-input:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-input__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-input__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"] }]
953
- }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
1203
+ args: [{ selector: 'ui-input', standalone: true, imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
1204
+ '[class.ui-input--touched]': 'touched()',
1205
+ '[class.ui-input--untouched]': '!touched()',
1206
+ '[class.ui-input--dirty]': 'dirty()',
1207
+ '[class.ui-input--pristine]': '!dirty()',
1208
+ '[class.ui-input--valid]': 'isValid()',
1209
+ '[class.ui-input--invalid]': 'isInvalid()',
1210
+ }, template: "<div\n class=\"ui-input-wrapper\"\n [class.ui-input-wrapper--error]=\"displayError()\"\n [class.ui-input-wrapper--disabled]=\"disabled()\"\n>\n @if (label()) {\n <label class=\"ui-input__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ui-input__required\">*</span>\n }\n </label>\n }\n <div class=\"ui-input__container\">\n <input\n class=\"ui-input\"\n [id]=\"inputId()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [(ngModel)]=\"value\"\n (blur)=\"onBlur()\"\n (input)=\"onInput()\"\n />\n </div>\n @if (displayError()) {\n <span class=\"ui-input__error\">{{ displayError() }}</span>\n }\n @if (hint() && !displayError()) {\n <span class=\"ui-input__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block}.ui-input-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-input__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-input__required{color:var(--ui-danger);margin-left:2px}.ui-input__container{position:relative}.ui-input{width:100%;padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-family:inherit;font-size:var(--ui-font-md);color:var(--ui-text);background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-input::placeholder{color:var(--ui-text-muted)}.ui-input:hover:not(:disabled):not(:read-only){border-color:var(--ui-border-hover)}.ui-input:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-input:disabled{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-input:read-only{background-color:var(--ui-bg-secondary)}.ui-input-wrapper--error .ui-input{border-color:var(--ui-danger)}.ui-input-wrapper--error .ui-input:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-input__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-input__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"] }]
1211
+ }], ctorParameters: () => [], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], validators: [{ type: i0.Input, args: [{ isSignal: true, alias: "validators", required: false }] }], validatorFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "validatorFn", required: false }] }], showErrorsOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrorsOn", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
954
1212
 
955
1213
  class CellValuePipe {
956
1214
  transform(row, key) {
@@ -2620,7 +2878,10 @@ class TabsComponent {
2620
2878
  tabList.forEach((tab, index) => {
2621
2879
  tab._setTabsParent(this, index);
2622
2880
  });
2623
- const _ = this.activeTab();
2881
+ });
2882
+ afterRenderEffect(() => {
2883
+ this.tabs();
2884
+ this.activeTab();
2624
2885
  this.updateIndicator();
2625
2886
  });
2626
2887
  }
@@ -5607,11 +5868,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
5607
5868
  /*
5608
5869
  * Public API Surface of @m1z23r/ngx-ui
5609
5870
  */
5610
- // Services
5871
+ // Validators
5611
5872
 
5612
5873
  /**
5613
5874
  * Generated bundle index. Do not edit.
5614
5875
  */
5615
5876
 
5616
- export { AccordionComponent, AccordionHeaderDirective, AccordionItemComponent, AlertComponent, BadgeComponent, ButtonComponent, CardComponent, CellTemplateDirective, CellValuePipe, CheckboxComponent, ChipInputComponent, ChipTemplateDirective, CircularProgressComponent, ContentComponent, ContextMenuDirective, DIALOG_DATA, DIALOG_REF, DatepickerComponent, DatetimepickerComponent, DialogRef, DialogService, DropdownComponent, DropdownDividerComponent, DropdownItemComponent, DropdownTriggerDirective, DynamicTabsComponent, FileChooserComponent, FilePreviewPipe, FileSizePipe, FooterComponent, InputComponent, LOADABLE, LoadingDirective, LoadingService, ModalComponent, NavbarComponent, OptionComponent, OptionTemplateDirective, PaginationComponent, ProgressComponent, RadioComponent, RadioGroupComponent, SelectComponent, ShellComponent, SidebarComponent, SidebarService, SidebarToggleComponent, SliderComponent, SpinnerComponent, SplitComponent, SplitPaneComponent, SwitchComponent, TAB_DATA, TAB_REF, TabActivePipe, TabComponent, TabIconDirective, TabRef, TableComponent, TabsComponent, TabsService, TextareaComponent, TimepickerComponent, ToastRef, ToastService, TooltipDirective, TreeComponent, TreeNodeComponent };
5877
+ export { AccordionComponent, AccordionHeaderDirective, AccordionItemComponent, AlertComponent, BadgeComponent, ButtonComponent, CardComponent, CellTemplateDirective, CellValuePipe, CheckboxComponent, ChipInputComponent, ChipTemplateDirective, CircularProgressComponent, ContentComponent, ContextMenuDirective, DIALOG_DATA, DIALOG_REF, DatepickerComponent, DatetimepickerComponent, DialogRef, DialogService, DropdownComponent, DropdownDividerComponent, DropdownItemComponent, DropdownTriggerDirective, DynamicTabsComponent, FileChooserComponent, FilePreviewPipe, FileSizePipe, FooterComponent, InputComponent, LOADABLE, LoadingDirective, LoadingService, ModalComponent, NavbarComponent, OptionComponent, OptionTemplateDirective, PaginationComponent, ProgressComponent, RadioComponent, RadioGroupComponent, SelectComponent, ShellComponent, SidebarComponent, SidebarService, SidebarToggleComponent, SliderComponent, SpinnerComponent, SplitComponent, SplitPaneComponent, SwitchComponent, TAB_DATA, TAB_REF, TabActivePipe, TabComponent, TabIconDirective, TabRef, TableComponent, TabsComponent, TabsService, TextareaComponent, TimepickerComponent, ToastRef, ToastService, TooltipDirective, TreeComponent, TreeNodeComponent, Validators };
5617
5878
  //# sourceMappingURL=m1z23r-ngx-ui.mjs.map