@arsedizioni/ars-utils 22.6.86 → 22.6.89

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.
Files changed (79) hide show
  1. package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +3158 -3344
  2. package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs.map +1 -1
  3. package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs +7616 -4772
  4. package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs.map +1 -1
  5. package/fesm2022/arsedizioni-ars-utils-core.date.mjs +321 -702
  6. package/fesm2022/arsedizioni-ars-utils-core.date.mjs.map +1 -1
  7. package/fesm2022/arsedizioni-ars-utils-core.markdown.mjs +445 -590
  8. package/fesm2022/arsedizioni-ars-utils-core.markdown.mjs.map +1 -1
  9. package/fesm2022/arsedizioni-ars-utils-core.mjs +1735 -2370
  10. package/fesm2022/arsedizioni-ars-utils-core.mjs.map +1 -1
  11. package/fesm2022/arsedizioni-ars-utils-core.validators.mjs +1280 -1470
  12. package/fesm2022/arsedizioni-ars-utils-core.validators.mjs.map +1 -1
  13. package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +1097 -1528
  14. package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs.map +1 -1
  15. package/fesm2022/arsedizioni-ars-utils-support.common.mjs +198 -294
  16. package/fesm2022/arsedizioni-ars-utils-support.common.mjs.map +1 -1
  17. package/fesm2022/arsedizioni-ars-utils-ui.controls.date.mjs +115 -117
  18. package/fesm2022/arsedizioni-ars-utils-ui.controls.date.mjs.map +1 -1
  19. package/fesm2022/arsedizioni-ars-utils-ui.controls.mjs +1607 -613
  20. package/fesm2022/arsedizioni-ars-utils-ui.controls.mjs.map +1 -1
  21. package/fesm2022/arsedizioni-ars-utils-ui.controls.tree.mjs +840 -367
  22. package/fesm2022/arsedizioni-ars-utils-ui.controls.tree.mjs.map +1 -1
  23. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.auth.mjs +1634 -651
  24. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.auth.mjs.map +1 -1
  25. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.mjs +1255 -792
  26. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.mjs.map +1 -1
  27. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.prompt.mjs +1410 -357
  28. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.prompt.mjs.map +1 -1
  29. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.select.mjs +2401 -944
  30. package/fesm2022/arsedizioni-ars-utils-ui.dialogs.select.mjs.map +1 -1
  31. package/fesm2022/arsedizioni-ars-utils-ui.files.mjs +1553 -741
  32. package/fesm2022/arsedizioni-ars-utils-ui.files.mjs.map +1 -1
  33. package/fesm2022/arsedizioni-ars-utils-ui.filters.mjs +901 -430
  34. package/fesm2022/arsedizioni-ars-utils-ui.filters.mjs.map +1 -1
  35. package/fesm2022/arsedizioni-ars-utils-ui.help.mjs +737 -530
  36. package/fesm2022/arsedizioni-ars-utils-ui.help.mjs.map +1 -1
  37. package/fesm2022/arsedizioni-ars-utils-ui.mjs +6638 -1755
  38. package/fesm2022/arsedizioni-ars-utils-ui.mjs.map +1 -1
  39. package/fesm2022/arsedizioni-ars-utils-ui.navigation.mjs +1479 -1207
  40. package/fesm2022/arsedizioni-ars-utils-ui.navigation.mjs.map +1 -1
  41. package/fesm2022/arsedizioni-ars-utils-ui.notifications.mjs +1003 -270
  42. package/fesm2022/arsedizioni-ars-utils-ui.notifications.mjs.map +1 -1
  43. package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs +497 -278
  44. package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs.map +1 -1
  45. package/fesm2022/arsedizioni-ars-utils-ui.paginator.mjs +48 -52
  46. package/fesm2022/arsedizioni-ars-utils-ui.paginator.mjs.map +1 -1
  47. package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs +464 -704
  48. package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs.map +1 -1
  49. package/fesm2022/arsedizioni-ars-utils-ui.tinymce.mjs +724 -657
  50. package/fesm2022/arsedizioni-ars-utils-ui.tinymce.mjs.map +1 -1
  51. package/fesm2022/arsedizioni-ars-utils.mjs +3 -19
  52. package/fesm2022/arsedizioni-ars-utils.mjs.map +1 -1
  53. package/package.json +1 -1
  54. package/types/arsedizioni-ars-utils-clipper.common.d.ts +1151 -1163
  55. package/types/arsedizioni-ars-utils-clipper.ui.d.ts +1588 -1426
  56. package/types/arsedizioni-ars-utils-core.d.ts +1169 -1172
  57. package/types/arsedizioni-ars-utils-core.date.d.ts +204 -208
  58. package/types/arsedizioni-ars-utils-core.markdown.d.ts +128 -126
  59. package/types/arsedizioni-ars-utils-core.validators.d.ts +270 -236
  60. package/types/arsedizioni-ars-utils-evolution.common.d.ts +1054 -1067
  61. package/types/arsedizioni-ars-utils-support.common.d.ts +225 -234
  62. package/types/arsedizioni-ars-utils-ui.controls.d.ts +440 -278
  63. package/types/arsedizioni-ars-utils-ui.controls.date.d.ts +24 -28
  64. package/types/arsedizioni-ars-utils-ui.controls.tree.d.ts +172 -136
  65. package/types/arsedizioni-ars-utils-ui.d.ts +2035 -821
  66. package/types/arsedizioni-ars-utils-ui.dialogs.auth.d.ts +327 -322
  67. package/types/arsedizioni-ars-utils-ui.dialogs.d.ts +343 -347
  68. package/types/arsedizioni-ars-utils-ui.dialogs.prompt.d.ts +167 -167
  69. package/types/arsedizioni-ars-utils-ui.dialogs.select.d.ts +373 -367
  70. package/types/arsedizioni-ars-utils-ui.files.d.ts +335 -283
  71. package/types/arsedizioni-ars-utils-ui.filters.d.ts +232 -160
  72. package/types/arsedizioni-ars-utils-ui.help.d.ts +204 -211
  73. package/types/arsedizioni-ars-utils-ui.navigation.d.ts +811 -646
  74. package/types/arsedizioni-ars-utils-ui.notifications.d.ts +74 -78
  75. package/types/arsedizioni-ars-utils-ui.oauth.d.ts +102 -62
  76. package/types/arsedizioni-ars-utils-ui.paginator.d.ts +19 -22
  77. package/types/arsedizioni-ars-utils-ui.shell.d.ts +376 -382
  78. package/types/arsedizioni-ars-utils-ui.tinymce.d.ts +244 -231
  79. package/types/arsedizioni-ars-utils.d.ts +1 -3
