@xui/form-field 2.0.0-alpha.20 → 2.0.0-alpha.21
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.
|
@@ -4,7 +4,18 @@ import { xui, createXConfigToken } from '@xui/core';
|
|
|
4
4
|
import { XFormFieldControl } from '@xui/core/form-field';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* A validation message for the control in a `xui-form-field`.
|
|
9
|
+
*
|
|
10
|
+
* ```html
|
|
11
|
+
* <xui-error>Enter a valid address.</xui-error>
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Project it into the field and it replaces the hint and helper text — but only while the control's
|
|
15
|
+
* error state is actually set, so it can be written unconditionally and needs no `@if`.
|
|
16
|
+
*/
|
|
7
17
|
class XuiError {
|
|
18
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
8
19
|
class = input('', /* @ts-ignore */
|
|
9
20
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
10
21
|
computedClass = computed(() => xui('block text-error text-sm font-medium', this.class()), /* @ts-ignore */
|
|
@@ -53,13 +64,32 @@ const formFieldColorText = cva('', {
|
|
|
53
64
|
},
|
|
54
65
|
defaultVariants: { color: 'none' }
|
|
55
66
|
});
|
|
67
|
+
/**
|
|
68
|
+
* Wraps a control with its label, helper text and validation message, and wires the three together.
|
|
69
|
+
*
|
|
70
|
+
* ```html
|
|
71
|
+
* <xui-form-field label="Email" labelInfo="(required)" helperText="We never share it.">
|
|
72
|
+
* <input xuiInput [formControl]="email" />
|
|
73
|
+
* <xui-error>Enter a valid address.</xui-error>
|
|
74
|
+
* </xui-form-field>
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* It finds the projected control through `XFormFieldControl`, so any xUI control registered under that
|
|
78
|
+
* token works — input, textarea, select, numeric-input, file-input, html-select. The `<label for>` is
|
|
79
|
+
* pointed at the real focusable element (the control's `controlId` when it wraps an inner input, else
|
|
80
|
+
* its host, which the field gives an id if it has none), and the projected `xui-error` replaces the
|
|
81
|
+
* hint only while the control actually reports an error. Throws if it contains no control.
|
|
82
|
+
*/
|
|
56
83
|
class XuiFormField {
|
|
57
84
|
config = injectXuiFormFieldConfig();
|
|
85
|
+
/** The projected control, found through `XFormFieldControl`. Read-only; the field throws if there is none. */
|
|
58
86
|
control = contentChild(XFormFieldControl, /* @ts-ignore */
|
|
59
87
|
...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
|
|
60
88
|
controlEl = contentChild(XFormFieldControl, { ...(ngDevMode ? { debugName: "controlEl" } : /* istanbul ignore next */ {}), read: ElementRef });
|
|
89
|
+
/** The projected `xui-error` messages. Shown in place of the hint while the control reports an error. */
|
|
61
90
|
errorChildren = contentChildren(XuiError, /* @ts-ignore */
|
|
62
91
|
...(ngDevMode ? [{ debugName: "errorChildren" }] : /* istanbul ignore next */ []));
|
|
92
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
63
93
|
class = input('', /* @ts-ignore */
|
|
64
94
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
65
95
|
/** The primary label rendered above (or beside, when `inline`) the control. */
|
|
@@ -202,7 +232,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
202
232
|
}]
|
|
203
233
|
}], ctorParameters: () => [], propDecorators: { control: [{ type: i0.ContentChild, args: [i0.forwardRef(() => XFormFieldControl), { isSignal: true }] }], controlEl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => XFormFieldControl), { ...{ read: ElementRef }, isSignal: true }] }], errorChildren: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => XuiError), { isSignal: true }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelInfo", required: false }] }], subLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "subLabel", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }] } });
|
|
204
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Supporting text under the control in a `xui-form-field`.
|
|
237
|
+
*
|
|
238
|
+
* ```html
|
|
239
|
+
* <xui-hint>Use the address you signed up with.</xui-hint>
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* The projected form of the field's `helperText` input, for hints that need markup rather than a plain
|
|
243
|
+
* string. Hidden while a `xui-error` is showing.
|
|
244
|
+
*/
|
|
205
245
|
class XuiHint {
|
|
246
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
206
247
|
class = input('', /* @ts-ignore */
|
|
207
248
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
208
249
|
computedClass = computed(() => xui('block text-sm text-foreground-subtle', this.class()), /* @ts-ignore */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xui-form-field.mjs","sources":["../../../../../../libs/ui/form-field/xui/src/lib/error.ts","../../../../../../libs/ui/form-field/xui/src/lib/form-field.token.ts","../../../../../../libs/ui/form-field/xui/src/lib/form-field.ts","../../../../../../libs/ui/form-field/xui/src/lib/hint.ts","../../../../../../libs/ui/form-field/xui/src/index.ts","../../../../../../libs/ui/form-field/xui/src/xui-form-field.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { xui } from '@xui/core';\nimport type { ClassValue } from 'clsx';\n\n@Component({\n selector: 'xui-error',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: '<ng-content />',\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiError {\n readonly class = input<ClassValue>('');\n\n protected computedClass = computed(() => xui('block text-error text-sm font-medium', this.class()));\n}\n","import { createXConfigToken } from '@xui/core';\nimport { XuiFormFieldColor } from './form-field';\n\nexport interface XuiFormFieldConfig {\n color: XuiFormFieldColor;\n inline: boolean;\n}\n\nexport const [injectXuiFormFieldConfig, provideXuiFormFieldConfig] = createXConfigToken<XuiFormFieldConfig>(\n 'XuiFormFieldConfig',\n {\n color: 'none',\n inline: false\n }\n);\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n contentChildren,\n effect,\n ElementRef,\n input,\n ViewEncapsulation\n} from '@angular/core';\nimport { xui } from '@xui/core';\nimport { XFormFieldControl } from '@xui/core/form-field';\nimport { cva, VariantProps } from 'class-variance-authority';\nimport type { ClassValue } from 'clsx';\nimport { XuiError } from './error';\nimport { injectXuiFormFieldConfig } from './form-field.token';\n\nlet nextId = 0;\n\nexport const formFieldRootVariants = cva('', {\n variants: {\n inline: {\n false: 'block space-y-2',\n true: 'flex items-baseline gap-3'\n }\n },\n defaultVariants: { inline: false }\n});\n\n/** `color` tints the label and helper text with a deliberate accent. */\nexport const formFieldColorText = cva('', {\n variants: {\n color: {\n none: '',\n primary: 'text-primary',\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error'\n }\n },\n defaultVariants: { color: 'none' }\n});\n\nexport type XuiFormFieldColor = NonNullable<VariantProps<typeof formFieldColorText>['color']>;\n\n@Component({\n selector: 'xui-form-field',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: `\n @if (label() || subLabel()) {\n <div [class]=\"inline() ? 'shrink-0' : ''\">\n @if (label()) {\n <label [attr.for]=\"labelFor()\" [class]=\"labelClass()\">\n {{ label() }}\n @if (labelInfo()) {\n <span class=\"text-foreground-subtle font-normal\">{{ labelInfo() }}</span>\n }\n </label>\n }\n @if (subLabel()) {\n <span class=\"text-foreground-muted block text-xs\">{{ subLabel() }}</span>\n }\n </div>\n }\n\n <div [class]=\"inline() ? 'flex-1 space-y-1.5' : 'space-y-1.5'\">\n <ng-content />\n\n @switch (hasDisplayedMessage()) {\n @case ('error') {\n <ng-content select=\"xui-error\" />\n }\n @default {\n <ng-content select=\"xui-hint\" />\n @if (helperText()) {\n <span [class]=\"helperClass()\">{{ helperText() }}</span>\n }\n }\n }\n </div>\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiFormField {\n private readonly config = injectXuiFormFieldConfig();\n\n readonly control = contentChild(XFormFieldControl);\n private readonly controlEl = contentChild(XFormFieldControl, { read: ElementRef });\n readonly errorChildren = contentChildren(XuiError);\n\n readonly class = input<ClassValue>('');\n\n /** The primary label rendered above (or beside, when `inline`) the control. */\n readonly label = input<string>('');\n\n /** Secondary text shown next to the label, e.g. \"(optional)\". */\n readonly labelInfo = input<string>('');\n\n /** A smaller description under the label. */\n readonly subLabel = input<string>('');\n\n /** Muted helper text under the control, hidden while an error is shown. */\n readonly helperText = input<string>('');\n\n /** A deliberate accent for the label and helper text. */\n readonly color = input<XuiFormFieldColor>(this.config.color);\n\n /** Lay the label beside the control rather than above it. */\n readonly inline = input<boolean, BooleanInput>(this.config.inline, { transform: booleanAttribute });\n\n private readonly generatedId = `xui-form-field-${nextId++}`;\n\n protected readonly computedClass = computed(() =>\n xui(formFieldRootVariants({ inline: this.inline() }), this.class())\n );\n\n protected readonly labelClass = computed(() =>\n xui('text-foreground block text-sm font-medium', formFieldColorText({ color: this.color() }))\n );\n\n protected readonly helperClass = computed(() =>\n xui('block text-sm text-foreground-subtle', formFieldColorText({ color: this.color() }))\n );\n\n /**\n * The id the `<label>` points at — the control's declared `controlId` when it\n * has one (the focusable element inside a wrapping component), else the host\n * element's own id, else the id we assign below. The fallback branches agree\n * with the effect's assignment.\n */\n protected readonly labelFor = computed(() => {\n if (!this.label()) {\n return null;\n }\n\n const providedId = this.control()?.controlId?.();\n\n if (providedId) {\n return providedId;\n }\n\n const el = this.controlEl()?.nativeElement as HTMLElement | undefined;\n return el?.id || this.generatedId;\n });\n\n protected readonly hasDisplayedMessage = computed<'error' | 'hint'>(() =>\n this.errorChildren() && this.errorChildren().length > 0 && this.control()?.errorState() ? 'error' : 'hint'\n );\n\n constructor() {\n effect(() => {\n if (!this.control()) {\n throw new Error('xui-form-field must contain an XFormFieldControl.');\n }\n });\n\n // Give the projected control our generated id (unless it already has one, or\n // it points the label at an inner element via `controlId`) so the rendered\n // <label for> genuinely points at it.\n effect(() => {\n const el = this.controlEl()?.nativeElement as HTMLElement | undefined;\n if (this.label() && el && !el.id && !this.control()?.controlId?.()) {\n el.id = this.generatedId;\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { xui } from '@xui/core';\nimport type { ClassValue } from 'clsx';\n\n@Component({\n selector: 'xui-hint',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: '<ng-content />',\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiHint {\n readonly class = input<ClassValue>('');\n\n protected computedClass = computed(() => xui('block text-sm text-foreground-subtle', this.class()));\n}\n","import { XuiError } from './lib/error';\nimport { XuiFormField } from './lib/form-field';\nimport { XuiHint } from './lib/hint';\nexport * from './lib/error';\nexport * from './lib/form-field';\nexport * from './lib/form-field.token';\nexport * from './lib/hint';\n\nexport const XuiFormFieldImports = [XuiFormField, XuiError, XuiHint] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"xui-form-field.mjs","sources":["../../../../../../libs/ui/form-field/xui/src/lib/error.ts","../../../../../../libs/ui/form-field/xui/src/lib/form-field.token.ts","../../../../../../libs/ui/form-field/xui/src/lib/form-field.ts","../../../../../../libs/ui/form-field/xui/src/lib/hint.ts","../../../../../../libs/ui/form-field/xui/src/index.ts","../../../../../../libs/ui/form-field/xui/src/xui-form-field.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { xui } from '@xui/core';\nimport type { ClassValue } from 'clsx';\n\n/**\n * A validation message for the control in a `xui-form-field`.\n *\n * ```html\n * <xui-error>Enter a valid address.</xui-error>\n * ```\n *\n * Project it into the field and it replaces the hint and helper text — but only while the control's\n * error state is actually set, so it can be written unconditionally and needs no `@if`.\n */\n@Component({\n selector: 'xui-error',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: '<ng-content />',\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiError {\n /** Extra classes, merged into the component's own rather than replacing them. */\n readonly class = input<ClassValue>('');\n\n protected computedClass = computed(() => xui('block text-error text-sm font-medium', this.class()));\n}\n","import { createXConfigToken } from '@xui/core';\nimport { XuiFormFieldColor } from './form-field';\n\nexport interface XuiFormFieldConfig {\n color: XuiFormFieldColor;\n inline: boolean;\n}\n\nexport const [injectXuiFormFieldConfig, provideXuiFormFieldConfig] = createXConfigToken<XuiFormFieldConfig>(\n 'XuiFormFieldConfig',\n {\n color: 'none',\n inline: false\n }\n);\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n contentChildren,\n effect,\n ElementRef,\n input,\n ViewEncapsulation\n} from '@angular/core';\nimport { xui } from '@xui/core';\nimport { XFormFieldControl } from '@xui/core/form-field';\nimport { cva, VariantProps } from 'class-variance-authority';\nimport type { ClassValue } from 'clsx';\nimport { XuiError } from './error';\nimport { injectXuiFormFieldConfig } from './form-field.token';\n\nlet nextId = 0;\n\nexport const formFieldRootVariants = cva('', {\n variants: {\n inline: {\n false: 'block space-y-2',\n true: 'flex items-baseline gap-3'\n }\n },\n defaultVariants: { inline: false }\n});\n\n/** `color` tints the label and helper text with a deliberate accent. */\nexport const formFieldColorText = cva('', {\n variants: {\n color: {\n none: '',\n primary: 'text-primary',\n success: 'text-success',\n warning: 'text-warning',\n error: 'text-error'\n }\n },\n defaultVariants: { color: 'none' }\n});\n\nexport type XuiFormFieldColor = NonNullable<VariantProps<typeof formFieldColorText>['color']>;\n\n/**\n * Wraps a control with its label, helper text and validation message, and wires the three together.\n *\n * ```html\n * <xui-form-field label=\"Email\" labelInfo=\"(required)\" helperText=\"We never share it.\">\n * <input xuiInput [formControl]=\"email\" />\n * <xui-error>Enter a valid address.</xui-error>\n * </xui-form-field>\n * ```\n *\n * It finds the projected control through `XFormFieldControl`, so any xUI control registered under that\n * token works — input, textarea, select, numeric-input, file-input, html-select. The `<label for>` is\n * pointed at the real focusable element (the control's `controlId` when it wraps an inner input, else\n * its host, which the field gives an id if it has none), and the projected `xui-error` replaces the\n * hint only while the control actually reports an error. Throws if it contains no control.\n */\n@Component({\n selector: 'xui-form-field',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: `\n @if (label() || subLabel()) {\n <div [class]=\"inline() ? 'shrink-0' : ''\">\n @if (label()) {\n <label [attr.for]=\"labelFor()\" [class]=\"labelClass()\">\n {{ label() }}\n @if (labelInfo()) {\n <span class=\"text-foreground-subtle font-normal\">{{ labelInfo() }}</span>\n }\n </label>\n }\n @if (subLabel()) {\n <span class=\"text-foreground-muted block text-xs\">{{ subLabel() }}</span>\n }\n </div>\n }\n\n <div [class]=\"inline() ? 'flex-1 space-y-1.5' : 'space-y-1.5'\">\n <ng-content />\n\n @switch (hasDisplayedMessage()) {\n @case ('error') {\n <ng-content select=\"xui-error\" />\n }\n @default {\n <ng-content select=\"xui-hint\" />\n @if (helperText()) {\n <span [class]=\"helperClass()\">{{ helperText() }}</span>\n }\n }\n }\n </div>\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiFormField {\n private readonly config = injectXuiFormFieldConfig();\n\n /** The projected control, found through `XFormFieldControl`. Read-only; the field throws if there is none. */\n readonly control = contentChild(XFormFieldControl);\n private readonly controlEl = contentChild(XFormFieldControl, { read: ElementRef });\n /** The projected `xui-error` messages. Shown in place of the hint while the control reports an error. */\n readonly errorChildren = contentChildren(XuiError);\n\n /** Extra classes, merged into the component's own rather than replacing them. */\n readonly class = input<ClassValue>('');\n\n /** The primary label rendered above (or beside, when `inline`) the control. */\n readonly label = input<string>('');\n\n /** Secondary text shown next to the label, e.g. \"(optional)\". */\n readonly labelInfo = input<string>('');\n\n /** A smaller description under the label. */\n readonly subLabel = input<string>('');\n\n /** Muted helper text under the control, hidden while an error is shown. */\n readonly helperText = input<string>('');\n\n /** A deliberate accent for the label and helper text. */\n readonly color = input<XuiFormFieldColor>(this.config.color);\n\n /** Lay the label beside the control rather than above it. */\n readonly inline = input<boolean, BooleanInput>(this.config.inline, { transform: booleanAttribute });\n\n private readonly generatedId = `xui-form-field-${nextId++}`;\n\n protected readonly computedClass = computed(() =>\n xui(formFieldRootVariants({ inline: this.inline() }), this.class())\n );\n\n protected readonly labelClass = computed(() =>\n xui('text-foreground block text-sm font-medium', formFieldColorText({ color: this.color() }))\n );\n\n protected readonly helperClass = computed(() =>\n xui('block text-sm text-foreground-subtle', formFieldColorText({ color: this.color() }))\n );\n\n /**\n * The id the `<label>` points at — the control's declared `controlId` when it\n * has one (the focusable element inside a wrapping component), else the host\n * element's own id, else the id we assign below. The fallback branches agree\n * with the effect's assignment.\n */\n protected readonly labelFor = computed(() => {\n if (!this.label()) {\n return null;\n }\n\n const providedId = this.control()?.controlId?.();\n\n if (providedId) {\n return providedId;\n }\n\n const el = this.controlEl()?.nativeElement as HTMLElement | undefined;\n return el?.id || this.generatedId;\n });\n\n protected readonly hasDisplayedMessage = computed<'error' | 'hint'>(() =>\n this.errorChildren() && this.errorChildren().length > 0 && this.control()?.errorState() ? 'error' : 'hint'\n );\n\n constructor() {\n effect(() => {\n if (!this.control()) {\n throw new Error('xui-form-field must contain an XFormFieldControl.');\n }\n });\n\n // Give the projected control our generated id (unless it already has one, or\n // it points the label at an inner element via `controlId`) so the rendered\n // <label for> genuinely points at it.\n effect(() => {\n const el = this.controlEl()?.nativeElement as HTMLElement | undefined;\n if (this.label() && el && !el.id && !this.control()?.controlId?.()) {\n el.id = this.generatedId;\n }\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';\nimport { xui } from '@xui/core';\nimport type { ClassValue } from 'clsx';\n\n/**\n * Supporting text under the control in a `xui-form-field`.\n *\n * ```html\n * <xui-hint>Use the address you signed up with.</xui-hint>\n * ```\n *\n * The projected form of the field's `helperText` input, for hints that need markup rather than a plain\n * string. Hidden while a `xui-error` is showing.\n */\n@Component({\n selector: 'xui-hint',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: '<ng-content />',\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiHint {\n /** Extra classes, merged into the component's own rather than replacing them. */\n readonly class = input<ClassValue>('');\n\n protected computedClass = computed(() => xui('block text-sm text-foreground-subtle', this.class()));\n}\n","import { XuiError } from './lib/error';\nimport { XuiFormField } from './lib/form-field';\nimport { XuiHint } from './lib/hint';\nexport * from './lib/error';\nexport * from './lib/form-field';\nexport * from './lib/form-field.token';\nexport * from './lib/hint';\n\nexport const XuiFormFieldImports = [XuiFormField, XuiError, XuiHint] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xui/form-field",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.21",
|
|
4
4
|
"description": "Modern Angular 22 UI Library based on TailwindCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@angular/cdk": "22",
|
|
40
40
|
"@angular/core": "22",
|
|
41
|
-
"@xui/core": "2.0.0-alpha.
|
|
41
|
+
"@xui/core": "2.0.0-alpha.21",
|
|
42
42
|
"class-variance-authority": "^0.7.1",
|
|
43
43
|
"clsx": "^2.1.1"
|
|
44
44
|
},
|
|
@@ -5,7 +5,18 @@ import { BooleanInput } from '@angular/cdk/coercion';
|
|
|
5
5
|
import { XFormFieldControl } from '@xui/core/form-field';
|
|
6
6
|
import { VariantProps } from 'class-variance-authority';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* A validation message for the control in a `xui-form-field`.
|
|
10
|
+
*
|
|
11
|
+
* ```html
|
|
12
|
+
* <xui-error>Enter a valid address.</xui-error>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Project it into the field and it replaces the hint and helper text — but only while the control's
|
|
16
|
+
* error state is actually set, so it can be written unconditionally and needs no `@if`.
|
|
17
|
+
*/
|
|
8
18
|
declare class XuiError {
|
|
19
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
9
20
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
10
21
|
protected computedClass: _angular_core.Signal<string>;
|
|
11
22
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<XuiError, never>;
|
|
@@ -20,11 +31,30 @@ declare const formFieldColorText: (props?: ({
|
|
|
20
31
|
color?: "none" | "primary" | "success" | "warning" | "error" | null | undefined;
|
|
21
32
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
22
33
|
type XuiFormFieldColor = NonNullable<VariantProps<typeof formFieldColorText>['color']>;
|
|
34
|
+
/**
|
|
35
|
+
* Wraps a control with its label, helper text and validation message, and wires the three together.
|
|
36
|
+
*
|
|
37
|
+
* ```html
|
|
38
|
+
* <xui-form-field label="Email" labelInfo="(required)" helperText="We never share it.">
|
|
39
|
+
* <input xuiInput [formControl]="email" />
|
|
40
|
+
* <xui-error>Enter a valid address.</xui-error>
|
|
41
|
+
* </xui-form-field>
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* It finds the projected control through `XFormFieldControl`, so any xUI control registered under that
|
|
45
|
+
* token works — input, textarea, select, numeric-input, file-input, html-select. The `<label for>` is
|
|
46
|
+
* pointed at the real focusable element (the control's `controlId` when it wraps an inner input, else
|
|
47
|
+
* its host, which the field gives an id if it has none), and the projected `xui-error` replaces the
|
|
48
|
+
* hint only while the control actually reports an error. Throws if it contains no control.
|
|
49
|
+
*/
|
|
23
50
|
declare class XuiFormField {
|
|
24
51
|
private readonly config;
|
|
52
|
+
/** The projected control, found through `XFormFieldControl`. Read-only; the field throws if there is none. */
|
|
25
53
|
readonly control: _angular_core.Signal<XFormFieldControl | undefined>;
|
|
26
54
|
private readonly controlEl;
|
|
55
|
+
/** The projected `xui-error` messages. Shown in place of the hint while the control reports an error. */
|
|
27
56
|
readonly errorChildren: _angular_core.Signal<readonly XuiError[]>;
|
|
57
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
28
58
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
29
59
|
/** The primary label rendered above (or beside, when `inline`) the control. */
|
|
30
60
|
readonly label: _angular_core.InputSignal<string>;
|
|
@@ -55,7 +85,18 @@ declare class XuiFormField {
|
|
|
55
85
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<XuiFormField, "xui-form-field", never, { "class": { "alias": "class"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelInfo": { "alias": "labelInfo"; "required": false; "isSignal": true; }; "subLabel": { "alias": "subLabel"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "inline": { "alias": "inline"; "required": false; "isSignal": true; }; }, {}, ["control", "controlEl", "errorChildren"], ["*", "xui-error", "xui-hint"], true, never>;
|
|
56
86
|
}
|
|
57
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Supporting text under the control in a `xui-form-field`.
|
|
90
|
+
*
|
|
91
|
+
* ```html
|
|
92
|
+
* <xui-hint>Use the address you signed up with.</xui-hint>
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* The projected form of the field's `helperText` input, for hints that need markup rather than a plain
|
|
96
|
+
* string. Hidden while a `xui-error` is showing.
|
|
97
|
+
*/
|
|
58
98
|
declare class XuiHint {
|
|
99
|
+
/** Extra classes, merged into the component's own rather than replacing them. */
|
|
59
100
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
60
101
|
protected computedClass: _angular_core.Signal<string>;
|
|
61
102
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<XuiHint, never>;
|