ngwr 14.1.0 → 14.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -22
- package/command-palette/styles/_index.scss +17 -0
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +4 -2
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +2 -2
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +17 -5
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +30 -1
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +429 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-cs.mjs +399 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-de.mjs +418 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-en.mjs +23 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +399 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-fr.mjs +423 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-he.mjs +422 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-hi.mjs +399 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-id.mjs +399 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-it.mjs +418 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ja.mjs +403 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ko.mjs +411 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-nl.mjs +415 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-pl.mjs +425 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-pt.mjs +408 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ru.mjs +11 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +399 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-tr.mjs +423 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-uk.mjs +420 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-vi.mjs +416 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs +407 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-zh.mjs +398 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox.mjs +2 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +24 -4
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +75 -10
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +185 -0
- package/fesm2022/ngwr-schema-form.mjs.map +1 -0
- package/fesm2022/ngwr-select.mjs +2 -2
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-validators.mjs +8 -1
- package/fesm2022/ngwr-validators.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/i18n/ar.json +389 -0
- package/i18n/cs.json +389 -0
- package/i18n/de.json +389 -0
- package/i18n/en.json +10 -2
- package/i18n/es.json +389 -0
- package/i18n/fr.json +389 -0
- package/i18n/he.json +389 -0
- package/i18n/hi.json +389 -0
- package/i18n/id.json +389 -0
- package/i18n/it.json +389 -0
- package/i18n/ja.json +389 -0
- package/i18n/ko.json +389 -0
- package/i18n/nl.json +389 -0
- package/i18n/pl.json +389 -0
- package/i18n/pt.json +389 -0
- package/i18n/ru.json +10 -2
- package/i18n/sv.json +389 -0
- package/i18n/tr.json +389 -0
- package/i18n/uk.json +389 -0
- package/i18n/vi.json +389 -0
- package/i18n/zh-TW.json +389 -0
- package/i18n/zh.json +389 -0
- package/llms-full.txt +87 -1
- package/llms.txt +1 -1
- package/package.json +89 -7
- package/schema-form/styles/_index.scss +15 -0
- package/schematics/migrations/v9/index.js +11 -3
- package/schematics/use/symbol-map.json +1 -0
- package/skills/ngwr/SKILL.md +1 -1
- package/skills/ngwr/references/catalog.md +21 -0
- package/styles.scss +1 -0
- package/theme/styles/_focus.scss +23 -2
- package/types/ngwr-calendar.d.ts +2 -0
- package/types/ngwr-command-palette.d.ts +1 -1
- package/types/ngwr-event-calendar.d.ts +5 -0
- package/types/ngwr-form.d.ts +88 -2
- package/types/ngwr-i18n-ar.d.ts +6 -0
- package/types/ngwr-i18n-cs.d.ts +6 -0
- package/types/ngwr-i18n-de.d.ts +6 -0
- package/types/ngwr-i18n-es.d.ts +6 -0
- package/types/ngwr-i18n-fr.d.ts +6 -0
- package/types/ngwr-i18n-he.d.ts +6 -0
- package/types/ngwr-i18n-hi.d.ts +6 -0
- package/types/ngwr-i18n-id.d.ts +6 -0
- package/types/ngwr-i18n-it.d.ts +6 -0
- package/types/ngwr-i18n-ja.d.ts +6 -0
- package/types/ngwr-i18n-ko.d.ts +6 -0
- package/types/ngwr-i18n-nl.d.ts +6 -0
- package/types/ngwr-i18n-pl.d.ts +6 -0
- package/types/ngwr-i18n-pt.d.ts +6 -0
- package/types/ngwr-i18n-sv.d.ts +6 -0
- package/types/ngwr-i18n-tr.d.ts +6 -0
- package/types/ngwr-i18n-uk.d.ts +6 -0
- package/types/ngwr-i18n-vi.d.ts +6 -0
- package/types/ngwr-i18n-zh-TW.d.ts +6 -0
- package/types/ngwr-i18n-zh.d.ts +6 -0
- package/types/ngwr-line-chart.d.ts +15 -0
- package/types/ngwr-pipes.d.ts +45 -4
- package/types/ngwr-schema-form.d.ts +90 -0
- package/types/ngwr-version.d.ts +1 -1
package/fesm2022/ngwr-form.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { input, computed, ViewEncapsulation, Component, InjectionToken, makeEnvi
|
|
|
4
4
|
import { NgControl } from '@angular/forms';
|
|
5
5
|
import { EMPTY } from 'rxjs';
|
|
6
6
|
import { useI18nText, WrI18n } from 'ngwr/i18n';
|
|
7
|
+
import { createMetadataKey } from '@angular/forms/signals';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @license
|
|
@@ -478,9 +479,37 @@ function useFormFieldAria(options) {
|
|
|
478
479
|
};
|
|
479
480
|
}
|
|
480
481
|
|
|
482
|
+
/**
|
|
483
|
+
* @license
|
|
484
|
+
*
|
|
485
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
486
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
487
|
+
*/
|
|
488
|
+
/**
|
|
489
|
+
* The metadata key `<wr-schema-form>` reads.
|
|
490
|
+
*
|
|
491
|
+
* ```ts
|
|
492
|
+
* const userSchema = schema<User>(path => {
|
|
493
|
+
* required(path.email);
|
|
494
|
+
* email(path.email);
|
|
495
|
+
* metadata(path.email, WR_FIELD, () => ({ kind: 'input', type: 'email', label: 'Work email' }));
|
|
496
|
+
* metadata(path.role, WR_FIELD, () => ({ kind: 'select', options: ROLES }));
|
|
497
|
+
* });
|
|
498
|
+
* ```
|
|
499
|
+
*
|
|
500
|
+
* A field with no `WR_FIELD` metadata is not an error and is not guessed at —
|
|
501
|
+
* `<wr-schema-form>` skips it, so a schema can describe more than one screen shows.
|
|
502
|
+
*/
|
|
503
|
+
const WR_FIELD = createMetadataKey();
|
|
504
|
+
/** `workEmail` -> `Work email`. The fallback label, and only ever a fallback. */
|
|
505
|
+
function wrFieldLabel(key) {
|
|
506
|
+
const spaced = key.replace(/([a-z\d])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ');
|
|
507
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
|
|
508
|
+
}
|
|
509
|
+
|
|
481
510
|
/**
|
|
482
511
|
* Generated bundle index. Do not edit.
|
|
483
512
|
*/
|
|
484
513
|
|
|
485
|
-
export { WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, WR_FORM_FIELD, WrFormError, WrFormField, WrFormItem, provideWrFormErrors, useFormFieldAria };
|
|
514
|
+
export { WR_FIELD, WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, WR_FORM_FIELD, WrFormError, WrFormField, WrFormItem, provideWrFormErrors, useFormFieldAria, wrFieldLabel };
|
|
486
515
|
//# sourceMappingURL=ngwr-form.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-form.mjs","sources":["../../../projects/lib/form/form-item.ts","../../../projects/lib/form/form-errors.ts","../../../projects/lib/form/tokens.ts","../../../projects/lib/form/form-field.ts","../../../projects/lib/form/form-field.html","../../../projects/lib/form/field-aria.ts","../../../projects/lib/form/ngwr-form.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Wraps a label + control + error message into a single field row.\n *\n * Toggle `hasError` to apply error styling to the projected label and\n * any descendant input / textarea / checkbox.\n *\n * @example\n * ```html\n * <wr-form-item [hasError]=\"form.controls.email.invalid\">\n * <label>Email</label>\n * <input wrInput formControlName=\"email\" />\n * <wr-form-error>Invalid email</wr-form-error>\n * </wr-form-item>\n * ```\n *\n * @see https://ngwr.dev/reference/components/form\n */\n@Component({\n selector: 'wr-form-item',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrFormItem {\n /**\n * When `true`, applies error coloring to the projected label and inputs.\n *\n * @default false\n */\n readonly hasError = input(false, { transform: coerceBooleanProperty });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-form-item'];\n if (this.hasError()) parts.push('wr-form-item--error');\n return parts.join(' ');\n });\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\n\n/** Pull a number out of a validator payload without trusting its shape. */\nfunction num(error: unknown, field: string): string {\n if (error && typeof error === 'object' && field in error) {\n const value = (error as Record<string, unknown>)[field];\n if (typeof value === 'number' || typeof value === 'string') return String(value);\n }\n return '';\n}\n\n/** What a message function is handed to build its sentence. */\nexport interface WrFormErrorContext {\n /** Validator key (classic forms) or Signal Forms `kind` that produced the error. */\n readonly key: string;\n /**\n * The validator's own payload — `{ requiredLength, actualLength }` for\n * `minlength`, `{ min }` for `wrMinDate`, and so on. `true` for the\n * flag-shaped validators, which carry nothing.\n */\n readonly error: unknown;\n /** The surrounding field's `label`, so a message can name the field. */\n readonly label: string;\n}\n\n/** A message, or a function that builds one from the validator's payload. */\nexport type WrFormErrorMessage = string | ((ctx: WrFormErrorContext) => string);\n\n/** Validator key → message. Keys are matched exactly against `control.errors`. */\nexport type WrFormErrorMessages = Readonly<Record<string, WrFormErrorMessage>>;\n\n/**\n * App-wide validation copy. Empty by default; `<wr-form-field>` falls through\n * to the `ngwr/i18n` catalog and then to a built-in English sentence, so a\n * form shows a usable message with no configuration at all.\n */\nexport const WR_FORM_ERRORS = new InjectionToken<WrFormErrorMessages>('WR_FORM_ERRORS', {\n providedIn: 'root',\n factory: () => ({}),\n});\n\n/**\n * Register validation messages for the whole app.\n *\n * Only the keys you name are overridden — everything else keeps resolving\n * through the i18n catalog, so this composes with `provideWrI18n()` rather than\n * replacing it. A projected `<wr-form-error key=\"…\">` still wins over both:\n * per-field copy beats app-wide copy.\n *\n * @example\n * ```ts\n * bootstrapApplication(App, {\n * providers: [\n * provideWrFormErrors({\n * required: 'Please fill this in.',\n * minlength: ({ error }) => `At least ${(error as { requiredLength: number }).requiredLength} characters.`,\n * }),\n * ],\n * });\n * ```\n */\nexport function provideWrFormErrors(messages: WrFormErrorMessages = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: WR_FORM_ERRORS, useValue: messages }]);\n}\n\n/**\n * Last-resort English, used when no app catalog and no i18n catalog answer.\n *\n * These exist so that a form with zero configuration still says something true\n * rather than rendering an empty error block. Every key here also ships as a\n * `validation.*` entry in `ngwr/i18n/{en,ru}`, which is what a localized app\n * actually reads.\n */\nexport const WR_FORM_ERROR_FALLBACKS: WrFormErrorMessages = {\n // Angular built-ins.\n required: 'This field is required.',\n requiredTrue: 'This field must be checked.',\n email: 'Enter a valid email address.',\n minlength: ({ error }) => `Enter at least ${num(error, 'requiredLength')} characters.`,\n maxlength: ({ error }) => `Enter at most ${num(error, 'requiredLength')} characters.`,\n min: ({ error }) => `Enter ${num(error, 'min')} or more.`,\n max: ({ error }) => `Enter ${num(error, 'max')} or less.`,\n pattern: 'This value is not in the expected format.',\n\n // WrValidators.\n // Not \"cannot be blank\": the validator PASSES on an empty value and fails on\n // any value that holds whitespace, so the blank wording described the one case\n // that never reaches this message — over a field reading `Ada Lovelace`.\n noWhitespace: 'This value cannot contain spaces.',\n hexColor: 'Enter a hex colour, e.g. #1a2b3c.',\n url: 'Enter a valid URL.',\n cardNumber: 'Enter a valid card number.',\n cvc: ({ error }) => `Enter the ${num(error, 'length')}-digit security code.`,\n iban: 'Enter a valid IBAN.',\n match: 'The two values do not match.',\n matchFields: 'These fields do not match.',\n oneOf: 'Choose one of the allowed values.',\n minDate: 'Choose a later date.',\n maxDate: 'Choose an earlier date.',\n};\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * What a projected control can read from its surrounding `<wr-form-field>`.\n *\n * The field renders `<label [for]>` before it can see what was projected into\n * it, so the id has to travel the other way: the control adopts the id the\n * label already points at. Doing it through DI keeps it a render-time binding,\n * which is what SSR needs — stamping the id from `afterNextRender` would leave\n * every prerendered page with a label pointing at nothing.\n */\nexport interface WrFormFieldContext {\n /** Id the field's `<label for>` points at. */\n readonly controlId: Signal<string>;\n\n /**\n * The reverse direction, for the one case the paragraph above does not cover: a\n * projected control that already carries its own `id` keeps it, and the label has\n * to follow, or `for` names an element that does not exist and the field ends up\n * with no label at all. Called during the control's construction, so the label's\n * binding still resolves in the same render pass.\n */\n adoptControlId(id: string): void;\n\n /**\n * Validator keys currently in error, once the control is touched or dirty.\n * Empty when the field is valid or has not been interacted with.\n */\n readonly errorKeys: Signal<readonly string[]>;\n\n /** Id of the element listing the visible messages, or `null` when there are none. */\n readonly describedBy: Signal<string | null>;\n\n /**\n * Id of the field's hint, or `null` when it is showing none — including while\n * an error has replaced it, since the two never render together and an\n * `aria-describedby` naming an absent element is an author error.\n *\n * Separate from {@link describedBy} rather than folded into it because the two\n * carry different weight: a control keyed `aria-invalid` on \"the field is\n * describing me\" would announce itself invalid for a plain hint. Compose the\n * pair with `useFormFieldAria()` instead of reading either one directly.\n *\n * Optional so an app that provides its own `WR_FORM_FIELD` keeps compiling; a\n * field without it simply describes nothing but its errors.\n */\n readonly hintId?: Signal<string | null>;\n}\n\n/** Present only inside a `<wr-form-field>`; inject with `{ optional: true }`. */\nexport const WR_FORM_FIELD = new InjectionToken<WrFormFieldContext>('WR_FORM_FIELD');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n DestroyRef,\n ViewEncapsulation,\n computed,\n contentChild,\n contentChildren,\n effect,\n forwardRef,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { NgControl } from '@angular/forms';\n\nimport { EMPTY, type Subscription } from 'rxjs';\n\nimport { WrI18n, useI18nText } from 'ngwr/i18n';\n\nimport { WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, type WrFormErrorMessage } from './form-errors';\nimport { WR_FORM_FIELD, type WrFormFieldContext } from './tokens';\n\nlet uid = 0;\n\n/** A message is either literal text or a function over the validator's payload. */\nfunction render(message: WrFormErrorMessage, key: string, error: unknown, label: string): string {\n return typeof message === 'function' ? message({ key, error, label }) : message;\n}\n\n/** Validator payloads are plain objects; anything else interpolates nothing. */\nfunction toParams(error: unknown): Record<string, unknown> | undefined {\n return error && typeof error === 'object' ? (error as Record<string, unknown>) : undefined;\n}\n\n/**\n * One error message tied to a validator key. Renders only when the parent\n * form-field has a matching error in `control.errors`, and only once the\n * control is touched or dirty.\n *\n * @example\n * ```html\n * <wr-form-error key=\"required\">This field is required.</wr-form-error>\n * <wr-form-error key=\"email\">That doesn't look right.</wr-form-error>\n * ```\n */\n@Component({\n selector: 'wr-form-error',\n template: `<ng-content />`,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-form-error wr-form-field__error',\n role: 'alert',\n '[attr.data-key]': 'key() ?? null',\n '[class.wr-form-field__error--hidden]': '!visible()',\n },\n})\nexport class WrFormError {\n /**\n * Validator key this message corresponds to (e.g. `'required'`).\n * Optional — without a key the message always renders, which is the\n * plain inline-error usage inside `<wr-form-item>`.\n */\n readonly key = input<string>();\n\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Whether this message is the one the current error calls for.\n *\n * The parent projects every `<wr-form-error>` through a single\n * `<ng-content select>`, which cannot filter — so each message decides for\n * itself. Without this, one invalid control rendered \"Email is required.\"\n * and \"That isn't a valid email.\" side by side, which is what the docs have\n * always described as gated behaviour.\n *\n * A keyless message always shows: that is the plain inline-error usage inside\n * `<wr-form-item>`, which has no error discovery at all.\n */\n protected readonly visible = computed(() => {\n const key = this.key();\n if (!key || !this.field) return true;\n return this.field.errorKeys().includes(key);\n });\n}\n\n/**\n * Wraps a label + control + hint + error messages into a single block —\n * the layout primitive every form ends up reinventing.\n *\n * - Auto-binds `label[for]` to the projected control via a generated id\n * (or use the form-control's `[id]` if you set one).\n * - Reads the projected control's `NgControl` to surface validation\n * errors only when the control has been touched / submitted.\n * - Optional `[required]` / `[optional]` markers next to the label.\n *\n * @example\n * ```html\n * <wr-form-field label=\"Email\" hint=\"We'll never share it.\">\n * <input wrInput [formControl]=\"email\" type=\"email\" />\n * <wr-form-error key=\"required\">Email is required.</wr-form-error>\n * <wr-form-error key=\"email\">Not a valid email.</wr-form-error>\n * </wr-form-field>\n * ```\n *\n * @see https://ngwr.dev/reference/components/form-field\n */\n@Component({\n selector: 'wr-form-field',\n templateUrl: './form-field.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: WR_FORM_FIELD,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrFormField),\n },\n ],\n})\nexport class WrFormField implements WrFormFieldContext {\n /** Label text shown above the control. */\n readonly label = input<string>('');\n\n /** Hint text shown below the control. Hidden when an error is visible. */\n readonly hint = input<string>('');\n\n /** Show a `*` next to the label. @default false */\n readonly required = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Show an \"optional\" marker next to the label — the word comes from\n * `optionalLabel`. Mutually exclusive with `required`. @default false\n */\n readonly optional = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Word inside the optional marker's parentheses. Falls back to\n * `form.optional`, then `'optional'`. The parentheses are the template's, so\n * no locale has to repeat punctuation.\n */\n readonly optionalLabel = input<string | null>(null);\n\n // Unlike the `*` marker beside it, this one is NOT `aria-hidden` — it sits\n // inside the `<label>` and is read as part of the control's accessible name,\n // so an English word here reached a Russian screen reader.\n protected readonly resolvedOptional = useI18nText(this.optionalLabel, 'form.optional', 'optional');\n\n /**\n * Force a specific id on the label's `for` attribute. Auto-generated\n * otherwise, and adopted by the projected `wrInput` unless that element\n * already carries an `id` of its own.\n */\n readonly controlId = input<string>(`wr-form-field-${++uid}`);\n\n // What a projected control reported it actually kept. `null` until one does — most\n // controls simply adopt `controlId`, and only a control with its own `id` overrides\n // it from the other direction.\n private readonly adoptedId = signal<string | null>(null);\n\n /**\n * Id the `<label for>` renders. A control that came with its own `id` keeps it, so\n * the label follows that instead of the generated one — otherwise `for` points at\n * an element that is not in the document and the field is unlabelled.\n */\n protected readonly labelFor = computed(() => this.adoptedId() ?? this.controlId());\n\n /** @internal `WrFormFieldContext` — see the token's docs. */\n adoptControlId(id: string): void {\n this.adoptedId.set(id);\n }\n\n /**\n * Projected `NgControl` — used to read touched / dirty / errors.\n *\n * This catches `[formField]` too: Angular's Signal Forms directive provides\n * `NgControl` via its interop shim, so both forms flavours land here.\n */\n protected readonly ngControl = contentChild(NgControl);\n\n /**\n * Bumped on every event the projected control emits.\n *\n * `AbstractControl`'s `touched` / `dirty` / `errors` accessors are NOT\n * reactive under classic forms — Angular reads them inside `untracked()`, and\n * `errors` is a plain assigned field. A `computed` over them therefore caches\n * its first value and never recomputes, which in a zoneless app means the\n * error block never appears at all. `control.events` is the reactive source\n * Angular does expose, so the computed depends on this counter instead.\n * Signal Forms needs none of this — its interop getters read live signals —\n * and harmlessly contributes no events.\n */\n private readonly revision = signal(0);\n\n constructor() {\n let sub: Subscription | null = null;\n effect(() => {\n const control = this.ngControl()?.control;\n sub?.unsubscribe();\n sub = (control?.events ?? EMPTY).subscribe(() => this.revision.update(n => n + 1));\n });\n inject(DestroyRef).onDestroy(() => sub?.unsubscribe());\n }\n\n protected readonly errors = computed(() => {\n this.revision();\n const c = this.ngControl();\n if (!c) return null;\n if (!c.touched && !c.dirty) return null;\n return c.errors;\n });\n\n protected readonly hasError = computed(() => {\n const errs = this.errors();\n return !!errs && Object.keys(errs).length > 0;\n });\n\n /** @internal Read by the projected `<wr-form-error>` children to decide which of them renders. */\n readonly errorKeys = computed<readonly string[]>(() => Object.keys(this.errors() ?? {}));\n\n /** @internal Read by the projected control so a screen reader is pointed at the message. */\n readonly describedBy = computed(() => (this.hasError() ? `${this.controlId()}-errors` : null));\n\n /**\n * @internal Read by the projected control so the hint is announced with the field.\n *\n * The hint used to carry no id at all, so the only thing `aria-describedby`\n * could ever name was the error block: the sentence explaining what to type was\n * on screen and reached a screen-reader user through no path whatsoever, and\n * the one gate that could have said so does not exist — axe has no rule that\n * visible help text must be programmatically associated.\n *\n * `null` while an error is showing, because the template swaps the hint out for\n * the message; publishing the id anyway would point every control at an element\n * that had just left the document.\n */\n readonly hintId = computed(() => (!this.hasError() && this.hint() ? `${this.controlId()}-hint` : null));\n\n /**\n * Render a catalog message for any error the markup does not already answer.\n *\n * On by default: a field with no `<wr-form-error>` at all is the common case,\n * and an empty error block helps nobody. Turn it off for a field whose copy is\n * entirely hand-written. @default true\n */\n readonly autoErrors = input(true, { transform: coerceBooleanProperty });\n\n private readonly projectedErrors = contentChildren(WrFormError);\n private readonly appMessages = inject(WR_FORM_ERRORS);\n private readonly i18n = inject(WrI18n, { optional: true });\n\n /**\n * Errors with no projected `<wr-form-error key>` to answer them, resolved to\n * text: the app catalog first, then the `validation.*` i18n keys, then a\n * built-in English sentence. Per-field markup always wins — it is the most\n * specific thing the author wrote.\n */\n protected readonly autoMessages = computed<readonly { key: string; text: string }[]>(() => {\n if (!this.autoErrors()) return [];\n const errors = this.errors();\n if (!errors) return [];\n\n const claimed = new Set(\n this.projectedErrors()\n .map(e => e.key())\n .filter(Boolean)\n );\n\n return Object.entries(errors)\n .filter(([key]) => !claimed.has(key))\n .map(([key, error]) => ({ key, text: this.resolve(key, error) }))\n .filter(m => m.text.length > 0);\n });\n\n private resolve(key: string, error: unknown): string {\n const app = this.appMessages[key];\n if (app !== undefined) return render(app, key, error, this.label());\n\n // `t()` reads the service's revision signal, so this recomputes on a locale\n // switch; a miss returns the key itself, which is the documented signal.\n const translated = this.i18n?.t(`validation.${key}`, toParams(error));\n if (translated && translated !== `validation.${key}`) return translated;\n\n const fallback = WR_FORM_ERROR_FALLBACKS[key];\n return fallback === undefined ? '' : render(fallback, key, error, this.label());\n }\n\n protected readonly classes = computed(() => {\n const parts = ['wr-form-field'];\n if (this.hasError()) parts.push('wr-form-field--invalid');\n if (this.required()) parts.push('wr-form-field--required');\n return parts.join(' ');\n });\n}\n","@if (label()) {\n <label class=\"wr-form-field__label\" [attr.for]=\"labelFor()\">\n {{ label() }}\n @if (required()) {\n <span class=\"wr-form-field__required\" aria-hidden=\"true\">*</span>\n } @else if (optional()) {\n <span class=\"wr-form-field__optional\">({{ resolvedOptional() }})</span>\n }\n </label>\n}\n\n<div class=\"wr-form-field__control\"><ng-content /></div>\n\n@if (hasError()) {\n <div class=\"wr-form-field__errors\" [attr.id]=\"describedBy()\">\n <ng-content select=\"wr-form-error\" />\n @for (message of autoMessages(); track message.key) {\n <div class=\"wr-form-error wr-form-field__error\" role=\"alert\" [attr.data-key]=\"message.key\">\n {{ message.text }}\n </div>\n }\n </div>\n} @else if (hint()) {\n <small class=\"wr-form-field__hint\" [attr.id]=\"hintId()\">{{ hint() }}</small>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type Signal, computed, inject } from '@angular/core';\n\nimport { WR_FORM_FIELD } from './tokens';\n\n/** What {@link useFormFieldAria} hands a control to bind on its own element. */\nexport interface WrFormFieldAria {\n /**\n * Id of the field's message block while it is showing one, of its hint\n * otherwise, and `null` when it is showing neither.\n */\n readonly describedBy: Signal<string | null>;\n /** `'true'` while the field has a validation error, `null` otherwise. */\n readonly ariaInvalid: Signal<'true' | null>;\n}\n\n/**\n * The two attributes that make a `<wr-form-field>`'s visible text — its error\n * message, or its hint — reach a screen reader. Bind both on whichever element\n * carries the control's role.\n *\n * Without them the copy the field renders is visible and nothing else: the\n * control announces itself as valid, and the text is associated with nothing.\n * No automated gate catches that — axe has no rule that a visible error or hint\n * must be programmatically associated with its control — so this helper exists\n * to make the wiring one line per control rather than three, and the specs are\n * the gate.\n *\n * The field renders an error OR a hint, never both, so `describedBy` names\n * whichever is on screen and `aria-invalid` is keyed SEPARATELY, on the field's\n * `errorKeys()`. Deriving it from `describedBy` instead — which is what every\n * control did while a hint had no id to name — makes a field with a plain hint\n * announce its control as invalid the moment the hint becomes describable.\n *\n * Must be called from an injection context (a field initialiser or a\n * constructor). Returns inert signals outside a `<wr-form-field>`.\n *\n * Pass `skipSelf` from a COMPOSITE control — one whose own template renders\n * other ngwr controls. Such a component shields its subtree by re-providing\n * `WR_FORM_FIELD` as `null`, or the inner parts each announce the outer field's\n * error as their own; a component sees its own providers, so it has to read the\n * real field from one level up.\n *\n * @example\n * ```ts\n * protected readonly fieldAria = useFormFieldAria();\n * ```\n * ```html\n * <input [attr.aria-invalid]=\"fieldAria.ariaInvalid()\" [attr.aria-describedby]=\"fieldAria.describedBy()\" />\n * ```\n */\nexport function useFormFieldAria(options?: { readonly skipSelf?: boolean }): WrFormFieldAria {\n const field = inject(WR_FORM_FIELD, { optional: true, skipSelf: options?.skipSelf ?? false });\n return {\n // `hintId` is optional on the interface so an app-provided field keeps\n // compiling; one without it describes nothing but its errors, as before.\n describedBy: computed(() => field?.describedBy() ?? field?.hintId?.() ?? null),\n ariaInvalid: computed<'true' | null>(() => ((field?.errorKeys().length ?? 0) > 0 ? 'true' : null)),\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-form.mjs","sources":["../../../projects/lib/form/form-item.ts","../../../projects/lib/form/form-errors.ts","../../../projects/lib/form/tokens.ts","../../../projects/lib/form/form-field.ts","../../../projects/lib/form/form-field.html","../../../projects/lib/form/field-aria.ts","../../../projects/lib/form/schema.ts","../../../projects/lib/form/ngwr-form.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\n/**\n * Wraps a label + control + error message into a single field row.\n *\n * Toggle `hasError` to apply error styling to the projected label and\n * any descendant input / textarea / checkbox.\n *\n * @example\n * ```html\n * <wr-form-item [hasError]=\"form.controls.email.invalid\">\n * <label>Email</label>\n * <input wrInput formControlName=\"email\" />\n * <wr-form-error>Invalid email</wr-form-error>\n * </wr-form-item>\n * ```\n *\n * @see https://ngwr.dev/reference/components/form\n */\n@Component({\n selector: 'wr-form-item',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrFormItem {\n /**\n * When `true`, applies error coloring to the projected label and inputs.\n *\n * @default false\n */\n readonly hasError = input(false, { transform: coerceBooleanProperty });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-form-item'];\n if (this.hasError()) parts.push('wr-form-item--error');\n return parts.join(' ');\n });\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\n\n/** Pull a number out of a validator payload without trusting its shape. */\nfunction num(error: unknown, field: string): string {\n if (error && typeof error === 'object' && field in error) {\n const value = (error as Record<string, unknown>)[field];\n if (typeof value === 'number' || typeof value === 'string') return String(value);\n }\n return '';\n}\n\n/** What a message function is handed to build its sentence. */\nexport interface WrFormErrorContext {\n /** Validator key (classic forms) or Signal Forms `kind` that produced the error. */\n readonly key: string;\n /**\n * The validator's own payload — `{ requiredLength, actualLength }` for\n * `minlength`, `{ min }` for `wrMinDate`, and so on. `true` for the\n * flag-shaped validators, which carry nothing.\n */\n readonly error: unknown;\n /** The surrounding field's `label`, so a message can name the field. */\n readonly label: string;\n}\n\n/** A message, or a function that builds one from the validator's payload. */\nexport type WrFormErrorMessage = string | ((ctx: WrFormErrorContext) => string);\n\n/** Validator key → message. Keys are matched exactly against `control.errors`. */\nexport type WrFormErrorMessages = Readonly<Record<string, WrFormErrorMessage>>;\n\n/**\n * App-wide validation copy. Empty by default; `<wr-form-field>` falls through\n * to the `ngwr/i18n` catalog and then to a built-in English sentence, so a\n * form shows a usable message with no configuration at all.\n */\nexport const WR_FORM_ERRORS = new InjectionToken<WrFormErrorMessages>('WR_FORM_ERRORS', {\n providedIn: 'root',\n factory: () => ({}),\n});\n\n/**\n * Register validation messages for the whole app.\n *\n * Only the keys you name are overridden — everything else keeps resolving\n * through the i18n catalog, so this composes with `provideWrI18n()` rather than\n * replacing it. A projected `<wr-form-error key=\"…\">` still wins over both:\n * per-field copy beats app-wide copy.\n *\n * @example\n * ```ts\n * bootstrapApplication(App, {\n * providers: [\n * provideWrFormErrors({\n * required: 'Please fill this in.',\n * minlength: ({ error }) => `At least ${(error as { requiredLength: number }).requiredLength} characters.`,\n * }),\n * ],\n * });\n * ```\n */\nexport function provideWrFormErrors(messages: WrFormErrorMessages = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: WR_FORM_ERRORS, useValue: messages }]);\n}\n\n/**\n * Last-resort English, used when no app catalog and no i18n catalog answer.\n *\n * These exist so that a form with zero configuration still says something true\n * rather than rendering an empty error block. Every key here also ships as a\n * `validation.*` entry in `ngwr/i18n/{en,ru}`, which is what a localized app\n * actually reads.\n */\nexport const WR_FORM_ERROR_FALLBACKS: WrFormErrorMessages = {\n // Angular built-ins.\n required: 'This field is required.',\n requiredTrue: 'This field must be checked.',\n email: 'Enter a valid email address.',\n minlength: ({ error }) => `Enter at least ${num(error, 'requiredLength')} characters.`,\n maxlength: ({ error }) => `Enter at most ${num(error, 'requiredLength')} characters.`,\n min: ({ error }) => `Enter ${num(error, 'min')} or more.`,\n max: ({ error }) => `Enter ${num(error, 'max')} or less.`,\n pattern: 'This value is not in the expected format.',\n\n // WrValidators.\n // Not \"cannot be blank\": the validator PASSES on an empty value and fails on\n // any value that holds whitespace, so the blank wording described the one case\n // that never reaches this message — over a field reading `Ada Lovelace`.\n noWhitespace: 'This value cannot contain spaces.',\n hexColor: 'Enter a hex colour, e.g. #1a2b3c.',\n url: 'Enter a valid URL.',\n cardNumber: 'Enter a valid card number.',\n cvc: ({ error }) => `Enter the ${num(error, 'length')}-digit security code.`,\n iban: 'Enter a valid IBAN.',\n match: 'The two values do not match.',\n matchFields: 'These fields do not match.',\n oneOf: 'Choose one of the allowed values.',\n minDate: 'Choose a later date.',\n maxDate: 'Choose an earlier date.',\n};\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * What a projected control can read from its surrounding `<wr-form-field>`.\n *\n * The field renders `<label [for]>` before it can see what was projected into\n * it, so the id has to travel the other way: the control adopts the id the\n * label already points at. Doing it through DI keeps it a render-time binding,\n * which is what SSR needs — stamping the id from `afterNextRender` would leave\n * every prerendered page with a label pointing at nothing.\n */\nexport interface WrFormFieldContext {\n /** Id the field's `<label for>` points at. */\n readonly controlId: Signal<string>;\n\n /**\n * The reverse direction, for the one case the paragraph above does not cover: a\n * projected control that already carries its own `id` keeps it, and the label has\n * to follow, or `for` names an element that does not exist and the field ends up\n * with no label at all. Called during the control's construction, so the label's\n * binding still resolves in the same render pass.\n */\n adoptControlId(id: string): void;\n\n /**\n * Validator keys currently in error, once the control is touched or dirty.\n * Empty when the field is valid or has not been interacted with.\n */\n readonly errorKeys: Signal<readonly string[]>;\n\n /** Id of the element listing the visible messages, or `null` when there are none. */\n readonly describedBy: Signal<string | null>;\n\n /**\n * Id of the field's hint, or `null` when it is showing none — including while\n * an error has replaced it, since the two never render together and an\n * `aria-describedby` naming an absent element is an author error.\n *\n * Separate from {@link describedBy} rather than folded into it because the two\n * carry different weight: a control keyed `aria-invalid` on \"the field is\n * describing me\" would announce itself invalid for a plain hint. Compose the\n * pair with `useFormFieldAria()` instead of reading either one directly.\n *\n * Optional so an app that provides its own `WR_FORM_FIELD` keeps compiling; a\n * field without it simply describes nothing but its errors.\n */\n readonly hintId?: Signal<string | null>;\n}\n\n/** Present only inside a `<wr-form-field>`; inject with `{ optional: true }`. */\nexport const WR_FORM_FIELD = new InjectionToken<WrFormFieldContext>('WR_FORM_FIELD');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n DestroyRef,\n ViewEncapsulation,\n computed,\n contentChild,\n contentChildren,\n effect,\n forwardRef,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { NgControl } from '@angular/forms';\n\nimport { EMPTY, type Subscription } from 'rxjs';\n\nimport { WrI18n, useI18nText } from 'ngwr/i18n';\n\nimport { WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, type WrFormErrorMessage } from './form-errors';\nimport { WR_FORM_FIELD, type WrFormFieldContext } from './tokens';\n\nlet uid = 0;\n\n/** A message is either literal text or a function over the validator's payload. */\nfunction render(message: WrFormErrorMessage, key: string, error: unknown, label: string): string {\n return typeof message === 'function' ? message({ key, error, label }) : message;\n}\n\n/** Validator payloads are plain objects; anything else interpolates nothing. */\nfunction toParams(error: unknown): Record<string, unknown> | undefined {\n return error && typeof error === 'object' ? (error as Record<string, unknown>) : undefined;\n}\n\n/**\n * One error message tied to a validator key. Renders only when the parent\n * form-field has a matching error in `control.errors`, and only once the\n * control is touched or dirty.\n *\n * @example\n * ```html\n * <wr-form-error key=\"required\">This field is required.</wr-form-error>\n * <wr-form-error key=\"email\">That doesn't look right.</wr-form-error>\n * ```\n */\n@Component({\n selector: 'wr-form-error',\n template: `<ng-content />`,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-form-error wr-form-field__error',\n role: 'alert',\n '[attr.data-key]': 'key() ?? null',\n '[class.wr-form-field__error--hidden]': '!visible()',\n },\n})\nexport class WrFormError {\n /**\n * Validator key this message corresponds to (e.g. `'required'`).\n * Optional — without a key the message always renders, which is the\n * plain inline-error usage inside `<wr-form-item>`.\n */\n readonly key = input<string>();\n\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Whether this message is the one the current error calls for.\n *\n * The parent projects every `<wr-form-error>` through a single\n * `<ng-content select>`, which cannot filter — so each message decides for\n * itself. Without this, one invalid control rendered \"Email is required.\"\n * and \"That isn't a valid email.\" side by side, which is what the docs have\n * always described as gated behaviour.\n *\n * A keyless message always shows: that is the plain inline-error usage inside\n * `<wr-form-item>`, which has no error discovery at all.\n */\n protected readonly visible = computed(() => {\n const key = this.key();\n if (!key || !this.field) return true;\n return this.field.errorKeys().includes(key);\n });\n}\n\n/**\n * Wraps a label + control + hint + error messages into a single block —\n * the layout primitive every form ends up reinventing.\n *\n * - Auto-binds `label[for]` to the projected control via a generated id\n * (or use the form-control's `[id]` if you set one).\n * - Reads the projected control's `NgControl` to surface validation\n * errors only when the control has been touched / submitted.\n * - Optional `[required]` / `[optional]` markers next to the label.\n *\n * @example\n * ```html\n * <wr-form-field label=\"Email\" hint=\"We'll never share it.\">\n * <input wrInput [formControl]=\"email\" type=\"email\" />\n * <wr-form-error key=\"required\">Email is required.</wr-form-error>\n * <wr-form-error key=\"email\">Not a valid email.</wr-form-error>\n * </wr-form-field>\n * ```\n *\n * @see https://ngwr.dev/reference/components/form-field\n */\n@Component({\n selector: 'wr-form-field',\n templateUrl: './form-field.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: WR_FORM_FIELD,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrFormField),\n },\n ],\n})\nexport class WrFormField implements WrFormFieldContext {\n /** Label text shown above the control. */\n readonly label = input<string>('');\n\n /** Hint text shown below the control. Hidden when an error is visible. */\n readonly hint = input<string>('');\n\n /** Show a `*` next to the label. @default false */\n readonly required = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Show an \"optional\" marker next to the label — the word comes from\n * `optionalLabel`. Mutually exclusive with `required`. @default false\n */\n readonly optional = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Word inside the optional marker's parentheses. Falls back to\n * `form.optional`, then `'optional'`. The parentheses are the template's, so\n * no locale has to repeat punctuation.\n */\n readonly optionalLabel = input<string | null>(null);\n\n // Unlike the `*` marker beside it, this one is NOT `aria-hidden` — it sits\n // inside the `<label>` and is read as part of the control's accessible name,\n // so an English word here reached a Russian screen reader.\n protected readonly resolvedOptional = useI18nText(this.optionalLabel, 'form.optional', 'optional');\n\n /**\n * Force a specific id on the label's `for` attribute. Auto-generated\n * otherwise, and adopted by the projected `wrInput` unless that element\n * already carries an `id` of its own.\n */\n readonly controlId = input<string>(`wr-form-field-${++uid}`);\n\n // What a projected control reported it actually kept. `null` until one does — most\n // controls simply adopt `controlId`, and only a control with its own `id` overrides\n // it from the other direction.\n private readonly adoptedId = signal<string | null>(null);\n\n /**\n * Id the `<label for>` renders. A control that came with its own `id` keeps it, so\n * the label follows that instead of the generated one — otherwise `for` points at\n * an element that is not in the document and the field is unlabelled.\n */\n protected readonly labelFor = computed(() => this.adoptedId() ?? this.controlId());\n\n /** @internal `WrFormFieldContext` — see the token's docs. */\n adoptControlId(id: string): void {\n this.adoptedId.set(id);\n }\n\n /**\n * Projected `NgControl` — used to read touched / dirty / errors.\n *\n * This catches `[formField]` too: Angular's Signal Forms directive provides\n * `NgControl` via its interop shim, so both forms flavours land here.\n */\n protected readonly ngControl = contentChild(NgControl);\n\n /**\n * Bumped on every event the projected control emits.\n *\n * `AbstractControl`'s `touched` / `dirty` / `errors` accessors are NOT\n * reactive under classic forms — Angular reads them inside `untracked()`, and\n * `errors` is a plain assigned field. A `computed` over them therefore caches\n * its first value and never recomputes, which in a zoneless app means the\n * error block never appears at all. `control.events` is the reactive source\n * Angular does expose, so the computed depends on this counter instead.\n * Signal Forms needs none of this — its interop getters read live signals —\n * and harmlessly contributes no events.\n */\n private readonly revision = signal(0);\n\n constructor() {\n let sub: Subscription | null = null;\n effect(() => {\n const control = this.ngControl()?.control;\n sub?.unsubscribe();\n sub = (control?.events ?? EMPTY).subscribe(() => this.revision.update(n => n + 1));\n });\n inject(DestroyRef).onDestroy(() => sub?.unsubscribe());\n }\n\n protected readonly errors = computed(() => {\n this.revision();\n const c = this.ngControl();\n if (!c) return null;\n if (!c.touched && !c.dirty) return null;\n return c.errors;\n });\n\n protected readonly hasError = computed(() => {\n const errs = this.errors();\n return !!errs && Object.keys(errs).length > 0;\n });\n\n /** @internal Read by the projected `<wr-form-error>` children to decide which of them renders. */\n readonly errorKeys = computed<readonly string[]>(() => Object.keys(this.errors() ?? {}));\n\n /** @internal Read by the projected control so a screen reader is pointed at the message. */\n readonly describedBy = computed(() => (this.hasError() ? `${this.controlId()}-errors` : null));\n\n /**\n * @internal Read by the projected control so the hint is announced with the field.\n *\n * The hint used to carry no id at all, so the only thing `aria-describedby`\n * could ever name was the error block: the sentence explaining what to type was\n * on screen and reached a screen-reader user through no path whatsoever, and\n * the one gate that could have said so does not exist — axe has no rule that\n * visible help text must be programmatically associated.\n *\n * `null` while an error is showing, because the template swaps the hint out for\n * the message; publishing the id anyway would point every control at an element\n * that had just left the document.\n */\n readonly hintId = computed(() => (!this.hasError() && this.hint() ? `${this.controlId()}-hint` : null));\n\n /**\n * Render a catalog message for any error the markup does not already answer.\n *\n * On by default: a field with no `<wr-form-error>` at all is the common case,\n * and an empty error block helps nobody. Turn it off for a field whose copy is\n * entirely hand-written. @default true\n */\n readonly autoErrors = input(true, { transform: coerceBooleanProperty });\n\n private readonly projectedErrors = contentChildren(WrFormError);\n private readonly appMessages = inject(WR_FORM_ERRORS);\n private readonly i18n = inject(WrI18n, { optional: true });\n\n /**\n * Errors with no projected `<wr-form-error key>` to answer them, resolved to\n * text: the app catalog first, then the `validation.*` i18n keys, then a\n * built-in English sentence. Per-field markup always wins — it is the most\n * specific thing the author wrote.\n */\n protected readonly autoMessages = computed<readonly { key: string; text: string }[]>(() => {\n if (!this.autoErrors()) return [];\n const errors = this.errors();\n if (!errors) return [];\n\n const claimed = new Set(\n this.projectedErrors()\n .map(e => e.key())\n .filter(Boolean)\n );\n\n return Object.entries(errors)\n .filter(([key]) => !claimed.has(key))\n .map(([key, error]) => ({ key, text: this.resolve(key, error) }))\n .filter(m => m.text.length > 0);\n });\n\n private resolve(key: string, error: unknown): string {\n const app = this.appMessages[key];\n if (app !== undefined) return render(app, key, error, this.label());\n\n // `t()` reads the service's revision signal, so this recomputes on a locale\n // switch; a miss returns the key itself, which is the documented signal.\n const translated = this.i18n?.t(`validation.${key}`, toParams(error));\n if (translated && translated !== `validation.${key}`) return translated;\n\n const fallback = WR_FORM_ERROR_FALLBACKS[key];\n return fallback === undefined ? '' : render(fallback, key, error, this.label());\n }\n\n protected readonly classes = computed(() => {\n const parts = ['wr-form-field'];\n if (this.hasError()) parts.push('wr-form-field--invalid');\n if (this.required()) parts.push('wr-form-field--required');\n return parts.join(' ');\n });\n}\n","@if (label()) {\n <label class=\"wr-form-field__label\" [attr.for]=\"labelFor()\">\n {{ label() }}\n @if (required()) {\n <span class=\"wr-form-field__required\" aria-hidden=\"true\">*</span>\n } @else if (optional()) {\n <span class=\"wr-form-field__optional\">({{ resolvedOptional() }})</span>\n }\n </label>\n}\n\n<div class=\"wr-form-field__control\"><ng-content /></div>\n\n@if (hasError()) {\n <div class=\"wr-form-field__errors\" [attr.id]=\"describedBy()\">\n <ng-content select=\"wr-form-error\" />\n @for (message of autoMessages(); track message.key) {\n <div class=\"wr-form-error wr-form-field__error\" role=\"alert\" [attr.data-key]=\"message.key\">\n {{ message.text }}\n </div>\n }\n </div>\n} @else if (hint()) {\n <small class=\"wr-form-field__hint\" [attr.id]=\"hintId()\">{{ hint() }}</small>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type Signal, computed, inject } from '@angular/core';\n\nimport { WR_FORM_FIELD } from './tokens';\n\n/** What {@link useFormFieldAria} hands a control to bind on its own element. */\nexport interface WrFormFieldAria {\n /**\n * Id of the field's message block while it is showing one, of its hint\n * otherwise, and `null` when it is showing neither.\n */\n readonly describedBy: Signal<string | null>;\n /** `'true'` while the field has a validation error, `null` otherwise. */\n readonly ariaInvalid: Signal<'true' | null>;\n}\n\n/**\n * The two attributes that make a `<wr-form-field>`'s visible text — its error\n * message, or its hint — reach a screen reader. Bind both on whichever element\n * carries the control's role.\n *\n * Without them the copy the field renders is visible and nothing else: the\n * control announces itself as valid, and the text is associated with nothing.\n * No automated gate catches that — axe has no rule that a visible error or hint\n * must be programmatically associated with its control — so this helper exists\n * to make the wiring one line per control rather than three, and the specs are\n * the gate.\n *\n * The field renders an error OR a hint, never both, so `describedBy` names\n * whichever is on screen and `aria-invalid` is keyed SEPARATELY, on the field's\n * `errorKeys()`. Deriving it from `describedBy` instead — which is what every\n * control did while a hint had no id to name — makes a field with a plain hint\n * announce its control as invalid the moment the hint becomes describable.\n *\n * Must be called from an injection context (a field initialiser or a\n * constructor). Returns inert signals outside a `<wr-form-field>`.\n *\n * Pass `skipSelf` from a COMPOSITE control — one whose own template renders\n * other ngwr controls. Such a component shields its subtree by re-providing\n * `WR_FORM_FIELD` as `null`, or the inner parts each announce the outer field's\n * error as their own; a component sees its own providers, so it has to read the\n * real field from one level up.\n *\n * @example\n * ```ts\n * protected readonly fieldAria = useFormFieldAria();\n * ```\n * ```html\n * <input [attr.aria-invalid]=\"fieldAria.ariaInvalid()\" [attr.aria-describedby]=\"fieldAria.describedBy()\" />\n * ```\n */\nexport function useFormFieldAria(options?: { readonly skipSelf?: boolean }): WrFormFieldAria {\n const field = inject(WR_FORM_FIELD, { optional: true, skipSelf: options?.skipSelf ?? false });\n return {\n // `hintId` is optional on the interface so an app-provided field keeps\n // compiling; one without it describes nothing but its errors, as before.\n describedBy: computed(() => field?.describedBy() ?? field?.hintId?.() ?? null),\n ariaInvalid: computed<'true' | null>(() => ((field?.errorKeys().length ?? 0) > 0 ? 'true' : null)),\n };\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { createMetadataKey } from '@angular/forms/signals';\n\n/**\n * How a field is DRAWN, attached to the same Signal Forms schema that already\n * says how it is validated.\n *\n * The alternative was a second schema — one for rules, one for presentation —\n * and it was rejected before it was written: two descriptions of one form drift\n * the moment someone renames a field in one of them, and nothing would report\n * it. Angular's `metadata()` takes a typed key and a `LogicFn`, so the\n * presentation rides on the schema the validators are already in, and it is\n * REACTIVE for free: a label, a set of options or a placeholder may depend on\n * the value of another field.\n *\n * What this deliberately does NOT carry: `required`, `disabled`, `readonly`,\n * `hidden`, `min`, `max`, and every validation rule. Those are Angular's own\n * schema functions, they already drive the control through `[formField]`, and\n * duplicating them here would create a second source of truth for state the form\n * already owns. That is not only a judgement call — Angular REFUSES a `[min]` or\n * `[required]` binding on a field-bound control (NG8022), so the second source\n * of truth is a compile error rather than a drift.\n */\nexport type WrFieldKind =\n 'input' | 'textarea' | 'number' | 'select' | 'checkbox' | 'switch' | 'radio' | 'date' | 'slider';\n\n/** One choice, for the kinds that offer a list. */\nexport interface WrFieldOption {\n readonly value: unknown;\n readonly label: string;\n readonly disabled?: boolean;\n}\n\n/**\n * The presentation of one field.\n *\n * `kind` is the only required member: everything else has a sane default, and a\n * schema that says no more than `{ kind: 'input' }` still renders a labelled,\n * error-bound control — the label falls back to the field's own name.\n */\nexport interface WrFieldSpec {\n readonly kind: WrFieldKind;\n /** Defaults to the field's key, de-camel-cased — `workEmail` becomes \"Work email\". */\n readonly label?: string;\n readonly placeholder?: string;\n /** Help text under the control. Errors replace it while the field is invalid. */\n readonly hint?: string;\n /** For `select` and `radio`. Ignored by every other kind. */\n readonly options?: readonly WrFieldOption[];\n /** Native `type` for `kind: 'input'` — `email`, `password`, `url`, `tel`. */\n readonly type?: string;\n /**\n * Granularity for `number` and `slider`. The BOUNDS are deliberately absent:\n * Angular refuses a `[min]` or `[max]` binding on a `[formField]`-bound\n * control outright (NG8022), because the field owns them — write `min(path.x,\n * 18)` in the schema and the control picks it up. `step` is presentation, has\n * no schema function, and stays here.\n */\n readonly step?: number;\n /**\n * Columns this field spans in `<wr-schema-form>`'s grid. Clamped to the form's\n * own `columns`, and 1 by default — a field is one cell unless it asks to be\n * wider.\n */\n readonly span?: number;\n}\n\n/**\n * The metadata key `<wr-schema-form>` reads.\n *\n * ```ts\n * const userSchema = schema<User>(path => {\n * required(path.email);\n * email(path.email);\n * metadata(path.email, WR_FIELD, () => ({ kind: 'input', type: 'email', label: 'Work email' }));\n * metadata(path.role, WR_FIELD, () => ({ kind: 'select', options: ROLES }));\n * });\n * ```\n *\n * A field with no `WR_FIELD` metadata is not an error and is not guessed at —\n * `<wr-schema-form>` skips it, so a schema can describe more than one screen shows.\n */\nexport const WR_FIELD = createMetadataKey<WrFieldSpec>();\n\n/** `workEmail` -> `Work email`. The fallback label, and only ever a fallback. */\nexport function wrFieldLabel(key: string): string {\n const spaced = key.replace(/([a-z\\d])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ');\n return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|