@@ -1,1525 +1,1335 @@
1
- import * as i0 from '@angular/core';
2
- import { input, Directive, forwardRef, effect, inject, DestroyRef } from '@angular/core';
3
- import { NG_VALIDATORS } from '@angular/forms';
4
- import { SystemUtils } from '@arsedizioni/ars-utils/core';
5
- import { endOfDay, startOfDay } from 'date-fns';
6
- import { validate } from '@angular/forms/signals';
7
-
8
- /**
9
- * Directive that delegates validation to an externally provided validator function.
10
- * Bind `[validator]="myFn"` where `myFn` is `(c: AbstractControl) => ValidationErrors | null`.
11
- */
12
- class ValidatorDirective {
13
- constructor() {
14
- /** The custom validator function to apply. */
15
- this.validator = input(undefined, /* @ts-ignore */
16
- ...(ngDevMode ? [{ debugName: "validator" }] : /* istanbul ignore next */ []));
17
- }
18
- /**
19
- * Invokes the provided validator function against the given control.
20
- * Returns `null` (valid) when no function is bound.
21
- * @param control - The form control to validate.
22
- */
23
- validate(control) {
24
- const fn = this.validator();
25
- return fn ? fn(control) : null;
26
- }
27
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
28
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: ValidatorDirective, isStandalone: true, selector: "[validator]", inputs: { validator: { classPropertyName: "validator", publicName: "validator", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true }], ngImport: i0 }); }
29
- }
30
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ValidatorDirective, decorators: [{
31
- type: Directive,
32
- args: [{
33
- selector: '[validator]',
34
- providers: [{ provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true }],
35
- standalone: true,
36
- }]
37
- }], propDecorators: { validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }] } });
38
-
39
- /**
40
- * Directive that validates a control using the host object's `isValid()` method
41
- * or a boolean expression passed via `[validIf]`.
42
- */
43
- class ValidIfDirective {
44
- constructor() {
45
- /** When `true`, the control is considered valid regardless of the bound value. */
46
- this.validIf = input(false, /* @ts-ignore */
47
- ...(ngDevMode ? [{ debugName: "validIf" }] : /* istanbul ignore next */ []));
48
- }
49
- /**
50
- * Validates the control value against a boolean flag or the value's own `isValid()` method.
51
- * @param control - The form control to validate.
52
- */
53
- validate(control) {
54
- let isValid = false;
55
- const c = control.value ? control.value : null;
56
- if (!c) {
57
- isValid = this.validIf() === true;
58
- }
59
- else {
60
- try {
61
- isValid = c.isValid();
62
- }
63
- catch { }
64
- }
65
- return isValid ? null : { validIf: "Non valido." };
66
- }
67
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ValidIfDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
68
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: ValidIfDirective, isStandalone: true, selector: "[validIf]", inputs: { validIf: { classPropertyName: "validIf", publicName: "validIf", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
69
- {
70
- provide: NG_VALIDATORS,
71
- useExisting: forwardRef(() => ValidIfDirective),
72
- multi: true,
73
- },
74
- ], ngImport: i0 }); }
75
- }
76
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: ValidIfDirective, decorators: [{
77
- type: Directive,
78
- args: [{
79
- selector: "[validIf]",
80
- providers: [
81
- {
82
- provide: NG_VALIDATORS,
83
- useExisting: forwardRef(() => ValidIfDirective),
84
- multi: true,
85
- },
86
- ],
87
- standalone: true,
88
- }]
89
- }], propDecorators: { validIf: [{ type: i0.Input, args: [{ isSignal: true, alias: "validIf", required: false }] }] } });
90
-
91
- /**
92
- * Directive that validates that the host control's value equals the value of another control.
93
- * Bind `[equals]="otherControl"`.
94
- *
95
- * The host control is re-validated whenever the OTHER control's value changes:
96
- * without this, typing a new password AFTER the confirmation field was filled
97
- * left the form incorrectly valid (the classic password/confirm bug).
98
- *
99
- * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the
100
- * other control's `valueChanges` runs with `{ emitEvent: false }`. Calling
101
- * Angular's `onValidatorChange` instead would re-emit valueChanges, so a
102
- * reciprocal setup (A [equals]=B and B [equals]=A) would overflow the stack.
103
- */
104
- class EqualsValidatorDirective {
105
- constructor() {
106
- /** The control whose value must match the host control's value. */
107
- this.equals = input(undefined, /* @ts-ignore */
108
- ...(ngDevMode ? [{ debugName: "equals" }] : /* istanbul ignore next */ []));
109
- // Re-subscribe whenever the [equals] binding points to a different control,
110
- // and re-validate the host on every change of the other control.
111
- effect(() => {
112
- const other = this.equals();
113
- this.subscription?.unsubscribe();
114
- this.subscription = other?.valueChanges.subscribe(() =>
115
- // emitEvent:false breaks the reciprocal valueChanges loop (see class doc).
116
- this.hostControl?.updateValueAndValidity({ emitEvent: false }));
117
- // Re-validate the host when the bound control itself is swapped.
118
- this.hostControl?.updateValueAndValidity({ emitEvent: false });
119
- });
120
- inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
121
- }
122
- /**
123
- * Validates that the host control value equals the bound control's value.
124
- * Returns `null` (valid) when no control is bound.
125
- * @param control - The form control to validate.
126
- * @returns `null` when valid, `{ equals: ... }` otherwise.
127
- */
128
- validate(control) {
129
- this.hostControl = control;
130
- const eq = this.equals();
131
- if (!eq)
132
- return null;
133
- return eq.value === control.value ? null : { equals: "Non valido." };
134
- }
135
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: EqualsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
136
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: EqualsValidatorDirective, isStandalone: true, selector: "[equals]", inputs: { equals: { classPropertyName: "equals", publicName: "equals", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
137
- {
138
- provide: NG_VALIDATORS,
139
- useExisting: forwardRef(() => EqualsValidatorDirective),
140
- multi: true,
141
- },
142
- ], ngImport: i0 }); }
143
- }
144
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: EqualsValidatorDirective, decorators: [{
145
- type: Directive,
146
- args: [{
147
- selector: "[equals]",
148
- providers: [
149
- {
150
- provide: NG_VALIDATORS,
151
- useExisting: forwardRef(() => EqualsValidatorDirective),
152
- multi: true,
153
- },
154
- ],
155
- standalone: true,
156
- }]
157
- }], ctorParameters: () => [], propDecorators: { equals: [{ type: i0.Input, args: [{ isSignal: true, alias: "equals", required: false }] }] } });
158
-
159
- /**
160
- * Directive that validates that the host control's value is different from another control's value.
161
- * Bind `[notEqual]="otherControl"`.
162
- *
163
- * The host control is re-validated whenever the OTHER control's value changes,
164
- * so editing either field keeps both error states consistent.
165
- *
166
- * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the
167
- * other control's `valueChanges` is run with `{ emitEvent: false }`. Using
168
- * Angular's `onValidatorChange` here instead would call `host.updateValueAndValidity()`
169
- * WITH events, so a reciprocal setup (A [notEqual]=B and B [notEqual]=A) would
170
- * ping-pong valueChanges between the two controls and overflow the stack.
171
- */
172
- class NotEqualValidatorDirective {
173
- constructor() {
174
- /** The control whose value must differ from the host control's value. */
175
- this.notEqual = input(undefined, /* @ts-ignore */
176
- ...(ngDevMode ? [{ debugName: "notEqual" }] : /* istanbul ignore next */ []));
177
- effect(() => {
178
- const other = this.notEqual();
179
- this.subscription?.unsubscribe();
180
- this.subscription = other?.valueChanges.subscribe(() =>
181
- // Re-validate the host WITHOUT emitting valueChanges, otherwise a
182
- // reciprocal binding would loop forever (see class doc).
183
- this.hostControl?.updateValueAndValidity({ emitEvent: false }));
184
- // Re-validate the host when the bound control itself is swapped.
185
- this.hostControl?.updateValueAndValidity({ emitEvent: false });
186
- });
187
- inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
188
- }
189
- /**
190
- * Validates that the host control value is not equal to the bound control's value.
191
- * Also clears the `notequal` error on the other control when the host becomes valid.
192
- * Returns `null` (valid) when no control is bound.
193
- * @param control - The form control to validate.
194
- * @returns `null` when valid, `{ notequal: true }` otherwise.
195
- */
196
- validate(control) {
197
- this.hostControl = control;
198
- const notEqual = this.notEqual();
199
- if (!notEqual)
200
- return null;
201
- const isValid = (!notEqual.value && !control.value) || (notEqual.value !== control.value);
202
- const errors = isValid ? null : { notequal: true };
203
- if (errors) {
204
- control.markAsTouched();
205
- }
206
- else if (notEqual.hasError('notequal')) {
207
- const { notequal: _removed, ...rest } = notEqual.errors ?? {};
208
- // emitEvent:false on both: clearing the partner's error must not feed
209
- // back through valueChanges/statusChanges into this validator.
210
- notEqual.setErrors(Object.keys(rest).length > 0 ? rest : null, { emitEvent: false });
211
- notEqual.updateValueAndValidity({ onlySelf: true, emitEvent: false });
212
- notEqual.markAsTouched();
213
- notEqual.markAsDirty();
214
- }
215
- return errors;
216
- }
217
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotEqualValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
218
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: NotEqualValidatorDirective, isStandalone: true, selector: "[notEqual]", inputs: { notEqual: { classPropertyName: "notEqual", publicName: "notEqual", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
219
- {
220
- provide: NG_VALIDATORS,
221
- useExisting: forwardRef(() => NotEqualValidatorDirective),
222
- multi: true,
223
- },
224
- ], ngImport: i0 }); }
225
- }
226
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotEqualValidatorDirective, decorators: [{
227
- type: Directive,
228
- args: [{
229
- selector: "[notEqual]",
230
- providers: [
231
- {
232
- provide: NG_VALIDATORS,
233
- useExisting: forwardRef(() => NotEqualValidatorDirective),
234
- multi: true,
235
- },
236
- ],
237
- standalone: true,
238
- }]
239
- }], ctorParameters: () => [], propDecorators: { notEqual: [{ type: i0.Input, args: [{ isSignal: true, alias: "notEqual", required: false }] }] } });
240
-
241
- /**
242
- * Directive that validates a semicolon-separated list of email addresses.
243
- * Apply `emails` to a text input containing one or more addresses separated by `;`.
244
- */
245
- class EmailsValidatorDirective {
246
- /**
247
- * Validates each address in a semicolon-separated email list.
248
- * Returns `null` when the control is empty.
249
- * @param control - The form control to validate.
250
- */
251
- validate(control) {
252
- const input = control.value;
253
- if (!input || input.length === 0)
254
- return null;
255
- const parts = input.replaceAll(/\r\n/g, '').split(';');
256
- const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));
257
- return isValid ? null : { emails: "Elenco non valido." };
258
- }
259
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: EmailsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
260
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: EmailsValidatorDirective, isStandalone: true, selector: "[emails]", providers: [
261
- {
262
- provide: NG_VALIDATORS,
263
- useExisting: forwardRef(() => EmailsValidatorDirective),
264
- multi: true,
265
- },
266
- ], ngImport: i0 }); }
267
- }
268
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: EmailsValidatorDirective, decorators: [{
269
- type: Directive,
270
- args: [{
271
- selector: "[emails]",
272
- providers: [
273
- {
274
- provide: NG_VALIDATORS,
275
- useExisting: forwardRef(() => EmailsValidatorDirective),
276
- multi: true,
277
- },
278
- ],
279
- standalone: true,
280
- }]
281
- }] });
282
-
283
- /**
284
- * Directive that validates a control value as a GUID / UUID string.
285
- * Apply `guid` to a text input that expects a valid UUID.
286
- */
287
- class GuidValidatorDirective {
288
- /**
289
- * Validates that the control value is a well-formed GUID / UUID.
290
- * Returns `null` when the control is empty.
291
- * @param control - The form control to validate.
292
- */
293
- validate(control) {
294
- const input = control.value;
295
- if (!input || input.length === 0)
296
- return null;
297
- return SystemUtils.parseUUID(input) ? null : { guid: "Non valido." };
298
- }
299
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: GuidValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
300
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: GuidValidatorDirective, isStandalone: true, selector: "[guid]", providers: [
301
- {
302
- provide: NG_VALIDATORS,
303
- useExisting: forwardRef(() => GuidValidatorDirective),
304
- multi: true,
305
- },
306
- ], ngImport: i0 }); }
307
- }
308
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: GuidValidatorDirective, decorators: [{
309
- type: Directive,
310
- args: [{
311
- selector: "[guid]",
312
- providers: [
313
- {
314
- provide: NG_VALIDATORS,
315
- useExisting: forwardRef(() => GuidValidatorDirective),
316
- multi: true,
317
- },
318
- ],
319
- standalone: true,
320
- }]
321
- }] });
322
-
323
- /**
324
- * Directive that validates a control value as a parseable SQL-compatible date string.
325
- * Apply `sqlDate` to a text input that expects a date after year 1750.
326
- */
327
- class SqlDateValidatorDirective {
328
- /**
329
- * Validates that the control value can be parsed as a date after 1750.
330
- * Returns `null` when the control is empty.
331
- * @param control - The form control to validate.
332
- */
333
- validate(control) {
334
- const input = control.value;
335
- if (!input || input.length === 0)
336
- return null;
337
- const parsed = SystemUtils.parseDate(input);
338
- if (!parsed)
339
- return { sqlDate: "Non valido." };
340
- const d = endOfDay(parsed);
341
- return d.getFullYear() > 1750 ? null : { sqlDate: "Non valido." };
342
- }
343
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SqlDateValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
344
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: SqlDateValidatorDirective, isStandalone: true, selector: "[sqlDate]", providers: [
345
- {
346
- provide: NG_VALIDATORS,
347
- useExisting: forwardRef(() => SqlDateValidatorDirective),
348
- multi: true,
349
- },
350
- ], ngImport: i0 }); }
351
- }
352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SqlDateValidatorDirective, decorators: [{
353
- type: Directive,
354
- args: [{
355
- selector: "[sqlDate]",
356
- providers: [
357
- {
358
- provide: NG_VALIDATORS,
359
- useExisting: forwardRef(() => SqlDateValidatorDirective),
360
- multi: true,
361
- },
362
- ],
363
- standalone: true,
364
- }]
365
- }] });
366
-
367
- /**
368
- * Directive that validates that a control value is not a future date.
369
- * Apply `notFuture` to a text input that expects a date on or before today.
370
- */
371
- class NotFutureValidatorDirective {
372
- /**
373
- * Validates that the control value represents a date that is not in the future.
374
- * Returns `null` when the control is empty.
375
- * @param control - The form control to validate.
376
- */
377
- validate(control) {
378
- const input = control.value;
379
- if (!input || input.length === 0)
380
- return null;
381
- const parsed = SystemUtils.parseDate(input);
382
- if (!parsed)
383
- return { notFuture: "Non valido." };
384
- const today = endOfDay(new Date());
385
- const d = endOfDay(parsed);
386
- return d <= today ? null : { notFuture: "Non valido." };
387
- }
388
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotFutureValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
389
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: NotFutureValidatorDirective, isStandalone: true, selector: "[notFuture]", providers: [
390
- {
391
- provide: NG_VALIDATORS,
392
- useExisting: forwardRef(() => NotFutureValidatorDirective),
393
- multi: true,
394
- },
395
- ], ngImport: i0 }); }
396
- }
397
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotFutureValidatorDirective, decorators: [{
398
- type: Directive,
399
- args: [{
400
- selector: "[notFuture]",
401
- providers: [
402
- {
403
- provide: NG_VALIDATORS,
404
- useExisting: forwardRef(() => NotFutureValidatorDirective),
405
- multi: true,
406
- },
407
- ],
408
- standalone: true,
409
- }]
410
- }] });
411
-
412
- /**
413
- * Directive that validates a control value as a well-formed URL.
414
- * Apply `url` to a text input that expects a URL.
415
- */
416
- class UrlValidatorDirective {
417
- /**
418
- * Validates that the control value is a well-formed URL.
419
- * Returns `null` (valid) when the control is empty.
420
- * @param control - The form control to validate.
421
- */
422
- validate(control) {
423
- const input = control.value;
424
- if (!input || input.length === 0)
425
- return null;
426
- return SystemUtils.parseUrl(input) ? null : { url: "Non valido." };
427
- }
428
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UrlValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
429
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: UrlValidatorDirective, isStandalone: true, selector: "[url]", providers: [
430
- {
431
- provide: NG_VALIDATORS,
432
- useExisting: forwardRef(() => UrlValidatorDirective),
433
- multi: true,
434
- },
435
- ], ngImport: i0 }); }
436
- }
437
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UrlValidatorDirective, decorators: [{
438
- type: Directive,
439
- args: [{
440
- selector: "[url]",
441
- providers: [
442
- {
443
- provide: NG_VALIDATORS,
444
- useExisting: forwardRef(() => UrlValidatorDirective),
445
- multi: true,
446
- },
447
- ],
448
- standalone: true,
449
- }]
450
- }] });
451
-
452
- /**
453
- * Directive that validates a file size against configurable minimum and maximum bounds.
454
- * Bind `[fileSize]` together with `[size]="fileSizeInMb"`, `[maxSizeMb]`, and `[minSizeMb]`.
455
- */
456
- class FileSizeValidatorDirective {
457
- constructor() {
458
- /** Maximum allowed file size in megabytes. Defaults to 5. */
459
- this.maxSizeMb = input(5, /* @ts-ignore */
460
- ...(ngDevMode ? [{ debugName: "maxSizeMb" }] : /* istanbul ignore next */ []));
461
- /** Minimum required file size in megabytes. Defaults to 0. */
462
- this.minSizeMb = input(0, /* @ts-ignore */
463
- ...(ngDevMode ? [{ debugName: "minSizeMb" }] : /* istanbul ignore next */ []));
464
- /** The actual file size in megabytes to validate against the bounds. */
465
- this.size = input(undefined, /* @ts-ignore */
466
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
467
- }
468
- /**
469
- * Validates that the bound file size falls within the configured min/max range.
470
- * Returns `null` when no control value is present.
471
- * @param control - The form control to validate.
472
- */
473
- validate(control) {
474
- const input = control.value;
475
- if (!input)
476
- return null;
477
- const s = this.size() ?? 0;
478
- const isValid = s <= this.maxSizeMb() && s >= this.minSizeMb();
479
- return isValid ? null : { fileSize: "Non valido." };
480
- }
481
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: FileSizeValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
482
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: FileSizeValidatorDirective, isStandalone: true, selector: "[fileSize]", inputs: { maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, minSizeMb: { classPropertyName: "minSizeMb", publicName: "minSizeMb", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
483
- {
484
- provide: NG_VALIDATORS,
485
- useExisting: forwardRef(() => FileSizeValidatorDirective),
486
- multi: true,
487
- },
488
- ], ngImport: i0 }); }
489
- }
490
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: FileSizeValidatorDirective, decorators: [{
491
- type: Directive,
492
- args: [{
493
- selector: "[fileSize]",
494
- providers: [
495
- {
496
- provide: NG_VALIDATORS,
497
- useExisting: forwardRef(() => FileSizeValidatorDirective),
498
- multi: true,
499
- },
500
- ],
501
- standalone: true,
502
- }]
503
- }], propDecorators: { maxSizeMb: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeMb", required: false }] }], minSizeMb: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSizeMb", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
504
-
505
- /**
506
- * Directive that validates that a control value does not exceed a maximum word count.
507
- * Bind `[maxTerms]="10"` to allow at most 10 whitespace-separated terms.
508
- */
509
- class MaxTermsValidatorDirective {
510
- constructor() {
511
- /** The maximum number of whitespace-separated terms allowed. */
512
- this.maxTerms = input(0, /* @ts-ignore */
513
- ...(ngDevMode ? [{ debugName: "maxTerms" }] : /* istanbul ignore next */ []));
514
- }
515
- /**
516
- * Validates that the control value contains no more than the configured number of terms.
517
- * Returns `null` when the control is empty.
518
- * @param control - The form control to validate.
519
- */
520
- validate(control) {
521
- const input = control.value;
522
- if (!input)
523
- return null;
524
- const terms = input.match(/\S+/g)?.length ?? 0;
525
- return terms <= this.maxTerms() ? null : { maxTerms: "Non valido." };
526
- }
527
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MaxTermsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
528
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: MaxTermsValidatorDirective, isStandalone: true, selector: "[maxTerms]", inputs: { maxTerms: { classPropertyName: "maxTerms", publicName: "maxTerms", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
529
- {
530
- provide: NG_VALIDATORS,
531
- useExisting: forwardRef(() => MaxTermsValidatorDirective),
532
- multi: true,
533
- },
534
- ], ngImport: i0 }); }
535
- }
536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MaxTermsValidatorDirective, decorators: [{
537
- type: Directive,
538
- args: [{
539
- selector: "[maxTerms]",
540
- providers: [
541
- {
542
- provide: NG_VALIDATORS,
543
- useExisting: forwardRef(() => MaxTermsValidatorDirective),
544
- multi: true,
545
- },
546
- ],
547
- standalone: true,
548
- }]
549
- }], propDecorators: { maxTerms: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTerms", required: false }] }] } });
550
-
551
- /**
552
- * Directive that validates a control value as a sufficiently strong password.
553
- * Apply `password` to a password input.
554
- */
555
- class PasswordValidatorDirective {
556
- /**
557
- * Validates that the control value meets the minimum password-strength requirements.
558
- * @param control - The form control to validate.
559
- */
560
- validate(control) {
561
- const input = control.value ?? '';
562
- const strength = SystemUtils.calculatePasswordStrength(input);
563
- return strength.isValid ? null : { password: "Non valido." };
564
- }
565
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: PasswordValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
566
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: PasswordValidatorDirective, isStandalone: true, selector: "[password]", providers: [
567
- {
568
- provide: NG_VALIDATORS,
569
- useExisting: forwardRef(() => PasswordValidatorDirective),
570
- multi: true,
571
- },
572
- ], ngImport: i0 }); }
573
- }
574
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: PasswordValidatorDirective, decorators: [{
575
- type: Directive,
576
- args: [{
577
- selector: "[password]",
578
- providers: [
579
- {
580
- provide: NG_VALIDATORS,
581
- useExisting: forwardRef(() => PasswordValidatorDirective),
582
- multi: true,
583
- },
584
- ],
585
- standalone: true,
586
- }]
587
- }] });
588
-
589
- /**
590
- * Directive that validates a time string against optional allowed time slot ranges.
591
- * Bind `[time]` and optionally `[slots]="'08:00-12:00|14:00-18:00'"` (pipe-separated ranges).
592
- */
593
- class TimeValidatorDirective {
594
- constructor() {
595
- /** Optional pipe-separated list of allowed time ranges, e.g. `"08:00-12:00|14:00-18:00"`. */
596
- this.slots = input(undefined, /* @ts-ignore */
597
- ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
598
- }
599
- /**
600
- * Parses a `"HH:MM"` time string into a comparable integer (e.g. `"09:30"` -> `930`).
601
- * Returns `-1` when the string is not a valid time.
602
- * @param value - The time string to parse.
603
- */
604
- getTime(value) {
605
- const p = value.split(':');
606
- if (p.length !== 2)
607
- return -1;
608
- const hh = parseInt(p[0], 10);
609
- if (isNaN(hh) || hh < 0 || hh > 23)
610
- return -1;
611
- const mm = parseInt(p[1], 10);
612
- if (isNaN(mm) || mm < 0 || mm > 59)
613
- return -1;
614
- return hh * 100 + mm;
615
- }
616
- /**
617
- * Validates that the control value is a valid time string and, when slots are configured,
618
- * that it falls within at least one of the allowed ranges.
619
- * Returns `null` when the control is empty.
620
- * @param control - The form control to validate.
621
- */
622
- validate(control) {
623
- const input = control.value;
624
- if (!input || input.length === 0)
625
- return null;
626
- const t = this.getTime(input);
627
- if (t === -1)
628
- return { time: "Non valido." };
629
- const slotsValue = this.slots();
630
- if (slotsValue) {
631
- const isValid = slotsValue.split('|').some(s => {
632
- const t1 = this.getTime(s.substring(0, 5));
633
- const t2 = this.getTime(s.substring(6));
634
- return t1 !== -1 && t2 !== -1 && t1 <= t && t2 >= t;
635
- });
636
- return isValid ? null : { time: "Non valido." };
637
- }
638
- return null;
639
- }
640
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: TimeValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
641
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: TimeValidatorDirective, isStandalone: true, selector: "[time]", inputs: { slots: { classPropertyName: "slots", publicName: "slots", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
642
- {
643
- provide: NG_VALIDATORS,
644
- useExisting: forwardRef(() => TimeValidatorDirective),
645
- multi: true,
646
- },
647
- ], ngImport: i0 }); }
648
- }
649
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: TimeValidatorDirective, decorators: [{
650
- type: Directive,
651
- args: [{
652
- selector: "[time]",
653
- providers: [
654
- {
655
- provide: NG_VALIDATORS,
656
- useExisting: forwardRef(() => TimeValidatorDirective),
657
- multi: true,
658
- },
659
- ],
660
- standalone: true,
661
- }]
662
- }], propDecorators: { slots: [{ type: i0.Input, args: [{ isSignal: true, alias: "slots", required: false }] }] } });
663
-
664
- /**
665
- * @file emptiness.ts
666
- *
667
- * The single definition of "empty" behind the `notEmpty` rule, in both its flavours: the
668
- * template-driven directive and the signal-form validator. It lives apart from either of them so
669
- * that the two faces of the same rule cannot drift, and it pulls in nothing — not
670
- * `@angular/forms`, not `@angular/core`.
671
- */
672
- /**
673
- * Tells whether a value is what the `notEmpty` rule rejects: a string made of whitespace alone,
674
- * or an array with no elements.
675
- *
676
- * An absent value and an empty string are deliberately NOT rejected: declaring a field mandatory
677
- * is the job of `required()`, and a blank field would otherwise raise two errors saying the same
678
- * thing. The empty array is the one exception, because there it IS the only shape emptiness can
679
- * take — a multi-select never holds `''`, and Angular's own `required()` does not see `[]` as
680
- * empty, so nothing else would catch it.
681
- *
682
- * @param value - The value to inspect.
683
- * @returns `true` when the value is a whitespace-only string or an empty array.
684
- */
1
+ import * as i0 from "@angular/core";
2
+ import { DestroyRef, Directive, effect, forwardRef, inject, input } from "@angular/core";
3
+ import { NG_VALIDATORS } from "@angular/forms";
4
+ import { SystemUtils } from "@arsedizioni/ars-utils/core";
5
+ import { endOfDay, startOfDay } from "date-fns";
6
+ import { validate } from "@angular/forms/signals";
7
+ var ValidatorDirective = class ValidatorDirective {
8
+ constructor() {
9
+ this.validator = input(void 0, ...ngDevMode ? [{ debugName: "validator" }] : /* istanbul ignore next */ []);
10
+ }
11
+ validate(control) {
12
+ const fn = this.validator();
13
+ return fn ? fn(control) : null;
14
+ }
15
+ static {
16
+ this.ɵfac = i0.ɵɵngDeclareFactory({
17
+ minVersion: "12.0.0",
18
+ version: "22.2.1",
19
+ ngImport: i0,
20
+ type: ValidatorDirective,
21
+ deps: [],
22
+ target: i0.ɵɵFactoryTarget.Directive
23
+ });
24
+ }
25
+ static {
26
+ this.ɵdir = i0.ɵɵngDeclareDirective({
27
+ minVersion: "17.1.0",
28
+ version: "22.2.1",
29
+ type: ValidatorDirective,
30
+ isStandalone: true,
31
+ selector: "[validator]",
32
+ inputs: { validator: {
33
+ classPropertyName: "validator",
34
+ publicName: "validator",
35
+ isSignal: true,
36
+ isRequired: false,
37
+ transformFunction: null
38
+ } },
39
+ providers: [{
40
+ provide: NG_VALIDATORS,
41
+ useExisting: ValidatorDirective,
42
+ multi: true
43
+ }],
44
+ ngImport: i0
45
+ });
46
+ }
47
+ };
48
+ i0.ɵɵngDeclareClassMetadata({
49
+ minVersion: "12.0.0",
50
+ version: "22.2.1",
51
+ ngImport: i0,
52
+ type: ValidatorDirective,
53
+ decorators: [{
54
+ type: Directive,
55
+ args: [{
56
+ selector: "[validator]",
57
+ providers: [{
58
+ provide: NG_VALIDATORS,
59
+ useExisting: ValidatorDirective,
60
+ multi: true
61
+ }],
62
+ standalone: true
63
+ }]
64
+ }],
65
+ propDecorators: { validator: [{
66
+ type: i0.Input,
67
+ args: [{
68
+ isSignal: true,
69
+ alias: "validator",
70
+ required: false
71
+ }]
72
+ }] }
73
+ });
74
+ var ValidIfDirective = class ValidIfDirective {
75
+ constructor() {
76
+ this.validIf = input(false, ...ngDevMode ? [{ debugName: "validIf" }] : /* istanbul ignore next */ []);
77
+ }
78
+ validate(control) {
79
+ let isValid = false;
80
+ const c = control.value ? control.value : null;
81
+ if (!c) isValid = this.validIf() === true;
82
+ else try {
83
+ isValid = c.isValid();
84
+ } catch {}
85
+ return isValid ? null : { validIf: "Non valido." };
86
+ }
87
+ static {
88
+ this.ɵfac = i0.ɵɵngDeclareFactory({
89
+ minVersion: "12.0.0",
90
+ version: "22.2.1",
91
+ ngImport: i0,
92
+ type: ValidIfDirective,
93
+ deps: [],
94
+ target: i0.ɵɵFactoryTarget.Directive
95
+ });
96
+ }
97
+ static {
98
+ this.ɵdir = i0.ɵɵngDeclareDirective({
99
+ minVersion: "17.1.0",
100
+ version: "22.2.1",
101
+ type: ValidIfDirective,
102
+ isStandalone: true,
103
+ selector: "[validIf]",
104
+ inputs: { validIf: {
105
+ classPropertyName: "validIf",
106
+ publicName: "validIf",
107
+ isSignal: true,
108
+ isRequired: false,
109
+ transformFunction: null
110
+ } },
111
+ providers: [{
112
+ provide: NG_VALIDATORS,
113
+ useExisting: forwardRef(() => ValidIfDirective),
114
+ multi: true
115
+ }],
116
+ ngImport: i0
117
+ });
118
+ }
119
+ };
120
+ i0.ɵɵngDeclareClassMetadata({
121
+ minVersion: "12.0.0",
122
+ version: "22.2.1",
123
+ ngImport: i0,
124
+ type: ValidIfDirective,
125
+ decorators: [{
126
+ type: Directive,
127
+ args: [{
128
+ selector: "[validIf]",
129
+ providers: [{
130
+ provide: NG_VALIDATORS,
131
+ useExisting: forwardRef(() => ValidIfDirective),
132
+ multi: true
133
+ }],
134
+ standalone: true
135
+ }]
136
+ }],
137
+ propDecorators: { validIf: [{
138
+ type: i0.Input,
139
+ args: [{
140
+ isSignal: true,
141
+ alias: "validIf",
142
+ required: false
143
+ }]
144
+ }] }
145
+ });
146
+ var EqualsValidatorDirective = class EqualsValidatorDirective {
147
+ constructor() {
148
+ this.equals = input(void 0, ...ngDevMode ? [{ debugName: "equals" }] : /* istanbul ignore next */ []);
149
+ effect(() => {
150
+ const other = this.equals();
151
+ this.subscription?.unsubscribe();
152
+ this.subscription = other?.valueChanges.subscribe(() => this.hostControl?.updateValueAndValidity({ emitEvent: false }));
153
+ this.hostControl?.updateValueAndValidity({ emitEvent: false });
154
+ });
155
+ inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
156
+ }
157
+ validate(control) {
158
+ this.hostControl = control;
159
+ const eq = this.equals();
160
+ if (!eq) return null;
161
+ return eq.value === control.value ? null : { equals: "Non valido." };
162
+ }
163
+ static {
164
+ this.ɵfac = i0.ɵɵngDeclareFactory({
165
+ minVersion: "12.0.0",
166
+ version: "22.2.1",
167
+ ngImport: i0,
168
+ type: EqualsValidatorDirective,
169
+ deps: [],
170
+ target: i0.ɵɵFactoryTarget.Directive
171
+ });
172
+ }
173
+ static {
174
+ this.ɵdir = i0.ɵɵngDeclareDirective({
175
+ minVersion: "17.1.0",
176
+ version: "22.2.1",
177
+ type: EqualsValidatorDirective,
178
+ isStandalone: true,
179
+ selector: "[equals]",
180
+ inputs: { equals: {
181
+ classPropertyName: "equals",
182
+ publicName: "equals",
183
+ isSignal: true,
184
+ isRequired: false,
185
+ transformFunction: null
186
+ } },
187
+ providers: [{
188
+ provide: NG_VALIDATORS,
189
+ useExisting: forwardRef(() => EqualsValidatorDirective),
190
+ multi: true
191
+ }],
192
+ ngImport: i0
193
+ });
194
+ }
195
+ };
196
+ i0.ɵɵngDeclareClassMetadata({
197
+ minVersion: "12.0.0",
198
+ version: "22.2.1",
199
+ ngImport: i0,
200
+ type: EqualsValidatorDirective,
201
+ decorators: [{
202
+ type: Directive,
203
+ args: [{
204
+ selector: "[equals]",
205
+ providers: [{
206
+ provide: NG_VALIDATORS,
207
+ useExisting: forwardRef(() => EqualsValidatorDirective),
208
+ multi: true
209
+ }],
210
+ standalone: true
211
+ }]
212
+ }],
213
+ ctorParameters: () => [],
214
+ propDecorators: { equals: [{
215
+ type: i0.Input,
216
+ args: [{
217
+ isSignal: true,
218
+ alias: "equals",
219
+ required: false
220
+ }]
221
+ }] }
222
+ });
223
+ var NotEqualValidatorDirective = class NotEqualValidatorDirective {
224
+ constructor() {
225
+ this.notEqual = input(void 0, ...ngDevMode ? [{ debugName: "notEqual" }] : /* istanbul ignore next */ []);
226
+ effect(() => {
227
+ const other = this.notEqual();
228
+ this.subscription?.unsubscribe();
229
+ this.subscription = other?.valueChanges.subscribe(() => this.hostControl?.updateValueAndValidity({ emitEvent: false }));
230
+ this.hostControl?.updateValueAndValidity({ emitEvent: false });
231
+ });
232
+ inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());
233
+ }
234
+ validate(control) {
235
+ this.hostControl = control;
236
+ const notEqual = this.notEqual();
237
+ if (!notEqual) return null;
238
+ const errors = !notEqual.value && !control.value || notEqual.value !== control.value ? null : { notequal: true };
239
+ if (errors) control.markAsTouched();
240
+ else if (notEqual.hasError("notequal")) {
241
+ const { notequal: _removed, ...rest } = notEqual.errors ?? {};
242
+ notEqual.setErrors(Object.keys(rest).length > 0 ? rest : null, { emitEvent: false });
243
+ notEqual.updateValueAndValidity({
244
+ onlySelf: true,
245
+ emitEvent: false
246
+ });
247
+ notEqual.markAsTouched();
248
+ notEqual.markAsDirty();
249
+ }
250
+ return errors;
251
+ }
252
+ static {
253
+ this.ɵfac = i0.ɵɵngDeclareFactory({
254
+ minVersion: "12.0.0",
255
+ version: "22.2.1",
256
+ ngImport: i0,
257
+ type: NotEqualValidatorDirective,
258
+ deps: [],
259
+ target: i0.ɵɵFactoryTarget.Directive
260
+ });
261
+ }
262
+ static {
263
+ this.ɵdir = i0.ɵɵngDeclareDirective({
264
+ minVersion: "17.1.0",
265
+ version: "22.2.1",
266
+ type: NotEqualValidatorDirective,
267
+ isStandalone: true,
268
+ selector: "[notEqual]",
269
+ inputs: { notEqual: {
270
+ classPropertyName: "notEqual",
271
+ publicName: "notEqual",
272
+ isSignal: true,
273
+ isRequired: false,
274
+ transformFunction: null
275
+ } },
276
+ providers: [{
277
+ provide: NG_VALIDATORS,
278
+ useExisting: forwardRef(() => NotEqualValidatorDirective),
279
+ multi: true
280
+ }],
281
+ ngImport: i0
282
+ });
283
+ }
284
+ };
285
+ i0.ɵɵngDeclareClassMetadata({
286
+ minVersion: "12.0.0",
287
+ version: "22.2.1",
288
+ ngImport: i0,
289
+ type: NotEqualValidatorDirective,
290
+ decorators: [{
291
+ type: Directive,
292
+ args: [{
293
+ selector: "[notEqual]",
294
+ providers: [{
295
+ provide: NG_VALIDATORS,
296
+ useExisting: forwardRef(() => NotEqualValidatorDirective),
297
+ multi: true
298
+ }],
299
+ standalone: true
300
+ }]
301
+ }],
302
+ ctorParameters: () => [],
303
+ propDecorators: { notEqual: [{
304
+ type: i0.Input,
305
+ args: [{
306
+ isSignal: true,
307
+ alias: "notEqual",
308
+ required: false
309
+ }]
310
+ }] }
311
+ });
312
+ var EmailsValidatorDirective = class EmailsValidatorDirective {
313
+ validate(control) {
314
+ const input = control.value;
315
+ if (!input || input.length === 0) return null;
316
+ return input.replaceAll(/\r\n/g, "").split(";").every((part) => part.length === 0 || !!SystemUtils.parseEmail(part)) ? null : { emails: "Elenco non valido." };
317
+ }
318
+ static {
319
+ this.ɵfac = i0.ɵɵngDeclareFactory({
320
+ minVersion: "12.0.0",
321
+ version: "22.2.1",
322
+ ngImport: i0,
323
+ type: EmailsValidatorDirective,
324
+ deps: [],
325
+ target: i0.ɵɵFactoryTarget.Directive
326
+ });
327
+ }
328
+ static {
329
+ this.ɵdir = i0.ɵɵngDeclareDirective({
330
+ minVersion: "14.0.0",
331
+ version: "22.2.1",
332
+ type: EmailsValidatorDirective,
333
+ isStandalone: true,
334
+ selector: "[emails]",
335
+ providers: [{
336
+ provide: NG_VALIDATORS,
337
+ useExisting: forwardRef(() => EmailsValidatorDirective),
338
+ multi: true
339
+ }],
340
+ ngImport: i0
341
+ });
342
+ }
343
+ };
344
+ i0.ɵɵngDeclareClassMetadata({
345
+ minVersion: "12.0.0",
346
+ version: "22.2.1",
347
+ ngImport: i0,
348
+ type: EmailsValidatorDirective,
349
+ decorators: [{
350
+ type: Directive,
351
+ args: [{
352
+ selector: "[emails]",
353
+ providers: [{
354
+ provide: NG_VALIDATORS,
355
+ useExisting: forwardRef(() => EmailsValidatorDirective),
356
+ multi: true
357
+ }],
358
+ standalone: true
359
+ }]
360
+ }]
361
+ });
362
+ var GuidValidatorDirective = class GuidValidatorDirective {
363
+ validate(control) {
364
+ const input = control.value;
365
+ if (!input || input.length === 0) return null;
366
+ return SystemUtils.parseUUID(input) ? null : { guid: "Non valido." };
367
+ }
368
+ static {
369
+ this.ɵfac = i0.ɵɵngDeclareFactory({
370
+ minVersion: "12.0.0",
371
+ version: "22.2.1",
372
+ ngImport: i0,
373
+ type: GuidValidatorDirective,
374
+ deps: [],
375
+ target: i0.ɵɵFactoryTarget.Directive
376
+ });
377
+ }
378
+ static {
379
+ this.ɵdir = i0.ɵɵngDeclareDirective({
380
+ minVersion: "14.0.0",
381
+ version: "22.2.1",
382
+ type: GuidValidatorDirective,
383
+ isStandalone: true,
384
+ selector: "[guid]",
385
+ providers: [{
386
+ provide: NG_VALIDATORS,
387
+ useExisting: forwardRef(() => GuidValidatorDirective),
388
+ multi: true
389
+ }],
390
+ ngImport: i0
391
+ });
392
+ }
393
+ };
394
+ i0.ɵɵngDeclareClassMetadata({
395
+ minVersion: "12.0.0",
396
+ version: "22.2.1",
397
+ ngImport: i0,
398
+ type: GuidValidatorDirective,
399
+ decorators: [{
400
+ type: Directive,
401
+ args: [{
402
+ selector: "[guid]",
403
+ providers: [{
404
+ provide: NG_VALIDATORS,
405
+ useExisting: forwardRef(() => GuidValidatorDirective),
406
+ multi: true
407
+ }],
408
+ standalone: true
409
+ }]
410
+ }]
411
+ });
412
+ var SqlDateValidatorDirective = class SqlDateValidatorDirective {
413
+ validate(control) {
414
+ const input = control.value;
415
+ if (!input || input.length === 0) return null;
416
+ const parsed = SystemUtils.parseDate(input);
417
+ if (!parsed) return { sqlDate: "Non valido." };
418
+ return endOfDay(parsed).getFullYear() > 1750 ? null : { sqlDate: "Non valido." };
419
+ }
420
+ static {
421
+ this.ɵfac = i0.ɵɵngDeclareFactory({
422
+ minVersion: "12.0.0",
423
+ version: "22.2.1",
424
+ ngImport: i0,
425
+ type: SqlDateValidatorDirective,
426
+ deps: [],
427
+ target: i0.ɵɵFactoryTarget.Directive
428
+ });
429
+ }
430
+ static {
431
+ this.ɵdir = i0.ɵɵngDeclareDirective({
432
+ minVersion: "14.0.0",
433
+ version: "22.2.1",
434
+ type: SqlDateValidatorDirective,
435
+ isStandalone: true,
436
+ selector: "[sqlDate]",
437
+ providers: [{
438
+ provide: NG_VALIDATORS,
439
+ useExisting: forwardRef(() => SqlDateValidatorDirective),
440
+ multi: true
441
+ }],
442
+ ngImport: i0
443
+ });
444
+ }
445
+ };
446
+ i0.ɵɵngDeclareClassMetadata({
447
+ minVersion: "12.0.0",
448
+ version: "22.2.1",
449
+ ngImport: i0,
450
+ type: SqlDateValidatorDirective,
451
+ decorators: [{
452
+ type: Directive,
453
+ args: [{
454
+ selector: "[sqlDate]",
455
+ providers: [{
456
+ provide: NG_VALIDATORS,
457
+ useExisting: forwardRef(() => SqlDateValidatorDirective),
458
+ multi: true
459
+ }],
460
+ standalone: true
461
+ }]
462
+ }]
463
+ });
464
+ var NotFutureValidatorDirective = class NotFutureValidatorDirective {
465
+ validate(control) {
466
+ const input = control.value;
467
+ if (!input || input.length === 0) return null;
468
+ const parsed = SystemUtils.parseDate(input);
469
+ if (!parsed) return { notFuture: "Non valido." };
470
+ const today = endOfDay(/* @__PURE__ */ new Date());
471
+ return endOfDay(parsed) <= today ? null : { notFuture: "Non valido." };
472
+ }
473
+ static {
474
+ this.ɵfac = i0.ɵɵngDeclareFactory({
475
+ minVersion: "12.0.0",
476
+ version: "22.2.1",
477
+ ngImport: i0,
478
+ type: NotFutureValidatorDirective,
479
+ deps: [],
480
+ target: i0.ɵɵFactoryTarget.Directive
481
+ });
482
+ }
483
+ static {
484
+ this.ɵdir = i0.ɵɵngDeclareDirective({
485
+ minVersion: "14.0.0",
486
+ version: "22.2.1",
487
+ type: NotFutureValidatorDirective,
488
+ isStandalone: true,
489
+ selector: "[notFuture]",
490
+ providers: [{
491
+ provide: NG_VALIDATORS,
492
+ useExisting: forwardRef(() => NotFutureValidatorDirective),
493
+ multi: true
494
+ }],
495
+ ngImport: i0
496
+ });
497
+ }
498
+ };
499
+ i0.ɵɵngDeclareClassMetadata({
500
+ minVersion: "12.0.0",
501
+ version: "22.2.1",
502
+ ngImport: i0,
503
+ type: NotFutureValidatorDirective,
504
+ decorators: [{
505
+ type: Directive,
506
+ args: [{
507
+ selector: "[notFuture]",
508
+ providers: [{
509
+ provide: NG_VALIDATORS,
510
+ useExisting: forwardRef(() => NotFutureValidatorDirective),
511
+ multi: true
512
+ }],
513
+ standalone: true
514
+ }]
515
+ }]
516
+ });
517
+ var UrlValidatorDirective = class UrlValidatorDirective {
518
+ validate(control) {
519
+ const input = control.value;
520
+ if (!input || input.length === 0) return null;
521
+ return SystemUtils.parseUrl(input) ? null : { url: "Non valido." };
522
+ }
523
+ static {
524
+ this.ɵfac = i0.ɵɵngDeclareFactory({
525
+ minVersion: "12.0.0",
526
+ version: "22.2.1",
527
+ ngImport: i0,
528
+ type: UrlValidatorDirective,
529
+ deps: [],
530
+ target: i0.ɵɵFactoryTarget.Directive
531
+ });
532
+ }
533
+ static {
534
+ this.ɵdir = i0.ɵɵngDeclareDirective({
535
+ minVersion: "14.0.0",
536
+ version: "22.2.1",
537
+ type: UrlValidatorDirective,
538
+ isStandalone: true,
539
+ selector: "[url]",
540
+ providers: [{
541
+ provide: NG_VALIDATORS,
542
+ useExisting: forwardRef(() => UrlValidatorDirective),
543
+ multi: true
544
+ }],
545
+ ngImport: i0
546
+ });
547
+ }
548
+ };
549
+ i0.ɵɵngDeclareClassMetadata({
550
+ minVersion: "12.0.0",
551
+ version: "22.2.1",
552
+ ngImport: i0,
553
+ type: UrlValidatorDirective,
554
+ decorators: [{
555
+ type: Directive,
556
+ args: [{
557
+ selector: "[url]",
558
+ providers: [{
559
+ provide: NG_VALIDATORS,
560
+ useExisting: forwardRef(() => UrlValidatorDirective),
561
+ multi: true
562
+ }],
563
+ standalone: true
564
+ }]
565
+ }]
566
+ });
567
+ var FileSizeValidatorDirective = class FileSizeValidatorDirective {
568
+ constructor() {
569
+ this.maxSizeMb = input(5, ...ngDevMode ? [{ debugName: "maxSizeMb" }] : /* istanbul ignore next */ []);
570
+ this.minSizeMb = input(0, ...ngDevMode ? [{ debugName: "minSizeMb" }] : /* istanbul ignore next */ []);
571
+ this.size = input(void 0, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
572
+ }
573
+ validate(control) {
574
+ if (!control.value) return null;
575
+ const s = this.size() ?? 0;
576
+ return s <= this.maxSizeMb() && s >= this.minSizeMb() ? null : { fileSize: "Non valido." };
577
+ }
578
+ static {
579
+ this.ɵfac = i0.ɵɵngDeclareFactory({
580
+ minVersion: "12.0.0",
581
+ version: "22.2.1",
582
+ ngImport: i0,
583
+ type: FileSizeValidatorDirective,
584
+ deps: [],
585
+ target: i0.ɵɵFactoryTarget.Directive
586
+ });
587
+ }
588
+ static {
589
+ this.ɵdir = i0.ɵɵngDeclareDirective({
590
+ minVersion: "17.1.0",
591
+ version: "22.2.1",
592
+ type: FileSizeValidatorDirective,
593
+ isStandalone: true,
594
+ selector: "[fileSize]",
595
+ inputs: {
596
+ maxSizeMb: {
597
+ classPropertyName: "maxSizeMb",
598
+ publicName: "maxSizeMb",
599
+ isSignal: true,
600
+ isRequired: false,
601
+ transformFunction: null
602
+ },
603
+ minSizeMb: {
604
+ classPropertyName: "minSizeMb",
605
+ publicName: "minSizeMb",
606
+ isSignal: true,
607
+ isRequired: false,
608
+ transformFunction: null
609
+ },
610
+ size: {
611
+ classPropertyName: "size",
612
+ publicName: "size",
613
+ isSignal: true,
614
+ isRequired: false,
615
+ transformFunction: null
616
+ }
617
+ },
618
+ providers: [{
619
+ provide: NG_VALIDATORS,
620
+ useExisting: forwardRef(() => FileSizeValidatorDirective),
621
+ multi: true
622
+ }],
623
+ ngImport: i0
624
+ });
625
+ }
626
+ };
627
+ i0.ɵɵngDeclareClassMetadata({
628
+ minVersion: "12.0.0",
629
+ version: "22.2.1",
630
+ ngImport: i0,
631
+ type: FileSizeValidatorDirective,
632
+ decorators: [{
633
+ type: Directive,
634
+ args: [{
635
+ selector: "[fileSize]",
636
+ providers: [{
637
+ provide: NG_VALIDATORS,
638
+ useExisting: forwardRef(() => FileSizeValidatorDirective),
639
+ multi: true
640
+ }],
641
+ standalone: true
642
+ }]
643
+ }],
644
+ propDecorators: {
645
+ maxSizeMb: [{
646
+ type: i0.Input,
647
+ args: [{
648
+ isSignal: true,
649
+ alias: "maxSizeMb",
650
+ required: false
651
+ }]
652
+ }],
653
+ minSizeMb: [{
654
+ type: i0.Input,
655
+ args: [{
656
+ isSignal: true,
657
+ alias: "minSizeMb",
658
+ required: false
659
+ }]
660
+ }],
661
+ size: [{
662
+ type: i0.Input,
663
+ args: [{
664
+ isSignal: true,
665
+ alias: "size",
666
+ required: false
667
+ }]
668
+ }]
669
+ }
670
+ });
671
+ var MaxTermsValidatorDirective = class MaxTermsValidatorDirective {
672
+ constructor() {
673
+ this.maxTerms = input(0, ...ngDevMode ? [{ debugName: "maxTerms" }] : /* istanbul ignore next */ []);
674
+ }
675
+ validate(control) {
676
+ const input = control.value;
677
+ if (!input) return null;
678
+ return (input.match(/\S+/g)?.length ?? 0) <= this.maxTerms() ? null : { maxTerms: "Non valido." };
679
+ }
680
+ static {
681
+ this.ɵfac = i0.ɵɵngDeclareFactory({
682
+ minVersion: "12.0.0",
683
+ version: "22.2.1",
684
+ ngImport: i0,
685
+ type: MaxTermsValidatorDirective,
686
+ deps: [],
687
+ target: i0.ɵɵFactoryTarget.Directive
688
+ });
689
+ }
690
+ static {
691
+ this.ɵdir = i0.ɵɵngDeclareDirective({
692
+ minVersion: "17.1.0",
693
+ version: "22.2.1",
694
+ type: MaxTermsValidatorDirective,
695
+ isStandalone: true,
696
+ selector: "[maxTerms]",
697
+ inputs: { maxTerms: {
698
+ classPropertyName: "maxTerms",
699
+ publicName: "maxTerms",
700
+ isSignal: true,
701
+ isRequired: false,
702
+ transformFunction: null
703
+ } },
704
+ providers: [{
705
+ provide: NG_VALIDATORS,
706
+ useExisting: forwardRef(() => MaxTermsValidatorDirective),
707
+ multi: true
708
+ }],
709
+ ngImport: i0
710
+ });
711
+ }
712
+ };
713
+ i0.ɵɵngDeclareClassMetadata({
714
+ minVersion: "12.0.0",
715
+ version: "22.2.1",
716
+ ngImport: i0,
717
+ type: MaxTermsValidatorDirective,
718
+ decorators: [{
719
+ type: Directive,
720
+ args: [{
721
+ selector: "[maxTerms]",
722
+ providers: [{
723
+ provide: NG_VALIDATORS,
724
+ useExisting: forwardRef(() => MaxTermsValidatorDirective),
725
+ multi: true
726
+ }],
727
+ standalone: true
728
+ }]
729
+ }],
730
+ propDecorators: { maxTerms: [{
731
+ type: i0.Input,
732
+ args: [{
733
+ isSignal: true,
734
+ alias: "maxTerms",
735
+ required: false
736
+ }]
737
+ }] }
738
+ });
739
+ var PasswordValidatorDirective = class PasswordValidatorDirective {
740
+ validate(control) {
741
+ const input = control.value ?? "";
742
+ return SystemUtils.calculatePasswordStrength(input).isValid ? null : { password: "Non valido." };
743
+ }
744
+ static {
745
+ this.ɵfac = i0.ɵɵngDeclareFactory({
746
+ minVersion: "12.0.0",
747
+ version: "22.2.1",
748
+ ngImport: i0,
749
+ type: PasswordValidatorDirective,
750
+ deps: [],
751
+ target: i0.ɵɵFactoryTarget.Directive
752
+ });
753
+ }
754
+ static {
755
+ this.ɵdir = i0.ɵɵngDeclareDirective({
756
+ minVersion: "14.0.0",
757
+ version: "22.2.1",
758
+ type: PasswordValidatorDirective,
759
+ isStandalone: true,
760
+ selector: "[password]",
761
+ providers: [{
762
+ provide: NG_VALIDATORS,
763
+ useExisting: forwardRef(() => PasswordValidatorDirective),
764
+ multi: true
765
+ }],
766
+ ngImport: i0
767
+ });
768
+ }
769
+ };
770
+ i0.ɵɵngDeclareClassMetadata({
771
+ minVersion: "12.0.0",
772
+ version: "22.2.1",
773
+ ngImport: i0,
774
+ type: PasswordValidatorDirective,
775
+ decorators: [{
776
+ type: Directive,
777
+ args: [{
778
+ selector: "[password]",
779
+ providers: [{
780
+ provide: NG_VALIDATORS,
781
+ useExisting: forwardRef(() => PasswordValidatorDirective),
782
+ multi: true
783
+ }],
784
+ standalone: true
785
+ }]
786
+ }]
787
+ });
788
+ var TimeValidatorDirective = class TimeValidatorDirective {
789
+ constructor() {
790
+ this.slots = input(void 0, ...ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []);
791
+ }
792
+ getTime(value) {
793
+ const p = value.split(":");
794
+ if (p.length !== 2) return -1;
795
+ const hh = parseInt(p[0], 10);
796
+ if (isNaN(hh) || hh < 0 || hh > 23) return -1;
797
+ const mm = parseInt(p[1], 10);
798
+ if (isNaN(mm) || mm < 0 || mm > 59) return -1;
799
+ return hh * 100 + mm;
800
+ }
801
+ validate(control) {
802
+ const input = control.value;
803
+ if (!input || input.length === 0) return null;
804
+ const t = this.getTime(input);
805
+ if (t === -1) return { time: "Non valido." };
806
+ const slotsValue = this.slots();
807
+ if (slotsValue) return slotsValue.split("|").some((s) => {
808
+ const t1 = this.getTime(s.substring(0, 5));
809
+ const t2 = this.getTime(s.substring(6));
810
+ return t1 !== -1 && t2 !== -1 && t1 <= t && t2 >= t;
811
+ }) ? null : { time: "Non valido." };
812
+ return null;
813
+ }
814
+ static {
815
+ this.ɵfac = i0.ɵɵngDeclareFactory({
816
+ minVersion: "12.0.0",
817
+ version: "22.2.1",
818
+ ngImport: i0,
819
+ type: TimeValidatorDirective,
820
+ deps: [],
821
+ target: i0.ɵɵFactoryTarget.Directive
822
+ });
823
+ }
824
+ static {
825
+ this.ɵdir = i0.ɵɵngDeclareDirective({
826
+ minVersion: "17.1.0",
827
+ version: "22.2.1",
828
+ type: TimeValidatorDirective,
829
+ isStandalone: true,
830
+ selector: "[time]",
831
+ inputs: { slots: {
832
+ classPropertyName: "slots",
833
+ publicName: "slots",
834
+ isSignal: true,
835
+ isRequired: false,
836
+ transformFunction: null
837
+ } },
838
+ providers: [{
839
+ provide: NG_VALIDATORS,
840
+ useExisting: forwardRef(() => TimeValidatorDirective),
841
+ multi: true
842
+ }],
843
+ ngImport: i0
844
+ });
845
+ }
846
+ };
847
+ i0.ɵɵngDeclareClassMetadata({
848
+ minVersion: "12.0.0",
849
+ version: "22.2.1",
850
+ ngImport: i0,
851
+ type: TimeValidatorDirective,
852
+ decorators: [{
853
+ type: Directive,
854
+ args: [{
855
+ selector: "[time]",
856
+ providers: [{
857
+ provide: NG_VALIDATORS,
858
+ useExisting: forwardRef(() => TimeValidatorDirective),
859
+ multi: true
860
+ }],
861
+ standalone: true
862
+ }]
863
+ }],
864
+ propDecorators: { slots: [{
865
+ type: i0.Input,
866
+ args: [{
867
+ isSignal: true,
868
+ alias: "slots",
869
+ required: false
870
+ }]
871
+ }] }
872
+ });
685
873
  function isBlankValue(value) {
686
- if (Array.isArray(value))
687
- return value.length === 0;
688
- if (typeof value !== 'string')
689
- return false;
690
- return value.length > 0 && value.trim().length === 0;
691
- }
692
-
693
- /**
694
- * Directive that validates that a control value is not blank: neither a whitespace-only string
695
- * nor an empty array. Apply `notEmpty` to a text input where non-blank content is required, or
696
- * to a multi-value control that must carry at least one entry.
697
- *
698
- * A value that is simply absent passes: saying "obbligatorio" is the job of `required`, which is
699
- * declared next to this one when both rules belong on the same control.
700
- */
701
- class NotEmptyValidatorDirective {
702
- /**
703
- * Validates that the control value carries content.
704
- * Returns `null` when the control is absent or holds a type this rule says nothing about.
705
- * @param control - The form control to validate.
706
- * @returns `{ notEmpty: true }` when the value is a blank string or an empty array, `null` otherwise.
707
- */
708
- validate(control) {
709
- return isBlankValue(control?.value) ? { notEmpty: true } : null;
710
- }
711
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotEmptyValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
712
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: NotEmptyValidatorDirective, isStandalone: true, selector: "[notEmpty]", providers: [
713
- {
714
- provide: NG_VALIDATORS,
715
- useExisting: forwardRef(() => NotEmptyValidatorDirective),
716
- multi: true,
717
- },
718
- ], ngImport: i0 }); }
874
+ if (Array.isArray(value)) return value.length === 0;
875
+ if (typeof value !== "string") return false;
876
+ return value.length > 0 && value.trim().length === 0;
719
877
  }
