@trackunit/react-form-wizard 0.1.103 → 0.1.105

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
@@ -233,12 +233,12 @@ const cvaFormWizardComponentStepForm = cssClassVarianceUtilities.cvaMerge(["grid
233
233
  * A wrapper component used by the FormWizard component to render each step.
234
234
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
235
235
  */
236
- const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, formSchema, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }) => {
236
+ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }) => {
237
237
  const navigate = reactRouter.useNavigate();
238
238
  const [isSubmitting, setIsSubmitting] = react.useState(false);
239
239
  const [submitHandlerInternal, setSubmitHandlerInternal] = react.useState(null);
240
240
  const form = reactHookForm.useForm({
241
- resolver: zod.zodResolver(formSchema),
241
+ resolver: zod.zodResolver(fullFormSchema.shape[stepKey]),
242
242
  mode: "all",
243
243
  defaultValues: fullFormState[stepKey],
244
244
  });
@@ -280,6 +280,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
280
280
  submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(fullFormState);
281
281
  }
282
282
  else if (nextStepPath) {
283
+ // eslint-disable-next-line local-rules/no-typescript-assertion
283
284
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
284
285
  }
285
286
  }, [basePath, fullFormState, isLastStep, navigate, nextStepPath, submitHandlerInternal]);
@@ -291,6 +292,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
291
292
  yield (submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data })));
292
293
  }
293
294
  else if (nextStepPath) {
295
+ // eslint-disable-next-line local-rules/no-typescript-assertion
294
296
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
295
297
  }
296
298
  })), [
@@ -304,7 +306,10 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
304
306
  stepKey,
305
307
  submitHandlerInternal,
306
308
  ]);
