@reformer/ui-kit 1.0.0-beta.1

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/dist/components/form-array/form-array-section.d.ts +60 -0
  4. package/dist/components/form-array/index.d.ts +2 -0
  5. package/dist/components/form-wizard/form-wizard-actions.d.ts +11 -0
  6. package/dist/components/form-wizard/form-wizard-progress.d.ts +7 -0
  7. package/dist/components/form-wizard/form-wizard.d.ts +40 -0
  8. package/dist/components/form-wizard/index.d.ts +8 -0
  9. package/dist/components/form-wizard/step-indicator.d.ts +10 -0
  10. package/dist/components/state/error-state.d.ts +10 -0
  11. package/dist/components/state/index.d.ts +2 -0
  12. package/dist/components/state/loading-state.d.ts +8 -0
  13. package/dist/components/ui/async-boundary.d.ts +63 -0
  14. package/dist/components/ui/box.d.ts +41 -0
  15. package/dist/components/ui/button.d.ts +35 -0
  16. package/dist/components/ui/checkbox.d.ts +48 -0
  17. package/dist/components/ui/collapsible.d.ts +59 -0
  18. package/dist/components/ui/example-card.d.ts +57 -0
  19. package/dist/components/ui/form-field.d.ts +72 -0
  20. package/dist/components/ui/input-mask.d.ts +52 -0
  21. package/dist/components/ui/input-password.d.ts +51 -0
  22. package/dist/components/ui/input.d.ts +54 -0
  23. package/dist/components/ui/radio-group.d.ts +60 -0
  24. package/dist/components/ui/section.d.ts +52 -0
  25. package/dist/components/ui/select.d.ts +316 -0
  26. package/dist/components/ui/textarea.d.ts +53 -0
  27. package/dist/form-array-section-CItAR061.js +92 -0
  28. package/dist/form-array.d.ts +2 -0
  29. package/dist/form-array.js +4 -0
  30. package/dist/form-wizard-C-yRYqTI.js +118 -0
  31. package/dist/form-wizard.d.ts +2 -0
  32. package/dist/form-wizard.js +7 -0
  33. package/dist/index.d.ts +37 -0
  34. package/dist/index.js +170 -0
  35. package/dist/lib/utils.d.ts +29 -0
  36. package/dist/loading-state-4VeOE6iN.js +38 -0
  37. package/dist/state.d.ts +2 -0
  38. package/dist/state.js +5 -0
  39. package/dist/ui/async-boundary.d.ts +2 -0
  40. package/dist/ui/async-boundary.js +12 -0
  41. package/dist/ui/box.d.ts +2 -0
  42. package/dist/ui/box.js +7 -0
  43. package/dist/ui/button.d.ts +2 -0
  44. package/dist/ui/button.js +78 -0
  45. package/dist/ui/checkbox.d.ts +2 -0
  46. package/dist/ui/checkbox.js +35 -0
  47. package/dist/ui/collapsible.d.ts +2 -0
  48. package/dist/ui/collapsible.js +31 -0
  49. package/dist/ui/form-field.d.ts +2 -0
  50. package/dist/ui/form-field.js +217 -0
  51. package/dist/ui/input-mask.d.ts +2 -0
  52. package/dist/ui/input-mask.js +36 -0
  53. package/dist/ui/input-password.d.ts +2 -0
  54. package/dist/ui/input-password.js +72 -0
  55. package/dist/ui/input.d.ts +2 -0
  56. package/dist/ui/input.js +48 -0
  57. package/dist/ui/radio-group.d.ts +2 -0
  58. package/dist/ui/radio-group.js +53 -0
  59. package/dist/ui/section.d.ts +2 -0
  60. package/dist/ui/section.js +16 -0
  61. package/dist/ui/select.d.ts +2 -0
  62. package/dist/ui/select.js +241 -0
  63. package/dist/ui/textarea.d.ts +2 -0
  64. package/dist/ui/textarea.js +38 -0
  65. package/dist/utils-DtaLkIY8.js +2776 -0
  66. package/llms.txt +3652 -0
  67. package/package.json +161 -0