720
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: NotEmptyValidatorDirective, decorators: [{
721
- type: Directive,
722
- args: [{
723
- selector: "[notEmpty]",
724
- providers: [
725
- {
726
- provide: NG_VALIDATORS,
727
- useExisting: forwardRef(() => NotEmptyValidatorDirective),
728
- multi: true,
729
- },
730
- ],
731
- standalone: true,
732
- }]
733
- }] });
734
-
735
- /**
736
- * @file italian.ts
737
- *
738
- * The two check algorithms behind the `italianVat` and `italianFiscalCode` rules, kept apart from
739
- * the validators that use them for the same reason `emptiness.ts` is: the rule must exist in one
740
- * place only, so that no second copy of it can drift. They pull in nothing — not `@angular/forms`,
741
- * not `@angular/core` — and they live here rather than in `SystemUtils` so that `core`, which sits
742
- * on the boot path of every application, does not carry code only a form needs.
743
- */
744
- /**
745
- * Digits an "omocodia" substitution replaces with a letter, in digit order: `0` becomes `L`, `1`
746
- * becomes `M`, and so on.
747
- *
748
- * The Agenzia delle Entrate applies it when two people would otherwise share the same fiscal code,
749
- * so a perfectly legitimate code can carry letters where the format expects numbers. Ignoring this
750
- * is the classic way a validator rejects a real person.
751
- */
752
- const OMOCODIA_CHARS = 'LMNPQRSTUV';
753
- /** Letters usable as month of birth, one per month from January (`A`) to December (`T`). */
754
- const MONTH_CHARS = 'ABCDEHLMPRST';
755
- /** Alphabet the control character of a fiscal code is drawn from. */
756
- const CONTROL_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
757
- /** Weight of each character sitting in an ODD position (1-based) of the first 15 of a fiscal code. */
878
+ var NotEmptyValidatorDirective = class NotEmptyValidatorDirective {
879
+ validate(control) {
880
+ return isBlankValue(control?.value) ? { notEmpty: true } : null;
881
+ }
882
+ static {
883
+ this.ɵfac = i0.ɵɵngDeclareFactory({
884
+ minVersion: "12.0.0",
885
+ version: "22.2.1",
886
+ ngImport: i0,
887
+ type: NotEmptyValidatorDirective,
888
+ deps: [],
889
+ target: i0.ɵɵFactoryTarget.Directive
890
+ });
891
+ }
892
+ static {
893
+ this.ɵdir = i0.ɵɵngDeclareDirective({
894
+ minVersion: "14.0.0",
895
+ version: "22.2.1",
896
+ type: NotEmptyValidatorDirective,
897
+ isStandalone: true,
898
+ selector: "[notEmpty]",
899
+ providers: [{
900
+ provide: NG_VALIDATORS,
901
+ useExisting: forwardRef(() => NotEmptyValidatorDirective),
902
+ multi: true
903
+ }],
904
+ ngImport: i0
905
+ });
906
+ }
907
+ };
908
+ i0.ɵɵngDeclareClassMetadata({
909
+ minVersion: "12.0.0",
910
+ version: "22.2.1",
911
+ ngImport: i0,
912
+ type: NotEmptyValidatorDirective,
913
+ decorators: [{
914
+ type: Directive,
915
+ args: [{
916
+ selector: "[notEmpty]",
917
+ providers: [{
918
+ provide: NG_VALIDATORS,
919
+ useExisting: forwardRef(() => NotEmptyValidatorDirective),
920
+ multi: true
921
+ }],
922
+ standalone: true
923
+ }]
924
+ }]
925
+ });
926
+ const OMOCODIA_CHARS = "LMNPQRSTUV";
927
+ const MONTH_CHARS = "ABCDEHLMPRST";
928
+ const CONTROL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
758
929
  const ODD_WEIGHTS = {
759
- '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, '5': 13, '6': 15, '7': 17, '8': 19, '9': 21,
760
- A: 1, B: 0, C: 5, D: 7, E: 9, F: 13, G: 15, H: 17, I: 19, J: 21, K: 2, L: 4, M: 18,
761
- N: 20, O: 11, P: 3, Q: 6, R: 8, S: 12, T: 14, U: 16, V: 10, W: 22, X: 25, Y: 24, Z: 23,
930
+ "0": 1,
931
+ "1": 0,
932
+ "2": 5,
933
+ "3": 7,
934
+ "4": 9,
935
+ "5": 13,
936
+ "6": 15,
937
+ "7": 17,
938
+ "8": 19,
939
+ "9": 21,
940
+ A: 1,
941
+ B: 0,
942
+ C: 5,
943
+ D: 7,
944
+ E: 9,
945
+ F: 13,
946
+ G: 15,
947
+ H: 17,
948
+ I: 19,
949
+ J: 21,
950
+ K: 2,
951
+ L: 4,
952
+ M: 18,
953
+ N: 20,
954
+ O: 11,
955
+ P: 3,
956
+ Q: 6,
957
+ R: 8,
958
+ S: 12,
959
+ T: 14,
960
+ U: 16,
961
+ V: 10,
962
+ W: 22,
963
+ X: 25,
964
+ Y: 24,
965
+ Z: 23
762
966
  };
