@reformer/cdk 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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/dist/FormArray-CBT-1kKN.js +120 -0
  4. package/dist/FormWizard-DLDm4FJM.js +311 -0
  5. package/dist/Slot-YDt2BEtP.js +27 -0
  6. package/dist/components/form-array/FormArray.d.ts +223 -0
  7. package/dist/components/form-array/FormArrayAddButton.d.ts +6 -0
  8. package/dist/components/form-array/FormArrayContext.d.ts +137 -0
  9. package/dist/components/form-array/FormArrayCount.d.ts +17 -0
  10. package/dist/components/form-array/FormArrayEmpty.d.ts +22 -0
  11. package/dist/components/form-array/FormArrayItemIndex.d.ts +24 -0
  12. package/dist/components/form-array/FormArrayList.d.ts +26 -0
  13. package/dist/components/form-array/FormArrayRemoveButton.d.ts +26 -0
  14. package/dist/components/form-array/index.d.ts +13 -0
  15. package/dist/components/form-array/types.d.ts +77 -0
  16. package/dist/components/form-array/useFormArray.d.ts +95 -0
  17. package/dist/components/form-field/FormField.d.ts +107 -0
  18. package/dist/components/form-field/FormFieldContext.d.ts +56 -0
  19. package/dist/components/form-field/FormFieldControl.d.ts +35 -0
  20. package/dist/components/form-field/FormFieldDescription.d.ts +30 -0
  21. package/dist/components/form-field/FormFieldError.d.ts +36 -0
  22. package/dist/components/form-field/FormFieldLabel.d.ts +35 -0
  23. package/dist/components/form-field/FormFieldRoot.d.ts +32 -0
  24. package/dist/components/form-field/index.d.ts +10 -0
  25. package/dist/components/form-field/types.d.ts +114 -0
  26. package/dist/components/form-field/useFormField.d.ts +111 -0
  27. package/dist/components/form-wizard/FormWizard.d.ts +47 -0
  28. package/dist/components/form-wizard/FormWizardActions.d.ts +98 -0
  29. package/dist/components/form-wizard/FormWizardContext.d.ts +84 -0
  30. package/dist/components/form-wizard/FormWizardIndicator.d.ts +118 -0
  31. package/dist/components/form-wizard/FormWizardNext.d.ts +35 -0
  32. package/dist/components/form-wizard/FormWizardPrev.d.ts +35 -0
  33. package/dist/components/form-wizard/FormWizardProgress.d.ts +83 -0
  34. package/dist/components/form-wizard/FormWizardStep.d.ts +55 -0
  35. package/dist/components/form-wizard/FormWizardSubmit.d.ts +43 -0
  36. package/dist/components/form-wizard/Slot.d.ts +20 -0
  37. package/dist/components/form-wizard/Step.d.ts +24 -0
  38. package/dist/components/form-wizard/index.d.ts +21 -0
  39. package/dist/components/form-wizard/types.d.ts +108 -0
  40. package/dist/form-array.d.ts +2 -0
  41. package/dist/form-array.js +15 -0
  42. package/dist/form-field.d.ts +2 -0
  43. package/dist/form-field.js +12 -0
  44. package/dist/form-wizard.d.ts +2 -0
  45. package/dist/form-wizard.js +22 -0
  46. package/dist/index.d.ts +6 -0
  47. package/dist/index.js +33 -0
  48. package/dist/useFormField-DV396Bxa.js +232 -0
  49. package/llms.txt +3294 -0
  50. package/package.json +90 -0
