@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.
@@ -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 { ReactNode } from 'react';
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
- /** Render function for custom UI */
44
- children: (props: FormNavigationActionsRenderProps) => ReactNode;
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
- * FormNavigation.Actions - Headless component for navigation buttons
58
+ * Hook to access Actions context (onSubmit handler)
48
59
  *
49
- * Provides all necessary props and state for building custom navigation UI.
50
- * No default UI - you build exactly what you need.
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
- * ## Render Props
53
- * - `prev` - props for Previous button (`onClick`, `disabled`)
54
- * - `next` - props for Next button (`onClick`, `disabled`)
55
- * - `submit` - props for Submit button (`onClick`, `disabled`, `isSubmitting`)
56
- * - `isFirstStep` - hide prev button on first step
57
- * - `isLastStep` - show submit instead of next on last step
58
- * - `isValidating` - show loading state during validation
59
- * - `isSubmitting` - show loading state during submission
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
- * @example Basic usage
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
- * @example With custom button component
87
- * ```tsx
88
- * <FormNavigation.Actions onSubmit={handleSubmit}>
89
- * {({ prev, next, submit, isFirstStep, isLastStep, isValidating }) => (
90
- * <ActionBar>
91
- * <ActionBar.Left>
92
- * {!isFirstStep && <IconButton icon="arrow-left" {...prev} />}
93
- * </ActionBar.Left>
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';
@@ -1,10 +1,15 @@
1
- import { F as i, c as t, e as r, b as s, d as n, a as g, u as m } from "./FormNavigation-3rg4tJyl.js";
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
- r as FormNavigationContext,
6
- s as FormNavigationIndicator,
7
- n as FormNavigationProgress,
8
- g as FormNavigationStep,
9
- m as useFormNavigation
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-3rg4tJyl.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-Di3Mss2W.js";
3
3
  export {
4
4
  o as FormArray,
5
5
  t as FormArrayAddButton,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reformer/ui",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.4",
4
4
  "description": "Headless UI components for @reformer/core - form arrays, multi-step wizards, and more",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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
- };