@trackunit/react-form-wizard 0.1.10 → 0.1.12

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
@@ -200,9 +200,9 @@ const cvaNavigationContainer = cssClassVarianceUtilities.cvaMerge(["flex", "gap-
200
200
  * The footer component for the FormWizard.
201
201
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
202
202
  */
203
- const FormWizardFooter = ({ onBack, onCancel, primaryActionLabel = "Next" }) => {
203
+ const FormWizardFooter = ({ disablePrimaryAction = false, onBack, onCancel, primaryActionLabel = "Next", }) => {
204
204
  const [t] = useTranslation();
205
- return (jsxRuntime.jsxs("div", { className: cvaFooterContainer(), children: [jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-cancel", onClick: onCancel, variant: "ghost-neutral", children: t("wizard.defaults.cancel") }), jsxRuntime.jsxs("div", { className: cvaNavigationContainer(), children: [onBack ? (jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-back", onClick: onBack, variant: "secondary", children: t("wizard.defaults.back") })) : null, jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-next", type: "submit", children: primaryActionLabel ? primaryActionLabel : t("wizard.defaults.next") })] })] }));
205
+ return (jsxRuntime.jsxs("div", { className: cvaFooterContainer(), children: [jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-cancel", onClick: onCancel, variant: "ghost-neutral", children: t("wizard.defaults.cancel") }), jsxRuntime.jsxs("div", { className: cvaNavigationContainer(), children: [onBack ? (jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-back", onClick: onBack, variant: "secondary", children: t("wizard.defaults.back") })) : null, jsxRuntime.jsx(reactComponents.Button, { dataTestId: "wizard-next", disabled: disablePrimaryAction, type: "submit", children: primaryActionLabel ? primaryActionLabel : t("wizard.defaults.next") })] })] }));
206
206
  };
207
207
 
208
208
  const cvaFormWizardHeader = cssClassVarianceUtilities.cvaMerge([
@@ -230,6 +230,7 @@ const cvaFormWizardComponentStepForm = cssClassVarianceUtilities.cvaMerge(["grid
230
230
  */
231
231
  const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, formSchema, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, }) => {
232
232
  const navigate = reactRouter.useNavigate();
233
+ const [isSubmitting, setIsSubmitting] = react.useState(false);
233
234
  const formRef = react.useRef(null);
234
235
  const [submitHandlerInternal, setSubmitHandlerInternal] = react.useState(null);
235
236
  const form = reactHookForm.useForm({
@@ -262,7 +263,12 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
262
263
  return onCancel ? onCancel() : navigate({ to: basePath, params: { stepPath: "" } });
263
264
  }, [onCancel, navigate, basePath]);
264
265
  const setSubmitHandler = react.useCallback(callback => {
265
- setSubmitHandlerInternal(() => callback);
266
+ const wrappedCallbackFunction = (fullFormStateInner) => __awaiter(void 0, void 0, void 0, function* () {
267
+ setIsSubmitting(true);
268
+ yield callback(fullFormStateInner);
269
+ setIsSubmitting(false);
270
+ });
271
+ setSubmitHandlerInternal(() => wrappedCallbackFunction);
266
272
  }, [setSubmitHandlerInternal]);
267
273
  const isEmptyStep = sharedUtils.objectKeys(form.getValues()).length === 0;
268
274
  const emptyStepSubmitHandler = react.useCallback((e) => {
@@ -274,7 +280,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
274
280
  setFullFormState(prev => (Object.assign(Object.assign({}, prev), { [stepKey]: data })));
275
281
  if (isLastStep) {
276
282
  //? This state is not updated for the submit handler below; therefore, there is duplication.
277
- submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data }));
283
+ yield (submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data })));
278
284
  }
279
285
  else if (nextStepPath) {
280
286
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
@@ -298,7 +304,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
298
304
  }) }), jsxRuntime.jsx(FormWizardFooter, { stepForms,
299
305
  onBack: previousStepPath ? () => navigate({ to: basePath, params: { stepPath: previousStepPath } }) : null,
300
306
  primaryActionLabel: isLastStep ? lastStepPrimaryActionLabel : undefined,
301
- onCancel: handleCancel })] }, String(stepKey)));
307
+ onCancel: handleCancel,
308
+ disablePrimaryAction: isSubmitting })] }, String(stepKey)));
302
309
  };
303
310
 
304
311
  const cvaFormWizardContainer = cssClassVarianceUtilities.cvaMerge(["h-full"]);