307
- const handleSubmit = react.useMemo(() => (isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler), [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
309
+ const handleSubmit = react.useMemo(() => {
310
+ return isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler;
311
+ }, [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
312
+ // TODO Replace with hoooooook
308
313
  react.useEffect(() => {
309
314
  // submit on cmd/ctrl + enter, always
310
315
  const handleKeyDown = (event) => {
@@ -327,7 +332,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
327
332
  setSubmitHandler: isLastStep ? setSubmitHandler : null,
328
333
  }) })) }), jsxRuntime.jsx(FormWizardFooter, { stepForms,
329
334
  onBack: previousStepPath
330
- ? () => navigate({ to: basePath, params: { stepPath: previousStepPath } })
335
+ ? // eslint-disable-next-line local-rules/no-typescript-assertion
336
+ () => navigate({ to: basePath, params: { stepPath: previousStepPath } })
331
337
  : null,
332
338
  primaryActionLabel: isLastStep ? lastStepPrimaryActionLabel : undefined,
333
339
  onCancel: handleCancel,
@@ -349,7 +355,6 @@ const cvaStepContainer = cssClassVarianceUtilities.cvaMerge(["h-full", "grid", "
349
355
  * Use the useFormWizard hook to generate the props for this component.
350
356
  */
351
357
  const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }) => {
352
- var _a;
353
358
  const { stepPath, subStepPath } = reactRouter.useParams({ strict: false });
354
359
  const [stepStates, setStepStates] = react.useState({});
355
360
  const [stepForms, setStepForms] = react.useState({});
@@ -361,21 +366,33 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
361
366
  sharedUtils.objectFromEntries(sharedUtils.objectEntries(steps)
362
367
  .filter(([_, { defaultValues }]) => defaultValues)
363
368
  .map(([key, { defaultValues }]) => [key, defaultValues])));
364
- const currentVisibleStepKey = (_a = sharedUtils.objectEntries(steps).find(([, { path }]) => subStepPath ? path === `${stepPath}/${subStepPath}` : path === stepPath)) === null || _a === void 0 ? void 0 : _a[0];
369
+ const currentVisibleStepKey = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
365
370
  const currentVisibleStepIndex = sharedUtils.objectKeys(steps)
366
- .filter(key => { var _a, _b, _c; return (_c = (_b = (_a = steps[key]).shouldRender) === null || _b === void 0 ? void 0 : _b.call(_a, fullFormState)) !== null && _c !== void 0 ? _c : true; })
371
+ .filter(key => {
372
+ var _a;
373
+ const step = steps[key];
374
+ return hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true;
375
+ })
367
376
  .findIndex(key => key === currentVisibleStepKey);
377
+ /**
378
+ * Asserts that step has a shouldRender.
379
+ * Is a workaround because I can't for the life of me get it to look up the step by a correctly typed
380
+ * template literal key of TComponentStepDefinitions and infer that it has a shouldRender automatically.👎
381
+ */
382
+ function hasShouldRenderProperty(obj) {
383
+ // TODO: remove this check if we can figure out a way to make TypeScript infer the type correctly
384
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, local-rules/no-typescript-assertion
385
+ return typeof obj.shouldRender === "function";
386
+ }
368
387
  return (jsxRuntime.jsx("div", { className: cvaFormWizardContainer({ className }), "data-testid": dataTestId, children: jsxRuntime.jsxs("div", { className: cvaFormWizardLayout(), children: [jsxRuntime.jsx(FormWizardSidebar, { children: sharedUtils.objectEntries(steps)
369
- .filter(([_, step]) => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })
370
- .map(([key, { path, title, sidebarDescription, parent, defaultValues }], index) => {
388
+ .filter(([_, step]) => { var _a; return (hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true); })
389
+ .map(([key, { title, sidebarDescription, defaultValues }], index) => {
371
390
  const isPastStep = index < currentVisibleStepIndex;
372
391
  const isFutureStep = index > currentVisibleStepIndex;
373
392
  const isCurrentStep = key === currentVisibleStepKey;
374
393
  const hasDefaultValue = defaultValues !== undefined;
375
- const isSubStep = parent !== undefined;
376
- const onlyParentSteps = sharedUtils.objectEntries(steps)
377
- .filter(([_, step]) => step.parent === undefined)
378
- .map(([k]) => k);
394
+ const isSubStep = key.toString().includes("/");
395
+ const rootSteps = sharedUtils.objectKeys(steps).filter(k => !k.toString().includes("/"));
379
396
  const previousStepKey = sharedUtils.objectKeys(steps)[index - 1];
380
397
  const stepState = () => {
381
398
  if (isCurrentStep) {
@@ -395,9 +412,10 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
395
412
  if (isFutureStep) {
396
413
  return sharedUtils.objectKeys(steps)
397
414
  .filter((stepKey, stepIndex) => {
398
- var _a, _b;
399
- return stepIndex < index && steps[stepKey].shouldRender
400
- ? (_b = (_a = steps[stepKey]).shouldRender) === null || _b === void 0 ? void 0 : _b.call(_a, fullFormState)
415
+ var _a;
416
+ const step = steps[stepKey];
417
+ return stepIndex < index && hasShouldRenderProperty(step)
418
+ ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)
401
419
  : true;
402
420
  })
403
421
  .every((pastStepKey) => stepStates[pastStepKey] === "valid")
@@ -408,7 +426,7 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
408
426
  };
409
427
  return (jsxRuntime.jsx(FormWizardSidebarStep, { key: String(key),
410
428
  state: stepState(),
411
- stepNumber: isSubStep ? undefined : onlyParentSteps.indexOf(key) + 1,
429
+ stepNumber: isSubStep ? undefined : rootSteps.indexOf(key) + 1,
412
430
  title,
413
431
  onNavigate: () => {
414
432
  previousStepKey &&
@@ -418,20 +436,19 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
418
436
  });
419
437
  },
420
438
  basePath,
421
- path: path,
439
+ path: String(key),
422
440
  subTitle: sidebarDescription,
423
441
  isSubStep }));
424
442
  }) }), jsxRuntime.jsx("div", { className: cvaStepContainer(), children: sharedUtils.objectEntries(steps)
425
- .filter(([_, step]) => {
426
- var _a, _b;
427
- return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true;
428
- })
443
+ .filter(([_, step]) => { var _a; return (hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true); })
429
444
  .map(([stepKey, props], index) => {
430
445
  var _a, _b, _c, _d;
431
- return (subStepPath ? props.path === `${stepPath}/${subStepPath}` : props.path === stepPath) ? (jsxRuntime.jsx(FormWizardStepWrapper, Object.assign({}, props, {
432
- // eslint-disable-next-line local-rules/no-typescript-assertion
433
- formSchema: props.formSchema, // TODO: FIX THIS string | number | symbol
434
- basePath,
446
+ const entriesOfRenderableSteps = sharedUtils.objectEntries(steps).filter(stepEntry => {
447
+ var _a;
448
+ const step = stepEntry[1];
449
+ return hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true;
450
+ });
451
+ return currentVisibleStepKey === stepKey ? (jsxRuntime.jsx(FormWizardStepWrapper, Object.assign({}, props, { basePath,
435
452
  stepKey: stepKey.toString(), // TODO: .toString() is a workaround
436
453
  stepForms,
437
454
  setStepForms,
@@ -441,8 +458,8 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
441
458
  setStepStates,
442
459
  fullFormSchema,
443
460
  lastStepPrimaryActionLabel,
444
- nextStepPath: (_b = (_a = sharedUtils.objectValues(steps).filter(step => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })[index + 1]) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : null,
445
- previousStepPath: (_d = (_c = sharedUtils.objectValues(steps).filter(step => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })[index - 1]) === null || _c === void 0 ? void 0 : _c.path) !== null && _d !== void 0 ? _d : null }), stepKey.toString())) : null;
461
+ nextStepPath: (_b = (_a = entriesOfRenderableSteps[index + 1]) === null || _a === void 0 ? void 0 : _a[0].toString()) !== null && _b !== void 0 ? _b : null,
462
+ previousStepPath: (_d = (_c = entriesOfRenderableSteps[index - 1]) === null || _c === void 0 ? void 0 : _c[0].toString()) !== null && _d !== void 0 ? _d : null }), stepKey.toString())) : null;
446
463
  }) })] }) }));
447
464
  };
