@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 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
- // TODO: Get previous path from before wizard the wizard was started
267
- return onCancel ? onCancel() : navigate({ to: basePath, params: { stepPath: "" } });
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
- * A hook to generate the props for the FormWizard component.
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
- // TODO: Get previous path from before wizard the wizard was started
263
- return onCancel ? onCancel() : navigate({ to: basePath, params: { stepPath: "" } });
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
- * A hook to generate the props for the FormWizard component.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-wizard",
3
- "version": "0.1.105",
3
+ "version": "0.1.106",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {
@@ -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
- * A hook to generate the props for the FormWizard component.
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 {};