@wiltech-labs/ngx-forms 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"wiltech-labs-ngx-forms.mjs","names":[],"sources":["../../src/lib/dynamic-form/components/text-field/text-field.ts","../../src/lib/dynamic-form/components/text-field/text-field.html","../../src/lib/dynamic-form/constants/form-field.constant.ts","../../src/lib/dynamic-form/components/textarea-field/textarea-field.ts","../../src/lib/dynamic-form/components/textarea-field/textarea-field.html","../../src/lib/dynamic-form/shared/field-subscript/field-subscript.ts","../../src/lib/dynamic-form/shared/field-subscript/field-subscript.html","../../src/lib/dynamic-form/components/checkbox-field/checkbox-field.ts","../../src/lib/dynamic-form/components/checkbox-field/checkbox-field.html","../../src/lib/dynamic-form/components/radio-field/radio-field.ts","../../src/lib/dynamic-form/components/radio-field/radio-field.html","../../src/lib/dynamic-form/components/select-field/select-field.ts","../../src/lib/dynamic-form/components/select-field/select-field.html","../../src/lib/dynamic-form/components/chips-field/chips-field.ts","../../src/lib/dynamic-form/components/chips-field/chips-field.html","../../src/lib/dynamic-form/components/slider-field/slider-field.ts","../../src/lib/dynamic-form/components/slider-field/slider-field.html","../../src/lib/dynamic-form/adapters/locale-date-adapter.ts","../../src/lib/dynamic-form/constants/date-time.constants.ts","../../src/lib/dynamic-form/config/forms-locale.token.ts","../../src/lib/dynamic-form/utils/mat-input-error-state.ts","../../src/lib/dynamic-form/utils/date-time.utils.ts","../../src/lib/dynamic-form/components/business-date-field/business-date-field.ts","../../src/lib/dynamic-form/components/business-date-field/business-date-field.html","../../src/lib/dynamic-form/components/business-time-field/business-time-field.ts","../../src/lib/dynamic-form/components/business-time-field/business-time-field.html","../../src/lib/dynamic-form/services/zoned-date-time.service.ts","../../src/lib/dynamic-form/components/instant-date-time-field/instant-date-time-field.ts","../../src/lib/dynamic-form/components/instant-date-time-field/instant-date-time-field.html","../../src/lib/dynamic-form/components/dynamic-form/dynamic-form.ts","../../src/lib/dynamic-form/components/dynamic-form/dynamic-form.html","../../src/lib/dynamic-form/utils/dynamic-form.utils.ts","../../src/lib/dynamic-form/builders/form-config.builder.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\n\r\n/**\r\n * Single-line Material input for the text, email, password, search and number field types.\r\n * `[formField]` sits on the native input, so Signals Forms and MatInput handle the value,\r\n * required marker, touched/disabled state and when the errors show.\r\n */\r\n@Component({\r\n selector: 'ngx-text-field',\r\n standalone: true,\r\n imports: [FormField, MatFormFieldModule, MatInputModule],\r\n templateUrl: './text-field.html',\r\n styleUrl: './text-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class TextField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string> | FieldTree<number>>();\r\n\r\n // [formField]'s typing can't take the union, but it handles both text and number inputs at runtime.\r\n protected readonly formField = computed(() => this.field() as FieldTree<string>);\r\n}\r\n","<mat-form-field class=\"TextField\" 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","export enum FormFieldType {\r\n TEXT = 'text',\r\n EMAIL = 'email',\r\n PASSWORD = 'password',\r\n SEARCH = 'search',\r\n RADIO = 'radio',\r\n CHECKBOX = 'checkbox',\r\n NUMBER = 'number',\r\n RANGE = 'range',\r\n SELECT = 'select',\r\n CHIPS = 'chips',\r\n TEXTAREA = 'textarea',\r\n CODE = 'code',\r\n BUSINESS_DATE = 'business-date',\r\n BUSINESS_TIME = 'business-time',\r\n INSTANT_DATE_TIME = 'instant-date-time',\r\n}\r\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { FormFieldType } from '../../constants/form-field.constant';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\n\r\nconst CODE_INDENT: string = ' ';\r\n\r\n/**\r\n * Multi-line Material textarea for the textarea and code field types. Code is monospaced and\r\n * Tab indents instead of moving focus, like an editor.\r\n */\r\n@Component({\r\n selector: 'ngx-textarea-field',\r\n standalone: true,\r\n imports: [FormField, MatFormFieldModule, MatInputModule],\r\n templateUrl: './textarea-field.html',\r\n styleUrl: './textarea-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class TextareaField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string>>();\r\n\r\n protected readonly isCode = computed(() => this.fieldDef().type === FormFieldType.CODE);\r\n\r\n protected onKeydown(event: KeyboardEvent): void {\r\n if (!this.isCode() || event.key !== 'Tab') {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n\r\n const textarea = event.target as HTMLTextAreaElement;\r\n const start = textarea.selectionStart ?? 0;\r\n const end = textarea.selectionEnd ?? 0;\r\n const indented = `${textarea.value.substring(0, start)}${CODE_INDENT}${textarea.value.substring(end)}`;\r\n\r\n textarea.value = indented;\r\n textarea.selectionStart = textarea.selectionEnd = start + CODE_INDENT.length;\r\n this.field()().value.set(indented);\r\n }\r\n}\r\n","<mat-form-field class=\"TextareaField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n <textarea\r\n matInput\r\n class=\"TextareaField-input\"\r\n [formField]=\"field()\"\r\n cdkTextareaAutosize\r\n [cdkAutosizeMinRows]=\"isCode() ? 8 : 4\"\r\n [class.is-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","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\r\nimport type { FieldTree, ValidationError } from '@angular/forms/signals';\r\nimport { MatError } from '@angular/material/form-field';\r\n\r\n/**\r\n * The hint/error line under a control that has no mat-form-field around it (checkbox, radio,\r\n * slider, instant date-time). Matches mat-form-field: errors replace the hint once touched.\r\n */\r\n@Component({\r\n selector: 'ngx-field-subscript',\r\n standalone: true,\r\n imports: [MatError],\r\n templateUrl: './field-subscript.html',\r\n styleUrl: './field-subscript.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class FieldSubscript {\r\n public readonly field = input.required<FieldTree<unknown>>();\r\n public readonly hint = input<string | undefined>(undefined);\r\n\r\n // Controls like mat-checkbox add their own message-less validator (Eg `required`) next to the\r\n // schema's, so keep one error per kind and prefer the one with a message.\r\n protected readonly errors = computed(() => {\r\n const byKind = new Map<string, ValidationError.WithFieldTree>();\r\n\r\n for (const error of this.field()().errors()) {\r\n const existing = byKind.get(error.kind);\r\n if (!existing || (!existing.message && error.message)) {\r\n byKind.set(error.kind, error);\r\n }\r\n }\r\n\r\n return [...byKind.values()];\r\n });\r\n}\r\n","@let state = field()();\r\n@if (state.touched() && state.invalid()) {\r\n @for (error of errors(); track error.kind) {\r\n <mat-error class=\"FieldSubscript-error\">{{ error.message ?? error.kind }}</mat-error>\r\n }\r\n} @else if (hint()) {\r\n <div class=\"FieldSubscript-hint\">{{ hint() }}</div>\r\n}\r\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatCheckbox } from '@angular/material/checkbox';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\r\n\r\n/** Material checkbox for the checkbox field type: a single yes/no value. */\r\n@Component({\r\n selector: 'ngx-checkbox-field',\r\n standalone: true,\r\n imports: [FormField, MatCheckbox, FieldSubscript],\r\n templateUrl: './checkbox-field.html',\r\n styleUrl: './checkbox-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class CheckboxField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<boolean>>();\r\n}\r\n","<mat-checkbox [formField]=\"field()\">\r\n {{ fieldDef().label }}\r\n @if (field()().required()) {\r\n <span aria-hidden=\"true\"> *</span>\r\n }\r\n</mat-checkbox>\r\n<ngx-field-subscript class=\"CheckboxField-subscript\" [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatRadioButton, MatRadioGroup } from '@angular/material/radio';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\r\n\r\nlet nextId: number = 0;\r\n\r\n/** Material radio group for the radio field type: one choice out of `fieldDef.options`, all visible. */\r\n@Component({\r\n selector: 'ngx-radio-field',\r\n standalone: true,\r\n imports: [FormField, MatRadioGroup, MatRadioButton, FieldSubscript],\r\n templateUrl: './radio-field.html',\r\n styleUrl: './radio-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class RadioField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string | number | boolean>>();\r\n\r\n protected readonly labelId: string = `radio-field-label-${nextId++}`;\r\n}\r\n","<div class=\"RadioField-label\" [id]=\"labelId\">\r\n {{ fieldDef().label }}\r\n @if (field()().required()) {\r\n <span aria-hidden=\"true\"> *</span>\r\n }\r\n</div>\r\n<mat-radio-group\r\n class=\"RadioField-group\"\r\n [class.is-vertical]=\"fieldDef().orientation === 'vertical'\"\r\n [attr.aria-orientation]=\"fieldDef().orientation ?? 'horizontal'\"\r\n [formField]=\"field()\"\r\n [attr.aria-labelledby]=\"labelId\"\r\n>\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<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatOption, MatSelect } from '@angular/material/select';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\n\r\n/** Material select for the select field type: one choice out of `fieldDef.options`, in a dropdown. */\r\n@Component({\r\n selector: 'ngx-select-field',\r\n standalone: true,\r\n imports: [FormField, MatFormFieldModule, MatSelect, MatOption],\r\n templateUrl: './select-field.html',\r\n styleUrl: './select-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SelectField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string | number | boolean>>();\r\n}\r\n","<mat-form-field class=\"SelectField\" 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","import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\r\nimport { MatChipGrid, MatChipInput, MatChipRemove, MatChipRow } from '@angular/material/chips';\r\nimport type { MatChipInputEvent } from '@angular/material/chips';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIcon } from '@angular/material/icon';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\n\r\n/**\r\n * Material chip grid for the chips field type: a free-text list of tokens (Eg keywords), typed one\r\n * at a time and removable individually. Driven by hand (`state().value.update(...)`), same as the\r\n * date/time fields — `[formField]` targets a single control's value, not a token-by-token list.\r\n */\r\n@Component({\r\n selector: 'ngx-chips-field',\r\n standalone: true,\r\n imports: [MatFormFieldModule, MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatIcon],\r\n templateUrl: './chips-field.html',\r\n styleUrl: './chips-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ChipsField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string[]>>();\r\n\r\n private readonly announcer = inject(LiveAnnouncer);\r\n\r\n protected readonly state = computed(() => this.field()());\r\n protected readonly chips = computed(() => this.state().value() ?? []);\r\n\r\n protected addChip(event: MatChipInputEvent): void {\r\n const value = (event.value || '').trim();\r\n\r\n if (value) {\r\n this.state().value.update((chips) => [...chips, value]);\r\n this.announcer.announce(`Added ${value}`);\r\n }\r\n\r\n event.chipInput.clear();\r\n }\r\n\r\n protected removeChip(chip: string): void {\r\n this.state().value.update((chips) => chips.filter((existing) => existing !== chip));\r\n this.announcer.announce(`Removed ${chip}`);\r\n }\r\n}\r\n","<mat-form-field class=\"ChipsField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\r\n <mat-label>{{ fieldDef().label }}</mat-label>\r\n\r\n <mat-chip-grid #grid [attr.aria-label]=\"fieldDef().label + ' entries'\">\r\n @for (chip of chips(); track chip) {\r\n <mat-chip-row (removed)=\"removeChip(chip)\">\r\n {{ chip }}\r\n <button matChipRemove [attr.aria-label]=\"'Remove ' + chip\">\r\n <mat-icon>cancel</mat-icon>\r\n </button>\r\n </mat-chip-row>\r\n }\r\n </mat-chip-grid>\r\n\r\n <input\r\n [matChipInputFor]=\"grid\"\r\n [placeholder]=\"'Add ' + fieldDef().label\"\r\n [disabled]=\"state().disabled()\"\r\n (blur)=\"state().markAsTouched()\"\r\n (matChipInputTokenEnd)=\"addChip($event)\"\r\n />\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","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { FormField } from '@angular/forms/signals';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { MatSlider, MatSliderThumb } from '@angular/material/slider';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\r\n\r\nlet nextId: number = 0;\r\n\r\n/** Material slider for the range field type, bounded by `fieldDef.min`/`max`/`step`. */\r\n@Component({\r\n selector: 'ngx-slider-field',\r\n standalone: true,\r\n imports: [FormField, MatSlider, MatSliderThumb, FieldSubscript],\r\n templateUrl: './slider-field.html',\r\n styleUrl: './slider-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SliderField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<number>>();\r\n\r\n protected readonly labelId: string = `slider-field-label-${nextId++}`;\r\n}\r\n","<div class=\"SliderField-label\">\r\n <span [id]=\"labelId\">\r\n {{ fieldDef().label }}\r\n @if (field()().required()) {\r\n <span aria-hidden=\"true\"> *</span>\r\n }\r\n </span>\r\n <span class=\"SliderField-value\">{{ field()().value() }}</span>\r\n</div>\r\n<mat-slider\r\n class=\"SliderField-slider\"\r\n discrete\r\n [min]=\"fieldDef().min ?? 0\"\r\n [max]=\"fieldDef().max ?? 100\"\r\n [step]=\"fieldDef().step ?? 1\"\r\n>\r\n <input matSliderThumb [formField]=\"field()\" [attr.aria-labelledby]=\"labelId\" />\r\n</mat-slider>\r\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n","import { Injectable } from '@angular/core';\r\nimport type { Provider } from '@angular/core';\r\nimport {\r\n DateAdapter,\r\n MAT_DATE_FORMATS,\r\n MAT_NATIVE_DATE_FORMATS,\r\n NativeDateAdapter,\r\n} from '@angular/material/core';\r\n\r\ntype DatePart = 'day' | 'month' | 'year';\r\n\r\nconst NUMERIC_DATE: RegExp = /^(\\d{1,4})\\D+(\\d{1,2})\\D+(\\d{1,4})$/;\r\n\r\n/**\r\n * NativeDateAdapter already *displays* dates in its locale, but its parse() hands typed text to\r\n * Date.parse(), which always reads 31/03/2024 as month-first. This parses typed numeric dates in\r\n * the same day/month/year order the locale displays them in.\r\n */\r\n@Injectable()\r\nexport class LocaleDateAdapter extends NativeDateAdapter {\r\n override parse(value: unknown, parseFormat?: unknown): Date | null {\r\n const match = typeof value === 'string' ? value.trim().match(NUMERIC_DATE) : null;\r\n if (!match) {\r\n return super.parse(value, parseFormat);\r\n }\r\n\r\n const parts: Partial<Record<DatePart, number>> = {};\r\n this.partOrder().forEach((part, index) => (parts[part] = Number(match[index + 1])));\r\n\r\n try {\r\n return this.createDate(parts.year!, parts.month! - 1, parts.day!);\r\n } catch {\r\n return this.invalid();\r\n }\r\n }\r\n\r\n private partOrder(): DatePart[] {\r\n return new Intl.DateTimeFormat(this.locale)\r\n .formatToParts(new Date(2000, 10, 22))\r\n .map((part) => part.type)\r\n .filter((type): type is DatePart => type === 'day' || type === 'month' || type === 'year');\r\n }\r\n}\r\n\r\n/**\r\n * Gives a component its own DateAdapter instance, so each field can call setLocale() with its own\r\n * locale without changing the format of every other picker in the app.\r\n */\r\nexport function provideLocaleDateAdapter(): Provider[] {\r\n return [\r\n { provide: DateAdapter, useClass: LocaleDateAdapter },\r\n { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },\r\n ];\r\n}\r\n","export const DEFAULT_DATE_TIME_LOCALE: string = 'en-GB';\r\n\r\nexport const INSTANT_DATE_TIME_INVALID_ERROR_LABEL: string = 'Not a valid date and time.';\r\nexport const BUSINESS_DATE_INVALID_ERROR_LABEL: string = 'Not a valid date.';\r\nexport const BUSINESS_TIME_INVALID_ERROR_LABEL: string = 'Not a valid time.';\r\n\r\n/** Which instant to pick when a wall-clock time happens twice (clocks going back). */\r\nexport type DateTimeDisambiguation = 'earlier' | 'later';\r\n\r\n/**\r\n * Config for the business-date, business-time and instant-date-time fields.\r\n * `min`/`max` use the field's own value format: '2024-12-25', '09:00' or '2024-01-01T00:00:00Z'.\r\n */\r\nexport interface DateTimeConfig {\r\n locale?: string; // Display and typing format, Eg 'en-GB' (31/03/2024) or 'en-US'. Defaults to 'en-GB'.\r\n min?: string; // Earliest allowed value, in the field's value format.\r\n max?: string; // Latest allowed value, in the field's value format.\r\n timeZone?: string; // instant-date-time only: IANA zone the user edits in. Defaults to the user's timezone.\r\n disambiguation?: DateTimeDisambiguation; // instant-date-time only: which occurrence when a wall-clock time happens twice.\r\n}\r\n","import { InjectionToken } from '@angular/core';\r\nimport { DEFAULT_DATE_TIME_LOCALE } from '../constants/date-time.constants';\r\n\r\n/** A plain function the app supplies, read fresh on every call — see `NGX_FORMS_LOCALE`. */\r\nexport type FormsLocaleResolver = () => string;\r\n\r\n/**\r\n * Which locale a date/time field's picker displays and parses in, when its own `FieldDef`\r\n * doesn't set `dateTimeConfig.locale` — an explicit per-field `locale` always wins over this.\r\n * Defaults to `DEFAULT_DATE_TIME_LOCALE` ('en-GB'), same as before this token existed, not the\r\n * browser's own language: unlike `ngx-dates`' `NGX_DATES_LOCALE` (read-only display text), this\r\n * locale also decides which *typed* day/month order `LocaleDateAdapter.parse()` accepts, so\r\n * switching it changes user input behaviour, not just wording — an app opts in deliberately:\r\n *\r\n * ```ts\r\n * { provide: NGX_FORMS_LOCALE, useFactory: () => { const translations = inject(TranslationsService); return () => translations.locale(); } }\r\n * ```\r\n *\r\n * A plain function rather than a direct import of `ngx-translations`' `TranslationsService`, so this package\r\n * stays buildable and publishable on its own — same reasoning as `ngx-dates`' `NGX_DATES_LOCALE`\r\n * (see root `CLAUDE.md`'s \"Inter-package deps\").\r\n */\r\nexport const NGX_FORMS_LOCALE = new InjectionToken<FormsLocaleResolver>('NGX_FORMS_LOCALE', {\r\n factory: () => () => DEFAULT_DATE_TIME_LOCALE,\r\n});\r\n","import { effect } from '@angular/core';\r\nimport type { Signal } from '@angular/core';\r\nimport type { FieldState } from '@angular/forms/signals';\r\nimport type { MatInput } from '@angular/material/input';\r\n\r\n/**\r\n * MatInput only works out its error state (red outline, visible mat-error) from an Angular forms\r\n * control bound to it. Picker inputs driven by hand have none, so this pushes the field's\r\n * touched && invalid state into them instead. Call from a constructor (needs an injection context).\r\n */\r\nexport function syncMatInputErrorState(\r\n inputs: Signal<readonly MatInput[]>,\r\n state: Signal<FieldState<unknown>>,\r\n): void {\r\n effect(() => {\r\n const hasError = state().touched() && state().invalid();\r\n\r\n for (const input of inputs()) {\r\n if (input.errorState !== hasError) {\r\n input.errorState = hasError;\r\n input.stateChanges.next();\r\n }\r\n }\r\n });\r\n}\r\n","import { Temporal } from 'temporal-polyfill';\r\nimport type { ValidationError } from '@angular/forms/signals';\r\nimport { FormFieldType } from '../constants/form-field.constant';\r\nimport {\r\n BUSINESS_DATE_INVALID_ERROR_LABEL,\r\n BUSINESS_TIME_INVALID_ERROR_LABEL,\r\n INSTANT_DATE_TIME_INVALID_ERROR_LABEL,\r\n} from '../constants/date-time.constants';\r\nimport type { FieldDef } from '../interfaces/field-definition';\r\n\r\n/** Parses a UTC instant, Eg '2024-03-31T01:30:00Z'. Null instead of throwing for empty/invalid input. */\r\nexport function parseInstant(value: string | null | undefined): Temporal.Instant | null {\r\n return tryParse(value, (v) => Temporal.Instant.from(v));\r\n}\r\n\r\n/** Parses a calendar date, Eg '2024-12-25'. Null instead of throwing for empty/invalid input. */\r\nexport function parsePlainDate(value: string | null | undefined): Temporal.PlainDate | null {\r\n return tryParse(value, (v) => Temporal.PlainDate.from(v));\r\n}\r\n\r\n/** Parses a time of day, Eg '09:00'. Null instead of throwing for empty/invalid input. */\r\nexport function parsePlainTime(value: string | null | undefined): Temporal.PlainTime | null {\r\n return tryParse(value, (v) => Temporal.PlainTime.from(v));\r\n}\r\n\r\ninterface DateTimeRule<T> {\r\n parse: (value: string | null | undefined) => T | null;\r\n compare: (a: T, b: T) => number;\r\n invalidMessage: string;\r\n}\r\n\r\nconst DATE_TIME_RULES: Partial<Record<FormFieldType, DateTimeRule<any>>> = {\r\n [FormFieldType.INSTANT_DATE_TIME]: {\r\n parse: parseInstant,\r\n compare: Temporal.Instant.compare,\r\n invalidMessage: INSTANT_DATE_TIME_INVALID_ERROR_LABEL,\r\n },\r\n [FormFieldType.BUSINESS_DATE]: {\r\n parse: parsePlainDate,\r\n compare: Temporal.PlainDate.compare,\r\n invalidMessage: BUSINESS_DATE_INVALID_ERROR_LABEL,\r\n },\r\n [FormFieldType.BUSINESS_TIME]: {\r\n parse: parsePlainTime,\r\n compare: Temporal.PlainTime.compare,\r\n invalidMessage: BUSINESS_TIME_INVALID_ERROR_LABEL,\r\n },\r\n};\r\n\r\nexport function isDateTimeField(type: FormFieldType): boolean {\r\n return type in DATE_TIME_RULES;\r\n}\r\n\r\n/** Format and dateTimeConfig min/max check for the date/time field types; null when valid or empty. */\r\nexport function dateTimeError(value: string | null, fieldDef: FieldDef): ValidationError | null {\r\n const rule = DATE_TIME_RULES[fieldDef.type];\r\n if (!rule || !value) {\r\n return null;\r\n }\r\n\r\n const parsed = rule.parse(value);\r\n if (!parsed) {\r\n return { kind: 'invalidDateTime', message: rule.invalidMessage };\r\n }\r\n\r\n const min = fieldDef.dateTimeConfig?.min;\r\n const parsedMin = rule.parse(min);\r\n if (parsedMin && rule.compare(parsed, parsedMin) < 0) {\r\n return { kind: 'minDateTime', message: `${fieldDef.label} cannot be before ${min}` };\r\n }\r\n\r\n const max = fieldDef.dateTimeConfig?.max;\r\n const parsedMax = rule.parse(max);\r\n if (parsedMax && rule.compare(parsed, parsedMax) > 0) {\r\n return { kind: 'maxDateTime', message: `${fieldDef.label} cannot be after ${max}` };\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction tryParse<T>(value: string | null | undefined, parse: (value: string) => T): T | null {\r\n if (!value) {\r\n return null;\r\n }\r\n\r\n try {\r\n return parse(value);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n viewChildren,\r\n} from '@angular/core';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { DateAdapter } from '@angular/material/core';\r\nimport { MatDatepickerModule } from '@angular/material/datepicker';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInput, MatInputModule } from '@angular/material/input';\r\nimport { Temporal } from 'temporal-polyfill';\r\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\r\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\r\nimport { parsePlainDate } from '../../utils/date-time.utils';\r\n\r\n/**\r\n * Calendar date with no timezone, Eg Christmas Day: the form value is a plain 'YYYY-MM-DD' string\r\n * and means the same day wherever it is read. The display format follows `dateTimeConfig.locale`.\r\n */\r\n@Component({\r\n selector: 'ngx-business-date-field',\r\n standalone: true,\r\n imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule],\r\n providers: [provideLocaleDateAdapter()],\r\n templateUrl: './business-date-field.html',\r\n styleUrl: './business-date-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class BusinessDateField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string | null>>();\r\n\r\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\r\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\r\n\r\n protected readonly state = computed(() => this.field()());\r\n protected readonly date = computed(() => toDate(this.state().value()));\r\n protected readonly minDate = computed(() => toDate(this.fieldDef().dateTimeConfig?.min));\r\n protected readonly maxDate = computed(() => toDate(this.fieldDef().dateTimeConfig?.max));\r\n\r\n private readonly inputs = viewChildren(MatInput);\r\n\r\n constructor() {\r\n syncMatInputErrorState(this.inputs, this.state);\r\n effect(() =>\r\n this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || this.resolveLocale()),\r\n );\r\n }\r\n\r\n protected onDateChange(date: Date | null): void {\r\n if (!date || isNaN(date.getTime())) {\r\n this.state().value.set(null);\r\n return;\r\n }\r\n\r\n this.state().value.set(\r\n Temporal.PlainDate.from({\r\n year: date.getFullYear(),\r\n month: date.getMonth() + 1,\r\n day: date.getDate(),\r\n }).toString(),\r\n );\r\n }\r\n}\r\n\r\nfunction toDate(value: string | null | undefined): Date | null {\r\n const plainDate = parsePlainDate(value);\r\n return plainDate ? new Date(plainDate.year, plainDate.month - 1, plainDate.day) : null;\r\n}\r\n","<mat-form-field class=\"BusinessDateField\" 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","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n viewChildren,\r\n} from '@angular/core';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { DateAdapter } from '@angular/material/core';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInput, MatInputModule } from '@angular/material/input';\r\nimport { MatTimepickerModule } from '@angular/material/timepicker';\r\nimport { Temporal } from 'temporal-polyfill';\r\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\r\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\r\nimport { parsePlainTime } from '../../utils/date-time.utils';\r\n\r\n/**\r\n * Time of day with no timezone, Eg \"open from 09:00\": the form value is a plain 'HH:mm' string\r\n * and means the same clock time wherever it is read. The display format follows `dateTimeConfig.locale`.\r\n */\r\n@Component({\r\n selector: 'ngx-business-time-field',\r\n standalone: true,\r\n imports: [MatFormFieldModule, MatInputModule, MatTimepickerModule],\r\n providers: [provideLocaleDateAdapter()],\r\n templateUrl: './business-time-field.html',\r\n styleUrl: './business-time-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class BusinessTimeField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string | null>>();\r\n\r\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\r\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\r\n\r\n protected readonly state = computed(() => this.field()());\r\n protected readonly time = computed(() => toDate(this.state().value()));\r\n protected readonly minTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.min));\r\n protected readonly maxTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.max));\r\n\r\n private readonly inputs = viewChildren(MatInput);\r\n\r\n constructor() {\r\n syncMatInputErrorState(this.inputs, this.state);\r\n effect(() =>\r\n this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || this.resolveLocale()),\r\n );\r\n }\r\n\r\n protected onTimeChange(time: Date | null): void {\r\n if (!time || isNaN(time.getTime())) {\r\n this.state().value.set(null);\r\n return;\r\n }\r\n\r\n this.state().value.set(\r\n Temporal.PlainTime.from({ hour: time.getHours(), minute: time.getMinutes() }).toString({\r\n smallestUnit: 'minute',\r\n }),\r\n );\r\n }\r\n}\r\n\r\n// The timepicker only reads the hours/minutes of this Date; 1 Jan is used because no timezone changes clocks on it.\r\nfunction toDate(value: string | null | undefined): Date | null {\r\n const plainTime = parsePlainTime(value);\r\n return plainTime ? new Date(2000, 0, 1, plainTime.hour, plainTime.minute) : null;\r\n}\r\n","<mat-form-field class=\"BusinessTimeField\" 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","import { Injectable } from '@angular/core';\r\nimport { Temporal } from 'temporal-polyfill';\r\nimport type { DateTimeDisambiguation } from '../constants/date-time.constants';\r\nimport { parseInstant } from '../utils/date-time.utils';\r\n\r\nexport interface ZonedInstantResult {\r\n instant: string; // UTC instant, Eg '2024-03-31T01:30:00Z'\r\n notice: string | null; // Set when the wall-clock time fell in a DST gap or overlap\r\n}\r\n\r\n/**\r\n * Bridges UTC instants and the JS `Date`s that Angular Material pickers work with.\r\n *\r\n * A picker `Date` is treated as a wall-clock value: its local getters (getFullYear, getHours, ...)\r\n * hold the date and time as seen in `timeZone`, not in the browser's own timezone.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class ZonedDateTimeService {\r\n /** UTC instant -> `Date` whose local fields show the wall-clock time in `timeZone`. */\r\n public toDate(instant: string | null | undefined, timeZone: string): Date | null {\r\n const zoned = this.toZoned(instant, timeZone);\r\n if (!zoned) {\r\n return null;\r\n }\r\n\r\n // Can be off by an hour only inside the browser's own DST gap, where JS Date can't hold that time.\r\n return new Date(zoned.year, zoned.month - 1, zoned.day, zoned.hour, zoned.minute);\r\n }\r\n\r\n /** Wall-clock date + time in `timeZone` -> UTC instant, resolving DST gaps and overlaps explicitly. */\r\n public toInstant(\r\n date: Date,\r\n time: Date,\r\n timeZone: string,\r\n disambiguation: DateTimeDisambiguation = 'earlier',\r\n ): ZonedInstantResult | null {\r\n try {\r\n const plainDateTime = Temporal.PlainDateTime.from({\r\n year: date.getFullYear(),\r\n month: date.getMonth() + 1,\r\n day: date.getDate(),\r\n hour: time.getHours(),\r\n minute: time.getMinutes(),\r\n });\r\n const earlier = plainDateTime.toZonedDateTime(timeZone, { disambiguation: 'earlier' });\r\n const later = plainDateTime.toZonedDateTime(timeZone, { disambiguation: 'later' });\r\n\r\n if (earlier.equals(later)) {\r\n return { instant: earlier.toInstant().toString(), notice: null };\r\n }\r\n\r\n const isGap = !earlier.toPlainDateTime().equals(plainDateTime);\r\n if (isGap) {\r\n return {\r\n instant: later.toInstant().toString(),\r\n notice:\r\n `${formatWallClock(plainDateTime)} does not exist in ${timeZone} (clocks go forward). ` +\r\n `Using ${formatWallClock(later.toPlainDateTime())} (UTC${later.offset}) instead.`,\r\n };\r\n }\r\n\r\n const chosen = disambiguation === 'later' ? later : earlier;\r\n return {\r\n instant: chosen.toInstant().toString(),\r\n notice:\r\n `${formatWallClock(plainDateTime)} happens twice in ${timeZone} (clocks go back). ` +\r\n `Using the ${chosen === earlier ? 'first' : 'second'} occurrence (UTC${chosen.offset}).`,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /** UTC offset of `instant` in `timeZone`, Eg '+01:00', or null when either is invalid. */\r\n public offset(instant: string | null | undefined, timeZone: string): string | null {\r\n return this.toZoned(instant, timeZone)?.offset ?? null;\r\n }\r\n\r\n private toZoned(\r\n instant: string | null | undefined,\r\n timeZone: string,\r\n ): Temporal.ZonedDateTime | null {\r\n try {\r\n return parseInstant(instant)?.toZonedDateTimeISO(timeZone) ?? null;\r\n } catch {\r\n // invalid timezone id\r\n return null;\r\n }\r\n }\r\n}\r\n\r\nfunction formatWallClock(plainDateTime: Temporal.PlainDateTime): string {\r\n return plainDateTime.toString({ smallestUnit: 'minute' }).replace('T', ' ');\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n linkedSignal,\r\n signal,\r\n viewChildren,\r\n} from '@angular/core';\r\nimport type { WritableSignal } from '@angular/core';\r\nimport type { FieldTree } from '@angular/forms/signals';\r\nimport { DateAdapter } from '@angular/material/core';\r\nimport { MatDatepickerModule } from '@angular/material/datepicker';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInput, MatInputModule } from '@angular/material/input';\r\nimport { MatTimepickerModule } from '@angular/material/timepicker';\r\nimport { Temporal } from 'temporal-polyfill';\r\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\r\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\r\nimport { ZonedDateTimeService } from '../../services/zoned-date-time.service';\r\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\r\n\r\n/**\r\n * Date and time field whose form value is a UTC instant (YYYY-MM-DDThh:mm:ssZ), edited through the\r\n * Material datepicker and timepicker as the wall-clock time of `dateTimeConfig.timeZone`.\r\n * The display format follows `dateTimeConfig.locale`, not the browser's.\r\n */\r\n@Component({\r\n selector: 'ngx-instant-date-time-field',\r\n standalone: true,\r\n imports: [\r\n MatFormFieldModule,\r\n MatInputModule,\r\n MatDatepickerModule,\r\n MatTimepickerModule,\r\n FieldSubscript,\r\n ],\r\n providers: [provideLocaleDateAdapter()],\r\n templateUrl: './instant-date-time-field.html',\r\n styleUrl: './instant-date-time-field.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class InstantDateTimeField {\r\n public readonly fieldDef = input.required<FieldDef>();\r\n public readonly field = input.required<FieldTree<string | null>>();\r\n\r\n private readonly zonedDateTime = inject(ZonedDateTimeService);\r\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\r\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\r\n\r\n /** Explains how a DST gap or overlap was resolved for the last value picked by the user. */\r\n protected readonly notice: WritableSignal<string | null> = signal(null);\r\n\r\n protected readonly state = computed(() => this.field()());\r\n protected readonly config = computed(() => this.fieldDef().dateTimeConfig);\r\n protected readonly timeZone = computed(\r\n () => this.config()?.timeZone || Temporal.Now.timeZoneId(),\r\n );\r\n protected readonly offset = computed(() =>\r\n this.zonedDateTime.offset(this.state().value(), this.timeZone()),\r\n );\r\n protected readonly minDate = computed(() =>\r\n this.zonedDateTime.toDate(this.config()?.min, this.timeZone()),\r\n );\r\n protected readonly maxDate = computed(() =>\r\n this.zonedDateTime.toDate(this.config()?.max, this.timeZone()),\r\n );\r\n\r\n // Only a change of the actual wall-clock time counts, so '' -> null (still empty) keeps a half-filled pick.\r\n private readonly wallClock = computed(\r\n () => this.zonedDateTime.toDate(this.state().value(), this.timeZone()),\r\n { equal: (a, b) => a?.getTime() === b?.getTime() },\r\n );\r\n\r\n // Both pickers follow the bound value, but can hold a half-filled pick until both parts are set.\r\n protected readonly date = linkedSignal(() => this.wallClock());\r\n protected readonly time = linkedSignal(() => this.wallClock());\r\n\r\n private readonly inputs = viewChildren(MatInput);\r\n\r\n constructor() {\r\n syncMatInputErrorState(this.inputs, this.state);\r\n effect(() => this.dateAdapter.setLocale(this.config()?.locale || this.resolveLocale()));\r\n }\r\n\r\n protected onDateChange(date: Date | null): void {\r\n if (sameParts(date, this.date(), (d) => [d.getFullYear(), d.getMonth(), d.getDate()])) {\r\n return;\r\n }\r\n\r\n this.date.set(date);\r\n this.commit();\r\n }\r\n\r\n // The timepicker re-emits values we set on it (Eg on blur); ignoring those keeps a DST notice visible.\r\n protected onTimeChange(time: Date | null): void {\r\n if (sameParts(time, this.time(), (t) => [t.getHours(), t.getMinutes()])) {\r\n return;\r\n }\r\n\r\n this.time.set(time);\r\n this.commit();\r\n }\r\n\r\n private commit(): void {\r\n this.notice.set(null);\r\n\r\n const date = this.date();\r\n const time = this.time();\r\n const value = this.state().value;\r\n\r\n if (!isValidDate(date) || !isValidDate(time)) {\r\n if (value() !== null) {\r\n value.set(null);\r\n }\r\n return;\r\n }\r\n\r\n const result = this.zonedDateTime.toInstant(\r\n date,\r\n time,\r\n this.timeZone(),\r\n this.config()?.disambiguation,\r\n );\r\n value.set(result?.instant ?? null);\r\n this.notice.set(result?.notice ?? null);\r\n }\r\n}\r\n\r\nfunction isValidDate(value: Date | null): value is Date {\r\n return value instanceof Date && !isNaN(value.getTime());\r\n}\r\n\r\nfunction sameParts(a: Date | null, b: Date | null, parts: (date: Date) => number[]): boolean {\r\n if (!isValidDate(a) || !isValidDate(b)) {\r\n return a === b;\r\n }\r\n\r\n const bParts = parts(b);\r\n return parts(a).every((part, index) => part === bParts[index]);\r\n}\r\n","<div class=\"InstantDateTimeField-label\">\r\n {{ fieldDef().label }}\r\n @if (state().required()) {\r\n <span aria-hidden=\"true\"> *</span>\r\n }\r\n</div>\r\n\r\n<div class=\"InstantDateTimeField-row\">\r\n <mat-form-field class=\"InstantDateTimeField-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=\"InstantDateTimeField-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=\"InstantDateTimeField-zone\">\r\n {{ timeZone() }}\r\n @if (offset()) {\r\n (UTC{{ offset() }})\r\n }\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=\"InstantDateTimeField-notice\">{{ notice() }}</div>\r\n}\r\n\r\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\r\n","import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\r\nimport type { InputSignal } from '@angular/core';\r\nimport type { FieldState, FieldTree } from '@angular/forms/signals';\r\nimport { MatButton } from '@angular/material/button';\r\nimport { TextField } from '../text-field/text-field';\r\nimport { TextareaField } from '../textarea-field/textarea-field';\r\nimport { CheckboxField } from '../checkbox-field/checkbox-field';\r\nimport { RadioField } from '../radio-field/radio-field';\r\nimport { SelectField } from '../select-field/select-field';\r\nimport { ChipsField } from '../chips-field/chips-field';\r\nimport { SliderField } from '../slider-field/slider-field';\r\nimport { BusinessDateField } from '../business-date-field/business-date-field';\r\nimport { BusinessTimeField } from '../business-time-field/business-time-field';\r\nimport { InstantDateTimeField } from '../instant-date-time-field/instant-date-time-field';\r\nimport type { FieldDef } from '../../interfaces/field-definition';\r\nimport type { BaseSchema } from '../../interfaces/base.schema';\r\n\r\n/**\r\n * Renders one Material field component per FieldDef, then right-aligned actions: a text\r\n * secondary action (\"Clear\" by default — label it \"Cancel\" when it leaves the form) and the filled\r\n * primary one (\"Save\"). Name both after what they do.\r\n */\r\n@Component({\r\n selector: 'ngx-dynamic-form',\r\n standalone: true,\r\n imports: [\r\n MatButton,\r\n TextField,\r\n TextareaField,\r\n CheckboxField,\r\n RadioField,\r\n SelectField,\r\n ChipsField,\r\n SliderField,\r\n BusinessDateField,\r\n BusinessTimeField,\r\n InstantDateTimeField,\r\n ],\r\n templateUrl: './dynamic-form.html',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n styleUrl: './dynamic-form.scss',\r\n})\r\nexport class DynamicForm<T extends BaseSchema = BaseSchema> {\r\n public metaInfo: InputSignal<FieldDef[]> = input.required<FieldDef[]>();\r\n public dynamicForm: InputSignal<FieldTree<T>> = input.required<FieldTree<T>>();\r\n\r\n /** Filled primary action. */\r\n public readonly submitLabel = input('Save');\r\n /** Text secondary action; emits `onFormClear`. */\r\n public readonly clearLabel = input('Clear');\r\n\r\n public onFormSubmit = output<void>();\r\n public onFormClear = output<void>();\r\n\r\n protected handleSubmit(): void {\r\n const fieldTree: FieldTree<unknown> = this.dynamicForm();\r\n const fieldState: FieldState<unknown> = fieldTree();\r\n\r\n if (fieldState.valid()) {\r\n this.onFormSubmit.emit();\r\n }\r\n }\r\n\r\n protected clearForm(): void {\r\n this.onFormClear.emit();\r\n }\r\n}\r\n","<div class=\"DynamicForm\">\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=\"DynamicForm-field\" [style.--ngx-field-max-width]=\"fieldDef.maxWidth\">\r\n @switch (fieldDef.type) {\r\n @case ('text') {\r\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('email') {\r\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('password') {\r\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('search') {\r\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('number') {\r\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('textarea') {\r\n <ngx-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('code') {\r\n <ngx-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('checkbox') {\r\n <ngx-checkbox-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('radio') {\r\n <ngx-radio-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('select') {\r\n <ngx-select-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('chips') {\r\n <ngx-chips-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('range') {\r\n <ngx-slider-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-date') {\r\n <ngx-business-date-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('business-time') {\r\n <ngx-business-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\r\n }\r\n @case ('instant-date-time') {\r\n <ngx-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=\"DynamicForm-actions\">\r\n <button matButton type=\"button\" (click)=\"clearForm()\">{{ clearLabel() }}</button>\r\n <button\r\n matButton=\"filled\"\r\n type=\"button\"\r\n [disabled]=\"dynamicForm()().invalid()\"\r\n (click)=\"handleSubmit()\"\r\n >\r\n {{ submitLabel() }}\r\n </button>\r\n </div>\r\n</div>\r\n","import type { FieldDef } from '../interfaces/field-definition';\r\nimport {\r\n disabled,\r\n email,\r\n max,\r\n maxLength,\r\n min,\r\n minLength,\r\n pattern,\r\n required,\r\n schema,\r\n validate,\r\n} from '@angular/forms/signals';\r\nimport type { Schema } from '@angular/forms/signals';\r\nimport { FormFieldType } from '../constants/form-field.constant';\r\nimport type { BaseSchema, SchemaConfig } from '../interfaces/base.schema';\r\nimport { dateTimeError, isDateTimeField } from './date-time.utils';\r\n\r\nexport function defineSchema<T extends BaseSchema>(config: SchemaConfig<T>): SchemaConfig<T> {\r\n return config;\r\n}\r\n\r\nexport function createEmptyEntity<T extends BaseSchema>(\r\n schemaType: T['schemaType'],\r\n defaults: Omit<T, 'id' | 'schemaType'>,\r\n): T {\r\n return {\r\n id: '',\r\n schemaType,\r\n ...defaults,\r\n } as T;\r\n}\r\n\r\n/** Turns field definitions into Signals Forms rules. The model can be any object, not just a BaseSchema. */\r\nexport function toSchema<T>(meta: FieldDef[]): Schema<T> {\r\n return schema<T>((path: any) => {\r\n for (const fieldDef of meta) {\r\n const property: string = fieldDef.name;\r\n const fieldPath: any = (path as any)[property];\r\n\r\n if (!fieldPath) {\r\n continue;\r\n }\r\n\r\n if (fieldDef.disabled) {\r\n disabled(fieldPath);\r\n }\r\n if (fieldDef.required) {\r\n required(fieldPath, { message: `${fieldDef.label} is required` });\r\n }\r\n if (typeof fieldDef.minLength !== 'undefined') {\r\n minLength(fieldPath, fieldDef.minLength, {\r\n message: `${fieldDef.label} must be at least ${fieldDef.minLength} characters`,\r\n });\r\n }\r\n if (typeof fieldDef.maxLength !== 'undefined') {\r\n maxLength(fieldPath, fieldDef.maxLength, {\r\n message: `${fieldDef.label} cannot exceed ${fieldDef.maxLength} characters`,\r\n });\r\n }\r\n if (fieldDef.type === FormFieldType.EMAIL) {\r\n email(fieldPath, { message: `${fieldDef.label} must be a valid email address` });\r\n }\r\n if (typeof fieldDef.pattern !== 'undefined') {\r\n pattern(fieldPath, toRegExp(fieldDef.pattern), {\r\n message: fieldDef.patternMessage ?? `${fieldDef.label} is not in the expected format`,\r\n });\r\n }\r\n if (typeof fieldDef.min !== 'undefined') {\r\n min(fieldPath, fieldDef.min, {\r\n message: `${fieldDef.label} must be at least ${fieldDef.min}`,\r\n });\r\n }\r\n if (typeof fieldDef.max !== 'undefined') {\r\n max(fieldPath, fieldDef.max, {\r\n message: `${fieldDef.label} cannot exceed ${fieldDef.max}`,\r\n });\r\n }\r\n\r\n if (isDateTimeField(fieldDef.type)) {\r\n validate(fieldPath, (ctx: any) => dateTimeError(ctx.value() as string | null, fieldDef));\r\n }\r\n }\r\n });\r\n}\r\n\r\n// A string pattern must match the whole value, like HTML's `pattern` attribute and Validators.pattern;\r\n// a RegExp is used as given, so its author controls anchoring.\r\nfunction toRegExp(value: RegExp | string): RegExp {\r\n return value instanceof RegExp ? value : new RegExp(`^(?:${value})$`);\r\n}\r\n","import { FormFieldType } from '../constants/form-field.constant';\r\nimport type { DateTimeConfig } from '../constants/date-time.constants';\r\nimport type { BaseSchema, SchemaConfig } from '../interfaces/base.schema';\r\nimport type { FieldDef, FieldOption } from '../interfaces/field-definition';\r\nimport { createEmptyEntity } from '../utils/dynamic-form.utils';\r\n\r\n/** A property of the schema that can be a form field. */\r\nexport type FieldName<T> = Exclude<Extract<keyof T, string>, 'schemaType'>;\r\n\r\n/** Everything on a FieldDef except what the builder method already sets. */\r\nexport type FieldOptions = Omit<FieldDef, 'name' | 'type' | 'label' | 'options' | 'dateTimeConfig'>;\r\n\r\n/** FieldOptions plus the dateTimeConfig for the business-date, business-time and instant-date-time fields. */\r\nexport type DateTimeFieldOptions = FieldOptions & { dateTimeConfig?: DateTimeConfig };\r\n\r\n/**\r\n * Fluent, type-checked way to build a SchemaConfig for DynamicForm. Field names are checked against\r\n * the schema, so a typo or renamed property fails at compile time.\r\n *\r\n * @example\r\n * const config = formConfig<FlightSchema>('flight')\r\n * .text('from', 'Departure City', { required: true, minLength: 3 })\r\n * .instantDateTime('date', 'Departure', { required: true, dateTimeConfig: { timeZone: 'Europe/London' } })\r\n * .checkbox('delayed', 'Delayed')\r\n * .build({ from: '', date: '', delayed: false });\r\n */\r\nexport class FormConfigBuilder<T extends BaseSchema> {\r\n private readonly fieldDefs: FieldDef[] = [];\r\n\r\n constructor(private readonly schemaType: T['schemaType']) {}\r\n\r\n public text(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.TEXT, name, label, options);\r\n }\r\n\r\n /** Text input with the email keyboard/autofill and a valid-email check. */\r\n public email(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.EMAIL, name, label, options);\r\n }\r\n\r\n public password(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.PASSWORD, name, label, options);\r\n }\r\n\r\n public search(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.SEARCH, name, label, options);\r\n }\r\n\r\n public number(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.NUMBER, name, label, options);\r\n }\r\n\r\n public textarea(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.TEXTAREA, name, label, options);\r\n }\r\n\r\n public code(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.CODE, name, label, options);\r\n }\r\n\r\n public checkbox(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.CHECKBOX, name, label, options);\r\n }\r\n\r\n /** Slider bounded by `options.min`/`max`/`step` (defaults 0-100, step 1). */\r\n public range(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.RANGE, name, label, options);\r\n }\r\n\r\n public radio(\r\n name: FieldName<T>,\r\n label: string,\r\n choices: FieldOption[],\r\n options?: FieldOptions,\r\n ): this {\r\n return this.add(FormFieldType.RADIO, name, label, { ...options, options: choices });\r\n }\r\n\r\n public select(\r\n name: FieldName<T>,\r\n label: string,\r\n choices: FieldOption[],\r\n options?: FieldOptions,\r\n ): this {\r\n return this.add(FormFieldType.SELECT, name, label, { ...options, options: choices });\r\n }\r\n\r\n /** Freeform list of tokens (Eg keywords), typed one at a time. */\r\n public chips(name: FieldName<T>, label: string, options?: FieldOptions): this {\r\n return this.add(FormFieldType.CHIPS, name, label, options);\r\n }\r\n\r\n /** Calendar date with no timezone, stored as 'YYYY-MM-DD'. */\r\n public businessDate(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\r\n return this.add(FormFieldType.BUSINESS_DATE, name, label, options);\r\n }\r\n\r\n /** Time of day with no timezone, stored as 'HH:mm'. */\r\n public businessTime(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\r\n return this.add(FormFieldType.BUSINESS_TIME, name, label, options);\r\n }\r\n\r\n /** Exact moment, stored as a UTC instant and edited in `dateTimeConfig.timeZone`. */\r\n public instantDateTime(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\r\n return this.add(FormFieldType.INSTANT_DATE_TIME, name, label, options);\r\n }\r\n\r\n /** A field that is part of the model and its validation, but never rendered. */\r\n public hidden(name: FieldName<T>, options?: FieldOptions): this {\r\n return this.add(FormFieldType.TEXT, name, name, { ...options, hidden: true });\r\n }\r\n\r\n /** The field definitions added so far, Eg to pass to `toSchema()` or DynamicForm's metaInfo. */\r\n public fields(): FieldDef[] {\r\n return [...this.fieldDefs];\r\n }\r\n\r\n /** The full config for DynamicForm; `id` and `schemaType` are filled in on the initial value. */\r\n public build(initialValue: Omit<T, 'id' | 'schemaType'>): SchemaConfig<T> {\r\n return {\r\n schemaType: this.schemaType,\r\n fields: this.fields(),\r\n initialValue: createEmptyEntity<T>(this.schemaType, initialValue),\r\n };\r\n }\r\n\r\n private add(type: FormFieldType, name: string, label: string, options?: Partial<FieldDef>): this {\r\n this.fieldDefs.push({ ...options, name, type, label });\r\n return this;\r\n }\r\n}\r\n\r\n/** Starts a FormConfigBuilder for schema `T`. */\r\nexport function formConfig<T extends BaseSchema>(\r\n schemaType: T['schemaType'],\r\n): FormConfigBuilder<T> {\r\n return new FormConfigBuilder<T>(schemaType);\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"wiltech-labs-ngx-forms.mjs","names":[],"sources":["../../src/lib/dynamic-form/components/text-field/text-field.ts","../../src/lib/dynamic-form/components/text-field/text-field.html","../../src/lib/dynamic-form/constants/form-field.constant.ts","../../src/lib/dynamic-form/components/textarea-field/textarea-field.ts","../../src/lib/dynamic-form/components/textarea-field/textarea-field.html","../../src/lib/dynamic-form/shared/field-subscript/field-subscript.ts","../../src/lib/dynamic-form/shared/field-subscript/field-subscript.html","../../src/lib/dynamic-form/components/checkbox-field/checkbox-field.ts","../../src/lib/dynamic-form/components/checkbox-field/checkbox-field.html","../../src/lib/dynamic-form/components/radio-field/radio-field.ts","../../src/lib/dynamic-form/components/radio-field/radio-field.html","../../src/lib/dynamic-form/components/select-field/select-field.ts","../../src/lib/dynamic-form/components/select-field/select-field.html","../../src/lib/dynamic-form/components/chips-field/chips-field.ts","../../src/lib/dynamic-form/components/chips-field/chips-field.html","../../src/lib/dynamic-form/components/theme-field/theme-field.ts","../../src/lib/dynamic-form/components/theme-field/theme-field.html","../../src/lib/dynamic-form/components/slider-field/slider-field.ts","../../src/lib/dynamic-form/components/slider-field/slider-field.html","../../src/lib/dynamic-form/adapters/locale-date-adapter.ts","../../src/lib/dynamic-form/constants/date-time.constants.ts","../../src/lib/dynamic-form/config/forms-locale.token.ts","../../src/lib/dynamic-form/utils/mat-input-error-state.ts","../../src/lib/dynamic-form/utils/date-time.utils.ts","../../src/lib/dynamic-form/components/business-date-field/business-date-field.ts","../../src/lib/dynamic-form/components/business-date-field/business-date-field.html","../../src/lib/dynamic-form/components/business-time-field/business-time-field.ts","../../src/lib/dynamic-form/components/business-time-field/business-time-field.html","../../src/lib/dynamic-form/services/zoned-date-time.service.ts","../../src/lib/dynamic-form/components/instant-date-time-field/instant-date-time-field.ts","../../src/lib/dynamic-form/components/instant-date-time-field/instant-date-time-field.html","../../src/lib/dynamic-form/components/dynamic-form/dynamic-form.ts","../../src/lib/dynamic-form/components/dynamic-form/dynamic-form.html","../../src/lib/dynamic-form/utils/dynamic-form.utils.ts","../../src/lib/dynamic-form/builders/form-config.builder.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport type { FieldDef } from '../../interfaces/field-definition';\n\n/**\n * Single-line Material input for the text, email, password, search and number field types.\n * `[formField]` sits on the native input, so Signals Forms and MatInput handle the value,\n * required marker, touched/disabled state and when the errors show.\n */\n@Component({\n selector: 'ngx-text-field',\n standalone: true,\n imports: [FormField, MatFormFieldModule, MatInputModule],\n templateUrl: './text-field.html',\n styleUrl: './text-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TextField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string> | FieldTree<number>>();\n\n // [formField]'s typing can't take the union, but it handles both text and number inputs at runtime.\n protected readonly formField = computed(() => this.field() as FieldTree<string>);\n}\n","<mat-form-field class=\"TextField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n <input matInput [type]=\"fieldDef().type\" [formField]=\"formField()\" />\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of field()().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","export enum FormFieldType {\n TEXT = 'text',\n EMAIL = 'email',\n PASSWORD = 'password',\n SEARCH = 'search',\n RADIO = 'radio',\n CHECKBOX = 'checkbox',\n NUMBER = 'number',\n RANGE = 'range',\n SELECT = 'select',\n CHIPS = 'chips',\n THEME = 'theme',\n TEXTAREA = 'textarea',\n CODE = 'code',\n BUSINESS_DATE = 'business-date',\n BUSINESS_TIME = 'business-time',\n INSTANT_DATE_TIME = 'instant-date-time',\n}\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { FormFieldType } from '../../constants/form-field.constant';\nimport type { FieldDef } from '../../interfaces/field-definition';\n\nconst CODE_INDENT: string = ' ';\n\n/**\n * Multi-line Material textarea for the textarea and code field types. Code is monospaced and\n * Tab indents instead of moving focus, like an editor.\n */\n@Component({\n selector: 'ngx-textarea-field',\n standalone: true,\n imports: [FormField, MatFormFieldModule, MatInputModule],\n templateUrl: './textarea-field.html',\n styleUrl: './textarea-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TextareaField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string>>();\n\n protected readonly isCode = computed(() => this.fieldDef().type === FormFieldType.CODE);\n\n protected onKeydown(event: KeyboardEvent): void {\n if (!this.isCode() || event.key !== 'Tab') {\n return;\n }\n\n event.preventDefault();\n\n const textarea = event.target as HTMLTextAreaElement;\n const start = textarea.selectionStart ?? 0;\n const end = textarea.selectionEnd ?? 0;\n const indented = `${textarea.value.substring(0, start)}${CODE_INDENT}${textarea.value.substring(end)}`;\n\n textarea.value = indented;\n textarea.selectionStart = textarea.selectionEnd = start + CODE_INDENT.length;\n this.field()().value.set(indented);\n }\n}\n","<mat-form-field class=\"TextareaField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n <textarea\n matInput\n class=\"TextareaField-input\"\n [formField]=\"field()\"\n cdkTextareaAutosize\n [cdkAutosizeMinRows]=\"isCode() ? 8 : 4\"\n [class.is-code]=\"isCode()\"\n [attr.spellcheck]=\"isCode() ? 'false' : null\"\n (keydown)=\"onKeydown($event)\"\n ></textarea>\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of field()().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport type { FieldTree, ValidationError } from '@angular/forms/signals';\nimport { MatError } from '@angular/material/form-field';\n\n/**\n * The hint/error line under a control that has no mat-form-field around it (checkbox, radio,\n * slider, instant date-time). Matches mat-form-field: errors replace the hint once touched.\n */\n@Component({\n selector: 'ngx-field-subscript',\n standalone: true,\n imports: [MatError],\n templateUrl: './field-subscript.html',\n styleUrl: './field-subscript.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FieldSubscript {\n public readonly field = input.required<FieldTree<unknown>>();\n public readonly hint = input<string | undefined>(undefined);\n\n // Controls like mat-checkbox add their own message-less validator (Eg `required`) next to the\n // schema's, so keep one error per kind and prefer the one with a message.\n protected readonly errors = computed(() => {\n const byKind = new Map<string, ValidationError.WithFieldTree>();\n\n for (const error of this.field()().errors()) {\n const existing = byKind.get(error.kind);\n if (!existing || (!existing.message && error.message)) {\n byKind.set(error.kind, error);\n }\n }\n\n return [...byKind.values()];\n });\n}\n","@let state = field()();\n@if (state.touched() && state.invalid()) {\n @for (error of errors(); track error.kind) {\n <mat-error class=\"FieldSubscript-error\">{{ error.message ?? error.kind }}</mat-error>\n }\n} @else if (hint()) {\n <div class=\"FieldSubscript-hint\">{{ hint() }}</div>\n}\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatCheckbox } from '@angular/material/checkbox';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\n\n/** Material checkbox for the checkbox field type: a single yes/no value. */\n@Component({\n selector: 'ngx-checkbox-field',\n standalone: true,\n imports: [FormField, MatCheckbox, FieldSubscript],\n templateUrl: './checkbox-field.html',\n styleUrl: './checkbox-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CheckboxField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<boolean>>();\n}\n","<mat-checkbox [formField]=\"field()\">\n {{ fieldDef().label }}\n @if (field()().required()) {\n <span aria-hidden=\"true\"> *</span>\n }\n</mat-checkbox>\n<ngx-field-subscript class=\"CheckboxField-subscript\" [field]=\"field()\" [hint]=\"fieldDef().hint\" />\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatRadioButton, MatRadioGroup } from '@angular/material/radio';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\n\nlet nextId: number = 0;\n\n/** Material radio group for the radio field type: one choice out of `fieldDef.options`, all visible. */\n@Component({\n selector: 'ngx-radio-field',\n standalone: true,\n imports: [FormField, MatRadioGroup, MatRadioButton, FieldSubscript],\n templateUrl: './radio-field.html',\n styleUrl: './radio-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class RadioField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string | number | boolean>>();\n\n protected readonly labelId: string = `radio-field-label-${nextId++}`;\n}\n","<div class=\"RadioField-label\" [id]=\"labelId\">\n {{ fieldDef().label }}\n @if (field()().required()) {\n <span aria-hidden=\"true\"> *</span>\n }\n</div>\n<mat-radio-group\n class=\"RadioField-group\"\n [class.is-vertical]=\"fieldDef().orientation === 'vertical'\"\n [attr.aria-orientation]=\"fieldDef().orientation ?? 'horizontal'\"\n [formField]=\"field()\"\n [attr.aria-labelledby]=\"labelId\"\n>\n @for (option of fieldDef().options ?? []; track option.value) {\n <mat-radio-button [value]=\"option.value\">{{ option.label }}</mat-radio-button>\n }\n</mat-radio-group>\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatOption, MatSelect } from '@angular/material/select';\nimport type { FieldDef } from '../../interfaces/field-definition';\n\n/** Material select for the select field type: one choice out of `fieldDef.options`, in a dropdown. */\n@Component({\n selector: 'ngx-select-field',\n standalone: true,\n imports: [FormField, MatFormFieldModule, MatSelect, MatOption],\n templateUrl: './select-field.html',\n styleUrl: './select-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SelectField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string | number | boolean>>();\n}\n","<mat-form-field class=\"SelectField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n <mat-select [formField]=\"field()\">\n @for (option of fieldDef().options ?? []; track option.value) {\n <mat-option [value]=\"option.value\">{{ option.label }}</mat-option>\n }\n </mat-select>\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of field()().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\nimport { MatChipGrid, MatChipInput, MatChipRemove, MatChipRow } from '@angular/material/chips';\nimport type { MatChipInputEvent } from '@angular/material/chips';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatIcon } from '@angular/material/icon';\nimport type { FieldDef } from '../../interfaces/field-definition';\n\n/**\n * Material chip grid for the chips field type: a free-text list of tokens (Eg keywords), typed one\n * at a time and removable individually. Driven by hand (`state().value.update(...)`), same as the\n * date/time fields — `[formField]` targets a single control's value, not a token-by-token list.\n */\n@Component({\n selector: 'ngx-chips-field',\n standalone: true,\n imports: [MatFormFieldModule, MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatIcon],\n templateUrl: './chips-field.html',\n styleUrl: './chips-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ChipsField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string[]>>();\n\n private readonly announcer = inject(LiveAnnouncer);\n\n protected readonly state = computed(() => this.field()());\n protected readonly chips = computed(() => this.state().value() ?? []);\n\n protected addChip(event: MatChipInputEvent): void {\n const value = (event.value || '').trim();\n\n if (value) {\n this.state().value.update((chips) => [...chips, value]);\n this.announcer.announce(`Added ${value}`);\n }\n\n event.chipInput.clear();\n }\n\n protected removeChip(chip: string): void {\n this.state().value.update((chips) => chips.filter((existing) => existing !== chip));\n this.announcer.announce(`Removed ${chip}`);\n }\n}\n","<mat-form-field class=\"ChipsField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n\n <mat-chip-grid #grid [attr.aria-label]=\"fieldDef().label + ' entries'\">\n @for (chip of chips(); track chip) {\n <mat-chip-row (removed)=\"removeChip(chip)\">\n {{ chip }}\n <button matChipRemove [attr.aria-label]=\"'Remove ' + chip\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n </mat-chip-grid>\n\n <input\n [matChipInputFor]=\"grid\"\n [placeholder]=\"'Add ' + fieldDef().label\"\n [disabled]=\"state().disabled()\"\n (blur)=\"state().markAsTouched()\"\n (matChipInputTokenEnd)=\"addChip($event)\"\n />\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of state().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatButtonToggleModule } from '@angular/material/button-toggle';\nimport { MatIcon } from '@angular/material/icon';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\n\nlet nextId: number = 0;\n\nconst DEFAULT_LIGHT_LABEL = 'Light';\nconst DEFAULT_DARK_LABEL = 'Dark';\n\n/** Material icon toggle group for the theme field type: a fixed choice between `'light'` and\n * `'dark'`, shown as a sun/moon icon pair instead of a dropdown or radio list.\n * `MatButtonToggleGroup` is a `ControlValueAccessor`, same as `MatRadioGroup`/`MatSelect`, so\n * `[formField]` works on it directly — no hand-written value sync needed.\n *\n * Labels come from `fieldDef.options` — same mechanism `RadioField`/`SelectField` already use, not\n * a separate config or token — matched by value since the two values and their icons are fixed\n * (`'light'`/`'dark'` only, each always paired with the same sun/moon icon); `options` only ever\n * supplies the label text for each, defaulting to English when absent. */\n@Component({\n selector: 'ngx-theme-field',\n standalone: true,\n imports: [FormField, MatButtonToggleModule, MatIcon, FieldSubscript],\n templateUrl: './theme-field.html',\n styleUrl: './theme-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ThemeField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string>>();\n\n protected readonly lightLabel = computed(\n () =>\n this.fieldDef().options?.find((option) => option.value === 'light')?.label ??\n DEFAULT_LIGHT_LABEL,\n );\n protected readonly darkLabel = computed(\n () =>\n this.fieldDef().options?.find((option) => option.value === 'dark')?.label ??\n DEFAULT_DARK_LABEL,\n );\n\n protected readonly labelId: string = `theme-field-label-${nextId++}`;\n}\n","<div class=\"ThemeField-label\" [id]=\"labelId\">\n {{ fieldDef().label }}\n @if (field()().required()) {\n <span aria-hidden=\"true\"> *</span>\n }\n</div>\n<mat-button-toggle-group\n class=\"ThemeField-group\"\n [formField]=\"field()\"\n [attr.aria-labelledby]=\"labelId\"\n>\n <mat-button-toggle value=\"light\" [attr.aria-label]=\"lightLabel()\">\n <mat-icon aria-hidden=\"true\">light_mode</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"dark\" [attr.aria-label]=\"darkLabel()\">\n <mat-icon aria-hidden=\"true\">dark_mode</mat-icon>\n </mat-button-toggle>\n</mat-button-toggle-group>\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\n","import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { MatSlider, MatSliderThumb } from '@angular/material/slider';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\n\nlet nextId: number = 0;\n\n/** Material slider for the range field type, bounded by `fieldDef.min`/`max`/`step`. */\n@Component({\n selector: 'ngx-slider-field',\n standalone: true,\n imports: [FormField, MatSlider, MatSliderThumb, FieldSubscript],\n templateUrl: './slider-field.html',\n styleUrl: './slider-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SliderField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<number>>();\n\n protected readonly labelId: string = `slider-field-label-${nextId++}`;\n}\n","<div class=\"SliderField-label\">\n <span [id]=\"labelId\">\n {{ fieldDef().label }}\n @if (field()().required()) {\n <span aria-hidden=\"true\"> *</span>\n }\n </span>\n <span class=\"SliderField-value\">{{ field()().value() }}</span>\n</div>\n<mat-slider\n class=\"SliderField-slider\"\n discrete\n [min]=\"fieldDef().min ?? 0\"\n [max]=\"fieldDef().max ?? 100\"\n [step]=\"fieldDef().step ?? 1\"\n>\n <input matSliderThumb [formField]=\"field()\" [attr.aria-labelledby]=\"labelId\" />\n</mat-slider>\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\n","import { Injectable } from '@angular/core';\nimport type { Provider } from '@angular/core';\nimport {\n DateAdapter,\n MAT_DATE_FORMATS,\n MAT_NATIVE_DATE_FORMATS,\n NativeDateAdapter,\n} from '@angular/material/core';\n\ntype DatePart = 'day' | 'month' | 'year';\n\nconst NUMERIC_DATE: RegExp = /^(\\d{1,4})\\D+(\\d{1,2})\\D+(\\d{1,4})$/;\n\n/**\n * NativeDateAdapter already *displays* dates in its locale, but its parse() hands typed text to\n * Date.parse(), which always reads 31/03/2024 as month-first. This parses typed numeric dates in\n * the same day/month/year order the locale displays them in.\n */\n@Injectable()\nexport class LocaleDateAdapter extends NativeDateAdapter {\n override parse(value: unknown, parseFormat?: unknown): Date | null {\n const match = typeof value === 'string' ? value.trim().match(NUMERIC_DATE) : null;\n if (!match) {\n return super.parse(value, parseFormat);\n }\n\n const parts: Partial<Record<DatePart, number>> = {};\n this.partOrder().forEach((part, index) => (parts[part] = Number(match[index + 1])));\n\n try {\n return this.createDate(parts.year!, parts.month! - 1, parts.day!);\n } catch {\n return this.invalid();\n }\n }\n\n private partOrder(): DatePart[] {\n return new Intl.DateTimeFormat(this.locale)\n .formatToParts(new Date(2000, 10, 22))\n .map((part) => part.type)\n .filter((type): type is DatePart => type === 'day' || type === 'month' || type === 'year');\n }\n}\n\n/**\n * Gives a component its own DateAdapter instance, so each field can call setLocale() with its own\n * locale without changing the format of every other picker in the app.\n */\nexport function provideLocaleDateAdapter(): Provider[] {\n return [\n { provide: DateAdapter, useClass: LocaleDateAdapter },\n { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS },\n ];\n}\n","export const DEFAULT_DATE_TIME_LOCALE: string = 'en-GB';\n\nexport const INSTANT_DATE_TIME_INVALID_ERROR_LABEL: string = 'Not a valid date and time.';\nexport const BUSINESS_DATE_INVALID_ERROR_LABEL: string = 'Not a valid date.';\nexport const BUSINESS_TIME_INVALID_ERROR_LABEL: string = 'Not a valid time.';\n\n/** Which instant to pick when a wall-clock time happens twice (clocks going back). */\nexport type DateTimeDisambiguation = 'earlier' | 'later';\n\n/**\n * Config for the business-date, business-time and instant-date-time fields.\n * `min`/`max` use the field's own value format: '2024-12-25', '09:00' or '2024-01-01T00:00:00Z'.\n */\nexport interface DateTimeConfig {\n locale?: string; // Display and typing format, Eg 'en-GB' (31/03/2024) or 'en-US'. Defaults to 'en-GB'.\n min?: string; // Earliest allowed value, in the field's value format.\n max?: string; // Latest allowed value, in the field's value format.\n timeZone?: string; // instant-date-time only: IANA zone the user edits in. Defaults to the user's timezone.\n disambiguation?: DateTimeDisambiguation; // instant-date-time only: which occurrence when a wall-clock time happens twice.\n}\n","import { InjectionToken } from '@angular/core';\nimport { DEFAULT_DATE_TIME_LOCALE } from '../constants/date-time.constants';\n\n/** A plain function the app supplies, read fresh on every call — see `NGX_FORMS_LOCALE`. */\nexport type FormsLocaleResolver = () => string;\n\n/**\n * Which locale a date/time field's picker displays and parses in, when its own `FieldDef`\n * doesn't set `dateTimeConfig.locale` — an explicit per-field `locale` always wins over this.\n * Defaults to `DEFAULT_DATE_TIME_LOCALE` ('en-GB'), same as before this token existed, not the\n * browser's own language: unlike `ngx-dates`' `NGX_DATES_LOCALE` (read-only display text), this\n * locale also decides which *typed* day/month order `LocaleDateAdapter.parse()` accepts, so\n * switching it changes user input behaviour, not just wording — an app opts in deliberately:\n *\n * ```ts\n * { provide: NGX_FORMS_LOCALE, useFactory: () => { const translations = inject(TranslationsService); return () => translations.locale(); } }\n * ```\n *\n * A plain function rather than a direct import of `ngx-translations`' `TranslationsService`, so this package\n * stays buildable and publishable on its own — same reasoning as `ngx-dates`' `NGX_DATES_LOCALE`\n * (see root `CLAUDE.md`'s \"Inter-package deps\").\n */\nexport const NGX_FORMS_LOCALE = new InjectionToken<FormsLocaleResolver>('NGX_FORMS_LOCALE', {\n factory: () => () => DEFAULT_DATE_TIME_LOCALE,\n});\n","import { effect } from '@angular/core';\nimport type { Signal } from '@angular/core';\nimport type { FieldState } from '@angular/forms/signals';\nimport type { MatInput } from '@angular/material/input';\n\n/**\n * MatInput only works out its error state (red outline, visible mat-error) from an Angular forms\n * control bound to it. Picker inputs driven by hand have none, so this pushes the field's\n * touched && invalid state into them instead. Call from a constructor (needs an injection context).\n */\nexport function syncMatInputErrorState(\n inputs: Signal<readonly MatInput[]>,\n state: Signal<FieldState<unknown>>,\n): void {\n effect(() => {\n const hasError = state().touched() && state().invalid();\n\n for (const input of inputs()) {\n if (input.errorState !== hasError) {\n input.errorState = hasError;\n input.stateChanges.next();\n }\n }\n });\n}\n","import { Temporal } from 'temporal-polyfill';\nimport type { ValidationError } from '@angular/forms/signals';\nimport { FormFieldType } from '../constants/form-field.constant';\nimport {\n BUSINESS_DATE_INVALID_ERROR_LABEL,\n BUSINESS_TIME_INVALID_ERROR_LABEL,\n INSTANT_DATE_TIME_INVALID_ERROR_LABEL,\n} from '../constants/date-time.constants';\nimport type { FieldDef } from '../interfaces/field-definition';\n\n/** Parses a UTC instant, Eg '2024-03-31T01:30:00Z'. Null instead of throwing for empty/invalid input. */\nexport function parseInstant(value: string | null | undefined): Temporal.Instant | null {\n return tryParse(value, (v) => Temporal.Instant.from(v));\n}\n\n/** Parses a calendar date, Eg '2024-12-25'. Null instead of throwing for empty/invalid input. */\nexport function parsePlainDate(value: string | null | undefined): Temporal.PlainDate | null {\n return tryParse(value, (v) => Temporal.PlainDate.from(v));\n}\n\n/** Parses a time of day, Eg '09:00'. Null instead of throwing for empty/invalid input. */\nexport function parsePlainTime(value: string | null | undefined): Temporal.PlainTime | null {\n return tryParse(value, (v) => Temporal.PlainTime.from(v));\n}\n\ninterface DateTimeRule<T> {\n parse: (value: string | null | undefined) => T | null;\n compare: (a: T, b: T) => number;\n invalidMessage: string;\n}\n\nconst DATE_TIME_RULES: Partial<Record<FormFieldType, DateTimeRule<any>>> = {\n [FormFieldType.INSTANT_DATE_TIME]: {\n parse: parseInstant,\n compare: Temporal.Instant.compare,\n invalidMessage: INSTANT_DATE_TIME_INVALID_ERROR_LABEL,\n },\n [FormFieldType.BUSINESS_DATE]: {\n parse: parsePlainDate,\n compare: Temporal.PlainDate.compare,\n invalidMessage: BUSINESS_DATE_INVALID_ERROR_LABEL,\n },\n [FormFieldType.BUSINESS_TIME]: {\n parse: parsePlainTime,\n compare: Temporal.PlainTime.compare,\n invalidMessage: BUSINESS_TIME_INVALID_ERROR_LABEL,\n },\n};\n\nexport function isDateTimeField(type: FormFieldType): boolean {\n return type in DATE_TIME_RULES;\n}\n\n/** Format and dateTimeConfig min/max check for the date/time field types; null when valid or empty. */\nexport function dateTimeError(value: string | null, fieldDef: FieldDef): ValidationError | null {\n const rule = DATE_TIME_RULES[fieldDef.type];\n if (!rule || !value) {\n return null;\n }\n\n const parsed = rule.parse(value);\n if (!parsed) {\n return { kind: 'invalidDateTime', message: rule.invalidMessage };\n }\n\n const min = fieldDef.dateTimeConfig?.min;\n const parsedMin = rule.parse(min);\n if (parsedMin && rule.compare(parsed, parsedMin) < 0) {\n return { kind: 'minDateTime', message: `${fieldDef.label} cannot be before ${min}` };\n }\n\n const max = fieldDef.dateTimeConfig?.max;\n const parsedMax = rule.parse(max);\n if (parsedMax && rule.compare(parsed, parsedMax) > 0) {\n return { kind: 'maxDateTime', message: `${fieldDef.label} cannot be after ${max}` };\n }\n\n return null;\n}\n\nfunction tryParse<T>(value: string | null | undefined, parse: (value: string) => T): T | null {\n if (!value) {\n return null;\n }\n\n try {\n return parse(value);\n } catch {\n return null;\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n viewChildren,\n} from '@angular/core';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { DateAdapter } from '@angular/material/core';\nimport { MatDatepickerModule } from '@angular/material/datepicker';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInput, MatInputModule } from '@angular/material/input';\nimport { Temporal } from 'temporal-polyfill';\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\nimport { parsePlainDate } from '../../utils/date-time.utils';\n\n/**\n * Calendar date with no timezone, Eg Christmas Day: the form value is a plain 'YYYY-MM-DD' string\n * and means the same day wherever it is read. The display format follows `dateTimeConfig.locale`.\n */\n@Component({\n selector: 'ngx-business-date-field',\n standalone: true,\n imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule],\n providers: [provideLocaleDateAdapter()],\n templateUrl: './business-date-field.html',\n styleUrl: './business-date-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BusinessDateField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string | null>>();\n\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\n\n protected readonly state = computed(() => this.field()());\n protected readonly date = computed(() => toDate(this.state().value()));\n protected readonly minDate = computed(() => toDate(this.fieldDef().dateTimeConfig?.min));\n protected readonly maxDate = computed(() => toDate(this.fieldDef().dateTimeConfig?.max));\n\n private readonly inputs = viewChildren(MatInput);\n\n constructor() {\n syncMatInputErrorState(this.inputs, this.state);\n effect(() =>\n this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || this.resolveLocale()),\n );\n }\n\n protected onDateChange(date: Date | null): void {\n if (!date || isNaN(date.getTime())) {\n this.state().value.set(null);\n return;\n }\n\n this.state().value.set(\n Temporal.PlainDate.from({\n year: date.getFullYear(),\n month: date.getMonth() + 1,\n day: date.getDate(),\n }).toString(),\n );\n }\n}\n\nfunction toDate(value: string | null | undefined): Date | null {\n const plainDate = parsePlainDate(value);\n return plainDate ? new Date(plainDate.year, plainDate.month - 1, plainDate.day) : null;\n}\n","<mat-form-field class=\"BusinessDateField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n <input\n matInput\n [matDatepicker]=\"datepicker\"\n [value]=\"date()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [required]=\"state().required()\"\n [disabled]=\"state().disabled()\"\n (blur)=\"state().markAsTouched()\"\n (dateChange)=\"onDateChange($event.value)\"\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of state().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n viewChildren,\n} from '@angular/core';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { DateAdapter } from '@angular/material/core';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInput, MatInputModule } from '@angular/material/input';\nimport { MatTimepickerModule } from '@angular/material/timepicker';\nimport { Temporal } from 'temporal-polyfill';\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\nimport { parsePlainTime } from '../../utils/date-time.utils';\n\n/**\n * Time of day with no timezone, Eg \"open from 09:00\": the form value is a plain 'HH:mm' string\n * and means the same clock time wherever it is read. The display format follows `dateTimeConfig.locale`.\n */\n@Component({\n selector: 'ngx-business-time-field',\n standalone: true,\n imports: [MatFormFieldModule, MatInputModule, MatTimepickerModule],\n providers: [provideLocaleDateAdapter()],\n templateUrl: './business-time-field.html',\n styleUrl: './business-time-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BusinessTimeField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string | null>>();\n\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\n\n protected readonly state = computed(() => this.field()());\n protected readonly time = computed(() => toDate(this.state().value()));\n protected readonly minTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.min));\n protected readonly maxTime = computed(() => toDate(this.fieldDef().dateTimeConfig?.max));\n\n private readonly inputs = viewChildren(MatInput);\n\n constructor() {\n syncMatInputErrorState(this.inputs, this.state);\n effect(() =>\n this.dateAdapter.setLocale(this.fieldDef().dateTimeConfig?.locale || this.resolveLocale()),\n );\n }\n\n protected onTimeChange(time: Date | null): void {\n if (!time || isNaN(time.getTime())) {\n this.state().value.set(null);\n return;\n }\n\n this.state().value.set(\n Temporal.PlainTime.from({ hour: time.getHours(), minute: time.getMinutes() }).toString({\n smallestUnit: 'minute',\n }),\n );\n }\n}\n\n// The timepicker only reads the hours/minutes of this Date; 1 Jan is used because no timezone changes clocks on it.\nfunction toDate(value: string | null | undefined): Date | null {\n const plainTime = parsePlainTime(value);\n return plainTime ? new Date(2000, 0, 1, plainTime.hour, plainTime.minute) : null;\n}\n","<mat-form-field class=\"BusinessTimeField\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ fieldDef().label }}</mat-label>\n <input\n matInput\n [matTimepicker]=\"timepicker\"\n [matTimepickerMin]=\"minTime()\"\n [matTimepickerMax]=\"maxTime()\"\n [value]=\"time()\"\n [required]=\"state().required()\"\n [disabled]=\"state().disabled()\"\n (blur)=\"state().markAsTouched()\"\n (valueChange)=\"onTimeChange($event)\"\n />\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\n\n @if (fieldDef().hint) {\n <mat-hint>{{ fieldDef().hint }}</mat-hint>\n }\n\n @for (error of state().errors(); track error.kind) {\n <mat-error>{{ error.message }}</mat-error>\n }\n</mat-form-field>\n","import { Injectable } from '@angular/core';\nimport { Temporal } from 'temporal-polyfill';\nimport type { DateTimeDisambiguation } from '../constants/date-time.constants';\nimport { parseInstant } from '../utils/date-time.utils';\n\nexport interface ZonedInstantResult {\n instant: string; // UTC instant, Eg '2024-03-31T01:30:00Z'\n notice: string | null; // Set when the wall-clock time fell in a DST gap or overlap\n}\n\n/**\n * Bridges UTC instants and the JS `Date`s that Angular Material pickers work with.\n *\n * A picker `Date` is treated as a wall-clock value: its local getters (getFullYear, getHours, ...)\n * hold the date and time as seen in `timeZone`, not in the browser's own timezone.\n */\n@Injectable({ providedIn: 'root' })\nexport class ZonedDateTimeService {\n /** UTC instant -> `Date` whose local fields show the wall-clock time in `timeZone`. */\n public toDate(instant: string | null | undefined, timeZone: string): Date | null {\n const zoned = this.toZoned(instant, timeZone);\n if (!zoned) {\n return null;\n }\n\n // Can be off by an hour only inside the browser's own DST gap, where JS Date can't hold that time.\n return new Date(zoned.year, zoned.month - 1, zoned.day, zoned.hour, zoned.minute);\n }\n\n /** Wall-clock date + time in `timeZone` -> UTC instant, resolving DST gaps and overlaps explicitly. */\n public toInstant(\n date: Date,\n time: Date,\n timeZone: string,\n disambiguation: DateTimeDisambiguation = 'earlier',\n ): ZonedInstantResult | null {\n try {\n const plainDateTime = Temporal.PlainDateTime.from({\n year: date.getFullYear(),\n month: date.getMonth() + 1,\n day: date.getDate(),\n hour: time.getHours(),\n minute: time.getMinutes(),\n });\n const earlier = plainDateTime.toZonedDateTime(timeZone, { disambiguation: 'earlier' });\n const later = plainDateTime.toZonedDateTime(timeZone, { disambiguation: 'later' });\n\n if (earlier.equals(later)) {\n return { instant: earlier.toInstant().toString(), notice: null };\n }\n\n const isGap = !earlier.toPlainDateTime().equals(plainDateTime);\n if (isGap) {\n return {\n instant: later.toInstant().toString(),\n notice:\n `${formatWallClock(plainDateTime)} does not exist in ${timeZone} (clocks go forward). ` +\n `Using ${formatWallClock(later.toPlainDateTime())} (UTC${later.offset}) instead.`,\n };\n }\n\n const chosen = disambiguation === 'later' ? later : earlier;\n return {\n instant: chosen.toInstant().toString(),\n notice:\n `${formatWallClock(plainDateTime)} happens twice in ${timeZone} (clocks go back). ` +\n `Using the ${chosen === earlier ? 'first' : 'second'} occurrence (UTC${chosen.offset}).`,\n };\n } catch {\n return null;\n }\n }\n\n /** UTC offset of `instant` in `timeZone`, Eg '+01:00', or null when either is invalid. */\n public offset(instant: string | null | undefined, timeZone: string): string | null {\n return this.toZoned(instant, timeZone)?.offset ?? null;\n }\n\n private toZoned(\n instant: string | null | undefined,\n timeZone: string,\n ): Temporal.ZonedDateTime | null {\n try {\n return parseInstant(instant)?.toZonedDateTimeISO(timeZone) ?? null;\n } catch {\n // invalid timezone id\n return null;\n }\n }\n}\n\nfunction formatWallClock(plainDateTime: Temporal.PlainDateTime): string {\n return plainDateTime.toString({ smallestUnit: 'minute' }).replace('T', ' ');\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n linkedSignal,\n signal,\n viewChildren,\n} from '@angular/core';\nimport type { WritableSignal } from '@angular/core';\nimport type { FieldTree } from '@angular/forms/signals';\nimport { DateAdapter } from '@angular/material/core';\nimport { MatDatepickerModule } from '@angular/material/datepicker';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInput, MatInputModule } from '@angular/material/input';\nimport { MatTimepickerModule } from '@angular/material/timepicker';\nimport { Temporal } from 'temporal-polyfill';\nimport { provideLocaleDateAdapter } from '../../adapters/locale-date-adapter';\nimport { NGX_FORMS_LOCALE } from '../../config/forms-locale.token';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport { syncMatInputErrorState } from '../../utils/mat-input-error-state';\nimport { ZonedDateTimeService } from '../../services/zoned-date-time.service';\nimport { FieldSubscript } from '../../shared/field-subscript/field-subscript';\n\n/**\n * Date and time field whose form value is a UTC instant (YYYY-MM-DDThh:mm:ssZ), edited through the\n * Material datepicker and timepicker as the wall-clock time of `dateTimeConfig.timeZone`.\n * The display format follows `dateTimeConfig.locale`, not the browser's.\n */\n@Component({\n selector: 'ngx-instant-date-time-field',\n standalone: true,\n imports: [\n MatFormFieldModule,\n MatInputModule,\n MatDatepickerModule,\n MatTimepickerModule,\n FieldSubscript,\n ],\n providers: [provideLocaleDateAdapter()],\n templateUrl: './instant-date-time-field.html',\n styleUrl: './instant-date-time-field.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class InstantDateTimeField {\n public readonly fieldDef = input.required<FieldDef>();\n public readonly field = input.required<FieldTree<string | null>>();\n\n private readonly zonedDateTime = inject(ZonedDateTimeService);\n private readonly dateAdapter = inject<DateAdapter<Date>>(DateAdapter);\n private readonly resolveLocale = inject(NGX_FORMS_LOCALE);\n\n /** Explains how a DST gap or overlap was resolved for the last value picked by the user. */\n protected readonly notice: WritableSignal<string | null> = signal(null);\n\n protected readonly state = computed(() => this.field()());\n protected readonly config = computed(() => this.fieldDef().dateTimeConfig);\n protected readonly timeZone = computed(\n () => this.config()?.timeZone || Temporal.Now.timeZoneId(),\n );\n protected readonly offset = computed(() =>\n this.zonedDateTime.offset(this.state().value(), this.timeZone()),\n );\n protected readonly minDate = computed(() =>\n this.zonedDateTime.toDate(this.config()?.min, this.timeZone()),\n );\n protected readonly maxDate = computed(() =>\n this.zonedDateTime.toDate(this.config()?.max, this.timeZone()),\n );\n\n // Only a change of the actual wall-clock time counts, so '' -> null (still empty) keeps a half-filled pick.\n private readonly wallClock = computed(\n () => this.zonedDateTime.toDate(this.state().value(), this.timeZone()),\n { equal: (a, b) => a?.getTime() === b?.getTime() },\n );\n\n // Both pickers follow the bound value, but can hold a half-filled pick until both parts are set.\n protected readonly date = linkedSignal(() => this.wallClock());\n protected readonly time = linkedSignal(() => this.wallClock());\n\n private readonly inputs = viewChildren(MatInput);\n\n constructor() {\n syncMatInputErrorState(this.inputs, this.state);\n effect(() => this.dateAdapter.setLocale(this.config()?.locale || this.resolveLocale()));\n }\n\n protected onDateChange(date: Date | null): void {\n if (sameParts(date, this.date(), (d) => [d.getFullYear(), d.getMonth(), d.getDate()])) {\n return;\n }\n\n this.date.set(date);\n this.commit();\n }\n\n // The timepicker re-emits values we set on it (Eg on blur); ignoring those keeps a DST notice visible.\n protected onTimeChange(time: Date | null): void {\n if (sameParts(time, this.time(), (t) => [t.getHours(), t.getMinutes()])) {\n return;\n }\n\n this.time.set(time);\n this.commit();\n }\n\n private commit(): void {\n this.notice.set(null);\n\n const date = this.date();\n const time = this.time();\n const value = this.state().value;\n\n if (!isValidDate(date) || !isValidDate(time)) {\n if (value() !== null) {\n value.set(null);\n }\n return;\n }\n\n const result = this.zonedDateTime.toInstant(\n date,\n time,\n this.timeZone(),\n this.config()?.disambiguation,\n );\n value.set(result?.instant ?? null);\n this.notice.set(result?.notice ?? null);\n }\n}\n\nfunction isValidDate(value: Date | null): value is Date {\n return value instanceof Date && !isNaN(value.getTime());\n}\n\nfunction sameParts(a: Date | null, b: Date | null, parts: (date: Date) => number[]): boolean {\n if (!isValidDate(a) || !isValidDate(b)) {\n return a === b;\n }\n\n const bParts = parts(b);\n return parts(a).every((part, index) => part === bParts[index]);\n}\n","<div class=\"InstantDateTimeField-label\">\n {{ fieldDef().label }}\n @if (state().required()) {\n <span aria-hidden=\"true\"> *</span>\n }\n</div>\n\n<div class=\"InstantDateTimeField-row\">\n <mat-form-field class=\"InstantDateTimeField-date\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>Date</mat-label>\n <input\n matInput\n [matDatepicker]=\"datepicker\"\n [value]=\"date()\"\n [min]=\"minDate()\"\n [max]=\"maxDate()\"\n [disabled]=\"state().disabled()\"\n (blur)=\"state().markAsTouched()\"\n (dateChange)=\"onDateChange($event.value)\"\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"datepicker\" />\n <mat-datepicker #datepicker (closed)=\"state().markAsTouched()\" />\n </mat-form-field>\n\n <mat-form-field class=\"InstantDateTimeField-time\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>Time</mat-label>\n <input\n matInput\n [matTimepicker]=\"timepicker\"\n [value]=\"time()\"\n [disabled]=\"state().disabled()\"\n (blur)=\"state().markAsTouched()\"\n (valueChange)=\"onTimeChange($event)\"\n />\n <mat-timepicker-toggle matIconSuffix [for]=\"timepicker\" />\n <mat-timepicker #timepicker (closed)=\"state().markAsTouched()\" />\n </mat-form-field>\n</div>\n\n<div class=\"InstantDateTimeField-zone\">\n {{ timeZone() }}\n @if (offset()) {\n (UTC{{ offset() }})\n }\n @if (state().value()) {\n · stored as {{ state().value() }}\n }\n</div>\n\n@if (notice()) {\n <div class=\"InstantDateTimeField-notice\">{{ notice() }}</div>\n}\n\n<ngx-field-subscript [field]=\"field()\" [hint]=\"fieldDef().hint\" />\n","import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\nimport type { InputSignal } from '@angular/core';\nimport type { FieldState, FieldTree } from '@angular/forms/signals';\nimport { MatButton } from '@angular/material/button';\nimport { TextField } from '../text-field/text-field';\nimport { TextareaField } from '../textarea-field/textarea-field';\nimport { CheckboxField } from '../checkbox-field/checkbox-field';\nimport { RadioField } from '../radio-field/radio-field';\nimport { SelectField } from '../select-field/select-field';\nimport { ChipsField } from '../chips-field/chips-field';\nimport { ThemeField } from '../theme-field/theme-field';\nimport { SliderField } from '../slider-field/slider-field';\nimport { BusinessDateField } from '../business-date-field/business-date-field';\nimport { BusinessTimeField } from '../business-time-field/business-time-field';\nimport { InstantDateTimeField } from '../instant-date-time-field/instant-date-time-field';\nimport type { FieldDef } from '../../interfaces/field-definition';\nimport type { BaseSchema } from '../../interfaces/base.schema';\n\n/**\n * Renders one Material field component per FieldDef, then right-aligned actions: a text\n * secondary action (\"Clear\" by default — label it \"Cancel\" when it leaves the form) and the filled\n * primary one (\"Save\"). Name both after what they do.\n */\n@Component({\n selector: 'ngx-dynamic-form',\n standalone: true,\n imports: [\n MatButton,\n TextField,\n TextareaField,\n CheckboxField,\n RadioField,\n SelectField,\n ChipsField,\n ThemeField,\n SliderField,\n BusinessDateField,\n BusinessTimeField,\n InstantDateTimeField,\n ],\n templateUrl: './dynamic-form.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrl: './dynamic-form.scss',\n})\nexport class DynamicForm<T extends BaseSchema = BaseSchema> {\n public metaInfo: InputSignal<FieldDef[]> = input.required<FieldDef[]>();\n public dynamicForm: InputSignal<FieldTree<T>> = input.required<FieldTree<T>>();\n\n /** Filled primary action. */\n public readonly submitLabel = input('Save');\n /** Text secondary action; emits `onFormClear`. */\n public readonly clearLabel = input('Clear');\n\n public onFormSubmit = output<void>();\n public onFormClear = output<void>();\n\n protected handleSubmit(): void {\n const fieldTree: FieldTree<unknown> = this.dynamicForm();\n const fieldState: FieldState<unknown> = fieldTree();\n\n if (fieldState.valid()) {\n this.onFormSubmit.emit();\n }\n }\n\n protected clearForm(): void {\n this.onFormClear.emit();\n }\n}\n","<div class=\"DynamicForm\">\n @for (fieldDef of metaInfo(); track fieldDef.name) {\n @let field = $any(dynamicForm())[fieldDef.name];\n\n @if (!fieldDef.hidden) {\n <div class=\"DynamicForm-field\" [style.--ngx-field-max-width]=\"fieldDef.maxWidth\">\n @switch (fieldDef.type) {\n @case ('text') {\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('email') {\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('password') {\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('search') {\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('number') {\n <ngx-text-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('textarea') {\n <ngx-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('code') {\n <ngx-textarea-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('checkbox') {\n <ngx-checkbox-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('radio') {\n <ngx-radio-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('select') {\n <ngx-select-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('chips') {\n <ngx-chips-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('theme') {\n <ngx-theme-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('range') {\n <ngx-slider-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('business-date') {\n <ngx-business-date-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('business-time') {\n <ngx-business-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n @case ('instant-date-time') {\n <ngx-instant-date-time-field [fieldDef]=\"fieldDef\" [field]=\"field\" />\n }\n }\n </div>\n }\n }\n\n <div class=\"DynamicForm-actions\">\n <button matButton type=\"button\" (click)=\"clearForm()\">{{ clearLabel() }}</button>\n <button\n matButton=\"filled\"\n type=\"button\"\n [disabled]=\"dynamicForm()().invalid()\"\n (click)=\"handleSubmit()\"\n >\n {{ submitLabel() }}\n </button>\n </div>\n</div>\n","import type { FieldDef } from '../interfaces/field-definition';\nimport {\n disabled,\n email,\n max,\n maxLength,\n min,\n minLength,\n pattern,\n required,\n schema,\n validate,\n} from '@angular/forms/signals';\nimport type { Schema } from '@angular/forms/signals';\nimport { FormFieldType } from '../constants/form-field.constant';\nimport type { BaseSchema, SchemaConfig } from '../interfaces/base.schema';\nimport { dateTimeError, isDateTimeField } from './date-time.utils';\n\nexport function defineSchema<T extends BaseSchema>(config: SchemaConfig<T>): SchemaConfig<T> {\n return config;\n}\n\nexport function createEmptyEntity<T extends BaseSchema>(\n schemaType: T['schemaType'],\n defaults: Omit<T, 'id' | 'schemaType'>,\n): T {\n return {\n id: '',\n schemaType,\n ...defaults,\n } as T;\n}\n\n/** Turns field definitions into Signals Forms rules. The model can be any object, not just a BaseSchema. */\nexport function toSchema<T>(meta: FieldDef[]): Schema<T> {\n return schema<T>((path: any) => {\n for (const fieldDef of meta) {\n const property: string = fieldDef.name;\n const fieldPath: any = (path as any)[property];\n\n if (!fieldPath) {\n continue;\n }\n\n if (fieldDef.disabled) {\n disabled(fieldPath);\n }\n if (fieldDef.required) {\n required(fieldPath, { message: `${fieldDef.label} is required` });\n }\n if (typeof fieldDef.minLength !== 'undefined') {\n minLength(fieldPath, fieldDef.minLength, {\n message: `${fieldDef.label} must be at least ${fieldDef.minLength} characters`,\n });\n }\n if (typeof fieldDef.maxLength !== 'undefined') {\n maxLength(fieldPath, fieldDef.maxLength, {\n message: `${fieldDef.label} cannot exceed ${fieldDef.maxLength} characters`,\n });\n }\n if (fieldDef.type === FormFieldType.EMAIL) {\n email(fieldPath, { message: `${fieldDef.label} must be a valid email address` });\n }\n if (typeof fieldDef.pattern !== 'undefined') {\n pattern(fieldPath, toRegExp(fieldDef.pattern), {\n message: fieldDef.patternMessage ?? `${fieldDef.label} is not in the expected format`,\n });\n }\n if (typeof fieldDef.min !== 'undefined') {\n min(fieldPath, fieldDef.min, {\n message: `${fieldDef.label} must be at least ${fieldDef.min}`,\n });\n }\n if (typeof fieldDef.max !== 'undefined') {\n max(fieldPath, fieldDef.max, {\n message: `${fieldDef.label} cannot exceed ${fieldDef.max}`,\n });\n }\n\n if (isDateTimeField(fieldDef.type)) {\n validate(fieldPath, (ctx: any) => dateTimeError(ctx.value() as string | null, fieldDef));\n }\n }\n });\n}\n\n// A string pattern must match the whole value, like HTML's `pattern` attribute and Validators.pattern;\n// a RegExp is used as given, so its author controls anchoring.\nfunction toRegExp(value: RegExp | string): RegExp {\n return value instanceof RegExp ? value : new RegExp(`^(?:${value})$`);\n}\n","import { FormFieldType } from '../constants/form-field.constant';\nimport type { DateTimeConfig } from '../constants/date-time.constants';\nimport type { BaseSchema, SchemaConfig } from '../interfaces/base.schema';\nimport type { FieldDef, FieldOption } from '../interfaces/field-definition';\nimport { createEmptyEntity } from '../utils/dynamic-form.utils';\n\n/** A property of the schema that can be a form field. */\nexport type FieldName<T> = Exclude<Extract<keyof T, string>, 'schemaType'>;\n\n/** Everything on a FieldDef except what the builder method already sets. */\nexport type FieldOptions = Omit<FieldDef, 'name' | 'type' | 'label' | 'options' | 'dateTimeConfig'>;\n\n/** FieldOptions plus the dateTimeConfig for the business-date, business-time and instant-date-time fields. */\nexport type DateTimeFieldOptions = FieldOptions & { dateTimeConfig?: DateTimeConfig };\n\n/**\n * Fluent, type-checked way to build a SchemaConfig for DynamicForm. Field names are checked against\n * the schema, so a typo or renamed property fails at compile time.\n *\n * @example\n * const config = formConfig<FlightSchema>('flight')\n * .text('from', 'Departure City', { required: true, minLength: 3 })\n * .instantDateTime('date', 'Departure', { required: true, dateTimeConfig: { timeZone: 'Europe/London' } })\n * .checkbox('delayed', 'Delayed')\n * .build({ from: '', date: '', delayed: false });\n */\nexport class FormConfigBuilder<T extends BaseSchema> {\n private readonly fieldDefs: FieldDef[] = [];\n\n constructor(private readonly schemaType: T['schemaType']) {}\n\n public text(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.TEXT, name, label, options);\n }\n\n /** Text input with the email keyboard/autofill and a valid-email check. */\n public email(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.EMAIL, name, label, options);\n }\n\n public password(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.PASSWORD, name, label, options);\n }\n\n public search(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.SEARCH, name, label, options);\n }\n\n public number(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.NUMBER, name, label, options);\n }\n\n public textarea(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.TEXTAREA, name, label, options);\n }\n\n public code(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.CODE, name, label, options);\n }\n\n public checkbox(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.CHECKBOX, name, label, options);\n }\n\n /** Slider bounded by `options.min`/`max`/`step` (defaults 0-100, step 1). */\n public range(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.RANGE, name, label, options);\n }\n\n public radio(\n name: FieldName<T>,\n label: string,\n choices: FieldOption[],\n options?: FieldOptions,\n ): this {\n return this.add(FormFieldType.RADIO, name, label, { ...options, options: choices });\n }\n\n public select(\n name: FieldName<T>,\n label: string,\n choices: FieldOption[],\n options?: FieldOptions,\n ): this {\n return this.add(FormFieldType.SELECT, name, label, { ...options, options: choices });\n }\n\n /** Freeform list of tokens (Eg keywords), typed one at a time. */\n public chips(name: FieldName<T>, label: string, options?: FieldOptions): this {\n return this.add(FormFieldType.CHIPS, name, label, options);\n }\n\n /** Fixed 'light'/'dark' choice, shown as a sun/moon icon toggle pair. `choices` only supplies\n * each value's label text (defaults to English 'Light'/'Dark') — the values themselves are\n * always 'light'/'dark', each tied to its own icon, so there's nothing else to choose here. */\n public theme(\n name: FieldName<T>,\n label: string,\n choices?: FieldOption[],\n options?: FieldOptions,\n ): this {\n return this.add(FormFieldType.THEME, name, label, { ...options, options: choices });\n }\n\n /** Calendar date with no timezone, stored as 'YYYY-MM-DD'. */\n public businessDate(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\n return this.add(FormFieldType.BUSINESS_DATE, name, label, options);\n }\n\n /** Time of day with no timezone, stored as 'HH:mm'. */\n public businessTime(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\n return this.add(FormFieldType.BUSINESS_TIME, name, label, options);\n }\n\n /** Exact moment, stored as a UTC instant and edited in `dateTimeConfig.timeZone`. */\n public instantDateTime(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this {\n return this.add(FormFieldType.INSTANT_DATE_TIME, name, label, options);\n }\n\n /** A field that is part of the model and its validation, but never rendered. */\n public hidden(name: FieldName<T>, options?: FieldOptions): this {\n return this.add(FormFieldType.TEXT, name, name, { ...options, hidden: true });\n }\n\n /** The field definitions added so far, Eg to pass to `toSchema()` or DynamicForm's metaInfo. */\n public fields(): FieldDef[] {\n return [...this.fieldDefs];\n }\n\n /** The full config for DynamicForm; `id` and `schemaType` are filled in on the initial value. */\n public build(initialValue: Omit<T, 'id' | 'schemaType'>): SchemaConfig<T> {\n return {\n schemaType: this.schemaType,\n fields: this.fields(),\n initialValue: createEmptyEntity<T>(this.schemaType, initialValue),\n };\n }\n\n private add(type: FormFieldType, name: string, label: string, options?: Partial<FieldDef>): this {\n this.fieldDefs.push({ ...options, name, type, label });\n return this;\n }\n}\n\n/** Starts a FormConfigBuilder for schema `T`. */\nexport function formConfig<T extends BaseSchema>(\n schemaType: T['schemaType'],\n): FormConfigBuilder<T> {\n return new FormConfigBuilder<T>(schemaType);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wiltech-labs/ngx-forms",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Shared Angular forms library — form builders, validators, and utility services for common form patterns.",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -13,6 +13,7 @@ export declare enum FormFieldType {
13
13
  RANGE = "range",
14
14
  SELECT = "select",
15
15
  CHIPS = "chips",
16
+ THEME = "theme",
16
17
  TEXTAREA = "textarea",
17
18
  CODE = "code",
18
19
  BUSINESS_DATE = "business-date",
@@ -240,6 +241,35 @@ export declare class ChipsField {
240
241
  };
241
242
  }, {}, never, never, true, never>;
242
243
  }
