@xui/html-select 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.
|
@@ -50,8 +50,10 @@ class XuiHtmlSelect {
|
|
|
50
50
|
/** The user-defined classes on the wrapper. Merged last so they win. */
|
|
51
51
|
class = input('', /* @ts-ignore */
|
|
52
52
|
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
53
|
+
/** Control height, from the shared control scale. */
|
|
53
54
|
size = input(this.config.size, /* @ts-ignore */
|
|
54
55
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
56
|
+
/** Stretch to the available width instead of hugging its contents. */
|
|
55
57
|
fill = input(this.config.fill, { ...(ngDevMode ? { debugName: "fill" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
56
58
|
/** Options as data; alternatively, project `<option>` elements. */
|
|
57
59
|
options = input([], /* @ts-ignore */
|
|
@@ -59,7 +61,9 @@ class XuiHtmlSelect {
|
|
|
59
61
|
/** A leading, unselectable prompt shown when nothing is chosen. */
|
|
60
62
|
placeholder = input(null, /* @ts-ignore */
|
|
61
63
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
64
|
+
/** Accessible name for the select, when no `<label>` points at it. */
|
|
62
65
|
ariaLabel = input(null, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
66
|
+
/** Block interaction and dim the control. */
|
|
63
67
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
64
68
|
value = signal(null, /* @ts-ignore */
|
|
65
69
|
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xui-html-select.mjs","sources":["../../../../../../libs/ui/html-select/xui/src/lib/html-select.token.ts","../../../../../../libs/ui/html-select/xui/src/lib/html-select.ts","../../../../../../libs/ui/html-select/xui/src/index.ts","../../../../../../libs/ui/html-select/xui/src/xui-html-select.ts"],"sourcesContent":["import { createXConfigToken } from '@xui/core';\nimport { XuiHtmlSelectVariants } from './html-select';\n\nexport interface XuiHtmlSelectConfig {\n size: XuiHtmlSelectVariants['size'];\n fill: boolean;\n}\n\nexport const [injectXuiHtmlSelectConfig, provideXuiHtmlSelectConfig] = createXConfigToken<XuiHtmlSelectConfig>(\n 'XuiHtmlSelectConfig',\n {\n size: 'md',\n fill: false\n }\n);\n","import type { BooleanInput } from '@angular/cdk/coercion';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n forwardRef,\n input,\n signal,\n type Signal\n} from '@angular/core';\nimport { ControlValueAccessor, type NgControl } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matExpandMoreRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { uniqueId } from '@xui/core/a11y';\nimport { XFormFieldControl } from '@xui/core/form-field';\nimport { createXErrorState, createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { XuiIcon } from '@xui/icon';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { ClassValue } from 'clsx';\nimport { injectXuiHtmlSelectConfig } from './html-select.token';\n\nexport const htmlSelectWrapperVariants = cva(\n 'border-border bg-surface-inset text-foreground focus-within:border-focus relative inline-flex items-center rounded-lg border transition-colors has-disabled:cursor-not-allowed has-disabled:opacity-50',\n {\n variants: {\n size: { md: 'h-(--control-height-md) text-sm', sm: 'h-(--control-height-sm) text-xs' },\n fill: { true: 'w-full', false: 'w-auto' }\n },\n defaultVariants: { size: 'md', fill: false }\n }\n);\n\nexport type XuiHtmlSelectVariants = VariantProps<typeof htmlSelectWrapperVariants>;\n\n/** One `<option>` when the options come as data rather than projected markup. */\nexport interface XuiHtmlSelectOption<T = string> {\n value: T;\n label: string;\n disabled?: boolean;\n}\n\n/**\n * A styled native `<select>`.\n *\n * ```html\n * <xui-html-select [(ngModel)]=\"sort\" [options]=\"['Newest', 'Oldest']\" />\n * <xui-html-select [(ngModel)]=\"env\">\n * <option value=\"dev\">Development</option>\n * </xui-html-select>\n * ```\n *\n * The real `<select>` underneath keeps the platform's dropdown, keyboard and\n * mobile behaviour — this only frames it and adds the chevron. Give it options\n * as data, or project `<option>` elements. It is a `ControlValueAccessor`, so\n * forms bind straight to it.\n */\n@Component({\n selector: 'xui-html-select',\n imports: [NgIcon, XuiIcon],\n viewProviders: [provideIcons({ matExpandMoreRound })],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [\n provideXValueAccessor(() => XuiHtmlSelect),\n {\n provide: XFormFieldControl,\n useExisting: forwardRef(() => XuiHtmlSelect)\n }\n ],\n template: `\n <select\n #field\n [id]=\"fieldId\"\n [class]=\"selectClass()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n (change)=\"onSelect(field.value)\"\n (blur)=\"cva.markTouched()\"\n >\n @if (placeholder(); as ph) {\n <option value=\"\" disabled [selected]=\"value() === null || value() === ''\">{{ ph }}</option>\n }\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\" [selected]=\"option.value === value()\">\n {{ option.label }}\n </option>\n }\n <ng-content />\n </select>\n\n <ng-icon\n xui\n size=\"sm\"\n name=\"matExpandMoreRound\"\n class=\"text-foreground-muted pointer-events-none absolute end-2.5\"\n />\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiHtmlSelect<T = string> implements ControlValueAccessor, XFormFieldControl {\n private readonly config = injectXuiHtmlSelectConfig();\n private readonly formState = createXErrorState();\n protected readonly fieldId = uniqueId('xui-html-select');\n\n /** Error state for `xui-form-field`, derived from the optional bound form control. */\n readonly errorState = this.formState.errorState;\n\n /** Points the form field's `<label for>` at the native select, not the host. */\n readonly controlId: Signal<string | null> = signal(this.fieldId).asReadonly();\n\n get ngControl(): NgControl | null {\n return this.formState.ngControl();\n }\n\n /** The user-defined classes on the wrapper. Merged last so they win. */\n readonly class = input<ClassValue>('');\n readonly size = input<XuiHtmlSelectVariants['size']>(this.config.size);\n readonly fill = input<boolean, BooleanInput>(this.config.fill, { transform: booleanAttribute });\n\n /** Options as data; alternatively, project `<option>` elements. */\n readonly options = input<readonly XuiHtmlSelectOption<T>[]>([]);\n /** A leading, unselectable prompt shown when nothing is chosen. */\n readonly placeholder = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null, { alias: 'aria-label' });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly value = signal<T | string | null>(null);\n\n protected readonly cva = createXValueAccessor<T | string | null>({\n onWrite: value => this.value.set(value),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n protected readonly computedClass = computed(() =>\n xui(htmlSelectWrapperVariants({ size: this.size(), fill: this.fill() }), this.class())\n );\n protected readonly selectClass = computed(() =>\n xui(\n 'w-full cursor-pointer appearance-none bg-transparent pe-8 ps-2.5 outline-none disabled:cursor-not-allowed',\n this.size() === 'sm' ? 'h-(--control-height-sm)' : 'h-(--control-height-md)'\n )\n );\n\n protected onSelect(value: string): void {\n // Recover the original typed option value (number, object) when the choice\n // came from the data-driven `options`, since the DOM only carries strings.\n const original = this.options().find(option => String(option.value) === value);\n const next = original ? original.value : value;\n\n this.value.set(next);\n this.cva.notifyChange(next);\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiHtmlSelect } from './lib/html-select';\n\nexport * from './lib/html-select';\nexport * from './lib/html-select.token';\n\nexport const XuiHtmlSelectImports = [XuiHtmlSelect] 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-html-select.mjs","sources":["../../../../../../libs/ui/html-select/xui/src/lib/html-select.token.ts","../../../../../../libs/ui/html-select/xui/src/lib/html-select.ts","../../../../../../libs/ui/html-select/xui/src/index.ts","../../../../../../libs/ui/html-select/xui/src/xui-html-select.ts"],"sourcesContent":["import { createXConfigToken } from '@xui/core';\nimport { XuiHtmlSelectVariants } from './html-select';\n\nexport interface XuiHtmlSelectConfig {\n size: XuiHtmlSelectVariants['size'];\n fill: boolean;\n}\n\nexport const [injectXuiHtmlSelectConfig, provideXuiHtmlSelectConfig] = createXConfigToken<XuiHtmlSelectConfig>(\n 'XuiHtmlSelectConfig',\n {\n size: 'md',\n fill: false\n }\n);\n","import type { BooleanInput } from '@angular/cdk/coercion';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n forwardRef,\n input,\n signal,\n type Signal\n} from '@angular/core';\nimport { ControlValueAccessor, type NgControl } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matExpandMoreRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { uniqueId } from '@xui/core/a11y';\nimport { XFormFieldControl } from '@xui/core/form-field';\nimport { createXErrorState, createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { XuiIcon } from '@xui/icon';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type { ClassValue } from 'clsx';\nimport { injectXuiHtmlSelectConfig } from './html-select.token';\n\nexport const htmlSelectWrapperVariants = cva(\n 'border-border bg-surface-inset text-foreground focus-within:border-focus relative inline-flex items-center rounded-lg border transition-colors has-disabled:cursor-not-allowed has-disabled:opacity-50',\n {\n variants: {\n size: { md: 'h-(--control-height-md) text-sm', sm: 'h-(--control-height-sm) text-xs' },\n fill: { true: 'w-full', false: 'w-auto' }\n },\n defaultVariants: { size: 'md', fill: false }\n }\n);\n\nexport type XuiHtmlSelectVariants = VariantProps<typeof htmlSelectWrapperVariants>;\n\n/** One `<option>` when the options come as data rather than projected markup. */\nexport interface XuiHtmlSelectOption<T = string> {\n value: T;\n label: string;\n disabled?: boolean;\n}\n\n/**\n * A styled native `<select>`.\n *\n * ```html\n * <xui-html-select [(ngModel)]=\"sort\" [options]=\"['Newest', 'Oldest']\" />\n * <xui-html-select [(ngModel)]=\"env\">\n * <option value=\"dev\">Development</option>\n * </xui-html-select>\n * ```\n *\n * The real `<select>` underneath keeps the platform's dropdown, keyboard and\n * mobile behaviour — this only frames it and adds the chevron. Give it options\n * as data, or project `<option>` elements. It is a `ControlValueAccessor`, so\n * forms bind straight to it.\n */\n@Component({\n selector: 'xui-html-select',\n imports: [NgIcon, XuiIcon],\n viewProviders: [provideIcons({ matExpandMoreRound })],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [\n provideXValueAccessor(() => XuiHtmlSelect),\n {\n provide: XFormFieldControl,\n useExisting: forwardRef(() => XuiHtmlSelect)\n }\n ],\n template: `\n <select\n #field\n [id]=\"fieldId\"\n [class]=\"selectClass()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n (change)=\"onSelect(field.value)\"\n (blur)=\"cva.markTouched()\"\n >\n @if (placeholder(); as ph) {\n <option value=\"\" disabled [selected]=\"value() === null || value() === ''\">{{ ph }}</option>\n }\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\" [selected]=\"option.value === value()\">\n {{ option.label }}\n </option>\n }\n <ng-content />\n </select>\n\n <ng-icon\n xui\n size=\"sm\"\n name=\"matExpandMoreRound\"\n class=\"text-foreground-muted pointer-events-none absolute end-2.5\"\n />\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiHtmlSelect<T = string> implements ControlValueAccessor, XFormFieldControl {\n private readonly config = injectXuiHtmlSelectConfig();\n private readonly formState = createXErrorState();\n protected readonly fieldId = uniqueId('xui-html-select');\n\n /** Error state for `xui-form-field`, derived from the optional bound form control. */\n readonly errorState = this.formState.errorState;\n\n /** Points the form field's `<label for>` at the native select, not the host. */\n readonly controlId: Signal<string | null> = signal(this.fieldId).asReadonly();\n\n get ngControl(): NgControl | null {\n return this.formState.ngControl();\n }\n\n /** The user-defined classes on the wrapper. Merged last so they win. */\n readonly class = input<ClassValue>('');\n /** Control height, from the shared control scale. */\n readonly size = input<XuiHtmlSelectVariants['size']>(this.config.size);\n /** Stretch to the available width instead of hugging its contents. */\n readonly fill = input<boolean, BooleanInput>(this.config.fill, { transform: booleanAttribute });\n\n /** Options as data; alternatively, project `<option>` elements. */\n readonly options = input<readonly XuiHtmlSelectOption<T>[]>([]);\n /** A leading, unselectable prompt shown when nothing is chosen. */\n readonly placeholder = input<string | null>(null);\n /** Accessible name for the select, when no `<label>` points at it. */\n readonly ariaLabel = input<string | null>(null, { alias: 'aria-label' });\n\n /** Block interaction and dim the control. */\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly value = signal<T | string | null>(null);\n\n protected readonly cva = createXValueAccessor<T | string | null>({\n onWrite: value => this.value.set(value),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n protected readonly computedClass = computed(() =>\n xui(htmlSelectWrapperVariants({ size: this.size(), fill: this.fill() }), this.class())\n );\n protected readonly selectClass = computed(() =>\n xui(\n 'w-full cursor-pointer appearance-none bg-transparent pe-8 ps-2.5 outline-none disabled:cursor-not-allowed',\n this.size() === 'sm' ? 'h-(--control-height-sm)' : 'h-(--control-height-md)'\n )\n );\n\n protected onSelect(value: string): void {\n // Recover the original typed option value (number, object) when the choice\n // came from the data-driven `options`, since the DOM only carries strings.\n const original = this.options().find(option => String(option.value) === value);\n const next = original ? original.value : value;\n\n this.value.set(next);\n this.cva.notifyChange(next);\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiHtmlSelect } from './lib/html-select';\n\nexport * from './lib/html-select';\nexport * from './lib/html-select.token';\n\nexport const XuiHtmlSelectImports = [XuiHtmlSelect] 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/html-select",
|
|
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",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"@angular/forms": "22",
|
|
42
42
|
"@ng-icons/core": "34",
|
|
43
43
|
"@ng-icons/material-icons": "34",
|
|
44
|
-
"@xui/core": "2.0.0-alpha.
|
|
45
|
-
"@xui/icon": "2.0.0-alpha.
|
|
44
|
+
"@xui/core": "2.0.0-alpha.21",
|
|
45
|
+
"@xui/icon": "2.0.0-alpha.21",
|
|
46
46
|
"class-variance-authority": "^0.7.1",
|
|
47
47
|
"clsx": "^2.1.1"
|
|
48
48
|
},
|
|
@@ -45,13 +45,17 @@ declare class XuiHtmlSelect<T = string> implements ControlValueAccessor, XFormFi
|
|
|
45
45
|
get ngControl(): NgControl | null;
|
|
46
46
|
/** The user-defined classes on the wrapper. Merged last so they win. */
|
|
47
47
|
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
48
|
+
/** Control height, from the shared control scale. */
|
|
48
49
|
readonly size: _angular_core.InputSignal<"md" | "sm" | null | undefined>;
|
|
50
|
+
/** Stretch to the available width instead of hugging its contents. */
|
|
49
51
|
readonly fill: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
50
52
|
/** Options as data; alternatively, project `<option>` elements. */
|
|
51
53
|
readonly options: _angular_core.InputSignal<readonly XuiHtmlSelectOption<T>[]>;
|
|
52
54
|
/** A leading, unselectable prompt shown when nothing is chosen. */
|
|
53
55
|
readonly placeholder: _angular_core.InputSignal<string | null>;
|
|
56
|
+
/** Accessible name for the select, when no `<label>` points at it. */
|
|
54
57
|
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
58
|
+
/** Block interaction and dim the control. */
|
|
55
59
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
56
60
|
protected readonly value: _angular_core.WritableSignal<string | T | null>;
|
|
57
61
|
protected readonly cva: _xui_core_forms.XValueAccessor<string | T | null>;
|