763
- /** Weight of each character sitting in an EVEN position (1-based) of the first 15 of a fiscal code. */
764
967
  const EVEN_WEIGHTS = {
765
- '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
766
- A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12,
767
- N: 13, O: 14, P: 15, Q: 16, R: 17, S: 18, T: 19, U: 20, V: 21, W: 22, X: 23, Y: 24, Z: 25,
968
+ "0": 0,
969
+ "1": 1,
970
+ "2": 2,
971
+ "3": 3,
972
+ "4": 4,
973
+ "5": 5,
974
+ "6": 6,
975
+ "7": 7,
976
+ "8": 8,
977
+ "9": 9,
978
+ A: 0,
979
+ B: 1,
980
+ C: 2,
981
+ D: 3,
982
+ E: 4,
983
+ F: 5,
984
+ G: 6,
985
+ H: 7,
986
+ I: 8,
987
+ J: 9,
988
+ K: 10,
989
+ L: 11,
990
+ M: 12,
991
+ N: 13,
992
+ O: 14,
993
+ P: 15,
994
+ Q: 16,
995
+ R: 17,
996
+ S: 18,
997
+ T: 19,
998
+ U: 20,
999
+ V: 21,
1000
+ W: 22,
1001
+ X: 23,
1002
+ Y: 24,
1003
+ Z: 25
768
1004
  };
