@reformer/ui 1.0.0-beta.3 → 1.0.0-beta.4
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/FormNavigation-Di3Mss2W.js +330 -0
- package/dist/form-navigation/FormNavigation.d.ts +6 -0
- package/dist/form-navigation/FormNavigationActions.d.ts +42 -39
- package/dist/form-navigation/FormNavigationNext.d.ts +35 -0
- package/dist/form-navigation/FormNavigationPrev.d.ts +35 -0
- package/dist/form-navigation/FormNavigationSubmit.d.ts +43 -0
- package/dist/form-navigation/Slot.d.ts +20 -0
- package/dist/form-navigation/index.d.ts +10 -2
- package/dist/form-navigation.js +11 -6
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/FormNavigation-3rg4tJyl.js +0 -227
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { jsx as p, Fragment as A } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as M, useContext as U, useMemo as Y, forwardRef as y, Children as D, isValidElement as j, cloneElement as L, useState as E, useCallback as F, useImperativeHandle as tt } from "react";
|
|
3
|
+
import { validateForm as G } from "@reformer/core/validators";
|
|
4
|
+
const H = M(null);
|
|
5
|
+
function g() {
|
|
6
|
+
const t = U(H);
|
|
7
|
+
if (!t)
|
|
8
|
+
throw new Error("useFormNavigation must be used within FormNavigation");
|
|
9
|
+
return t;
|
|
10
|
+
}
|
|
11
|
+
function I({
|
|
12
|
+
component: t,
|
|
13
|
+
control: n,
|
|
14
|
+
_stepIndex: s,
|
|
15
|
+
...e
|
|
16
|
+
}) {
|
|
17
|
+
const { currentStep: i } = g();
|
|
18
|
+
return s === void 0 || i !== s ? null : /* @__PURE__ */ p(t, { control: n, ...e });
|
|
19
|
+
}
|
|
20
|
+
I.displayName = "FormNavigation.Step";
|
|
21
|
+
function O({ steps: t, children: n }) {
|
|
22
|
+
if (typeof n != "function")
|
|
23
|
+
throw new Error(
|
|
24
|
+
"FormNavigation.Indicator requires children as a render function. Example: <FormNavigation.Indicator steps={STEPS}>{({ steps }) => <YourUI />}</FormNavigation.Indicator>"
|
|
25
|
+
);
|
|
26
|
+
const { currentStep: s, totalSteps: e, completedSteps: i, goToStep: r } = g(), c = {
|
|
27
|
+
steps: t.map((o) => ({
|
|
28
|
+
...o,
|
|
29
|
+
isCurrent: s === o.number,
|
|
30
|
+
isCompleted: i.includes(o.number),
|
|
31
|
+
canNavigate: o.number === 1 || i.includes(o.number - 1)
|
|
32
|
+
})),
|
|
33
|
+
goToStep: r,
|
|
34
|
+
currentStep: s,
|
|
35
|
+
totalSteps: e,
|
|
36
|
+
completedSteps: i
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ p(A, { children: n(c) });
|
|
39
|
+
}
|
|
40
|
+
O.displayName = "FormNavigation.Indicator";
|
|
41
|
+
const $ = M(null);
|
|
42
|
+
function et() {
|
|
43
|
+
const t = U($);
|
|
44
|
+
if (!t)
|
|
45
|
+
throw new Error(
|
|
46
|
+
"FormNavigation.Prev/Next/Submit must be used within FormNavigation.Actions. Wrap your navigation buttons with <FormNavigation.Actions>."
|
|
47
|
+
);
|
|
48
|
+
return t;
|
|
49
|
+
}
|
|
50
|
+
function ot(t) {
|
|
51
|
+
return typeof t == "function";
|
|
52
|
+
}
|
|
53
|
+
function z({
|
|
54
|
+
onSubmit: t,
|
|
55
|
+
children: n,
|
|
56
|
+
className: s,
|
|
57
|
+
style: e
|
|
58
|
+
}) {
|
|
59
|
+
const { isFirstStep: i, isLastStep: r, isValidating: a, isSubmitting: c, goToNextStep: o, goToPreviousStep: m } = g(), d = Y(() => ({ onSubmit: t }), [t]);
|
|
60
|
+
if (ot(n)) {
|
|
61
|
+
const v = a || c;
|
|
62
|
+
return /* @__PURE__ */ p(A, { children: n({
|
|
63
|
+
prev: {
|
|
64
|
+
onClick: m,
|
|
65
|
+
disabled: v
|
|
66
|
+
},
|
|
67
|
+
next: {
|
|
68
|
+
onClick: () => o(),
|
|
69
|
+
disabled: v
|
|
70
|
+
},
|
|
71
|
+
submit: {
|
|
72
|
+
onClick: () => t?.(),
|
|
73
|
+
disabled: v,
|
|
74
|
+
isSubmitting: c
|
|
75
|
+
},
|
|
76
|
+
isFirstStep: i,
|
|
77
|
+
isLastStep: r,
|
|
78
|
+
isValidating: a,
|
|
79
|
+
isSubmitting: c
|
|
80
|
+
}) });
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ p($.Provider, { value: d, children: s || e ? /* @__PURE__ */ p("div", { className: s, style: e, children: n }) : /* @__PURE__ */ p(A, { children: n }) });
|
|
83
|
+
}
|
|
84
|
+
z.displayName = "FormNavigation.Actions";
|
|
85
|
+
function J({ children: t }) {
|
|
86
|
+
if (typeof t != "function")
|
|
87
|
+
throw new Error(
|
|
88
|
+
"FormNavigation.Progress requires children as a render function. Example: <FormNavigation.Progress>{({ current, total }) => <YourUI />}</FormNavigation.Progress>"
|
|
89
|
+
);
|
|
90
|
+
const { currentStep: n, totalSteps: s, completedSteps: e, isFirstStep: i, isLastStep: r } = g(), a = {
|
|
91
|
+
current: n,
|
|
92
|
+
total: s,
|
|
93
|
+
percent: Math.round(n / s * 100),
|
|
94
|
+
completedCount: e.length,
|
|
95
|
+
isFirstStep: i,
|
|
96
|
+
isLastStep: r
|
|
97
|
+
};
|
|
98
|
+
return /* @__PURE__ */ p(A, { children: t(a) });
|
|
99
|
+
}
|
|
100
|
+
J.displayName = "FormNavigation.Progress";
|
|
101
|
+
function it(t, n) {
|
|
102
|
+
const s = { ...t };
|
|
103
|
+
for (const e of Object.keys(n)) {
|
|
104
|
+
const i = t[e], r = n[e];
|
|
105
|
+
e.startsWith("on") && typeof i == "function" && typeof r == "function" ? s[e] = (...a) => {
|
|
106
|
+
r(...a), i(...a);
|
|
107
|
+
} : e === "className" && typeof i == "string" && typeof r == "string" ? s[e] = [r, i].filter(Boolean).join(" ") : e === "style" && typeof i == "object" && typeof r == "object" ? s[e] = { ...r, ...i } : e === "disabled" ? s[e] = !!i || !!r : r !== void 0 && (s[e] = r);
|
|
108
|
+
}
|
|
109
|
+
return s;
|
|
110
|
+
}
|
|
111
|
+
const k = y(
|
|
112
|
+
({ children: t, ...n }, s) => {
|
|
113
|
+
const e = D.only(t);
|
|
114
|
+
if (!j(e))
|
|
115
|
+
return null;
|
|
116
|
+
const i = e.props, r = it(n, i), a = e.ref;
|
|
117
|
+
return L(e, {
|
|
118
|
+
...r,
|
|
119
|
+
ref: s || a
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
k.displayName = "Slot";
|
|
124
|
+
const K = y(
|
|
125
|
+
({ children: t, asChild: n = !1, disabled: s, ...e }, i) => {
|
|
126
|
+
const { goToPreviousStep: r, isFirstStep: a, isValidating: c, isSubmitting: o } = g();
|
|
127
|
+
return /* @__PURE__ */ p(
|
|
128
|
+
n ? k : "button",
|
|
129
|
+
{
|
|
130
|
+
ref: i,
|
|
131
|
+
type: n ? void 0 : "button",
|
|
132
|
+
onClick: r,
|
|
133
|
+
disabled: s || (a || c || o),
|
|
134
|
+
"data-first-step": a || void 0,
|
|
135
|
+
...e,
|
|
136
|
+
children: t
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
K.displayName = "FormNavigation.Prev";
|
|
142
|
+
const Q = y(
|
|
143
|
+
({ children: t, asChild: n = !1, disabled: s, ...e }, i) => {
|
|
144
|
+
const { goToNextStep: r, isLastStep: a, isValidating: c, isSubmitting: o } = g();
|
|
145
|
+
return /* @__PURE__ */ p(
|
|
146
|
+
n ? k : "button",
|
|
147
|
+
{
|
|
148
|
+
ref: i,
|
|
149
|
+
type: n ? void 0 : "button",
|
|
150
|
+
onClick: () => r(),
|
|
151
|
+
disabled: s || (a || c || o),
|
|
152
|
+
"data-last-step": a || void 0,
|
|
153
|
+
...e,
|
|
154
|
+
children: t
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
Q.displayName = "FormNavigation.Next";
|
|
160
|
+
const X = y(
|
|
161
|
+
({ children: t, asChild: n = !1, disabled: s, loadingText: e, ...i }, r) => {
|
|
162
|
+
const { isLastStep: a, isValidating: c, isSubmitting: o } = g(), { onSubmit: m } = et();
|
|
163
|
+
return /* @__PURE__ */ p(
|
|
164
|
+
n ? k : "button",
|
|
165
|
+
{
|
|
166
|
+
ref: r,
|
|
167
|
+
type: n ? void 0 : "submit",
|
|
168
|
+
onClick: () => m?.(),
|
|
169
|
+
disabled: s || (!a || c || o),
|
|
170
|
+
"data-submitting": o || void 0,
|
|
171
|
+
"data-not-last-step": !a || void 0,
|
|
172
|
+
...i,
|
|
173
|
+
children: o && e ? e : t
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
X.displayName = "FormNavigation.Submit";
|
|
179
|
+
function nt({ form: t, config: n, children: s, onStepChange: e, scrollToTop: i = !0 }, r) {
|
|
180
|
+
const a = (u) => {
|
|
181
|
+
let l = 0;
|
|
182
|
+
return D.forEach(u, (f) => {
|
|
183
|
+
if (j(f))
|
|
184
|
+
if (f.type === I)
|
|
185
|
+
l += 1;
|
|
186
|
+
else {
|
|
187
|
+
const q = f.props;
|
|
188
|
+
q.children && (l += a(q.children));
|
|
189
|
+
}
|
|
190
|
+
}), l;
|
|
191
|
+
}, c = a(s), [o, m] = E(1), [d, v] = E([]), [N, S] = E(!1), R = t.submitting.value, h = F(async () => {
|
|
192
|
+
const u = n.stepValidations[o];
|
|
193
|
+
if (!u)
|
|
194
|
+
return console.warn(`No validation schema for step ${o}`), !0;
|
|
195
|
+
S(!0);
|
|
196
|
+
try {
|
|
197
|
+
return await G(t, u);
|
|
198
|
+
} finally {
|
|
199
|
+
S(!1);
|
|
200
|
+
}
|
|
201
|
+
}, [t, o, n.stepValidations]), P = F(async () => {
|
|
202
|
+
if (!await h())
|
|
203
|
+
return t.markAsTouched(), !1;
|
|
204
|
+
if (d.includes(o) || v((l) => [...l, o]), o < c) {
|
|
205
|
+
const l = o + 1;
|
|
206
|
+
m(l), e?.(l), i && window.scrollTo({ top: 0, behavior: "smooth" });
|
|
207
|
+
}
|
|
208
|
+
return !0;
|
|
209
|
+
}, [
|
|
210
|
+
h,
|
|
211
|
+
o,
|
|
212
|
+
d,
|
|
213
|
+
c,
|
|
214
|
+
t,
|
|
215
|
+
e,
|
|
216
|
+
i
|
|
217
|
+
]), w = F(() => {
|
|
218
|
+
if (o > 1) {
|
|
219
|
+
const u = o - 1;
|
|
220
|
+
m(u), e?.(u), i && window.scrollTo({ top: 0, behavior: "smooth" });
|
|
221
|
+
}
|
|
222
|
+
}, [o, e, i]), x = F(
|
|
223
|
+
(u) => (u === 1 || d.includes(u - 1)) && u >= 1 && u <= c ? (m(u), e?.(u), i && window.scrollTo({ top: 0, behavior: "smooth" }), !0) : !1,
|
|
224
|
+
[d, c, e, i]
|
|
225
|
+
), T = F(
|
|
226
|
+
async (u) => {
|
|
227
|
+
S(!0);
|
|
228
|
+
try {
|
|
229
|
+
return await G(t, n.fullValidation) ? t.submit(u) : (t.markAsTouched(), null);
|
|
230
|
+
} finally {
|
|
231
|
+
S(!1);
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
[t, n.fullValidation]
|
|
235
|
+
), C = o === 1, V = o === c;
|
|
236
|
+
tt(
|
|
237
|
+
r,
|
|
238
|
+
() => ({
|
|
239
|
+
currentStep: o,
|
|
240
|
+
completedSteps: d,
|
|
241
|
+
validateCurrentStep: h,
|
|
242
|
+
goToNextStep: P,
|
|
243
|
+
goToPreviousStep: w,
|
|
244
|
+
goToStep: x,
|
|
245
|
+
submit: T,
|
|
246
|
+
isFirstStep: C,
|
|
247
|
+
isLastStep: V,
|
|
248
|
+
isValidating: N
|
|
249
|
+
}),
|
|
250
|
+
[
|
|
251
|
+
o,
|
|
252
|
+
d,
|
|
253
|
+
h,
|
|
254
|
+
P,
|
|
255
|
+
w,
|
|
256
|
+
x,
|
|
257
|
+
T,
|
|
258
|
+
C,
|
|
259
|
+
V,
|
|
260
|
+
N
|
|
261
|
+
]
|
|
262
|
+
);
|
|
263
|
+
const Z = Y(
|
|
264
|
+
() => ({
|
|
265
|
+
// State
|
|
266
|
+
currentStep: o,
|
|
267
|
+
totalSteps: c,
|
|
268
|
+
completedSteps: d,
|
|
269
|
+
isFirstStep: C,
|
|
270
|
+
isLastStep: V,
|
|
271
|
+
isValidating: N,
|
|
272
|
+
isSubmitting: R,
|
|
273
|
+
form: t,
|
|
274
|
+
// Navigation methods
|
|
275
|
+
goToNextStep: P,
|
|
276
|
+
goToPreviousStep: w,
|
|
277
|
+
goToStep: x
|
|
278
|
+
}),
|
|
279
|
+
[
|
|
280
|
+
o,
|
|
281
|
+
c,
|
|
282
|
+
d,
|
|
283
|
+
C,
|
|
284
|
+
V,
|
|
285
|
+
N,
|
|
286
|
+
R,
|
|
287
|
+
t,
|
|
288
|
+
P,
|
|
289
|
+
w,
|
|
290
|
+
x
|
|
291
|
+
]
|
|
292
|
+
);
|
|
293
|
+
let W = 0;
|
|
294
|
+
const B = (u) => D.map(u, (l) => {
|
|
295
|
+
if (!j(l))
|
|
296
|
+
return l;
|
|
297
|
+
const f = l.props;
|
|
298
|
+
return l.type === I ? (W += 1, L(l, {
|
|
299
|
+
...f,
|
|
300
|
+
_stepIndex: W
|
|
301
|
+
// 1-based indexing
|
|
302
|
+
})) : typeof f.children == "function" ? l : f.children ? L(l, {
|
|
303
|
+
...f,
|
|
304
|
+
children: B(f.children)
|
|
305
|
+
}) : l;
|
|
306
|
+
}), _ = B(s);
|
|
307
|
+
return /* @__PURE__ */ p(H.Provider, { value: Z, children: _ });
|
|
308
|
+
}
|
|
309
|
+
const st = y(nt), b = st;
|
|
310
|
+
b.Step = I;
|
|
311
|
+
b.Indicator = O;
|
|
312
|
+
b.Actions = z;
|
|
313
|
+
b.Progress = J;
|
|
314
|
+
b.Prev = K;
|
|
315
|
+
b.Next = Q;
|
|
316
|
+
b.Submit = X;
|
|
317
|
+
export {
|
|
318
|
+
b as F,
|
|
319
|
+
k as S,
|
|
320
|
+
I as a,
|
|
321
|
+
O as b,
|
|
322
|
+
z as c,
|
|
323
|
+
J as d,
|
|
324
|
+
H as e,
|
|
325
|
+
et as f,
|
|
326
|
+
K as g,
|
|
327
|
+
Q as h,
|
|
328
|
+
X as i,
|
|
329
|
+
g as u
|
|
330
|
+
};
|
|
@@ -2,6 +2,9 @@ import { FormNavigationStep } from './FormNavigationStep';
|
|
|
2
2
|
import { FormNavigationIndicator } from './FormNavigationIndicator';
|
|
3
3
|
import { FormNavigationActions } from './FormNavigationActions';
|
|
4
4
|
import { FormNavigationProgress } from './FormNavigationProgress';
|
|
5
|
+
import { FormNavigationPrev } from './FormNavigationPrev';
|
|
6
|
+
import { FormNavigationNext } from './FormNavigationNext';
|
|
7
|
+
import { FormNavigationSubmit } from './FormNavigationSubmit';
|
|
5
8
|
import type { FormNavigationHandle, FormNavigationProps } from './types';
|
|
6
9
|
declare const FormNavigationBase: <T extends Record<string, any>>(props: FormNavigationProps<T> & {
|
|
7
10
|
ref?: React.ForwardedRef<FormNavigationHandle<T>>;
|
|
@@ -11,6 +14,9 @@ type FormNavigationComponent = typeof FormNavigationBase & {
|
|
|
11
14
|
Indicator: typeof FormNavigationIndicator;
|
|
12
15
|
Actions: typeof FormNavigationActions;
|
|
13
16
|
Progress: typeof FormNavigationProgress;
|
|
17
|
+
Prev: typeof FormNavigationPrev;
|
|
18
|
+
Next: typeof FormNavigationNext;
|
|
19
|
+
Submit: typeof FormNavigationSubmit;
|
|
14
20
|
};
|
|
15
21
|
export declare const FormNavigation: FormNavigationComponent;
|
|
16
22
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Props for a navigation button (prev/next)
|
|
4
4
|
*/
|
|
@@ -34,31 +34,48 @@ export interface FormNavigationActionsRenderProps {
|
|
|
34
34
|
/** Whether form is submitting */
|
|
35
35
|
isSubmitting: boolean;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Render function type for headless mode
|
|
39
|
+
*/
|
|
40
|
+
type RenderFunction = (props: FormNavigationActionsRenderProps) => ReactNode;
|
|
37
41
|
/**
|
|
38
42
|
* Props for FormNavigation.Actions component
|
|
39
43
|
*/
|
|
40
44
|
export interface FormNavigationActionsProps {
|
|
41
45
|
/** Submit handler (called on last step) */
|
|
42
46
|
onSubmit?: () => void | Promise<void>;
|
|
43
|
-
/**
|
|
44
|
-
children:
|
|
47
|
+
/** Children: render function (headless) or ReactNode (compound components) */
|
|
48
|
+
children: ReactNode | RenderFunction;
|
|
49
|
+
/** Optional className for wrapper (compound mode only) */
|
|
50
|
+
className?: string;
|
|
51
|
+
/** Optional style for wrapper (compound mode only) */
|
|
52
|
+
style?: CSSProperties;
|
|
53
|
+
}
|
|
54
|
+
interface FormNavigationActionsContextValue {
|
|
55
|
+
onSubmit?: () => void | Promise<void>;
|
|
45
56
|
}
|
|
46
57
|
/**
|
|
47
|
-
*
|
|
58
|
+
* Hook to access Actions context (onSubmit handler)
|
|
48
59
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
60
|
+
* Must be used within FormNavigation.Actions component.
|
|
61
|
+
* Used internally by FormNavigation.Submit.
|
|
62
|
+
*/
|
|
63
|
+
export declare function useFormNavigationActions(): FormNavigationActionsContextValue;
|
|
64
|
+
/**
|
|
65
|
+
* FormNavigation.Actions - Container for navigation buttons
|
|
51
66
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
67
|
+
* Supports two modes:
|
|
68
|
+
*
|
|
69
|
+
* ## 1. Compound Components Mode (recommended for simple cases)
|
|
70
|
+
* ```tsx
|
|
71
|
+
* <FormNavigation.Actions onSubmit={handleSubmit}>
|
|
72
|
+
* <FormNavigation.Prev>Back</FormNavigation.Prev>
|
|
73
|
+
* <FormNavigation.Next>Next</FormNavigation.Next>
|
|
74
|
+
* <FormNavigation.Submit loadingText="Submitting...">Submit</FormNavigation.Submit>
|
|
75
|
+
* </FormNavigation.Actions>
|
|
76
|
+
* ```
|
|
60
77
|
*
|
|
61
|
-
*
|
|
78
|
+
* ## 2. Render Props Mode (for complex/custom layouts)
|
|
62
79
|
* ```tsx
|
|
63
80
|
* <FormNavigation.Actions onSubmit={handleSubmit}>
|
|
64
81
|
* {({ prev, next, submit, isFirstStep, isLastStep }) => (
|
|
@@ -83,31 +100,17 @@ export interface FormNavigationActionsProps {
|
|
|
83
100
|
* </FormNavigation.Actions>
|
|
84
101
|
* ```
|
|
85
102
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* <ActionBar.Right>
|
|
95
|
-
* {isLastStep ? (
|
|
96
|
-
* <PrimaryButton {...submit} loading={submit.isSubmitting}>
|
|
97
|
-
* Submit Application
|
|
98
|
-
* </PrimaryButton>
|
|
99
|
-
* ) : (
|
|
100
|
-
* <PrimaryButton {...next} loading={isValidating}>
|
|
101
|
-
* Continue
|
|
102
|
-
* </PrimaryButton>
|
|
103
|
-
* )}
|
|
104
|
-
* </ActionBar.Right>
|
|
105
|
-
* </ActionBar>
|
|
106
|
-
* )}
|
|
107
|
-
* </FormNavigation.Actions>
|
|
108
|
-
* ```
|
|
103
|
+
* ## Render Props (headless mode)
|
|
104
|
+
* - `prev` - props for Previous button (`onClick`, `disabled`)
|
|
105
|
+
* - `next` - props for Next button (`onClick`, `disabled`)
|
|
106
|
+
* - `submit` - props for Submit button (`onClick`, `disabled`, `isSubmitting`)
|
|
107
|
+
* - `isFirstStep` - hide prev button on first step
|
|
108
|
+
* - `isLastStep` - show submit instead of next on last step
|
|
109
|
+
* - `isValidating` - show loading state during validation
|
|
110
|
+
* - `isSubmitting` - show loading state during submission
|
|
109
111
|
*/
|
|
110
|
-
export declare function FormNavigationActions({ onSubmit, children }: FormNavigationActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
export declare function FormNavigationActions({ onSubmit, children, className, style, }: FormNavigationActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
111
113
|
export declare namespace FormNavigationActions {
|
|
112
114
|
var displayName: string;
|
|
113
115
|
}
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for FormNavigation.Next component
|
|
4
|
+
*/
|
|
5
|
+
export interface FormNavigationNextProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
6
|
+
/** Button content */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** Render as child element (merge props into child) */
|
|
9
|
+
asChild?: boolean;
|
|
10
|
+
/** Additional disabled state (merged with automatic via OR) */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* FormNavigation.Next - Next step button component
|
|
15
|
+
*
|
|
16
|
+
* Renders a button that validates current step and navigates to the next.
|
|
17
|
+
* Automatically disabled on the last step, during validation, or during submission.
|
|
18
|
+
*
|
|
19
|
+
* @example Basic usage
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <FormNavigation.Actions>
|
|
22
|
+
* <FormNavigation.Next>Continue</FormNavigation.Next>
|
|
23
|
+
* </FormNavigation.Actions>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example With custom button (asChild)
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <FormNavigation.Next asChild>
|
|
29
|
+
* <MyButton variant="primary">
|
|
30
|
+
* Next <ArrowRight />
|
|
31
|
+
* </MyButton>
|
|
32
|
+
* </FormNavigation.Next>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const FormNavigationNext: import("react").ForwardRefExoticComponent<FormNavigationNextProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for FormNavigation.Prev component
|
|
4
|
+
*/
|
|
5
|
+
export interface FormNavigationPrevProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
6
|
+
/** Button content */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** Render as child element (merge props into child) */
|
|
9
|
+
asChild?: boolean;
|
|
10
|
+
/** Additional disabled state (merged with automatic via OR) */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* FormNavigation.Prev - Previous step button component
|
|
15
|
+
*
|
|
16
|
+
* Renders a button that navigates to the previous step.
|
|
17
|
+
* Automatically disabled on the first step, during validation, or during submission.
|
|
18
|
+
*
|
|
19
|
+
* @example Basic usage
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <FormNavigation.Actions>
|
|
22
|
+
* <FormNavigation.Prev>Back</FormNavigation.Prev>
|
|
23
|
+
* </FormNavigation.Actions>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example With custom button (asChild)
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <FormNavigation.Prev asChild>
|
|
29
|
+
* <MyButton variant="ghost">
|
|
30
|
+
* <ArrowLeft /> Back
|
|
31
|
+
* </MyButton>
|
|
32
|
+
* </FormNavigation.Prev>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const FormNavigationPrev: import("react").ForwardRefExoticComponent<FormNavigationPrevProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for FormNavigation.Submit component
|
|
4
|
+
*/
|
|
5
|
+
export interface FormNavigationSubmitProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
6
|
+
/** Button content */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** Render as child element (merge props into child) */
|
|
9
|
+
asChild?: boolean;
|
|
10
|
+
/** Additional disabled state (merged with automatic via OR) */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** Content to show during submission (replaces children) */
|
|
13
|
+
loadingText?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* FormNavigation.Submit - Form submission button component
|
|
17
|
+
*
|
|
18
|
+
* Renders a button that submits the form on the last step.
|
|
19
|
+
* Automatically disabled when not on the last step, during validation, or during submission.
|
|
20
|
+
* Shows `loadingText` content during submission if provided.
|
|
21
|
+
*
|
|
22
|
+
* @example Basic usage
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <FormNavigation.Actions onSubmit={handleSubmit}>
|
|
25
|
+
* <FormNavigation.Submit>Submit</FormNavigation.Submit>
|
|
26
|
+
* </FormNavigation.Actions>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example With loading text
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <FormNavigation.Submit loadingText="Submitting...">
|
|
32
|
+
* Submit Application
|
|
33
|
+
* </FormNavigation.Submit>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example With custom button (asChild)
|
|
37
|
+
* ```tsx
|
|
38
|
+
* <FormNavigation.Submit asChild loadingText={<Spinner />}>
|
|
39
|
+
* <MyButton variant="success">Complete</MyButton>
|
|
40
|
+
* </FormNavigation.Submit>
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const FormNavigationSubmit: import("react").ForwardRefExoticComponent<FormNavigationSubmitProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode, type HTMLAttributes } from 'react';
|
|
2
|
+
export interface SlotProps extends HTMLAttributes<HTMLElement> {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Slot component for asChild pattern.
|
|
7
|
+
*
|
|
8
|
+
* Renders its child element and merges props from the Slot into the child.
|
|
9
|
+
* Used to allow custom components to be rendered in place of default elements.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // Instead of rendering a button, renders MyButton with merged props
|
|
14
|
+
* <Slot onClick={handleClick} disabled={true}>
|
|
15
|
+
* <MyButton className="custom">Click me</MyButton>
|
|
16
|
+
* </Slot>
|
|
17
|
+
* // Result: <MyButton onClick={handleClick} disabled={true} className="custom">Click me</MyButton>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const Slot: import("react").ForwardRefExoticComponent<SlotProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
export { FormNavigation } from './FormNavigation';
|
|
2
2
|
export { FormNavigationStep } from './FormNavigationStep';
|
|
3
3
|
export { FormNavigationIndicator } from './FormNavigationIndicator';
|
|
4
|
-
export { FormNavigationActions } from './FormNavigationActions';
|
|
4
|
+
export { FormNavigationActions, useFormNavigationActions } from './FormNavigationActions';
|
|
5
5
|
export { FormNavigationProgress } from './FormNavigationProgress';
|
|
6
|
+
export { FormNavigationPrev } from './FormNavigationPrev';
|
|
7
|
+
export { FormNavigationNext } from './FormNavigationNext';
|
|
8
|
+
export { FormNavigationSubmit } from './FormNavigationSubmit';
|
|
9
|
+
export { Slot } from './Slot';
|
|
10
|
+
export type { SlotProps } from './Slot';
|
|
6
11
|
export { useFormNavigation, FormNavigationContext } from './FormNavigationContext';
|
|
7
12
|
export type { FormNavigationHandle, FormNavigationProps, FormNavigationConfig } from './types';
|
|
8
13
|
export type { FormNavigationStepProps } from './FormNavigationStep';
|
|
9
14
|
export type { FormNavigationContextValue } from './FormNavigationContext';
|
|
10
15
|
export type { FormNavigationIndicatorProps, FormNavigationIndicatorStep, FormNavigationIndicatorStepWithState, FormNavigationIndicatorRenderProps, } from './FormNavigationIndicator';
|
|
11
|
-
export type { FormNavigationActionsProps, FormNavigationActionsRenderProps, FormNavigationButtonProps, FormNavigationSubmitProps, } from './FormNavigationActions';
|
|
16
|
+
export type { FormNavigationActionsProps, FormNavigationActionsRenderProps, FormNavigationButtonProps, FormNavigationSubmitProps as FormNavigationSubmitRenderProps, } from './FormNavigationActions';
|
|
17
|
+
export type { FormNavigationPrevProps } from './FormNavigationPrev';
|
|
18
|
+
export type { FormNavigationNextProps } from './FormNavigationNext';
|
|
19
|
+
export type { FormNavigationSubmitProps } from './FormNavigationSubmit';
|
|
12
20
|
export type { FormNavigationProgressProps, FormNavigationProgressRenderProps, } from './FormNavigationProgress';
|
package/dist/form-navigation.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { F as i, c as t, e as
|
|
1
|
+
import { F as i, c as t, e as s, b as r, h as n, g, d as m, a as v, i as F, S as N, u as e, f as c } from "./FormNavigation-Di3Mss2W.js";
|
|
2
2
|
export {
|
|
3
3
|
i as FormNavigation,
|
|
4
4
|
t as FormNavigationActions,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
n as
|
|
8
|
-
g as
|
|
9
|
-
m as
|
|
5
|
+
s as FormNavigationContext,
|
|
6
|
+
r as FormNavigationIndicator,
|
|
7
|
+
n as FormNavigationNext,
|
|
8
|
+
g as FormNavigationPrev,
|
|
9
|
+
m as FormNavigationProgress,
|
|
10
|
+
v as FormNavigationStep,
|
|
11
|
+
F as FormNavigationSubmit,
|
|
12
|
+
N as Slot,
|
|
13
|
+
e as useFormNavigation,
|
|
14
|
+
c as useFormNavigationActions
|
|
10
15
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as o, b as t, g as s, e as m, d as e, h as F, f as i, a as n, c as A, u as y, i as g, j as u } from "./FormArray-K2YVvq1u.js";
|
|
2
|
-
import { F as x, c as N, e as d, b as C, d as I, a as c, u as p } from "./FormNavigation-
|
|
2
|
+
import { F as x, c as N, e as d, b as C, d as I, a as c, u as p } from "./FormNavigation-Di3Mss2W.js";
|
|
3
3
|
export {
|
|
4
4
|
o as FormArray,
|
|
5
5
|
t as FormArrayAddButton,
|
package/package.json
CHANGED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import { jsx as f, Fragment as C } from "react/jsx-runtime";
|
|
2
|
-
import { createContext as $, useContext as z, forwardRef as J, useState as V, useCallback as m, useImperativeHandle as K, useMemo as O, Children as L, isValidElement as U, cloneElement as W } from "react";
|
|
3
|
-
import { validateForm as Y } from "@reformer/core/validators";
|
|
4
|
-
const G = $(null);
|
|
5
|
-
function P() {
|
|
6
|
-
const e = z(G);
|
|
7
|
-
if (!e)
|
|
8
|
-
throw new Error("useFormNavigation must be used within FormNavigation");
|
|
9
|
-
return e;
|
|
10
|
-
}
|
|
11
|
-
function x({
|
|
12
|
-
component: e,
|
|
13
|
-
control: i,
|
|
14
|
-
_stepIndex: a,
|
|
15
|
-
...s
|
|
16
|
-
}) {
|
|
17
|
-
const { currentStep: o } = P();
|
|
18
|
-
return a === void 0 || o !== a ? null : /* @__PURE__ */ f(e, { control: i, ...s });
|
|
19
|
-
}
|
|
20
|
-
x.displayName = "FormNavigation.Step";
|
|
21
|
-
function M({ steps: e, children: i }) {
|
|
22
|
-
if (typeof i != "function")
|
|
23
|
-
throw new Error(
|
|
24
|
-
"FormNavigation.Indicator requires children as a render function. Example: <FormNavigation.Indicator steps={STEPS}>{({ steps }) => <YourUI />}</FormNavigation.Indicator>"
|
|
25
|
-
);
|
|
26
|
-
const { currentStep: a, totalSteps: s, completedSteps: o, goToStep: u } = P(), c = {
|
|
27
|
-
steps: e.map((t) => ({
|
|
28
|
-
...t,
|
|
29
|
-
isCurrent: a === t.number,
|
|
30
|
-
isCompleted: o.includes(t.number),
|
|
31
|
-
canNavigate: t.number === 1 || o.includes(t.number - 1)
|
|
32
|
-
})),
|
|
33
|
-
goToStep: u,
|
|
34
|
-
currentStep: a,
|
|
35
|
-
totalSteps: s,
|
|
36
|
-
completedSteps: o
|
|
37
|
-
};
|
|
38
|
-
return /* @__PURE__ */ f(C, { children: i(c) });
|
|
39
|
-
}
|
|
40
|
-
M.displayName = "FormNavigation.Indicator";
|
|
41
|
-
function j({ onSubmit: e, children: i }) {
|
|
42
|
-
if (typeof i != "function")
|
|
43
|
-
throw new Error(
|
|
44
|
-
"FormNavigation.Actions requires children as a render function. Example: <FormNavigation.Actions>{({ prev, next }) => <YourUI />}</FormNavigation.Actions>"
|
|
45
|
-
);
|
|
46
|
-
const { isFirstStep: a, isLastStep: s, isValidating: o, isSubmitting: u, goToNextStep: p, goToPreviousStep: c } = P(), t = o || u;
|
|
47
|
-
return /* @__PURE__ */ f(C, { children: i({
|
|
48
|
-
prev: {
|
|
49
|
-
onClick: c,
|
|
50
|
-
disabled: t
|
|
51
|
-
},
|
|
52
|
-
next: {
|
|
53
|
-
onClick: () => p(),
|
|
54
|
-
disabled: t
|
|
55
|
-
},
|
|
56
|
-
submit: {
|
|
57
|
-
onClick: () => e?.(),
|
|
58
|
-
disabled: t,
|
|
59
|
-
isSubmitting: u
|
|
60
|
-
},
|
|
61
|
-
isFirstStep: a,
|
|
62
|
-
isLastStep: s,
|
|
63
|
-
isValidating: o,
|
|
64
|
-
isSubmitting: u
|
|
65
|
-
}) });
|
|
66
|
-
}
|
|
67
|
-
j.displayName = "FormNavigation.Actions";
|
|
68
|
-
function B({ children: e }) {
|
|
69
|
-
if (typeof e != "function")
|
|
70
|
-
throw new Error(
|
|
71
|
-
"FormNavigation.Progress requires children as a render function. Example: <FormNavigation.Progress>{({ current, total }) => <YourUI />}</FormNavigation.Progress>"
|
|
72
|
-
);
|
|
73
|
-
const { currentStep: i, totalSteps: a, completedSteps: s, isFirstStep: o, isLastStep: u } = P(), p = {
|
|
74
|
-
current: i,
|
|
75
|
-
total: a,
|
|
76
|
-
percent: Math.round(i / a * 100),
|
|
77
|
-
completedCount: s.length,
|
|
78
|
-
isFirstStep: o,
|
|
79
|
-
isLastStep: u
|
|
80
|
-
};
|
|
81
|
-
return /* @__PURE__ */ f(C, { children: e(p) });
|
|
82
|
-
}
|
|
83
|
-
B.displayName = "FormNavigation.Progress";
|
|
84
|
-
function Q({ form: e, config: i, children: a, onStepChange: s, scrollToTop: o = !0 }, u) {
|
|
85
|
-
const p = (n) => {
|
|
86
|
-
let r = 0;
|
|
87
|
-
return L.forEach(n, (l) => {
|
|
88
|
-
if (U(l))
|
|
89
|
-
if (l.type === x)
|
|
90
|
-
r += 1;
|
|
91
|
-
else {
|
|
92
|
-
const q = l.props;
|
|
93
|
-
q.children && (r += p(q.children));
|
|
94
|
-
}
|
|
95
|
-
}), r;
|
|
96
|
-
}, c = p(a), [t, v] = V(1), [d, D] = V([]), [g, S] = V(!1), E = e.submitting.value, N = m(async () => {
|
|
97
|
-
const n = i.stepValidations[t];
|
|
98
|
-
if (!n)
|
|
99
|
-
return console.warn(`No validation schema for step ${t}`), !0;
|
|
100
|
-
S(!0);
|
|
101
|
-
try {
|
|
102
|
-
return await Y(e, n);
|
|
103
|
-
} finally {
|
|
104
|
-
S(!1);
|
|
105
|
-
}
|
|
106
|
-
}, [e, t, i.stepValidations]), F = m(async () => {
|
|
107
|
-
if (!await N())
|
|
108
|
-
return e.markAsTouched(), !1;
|
|
109
|
-
if (d.includes(t) || D((r) => [...r, t]), t < c) {
|
|
110
|
-
const r = t + 1;
|
|
111
|
-
v(r), s?.(r), o && window.scrollTo({ top: 0, behavior: "smooth" });
|
|
112
|
-
}
|
|
113
|
-
return !0;
|
|
114
|
-
}, [
|
|
115
|
-
N,
|
|
116
|
-
t,
|
|
117
|
-
d,
|
|
118
|
-
c,
|
|
119
|
-
e,
|
|
120
|
-
s,
|
|
121
|
-
o
|
|
122
|
-
]), h = m(() => {
|
|
123
|
-
if (t > 1) {
|
|
124
|
-
const n = t - 1;
|
|
125
|
-
v(n), s?.(n), o && window.scrollTo({ top: 0, behavior: "smooth" });
|
|
126
|
-
}
|
|
127
|
-
}, [t, s, o]), b = m(
|
|
128
|
-
(n) => (n === 1 || d.includes(n - 1)) && n >= 1 && n <= c ? (v(n), s?.(n), o && window.scrollTo({ top: 0, behavior: "smooth" }), !0) : !1,
|
|
129
|
-
[d, c, s, o]
|
|
130
|
-
), A = m(
|
|
131
|
-
async (n) => {
|
|
132
|
-
S(!0);
|
|
133
|
-
try {
|
|
134
|
-
return await Y(e, i.fullValidation) ? e.submit(n) : (e.markAsTouched(), null);
|
|
135
|
-
} finally {
|
|
136
|
-
S(!1);
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
[e, i.fullValidation]
|
|
140
|
-
), w = t === 1, y = t === c;
|
|
141
|
-
K(
|
|
142
|
-
u,
|
|
143
|
-
() => ({
|
|
144
|
-
currentStep: t,
|
|
145
|
-
completedSteps: d,
|
|
146
|
-
validateCurrentStep: N,
|
|
147
|
-
goToNextStep: F,
|
|
148
|
-
goToPreviousStep: h,
|
|
149
|
-
goToStep: b,
|
|
150
|
-
submit: A,
|
|
151
|
-
isFirstStep: w,
|
|
152
|
-
isLastStep: y,
|
|
153
|
-
isValidating: g
|
|
154
|
-
}),
|
|
155
|
-
[
|
|
156
|
-
t,
|
|
157
|
-
d,
|
|
158
|
-
N,
|
|
159
|
-
F,
|
|
160
|
-
h,
|
|
161
|
-
b,
|
|
162
|
-
A,
|
|
163
|
-
w,
|
|
164
|
-
y,
|
|
165
|
-
g
|
|
166
|
-
]
|
|
167
|
-
);
|
|
168
|
-
const H = O(
|
|
169
|
-
() => ({
|
|
170
|
-
// State
|
|
171
|
-
currentStep: t,
|
|
172
|
-
totalSteps: c,
|
|
173
|
-
completedSteps: d,
|
|
174
|
-
isFirstStep: w,
|
|
175
|
-
isLastStep: y,
|
|
176
|
-
isValidating: g,
|
|
177
|
-
isSubmitting: E,
|
|
178
|
-
form: e,
|
|
179
|
-
// Navigation methods
|
|
180
|
-
goToNextStep: F,
|
|
181
|
-
goToPreviousStep: h,
|
|
182
|
-
goToStep: b
|
|
183
|
-
}),
|
|
184
|
-
[
|
|
185
|
-
t,
|
|
186
|
-
c,
|
|
187
|
-
d,
|
|
188
|
-
w,
|
|
189
|
-
y,
|
|
190
|
-
g,
|
|
191
|
-
E,
|
|
192
|
-
e,
|
|
193
|
-
F,
|
|
194
|
-
h,
|
|
195
|
-
b
|
|
196
|
-
]
|
|
197
|
-
);
|
|
198
|
-
let k = 0;
|
|
199
|
-
const T = (n) => L.map(n, (r) => {
|
|
200
|
-
if (!U(r))
|
|
201
|
-
return r;
|
|
202
|
-
const l = r.props;
|
|
203
|
-
return r.type === x ? (k += 1, W(r, {
|
|
204
|
-
...l,
|
|
205
|
-
_stepIndex: k
|
|
206
|
-
// 1-based indexing
|
|
207
|
-
})) : typeof l.children == "function" ? r : l.children ? W(r, {
|
|
208
|
-
...l,
|
|
209
|
-
children: T(l.children)
|
|
210
|
-
}) : r;
|
|
211
|
-
}), R = T(a);
|
|
212
|
-
return /* @__PURE__ */ f(G.Provider, { value: H, children: R });
|
|
213
|
-
}
|
|
214
|
-
const X = J(Q), I = X;
|
|
215
|
-
I.Step = x;
|
|
216
|
-
I.Indicator = M;
|
|
217
|
-
I.Actions = j;
|
|
218
|
-
I.Progress = B;
|
|
219
|
-
export {
|
|
220
|
-
I as F,
|
|
221
|
-
x as a,
|
|
222
|
-
M as b,
|
|
223
|
-
j as c,
|
|
224
|
-
B as d,
|
|
225
|
-
G as e,
|
|
226
|
-
P as u
|
|
227
|
-
};
|