ngwr 14.2.0 → 14.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -22
- package/fesm2022/ngwr-calendar.mjs +4 -2
- package/fesm2022/ngwr-calendar.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-line-chart.mjs +24 -4
- package/fesm2022/ngwr-line-chart.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 +221 -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/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/types/ngwr-calendar.d.ts +2 -0
- 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
|
@@ -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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"}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/** Base Arabic catalog for ngwr built-in component strings. */
|
|
2
|
+
const wrAr = {
|
|
3
|
+
common: {
|
|
4
|
+
ok: 'موافق',
|
|
5
|
+
cancel: 'إلغاء',
|
|
6
|
+
close: 'إغلاق',
|
|
7
|
+
confirm: 'تأكيد',
|
|
8
|
+
delete: 'حذف',
|
|
9
|
+
save: 'حفظ',
|
|
10
|
+
edit: 'تعديل',
|
|
11
|
+
add: 'إضافة',
|
|
12
|
+
remove: 'إزالة',
|
|
13
|
+
clear: 'مسح',
|
|
14
|
+
search: 'بحث',
|
|
15
|
+
loading: 'جارٍ التحميل…',
|
|
16
|
+
select: 'تحديد',
|
|
17
|
+
next: 'التالي',
|
|
18
|
+
previous: 'السابق',
|
|
19
|
+
back: 'رجوع',
|
|
20
|
+
today: 'اليوم',
|
|
21
|
+
yesterday: 'أمس',
|
|
22
|
+
tomorrow: 'غدًا',
|
|
23
|
+
of: 'من',
|
|
24
|
+
},
|
|
25
|
+
pagination: {
|
|
26
|
+
prev: 'الصفحة السابقة',
|
|
27
|
+
next: 'الصفحة التالية',
|
|
28
|
+
itemsPerPage: 'عدد العناصر في الصفحة',
|
|
29
|
+
perPage: '{{size}} / صفحة',
|
|
30
|
+
goToPage: 'الانتقال إلى الصفحة {{page}}',
|
|
31
|
+
label: 'ترقيم الصفحات',
|
|
32
|
+
pageOf: 'الصفحة {{current}} من {{total}}',
|
|
33
|
+
range: '{{from}}–{{to}} من {{total}}',
|
|
34
|
+
compact: '{{current}} / {{total}}',
|
|
35
|
+
},
|
|
36
|
+
table: {
|
|
37
|
+
empty: 'لا توجد بيانات',
|
|
38
|
+
loading: 'جارٍ التحميل…',
|
|
39
|
+
sort: 'فرز العمود',
|
|
40
|
+
filter: 'تصفية العمود',
|
|
41
|
+
selectAll: 'تحديد كل الصفوف',
|
|
42
|
+
selectRow: 'تحديد الصف',
|
|
43
|
+
expandRow: 'تبديل تفاصيل الصف',
|
|
44
|
+
toggleRow: 'تبديل الصفوف الفرعية',
|
|
45
|
+
selectGroup: 'تحديد المجموعة',
|
|
46
|
+
toggleGroup: 'تبديل المجموعة',
|
|
47
|
+
noMatches: 'لا توجد نتائج مطابقة',
|
|
48
|
+
search: 'بحث',
|
|
49
|
+
reset: 'إعادة تعيين',
|
|
50
|
+
},
|
|
51
|
+
eventCalendar: {
|
|
52
|
+
today: 'اليوم',
|
|
53
|
+
previous: 'السابق',
|
|
54
|
+
next: 'التالي',
|
|
55
|
+
month: 'شهر',
|
|
56
|
+
week: 'أسبوع',
|
|
57
|
+
day: 'يوم',
|
|
58
|
+
time: 'الوقت',
|
|
59
|
+
allDay: 'طوال اليوم',
|
|
60
|
+
label: 'التقويم',
|
|
61
|
+
more: '+{{count}} أخرى',
|
|
62
|
+
header: '{{month}} {{year}}',
|
|
63
|
+
range: '{{from}} – {{to}}',
|
|
64
|
+
chipLabel: '{{title}}، {{time}}',
|
|
65
|
+
slotLabel: '{{time}} — {{date}}',
|
|
66
|
+
allDayCellLabel: '{{label}} — {{date}}',
|
|
67
|
+
},
|
|
68
|
+
tour: {
|
|
69
|
+
next: 'التالي',
|
|
70
|
+
back: 'السابق',
|
|
71
|
+
done: 'تم',
|
|
72
|
+
skip: 'تخطي الجولة',
|
|
73
|
+
progress: 'الخطوة {{current}} من {{total}}',
|
|
74
|
+
},
|
|
75
|
+
splitter: {
|
|
76
|
+
divider: 'تغيير حجم الأجزاء',
|
|
77
|
+
},
|
|
78
|
+
stepper: {
|
|
79
|
+
optional: 'اختياري',
|
|
80
|
+
},
|
|
81
|
+
transfer: {
|
|
82
|
+
source: 'المتاح',
|
|
83
|
+
target: 'المحدد',
|
|
84
|
+
search: 'بحث',
|
|
85
|
+
empty: 'لا شيء هنا',
|
|
86
|
+
selectAll: 'تحديد الكل',
|
|
87
|
+
toTarget: 'النقل إلى المحدد',
|
|
88
|
+
toSource: 'النقل إلى المتاح',
|
|
89
|
+
count: '{{checked}} / {{total}}',
|
|
90
|
+
},
|
|
91
|
+
form: {
|
|
92
|
+
optional: 'اختياري',
|
|
93
|
+
},
|
|
94
|
+
validation: {
|
|
95
|
+
required: 'هذا الحقل مطلوب.',
|
|
96
|
+
requiredTrue: 'يجب تحديد هذا الحقل.',
|
|
97
|
+
email: 'أدخل عنوان بريد إلكتروني صالحًا.',
|
|
98
|
+
minlength: 'الحد الأدنى لعدد الأحرف: {{requiredLength}}.',
|
|
99
|
+
maxlength: 'الحد الأقصى لعدد الأحرف: {{requiredLength}}.',
|
|
100
|
+
min: 'أدخل {{min}} أو أكثر.',
|
|
101
|
+
max: 'أدخل {{max}} أو أقل.',
|
|
102
|
+
pattern: 'هذه القيمة لا تطابق التنسيق المتوقع.',
|
|
103
|
+
noWhitespace: 'لا يمكن أن تحتوي هذه القيمة على مسافات.',
|
|
104
|
+
hexColor: 'أدخل لونًا بالنظام الست عشري، مثل #1a2b3c.',
|
|
105
|
+
url: 'أدخل عنوان URL صالحًا.',
|
|
106
|
+
cardNumber: 'أدخل رقم بطاقة صالحًا.',
|
|
107
|
+
cvc: 'أدخل رمز الأمان (عدد الخانات: {{length}}).',
|
|
108
|
+
iban: 'أدخل رقم IBAN صالحًا.',
|
|
109
|
+
match: 'القيمتان غير متطابقتين.',
|
|
110
|
+
matchFields: 'الحقول غير متطابقة.',
|
|
111
|
+
oneOf: 'اختر إحدى القيم المسموح بها.',
|
|
112
|
+
minDate: 'اختر تاريخًا لاحقًا.',
|
|
113
|
+
maxDate: 'اختر تاريخًا سابقًا.',
|
|
114
|
+
},
|
|
115
|
+
select: {
|
|
116
|
+
// The combobox's own accessible name, also read by `wr-tree` and
|
|
117
|
+
// `wr-cascader`. «تحديد» is the word this catalog uses for marking rows and
|
|
118
|
+
// groups that already exist; picking one value out of a list is «اختيار»,
|
|
119
|
+
// which is also the verb the placeholder «اختر…» below opens with.
|
|
120
|
+
label: 'اختيار',
|
|
121
|
+
placeholder: 'اختر…',
|
|
122
|
+
empty: 'لا توجد خيارات',
|
|
123
|
+
clearSelection: 'مسح التحديد',
|
|
124
|
+
removeItem: 'إزالة {{label}}',
|
|
125
|
+
noResults: 'لا توجد نتائج',
|
|
126
|
+
loading: 'جارٍ التحميل…',
|
|
127
|
+
more: '+{{count}} أخرى',
|
|
128
|
+
},
|
|
129
|
+
// `tree` covers both inline display and combobox-mode pickers
|
|
130
|
+
// (replaces the dropped `treeSelect` namespace).
|
|
131
|
+
tree: {
|
|
132
|
+
expand: 'توسيع',
|
|
133
|
+
collapse: 'طي',
|
|
134
|
+
placeholder: 'اختر…',
|
|
135
|
+
clearSelection: 'مسح التحديد',
|
|
136
|
+
removeItem: 'إزالة {{label}}',
|
|
137
|
+
more: '+{{count}} أخرى',
|
|
138
|
+
},
|
|
139
|
+
commandPalette: {
|
|
140
|
+
label: 'لوحة الأوامر',
|
|
141
|
+
placeholder: 'اكتب أمرًا أو ابحث…',
|
|
142
|
+
noResults: 'لا توجد نتائج',
|
|
143
|
+
loading: 'جارٍ البحث…',
|
|
144
|
+
escHint: 'esc',
|
|
145
|
+
},
|
|
146
|
+
empty: {
|
|
147
|
+
noData: 'لا توجد بيانات',
|
|
148
|
+
},
|
|
149
|
+
fileUpload: {
|
|
150
|
+
browse: 'انقر للاستعراض',
|
|
151
|
+
dropZone: 'أو أفلت الملفات هنا',
|
|
152
|
+
dropZoneLabel: 'منطقة إفلات الملفات — انقر أو أفلت الملفات',
|
|
153
|
+
removeFile: 'إزالة الملف',
|
|
154
|
+
invalid: 'نوع ملف غير مدعوم',
|
|
155
|
+
tooBig: 'حجم الملف كبير جدًا',
|
|
156
|
+
size: '{{value}} {{unit}}',
|
|
157
|
+
unitByte: 'بايت',
|
|
158
|
+
unitKb: 'كيلوبايت',
|
|
159
|
+
unitMb: 'ميجابايت',
|
|
160
|
+
unitGb: 'جيجابايت',
|
|
161
|
+
unitTb: 'تيرابايت',
|
|
162
|
+
},
|
|
163
|
+
popconfirm: {
|
|
164
|
+
label: 'تأكيد الإجراء',
|
|
165
|
+
confirm: 'تأكيد',
|
|
166
|
+
cancel: 'إلغاء',
|
|
167
|
+
},
|
|
168
|
+
toast: {
|
|
169
|
+
region: 'الإشعارات',
|
|
170
|
+
close: 'إغلاق',
|
|
171
|
+
copy: 'نسخ',
|
|
172
|
+
copied: 'تم النسخ',
|
|
173
|
+
closeAll: 'إغلاق الكل',
|
|
174
|
+
},
|
|
175
|
+
input: {
|
|
176
|
+
showPassword: 'إظهار كلمة المرور',
|
|
177
|
+
hidePassword: 'إخفاء كلمة المرور',
|
|
178
|
+
},
|
|
179
|
+
inputNumber: {
|
|
180
|
+
increment: 'زيادة',
|
|
181
|
+
decrement: 'إنقاص',
|
|
182
|
+
},
|
|
183
|
+
inputOtp: {
|
|
184
|
+
label: 'رمز التحقق',
|
|
185
|
+
digit: 'الرقم {{index}}',
|
|
186
|
+
character: 'الحرف {{index}}',
|
|
187
|
+
},
|
|
188
|
+
anchor: {
|
|
189
|
+
label: 'جدول المحتويات',
|
|
190
|
+
},
|
|
191
|
+
avatar: {
|
|
192
|
+
alt: 'الصورة الرمزية',
|
|
193
|
+
},
|
|
194
|
+
backTop: {
|
|
195
|
+
label: 'العودة إلى الأعلى',
|
|
196
|
+
},
|
|
197
|
+
breadcrumbs: {
|
|
198
|
+
label: 'مسار التنقل',
|
|
199
|
+
},
|
|
200
|
+
burger: {
|
|
201
|
+
label: 'تبديل القائمة',
|
|
202
|
+
},
|
|
203
|
+
calendar: {
|
|
204
|
+
prevMonth: 'الشهر السابق',
|
|
205
|
+
nextMonth: 'الشهر التالي',
|
|
206
|
+
prevYear: 'السنة السابقة',
|
|
207
|
+
nextYear: 'السنة التالية',
|
|
208
|
+
// The month / year pickers are `role="listbox"`, and a listbox owes a
|
|
209
|
+
// name — without one a screen reader announces the control as nothing at
|
|
210
|
+
// all. Caught by `check:state-a11y` once a state finally opened the view.
|
|
211
|
+
monthList: 'الأشهر',
|
|
212
|
+
yearList: 'السنوات',
|
|
213
|
+
prevYears: '12 سنة سابقة',
|
|
214
|
+
nextYears: '12 سنة تالية',
|
|
215
|
+
header: '{{month}} {{year}}',
|
|
216
|
+
yearRange: '{{from}} – {{to}}',
|
|
217
|
+
dayLabel: '{{weekday}}، {{date}}',
|
|
218
|
+
},
|
|
219
|
+
imageCropper: {
|
|
220
|
+
empty: 'لا توجد صورة',
|
|
221
|
+
window: 'منطقة الاقتصاص',
|
|
222
|
+
keyHelp: 'مفاتيح الأسهم تحرّك منطقة الاقتصاص. اضغط باستمرار على Alt مع أحد مفاتيح الأسهم لتغيير حجمها، وعلى Shift لخطوات أكبر. ' +
|
|
223
|
+
'يُعلن عن المنطقة بقيم اليسار والأعلى والعرض والارتفاع بالبكسل داخل الصورة.',
|
|
224
|
+
},
|
|
225
|
+
sortableList: {
|
|
226
|
+
keyHelp: 'اضغط مفتاح المسافة لالتقاط هذا العنصر، ثم استخدم مفاتيح الأسهم لتحريكه. ' +
|
|
227
|
+
'اضغط مفتاح المسافة مرة أخرى لإفلاته، أو Escape لإعادته إلى مكانه.',
|
|
228
|
+
grabbed: 'تم الالتقاط. {{index}} من {{total}}.',
|
|
229
|
+
moved: '{{index}} من {{total}}.',
|
|
230
|
+
dropped: 'تم الإفلات. {{index}} من {{total}}.',
|
|
231
|
+
cancelled: 'تم إلغاء النقل.',
|
|
232
|
+
},
|
|
233
|
+
colorPicker: {
|
|
234
|
+
area: 'التشبع والسطوع، {{saturation}}% و{{brightness}}%',
|
|
235
|
+
hue: 'درجة اللون',
|
|
236
|
+
alpha: 'العتامة',
|
|
237
|
+
formatHex: 'HEX',
|
|
238
|
+
formatRgb: 'RGB',
|
|
239
|
+
formatHsl: 'HSL',
|
|
240
|
+
channelHex: 'HEX',
|
|
241
|
+
channelRed: 'R',
|
|
242
|
+
channelGreen: 'G',
|
|
243
|
+
channelBlue: 'B',
|
|
244
|
+
channelHue: 'H',
|
|
245
|
+
channelSaturation: 'S%',
|
|
246
|
+
channelLightness: 'L%',
|
|
247
|
+
channelAlpha: 'A%',
|
|
248
|
+
},
|
|
249
|
+
calendarHeatmap: {
|
|
250
|
+
label: 'خريطة حرارية للتقويم',
|
|
251
|
+
},
|
|
252
|
+
lineChart: {
|
|
253
|
+
label: 'مخطط خطي',
|
|
254
|
+
// The one counted string that cannot dodge the noun — it IS the noun. Arabic
|
|
255
|
+
// wants «آلاف» from three to ten and «ألف» from eleven up, and one axis
|
|
256
|
+
// carries ticks from both ranges. «ألف» invariant is what Arabic analytics
|
|
257
|
+
// UIs print, and it is the correct form for the large ticks that are the
|
|
258
|
+
// reason to abbreviate at all.
|
|
259
|
+
thousands: '{{value}} ألف',
|
|
260
|
+
},
|
|
261
|
+
donutChart: {
|
|
262
|
+
label: 'مخطط دائري مجوف',
|
|
263
|
+
},
|
|
264
|
+
compare: {
|
|
265
|
+
label: 'فاصل المقارنة',
|
|
266
|
+
},
|
|
267
|
+
// The two `roledescription` values are spoken INSTEAD of the role name, so they
|
|
268
|
+
// are bare nouns. Arabic has no letter case, so English's lowercase rule has no
|
|
269
|
+
// counterpart here — what carries it is dropping the definite article.
|
|
270
|
+
carousel: {
|
|
271
|
+
label: 'العرض الدوّار',
|
|
272
|
+
goToSlide: 'الانتقال إلى الشريحة {{index}}',
|
|
273
|
+
prev: 'الشريحة السابقة',
|
|
274
|
+
next: 'الشريحة التالية',
|
|
275
|
+
pagination: 'ترقيم شرائح العرض الدوّار',
|
|
276
|
+
roledescription: 'عرض دوّار',
|
|
277
|
+
slideRoledescription: 'شريحة',
|
|
278
|
+
},
|
|
279
|
+
actionSheet: {
|
|
280
|
+
label: 'الإجراءات',
|
|
281
|
+
},
|
|
282
|
+
alert: {
|
|
283
|
+
close: 'إغلاق التنبيه',
|
|
284
|
+
},
|
|
285
|
+
qr: {
|
|
286
|
+
label: 'رمز QR',
|
|
287
|
+
},
|
|
288
|
+
image: {
|
|
289
|
+
viewer: 'معاينة الصورة',
|
|
290
|
+
open: 'فتح المعاينة',
|
|
291
|
+
close: 'إغلاق المعاينة',
|
|
292
|
+
},
|
|
293
|
+
window: {
|
|
294
|
+
close: 'إغلاق',
|
|
295
|
+
minimize: 'تصغير',
|
|
296
|
+
maximize: 'تكبير',
|
|
297
|
+
restore: 'استعادة',
|
|
298
|
+
restoreDown: 'استعادة لأسفل',
|
|
299
|
+
restoreWindow: 'استعادة {{title}}',
|
|
300
|
+
closeWindow: 'إغلاق النافذة',
|
|
301
|
+
untitled: 'بلا عنوان',
|
|
302
|
+
taskbar: 'النوافذ المصغّرة',
|
|
303
|
+
},
|
|
304
|
+
dialog: {
|
|
305
|
+
close: 'إغلاق مربع الحوار',
|
|
306
|
+
},
|
|
307
|
+
// Deliberately generic: a popover panel has no universal name, and an unnamed
|
|
308
|
+
// `role="dialog"` announces as nothing at all. Override per instance with
|
|
309
|
+
// `[ariaLabel]`.
|
|
310
|
+
popover: {
|
|
311
|
+
label: 'لوحة منبثقة',
|
|
312
|
+
},
|
|
313
|
+
markdown: {
|
|
314
|
+
copy: 'نسخ الكود',
|
|
315
|
+
copied: 'تم النسخ',
|
|
316
|
+
taskDone: 'تم:',
|
|
317
|
+
taskTodo: 'لم يتم:',
|
|
318
|
+
},
|
|
319
|
+
// Arabic inflects a counted noun differently at one, at two, at three-to-ten
|
|
320
|
+
// and at eleven-and-up, and the interpolator has no plural machinery — so a
|
|
321
|
+
// string that counts ITEMS here does one of two things rather than write
|
|
322
|
+
// "{{count}} <noun>" and be wrong at most counts. Either the number goes LAST,
|
|
323
|
+
// after a colon, so no noun has to agree with it (`mention.available`,
|
|
324
|
+
// `validation.minlength` / `.maxlength` / `.cvc`), or the noun is dropped: the
|
|
325
|
+
// overflow chips in `select`, `tree` and `eventCalendar` read
|
|
326
|
+
// «+{{count}} أخرى», the invariable feminine-singular form a non-human plural
|
|
327
|
+
// takes, leaving nothing for the count to inflect. `lineChart.thousands` is
|
|
328
|
+
// the one string that can do neither, and the note there says why.
|
|
329
|
+
marquee: {
|
|
330
|
+
label: 'شريط متحرك',
|
|
331
|
+
link: 'رابط',
|
|
332
|
+
},
|
|
333
|
+
mention: {
|
|
334
|
+
listbox: 'الإشارات',
|
|
335
|
+
available: 'المطابقات المتاحة: {{count}}',
|
|
336
|
+
inserted: 'تم الإدراج: {{label}}',
|
|
337
|
+
},
|
|
338
|
+
drawer: {
|
|
339
|
+
close: 'إغلاق اللوحة',
|
|
340
|
+
},
|
|
341
|
+
datePicker: {
|
|
342
|
+
open: 'فتح التقويم',
|
|
343
|
+
openTime: 'فتح منتقي الوقت',
|
|
344
|
+
openDateTime: 'فتح منتقي التاريخ والوقت',
|
|
345
|
+
openRange: 'فتح تقويم الفترة',
|
|
346
|
+
panel: 'اختيار التاريخ',
|
|
347
|
+
panelTime: 'اختيار الوقت',
|
|
348
|
+
panelDateTime: 'اختيار التاريخ والوقت',
|
|
349
|
+
panelRange: 'اختيار الفترة',
|
|
350
|
+
panelRangeDateTime: 'اختيار الفترة بالتاريخ والوقت',
|
|
351
|
+
rangeStart: 'بداية الفترة',
|
|
352
|
+
rangeEnd: 'نهاية الفترة',
|
|
353
|
+
startTime: 'وقت البدء',
|
|
354
|
+
endTime: 'وقت الانتهاء',
|
|
355
|
+
hours: 'الساعات',
|
|
356
|
+
minutes: 'الدقائق',
|
|
357
|
+
seconds: 'الثواني',
|
|
358
|
+
incrementHours: 'زيادة الساعات',
|
|
359
|
+
decrementHours: 'إنقاص الساعات',
|
|
360
|
+
incrementMinutes: 'زيادة الدقائق',
|
|
361
|
+
decrementMinutes: 'إنقاص الدقائق',
|
|
362
|
+
incrementSeconds: 'زيادة الثواني',
|
|
363
|
+
decrementSeconds: 'إنقاص الثواني',
|
|
364
|
+
toggleAmPm: 'تبديل ص / م',
|
|
365
|
+
am: 'ص',
|
|
366
|
+
pm: 'م',
|
|
367
|
+
},
|
|
368
|
+
sidebar: {
|
|
369
|
+
label: 'الشريط الجانبي',
|
|
370
|
+
},
|
|
371
|
+
spinner: {
|
|
372
|
+
label: 'جارٍ التحميل',
|
|
373
|
+
},
|
|
374
|
+
rating: {
|
|
375
|
+
label: 'التقييم',
|
|
376
|
+
},
|
|
377
|
+
gauge: {
|
|
378
|
+
label: 'عداد',
|
|
379
|
+
},
|
|
380
|
+
progress: {
|
|
381
|
+
label: 'التقدم',
|
|
382
|
+
},
|
|
383
|
+
meterGroup: {
|
|
384
|
+
label: 'مقياس',
|
|
385
|
+
},
|
|
386
|
+
knob: {
|
|
387
|
+
label: 'القيمة',
|
|
388
|
+
},
|
|
389
|
+
slider: {
|
|
390
|
+
label: 'القيمة',
|
|
391
|
+
lower: 'القيمة الدنيا',
|
|
392
|
+
upper: 'القيمة العليا',
|
|
393
|
+
},
|
|
394
|
+
speedDial: {
|
|
395
|
+
label: 'الإجراءات',
|
|
396
|
+
},
|
|
397
|
+
statistic: {
|
|
398
|
+
delta: '{{value}}{{suffix}}',
|
|
399
|
+
deltaSuffix: '%',
|
|
400
|
+
},
|
|
401
|
+
result: {
|
|
402
|
+
notFound: 'عذرًا، الصفحة التي زرتها غير موجودة.',
|
|
403
|
+
forbidden: 'عذرًا، ليس لديك إذن بالوصول إلى هذه الصفحة.',
|
|
404
|
+
serverError: 'عذرًا، حدث خطأ ما.',
|
|
405
|
+
},
|
|
406
|
+
date: {
|
|
407
|
+
months: {
|
|
408
|
+
jan: 'يناير',
|
|
409
|
+
feb: 'فبراير',
|
|
410
|
+
mar: 'مارس',
|
|
411
|
+
apr: 'أبريل',
|
|
412
|
+
may: 'مايو',
|
|
413
|
+
jun: 'يونيو',
|
|
414
|
+
jul: 'يوليو',
|
|
415
|
+
aug: 'أغسطس',
|
|
416
|
+
sep: 'سبتمبر',
|
|
417
|
+
oct: 'أكتوبر',
|
|
418
|
+
nov: 'نوفمبر',
|
|
419
|
+
dec: 'ديسمبر',
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Generated bundle index. Do not edit.
|
|
426
|
+
*/
|
|
427
|
+
|
|
428
|
+
export { wrAr };
|
|
429
|
+
//# sourceMappingURL=ngwr-i18n-ar.mjs.map
|