769
- /**
770
- * Shape of a fiscal code of a natural person, omocodia included: every group that is normally
771
- * numeric also admits the ten letters that stand in for a digit.
772
- */
773
1005
  const FISCAL_CODE_REGEX = /^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$/;
774
- /**
775
- * Strips what a user types around a code without changing the code itself: surrounding and inner
776
- * spaces, dots and dashes, and the letter case.
777
- *
778
- * Accepting a pasted `"IT 123 456 789 01"` is not indulgence — the value arrives from an invoice,
779
- * a registry export or a colleague's e-mail far more often than it is typed character by
780
- * character, and rejecting it teaches nothing to the person who pasted it.
781
- *
782
- * @param value - The raw value as the user entered it.
783
- * @returns The value in upper case with spaces, dots and dashes removed.
784
- */
785
1006
  function normalize(value) {
786
- return (value ?? '').toUpperCase().replace(/[\s.\-/]/g, '');
1007
+ return (value ?? "").toUpperCase().replace(/[\s.\-/]/g, "");
787
1008
  }
788
- /**
789
- * Turns the letters an omocodia substitution left behind back into the digits they stand for.
790
- *
791
- * @param value - A group of characters of a fiscal code that is numeric in the plain form.
792
- * @returns The same group with every substitution letter replaced by its digit.
793
- */
794
1009
  function decodeOmocodia(value) {
795
- let decoded = '';
796
- for (const char of value) {
797
- const index = OMOCODIA_CHARS.indexOf(char);
798
- decoded += index === -1 ? char : String(index);
799
- }
800
- return decoded;
1010
+ let decoded = "";
1011
+ for (const char of value) {
1012
+ const index = OMOCODIA_CHARS.indexOf(char);
1013
+ decoded += index === -1 ? char : String(index);
1014
+ }
1015
+ return decoded;
801
1016
  }
802
- /**
803
- * Tells whether a value is a valid Italian VAT number (partita IVA).
804
- *
805
- * Eleven digits, of which the last one is the check digit of the Luhn-like algorithm of
806
- * D.P.R. 633/72: the digits in even position (1-based) are doubled and folded back under ten, the
807
- * sum is completed to the next multiple of ten, and what is missing is the check digit. An
808
- * optional `IT` prefix is accepted, because that is how the number travels on invoices and in
809
- * VIES exports.
810
- *
811
- * The seven digits of the sequential number are required not to be all zeros, which is the one
812
- * combination the checksum happily accepts and the Agenzia delle Entrate never issues. The office
813
- * code (positions 8 to 10) is deliberately NOT checked against the list of the provinces: that
814
- * list grows, and a validator that rejects a number issued last month is worse than one that lets
815
- * a fabricated office code through.
816
- *
817
- * @param value - The value to check, with or without the `IT` prefix and any spacing.
818
- * @returns `true` when the value is a well-formed VAT number.
819
- */
820
1017
  function isValidItalianVat(value) {
821
- const normalized = normalize(value);
822
- const digits = normalized.startsWith('IT') ? normalized.slice(2) : normalized;
823
- if (!/^\d{11}$/.test(digits))
824
- return false;
825
- if (digits.startsWith('0000000'))
826
- return false;
827
- let sum = 0;
828
- for (let i = 0; i < 10; i++) {
829
- let digit = digits.charCodeAt(i) - 48;
830
- // Positions are 1-based in the norm, so the doubled ones are those at an even index here.
831
- if (i % 2 === 1) {
832
- digit *= 2;
833
- if (digit > 9)
834
- digit -= 9;
835
- }
836
- sum += digit;
837
- }
838
- const check = (10 - (sum % 10)) % 10;
839
- return check === digits.charCodeAt(10) - 48;
1018
+ const normalized = normalize(value);
1019
+ const digits = normalized.startsWith("IT") ? normalized.slice(2) : normalized;
1020
+ if (!/^\d{11}$/.test(digits)) return false;
1021
+ if (digits.startsWith("0000000")) return false;
1022
+ let sum = 0;
1023
+ for (let i = 0; i < 10; i++) {
1024
+ let digit = digits.charCodeAt(i) - 48;
1025
+ if (i % 2 === 1) {
1026
+ digit *= 2;
1027
+ if (digit > 9) digit -= 9;
1028
+ }
1029
+ sum += digit;
1030
+ }
1031
+ return (10 - sum % 10) % 10 === digits.charCodeAt(10) - 48;
840
1032
  }