@@ -325,7 +332,9 @@ const FormWizard = ({ lastStepPrimaryActionLabel, steps, fullFormSchema, onCance
325
332
  // A possible workaround could be to type it Partial<<DeepPartial<...>>> everywhere
326
333
  // Any weakening of the type in a union would be worse and likely just push the issue forward until it hits react-hook-form
327
334
  // eslint-disable-next-line local-rules/no-typescript-assertion
328
- {});
335
+ sharedUtils.objectFromEntries(sharedUtils.objectEntries(steps)
336
+ .filter(([_, { defaultValues }]) => defaultValues)
337
+ .map(([key, { defaultValues }]) => [key, defaultValues])));
329
338
  const currentVisibleStepKey = (_a = sharedUtils.objectEntries(steps).find(([, { path }]) => subStepPath ? path === `${stepPath}/${subStepPath}` : path === stepPath)) === null || _a === void 0 ? void 0 : _a[0];
330
339
  const currentVisibleStepIndex = sharedUtils.objectKeys(steps).findIndex(key => key === currentVisibleStepKey);
331
340
  return (jsxRuntime.jsx("div", { className: cvaFormWizardContainer({ className }), "data-testid": dataTestId, children: jsxRuntime.jsxs("div", { className: cvaFormWizardLayout(), children: [jsxRuntime.jsx(FormWizardSidebar, { children: sharedUtils.objectEntries(steps)
package/index.esm.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
3
  import { Link, useNavigate, useParams } from '@tanstack/react-router';
4
- import { objectKeys, objectEntries, objectValues, objectFromEntries } from '@trackunit/shared-utils';
5
- import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
4
+ import { objectKeys, objectFromEntries, objectEntries, objectValues } from '@trackunit/shared-utils';
5
+ import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
6
6
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
7
7
  import { Icon, Button, Heading } from '@trackunit/react-components';
8
8
  import { zodResolver } from '@hookform/resolvers/zod';
@@ -196,9 +196,9 @@ const cvaNavigationContainer = cvaMerge(["flex", "gap-responsive-space"]);
196
196
  * The footer component for the FormWizard.
197
197
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
198
198
  */
199
- const FormWizardFooter = ({ onBack, onCancel, primaryActionLabel = "Next" }) => {
199
+ const FormWizardFooter = ({ disablePrimaryAction = false, onBack, onCancel, primaryActionLabel = "Next", }) => {
200
200
  const [t] = useTranslation();
201
- return (jsxs("div", { className: cvaFooterContainer(), children: [jsx(Button, { dataTestId: "wizard-cancel", onClick: onCancel, variant: "ghost-neutral", children: t("wizard.defaults.cancel") }), jsxs("div", { className: cvaNavigationContainer(), children: [onBack ? (jsx(Button, { dataTestId: "wizard-back", onClick: onBack, variant: "secondary", children: t("wizard.defaults.back") })) : null, jsx(Button, { dataTestId: "wizard-next", type: "submit", children: primaryActionLabel ? primaryActionLabel : t("wizard.defaults.next") })] })] }));
201
+ return (jsxs("div", { className: cvaFooterContainer(), children: [jsx(Button, { dataTestId: "wizard-cancel", onClick: onCancel, variant: "ghost-neutral", children: t("wizard.defaults.cancel") }), jsxs("div", { className: cvaNavigationContainer(), children: [onBack ? (jsx(Button, { dataTestId: "wizard-back", onClick: onBack, variant: "secondary", children: t("wizard.defaults.back") })) : null, jsx(Button, { dataTestId: "wizard-next", disabled: disablePrimaryAction, type: "submit", children: primaryActionLabel ? primaryActionLabel : t("wizard.defaults.next") })] })] }));
202
202
  };
203
203
 
204
204
  const cvaFormWizardHeader = cvaMerge([
@@ -226,6 +226,7 @@ const cvaFormWizardComponentStepForm = cvaMerge(["grid-rows-min-fr-min", "grid",
226
226
  */
227
227
  const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, formSchema, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, }) => {
228
228
  const navigate = useNavigate();
229
+ const [isSubmitting, setIsSubmitting] = useState(false);
229
230
  const formRef = useRef(null);
230
231
  const [submitHandlerInternal, setSubmitHandlerInternal] = useState(null);
231
232
  const form = useForm({
@@ -258,7 +259,12 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
258
259
  return onCancel ? onCancel() : navigate({ to: basePath, params: { stepPath: "" } });
259
260
  }, [onCancel, navigate, basePath]);
260
261
  const setSubmitHandler = useCallback(callback => {
261
- setSubmitHandlerInternal(() => callback);
262
+ const wrappedCallbackFunction = (fullFormStateInner) => __awaiter(void 0, void 0, void 0, function* () {
263
+ setIsSubmitting(true);
264
+ yield callback(fullFormStateInner);
265
+ setIsSubmitting(false);
266
+ });
267
+ setSubmitHandlerInternal(() => wrappedCallbackFunction);
262
268
  }, [setSubmitHandlerInternal]);
263
269
  const isEmptyStep = objectKeys(form.getValues()).length === 0;
264
270
  const emptyStepSubmitHandler = useCallback((e) => {
@@ -270,7 +276,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
270
276
  setFullFormState(prev => (Object.assign(Object.assign({}, prev), { [stepKey]: data })));
271
277
  if (isLastStep) {
272
278
  //? This state is not updated for the submit handler below; therefore, there is duplication.
273
- submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data }));
279
+ yield (submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data })));
274
280
  }
275
281
  else if (nextStepPath) {
276
282
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
@@ -294,7 +300,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
294
300
  }) }), jsx(FormWizardFooter, { stepForms,
295
301
  onBack: previousStepPath ? () => navigate({ to: basePath, params: { stepPath: previousStepPath } }) : null,
296
302
  primaryActionLabel: isLastStep ? lastStepPrimaryActionLabel : undefined,
297
- onCancel: handleCancel })] }, String(stepKey)));
303
+ onCancel: handleCancel,
304
+ disablePrimaryAction: isSubmitting })] }, String(stepKey)));
298
305
  };