448
465
 
package/index.esm.js CHANGED
@@ -1,7 +1,7 @@
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, objectFromEntries, objectEntries, objectValues } from '@trackunit/shared-utils';
4
+ import { objectKeys, objectFromEntries, objectEntries } from '@trackunit/shared-utils';
5
5
  import { useState, 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';
@@ -229,12 +229,12 @@ const cvaFormWizardComponentStepForm = cvaMerge(["grid-rows-min-fr-min", "grid",
229
229
  * A wrapper component used by the FormWizard component to render each step.
230
230
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
231
231
  */
232
- const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, formSchema, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }) => {
232
+ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, component, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }) => {
233
233
  const navigate = useNavigate();
234
234
  const [isSubmitting, setIsSubmitting] = useState(false);
235
235
  const [submitHandlerInternal, setSubmitHandlerInternal] = useState(null);
236
236
  const form = useForm({
237
- resolver: zodResolver(formSchema),
237
+ resolver: zodResolver(fullFormSchema.shape[stepKey]),
238
238
  mode: "all",
239
239
  defaultValues: fullFormState[stepKey],
240
240
  });
@@ -276,6 +276,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
276
276
  submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(fullFormState);
277
277
  }
278
278
  else if (nextStepPath) {
279
+ // eslint-disable-next-line local-rules/no-typescript-assertion
279
280
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
280
281
  }
281
282
  }, [basePath, fullFormState, isLastStep, navigate, nextStepPath, submitHandlerInternal]);
@@ -287,6 +288,7 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
287
288
  yield (submitHandlerInternal === null || submitHandlerInternal === void 0 ? void 0 : submitHandlerInternal(Object.assign(Object.assign({}, fullFormState), { [stepKey]: data })));