841
- /**
842
- * Tells whether a value is a valid Italian fiscal code (codice fiscale), in either of the two
843
- * shapes a form can receive.
844
- *
845
- * A natural person has the sixteen-character code of D.M. 23/12/1976: the shape is checked, the
846
- * month letter and the day of birth are checked (41 to 71 for a woman, which is the day plus
847
- * forty), and the sixteenth character is recomputed from the first fifteen and compared. Letters
848
- * left by an omocodia substitution are accepted and decoded before the date is judged, so a
849
- * legitimately altered code is not turned away.
850
- *
851
- * A company or a public body has no such code: its fiscal code IS its VAT number, eleven digits
852
- * checked by {@link isValidItalianVat}. Both are accepted here because a single "codice fiscale"
853
- * field in a registry form receives both, and asking the user which kind they are about to type is
854
- * a question the code can answer by itself.
855
- *
856
- * @param value - The value to check, in any case and with any spacing.
857
- * @returns `true` when the value is a well-formed fiscal code of either shape.
858
- */
859
1033
  function isValidItalianFiscalCode(value) {
860
- const code = normalize(value);
861
- // A company or a public body: its fiscal code is the VAT number.
862
- if (/^\d{11}$/.test(code))
863
- return isValidItalianVat(code);
864
- if (code.length !== 16 || !FISCAL_CODE_REGEX.test(code))
865
- return false;
866
- // The day carries the sex: 01-31 for a man, 41-71 for a woman (the day plus forty).
867
- const day = parseInt(decodeOmocodia(code.substring(9, 11)), 10);
868
- const isValidDay = (day >= 1 && day <= 31) || (day >= 41 && day <= 71);
869
- if (!isValidDay)
870
- return false;
871
- // The month letter is already constrained by the regex; this keeps the two in step if it changes.
872
- if (!MONTH_CHARS.includes(code[8]))
873
- return false;
874
- let sum = 0;
875
- for (let i = 0; i < 15; i++) {
876
- // Odd positions in the norm are the even indexes here. The character is weighted as it is
877
- // written, substitution letters included: the control character is computed on the altered
878
- // code, not on the original one.
879
- sum += i % 2 === 0 ? ODD_WEIGHTS[code[i]] : EVEN_WEIGHTS[code[i]];
880
- }
881
- return CONTROL_CHARS[sum % 26] === code[15];
1034
+ const code = normalize(value);
1035
+ if (/^\d{11}$/.test(code)) return isValidItalianVat(code);
1036
+ if (code.length !== 16 || !FISCAL_CODE_REGEX.test(code)) return false;
1037
+ const day = parseInt(decodeOmocodia(code.substring(9, 11)), 10);
1038
+ if (!(day >= 1 && day <= 31 || day >= 41 && day <= 71)) return false;
1039
+ if (!MONTH_CHARS.includes(code[8])) return false;
1040
+ let sum = 0;
1041
+ for (let i = 0; i < 15; i++) sum += i % 2 === 0 ? ODD_WEIGHTS[code[i]] : EVEN_WEIGHTS[code[i]];
1042
+ return CONTROL_CHARS[sum % 26] === code[15];
882
1043
  }
883
-
884
- /**
885
- * Default texts of the rules declared here, in one place so that the validators and the fallback
886
- * map of `SignalsUtils.getFieldErrorMessage` cannot drift apart: a rule added below without a
887
- * message here would show "Errore", and one renamed here without touching the validator would
888
- * leave the map with a kind nobody produces.
889
- */
890
- /**
891
- * Earliest year {@link date} and {@link dateRange} accept: 1750.
892
- *
893
- * It is the floor of what the backend can store, and it is set that low on purpose: a birth date,
894
- * the date of an old norm or the commissioning of an old machine are real data well before 1970.
895
- * What it does catch is the 01/01/0001 or 01/01/0020 that a mistyped year produces, which SQL
896
- * Server would reject with an error nobody can read.
897
- */
898
1044
  const MIN_VALID_YEAR = 1750;
899
1045
  const ARS_VALIDATOR_MESSAGES = {
900
- required: 'Obbligatorio',
901
- guid: 'Ticket non riconosciuto',
902
- password: 'Password non sufficientemente robusta',
903
- notEmpty: 'Non può essere vuoto o contenere solo spazi.',
904
- notEqual: 'Deve essere diverso dall\'altro valore',
905
- // Emitted by `SqlDateValidatorDirective`, which a `[formField]` on a ControlValueAccessor still reads.
906
- sqlDate: 'Data non valida',
907
- date: 'Data non valida',
908
- dateRange: 'Intervallo non valido',
909
- notFuture: 'La data non può essere futura',
910
- notPast: 'La data non può essere passata',
911
- url: 'Indirizzo non valido',
912
- maxTerms: 'Troppe parole',
913
- fileSize: 'Dimensione del file non ammessa',
914
- validIf: 'Non valido',
915
- emails: 'Elenco non valido',
916
- time: 'Orario non valido',
917
- equals: 'I due valori non coincidono',
918
- otp: 'Codice non valido',
919
- italianVat: 'Partita IVA non valida',
920
- italianFiscalCode: 'Codice fiscale non valido',
1046
+ required: "Obbligatorio",
1047
+ guid: "Ticket non riconosciuto",
1048
+ password: "Password non sufficientemente robusta",
1049
+ notEmpty: "Non può essere vuoto o contenere solo spazi.",
1050
+ notEqual: "Deve essere diverso dall'altro valore",
1051
+ sqlDate: "Data non valida",
1052
+ date: "Data non valida",
1053
+ dateRange: "Intervallo non valido",
1054
+ notFuture: "La data non può essere futura",
1055
+ notPast: "La data non può essere passata",
1056
+ url: "Indirizzo non valido",
1057
+ maxTerms: "Troppe parole",
1058
+ fileSize: "Dimensione del file non ammessa",
1059
+ validIf: "Non valido",
1060
+ emails: "Elenco non valido",
1061
+ time: "Orario non valido",
1062
+ equals: "I due valori non coincidono",
1063
+ otp: "Codice non valido",
1064
+ italianVat: "Partita IVA non valida",
1065
+ italianFiscalCode: "Codice fiscale non valido"
921
1066
  };
922
- /**
923
- * Requires the value to be a well-formed GUID / UUID.
924
- *
925
- * The signal-form counterpart of `GuidValidatorDirective`, sharing its rule down to the empty
926
- * case: an empty value is NOT an error here, because saying "obbligatorio" is the job of
927
- * `required()` and two errors on one empty field only ever read as noise.
928
- *
929
- * @param path - Path of the field to validate.
930
- * @param config - Optional message override.
931
- * @returns void
932
- * @example
933
- * const f = form(this.model, p => { required(p.serial); guid(p.serial); });
934
- */
935
1067
  function guid(path, config) {
936
- validate(path, ctx => {
937
- if (config?.when && !config.when(ctx))
938
- return null;
939
- const input = ctx.value();
940
- if (!input || input.length === 0)
941
- return null;
942
- return SystemUtils.parseUUID(input)
943
- ? null
944
- : { kind: 'guid', message: config?.message ?? ARS_VALIDATOR_MESSAGES['guid'] };
945
- });
1068
+ validate(path, (ctx) => {
1069
+ if (config?.when && !config.when(ctx)) return null;
1070
+ const input = ctx.value();
1071
+ if (!input || input.length === 0) return null;
1072
+ return SystemUtils.parseUUID(input) ? null : {
1073
+ kind: "guid",
1074
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["guid"]
1075
+ };
1076
+ });
946
1077
  }
947
- /**
948
- * Requires the value to be a password strong enough for {@link SystemUtils.calculatePasswordStrength}.
949
- *
950
- * The signal-form counterpart of `PasswordValidatorDirective`. Unlike {@link guid} it does judge
951
- * the empty value, because an empty password IS a weak one and the directive behaved the same way.
952
- *
953
- * @param path - Path of the field to validate.
954
- * @param config - Optional message override.
955
- * @returns void
956
- */
957
1078
  function password(path, config) {
958
- validate(path, ctx => {
959
- if (config?.when && !config.when(ctx))
960
- return null;
961
- const strength = SystemUtils.calculatePasswordStrength(ctx.value() ?? '');
962
- return strength.isValid
963
- ? null
964
- : { kind: 'password', message: config?.message ?? ARS_VALIDATOR_MESSAGES['password'] };
965
- });
1079
+ validate(path, (ctx) => {
1080
+ if (config?.when && !config.when(ctx)) return null;
1081
+ return SystemUtils.calculatePasswordStrength(ctx.value() ?? "").isValid ? null : {
1082
+ kind: "password",
1083
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["password"]
1084
+ };
1085
+ });
966
1086
  }
967
- /**
968
- * Requires the value not to be made of whitespace alone, and a collection not to be empty.
969
- *
970
- * The signal-form counterpart of `NotEmptyValidatorDirective`, sharing its predicate through
971
- * {@link isBlankValue}: a blank string and an empty array are errors, an absent value is not.
972
- * That last part is not an oversight — saying "obbligatorio" belongs to `required()`, and a field
973
- * that is merely blank would otherwise raise two errors that mean the same thing. Declare the two
974
- * together when a field must be both present and non-blank.
975
- *
976
- * Replaces the `pattern(p.x, /\S/)` workaround: same rule, but the intent is in the name and the
977
- * error kind is `notEmpty` rather than `pattern`.
978
- *
979
- * On a multi-value field this rule is the ONLY one that sees an empty selection: Angular's
980
- * `required()` treats emptiness as `'' | false | null | undefined`, so an empty array walks past
981
- * it. Give it a message of its own there, because the default one talks about whitespace.
982
- *
983
- * @param path - Path of the field to validate.
984
- * @param config - Optional message override.
985
- * @returns void
986
- * @example
987
- * const f = form(this.model, p => { required(p.city); notEmpty(p.city); });
988
- * @example
989
- * const f = form(this.model, p => { notEmpty(p.tags); }); // at least one tag
990
- */
991
1087
  function notEmpty(path, config) {
992
- validate(path, ctx => {
993
- if (config?.when && !config.when(ctx))
994
- return null;
995
- return isBlankValue(ctx.value())
996
- ? { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] }
997
- : null;
998
- });
1088
+ validate(path, (ctx) => {
1089
+ if (config?.when && !config.when(ctx)) return null;
1090
+ return isBlankValue(ctx.value()) ? {
1091
+ kind: "notEmpty",
1092
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["notEmpty"]
1093
+ } : null;
1094
+ });
999
1095
  }
