@xui/numeric-input 2.0.0-alpha.15 → 2.0.0-alpha.17
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
CHANGED
|
@@ -127,7 +127,7 @@ The full token reference, rendered in both themes, is the **Design tokens** page
|
|
|
127
127
|
|
|
128
128
|
**Date & time** — [`@xui/date-input`](https://www.npmjs.com/package/@xui/date-input) · [`@xui/date-picker`](https://www.npmjs.com/package/@xui/date-picker) · [`@xui/date-range-input`](https://www.npmjs.com/package/@xui/date-range-input) · [`@xui/date-range-picker`](https://www.npmjs.com/package/@xui/date-range-picker) · [`@xui/time-picker`](https://www.npmjs.com/package/@xui/time-picker) · [`@xui/timezone-select`](https://www.npmjs.com/package/@xui/timezone-select)
|
|
129
129
|
|
|
130
|
-
**Data display** — [`@xui/avatar`](https://www.npmjs.com/package/@xui/avatar) · [`@xui/
|
|
130
|
+
**Data display** — [`@xui/avatar`](https://www.npmjs.com/package/@xui/avatar) · [`@xui/card`](https://www.npmjs.com/package/@xui/card) · [`@xui/card-list`](https://www.npmjs.com/package/@xui/card-list) · [`@xui/carousel`](https://www.npmjs.com/package/@xui/carousel) · [`@xui/data-table`](https://www.npmjs.com/package/@xui/data-table) · [`@xui/descriptions`](https://www.npmjs.com/package/@xui/descriptions) · [`@xui/entity-title`](https://www.npmjs.com/package/@xui/entity-title) · [`@xui/kbd`](https://www.npmjs.com/package/@xui/kbd) · [`@xui/statistic`](https://www.npmjs.com/package/@xui/statistic) · [`@xui/status`](https://www.npmjs.com/package/@xui/status) · [`@xui/table`](https://www.npmjs.com/package/@xui/table) · [`@xui/tag`](https://www.npmjs.com/package/@xui/tag) · [`@xui/timeline`](https://www.npmjs.com/package/@xui/timeline) · [`@xui/tree`](https://www.npmjs.com/package/@xui/tree)
|
|
131
131
|
|
|
132
132
|
**Navigation** — [`@xui/breadcrumb`](https://www.npmjs.com/package/@xui/breadcrumb) · [`@xui/menubar`](https://www.npmjs.com/package/@xui/menubar) · [`@xui/navbar`](https://www.npmjs.com/package/@xui/navbar) · [`@xui/navigation-menu`](https://www.npmjs.com/package/@xui/navigation-menu) · [`@xui/pagination`](https://www.npmjs.com/package/@xui/pagination) · [`@xui/panel-stack`](https://www.npmjs.com/package/@xui/panel-stack) · [`@xui/steps`](https://www.npmjs.com/package/@xui/steps) · [`@xui/tabs`](https://www.npmjs.com/package/@xui/tabs)
|
|
133
133
|
|
|
@@ -98,8 +98,18 @@ class XuiNumericInput {
|
|
|
98
98
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
99
99
|
fieldClass = computed(() => xui('text-foreground placeholder:text-foreground-subtle w-full min-w-0 bg-transparent tabular-nums outline-none', this.size() === 'sm' ? 'px-(--control-padding-sm) text-xs' : 'px-(--control-padding-md) text-sm'), /* @ts-ignore */
|
|
100
100
|
...(ngDevMode ? [{ debugName: "fieldClass" }] : /* istanbul ignore next */ []));
|
|
101
|
-
stepperColumnClass = computed(() => 'border-border flex shrink-0 flex-col
|
|
101
|
+
stepperColumnClass = computed(() => xui('border-border flex shrink-0 flex-col',
|
|
102
|
+
// The rule divides the steppers from the field, so it belongs on whichever edge faces it —
|
|
103
|
+
// on the outer edge it would just double up on the wrapper's own border.
|
|
104
|
+
this.buttonPosition() === 'left' ? 'border-e' : 'border-s'), /* @ts-ignore */
|
|
102
105
|
...(ngDevMode ? [{ debugName: "stepperColumnClass" }] : /* istanbul ignore next */ []));
|
|
106
|
+
/**
|
|
107
|
+
* The two steppers split the control height between them, so a glyph sized off the icon scale
|
|
108
|
+
* (`sm` is 16px) makes the column taller than the field — and the wrapper clips the overflow,
|
|
109
|
+
* taking the bottom arrow with it. Size to the row instead: half of 24px or 30px, less a hair.
|
|
110
|
+
*/
|
|
111
|
+
stepperIconSize = computed(() => (this.size() === 'sm' ? '10px' : '12px'), /* @ts-ignore */
|
|
112
|
+
...(ngDevMode ? [{ debugName: "stepperIconSize" }] : /* istanbul ignore next */ []));
|
|
103
113
|
stepperClass = computed(() => 'text-foreground-muted hover:bg-hover-overlay hover:text-foreground flex flex-1 items-center justify-center px-1.5 disabled:pointer-events-none disabled:opacity-40', /* @ts-ignore */
|
|
104
114
|
...(ngDevMode ? [{ debugName: "stepperClass" }] : /* istanbul ignore next */ []));
|
|
105
115
|
onInput(raw) {
|
|
@@ -213,7 +223,7 @@ class XuiNumericInput {
|
|
|
213
223
|
[disabled]="!canIncrement()"
|
|
214
224
|
(click)="step(stepSize())"
|
|
215
225
|
>
|
|
216
|
-
<ng-icon xui size="
|
|
226
|
+
<ng-icon xui [size]="stepperIconSize()" name="matKeyboardArrowUpRound" />
|
|
217
227
|
</button>
|
|
218
228
|
<button
|
|
219
229
|
type="button"
|
|
@@ -223,7 +233,7 @@ class XuiNumericInput {
|
|
|
223
233
|
[disabled]="!canDecrement()"
|
|
224
234
|
(click)="step(-stepSize())"
|
|
225
235
|
>
|
|
226
|
-
<ng-icon xui size="
|
|
236
|
+
<ng-icon xui [size]="stepperIconSize()" name="matKeyboardArrowDownRound" />
|
|
227
237
|
</button>
|
|
228
238
|
</div>
|
|
229
239
|
</ng-template>
|
|
@@ -282,7 +292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
282
292
|
[disabled]="!canIncrement()"
|
|
283
293
|
(click)="step(stepSize())"
|
|
284
294
|
>
|
|
285
|
-
<ng-icon xui size="
|
|
295
|
+
<ng-icon xui [size]="stepperIconSize()" name="matKeyboardArrowUpRound" />
|
|
286
296
|
</button>
|
|
287
297
|
<button
|
|
288
298
|
type="button"
|
|
@@ -292,7 +302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
292
302
|
[disabled]="!canDecrement()"
|
|
293
303
|
(click)="step(-stepSize())"
|
|
294
304
|
>
|
|
295
|
-
<ng-icon xui size="
|
|
305
|
+
<ng-icon xui [size]="stepperIconSize()" name="matKeyboardArrowDownRound" />
|
|
296
306
|
</button>
|
|
297
307
|
</div>
|
|
298
308
|
</ng-template>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xui-numeric-input.mjs","sources":["../../../../../../libs/ui/numeric-input/xui/src/lib/numeric-input.token.ts","../../../../../../libs/ui/numeric-input/xui/src/lib/numeric-input.ts","../../../../../../libs/ui/numeric-input/xui/src/index.ts","../../../../../../libs/ui/numeric-input/xui/src/xui-numeric-input.ts"],"sourcesContent":["import { createXConfigToken } from '@xui/core';\n\nexport type XuiNumericInputSize = 'md' | 'sm';\n/** Where the stepper buttons sit. */\nexport type XuiNumericButtonPosition = 'right' | 'left' | 'none';\n\nexport interface XuiNumericInputConfig {\n size: XuiNumericInputSize;\n buttonPosition: XuiNumericButtonPosition;\n /** Step applied by a click or ArrowUp/Down. */\n stepSize: number;\n /** Step when Shift is held — the coarse jump. */\n majorStepSize: number;\n /** Step when Alt is held — the fine nudge. */\n minorStepSize: number;\n /** Snap an out-of-range value back into [min, max] when focus leaves. */\n clampValueOnBlur: boolean;\n}\n\n/** Application-wide defaults for XuiNumericInput. */\nexport const [injectXuiNumericInputConfig, provideXuiNumericInputConfig] = createXConfigToken<XuiNumericInputConfig>(\n 'XuiNumericInputConfig',\n {\n size: 'md',\n buttonPosition: 'right',\n stepSize: 1,\n majorStepSize: 10,\n minorStepSize: 0.1,\n clampValueOnBlur: true\n }\n);\n","import type { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n forwardRef,\n input,\n linkedSignal,\n numberAttribute,\n signal,\n type Signal\n} from '@angular/core';\nimport { ControlValueAccessor, type NgControl } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matKeyboardArrowDownRound, matKeyboardArrowUpRound } 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 type { ClassValue } from 'clsx';\nimport {\n injectXuiNumericInputConfig,\n type XuiNumericButtonPosition,\n type XuiNumericInputSize\n} from './numeric-input.token';\n\n/**\n * A number field with stepper buttons and keyboard increment.\n *\n * ```html\n * <xui-numeric-input [(ngModel)]=\"quantity\" [min]=\"0\" [max]=\"99\" />\n * ```\n *\n * The value is a `number | null` (empty is `null`, not `0`, so \"no answer\" is\n * distinct from zero). ArrowUp/Down step by `stepSize`; Shift steps by\n * `majorStepSize`, Alt by `minorStepSize`. It is a `ControlValueAccessor`, so\n * forms bind to it directly, and it clamps into `[min, max]` on blur.\n */\n@Component({\n selector: 'xui-numeric-input',\n imports: [NgTemplateOutlet, NgIcon, XuiIcon],\n viewProviders: [provideIcons({ matKeyboardArrowUpRound, matKeyboardArrowDownRound })],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [\n provideXValueAccessor(() => XuiNumericInput),\n {\n provide: XFormFieldControl,\n useExisting: forwardRef(() => XuiNumericInput)\n }\n ],\n template: `\n @if (buttonPosition() === 'left') {\n <ng-container [ngTemplateOutlet]=\"steppers\" />\n }\n\n <input\n #field\n [id]=\"fieldId\"\n type=\"text\"\n inputmode=\"decimal\"\n [class]=\"fieldClass()\"\n [value]=\"display()\"\n [disabled]=\"isDisabled()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"spinbutton\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"min() ?? null\"\n [attr.aria-valuemax]=\"max() ?? null\"\n (input)=\"onInput(field.value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n\n @if (buttonPosition() === 'right') {\n <ng-container [ngTemplateOutlet]=\"steppers\" />\n }\n\n <ng-template #steppers>\n <div [class]=\"stepperColumnClass()\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Increment\"\n [class]=\"stepperClass()\"\n [disabled]=\"!canIncrement()\"\n (click)=\"step(stepSize())\"\n >\n <ng-icon xui size=\"sm\" name=\"matKeyboardArrowUpRound\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Decrement\"\n [class]=\"stepperClass()\"\n [disabled]=\"!canDecrement()\"\n (click)=\"step(-stepSize())\"\n >\n <ng-icon xui size=\"sm\" name=\"matKeyboardArrowDownRound\" />\n </button>\n </div>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiNumericInput implements ControlValueAccessor, XFormFieldControl {\n private readonly config = injectXuiNumericInputConfig();\n private readonly formState = createXErrorState();\n protected readonly fieldId = uniqueId('xui-numeric-input');\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 inner text field, 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<XuiNumericInputSize>(this.config.size);\n readonly buttonPosition = input<XuiNumericButtonPosition>(this.config.buttonPosition);\n\n readonly placeholder = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null, { alias: 'aria-label' });\n\n readonly min = input<number | undefined, NumberInput>(undefined, { transform: numberAttribute });\n readonly max = input<number | undefined, NumberInput>(undefined, { transform: numberAttribute });\n readonly stepSize = input<number, NumberInput>(this.config.stepSize, { transform: numberAttribute });\n readonly majorStepSize = input<number, NumberInput>(this.config.majorStepSize, { transform: numberAttribute });\n readonly minorStepSize = input<number, NumberInput>(this.config.minorStepSize, { transform: numberAttribute });\n readonly clampValueOnBlur = input<boolean, BooleanInput>(this.config.clampValueOnBlur, {\n transform: booleanAttribute\n });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly cva = createXValueAccessor<number | null>({\n onWrite: value => {\n this.value.set(value ?? null);\n this.text.set(value == null ? '' : String(value));\n },\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n // Aliased so the writable `value` linkedSignal below can own the public name.\n // Coerce so `value=\"5\"` (a string attribute) becomes the number 5, not the\n // string \"5\" that would then concatenate under `+ stepSize`.\n readonly valueInput = input<number | null, number | string | null | undefined>(null, {\n // eslint-disable-next-line @angular-eslint/no-input-rename\n alias: 'value',\n transform: raw => (raw == null || raw === '' ? null : Number(raw))\n });\n /** The current numeric value, or `null` when empty. Two-way via `value`. */\n readonly value = linkedSignal(this.valueInput);\n\n // The text the field shows. Kept separate from `value` so a half-typed entry\n // (\"-\", \"1.\") is preserved while the parsed value stays null/last-valid.\n private readonly text = signal<string>('');\n protected readonly display = computed(() => {\n const value = this.value();\n\n // Do not overwrite what the user is mid-typing with a formatted number.\n return this.text() !== '' || value == null ? this.text() : String(value);\n });\n\n protected readonly canIncrement = computed(() => !this.isDisabled() && !this.atMax(this.value()));\n protected readonly canDecrement = computed(() => !this.isDisabled() && !this.atMin(this.value()));\n\n protected readonly computedClass = computed(() =>\n xui(\n 'border-border bg-surface-inset focus-within:border-focus inline-flex items-stretch overflow-hidden rounded-lg border transition-colors',\n // The wrapper carries the control height so the stepper column cannot stretch the field\n // past the shared scale.\n this.size() === 'sm' ? 'h-(--control-height-sm)' : 'h-(--control-height-md)',\n this.isDisabled() && 'cursor-not-allowed opacity-50',\n this.class()\n )\n );\n protected readonly fieldClass = computed(() =>\n xui(\n 'text-foreground placeholder:text-foreground-subtle w-full min-w-0 bg-transparent tabular-nums outline-none',\n this.size() === 'sm' ? 'px-(--control-padding-sm) text-xs' : 'px-(--control-padding-md) text-sm'\n )\n );\n protected readonly stepperColumnClass = computed(() => 'border-border flex shrink-0 flex-col border-s');\n protected readonly stepperClass = computed(\n () =>\n 'text-foreground-muted hover:bg-hover-overlay hover:text-foreground flex flex-1 items-center justify-center px-1.5 disabled:pointer-events-none disabled:opacity-40'\n );\n\n protected onInput(raw: string): void {\n this.text.set(raw);\n\n const parsed = this.parse(raw);\n this.value.set(parsed);\n this.cva.notifyChange(parsed);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') {\n return;\n }\n\n event.preventDefault();\n const magnitude = event.shiftKey ? this.majorStepSize() : event.altKey ? this.minorStepSize() : this.stepSize();\n this.step(event.key === 'ArrowUp' ? magnitude : -magnitude);\n }\n\n protected onBlur(): void {\n if (this.clampValueOnBlur()) {\n this.commit(this.clamp(this.value()));\n }\n\n // Re-sync the text with the committed value, dropping a half-typed entry.\n this.text.set(this.value() == null ? '' : String(this.value()));\n this.cva.markTouched();\n }\n\n step(delta: number): void {\n if (this.isDisabled()) {\n return;\n }\n\n const base = this.value() ?? 0;\n // Round to the step grid so 0.1 + 0.2 does not drift to 0.30000000000000004.\n const next = this.clamp(this.round(base + delta));\n this.commit(next);\n this.text.set(next == null ? '' : String(next));\n }\n\n private commit(value: number | null): void {\n this.value.set(value);\n this.cva.notifyChange(value);\n }\n\n private parse(raw: string): number | null {\n const trimmed = raw.trim();\n\n if (trimmed === '' || trimmed === '-' || trimmed === '.' || trimmed === '-.') {\n return null;\n }\n\n const parsed = Number(trimmed);\n\n return Number.isFinite(parsed) ? parsed : this.value();\n }\n\n private clamp(value: number | null): number | null {\n if (value == null) {\n return null;\n }\n\n const min = this.min();\n const max = this.max();\n\n return Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));\n }\n\n private round(value: number): number {\n // Keep a sane number of decimals so step math stays exact.\n return Math.round(value * 1e10) / 1e10;\n }\n\n private atMax(value: number | null): boolean {\n return value != null && this.max() != null && value >= this.max()!;\n }\n\n private atMin(value: number | null): boolean {\n return value != null && this.min() != null && value <= this.min()!;\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 { XuiNumericInput } from './lib/numeric-input';\n\nexport * from './lib/numeric-input';\nexport * from './lib/numeric-input.token';\n\nexport const XuiNumericInputImports = [XuiNumericInput] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;AAmBA;AACO,MAAM,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,GAAG,kBAAkB,CAC3F,uBAAuB,EACvB;AACE,IAAA,IAAI,EAAE,IAAI;AACV,IAAA,cAAc,EAAE,OAAO;AACvB,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,aAAa,EAAE,EAAE;AACjB,IAAA,aAAa,EAAE,GAAG;AAClB,IAAA,gBAAgB,EAAE;AACnB,CAAA;;ACCH;;;;;;;;;;;AAWG;MAuEU,eAAe,CAAA;IACT,MAAM,GAAG,2BAA2B,EAAE;IACtC,SAAS,GAAG,iBAAiB,EAAE;AAC7B,IAAA,OAAO,GAAG,QAAQ,CAAC,mBAAmB,CAAC;;AAGjD,IAAA,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU;;IAGtC,SAAS,GAA0B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE;AAE7E,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;IACnC;;IAGS,KAAK,GAAG,KAAK,CAAa,EAAE;8EAAC;AAC7B,IAAA,IAAI,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,IAAI;6EAAC;AACnD,IAAA,cAAc,GAAG,KAAK,CAA2B,IAAI,CAAC,MAAM,CAAC,cAAc;uFAAC;IAE5E,WAAW,GAAG,KAAK,CAAgB,IAAI;oFAAC;IACxC,SAAS,GAAG,KAAK,CAAgB,IAAI,iFAAI,KAAK,EAAE,YAAY,EAAA,CAAG;IAE/D,GAAG,GAAG,KAAK,CAAkC,SAAS,2EAAI,SAAS,EAAE,eAAe,EAAA,CAAG;IACvF,GAAG,GAAG,KAAK,CAAkC,SAAS,2EAAI,SAAS,EAAE,eAAe,EAAA,CAAG;AACvF,IAAA,QAAQ,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AAC3F,IAAA,aAAa,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,aAAa,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,eAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AACrG,IAAA,aAAa,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,aAAa,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,eAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AACrG,IAAA,gBAAgB,GAAG,KAAK,CAAwB,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,kBAAA,EAAA,8BAAA,EAAA,CAAA,EACnF,SAAS,EAAE,gBAAgB,GAC3B;IAEO,QAAQ,GAAG,KAAK,CAAwB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAErE,GAAG,GAAG,oBAAoB,CAAgB;QAC3D,OAAO,EAAE,KAAK,IAAG;YACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,EAAE,IAAI,CAAC;AAChB,KAAA,CAAC;AACiB,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ;;;;IAKxC,UAAU,GAAG,KAAK,CAAoD,IAAI,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,YAAA,EAAA,8BAAA,EAAA,CAAA;;AAEjF,QAAA,KAAK,EAAE,OAAO;QACd,SAAS,EAAE,GAAG,KAAK,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE,GAAG,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAA,CAClE;;AAEO,IAAA,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU;8EAAC;;;IAI7B,IAAI,GAAG,MAAM,CAAS,EAAE;6EAAC;AACvB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE;;QAG1B,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1E,CAAC;gFAAC;IAEiB,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;qFAAC;IAC9E,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;qFAAC;IAE9E,aAAa,GAAG,QAAQ,CAAC,MAC1C,GAAG,CACD,wIAAwI;;;IAGxI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,yBAAyB,GAAG,yBAAyB,EAC5E,IAAI,CAAC,UAAU,EAAE,IAAI,+BAA+B,EACpD,IAAI,CAAC,KAAK,EAAE,CACb;sFACF;IACkB,UAAU,GAAG,QAAQ,CAAC,MACvC,GAAG,CACD,4GAA4G,EAC5G,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,mCAAmC,GAAG,mCAAmC,CACjG;mFACF;AACkB,IAAA,kBAAkB,GAAG,QAAQ,CAAC,MAAM,+CAA+C;2FAAC;AACpF,IAAA,YAAY,GAAG,QAAQ,CACxC,MACE,oKAAoK;qFACvK;AAES,IAAA,OAAO,CAAC,GAAW,EAAA;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAElB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC9B,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACtB,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC;IAC/B;AAEU,IAAA,SAAS,CAAC,KAAoB,EAAA;AACtC,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE;YACxD;QACF;QAEA,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC/G,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,GAAG,SAAS,GAAG,CAAC,SAAS,CAAC;IAC7D;IAEU,MAAM,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;AAC3B,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACvC;;QAGA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AAC/D,QAAA,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE;IACxB;AAEA,IAAA,IAAI,CAAC,KAAa,EAAA;AAChB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;YACrB;QACF;QAEA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC;;AAE9B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;AACjD,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD;AAEQ,IAAA,MAAM,CAAC,KAAoB,EAAA;AACjC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACrB,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC;IAC9B;AAEQ,IAAA,KAAK,CAAC,GAAW,EAAA;AACvB,QAAA,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE;AAE1B,QAAA,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE;AAC5E,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;AAE9B,QAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE;IACxD;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,IAAI,KAAK,IAAI,IAAI,EAAE;AACjB,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;AACtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QAEtB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrE;AAEQ,IAAA,KAAK,CAAC,KAAa,EAAA;;QAEzB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI;IACxC;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAG;IACpE;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAG;IACpE;AAES,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU;AAChC,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;AAC5C,IAAA,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB;AAC9C,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;0HA7K1C,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,uBAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,SAAA,EAhEf;AACT,YAAA,qBAAqB,EAAC,MAAM,eAAe,EAAC;AAC5C,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,EAAC,MAAM,eAAe;AAC9C;SACF,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA/DS,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAC5B,CAAC,YAAY,CAAC,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC,CAAC,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAmE1E,eAAe,EAAA,UAAA,EAAA,CAAA;kBAtE3B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,OAAO,EAAE,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC;oBAC5C,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC,CAAC;oBACrF,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,SAAS,EAAE;AACT,wBAAA,qBAAqB,EAAC,MAAK,eAAgB,EAAC;AAC5C,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,EAAC,qBAAqB;AAC9C;AACF,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE;AACZ;AACF,iBAAA;;;AC1GM,MAAM,sBAAsB,GAAG,CAAC,eAAe;;ACLtD;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"xui-numeric-input.mjs","sources":["../../../../../../libs/ui/numeric-input/xui/src/lib/numeric-input.token.ts","../../../../../../libs/ui/numeric-input/xui/src/lib/numeric-input.ts","../../../../../../libs/ui/numeric-input/xui/src/index.ts","../../../../../../libs/ui/numeric-input/xui/src/xui-numeric-input.ts"],"sourcesContent":["import { createXConfigToken } from '@xui/core';\n\nexport type XuiNumericInputSize = 'md' | 'sm';\n/** Where the stepper buttons sit. */\nexport type XuiNumericButtonPosition = 'right' | 'left' | 'none';\n\nexport interface XuiNumericInputConfig {\n size: XuiNumericInputSize;\n buttonPosition: XuiNumericButtonPosition;\n /** Step applied by a click or ArrowUp/Down. */\n stepSize: number;\n /** Step when Shift is held — the coarse jump. */\n majorStepSize: number;\n /** Step when Alt is held — the fine nudge. */\n minorStepSize: number;\n /** Snap an out-of-range value back into [min, max] when focus leaves. */\n clampValueOnBlur: boolean;\n}\n\n/** Application-wide defaults for XuiNumericInput. */\nexport const [injectXuiNumericInputConfig, provideXuiNumericInputConfig] = createXConfigToken<XuiNumericInputConfig>(\n 'XuiNumericInputConfig',\n {\n size: 'md',\n buttonPosition: 'right',\n stepSize: 1,\n majorStepSize: 10,\n minorStepSize: 0.1,\n clampValueOnBlur: true\n }\n);\n","import type { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n forwardRef,\n input,\n linkedSignal,\n numberAttribute,\n signal,\n type Signal\n} from '@angular/core';\nimport { ControlValueAccessor, type NgControl } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matKeyboardArrowDownRound, matKeyboardArrowUpRound } 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, type XuiIconSize } from '@xui/icon';\nimport type { ClassValue } from 'clsx';\nimport {\n injectXuiNumericInputConfig,\n type XuiNumericButtonPosition,\n type XuiNumericInputSize\n} from './numeric-input.token';\n\n/**\n * A number field with stepper buttons and keyboard increment.\n *\n * ```html\n * <xui-numeric-input [(ngModel)]=\"quantity\" [min]=\"0\" [max]=\"99\" />\n * ```\n *\n * The value is a `number | null` (empty is `null`, not `0`, so \"no answer\" is\n * distinct from zero). ArrowUp/Down step by `stepSize`; Shift steps by\n * `majorStepSize`, Alt by `minorStepSize`. It is a `ControlValueAccessor`, so\n * forms bind to it directly, and it clamps into `[min, max]` on blur.\n */\n@Component({\n selector: 'xui-numeric-input',\n imports: [NgTemplateOutlet, NgIcon, XuiIcon],\n viewProviders: [provideIcons({ matKeyboardArrowUpRound, matKeyboardArrowDownRound })],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n providers: [\n provideXValueAccessor(() => XuiNumericInput),\n {\n provide: XFormFieldControl,\n useExisting: forwardRef(() => XuiNumericInput)\n }\n ],\n template: `\n @if (buttonPosition() === 'left') {\n <ng-container [ngTemplateOutlet]=\"steppers\" />\n }\n\n <input\n #field\n [id]=\"fieldId\"\n type=\"text\"\n inputmode=\"decimal\"\n [class]=\"fieldClass()\"\n [value]=\"display()\"\n [disabled]=\"isDisabled()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"spinbutton\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"min() ?? null\"\n [attr.aria-valuemax]=\"max() ?? null\"\n (input)=\"onInput(field.value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n\n @if (buttonPosition() === 'right') {\n <ng-container [ngTemplateOutlet]=\"steppers\" />\n }\n\n <ng-template #steppers>\n <div [class]=\"stepperColumnClass()\">\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Increment\"\n [class]=\"stepperClass()\"\n [disabled]=\"!canIncrement()\"\n (click)=\"step(stepSize())\"\n >\n <ng-icon xui [size]=\"stepperIconSize()\" name=\"matKeyboardArrowUpRound\" />\n </button>\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Decrement\"\n [class]=\"stepperClass()\"\n [disabled]=\"!canDecrement()\"\n (click)=\"step(-stepSize())\"\n >\n <ng-icon xui [size]=\"stepperIconSize()\" name=\"matKeyboardArrowDownRound\" />\n </button>\n </div>\n </ng-template>\n `,\n host: {\n '[class]': 'computedClass()'\n }\n})\nexport class XuiNumericInput implements ControlValueAccessor, XFormFieldControl {\n private readonly config = injectXuiNumericInputConfig();\n private readonly formState = createXErrorState();\n protected readonly fieldId = uniqueId('xui-numeric-input');\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 inner text field, 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<XuiNumericInputSize>(this.config.size);\n readonly buttonPosition = input<XuiNumericButtonPosition>(this.config.buttonPosition);\n\n readonly placeholder = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null, { alias: 'aria-label' });\n\n readonly min = input<number | undefined, NumberInput>(undefined, { transform: numberAttribute });\n readonly max = input<number | undefined, NumberInput>(undefined, { transform: numberAttribute });\n readonly stepSize = input<number, NumberInput>(this.config.stepSize, { transform: numberAttribute });\n readonly majorStepSize = input<number, NumberInput>(this.config.majorStepSize, { transform: numberAttribute });\n readonly minorStepSize = input<number, NumberInput>(this.config.minorStepSize, { transform: numberAttribute });\n readonly clampValueOnBlur = input<boolean, BooleanInput>(this.config.clampValueOnBlur, {\n transform: booleanAttribute\n });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly cva = createXValueAccessor<number | null>({\n onWrite: value => {\n this.value.set(value ?? null);\n this.text.set(value == null ? '' : String(value));\n },\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n // Aliased so the writable `value` linkedSignal below can own the public name.\n // Coerce so `value=\"5\"` (a string attribute) becomes the number 5, not the\n // string \"5\" that would then concatenate under `+ stepSize`.\n readonly valueInput = input<number | null, number | string | null | undefined>(null, {\n // eslint-disable-next-line @angular-eslint/no-input-rename\n alias: 'value',\n transform: raw => (raw == null || raw === '' ? null : Number(raw))\n });\n /** The current numeric value, or `null` when empty. Two-way via `value`. */\n readonly value = linkedSignal(this.valueInput);\n\n // The text the field shows. Kept separate from `value` so a half-typed entry\n // (\"-\", \"1.\") is preserved while the parsed value stays null/last-valid.\n private readonly text = signal<string>('');\n protected readonly display = computed(() => {\n const value = this.value();\n\n // Do not overwrite what the user is mid-typing with a formatted number.\n return this.text() !== '' || value == null ? this.text() : String(value);\n });\n\n protected readonly canIncrement = computed(() => !this.isDisabled() && !this.atMax(this.value()));\n protected readonly canDecrement = computed(() => !this.isDisabled() && !this.atMin(this.value()));\n\n protected readonly computedClass = computed(() =>\n xui(\n 'border-border bg-surface-inset focus-within:border-focus inline-flex items-stretch overflow-hidden rounded-lg border transition-colors',\n // The wrapper carries the control height so the stepper column cannot stretch the field\n // past the shared scale.\n this.size() === 'sm' ? 'h-(--control-height-sm)' : 'h-(--control-height-md)',\n this.isDisabled() && 'cursor-not-allowed opacity-50',\n this.class()\n )\n );\n protected readonly fieldClass = computed(() =>\n xui(\n 'text-foreground placeholder:text-foreground-subtle w-full min-w-0 bg-transparent tabular-nums outline-none',\n this.size() === 'sm' ? 'px-(--control-padding-sm) text-xs' : 'px-(--control-padding-md) text-sm'\n )\n );\n protected readonly stepperColumnClass = computed(() =>\n xui(\n 'border-border flex shrink-0 flex-col',\n // The rule divides the steppers from the field, so it belongs on whichever edge faces it —\n // on the outer edge it would just double up on the wrapper's own border.\n this.buttonPosition() === 'left' ? 'border-e' : 'border-s'\n )\n );\n\n /**\n * The two steppers split the control height between them, so a glyph sized off the icon scale\n * (`sm` is 16px) makes the column taller than the field — and the wrapper clips the overflow,\n * taking the bottom arrow with it. Size to the row instead: half of 24px or 30px, less a hair.\n */\n protected readonly stepperIconSize = computed<XuiIconSize>(() => (this.size() === 'sm' ? '10px' : '12px'));\n protected readonly stepperClass = computed(\n () =>\n 'text-foreground-muted hover:bg-hover-overlay hover:text-foreground flex flex-1 items-center justify-center px-1.5 disabled:pointer-events-none disabled:opacity-40'\n );\n\n protected onInput(raw: string): void {\n this.text.set(raw);\n\n const parsed = this.parse(raw);\n this.value.set(parsed);\n this.cva.notifyChange(parsed);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') {\n return;\n }\n\n event.preventDefault();\n const magnitude = event.shiftKey ? this.majorStepSize() : event.altKey ? this.minorStepSize() : this.stepSize();\n this.step(event.key === 'ArrowUp' ? magnitude : -magnitude);\n }\n\n protected onBlur(): void {\n if (this.clampValueOnBlur()) {\n this.commit(this.clamp(this.value()));\n }\n\n // Re-sync the text with the committed value, dropping a half-typed entry.\n this.text.set(this.value() == null ? '' : String(this.value()));\n this.cva.markTouched();\n }\n\n step(delta: number): void {\n if (this.isDisabled()) {\n return;\n }\n\n const base = this.value() ?? 0;\n // Round to the step grid so 0.1 + 0.2 does not drift to 0.30000000000000004.\n const next = this.clamp(this.round(base + delta));\n this.commit(next);\n this.text.set(next == null ? '' : String(next));\n }\n\n private commit(value: number | null): void {\n this.value.set(value);\n this.cva.notifyChange(value);\n }\n\n private parse(raw: string): number | null {\n const trimmed = raw.trim();\n\n if (trimmed === '' || trimmed === '-' || trimmed === '.' || trimmed === '-.') {\n return null;\n }\n\n const parsed = Number(trimmed);\n\n return Number.isFinite(parsed) ? parsed : this.value();\n }\n\n private clamp(value: number | null): number | null {\n if (value == null) {\n return null;\n }\n\n const min = this.min();\n const max = this.max();\n\n return Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));\n }\n\n private round(value: number): number {\n // Keep a sane number of decimals so step math stays exact.\n return Math.round(value * 1e10) / 1e10;\n }\n\n private atMax(value: number | null): boolean {\n return value != null && this.max() != null && value >= this.max()!;\n }\n\n private atMin(value: number | null): boolean {\n return value != null && this.min() != null && value <= this.min()!;\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 { XuiNumericInput } from './lib/numeric-input';\n\nexport * from './lib/numeric-input';\nexport * from './lib/numeric-input.token';\n\nexport const XuiNumericInputImports = [XuiNumericInput] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;AAmBA;AACO,MAAM,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,GAAG,kBAAkB,CAC3F,uBAAuB,EACvB;AACE,IAAA,IAAI,EAAE,IAAI;AACV,IAAA,cAAc,EAAE,OAAO;AACvB,IAAA,QAAQ,EAAE,CAAC;AACX,IAAA,aAAa,EAAE,EAAE;AACjB,IAAA,aAAa,EAAE,GAAG;AAClB,IAAA,gBAAgB,EAAE;AACnB,CAAA;;ACCH;;;;;;;;;;;AAWG;MAuEU,eAAe,CAAA;IACT,MAAM,GAAG,2BAA2B,EAAE;IACtC,SAAS,GAAG,iBAAiB,EAAE;AAC7B,IAAA,OAAO,GAAG,QAAQ,CAAC,mBAAmB,CAAC;;AAGjD,IAAA,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU;;IAGtC,SAAS,GAA0B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE;AAE7E,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;IACnC;;IAGS,KAAK,GAAG,KAAK,CAAa,EAAE;8EAAC;AAC7B,IAAA,IAAI,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,IAAI;6EAAC;AACnD,IAAA,cAAc,GAAG,KAAK,CAA2B,IAAI,CAAC,MAAM,CAAC,cAAc;uFAAC;IAE5E,WAAW,GAAG,KAAK,CAAgB,IAAI;oFAAC;IACxC,SAAS,GAAG,KAAK,CAAgB,IAAI,iFAAI,KAAK,EAAE,YAAY,EAAA,CAAG;IAE/D,GAAG,GAAG,KAAK,CAAkC,SAAS,2EAAI,SAAS,EAAE,eAAe,EAAA,CAAG;IACvF,GAAG,GAAG,KAAK,CAAkC,SAAS,2EAAI,SAAS,EAAE,eAAe,EAAA,CAAG;AACvF,IAAA,QAAQ,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AAC3F,IAAA,aAAa,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,aAAa,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,eAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AACrG,IAAA,aAAa,GAAG,KAAK,CAAsB,IAAI,CAAC,MAAM,CAAC,aAAa,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,eAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,eAAe,GAAG;AACrG,IAAA,gBAAgB,GAAG,KAAK,CAAwB,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,kBAAA,EAAA,8BAAA,EAAA,CAAA,EACnF,SAAS,EAAE,gBAAgB,GAC3B;IAEO,QAAQ,GAAG,KAAK,CAAwB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAErE,GAAG,GAAG,oBAAoB,CAAgB;QAC3D,OAAO,EAAE,KAAK,IAAG;YACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,EAAE,IAAI,CAAC;AAChB,KAAA,CAAC;AACiB,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ;;;;IAKxC,UAAU,GAAG,KAAK,CAAoD,IAAI,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,YAAA,EAAA,8BAAA,EAAA,CAAA;;AAEjF,QAAA,KAAK,EAAE,OAAO;QACd,SAAS,EAAE,GAAG,KAAK,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE,GAAG,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAA,CAClE;;AAEO,IAAA,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU;8EAAC;;;IAI7B,IAAI,GAAG,MAAM,CAAS,EAAE;6EAAC;AACvB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE;;QAG1B,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1E,CAAC;gFAAC;IAEiB,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;qFAAC;IAC9E,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;qFAAC;IAE9E,aAAa,GAAG,QAAQ,CAAC,MAC1C,GAAG,CACD,wIAAwI;;;IAGxI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,yBAAyB,GAAG,yBAAyB,EAC5E,IAAI,CAAC,UAAU,EAAE,IAAI,+BAA+B,EACpD,IAAI,CAAC,KAAK,EAAE,CACb;sFACF;IACkB,UAAU,GAAG,QAAQ,CAAC,MACvC,GAAG,CACD,4GAA4G,EAC5G,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,mCAAmC,GAAG,mCAAmC,CACjG;mFACF;IACkB,kBAAkB,GAAG,QAAQ,CAAC,MAC/C,GAAG,CACD,sCAAsC;;;AAGtC,IAAA,IAAI,CAAC,cAAc,EAAE,KAAK,MAAM,GAAG,UAAU,GAAG,UAAU,CAC3D;2FACF;AAED;;;;AAIG;IACgB,eAAe,GAAG,QAAQ,CAAc,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;wFAAC;AACvF,IAAA,YAAY,GAAG,QAAQ,CACxC,MACE,oKAAoK;qFACvK;AAES,IAAA,OAAO,CAAC,GAAW,EAAA;AAC3B,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAElB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC9B,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACtB,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC;IAC/B;AAEU,IAAA,SAAS,CAAC,KAAoB,EAAA;AACtC,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE;YACxD;QACF;QAEA,KAAK,CAAC,cAAc,EAAE;AACtB,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC/G,QAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,GAAG,SAAS,GAAG,CAAC,SAAS,CAAC;IAC7D;IAEU,MAAM,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;AAC3B,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACvC;;QAGA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AAC/D,QAAA,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE;IACxB;AAEA,IAAA,IAAI,CAAC,KAAa,EAAA;AAChB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;YACrB;QACF;QAEA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC;;AAE9B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;AACjD,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD;AAEQ,IAAA,MAAM,CAAC,KAAoB,EAAA;AACjC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACrB,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC;IAC9B;AAEQ,IAAA,KAAK,CAAC,GAAW,EAAA;AACvB,QAAA,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE;AAE1B,QAAA,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE;AAC5E,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;AAE9B,QAAA,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE;IACxD;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,IAAI,KAAK,IAAI,IAAI,EAAE;AACjB,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;AACtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QAEtB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrE;AAEQ,IAAA,KAAK,CAAC,KAAa,EAAA;;QAEzB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI;IACxC;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAG;IACpE;AAEQ,IAAA,KAAK,CAAC,KAAoB,EAAA;AAChC,QAAA,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAG;IACpE;AAES,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU;AAChC,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;AAC5C,IAAA,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB;AAC9C,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;0HA3L1C,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,uBAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,SAAA,EAhEf;AACT,YAAA,qBAAqB,EAAC,MAAM,eAAe,EAAC;AAC5C,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,EAAC,MAAM,eAAe;AAC9C;SACF,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA/DS,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAC5B,CAAC,YAAY,CAAC,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC,CAAC,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAmE1E,eAAe,EAAA,UAAA,EAAA,CAAA;kBAtE3B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,OAAO,EAAE,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC;oBAC5C,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC,CAAC;oBACrF,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,SAAS,EAAE;AACT,wBAAA,qBAAqB,EAAC,MAAK,eAAgB,EAAC;AAC5C,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,EAAC,qBAAqB;AAC9C;AACF,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE;AACZ;AACF,iBAAA;;;AC1GM,MAAM,sBAAsB,GAAG,CAAC,eAAe;;ACLtD;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xui/numeric-input",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.17",
|
|
4
4
|
"description": "Modern Angular 22 UI Library based on TailwindCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/rikarin/xui/issues"
|
|
14
14
|
},
|
|
15
15
|
"repository": "https://github.com/Rikarin/xui",
|
|
16
|
-
"license": "
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
17
|
"author": "Jiu",
|
|
18
18
|
"maintainers": [
|
|
19
19
|
"Jiu",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"@angular/forms": "22",
|
|
43
43
|
"@ng-icons/core": "34",
|
|
44
44
|
"@ng-icons/material-icons": "34",
|
|
45
|
-
"@xui/core": "2.0.0-alpha.
|
|
46
|
-
"@xui/icon": "2.0.0-alpha.
|
|
45
|
+
"@xui/core": "2.0.0-alpha.17",
|
|
46
|
+
"@xui/icon": "2.0.0-alpha.17",
|
|
47
47
|
"clsx": "^2.1.1"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
@@ -4,6 +4,7 @@ import { Signal } from '@angular/core';
|
|
|
4
4
|
import { NumberInput, BooleanInput } from '@angular/cdk/coercion';
|
|
5
5
|
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
|
6
6
|
import { XFormFieldControl } from '@xui/core/form-field';
|
|
7
|
+
import { XuiIconSize } from '@xui/icon';
|
|
7
8
|
import { ClassValue } from 'clsx';
|
|
8
9
|
|
|
9
10
|
type XuiNumericInputSize = 'md' | 'sm';
|
|
@@ -71,6 +72,12 @@ declare class XuiNumericInput implements ControlValueAccessor, XFormFieldControl
|
|
|
71
72
|
protected readonly computedClass: Signal<string>;
|
|
72
73
|
protected readonly fieldClass: Signal<string>;
|
|
73
74
|
protected readonly stepperColumnClass: Signal<string>;
|
|
75
|
+
/**
|
|
76
|
+
* The two steppers split the control height between them, so a glyph sized off the icon scale
|
|
77
|
+
* (`sm` is 16px) makes the column taller than the field — and the wrapper clips the overflow,
|
|
78
|
+
* taking the bottom arrow with it. Size to the row instead: half of 24px or 30px, less a hair.
|
|
79
|
+
*/
|
|
80
|
+
protected readonly stepperIconSize: Signal<XuiIconSize>;
|
|
74
81
|
protected readonly stepperClass: Signal<string>;
|
|
75
82
|
protected onInput(raw: string): void;
|
|
76
83
|
protected onKeydown(event: KeyboardEvent): void;
|