rhf-stepper 0.2.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A lightweight, headless multi-step form helper for [react-hook-form](https://react-hook-form.com). Build wizards, multi-step forms, and stepped workflows with automatic per-step validation. Bring your own UI — rhf-stepper handles the logic.
4
4
 
5
- [Documentation](https://rhf-stepper-docs-git-master-omerrkosars-projects.vercel.app/docs)
5
+ [Documentation](https://rhf-stepper-docs.vercel.app/docs)
6
6
 
7
7
  ## Installation
8
8
 
@@ -26,8 +26,8 @@ yarn add rhf-stepper
26
26
  ## Quick Start
27
27
 
28
28
  ```tsx
29
- import { useForm } from 'react-hook-form'
30
- import { Form, Step, Controller, useFormContext } from 'rhf-stepper'
29
+ import { useForm, FormProvider } from 'react-hook-form'
30
+ import { Stepper, Step, Controller, useStepper } from 'rhf-stepper'
31
31
 
32
32
  type FormValues = {
33
33
  name: string
@@ -40,36 +40,40 @@ function MyMultiStepForm() {
40
40
  const form = useForm<FormValues>()
41
41
 
42
42
  return (
43
- <Form form={form} onSubmit={(data) => console.log(data)}>
44
- {({ currentStep }) => (
45
- <>
46
- <Step>
47
- {currentStep === 0 && (
48
- <>
49
- <Controller name="name" render={({ field }) => <input {...field} placeholder="Name" />} />
50
- <Controller name="email" render={({ field }) => <input {...field} placeholder="Email" />} />
51
- </>
52
- )}
53
- </Step>
54
-
55
- <Step>
56
- {currentStep === 1 && (
57
- <>
58
- <Controller name="address" render={({ field }) => <input {...field} placeholder="Address" />} />
59
- <Controller name="city" render={({ field }) => <input {...field} placeholder="City" />} />
60
- </>
61
- )}
62
- </Step>
63
-
64
- <StepNavigation />
65
- </>
66
- )}
67
- </Form>
43
+ <FormProvider {...form}>
44
+ <form onSubmit={form.handleSubmit((data) => console.log(data))}>
45
+ <Stepper>
46
+ {({ activeStep }) => (
47
+ <>
48
+ <Step>
49
+ {activeStep === 0 && (
50
+ <>
51
+ <Controller name="name" render={({ field }) => <input {...field} placeholder="Name" />} />
52
+ <Controller name="email" render={({ field }) => <input {...field} placeholder="Email" />} />
53
+ </>
54
+ )}
55
+ </Step>
56
+
57
+ <Step>
58
+ {activeStep === 1 && (
59
+ <>
60
+ <Controller name="address" render={({ field }) => <input {...field} placeholder="Address" />} />
61
+ <Controller name="city" render={({ field }) => <input {...field} placeholder="City" />} />
62
+ </>
63
+ )}
64
+ </Step>
65
+
66
+ <StepNavigation />
67
+ </>
68
+ )}
69
+ </Stepper>
70
+ </form>
71
+ </FormProvider>
68
72
  )
69
73
  }
70
74
 
71
75
  function StepNavigation() {
72
- const { next, prev, isFirstStep, isLastStep } = useFormContext()
76
+ const { next, prev, isFirstStep, isLastStep } = useStepper()
73
77
 
74
78
  return (
75
79
  <div>
@@ -81,67 +85,63 @@ function StepNavigation() {
81
85
  }
82
86
  ```
83
87
 
84
- > **Important:** `<Step>` components must always be mounted in the tree. Conditionally render the `<Controller>` fields inside each `<Step>` based on `currentStep` to show/hide step content.
88
+ > **Important:** Do not conditionally render `<Step>` based on `activeStep`. This would break step counting and cause `isLastStep`, `next()`, and other navigation to behave incorrectly. Always keep steps mounted and conditionally render only the children inside each step.
85
89
 
86
90
  ## API Reference
87
91
 
88
- ### `<Form>`
92
+ ### `<Stepper>`
89
93
 
90
- The root component that replaces the standard `<form>` element. Manages step state and validation.
94
+ The root component that manages step state and validation. Does **not** render a `<form>` element you provide your own `<form>` and wrap with react-hook-form's `<FormProvider>`.
91
95
 
92
96
  ```tsx
93
- <Form
94
- form={form}
95
- onSubmit={handleSubmit}
96
- stepValidationMode="forward"
97
- >
98
- {children}
99
- </Form>
97
+ <FormProvider {...form}>
98
+ <form onSubmit={form.handleSubmit(handleSubmit)}>
99
+ <Stepper stepValidationMode="forward">
100
+ {children}
101
+ </Stepper>
102
+ </form>
103
+ </FormProvider>
100
104
  ```
101
105
 
102
106
  #### Props
103
107
 
104
108
  | Prop | Type | Default | Description |
105
109
  |------|------|---------|-------------|
106
- | `form` | `UseFormReturn<T>` | *required* | The form instance from `useForm()` |
107
- | `onSubmit` | `(values: T) => void` | *required* | Called with form values on valid submission |
110
+ | `form` | `UseFormReturn<T>` | - | The form instance from `useForm()`. Optional if wrapped in `<FormProvider>` |
108
111
  | `stepValidationMode` | `'forward' \| 'all' \| 'none'` | `'forward'` | When to validate step fields (see below) |
109
112
  | `children` | `ReactNode \| (context) => ReactNode` | *required* | Form content. Accepts a render function for context access |
110
- | `ref` | `Ref<HTMLFormElement>` | - | Ref forwarded to the underlying `<form>` element |
111
-
112
- All other props are passed through to the underlying `<form>` element (e.g., `className`, `id`).
113
113
 
114
114
  #### Step Validation Modes
115
115
 
116
116
  | Mode | Description |
117
117
  |------|-------------|
118
- | `'forward'` | Validates current step fields only when navigating forward (via `next()` or `setCurrentStep` to a later step) |
118
+ | `'forward'` | Validates current step fields only when navigating forward (via `next()` or `jumpTo` to a later step) |
119
119
  | `'all'` | Validates current step fields on every navigation (forward and backward) |
120
120
  | `'none'` | No automatic validation. Navigate freely between steps |
121
121
 
122
122
  #### Render Function
123
123
 
124
- When using a render function as children, you receive the full `FormContextValue`:
124
+ When using a render function as children, you receive the full `StepperContextValue`:
125
125
 
126
126
  ```tsx
127
- <Form form={form} onSubmit={handleSubmit}>
128
- {({ currentStep, isFirstStep, isLastStep, next, prev }) => (
129
- // render steps based on currentStep
127
+ <Stepper>
128
+ {({ activeStep, isFirstStep, isLastStep, next, prev }) => (
129
+ // render steps based on activeStep
130
130
  )}
131
- </Form>
131
+ </Stepper>
132
132
  ```
133
133
 
134
134
  ---
135
135
 
136
136
  ### `<Step>`
137
137
 
138
- Groups `<Controller>` fields into a logical step. Fields inside a `<Step>` are automatically registered and validated together. Each `<Step>` defines a step boundary -- conditionally render its children based on `currentStep` to control which step is visible.
138
+ Groups `<Controller>` fields into a logical step. Fields inside a `<Step>` are automatically registered and validated together. Each `<Step>` defines a step boundary conditionally render its children based on `activeStep` to control which step is visible.
139
139
 
140
- > **Important:** `<Step>` components must always be mounted in the tree. Do not conditionally render the `<Step>` itself -- only its children.
140
+ > **Important:** Do not conditionally render `<Step>` based on `activeStep`. This would break step counting and cause `isLastStep`, `next()`, and other navigation to behave incorrectly. Always keep steps mounted and conditionally render only the children inside each step. Steps **can** be conditionally rendered based on form values for dynamic forms (see [Dynamic Steps](#dynamic-steps)).
141
141
 
142
142
  ```tsx
143
143
  <Step>
144
- {currentStep === 0 && (
144
+ {activeStep === 0 && (
145
145
  <>
146
146
  <Controller name="firstName" render={({ field }) => <input {...field} />} />
147
147
  <Controller name="lastName" render={({ field }) => <input {...field} />} />
@@ -150,23 +150,6 @@ Groups `<Controller>` fields into a logical step. Fields inside a `<Step>` are a
150
150
  </Step>
151
151
  ```
152
152
 
153
- Steps can be nested for sub-step grouping:
154
-
155
- ```tsx
156
- <Step>
157
- <Step>
158
- {currentStep === 0 && (
159
- <Controller name="a" render={({ field }) => <input {...field} />} />
160
- )}
161
- </Step>
162
- <Step>
163
- {currentStep === 1 && (
164
- <Controller name="b" render={({ field }) => <input {...field} />} />
165
- )}
166
- </Step>
167
- </Step>
168
- ```
169
-
170
153
  ---
171
154
 
172
155
  ### `<Controller>`
@@ -188,43 +171,77 @@ A drop-in replacement for react-hook-form's `Controller`. It automatically regis
188
171
 
189
172
  #### Props
190
173
 
191
- Same as [react-hook-form's Controller](https://react-hook-form.com/docs/usecontroller/controller). The `control` prop is optional -- it's automatically resolved from the `<Form>` context.
174
+ Same as [react-hook-form's Controller](https://react-hook-form.com/docs/usecontroller/controller). The `control` prop is optional it's automatically resolved from `<FormProvider>`.
175
+
176
+ ---
177
+
178
+ ### `useController()`
179
+
180
+ A hook alternative to `<Controller>`. Drop-in replacement for react-hook-form's `useController` that automatically registers the field with the nearest `<Step>`.
181
+
182
+ ```tsx
183
+ import { useController } from 'rhf-stepper'
184
+
185
+ function CustomInput({ name }: { name: string }) {
186
+ const { field, fieldState } = useController({ name, rules: { required: 'Required' } })
187
+
188
+ return (
189
+ <div>
190
+ <input {...field} />
191
+ {fieldState.error && <span>{fieldState.error.message}</span>}
192
+ </div>
193
+ )
194
+ }
195
+ ```
196
+
197
+ #### Props
198
+
199
+ Same as [react-hook-form's useController](https://react-hook-form.com/docs/usecontroller).
192
200
 
193
201
  ---
194
202
 
195
- ### `useFormContext()`
203
+ ### `useStepper()`
196
204
 
197
- Hook to access the stepper state from any component inside `<Form>`.
205
+ Hook to access the stepper state from any component inside `<Stepper>`.
198
206
 
199
207
  ```tsx
200
208
  const {
201
- form,
202
- currentStep,
203
- setCurrentStep,
204
- currentStepNode,
205
- currentStepArr,
206
- validatedFields,
209
+ activeStep,
210
+ jumpTo,
211
+ fields,
212
+ validSteps,
207
213
  isFirstStep,
208
214
  isLastStep,
209
215
  next,
210
216
  prev,
211
- } = useFormContext<MyFormValues>()
217
+ } = useStepper<MyFormValues>()
212
218
  ```
213
219
 
214
- #### Return Value (`FormContextValue<T>`)
220
+ #### Return Value (`StepperContextValue<T>`)
215
221
 
216
222
  | Property | Type | Description |
217
223
  |----------|------|-------------|
218
- | `form` | `UseFormReturn<T>` | The react-hook-form instance |
219
- | `currentStep` | `number \| number[] \| null` | Current step index. `number[]` for nested steps |
220
- | `setCurrentStep` | `(step: number \| number[]) => Promise<void>` | Navigate to a specific step. Validates before navigating (based on `stepValidationMode`) |
221
- | `currentStepNode` | `StepTree \| undefined` | The current step's node in the step tree |
222
- | `currentStepArr` | `string[] \| null` | Field names registered in the current step |
223
- | `validatedFields` | `string[]` | Field names that have been validated via step navigation |
224
+ | `activeStep` | `number` | Current step index (0-based) |
225
+ | `jumpTo` | `(step: number, onLeave?) => Promise<boolean>` | Navigate to a specific step. Validates before navigating (based on `stepValidationMode`). Returns `true` if navigation succeeded |
226
+ | `fields` | `string[] \| null` | Field names registered in the current step |
227
+ | `validSteps` | `number[]` | Step indices that have passed validation |
224
228
  | `isFirstStep` | `boolean` | `true` if on the first step |
225
229
  | `isLastStep` | `boolean` | `true` if on the last step |
226
- | `next` | `() => void` | Navigate to the next step (validates current step first) |
227
- | `prev` | `() => void` | Navigate to the previous step |
230
+ | `next` | `(onLeave?) => Promise<boolean>` | Navigate to the next step. Validates current step first. Returns `true` if navigation succeeded |
231
+ | `prev` | `(onLeave?) => Promise<boolean>` | Navigate to the previous step. Returns `true` if navigation succeeded |
232
+
233
+ #### `onLeave` Callback
234
+
235
+ `next`, `prev`, and `jumpTo` accept an optional `onLeave` callback that runs **after validation passes but before the step changes**. Use it for side effects like fetching data or auto-filling fields:
236
+
237
+ ```tsx
238
+ await next(async (values) => {
239
+ // values contains only the current step's fields
240
+ const res = await fetch(`/api/lookup?zip=${values.zipCode}`)
241
+ const data = await res.json()
242
+ form.setValue('city', data.city)
243
+ })
244
+ ```
228
245
 
229
246
  ---
230
247
 
@@ -233,8 +250,8 @@ const {
233
250
  ### Basic Two-Step Form
234
251
 
235
252
  ```tsx
236
- import { useForm } from 'react-hook-form'
237
- import { Form, Step, Controller, useFormContext } from 'rhf-stepper'
253
+ import { useForm, FormProvider } from 'react-hook-form'
254
+ import { Stepper, Step, Controller, useStepper } from 'rhf-stepper'
238
255
 
239
256
  type SignupForm = {
240
257
  email: string
@@ -247,62 +264,66 @@ function SignupWizard() {
247
264
  const form = useForm<SignupForm>()
248
265
 
249
266
  return (
250
- <Form form={form} onSubmit={(data) => console.log(data)}>
251
- {({ currentStep }) => (
252
- <>
253
- <Step>
254
- {currentStep === 0 && (
255
- <>
256
- <Controller
257
- name="email"
258
- rules={{ required: 'Email is required' }}
259
- render={({ field, fieldState }) => (
260
- <div>
261
- <input {...field} type="email" placeholder="Email" />
262
- {fieldState.error && <p>{fieldState.error.message}</p>}
263
- </div>
264
- )}
265
- />
266
- <Controller
267
- name="password"
268
- rules={{ required: 'Password is required', minLength: { value: 8, message: 'Min 8 characters' } }}
269
- render={({ field, fieldState }) => (
270
- <div>
271
- <input {...field} type="password" placeholder="Password" />
272
- {fieldState.error && <p>{fieldState.error.message}</p>}
273
- </div>
274
- )}
275
- />
276
- </>
277
- )}
278
- </Step>
279
-
280
- <Step>
281
- {currentStep === 1 && (
282
- <>
283
- <Controller
284
- name="firstName"
285
- rules={{ required: 'First name is required' }}
286
- render={({ field }) => <input {...field} placeholder="First Name" />}
287
- />
288
- <Controller
289
- name="lastName"
290
- rules={{ required: 'Last name is required' }}
291
- render={({ field }) => <input {...field} placeholder="Last Name" />}
292
- />
293
- </>
294
- )}
295
- </Step>
296
-
297
- <Navigation />
298
- </>
299
- )}
300
- </Form>
267
+ <FormProvider {...form}>
268
+ <form onSubmit={form.handleSubmit((data) => console.log(data))}>
269
+ <Stepper>
270
+ {({ activeStep }) => (
271
+ <>
272
+ <Step>
273
+ {activeStep === 0 && (
274
+ <>
275
+ <Controller
276
+ name="email"
277
+ rules={{ required: 'Email is required' }}
278
+ render={({ field, fieldState }) => (
279
+ <div>
280
+ <input {...field} type="email" placeholder="Email" />
281
+ {fieldState.error && <p>{fieldState.error.message}</p>}
282
+ </div>
283
+ )}
284
+ />
285
+ <Controller
286
+ name="password"
287
+ rules={{ required: 'Password is required', minLength: { value: 8, message: 'Min 8 characters' } }}
288
+ render={({ field, fieldState }) => (
289
+ <div>
290
+ <input {...field} type="password" placeholder="Password" />
291
+ {fieldState.error && <p>{fieldState.error.message}</p>}
292
+ </div>
293
+ )}
294
+ />
295
+ </>
296
+ )}
297
+ </Step>
298
+
299
+ <Step>
300
+ {activeStep === 1 && (
301
+ <>
302
+ <Controller
303
+ name="firstName"
304
+ rules={{ required: 'First name is required' }}
305
+ render={({ field }) => <input {...field} placeholder="First Name" />}
306
+ />
307
+ <Controller
308
+ name="lastName"
309
+ rules={{ required: 'Last name is required' }}
310
+ render={({ field }) => <input {...field} placeholder="Last Name" />}
311
+ />
312
+ </>
313
+ )}
314
+ </Step>
315
+
316
+ <Navigation />
317
+ </>
318
+ )}
319
+ </Stepper>
320
+ </form>
321
+ </FormProvider>
301
322
  )
302
323
  }
303
324
 
304
325
  function Navigation() {
305
- const { next, prev, isFirstStep, isLastStep } = useFormContext()
326
+ const { next, prev, isFirstStep, isLastStep } = useStepper()
306
327
 
307
328
  return (
308
329
  <div>
@@ -318,13 +339,13 @@ function Navigation() {
318
339
 
319
340
  ```tsx
320
341
  function StepIndicator() {
321
- const { currentStep, setCurrentStep } = useFormContext()
342
+ const { activeStep, jumpTo } = useStepper()
322
343
 
323
344
  return (
324
345
  <nav>
325
- <button type="button" onClick={() => setCurrentStep(0)}>Account</button>
326
- <button type="button" onClick={() => setCurrentStep(1)}>Profile</button>
327
- <button type="button" onClick={() => setCurrentStep(2)}>Review</button>
346
+ <button type="button" onClick={() => jumpTo(0)}>Account</button>
347
+ <button type="button" onClick={() => jumpTo(1)}>Profile</button>
348
+ <button type="button" onClick={() => jumpTo(2)}>Review</button>
328
349
  </nav>
329
350
  )
330
351
  }
@@ -333,18 +354,44 @@ function StepIndicator() {
333
354
  ### Skip Validation
334
355
 
335
356
  ```tsx
336
- <Form form={form} onSubmit={handleSubmit} stepValidationMode="none">
357
+ <Stepper stepValidationMode="none">
337
358
  {/* Users can freely navigate between steps without validation */}
338
- </Form>
359
+ </Stepper>
360
+ ```
361
+
362
+ ### Dynamic Steps
363
+
364
+ `<Step>` components can be conditionally rendered based on **form values** (not `activeStep`) for dynamic forms:
365
+
366
+ ```tsx
367
+ const needsShipping = useWatch({ control: form.control, name: 'needsShipping' })
368
+
369
+ <Stepper>
370
+ {({ activeStep }) => (
371
+ <>
372
+ <Step>{activeStep === 0 && <AccountFields />}</Step>
373
+
374
+ {needsShipping && (
375
+ <Step>{activeStep === 1 && <ShippingFields />}</Step>
376
+ )}
377
+
378
+ <Step>
379
+ {activeStep === (needsShipping ? 2 : 1) && <PaymentFields />}
380
+ </Step>
381
+ </>
382
+ )}
383
+ </Stepper>
339
384
  ```
340
385
 
341
386
  ### Accessing the Form Instance
342
387
 
343
- `useFormContext` returns the full `react-hook-form` instance under the `form` property:
388
+ Since `useStepper` only returns stepper state, use react-hook-form's `useFormContext` to access the form instance:
344
389
 
345
390
  ```tsx
391
+ import { useFormContext } from 'react-hook-form'
392
+
346
393
  function ResetButton() {
347
- const { form } = useFormContext<MyFormValues>()
394
+ const form = useFormContext<MyFormValues>()
348
395
 
349
396
  return (
350
397
  <button type="button" onClick={() => form.reset()}>
@@ -358,22 +405,20 @@ function ResetButton() {
358
405
 
359
406
  ```ts
360
407
  import type {
361
- FormContextValue,
362
- FormProps,
408
+ StepperContextValue,
409
+ StepperProps,
363
410
  ControllerProps,
364
411
  ControllerRenderArgs,
365
- StepTree,
366
412
  StepValidationMode,
367
413
  } from 'rhf-stepper'
368
414
  ```
369
415
 
370
416
  | Type | Description |
371
417
  |------|-------------|
372
- | `FormContextValue<T>` | Return type of `useFormContext()` |
373
- | `FormProps<T>` | Props for the `<Form>` component |
418
+ | `StepperContextValue<T>` | Return type of `useStepper()` |
419
+ | `StepperProps<T>` | Props for the `<Stepper>` component |
374
420
  | `ControllerProps<T, N>` | Props for the `<Controller>` component |
375
421
  | `ControllerRenderArgs<T, N>` | Arguments passed to the Controller `render` function |
376
- | `StepTree` | Recursive type representing the step structure (`string \| StepTree[]`) |
377
422
  | `StepValidationMode` | `'all' \| 'forward' \| 'none'` |
378
423
 
379
424
  ## License
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ComponentProps } from 'react';
3
- import { FieldValues, FieldPath, Controller as Controller$1, ControllerRenderProps, ControllerFieldState, UseFormStateReturn, UseFormReturn } from 'react-hook-form';
3
+ import { FieldValues, FieldPath, Controller as Controller$1, ControllerRenderProps, ControllerFieldState, UseFormStateReturn, UseControllerProps, UseControllerReturn, UseFormReturn } from 'react-hook-form';
4
4
 
5
5
  type ControllerRenderArgs<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = {
6
6
  field: ControllerRenderProps<TFieldValues, TName>;
@@ -8,36 +8,33 @@ type ControllerRenderArgs<TFieldValues extends FieldValues = FieldValues, TName
8
8
  formState: UseFormStateReturn<TFieldValues>;
9
9
  };
10
10
  type ControllerProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = ComponentProps<typeof Controller$1<TFieldValues, TName>>;
11
- declare function Controller<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, control, ...rest }: ControllerProps<TFieldValues, TName>): react_jsx_runtime.JSX.Element;
11
+ declare function Controller<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, ...rest }: ControllerProps<TFieldValues, TName>): react_jsx_runtime.JSX.Element;
12
12
  declare namespace Controller {
13
13
  var displayName: string;
14
14
  }
15
15
 
16
- type StepTree = StepTree[] | string;
16
+ declare function useController<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: UseControllerProps<TFieldValues, TName>): UseControllerReturn<TFieldValues, TName>;
17
+
17
18
  type StepValidationMode = 'all' | 'forward' | 'none';
19
+ type MaybePromise<T = void> = T | Promise<T>;
18
20
 
19
- type FormContextValue<TFieldValues extends FieldValues = FieldValues> = {
20
- form: UseFormReturn<TFieldValues>;
21
- currentStep: number | number[] | null;
22
- setCurrentStep: (step: number | number[], beforeStepChange?: (values: Partial<TFieldValues>) => Promise<void>) => Promise<boolean>;
23
- currentStepNode: StepTree | undefined;
24
- currentStepArr: string[] | null;
25
- validatedFields: string[];
21
+ type StepperContextValue<TFieldValues extends FieldValues = FieldValues> = {
22
+ activeStep: number;
23
+ jumpTo: (step: number, onLeave?: (values: Partial<TFieldValues>) => MaybePromise<void>) => Promise<boolean>;
24
+ fields: string[] | null;
25
+ validSteps: number[];
26
26
  isFirstStep: boolean;
27
27
  isLastStep: boolean;
28
- next: (beforeStepChange?: (values: Partial<TFieldValues>) => Promise<void>) => Promise<boolean>;
29
- prev: (beforeStepChange?: (values: Partial<TFieldValues>) => Promise<void>) => Promise<boolean>;
28
+ next: (onLeave?: ((values: Partial<TFieldValues>) => MaybePromise<void>) | unknown) => Promise<boolean>;
29
+ prev: (onLeave?: ((values: Partial<TFieldValues>) => MaybePromise<void>) | unknown) => Promise<boolean>;
30
30
  };
31
- declare function useFormContext<TFieldValues extends FieldValues = FieldValues>(): FormContextValue<TFieldValues>;
32
- interface FormProps<TFieldValues extends FieldValues = FieldValues> extends Omit<React.ComponentProps<'form'>, 'onSubmit' | 'children'> {
33
- form: UseFormReturn<TFieldValues>;
34
- onSubmit: (values: TFieldValues) => void;
31
+ interface StepperProps<TFieldValues extends FieldValues = FieldValues> {
32
+ form?: UseFormReturn<TFieldValues>;
35
33
  stepValidationMode?: StepValidationMode;
36
- children: React.ReactNode | ((context: FormContextValue<TFieldValues>) => React.ReactNode);
34
+ children: React.ReactNode | ((context: StepperContextValue<TFieldValues>) => React.ReactNode);
37
35
  }
38
- declare const Form: <TFieldValues extends FieldValues = FieldValues>(props: FormProps<TFieldValues> & {
39
- ref?: React.Ref<HTMLFormElement>;
40
- }) => React.JSX.Element;
36
+ declare function Stepper<TFieldValues extends FieldValues = FieldValues>({ form: formProps, stepValidationMode, children }: StepperProps<TFieldValues>): react_jsx_runtime.JSX.Element;
37
+ declare function useStepper<TFieldValues extends FieldValues = FieldValues>(): StepperContextValue<TFieldValues>;
41
38
 
42
39
  declare function Step({ children }: {
43
40
  children: React.ReactNode;
@@ -46,4 +43,4 @@ declare namespace Step {
46
43
  var displayName: string;
47
44
  }
48
45
 
49
- export { Controller, type ControllerProps, type ControllerRenderArgs, Form, type FormContextValue, type FormProps, Step, type StepTree, type StepValidationMode, useFormContext };
46
+ export { Controller, type ControllerProps, type ControllerRenderArgs, Step, type StepValidationMode, Stepper, type StepperContextValue, type StepperProps, useController, useStepper };