@wiltech-labs/ngx-forms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2211 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, Injectable, computed, effect, inject, input, linkedSignal, output, signal, viewChildren } from "@angular/core";
3
+ import { MatButton } from "@angular/material/button";
4
+ import { FormField, disabled, email, max, maxLength, min, minLength, pattern, required, schema, validate } from "@angular/forms/signals";
5
+ import * as i1 from "@angular/material/form-field";
6
+ import { MatError, MatFormFieldModule } from "@angular/material/form-field";
7
+ import * as i2 from "@angular/material/input";
8
+ import { MatInput, MatInputModule } from "@angular/material/input";
9
+ import * as i3$2 from "@angular/cdk/text-field";
10
+ import { MatCheckbox } from "@angular/material/checkbox";
11
+ import { MatRadioButton, MatRadioGroup } from "@angular/material/radio";
12
+ import { MatOption, MatSelect } from "@angular/material/select";
13
+ import { MatSlider, MatSliderThumb } from "@angular/material/slider";
14
+ import { DateAdapter, MAT_DATE_FORMATS, MAT_NATIVE_DATE_FORMATS, NativeDateAdapter } from "@angular/material/core";
15
+ import * as i3$1 from "@angular/material/datepicker";
16
+ import { MatDatepickerModule } from "@angular/material/datepicker";
17
+ import { Temporal } from "temporal-polyfill";
18
+ import * as i3 from "@angular/material/timepicker";
19
+ import { MatTimepickerModule } from "@angular/material/timepicker";
20
+ var TextField = class TextField {
21
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
22
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
23
+ formField = computed(() => this.field(), ...ngDevMode ? [{ debugName: "formField" }] : /* istanbul ignore next */ []);
24
+ static ɵfac = i0.ɵɵngDeclareFactory({
25
+ minVersion: "12.0.0",
26
+ version: "22.2.0",
27
+ ngImport: i0,
28
+ type: TextField,
29
+ deps: [],
30
+ target: i0.ɵɵFactoryTarget.Component
31
+ });
32
+ static ɵcmp = i0.ɵɵngDeclareComponent({
33
+ minVersion: "17.0.0",
34
+ version: "22.2.0",
35
+ type: TextField,
36
+ isStandalone: true,
37
+ selector: "app-text-field",
38
+ inputs: {
39
+ fieldDef: {
40
+ classPropertyName: "fieldDef",
41
+ publicName: "fieldDef",
42
+ isSignal: true,
43
+ isRequired: true,
44
+ transformFunction: null
45
+ },
46
+ field: {
47
+ classPropertyName: "field",
48
+ publicName: "field",
49
+ isSignal: true,
50
+ isRequired: true,
51
+ transformFunction: null
52
+ }
53
+ },
54
+ ngImport: i0,
55
+ template: "<mat-form-field class=\"text-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input matInput [type]=\"fieldDef().type\" [formField]=\"formField()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
56
+ styles: [":host{display:block}.text-field{width:100%}\n"],
57
+ dependencies: [
58
+ {
59
+ kind: "directive",
60
+ type: FormField,
61
+ selector: "[formField]",
62
+ inputs: ["formField"],
63
+ exportAs: ["formField"]
64
+ },
65
+ {
66
+ kind: "ngmodule",
67
+ type: MatFormFieldModule
68
+ },
69
+ {
70
+ kind: "component",
71
+ type: i1.MatFormField,
72
+ selector: "mat-form-field",
73
+ inputs: [
74
+ "hideRequiredMarker",
75
+ "color",
76
+ "floatLabel",
77
+ "appearance",
78
+ "subscriptSizing",
79
+ "hintLabel"
80
+ ],
81
+ exportAs: ["matFormField"]
82
+ },
83
+ {
84
+ kind: "directive",
85
+ type: i1.MatLabel,
86
+ selector: "mat-label"
87
+ },
88
+ {
89
+ kind: "directive",
90
+ type: i1.MatHint,
91
+ selector: "mat-hint",
92
+ inputs: ["align", "id"]
93
+ },
94
+ {
95
+ kind: "directive",
96
+ type: i1.MatError,
97
+ selector: "mat-error, [matError]",
98
+ inputs: ["id"]
99
+ },
100
+ {
101
+ kind: "ngmodule",
102
+ type: MatInputModule
103
+ },
104
+ {
105
+ kind: "directive",
106
+ type: i2.MatInput,
107
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
108
+ inputs: [
109
+ "disabled",
110
+ "id",
111
+ "placeholder",
112
+ "name",
113
+ "required",
114
+ "type",
115
+ "errorStateMatcher",
116
+ "aria-describedby",
117
+ "value",
118
+ "readonly",
119
+ "disabledInteractive"
120
+ ],
121
+ exportAs: ["matInput"]
122
+ }
123
+ ],
124
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
125
+ });
126
+ };
127
+ i0.ɵɵngDeclareClassMetadata({
128
+ minVersion: "12.0.0",
129
+ version: "22.2.0",
130
+ ngImport: i0,
131
+ type: TextField,
132
+ decorators: [{
133
+ type: Component,
134
+ args: [{
135
+ selector: "app-text-field",
136
+ standalone: true,
137
+ imports: [
138
+ FormField,
139
+ MatFormFieldModule,
140
+ MatInputModule
141
+ ],
142
+ changeDetection: ChangeDetectionStrategy.OnPush,
143
+ template: "<mat-form-field class=\"text-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input matInput [type]=\"fieldDef().type\" [formField]=\"formField()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
144
+ styles: [":host{display:block}.text-field{width:100%}\n"]
145
+ }]
146
+ }],
147
+ propDecorators: {
148
+ fieldDef: [{
149
+ type: i0.Input,
150
+ args: [{
151
+ isSignal: true,
152
+ alias: "fieldDef",
153
+ required: true
154
+ }]
155
+ }],
156
+ field: [{
157
+ type: i0.Input,
158
+ args: [{
159
+ isSignal: true,
160
+ alias: "field",
161
+ required: true
162
+ }]
163
+ }]
164
+ }
165
+ });
166
+ var FormFieldType;
167
+ (function(FormFieldType) {
168
+ FormFieldType["TEXT"] = "text";
169
+ FormFieldType["EMAIL"] = "email";
170
+ FormFieldType["PASSWORD"] = "password";
171
+ FormFieldType["SEARCH"] = "search";
172
+ FormFieldType["RADIO"] = "radio";
173
+ FormFieldType["CHECKBOX"] = "checkbox";
174
+ FormFieldType["NUMBER"] = "number";
175
+ FormFieldType["RANGE"] = "range";
176
+ FormFieldType["SELECT"] = "select";
177
+ FormFieldType["TEXTAREA"] = "textarea";
178
+ FormFieldType["CODE"] = "code";
179
+ FormFieldType["BUSINESS_DATE"] = "business-date";
180
+ FormFieldType["BUSINESS_TIME"] = "business-time";
181
+ FormFieldType["INSTANT_DATE_TIME"] = "instant-date-time";
182
+ })(FormFieldType || (FormFieldType = {}));
183
+ const CODE_INDENT = " ";
184
+ var TextareaField = class TextareaField {
185
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
186
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
187
+ isCode = computed(() => this.fieldDef().type === FormFieldType.CODE, ...ngDevMode ? [{ debugName: "isCode" }] : /* istanbul ignore next */ []);
188
+ onKeydown(event) {
189
+ if (!this.isCode() || event.key !== "Tab") return;
190
+ event.preventDefault();
191
+ const textarea = event.target;
192
+ const start = textarea.selectionStart ?? 0;
193
+ const end = textarea.selectionEnd ?? 0;
194
+ const indented = `${textarea.value.substring(0, start)}${CODE_INDENT}${textarea.value.substring(end)}`;
195
+ textarea.value = indented;
196
+ textarea.selectionStart = textarea.selectionEnd = start + 2;
197
+ this.field()().value.set(indented);
198
+ }
199
+ static ɵfac = i0.ɵɵngDeclareFactory({
200
+ minVersion: "12.0.0",
201
+ version: "22.2.0",
202
+ ngImport: i0,
203
+ type: TextareaField,
204
+ deps: [],
205
+ target: i0.ɵɵFactoryTarget.Component
206
+ });
207
+ static ɵcmp = i0.ɵɵngDeclareComponent({
208
+ minVersion: "17.0.0",
209
+ version: "22.2.0",
210
+ type: TextareaField,
211
+ isStandalone: true,
212
+ selector: "app-textarea-field",
213
+ inputs: {
214
+ fieldDef: {
215
+ classPropertyName: "fieldDef",
216
+ publicName: "fieldDef",
217
+ isSignal: true,
218
+ isRequired: true,
219
+ transformFunction: null
220
+ },
221
+ field: {
222
+ classPropertyName: "field",
223
+ publicName: "field",
224
+ isSignal: true,
225
+ isRequired: true,
226
+ transformFunction: null
227
+ }
228
+ },
229
+ ngImport: i0,
230
+ template: "<mat-form-field class=\"textarea-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <textarea\r\n matInput\r\n [formField]=\"field()\"\r\n cdkTextareaAutosize\r\n [cdkAutosizeMinRows]=\"isCode() ? 8 : 4\"\r\n [class.textarea-field-code]=\"isCode()\"\r\n [attr.spellcheck]=\"isCode() ? 'false' : null\"\r\n (keydown)=\"onKeydown($event)\"\r\n ></textarea>\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
231
+ styles: [":host{display:block}.textarea-field{width:100%}.textarea-field-code{font-family:Courier New,Consolas,monospace;font-size:.85rem;tab-size:2}\n"],
232
+ dependencies: [
233
+ {
234
+ kind: "directive",
235
+ type: FormField,
236
+ selector: "[formField]",
237
+ inputs: ["formField"],
238
+ exportAs: ["formField"]
239
+ },
240
+ {
241
+ kind: "ngmodule",
242
+ type: MatFormFieldModule
243
+ },
244
+ {
245
+ kind: "component",
246
+ type: i1.MatFormField,
247
+ selector: "mat-form-field",
248
+ inputs: [
249
+ "hideRequiredMarker",
250
+ "color",
251
+ "floatLabel",
252
+ "appearance",
253
+ "subscriptSizing",
254
+ "hintLabel"
255
+ ],
256
+ exportAs: ["matFormField"]
257
+ },
258
+ {
259
+ kind: "directive",
260
+ type: i1.MatLabel,
261
+ selector: "mat-label"
262
+ },
263
+ {
264
+ kind: "directive",
265
+ type: i1.MatHint,
266
+ selector: "mat-hint",
267
+ inputs: ["align", "id"]
268
+ },
269
+ {
270
+ kind: "directive",
271
+ type: i1.MatError,
272
+ selector: "mat-error, [matError]",
273
+ inputs: ["id"]
274
+ },
275
+ {
276
+ kind: "ngmodule",
277
+ type: MatInputModule
278
+ },
279
+ {
280
+ kind: "directive",
281
+ type: i2.MatInput,
282
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
283
+ inputs: [
284
+ "disabled",
285
+ "id",
286
+ "placeholder",
287
+ "name",
288
+ "required",
289
+ "type",
290
+ "errorStateMatcher",
291
+ "aria-describedby",
292
+ "value",
293
+ "readonly",
294
+ "disabledInteractive"
295
+ ],
296
+ exportAs: ["matInput"]
297
+ },
298
+ {
299
+ kind: "directive",
300
+ type: i3$2.CdkTextareaAutosize,
301
+ selector: "textarea[cdkTextareaAutosize]",
302
+ inputs: [
303
+ "cdkAutosizeMinRows",
304
+ "cdkAutosizeMaxRows",
305
+ "cdkTextareaAutosize",
306
+ "placeholder"
307
+ ],
308
+ exportAs: ["cdkTextareaAutosize"]
309
+ }
310
+ ],
311
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
312
+ });
313
+ };
314
+ i0.ɵɵngDeclareClassMetadata({
315
+ minVersion: "12.0.0",
316
+ version: "22.2.0",
317
+ ngImport: i0,
318
+ type: TextareaField,
319
+ decorators: [{
320
+ type: Component,
321
+ args: [{
322
+ selector: "app-textarea-field",
323
+ standalone: true,
324
+ imports: [
325
+ FormField,
326
+ MatFormFieldModule,
327
+ MatInputModule
328
+ ],
329
+ changeDetection: ChangeDetectionStrategy.OnPush,
330
+ template: "<mat-form-field class=\"textarea-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <textarea\r\n matInput\r\n [formField]=\"field()\"\r\n cdkTextareaAutosize\r\n [cdkAutosizeMinRows]=\"isCode() ? 8 : 4\"\r\n [class.textarea-field-code]=\"isCode()\"\r\n [attr.spellcheck]=\"isCode() ? 'false' : null\"\r\n (keydown)=\"onKeydown($event)\"\r\n ></textarea>\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
331
+ styles: [":host{display:block}.textarea-field{width:100%}.textarea-field-code{font-family:Courier New,Consolas,monospace;font-size:.85rem;tab-size:2}\n"]
332
+ }]
333
+ }],
334
+ propDecorators: {
335
+ fieldDef: [{
336
+ type: i0.Input,
337
+ args: [{
338
+ isSignal: true,
339
+ alias: "fieldDef",
340
+ required: true
341
+ }]
342
+ }],
343
+ field: [{
344
+ type: i0.Input,
345
+ args: [{
346
+ isSignal: true,
347
+ alias: "field",
348
+ required: true
349
+ }]
350
+ }]
351
+ }
352
+ });
353
+ var FieldSubscript = class FieldSubscript {
354
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
355
+ hint = input(void 0, ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
356
+ errors = computed(() => {
357
+ const byKind = /* @__PURE__ */ new Map();
358
+ for (const error of this.field()().errors()) {
359
+ const existing = byKind.get(error.kind);
360
+ if (!existing || !existing.message && error.message) byKind.set(error.kind, error);
361
+ }
362
+ return [...byKind.values()];
363
+ }, ...ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []);
364
+ static ɵfac = i0.ɵɵngDeclareFactory({
365
+ minVersion: "12.0.0",
366
+ version: "22.2.0",
367
+ ngImport: i0,
368
+ type: FieldSubscript,
369
+ deps: [],
370
+ target: i0.ɵɵFactoryTarget.Component
371
+ });
372
+ static ɵcmp = i0.ɵɵngDeclareComponent({
373
+ minVersion: "17.0.0",
374
+ version: "22.2.0",
375
+ type: FieldSubscript,
376
+ isStandalone: true,
377
+ selector: "app-field-subscript",
378
+ inputs: {
379
+ field: {
380
+ classPropertyName: "field",
381
+ publicName: "field",
382
+ isSignal: true,
383
+ isRequired: true,
384
+ transformFunction: null
385
+ },
386
+ hint: {
387
+ classPropertyName: "hint",
388
+ publicName: "hint",
389
+ isSignal: true,
390
+ isRequired: false,
391
+ transformFunction: null
392
+ }
393
+ },
394
+ ngImport: i0,
395
+ template: "@let state = field()();\r\n@if (state.touched() && state.invalid()) {\r\n @for (error of errors(); track error.kind) {\r\n <mat-error class=\"field-subscript-error\">{{ error.message ?? error.kind }}</mat-error>\r\n }\r\n} @else if (hint()) {\r\n <div class=\"field-subscript-hint\">{{ hint() }}</div>\r\n}\r\n",
396
+ styles: [":host{display:block}.field-subscript-hint{font-size:12px;color:#0009;margin-top:4px;line-height:1.2}.field-subscript-error{display:block;margin-top:4px;font-size:12px;line-height:1.2}\n"],
397
+ dependencies: [{
398
+ kind: "directive",
399
+ type: MatError,
400
+ selector: "mat-error, [matError]",
401
+ inputs: ["id"]
402
+ }],
403
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
404
+ });
405
+ };
406
+ i0.ɵɵngDeclareClassMetadata({
407
+ minVersion: "12.0.0",
408
+ version: "22.2.0",
409
+ ngImport: i0,
410
+ type: FieldSubscript,
411
+ decorators: [{
412
+ type: Component,
413
+ args: [{
414
+ selector: "app-field-subscript",
415
+ standalone: true,
416
+ imports: [MatError],
417
+ changeDetection: ChangeDetectionStrategy.OnPush,
418
+ template: "@let state = field()();\r\n@if (state.touched() && state.invalid()) {\r\n @for (error of errors(); track error.kind) {\r\n <mat-error class=\"field-subscript-error\">{{ error.message ?? error.kind }}</mat-error>\r\n }\r\n} @else if (hint()) {\r\n <div class=\"field-subscript-hint\">{{ hint() }}</div>\r\n}\r\n",
419
+ styles: [":host{display:block}.field-subscript-hint{font-size:12px;color:#0009;margin-top:4px;line-height:1.2}.field-subscript-error{display:block;margin-top:4px;font-size:12px;line-height:1.2}\n"]
420
+ }]
421
+ }],
422
+ propDecorators: {
423
+ field: [{
424
+ type: i0.Input,
425
+ args: [{
426
+ isSignal: true,
427
+ alias: "field",
428
+ required: true
429
+ }]
430
+ }],
431
+ hint: [{
432
+ type: i0.Input,
433
+ args: [{
434
+ isSignal: true,
435
+ alias: "hint",
436
+ required: false
437
+ }]
438
+ }]
439
+ }
440
+ });
441
+ var CheckboxField = class CheckboxField {
442
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
443
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
444
+ static ɵfac = i0.ɵɵngDeclareFactory({
445
+ minVersion: "12.0.0",
446
+ version: "22.2.0",
447
+ ngImport: i0,
448
+ type: CheckboxField,
449
+ deps: [],
450
+ target: i0.ɵɵFactoryTarget.Component
451
+ });
452
+ static ɵcmp = i0.ɵɵngDeclareComponent({
453
+ minVersion: "17.0.0",
454
+ version: "22.2.0",
455
+ type: CheckboxField,
456
+ isStandalone: true,
457
+ selector: "app-checkbox-field",
458
+ inputs: {
459
+ fieldDef: {
460
+ classPropertyName: "fieldDef",
461
+ publicName: "fieldDef",
462
+ isSignal: true,
463
+ isRequired: true,
464
+ transformFunction: null
465
+ },
466
+ field: {
467
+ classPropertyName: "field",
468
+ publicName: "field",
469
+ isSignal: true,
470
+ isRequired: true,
471
+ transformFunction: null
472
+ }
473
+ },
474
+ ngImport: i0,
475
+ template: "<mat-checkbox [formField]=\"field()\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</mat-checkbox>\r\n<app-field-subscript class=\"checkbox-field-subscript\" [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
476
+ styles: [":host{display:block}.checkbox-field-subscript{padding-left:40px;margin-top:-4px}\n"],
477
+ dependencies: [
478
+ {
479
+ kind: "directive",
480
+ type: FormField,
481
+ selector: "[formField]",
482
+ inputs: ["formField"],
483
+ exportAs: ["formField"]
484
+ },
485
+ {
486
+ kind: "component",
487
+ type: MatCheckbox,
488
+ selector: "mat-checkbox",
489
+ inputs: [
490
+ "aria-label",
491
+ "aria-labelledby",
492
+ "aria-describedby",
493
+ "aria-expanded",
494
+ "aria-controls",
495
+ "aria-owns",
496
+ "id",
497
+ "required",
498
+ "labelPosition",
499
+ "name",
500
+ "value",
501
+ "disableRipple",
502
+ "tabIndex",
503
+ "color",
504
+ "disabledInteractive",
505
+ "checked",
506
+ "disabled",
507
+ "indeterminate"
508
+ ],
509
+ outputs: ["change", "indeterminateChange"],
510
+ exportAs: ["matCheckbox"]
511
+ },
512
+ {
513
+ kind: "component",
514
+ type: FieldSubscript,
515
+ selector: "app-field-subscript",
516
+ inputs: ["field", "hint"]
517
+ }
518
+ ],
519
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
520
+ });
521
+ };
522
+ i0.ɵɵngDeclareClassMetadata({
523
+ minVersion: "12.0.0",
524
+ version: "22.2.0",
525
+ ngImport: i0,
526
+ type: CheckboxField,
527
+ decorators: [{
528
+ type: Component,
529
+ args: [{
530
+ selector: "app-checkbox-field",
531
+ standalone: true,
532
+ imports: [
533
+ FormField,
534
+ MatCheckbox,
535
+ FieldSubscript
536
+ ],
537
+ changeDetection: ChangeDetectionStrategy.OnPush,
538
+ template: "<mat-checkbox [formField]=\"field()\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</mat-checkbox>\r\n<app-field-subscript class=\"checkbox-field-subscript\" [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
539
+ styles: [":host{display:block}.checkbox-field-subscript{padding-left:40px;margin-top:-4px}\n"]
540
+ }]
541
+ }],
542
+ propDecorators: {
543
+ fieldDef: [{
544
+ type: i0.Input,
545
+ args: [{
546
+ isSignal: true,
547
+ alias: "fieldDef",
548
+ required: true
549
+ }]
550
+ }],
551
+ field: [{
552
+ type: i0.Input,
553
+ args: [{
554
+ isSignal: true,
555
+ alias: "field",
556
+ required: true
557
+ }]
558
+ }]
559
+ }
560
+ });
561
+ let nextId$1 = 0;
562
+ var RadioField = class RadioField {
563
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
564
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
565
+ labelId = `radio-field-label-${nextId$1++}`;
566
+ static ɵfac = i0.ɵɵngDeclareFactory({
567
+ minVersion: "12.0.0",
568
+ version: "22.2.0",
569
+ ngImport: i0,
570
+ type: RadioField,
571
+ deps: [],
572
+ target: i0.ɵɵFactoryTarget.Component
573
+ });
574
+ static ɵcmp = i0.ɵɵngDeclareComponent({
575
+ minVersion: "17.0.0",
576
+ version: "22.2.0",
577
+ type: RadioField,
578
+ isStandalone: true,
579
+ selector: "app-radio-field",
580
+ inputs: {
581
+ fieldDef: {
582
+ classPropertyName: "fieldDef",
583
+ publicName: "fieldDef",
584
+ isSignal: true,
585
+ isRequired: true,
586
+ transformFunction: null
587
+ },
588
+ field: {
589
+ classPropertyName: "field",
590
+ publicName: "field",
591
+ isSignal: true,
592
+ isRequired: true,
593
+ transformFunction: null
594
+ }
595
+ },
596
+ ngImport: i0,
597
+ template: "<div class=\"radio-field-label\" [id]=\"labelId\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</div>\r\n<mat-radio-group\r\n class=\"radio-field-group\"\r\n [class.radio-field-group-vertical]=\"fieldDef().orientation === 'vertical'\"\r\n [attr.aria-orientation]=\"fieldDef().orientation ?? 'horizontal'\"\r\n [formField]=\"field()\"\r\n [attr.aria-labelledby]=\"labelId\">\r\n @for (option of fieldDef().options ?? []; track option.value) {\r\n <mat-radio-button [value]=\"option.value\">{{ option.label }}</mat-radio-button>\r\n }\r\n</mat-radio-group>\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
598
+ styles: [":host{display:block}.radio-field-label{font-size:14px;color:#0009;margin-bottom:0}.radio-field-group{display:flex;flex-wrap:wrap;column-gap:8px}.radio-field-group-vertical{flex-direction:column;flex-wrap:nowrap;align-items:flex-start}\n"],
599
+ dependencies: [
600
+ {
601
+ kind: "directive",
602
+ type: FormField,
603
+ selector: "[formField]",
604
+ inputs: ["formField"],
605
+ exportAs: ["formField"]
606
+ },
607
+ {
608
+ kind: "directive",
609
+ type: MatRadioGroup,
610
+ selector: "mat-radio-group",
611
+ inputs: [
612
+ "color",
613
+ "name",
614
+ "labelPosition",
615
+ "value",
616
+ "selected",
617
+ "disabled",
618
+ "required",
619
+ "disabledInteractive"
620
+ ],
621
+ outputs: ["change"],
622
+ exportAs: ["matRadioGroup"]
623
+ },
624
+ {
625
+ kind: "component",
626
+ type: MatRadioButton,
627
+ selector: "mat-radio-button",
628
+ inputs: [
629
+ "id",
630
+ "name",
631
+ "aria-label",
632
+ "aria-labelledby",
633
+ "aria-describedby",
634
+ "disableRipple",
635
+ "tabIndex",
636
+ "checked",
637
+ "value",
638
+ "labelPosition",
639
+ "disabled",
640
+ "required",
641
+ "color",
642
+ "disabledInteractive"
643
+ ],
644
+ outputs: ["change"],
645
+ exportAs: ["matRadioButton"]
646
+ },
647
+ {
648
+ kind: "component",
649
+ type: FieldSubscript,
650
+ selector: "app-field-subscript",
651
+ inputs: ["field", "hint"]
652
+ }
653
+ ],
654
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
655
+ });
656
+ };
657
+ i0.ɵɵngDeclareClassMetadata({
658
+ minVersion: "12.0.0",
659
+ version: "22.2.0",
660
+ ngImport: i0,
661
+ type: RadioField,
662
+ decorators: [{
663
+ type: Component,
664
+ args: [{
665
+ selector: "app-radio-field",
666
+ standalone: true,
667
+ imports: [
668
+ FormField,
669
+ MatRadioGroup,
670
+ MatRadioButton,
671
+ FieldSubscript
672
+ ],
673
+ changeDetection: ChangeDetectionStrategy.OnPush,
674
+ template: "<div class=\"radio-field-label\" [id]=\"labelId\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</div>\r\n<mat-radio-group\r\n class=\"radio-field-group\"\r\n [class.radio-field-group-vertical]=\"fieldDef().orientation === 'vertical'\"\r\n [attr.aria-orientation]=\"fieldDef().orientation ?? 'horizontal'\"\r\n [formField]=\"field()\"\r\n [attr.aria-labelledby]=\"labelId\">\r\n @for (option of fieldDef().options ?? []; track option.value) {\r\n <mat-radio-button [value]=\"option.value\">{{ option.label }}</mat-radio-button>\r\n }\r\n</mat-radio-group>\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
675
+ styles: [":host{display:block}.radio-field-label{font-size:14px;color:#0009;margin-bottom:0}.radio-field-group{display:flex;flex-wrap:wrap;column-gap:8px}.radio-field-group-vertical{flex-direction:column;flex-wrap:nowrap;align-items:flex-start}\n"]
676
+ }]
677
+ }],
678
+ propDecorators: {
679
+ fieldDef: [{
680
+ type: i0.Input,
681
+ args: [{
682
+ isSignal: true,
683
+ alias: "fieldDef",
684
+ required: true
685
+ }]
686
+ }],
687
+ field: [{
688
+ type: i0.Input,
689
+ args: [{
690
+ isSignal: true,
691
+ alias: "field",
692
+ required: true
693
+ }]
694
+ }]
695
+ }
696
+ });
697
+ var SelectField = class SelectField {
698
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
699
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
700
+ static ɵfac = i0.ɵɵngDeclareFactory({
701
+ minVersion: "12.0.0",
702
+ version: "22.2.0",
703
+ ngImport: i0,
704
+ type: SelectField,
705
+ deps: [],
706
+ target: i0.ɵɵFactoryTarget.Component
707
+ });
708
+ static ɵcmp = i0.ɵɵngDeclareComponent({
709
+ minVersion: "17.0.0",
710
+ version: "22.2.0",
711
+ type: SelectField,
712
+ isStandalone: true,
713
+ selector: "app-select-field",
714
+ inputs: {
715
+ fieldDef: {
716
+ classPropertyName: "fieldDef",
717
+ publicName: "fieldDef",
718
+ isSignal: true,
719
+ isRequired: true,
720
+ transformFunction: null
721
+ },
722
+ field: {
723
+ classPropertyName: "field",
724
+ publicName: "field",
725
+ isSignal: true,
726
+ isRequired: true,
727
+ transformFunction: null
728
+ }
729
+ },
730
+ ngImport: i0,
731
+ template: "<mat-form-field class=\"select-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <mat-select [formField]=\"field()\">\r\n @for (option of fieldDef().options ?? []; track option.value) {\r\n <mat-option [value]=\"option.value\">{{ option.label }}</mat-option>\r\n }\r\n </mat-select>\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
732
+ styles: [":host{display:block}.select-field{width:100%}\n"],
733
+ dependencies: [
734
+ {
735
+ kind: "directive",
736
+ type: FormField,
737
+ selector: "[formField]",
738
+ inputs: ["formField"],
739
+ exportAs: ["formField"]
740
+ },
741
+ {
742
+ kind: "ngmodule",
743
+ type: MatFormFieldModule
744
+ },
745
+ {
746
+ kind: "component",
747
+ type: i1.MatFormField,
748
+ selector: "mat-form-field",
749
+ inputs: [
750
+ "hideRequiredMarker",
751
+ "color",
752
+ "floatLabel",
753
+ "appearance",
754
+ "subscriptSizing",
755
+ "hintLabel"
756
+ ],
757
+ exportAs: ["matFormField"]
758
+ },
759
+ {
760
+ kind: "directive",
761
+ type: i1.MatLabel,
762
+ selector: "mat-label"
763
+ },
764
+ {
765
+ kind: "directive",
766
+ type: i1.MatHint,
767
+ selector: "mat-hint",
768
+ inputs: ["align", "id"]
769
+ },
770
+ {
771
+ kind: "directive",
772
+ type: i1.MatError,
773
+ selector: "mat-error, [matError]",
774
+ inputs: ["id"]
775
+ },
776
+ {
777
+ kind: "component",
778
+ type: MatSelect,
779
+ selector: "mat-select",
780
+ inputs: [
781
+ "aria-describedby",
782
+ "panelClass",
783
+ "disabled",
784
+ "disableRipple",
785
+ "tabIndex",
786
+ "hideSingleSelectionIndicator",
787
+ "placeholder",
788
+ "required",
789
+ "multiple",
790
+ "disableOptionCentering",
791
+ "compareWith",
792
+ "value",
793
+ "aria-label",
794
+ "aria-labelledby",
795
+ "errorStateMatcher",
796
+ "typeaheadDebounceInterval",
797
+ "sortComparator",
798
+ "id",
799
+ "panelWidth",
800
+ "canSelectNullableOptions"
801
+ ],
802
+ outputs: [
803
+ "openedChange",
804
+ "opened",
805
+ "closed",
806
+ "selectionChange",
807
+ "valueChange"
808
+ ],
809
+ exportAs: ["matSelect"]
810
+ },
811
+ {
812
+ kind: "component",
813
+ type: MatOption,
814
+ selector: "mat-option",
815
+ inputs: [
816
+ "value",
817
+ "id",
818
+ "disabled"
819
+ ],
820
+ outputs: ["onSelectionChange"],
821
+ exportAs: ["matOption"]
822
+ }
823
+ ],
824
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
825
+ });
826
+ };
827
+ i0.ɵɵngDeclareClassMetadata({
828
+ minVersion: "12.0.0",
829
+ version: "22.2.0",
830
+ ngImport: i0,
831
+ type: SelectField,
832
+ decorators: [{
833
+ type: Component,
834
+ args: [{
835
+ selector: "app-select-field",
836
+ standalone: true,
837
+ imports: [
838
+ FormField,
839
+ MatFormFieldModule,
840
+ MatSelect,
841
+ MatOption
842
+ ],
843
+ changeDetection: ChangeDetectionStrategy.OnPush,
844
+ template: "<mat-form-field class=\"select-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <mat-select [formField]=\"field()\">\r\n @for (option of fieldDef().options ?? []; track option.value) {\r\n <mat-option [value]=\"option.value\">{{ option.label }}</mat-option>\r\n }\r\n </mat-select>\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of field()().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
845
+ styles: [":host{display:block}.select-field{width:100%}\n"]
846
+ }]
847
+ }],
848
+ propDecorators: {
849
+ fieldDef: [{
850
+ type: i0.Input,
851
+ args: [{
852
+ isSignal: true,
853
+ alias: "fieldDef",
854
+ required: true
855
+ }]
856
+ }],
857
+ field: [{
858
+ type: i0.Input,
859
+ args: [{
860
+ isSignal: true,
861
+ alias: "field",
862
+ required: true
863
+ }]
864
+ }]
865
+ }
866
+ });
867
+ let nextId = 0;
868
+ var SliderField = class SliderField {
869
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
870
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
871
+ labelId = `slider-field-label-${nextId++}`;
872
+ static ɵfac = i0.ɵɵngDeclareFactory({
873
+ minVersion: "12.0.0",
874
+ version: "22.2.0",
875
+ ngImport: i0,
876
+ type: SliderField,
877
+ deps: [],
878
+ target: i0.ɵɵFactoryTarget.Component
879
+ });
880
+ static ɵcmp = i0.ɵɵngDeclareComponent({
881
+ minVersion: "17.0.0",
882
+ version: "22.2.0",
883
+ type: SliderField,
884
+ isStandalone: true,
885
+ selector: "app-slider-field",
886
+ inputs: {
887
+ fieldDef: {
888
+ classPropertyName: "fieldDef",
889
+ publicName: "fieldDef",
890
+ isSignal: true,
891
+ isRequired: true,
892
+ transformFunction: null
893
+ },
894
+ field: {
895
+ classPropertyName: "field",
896
+ publicName: "field",
897
+ isSignal: true,
898
+ isRequired: true,
899
+ transformFunction: null
900
+ }
901
+ },
902
+ ngImport: i0,
903
+ template: "<div class=\"slider-field-label\">\r\n <span [id]=\"labelId\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n </span>\r\n <span class=\"slider-field-value\">{{ field()().value() }}</span>\r\n</div>\r\n<mat-slider\r\n class=\"slider-field-slider\"\r\n discrete\r\n [min]=\"fieldDef().min ?? 0\"\r\n [max]=\"fieldDef().max ?? 100\"\r\n [step]=\"fieldDef().step ?? 1\">\r\n <input matSliderThumb [formField]=\"field()\" [attr.aria-labelledby]=\"labelId\" />\r\n</mat-slider>\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
904
+ styles: [":host{display:block}.slider-field-label{font-size:14px;color:#0009;display:flex;justify-content:space-between;align-items:baseline;margin-bottom:0}.slider-field-value{font-size:14px;font-weight:600;color:var(--mat-sys-primary, #3f51b5)}.slider-field-slider{display:block;width:100%;margin:0}\n"],
905
+ dependencies: [
906
+ {
907
+ kind: "directive",
908
+ type: FormField,
909
+ selector: "[formField]",
910
+ inputs: ["formField"],
911
+ exportAs: ["formField"]
912
+ },
913
+ {
914
+ kind: "component",
915
+ type: MatSlider,
916
+ selector: "mat-slider",
917
+ inputs: [
918
+ "disabled",
919
+ "discrete",
920
+ "showTickMarks",
921
+ "min",
922
+ "color",
923
+ "disableRipple",
924
+ "max",
925
+ "step",
926
+ "displayWith"
927
+ ],
928
+ exportAs: ["matSlider"]
929
+ },
930
+ {
931
+ kind: "directive",
932
+ type: MatSliderThumb,
933
+ selector: "input[matSliderThumb]",
934
+ inputs: ["value"],
935
+ outputs: [
936
+ "valueChange",
937
+ "dragStart",
938
+ "dragEnd"
939
+ ],
940
+ exportAs: ["matSliderThumb"]
941
+ },
942
+ {
943
+ kind: "component",
944
+ type: FieldSubscript,
945
+ selector: "app-field-subscript",
946
+ inputs: ["field", "hint"]
947
+ }
948
+ ],
949
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
950
+ });
951
+ };
952
+ i0.ɵɵngDeclareClassMetadata({
953
+ minVersion: "12.0.0",
954
+ version: "22.2.0",
955
+ ngImport: i0,
956
+ type: SliderField,
957
+ decorators: [{
958
+ type: Component,
959
+ args: [{
960
+ selector: "app-slider-field",
961
+ standalone: true,
962
+ imports: [
963
+ FormField,
964
+ MatSlider,
965
+ MatSliderThumb,
966
+ FieldSubscript
967
+ ],
968
+ changeDetection: ChangeDetectionStrategy.OnPush,
969
+ template: "<div class=\"slider-field-label\">\r\n <span [id]=\"labelId\">\r\n {{ fieldDef().label }}@if (field()().required()) {<span aria-hidden=\"true\"> *</span>}\r\n </span>\r\n <span class=\"slider-field-value\">{{ field()().value() }}</span>\r\n</div>\r\n<mat-slider\r\n class=\"slider-field-slider\"\r\n discrete\r\n [min]=\"fieldDef().min ?? 0\"\r\n [max]=\"fieldDef().max ?? 100\"\r\n [step]=\"fieldDef().step ?? 1\">\r\n <input matSliderThumb [formField]=\"field()\" [attr.aria-labelledby]=\"labelId\" />\r\n</mat-slider>\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
970
+ styles: [":host{display:block}.slider-field-label{font-size:14px;color:#0009;display:flex;justify-content:space-between;align-items:baseline;margin-bottom:0}.slider-field-value{font-size:14px;font-weight:600;color:var(--mat-sys-primary, #3f51b5)}.slider-field-slider{display:block;width:100%;margin:0}\n"]
971
+ }]
972
+ }],
973
+ propDecorators: {
974
+ fieldDef: [{
975
+ type: i0.Input,
976
+ args: [{
977
+ isSignal: true,
978
+ alias: "fieldDef",
979
+ required: true
980
+ }]
981
+ }],
982
+ field: [{
983
+ type: i0.Input,
984
+ args: [{
985
+ isSignal: true,
986
+ alias: "field",
987
+ required: true
988
+ }]
989
+ }]
990
+ }
991
+ });
992
+ const NUMERIC_DATE = /^(\d{1,4})\D+(\d{1,2})\D+(\d{1,4})$/;
993
+ var LocaleDateAdapter = class LocaleDateAdapter extends NativeDateAdapter {
994
+ parse(value, parseFormat) {
995
+ const match = typeof value === "string" ? value.trim().match(NUMERIC_DATE) : null;
996
+ if (!match) return super.parse(value, parseFormat);
997
+ const parts = {};
998
+ this.partOrder().forEach((part, index) => parts[part] = Number(match[index + 1]));
999
+ try {
1000
+ return this.createDate(parts.year, parts.month - 1, parts.day);
1001
+ } catch {
1002
+ return this.invalid();
1003
+ }
1004
+ }
1005
+ partOrder() {
1006
+ return new Intl.DateTimeFormat(this.locale).formatToParts(new Date(2e3, 10, 22)).map((part) => part.type).filter((type) => type === "day" || type === "month" || type === "year");
1007
+ }
1008
+ static ɵfac = i0.ɵɵngDeclareFactory({
1009
+ minVersion: "12.0.0",
1010
+ version: "22.2.0",
1011
+ ngImport: i0,
1012
+ type: LocaleDateAdapter,
1013
+ deps: null,
1014
+ target: i0.ɵɵFactoryTarget.Injectable
1015
+ });
1016
+ static ɵprov = i0.ɵɵngDeclareInjectable({
1017
+ minVersion: "12.0.0",
1018
+ version: "22.2.0",
1019
+ ngImport: i0,
1020
+ type: LocaleDateAdapter
1021
+ });
1022
+ };
1023
+ i0.ɵɵngDeclareClassMetadata({
1024
+ minVersion: "12.0.0",
1025
+ version: "22.2.0",
1026
+ ngImport: i0,
1027
+ type: LocaleDateAdapter,
1028
+ decorators: [{ type: Injectable }]
1029
+ });
1030
+ function provideLocaleDateAdapter() {
1031
+ return [{
1032
+ provide: DateAdapter,
1033
+ useClass: LocaleDateAdapter
1034
+ }, {
1035
+ provide: MAT_DATE_FORMATS,
1036
+ useValue: MAT_NATIVE_DATE_FORMATS
1037
+ }];
1038
+ }
1039
+ const INSTANT_DATE_TIME_INVALID_ERROR_LABEL = "Not a valid date and time.";
1040
+ const BUSINESS_DATE_INVALID_ERROR_LABEL = "Not a valid date.";
1041
+ const BUSINESS_TIME_INVALID_ERROR_LABEL = "Not a valid time.";
1042
+ function syncMatInputErrorState(inputs, state) {
1043
+ effect(() => {
1044
+ const hasError = state().touched() && state().invalid();
1045
+ for (const input of inputs()) if (input.errorState !== hasError) {
1046
+ input.errorState = hasError;
1047
+ input.stateChanges.next();
1048
+ }
1049
+ });
1050
+ }
1051
+ function parseInstant(value) {
1052
+ return tryParse(value, (v) => Temporal.Instant.from(v));
1053
+ }
1054
+ function parsePlainDate(value) {
1055
+ return tryParse(value, (v) => Temporal.PlainDate.from(v));
1056
+ }
1057
+ function parsePlainTime(value) {
1058
+ return tryParse(value, (v) => Temporal.PlainTime.from(v));
1059
+ }
1060
+ const DATE_TIME_RULES = {
1061
+ [FormFieldType.INSTANT_DATE_TIME]: {
1062
+ parse: parseInstant,
1063
+ compare: Temporal.Instant.compare,
1064
+ invalidMessage: INSTANT_DATE_TIME_INVALID_ERROR_LABEL
1065
+ },
1066
+ [FormFieldType.BUSINESS_DATE]: {
1067
+ parse: parsePlainDate,
1068
+ compare: Temporal.PlainDate.compare,
1069
+ invalidMessage: BUSINESS_DATE_INVALID_ERROR_LABEL
1070
+ },
1071
+ [FormFieldType.BUSINESS_TIME]: {
1072
+ parse: parsePlainTime,
1073
+ compare: Temporal.PlainTime.compare,
1074
+ invalidMessage: BUSINESS_TIME_INVALID_ERROR_LABEL
1075
+ }
1076
+ };
1077
+ function isDateTimeField(type) {
1078
+ return type in DATE_TIME_RULES;
1079
+ }
1080
+ function dateTimeError(value, fieldDef) {
1081
+ const rule = DATE_TIME_RULES[fieldDef.type];
1082
+ if (!rule || !value) return null;
1083
+ const parsed = rule.parse(value);
1084
+ if (!parsed) return {
1085
+ kind: "invalidDateTime",
1086
+ message: rule.invalidMessage
1087
+ };
1088
+ const min = fieldDef.dateTimeConfig?.min;
1089
+ const parsedMin = rule.parse(min);
1090
+ if (parsedMin && rule.compare(parsed, parsedMin) < 0) return {
1091
+ kind: "minDateTime",
1092
+ message: `${fieldDef.label} cannot be before ${min}`
1093
+ };
1094
+ const max = fieldDef.dateTimeConfig?.max;
1095
+ const parsedMax = rule.parse(max);
1096
+ if (parsedMax && rule.compare(parsed, parsedMax) > 0) return {
1097
+ kind: "maxDateTime",
1098
+ message: `${fieldDef.label} cannot be after ${max}`
1099
+ };
1100
+ return null;
1101
+ }
1102
+ function tryParse(value, parse) {
1103
+ if (!value) return null;
1104
+ try {
1105
+ return parse(value);
1106
+ } catch {
1107
+ return null;
1108
+ }
1109
+ }
1110
+ var BusinessDateField = class BusinessDateField {
1111
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
1112
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
1113
+ dateAdapter = inject(DateAdapter);
1114
+ state = computed(() => this.field()(), ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
1115
+ date = computed(() => toDate$1(this.state().value()), ...ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []);
1116
+ minDate = computed(() => toDate$1(this.fieldDef().dateTimeConfig?.min), ...ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []);
1117
+ maxDate = computed(() => toDate$1(this.fieldDef().dateTimeConfig?.max), ...ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []);
1118
+ inputs = viewChildren(MatInput, ...ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []);
1119
+ constructor() {
1120
+ syncMatInputErrorState(this.inputs, this.state);
1121
+ effect(() => this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || "en-GB"));
1122
+ }
1123
+ onDateChange(date) {
1124
+ if (!date || isNaN(date.getTime())) {
1125
+ this.state().value.set(null);
1126
+ return;
1127
+ }
1128
+ this.state().value.set(Temporal.PlainDate.from({
1129
+ year: date.getFullYear(),
1130
+ month: date.getMonth() + 1,
1131
+ day: date.getDate()
1132
+ }).toString());
1133
+ }
1134
+ static ɵfac = i0.ɵɵngDeclareFactory({
1135
+ minVersion: "12.0.0",
1136
+ version: "22.2.0",
1137
+ ngImport: i0,
1138
+ type: BusinessDateField,
1139
+ deps: [],
1140
+ target: i0.ɵɵFactoryTarget.Component
1141
+ });
1142
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1143
+ minVersion: "17.0.0",
1144
+ version: "22.2.0",
1145
+ type: BusinessDateField,
1146
+ isStandalone: true,
1147
+ selector: "app-business-date-field",
1148
+ inputs: {
1149
+ fieldDef: {
1150
+ classPropertyName: "fieldDef",
1151
+ publicName: "fieldDef",
1152
+ isSignal: true,
1153
+ isRequired: true,
1154
+ transformFunction: null
1155
+ },
1156
+ field: {
1157
+ classPropertyName: "field",
1158
+ publicName: "field",
1159
+ isSignal: true,
1160
+ isRequired: true,
1161
+ transformFunction: null
1162
+ }
1163
+ },
1164
+ providers: [provideLocaleDateAdapter()],
1165
+ viewQueries: [{
1166
+ propertyName: "inputs",
1167
+ predicate: MatInput,
1168
+ descendants: true,
1169
+ isSignal: true
1170
+ }],
1171
+ ngImport: i0,
1172
+ template: "<mat-form-field class=\"business-date-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input\r\n matInput\r\n [matDatepicker]=\"datepicker\"\r\n [value]=\"date()\"\r\n [min]=\"minDate()\"\r\n [max]=\"maxDate()\"\r\n [required]=\"state().required()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (dateChange)=\"onDateChange($event.value)\"\r\n />\r\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\r\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of state().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
1173
+ styles: [":host{display:block}.business-date-field{width:100%}\n"],
1174
+ dependencies: [
1175
+ {
1176
+ kind: "ngmodule",
1177
+ type: MatFormFieldModule
1178
+ },
1179
+ {
1180
+ kind: "component",
1181
+ type: i1.MatFormField,
1182
+ selector: "mat-form-field",
1183
+ inputs: [
1184
+ "hideRequiredMarker",
1185
+ "color",
1186
+ "floatLabel",
1187
+ "appearance",
1188
+ "subscriptSizing",
1189
+ "hintLabel"
1190
+ ],
1191
+ exportAs: ["matFormField"]
1192
+ },
1193
+ {
1194
+ kind: "directive",
1195
+ type: i1.MatLabel,
1196
+ selector: "mat-label"
1197
+ },
1198
+ {
1199
+ kind: "directive",
1200
+ type: i1.MatHint,
1201
+ selector: "mat-hint",
1202
+ inputs: ["align", "id"]
1203
+ },
1204
+ {
1205
+ kind: "directive",
1206
+ type: i1.MatError,
1207
+ selector: "mat-error, [matError]",
1208
+ inputs: ["id"]
1209
+ },
1210
+ {
1211
+ kind: "directive",
1212
+ type: i1.MatSuffix,
1213
+ selector: "[matSuffix], [matIconSuffix], [matTextSuffix]",
1214
+ inputs: ["matTextSuffix"]
1215
+ },
1216
+ {
1217
+ kind: "ngmodule",
1218
+ type: MatInputModule
1219
+ },
1220
+ {
1221
+ kind: "directive",
1222
+ type: i2.MatInput,
1223
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
1224
+ inputs: [
1225
+ "disabled",
1226
+ "id",
1227
+ "placeholder",
1228
+ "name",
1229
+ "required",
1230
+ "type",
1231
+ "errorStateMatcher",
1232
+ "aria-describedby",
1233
+ "value",
1234
+ "readonly",
1235
+ "disabledInteractive"
1236
+ ],
1237
+ exportAs: ["matInput"]
1238
+ },
1239
+ {
1240
+ kind: "ngmodule",
1241
+ type: MatDatepickerModule
1242
+ },
1243
+ {
1244
+ kind: "component",
1245
+ type: i3$1.MatDatepicker,
1246
+ selector: "mat-datepicker",
1247
+ exportAs: ["matDatepicker"]
1248
+ },
1249
+ {
1250
+ kind: "directive",
1251
+ type: i3$1.MatDatepickerInput,
1252
+ selector: "input[matDatepicker]",
1253
+ inputs: [
1254
+ "matDatepicker",
1255
+ "min",
1256
+ "max",
1257
+ "matDatepickerFilter"
1258
+ ],
1259
+ exportAs: ["matDatepickerInput"]
1260
+ },
1261
+ {
1262
+ kind: "component",
1263
+ type: i3$1.MatDatepickerToggle,
1264
+ selector: "mat-datepicker-toggle",
1265
+ inputs: [
1266
+ "for",
1267
+ "tabIndex",
1268
+ "aria-label",
1269
+ "disabled",
1270
+ "disableRipple"
1271
+ ],
1272
+ exportAs: ["matDatepickerToggle"]
1273
+ }
1274
+ ],
1275
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1276
+ });
1277
+ };
1278
+ i0.ɵɵngDeclareClassMetadata({
1279
+ minVersion: "12.0.0",
1280
+ version: "22.2.0",
1281
+ ngImport: i0,
1282
+ type: BusinessDateField,
1283
+ decorators: [{
1284
+ type: Component,
1285
+ args: [{
1286
+ selector: "app-business-date-field",
1287
+ standalone: true,
1288
+ imports: [
1289
+ MatFormFieldModule,
1290
+ MatInputModule,
1291
+ MatDatepickerModule
1292
+ ],
1293
+ providers: [provideLocaleDateAdapter()],
1294
+ changeDetection: ChangeDetectionStrategy.OnPush,
1295
+ template: "<mat-form-field class=\"business-date-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input\r\n matInput\r\n [matDatepicker]=\"datepicker\"\r\n [value]=\"date()\"\r\n [min]=\"minDate()\"\r\n [max]=\"maxDate()\"\r\n [required]=\"state().required()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (dateChange)=\"onDateChange($event.value)\"\r\n />\r\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\r\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of state().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
1296
+ styles: [":host{display:block}.business-date-field{width:100%}\n"]
1297
+ }]
1298
+ }],
1299
+ ctorParameters: () => [],
1300
+ propDecorators: {
1301
+ fieldDef: [{
1302
+ type: i0.Input,
1303
+ args: [{
1304
+ isSignal: true,
1305
+ alias: "fieldDef",
1306
+ required: true
1307
+ }]
1308
+ }],
1309
+ field: [{
1310
+ type: i0.Input,
1311
+ args: [{
1312
+ isSignal: true,
1313
+ alias: "field",
1314
+ required: true
1315
+ }]
1316
+ }],
1317
+ inputs: [{
1318
+ type: i0.ViewChildren,
1319
+ args: [i0.forwardRef(() => MatInput), { isSignal: true }]
1320
+ }]
1321
+ }
1322
+ });
1323
+ function toDate$1(value) {
1324
+ const plainDate = parsePlainDate(value);
1325
+ return plainDate ? new Date(plainDate.year, plainDate.month - 1, plainDate.day) : null;
1326
+ }
1327
+ var BusinessTimeField = class BusinessTimeField {
1328
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
1329
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
1330
+ dateAdapter = inject(DateAdapter);
1331
+ state = computed(() => this.field()(), ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
1332
+ time = computed(() => toDate(this.state().value()), ...ngDevMode ? [{ debugName: "time" }] : /* istanbul ignore next */ []);
1333
+ minTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.min), ...ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []);
1334
+ maxTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.max), ...ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []);
1335
+ inputs = viewChildren(MatInput, ...ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []);
1336
+ constructor() {
1337
+ syncMatInputErrorState(this.inputs, this.state);
1338
+ effect(() => this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || "en-GB"));
1339
+ }
1340
+ onTimeChange(time) {
1341
+ if (!time || isNaN(time.getTime())) {
1342
+ this.state().value.set(null);
1343
+ return;
1344
+ }
1345
+ this.state().value.set(Temporal.PlainTime.from({
1346
+ hour: time.getHours(),
1347
+ minute: time.getMinutes()
1348
+ }).toString({ smallestUnit: "minute" }));
1349
+ }
1350
+ static ɵfac = i0.ɵɵngDeclareFactory({
1351
+ minVersion: "12.0.0",
1352
+ version: "22.2.0",
1353
+ ngImport: i0,
1354
+ type: BusinessTimeField,
1355
+ deps: [],
1356
+ target: i0.ɵɵFactoryTarget.Component
1357
+ });
1358
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1359
+ minVersion: "17.0.0",
1360
+ version: "22.2.0",
1361
+ type: BusinessTimeField,
1362
+ isStandalone: true,
1363
+ selector: "app-business-time-field",
1364
+ inputs: {
1365
+ fieldDef: {
1366
+ classPropertyName: "fieldDef",
1367
+ publicName: "fieldDef",
1368
+ isSignal: true,
1369
+ isRequired: true,
1370
+ transformFunction: null
1371
+ },
1372
+ field: {
1373
+ classPropertyName: "field",
1374
+ publicName: "field",
1375
+ isSignal: true,
1376
+ isRequired: true,
1377
+ transformFunction: null
1378
+ }
1379
+ },
1380
+ providers: [provideLocaleDateAdapter()],
1381
+ viewQueries: [{
1382
+ propertyName: "inputs",
1383
+ predicate: MatInput,
1384
+ descendants: true,
1385
+ isSignal: true
1386
+ }],
1387
+ ngImport: i0,
1388
+ template: "<mat-form-field class=\"business-time-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input\r\n matInput\r\n [matTimepicker]=\"timepicker\"\r\n [matTimepickerMin]=\"minTime()\"\r\n [matTimepickerMax]=\"maxTime()\"\r\n [value]=\"time()\"\r\n [required]=\"state().required()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (valueChange)=\"onTimeChange($event)\"\r\n />\r\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\r\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of state().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
1389
+ styles: [":host{display:block}.business-time-field{width:100%}\n"],
1390
+ dependencies: [
1391
+ {
1392
+ kind: "ngmodule",
1393
+ type: MatFormFieldModule
1394
+ },
1395
+ {
1396
+ kind: "component",
1397
+ type: i1.MatFormField,
1398
+ selector: "mat-form-field",
1399
+ inputs: [
1400
+ "hideRequiredMarker",
1401
+ "color",
1402
+ "floatLabel",
1403
+ "appearance",
1404
+ "subscriptSizing",
1405
+ "hintLabel"
1406
+ ],
1407
+ exportAs: ["matFormField"]
1408
+ },
1409
+ {
1410
+ kind: "directive",
1411
+ type: i1.MatLabel,
1412
+ selector: "mat-label"
1413
+ },
1414
+ {
1415
+ kind: "directive",
1416
+ type: i1.MatHint,
1417
+ selector: "mat-hint",
1418
+ inputs: ["align", "id"]
1419
+ },
1420
+ {
1421
+ kind: "directive",
1422
+ type: i1.MatError,
1423
+ selector: "mat-error, [matError]",
1424
+ inputs: ["id"]
1425
+ },
1426
+ {
1427
+ kind: "directive",
1428
+ type: i1.MatSuffix,
1429
+ selector: "[matSuffix], [matIconSuffix], [matTextSuffix]",
1430
+ inputs: ["matTextSuffix"]
1431
+ },
1432
+ {
1433
+ kind: "ngmodule",
1434
+ type: MatInputModule
1435
+ },
1436
+ {
1437
+ kind: "directive",
1438
+ type: i2.MatInput,
1439
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
1440
+ inputs: [
1441
+ "disabled",
1442
+ "id",
1443
+ "placeholder",
1444
+ "name",
1445
+ "required",
1446
+ "type",
1447
+ "errorStateMatcher",
1448
+ "aria-describedby",
1449
+ "value",
1450
+ "readonly",
1451
+ "disabledInteractive"
1452
+ ],
1453
+ exportAs: ["matInput"]
1454
+ },
1455
+ {
1456
+ kind: "ngmodule",
1457
+ type: MatTimepickerModule
1458
+ },
1459
+ {
1460
+ kind: "component",
1461
+ type: i3.MatTimepicker,
1462
+ selector: "mat-timepicker",
1463
+ inputs: [
1464
+ "interval",
1465
+ "options",
1466
+ "disableRipple",
1467
+ "aria-label",
1468
+ "aria-labelledby",
1469
+ "panelClass"
1470
+ ],
1471
+ outputs: [
1472
+ "selected",
1473
+ "opened",
1474
+ "closed"
1475
+ ],
1476
+ exportAs: ["matTimepicker"]
1477
+ },
1478
+ {
1479
+ kind: "directive",
1480
+ type: i3.MatTimepickerInput,
1481
+ selector: "input[matTimepicker]",
1482
+ inputs: [
1483
+ "value",
1484
+ "matTimepicker",
1485
+ "matTimepickerMin",
1486
+ "matTimepickerMax",
1487
+ "matTimepickerOpenOnClick",
1488
+ "disabled"
1489
+ ],
1490
+ outputs: ["valueChange"],
1491
+ exportAs: ["matTimepickerInput"]
1492
+ },
1493
+ {
1494
+ kind: "component",
1495
+ type: i3.MatTimepickerToggle,
1496
+ selector: "mat-timepicker-toggle",
1497
+ inputs: [
1498
+ "for",
1499
+ "aria-label",
1500
+ "aria-labelledby",
1501
+ "disabled",
1502
+ "tabIndex",
1503
+ "disableRipple"
1504
+ ],
1505
+ exportAs: ["matTimepickerToggle"]
1506
+ }
1507
+ ],
1508
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1509
+ });
1510
+ };
1511
+ i0.ɵɵngDeclareClassMetadata({
1512
+ minVersion: "12.0.0",
1513
+ version: "22.2.0",
1514
+ ngImport: i0,
1515
+ type: BusinessTimeField,
1516
+ decorators: [{
1517
+ type: Component,
1518
+ args: [{
1519
+ selector: "app-business-time-field",
1520
+ standalone: true,
1521
+ imports: [
1522
+ MatFormFieldModule,
1523
+ MatInputModule,
1524
+ MatTimepickerModule
1525
+ ],
1526
+ providers: [provideLocaleDateAdapter()],
1527
+ changeDetection: ChangeDetectionStrategy.OnPush,
1528
+ template: "<mat-form-field class=\"business-time-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <input\r\n matInput\r\n [matTimepicker]=\"timepicker\"\r\n [matTimepickerMin]=\"minTime()\"\r\n [matTimepickerMax]=\"maxTime()\"\r\n [value]=\"time()\"\r\n [required]=\"state().required()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (valueChange)=\"onTimeChange($event)\"\r\n />\r\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\r\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\r\n\r\n @if (fieldDef().hint) {\r\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\r\n }\r\n\r\n @for (error of state().errors(); track error.kind) {\r\n <mat-error>{{ error.message }}</mat-error>\r\n }\r\n</mat-form-field>\r\n",
1529
+ styles: [":host{display:block}.business-time-field{width:100%}\n"]
1530
+ }]
1531
+ }],
1532
+ ctorParameters: () => [],
1533
+ propDecorators: {
1534
+ fieldDef: [{
1535
+ type: i0.Input,
1536
+ args: [{
1537
+ isSignal: true,
1538
+ alias: "fieldDef",
1539
+ required: true
1540
+ }]
1541
+ }],
1542
+ field: [{
1543
+ type: i0.Input,
1544
+ args: [{
1545
+ isSignal: true,
1546
+ alias: "field",
1547
+ required: true
1548
+ }]
1549
+ }],
1550
+ inputs: [{
1551
+ type: i0.ViewChildren,
1552
+ args: [i0.forwardRef(() => MatInput), { isSignal: true }]
1553
+ }]
1554
+ }
1555
+ });
1556
+ function toDate(value) {
1557
+ const plainTime = parsePlainTime(value);
1558
+ return plainTime ? new Date(2e3, 0, 1, plainTime.hour, plainTime.minute) : null;
1559
+ }
1560
+ var ZonedDateTimeService = class ZonedDateTimeService {
1561
+ toDate(instant, timeZone) {
1562
+ const zoned = this.toZoned(instant, timeZone);
1563
+ if (!zoned) return null;
1564
+ return new Date(zoned.year, zoned.month - 1, zoned.day, zoned.hour, zoned.minute);
1565
+ }
1566
+ toInstant(date, time, timeZone, disambiguation = "earlier") {
1567
+ try {
1568
+ const plainDateTime = Temporal.PlainDateTime.from({
1569
+ year: date.getFullYear(),
1570
+ month: date.getMonth() + 1,
1571
+ day: date.getDate(),
1572
+ hour: time.getHours(),
1573
+ minute: time.getMinutes()
1574
+ });
1575
+ const earlier = plainDateTime.toZonedDateTime(timeZone, { disambiguation: "earlier" });
1576
+ const later = plainDateTime.toZonedDateTime(timeZone, { disambiguation: "later" });
1577
+ if (earlier.equals(later)) return {
1578
+ instant: earlier.toInstant().toString(),
1579
+ notice: null
1580
+ };
1581
+ if (!earlier.toPlainDateTime().equals(plainDateTime)) return {
1582
+ instant: later.toInstant().toString(),
1583
+ notice: `${formatWallClock(plainDateTime)} does not exist in ${timeZone} (clocks go forward). Using ${formatWallClock(later.toPlainDateTime())} (UTC${later.offset}) instead.`
1584
+ };
1585
+ const chosen = disambiguation === "later" ? later : earlier;
1586
+ return {
1587
+ instant: chosen.toInstant().toString(),
1588
+ notice: `${formatWallClock(plainDateTime)} happens twice in ${timeZone} (clocks go back). Using the ${chosen === earlier ? "first" : "second"} occurrence (UTC${chosen.offset}).`
1589
+ };
1590
+ } catch {
1591
+ return null;
1592
+ }
1593
+ }
1594
+ offset(instant, timeZone) {
1595
+ return this.toZoned(instant, timeZone)?.offset ?? null;
1596
+ }
1597
+ toZoned(instant, timeZone) {
1598
+ try {
1599
+ return parseInstant(instant)?.toZonedDateTimeISO(timeZone) ?? null;
1600
+ } catch {
1601
+ return null;
1602
+ }
1603
+ }
1604
+ static ɵfac = i0.ɵɵngDeclareFactory({
1605
+ minVersion: "12.0.0",
1606
+ version: "22.2.0",
1607
+ ngImport: i0,
1608
+ type: ZonedDateTimeService,
1609
+ deps: [],
1610
+ target: i0.ɵɵFactoryTarget.Injectable
1611
+ });
1612
+ static ɵprov = i0.ɵɵngDeclareInjectable({
1613
+ minVersion: "12.0.0",
1614
+ version: "22.2.0",
1615
+ ngImport: i0,
1616
+ type: ZonedDateTimeService,
1617
+ providedIn: "root"
1618
+ });
1619
+ };
1620
+ i0.ɵɵngDeclareClassMetadata({
1621
+ minVersion: "12.0.0",
1622
+ version: "22.2.0",
1623
+ ngImport: i0,
1624
+ type: ZonedDateTimeService,
1625
+ decorators: [{
1626
+ type: Injectable,
1627
+ args: [{ providedIn: "root" }]
1628
+ }]
1629
+ });
1630
+ function formatWallClock(plainDateTime) {
1631
+ return plainDateTime.toString({ smallestUnit: "minute" }).replace("T", " ");
1632
+ }
1633
+ var InstantDateTimeField = class InstantDateTimeField {
1634
+ fieldDef = input.required(...ngDevMode ? [{ debugName: "fieldDef" }] : /* istanbul ignore next */ []);
1635
+ field = input.required(...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
1636
+ zonedDateTime = inject(ZonedDateTimeService);
1637
+ dateAdapter = inject(DateAdapter);
1638
+ notice = signal(null, ...ngDevMode ? [{ debugName: "notice" }] : /* istanbul ignore next */ []);
1639
+ state = computed(() => this.field()(), ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
1640
+ config = computed(() => this.fieldDef().dateTimeConfig, ...ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []);
1641
+ timeZone = computed(() => this.config()?.timeZone || Temporal.Now.timeZoneId(), ...ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []);
1642
+ offset = computed(() => this.zonedDateTime.offset(this.state().value(), this.timeZone()), ...ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []);
1643
+ minDate = computed(() => this.zonedDateTime.toDate(this.config()?.min, this.timeZone()), ...ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []);
1644
+ maxDate = computed(() => this.zonedDateTime.toDate(this.config()?.max, this.timeZone()), ...ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []);
1645
+ wallClock = computed(() => this.zonedDateTime.toDate(this.state().value(), this.timeZone()), {
1646
+ ...ngDevMode ? { debugName: "wallClock" } : /* istanbul ignore next */ {},
1647
+ equal: (a, b) => a?.getTime() === b?.getTime()
1648
+ });
1649
+ date = linkedSignal(() => this.wallClock(), ...ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []);
1650
+ time = linkedSignal(() => this.wallClock(), ...ngDevMode ? [{ debugName: "time" }] : /* istanbul ignore next */ []);
1651
+ inputs = viewChildren(MatInput, ...ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []);
1652
+ constructor() {
1653
+ syncMatInputErrorState(this.inputs, this.state);
1654
+ effect(() => this.dateAdapter.setLocale(this.config()?.locale || "en-GB"));
1655
+ }
1656
+ onDateChange(date) {
1657
+ if (sameParts(date, this.date(), (d) => [
1658
+ d.getFullYear(),
1659
+ d.getMonth(),
1660
+ d.getDate()
1661
+ ])) return;
1662
+ this.date.set(date);
1663
+ this.commit();
1664
+ }
1665
+ onTimeChange(time) {
1666
+ if (sameParts(time, this.time(), (t) => [t.getHours(), t.getMinutes()])) return;
1667
+ this.time.set(time);
1668
+ this.commit();
1669
+ }
1670
+ commit() {
1671
+ this.notice.set(null);
1672
+ const date = this.date();
1673
+ const time = this.time();
1674
+ const value = this.state().value;
1675
+ if (!isValidDate(date) || !isValidDate(time)) {
1676
+ if (value() !== null) value.set(null);
1677
+ return;
1678
+ }
1679
+ const result = this.zonedDateTime.toInstant(date, time, this.timeZone(), this.config()?.disambiguation);
1680
+ value.set(result?.instant ?? null);
1681
+ this.notice.set(result?.notice ?? null);
1682
+ }
1683
+ static ɵfac = i0.ɵɵngDeclareFactory({
1684
+ minVersion: "12.0.0",
1685
+ version: "22.2.0",
1686
+ ngImport: i0,
1687
+ type: InstantDateTimeField,
1688
+ deps: [],
1689
+ target: i0.ɵɵFactoryTarget.Component
1690
+ });
1691
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1692
+ minVersion: "17.0.0",
1693
+ version: "22.2.0",
1694
+ type: InstantDateTimeField,
1695
+ isStandalone: true,
1696
+ selector: "app-instant-date-time-field",
1697
+ inputs: {
1698
+ fieldDef: {
1699
+ classPropertyName: "fieldDef",
1700
+ publicName: "fieldDef",
1701
+ isSignal: true,
1702
+ isRequired: true,
1703
+ transformFunction: null
1704
+ },
1705
+ field: {
1706
+ classPropertyName: "field",
1707
+ publicName: "field",
1708
+ isSignal: true,
1709
+ isRequired: true,
1710
+ transformFunction: null
1711
+ }
1712
+ },
1713
+ providers: [provideLocaleDateAdapter()],
1714
+ viewQueries: [{
1715
+ propertyName: "inputs",
1716
+ predicate: MatInput,
1717
+ descendants: true,
1718
+ isSignal: true
1719
+ }],
1720
+ ngImport: i0,
1721
+ template: "<div class=\"instant-date-time-field-label\">\r\n {{ fieldDef().label }}@if (state().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</div>\r\n\r\n<div class=\"instant-date-time-field-row\">\r\n <mat-form-field class=\"instant-date-time-field-date\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>Date</mat-label>\r\n <input\r\n matInput\r\n [matDatepicker]=\"datepicker\"\r\n [value]=\"date()\"\r\n [min]=\"minDate()\"\r\n [max]=\"maxDate()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (dateChange)=\"onDateChange($event.value)\"\r\n />\r\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\r\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\r\n </mat-form-field>\r\n\r\n <mat-form-field class=\"instant-date-time-field-time\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>Time</mat-label>\r\n <input\r\n matInput\r\n [matTimepicker]=\"timepicker\"\r\n [value]=\"time()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (valueChange)=\"onTimeChange($event)\"\r\n />\r\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\r\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\r\n </mat-form-field>\r\n</div>\r\n\r\n<div class=\"instant-date-time-field-zone\">\r\n {{ timeZone() }}@if (offset()) { (UTC{{ offset() }})}\r\n @if (state().value()) {\r\n · stored as {{ state().value() }}\r\n }\r\n</div>\r\n\r\n@if (notice()) {\r\n <div class=\"instant-date-time-field-notice\">{{ notice() }}</div>\r\n}\r\n\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
1722
+ styles: [":host{display:block}.instant-date-time-field-label{margin-bottom:6px;font-size:14px;color:#0009}.instant-date-time-field-row{display:flex;gap:8px;width:100%}@media(max-width:400px){.instant-date-time-field-row{flex-direction:column}}.instant-date-time-field-date{flex:3;min-width:0}.instant-date-time-field-time{flex:2;min-width:0}.instant-date-time-field-zone{font-size:12px;color:#0009;margin-top:4px;line-height:1.2}.instant-date-time-field-notice{font-size:12px;color:#8a5a00;margin-top:4px}\n"],
1723
+ dependencies: [
1724
+ {
1725
+ kind: "ngmodule",
1726
+ type: MatFormFieldModule
1727
+ },
1728
+ {
1729
+ kind: "component",
1730
+ type: i1.MatFormField,
1731
+ selector: "mat-form-field",
1732
+ inputs: [
1733
+ "hideRequiredMarker",
1734
+ "color",
1735
+ "floatLabel",
1736
+ "appearance",
1737
+ "subscriptSizing",
1738
+ "hintLabel"
1739
+ ],
1740
+ exportAs: ["matFormField"]
1741
+ },
1742
+ {
1743
+ kind: "directive",
1744
+ type: i1.MatLabel,
1745
+ selector: "mat-label"
1746
+ },
1747
+ {
1748
+ kind: "directive",
1749
+ type: i1.MatSuffix,
1750
+ selector: "[matSuffix], [matIconSuffix], [matTextSuffix]",
1751
+ inputs: ["matTextSuffix"]
1752
+ },
1753
+ {
1754
+ kind: "ngmodule",
1755
+ type: MatInputModule
1756
+ },
1757
+ {
1758
+ kind: "directive",
1759
+ type: i2.MatInput,
1760
+ selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",
1761
+ inputs: [
1762
+ "disabled",
1763
+ "id",
1764
+ "placeholder",
1765
+ "name",
1766
+ "required",
1767
+ "type",
1768
+ "errorStateMatcher",
1769
+ "aria-describedby",
1770
+ "value",
1771
+ "readonly",
1772
+ "disabledInteractive"
1773
+ ],
1774
+ exportAs: ["matInput"]
1775
+ },
1776
+ {
1777
+ kind: "ngmodule",
1778
+ type: MatDatepickerModule
1779
+ },
1780
+ {
1781
+ kind: "component",
1782
+ type: i3$1.MatDatepicker,
1783
+ selector: "mat-datepicker",
1784
+ exportAs: ["matDatepicker"]
1785
+ },
1786
+ {
1787
+ kind: "directive",
1788
+ type: i3$1.MatDatepickerInput,
1789
+ selector: "input[matDatepicker]",
1790
+ inputs: [
1791
+ "matDatepicker",
1792
+ "min",
1793
+ "max",
1794
+ "matDatepickerFilter"
1795
+ ],
1796
+ exportAs: ["matDatepickerInput"]
1797
+ },
1798
+ {
1799
+ kind: "component",
1800
+ type: i3$1.MatDatepickerToggle,
1801
+ selector: "mat-datepicker-toggle",
1802
+ inputs: [
1803
+ "for",
1804
+ "tabIndex",
1805
+ "aria-label",
1806
+ "disabled",
1807
+ "disableRipple"
1808
+ ],
1809
+ exportAs: ["matDatepickerToggle"]
1810
+ },
1811
+ {
1812
+ kind: "ngmodule",
1813
+ type: MatTimepickerModule
1814
+ },
1815
+ {
1816
+ kind: "component",
1817
+ type: i3.MatTimepicker,
1818
+ selector: "mat-timepicker",
1819
+ inputs: [
1820
+ "interval",
1821
+ "options",
1822
+ "disableRipple",
1823
+ "aria-label",
1824
+ "aria-labelledby",
1825
+ "panelClass"
1826
+ ],
1827
+ outputs: [
1828
+ "selected",
1829
+ "opened",
1830
+ "closed"
1831
+ ],
1832
+ exportAs: ["matTimepicker"]
1833
+ },
1834
+ {
1835
+ kind: "directive",
1836
+ type: i3.MatTimepickerInput,
1837
+ selector: "input[matTimepicker]",
1838
+ inputs: [
1839
+ "value",
1840
+ "matTimepicker",
1841
+ "matTimepickerMin",
1842
+ "matTimepickerMax",
1843
+ "matTimepickerOpenOnClick",
1844
+ "disabled"
1845
+ ],
1846
+ outputs: ["valueChange"],
1847
+ exportAs: ["matTimepickerInput"]
1848
+ },
1849
+ {
1850
+ kind: "component",
1851
+ type: i3.MatTimepickerToggle,
1852
+ selector: "mat-timepicker-toggle",
1853
+ inputs: [
1854
+ "for",
1855
+ "aria-label",
1856
+ "aria-labelledby",
1857
+ "disabled",
1858
+ "tabIndex",
1859
+ "disableRipple"
1860
+ ],
1861
+ exportAs: ["matTimepickerToggle"]
1862
+ },
1863
+ {
1864
+ kind: "component",
1865
+ type: FieldSubscript,
1866
+ selector: "app-field-subscript",
1867
+ inputs: ["field", "hint"]
1868
+ }
1869
+ ],
1870
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1871
+ });
1872
+ };
1873
+ i0.ɵɵngDeclareClassMetadata({
1874
+ minVersion: "12.0.0",
1875
+ version: "22.2.0",
1876
+ ngImport: i0,
1877
+ type: InstantDateTimeField,
1878
+ decorators: [{
1879
+ type: Component,
1880
+ args: [{
1881
+ selector: "app-instant-date-time-field",
1882
+ standalone: true,
1883
+ imports: [
1884
+ MatFormFieldModule,
1885
+ MatInputModule,
1886
+ MatDatepickerModule,
1887
+ MatTimepickerModule,
1888
+ FieldSubscript
1889
+ ],
1890
+ providers: [provideLocaleDateAdapter()],
1891
+ changeDetection: ChangeDetectionStrategy.OnPush,
1892
+ template: "<div class=\"instant-date-time-field-label\">\r\n {{ fieldDef().label }}@if (state().required()) {<span aria-hidden=\"true\"> *</span>}\r\n</div>\r\n\r\n<div class=\"instant-date-time-field-row\">\r\n <mat-form-field class=\"instant-date-time-field-date\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>Date</mat-label>\r\n <input\r\n matInput\r\n [matDatepicker]=\"datepicker\"\r\n [value]=\"date()\"\r\n [min]=\"minDate()\"\r\n [max]=\"maxDate()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (dateChange)=\"onDateChange($event.value)\"\r\n />\r\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\r\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\r\n </mat-form-field>\r\n\r\n <mat-form-field class=\"instant-date-time-field-time\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>Time</mat-label>\r\n <input\r\n matInput\r\n [matTimepicker]=\"timepicker\"\r\n [value]=\"time()\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (valueChange)=\"onTimeChange($event)\"\r\n />\r\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\r\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\r\n </mat-form-field>\r\n</div>\r\n\r\n<div class=\"instant-date-time-field-zone\">\r\n {{ timeZone() }}@if (offset()) { (UTC{{ offset() }})}\r\n @if (state().value()) {\r\n · stored as {{ state().value() }}\r\n }\r\n</div>\r\n\r\n@if (notice()) {\r\n <div class=\"instant-date-time-field-notice\">{{ notice() }}</div>\r\n}\r\n\r\n<app-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n",
1893
+ styles: [":host{display:block}.instant-date-time-field-label{margin-bottom:6px;font-size:14px;color:#0009}.instant-date-time-field-row{display:flex;gap:8px;width:100%}@media(max-width:400px){.instant-date-time-field-row{flex-direction:column}}.instant-date-time-field-date{flex:3;min-width:0}.instant-date-time-field-time{flex:2;min-width:0}.instant-date-time-field-zone{font-size:12px;color:#0009;margin-top:4px;line-height:1.2}.instant-date-time-field-notice{font-size:12px;color:#8a5a00;margin-top:4px}\n"]
1894
+ }]
1895
+ }],
1896
+ ctorParameters: () => [],
1897
+ propDecorators: {
1898
+ fieldDef: [{
1899
+ type: i0.Input,
1900
+ args: [{
1901
+ isSignal: true,
1902
+ alias: "fieldDef",
1903
+ required: true
1904
+ }]
1905
+ }],
1906
+ field: [{
1907
+ type: i0.Input,
1908
+ args: [{
1909
+ isSignal: true,
1910
+ alias: "field",
1911
+ required: true
1912
+ }]
1913
+ }],
1914
+ inputs: [{
1915
+ type: i0.ViewChildren,
1916
+ args: [i0.forwardRef(() => MatInput), { isSignal: true }]
1917
+ }]
1918
+ }
1919
+ });
1920
+ function isValidDate(value) {
1921
+ return value instanceof Date && !isNaN(value.getTime());
1922
+ }
1923
+ function sameParts(a, b, parts) {
1924
+ if (!isValidDate(a) || !isValidDate(b)) return a === b;
1925
+ const bParts = parts(b);
1926
+ return parts(a).every((part, index) => part === bParts[index]);
1927
+ }
1928
+ var DynamicForm = class DynamicForm {
1929
+ metaInfo = input.required(...ngDevMode ? [{ debugName: "metaInfo" }] : /* istanbul ignore next */ []);
1930
+ dynamicForm = input.required(...ngDevMode ? [{ debugName: "dynamicForm" }] : /* istanbul ignore next */ []);
1931
+ onFormSubmit = output();
1932
+ onFormClear = output();
1933
+ handleSubmit() {
1934
+ if (this.dynamicForm()().valid()) this.onFormSubmit.emit();
1935
+ }
1936
+ clearForm() {
1937
+ this.onFormClear.emit();
1938
+ }
1939
+ static ɵfac = i0.ɵɵngDeclareFactory({
1940
+ minVersion: "12.0.0",
1941
+ version: "22.2.0",
1942
+ ngImport: i0,
1943
+ type: DynamicForm,
1944
+ deps: [],
1945
+ target: i0.ɵɵFactoryTarget.Component
1946
+ });
1947
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1948
+ minVersion: "17.0.0",
1949
+ version: "22.2.0",
1950
+ type: DynamicForm,
1951
+ isStandalone: true,
1952
+ selector: "app-dynamic-form",
1953
+ inputs: {
1954
+ metaInfo: {
1955
+ classPropertyName: "metaInfo",
1956
+ publicName: "metaInfo",
1957
+ isSignal: true,
1958
+ isRequired: true,
1959
+ transformFunction: null
1960
+ },
1961
+ dynamicForm: {
1962
+ classPropertyName: "dynamicForm",
1963
+ publicName: "dynamicForm",
1964
+ isSignal: true,
1965
+ isRequired: true,
1966
+ transformFunction: null
1967
+ }
1968
+ },
1969
+ outputs: {
1970
+ onFormSubmit: "onFormSubmit",
1971
+ onFormClear: "onFormClear"
1972
+ },
1973
+ ngImport: i0,
1974
+ template: "<div class=\"dynamic-form-container\">\r\n @for (fieldDef of metaInfo(); track fieldDef.name) {\r\n @let field = $any(dynamicForm())[fieldDef.name];\r\n\r\n @if (!fieldDef.hidden) {\r\n <div class=\"dynamic-form-field\" [style.--field-max-width]=\"fieldDef.maxWidth\">\r\n @switch (fieldDef.type) {\r\n @case ('text') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('email') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('password') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('search') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('number') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('textarea') {\r\n <app-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('code') {\r\n <app-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('checkbox') {\r\n <app-checkbox-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('radio') {\r\n <app-radio-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('select') {\r\n <app-select-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('range') {\r\n <app-slider-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-date') {\r\n <app-business-date-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-time') {\r\n <app-business-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('instant-date-time') {\r\n <app-instant-date-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n <div class=\"dynamic-form-actions-container\">\r\n <button mat-flat-button\r\n [disabled]=\"dynamicForm()().invalid()\"\r\n (click)=\"handleSubmit()\">Save\r\n </button>\r\n <button matButton=\"outlined\" (click)=\"clearForm()\">Clear</button>\r\n </div>\r\n</div>\r\n",
1975
+ styles: [".dynamic-form-container{padding:2rem 3rem;display:flex;flex-direction:column;align-items:center;width:100%;gap:16px;box-sizing:border-box}.dynamic-form-field{display:flex;flex-direction:column;max-width:var(--field-max-width, 400px);width:100%;margin:0 auto;font-family:Roboto,Helvetica Neue,sans-serif}.dynamic-form-actions-container{display:flex;gap:20px}\n"],
1976
+ dependencies: [
1977
+ {
1978
+ kind: "component",
1979
+ type: MatButton,
1980
+ selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ",
1981
+ inputs: ["matButton"],
1982
+ exportAs: ["matButton", "matAnchor"]
1983
+ },
1984
+ {
1985
+ kind: "component",
1986
+ type: TextField,
1987
+ selector: "app-text-field",
1988
+ inputs: ["fieldDef", "field"]
1989
+ },
1990
+ {
1991
+ kind: "component",
1992
+ type: TextareaField,
1993
+ selector: "app-textarea-field",
1994
+ inputs: ["fieldDef", "field"]
1995
+ },
1996
+ {
1997
+ kind: "component",
1998
+ type: CheckboxField,
1999
+ selector: "app-checkbox-field",
2000
+ inputs: ["fieldDef", "field"]
2001
+ },
2002
+ {
2003
+ kind: "component",
2004
+ type: RadioField,
2005
+ selector: "app-radio-field",
2006
+ inputs: ["fieldDef", "field"]
2007
+ },
2008
+ {
2009
+ kind: "component",
2010
+ type: SelectField,
2011
+ selector: "app-select-field",
2012
+ inputs: ["fieldDef", "field"]
2013
+ },
2014
+ {
2015
+ kind: "component",
2016
+ type: SliderField,
2017
+ selector: "app-slider-field",
2018
+ inputs: ["fieldDef", "field"]
2019
+ },
2020
+ {
2021
+ kind: "component",
2022
+ type: BusinessDateField,
2023
+ selector: "app-business-date-field",
2024
+ inputs: ["fieldDef", "field"]
2025
+ },
2026
+ {
2027
+ kind: "component",
2028
+ type: BusinessTimeField,
2029
+ selector: "app-business-time-field",
2030
+ inputs: ["fieldDef", "field"]
2031
+ },
2032
+ {
2033
+ kind: "component",
2034
+ type: InstantDateTimeField,
2035
+ selector: "app-instant-date-time-field",
2036
+ inputs: ["fieldDef", "field"]
2037
+ }
2038
+ ],
2039
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2040
+ });
2041
+ };
2042
+ i0.ɵɵngDeclareClassMetadata({
2043
+ minVersion: "12.0.0",
2044
+ version: "22.2.0",
2045
+ ngImport: i0,
2046
+ type: DynamicForm,
2047
+ decorators: [{
2048
+ type: Component,
2049
+ args: [{
2050
+ selector: "app-dynamic-form",
2051
+ standalone: true,
2052
+ imports: [
2053
+ MatButton,
2054
+ TextField,
2055
+ TextareaField,
2056
+ CheckboxField,
2057
+ RadioField,
2058
+ SelectField,
2059
+ SliderField,
2060
+ BusinessDateField,
2061
+ BusinessTimeField,
2062
+ InstantDateTimeField
2063
+ ],
2064
+ changeDetection: ChangeDetectionStrategy.OnPush,
2065
+ template: "<div class=\"dynamic-form-container\">\r\n @for (fieldDef of metaInfo(); track fieldDef.name) {\r\n @let field = $any(dynamicForm())[fieldDef.name];\r\n\r\n @if (!fieldDef.hidden) {\r\n <div class=\"dynamic-form-field\" [style.--field-max-width]=\"fieldDef.maxWidth\">\r\n @switch (fieldDef.type) {\r\n @case ('text') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('email') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('password') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('search') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('number') {\r\n <app-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('textarea') {\r\n <app-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('code') {\r\n <app-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('checkbox') {\r\n <app-checkbox-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('radio') {\r\n <app-radio-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('select') {\r\n <app-select-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('range') {\r\n <app-slider-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-date') {\r\n <app-business-date-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-time') {\r\n <app-business-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('instant-date-time') {\r\n <app-instant-date-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n <div class=\"dynamic-form-actions-container\">\r\n <button mat-flat-button\r\n [disabled]=\"dynamicForm()().invalid()\"\r\n (click)=\"handleSubmit()\">Save\r\n </button>\r\n <button matButton=\"outlined\" (click)=\"clearForm()\">Clear</button>\r\n </div>\r\n</div>\r\n",
2066
+ styles: [".dynamic-form-container{padding:2rem 3rem;display:flex;flex-direction:column;align-items:center;width:100%;gap:16px;box-sizing:border-box}.dynamic-form-field{display:flex;flex-direction:column;max-width:var(--field-max-width, 400px);width:100%;margin:0 auto;font-family:Roboto,Helvetica Neue,sans-serif}.dynamic-form-actions-container{display:flex;gap:20px}\n"]
2067
+ }]
2068
+ }],
2069
+ propDecorators: {
2070
+ metaInfo: [{
2071
+ type: i0.Input,
2072
+ args: [{
2073
+ isSignal: true,
2074
+ alias: "metaInfo",
2075
+ required: true
2076
+ }]
2077
+ }],
2078
+ dynamicForm: [{
2079
+ type: i0.Input,
2080
+ args: [{
2081
+ isSignal: true,
2082
+ alias: "dynamicForm",
2083
+ required: true
2084
+ }]
2085
+ }],
2086
+ onFormSubmit: [{
2087
+ type: i0.Output,
2088
+ args: ["onFormSubmit"]
2089
+ }],
2090
+ onFormClear: [{
2091
+ type: i0.Output,
2092
+ args: ["onFormClear"]
2093
+ }]
2094
+ }
2095
+ });
2096
+ function defineSchema(config) {
2097
+ return config;
2098
+ }
2099
+ function createEmptyEntity(schemaType, defaults) {
2100
+ return {
2101
+ id: "",
2102
+ schemaType,
2103
+ ...defaults
2104
+ };
2105
+ }
2106
+ function toSchema(meta) {
2107
+ return schema((path) => {
2108
+ for (const fieldDef of meta) {
2109
+ const fieldPath = path[fieldDef.name];
2110
+ if (!fieldPath) continue;
2111
+ if (fieldDef.disabled) disabled(fieldPath);
2112
+ if (fieldDef.required) required(fieldPath, { message: `${fieldDef.label} is required` });
2113
+ if (typeof fieldDef.minLength !== "undefined") minLength(fieldPath, fieldDef.minLength, { message: `${fieldDef.label} must be at least ${fieldDef.minLength} characters` });
2114
+ if (typeof fieldDef.maxLength !== "undefined") maxLength(fieldPath, fieldDef.maxLength, { message: `${fieldDef.label} cannot exceed ${fieldDef.maxLength} characters` });
2115
+ if (fieldDef.type === FormFieldType.EMAIL) email(fieldPath, { message: `${fieldDef.label} must be a valid email address` });
2116
+ if (typeof fieldDef.pattern !== "undefined") pattern(fieldPath, toRegExp(fieldDef.pattern), { message: fieldDef.patternMessage ?? `${fieldDef.label} is not in the expected format` });
2117
+ if (typeof fieldDef.min !== "undefined") min(fieldPath, fieldDef.min, { message: `${fieldDef.label} must be at least ${fieldDef.min}` });
2118
+ if (typeof fieldDef.max !== "undefined") max(fieldPath, fieldDef.max, { message: `${fieldDef.label} cannot exceed ${fieldDef.max}` });
2119
+ if (isDateTimeField(fieldDef.type)) validate(fieldPath, (ctx) => dateTimeError(ctx.value(), fieldDef));
2120
+ }
2121
+ });
2122
+ }
2123
+ function toRegExp(value) {
2124
+ return value instanceof RegExp ? value : new RegExp(`^(?:${value})$`);
2125
+ }
2126
+ var FormConfigBuilder = class {
2127
+ schemaType;
2128
+ fieldDefs = [];
2129
+ constructor(schemaType) {
2130
+ this.schemaType = schemaType;
2131
+ }
2132
+ text(name, label, options) {
2133
+ return this.add(FormFieldType.TEXT, name, label, options);
2134
+ }
2135
+ email(name, label, options) {
2136
+ return this.add(FormFieldType.EMAIL, name, label, options);
2137
+ }
2138
+ password(name, label, options) {
2139
+ return this.add(FormFieldType.PASSWORD, name, label, options);
2140
+ }
2141
+ search(name, label, options) {
2142
+ return this.add(FormFieldType.SEARCH, name, label, options);
2143
+ }
2144
+ number(name, label, options) {
2145
+ return this.add(FormFieldType.NUMBER, name, label, options);
2146
+ }
2147
+ textarea(name, label, options) {
2148
+ return this.add(FormFieldType.TEXTAREA, name, label, options);
2149
+ }
2150
+ code(name, label, options) {
2151
+ return this.add(FormFieldType.CODE, name, label, options);
2152
+ }
2153
+ checkbox(name, label, options) {
2154
+ return this.add(FormFieldType.CHECKBOX, name, label, options);
2155
+ }
2156
+ range(name, label, options) {
2157
+ return this.add(FormFieldType.RANGE, name, label, options);
2158
+ }
2159
+ radio(name, label, choices, options) {
2160
+ return this.add(FormFieldType.RADIO, name, label, {
2161
+ ...options,
2162
+ options: choices
2163
+ });
2164
+ }
2165
+ select(name, label, choices, options) {
2166
+ return this.add(FormFieldType.SELECT, name, label, {
2167
+ ...options,
2168
+ options: choices
2169
+ });
2170
+ }
2171
+ businessDate(name, label, options) {
2172
+ return this.add(FormFieldType.BUSINESS_DATE, name, label, options);
2173
+ }
2174
+ businessTime(name, label, options) {
2175
+ return this.add(FormFieldType.BUSINESS_TIME, name, label, options);
2176
+ }
2177
+ instantDateTime(name, label, options) {
2178
+ return this.add(FormFieldType.INSTANT_DATE_TIME, name, label, options);
2179
+ }
2180
+ hidden(name, options) {
2181
+ return this.add(FormFieldType.TEXT, name, name, {
2182
+ ...options,
2183
+ hidden: true
2184
+ });
2185
+ }
2186
+ fields() {
2187
+ return [...this.fieldDefs];
2188
+ }
2189
+ build(initialValue) {
2190
+ return {
2191
+ schemaType: this.schemaType,
2192
+ fields: this.fields(),
2193
+ initialValue: createEmptyEntity(this.schemaType, initialValue)
2194
+ };
2195
+ }
2196
+ add(type, name, label, options) {
2197
+ this.fieldDefs.push({
2198
+ ...options,
2199
+ name,
2200
+ type,
2201
+ label
2202
+ });
2203
+ return this;
2204
+ }
2205
+ };
2206
+ function formConfig(schemaType) {
2207
+ return new FormConfigBuilder(schemaType);
2208
+ }
2209
+ export { BusinessDateField, BusinessTimeField, CheckboxField, DynamicForm, FormConfigBuilder, FormFieldType, InstantDateTimeField, RadioField, SelectField, SliderField, TextField, TextareaField, ZonedDateTimeService, createEmptyEntity, defineSchema, formConfig, toSchema };
2210
+
2211
+ //# sourceMappingURL=wiltech-labs-ngx-forms.mjs.map