@central-design-system/components 4.0.0-alpha.2 → 4.0.0-alpha.3
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/CHANGELOG.md +5 -1
- package/MIGRATION.md +1 -1
- package/dist/cjs/entry.js +10 -10
- package/dist/es/entry.js +173 -163
- package/dist/es/entry.js.map +1 -1
- package/dist/es/src/components/CdsList/CdsList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/src/components/CdsList/CdsListGroup.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/src/components/CdsList/CdsListItem.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/src/components/CdsList/CdsListSubheader.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/src/components/CdsList/api/CdsList.constants.js +4 -4
- package/dist/es/src/components/CdsList/api/CdsList.props.js +2 -2
- package/dist/es/src/components/CdsList/index.js +1 -1
- package/dist/es/src/components/CdsOtpInput/CdsOtpField.js +2 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpField.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpField.vue_vue_type_script_setup_true_lang.js +62 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpField.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpGroup.js +2 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpGroup.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpGroup.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpInput.css +204 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpInput.js +2 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpInput.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpInput.vue_vue_type_script_setup_true_lang.js +338 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpSeparator.js +2 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpSeparator.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpSeparator.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/es/src/components/CdsOtpInput/CdsOtpSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.constants.js +16 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.constants.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.props.js +97 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.props.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.types.js +2 -0
- package/dist/es/src/components/CdsOtpInput/api/CdsOtpInput.types.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/composables/useOtpInput.js +329 -0
- package/dist/es/src/components/CdsOtpInput/composables/useOtpInput.js.map +1 -0
- package/dist/es/src/components/CdsOtpInput/index.js +17 -0
- package/dist/es/src/components/CdsOtpInput/index.js.map +1 -0
- package/dist/es/src/components/index.js +10 -0
- package/dist/es/src/components/index.js.map +1 -1
- package/dist/es/src/composables/useDisabled/index.js +1 -1
- package/dist/es/src/composables/useDisabled/index.js.map +1 -1
- package/dist/es/src/composables/useLoader/index.js +1 -1
- package/dist/es/src/composables/useLoader/index.js.map +1 -1
- package/dist/es/src/composables/useLocation/index.js +1 -1
- package/dist/es/src/composables/useLocation/index.js.map +1 -1
- package/dist/es/src/composables/useRouter/index.js +1 -1
- package/dist/es/src/composables/useRouter/index.js.map +1 -1
- package/dist/es/src/locales/ru.js +1 -0
- package/dist/es/src/locales/ru.js.map +1 -1
- package/dist/esm-node/entry.mjs +173 -163
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpField.mjs +2 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpField.vue_vue_type_script_setup_true_lang.mjs +62 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpGroup.mjs +2 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpGroup.vue_vue_type_script_setup_true_lang.mjs +51 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpInput.css +204 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpInput.mjs +2 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpInput.vue_vue_type_script_setup_true_lang.mjs +336 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpSeparator.mjs +2 -0
- package/dist/esm-node/src/components/CdsOtpInput/CdsOtpSeparator.vue_vue_type_script_setup_true_lang.mjs +34 -0
- package/dist/esm-node/src/components/CdsOtpInput/api/CdsOtpInput.constants.mjs +16 -0
- package/dist/esm-node/src/components/CdsOtpInput/api/CdsOtpInput.props.mjs +97 -0
- package/dist/esm-node/src/components/CdsOtpInput/api/CdsOtpInput.types.mjs +2 -0
- package/dist/esm-node/src/components/CdsOtpInput/composables/useOtpInput.mjs +329 -0
- package/dist/esm-node/src/components/CdsOtpInput/index.mjs +17 -0
- package/dist/esm-node/src/components/index.mjs +10 -0
- package/dist/esm-node/src/composables/useLoader/index.mjs +1 -1
- package/dist/esm-node/src/composables/useLocation/index.mjs +1 -1
- package/dist/esm-node/src/composables/useRouter/index.mjs +1 -1
- package/dist/esm-node/src/locales/ru.mjs +1 -0
- package/dist/iife/entry.js +10 -10
- package/dist/styles.css +1 -1
- package/dist/types/components/CdsOtpInput/CdsOtpField.vue.d.ts +25 -0
- package/dist/types/components/CdsOtpInput/CdsOtpGroup.vue.d.ts +34 -0
- package/dist/types/components/CdsOtpInput/CdsOtpInput.vue.d.ts +222 -0
- package/dist/types/components/CdsOtpInput/CdsOtpSeparator.vue.d.ts +25 -0
- package/dist/types/components/CdsOtpInput/api/CdsOtpInput.constants.d.ts +9 -0
- package/dist/types/components/CdsOtpInput/api/CdsOtpInput.props.d.ts +340 -0
- package/dist/types/components/CdsOtpInput/api/CdsOtpInput.types.d.ts +47 -0
- package/dist/types/components/CdsOtpInput/composables/useOtpInput.d.ts +76 -0
- package/dist/types/components/CdsOtpInput/index.d.ts +529 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/entry.d.ts +5 -1
- package/dist/types/locales/en.d.ts +1 -0
- package/dist/types/locales/ru.d.ts +1 -0
- package/llms/llms-components.txt +512 -1
- package/llms/llms-full.txt +513 -2
- package/llms/llms-guides.txt +1 -1
- package/llms/llms-migration.txt +2 -2
- package/llms/llms-tokens.txt +1 -1
- package/llms/llms.txt +4 -3
- package/package.json +1 -1
package/llms/llms-components.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Central Design System (CDS 4) — компоненты
|
|
2
2
|
|
|
3
|
-
> Версия: 4.0.0-alpha.
|
|
3
|
+
> Версия: 4.0.0-alpha.3
|
|
4
4
|
> Документация всех компонентов `@central-design-system/components`: назначение, примеры и полный контракт API.
|
|
5
5
|
> Сгенерировано автоматически (`bun run generate:meta` → `bun run generate:llms`). Не редактировать вручную.
|
|
6
6
|
|
|
@@ -19750,6 +19750,517 @@ function onUpdateModelValue(value: boolean, id: number) {
|
|
|
19750
19750
|
|
|
19751
19751
|
---
|
|
19752
19752
|
|
|
19753
|
+
# CdsOtpInput
|
|
19754
|
+
|
|
19755
|
+
_Категория: Controls · появился в 4.0.0 · статус: new_
|
|
19756
|
+
|
|
19757
|
+
Поле ввода одноразового кода — из SMS, письма или приложения-аутентификатора. Внешне это ряд отдельных ячеек, но ввод принимает один скрытый `input`: поэтому работают автозаполнение кода из SMS, вставка целой строкой из буфера, выделение и стрелки, а фокус не приходится перепрыгивать между ячейками вручную.
|
|
19758
|
+
|
|
19759
|
+
**Смотрите также:** Для обычного короткого текста или числа возьмите CdsTextInput: `CdsOtpInput` нужен там, где длина ввода известна заранее и каждый символ показывается отдельной ячейкой.
|
|
19760
|
+
|
|
19761
|
+
## Анатомия
|
|
19762
|
+
|
|
19763
|
+
Ячейки (`CdsOtpField`) только рисуют код — введённый символ, заполнитель или
|
|
19764
|
+
мигающую каретку. Настоящий ввод принимает скрытый `input`: он прижат к нижнему
|
|
19765
|
+
краю компонента, поэтому подсказка автозаполнения из SMS появляется под ячейками
|
|
19766
|
+
и ничего не перекрывает. Между ячейками может стоять разделитель
|
|
19767
|
+
(`CdsOtpSeparator`), а в слитном виде ячейки собираются в группу (`CdsOtpGroup`).
|
|
19768
|
+
|
|
19769
|
+
**Пример — `Anatomy.vue`:**
|
|
19770
|
+
|
|
19771
|
+
```vue
|
|
19772
|
+
<script setup lang="ts">
|
|
19773
|
+
import AnatomyDemo from '@cds/utils/docs/AnatomyDemo.vue';
|
|
19774
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19775
|
+
|
|
19776
|
+
// Схема 1: обычный ряд — ячейки и разделители между ними
|
|
19777
|
+
const fieldsMarkers = [
|
|
19778
|
+
{ selector: '.cds-otp-input__content', label: 'Ряд ячеек', side: 'right' as const },
|
|
19779
|
+
{ selector: '.cds-otp-field', label: 'Ячейка (CdsOtpField)', side: 'top' as const },
|
|
19780
|
+
{ selector: '.cds-otp-separator', label: 'Разделитель (CdsOtpSeparator)', side: 'bottom' as const },
|
|
19781
|
+
{ selector: '.cds-otp-field__placeholder', label: 'Символ-заполнитель', side: 'bottom' as const }
|
|
19782
|
+
];
|
|
19783
|
+
|
|
19784
|
+
// Схема 2: слитный вид — ячейки собраны в общую группу
|
|
19785
|
+
const mergedMarkers = [
|
|
19786
|
+
{ selector: '.cds-otp-field', label: 'Ячейка (CdsOtpField)', side: 'top' as const },
|
|
19787
|
+
{ selector: '.cds-otp-group', label: 'Группа (CdsOtpGroup)', side: 'bottom' as const }
|
|
19788
|
+
];
|
|
19789
|
+
</script>
|
|
19790
|
+
|
|
19791
|
+
<template>
|
|
19792
|
+
<div class="flex flex-col gap-600">
|
|
19793
|
+
<AnatomyDemo :markers="fieldsMarkers">
|
|
19794
|
+
<CdsOtpInput model-value="12" divider="-" placeholder="0" />
|
|
19795
|
+
</AnatomyDemo>
|
|
19796
|
+
|
|
19797
|
+
<AnatomyDemo :markers="mergedMarkers">
|
|
19798
|
+
<CdsOtpInput model-value="12" merged />
|
|
19799
|
+
</AnatomyDemo>
|
|
19800
|
+
</div>
|
|
19801
|
+
</template>
|
|
19802
|
+
```
|
|
19803
|
+
|
|
19804
|
+
## Вариации
|
|
19805
|
+
|
|
19806
|
+
### Длина и тип кода
|
|
19807
|
+
|
|
19808
|
+
Свойство `length` задаёт число ячеек, `type` — что можно вводить: `number`
|
|
19809
|
+
(по умолчанию) принимает только цифры и открывает цифровую клавиатуру на
|
|
19810
|
+
мобильных, `text` — любые символы, `password` дополнительно скрывает введённое
|
|
19811
|
+
точками. Тот же эффект без смены типа даёт `masked`.
|
|
19812
|
+
|
|
19813
|
+
**Пример — `LengthAndType.vue`:**
|
|
19814
|
+
|
|
19815
|
+
```vue
|
|
19816
|
+
<script setup lang="ts">
|
|
19817
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19818
|
+
</script>
|
|
19819
|
+
|
|
19820
|
+
<template>
|
|
19821
|
+
<div class="flex flex-col items-center gap-400">
|
|
19822
|
+
<CdsOtpInput :length="4" model-value="1234" />
|
|
19823
|
+
<CdsOtpInput type="text" model-value="AB12CD" />
|
|
19824
|
+
<CdsOtpInput type="password" model-value="123456" />
|
|
19825
|
+
</div>
|
|
19826
|
+
</template>
|
|
19827
|
+
```
|
|
19828
|
+
|
|
19829
|
+
### Допустимые символы
|
|
19830
|
+
|
|
19831
|
+
Свойство `pattern` сужает набор символов: имя готового набора (`numeric`,
|
|
19832
|
+
`alpha`, `alphanumeric`, `unicode-alpha`, `unicode-alphanumeric`) или своё
|
|
19833
|
+
регулярное выражение. Проверка идёт посимвольно — лишние символы не попадут в
|
|
19834
|
+
поле ни с клавиатуры, ни из буфера обмена.
|
|
19835
|
+
|
|
19836
|
+
**Пример — `Pattern.vue`:**
|
|
19837
|
+
|
|
19838
|
+
```vue
|
|
19839
|
+
<script setup lang="ts">
|
|
19840
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19841
|
+
</script>
|
|
19842
|
+
|
|
19843
|
+
<template>
|
|
19844
|
+
<div class="flex flex-col items-center gap-400">
|
|
19845
|
+
<CdsOtpInput type="text" pattern="alpha" :length="4" placeholder="A" />
|
|
19846
|
+
<CdsOtpInput type="text" pattern="alphanumeric" placeholder="X" />
|
|
19847
|
+
<CdsOtpInput type="text" :pattern="/[0-9A-F]/" placeholder="F" />
|
|
19848
|
+
</div>
|
|
19849
|
+
</template>
|
|
19850
|
+
```
|
|
19851
|
+
|
|
19852
|
+
### Разделитель
|
|
19853
|
+
|
|
19854
|
+
Свойство `divider` ставит символ между ячейками — например, дефис в коде вида
|
|
19855
|
+
`123-456`. Слот `divider` даёт полную свободу разметки и получает `index` —
|
|
19856
|
+
номер ячейки слева от разделителя, так что разделитель можно поставить только
|
|
19857
|
+
в нужном месте.
|
|
19858
|
+
|
|
19859
|
+
**Пример — `Divider.vue`:**
|
|
19860
|
+
|
|
19861
|
+
```vue
|
|
19862
|
+
<script setup lang="ts">
|
|
19863
|
+
import { CdsIcon, CdsOtpInput } from '@central-design-system/components';
|
|
19864
|
+
</script>
|
|
19865
|
+
|
|
19866
|
+
<template>
|
|
19867
|
+
<div class="flex flex-col items-center gap-400">
|
|
19868
|
+
<CdsOtpInput divider="-" model-value="123456" />
|
|
19869
|
+
|
|
19870
|
+
<CdsOtpInput model-value="123456">
|
|
19871
|
+
<template #divider="{ index }">
|
|
19872
|
+
<CdsIcon v-if="index === 2" name="minus" size="sm" />
|
|
19873
|
+
</template>
|
|
19874
|
+
</CdsOtpInput>
|
|
19875
|
+
</div>
|
|
19876
|
+
</template>
|
|
19877
|
+
```
|
|
19878
|
+
|
|
19879
|
+
### Слитный вид
|
|
19880
|
+
|
|
19881
|
+
Свойство `merged` убирает промежутки: ячейки становятся одним полем с общей
|
|
19882
|
+
рамкой. Такой вид компактнее и меньше дробит форму.
|
|
19883
|
+
|
|
19884
|
+
**Пример — `Merged.vue`:**
|
|
19885
|
+
|
|
19886
|
+
```vue
|
|
19887
|
+
<script setup lang="ts">
|
|
19888
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19889
|
+
</script>
|
|
19890
|
+
|
|
19891
|
+
<template>
|
|
19892
|
+
<div class="flex justify-center">
|
|
19893
|
+
<CdsOtpInput merged model-value="1234" />
|
|
19894
|
+
</div>
|
|
19895
|
+
</template>
|
|
19896
|
+
```
|
|
19897
|
+
|
|
19898
|
+
### Заполнитель
|
|
19899
|
+
|
|
19900
|
+
Свойство `placeholder` показывает символ в пустых ячейках — подсказку формата
|
|
19901
|
+
или просто точку, чтобы ряд не выглядел пустым.
|
|
19902
|
+
|
|
19903
|
+
**Пример — `Placeholder.vue`:**
|
|
19904
|
+
|
|
19905
|
+
```vue
|
|
19906
|
+
<script setup lang="ts">
|
|
19907
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19908
|
+
</script>
|
|
19909
|
+
|
|
19910
|
+
<template>
|
|
19911
|
+
<div class="flex flex-col items-center gap-400">
|
|
19912
|
+
<CdsOtpInput placeholder="0" />
|
|
19913
|
+
<CdsOtpInput placeholder="•" />
|
|
19914
|
+
</div>
|
|
19915
|
+
</template>
|
|
19916
|
+
```
|
|
19917
|
+
|
|
19918
|
+
### Размеры
|
|
19919
|
+
|
|
19920
|
+
Свойство `size` меняет высоту ячеек и размер шрифта. Размер по умолчанию — `md`.
|
|
19921
|
+
|
|
19922
|
+
**Пример — `Sizes.vue`:**
|
|
19923
|
+
|
|
19924
|
+
```vue
|
|
19925
|
+
<script setup lang="ts">
|
|
19926
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19927
|
+
|
|
19928
|
+
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
19929
|
+
</script>
|
|
19930
|
+
|
|
19931
|
+
<template>
|
|
19932
|
+
<div class="flex flex-col items-center gap-400">
|
|
19933
|
+
<CdsOtpInput v-for="size of sizes" :key="size" :size="size" :length="4" model-value="1234" />
|
|
19934
|
+
</div>
|
|
19935
|
+
</template>
|
|
19936
|
+
```
|
|
19937
|
+
|
|
19938
|
+
### Состояния
|
|
19939
|
+
|
|
19940
|
+
`disabled` блокирует ввод, `error` подсвечивает весь ряд ошибкой, `loading`
|
|
19941
|
+
показывает индикатор поверх ячеек и не стирает набранный код. `focus-all`
|
|
19942
|
+
подсвечивает весь ряд, пока поле в фокусе, а не только активную ячейку.
|
|
19943
|
+
|
|
19944
|
+
**Пример — `States.vue`:**
|
|
19945
|
+
|
|
19946
|
+
```vue
|
|
19947
|
+
<script setup lang="ts">
|
|
19948
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
19949
|
+
</script>
|
|
19950
|
+
|
|
19951
|
+
<template>
|
|
19952
|
+
<div class="flex flex-col items-center gap-400">
|
|
19953
|
+
<CdsOtpInput :length="4" model-value="12" disabled />
|
|
19954
|
+
<CdsOtpInput :length="4" model-value="1234" error />
|
|
19955
|
+
<CdsOtpInput :length="4" model-value="1234" loading />
|
|
19956
|
+
<CdsOtpInput :length="4" model-value="12" focus-all />
|
|
19957
|
+
</div>
|
|
19958
|
+
</template>
|
|
19959
|
+
```
|
|
19960
|
+
|
|
19961
|
+
### Слоты
|
|
19962
|
+
|
|
19963
|
+
| Слот | Описание |
|
|
19964
|
+
| :-------- | :---------------------------------------------------------------------------- |
|
|
19965
|
+
| `fields` | Ряд ячеек целиком — своя разметка из `CdsOtpGroup`, `CdsOtpField` и `CdsOtpSeparator` |
|
|
19966
|
+
| `divider` | Разделитель между ячейками, `index` — номер ячейки слева от него |
|
|
19967
|
+
| `loader` | Свой индикатор загрузки (при `loading`) |
|
|
19968
|
+
| `default` | Произвольный контент поверх ячеек |
|
|
19969
|
+
|
|
19970
|
+
Слот `fields` нужен, когда ячейки собираются в группы: каждая `CdsOtpField`
|
|
19971
|
+
получает свой `index`, а `CdsOtpGroup` объединяет соседние ячейки в общую рамку.
|
|
19972
|
+
|
|
19973
|
+
**Пример — `CustomFields.vue`:**
|
|
19974
|
+
|
|
19975
|
+
```vue
|
|
19976
|
+
<script setup lang="ts">
|
|
19977
|
+
import { CdsOtpField, CdsOtpGroup, CdsOtpInput, CdsOtpSeparator } from '@central-design-system/components';
|
|
19978
|
+
</script>
|
|
19979
|
+
|
|
19980
|
+
<template>
|
|
19981
|
+
<div class="flex justify-center">
|
|
19982
|
+
<CdsOtpInput model-value="123456">
|
|
19983
|
+
<template #fields>
|
|
19984
|
+
<CdsOtpGroup merged>
|
|
19985
|
+
<CdsOtpField v-for="index of [0, 1, 2]" :key="index" :index="index" />
|
|
19986
|
+
</CdsOtpGroup>
|
|
19987
|
+
|
|
19988
|
+
<CdsOtpSeparator>—</CdsOtpSeparator>
|
|
19989
|
+
|
|
19990
|
+
<CdsOtpGroup merged>
|
|
19991
|
+
<CdsOtpField v-for="index of [3, 4, 5]" :key="index" :index="index" />
|
|
19992
|
+
</CdsOtpGroup>
|
|
19993
|
+
</template>
|
|
19994
|
+
</CdsOtpInput>
|
|
19995
|
+
</div>
|
|
19996
|
+
</template>
|
|
19997
|
+
```
|
|
19998
|
+
|
|
19999
|
+
## Рекомендации
|
|
20000
|
+
|
|
20001
|
+
| ✅ Хорошо | ❌ Плохо |
|
|
20002
|
+
| --- | --- |
|
|
20003
|
+
| Число ячеек равно длине кода — пользователь сразу видит, сколько символов вводить. | Лишние ячейки заставляют гадать, весь ли код набран. |
|
|
20004
|
+
| Код целиком набирается в одном поле: вставка из буфера и автозаполнение из SMS работают. | Отдельные текстовые поля ломают вставку кода и заставляют вручную перепрыгивать фокус. |
|
|
20005
|
+
| При ошибке поле остаётся доступным, а текст рядом говорит, что делать дальше. | Заблокированное поле без объяснения не даёт исправить код. |
|
|
20006
|
+
|
|
20007
|
+
## Сценарии использования
|
|
20008
|
+
|
|
20009
|
+
### Подтверждение по SMS
|
|
20010
|
+
|
|
20011
|
+
Событие `finish` срабатывает, как только код набран целиком, — отправляйте
|
|
20012
|
+
запрос по нему, отдельная кнопка не нужна. На время проверки включите `loading`:
|
|
20013
|
+
код остаётся на экране, а поле не выглядит сломанным. Если сервер не принял код,
|
|
20014
|
+
`error` подсвечивает ряд, а методы `reset()` и `focus()` через ref очищают поле
|
|
20015
|
+
и возвращают в него курсор.
|
|
20016
|
+
|
|
20017
|
+
**Пример — `SmsConfirmation.vue`:**
|
|
20018
|
+
|
|
20019
|
+
```vue
|
|
20020
|
+
<script setup lang="ts">
|
|
20021
|
+
import { CdsOtpInput } from '@central-design-system/components';
|
|
20022
|
+
import { ref } from 'vue';
|
|
20023
|
+
|
|
20024
|
+
const otpRef = ref<InstanceType<typeof CdsOtpInput>>();
|
|
20025
|
+
|
|
20026
|
+
const code = ref('');
|
|
20027
|
+
const loading = ref(false);
|
|
20028
|
+
const status = ref<'idle' | 'success' | 'error'>('idle');
|
|
20029
|
+
|
|
20030
|
+
// Имитация проверки кода на сервере: верный код — 123456
|
|
20031
|
+
function onFinish(value: string) {
|
|
20032
|
+
loading.value = true;
|
|
20033
|
+
status.value = 'idle';
|
|
20034
|
+
|
|
20035
|
+
setTimeout(() => {
|
|
20036
|
+
loading.value = false;
|
|
20037
|
+
status.value = value === '123456' ? 'success' : 'error';
|
|
20038
|
+
|
|
20039
|
+
if (status.value === 'error') {
|
|
20040
|
+
otpRef.value?.reset();
|
|
20041
|
+
otpRef.value?.focus();
|
|
20042
|
+
}
|
|
20043
|
+
}, 1000);
|
|
20044
|
+
}
|
|
20045
|
+
</script>
|
|
20046
|
+
|
|
20047
|
+
<template>
|
|
20048
|
+
<div class="flex flex-col items-center gap-300">
|
|
20049
|
+
<p class="text-200 text-content-secondary">Код отправлен на +7 999 000-00-00</p>
|
|
20050
|
+
|
|
20051
|
+
<CdsOtpInput
|
|
20052
|
+
ref="otpRef"
|
|
20053
|
+
v-model="code"
|
|
20054
|
+
:loading="loading"
|
|
20055
|
+
:error="status === 'error'"
|
|
20056
|
+
@finish="onFinish"
|
|
20057
|
+
@update:model-value="status = 'idle'"
|
|
20058
|
+
/>
|
|
20059
|
+
|
|
20060
|
+
<p v-if="status === 'success'" class="text-200 text-status-success-content">Код подтверждён</p>
|
|
20061
|
+
<p v-else-if="status === 'error'" class="text-200 text-status-danger-content">
|
|
20062
|
+
Код неверный — введите последние цифры из SMS ещё раз
|
|
20063
|
+
</p>
|
|
20064
|
+
<p v-else class="text-200 text-content-tertiary">Введите 123456, чтобы увидеть подтверждение</p>
|
|
20065
|
+
</div>
|
|
20066
|
+
</template>
|
|
20067
|
+
```
|
|
20068
|
+
|
|
20069
|
+
### Повторная отправка кода
|
|
20070
|
+
|
|
20071
|
+
Кнопка «Отправить снова» открывается по таймеру — так пользователь не завалит
|
|
20072
|
+
запросами шлюз. Вместе с новым кодом сбрасывайте поле: `reset()` очищает ячейки,
|
|
20073
|
+
`focus()` ставит курсор в первую, и старый код не смешивается с новым.
|
|
20074
|
+
|
|
20075
|
+
**Пример — `ResendCode.vue`:**
|
|
20076
|
+
|
|
20077
|
+
```vue
|
|
20078
|
+
<script setup lang="ts">
|
|
20079
|
+
import { CdsButton, CdsOtpInput } from '@central-design-system/components';
|
|
20080
|
+
import { onScopeDispose, ref } from 'vue';
|
|
20081
|
+
|
|
20082
|
+
const otpRef = ref<InstanceType<typeof CdsOtpInput>>();
|
|
20083
|
+
|
|
20084
|
+
const code = ref('');
|
|
20085
|
+
const seconds = ref(15);
|
|
20086
|
+
|
|
20087
|
+
let timer: ReturnType<typeof setInterval> | undefined;
|
|
20088
|
+
|
|
20089
|
+
function countdown() {
|
|
20090
|
+
clearInterval(timer);
|
|
20091
|
+
|
|
20092
|
+
timer = setInterval(() => {
|
|
20093
|
+
seconds.value -= 1;
|
|
20094
|
+
|
|
20095
|
+
if (seconds.value <= 0) clearInterval(timer);
|
|
20096
|
+
}, 1000);
|
|
20097
|
+
}
|
|
20098
|
+
|
|
20099
|
+
function resend() {
|
|
20100
|
+
seconds.value = 15;
|
|
20101
|
+
countdown();
|
|
20102
|
+
|
|
20103
|
+
otpRef.value?.reset();
|
|
20104
|
+
otpRef.value?.focus();
|
|
20105
|
+
}
|
|
20106
|
+
|
|
20107
|
+
countdown();
|
|
20108
|
+
onScopeDispose(() => clearInterval(timer));
|
|
20109
|
+
</script>
|
|
20110
|
+
|
|
20111
|
+
<template>
|
|
20112
|
+
<div class="flex flex-col items-center gap-300">
|
|
20113
|
+
<CdsOtpInput ref="otpRef" v-model="code" placeholder="•" />
|
|
20114
|
+
|
|
20115
|
+
<CdsButton
|
|
20116
|
+
appearance="tertiary"
|
|
20117
|
+
size="sm"
|
|
20118
|
+
:disabled="seconds > 0"
|
|
20119
|
+
:text="seconds > 0 ? `Отправить снова через ${seconds} с` : 'Отправить код снова'"
|
|
20120
|
+
@click="resend"
|
|
20121
|
+
/>
|
|
20122
|
+
</div>
|
|
20123
|
+
</template>
|
|
20124
|
+
```
|
|
20125
|
+
|
|
20126
|
+
### Код в форме
|
|
20127
|
+
|
|
20128
|
+
Когда код — часть формы входа, оставьте кнопку подтверждения: она даёт явный
|
|
20129
|
+
момент отправки. Кнопка ждёт, пока набраны все символы, — длину кода видно из
|
|
20130
|
+
`v-model`, а `disabled` на поле фиксирует уже подтверждённый код.
|
|
20131
|
+
|
|
20132
|
+
**Пример — `TwoFactorForm.vue`:**
|
|
20133
|
+
|
|
20134
|
+
```vue
|
|
20135
|
+
<script setup lang="ts">
|
|
20136
|
+
import { CdsButton, CdsForm, CdsOtpInput } from '@central-design-system/components';
|
|
20137
|
+
import { computed, ref } from 'vue';
|
|
20138
|
+
|
|
20139
|
+
const code = ref('');
|
|
20140
|
+
const loading = ref(false);
|
|
20141
|
+
const confirmed = ref(false);
|
|
20142
|
+
|
|
20143
|
+
const isComplete = computed(() => code.value.length === 6);
|
|
20144
|
+
|
|
20145
|
+
function submit() {
|
|
20146
|
+
loading.value = true;
|
|
20147
|
+
|
|
20148
|
+
setTimeout(() => {
|
|
20149
|
+
loading.value = false;
|
|
20150
|
+
confirmed.value = true;
|
|
20151
|
+
}, 1000);
|
|
20152
|
+
}
|
|
20153
|
+
</script>
|
|
20154
|
+
|
|
20155
|
+
<template>
|
|
20156
|
+
<CdsForm class="flex flex-col items-center gap-300 w-[350px] m-auto" @submit.prevent="submit">
|
|
20157
|
+
<p class="text-200 text-content-secondary">Введите код из приложения-аутентификатора</p>
|
|
20158
|
+
|
|
20159
|
+
<CdsOtpInput v-model="code" :disabled="confirmed" divider="-" />
|
|
20160
|
+
|
|
20161
|
+
<CdsButton type="submit" text="Подтвердить вход" :disabled="!isComplete || confirmed" :loading="loading" block />
|
|
20162
|
+
|
|
20163
|
+
<p v-if="confirmed" class="text-200 text-status-success-content">Вход подтверждён</p>
|
|
20164
|
+
</CdsForm>
|
|
20165
|
+
</template>
|
|
20166
|
+
```
|
|
20167
|
+
|
|
20168
|
+
## API
|
|
20169
|
+
|
|
20170
|
+
### CdsOtpInput
|
|
20171
|
+
|
|
20172
|
+
**Props**
|
|
20173
|
+
|
|
20174
|
+
| Prop | Type | Default | Required | Description |
|
|
20175
|
+
| --- | --- | --- | --- | --- |
|
|
20176
|
+
| `activeColor` | `string \| undefined` | — | no | Цвет компонента, когда он находится в активном состоянии |
|
|
20177
|
+
| `autofocus` | `boolean \| undefined` | — | no | Включает автофокус |
|
|
20178
|
+
| `baseColor` | `string \| undefined` | — | no | Цвет неактивного компонента |
|
|
20179
|
+
| `bgColor` | `string \| undefined` | — | no | Цвет фона компонента |
|
|
20180
|
+
| `color` | `string \| undefined` | — | no | Цвет компонента |
|
|
20181
|
+
| `disabled` | `boolean \| null \| undefined` | `null` | no | Заблокированное состояние |
|
|
20182
|
+
| `divider` | `string \| undefined` | — | no | Символ-разделитель, который ставится между ячейками кода |
|
|
20183
|
+
| `error` | `boolean \| undefined` | — | no | Состояние ошибки |
|
|
20184
|
+
| `focusAll` | `boolean \| undefined` | — | no | Подсвечивать все ячейки, пока поле находится в фокусе, а не только активную |
|
|
20185
|
+
| `focused` | `boolean \| undefined` | — | no | Управляет состоянием фокуса компонента. Когда `true`, компонент считается сфокусированным и может применять соответствующие стили или поведение. |
|
|
20186
|
+
| `height` | `string \| number \| undefined` | — | no | Высота компонента |
|
|
20187
|
+
| `label` | `string \| undefined` | `'$cds.input.otp'` | no | Доступное имя поля (`aria-label`). Принимает ключ локализации вида `$cds.input.otp` |
|
|
20188
|
+
| `length` | `string \| number \| undefined` | `6` | no | Количество ячеек кода |
|
|
20189
|
+
| `loading` | `string \| boolean \| undefined` | — | no | Индикатор загрузки для компонента |
|
|
20190
|
+
| `masked` | `boolean \| undefined` | — | no | Скрывать введённые символы точками |
|
|
20191
|
+
| `maxHeight` | `string \| number \| undefined` | — | no | Максимальная высота компонента |
|
|
20192
|
+
| `maxWidth` | `string \| number \| undefined` | — | no | Максимальная ширина компонента |
|
|
20193
|
+
| `merged` | `boolean \| undefined` | — | no | Слитный вид: ячейки объединяются в одно поле без промежутков между ними |
|
|
20194
|
+
| `minHeight` | `string \| number \| undefined` | — | no | Минимальная высота компонента |
|
|
20195
|
+
| `minWidth` | `string \| number \| undefined` | — | no | Минимальная ширина компонента |
|
|
20196
|
+
| `modelValue` | `string \| number \| undefined` | — | no | Значение компонента v-model |
|
|
20197
|
+
| `pattern` | `RegExp \| "numeric" \| "alpha" \| "alphanumeric" \| "unicode-alpha" \| "unicode-alphanumeric" \| undefined` | — | no | Допустимые символы: имя готового паттерна (`numeric`, `alpha`, `alphanumeric`, `unicode-alpha`, `unicode-alphanumeric`) или собственное регулярное выражение |
|
|
20198
|
+
| `placeholder` | `string \| undefined` | — | no | Символ-заполнитель, который показывается в пустой ячейке |
|
|
20199
|
+
| `size` | `number \| "xs" \| "sm" \| "md" \| "lg" \| "xl" \| undefined` | `'md'` | no | Размер компонента |
|
|
20200
|
+
| `textColor` | `string \| undefined` | — | no | Цвет текста компонента |
|
|
20201
|
+
| `theme` | `string \| undefined` | — | no | Тема компонента |
|
|
20202
|
+
| `type` | `CdsOtpInputType \| undefined` | `'number'` | no | Тип вводимого кода. `number` ограничивает ввод цифрами, `password` скрывает символы |
|
|
20203
|
+
| `width` | `string \| number \| undefined` | — | no | Ширина компонента |
|
|
20204
|
+
|
|
20205
|
+
**Events**
|
|
20206
|
+
|
|
20207
|
+
| Name | Type | Description |
|
|
20208
|
+
| --- | --- | --- |
|
|
20209
|
+
| `finish` | `[value: string]` | Срабатывает, когда код набран полностью |
|
|
20210
|
+
| `update:focused` | `[focused: boolean]` | Срабатывает при получении или потере фокуса |
|
|
20211
|
+
| `update:modelValue` | `[value: string]` | Срабатывает при изменении значения компонента |
|
|
20212
|
+
|
|
20213
|
+
**Slots**
|
|
20214
|
+
|
|
20215
|
+
| Name | Type | Description |
|
|
20216
|
+
| --- | --- | --- |
|
|
20217
|
+
| `default` | `any` | Произвольный контент поверх ячеек кода |
|
|
20218
|
+
| `divider` | `{ index: number; }` | Разделитель между ячейками. `index` — номер ячейки слева от разделителя |
|
|
20219
|
+
| `fields` | `any` | Полностью заменяет ряд ячеек собственной разметкой из `CdsOtpGroup`, `CdsOtpField` и `CdsOtpSeparator` |
|
|
20220
|
+
| `loader` | `any` | Пользовательский индикатор загрузки |
|
|
20221
|
+
|
|
20222
|
+
**Exposed**
|
|
20223
|
+
|
|
20224
|
+
| Name | Type | Description |
|
|
20225
|
+
| --- | --- | --- |
|
|
20226
|
+
| `blur` | `() => void` | Снять фокус с поля |
|
|
20227
|
+
| `focus` | `() => void` | Установить фокус на поле |
|
|
20228
|
+
| `inputRef` | `HTMLInputElement \| undefined` | Ref-ссылка на скрытый input, который принимает ввод кода |
|
|
20229
|
+
| `isFocused` | `boolean \| undefined` | Состояние фокуса поля |
|
|
20230
|
+
| `reset` | `() => void` | Очистить введённый код |
|
|
20231
|
+
|
|
20232
|
+
### CdsOtpField
|
|
20233
|
+
|
|
20234
|
+
**Props**
|
|
20235
|
+
|
|
20236
|
+
| Prop | Type | Default | Required | Description |
|
|
20237
|
+
| --- | --- | --- | --- | --- |
|
|
20238
|
+
| `index` | `number` | — | yes | Порядковый номер ячейки, начиная с нуля |
|
|
20239
|
+
|
|
20240
|
+
### CdsOtpGroup
|
|
20241
|
+
|
|
20242
|
+
**Props**
|
|
20243
|
+
|
|
20244
|
+
| Prop | Type | Default | Required | Description |
|
|
20245
|
+
| --- | --- | --- | --- | --- |
|
|
20246
|
+
| `merged` | `boolean \| null \| undefined` | — | no | Слитный вид группы. По умолчанию наследуется от родительского `CdsOtpInput` |
|
|
20247
|
+
|
|
20248
|
+
**Slots**
|
|
20249
|
+
|
|
20250
|
+
| Name | Type | Description |
|
|
20251
|
+
| --- | --- | --- |
|
|
20252
|
+
| `default` | `any` | Ячейки кода группы |
|
|
20253
|
+
|
|
20254
|
+
### CdsOtpSeparator
|
|
20255
|
+
|
|
20256
|
+
**Slots**
|
|
20257
|
+
|
|
20258
|
+
| Name | Type | Description |
|
|
20259
|
+
| --- | --- | --- |
|
|
20260
|
+
| `default` | `any` | Содержимое разделителя |
|
|
20261
|
+
|
|
20262
|
+
---
|
|
20263
|
+
|
|
19753
20264
|
# CdsOverlay
|
|
19754
20265
|
|
|
19755
20266
|
_Категория: Content · появился в 4.0.0_
|