@@ -0,0 +1,72 @@
1
+ import { FieldNode } from '@reformer/core';
2
+ import * as React from 'react';
3
+ /** Props компонента {@link FormField}. */
4
+ export interface FormFieldProps {
5
+ /**
6
+ * Поле формы. Из него берутся `component` (тип контрола), `componentProps`,
7
+ * `value`, `error`, `pending`, `setValue`, `blur`. Контрол инстанцируется
8
+ * автоматически через `CdkFormField.Control`.
9
+ */
10
+ control: FieldNode<any>;
11
+ /** Дополнительный CSS-класс для корневой `<div>`-обёртки. */
12
+ className?: string;
13
+ /**
14
+ * Префикс для `data-testid` (`field-<id>`, `label-<id>`, `input-<id>`,
15
+ * `error-<id>`). Если опущен — пытается взять `componentProps.testId`,
16
+ * иначе подставляет `'unknown'`.
17
+ */
18
+ testId?: string;
19
+ /**
20
+ * Кастомный input — оборачивается в `CdkFormField.Control asChild`. Используется,
21
+ * когда нужен нестандартный контрол (например, сторонняя маска), не
22
+ * зарегистрированный в `control.component`.
23
+ */
24
+ children?: React.ReactNode;
25
+ }
26
+ /**
27
+ * Готовый wrapper поля: автоматически рендерит `Label` → `Control` → `Error`
28
+ * из `@reformer/cdk/form-field`. Подключается напрямую `<FormField control=... />`
29
+ * или как `fieldWrapper` для `FormRenderer`.
30
+ *
31
+ * Особенности:
32
+ * - Для `Checkbox` верхний `Label` не рендерится (label идёт справа от контрола).
33
+ * - При `pending = true` (async-валидация) под полем показывается «Проверка...».
34
+ * - Обёрнут в `React.memo` со сравнением по ссылке `control` — критично для
35
+ * производительности больших форм.
36
+ *
37
+ * @example Standalone в обычной форме
38
+ * ```tsx
39
+ * import { useMemo } from 'react';
40
+ * import { createForm, type FormSchema } from '@reformer/core';
41
+ * import { Button, FormField, Input } from '@reformer/ui-kit';
42
+ *
43
+ * function RegistrationPage() {
44
+ * const form = useMemo(
45
+ * () => createForm<FormSchema<{ email: string }>>({
46
+ * email: { component: Input, componentProps: { label: 'Email' } },
47
+ * }),
48
+ * []
49
+ * );
50
+ * return (
51
+ * <form>
52
+ * <FormField control={form.email} testId="email" />
53
+ * <Button type="submit">OK</Button>
54
+ * </form>
55
+ * );
56
+ * }
57
+ * ```
58
+ *
59
+ * @example В качестве `fieldWrapper` для FormRenderer
60
+ * ```tsx
61
+ * import { FormRenderer, createRenderSchema } from '@reformer/renderer-react';
62
+ * import { FormField } from '@reformer/ui-kit';
63
+ *
64
+ * const schema = createRenderSchema<MyForm>((path) => ({
65
+ * component: 'Box',
66
+ * children: [{ component: path.email }, { component: path.phone }],
67
+ * }));
68
+ *
69
+ * <FormRenderer render={schema} settings={{ fieldWrapper: FormField }} />
70
+ * ```
71
+ */
72
+ export declare const FormField: React.NamedExoticComponent<FormFieldProps>;
@@ -0,0 +1,52 @@
1
+ import * as React from 'react';
2
+ /** Props компонента {@link InputMask}. */
3
+ export interface InputMaskProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
4
+ /** Дополнительный CSS-класс. */
5
+ className?: string;
6
+ /** Текущее значение поля. `null`/`undefined` рендерится как пустое поле. */
7
+ value?: string | null;
8
+ /** Обработчик изменений. Пустая строка приводится к `null`. */
9
+ onChange?: (value: string | null) => void;
10
+ /** Срабатывает при потере фокуса. */
11
+ onBlur?: () => void;
12
+ /**
13
+ * Шаблон маски: символ `'9'` означает «цифра», все остальные символы (`+`,
14
+ * `-`, `(`, `)`, пробел, точка) — литералы и используются в `placeholder`.
15
+ * Пример: `'+7 (999) 999-99-99'`.
16
+ */
17
+ mask?: string;
18
+ /** Подсказка внутри поля. По умолчанию равна `mask` для подсветки формата. */
19
+ placeholder?: string;
20
+ /** Блокирует ввод и редактирование. */
21
+ disabled?: boolean;
22
+ }
23
+ /**
24
+ * Текстовое поле с поддержкой простой маски-подсказки (через шаблон вида
25
+ * `'9'` для цифр). Маска показывается в `placeholder`, но автоматическая
26
+ * вставка литералов **не** выполняется — компонент просто помечает формат.
27
+ *
28
+ * @example Маска для телефона
29
+ * ```tsx
30
+ * import { InputMask } from '@reformer/ui-kit';
31
+ *
32
+ * <InputMask
33
+ * value={phone}
34
+ * onChange={setPhone}
35
+ * mask="+7 (999) 999-99-99"
36
+ * />
37
+ * ```
38
+ *
39
+ * @example Маска для даты `DD.MM.YYYY`
40
+ * ```tsx
41
+ * import { InputMask } from '@reformer/ui-kit';
42
+ *
43
+ * <InputMask
44
+ * value={birthDate}
45
+ * onChange={setBirthDate}
46
+ * mask="99.99.9999"
47
+ * placeholder="Дата рождения"
48
+ * />
49
+ * ```
50
+ */
51
+ declare const InputMask: React.ForwardRefExoticComponent<InputMaskProps & React.RefAttributes<HTMLInputElement>>;
52
+ export { InputMask };
@@ -0,0 +1,51 @@
1
+ import * as React from 'react';
2
+ /** Props компонента {@link InputPassword}. */
3
+ export interface InputPasswordProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
4
+ /** Дополнительный CSS-класс. */
5
+ className?: string;
6
+ /** Текущее значение пароля. `null`/`undefined` рендерится как пустое поле. */
7
+ value?: string | null;
8
+ /** Обработчик изменений. Пустая строка приводится к `null`. */
9
+ onChange?: (value: string | null) => void;
10
+ /** Срабатывает при потере фокуса. */
11
+ onBlur?: () => void;
12
+ /** Подсказка внутри поля. По умолчанию `'Password'`. */
13
+ placeholder?: string;
14
+ /** Блокирует ввод. */
15
+ disabled?: boolean;
16
+ /**
17
+ * Показывать ли иконку переключения видимости (eye/eye-off). По умолчанию
18
+ * `true`. Иконка появляется только когда `value` непустой.
19
+ */
20
+ showToggle?: boolean;
21
+ }
22
+ /**
23
+ * Поле ввода пароля с переключателем видимости (иконка eye/eye-off).
24
+ * Кнопка переключения показывается, когда `showToggle = true` (по умолчанию)
25
+ * и `value` непустой.
26
+ *
27
+ * @example С переключателем видимости
28
+ * ```tsx
29
+ * import { InputPassword } from '@reformer/ui-kit';
30
+ *
31
+ * <InputPassword
32
+ * value={password}
33
+ * onChange={setPassword}
34
+ * placeholder="Пароль"
35
+ * />
36
+ * ```
37
+ *
38
+ * @example Без переключателя (например, для подтверждения пароля)
39
+ * ```tsx
40
+ * import { InputPassword } from '@reformer/ui-kit';
41
+ *
42
+ * <InputPassword
43
+ * value={confirmPassword}
44
+ * onChange={setConfirmPassword}
45
+ * placeholder="Повторите пароль"
46
+ * showToggle={false}
47
+ * />
48
+ * ```
49
+ */
50
+ declare const InputPassword: React.ForwardRefExoticComponent<InputPasswordProps & React.RefAttributes<HTMLInputElement>>;
51
+ export { InputPassword };
@@ -0,0 +1,54 @@
1
+ import * as React from 'react';
2
+ /** Props компонента {@link Input}. */
3
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
4
+ /** Дополнительный CSS-класс (мерджится с дефолтными Tailwind-классами через `tailwind-merge`). */
5
+ className?: string;
6
+ /**
7
+ * Текущее значение поля. Для `type='number'` ожидается `number | null`,
8
+ * для остальных — `string | null`. `null`/`undefined` рендерится как пустое поле.
9
+ */
10
+ value?: string | number | null;
11
+ /**
12
+ * Обработчик изменений. Получает уже распарсенное значение:
13
+ * - для `type='number'` — `number` или `null` (для пустой строки),
14
+ * - иначе — `string` или `null`.
15
+ * `NaN` не прокидывается. При `min >= 0` отрицательные значения превращаются в `0`.
16
+ */
17
+ onChange?: (value: string | number | null) => void;
18
+ /** Срабатывает при потере фокуса. Используется `FormField` для пометки `touched`. */
19
+ onBlur?: () => void;
20
+ /** HTML-тип input. Для `'number'` включается специальный парсинг значения. */
21
+ type?: 'text' | 'email' | 'number' | 'tel' | 'url' | 'password';
22
+ /** Подсказка внутри поля. */
23
+ placeholder?: string;
24
+ /** Блокирует ввод и редактирование. */
25
+ disabled?: boolean;
26
+ }
27
+ /**
28
+ * Текстовое поле ввода. Контролируемый компонент с тривиальным API: `value`/`onChange`
29
+ * получает строку (или число для `type="number"`). Все нативные `<input>`-атрибуты
30
+ * (кроме `value`/`onChange`) прокидываются как есть.
31
+ *
32
+ * @example Базовое строковое поле
33
+ * ```tsx
34
+ * import { Input } from '@reformer/ui-kit';
35
+ *
36
+ * <Input value={email} onChange={setEmail} type="email" placeholder="you@example.com" />
37
+ * ```
38
+ *
39
+ * @example Числовое поле с лимитом снизу
40
+ * ```tsx
41
+ * import { Input } from '@reformer/ui-kit';
42
+ *
43
+ * // Пустой ввод даёт null. Отрицательные значения зажимаются к 0 из-за min={0}.
44
+ * <Input
45
+ * type="number"
46
+ * value={age}
47
+ * onChange={(v) => setAge(v as number | null)}
48
+ * min={0}
49
+ * placeholder="Возраст"
50
+ * />
51
+ * ```
52
+ */
53
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
54
+ export { Input };
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ /** Один вариант для {@link RadioGroup}. */
3
+ export interface RadioOption {
4
+ /** Значение, попадающее в `onChange`. Должно быть строкой (DOM `value` всегда string). */
5
+ value: string;
6
+ /** Подпись варианта, отображаемая справа от radio. */
7
+ label: string;
8
+ }
9
+ /** Props компонента {@link RadioGroup}. */
10
+ export interface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
11
+ /** Дополнительный CSS-класс контейнера. По умолчанию вертикальная раскладка `flex flex-col gap-2`. */
12
+ className?: string;
13
+ /** Текущее значение. Должно совпадать с одним из `options[i].value`. `null` — ничего не выбрано. */
14
+ value?: string | null;
15
+ /** Обработчик выбора. Получает `event.target.value`. */
16
+ onChange?: (value: string) => void;
17
+ /** Срабатывает при потере фокуса любым из radio. */
18
+ onBlur?: () => void;
19
+ /** Список вариантов выбора. */
20
+ options: RadioOption[];
21
+ /** Блокирует все варианты. */
22
+ disabled?: boolean;
23
+ /** Test-id (используется как для контейнера, так и как префикс для каждого radio). */
24
+ 'data-testid'?: string;
25
+ }
26
+ /**
27
+ * Группа радио-кнопок из массива `options`. По умолчанию раскладывается
28
+ * вертикально; для горизонтальной — `className="!flex-row gap-6"`.
29
+ *
30
+ * @example Вертикальная раскладка
31
+ * ```tsx
32
+ * import { RadioGroup } from '@reformer/ui-kit';
33
+ *
34
+ * const LOAN_TYPES = [
35
+ * { value: 'consumer', label: 'Потребительский' },
36
+ * { value: 'mortgage', label: 'Ипотека' },
37
+ * { value: 'auto', label: 'Авто' },
38
+ * ];
39
+ *
40
+ * <RadioGroup value={loanType} onChange={setLoanType} options={LOAN_TYPES} />
41
+ * ```
42
+ *
43
+ * @example Горизонтальная раскладка размеров одежды
44
+ * ```tsx
45
+ * import { RadioGroup } from '@reformer/ui-kit';
46
+ *
47
+ * <RadioGroup
48
+ * value={size}
49
+ * onChange={setSize}
50
+ * className="!flex-row gap-6"
51
+ * options={[
52
+ * { value: 's', label: 'S' },
53
+ * { value: 'm', label: 'M' },
54
+ * { value: 'l', label: 'L' },
55
+ * ]}
56
+ * />
57
+ * ```
58
+ */
59
+ declare const RadioGroup: React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<HTMLDivElement>>;
60
+ export { RadioGroup };
@@ -0,0 +1,52 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Props компонента Section
4
+ */
5
+ export interface SectionProps {
6
+ /** Заголовок секции */
7
+ title?: string;
8
+ /** HTML элемент для заголовка (h1-h6). По умолчанию h3 */
9
+ titleAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
10
+ /** CSS класс для контейнера */
11
+ className?: string;
12
+ /** CSS класс для заголовка */
13
+ titleClassName?: string;
14
+ /** Дочерние элементы */
15
+ children?: ReactNode;
16
+ }
17
+ /**
18
+ * Section - секция формы с заголовком.
19
+ *
20
+ * Семантический `<section>`-контейнер для группировки связанных полей
21
+ * с опциональным заголовком (`titleAs` управляет уровнем `h1`-`h6`).
22
+ *
23
+ * @example Заголовок h2 + сетка из двух колонок
24
+ * ```typescript
25
+ * {
26
+ * component: Section,
27
+ * componentProps: {
28
+ * title: 'Личные данные',
29
+ * titleAs: 'h2',
30
+ * titleClassName: 'text-xl font-bold',
31
+ * className: 'grid grid-cols-2 gap-4',
32
+ * },
33
+ * children: [
34
+ * { component: path.firstName },
35
+ * { component: path.lastName },
36
+ * ],
37
+ * }
38
+ * ```
39
+ *
40
+ * @example Section без заголовка (только обёртка)
41
+ * ```typescript
42
+ * {
43
+ * component: Section,
44
+ * componentProps: { className: 'space-y-4 mt-4' },
45
+ * children: [
46
+ * { component: path.address },
47
+ * { component: path.city },
48
+ * ],
49
+ * }
50
+ * ```
51
+ */
52
+ export declare function Section({ title, titleAs: TitleTag, className, titleClassName, children, }: SectionProps): ReactNode;
@@ -0,0 +1,316 @@
1
+ import * as React from 'react';
2
+ import * as SelectPrimitive from '@radix-ui/react-select';
3
+ /** Параметры запроса к {@link ResourceConfig.load}. */
4
+ interface ResourceLoadParams {
5
+ /** Поисковый запрос (для async-фильтрации). */
6
+ search?: string;
7
+ /** Номер страницы (1-based) для пагинации. */
8
+ page?: number;
9
+ /** Размер страницы. */
10
+ pageSize?: number;
11
+ /** Дополнительные пользовательские параметры. */
12
+ [key: string]: unknown;
13
+ }
14
+ /** Один элемент, возвращаемый {@link ResourceConfig.load}. */
15
+ interface ResourceItem<T> {
16
+ /** Уникальный ключ элемента (для React `key`). */
17
+ id: string | number;
18
+ /** Видимая подпись опции. */
19
+ label: string;
20
+ /** Значение, которое попадает в `onChange` (всегда приводится к строке). */
21
+ value: T;
22
+ /** Опциональное имя группы — варианты с одинаковым `group` объединяются в `SelectGroup`. */
23
+ group?: string;
24
+ /** Дополнительные поля бек-данных. */
25
+ [key: string]: unknown;
26
+ }
27
+ /** Ответ {@link ResourceConfig.load}. */
28
+ interface ResourceResult<T> {
29
+ /** Список вариантов. */
30
+ items: ResourceItem<T>[];
31
+ /** Общее число доступных вариантов (для пагинации). */
32
+ totalCount: number;
33
+ }
34
+ /** Конфигурация асинхронного источника опций для {@link Select}. */
35
+ export interface ResourceConfig<T> {
36
+ /**
37
+ * Стратегия загрузки:
38
+ * - `'static'` — варианты загружаются один раз и больше не меняются;
39
+ * - `'preload'` — загрузка на маунт компонента (используется по умолчанию в {@link Select});
40
+ * - `'partial'` — порционная загрузка (нужен будет внешний механизм пагинации).
41
+ */
42
+ type: 'static' | 'preload' | 'partial';
43
+ /** Функция загрузки опций. Должна вернуть `{ items, totalCount }`. */
44
+ load: (params?: ResourceLoadParams) => Promise<ResourceResult<T>>;
45
+ }
46
+ /** Props компонента {@link Select}. */
47
+ export interface SelectProps<T> extends Omit<React.ComponentProps<typeof SelectPrimitive.Root>, 'value' | 'onValueChange'> {
48
+ /** Дополнительный CSS-класс для триггера. */
49
+ className?: string;
50
+ /** Выбранное значение. Всегда строка из `option.value`. `null` — ничего не выбрано. */
51
+ value?: string | null;
52
+ /** Обработчик выбора. При нажатии на крестик (`clearable`) приходит `null`. */
53
+ onChange?: (value: string | null) => void;
54
+ /** Срабатывает при закрытии дропдауна (через `onOpenChange(false)`). */
55
+ onBlur?: () => void;
56
+ /** Асинхронный источник опций. Если задан вместе с `options`, приоритет у `options`. */
57
+ resource?: ResourceConfig<T>;
58
+ /**
59
+ * Inline-варианты. `value` приводится к строке. Опции с одинаковым `group`
60
+ * объединяются в `SelectGroup` с `SelectLabel` (см. рецепт grouped options).
61
+ */
62
+ options?: Array<{
63
+ value: string | number;
64
+ label: string;
65
+ group?: string;
66
+ }>;
67
+ /** Подсказка в триггере. По умолчанию `'Select an option...'`. */
68
+ placeholder?: string;
69
+ /** Блокирует выбор. */
70
+ disabled?: boolean;
71
+ /** Показывать ли кнопку очистки (X) справа от значения. По умолчанию `false`. */
72
+ clearable?: boolean;
73
+ }
74
+ /**
75
+ * Выпадающий список на `@radix-ui/react-select`. Поддерживает два режима
76
+ * источника данных: inline `options` и async `resource`. При `clearable=true`
77
+ * показывает крестик для сброса значения в `null`.
78
+ *
79
+ * @example Inline-options
80
+ * ```tsx
81
+ * import { Select } from '@reformer/ui-kit';
82
+ *
83
+ * <Select
84
+ * value={loanType}
85
+ * onChange={setLoanType}
86
+ * placeholder="Тип кредита"
87
+ * options={[
88
+ * { value: 'consumer', label: 'Потребительский' },
89
+ * { value: 'mortgage', label: 'Ипотека' },
90
+ * { value: 'auto', label: 'Авто' },
91
+ * ]}
92
+ * />
93
+ * ```
94
+ *
95
+ * @example Grouped options
96
+ * ```tsx
97
+ * import { Select } from '@reformer/ui-kit';
98
+ *
99
+ * <Select
100
+ * value={city}
101
+ * onChange={setCity}
102
+ * options={[
103
+ * { value: 'msk', label: 'Москва', group: 'Россия' },
104
+ * { value: 'spb', label: 'Санкт-Петербург', group: 'Россия' },
105
+ * { value: 'minsk', label: 'Минск', group: 'Беларусь' },
106
+ * ]}
107
+ * />
108
+ * ```
109
+ */
110
+ declare const Select: React.ForwardRefExoticComponent<SelectProps<any> & {
111
+ 'data-testid'?: string;
112
+ 'aria-invalid'?: boolean | "true" | "false";
113
+ } & React.RefAttributes<HTMLButtonElement>>;
114
+ /**
115
+ * Группа `<SelectItem>` с заголовком {@link SelectLabel}. Тонкая обёртка над
116
+ * `Radix.Select.Group`. Используется при ручной сборке кастомного дропдауна
117
+ * вместо `options`-проп `Select`.
118
+ *
119
+ * @example Группа с заголовком
120
+ * ```tsx
121
+ * import { SelectGroup, SelectLabel, SelectItem } from '@reformer/ui-kit/select';
122
+ *
123
+ * <SelectGroup>
124
+ * <SelectLabel>Фрукты</SelectLabel>
125
+ * <SelectItem value="apple">Яблоко</SelectItem>
126
+ * <SelectItem value="pear">Груша</SelectItem>
127
+ * </SelectGroup>
128
+ * ```
129
+ *
130
+ * @example Несколько групп подряд внутри SelectContent
131
+ * ```tsx
132
+ * import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@reformer/ui-kit/select';
133
+ *
134
+ * <Select value={city} onChange={setCity}>
135
+ * <SelectTrigger><SelectValue placeholder="Город" /></SelectTrigger>
136
+ * <SelectContent>
137
+ * <SelectGroup>
138
+ * <SelectLabel>Россия</SelectLabel>
139
+ * <SelectItem value="msk">Москва</SelectItem>
140
+ * </SelectGroup>
141
+ * <SelectGroup>
142
+ * <SelectLabel>Беларусь</SelectLabel>
143
+ * <SelectItem value="minsk">Минск</SelectItem>
144
+ * </SelectGroup>
145
+ * </SelectContent>
146
+ * </Select>
147
+ * ```
148
+ */
149
+ declare function SelectGroup({ ...props }: React.ComponentProps<typeof SelectPrimitive.Group>): import("react/jsx-runtime").JSX.Element;
150
+ /**
151
+ * Отображает выбранное значение внутри {@link SelectTrigger}. Обёртка над
152
+ * `Radix.Select.Value`. Поддерживает `placeholder` для пустого состояния.
153
+ *
154
+ * @example Стандартный placeholder
155
+ * ```tsx
156
+ * import { SelectTrigger, SelectValue } from '@reformer/ui-kit/select';
157
+ *
158
+ * <SelectTrigger>
159
+ * <SelectValue placeholder="Выберите вариант" />
160
+ * </SelectTrigger>
161
+ * ```
162
+ *
163
+ * @example Кастомное представление выбранного значения через children
164
+ * ```tsx
165
+ * import { SelectTrigger, SelectValue } from '@reformer/ui-kit/select';
166
+ *
167
+ * <SelectTrigger>
168
+ * <SelectValue placeholder="Не выбрано">
169
+ * {value && <span className="font-bold">{value}</span>}
170
+ * </SelectValue>
171
+ * </SelectTrigger>
172
+ * ```
173
+ */
174
+ declare function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>): import("react/jsx-runtime").JSX.Element;
175
+ /**
176
+ * Кнопка-открывалка списка для {@link Select}. Обёртка над
177
+ * `Radix.Select.Trigger` с дефолтными стилями (h-9, rounded, border) и
178
+ * `ChevronDown` справа.
179
+ *
180
+ * @example Дефолтный размер
181
+ * ```tsx
182
+ * import { SelectTrigger, SelectValue } from '@reformer/ui-kit/select';
183
+ *
184
+ * <SelectTrigger>
185
+ * <SelectValue placeholder="Выберите страну" />
186
+ * </SelectTrigger>
187
+ * ```
188
+ *
189
+ * @example Компактный (size='sm')
190
+ * ```tsx
191
+ * import { SelectTrigger, SelectValue } from '@reformer/ui-kit/select';
192
+ *
193
+ * <SelectTrigger size="sm" className="w-32">
194
+ * <SelectValue placeholder="Сорт." />
195
+ * </SelectTrigger>
196
+ * ```
197
+ */
198
+ declare function SelectTrigger({ className, size, children, 'aria-label': ariaLabel, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
199
+ size?: 'sm' | 'default';
200
+ }): import("react/jsx-runtime").JSX.Element;
201
+ /**
202
+ * Дропдаун-контент {@link Select} (попап со списком). Обёртка над
203
+ * `Radix.Select.Content` с порталом, скролл-кнопками сверху/снизу и
204
+ * `position='popper'` по умолчанию (растягивается под ширину триггера).
205
+ *
206
+ * @example Popper-режим (default — ширина равна триггеру)
207
+ * ```tsx
208
+ * import { SelectContent, SelectItem } from '@reformer/ui-kit/select';
209
+ *
210
+ * <SelectContent>
211
+ * <SelectItem value="a">A</SelectItem>
212
+ * <SelectItem value="b">B</SelectItem>
213
+ * </SelectContent>
214
+ * ```
215
+ *
216
+ * @example Item-aligned (контент центрируется по выбранному элементу)
217
+ * ```tsx
218
+ * import { SelectContent, SelectItem } from '@reformer/ui-kit/select';
219
+ *
220
+ * <SelectContent position="item-aligned">
221
+ * {LONG_LIST.map((x) => <SelectItem key={x.id} value={x.id}>{x.label}</SelectItem>)}
222
+ * </SelectContent>
223
+ * ```
224
+ */
225
+ declare function SelectContent({ className, children, position, ...props }: React.ComponentProps<typeof SelectPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
226
+ /**
227
+ * Заголовок секции внутри {@link SelectGroup}. Обёртка над
228
+ * `Radix.Select.Label`. Не выбирается; используется для визуального разделения
229
+ * групп.
230
+ *
231
+ * @example Простая подпись группы
232
+ * ```tsx
233
+ * import { SelectGroup, SelectLabel, SelectItem } from '@reformer/ui-kit/select';
234
+ *
235
+ * <SelectGroup>
236
+ * <SelectLabel>Овощи</SelectLabel>
237
+ * <SelectItem value="potato">Картошка</SelectItem>
238
+ * </SelectGroup>
239
+ * ```
240
+ *
241
+ * @example Кастомный класс заголовка
242
+ * ```tsx
243
+ * import { SelectGroup, SelectLabel } from '@reformer/ui-kit/select';
244
+ *
245
+ * <SelectGroup>
246
+ * <SelectLabel className="text-blue-600 font-bold">Премиум</SelectLabel>
247
+ * </SelectGroup>
248
+ * ```
249
+ */
250
+ declare function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>): import("react/jsx-runtime").JSX.Element;
251
+ /**
252
+ * Один пункт списка {@link Select}. Обёртка над `Radix.Select.Item` с
253
+ * чекмарком-индикатором (`CheckIcon`) для выбранного варианта.
254
+ *
255
+ * @example Простой пункт
256
+ * ```tsx
257
+ * import { SelectItem } from '@reformer/ui-kit/select';
258
+ *
259
+ * <SelectItem value="apple">Яблоко</SelectItem>
260
+ * ```
261
+ *
262
+ * @example Заблокированный пункт
263
+ * ```tsx
264
+ * import { SelectItem } from '@reformer/ui-kit/select';
265
+ *
266
+ * <SelectItem value="premium" disabled>
267
+ * Premium (требуется подписка)
268
+ * </SelectItem>
269
+ * ```
270
+ */
271
+ declare function SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
272
+ /**
273
+ * Кнопка-стрелка для скролла вверх в дропдауне {@link SelectContent}.
274
+ * `SelectContent` добавляет её автоматически, экспорт нужен для случаев
275
+ * полностью кастомной сборки.
276
+ *
277
+ * @example Автоматическое добавление SelectContent
278
+ * ```tsx
279
+ * import { SelectContent, SelectItem } from '@reformer/ui-kit/select';
280
+ *
281
+ * <SelectContent>
282
+ * <SelectItem value="a">A</SelectItem>
283
+ * </SelectContent>
284
+ * ```
285
+ *
286
+ * @example Ручное использование (кастомная сборка дропдауна)
287
+ * ```tsx
288
+ * import { SelectScrollUpButton } from '@reformer/ui-kit/select';
289
+ *
290
+ * <SelectScrollUpButton className="bg-gray-50 text-gray-600" />
291
+ * ```
292
+ */
293
+ declare function SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>): import("react/jsx-runtime").JSX.Element;
294
+ /**
295
+ * Кнопка-стрелка для скролла вниз в дропдауне {@link SelectContent}.
296
+ * `SelectContent` добавляет её автоматически, экспорт нужен для случаев
297
+ * полностью кастомной сборки.
298
+ *
299
+ * @example Автоматическое добавление SelectContent
300
+ * ```tsx
301
+ * import { SelectContent, SelectItem } from '@reformer/ui-kit/select';
302
+ *
303
+ * <SelectContent>
304
+ * <SelectItem value="a">A</SelectItem>
305
+ * </SelectContent>
306
+ * ```
307
+ *
308
+ * @example Ручное использование (кастомная сборка дропдауна)
309
+ * ```tsx
310
+ * import { SelectScrollDownButton } from '@reformer/ui-kit/select';
311
+ *
312
+ * <SelectScrollDownButton className="bg-gray-50 text-gray-600" />
313
+ * ```
314
+ */
315
+ declare function SelectScrollDownButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>): import("react/jsx-runtime").JSX.Element;
316
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue, };