@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Alexandr Bukhtatyy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # @reformer/ui-kit
2
+
3
+ Headless UI components for `@reformer/core` - build accessible, fully customizable form interfaces.
4
+
5
+ ## Features
6
+
7
+ - **Headless** - No default styles, complete design freedom
8
+ - **Compound Components** - Declarative, composable API
9
+ - **Render Props** - Full control over rendering
10
+ - **TypeScript** - Fully typed with generics support
11
+ - **Tree-shakable** - Import only what you need
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @reformer/cdk @reformer/core
17
+ ```
18
+
19
+ ## Components
20
+
21
+ ### FormArray
22
+
23
+ Manage dynamic form arrays with add/remove functionality.
24
+
25
+ ```tsx
26
+ import { FormArray } from '@reformer/cdk/form-array';
27
+
28
+ <FormArray.Root control={form.items}>
29
+ <FormArray.Empty>
30
+ <p>No items yet</p>
31
+ </FormArray.Empty>
32
+
33
+ <FormArray.List>
34
+ {({ control, index, remove }) => (
35
+ <div>
36
+ <span>Item #{index + 1}</span>
37
+ <ItemForm control={control} />
38
+ <button onClick={remove}>Remove</button>
39
+ </div>
40
+ )}
41
+ </FormArray.List>
42
+
43
+ <FormArray.AddButton>Add Item</FormArray.AddButton>
44
+ </FormArray.Root>;
45
+ ```
46
+
47
+ ### FormWizard
48
+
49
+ Build multi-step form wizards with validation.
50
+
51
+ ```tsx
52
+ import { FormWizard } from '@reformer/cdk/form-wizard';
53
+
54
+ <FormWizard form={form} config={config}>
55
+ <FormWizard.Indicator steps={STEPS}>
56
+ {({ steps, goToStep }) => (
57
+ <nav>
58
+ {steps.map((step) => (
59
+ <button
60
+ key={step.number}
61
+ onClick={() => goToStep(step.number)}
62
+ disabled={!step.canNavigate}
63
+ >
64
+ {step.title}
65
+ </button>
66
+ ))}
67
+ </nav>
68
+ )}
69
+ </FormWizard.Indicator>
70
+
71
+ <FormWizard.Step component={Step1} control={form} />
72
+ <FormWizard.Step component={Step2} control={form} />
73
+
74
+ <FormWizard.Actions onSubmit={handleSubmit}>
75
+ {({ prev, next, submit, isFirstStep, isLastStep }) => (
76
+ <div>
77
+ {!isFirstStep && <button {...prev}>Back</button>}
78
+ {!isLastStep ? <button {...next}>Next</button> : <button {...submit}>Submit</button>}
79
+ </div>
80
+ )}
81
+ </FormWizard.Actions>
82
+ </FormWizard>;
83
+ ```
84
+
85
+ ## Hooks
86
+
87
+ For full customization, use the hooks directly:
88
+
89
+ ```tsx
90
+ import { useFormArray } from '@reformer/cdk/form-array';
91
+ import { useFormWizard } from '@reformer/cdk/form-wizard';
92
+ ```
93
+
94
+ ## License
95
+
96
+ MIT
@@ -0,0 +1,60 @@
1
+ import { ComponentType, ReactNode } from 'react';
2
+ import { ArrayNode, FieldPathNode, FormArrayProxy, FormFields, FormProxy } from '@reformer/core';
3
+ import { FieldWrapperProps } from '@reformer/renderer-react';
4
+ export interface FormArraySectionProps<T extends FormFields> {
5
+ /**
6
+ * Резолвится автоматически: уже-резолвленный ArrayNode/FormArrayProxy ИЛИ
7
+ * FieldPathNode (path.<arrayField>) — в этом случае через `form` + navigator.
8
+ */
9
+ control: FormArrayProxy<T> | ArrayNode<T> | FieldPathNode<unknown, unknown> | undefined;
10
+ /** React FC получает `control: FormProxy<T>` для каждого элемента. */
11
+ itemComponent: ComponentType<{
12
+ control: FormProxy<T>;
13
+ }>;
14
+ /** Заголовок секции (рендерится h3). */
15
+ title?: string;
16
+ /** Метка для каждого item — строка-префикс или функция. */
17
+ itemLabel?: string | ((control: FormProxy<T>, index: number) => string);
18
+ /** Текст кнопки добавления. По умолчанию `'+ Добавить'`. */
19
+ addButtonLabel?: string;
20
+ /** Текст кнопки удаления. По умолчанию `'Удалить'`. */
21
+ removeButtonLabel?: string;
22
+ /** Сообщение пустого состояния. */
23
+ emptyMessage?: string;
24
+ /** Подсказка под пустым состоянием. */
25
+ emptyMessageHint?: string;
26
+ /**
27
+ * Условие видимости секции. Если `false` — секция полностью скрыта.
28
+ * Удобно для toggle-чекбоксов вида «У меня есть имущество».
29
+ */
30
+ hasItems?: boolean;
31
+ /**
32
+ * Plain-leaf значения для новых items (передаётся в `FormArray.AddButton`).
33
+ * НЕ FieldConfig — только примитивы по форме item-типа `T`.
34
+ *
35
+ * Тип `Partial<T>` — TS проверит, что initialValue совместим с типом элемента.
36
+ * Передавайте generic явно для лучшей type-safety:
37
+ * `<FormArraySection<PropertyItem> initialValue={createPropertyItem()} ...>`.
38
+ */
39
+ initialValue?: Partial<T>;
40
+ /** Показывать «Удалить» когда остался один элемент. По умолчанию `false`. */
41
+ showRemoveOnSingle?: boolean;
42
+ /** Максимум items — AddButton отключается при достижении. */
43
+ maxItems?: number;
44
+ /** Внешний className секции. */
45
+ className?: string;
46
+ /** Класс card-обёртки каждого item. */
47
+ cardClassName?: string;
48
+ /**
49
+ * FormProxy. Авто-инъектится `RenderNodeComponent` через
50
+ * `__selfManagedChildren` маркер. Передавать вручную — только при
51
+ * использовании вне стандартного render-tree.
52
+ */
53
+ form?: FormProxy<unknown>;
54
+ /**
55
+ * Field wrapper для дочерних полей. Авто-инъектится `RenderNodeComponent`;
56
+ * переопределить для использования другого wrapper в этой секции.
57
+ */
58
+ fieldWrapper?: ComponentType<FieldWrapperProps>;
59
+ }
60
+ export declare function FormArraySection<T extends FormFields>({ control, itemComponent: ItemComponent, title, itemLabel, addButtonLabel, removeButtonLabel, emptyMessage, emptyMessageHint, hasItems, initialValue, showRemoveOnSingle, maxItems, className, cardClassName, form, }: FormArraySectionProps<T>): ReactNode;
@@ -0,0 +1,2 @@
1
+ export { FormArraySection } from './form-array-section';
2
+ export type { FormArraySectionProps } from './form-array-section';
@@ -0,0 +1,11 @@
1
+ import { FC } from 'react';
2
+ import { FormWizardActionsRenderProps } from '@reformer/cdk/form-wizard';
3
+ export interface FormWizardActionsProps extends FormWizardActionsRenderProps {
4
+ className?: string;
5
+ prevLabel?: string;
6
+ nextLabel?: string;
7
+ submitLabel?: string;
8
+ validatingLabel?: string;
9
+ submittingLabel?: string;
10
+ }
11
+ export declare const FormWizardActions: FC<FormWizardActionsProps>;
@@ -0,0 +1,7 @@
1
+ import { FC, ReactNode } from 'react';
2
+ import { FormWizardProgressRenderProps } from '@reformer/cdk/form-wizard';
3
+ export interface FormWizardProgressProps extends FormWizardProgressRenderProps {
4
+ className?: string;
5
+ format?: (props: FormWizardProgressRenderProps) => ReactNode;
6
+ }
7
+ export declare const FormWizardProgress: FC<FormWizardProgressProps>;
@@ -0,0 +1,40 @@
1
+ import { ComponentType, ReactElement, ReactNode } from 'react';
2
+ import { FormWizard as FormWizardHeadless, FormWizardActionsProps as HeadlessFormWizardActionsProps, FormWizardHandle, FormWizardProps as FormWizardHeadlessProps } from '@reformer/cdk/form-wizard';
3
+ import { FormProxy } from '@reformer/core';
4
+ import { RenderNode } from '@reformer/renderer-react';
5
+ /**
6
+ * Полиморфное тело шага.
7
+ *
8
+ * - FC получает `control={form}`.
9
+ * - ReactNode рендерится напрямую (статический JSX).
10
+ * - RenderNode<T> рендерится через `<RenderNodeComponent>`.
11
+ */
12
+ export type FormWizardStepBody<T> = ComponentType<{
13
+ control: FormProxy<T>;
14
+ }> | ReactNode | RenderNode<T>;
15
+ export interface FormWizardStep<T> {
16
+ /** Step number (1-based). */
17
+ number: number;
18
+ /** Step title shown in indicator. */
19
+ title: string;
20
+ /** Optional icon (string или ReactNode). Передаётся в headless Indicator. */
21
+ icon?: string;
22
+ /** Body — FC | ReactNode | RenderNode<T>. */
23
+ body: FormWizardStepBody<T>;
24
+ }
25
+ export interface FormWizardProps<T extends Record<string, any>> extends FormWizardHeadlessProps<T> {
26
+ className?: string;
27
+ steps: FormWizardStep<T>[];
28
+ onSubmit: HeadlessFormWizardActionsProps['onSubmit'];
29
+ }
30
+ declare const FormWizardForwarded: <T extends Record<string, any>>(props: FormWizardProps<T> & {
31
+ ref?: React.Ref<FormWizardHandle<T>>;
32
+ }) => ReactElement | null;
33
+ type FormWizardCompound = typeof FormWizardForwarded & {
34
+ Indicator: typeof FormWizardHeadless.Indicator;
35
+ Step: typeof FormWizardHeadless.Step;
36
+ Actions: typeof FormWizardHeadless.Actions;
37
+ Progress: typeof FormWizardHeadless.Progress;
38
+ };
39
+ declare const FormWizard: FormWizardCompound;
40
+ export { FormWizard };
@@ -0,0 +1,8 @@
1
+ export { FormWizard } from './form-wizard';
2
+ export type { FormWizardProps, FormWizardStep, FormWizardStepBody } from './form-wizard';
3
+ export { StepIndicator } from './step-indicator';
4
+ export type { StepIndicatorProps } from './step-indicator';
5
+ export { FormWizardActions } from './form-wizard-actions';
6
+ export type { FormWizardActionsProps } from './form-wizard-actions';
7
+ export { FormWizardProgress } from './form-wizard-progress';
8
+ export type { FormWizardProgressProps } from './form-wizard-progress';
@@ -0,0 +1,10 @@
1
+ import { FC } from 'react';
2
+ import { FormWizardIndicatorStepWithState, FormWizardIndicatorRenderProps } from '@reformer/cdk/form-wizard';
3
+ export interface StepIndicatorProps extends FormWizardIndicatorRenderProps {
4
+ className?: string;
5
+ /** Aria-label контейнера навигации. По умолчанию «Шаги формы». */
6
+ navAriaLabel?: string;
7
+ /** Кастомный шаблон aria-label для шага. Получает {step}. */
8
+ stepAriaLabel?: (step: FormWizardIndicatorStepWithState) => string;
9
+ }
10
+ export declare const StepIndicator: FC<StepIndicatorProps>;
@@ -0,0 +1,10 @@
1
+ import { ReactNode } from 'react';
2
+ interface ErrorStateProps {
3
+ error: string;
4
+ title?: string;
5
+ onRetry?: () => void;
6
+ retryLabel?: string;
7
+ className?: string;
8
+ }
9
+ export declare function ErrorState({ error, title, onRetry, retryLabel, className, }: ErrorStateProps): ReactNode;
10
+ export {};
@@ -0,0 +1,2 @@
1
+ export { ErrorState } from './error-state';
2
+ export { LoadingState } from './loading-state';
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ interface LoadingStateProps {
3
+ title?: string;
4
+ subtitle?: string;
5
+ className?: string;
6
+ }
7
+ export declare function LoadingState({ title, subtitle, className, }: LoadingStateProps): ReactNode;
8
+ export {};
@@ -0,0 +1,63 @@
1
+ import { ComponentType, ReactNode } from 'react';
2
+ /** Состояние асинхронной операции, ожидаемое {@link AsyncBoundary}. */
3
+ export type AsyncStatus = 'loading' | 'error' | 'ready';
4
+ /** Props компонента {@link AsyncBoundary}. */
5
+ export interface AsyncBoundaryProps {
6
+ /** Текущее состояние асинхронной операции. Управляется снаружи. */
7
+ status: AsyncStatus;
8
+ /** Компонент, рендерящийся при `status === 'loading'`. Без props. Если не передан — `null`. */
9
+ LoadingComponent?: ComponentType;
10
+ /** Компонент, рендерящийся при `status === 'error'`. Без props. Если не передан — `null`. */
11
+ ErrorComponent?: ComponentType;
12
+ /** Контент, рендерящийся при `status === 'ready'`. */
13
+ children?: ReactNode;
14
+ }
15
+ /**
16
+ * Контейнер с тремя состояниями (`loading`/`error`/`ready`). В состоянии `ready`
17
+ * отображает `children`. Для loading/error используются переданные slot-компоненты
18
+ * (`ComponentType`, без props — для кастомизации передай тонкую обёртку).
19
+ *
20
+ * Это не Suspense-boundary: ничего не throw'ится, состоянием управляешь сам.
21
+ *
22
+ * @example Загрузка списка с обработкой ошибки
23
+ * ```tsx
24
+ * import { useEffect, useState } from 'react';
25
+ * import { AsyncBoundary, type AsyncStatus } from '@reformer/ui-kit';
26
+ *
27
+ * function CountriesPage() {
28
+ * const [status, setStatus] = useState<AsyncStatus>('loading');
29
+ * const [countries, setCountries] = useState<string[]>([]);
30
+ *
31
+ * useEffect(() => {
32
+ * fetch('/api/countries')
33
+ * .then((r) => r.json())
34
+ * .then((d) => { setCountries(d); setStatus('ready'); })
35
+ * .catch(() => setStatus('error'));
36
+ * }, []);
37
+ *
38
+ * return (
39
+ * <AsyncBoundary
40
+ * status={status}
41
+ * LoadingComponent={() => <p>Загружаем страны...</p>}
42
+ * ErrorComponent={() => <p>Ошибка загрузки</p>}
43
+ * >
44
+ * <ul>{countries.map((c) => <li key={c}>{c}</li>)}</ul>
45
+ * </AsyncBoundary>
46
+ * );
47
+ * }
48
+ * ```
49
+ *
50
+ * @example Внутри RenderSchema (статус подставляется через `patchProps`)
51
+ * ```tsx
52
+ * import { AsyncBoundary } from '@reformer/ui-kit';
53
+ *
54
+ * createRenderSchema((path) => ({
55
+ * selector: 'data-boundary',
56
+ * component: AsyncBoundary,
57
+ * componentProps: { status: 'loading', LoadingComponent: Spinner },
58
+ * children: [...],
59
+ * }));
60
+ * // позже: schema.node('data-boundary').patchProps({ status: 'ready' });
61
+ * ```
62
+ */
63
+ export declare function AsyncBoundary({ status, LoadingComponent, ErrorComponent, children, }: AsyncBoundaryProps): ReactNode;
@@ -0,0 +1,41 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Props компонента Box
4
+ */
5
+ export interface BoxProps {
6
+ /** CSS класс для стилизации */
7
+ className?: string;
8
+ /** Дочерние элементы */
9
+ children?: ReactNode;
10
+ }
11
+ /**
12
+ * Box - базовый контейнер-обёртка.
13
+ *
14
+ * Простой `<div>` для группировки элементов в `RenderSchema`. Используйте
15
+ * `className` для настройки layout через atomic CSS (Tailwind).
16
+ *
17
+ * @example Вертикальный список полей в RenderSchema
18
+ * ```typescript
19
+ * {
20
+ * component: Box,
21
+ * componentProps: { className: 'flex flex-col gap-4' },
22
+ * children: [
23
+ * { component: path.email },
24
+ * { component: path.password },
25
+ * ],
26
+ * }
27
+ * ```
28
+ *
29
+ * @example Двухколоночная сетка
30
+ * ```typescript
31
+ * {
32
+ * component: Box,
33
+ * componentProps: { className: 'grid grid-cols-2 gap-4' },
34
+ * children: [
35
+ * { component: path.firstName },
36
+ * { component: path.lastName },
37
+ * ],
38
+ * }
39
+ * ```
40
+ */
41
+ export declare function Box({ className, children }: BoxProps): ReactNode;
@@ -0,0 +1,35 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import * as React from 'react';
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
5
+ size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ /**
8
+ * Базовая кнопка на shadcn/Radix `Slot`. Поддерживает 6 вариантов
9
+ * (`default`/`destructive`/`outline`/`secondary`/`ghost`/`link`), 6 размеров
10
+ * (`default`/`sm`/`lg`/`icon`/`icon-sm`/`icon-lg`) и `asChild` для замены
11
+ * корневого DOM-узла на дочерний элемент (например, `<Link>` из роутера).
12
+ *
13
+ * @example Variants matrix (для design-system документации)
14
+ * ```tsx
15
+ * import { Button } from '@reformer/ui-kit';
16
+ *
17
+ * {(['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'] as const).map(
18
+ * (v) => <Button key={v} variant={v}>{v}</Button>
19
+ * )}
20
+ * ```
21
+ *
22
+ * @example asChild + react-router Link (стили кнопки на анкоре)
23
+ * ```tsx
24
+ * import { Link } from 'react-router-dom';
25
+ * import { Button } from '@reformer/ui-kit';
26
+ *
27
+ * <Button asChild variant="outline" size="lg">
28
+ * <Link to="/dashboard">Открыть дашборд</Link>
29
+ * </Button>
30
+ * ```
31
+ */
32
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
33
+ asChild?: boolean;
34
+ }): import("react/jsx-runtime").JSX.Element;
35
+ export { Button };
@@ -0,0 +1,48 @@
1
+ import * as React from 'react';
2
+ /** Props компонента {@link Checkbox}. */
3
+ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
4
+ /** Дополнительный CSS-класс для самого input. */
5
+ className?: string;
6
+ /** Состояние чекбокса. `undefined` рендерится как `false`. */
7
+ value?: boolean;
8
+ /** Вызывается при изменении. Получает `event.target.checked`. */
9
+ onChange?: (value: boolean) => void;
10
+ /** Срабатывает при потере фокуса. */
11
+ onBlur?: () => void;
12
+ /** Подпись справа от чекбокса. Если опущена — рендерится только сам контрол. */
13
+ label?: string;
14
+ /** Блокирует переключение. */
15
+ disabled?: boolean;
16
+ /** Test-id для e2e (используется как `data-testid` на input). */
17
+ 'data-testid'?: string;
18
+ }
19
+ /**
20
+ * Чекбокс с опциональной подписью справа. Контракт `value`/`onChange` —
21
+ * `boolean`, не строка.
22
+ *
23
+ * `FormField` из `@reformer/ui-kit` детектит `Checkbox` и не рендерит верхний
24
+ * `Label`, чтобы не дублировать подпись.
25
+ *
26
+ * @example Согласие с условиями
27
+ * ```tsx
28
+ * import { Checkbox } from '@reformer/ui-kit';
29
+ *
30
+ * <Checkbox
31
+ * value={agree}
32
+ * onChange={setAgree}
33
+ * label="Согласен с условиями обработки персональных данных"
34
+ * />
35
+ * ```
36
+ *
37
+ * @example Без подписи (label справа добавляется снаружи)
38
+ * ```tsx
39
+ * import { Checkbox } from '@reformer/ui-kit';
40
+ *
41
+ * <div className="flex items-center gap-2">
42
+ * <Checkbox value={hasMortgage} onChange={setHasMortgage} />
43
+ * <span>У меня уже есть ипотека</span>
44
+ * </div>
45
+ * ```
46
+ */
47
+ declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
48
+ export { Checkbox };
@@ -0,0 +1,59 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Props компонента Collapsible
4
+ */
5
+ export interface CollapsibleProps {
6
+ /** Заголовок секции */
7
+ title: string;
8
+ /** Начальное состояние (развёрнуто по умолчанию) */
9
+ defaultOpen?: boolean;
10
+ /** CSS класс для контейнера */
11
+ className?: string;
12
+ /** CSS класс для заголовка */
13
+ titleClassName?: string;
14
+ /** CSS класс для контента */
15
+ contentClassName?: string;
16
+ /** Дочерние элементы */
17
+ children?: ReactNode;
18
+ }
19
+ /**
20
+ * Collapsible - сворачиваемая секция формы.
21
+ *
22
+ * Заголовок-кнопка переключает видимость `children`. Состояние локальное
23
+ * (`useState`), внешний control пока не поддерживается — для управляемого
24
+ * варианта используй `RenderSchema.node('selector').setHidden(true)` поверх
25
+ * обычного `Box`.
26
+ *
27
+ * @example Свёрнута по умолчанию
28
+ * ```typescript
29
+ * {
30
+ * component: Collapsible,
31
+ * componentProps: {
32
+ * title: 'Дополнительные параметры',
33
+ * defaultOpen: false,
34
+ * className: 'border rounded p-4',
35
+ * titleClassName: 'font-semibold w-full text-left',
36
+ * },
37
+ * children: [
38
+ * { component: path.notes },
39
+ * { component: path.tags },
40
+ * ],
41
+ * }
42
+ * ```
43
+ *
44
+ * @example Развёрнута, со специальным фоном контента
45
+ * ```typescript
46
+ * {
47
+ * component: Collapsible,
48
+ * componentProps: {
49
+ * title: 'Адрес доставки',
50
+ * defaultOpen: true,
51
+ * contentClassName: 'mt-2 bg-gray-50 p-3 rounded',
52
+ * },
53
+ * children: [
54
+ * { component: path.deliveryAddress },
55
+ * ],
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function Collapsible({ title, defaultOpen, className, titleClassName, contentClassName, children, }: CollapsibleProps): ReactNode;
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ /** Props компонента {@link ExampleCard}. */
3
+ export interface ExampleCardProps {
4
+ /** Заголовок карточки (обязательный). */
5
+ title: string;
6
+ /** Описание под заголовком. */
7
+ description?: string;
8
+ /** Контент примера, отображаемый в режиме «пример». */
9
+ children: React.ReactNode;
10
+ /** Текст исходного кода, копируемый в clipboard в режиме «код». */
11
+ code: string;
12
+ /** Дополнительный CSS-класс контейнера. */
13
+ className?: string;
14
+ /** Tailwind-класс фона карточки. По умолчанию `'bg-white'`. */
15
+ bgColor?: string;
16
+ }
17
+ /**
18
+ * Карточка-обёртка для демонстрации компонентов в playground: заголовок,
19
+ * описание, область с примером и кнопка переключения исходного кода с
20
+ * copy-to-clipboard.
21
+ *
22
+ * Утилита для playground/документации, не для продакшена.
23
+ *
24
+ * @example Базовое использование
25
+ * ```tsx
26
+ * import { ExampleCard, Input } from '@reformer/ui-kit';
27
+ * import { useState } from 'react';
28
+ *
29
+ * function Demo() {
30
+ * const [v, setV] = useState<string | null>(null);
31
+ * return (
32
+ * <ExampleCard
33
+ * title="Input — базовый"
34
+ * description="Однострочное поле с placeholder"
35
+ * code={`<Input value={v} onChange={setV} placeholder="Email" />`}
36
+ * >
37
+ * <Input value={v} onChange={setV} placeholder="Email" />
38
+ * </ExampleCard>
39
+ * );
40
+ * }
41
+ * ```
42
+ *
43
+ * @example С кастомным фоном (для подсветки группы)
44
+ * ```tsx
45
+ * import { ExampleCard, Button } from '@reformer/ui-kit';
46
+ *
47
+ * <ExampleCard
48
+ * title="Destructive button"
49
+ * description="Кнопка опасного действия"
50
+ * bgColor="bg-red-50"
51
+ * code={`<Button variant="destructive">Delete</Button>`}
52
+ * >
53
+ * <Button variant="destructive">Delete</Button>
54
+ * </ExampleCard>
55
+ * ```
56
+ */
57
+ export declare function ExampleCard({ title, description, children, code, className, bgColor, }: ExampleCardProps): import("react/jsx-runtime").JSX.Element;