diff --git a/docs/components-api/inputotp.md b/docs/components-api/inputotp.md index bceec645..8397964c 100644 --- a/docs/components-api/inputotp.md +++ b/docs/components-api/inputotp.md @@ -4,11 +4,12 @@ > ✅ **Реализован**: `ExtraInputOtpComponent` (`@cdek-it/angular-ui-kit`) соответствует спецификации. -| Свойство | Описание | Типизация | -| -------------- | ---------------------------------------- | --------- | -| `length` | количество полей ввода | `number` | -| `mask` | скрывать введённое значение (как пароль) | `boolean` | -| `integer-only` | допускать только цифры | `boolean` | +| Свойство | Описание | Типизация | +| -------------- | ---------------------------------------- | ------------------------ | +| `length` | количество полей ввода | `number` | +| `mask` | скрывать введённое значение (как пароль) | `boolean` | +| `integer-only` | допускать только цифры | `boolean` | +| `size` | размер ячейки | `small \| base \| large` | # События diff --git a/src/lib/components/inputotp/inputotp.component.ts b/src/lib/components/inputotp/inputotp.component.ts index 8f4a77be..890369af 100644 --- a/src/lib/components/inputotp/inputotp.component.ts +++ b/src/lib/components/inputotp/inputotp.component.ts @@ -14,6 +14,8 @@ import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, NgControl, Reacti import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { InputOtp, InputOtpChangeEvent } from 'primeng/inputotp'; +export type ExtraInputOtpSize = 'small' | 'base' | 'large'; + export interface ExtraInputOtpChangeEvent { value: string; originalEvent: Event; @@ -37,6 +39,7 @@ export interface ExtraInputOtpChangeEvent { [length]="length" [mask]="mask" [integerOnly]="integerOnly" + [size]="primeSize" [disabled]="disabled" [invalid]="invalid" [formControl]="control" @@ -54,9 +57,16 @@ export class ExtraInputOtpComponent implements ControlValueAccessor, OnInit { @Input() length = 4; @Input() mask = false; @Input() integerOnly = false; + /** Размер ячейки. */ + @Input() size: ExtraInputOtpSize = 'base'; disabled = false; + /** PrimeNG знает только small/large; base — размер по умолчанию, без класса. */ + protected get primeSize(): 'small' | 'large' | undefined { + return this.size === 'base' ? undefined : this.size; + } + @Output() onChange = new EventEmitter(); private _onChange: (value: string | null) => void = () => {}; diff --git a/src/lib/providers/prime-preset/tokens/components/inputotp.ts b/src/lib/providers/prime-preset/tokens/components/inputotp.ts index 492972a5..337857b9 100644 --- a/src/lib/providers/prime-preset/tokens/components/inputotp.ts +++ b/src/lib/providers/prime-preset/tokens/components/inputotp.ts @@ -25,21 +25,26 @@ export const inputotpCss = ({ dt }: { dt: (token: string) => string }): string = /* ─── Invalid + Focus ─── */ .p-inputotp.p-component .p-inputtext.p-invalid:focus { border-color: ${dt('inputtext.root.invalidBorderColor')}; - box-shadow: 0 0 0 ${dt('inputtext.root.focusRing.width')} ${dt('color.bg.status.danger.weak.active')}; + box-shadow: 0 0 0 ${dt('inputtext.root.focusRing.width')} ${dt('color.border.status.danger.focus')}; } /* ─── Small ─── */ .p-inputotp.p-component .p-inputtext.p-inputtext-sm { + height: ${dt('inputotp.extend.extSm.height')}; + /* радиус inputtext (14px) на ячейке 28px смыкается в круг — для sm свой */ + border-radius: ${dt('inputotp.extend.extSm.borderRadius')}; padding-block: ${dt('inputtext.root.sm.paddingY')}; } /* ─── Base ─── */ .p-inputotp.p-component .p-inputtext:not(.p-inputtext-sm):not(.p-inputtext-lg):not(.p-inputtext-xlg) { + height: ${dt('inputotp.extend.height')}; padding-block: ${dt('inputtext.root.paddingY')}; } /* ─── Large ─── */ .p-inputotp.p-component .p-inputtext.p-inputtext-lg { + height: ${dt('inputotp.extend.extLg.height')}; padding-block: ${dt('inputtext.root.lg.paddingY')}; } diff --git a/src/lib/providers/prime-preset/tokens/tokens.json b/src/lib/providers/prime-preset/tokens/tokens.json index 363335f8..f57d86c5 100644 --- a/src/lib/providers/prime-preset/tokens/tokens.json +++ b/src/lib/providers/prime-preset/tokens/tokens.json @@ -703,7 +703,7 @@ } }, "border": { - "focus": "{colors.solid.green.200}", + "focus": "{colors.alpha.green.200}", "neutral": { "default": "{colors.solid.zinc.200}", "strong": "{colors.solid.zinc.300}", @@ -722,7 +722,8 @@ "danger": { "subtle": "{colors.solid.red.400}", "default": "{colors.solid.red.500}", - "strong": "{colors.solid.red.600}" + "strong": "{colors.solid.red.600}", + "focus": "{colors.alpha.red.200}" }, "info": { "default": "{colors.solid.blue.500}", @@ -966,7 +967,7 @@ } }, "border": { - "focus": "{colors.solid.green.200}", + "focus": "{colors.alpha.green.200}", "neutral": { "default": "{colors.solid.zinc.800}", "strong": "{colors.solid.zinc.700}", @@ -985,7 +986,8 @@ "danger": { "subtle": "{colors.solid.red.600}", "default": "{colors.solid.red.500}", - "strong": "{colors.solid.red.400}" + "strong": "{colors.solid.red.400}", + "focus": "{colors.alpha.red.200}" }, "info": { "default": "{colors.solid.blue.500}", @@ -3297,25 +3299,26 @@ "inputotp": { "extend": { "height": "{dimension.size.1100}", - "borderWidth": "{dimension.borderWidth.100}" + "borderWidth": "{dimension.borderWidth.100}", + "extSm": { + "height": "{dimension.size.800}", + "borderRadius": "{dimension.borderRadius.200}" + }, + "extLg": { + "height": "{dimension.size.1200}" + } }, "root": { "gap": "{dimension.space.200}" }, "input": { - "width": "{dimension.size.1800}", + "width": "{dimension.size.1100}", "lg": { - "width": "{dimension.size.1900}" + "width": "{dimension.size.1200}" }, "sm": { - "width": "{dimension.size.1700}" + "width": "{dimension.size.800}" } - }, - "sm": { - "width": "{dimension.size.none}" - }, - "lg": { - "width": "{dimension.size.none}" } }, "inputtext": { diff --git a/src/stories/components/inputotp/inputotp.stories.ts b/src/stories/components/inputotp/inputotp.stories.ts index b3e6da73..63c82f35 100644 --- a/src/stories/components/inputotp/inputotp.stories.ts +++ b/src/stories/components/inputotp/inputotp.stories.ts @@ -62,6 +62,16 @@ import { ExtraInputOtpComponent } from '@cdek-it/angular-ui-kit'; type: { summary: 'boolean' } } }, + size: { + control: 'select', + options: ['small', 'base', 'large'], + description: 'Размер ячейки', + table: { + category: 'Свойства', + defaultValue: { summary: "'base'" }, + type: { summary: "'small' | 'base' | 'large'" } + } + }, // ── Состояния (управляются через FormControl) ───────────────── disabled: { control: 'boolean', @@ -97,6 +107,7 @@ import { ExtraInputOtpComponent } from '@cdek-it/angular-ui-kit'; length: 4, mask: false, integerOnly: false, + size: 'base', disabled: false, invalid: false } @@ -114,6 +125,7 @@ export const Default: Story = { if (args.length !== 4) parts.push(`[length]="${args.length}"`); if (args.mask) parts.push(`[mask]="true"`); if (args.integerOnly) parts.push(`[integerOnly]="true"`); + if (args.size && args.size !== 'base') parts.push(`size="${args.size}"`); const validators = args.invalid ? [() => ({ invalid: true })] : []; const control = new FormControl({ value: '', disabled: args.disabled }, validators);