299
306
 
300
307
  const cvaFormWizardContainer = cvaMerge(["h-full"]);
@@ -321,7 +328,9 @@ const FormWizard = ({ lastStepPrimaryActionLabel, steps, fullFormSchema, onCance
321
328
  // A possible workaround could be to type it Partial<<DeepPartial<...>>> everywhere
322
329
  // Any weakening of the type in a union would be worse and likely just push the issue forward until it hits react-hook-form
323
330
  // eslint-disable-next-line local-rules/no-typescript-assertion
324
- {});
331
+ objectFromEntries(objectEntries(steps)
332
+ .filter(([_, { defaultValues }]) => defaultValues)
333
+ .map(([key, { defaultValues }]) => [key, defaultValues])));
325
334
  const currentVisibleStepKey = (_a = objectEntries(steps).find(([, { path }]) => subStepPath ? path === `${stepPath}/${subStepPath}` : path === stepPath)) === null || _a === void 0 ? void 0 : _a[0];
326
335
  const currentVisibleStepIndex = objectKeys(steps).findIndex(key => key === currentVisibleStepKey);
327
336
  return (jsx("div", { className: cvaFormWizardContainer({ className }), "data-testid": dataTestId, children: jsxs("div", { className: cvaFormWizardLayout(), children: [jsx(FormWizardSidebar, { children: objectEntries(steps)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-wizard",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {
@@ -1,7 +1,7 @@
1
1
  import { RegisteredRouter, RouteIds } from "@tanstack/react-router";
2
2
  import { CommonProps } from "@trackunit/react-components";
3
3
  import { ReactNode } from "react";
4
- import { UseFormReturn } from "react-hook-form";
4
+ import { DeepPartial, UseFormReturn } from "react-hook-form";
5
5
  import { AnyZodObject, SomeZodObject, z } from "zod";
6
6
  export type StepState = "active" | "done" | "invalid" | "disabled" | "ready";
7
7
  export type StepDefinitions<TFullSchema extends AnyZodObject> = {
@@ -22,6 +22,7 @@ interface DefinedStep<TStepSchema extends TFullSchemaValue[keyof TFullSchemaValu
22
22
  component: (props: StepComponentPropsInner<TStepSchema, TFullSchemaValue>) => React.ReactNode;
23
23
  parent?: keyof TFullSchemaValue;
24
24
  shouldRender?: (fullFormState: Partial<TFullSchemaValue>) => boolean;
25
+ defaultValues?: DeepPartial<TStepSchema>;
25
26
  }
26
27
  export type StepComponentProps<TFullSchemaHook extends () => AnyZodObject, TStepKey extends keyof z.TypeOf<ReturnType<TFullSchemaHook>>> = StepComponentPropsInner<z.TypeOf<ReturnType<TFullSchemaHook>>[TStepKey], z.TypeOf<ReturnType<TFullSchemaHook>>>;
27
28
  export type ComponentStepDefinitions<TFullSchema extends AnyZodObject> = {
@@ -4,10 +4,11 @@ interface FormWizardFooterProps extends CommonProps {
4
4
  primaryActionLabel?: string;
5
5
  onCancel: () => void;
6
6
  onBack: (() => void) | null;
7
+ disablePrimaryAction?: boolean;
7
8
  }
8
9
  /**
9
10
  * The footer component for the FormWizard.
10
11
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
11
12
  */
12
- export declare const FormWizardFooter: ({ onBack, onCancel, primaryActionLabel }: FormWizardFooterProps) => JSX.Element;
13
+ export declare const FormWizardFooter: ({ disablePrimaryAction, onBack, onCancel, primaryActionLabel, }: FormWizardFooterProps) => JSX.Element;
13
14
  export {};