288
289
  }
289
290
  else if (nextStepPath) {
291
+ // eslint-disable-next-line local-rules/no-typescript-assertion
290
292
  navigate({ to: basePath, params: { stepPath: nextStepPath } });
291
293
  }
292
294
  })), [
@@ -300,7 +302,10 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
300
302
  stepKey,
301
303
  submitHandlerInternal,
302
304
  ]);
303
- const handleSubmit = useMemo(() => (isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler), [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
305
+ const handleSubmit = useMemo(() => {
306
+ return isEmptyStep && form.formState.isValid ? emptyStepSubmitHandler : stepSubmitHandler;
307
+ }, [emptyStepSubmitHandler, form.formState.isValid, isEmptyStep, stepSubmitHandler]);
308
+ // TODO Replace with hoooooook
304
309
  useEffect(() => {
305
310
  // submit on cmd/ctrl + enter, always
306
311
  const handleKeyDown = (event) => {
@@ -323,7 +328,8 @@ const FormWizardStepWrapper = ({ stepKey, onCancel, description, title, componen
323
328
  setSubmitHandler: isLastStep ? setSubmitHandler : null,
324
329
  }) })) }), jsx(FormWizardFooter, { stepForms,
325
330
  onBack: previousStepPath
326
- ? () => navigate({ to: basePath, params: { stepPath: previousStepPath } })
331
+ ? // eslint-disable-next-line local-rules/no-typescript-assertion
332
+ () => navigate({ to: basePath, params: { stepPath: previousStepPath } })
327
333
  : null,
328
334
  primaryActionLabel: isLastStep ? lastStepPrimaryActionLabel : undefined,
329
335
  onCancel: handleCancel,
@@ -345,7 +351,6 @@ const cvaStepContainer = cvaMerge(["h-full", "grid", "bg-white", "overflow-hidde
345
351
  * Use the useFormWizard hook to generate the props for this component.
346
352
  */
347
353
  const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }) => {
348
- var _a;
349
354
  const { stepPath, subStepPath } = useParams({ strict: false });
350
355
  const [stepStates, setStepStates] = useState({});
351
356
  const [stepForms, setStepForms] = useState({});
@@ -357,21 +362,33 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
357
362
  objectFromEntries(objectEntries(steps)
358
363
  .filter(([_, { defaultValues }]) => defaultValues)
359
364
  .map(([key, { defaultValues }]) => [key, defaultValues])));
360
- const currentVisibleStepKey = (_a = objectEntries(steps).find(([, { path }]) => subStepPath ? path === `${stepPath}/${subStepPath}` : path === stepPath)) === null || _a === void 0 ? void 0 : _a[0];
365
+ const currentVisibleStepKey = subStepPath ? `${stepPath}/${subStepPath}` : stepPath;
361
366
  const currentVisibleStepIndex = objectKeys(steps)
362
- .filter(key => { var _a, _b, _c; return (_c = (_b = (_a = steps[key]).shouldRender) === null || _b === void 0 ? void 0 : _b.call(_a, fullFormState)) !== null && _c !== void 0 ? _c : true; })
367
+ .filter(key => {
368
+ var _a;
369
+ const step = steps[key];
370
+ return hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true;
371
+ })
363
372
  .findIndex(key => key === currentVisibleStepKey);
373
+ /**
374
+ * Asserts that step has a shouldRender.
375
+ * Is a workaround because I can't for the life of me get it to look up the step by a correctly typed
376
+ * template literal key of TComponentStepDefinitions and infer that it has a shouldRender automatically.👎
377
+ */
378
+ function hasShouldRenderProperty(obj) {
379
+ // TODO: remove this check if we can figure out a way to make TypeScript infer the type correctly
380
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, local-rules/no-typescript-assertion
381
+ return typeof obj.shouldRender === "function";
382
+ }
364
383
  return (jsx("div", { className: cvaFormWizardContainer({ className }), "data-testid": dataTestId, children: jsxs("div", { className: cvaFormWizardLayout(), children: [jsx(FormWizardSidebar, { children: objectEntries(steps)
365
- .filter(([_, step]) => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })
366
- .map(([key, { path, title, sidebarDescription, parent, defaultValues }], index) => {
384
+ .filter(([_, step]) => { var _a; return (hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true); })
385
+ .map(([key, { title, sidebarDescription, defaultValues }], index) => {
367
386
  const isPastStep = index < currentVisibleStepIndex;
368
387
  const isFutureStep = index > currentVisibleStepIndex;
369
388
  const isCurrentStep = key === currentVisibleStepKey;
370
389
  const hasDefaultValue = defaultValues !== undefined;
371
- const isSubStep = parent !== undefined;
372
- const onlyParentSteps = objectEntries(steps)
373
- .filter(([_, step]) => step.parent === undefined)
374
- .map(([k]) => k);
390
+ const isSubStep = key.toString().includes("/");
391
+ const rootSteps = objectKeys(steps).filter(k => !k.toString().includes("/"));
375
392
  const previousStepKey = objectKeys(steps)[index - 1];
376
393
  const stepState = () => {
377
394
  if (isCurrentStep) {
@@ -391,9 +408,10 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
391
408
  if (isFutureStep) {
392
409
  return objectKeys(steps)
393
410
  .filter((stepKey, stepIndex) => {
394
- var _a, _b;
395
- return stepIndex < index && steps[stepKey].shouldRender
396
- ? (_b = (_a = steps[stepKey]).shouldRender) === null || _b === void 0 ? void 0 : _b.call(_a, fullFormState)
411
+ var _a;
412
+ const step = steps[stepKey];
413
+ return stepIndex < index && hasShouldRenderProperty(step)
414
+ ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)
397
415
  : true;
398
416
  })
399
417
  .every((pastStepKey) => stepStates[pastStepKey] === "valid")
@@ -404,7 +422,7 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
404
422
  };
405
423
  return (jsx(FormWizardSidebarStep, { key: String(key),
406
424
  state: stepState(),
407
- stepNumber: isSubStep ? undefined : onlyParentSteps.indexOf(key) + 1,
425
+ stepNumber: isSubStep ? undefined : rootSteps.indexOf(key) + 1,
408
426
  title,
409
427
  onNavigate: () => {
410
428
  previousStepKey &&
@@ -414,20 +432,19 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
414
432
  });
415
433
  },
416
434
  basePath,
417
- path: path,
435
+ path: String(key),
418
436
  subTitle: sidebarDescription,
419
437
  isSubStep }));
420
438
  }) }), jsx("div", { className: cvaStepContainer(), children: objectEntries(steps)
421
- .filter(([_, step]) => {
422
- var _a, _b;
423
- return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true;
424
- })
439
+ .filter(([_, step]) => { var _a; return (hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true); })
425
440
  .map(([stepKey, props], index) => {
426
441
  var _a, _b, _c, _d;
427
- return (subStepPath ? props.path === `${stepPath}/${subStepPath}` : props.path === stepPath) ? (jsx(FormWizardStepWrapper, Object.assign({}, props, {
428
- // eslint-disable-next-line local-rules/no-typescript-assertion
429
- formSchema: props.formSchema, // TODO: FIX THIS string | number | symbol
430
- basePath,
442
+ const entriesOfRenderableSteps = objectEntries(steps).filter(stepEntry => {
443
+ var _a;
444
+ const step = stepEntry[1];
445
+ return hasShouldRenderProperty(step) ? (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState) : true;
446
+ });
447
+ return currentVisibleStepKey === stepKey ? (jsx(FormWizardStepWrapper, Object.assign({}, props, { basePath,
431
448
  stepKey: stepKey.toString(), // TODO: .toString() is a workaround
432
449
  stepForms,
433
450
  setStepForms,
@@ -437,8 +454,8 @@ const FormWizard = ({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema,
437
454
  setStepStates,
438
455
  fullFormSchema,
439
456
  lastStepPrimaryActionLabel,
440
- nextStepPath: (_b = (_a = objectValues(steps).filter(step => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })[index + 1]) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : null,
441
- previousStepPath: (_d = (_c = objectValues(steps).filter(step => { var _a, _b; return (_b = (_a = step.shouldRender) === null || _a === void 0 ? void 0 : _a.call(step, fullFormState)) !== null && _b !== void 0 ? _b : true; })[index - 1]) === null || _c === void 0 ? void 0 : _c.path) !== null && _d !== void 0 ? _d : null }), stepKey.toString())) : null;
457
+ nextStepPath: (_b = (_a = entriesOfRenderableSteps[index + 1]) === null || _a === void 0 ? void 0 : _a[0].toString()) !== null && _b !== void 0 ? _b : null,
458
+ previousStepPath: (_d = (_c = entriesOfRenderableSteps[index - 1]) === null || _c === void 0 ? void 0 : _c[0].toString()) !== null && _d !== void 0 ? _d : null }), stepKey.toString())) : null;
442
459
  }) })] }) }));
443
460
  };
444
461
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-wizard",
3
- "version": "0.1.103",
3
+ "version": "0.1.105",
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
  /// <reference types="react" />
2
2
  import { UseFormReturn } from "react-hook-form";
3
3
  import { AnyZodObject, z } from "zod";
4
- import { ComponentStepDefinitions, FromWizardComponentProps } from "./useFormWizard";
4
+ import { FromWizardComponentProps, StepDefinitions } from "./useFormWizard";
5
5
  export type FormWizardStepFormReturnMap<TFullSchema extends AnyZodObject> = Partial<{
6
6
  [TStepKey in keyof z.infer<TFullSchema>]: UseFormReturn<z.TypeOf<TFullSchema>[TStepKey]>;
7
7
  }>;
@@ -9,4 +9,4 @@ export type FormWizardStepFormReturnMap<TFullSchema extends AnyZodObject> = Part
9
9
  * The FormWizard component is used for forms in multiple steps.
10
10
  * Use the useFormWizard hook to generate the props for this component.
11
11
  */
12
- export declare const FormWizard: <TFullSchema extends AnyZodObject, TComponentStepDefinitions extends ComponentStepDefinitions<TFullSchema>>({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }: FromWizardComponentProps<TFullSchema, TComponentStepDefinitions>) => JSX.Element;
12
+ export declare const FormWizard: <TFullSchema extends AnyZodObject, TComponentStepDefinitions extends StepDefinitions<TFullSchema>>({ lastStepPrimaryActionLabel, isEdit, steps, fullFormSchema, onCancel, className, dataTestId, basePath, }: FromWizardComponentProps<TFullSchema, TComponentStepDefinitions>) => JSX.Element;
@@ -1,11 +1,14 @@
1
1
  import { RegisteredRouter, RouteIds } from "@tanstack/react-router";
2
2
  import { CommonProps } from "@trackunit/react-components";
3
+ import { MappedOmit } from "@trackunit/shared-utils";
3
4
  import { ReactNode } from "react";
4
5
  import { UseFormReturn } from "react-hook-form";
5
6
  import { AnyZodObject, SomeZodObject, z } from "zod";
6
7
  export type StepState = "active" | "done" | "invalid" | "disabled" | "ready";
7
8
  export type StepDefinitions<TFullSchema extends AnyZodObject> = {
8
- [KStepKey in keyof z.TypeOf<TFullSchema>]: DefinedStep<z.TypeOf<TFullSchema>[KStepKey], z.TypeOf<TFullSchema>>;
9
+ [KFullStepKey in keyof z.TypeOf<TFullSchema>]: KFullStepKey extends `${infer ParentStepKey}/${infer _SubStepKey}` ? ParentStepKey extends keyof z.TypeOf<TFullSchema> ? DefinedStep<z.TypeOf<TFullSchema>[KFullStepKey], z.TypeOf<TFullSchema>> & {
10
+ shouldRender?: (fullFormState: Partial<z.TypeOf<TFullSchema>>) => boolean;
11
+ } : never : DefinedStep<z.TypeOf<TFullSchema>[KFullStepKey], z.TypeOf<TFullSchema>>;
9
12
  };
10
13
  export type StepComponentPropsInner<TStepSchema extends TFullSchemaValue[keyof TFullSchemaValue], TFullSchemaValue extends z.TypeOf<AnyZodObject>> = {
11
14
  form: UseFormReturn<TStepSchema>;
@@ -16,26 +19,17 @@ export interface SimpleStepProps {
16
19
  title: string;
17
20
  description: string | ReactNode;
18
21
  sidebarDescription?: string;
19
- path: string;
20
22
  containerClassName?: string;
21
23
  }
22
24
  interface DefinedStep<TStepSchema extends TFullSchemaValue[keyof TFullSchemaValue], TFullSchemaValue extends z.TypeOf<AnyZodObject>> extends SimpleStepProps {
23
25
  component: (props: StepComponentPropsInner<TStepSchema, TFullSchemaValue>) => React.ReactNode;
24
- parent?: keyof TFullSchemaValue;
25
- shouldRender?: (fullFormState: Partial<TFullSchemaValue>) => boolean;
26
26
  defaultValues?: TStepSchema;
27
27
  }
28
28
  export type StepComponentProps<TFullSchemaHook extends () => AnyZodObject, TStepKey extends keyof z.TypeOf<ReturnType<TFullSchemaHook>>> = StepComponentPropsInner<z.TypeOf<ReturnType<TFullSchemaHook>>[TStepKey], z.TypeOf<ReturnType<TFullSchemaHook>>>;
29
- export type ComponentStepDefinitions<TFullSchema extends AnyZodObject> = {
30
- [KStepKey in keyof z.TypeOf<TFullSchema>]: DefinedComponentStep<z.TypeOf<TFullSchema>[KStepKey], z.TypeOf<TFullSchema>>;
31
- };
32
- interface DefinedComponentStep<TStepSchema extends TFullSchemaValue[keyof TFullSchemaValue], TFullSchemaValue extends z.TypeOf<AnyZodObject>> extends DefinedStep<TStepSchema, TFullSchemaValue> {
33
- formSchema: TStepSchema;
34
- }
35
- export interface FromWizardComponentProps<TFullSchema extends AnyZodObject, TComponentStepDefinitions extends ComponentStepDefinitions<TFullSchema>> extends Omit<UseFormWizardProps<TFullSchema, TComponentStepDefinitions>, "steps">, CommonProps {
29
+ export interface FromWizardComponentProps<TFullSchema extends AnyZodObject, TComponentStepDefinitions extends StepDefinitions<TFullSchema>> extends MappedOmit<UseFormWizardProps<TFullSchema, TComponentStepDefinitions>, "steps">, CommonProps {
36
30
  steps: TComponentStepDefinitions;
37
31
  }
38
- export type StringWithStepKey<TPath> = TPath extends `${infer Prefix}/$stepPath` ? TPath : never;
32
+ export type StringWithStepKey<TPath> = TPath extends `${infer _Prefix}/$stepPath` ? TPath : never;
39
33
  export interface UseFormWizardProps<TFullSchema extends SomeZodObject, TStepDefinitions extends StepDefinitions<TFullSchema>> {
40
34
  fullFormSchema: TFullSchema;
41
35
  lastStepPrimaryActionLabel: string;
@@ -47,5 +41,5 @@ export interface UseFormWizardProps<TFullSchema extends SomeZodObject, TStepDefi
47
41
  /**
48
42
  * A hook to generate the props for the FormWizard component.
49
43
  */
50
- export declare const useFormWizard: <TStepDefinition extends StepDefinitions<TFullSchema>, TFullSchema extends AnyZodObject>(props: UseFormWizardProps<TFullSchema, TStepDefinition>) => FromWizardComponentProps<TFullSchema, ComponentStepDefinitions<TFullSchema>>;
44
+ export declare const useFormWizard: <TStepDefinition extends StepDefinitions<TFullSchema>, TFullSchema extends AnyZodObject>(props: UseFormWizardProps<TFullSchema, TStepDefinition>) => FromWizardComponentProps<TFullSchema, StepDefinitions<TFullSchema>>;
51
45
  export {};
@@ -3,7 +3,7 @@ import { Dispatch, ReactNode, SetStateAction } from "react";
3
3
  import { DeepPartial, UseFormReturn } from "react-hook-form";
4
4
  import { AnyZodObject, z } from "zod";
5
5
  import { FormWizardStepFormReturnMap } from "../FormWizard/FormWizard";
6
- import { ComponentStepDefinitions, SimpleStepProps, StepComponentPropsInner, StringWithStepKey } from "../FormWizard/useFormWizard";
6
+ import { SimpleStepProps, StepComponentPropsInner, StepDefinitions, StringWithStepKey } from "../FormWizard/useFormWizard";
7
7
  export type StepFormValidity = "valid" | "invalid";
8
8
  export interface FormWizardStepWrapperProps<TStepKey extends keyof z.TypeOf<TFullSchema>, TFullSchema extends AnyZodObject> extends SimpleStepProps {
9
9
  description: string | ReactNode;
@@ -16,8 +16,7 @@ export interface FormWizardStepWrapperProps<TStepKey extends keyof z.TypeOf<TFul
16
16
  fullFormState: DeepPartial<z.TypeOf<TFullSchema>>;
17
17
  setFullFormState: Dispatch<SetStateAction<DeepPartial<z.TypeOf<TFullSchema>>>>;
18
18
  stepKey: TStepKey;
19
- formSchema: z.TypeOf<TFullSchema>[TStepKey];
20
- setStepStates: Dispatch<SetStateAction<Partial<Record<keyof ComponentStepDefinitions<TFullSchema>, StepFormValidity>>>>;
19
+ setStepStates: Dispatch<SetStateAction<Partial<Record<keyof StepDefinitions<TFullSchema>, StepFormValidity>>>>;
21
20
  component: (props: StepComponentPropsInner<DeepPartial<z.TypeOf<TFullSchema>[TStepKey]>, z.TypeOf<TFullSchema>>) => ReactNode;
22
21
  stepForms: FormWizardStepFormReturnMap<TFullSchema>;
23
22
  setStepForms: Dispatch<SetStateAction<Partial<{
@@ -28,4 +27,4 @@ export interface FormWizardStepWrapperProps<TStepKey extends keyof z.TypeOf<TFul
28
27
  * A wrapper component used by the FormWizard component to render each step.
29
28
  * In most cases you should not be using this component directly, but rather use the FormWizard component.
30
29
  */
31
- export declare const FormWizardStepWrapper: <TFullSchema extends AnyZodObject, TStepKey extends keyof z.TypeOf<TFullSchema>>({ stepKey, onCancel, description, title, component, formSchema, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }: FormWizardStepWrapperProps<TStepKey, TFullSchema>) => JSX.Element;
30
+ export declare const FormWizardStepWrapper: <TFullSchema extends AnyZodObject, TStepKey extends keyof z.TypeOf<TFullSchema>>({ stepKey, onCancel, description, title, component, nextStepPath, previousStepPath, lastStepPrimaryActionLabel, fullFormSchema, setFullFormState, fullFormState, stepForms, setStepForms, setStepStates, basePath, containerClassName, }: FormWizardStepWrapperProps<TStepKey, TFullSchema>) => JSX.Element;