244
+ /** Material icon toggle group for the theme field type: a fixed choice between `'light'` and
245
+ * `'dark'`, shown as a sun/moon icon pair instead of a dropdown or radio list.
246
+ * `MatButtonToggleGroup` is a `ControlValueAccessor`, same as `MatRadioGroup`/`MatSelect`, so
247
+ * `[formField]` works on it directly — no hand-written value sync needed.
248
+ *
249
+ * Labels come from `fieldDef.options` — same mechanism `RadioField`/`SelectField` already use, not
250
+ * a separate config or token — matched by value since the two values and their icons are fixed
251
+ * (`'light'`/`'dark'` only, each always paired with the same sun/moon icon); `options` only ever
252
+ * supplies the label text for each, defaulting to English when absent. */
253
+ export declare class ThemeField {
254
+ readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
255
+ readonly field: import("@angular/core").InputSignal<FieldTree<string>>;
256
+ protected readonly lightLabel: import("@angular/core").Signal<string>;
257
+ protected readonly darkLabel: import("@angular/core").Signal<string>;
258
+ protected readonly labelId: string;
259
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThemeField, never>;
260
+ static ɵcmp: i0.ɵɵComponentDeclaration<ThemeField, "ngx-theme-field", never, {
261
+ "fieldDef": {
262
+ "alias": "fieldDef";
263
+ "required": true;
264
+ "isSignal": true;
265
+ };
266
+ "field": {
267
+ "alias": "field";
268
+ "required": true;
269
+ "isSignal": true;
270
+ };
271
+ }, {}, never, never, true, never>;
272
+ }
243
273
  /** Material slider for the range field type, bounded by `fieldDef.min`/`max`/`step`. */
244
274
  export declare class SliderField {
245
275
  readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
@@ -398,6 +428,10 @@ export declare class FormConfigBuilder<T extends BaseSchema> {
398
428
  select(name: FieldName<T>, label: string, choices: FieldOption[], options?: FieldOptions): this;
399
429
  /** Freeform list of tokens (Eg keywords), typed one at a time. */
400
430
  chips(name: FieldName<T>, label: string, options?: FieldOptions): this;
431
+ /** Fixed 'light'/'dark' choice, shown as a sun/moon icon toggle pair. `choices` only supplies
432
+ * each value's label text (defaults to English 'Light'/'Dark') — the values themselves are
433
+ * always 'light'/'dark', each tied to its own icon, so there's nothing else to choose here. */
434
+ theme(name: FieldName<T>, label: string, choices?: FieldOption[], options?: FieldOptions): this;
401
435
  /** Calendar date with no timezone, stored as 'YYYY-MM-DD'. */
402
436
  businessDate(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this;
403
437
  /** Time of day with no timezone, stored as 'HH:mm'. */