@zellvora/ng-input 0.1.1

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.
@@ -0,0 +1,663 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { WritableSignal, Signal, Injector, Type, Provider, InjectionToken, ChangeDetectorRef, DestroyRef, EventEmitter } from '@angular/core';
3
+ import * as _zellvora_ng_input from '@zellvora/ng-input';
4
+ import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
5
+
6
+ /**
7
+ * Signal Validation Engine — type contracts.
8
+ *
9
+ * Validators are *pure functions* of a value (and optionally the whole form
10
+ * model for cross-field rules). They never touch Angular `AbstractControl`,
11
+ * never use Observables/Subjects/EventEmitter. The engine wraps them in
12
+ * `computed()` so validation re-runs automatically when the value changes.
13
+ */
14
+ /** Map of error-key -> error payload, or `null` when the value is valid. */
15
+ type ZvErrors = Record<string, unknown> | null;
16
+ /** Synchronous validator: pure function from value (+model) to errors. */
17
+ type ZvValidator<V = unknown, M = Record<string, unknown>> = (value: V, model: M) => ZvErrors;
18
+ /** Asynchronous validator: e.g. server uniqueness checks. */
19
+ type ZvAsyncValidator<V = unknown, M = Record<string, unknown>> = (value: V, model: M) => Promise<ZvErrors>;
20
+ /** Per-control validation configuration used when declaring a form. */
21
+ interface ZvFieldConfig<V = unknown, M = Record<string, unknown>> {
22
+ validators?: ZvValidator<V, M>[];
23
+ asyncValidators?: ZvAsyncValidator<V, M>[];
24
+ /** Debounce (ms) before async validators fire after the last change. */
25
+ debounce?: number;
26
+ /** Initial disabled state. */
27
+ disabled?: boolean;
28
+ }
29
+ /** Aggregate control status, mirroring familiar Angular semantics. */
30
+ type ZvControlStatus = 'VALID' | 'INVALID' | 'PENDING' | 'DISABLED';
31
+
32
+ /**
33
+ * Signal Form Engine — the single source of truth for the whole library.
34
+ *
35
+ * A form is a `WritableSignal<T>` model plus a lazily-created `ZvControl` per
36
+ * field. Every piece of derived state (value, errors, validity, status) is a
37
+ * `computed()`, so it recomputes automatically and never needs subscriptions,
38
+ * `patchValue`, `setValue`, or manual change detection.
39
+ *
40
+ * The Reactive and Template adapters wrap *this* — they add no validation or
41
+ * state logic of their own.
42
+ */
43
+
44
+ /** Declarative form definition: per-field validator config. */
45
+ type ZvFormSchema<T> = {
46
+ [K in keyof T]?: ZvFieldConfig<T[K], T>;
47
+ };
48
+ interface ZvFormOptions {
49
+ /**
50
+ * Injector used to register async-validation effects. Defaults to the
51
+ * ambient injector when `createForm` is called in an injection context.
52
+ */
53
+ injector?: Injector;
54
+ }
55
+ /** A reactive view over one field of the form model. */
56
+ interface ZvControl<V> {
57
+ readonly key: string;
58
+ /** Current value (computed view of `model()[key]`). */
59
+ readonly value: Signal<V>;
60
+ /** Two-way friendly model alias (same as `value`). */
61
+ readonly model: Signal<V>;
62
+ readonly disabled: Signal<boolean>;
63
+ readonly required: Signal<boolean>;
64
+ readonly dirty: Signal<boolean>;
65
+ readonly touched: Signal<boolean>;
66
+ readonly pending: Signal<boolean>;
67
+ readonly errors: Signal<ZvErrors>;
68
+ readonly valid: Signal<boolean>;
69
+ readonly invalid: Signal<boolean>;
70
+ readonly status: Signal<ZvControlStatus>;
71
+ setValue(v: V): void;
72
+ update(fn: (v: V) => V): void;
73
+ setDisabled(disabled: boolean): void;
74
+ markTouched(touched?: boolean): void;
75
+ markDirty(dirty?: boolean): void;
76
+ reset(): void;
77
+ }
78
+ /** The form object returned by `createForm`. */
79
+ interface ZvSignalForm<T extends Record<string, unknown>> {
80
+ /** The model — the writable source of truth. */
81
+ readonly model: WritableSignal<T>;
82
+ /** Get (and lazily create) a typed control for a field. */
83
+ control<K extends keyof T & string>(key: K): ZvControl<T[K]>;
84
+ readonly value: Signal<T>;
85
+ readonly errors: Signal<Record<string, ZvErrors>>;
86
+ readonly valid: Signal<boolean>;
87
+ readonly invalid: Signal<boolean>;
88
+ readonly dirty: Signal<boolean>;
89
+ readonly touched: Signal<boolean>;
90
+ readonly pending: Signal<boolean>;
91
+ readonly status: Signal<ZvControlStatus>;
92
+ patch(partial: Partial<T>): void;
93
+ setValue(value: T): void;
94
+ reset(value?: T): void;
95
+ markAllTouched(): void;
96
+ }
97
+ /**
98
+ * Create a Signal Form.
99
+ *
100
+ * @example
101
+ * const form = createForm(
102
+ * { firstName: '', email: '', age: null as number | null },
103
+ * { email: { validators: [ZvValidators.required, ZvValidators.email] } },
104
+ * );
105
+ * form.control('email').invalid(); // computed signal
106
+ */
107
+ declare function createForm<T extends Record<string, unknown>>(initial: T, schema?: ZvFormSchema<T>, options?: ZvFormOptions): ZvSignalForm<T>;
108
+
109
+ /**
110
+ * Built-in signal validators.
111
+ *
112
+ * Each is a pure `ZvValidator` (or a factory returning one). They are shared by
113
+ * the Signal Form Engine, and — via thin wrappers — by the Reactive and
114
+ * Template adapters, so validation logic is written exactly once.
115
+ */
116
+
117
+ declare const ZV_PATTERNS: {
118
+ readonly email: RegExp;
119
+ readonly phone: RegExp;
120
+ readonly mobile: RegExp;
121
+ readonly url: RegExp;
122
+ readonly pan: RegExp;
123
+ readonly gst: RegExp;
124
+ readonly aadhaar: RegExp;
125
+ readonly cvv: RegExp;
126
+ readonly passport: RegExp;
127
+ readonly drivingLicense: RegExp;
128
+ readonly pincode: RegExp;
129
+ readonly ifsc: RegExp;
130
+ readonly swift: RegExp;
131
+ readonly iban: RegExp;
132
+ readonly time: RegExp;
133
+ readonly password: RegExp;
134
+ };
135
+ declare const ZvValidators: {
136
+ readonly required: ZvValidator & {
137
+ zvRequired: boolean;
138
+ };
139
+ readonly email: ZvValidator<unknown>;
140
+ readonly phone: ZvValidator<unknown>;
141
+ readonly mobile: ZvValidator<unknown>;
142
+ readonly url: ZvValidator<unknown>;
143
+ readonly pincode: ZvValidator<unknown>;
144
+ readonly cvv: ZvValidator<unknown>;
145
+ readonly passport: ZvValidator<unknown>;
146
+ readonly drivingLicense: ZvValidator<unknown>;
147
+ readonly ifsc: ZvValidator<unknown>;
148
+ readonly swift: ZvValidator<unknown>;
149
+ readonly iban: ZvValidator<unknown>;
150
+ readonly time: ZvValidator<unknown>;
151
+ readonly pan: ZvValidator<unknown>;
152
+ readonly gst: ZvValidator<unknown>;
153
+ readonly password: ZvValidator<unknown>;
154
+ readonly pattern: (p: string | RegExp) => ZvValidator;
155
+ readonly regex: (p: string | RegExp) => ZvValidator;
156
+ readonly min: (n: number) => ZvValidator<number | string | null>;
157
+ readonly max: (n: number) => ZvValidator<number | string | null>;
158
+ readonly minLength: (n: number) => ZvValidator;
159
+ readonly maxLength: (n: number) => ZvValidator;
160
+ readonly date: ZvValidator;
161
+ /** Minimum whole-year age relative to today. */
162
+ readonly age: (minYears: number) => ZvValidator;
163
+ readonly aadhaar: ZvValidator;
164
+ readonly creditCard: ZvValidator;
165
+ /** Max file size in bytes (works on File | File[]). */
166
+ readonly fileSize: (maxBytes: number) => ZvValidator;
167
+ /** Allowed MIME types (e.g. ['image/png','application/pdf']). */
168
+ readonly mimeType: (allowed: string[]) => ZvValidator;
169
+ /** Image max width/height (async-free: relies on already-measured dims). */
170
+ readonly imageSize: (maxW: number, maxH: number) => ZvValidator<{
171
+ width: number;
172
+ height: number;
173
+ } | null>;
174
+ /**
175
+ * Cross-field: a control validator that compares against another model key.
176
+ * Use as a field validator; it receives the full model as 2nd arg.
177
+ */
178
+ readonly confirm: (otherField: string, key?: string) => ZvValidator;
179
+ };
180
+
181
+ /** Shared types for all Zellvora form controls. */
182
+ type ZvAppearance = 'outlined' | 'filled' | 'standard';
183
+ type ZvSize = 'sm' | 'md' | 'lg' | 'compact' | 'dense';
184
+ type ZvTheme = 'material' | 'bootstrap' | 'custom';
185
+ type ZvColor = 'primary' | 'accent' | 'warn' | 'success' | 'info';
186
+ type ZvStatus = 'error' | 'success' | 'warning' | 'info' | null;
187
+ type ZvDir = 'ltr' | 'rtl';
188
+ /** A selectable option for select / multiselect / radio. */
189
+ interface ZvOption<T = unknown> {
190
+ label: string;
191
+ value: T;
192
+ disabled?: boolean;
193
+ icon?: string;
194
+ group?: string;
195
+ }
196
+ /** Resolved component-wide defaults provided via ZV_INPUT_CONFIG. */
197
+ interface ZvInputConfig {
198
+ appearance: ZvAppearance;
199
+ size: ZvSize;
200
+ theme: ZvTheme;
201
+ color: ZvColor;
202
+ floatingLabel: boolean;
203
+ dir: ZvDir;
204
+ clearable: boolean;
205
+ /** Debounce (ms) applied to value emissions for async/server validators. */
206
+ debounce: number;
207
+ }
208
+ declare const ZV_DEFAULT_CONFIG: ZvInputConfig;
209
+
210
+ declare abstract class SignalControlAccessor<T = unknown> {
211
+ protected readonly config: _zellvora_ng_input.ZvInputConfig;
212
+ /** Override per concrete control: 'input' | 'select' | ... */
213
+ abstract readonly controlType: string;
214
+ readonly id: _angular_core.WritableSignal<string>;
215
+ readonly name: _angular_core.InputSignal<string | undefined>;
216
+ /** The Signal Form to bind to (use with `controlName`). */
217
+ readonly form: _angular_core.InputSignal<ZvSignalForm<Record<string, unknown>> | undefined>;
218
+ readonly controlName: _angular_core.InputSignal<string | undefined>;
219
+ readonly value: _angular_core.ModelSignal<T | null>;
220
+ /** Alias of `value` for `[(model)]` ergonomics. */
221
+ readonly modelValue: _angular_core.ModelSignal<T | null>;
222
+ readonly label: _angular_core.InputSignal<string | undefined>;
223
+ readonly placeholder: _angular_core.InputSignal<string>;
224
+ readonly hint: _angular_core.InputSignal<string | undefined>;
225
+ readonly helperText: _angular_core.InputSignal<string | undefined>;
226
+ readonly errorMessage: _angular_core.InputSignal<string | undefined>;
227
+ readonly prefixIcon: _angular_core.InputSignal<string | undefined>;
228
+ readonly suffixIcon: _angular_core.InputSignal<string | undefined>;
229
+ readonly tooltip: _angular_core.InputSignal<string | undefined>;
230
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
231
+ readonly autocomplete: _angular_core.InputSignal<string>;
232
+ readonly loadingText: _angular_core.InputSignal<string | undefined>;
233
+ readonly tabIndex: _angular_core.InputSignalWithTransform<number, unknown>;
234
+ readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
235
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
236
+ readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
237
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
238
+ readonly floatingLabel: _angular_core.InputSignalWithTransform<boolean, unknown>;
239
+ readonly minlength: _angular_core.InputSignalWithTransform<number | undefined, number | undefined>;
240
+ readonly maxlength: _angular_core.InputSignalWithTransform<number | undefined, number | undefined>;
241
+ readonly min: _angular_core.InputSignal<string | number | Date | undefined>;
242
+ readonly max: _angular_core.InputSignal<string | number | Date | undefined>;
243
+ readonly mask: _angular_core.InputSignal<string | undefined>;
244
+ readonly appearance: _angular_core.InputSignal<ZvAppearance>;
245
+ readonly size: _angular_core.InputSignal<ZvSize>;
246
+ readonly theme: _angular_core.InputSignal<ZvTheme>;
247
+ readonly color: _angular_core.InputSignal<ZvColor>;
248
+ readonly dir: _angular_core.InputSignal<ZvDir>;
249
+ readonly variant: _angular_core.InputSignal<string | undefined>;
250
+ readonly density: _angular_core.InputSignal<string | undefined>;
251
+ readonly rounded: _angular_core.InputSignalWithTransform<boolean, unknown>;
252
+ readonly statusInput: _angular_core.InputSignal<ZvStatus>;
253
+ readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
254
+ private readonly _disabledOverride;
255
+ readonly change: _angular_core.OutputEmitterRef<T | null>;
256
+ readonly inputEvent: _angular_core.OutputEmitterRef<T | null>;
257
+ readonly focusEvent: _angular_core.OutputEmitterRef<FocusEvent>;
258
+ readonly blurEvent: _angular_core.OutputEmitterRef<FocusEvent>;
259
+ private readonly _touched;
260
+ private readonly _focused;
261
+ private readonly _dirty;
262
+ /** The bound engine control, if `[form] + controlName` are set. */
263
+ protected readonly boundControl: Signal<ZvControl<T> | null>;
264
+ readonly current: Signal<T | null>;
265
+ readonly disabled: Signal<boolean>;
266
+ /** Errors injected by the Reactive/Template adapter (no bound signal form). */
267
+ private readonly _externalErrors;
268
+ readonly errors: Signal<ZvErrors>;
269
+ readonly valid: Signal<boolean>;
270
+ readonly invalid: Signal<boolean>;
271
+ readonly pending: Signal<boolean>;
272
+ readonly dirty: Signal<boolean>;
273
+ readonly touched: Signal<boolean>;
274
+ readonly focused: Signal<boolean>;
275
+ readonly required: Signal<boolean>;
276
+ readonly status: Signal<ZvControlStatus>;
277
+ /** Show validation error only once the field has been interacted with. */
278
+ readonly showError: Signal<boolean>;
279
+ /** Resolved error text: explicit `errorMessage` wins, else the first error. */
280
+ readonly errorText: Signal<string | null>;
281
+ readonly hasValue: Signal<boolean>;
282
+ constructor();
283
+ protected commit(v: T | null, kind: 'input' | 'change'): void;
284
+ protected onFocus(ev: FocusEvent): void;
285
+ protected onBlur(ev: FocusEvent): void;
286
+ setDisabled(disabled: boolean): void;
287
+ /** Accept a value from a Reactive/Template control without re-emitting. */
288
+ acceptExternalValue(v: T | null): void;
289
+ /** Push validation errors computed by the adapter (same ZvValidators). */
290
+ setExternalErrors(e: ZvErrors): void;
291
+ /** Mark touched from the adapter (e.g. on blur). */
292
+ markTouched(): void;
293
+ /** Subscribe to value commits (adapter -> NgControl onChange). */
294
+ readonly committed: _angular_core.OutputEmitterRef<T | null>;
295
+ clear(): void;
296
+ protected readonly hostClasses: Signal<string>;
297
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SignalControlAccessor<any>, never>;
298
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SignalControlAccessor<any>, never, never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "modelValue": { "alias": "model"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "prefixIcon": { "alias": "prefixIcon"; "required": false; "isSignal": true; }; "suffixIcon": { "alias": "suffixIcon"; "required": false; "isSignal": true; }; "tooltip": { "alias": "tooltip"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "requiredInput": { "alias": "required"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "floatingLabel": { "alias": "floatingLabel"; "required": false; "isSignal": true; }; "minlength": { "alias": "minlength"; "required": false; "isSignal": true; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "mask": { "alias": "mask"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "theme": { "alias": "theme"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "dir": { "alias": "dir"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "rounded": { "alias": "rounded"; "required": false; "isSignal": true; }; "statusInput": { "alias": "status"; "required": false; "isSignal": true; }; "disabledInput": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "modelValue": "modelChange"; "change": "change"; "inputEvent": "input"; "focusEvent": "focus"; "blurEvent": "blur"; "committed": "zvCommitted"; }, never, never, true, never>;
299
+ }
300
+
301
+ /**
302
+ * Alias a concrete control to the abstract `SignalControlAccessor` token so the
303
+ * Reactive/Template adapter directive can inject it from the same element.
304
+ */
305
+ declare function provideSignalControl(cmp: Type<unknown>): Provider;
306
+
307
+ /**
308
+ * App-wide defaults for every Zellvora control. Override at root or per
309
+ * lazy-loaded scope. Tree-shakable: the default is the bundled constant.
310
+ */
311
+ declare const ZV_INPUT_CONFIG: InjectionToken<ZvInputConfig>;
312
+ /** Provide partial overrides without restating the full config. */
313
+ declare function provideZvInput(overrides?: Partial<ZvInputConfig>): Provider;
314
+
315
+ /**
316
+ * Presentational wrapper: label, prefix/suffix icons, hint/error row,
317
+ * loading + clear affordances. Controls project their native element into it.
318
+ * Signal-first and OnPush — it never triggers extra change detection.
319
+ */
320
+ declare class ZvFieldShell {
321
+ readonly for: _angular_core.InputSignal<string | undefined>;
322
+ readonly label: _angular_core.InputSignal<string | undefined>;
323
+ readonly required: _angular_core.InputSignal<boolean>;
324
+ readonly hint: _angular_core.InputSignal<string | undefined>;
325
+ readonly helperText: _angular_core.InputSignal<string | undefined>;
326
+ readonly errorText: _angular_core.InputSignal<string | null | undefined>;
327
+ readonly invalid: _angular_core.InputSignal<boolean>;
328
+ readonly prefixIcon: _angular_core.InputSignal<string | undefined>;
329
+ readonly suffixIcon: _angular_core.InputSignal<string | undefined>;
330
+ readonly loading: _angular_core.InputSignal<boolean>;
331
+ readonly loadingText: _angular_core.InputSignal<string | undefined>;
332
+ readonly clearable: _angular_core.InputSignal<boolean>;
333
+ readonly hasValue: _angular_core.InputSignal<boolean>;
334
+ readonly disabled: _angular_core.InputSignal<boolean>;
335
+ readonly readonly: _angular_core.InputSignal<boolean>;
336
+ readonly clear: _angular_core.OutputEmitterRef<void>;
337
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvFieldShell, never>;
338
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvFieldShell, "zv-field-shell", never, { "for": { "alias": "for"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "errorText": { "alias": "errorText"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "prefixIcon": { "alias": "prefixIcon"; "required": false; "isSignal": true; }; "suffixIcon": { "alias": "suffixIcon"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "hasValue": { "alias": "hasValue"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; }, { "clear": "clear"; }, never, ["*"], true, never>;
339
+ }
340
+
341
+ /**
342
+ * Single-line text input. Signal-first: binds via `[(value)]`, or via a Signal
343
+ * Form using `[form]` + `controlName`.
344
+ *
345
+ * @example <zv-input [form]="form" controlName="firstName" label="First name" />
346
+ */
347
+ declare class ZvInput extends SignalControlAccessor<string> {
348
+ readonly controlType = "input";
349
+ readonly inputType: _angular_core.InputSignal<string>;
350
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvInput, never>;
351
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvInput, "zv-input", never, { "inputType": { "alias": "inputType"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
352
+ }
353
+
354
+ /**
355
+ * Base class shared by every Zellvora control.
356
+ *
357
+ * Implements `ControlValueAccessor` + `Validator` so the same component works
358
+ * unchanged across Template-Driven (`ngModel`), Reactive (`formControlName`)
359
+ * and Signal Forms (via the `zvSignal` directive). Internal state is held in
360
+ * signals, so views can run fully `OnPush` with no manual `markForCheck`.
361
+ *
362
+ * Concrete controls extend this, set `controlType`, and bind `[value]` /
363
+ * `(handleInput)` / `(handleBlur)` in their template.
364
+ */
365
+ declare abstract class ZvBaseControl<T = unknown> implements ControlValueAccessor, Validator {
366
+ protected readonly config: _zellvora_ng_input.ZvInputConfig;
367
+ protected readonly cdr: ChangeDetectorRef;
368
+ protected readonly destroyRef: DestroyRef;
369
+ /** Override in subclass: 'input' | 'email' | 'select' ... drives styling/ARIA. */
370
+ abstract readonly controlType: string;
371
+ get id(): string;
372
+ name?: string;
373
+ label?: string;
374
+ placeholder: string;
375
+ hint?: string;
376
+ helperText?: string;
377
+ errorMessage?: string;
378
+ prefixIcon?: string;
379
+ suffixIcon?: string;
380
+ tooltip?: string;
381
+ ariaLabel?: string;
382
+ autocomplete: string;
383
+ loadingText?: string;
384
+ tabIndex: number;
385
+ clearable: boolean;
386
+ readonly: boolean;
387
+ required: boolean;
388
+ loading: boolean;
389
+ floatingLabel: boolean;
390
+ minlength?: number;
391
+ maxlength?: number;
392
+ min?: number | string | Date;
393
+ max?: number | string | Date;
394
+ pattern?: string | RegExp;
395
+ mask?: string;
396
+ appearance: ZvAppearance;
397
+ size: ZvSize;
398
+ theme: ZvTheme;
399
+ color: ZvColor;
400
+ dir: ZvDir;
401
+ status: ZvStatus;
402
+ protected readonly _value: WritableSignal<T | null>;
403
+ protected readonly _disabled: WritableSignal<boolean>;
404
+ protected readonly _touched: WritableSignal<boolean>;
405
+ protected readonly _focused: WritableSignal<boolean>;
406
+ /** Public readonly value signal — useful for Signal Forms & templates. */
407
+ readonly valueSig: _angular_core.Signal<T | null>;
408
+ readonly disabledSig: _angular_core.Signal<boolean>;
409
+ readonly focusedSig: _angular_core.Signal<boolean>;
410
+ /** Has content for floating-label / empty-state styling. */
411
+ readonly hasValue: _angular_core.Signal<boolean>;
412
+ /** Enables `[(value)]`. */
413
+ readonly valueChange: EventEmitter<T | null>;
414
+ readonly input: EventEmitter<T | null>;
415
+ readonly change: EventEmitter<T | null>;
416
+ readonly focus: EventEmitter<FocusEvent>;
417
+ readonly blur: EventEmitter<FocusEvent>;
418
+ /** `[(value)]` setter for direct (non-forms) usage. */
419
+ set value(v: T | null);
420
+ get value(): T | null;
421
+ set disabled(v: boolean);
422
+ get disabled(): boolean;
423
+ /** A writable signal holding the form model, e.g. `signal({ name: '' })`. */
424
+ signal?: WritableSignal<Record<string, unknown>>;
425
+ /** Key within the signal model this control is bound to. */
426
+ controlName?: string;
427
+ private _onChange;
428
+ private _onTouched;
429
+ private _onValidatorChange;
430
+ constructor();
431
+ /** Signal Forms: push control -> model (called from setValue). */
432
+ private syncToSignal;
433
+ writeValue(value: T | null): void;
434
+ registerOnChange(fn: (v: T | null) => void): void;
435
+ registerOnTouched(fn: () => void): void;
436
+ setDisabledState(isDisabled: boolean): void;
437
+ validate(control: AbstractControl): ValidationErrors | null;
438
+ registerOnValidatorChange(fn: () => void): void;
439
+ /** Override to contribute control-specific validators (email, min, etc.). */
440
+ protected ownValidators(): ValidatorFn[];
441
+ /** Call when constraint inputs change so the parent re-runs validation. */
442
+ protected notifyValidatorChange(): void;
443
+ protected setValue(v: T | null, emitInput?: boolean): void;
444
+ protected handleInput(v: T | null): void;
445
+ protected handleChange(v: T | null): void;
446
+ protected handleFocus(ev: FocusEvent): void;
447
+ protected handleBlur(ev: FocusEvent): void;
448
+ /** Clear button handler. */
449
+ clear(): void;
450
+ get hostClasses(): Record<string, boolean>;
451
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvBaseControl<any>, never>;
452
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ZvBaseControl<any>, never, never, { "name": { "alias": "name"; "required": false; }; "label": { "alias": "label"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "hint": { "alias": "hint"; "required": false; }; "helperText": { "alias": "helperText"; "required": false; }; "errorMessage": { "alias": "errorMessage"; "required": false; }; "prefixIcon": { "alias": "prefixIcon"; "required": false; }; "suffixIcon": { "alias": "suffixIcon"; "required": false; }; "tooltip": { "alias": "tooltip"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "loadingText": { "alias": "loadingText"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "clearable": { "alias": "clearable"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "required": { "alias": "required"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "floatingLabel": { "alias": "floatingLabel"; "required": false; }; "minlength": { "alias": "minlength"; "required": false; }; "maxlength": { "alias": "maxlength"; "required": false; }; "min": { "alias": "min"; "required": false; }; "max": { "alias": "max"; "required": false; }; "pattern": { "alias": "pattern"; "required": false; }; "mask": { "alias": "mask"; "required": false; }; "appearance": { "alias": "appearance"; "required": false; }; "size": { "alias": "size"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "color": { "alias": "color"; "required": false; }; "dir": { "alias": "dir"; "required": false; }; "status": { "alias": "status"; "required": false; }; "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "signal": { "alias": "signal"; "required": false; }; "controlName": { "alias": "controlName"; "required": false; }; }, { "valueChange": "valueChange"; "input": "input"; "change": "change"; "focus": "focus"; "blur": "blur"; }, never, never, true, never>;
453
+ static ngAcceptInputType_tabIndex: unknown;
454
+ static ngAcceptInputType_clearable: unknown;
455
+ static ngAcceptInputType_readonly: unknown;
456
+ static ngAcceptInputType_required: unknown;
457
+ static ngAcceptInputType_loading: unknown;
458
+ static ngAcceptInputType_floatingLabel: unknown;
459
+ static ngAcceptInputType_minlength: unknown;
460
+ static ngAcceptInputType_maxlength: unknown;
461
+ static ngAcceptInputType_disabled: unknown;
462
+ }
463
+
464
+ /**
465
+ * Base for all single-line / multi-line text controls. Subclasses set
466
+ * `controlType`, the native `inputType`, and any extra validators.
467
+ */
468
+ declare abstract class ZvTextControlBase extends ZvBaseControl<string> {
469
+ /** Native input type; overridden per control (text/email/password/...). */
470
+ abstract readonly inputType: string;
471
+ maxRows: number;
472
+ protected onNativeInput(ev: Event): void;
473
+ protected onNativeChange(ev: Event): void;
474
+ protected ownValidators(): ValidatorFn[];
475
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvTextControlBase, never>;
476
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ZvTextControlBase, never, never, { "maxRows": { "alias": "maxRows"; "required": false; }; }, {}, never, never, true, never>;
477
+ }
478
+
479
+ declare class ZvEmail extends ZvTextControlBase {
480
+ readonly controlType = "email";
481
+ readonly inputType = "email";
482
+ autocomplete: string;
483
+ protected ownValidators(): ValidatorFn[];
484
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvEmail, never>;
485
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvEmail, "zv-email", never, {}, {}, never, never, true, never>;
486
+ }
487
+
488
+ declare class ZvPassword extends ZvTextControlBase {
489
+ readonly controlType = "password";
490
+ readonly inputType = "password";
491
+ autocomplete: string;
492
+ toggle: boolean;
493
+ strong: boolean;
494
+ readonly reveal: _angular_core.WritableSignal<boolean>;
495
+ protected ownValidators(): ValidatorFn[];
496
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvPassword, never>;
497
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvPassword, "zv-password", never, { "toggle": { "alias": "toggle"; "required": false; }; "strong": { "alias": "strong"; "required": false; }; }, {}, never, never, true, never>;
498
+ static ngAcceptInputType_toggle: unknown;
499
+ static ngAcceptInputType_strong: unknown;
500
+ }
501
+
502
+ declare class ZvNumber extends ZvBaseControl<number> {
503
+ readonly controlType = "number";
504
+ step: number;
505
+ protected onInput(ev: Event): void;
506
+ protected ownValidators(): ValidatorFn[];
507
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvNumber, never>;
508
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvNumber, "zv-number", never, { "step": { "alias": "step"; "required": false; }; }, {}, never, never, true, never>;
509
+ static ngAcceptInputType_step: unknown;
510
+ }
511
+
512
+ declare class ZvTextarea extends ZvTextControlBase {
513
+ readonly controlType = "textarea";
514
+ readonly inputType = "textarea";
515
+ rows: number;
516
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvTextarea, never>;
517
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvTextarea, "zv-textarea", never, { "rows": { "alias": "rows"; "required": false; }; }, {}, never, never, true, never>;
518
+ static ngAcceptInputType_rows: unknown;
519
+ }
520
+
521
+ /**
522
+ * Wraps the native date input for full a11y + parity, normalizing the value to
523
+ * an ISO `yyyy-MM-dd` string. Swap the inner element for a custom calendar
524
+ * without touching the CVA contract.
525
+ */
526
+ declare class ZvDatepicker extends ZvBaseControl<string> {
527
+ readonly controlType = "datepicker";
528
+ protected onInput(ev: Event): void;
529
+ protected ownValidators(): ValidatorFn[];
530
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvDatepicker, never>;
531
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvDatepicker, "zv-datepicker", never, {}, {}, never, never, true, never>;
532
+ }
533
+
534
+ declare class ZvTimepicker extends ZvBaseControl<string> {
535
+ readonly controlType = "timepicker";
536
+ protected onInput(ev: Event): void;
537
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvTimepicker, never>;
538
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvTimepicker, "zv-timepicker", never, {}, {}, never, never, true, never>;
539
+ }
540
+
541
+ /**
542
+ * Single-select with virtual-scrolled listbox + keyboard support.
543
+ * Accepts either `ZvOption[]` or a raw `T[]` via `bindLabel`/`bindValue`.
544
+ */
545
+ declare class ZvSelect<T = unknown> extends SignalControlAccessor<T> {
546
+ readonly controlType = "select";
547
+ readonly items: _angular_core.InputSignal<ZvOption<T>[] | T[]>;
548
+ readonly bindLabel: _angular_core.InputSignal<string>;
549
+ readonly bindValue: _angular_core.InputSignal<string>;
550
+ readonly open: _angular_core.WritableSignal<boolean>;
551
+ readonly options: _angular_core.Signal<ZvOption<T>[]>;
552
+ readonly selectedLabel: _angular_core.Signal<string>;
553
+ toggle(): void;
554
+ pick(o: ZvOption<T>): void;
555
+ onKeydown(ev: KeyboardEvent): void;
556
+ trackByValue: (_: number, o: ZvOption<T>) => unknown;
557
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvSelect<any>, never>;
558
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvSelect<any>, "zv-select", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "bindLabel": { "alias": "bindLabel"; "required": false; "isSignal": true; }; "bindValue": { "alias": "bindValue"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
559
+ }
560
+
561
+ declare class ZvMultiselect<T = unknown> extends ZvBaseControl<T[]> {
562
+ readonly controlType = "multiselect";
563
+ items: ZvOption<T>[] | T[];
564
+ bindLabel: string;
565
+ bindValue: string;
566
+ readonly open: _angular_core.WritableSignal<boolean>;
567
+ get options(): ZvOption<T>[];
568
+ readonly summary: _angular_core.Signal<string>;
569
+ isSelected: (v: T) => boolean;
570
+ toggle(): void;
571
+ picktoggle(o: ZvOption<T>): void;
572
+ trackByValue: (_: number, o: ZvOption<T>) => T;
573
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvMultiselect<any>, never>;
574
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvMultiselect<any>, "zv-multiselect", never, { "items": { "alias": "items"; "required": false; }; "bindLabel": { "alias": "bindLabel"; "required": false; }; "bindValue": { "alias": "bindValue"; "required": false; }; }, {}, never, never, true, never>;
575
+ }
576
+
577
+ declare class ZvCheckbox extends ZvBaseControl<boolean> {
578
+ readonly controlType = "checkbox";
579
+ protected onToggle(ev: Event): void;
580
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvCheckbox, never>;
581
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvCheckbox, "zv-checkbox", never, {}, {}, never, never, true, never>;
582
+ }
583
+
584
+ declare class ZvRadio<T = unknown> extends ZvBaseControl<T> {
585
+ readonly controlType = "radio";
586
+ items: ZvOption<T>[] | T[];
587
+ bindLabel: string;
588
+ bindValue: string;
589
+ get options(): ZvOption<T>[];
590
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvRadio<any>, never>;
591
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvRadio<any>, "zv-radio", never, { "items": { "alias": "items"; "required": false; }; "bindLabel": { "alias": "bindLabel"; "required": false; }; "bindValue": { "alias": "bindValue"; "required": false; }; }, {}, never, never, true, never>;
592
+ }
593
+
594
+ declare class ZvSwitch extends ZvBaseControl<boolean> {
595
+ readonly controlType = "switch";
596
+ protected onToggle(ev: Event): void;
597
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvSwitch, never>;
598
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvSwitch, "zv-switch", never, {}, {}, never, never, true, never>;
599
+ }
600
+
601
+ declare class ZvPin extends ZvBaseControl<string> {
602
+ readonly controlType = "pin";
603
+ length: number;
604
+ masked: boolean;
605
+ get cells(): number[];
606
+ digitAt(i: number): string;
607
+ onCell(i: number, ev: Event): void;
608
+ onKey(i: number, ev: KeyboardEvent): void;
609
+ private focusCell;
610
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvPin, never>;
611
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvPin, "zv-pin", never, { "length": { "alias": "length"; "required": false; }; "masked": { "alias": "masked"; "required": false; }; }, {}, never, never, true, never>;
612
+ static ngAcceptInputType_length: unknown;
613
+ }
614
+
615
+ declare class ZvUpload extends ZvBaseControl<File[]> {
616
+ readonly controlType = "upload";
617
+ multiple: boolean;
618
+ accept: string;
619
+ readonly dragging: _angular_core.WritableSignal<boolean>;
620
+ readonly files: _angular_core.WritableSignal<File[]>;
621
+ onPick(ev: Event): void;
622
+ onDrop(ev: DragEvent): void;
623
+ private commit;
624
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvUpload, never>;
625
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZvUpload, "zv-upload", never, { "multiple": { "alias": "multiple"; "required": false; }; "accept": { "alias": "accept"; "required": false; }; }, {}, never, never, true, never>;
626
+ static ngAcceptInputType_multiple: unknown;
627
+ }
628
+
629
+ declare class ZvControlValueAccessor implements ControlValueAccessor {
630
+ private readonly host;
631
+ private onChange;
632
+ private onTouched;
633
+ constructor();
634
+ writeValue(value: unknown): void;
635
+ registerOnChange(fn: (v: unknown) => void): void;
636
+ registerOnTouched(fn: () => void): void;
637
+ setDisabledState(isDisabled: boolean): void;
638
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZvControlValueAccessor, never>;
639
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ZvControlValueAccessor, "zv-input[formControl],zv-input[formControlName],zv-input[ngModel],zv-email[formControl],zv-email[formControlName],zv-email[ngModel],zv-password[formControl],zv-password[formControlName],zv-password[ngModel],zv-number[formControl],zv-number[formControlName],zv-number[ngModel],zv-textarea[formControl],zv-textarea[formControlName],zv-textarea[ngModel],zv-select[formControl],zv-select[formControlName],zv-select[ngModel],zv-multiselect[formControl],zv-multiselect[formControlName],zv-multiselect[ngModel],zv-checkbox[formControl],zv-checkbox[formControlName],zv-checkbox[ngModel],zv-radio[formControl],zv-radio[formControlName],zv-radio[ngModel],zv-switch[formControl],zv-switch[formControlName],zv-switch[ngModel],zv-datepicker[formControl],zv-datepicker[formControlName],zv-datepicker[ngModel],zv-timepicker[formControl],zv-timepicker[formControlName],zv-timepicker[ngModel],zv-pin[formControl],zv-pin[formControlName],zv-pin[ngModel],zv-upload[formControl],zv-upload[formControlName],zv-upload[ngModel]", never, {}, {}, never, never, true, never>;
640
+ }
641
+
642
+ /**
643
+ * Reactive/Template validator bridge.
644
+ *
645
+ * Wraps the *same* signal `ZvValidators` as Angular `ValidatorFn`s so Reactive
646
+ * and Template forms reuse identical logic — zero duplication.
647
+ *
648
+ * @example
649
+ * new FormControl('', [toNgValidator(ZvValidators.required), toNgValidator(ZvValidators.email)])
650
+ */
651
+
652
+ declare function toNgValidator(v: ZvValidator): ValidatorFn;
653
+ declare function toNgAsyncValidator(v: ZvAsyncValidator): AsyncValidatorFn;
654
+ /** Convenience: map many ZvValidators to one Angular ValidatorFn list. */
655
+ declare const ngValidators: (...vs: ZvValidator[]) => ValidatorFn[];
656
+
657
+ /** Default human-readable messages for built-in validator error keys. */
658
+ declare const ZV_DEFAULT_MESSAGES: Record<string, (info: unknown) => string>;
659
+ /** Resolve the first error in `errors` to a display string. */
660
+ declare function formatError(errors: ZvErrors, overrides?: Record<string, string>): string | null;
661
+
662
+ export { SignalControlAccessor, ZV_DEFAULT_CONFIG, ZV_DEFAULT_MESSAGES, ZV_INPUT_CONFIG, ZV_PATTERNS, ZvCheckbox, ZvControlValueAccessor, ZvDatepicker, ZvEmail, ZvFieldShell, ZvInput, ZvMultiselect, ZvNumber, ZvPassword, ZvPin, ZvRadio, ZvSelect, ZvSwitch, ZvTextarea, ZvTimepicker, ZvUpload, ZvValidators, createForm, formatError, ngValidators, provideSignalControl, provideZvInput, toNgAsyncValidator, toNgValidator };
663
+ export type { ZvAppearance, ZvAsyncValidator, ZvColor, ZvControl, ZvControlStatus, ZvDir, ZvErrors, ZvFieldConfig, ZvFormOptions, ZvFormSchema, ZvInputConfig, ZvOption, ZvSignalForm, ZvSize, ZvStatus, ZvTheme, ZvValidator };