@reformer/ui-kit 7.0.0 → 9.0.0
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/dist/components/state/error-state.d.ts +1 -2
- package/dist/components/state/index.d.ts +2 -0
- package/dist/components/state/loading-state.d.ts +1 -2
- package/dist/components/ui/checkbox.d.ts +1 -1
- package/dist/components/ui/input-mask.d.ts +1 -1
- package/dist/components/ui/input-password.d.ts +1 -1
- package/dist/components/ui/input.d.ts +30 -18
- package/dist/components/ui/select.d.ts +3 -3
- package/dist/components/ui/textarea.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/ui/form-field.js +141 -133
- package/dist/ui/input.js +52 -42
- package/llms.txt +55 -52
- package/package.json +6 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
interface ErrorStateProps {
|
|
2
|
+
export interface ErrorStateProps {
|
|
3
3
|
/** Текст ошибки, показывается под заголовком. */
|
|
4
4
|
error: string;
|
|
5
5
|
/** Заголовок блока ошибки. По умолчанию `'Ошибка загрузки'`. */
|
|
@@ -28,4 +28,3 @@ interface ErrorStateProps {
|
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
export declare function ErrorState({ error, title, onRetry, retryLabel, className, }: ErrorStateProps): ReactNode;
|
|
31
|
-
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
interface LoadingStateProps {
|
|
2
|
+
export interface LoadingStateProps {
|
|
3
3
|
/** Основной текст. По умолчанию `'Загрузка данных...'`. */
|
|
4
4
|
title?: string;
|
|
5
5
|
/** Вспомогательный текст под спиннером. По умолчанию `'Пожалуйста, подождите'`. */
|
|
@@ -23,4 +23,3 @@ interface LoadingStateProps {
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export declare function LoadingState({ title, subtitle, className, }: LoadingStateProps): ReactNode;
|
|
26
|
-
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/** Props компонента {@link Checkbox}. */
|
|
3
|
-
export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
3
|
+
export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'checked' | 'defaultChecked'> {
|
|
4
4
|
/** Дополнительный CSS-класс для самого input. */
|
|
5
5
|
className?: string;
|
|
6
6
|
/** Состояние чекбокса. `undefined` рендерится как `false`. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/** Props компонента {@link InputMask}. */
|
|
3
|
-
export interface InputMaskProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
|
|
3
|
+
export interface InputMaskProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'defaultValue'> {
|
|
4
4
|
/** Дополнительный CSS-класс. */
|
|
5
5
|
className?: string;
|
|
6
6
|
/** Текущее значение поля. `null`/`undefined` рендерится как пустое поле. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/** Props компонента {@link InputPassword}. */
|
|
3
|
-
export interface InputPasswordProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
3
|
+
export interface InputPasswordProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'defaultValue'> {
|
|
4
4
|
/** Дополнительный CSS-класс. */
|
|
5
5
|
className?: string;
|
|
6
6
|
/** Текущее значение пароля. `null`/`undefined` рендерится как пустое поле. */
|
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/** Общие props компонента {@link Input}, не зависящие от `type`. */
|
|
3
|
+
interface InputBaseProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'defaultValue' | 'type'> {
|
|
4
4
|
/** Дополнительный CSS-класс (мерджится с дефолтными Tailwind-классами через `tailwind-merge`). */
|
|
5
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
6
|
/** Срабатывает при потере фокуса. Используется `FormField` для пометки `touched`. */
|
|
19
7
|
onBlur?: () => void;
|
|
20
|
-
/** HTML-тип input. Для `'number'` включается специальный парсинг значения. */
|
|
21
|
-
type?: 'text' | 'email' | 'number' | 'tel' | 'url' | 'password';
|
|
22
8
|
/** Подсказка внутри поля. */
|
|
23
9
|
placeholder?: string;
|
|
24
10
|
/** Блокирует ввод и редактирование. */
|
|
25
11
|
disabled?: boolean;
|
|
26
12
|
}
|
|
13
|
+
/** Props числового поля (`type="number"`): `value`/`onChange` работают с `number`. */
|
|
14
|
+
export interface NumberInputProps extends InputBaseProps {
|
|
15
|
+
/** HTML-тип input. Включает специальный парсинг значения. */
|
|
16
|
+
type: 'number';
|
|
17
|
+
/** Текущее значение. `null`/`undefined` рендерится как пустое поле. */
|
|
18
|
+
value?: number | null;
|
|
19
|
+
/**
|
|
20
|
+
* Обработчик изменений. Получает уже распарсенное `number` или `null` (для пустой строки).
|
|
21
|
+
* `NaN` не прокидывается. При `min >= 0` отрицательные значения превращаются в `0`.
|
|
22
|
+
*/
|
|
23
|
+
onChange?: (value: number | null) => void;
|
|
24
|
+
}
|
|
25
|
+
/** Props строкового поля (любой `type`, кроме `number`): `value`/`onChange` — строковые. */
|
|
26
|
+
export interface TextInputProps extends InputBaseProps {
|
|
27
|
+
/** HTML-тип input. По умолчанию `'text'`. */
|
|
28
|
+
type?: 'text' | 'email' | 'tel' | 'url' | 'password';
|
|
29
|
+
/** Текущее значение. `null`/`undefined` рендерится как пустое поле. */
|
|
30
|
+
value?: string | null;
|
|
31
|
+
/** Обработчик изменений. Получает строку или `null` (для пустой строки). */
|
|
32
|
+
onChange?: (value: string | null) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Props компонента {@link Input} — дискриминированный union по `type`:
|
|
36
|
+
* `type="number"` даёт `number | null` для `value`/`onChange`, любой другой `type` — `string | null`.
|
|
37
|
+
*/
|
|
38
|
+
export type InputProps = NumberInputProps | TextInputProps;
|
|
27
39
|
/**
|
|
28
40
|
* Текстовое поле ввода. Контролируемый компонент с тривиальным API: `value`/`onChange`
|
|
29
41
|
* получает строку (или число для `type="number"`). Все нативные `<input>`-атрибуты
|
|
@@ -44,7 +56,7 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
|
|
|
44
56
|
* <Input
|
|
45
57
|
* type="number"
|
|
46
58
|
* value={age}
|
|
47
|
-
* onChange={
|
|
59
|
+
* onChange={setAge}
|
|
48
60
|
* min={0}
|
|
49
61
|
* placeholder="Возраст"
|
|
50
62
|
* />
|
|
@@ -62,7 +74,7 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
|
|
|
62
74
|
* type="email"
|
|
63
75
|
* value={value}
|
|
64
76
|
* disabled={disabled}
|
|
65
|
-
* onChange={(v) => control.setValue(
|
|
77
|
+
* onChange={(v) => control.setValue(v ?? '')}
|
|
66
78
|
* onBlur={() => control.markAsTouched()}
|
|
67
79
|
* aria-invalid={shouldShowError}
|
|
68
80
|
* placeholder={shouldShowError ? errors[0]?.message : 'you@example.com'}
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
4
4
|
export type { ResourceConfig, ResourceLoadParams, ResourceItem, ResourceResult, ResourceStrategy, NormalizedOption, } from './select-resource';
|
|
5
5
|
/** Props компонента {@link Select}. */
|
|
6
|
-
export interface SelectProps
|
|
6
|
+
export interface SelectProps extends Omit<React.ComponentProps<typeof SelectPrimitive.Root>, 'value' | 'onValueChange'> {
|
|
7
7
|
/** Дополнительный CSS-класс для триггера. */
|
|
8
8
|
className?: string;
|
|
9
9
|
/** Выбранное значение. Всегда строка из `option.value`. `null` — ничего не выбрано. */
|
|
@@ -13,7 +13,7 @@ export interface SelectProps<T> extends Omit<React.ComponentProps<typeof SelectP
|
|
|
13
13
|
/** Срабатывает при закрытии дропдауна (через `onOpenChange(false)`). */
|
|
14
14
|
onBlur?: () => void;
|
|
15
15
|
/** Асинхронный источник опций. Если задан вместе с `options`, приоритет у `options`. */
|
|
16
|
-
resource?: ResourceConfig<
|
|
16
|
+
resource?: ResourceConfig<unknown>;
|
|
17
17
|
/**
|
|
18
18
|
* Inline-варианты. `value` приводится к строке. Опции с одинаковым `group`
|
|
19
19
|
* объединяются в `SelectGroup` с `SelectLabel` (см. рецепт grouped options).
|
|
@@ -97,7 +97,7 @@ export interface SelectProps<T> extends Omit<React.ComponentProps<typeof SelectP
|
|
|
97
97
|
* <Select value={country} onChange={setCountry} resource={countries} />
|
|
98
98
|
* ```
|
|
99
99
|
*/
|
|
100
|
-
declare const Select: React.ForwardRefExoticComponent<SelectProps
|
|
100
|
+
declare const Select: React.ForwardRefExoticComponent<SelectProps & {
|
|
101
101
|
'data-testid'?: string;
|
|
102
102
|
'aria-invalid'?: boolean | "true" | "false";
|
|
103
103
|
} & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/** Props компонента {@link Textarea}. */
|
|
3
|
-
export interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange'> {
|
|
3
|
+
export interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange' | 'defaultValue'> {
|
|
4
4
|
/** Дополнительный CSS-класс. */
|
|
5
5
|
className?: string;
|
|
6
6
|
/** Текущее значение. `null`/`undefined` рендерится как пустое поле. */
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export { Textarea } from './components/ui/textarea';
|
|
|
27
27
|
export type { TextareaProps } from './components/ui/textarea';
|
|
28
28
|
export { ErrorState } from './components/state/error-state';
|
|
29
29
|
export { LoadingState } from './components/state/loading-state';
|
|
30
|
+
export type { ErrorStateProps } from './components/state/error-state';
|
|
31
|
+
export type { LoadingStateProps } from './components/state/loading-state';
|
|
30
32
|
export { FormArraySection } from './components/form-array/form-array-section';
|
|
31
33
|
export type { FormArraySectionProps } from './components/form-array/form-array-section';
|
|
32
34
|
export { FormWizard } from './components/form-wizard/form-wizard';
|
package/dist/ui/form-field.js
CHANGED
|
@@ -1,219 +1,227 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
3
|
-
import { forwardRef as
|
|
1
|
+
import { jsx as d, jsxs as $, Fragment as w } from "react/jsx-runtime";
|
|
2
|
+
import * as A from "react";
|
|
3
|
+
import { forwardRef as b, Children as T, isValidElement as V, cloneElement as W, useId as M, useMemo as x, createContext as k, useContext as R } from "react";
|
|
4
4
|
import { useFormControl as O } from "@reformer/core";
|
|
5
|
-
import { Checkbox as
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
import { Checkbox as z } from "./checkbox.js";
|
|
6
|
+
function G(...e) {
|
|
7
|
+
return (t) => {
|
|
8
|
+
for (const o of e)
|
|
9
|
+
typeof o == "function" ? o(t) : o != null && (o.current = t);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function H(e, t) {
|
|
13
|
+
const o = { ...e };
|
|
14
|
+
for (const r of Object.keys(t)) {
|
|
15
|
+
const n = e[r], l = t[r];
|
|
16
|
+
r.startsWith("on") && typeof n == "function" && typeof l == "function" ? o[r] = (...i) => {
|
|
17
|
+
l(...i), n(...i);
|
|
18
|
+
} : r === "className" && typeof n == "string" && typeof l == "string" ? o[r] = [l, n].filter(Boolean).join(" ") : r === "style" && typeof n == "object" && typeof l == "object" ? o[r] = { ...l, ...n } : r === "disabled" ? o[r] = !!n || !!l : l !== void 0 && (o[r] = l);
|
|
13
19
|
}
|
|
14
|
-
return
|
|
20
|
+
return o;
|
|
15
21
|
}
|
|
16
|
-
const
|
|
17
|
-
({ children: e, ...
|
|
18
|
-
const r =
|
|
19
|
-
if (!
|
|
22
|
+
const F = b(
|
|
23
|
+
({ children: e, ...t }, o) => {
|
|
24
|
+
const r = T.only(e);
|
|
25
|
+
if (!V(r))
|
|
20
26
|
return null;
|
|
21
|
-
const
|
|
22
|
-
return
|
|
23
|
-
...
|
|
24
|
-
ref:
|
|
27
|
+
const n = r.props, l = H(t, n), i = r.ref, s = G(o, i);
|
|
28
|
+
return W(r, {
|
|
29
|
+
...l,
|
|
30
|
+
ref: s
|
|
25
31
|
});
|
|
26
32
|
}
|
|
27
33
|
);
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
function
|
|
31
|
-
const e =
|
|
34
|
+
F.displayName = "Slot";
|
|
35
|
+
const j = k(null);
|
|
36
|
+
function I() {
|
|
37
|
+
const e = R(j);
|
|
32
38
|
if (!e)
|
|
33
39
|
throw new Error(
|
|
34
40
|
"FormField.* components must be used within <FormField.Root>. Wrap your field with <FormField.Root control={control}>."
|
|
35
41
|
);
|
|
36
42
|
return e;
|
|
37
43
|
}
|
|
44
|
+
const J = (e) => e.message || e.code, K = k(J);
|
|
45
|
+
function D() {
|
|
46
|
+
return R(K);
|
|
47
|
+
}
|
|
38
48
|
function N({
|
|
39
49
|
control: e,
|
|
40
|
-
children:
|
|
41
|
-
id:
|
|
50
|
+
children: t,
|
|
51
|
+
id: o,
|
|
42
52
|
hasDescription: r = !1
|
|
43
53
|
}) {
|
|
44
|
-
const
|
|
54
|
+
const n = M(), l = o ?? n, i = x(
|
|
45
55
|
() => ({
|
|
46
|
-
controlId: `control-${
|
|
47
|
-
labelId: `label-${
|
|
48
|
-
descriptionId: `desc-${
|
|
49
|
-
errorId: `error-${
|
|
56
|
+
controlId: `control-${l}`,
|
|
57
|
+
labelId: `label-${l}`,
|
|
58
|
+
descriptionId: `desc-${l}`,
|
|
59
|
+
errorId: `error-${l}`
|
|
50
60
|
}),
|
|
51
|
-
[
|
|
52
|
-
), s = O(e), c =
|
|
61
|
+
[l]
|
|
62
|
+
), s = O(e), c = D(), f = x(() => {
|
|
53
63
|
const {
|
|
54
|
-
value:
|
|
55
|
-
errors:
|
|
64
|
+
value: a,
|
|
65
|
+
errors: u,
|
|
56
66
|
pending: m,
|
|
57
|
-
disabled:
|
|
67
|
+
disabled: C,
|
|
58
68
|
valid: y,
|
|
59
|
-
invalid:
|
|
60
|
-
touched:
|
|
61
|
-
shouldShowError:
|
|
69
|
+
invalid: g,
|
|
70
|
+
touched: E,
|
|
71
|
+
shouldShowError: v,
|
|
62
72
|
componentProps: p
|
|
63
73
|
} = s;
|
|
64
74
|
return {
|
|
65
|
-
value:
|
|
66
|
-
errors:
|
|
75
|
+
value: a,
|
|
76
|
+
errors: u,
|
|
67
77
|
pending: m,
|
|
68
|
-
disabled:
|
|
78
|
+
disabled: C,
|
|
69
79
|
valid: y,
|
|
70
|
-
invalid:
|
|
71
|
-
touched:
|
|
72
|
-
shouldShowError:
|
|
73
|
-
error:
|
|
80
|
+
invalid: g,
|
|
81
|
+
touched: E,
|
|
82
|
+
shouldShowError: v,
|
|
83
|
+
error: v && u[0] ? c(u[0]) : void 0,
|
|
74
84
|
label: p.label,
|
|
75
85
|
required: !!p.required,
|
|
76
86
|
componentProps: p,
|
|
77
87
|
control: e,
|
|
78
|
-
ids:
|
|
88
|
+
ids: i,
|
|
79
89
|
hasDescription: r
|
|
80
90
|
};
|
|
81
|
-
}, [s, e,
|
|
82
|
-
return /* @__PURE__ */
|
|
91
|
+
}, [s, e, i, r, c]);
|
|
92
|
+
return /* @__PURE__ */ d(j.Provider, { value: f, children: t });
|
|
83
93
|
}
|
|
84
94
|
N.displayName = "FormField.Root";
|
|
85
|
-
const
|
|
86
|
-
({ asChild: e = !1, children:
|
|
87
|
-
const { label:
|
|
88
|
-
return !c && !
|
|
95
|
+
const S = b(
|
|
96
|
+
({ asChild: e = !1, children: t, forceRender: o = !1, ...r }, n) => {
|
|
97
|
+
const { label: l, required: i, ids: s } = I(), c = t ?? l;
|
|
98
|
+
return !c && !o ? null : /* @__PURE__ */ $(e ? F : "label", { ref: n, id: s.labelId, htmlFor: e ? void 0 : s.controlId, ...r, children: [
|
|
89
99
|
c,
|
|
90
|
-
|
|
100
|
+
i && /* @__PURE__ */ d("span", { "aria-hidden": "true", children: " *" })
|
|
91
101
|
] });
|
|
92
102
|
}
|
|
93
103
|
);
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
({ asChild: e = !1, children:
|
|
104
|
+
S.displayName = "FormField.Label";
|
|
105
|
+
const q = b(
|
|
106
|
+
({ asChild: e = !1, children: t, ...o }, r) => {
|
|
97
107
|
const {
|
|
98
|
-
control:
|
|
99
|
-
value:
|
|
100
|
-
disabled:
|
|
108
|
+
control: n,
|
|
109
|
+
value: l,
|
|
110
|
+
disabled: i,
|
|
101
111
|
shouldShowError: s,
|
|
102
112
|
errors: c,
|
|
103
|
-
required:
|
|
113
|
+
required: f,
|
|
104
114
|
ids: a,
|
|
105
|
-
hasDescription:
|
|
106
|
-
componentProps:
|
|
107
|
-
} =
|
|
108
|
-
|
|
115
|
+
hasDescription: u,
|
|
116
|
+
componentProps: m
|
|
117
|
+
} = I(), C = [
|
|
118
|
+
u ? a.descriptionId : null,
|
|
109
119
|
s && c.length > 0 ? a.errorId : null
|
|
110
|
-
].filter(Boolean).join(" ") || void 0,
|
|
120
|
+
].filter(Boolean).join(" ") || void 0, y = {
|
|
111
121
|
id: a.controlId,
|
|
112
122
|
"aria-labelledby": a.labelId,
|
|
113
123
|
"aria-invalid": s ? !0 : void 0,
|
|
114
|
-
"aria-describedby":
|
|
124
|
+
"aria-describedby": C,
|
|
115
125
|
"aria-errormessage": s && c.length > 0 ? a.errorId : void 0,
|
|
116
|
-
"aria-required":
|
|
126
|
+
"aria-required": f ? !0 : void 0
|
|
117
127
|
};
|
|
118
|
-
if (
|
|
119
|
-
return /* @__PURE__ */
|
|
120
|
-
const
|
|
121
|
-
return /* @__PURE__ */
|
|
122
|
-
|
|
128
|
+
if (t || e)
|
|
129
|
+
return /* @__PURE__ */ d(F, { ref: r, ...y, ...o, children: t });
|
|
130
|
+
const g = n.component, { testId: E, ...v } = m ?? {};
|
|
131
|
+
return /* @__PURE__ */ d(
|
|
132
|
+
g,
|
|
123
133
|
{
|
|
124
134
|
ref: r,
|
|
125
|
-
...
|
|
126
|
-
...
|
|
127
|
-
...
|
|
128
|
-
value:
|
|
129
|
-
disabled:
|
|
130
|
-
onChange: (
|
|
131
|
-
onBlur: () =>
|
|
135
|
+
...v,
|
|
136
|
+
...y,
|
|
137
|
+
...o,
|
|
138
|
+
value: l,
|
|
139
|
+
disabled: i,
|
|
140
|
+
onChange: (p) => n.setValue(p),
|
|
141
|
+
onBlur: () => n.markAsTouched()
|
|
132
142
|
}
|
|
133
143
|
);
|
|
134
144
|
}
|
|
135
145
|
);
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
({ asChild: e = !1, multi:
|
|
139
|
-
const { shouldShowError:
|
|
140
|
-
if (!
|
|
141
|
-
const
|
|
142
|
-
return
|
|
143
|
-
|
|
146
|
+
q.displayName = "FormField.Control";
|
|
147
|
+
const B = b(
|
|
148
|
+
({ asChild: e = !1, multi: t = !1, render: o, children: r, ...n }, l) => {
|
|
149
|
+
const { shouldShowError: i, errors: s, ids: c } = I(), f = D();
|
|
150
|
+
if (!i || s.length === 0) return null;
|
|
151
|
+
const a = e ? F : "p";
|
|
152
|
+
return o ? /* @__PURE__ */ d(w, { children: s.map((u, m) => /* @__PURE__ */ d(
|
|
153
|
+
a,
|
|
144
154
|
{
|
|
145
155
|
id: m === 0 ? c.errorId : void 0,
|
|
146
156
|
role: "alert",
|
|
147
|
-
...
|
|
148
|
-
children:
|
|
157
|
+
...n,
|
|
158
|
+
children: o(u, m)
|
|
149
159
|
},
|
|
150
|
-
|
|
151
|
-
)) }) :
|
|
152
|
-
|
|
160
|
+
u.code ?? m
|
|
161
|
+
)) }) : t ? /* @__PURE__ */ d(w, { children: s.map((u, m) => /* @__PURE__ */ d(
|
|
162
|
+
a,
|
|
153
163
|
{
|
|
154
164
|
id: m === 0 ? c.errorId : void 0,
|
|
155
165
|
role: "alert",
|
|
156
|
-
...
|
|
157
|
-
children:
|
|
166
|
+
...n,
|
|
167
|
+
children: f(u)
|
|
158
168
|
},
|
|
159
|
-
|
|
160
|
-
)) }) : /* @__PURE__ */
|
|
169
|
+
u.code ?? m
|
|
170
|
+
)) }) : /* @__PURE__ */ d(a, { ref: l, id: c.errorId, role: "alert", ...n, children: r ?? f(s[0]) });
|
|
161
171
|
}
|
|
162
172
|
);
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
({ asChild: e = !1, children:
|
|
166
|
-
const { ids:
|
|
167
|
-
return /* @__PURE__ */
|
|
173
|
+
B.displayName = "FormField.Error";
|
|
174
|
+
const L = b(
|
|
175
|
+
({ asChild: e = !1, children: t, ...o }, r) => {
|
|
176
|
+
const { ids: n } = I();
|
|
177
|
+
return /* @__PURE__ */ d(e ? F : "p", { ref: r, id: n.descriptionId, ...o, children: t });
|
|
168
178
|
}
|
|
169
179
|
);
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
E(G);
|
|
179
|
-
function H({
|
|
180
|
+
L.displayName = "FormField.Description";
|
|
181
|
+
const h = N;
|
|
182
|
+
h.Root = N;
|
|
183
|
+
h.Label = S;
|
|
184
|
+
h.Control = q;
|
|
185
|
+
h.Error = B;
|
|
186
|
+
h.Description = L;
|
|
187
|
+
function P({
|
|
180
188
|
className: e,
|
|
181
|
-
testIdProp:
|
|
182
|
-
isCheckbox:
|
|
189
|
+
testIdProp: t,
|
|
190
|
+
isCheckbox: o,
|
|
183
191
|
customChildren: r
|
|
184
192
|
}) {
|
|
185
|
-
const { componentProps:
|
|
186
|
-
return /* @__PURE__ */
|
|
187
|
-
!
|
|
188
|
-
|
|
193
|
+
const { componentProps: n, pending: l } = I(), i = t ?? n?.testId ?? "unknown";
|
|
194
|
+
return /* @__PURE__ */ $("div", { className: e, "data-testid": `field-${i}`, children: [
|
|
195
|
+
!o && /* @__PURE__ */ d(
|
|
196
|
+
h.Label,
|
|
189
197
|
{
|
|
190
198
|
className: "block mb-1 text-sm font-medium",
|
|
191
|
-
"data-testid": `label-${
|
|
199
|
+
"data-testid": `label-${i}`
|
|
192
200
|
}
|
|
193
201
|
),
|
|
194
|
-
r ? /* @__PURE__ */
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
-
|
|
202
|
+
r ? /* @__PURE__ */ d(h.Control, { asChild: !0, children: r }) : /* @__PURE__ */ d(h.Control, { "data-testid": `input-${i}` }),
|
|
203
|
+
/* @__PURE__ */ d(
|
|
204
|
+
h.Error,
|
|
197
205
|
{
|
|
198
206
|
className: "text-destructive text-sm mt-1 block",
|
|
199
|
-
"data-testid": `error-${
|
|
207
|
+
"data-testid": `error-${i}`
|
|
200
208
|
}
|
|
201
209
|
),
|
|
202
|
-
|
|
210
|
+
l && /* @__PURE__ */ d("span", { className: "text-gray-500 text-sm mt-1 block", children: "Проверка..." })
|
|
203
211
|
] });
|
|
204
212
|
}
|
|
205
|
-
const
|
|
206
|
-
const
|
|
207
|
-
return /* @__PURE__ */
|
|
208
|
-
|
|
213
|
+
const Q = ({ control: e, className: t, testId: o, children: r }) => {
|
|
214
|
+
const n = e.component === z;
|
|
215
|
+
return /* @__PURE__ */ d(h.Root, { control: e, children: /* @__PURE__ */ d(
|
|
216
|
+
P,
|
|
209
217
|
{
|
|
210
|
-
className:
|
|
211
|
-
testIdProp:
|
|
212
|
-
isCheckbox:
|
|
218
|
+
className: t,
|
|
219
|
+
testIdProp: o,
|
|
220
|
+
isCheckbox: n,
|
|
213
221
|
customChildren: r
|
|
214
222
|
}
|
|
215
223
|
) });
|
|
216
|
-
},
|
|
224
|
+
}, _ = A.memo(Q, (e, t) => e.control === t.control && e.className === t.className && e.testId === t.testId && e.children === t.children);
|
|
217
225
|
export {
|
|
218
|
-
|
|
226
|
+
_ as FormField
|
|
219
227
|
};
|
package/dist/ui/input.js
CHANGED
|
@@ -1,48 +1,58 @@
|
|
|
1
1
|
import { jsx as g } from "react/jsx-runtime";
|
|
2
2
|
import * as u from "react";
|
|
3
|
-
import { c as
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
s !== void 0 && s >= 0 && o < 0 ? r?.(0) : r?.(o);
|
|
16
|
-
}
|
|
3
|
+
import { c as b } from "../utils-DtaLkIY8.js";
|
|
4
|
+
const h = u.forwardRef((e, l) => {
|
|
5
|
+
const o = e.type ?? "text", r = (n) => {
|
|
6
|
+
const t = n.target.value;
|
|
7
|
+
if (e.type === "number")
|
|
8
|
+
if (t === "")
|
|
9
|
+
e.onChange?.(null);
|
|
10
|
+
else {
|
|
11
|
+
const i = Number(t);
|
|
12
|
+
if (!isNaN(i)) {
|
|
13
|
+
const a = e.min !== void 0 ? Number(e.min) : void 0;
|
|
14
|
+
a !== void 0 && a >= 0 && i < 0 ? e.onChange?.(0) : e.onChange?.(i);
|
|
17
15
|
}
|
|
18
|
-
else
|
|
19
|
-
r?.(t || null);
|
|
20
|
-
}, b = u.useMemo(() => i == null ? "" : e === "number" && typeof i == "number" ? isNaN(i) ? "" : i.toString() : String(i), [i, e]);
|
|
21
|
-
return /* @__PURE__ */ g(
|
|
22
|
-
"input",
|
|
23
|
-
{
|
|
24
|
-
ref: c,
|
|
25
|
-
type: e,
|
|
26
|
-
value: b,
|
|
27
|
-
disabled: m,
|
|
28
|
-
placeholder: d,
|
|
29
|
-
"data-slot": "input",
|
|
30
|
-
className: v(
|
|
31
|
-
"h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs transition-colors",
|
|
32
|
-
"placeholder:text-muted-foreground",
|
|
33
|
-
"focus-visible:outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
34
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
35
|
-
"aria-invalid:border-destructive aria-invalid:ring-destructive/20",
|
|
36
|
-
l
|
|
37
|
-
),
|
|
38
|
-
onChange: f,
|
|
39
|
-
onBlur: a,
|
|
40
|
-
...n
|
|
41
16
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
|
|
17
|
+
else
|
|
18
|
+
e.onChange?.(t || null);
|
|
19
|
+
}, s = u.useMemo(() => {
|
|
20
|
+
const n = e.value;
|
|
21
|
+
return n == null ? "" : e.type === "number" && typeof n == "number" ? isNaN(n) ? "" : n.toString() : String(n);
|
|
22
|
+
}, [e.value, e.type]), {
|
|
23
|
+
className: d,
|
|
24
|
+
onBlur: c,
|
|
25
|
+
placeholder: m,
|
|
26
|
+
disabled: v,
|
|
27
|
+
value: y,
|
|
28
|
+
onChange: N,
|
|
29
|
+
type: x,
|
|
30
|
+
...f
|
|
31
|
+
} = e;
|
|
32
|
+
return /* @__PURE__ */ g(
|
|
33
|
+
"input",
|
|
34
|
+
{
|
|
35
|
+
ref: l,
|
|
36
|
+
type: o,
|
|
37
|
+
value: s,
|
|
38
|
+
disabled: v,
|
|
39
|
+
placeholder: m,
|
|
40
|
+
"data-slot": "input",
|
|
41
|
+
className: b(
|
|
42
|
+
"h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs transition-colors",
|
|
43
|
+
"placeholder:text-muted-foreground",
|
|
44
|
+
"focus-visible:outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
45
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
46
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20",
|
|
47
|
+
d
|
|
48
|
+
),
|
|
49
|
+
onChange: r,
|
|
50
|
+
onBlur: c,
|
|
51
|
+
...f
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
h.displayName = "Input";
|
|
46
56
|
export {
|
|
47
|
-
|
|
57
|
+
h as Input
|
|
48
58
|
};
|
package/llms.txt
CHANGED
|
@@ -435,7 +435,6 @@ import { Textarea } from '@reformer/ui-kit';
|
|
|
435
435
|
- [03-choice-fields.md](03-choice-fields.md) — Select, Checkbox, RadioGroup.
|
|
436
436
|
- [05-form-field-integration.md](05-form-field-integration.md) — как все эти поля автоматически подключаются через `FormField`.
|
|
437
437
|
- [06-troubleshooting.md](06-troubleshooting.md) — «number возвращает строку», «mask пропускает символы», «password toggle не появляется».
|
|
438
|
-
- Эталон: `examples/registration-form/RegistrationForm.tsx`, `examples/complex-multy-step-form/schemas/schema.ts` (monorepo examples).
|
|
439
438
|
|
|
440
439
|
## 12. Checkbox
|
|
441
440
|
|
|
@@ -801,7 +800,6 @@ const form = createForm<{ city: string }>({ model, schema });
|
|
|
801
800
|
- [02-text-fields.md](02-text-fields.md) — `Input`, `InputMask`, `InputPassword`, `Textarea`.
|
|
802
801
|
- [05-form-field-integration.md](05-form-field-integration.md) — `FormField` распознаёт `Checkbox` и не дублирует label.
|
|
803
802
|
- [06-troubleshooting.md](06-troubleshooting.md) — «Select не показывает options», «options vs resource», «onBlur не срабатывает на Select/RadioGroup».
|
|
804
|
-
- Эталон: `examples/complex-multy-step-form/schemas/schema.ts` (monorepo example) — большой пример с `Select` и `Checkbox` в реальной форме.
|
|
805
803
|
|
|
806
804
|
## 16. Button
|
|
807
805
|
|
|
@@ -1205,8 +1203,6 @@ function CreditApplicationPage() {
|
|
|
1205
1203
|
}
|
|
1206
1204
|
```
|
|
1207
1205
|
|
|
1208
|
-
Эталон: `examples/complex-multy-step-form-renderer/CreditApplicationFormRenderer.tsx` (monorepo example).
|
|
1209
|
-
|
|
1210
1206
|
`testId` рендерер берёт из `componentProps.testId` листа schema:
|
|
1211
1207
|
|
|
1212
1208
|
```tsx
|
|
@@ -1298,7 +1294,6 @@ const form = createForm<{ accept: boolean }>({ model, schema });
|
|
|
1298
1294
|
- [04-layout-and-buttons.md](04-layout-and-buttons.md) — `Button` для submit/prev/next.
|
|
1299
1295
|
- [06-troubleshooting.md](06-troubleshooting.md) — «label дублируется», «error не появляется», «FormField не подцепляет ошибки».
|
|
1300
1296
|
- CDK-хуки: [@reformer/cdk/form-field](../../../reformer-cdk/docs/llms/) (`FormField.Root`, `useFormFieldContext`).
|
|
1301
|
-
- Эталон: `examples/complex-multy-step-form-renderer/CreditApplicationFormRenderer.tsx` (monorepo example) — `FormField` как `fieldWrapper` целой multi-step формы.
|
|
1302
1297
|
|
|
1303
1298
|
## 25. 1. `Input type="number"` возвращает строку, а не число (или `null`)
|
|
1304
1299
|
|
|
@@ -1680,14 +1675,7 @@ const handleSubmit = async () => {
|
|
|
1680
1675
|
> **`config` не привязан к типу формы.** `FormWizardConfig` — это `{ validateStep?, validateAll? }`,
|
|
1681
1676
|
> оба колбэка возвращают `boolean | Promise<boolean>`. Канон M1 — прогонять
|
|
1682
1677
|
> `validateFormModel(model, schema)` (именно он исполняет `validators` листьев;
|
|
1683
|
-
> `form.validate()` по нодам схемные правила НЕ запустит).
|
|
1684
|
-
> `examples/complex-multy-step-form/schemas/validation.ts`. Реальный эталон собирает конфиг фабрикой:
|
|
1685
|
-
>
|
|
1686
|
-
> ```tsx
|
|
1687
|
-
> import { makeCreditValidationConfig } from './schemas/validation';
|
|
1688
|
-
> const config = useMemo(() => makeCreditValidationConfig(model), [model]);
|
|
1689
|
-
> // → { validateStep: (step) => Promise<boolean>, validateAll: () => Promise<boolean> }
|
|
1690
|
-
> ```
|
|
1678
|
+
> `form.validate()` по нодам схемные правила НЕ запустит).
|
|
1691
1679
|
|
|
1692
1680
|
### Альтернатива — imperative submit с values
|
|
1693
1681
|
|
|
@@ -1914,7 +1902,7 @@ const renderSchema = createRenderSchema<CreditApplication>(() => ({
|
|
|
1914
1902
|
|
|
1915
1903
|
ui-kit FormArraySection маркирован `__selfManagedChildren = true` — родитель-renderer пробрасывает `form` без рекурсии.
|
|
1916
1904
|
|
|
1917
|
-
> Альтернатива — нативный array-узел движка `{ array: model.properties, initialValue, item: (im) => ({ children: [ { value: im.$.field, component } ] }) }
|
|
1905
|
+
> Альтернатива — нативный array-узел движка `{ array: model.properties, initialValue, item: (im) => ({ children: [ { value: im.$.field, component } ] }) }`.
|
|
1918
1906
|
|
|
1919
1907
|
## 45. JSON (renderer-json)
|
|
1920
1908
|
|
|
@@ -2118,7 +2106,7 @@ const onSubmit = async () => {
|
|
|
2118
2106
|
|
|
2119
2107
|
Cross-field правила (например, «доп. телефон отличается от основного») — это
|
|
2120
2108
|
именованные `ModelValidator<value, scope, root>` в том же массиве `validators`
|
|
2121
|
-
(читают корень формы через третий аргумент).
|
|
2109
|
+
(читают корень формы через третий аргумент).
|
|
2122
2110
|
|
|
2123
2111
|
## 51. Advanced — strict mask через FormField + children slot
|
|
2124
2112
|
|
|
@@ -2410,7 +2398,7 @@ Props компонента {@link Checkbox}.
|
|
|
2410
2398
|
```typescript
|
|
2411
2399
|
export interface CheckboxProps extends Omit<
|
|
2412
2400
|
React.InputHTMLAttributes<HTMLInputElement>,
|
|
2413
|
-
'value' | 'onChange' | 'type'
|
|
2401
|
+
'value' | 'onChange' | 'type' | 'checked' | 'defaultChecked'
|
|
2414
2402
|
> {
|
|
2415
2403
|
/** Дополнительный CSS-класс для самого input. */
|
|
2416
2404
|
className?: string;
|
|
@@ -2595,6 +2583,28 @@ return <ErrorState error={error} onRetry={() => window.location.reload()} />;
|
|
|
2595
2583
|
|
|
2596
2584
|
_Source: src/components/state/error-state.tsx_
|
|
2597
2585
|
|
|
2586
|
+
### ErrorStateProps
|
|
2587
|
+
|
|
2588
|
+
**Kind:** `interface`
|
|
2589
|
+
|
|
2590
|
+
**Signature:**
|
|
2591
|
+
```typescript
|
|
2592
|
+
export interface ErrorStateProps {
|
|
2593
|
+
/** Текст ошибки, показывается под заголовком. */
|
|
2594
|
+
error: string;
|
|
2595
|
+
/** Заголовок блока ошибки. По умолчанию `'Ошибка загрузки'`. */
|
|
2596
|
+
title?: string;
|
|
2597
|
+
/** Колбэк повторной попытки. Если задан — рендерится кнопка «Повторить». */
|
|
2598
|
+
onRetry?: () => void;
|
|
2599
|
+
/** Подпись кнопки повтора. По умолчанию `'Повторить'`. */
|
|
2600
|
+
retryLabel?: string;
|
|
2601
|
+
/** Внешний CSS-класс контейнера. По умолчанию `'w-full'`. */
|
|
2602
|
+
className?: string;
|
|
2603
|
+
}
|
|
2604
|
+
```
|
|
2605
|
+
|
|
2606
|
+
_Source: src/components/state/error-state.tsx_
|
|
2607
|
+
|
|
2598
2608
|
### ExampleCard
|
|
2599
2609
|
|
|
2600
2610
|
**Kind:** `function`
|
|
@@ -3199,7 +3209,7 @@ import { Input } from '@reformer/ui-kit';
|
|
|
3199
3209
|
<Input
|
|
3200
3210
|
type="number"
|
|
3201
3211
|
value={age}
|
|
3202
|
-
onChange={
|
|
3212
|
+
onChange={setAge}
|
|
3203
3213
|
min={0}
|
|
3204
3214
|
placeholder="Возраст"
|
|
3205
3215
|
/>
|
|
@@ -3217,7 +3227,7 @@ return (
|
|
|
3217
3227
|
type="email"
|
|
3218
3228
|
value={value}
|
|
3219
3229
|
disabled={disabled}
|
|
3220
|
-
onChange={(v) => control.setValue(
|
|
3230
|
+
onChange={(v) => control.setValue(v ?? '')}
|
|
3221
3231
|
onBlur={() => control.markAsTouched()}
|
|
3222
3232
|
aria-invalid={shouldShowError}
|
|
3223
3233
|
placeholder={shouldShowError ? errors[0]?.message : 'you@example.com'}
|
|
@@ -3278,7 +3288,7 @@ Props компонента {@link InputMask}.
|
|
|
3278
3288
|
```typescript
|
|
3279
3289
|
export interface InputMaskProps extends Omit<
|
|
3280
3290
|
React.InputHTMLAttributes<HTMLInputElement>,
|
|
3281
|
-
'value' | 'onChange'
|
|
3291
|
+
'value' | 'onChange' | 'defaultValue'
|
|
3282
3292
|
> {
|
|
3283
3293
|
/** Дополнительный CSS-класс. */
|
|
3284
3294
|
className?: string;
|
|
@@ -3353,7 +3363,7 @@ Props компонента {@link InputPassword}.
|
|
|
3353
3363
|
```typescript
|
|
3354
3364
|
export interface InputPasswordProps extends Omit<
|
|
3355
3365
|
React.InputHTMLAttributes<HTMLInputElement>,
|
|
3356
|
-
'value' | 'onChange' | 'type'
|
|
3366
|
+
'value' | 'onChange' | 'type' | 'defaultValue'
|
|
3357
3367
|
> {
|
|
3358
3368
|
/** Дополнительный CSS-класс. */
|
|
3359
3369
|
className?: string;
|
|
@@ -3379,39 +3389,14 @@ _Source: src/components/ui/input-password.tsx_
|
|
|
3379
3389
|
|
|
3380
3390
|
### InputProps
|
|
3381
3391
|
|
|
3382
|
-
**Kind:** `
|
|
3392
|
+
**Kind:** `type`
|
|
3383
3393
|
|
|
3384
|
-
Props компонента {@link Input}
|
|
3394
|
+
Props компонента {@link Input} — дискриминированный union по `type`:
|
|
3395
|
+
`type="number"` даёт `number | null` для `value`/`onChange`, любой другой `type` — `string | null`.
|
|
3385
3396
|
|
|
3386
3397
|
**Signature:**
|
|
3387
3398
|
```typescript
|
|
3388
|
-
export
|
|
3389
|
-
React.InputHTMLAttributes<HTMLInputElement>,
|
|
3390
|
-
'value' | 'onChange'
|
|
3391
|
-
> {
|
|
3392
|
-
/** Дополнительный CSS-класс (мерджится с дефолтными Tailwind-классами через `tailwind-merge`). */
|
|
3393
|
-
className?: string;
|
|
3394
|
-
/**
|
|
3395
|
-
* Текущее значение поля. Для `type='number'` ожидается `number | null`,
|
|
3396
|
-
* для остальных — `string | null`. `null`/`undefined` рендерится как пустое поле.
|
|
3397
|
-
*/
|
|
3398
|
-
value?: string | number | null;
|
|
3399
|
-
/**
|
|
3400
|
-
* Обработчик изменений. Получает уже распарсенное значение:
|
|
3401
|
-
* - для `type='number'` — `number` или `null` (для пустой строки),
|
|
3402
|
-
* - иначе — `string` или `null`.
|
|
3403
|
-
* `NaN` не прокидывается. При `min >= 0` отрицательные значения превращаются в `0`.
|
|
3404
|
-
*/
|
|
3405
|
-
onChange?: (value: string | number | null) => void;
|
|
3406
|
-
/** Срабатывает при потере фокуса. Используется `FormField` для пометки `touched`. */
|
|
3407
|
-
onBlur?: () => void;
|
|
3408
|
-
/** HTML-тип input. Для `'number'` включается специальный парсинг значения. */
|
|
3409
|
-
type?: 'text' | 'email' | 'number' | 'tel' | 'url' | 'password';
|
|
3410
|
-
/** Подсказка внутри поля. */
|
|
3411
|
-
placeholder?: string;
|
|
3412
|
-
/** Блокирует ввод и редактирование. */
|
|
3413
|
-
disabled?: boolean;
|
|
3414
|
-
}
|
|
3399
|
+
export type InputProps = NumberInputProps | TextInputProps;
|
|
3415
3400
|
```
|
|
3416
3401
|
|
|
3417
3402
|
_Source: src/components/ui/input.tsx_
|
|
@@ -3449,6 +3434,24 @@ return <LoadingState />;
|
|
|
3449
3434
|
|
|
3450
3435
|
_Source: src/components/state/loading-state.tsx_
|
|
3451
3436
|
|
|
3437
|
+
### LoadingStateProps
|
|
3438
|
+
|
|
3439
|
+
**Kind:** `interface`
|
|
3440
|
+
|
|
3441
|
+
**Signature:**
|
|
3442
|
+
```typescript
|
|
3443
|
+
export interface LoadingStateProps {
|
|
3444
|
+
/** Основной текст. По умолчанию `'Загрузка данных...'`. */
|
|
3445
|
+
title?: string;
|
|
3446
|
+
/** Вспомогательный текст под спиннером. По умолчанию `'Пожалуйста, подождите'`. */
|
|
3447
|
+
subtitle?: string;
|
|
3448
|
+
/** Внешний CSS-класс контейнера. По умолчанию центрирует спиннер с отступами. */
|
|
3449
|
+
className?: string;
|
|
3450
|
+
}
|
|
3451
|
+
```
|
|
3452
|
+
|
|
3453
|
+
_Source: src/components/state/loading-state.tsx_
|
|
3454
|
+
|
|
3452
3455
|
### RadioGroup
|
|
3453
3456
|
|
|
3454
3457
|
**Kind:** `const`
|
|
@@ -3899,7 +3902,7 @@ Props компонента {@link Select}.
|
|
|
3899
3902
|
|
|
3900
3903
|
**Signature:**
|
|
3901
3904
|
```typescript
|
|
3902
|
-
export interface SelectProps
|
|
3905
|
+
export interface SelectProps extends Omit<
|
|
3903
3906
|
React.ComponentProps<typeof SelectPrimitive.Root>,
|
|
3904
3907
|
'value' | 'onValueChange'
|
|
3905
3908
|
> {
|
|
@@ -3912,7 +3915,7 @@ export interface SelectProps<T> extends Omit<
|
|
|
3912
3915
|
/** Срабатывает при закрытии дропдауна (через `onOpenChange(false)`). */
|
|
3913
3916
|
onBlur?: () => void;
|
|
3914
3917
|
/** Асинхронный источник опций. Если задан вместе с `options`, приоритет у `options`. */
|
|
3915
|
-
resource?: ResourceConfig<
|
|
3918
|
+
resource?: ResourceConfig<unknown>;
|
|
3916
3919
|
/**
|
|
3917
3920
|
* Inline-варианты. `value` приводится к строке. Опции с одинаковым `group`
|
|
3918
3921
|
* объединяются в `SelectGroup` с `SelectLabel` (см. рецепт grouped options).
|
|
@@ -4163,7 +4166,7 @@ Props компонента {@link Textarea}.
|
|
|
4163
4166
|
```typescript
|
|
4164
4167
|
export interface TextareaProps extends Omit<
|
|
4165
4168
|
React.TextareaHTMLAttributes<HTMLTextAreaElement>,
|
|
4166
|
-
'value' | 'onChange'
|
|
4169
|
+
'value' | 'onChange' | 'defaultValue'
|
|
4167
4170
|
> {
|
|
4168
4171
|
/** Дополнительный CSS-класс. */
|
|
4169
4172
|
className?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reformer/ui-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Styled form components with Tailwind CSS and Radix UI for @reformer ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -121,23 +121,22 @@
|
|
|
121
121
|
"llms.txt"
|
|
122
122
|
],
|
|
123
123
|
"peerDependencies": {
|
|
124
|
-
"@radix-ui/react-select": "^2.0.0",
|
|
125
|
-
"@radix-ui/react-slot": "^1.0.0",
|
|
126
124
|
"@reformer/cdk": ">=1.0.0",
|
|
127
125
|
"@reformer/core": ">=1.1.0",
|
|
128
126
|
"@reformer/renderer-react": ">=1.0.0",
|
|
129
|
-
"lucide-react": ">=0.400.0 <1.0.0",
|
|
130
127
|
"react": "^18.0.0 || ^19.0.0",
|
|
131
128
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
132
129
|
},
|
|
133
130
|
"dependencies": {
|
|
131
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
132
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
134
133
|
"class-variance-authority": "^0.7.0",
|
|
135
134
|
"clsx": "^2.0.0",
|
|
136
|
-
"
|
|
135
|
+
"lucide-react": "^0.553.0",
|
|
136
|
+
"tailwind-merge": "^2.0.0 || ^3.0.0",
|
|
137
|
+
"tslib": "^2.6.0"
|
|
137
138
|
},
|
|
138
139
|
"devDependencies": {
|
|
139
|
-
"@radix-ui/react-select": "^2.2.6",
|
|
140
|
-
"@radix-ui/react-slot": "^1.2.4",
|
|
141
140
|
"@reformer/cdk": "*",
|
|
142
141
|
"@reformer/core": "*",
|
|
143
142
|
"@reformer/renderer-react": "*",
|
|
@@ -148,7 +147,6 @@
|
|
|
148
147
|
"@vitest/utils": "^4.0.8",
|
|
149
148
|
"class-variance-authority": "^0.7.1",
|
|
150
149
|
"clsx": "^2.1.1",
|
|
151
|
-
"lucide-react": "^0.553.0",
|
|
152
150
|
"react": "^19.2.1",
|
|
153
151
|
"react-dom": "^19.2.1",
|
|
154
152
|
"tailwind-merge": "^3.4.0",
|