@@ -0,0 +1,108 @@
1
+ import { ReactNode } from 'react';
2
+ import { FormProxy, ValidationSchemaFn } from '@reformer/core';
3
+ /**
4
+ * Configuration for multi-step form navigation
5
+ * Note: totalSteps is inferred from children count
6
+ */
7
+ export interface FormWizardConfig<T extends Record<string, any>> {
8
+ /** Validation schemas per step (1-based indexing) */
9
+ stepValidations: Record<number, ValidationSchemaFn<T>>;
10
+ /** Full validation schema for submit */
11
+ fullValidation: ValidationSchemaFn<T>;
12
+ }
13
+ /**
14
+ * Handle для внешнего управления {@link FormWizard} через `useRef`.
15
+ *
16
+ * Используется, когда submit/навигация инициируется снаружи дерева Wizard:
17
+ * шапка страницы, breadcrumbs, side-effect от API. Получают через
18
+ * `useRef<FormWizardHandle<T>>(null)` и передают в `<FormWizard ref={...}>`.
19
+ *
20
+ * - `goToNextStep()` / `submit()` запускают валидацию текущего шага / всей
21
+ * формы соответственно.
22
+ * - `goToStep(n)` возвращает `false`, если предыдущий шаг не в `completedSteps`
23
+ * (защита от пропуска валидации) либо `n` вне диапазона `[1; totalSteps]`.
24
+ * - `submit()` возвращает `R | null`. `null` — форма не прошла `fullValidation`.
25
+ *
26
+ * @typeParam T - Тип значения корневой формы (`FormProxy<T>`).
27
+ *
28
+ * @example «Сохранить и выйти» поверх wizard
29
+ * ```tsx
30
+ * import { useRef } from 'react';
31
+ * import { FormWizard, type FormWizardHandle } from '@reformer/cdk/form-wizard';
32
+ *
33
+ * function Page({ form, config }: Props) {
34
+ * const navRef = useRef<FormWizardHandle<CreditApplication>>(null);
35
+ *
36
+ * const handleSaveAndExit = async () => {
37
+ * const saved = await navRef.current?.submit((values) => api.saveDraft(values));
38
+ * if (saved) router.push('/dashboard');
39
+ * };
40
+ *
41
+ * return (
42
+ * <>
43
+ * <header>
44
+ * <button onClick={handleSaveAndExit}>Сохранить и выйти</button>
45
+ * </header>
46
+ * <FormWizard ref={navRef} form={form} config={config}>
47
+ * <FormWizard.Step component={Step1} control={form} />
48
+ * <FormWizard.Step component={Step2} control={form} />
49
+ * </FormWizard>
50
+ * </>
51
+ * );
52
+ * }
53
+ * ```
54
+ *
55
+ * @example Программный переход на шаг с проверкой доступности
56
+ * ```tsx
57
+ * const handleClickContacts = () => {
58
+ * const ok = navRef.current?.goToStep(3);
59
+ * if (!ok) toast('Сначала заполните предыдущие шаги');
60
+ * };
61
+ *
62
+ * // Или с явной валидацией текущего шага:
63
+ * const moveOn = async () => {
64
+ * const valid = await navRef.current?.validateCurrentStep();
65
+ * if (!valid) return;
66
+ * await navRef.current?.goToNextStep();
67
+ * };
68
+ * ```
69
+ */
70
+ export interface FormWizardHandle<T extends Record<string, any>> {
71
+ /** Form instance — используется в RenderBehaviorFn для доступа к форме через ref */
72
+ form: FormProxy<T>;
73
+ /** Current step (1-based) */
74
+ currentStep: number;
75
+ /** Completed steps */
76
+ completedSteps: number[];
77
+ /** Validate current step */
78
+ validateCurrentStep: () => Promise<boolean>;
79
+ /** Go to next step (with validation) */
80
+ goToNextStep: () => Promise<boolean>;
81
+ /** Go to previous step */
82
+ goToPreviousStep: () => void;
83
+ /** Go to specific step */
84
+ goToStep: (step: number) => boolean;
85
+ /** Submit form (with full validation) */
86
+ submit: <R>(onSubmit: (values: T) => Promise<R> | R) => Promise<R | null>;
87
+ /** Is this the first step */
88
+ isFirstStep: boolean;
89
+ /** Is this the last step */
90
+ isLastStep: boolean;
91
+ /** Is validation in progress */
92
+ isValidating: boolean;
93
+ }
94
+ /**
95
+ * Props for FormWizard component
96
+ */
97
+ export interface FormWizardProps<T extends Record<string, any>> {
98
+ /** Form instance */
99
+ form: FormProxy<T>;
100
+ /** Step configuration (validation schemas) */
101
+ config: FormWizardConfig<T>;
102
+ /** Children (Step components, Indicator, Actions, Progress, or any ReactNode) */
103
+ children?: ReactNode;
104
+ /** Callback when step changes */
105
+ onStepChange?: (step: number) => void;
106
+ /** Scroll to top on step change */
107
+ scrollToTop?: boolean;
108
+ }
@@ -0,0 +1,2 @@
1
+ export * from './components/form-array/index'
2
+ export {}
@@ -0,0 +1,15 @@
1
+ import { F as o, b as t, g as m, e as s, d as e, h as y, f as A, a as F, c as n, u, i as x, j as C } from "./FormArray-CBT-1kKN.js";
2
+ export {
3
+ o as FormArray,
4
+ t as FormArrayAddButton,
5
+ m as FormArrayContext,
6
+ s as FormArrayCount,
7
+ e as FormArrayEmpty,
8
+ y as FormArrayItemContext,
9
+ A as FormArrayItemIndex,
10
+ F as FormArrayList,
11
+ n as FormArrayRemoveButton,
12
+ u as useFormArray,
13
+ x as useFormArrayContext,
14
+ C as useFormArrayItemContext
15
+ };
@@ -0,0 +1,2 @@
1
+ export * from './components/form-field/index'
2
+ export {}
@@ -0,0 +1,12 @@
1
+ import { F as e, f as r, c as s, e as a, d as i, b as l, a as d, u as m, g as t } from "./useFormField-DV396Bxa.js";
2
+ export {
3
+ e as FormField,
4
+ r as FormFieldContext,
5
+ s as FormFieldControl,
6
+ a as FormFieldDescription,
7
+ i as FormFieldError,
8
+ l as FormFieldLabel,
9
+ d as FormFieldRoot,
10
+ m as useFormField,
11
+ t as useFormFieldContext
12
+ };
@@ -0,0 +1,2 @@
1
+ export * from './components/form-wizard/index'
2
+ export {}
@@ -0,0 +1,22 @@
1
+ import { F as e, c as d, e as F, b as z, h as W, g as n, d as p, a as u, i as x, u as S, f as c } from "./FormWizard-DLDm4FJM.js";
2
+ import { jsx as a, Fragment as o } from "react/jsx-runtime";
3
+ import { S as g } from "./Slot-YDt2BEtP.js";
4
+ function s({ children: r }) {
5
+ return /* @__PURE__ */ a(o, { children: r });
6
+ }
7
+ s.displayName = "Step";
8
+ export {
9
+ e as FormWizard,
10
+ d as FormWizardActions,
11
+ F as FormWizardContext,
12
+ z as FormWizardIndicator,
13
+ W as FormWizardNext,
14
+ n as FormWizardPrev,
15
+ p as FormWizardProgress,
16
+ u as FormWizardStep,
17
+ x as FormWizardSubmit,
18
+ g as Slot,
19
+ s as Step,
20
+ S as useFormWizard,
21
+ c as useFormWizardActions
22
+ };
@@ -0,0 +1,6 @@
1
+ export { FormArray, FormArrayList, FormArrayAddButton, FormArrayRemoveButton, FormArrayEmpty, FormArrayCount, FormArrayItemIndex, useFormArray, FormArrayContext, FormArrayItemContext, useFormArrayContext, useFormArrayItemContext, } from './components/form-array';
2
+ export type { FormArrayHandle, FormArrayItem, UseFormArrayReturn, FormArrayRootProps, FormArrayListProps, FormArrayItemRenderProps, FormArrayAddButtonProps, FormArrayRemoveButtonProps, FormArrayEmptyProps, FormArrayCountProps, FormArrayItemIndexProps, FormArrayContextValue, FormArrayItemContextValue, } from './components/form-array';
3
+ export { FormField, FormFieldRoot, FormFieldLabel, FormFieldControl, FormFieldError, FormFieldDescription, useFormField, FormFieldContext, useFormFieldContext, } from './components/form-field';
4
+ export type { FormFieldIds, FormFieldContextValue, FormFieldRootProps, FormFieldLabelProps, FormFieldControlProps, FormFieldErrorProps, FormFieldDescriptionProps, UseFormFieldReturn, UseFormFieldState, UseFormFieldLabelProps, UseFormFieldControlProps, UseFormFieldErrorProps, UseFormFieldDescriptionProps, } from './components/form-field';
5
+ export { FormWizard, FormWizardStep, FormWizardIndicator, FormWizardActions, FormWizardProgress, useFormWizard, FormWizardContext, } from './components/form-wizard';
6
+ export type { FormWizardHandle, FormWizardProps, FormWizardConfig, FormWizardStepProps, FormWizardContextValue, FormWizardIndicatorProps, FormWizardIndicatorStep, FormWizardIndicatorStepWithState, FormWizardIndicatorRenderProps, FormWizardActionsProps, FormWizardActionsRenderProps, FormWizardButtonProps, FormWizardSubmitProps, FormWizardProgressProps, FormWizardProgressRenderProps, } from './components/form-wizard';
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ import { F as a, b as F, g as s, e, d as m, h as t, f as d, a as i, c as n, u as A, i as y, j as u } from "./FormArray-CBT-1kKN.js";
2
+ import { F as x, f as C, c as z, e as W, d as c, b as p, a as f, u as I, g as b } from "./useFormField-DV396Bxa.js";
3
+ import { F as B, c as E, e as L, b as R, d as h, a as j, u as v } from "./FormWizard-DLDm4FJM.js";
4
+ export {
5
+ a as FormArray,
6
+ F as FormArrayAddButton,
7
+ s as FormArrayContext,
8
+ e as FormArrayCount,
9
+ m as FormArrayEmpty,
10
+ t as FormArrayItemContext,
11
+ d as FormArrayItemIndex,
12
+ i as FormArrayList,
13
+ n as FormArrayRemoveButton,
14
+ x as FormField,
15
+ C as FormFieldContext,
16
+ z as FormFieldControl,
17
+ W as FormFieldDescription,
18
+ c as FormFieldError,
19
+ p as FormFieldLabel,
20
+ f as FormFieldRoot,
21
+ B as FormWizard,
22
+ E as FormWizardActions,
23
+ L as FormWizardContext,
24
+ R as FormWizardIndicator,
25
+ h as FormWizardProgress,
26
+ j as FormWizardStep,
27
+ A as useFormArray,
28
+ y as useFormArrayContext,
29
+ u as useFormArrayItemContext,
30
+ I as useFormField,
31
+ b as useFormFieldContext,
32
+ v as useFormWizard
33
+ };
@@ -0,0 +1,232 @@
1
+ import { jsx as p, jsxs as S, Fragment as P } from "react/jsx-runtime";
2
+ import { createContext as T, useContext as V, useId as q, useMemo as v, forwardRef as g } from "react";
3
+ import { useFormControl as E } from "@reformer/core";
4
+ import { S as C } from "./Slot-YDt2BEtP.js";
5
+ const $ = T(null);
6
+ function w() {
7
+ const r = V($);
8
+ if (!r)
9
+ throw new Error(
10
+ "FormField.* components must be used within <FormField.Root>. Wrap your field with <FormField.Root control={control}>."
11
+ );
12
+ return r;
13
+ }
14
+ function y({
15
+ control: r,
16
+ children: a,
17
+ id: s,
18
+ hasDescription: d = !1
19
+ }) {
20
+ const e = q(), i = s ?? e, c = v(
21
+ () => ({
22
+ controlId: `control-${i}`,
23
+ labelId: `label-${i}`,
24
+ descriptionId: `desc-${i}`,
25
+ errorId: `error-${i}`
26
+ }),
27
+ [i]
28
+ ), o = E(r), t = v(() => {
29
+ const {
30
+ value: u,
31
+ errors: l,
32
+ pending: n,
33
+ disabled: I,
34
+ valid: F,
35
+ invalid: b,
36
+ touched: h,
37
+ shouldShowError: m,
38
+ componentProps: x
39
+ } = o;
40
+ return {
41
+ value: u,
42
+ errors: l,
43
+ pending: n,
44
+ disabled: I,
45
+ valid: F,
46
+ invalid: b,
47
+ touched: h,
48
+ shouldShowError: m,
49
+ error: m ? l[0]?.message : void 0,
50
+ label: x.label,
51
+ required: !!x.required,
52
+ componentProps: x,
53
+ control: r,
54
+ ids: c,
55
+ hasDescription: d
56
+ };
57
+ }, [o, r, c, d]);
58
+ return /* @__PURE__ */ p($.Provider, { value: t, children: a });
59
+ }
60
+ y.displayName = "FormField.Root";
61
+ const k = g(
62
+ ({ asChild: r = !1, children: a, forceRender: s = !1, ...d }, e) => {
63
+ const { label: i, required: c, ids: o } = w(), t = a ?? i;
64
+ return !t && !s ? null : /* @__PURE__ */ S(r ? C : "label", { ref: e, id: o.labelId, htmlFor: r ? void 0 : o.controlId, ...d, children: [
65
+ t,
66
+ c && /* @__PURE__ */ p("span", { "aria-hidden": "true", children: " *" })
67
+ ] });
68
+ }
69
+ );
70
+ k.displayName = "FormField.Label";
71
+ const A = g(
72
+ ({ asChild: r = !1, children: a, ...s }, d) => {
73
+ const {
74
+ control: e,
75
+ value: i,
76
+ disabled: c,
77
+ shouldShowError: o,
78
+ errors: t,
79
+ required: u,
80
+ ids: l,
81
+ hasDescription: n,
82
+ componentProps: I
83
+ } = w(), F = [
84
+ n ? l.descriptionId : null,
85
+ o && t.length > 0 ? l.errorId : null
86
+ ].filter(Boolean).join(" ") || void 0, b = {
87
+ id: l.controlId,
88
+ "aria-labelledby": l.labelId,
89
+ "aria-invalid": o ? !0 : void 0,
90
+ "aria-describedby": F,
91
+ "aria-errormessage": o && t.length > 0 ? l.errorId : void 0,
92
+ "aria-required": u ? !0 : void 0
93
+ };
94
+ if (a || r)
95
+ return /* @__PURE__ */ p(C, { ref: d, ...b, ...s, children: a });
96
+ const h = e.component;
97
+ return /* @__PURE__ */ p(
98
+ h,
99
+ {
100
+ ref: d,
101
+ ...I,
102
+ ...b,
103
+ ...s,
104
+ value: i,
105
+ disabled: c,
106
+ onChange: (m) => e.setValue(m),
107
+ onBlur: () => e.markAsTouched()
108
+ }
109
+ );
110
+ }
111
+ );
112
+ A.displayName = "FormField.Control";
113
+ const B = g(
114
+ ({ asChild: r = !1, multi: a = !1, render: s, children: d, ...e }, i) => {
115
+ const { shouldShowError: c, errors: o, ids: t } = w();
116
+ if (!c || o.length === 0) return null;
117
+ const u = r ? C : "p";
118
+ return s ? /* @__PURE__ */ p(P, { children: o.map((l, n) => /* @__PURE__ */ p(
119
+ u,
120
+ {
121
+ id: n === 0 ? t.errorId : void 0,
122
+ role: "alert",
123
+ ...e,
124
+ children: s(l, n)
125
+ },
126
+ l.code ?? n
127
+ )) }) : a ? /* @__PURE__ */ p(P, { children: o.map((l, n) => /* @__PURE__ */ p(
128
+ u,
129
+ {
130
+ id: n === 0 ? t.errorId : void 0,
131
+ role: "alert",
132
+ ...e,
133
+ children: l.message
134
+ },
135
+ l.code ?? n
136
+ )) }) : /* @__PURE__ */ p(u, { ref: i, id: t.errorId, role: "alert", ...e, children: d ?? o[0].message });
137
+ }
138
+ );
139
+ B.displayName = "FormField.Error";
140
+ const R = g(
141
+ ({ asChild: r = !1, children: a, ...s }, d) => {
142
+ const { ids: e } = w();
143
+ return /* @__PURE__ */ p(r ? C : "p", { ref: d, id: e.descriptionId, ...s, children: a });
144
+ }
145
+ );
146
+ R.displayName = "FormField.Description";
147
+ const f = y;
148
+ f.Root = y;
149
+ f.Label = k;
150
+ f.Control = A;
151
+ f.Error = B;
152
+ f.Description = R;
153
+ function U(r, a) {
154
+ const s = q(), d = a ?? s, e = v(
155
+ () => ({
156
+ controlId: `control-${d}`,
157
+ labelId: `label-${d}`,
158
+ descriptionId: `desc-${d}`,
159
+ errorId: `error-${d}`
160
+ }),
161
+ [d]
162
+ ), i = E(r);
163
+ return v(() => {
164
+ const {
165
+ value: c,
166
+ errors: o,
167
+ pending: t,
168
+ disabled: u,
169
+ valid: l,
170
+ invalid: n,
171
+ touched: I,
172
+ shouldShowError: F,
173
+ componentProps: b
174
+ } = i, h = !!b.required;
175
+ return {
176
+ ids: e,
177
+ labelProps: {
178
+ id: e.labelId,
179
+ htmlFor: e.controlId
180
+ },
181
+ controlProps: {
182
+ id: e.controlId,
183
+ value: c,
184
+ disabled: u,
185
+ "aria-labelledby": e.labelId,
186
+ "aria-invalid": F ? !0 : void 0,
187
+ "aria-errormessage": F && o.length > 0 ? e.errorId : void 0,
188
+ "aria-required": h ? !0 : void 0,
189
+ onChange: (m) => r.setValue(m),
190
+ onBlur: () => r.markAsTouched()
191
+ },
192
+ errorProps: {
193
+ id: e.errorId,
194
+ role: "alert"
195
+ },
196
+ descriptionProps: {
197
+ id: e.descriptionId
198
+ },
199
+ state: {
200
+ value: c,
201
+ errors: o,
202
+ error: F ? o[0]?.message : void 0,
203
+ isPending: t,
204
+ isDisabled: u,
205
+ isValid: l,
206
+ isInvalid: n,
207
+ isTouched: I,
208
+ shouldShowError: F,
209
+ label: b.label,
210
+ required: h,
211
+ componentProps: b
212
+ },
213
+ actions: {
214
+ setValue: (m) => r.setValue(m),
215
+ markAsTouched: () => r.markAsTouched(),
216
+ markAsUntouched: () => r.markAsUntouched(),
217
+ reset: (m) => r.reset(m)
218
+ }
219
+ };
220
+ }, [i, r, e]);
221
+ }
222
+ export {
223
+ f as F,
224
+ y as a,
225
+ k as b,
226
+ A as c,
227
+ B as d,
228
+ R as e,
229
+ $ as f,
230
+ w as g,
231
+ U as u
232
+ };