1000
- /**
1001
- * Requires the value to differ from the value of another field of the same form.
1002
- *
1003
- * The signal-form counterpart of `NotEqualValidatorDirective`, with its exact rule: two empty
1004
- * values are considered different, so an untouched pair of fields does not start out in error.
1005
- * Reactive on both fields — editing either one re-validates this one, which is what the
1006
- * directive needed a `valueChanges` subscription (and a re-entrancy guard) to achieve.
1007
- *
1008
- * @param path - Path of the field to validate.
1009
- * @param other - Path of the field whose value must differ.
1010
- * @param config - Optional message override and `when` condition.
1011
- * @returns void
1012
- */
1013
1096
  function notEqual(path, other, config) {
1014
- validate(path, ctx => {
1015
- if (config?.when && !config.when(ctx))
1016
- return null;
1017
- const mine = ctx.value();
1018
- const theirs = ctx.valueOf(other);
1019
- const isValid = (!theirs && !mine) || theirs !== mine;
1020
- return isValid ? null : { kind: 'notEqual', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEqual'] };
1021
- });
1097
+ validate(path, (ctx) => {
1098
+ if (config?.when && !config.when(ctx)) return null;
1099
+ const mine = ctx.value();
1100
+ const theirs = ctx.valueOf(other);
1101
+ return !theirs && !mine || theirs !== mine ? null : {
1102
+ kind: "notEqual",
1103
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["notEqual"]
1104
+ };
1105
+ });
1022
1106
  }
1023
- /**
1024
- * Requires the value to be a real date, as {@link SystemUtils.parseDate} understands one.
1025
- *
1026
- * This is the rule for anything a user picks or types as a date: it accepts both the `Date` a
1027
- * Material datepicker or timepicker writes into the model and the text of a plain input, since
1028
- * `parseDate` handles the shapes this codebase produces (ISO, `dd/MM/yyyy`, `yyyy-MM-dd`, and the
1029
- * shorthand forms). Empty passes — saying "obbligatorio" is the job of `required()`.
1030
- *
1031
- * A date earlier than {@link MIN_VALID_YEAR} (1750) is rejected: it is what the backend can
1032
- * store, so an earlier value is a mistyped year rather than data.
1033
- *
1034
- * It is also the signal-form counterpart of `SqlDateValidatorDirective`: one rule for every date,
1035
- * whether it is typed or picked.
1036
- *
1037
- * @param path - Path of the field to validate.
1038
- * @param config - Optional message override and `when` condition.
1039
- * @returns void
1040
- * @example
1041
- * const f = form(this.model, p => { required(p.expiry); date(p.expiry); });
1042
- */
1043
1107
  function date(path, config) {
1044
- validate(path, ctx => {
1045
- if (config?.when && !config.when(ctx))
1046
- return null;
1047
- const input = ctx.value();
1048
- if (input === undefined || input === null || input === '')
1049
- return null;
1050
- const parsed = SystemUtils.parseDate(input);
1051
- return parsed && parsed.getFullYear() >= MIN_VALID_YEAR
1052
- ? null
1053
- : { kind: 'date', message: config?.message ?? ARS_VALIDATOR_MESSAGES['date'] };
1054
- });
1108
+ validate(path, (ctx) => {
1109
+ if (config?.when && !config.when(ctx)) return null;
1110
+ const input = ctx.value();
1111
+ if (input === void 0 || input === null || input === "") return null;
1112
+ const parsed = SystemUtils.parseDate(input);
1113
+ return parsed && parsed.getFullYear() >= 1750 ? null : {
1114
+ kind: "date",
1115
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["date"]
1116
+ };
1117
+ });
1055
1118
  }
1056
- /**
1057
- * Requires the two ends of a date range to be real dates and to be in order.
1058
- *
1059
- * Written for the two inputs of a `mat-date-range-input`, whose start and end live in two
1060
- * separate fields of the model. Each end is checked with the same rule as {@link date}, and the
1061
- * ordering is checked only when BOTH ends are filled in — a half-open range ("from today
1062
- * onwards") is a legitimate filter, not an error. The {@link MIN_VALID_YEAR} floor of {@link date}
1063
- * applies to both ends.
1064
- *
1065
- * The rule is bound to BOTH paths, so the error appears on whichever end the user is looking at
1066
- * and a single `<mat-error>` under the range can read either one. Comparison is made on the end
1067
- * of the day, so picking the same day for both ends is valid.
1068
- *
1069
- * @param from - Path of the field holding the start of the range.
1070
- * @param to - Path of the field holding the end of the range.
1071
- * @param config - Optional message override (used for the ordering error) and `when` condition.
1072
- * @returns void
1073
- * @example
1074
- * const f = form(this.model, p => { dateRange(p.sentFrom, p.sentTo); });
1075
- */
1076
1119
  function dateRange(from, to, config) {
1077
- date(from, config);
1078
- date(to, config);
1079
- /**
1080
- * Compares the two ends of the range once both of them are filled in.
1081
- * @param startValue - Raw value of the start field.
1082
- * @param endValue - Raw value of the end field.
1083
- * @returns The ordering error, or `null` when the pair is acceptable.
1084
- */
1085
- const checkOrder = (startValue, endValue) => {
1086
- const start = SystemUtils.parseDate(startValue ?? undefined);
1087
- const end = SystemUtils.parseDate(endValue ?? undefined);
1088
- // A half-open range is legitimate: nothing to compare until both ends are there. An end that
1089
- // is not a valid date is already reported by the `date` rule bound above, so it is skipped
1090
- // here rather than reported twice.
1091
- if (!start || !end)
1092
- return null;
1093
- if (start.getFullYear() < MIN_VALID_YEAR || end.getFullYear() < MIN_VALID_YEAR)
1094
- return null;
1095
- return endOfDay(start) <= endOfDay(end)
1096
- ? null
1097
- : { kind: 'dateRange', message: config?.message ?? ARS_VALIDATOR_MESSAGES['dateRange'] };
1098
- };
1099
- // Reading the opposite end through `valueOf` keeps each rule reactive on the other field, so
1100
- // filling in one end re-validates the other.
1101
- validate(from, ctx => {
1102
- if (config?.when && !config.when(ctx))
1103
- return null;
1104
- return checkOrder(ctx.value(), ctx.valueOf(to));
1105
- });
1106
- validate(to, ctx => {
1107
- if (config?.when && !config.when(ctx))
1108
- return null;
1109
- return checkOrder(ctx.valueOf(from), ctx.value());
1110
- });
1120
+ date(from, config);
1121
+ date(to, config);
1122
+ const checkOrder = (startValue, endValue) => {
1123
+ const start = SystemUtils.parseDate(startValue ?? void 0);
1124
+ const end = SystemUtils.parseDate(endValue ?? void 0);
1125
+ if (!start || !end) return null;
1126
+ if (start.getFullYear() < 1750 || end.getFullYear() < 1750) return null;
1127
+ return endOfDay(start) <= endOfDay(end) ? null : {
1128
+ kind: "dateRange",
1129
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["dateRange"]
1130
+ };
1131
+ };
1132
+ validate(from, (ctx) => {
1133
+ if (config?.when && !config.when(ctx)) return null;
1134
+ return checkOrder(ctx.value(), ctx.valueOf(to));
1135
+ });
1136
+ validate(to, (ctx) => {
1137
+ if (config?.when && !config.when(ctx)) return null;
1138
+ return checkOrder(ctx.valueOf(from), ctx.value());
1139
+ });
1111
1140
  }
1112
- /**
1113
- * Requires the value to be a date that is not in the future.
1114
- *
1115
- * The signal-form counterpart of `NotFutureValidatorDirective`. Today counts as valid: the
1116
- * comparison is made on the end of the day, so a date entered this morning does not become
1117
- * invalid because the clock says 09:00.
1118
- *
1119
- * Like {@link notPast}, it accepts both the `Date` a Material datepicker writes into the model and
1120
- * the text of a plain input. An empty value passes: saying "obbligatorio" is the job of
1121
- * `required()`.
1122
- *
1123
- * @param path - Path of the field to validate.
1124
- * @param config - Optional message override and `when` condition.
1125
- * @returns void
1126
- * @example
1127
- * const f = form(this.model, p => { required(p.executionDate); notFuture(p.executionDate); });
1128
- */
1129
1141
  function notFuture(path, config) {
1130
- validate(path, ctx => {
1131
- if (config?.when && !config.when(ctx))
1132
- return null;
1133
- const input = ctx.value();
1134
- if (input === undefined || input === null || input === '')
1135
- return null;
1136
- const parsed = SystemUtils.parseDate(input);
1137
- const invalid = { kind: 'notFuture', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notFuture'] };
1138
- if (!parsed)
1139
- return invalid;
1140
- return endOfDay(parsed) <= endOfDay(new Date()) ? null : invalid;
1141
- });
1142
+ validate(path, (ctx) => {
1143
+ if (config?.when && !config.when(ctx)) return null;
1144
+ const input = ctx.value();
1145
+ if (input === void 0 || input === null || input === "") return null;
1146
+ const parsed = SystemUtils.parseDate(input);
1147
+ const invalid = {
1148
+ kind: "notFuture",
1149
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["notFuture"]
1150
+ };
1151
+ if (!parsed) return invalid;
1152
+ return endOfDay(parsed) <= endOfDay(/* @__PURE__ */ new Date()) ? null : invalid;
1153
+ });
1142
1154
  }
1143
- /**
1144
- * Requires the value to be a date that is not in the past.
1145
- *
1146
- * The mirror image of {@link notFuture}, for the fields that can only look forward: an expiry, a
1147
- * deadline, the date of a course still to be held. Today counts as valid — the comparison is made
1148
- * on the start of the day, so a date picked this afternoon for today does not become invalid
1149
- * because the clock has moved on.
1150
- *
1151
- * Like {@link date}, and unlike the older {@link notFuture}, it accepts both the `Date` a Material
1152
- * datepicker writes into the model and the text of a plain input. An empty value passes: saying
1153
- * "obbligatorio" is the job of `required()`.
1154
- *
1155
- * @param path - Path of the field to validate.
1156
- * @param config - Optional message override and `when` condition.
1157
- * @returns void
1158
- * @example
1159
- * const f = form(this.model, p => { required(p.scadenza); notPast(p.scadenza); });
1160
- */
1161
1155
  function notPast(path, config) {
1162
- validate(path, ctx => {
1163
- if (config?.when && !config.when(ctx))
1164
- return null;
1165
- const input = ctx.value();
1166
- if (input === undefined || input === null || input === '')
1167
- return null;
1168
- const parsed = SystemUtils.parseDate(input);
1169
- const invalid = { kind: 'notPast', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notPast'] };
1170
- if (!parsed)
1171
- return invalid;
1172
- return startOfDay(parsed) >= startOfDay(new Date()) ? null : invalid;
1173
- });
1156
+ validate(path, (ctx) => {
1157
+ if (config?.when && !config.when(ctx)) return null;
1158
+ const input = ctx.value();
1159
+ if (input === void 0 || input === null || input === "") return null;
1160
+ const parsed = SystemUtils.parseDate(input);
1161
+ const invalid = {
1162
+ kind: "notPast",
1163
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["notPast"]
1164
+ };
1165
+ if (!parsed) return invalid;
1166
+ return startOfDay(parsed) >= startOfDay(/* @__PURE__ */ new Date()) ? null : invalid;
1167
+ });
1174
1168
  }
1175
- /**
1176
- * Requires the value to be a well-formed URL. An empty value passes, as everywhere else here.
1177
- *
1178
- * The signal-form counterpart of `UrlValidatorDirective`.
1179
- *
1180
- * @param path - Path of the field to validate.
1181
- * @param config - Optional message override and `when` condition.
1182
- * @returns void
1183
- */
1184
1169
  function url(path, config) {
1185
- validate(path, ctx => {
1186
- if (config?.when && !config.when(ctx))
1187
- return null;
1188
- const input = ctx.value();
1189
- if (!input || input.length === 0)
1190
- return null;
1191
- return SystemUtils.parseUrl(input)
1192
- ? null
1193
- : { kind: 'url', message: config?.message ?? ARS_VALIDATOR_MESSAGES['url'] };
1194
- });
1170
+ validate(path, (ctx) => {
1171
+ if (config?.when && !config.when(ctx)) return null;
1172
+ const input = ctx.value();
1173
+ if (!input || input.length === 0) return null;
1174
+ return SystemUtils.parseUrl(input) ? null : {
1175
+ kind: "url",
1176
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["url"]
1177
+ };
1178
+ });
1195
1179
  }
1196
- /**
1197
- * Requires the value to hold no more than `max` whitespace-separated terms.
1198
- *
1199
- * The signal-form counterpart of `MaxTermsValidatorDirective`, used on the search boxes where
1200
- * the backend refuses a query past a certain number of words.
1201
- *
1202
- * @param path - Path of the field to validate.
1203
- * @param max - The maximum number of terms, as a number or a reactive function.
1204
- * @param config - Optional message override and `when` condition.
1205
- * @returns void
1206
- */
1207
1180
  function maxTerms(path, max, config) {
1208
- validate(path, ctx => {
1209
- if (config?.when && !config.when(ctx))
1210
- return null;
1211
- const input = ctx.value();
1212
- if (!input)
1213
- return null;
1214
- const terms = input.match(/\S+/g)?.length ?? 0;
1215
- return terms <= (typeof max === 'function' ? max() : max)
1216
- ? null
1217
- : { kind: 'maxTerms', message: config?.message ?? ARS_VALIDATOR_MESSAGES['maxTerms'] };
1218
- });
1181
+ validate(path, (ctx) => {
1182
+ if (config?.when && !config.when(ctx)) return null;
1183
+ const input = ctx.value();
1184
+ if (!input) return null;
1185
+ return (input.match(/\S+/g)?.length ?? 0) <= (typeof max === "function" ? max() : max) ? null : {
1186
+ kind: "maxTerms",
1187
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["maxTerms"]
1188
+ };
1189
+ });
1219
1190
  }
1220
- /**
1221
- * Requires the size of the picked file to fall within the allowed range.
1222
- *
1223
- * The signal-form counterpart of `FileSizeValidatorDirective`, and it keeps its shape: the field
1224
- * itself holds the file NAME, while the size arrives from outside — the control that picked the
1225
- * file knows it, the form does not. An empty field passes, so "no file" is `required()`'s call
1226
- * and not a size error.
1227
- *
1228
- * @param path - Path of the field holding the file name.
1229
- * @param sizeMb - The size of the picked file in megabytes, as a reactive function.
1230
- * @param maxSizeMb - The maximum allowed size in megabytes. Defaults to `5`.
1231
- * @param minSizeMb - The minimum required size in megabytes. Defaults to `0`.
1232
- * @param config - Optional message override and `when` condition.
1233
- * @returns void
1234
- */
1235
1191
  function fileSize(path, sizeMb, maxSizeMb = 5, minSizeMb = 0, config) {
1236
- validate(path, ctx => {
1237
- if (config?.when && !config.when(ctx))
1238
- return null;
1239
- if (!ctx.value())
1240
- return null;
1241
- const size = sizeMb() ?? 0;
1242
- const max = typeof maxSizeMb === 'function' ? maxSizeMb() : maxSizeMb;
1243
- const min = typeof minSizeMb === 'function' ? minSizeMb() : minSizeMb;
1244
- return size <= max && size >= min
1245
- ? null
1246
- : { kind: 'fileSize', message: config?.message ?? ARS_VALIDATOR_MESSAGES['fileSize'] };
1247
- });
1192
+ validate(path, (ctx) => {
1193
+ if (config?.when && !config.when(ctx)) return null;
1194
+ if (!ctx.value()) return null;
1195
+ const size = sizeMb() ?? 0;
1196
+ const max = typeof maxSizeMb === "function" ? maxSizeMb() : maxSizeMb;
1197
+ const min = typeof minSizeMb === "function" ? minSizeMb() : minSizeMb;
1198
+ return size <= max && size >= min ? null : {
1199
+ kind: "fileSize",
1200
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["fileSize"]
1201
+ };
1202
+ });
1248
1203
  }
1249
- /**
1250
- * Requires the value to declare itself valid.
1251
- *
1252
- * The signal-form counterpart of `ValidIfDirective`: when the field holds an object implementing
1253
- * `Validated` the verdict is its own `isValid()`, and when the field is empty the verdict is the
1254
- * `flag`. It is the escape hatch for the composite controls whose validity only they can judge.
1255
- *
1256
- * @param path - Path of the field to validate.
1257
- * @param flag - Verdict used while the field is empty, as a boolean or a reactive function.
1258
- * Defaults to `false`.
1259
- * @param config - Optional message override and `when` condition.
1260
- * @returns void
1261
- */
1262
1204
  function validIf(path, flag = false, config) {
1263
- validate(path, ctx => {
1264
- if (config?.when && !config.when(ctx))
1265
- return null;
1266
- const value = ctx.value();
1267
- let isValid;
1268
- if (!value) {
1269
- isValid = (typeof flag === 'function' ? flag() : flag) === true;
1270
- }
1271
- else {
1272
- try {
1273
- isValid = value.isValid?.() === true;
1274
- }
1275
- catch {
1276
- isValid = false;
1277
- }
1278
- }
1279
- return isValid ? null : { kind: 'validIf', message: config?.message ?? ARS_VALIDATOR_MESSAGES['validIf'] };
1280
- });
1205
+ validate(path, (ctx) => {
1206
+ if (config?.when && !config.when(ctx)) return null;
1207
+ const value = ctx.value();
1208
+ let isValid;
1209
+ if (!value) isValid = (typeof flag === "function" ? flag() : flag) === true;
1210
+ else try {
1211
+ isValid = value.isValid?.() === true;
1212
+ } catch {
1213
+ isValid = false;
1214
+ }
1215
+ return isValid ? null : {
1216
+ kind: "validIf",
1217
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["validIf"]
1218
+ };
1219
+ });
1281
1220
  }
1282
- /**
1283
- * Requires the value to be a semicolon-separated list of valid e-mail addresses.
1284
- *
1285
- * The signal-form counterpart of `EmailsValidatorDirective`. An empty value passes, and so does
1286
- * an empty entry between two semicolons: the list is typed by hand and a trailing `;` is not a
1287
- * mistake worth an error.
1288
- *
1289
- * @param path - Path of the field to validate.
1290
- * @param config - Optional message override and `when` condition.
1291
- * @returns void
1292
- */
1293
1221
  function emails(path, config) {
1294
- validate(path, ctx => {
1295
- if (config?.when && !config.when(ctx))
1296
- return null;
1297
- const input = ctx.value();
1298
- if (!input || input.length === 0)
1299
- return null;
1300
- const parts = input.replaceAll(/\r\n/g, '').split(';');
1301
- const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));
1302
- return isValid ? null : { kind: 'emails', message: config?.message ?? ARS_VALIDATOR_MESSAGES['emails'] };
1303
- });
1222
+ validate(path, (ctx) => {
1223
+ if (config?.when && !config.when(ctx)) return null;
1224
+ const input = ctx.value();
1225
+ if (!input || input.length === 0) return null;
1226
+ return input.replaceAll(/\r\n/g, "").split(";").every((part) => part.length === 0 || !!SystemUtils.parseEmail(part)) ? null : {
1227
+ kind: "emails",
1228
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["emails"]
1229
+ };
1230
+ });
1304
1231
  }
1305
- /**
1306
- * Requires the value to be a `"HH:MM"` time and, when slots are given, to fall inside one of them.
1307
- *
1308
- * The signal-form counterpart of `TimeValidatorDirective`. An empty value passes.
1309
- *
1310
- * @param path - Path of the field to validate.
1311
- * @param slots - Optional reactive function returning the pipe-separated allowed ranges
1312
- * (e.g. `"08:00-12:00|14:00-18:00"`), or `undefined` for no restriction.
1313
- * @param config - Optional message override and `when` condition.
1314
- * @returns void
1315
- */
1316
1232
  function time(path, slots, config) {
1317
- /**
1318
- * Turns `"HH:MM"` into a comparable integer (`"09:30"` -> `930`).
1319
- * @param value - The time string to parse.
1320
- * @returns The comparable integer, or `-1` when the string is not a valid time.
1321
- */
1322
- const getTime = (value) => {
1323
- const p = value.split(':');
1324
- if (p.length !== 2)
1325
- return -1;
1326
- const hh = parseInt(p[0], 10);
1327
- if (isNaN(hh) || hh < 0 || hh > 23)
1328
- return -1;
1329
- const mm = parseInt(p[1], 10);
1330
- if (isNaN(mm) || mm < 0 || mm > 59)
1331
- return -1;
1332
- return hh * 100 + mm;
1333
- };
1334
- validate(path, ctx => {
1335
- if (config?.when && !config.when(ctx))
1336
- return null;
1337
- const input = ctx.value();
1338
- if (!input || input.length === 0)
1339
- return null;
1340
- const invalid = { kind: 'time', message: config?.message ?? ARS_VALIDATOR_MESSAGES['time'] };
1341
- const t = getTime(input);
1342
- if (t === -1)
1343
- return invalid;
1344
- const slotsValue = slots?.();
1345
- if (slotsValue) {
1346
- const inSlot = slotsValue.split('|').some(s => {
1347
- const from = getTime(s.substring(0, 5));
1348
- const to = getTime(s.substring(6));
1349
- return from !== -1 && to !== -1 && from <= t && to >= t;
1350
- });
1351
- if (!inSlot)
1352
- return invalid;
1353
- }
1354
- return null;
1355
- });
1233
+ const getTime = (value) => {
1234
+ const p = value.split(":");
1235
+ if (p.length !== 2) return -1;
1236
+ const hh = parseInt(p[0], 10);
1237
+ if (isNaN(hh) || hh < 0 || hh > 23) return -1;
1238
+ const mm = parseInt(p[1], 10);
1239
+ if (isNaN(mm) || mm < 0 || mm > 59) return -1;
1240
+ return hh * 100 + mm;
1241
+ };
1242
+ validate(path, (ctx) => {
1243
+ if (config?.when && !config.when(ctx)) return null;
1244
+ const input = ctx.value();
1245
+ if (!input || input.length === 0) return null;
1246
+ const invalid = {
1247
+ kind: "time",
1248
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["time"]
1249
+ };
1250
+ const t = getTime(input);
1251
+ if (t === -1) return invalid;
1252
+ const slotsValue = slots?.();
1253
+ if (slotsValue) {
1254
+ if (!slotsValue.split("|").some((s) => {
1255
+ const from = getTime(s.substring(0, 5));
1256
+ const to = getTime(s.substring(6));
1257
+ return from !== -1 && to !== -1 && from <= t && to >= t;
1258
+ })) return invalid;
1259
+ }
1260
+ return null;
1261
+ });
1356
1262
  }
1357
- /**
1358
- * Requires the value to equal the value of another field of the same form.
1359
- *
1360
- * The signal-form counterpart of `EqualsValidatorDirective`. Reactive on both fields, which is
1361
- * what the directive needed a `valueChanges` subscription to obtain: retyping the first password
1362
- * re-validates the confirmation without anyone wiring the two together.
1363
- *
1364
- * @param path - Path of the field to validate.
1365
- * @param other - Path of the field whose value must match.
1366
- * @param config - Optional message override and `when` condition.
1367
- * @returns void
1368
- */
1369
1263
  function equals(path, other, config) {
1370
- validate(path, ctx => {
1371
- if (config?.when && !config.when(ctx))
1372
- return null;
1373
- return ctx.valueOf(other) === ctx.value()
1374
- ? null
1375
- : { kind: 'equals', message: config?.message ?? ARS_VALIDATOR_MESSAGES['equals'] };
1376
- });
1264
+ validate(path, (ctx) => {
1265
+ if (config?.when && !config.when(ctx)) return null;
1266
+ return ctx.valueOf(other) === ctx.value() ? null : {
1267
+ kind: "equals",
1268
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["equals"]
1269
+ };
1270
+ });
1377
1271
  }
1378
- /**
1379
- * Requires the value to be either empty or a complete six-digit one-time code.
1380
- *
1381
- * The schema-level counterpart of the validator inside `OtpInputComponent`: a partial code is an
1382
- * error, an empty one is `required()`'s business.
1383
- *
1384
- * @param path - Path of the field to validate.
1385
- * @param config - Optional message override and `when` condition.
1386
- * @returns void
1387
- */
1388
1272
  function otp(path, config) {
1389
- validate(path, ctx => {
1390
- if (config?.when && !config.when(ctx))
1391
- return null;
1392
- const input = ctx.value() ?? '';
1393
- if (input.length === 0)
1394
- return null;
1395
- return /^\d{6}$/.test(input)
1396
- ? null
1397
- : { kind: 'otp', message: config?.message ?? ARS_VALIDATOR_MESSAGES['otp'] };
1398
- });
1273
+ validate(path, (ctx) => {
1274
+ if (config?.when && !config.when(ctx)) return null;
1275
+ const input = ctx.value() ?? "";
1276
+ if (input.length === 0) return null;
1277
+ return /^\d{6}$/.test(input) ? null : {
1278
+ kind: "otp",
1279
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["otp"]
1280
+ };
1281
+ });
1399
1282
  }
1400
- /**
1401
- * Requires the value to be a valid Italian VAT number (partita IVA).
1402
- *
1403
- * Eleven digits whose last one is the check digit of D.P.R. 633/72, so a mistyped or invented
1404
- * number is caught here rather than by the backend that will refuse the invoice. An `IT` prefix
1405
- * and the spacing of a pasted value are tolerated, because that is the shape the number arrives
1406
- * in; what is stored is still whatever the user typed, since this rule only judges.
1407
- *
1408
- * An empty value passes, as everywhere else here: declaring the field mandatory is `required()`'s
1409
- * job.
1410
- *
1411
- * @param path - Path of the field to validate.
1412
- * @param config - Optional message override and `when` condition.
1413
- * @returns void
1414
- * @example
1415
- * const f = form(this.model, p => { required(p.partitaIva); italianVat(p.partitaIva); });
1416
- */
1417
1283
  function italianVat(path, config) {
1418
- validate(path, ctx => {
1419
- if (config?.when && !config.when(ctx))
1420
- return null;
1421
- const input = ctx.value();
1422
- if (!input || input.length === 0)
1423
- return null;
1424
- return isValidItalianVat(input)
1425
- ? null
1426
- : { kind: 'italianVat', message: config?.message ?? ARS_VALIDATOR_MESSAGES['italianVat'] };
1427
- });
1284
+ validate(path, (ctx) => {
1285
+ if (config?.when && !config.when(ctx)) return null;
1286
+ const input = ctx.value();
1287
+ if (!input || input.length === 0) return null;
1288
+ return isValidItalianVat(input) ? null : {
1289
+ kind: "italianVat",
1290
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["italianVat"]
1291
+ };
1292
+ });
1428
1293
  }
1429
- /**
1430
- * Requires the value to be a valid Italian fiscal code (codice fiscale).
1431
- *
1432
- * Both shapes a registry form receives are accepted: the sixteen-character code of a natural
1433
- * person, control character recomputed and compared, and the eleven digits of a company or a
1434
- * public body, whose fiscal code IS its VAT number. Nothing has to tell the rule which one is
1435
- * coming — the value says it by its own length.
1436
- *
1437
- * Codes altered by an "omocodia" substitution (digits replaced by letters when two people would
1438
- * otherwise share a code) are accepted: they are issued by the Agenzia delle Entrate and rejecting
1439
- * them is the classic way a form turns away a real person.
1440
- *
1441
- * An empty value passes. Pair with `required()` when the field is mandatory, and reach for
1442
- * {@link italianVat} instead on a field that is specifically a VAT number.
1443
- *
1444
- * @param path - Path of the field to validate.
1445
- * @param config - Optional message override and `when` condition.
1446
- * @returns void
1447
- * @example
1448
- * const f = form(this.model, p => { required(p.codiceFiscale); italianFiscalCode(p.codiceFiscale); });
1449
- */
1450
1294
  function italianFiscalCode(path, config) {
1451
- validate(path, ctx => {
1452
- if (config?.when && !config.when(ctx))
1453
- return null;
1454
- const input = ctx.value();
1455
- if (!input || input.length === 0)
1456
- return null;
1457
- return isValidItalianFiscalCode(input)
1458
- ? null
1459
- : {
1460
- kind: 'italianFiscalCode',
1461
- message: config?.message ?? ARS_VALIDATOR_MESSAGES['italianFiscalCode'],
1462
- };
1463
- });
1295
+ validate(path, (ctx) => {
1296
+ if (config?.when && !config.when(ctx)) return null;
1297
+ const input = ctx.value();
1298
+ if (!input || input.length === 0) return null;
1299
+ return isValidItalianFiscalCode(input) ? null : {
1300
+ kind: "italianFiscalCode",
1301
+ message: config?.message ?? ARS_VALIDATOR_MESSAGES["italianFiscalCode"]
1302
+ };
1303
+ });
1464
1304
  }
1465
- /** Helpers around signal forms that are not validators themselves. */
1466
- class SignalsUtils {
1467
- /**
1468
- * Builds the error text for a signal-forms field.
1469
- *
1470
- * Deliberately dumb: the wording lives in the schema, next to the rule that produces it
1471
- * (`required(p.x, { message: ... })`), so a field says what is wrong with it in one place
1472
- * instead of here in a switch that has to guess from the error kind. The map below is only
1473
- * the safety net for the rules declared without a message — the Angular built-ins, plus
1474
- * {@link ARS_VALIDATOR_MESSAGES} for the ones declared in this file.
1475
- * @param errors - The errors currently on the field, from `f.x().errors()`.
1476
- * @param message - Optional override applied to every error of the field.
1477
- * @returns The first relevant error text, or `undefined` when the field has no errors.
1478
- */
1479
- static getFieldErrorMessage(errors, message) {
1480
- if (!errors || errors.length === 0)
1481
- return undefined;
1482
- const fallback = {
1483
- // Angular built-ins declared without a message of their own.
1484
- min: 'Valore troppo basso',
1485
- max: 'Valore troppo alto',
1486
- minLength: 'Testo troppo corto',
1487
- maxLength: 'Testo troppo lungo',
1488
- pattern: 'Formato non valido',
1489
- email: 'Indirizzo email non valido',
1490
- minDate: 'Data troppo indietro',
1491
- maxDate: 'Data troppo avanti',
1492
- parse: 'Valore non valido',
1493
- matDatepickerParse: 'Data non valida',
1494
- matDatepickerMin: 'Data troppo indietro',
1495
- matDatepickerMax: 'Data troppo avanti',
1496
- matDatepickerFilter: 'Data non selezionabile',
1497
- matStartDateInvalid: 'Intervallo non valido',
1498
- matEndDateInvalid: 'Intervallo non valido',
1499
- matTimepickerParse: 'Orario non valido',
1500
- matTimepickerMin: 'Orario troppo presto',
1501
- matTimepickerMax: 'Orario troppo tardi',
1502
- // The rules of this file, from the single table above: adding a validator there is enough,
1503
- // and this map can never fall behind it.
1504
- ...ARS_VALIDATOR_MESSAGES,
1505
- };
1506
- message = message ?? errors[0].message ?? fallback[errors[0].kind] ?? '';
1507
- return message.length > 0 ? message : 'Non valido';
1508
- }
1509
- }
1510
-
1511
- /*
1512
- * Public API Surface of @arsedizioni/ars-utils/core.validators
1513
- *
1514
- * Template-driven form validators. Kept OUT of `core` on purpose: every one of them pulls in
1515
- * `@angular/forms` (53 KB), and `core` is on the boot path of every application through
1516
- * `ThemeService`, `BroadcastService` and friends. Importing a validator now costs `@angular/forms`
1517
- * only to the lazy chunk that actually uses one.
1518
- */
1519
-
1520
- /**
1521
- * Generated bundle index. Do not edit.
1522
- */
1523
-
1305
+ var SignalsUtils = class {
1306
+ static getFieldErrorMessage(errors, message) {
1307
+ if (!errors || errors.length === 0) return void 0;
1308
+ const fallback = {
1309
+ min: "Valore troppo basso",
1310
+ max: "Valore troppo alto",
1311
+ minLength: "Testo troppo corto",
1312
+ maxLength: "Testo troppo lungo",
1313
+ pattern: "Formato non valido",
1314
+ email: "Indirizzo email non valido",
1315
+ minDate: "Data troppo indietro",
1316
+ maxDate: "Data troppo avanti",
1317
+ parse: "Valore non valido",
1318
+ matDatepickerParse: "Data non valida",
1319
+ matDatepickerMin: "Data troppo indietro",
1320
+ matDatepickerMax: "Data troppo avanti",
1321
+ matDatepickerFilter: "Data non selezionabile",
1322
+ matStartDateInvalid: "Intervallo non valido",
1323
+ matEndDateInvalid: "Intervallo non valido",
1324
+ matTimepickerParse: "Orario non valido",
1325
+ matTimepickerMin: "Orario troppo presto",
1326
+ matTimepickerMax: "Orario troppo tardi",
1327
+ ...ARS_VALIDATOR_MESSAGES
1328
+ };
1329
+ message = message ?? errors[0].message ?? fallback[errors[0].kind] ?? "";
1330
+ return message.length > 0 ? message : "Non valido";
1331
+ }
1332
+ };
1524
1333
  export { ARS_VALIDATOR_MESSAGES, EmailsValidatorDirective, EqualsValidatorDirective, FileSizeValidatorDirective, GuidValidatorDirective, MIN_VALID_YEAR, MaxTermsValidatorDirective, NotEmptyValidatorDirective, NotEqualValidatorDirective, NotFutureValidatorDirective, PasswordValidatorDirective, SignalsUtils, SqlDateValidatorDirective, TimeValidatorDirective, UrlValidatorDirective, ValidIfDirective, ValidatorDirective, date, dateRange, emails, equals, fileSize, guid, italianFiscalCode, italianVat, maxTerms, notEmpty, notEqual, notFuture, notPast, otp, password, time, url, validIf };
1525
- //# sourceMappingURL=arsedizioni-ars-utils-core.validators.mjs.map
1334
+
1335
+ //# sourceMappingURL=arsedizioni-ars-utils-core.validators.mjs.map