@trackunit/react-form-wizard 0.1.105 → 0.1.106
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/index.cjs.js +56 -5
- package/index.esm.js +56 -5
- package/package.json +1 -1
- package/src/FormWizard/useFormWizard.d.ts +52 -1
package/index.cjs.js
CHANGED
|
@@ -263,9 +263,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
|
|
|
263
263
|
}, [form.formState.isValid, setStepStates, stepKey]);
|
|
264
264
|
const isLastStep = nextStepPath === null;
|
|
265
265
|
const handleCancel = react.useCallback(() => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}, [onCancel, navigate, basePath]);
|
|
266
|
+
return onCancel ? onCancel() : navigate({ to: "../../" });
|
|
267
|
+
}, [onCancel, navigate]);
|
|
269
268
|
const setSubmitHandler = react.useCallback(callback => {
|
|
270
269
|
const wrappedCallbackFunction = (fullFormStateInner) => __awaiter(void 0, void 0, void 0, function* () {
|
|
271
270
|
setIsSubmitting(true);
|
|
@@ -309,7 +308,6 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
|
|
|
309
308
|
const handleSubmit = react.useMemo(() => {
|
|
310
309
|
return isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler;
|
|
311
310
|
}, [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
|
|
312
|
-
// TODO Replace with hoooooook
|
|
313
311
|
react.useEffect(() => {
|
|
314
312
|
// submit on cmd/ctrl + enter, always
|
|
315
313
|
const handleKeyDown = (event) => {
|
|
@@ -355,6 +353,7 @@ const cvaStepContainer = cssClassVarianceUtilities.cvaMerge(["h-full", "grid", "
|
|
|
355
353
|
* Use the useFormWizard hook to generate the props for this component.
|
|
356
354
|
*/
|
|
357
355
|
const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }) => {
|
|
356
|
+
const navigate = reactRouter.useNavigate();
|
|
358
357
|
const { stepPath, subStepPath } = reactRouter.useParams({ strict: false });
|
|
359
358
|
const [stepStates, setStepStates] = react.useState({});
|
|
360
359
|
const [stepForms, setStepForms] = react.useState({});
|
|
@@ -366,6 +365,12 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
|
|
|
366
365
|
sharedUtils.objectFromEntries(sharedUtils.objectEntries(steps)
|
|
367
366
|
.filter(([_, { defaultValues }]) => defaultValues)
|
|
368
367
|
.map(([key, { defaultValues }]) => [key, defaultValues])));
|
|
368
|
+
// If URL does not match a key from the schema, navigate to the first step
|
|
369
|
+
const firstSchemaKey = String(sharedUtils.objectKeys(fullFormSchema.shape)[0]);
|
|
370
|
+
const keyToCheck = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
|
|
371
|
+
if (fullFormSchema.shape[keyToCheck] === undefined) {
|
|
372
|
+
navigate({ to: basePath, params: { stepPath: firstSchemaKey } });
|
|
373
|
+
}
|
|
369
374
|
const currentVisibleStepKey = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
|
|
370
375
|
const currentVisibleStepIndex = sharedUtils.objectKeys(steps)
|
|
371
376
|
.filter(key => {
|
|
@@ -464,7 +469,53 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
|
|
|
464
469
|
};
|
|
465
470
|
|
|
466
471
|
/**
|
|
467
|
-
*
|
|
472
|
+
* Generates the props for rendering a Form Wizard component.
|
|
473
|
+
* This hook processes the provided step definitions and form schema to prepare the necessary props for the Form Wizard component.
|
|
474
|
+
*
|
|
475
|
+
* @param props Configuration options for the Form Wizard component.
|
|
476
|
+
* @param props.fullFormSchema The Zod schema for the entire form.
|
|
477
|
+
* @param props.lastStepPrimaryActionLabel Label for the primary action button on the last step.
|
|
478
|
+
* @param props.onCancel Callback to execute when canceling the form submission. Defaults to navigating to the parent route.
|
|
479
|
+
* @param props.basePath Base path for routing within the form wizard.
|
|
480
|
+
* @param props.steps Definitions for each step in the form wizard. Keys are used as path and a slash is used to define a substep.
|
|
481
|
+
* @param props.isEdit Indicates whether the form is being edited or created. If the step has a default value, it is considered valid when editing.
|
|
482
|
+
* @example
|
|
483
|
+
* ```
|
|
484
|
+
* typescript
|
|
485
|
+
* import { useFormWizard } from './path/to/useFormWizard';
|
|
486
|
+
* const { steps,...wizardProps } = useFormWizard({
|
|
487
|
+
* fullFormSchema: useYourZodSchema(),
|
|
488
|
+
* lastStepPrimaryActionLabel: 'Finish',
|
|
489
|
+
* basePath: '/your-base-path/$stepPath',
|
|
490
|
+
* steps: {
|
|
491
|
+
* entry: {
|
|
492
|
+
* title: "Add your thing",
|
|
493
|
+
* description: Choose how to add your thing,
|
|
494
|
+
* sidebarDescription: Choose how to add your thing,
|
|
495
|
+
* defaultValues: { entryMethod: "upload" },
|
|
496
|
+
* component: stepProps => <EntryMethodStep {...stepProps} />,
|
|
497
|
+
* },
|
|
498
|
+
* "entry/manual": {
|
|
499
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "manual",
|
|
500
|
+
* title: "Type your thing",
|
|
501
|
+
* description: "Manually type your thing",
|
|
502
|
+
* component: stepProps => <ManualStep {...stepProps} />,
|
|
503
|
+
* },
|
|
504
|
+
* "entry/upload": {
|
|
505
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "upload",
|
|
506
|
+
* title: "Upload your thing",
|
|
507
|
+
* description: "Upload a spreadsheet thing",
|
|
508
|
+
* component: stepProps => <UploadStep {...stepProps} />,
|
|
509
|
+
* },
|
|
510
|
+
* review: {
|
|
511
|
+
* title: "Review & Save",
|
|
512
|
+
* description: "Make sure everythings looks alright",
|
|
513
|
+
* sidebarDescription: "Make sure everythings looks alright",
|
|
514
|
+
* component: stepProps => <ReviewSaveStep {...stepProps} />,
|
|
515
|
+
* },
|
|
516
|
+
* },
|
|
517
|
+
* ```
|
|
518
|
+
});
|
|
468
519
|
*/
|
|
469
520
|
const useFormWizard = (props) => {
|
|
470
521
|
return react.useMemo(() => (Object.assign(Object.assign({}, props), {
|
package/index.esm.js
CHANGED
|
@@ -259,9 +259,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
|
|
|
259
259
|
}, [form.formState.isValid, setStepStates, stepKey]);
|
|
260
260
|
const isLastStep = nextStepPath === null;
|
|
261
261
|
const handleCancel = useCallback(() => {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}, [onCancel, navigate, basePath]);
|
|
262
|
+
return onCancel ? onCancel() : navigate({ to: "../../" });
|
|
263
|
+
}, [onCancel, navigate]);
|
|
265
264
|
const setSubmitHandler = useCallback(callback => {
|
|
266
265
|
const wrappedCallbackFunction = (fullFormStateInner) => __awaiter(void 0, void 0, void 0, function* () {
|
|
267
266
|
setIsSubmitting(true);
|
|
@@ -305,7 +304,6 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
|
|
|
305
304
|
const handleSubmit = useMemo(() => {
|
|
306
305
|
return isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler;
|
|
307
306
|
}, [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
|
|
308
|
-
// TODO Replace with hoooooook
|
|
309
307
|
useEffect(() => {
|
|
310
308
|
// submit on cmd/ctrl + enter, always
|
|
311
309
|
const handleKeyDown = (event) => {
|
|
@@ -351,6 +349,7 @@ const cvaStepContainer = cvaMerge(["h-full", "grid", "bg-white", "overflow-hidde
|
|
|
351
349
|
* Use the useFormWizard hook to generate the props for this component.
|
|
352
350
|
*/
|
|
353
351
|
const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }) => {
|
|
352
|
+
const navigate = useNavigate();
|
|
354
353
|
const { stepPath, subStepPath } = useParams({ strict: false });
|
|
355
354
|
const [stepStates, setStepStates] = useState({});
|
|
356
355
|
const [stepForms, setStepForms] = useState({});
|
|
@@ -362,6 +361,12 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
|
|
|
362
361
|
objectFromEntries(objectEntries(steps)
|
|
363
362
|
.filter(([_, { defaultValues }]) => defaultValues)
|
|
364
363
|
.map(([key, { defaultValues }]) => [key, defaultValues])));
|
|
364
|
+
// If URL does not match a key from the schema, navigate to the first step
|
|
365
|
+
const firstSchemaKey = String(objectKeys(fullFormSchema.shape)[0]);
|
|
366
|
+
const keyToCheck = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
|
|
367
|
+
if (fullFormSchema.shape[keyToCheck] === undefined) {
|
|
368
|
+
navigate({ to: basePath, params: { stepPath: firstSchemaKey } });
|
|
369
|
+
}
|
|
365
370
|
const currentVisibleStepKey = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
|
|
366
371
|
const currentVisibleStepIndex = objectKeys(steps)
|
|
367
372
|
.filter(key => {
|
|
@@ -460,7 +465,53 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
|
|
|
460
465
|
};
|
|
461
466
|
|
|
462
467
|
/**
|
|
463
|
-
*
|
|
468
|
+
* Generates the props for rendering a Form Wizard component.
|
|
469
|
+
* This hook processes the provided step definitions and form schema to prepare the necessary props for the Form Wizard component.
|
|
470
|
+
*
|
|
471
|
+
* @param props Configuration options for the Form Wizard component.
|
|
472
|
+
* @param props.fullFormSchema The Zod schema for the entire form.
|
|
473
|
+
* @param props.lastStepPrimaryActionLabel Label for the primary action button on the last step.
|
|
474
|
+
* @param props.onCancel Callback to execute when canceling the form submission. Defaults to navigating to the parent route.
|
|
475
|
+
* @param props.basePath Base path for routing within the form wizard.
|
|
476
|
+
* @param props.steps Definitions for each step in the form wizard. Keys are used as path and a slash is used to define a substep.
|
|
477
|
+
* @param props.isEdit Indicates whether the form is being edited or created. If the step has a default value, it is considered valid when editing.
|
|
478
|
+
* @example
|
|
479
|
+
* ```
|
|
480
|
+
* typescript
|
|
481
|
+
* import { useFormWizard } from './path/to/useFormWizard';
|
|
482
|
+
* const { steps,...wizardProps } = useFormWizard({
|
|
483
|
+
* fullFormSchema: useYourZodSchema(),
|
|
484
|
+
* lastStepPrimaryActionLabel: 'Finish',
|
|
485
|
+
* basePath: '/your-base-path/$stepPath',
|
|
486
|
+
* steps: {
|
|
487
|
+
* entry: {
|
|
488
|
+
* title: "Add your thing",
|
|
489
|
+
* description: Choose how to add your thing,
|
|
490
|
+
* sidebarDescription: Choose how to add your thing,
|
|
491
|
+
* defaultValues: { entryMethod: "upload" },
|
|
492
|
+
* component: stepProps => <EntryMethodStep {...stepProps} />,
|
|
493
|
+
* },
|
|
494
|
+
* "entry/manual": {
|
|
495
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "manual",
|
|
496
|
+
* title: "Type your thing",
|
|
497
|
+
* description: "Manually type your thing",
|
|
498
|
+
* component: stepProps => <ManualStep {...stepProps} />,
|
|
499
|
+
* },
|
|
500
|
+
* "entry/upload": {
|
|
501
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "upload",
|
|
502
|
+
* title: "Upload your thing",
|
|
503
|
+
* description: "Upload a spreadsheet thing",
|
|
504
|
+
* component: stepProps => <UploadStep {...stepProps} />,
|
|
505
|
+
* },
|
|
506
|
+
* review: {
|
|
507
|
+
* title: "Review & Save",
|
|
508
|
+
* description: "Make sure everythings looks alright",
|
|
509
|
+
* sidebarDescription: "Make sure everythings looks alright",
|
|
510
|
+
* component: stepProps => <ReviewSaveStep {...stepProps} />,
|
|
511
|
+
* },
|
|
512
|
+
* },
|
|
513
|
+
* ```
|
|
514
|
+
});
|
|
464
515
|
*/
|
|
465
516
|
const useFormWizard = (props) => {
|
|
466
517
|
return useMemo(() => (Object.assign(Object.assign({}, props), {
|
package/package.json
CHANGED
|
@@ -30,6 +30,11 @@ export interface FromWizardComponentProps<TFullSchema extends AnyZodObject, TCom
|
|
|
30
30
|
steps: TComponentStepDefinitions;
|
|
31
31
|
}
|
|
32
32
|
export type StringWithStepKey<TPath> = TPath extends `${infer _Prefix}/$stepPath` ? TPath : never;
|
|
33
|
+
/**
|
|
34
|
+
* The main props interface for the useFormWizard hook.
|
|
35
|
+
* This interface contains the full configuration needed
|
|
36
|
+
* for the Hook to generate the props for the wizard component.
|
|
37
|
+
*/
|
|
33
38
|
export interface UseFormWizardProps<TFullSchema extends SomeZodObject, TStepDefinitions extends StepDefinitions<TFullSchema>> {
|
|
34
39
|
fullFormSchema: TFullSchema;
|
|
35
40
|
lastStepPrimaryActionLabel: string;
|
|
@@ -39,7 +44,53 @@ export interface UseFormWizardProps<TFullSchema extends SomeZodObject, TStepDefi
|
|
|
39
44
|
isEdit?: boolean;
|
|
40
45
|
}
|
|
41
46
|
/**
|
|
42
|
-
*
|
|
47
|
+
* Generates the props for rendering a Form Wizard component.
|
|
48
|
+
* This hook processes the provided step definitions and form schema to prepare the necessary props for the Form Wizard component.
|
|
49
|
+
*
|
|
50
|
+
* @param props Configuration options for the Form Wizard component.
|
|
51
|
+
* @param props.fullFormSchema The Zod schema for the entire form.
|
|
52
|
+
* @param props.lastStepPrimaryActionLabel Label for the primary action button on the last step.
|
|
53
|
+
* @param props.onCancel Callback to execute when canceling the form submission. Defaults to navigating to the parent route.
|
|
54
|
+
* @param props.basePath Base path for routing within the form wizard.
|
|
55
|
+
* @param props.steps Definitions for each step in the form wizard. Keys are used as path and a slash is used to define a substep.
|
|
56
|
+
* @param props.isEdit Indicates whether the form is being edited or created. If the step has a default value, it is considered valid when editing.
|
|
57
|
+
* @example
|
|
58
|
+
* ```
|
|
59
|
+
* typescript
|
|
60
|
+
* import { useFormWizard } from './path/to/useFormWizard';
|
|
61
|
+
* const { steps,...wizardProps } = useFormWizard({
|
|
62
|
+
* fullFormSchema: useYourZodSchema(),
|
|
63
|
+
* lastStepPrimaryActionLabel: 'Finish',
|
|
64
|
+
* basePath: '/your-base-path/$stepPath',
|
|
65
|
+
* steps: {
|
|
66
|
+
* entry: {
|
|
67
|
+
* title: "Add your thing",
|
|
68
|
+
* description: Choose how to add your thing,
|
|
69
|
+
* sidebarDescription: Choose how to add your thing,
|
|
70
|
+
* defaultValues: { entryMethod: "upload" },
|
|
71
|
+
* component: stepProps => <EntryMethodStep {...stepProps} />,
|
|
72
|
+
* },
|
|
73
|
+
* "entry/manual": {
|
|
74
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "manual",
|
|
75
|
+
* title: "Type your thing",
|
|
76
|
+
* description: "Manually type your thing",
|
|
77
|
+
* component: stepProps => <ManualStep {...stepProps} />,
|
|
78
|
+
* },
|
|
79
|
+
* "entry/upload": {
|
|
80
|
+
* shouldRender: fullFormState => fullFormState.entry?.entryMethod === "upload",
|
|
81
|
+
* title: "Upload your thing",
|
|
82
|
+
* description: "Upload a spreadsheet thing",
|
|
83
|
+
* component: stepProps => <UploadStep {...stepProps} />,
|
|
84
|
+
* },
|
|
85
|
+
* review: {
|
|
86
|
+
* title: "Review & Save",
|
|
87
|
+
* description: "Make sure everythings looks alright",
|
|
88
|
+
* sidebarDescription: "Make sure everythings looks alright",
|
|
89
|
+
* component: stepProps => <ReviewSaveStep {...stepProps} />,
|
|
90
|
+
* },
|
|
91
|
+
* },
|
|
92
|
+
* ```
|
|
93
|
+
});
|
|
43
94
|
*/
|
|
44
95
|
export declare const useFormWizard: <TStepDefinition extends StepDefinitions<TFullSchema>, TFullSchema extends AnyZodObject>(props: UseFormWizardProps<TFullSchema, TStepDefinition>) => FromWizardComponentProps<TFullSchema, StepDefinitions<TFullSchema>>;
|
|
45
96
|
export {};
|