@jfdevelops/react-multi-step-form 1.0.0-alpha.32 → 1.0.0-alpha.34
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/dist/create-context.cjs +6 -8
- package/dist/create-context.cjs.map +1 -1
- package/dist/create-context.d.cts +19 -21
- package/dist/create-context.d.mts +19 -21
- package/dist/create-context.mjs +12 -14
- package/dist/create-context.mjs.map +1 -1
- package/dist/field.cjs.map +1 -1
- package/dist/field.d.cts +15 -15
- package/dist/field.d.mts +15 -15
- package/dist/field.mjs.map +1 -1
- package/dist/form-config.cjs +38 -6
- package/dist/form-config.cjs.map +1 -1
- package/dist/form-config.d.cts +52 -18
- package/dist/form-config.d.mts +52 -18
- package/dist/form-config.mjs +38 -6
- package/dist/form-config.mjs.map +1 -1
- package/dist/hooks/use-multi-step-form-data.cjs +4 -22
- package/dist/hooks/use-multi-step-form-data.cjs.map +1 -1
- package/dist/hooks/use-multi-step-form-data.d.cts +12 -10
- package/dist/hooks/use-multi-step-form-data.d.mts +12 -10
- package/dist/hooks/use-multi-step-form-data.mjs +5 -22
- package/dist/hooks/use-multi-step-form-data.mjs.map +1 -1
- package/dist/hooks/use-selector.cjs.map +1 -1
- package/dist/hooks/use-selector.d.cts +18 -4
- package/dist/hooks/use-selector.d.mts +18 -4
- package/dist/hooks/use-selector.mjs.map +1 -1
- package/dist/index.cjs +2 -3
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/schema.cjs +87 -10
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +66 -25
- package/dist/schema.d.mts +66 -25
- package/dist/schema.mjs +88 -11
- package/dist/schema.mjs.map +1 -1
- package/dist/selector.cjs.map +1 -1
- package/dist/selector.d.cts +8 -8
- package/dist/selector.d.mts +8 -8
- package/dist/selector.mjs.map +1 -1
- package/dist/step-schema.cjs +54 -56
- package/dist/step-schema.cjs.map +1 -1
- package/dist/step-schema.d.cts +62 -61
- package/dist/step-schema.d.mts +62 -61
- package/dist/step-schema.mjs +57 -58
- package/dist/step-schema.mjs.map +1 -1
- package/dist/utils.cjs +12 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +12 -0
- package/dist/utils.d.mts +12 -0
- package/dist/utils.mjs +13 -2
- package/dist/utils.mjs.map +1 -1
- package/package.json +2 -2
package/dist/create-context.cjs
CHANGED
|
@@ -8,10 +8,6 @@ function createComponent(ctx) {
|
|
|
8
8
|
return ((props) => fn(ctx, props));
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Create multi step form context with a {@linkcode MultiStepFormSchema} instance.
|
|
13
|
-
* @param schema The {@linkcode MultiStepFormSchema} instance.
|
|
14
|
-
*/
|
|
15
11
|
function createMultiStepFormContext(schema) {
|
|
16
12
|
const useMultiStepFormData = require_use_multi_step_form_data.createMultiStepFormDataHook(schema);
|
|
17
13
|
function useCurrentStepData(options) {
|
|
@@ -39,9 +35,10 @@ function createMultiStepFormContext(schema) {
|
|
|
39
35
|
function useProgress(options) {
|
|
40
36
|
const steps = useMultiStepFormData((data) => data.stepSchema.steps.value.length);
|
|
41
37
|
const { targetStep, maxProgressValue = 100, totalSteps = steps, progressTextTransformer } = options;
|
|
42
|
-
|
|
38
|
+
(0, __jfdevelops_multi_step_form_core.createInvariant)("[useProgress]")(schema.getSnapshot().stepSchema.steps.isValidStep(targetStep), "Invalid step number");
|
|
39
|
+
const currentStep = targetStep.replace("step", "");
|
|
43
40
|
return {
|
|
44
|
-
value: currentStep / totalSteps * maxProgressValue,
|
|
41
|
+
value: Number.parseInt(currentStep, 10) / totalSteps * maxProgressValue,
|
|
45
42
|
maxProgressValue,
|
|
46
43
|
ProgressText: progressTextTransformer ? withProgressText({
|
|
47
44
|
targetStep,
|
|
@@ -74,8 +71,9 @@ function createMultiStepFormContext(schema) {
|
|
|
74
71
|
})(cb);
|
|
75
72
|
}
|
|
76
73
|
function withNoStepDataFound(options, cb) {
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
const { steps } = schema.getSnapshot().stepSchema;
|
|
75
|
+
(0, __jfdevelops_multi_step_form_core.createInvariant)("[withNoStepDataFound]")(steps.isValidStep(options.targetStep), (formatter) => `Invalid step number "${options.targetStep}". Valid steps are: ${formatter.format(steps.as("array.string.untyped"))}`);
|
|
76
|
+
return createComponent({ targetStep: options.targetStep })(cb);
|
|
79
77
|
}
|
|
80
78
|
return {
|
|
81
79
|
useMultiStepFormData,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-context.cjs","names":["createMultiStepFormDataHook","MultiStepFormStepSchema","throwIfInvalidStepNumber"],"sources":["../src/create-context.tsx"],"sourcesContent":["import { MultiStepFormStepSchema } from '@jfdevelops/multi-step-form-core';\nimport { type ComponentProps, type ReactNode } from 'react';\nimport {\n createMultiStepFormDataHook,\n throwIfInvalidStepNumber,\n UseMultiStepFormData,\n} from './hooks/use-multi-step-form-data';\nimport { MultiStepFormSchema, type AnyMultiStepFormSchema } from './schema';\nimport type {\n CreatedMultiStepFormComponent,\n CreateFunction,\n} from './step-schema';\n\ntype BaseOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n /**\n * The step to return data from.\n */\n targetStep: TTargetStep;\n};\nexport type UseCurrentStepOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props,\n isDataGuaranteed extends boolean = false\n> = BaseOptions<TSchema, TTargetStep> & {\n /**\n * Determines if the result should follow \"strictness\".\n * The result will change based on the value for this option.\n *\n * - `true`: `data` is **defined** and `hasData` isn't available.\n * - `false`: `data` _can be_ `undefined`, but the `hasData` property is available\n * to help with type narrowing.\n *\n * @default false\n * @example\n * ### `true`\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData } = useCurrentStep({\n * stepNumber: 1,\n * isDataGuaranteed: true,\n * })\n *\n * // Notice how `NoCurrentData` is still available\n * // Do things with `data` here\n * }\n * ```\n *\n * ### `false` - The default\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData, hasData } = useCurrentStep({\n * stepNumber: 1,\n * })\n *\n * if (!hasData) {\n * return <NoCurrentData />\n * }\n *\n * // Do things with `data` here\n * }\n * ```\n */\n isDataGuaranteed?: isDataGuaranteed;\n /**\n * An optional transformation function to provide a custom not found message.\n */\n notFoundMessage?: CreateFunction<\n [ctx: BaseOptions<TSchema, TTargetStep>, props: props],\n ReactNode\n >;\n};\nexport interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {\n /**\n * The current step's data.\n */\n data: TData | undefined;\n /**\n * Boolean indicating if the current step has data.\n */\n hasData: boolean;\n /**\n * Component to render some sort of error if `data` isn't defined.\n */\n NoCurrentData: CreatedMultiStepFormComponent<\n TProps extends undefined ? Omit<ComponentProps<'div'>, 'children'> : TProps\n >;\n}\nexport interface UseCurrentStepErrorResult<TData = unknown, TProps = undefined>\n extends UseCurrentStepBaseResult<TData, TProps> {\n data: undefined;\n hasData: false;\n}\nexport interface UseCurrentStepSuccessResult<\n TData = unknown,\n TProps = undefined\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: TData;\n hasData: true;\n}\nexport type UseCurrentStepResult<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props,\n isDataGuaranteed extends boolean = false\n> = isDataGuaranteed extends true\n ? Omit<\n UseCurrentStepSuccessResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >,\n 'hasData'\n >\n :\n | UseCurrentStepErrorResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >\n | UseCurrentStepSuccessResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >;\nexport type UseProgressBaseOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>\n> = BaseOptions<TSchema, TTargetStep> & {\n /**\n * The total amount of steps that are in the form.\n *\n * @default schema.stepData.steps.value.length\n */\n totalSteps?: number;\n /**\n * The highest value the progress indicator should go.\n *\n * @default 100\n */\n maxProgressValue?: number;\n};\nexport type UseProgressOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props\n> = UseProgressBaseOptions<TSchema, TTargetStep> & {\n /**\n * An optional transformation function to provide a custom progress text.\n */\n progressTextTransformer?: CreateFunction<\n [ctx: Required<UseProgressBaseOptions<TSchema, TTargetStep>>, props],\n ReactNode\n >;\n};\nexport type UseProgressResult<props> = {\n /**\n * The value of the progress indicator.\n */\n value: number;\n /**\n * The highest value the progress indicator can be.\n *\n * @default 100\n */\n maxProgressValue: number;\n ProgressText: CreatedMultiStepFormComponent<\n props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props\n >;\n};\nexport type CreateHOC<TContext, TProps> = (\n ctx: TContext,\n props: TProps\n) => CreatedMultiStepFormComponent<TProps>;\n\nexport type MultiStepFormContextResult<\n TSchema extends AnyMultiStepFormSchema,\n TResolvedStep extends MultiStepFormSchema.resolvedStep<TSchema> = MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n // MultiStepFormContext: schema;\n // MultiStepFormProvider: (props: { children: ReactNode }) => JSX.Element;\n // useMultiStepFormSchema: schema;\n useMultiStepFormData: UseMultiStepFormData<TSchema>;\n /**\n * Gets the data for the specified step.\n *\n * @returns The data for the given step number.\n */\n useCurrentStepData: <\n targetStep extends keyof TResolvedStep,\n props = undefined,\n isDataGuaranteed extends boolean = false\n >(\n options: UseCurrentStepOptions<TSchema, targetStep, props, isDataGuaranteed>\n ) => UseCurrentStepResult<TSchema, targetStep, props, isDataGuaranteed>;\n useProgress: <targetStep extends keyof TResolvedStep, props = undefined>(\n options: UseProgressOptions<TSchema, targetStep, props>\n ) => UseProgressResult<props>;\n /**\n * A hook that can be used to check if the form can be restarted. If no {@linkcode cb}\n * is provided, the return value will be dictated by if there is an object stored in\n * {@link MultiStepFormSchema#storage}.\n * @param cb A callback function to provide custom logic for if the form can restart.\n * @returns A boolean indicating if the form can restart.\n */\n useCanRestartForm: (cb?: (canRestart: boolean) => boolean) => boolean;\n /**\n * A HOC for creating a custom progress text for `useProgress`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.\n */\n withProgressText: <targetStep extends keyof TResolvedStep, props = undefined>(\n options: UseProgressBaseOptions<TSchema, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<TSchema, targetStep>>,\n props: props\n ) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n /**\n * A HOC for creating a custom not found component for when a step's data is `undefined`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.\n */\n withNoStepDataFound: <\n targetStep extends keyof TResolvedStep,\n props = undefined\n >(\n options: BaseOptions<TSchema, targetStep>,\n cb: (ctx: BaseOptions<TSchema, targetStep>, props: props) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n};\n\nfunction createComponent<ctx>(ctx: ctx) {\n return function <props>(fn: CreateFunction<[ctx, props], ReactNode>) {\n return ((props: props) =>\n fn(ctx, props)) as CreatedMultiStepFormComponent<props>;\n };\n}\n\n/**\n * Create multi step form context with a {@linkcode MultiStepFormSchema} instance.\n * @param schema The {@linkcode MultiStepFormSchema} instance.\n */\n// export function createMultiStepFormContext<\n// schema extends AnyMultiStepFormSchema\n// >(schema: schema): MultiStepFormContextResult<schema>;\n// /**\n// * Create multi step form context without a {@linkcode MultiStepFormSchema} instance.\n// *\n// * The {@linkcode MultiStepFormSchema} instance is returned.\n// * @param options Options to create a new instance of {@linkcode MultiStepFormSchema}.\n// */\n// export function createMultiStepFormContext<\n// step extends Step<casing>,\n// casing extends CasingType = DefaultCasing,\n// storageKey extends string = DefaultStorageKey,\n// resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n// stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n// schema extends MultiStepFormSchema<\n// step,\n// casing,\n// storageKey,\n// resolvedStep,\n// stepNumbers\n// > = MultiStepFormSchema<step, casing, storageKey, resolvedStep, stepNumbers>\n// >(\n// options: MultiStepFormSchemaConfig<\n// step,\n// Constrain<casing, CasingType>,\n// storageKey\n// >\n// ): MultiStepFormContextResult<schema> & {\n// schema: MultiStepFormSchema<step, casing, storageKey>;\n// };\nexport function createMultiStepFormContext<\n schema extends AnyMultiStepFormSchema,\n resolvedStep extends MultiStepFormSchema.resolvedStep<schema> = MultiStepFormSchema.resolvedStep<schema>\n>(schema: schema): MultiStepFormContextResult<schema> {\n // const isInstance = schemaOrOptions instanceof MultiStepFormSchema;\n // const schema: schema = isInstance\n // ? schemaOrOptions\n // : createMultiStepFormSchema(schemaOrOptions);\n // const Context = createContext(schema);\n\n // function Provider({ children }: { children: ReactNode }) {\n // const [observer] = useState(() => new MultiStepFormObserver({ schema }));\n\n // useEffect(() => {\n // const unmount = schema.mount();\n\n // return () => {\n // unmount();\n // observer.destroy();\n // };\n // }, [observer]);\n\n // return <Context.Provider value={observer}>{children}</Context.Provider>;\n // }\n\n // function throwIfInvalidStepNumber(\n // schema: MultiStepFormSchema<step, casing, storageKey>,\n // stepNumber: number\n // ) {\n // const formatter = new Intl.ListFormat('en', {\n // type: 'disjunction',\n // style: 'long',\n // });\n // const { as, isValidStepNumber } = schema.stepSchema.steps;\n\n // invariant(\n // isValidStepNumber(stepNumber),\n // `The step number \"${stepNumber}\" is not a valid step number. Valid step numbers include ${formatter.format(\n // as('array.string.untyped')\n // )}`,\n // TypeError\n // );\n // }\n\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n const useMultiStepFormData = createMultiStepFormDataHook(schema);\n\n function useCurrentStepData<\n targetStep extends keyof resolvedStep,\n props = undefined,\n isDataGuaranteed extends boolean = false\n >(\n options: UseCurrentStepOptions<schema, targetStep, props, isDataGuaranteed>\n ): UseCurrentStepResult<schema, targetStep, props, isDataGuaranteed> {\n const { targetStep, notFoundMessage, isDataGuaranteed } = options;\n const data = useMultiStepFormData({\n targetStep,\n });\n const NoDataFoundComponent = notFoundMessage\n ? withNoStepDataFound({ targetStep }, notFoundMessage)\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>No data found for step {String(targetStep)}</div>\n );\n\n if (isDataGuaranteed) {\n return {\n data,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n if (MultiStepFormStepSchema.hasData(data)) {\n return {\n data,\n hasData: true,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n return {\n data: undefined,\n hasData: false,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n function useProgress<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: UseProgressOptions<schema, targetStep, props>\n ): UseProgressResult<props> {\n const steps = useMultiStepFormData(\n (data) => data.stepSchema.steps.value.length\n );\n const {\n targetStep,\n maxProgressValue = 100,\n totalSteps = steps,\n progressTextTransformer,\n } = options;\n const currentStep = throwIfInvalidStepNumber(schema, targetStep);\n const value = (currentStep / totalSteps) * maxProgressValue;\n const ProgressText = progressTextTransformer\n ? withProgressText(\n { targetStep, maxProgressValue, totalSteps },\n progressTextTransformer\n )\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>\n Step {currentStep}/{totalSteps}\n </div>\n );\n\n return {\n value,\n maxProgressValue,\n ProgressText: ProgressText as never,\n };\n }\n\n function useCanRestartForm(cb?: CreateFunction<[boolean], boolean>) {\n const storage = useMultiStepFormData((data) => data.storage);\n const value = storage.get();\n const canRestart = Boolean(\n value && typeof value === 'object' && Object.keys(value).length > 0\n );\n\n if (cb) {\n return cb(canRestart);\n }\n\n return canRestart;\n }\n\n function withProgressText<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: UseProgressBaseOptions<schema, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<schema, targetStep>>,\n props: props\n ) => ReactNode\n ) {\n const steps = schema.getSnapshot().stepSchema.steps.value.length;\n const { targetStep, maxProgressValue = 100, totalSteps = steps } = options;\n\n return createComponent({ targetStep, maxProgressValue, totalSteps })(cb);\n }\n\n function withNoStepDataFound<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: BaseOptions<schema, targetStep>,\n cb: (ctx: BaseOptions<schema, targetStep>, props: props) => ReactNode\n ) {\n throwIfInvalidStepNumber(schema, options.targetStep);\n\n return createComponent(options)(cb);\n }\n\n return {\n // MultiStepFormContext: Context,\n useMultiStepFormData,\n useCurrentStepData,\n useProgress,\n useCanRestartForm,\n withProgressText,\n withNoStepDataFound,\n };\n}\n"],"mappings":";;;;;AA0OA,SAAS,gBAAqB,KAAU;AACtC,QAAO,SAAiB,IAA6C;AACnE,WAAS,UACP,GAAG,KAAK,MAAM;;;;;;;AAuCpB,SAAgB,2BAGd,QAAoD;CA0CpD,MAAM,uBAAuBA,6DAA4B,OAAO;CAEhE,SAAS,mBAKP,SACmE;EACnE,MAAM,EAAE,YAAY,iBAAiB,qBAAqB;EAC1D,MAAM,OAAO,qBAAqB,EAChC,YACD,CAAC;EACF,MAAM,uBAAuB,kBACzB,oBAAoB,EAAE,YAAY,EAAE,gBAAgB,IACnD,UACC,4CAAC;GAAI,GAAI;cAAO,2BAAwB,OAAO,WAAW;IAAO;AAGvE,MAAI,iBACF,QAAO;GACL;GACA,eAAe;GAChB;AAGH,MAAIC,0DAAwB,QAAQ,KAAK,CACvC,QAAO;GACL;GACA,SAAS;GACT,eAAe;GAChB;AAGH,SAAO;GACL,MAAM;GACN,SAAS;GACT,eAAe;GAChB;;CAGH,SAAS,YAIP,SAC0B;EAC1B,MAAM,QAAQ,sBACX,SAAS,KAAK,WAAW,MAAM,MAAM,OACvC;EACD,MAAM,EACJ,YACA,mBAAmB,KACnB,aAAa,OACb,4BACE;EACJ,MAAM,cAAcC,0DAAyB,QAAQ,WAAW;AAahE,SAAO;GACL,OAba,cAAc,aAAc;GAczC;GACA,cAdmB,0BACjB,iBACE;IAAE;IAAY;IAAkB;IAAY,EAC5C,wBACD,IACA,UACC,4CAAC;IAAI,GAAI;;KAAO;KACR;KAAY;KAAE;;KAChB;GAOX;;CAGH,SAAS,kBAAkB,IAAyC;EAElE,MAAM,QADU,sBAAsB,SAAS,KAAK,QAAQ,CACtC,KAAK;EAC3B,MAAM,aAAa,QACjB,SAAS,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC,SAAS,EACnE;AAED,MAAI,GACF,QAAO,GAAG,WAAW;AAGvB,SAAO;;CAGT,SAAS,iBAIP,SACA,IAIA;EACA,MAAM,QAAQ,OAAO,aAAa,CAAC,WAAW,MAAM,MAAM;EAC1D,MAAM,EAAE,YAAY,mBAAmB,KAAK,aAAa,UAAU;AAEnE,SAAO,gBAAgB;GAAE;GAAY;GAAkB;GAAY,CAAC,CAAC,GAAG;;CAG1E,SAAS,oBAIP,SACA,IACA;AACA,4DAAyB,QAAQ,QAAQ,WAAW;AAEpD,SAAO,gBAAgB,QAAQ,CAAC,GAAG;;AAGrC,QAAO;EAEL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
1
|
+
{"version":3,"file":"create-context.cjs","names":["createMultiStepFormDataHook","MultiStepFormStepSchema"],"sources":["../src/create-context.tsx"],"sourcesContent":["import {\n createInvariant,\n MultiStepFormStepSchema,\n type Invariant,\n type steps,\n} from '@jfdevelops/multi-step-form-core';\nimport type { StepSchema } from '@jfdevelops/multi-step-form-core/_internals';\nimport { type ComponentProps, type ReactNode } from 'react';\nimport {\n createMultiStepFormDataHook,\n UseMultiStepFormData,\n} from './hooks/use-multi-step-form-data';\nimport { MultiStepFormSchema } from './schema';\nimport type { CreatedMultiStepFormComponent, CreateFunction } from './utils';\n\ntype BaseOptions<targetStep extends string> = {\n /**\n * The step to return data from.\n */\n targetStep: targetStep;\n};\nexport type UseCurrentStepOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n isDataGuaranteed extends boolean = false,\n> = BaseOptions<targetStep> & {\n /**\n * Determines if the result should follow \"strictness\".\n * The result will change based on the value for this option.\n *\n * - `true`: `data` is **defined** and `hasData` isn't available.\n * - `false`: `data` _can be_ `undefined`, but the `hasData` property is available\n * to help with type narrowing.\n *\n * @default false\n * @example\n * ### `true`\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData } = useCurrentStep({\n * stepNumber: 1,\n * isDataGuaranteed: true,\n * })\n *\n * // Notice how `NoCurrentData` is still available\n * // Do things with `data` here\n * }\n * ```\n *\n * ### `false` - The default\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData, hasData } = useCurrentStep({\n * stepNumber: 1,\n * })\n *\n * if (!hasData) {\n * return <NoCurrentData />\n * }\n *\n * // Do things with `data` here\n * }\n * ```\n */\n isDataGuaranteed?: isDataGuaranteed;\n /**\n * An optional transformation function to provide a custom not found message.\n */\n notFoundMessage?: CreateFunction<\n [ctx: BaseOptions<targetStep>, props: props],\n ReactNode\n >;\n};\nexport interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {\n /**\n * The current step's data.\n */\n data: TData | undefined;\n /**\n * Boolean indicating if the current step has data.\n */\n hasData: boolean;\n /**\n * Component to render some sort of error if `data` isn't defined.\n */\n NoCurrentData: CreatedMultiStepFormComponent<\n TProps extends undefined ? Omit<ComponentProps<'div'>, 'children'> : TProps\n >;\n}\nexport interface UseCurrentStepErrorResult<\n TData = unknown,\n TProps = undefined,\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: undefined;\n hasData: false;\n}\nexport interface UseCurrentStepSuccessResult<\n TData = unknown,\n TProps = undefined,\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: TData;\n hasData: true;\n}\nexport type UseCurrentStepResult<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n isDataGuaranteed extends boolean = false,\n> = isDataGuaranteed extends true\n ? Omit<\n UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>,\n 'hasData'\n >\n :\n | UseCurrentStepErrorResult<steps.getCurrent<value, targetStep>, props>\n | UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>;\nexport type UseProgressBaseOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n> = BaseOptions<targetStep> & {\n /**\n * The total amount of steps that are in the form.\n *\n * @default schema.stepData.steps.value.length\n */\n totalSteps?: number;\n /**\n * The highest value the progress indicator should go.\n *\n * @default 100\n */\n maxProgressValue?: number;\n};\nexport type UseProgressOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n> = UseProgressBaseOptions<def, value, targetStep> & {\n /**\n * An optional transformation function to provide a custom progress text.\n */\n progressTextTransformer?: CreateFunction<\n [ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props],\n ReactNode\n >;\n};\nexport type UseProgressResult<props> = {\n /**\n * The value of the progress indicator.\n */\n value: number;\n /**\n * The highest value the progress indicator can be.\n *\n * @default 100\n */\n maxProgressValue: number;\n ProgressText: CreatedMultiStepFormComponent<\n props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props\n >;\n};\nexport type CreateHOC<TContext, TProps> = (\n ctx: TContext,\n props: TProps\n) => CreatedMultiStepFormComponent<TProps>;\n\nexport type MultiStepFormContextResult<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n> = {\n useMultiStepFormData: UseMultiStepFormData<def, value>;\n /**\n * Gets the data for the specified step.\n *\n * @returns The data for the given step number.\n */\n useCurrentStepData: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n isDataGuaranteed extends boolean = false,\n >(\n options: UseCurrentStepOptions<\n def,\n value,\n targetStep,\n props,\n isDataGuaranteed\n >\n ) => UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed>;\n useProgress: <targetStep extends steps.StepNumbers<value>, props = undefined>(\n options: UseProgressOptions<def, value, targetStep, props>\n ) => UseProgressResult<props>;\n /**\n * A hook that can be used to check if the form can be restarted. If no {@linkcode cb}\n * is provided, the return value will be dictated by if there is an object stored in\n * {@link MultiStepFormSchema#storage}.\n * @param cb A callback function to provide custom logic for if the form can restart.\n * @returns A boolean indicating if the form can restart.\n */\n useCanRestartForm: (cb?: (canRestart: boolean) => boolean) => boolean;\n /**\n * A HOC for creating a custom progress text for `useProgress`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.\n */\n withProgressText: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressBaseOptions<def, value, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<def, value, targetStep>>,\n props: props\n ) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n /**\n * A HOC for creating a custom not found component for when a step's data is `undefined`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.\n */\n withNoStepDataFound: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: BaseOptions<targetStep>,\n cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n};\n\nfunction createComponent<ctx>(ctx: ctx) {\n return function <props>(fn: CreateFunction<[ctx, props], ReactNode>) {\n return ((props: props) =>\n fn(ctx, props)) as CreatedMultiStepFormComponent<props>;\n };\n}\n\nexport function createMultiStepFormContext<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n>(\n schema: MultiStepFormSchema<def, value>\n): MultiStepFormContextResult<def, value> {\n const useMultiStepFormData = createMultiStepFormDataHook(schema);\n\n function useCurrentStepData<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n isDataGuaranteed extends boolean = false,\n >(\n options: UseCurrentStepOptions<\n def,\n value,\n targetStep,\n props,\n isDataGuaranteed\n >\n ): UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed> {\n const { targetStep, notFoundMessage, isDataGuaranteed } = options;\n const data = useMultiStepFormData({\n targetStep,\n });\n const NoDataFoundComponent = notFoundMessage\n ? withNoStepDataFound({ targetStep }, notFoundMessage)\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>No data found for step {String(targetStep)}</div>\n );\n\n if (isDataGuaranteed) {\n return {\n data,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n if (MultiStepFormStepSchema.hasData(data)) {\n return {\n data,\n hasData: true,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n return {\n data: undefined,\n hasData: false,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n function useProgress<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressOptions<def, value, targetStep, props>\n ): UseProgressResult<props> {\n const steps = useMultiStepFormData(\n (data) => data.stepSchema.steps.value.length\n );\n const {\n targetStep,\n maxProgressValue = 100,\n totalSteps = steps,\n progressTextTransformer,\n } = options;\n const invariant: Invariant = createInvariant('[useProgress]');\n\n invariant(\n schema.getSnapshot().stepSchema.steps.isValidStep(targetStep),\n 'Invalid step number'\n );\n\n const currentStep = targetStep.replace('step', '');\n const value =\n (Number.parseInt(currentStep, 10) / totalSteps) * maxProgressValue;\n const ProgressText = progressTextTransformer\n ? withProgressText(\n { targetStep, maxProgressValue, totalSteps },\n progressTextTransformer\n )\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>\n Step {currentStep}/{totalSteps}\n </div>\n );\n\n return {\n value,\n maxProgressValue,\n ProgressText: ProgressText as never,\n };\n }\n\n function useCanRestartForm(cb?: CreateFunction<[boolean], boolean>) {\n const storage = useMultiStepFormData((data) => data.storage);\n const value = storage.get();\n const canRestart = Boolean(\n value && typeof value === 'object' && Object.keys(value).length > 0\n );\n\n if (cb) {\n return cb(canRestart);\n }\n\n return canRestart;\n }\n\n function withProgressText<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressBaseOptions<def, value, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<def, value, targetStep>>,\n props: props\n ) => ReactNode\n ) {\n const steps = schema.getSnapshot().stepSchema.steps.value.length;\n const { targetStep, maxProgressValue = 100, totalSteps = steps } = options;\n\n return createComponent({ targetStep, maxProgressValue, totalSteps })(cb);\n }\n\n function withNoStepDataFound<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: BaseOptions<targetStep>,\n cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode\n ) {\n const { steps } = schema.getSnapshot().stepSchema;\n const invariant: Invariant = createInvariant('[withNoStepDataFound]');\n\n invariant(\n steps.isValidStep(options.targetStep),\n (formatter) =>\n `Invalid step number \"${options.targetStep}\". Valid steps are: ${formatter.format(steps.as('array.string.untyped'))}`\n );\n\n return createComponent({ targetStep: options.targetStep })(cb);\n }\n\n return {\n useMultiStepFormData,\n useCurrentStepData,\n useProgress,\n useCanRestartForm,\n withProgressText,\n withNoStepDataFound,\n };\n}\n"],"mappings":";;;;;AA4OA,SAAS,gBAAqB,KAAU;AACtC,QAAO,SAAiB,IAA6C;AACnE,WAAS,UACP,GAAG,KAAK,MAAM;;;AAIpB,SAAgB,2BAId,QACwC;CACxC,MAAM,uBAAuBA,6DAA4B,OAAO;CAEhE,SAAS,mBAKP,SAOuE;EACvE,MAAM,EAAE,YAAY,iBAAiB,qBAAqB;EAC1D,MAAM,OAAO,qBAAqB,EAChC,YACD,CAAC;EACF,MAAM,uBAAuB,kBACzB,oBAAoB,EAAE,YAAY,EAAE,gBAAgB,IACnD,UACC,4CAAC;GAAI,GAAI;cAAO,2BAAwB,OAAO,WAAW;IAAO;AAGvE,MAAI,iBACF,QAAO;GACL;GACA,eAAe;GAChB;AAGH,MAAIC,0DAAwB,QAAQ,KAAK,CACvC,QAAO;GACL;GACA,SAAS;GACT,eAAe;GAChB;AAGH,SAAO;GACL,MAAM;GACN,SAAS;GACT,eAAe;GAChB;;CAGH,SAAS,YAIP,SAC0B;EAC1B,MAAM,QAAQ,sBACX,SAAS,KAAK,WAAW,MAAM,MAAM,OACvC;EACD,MAAM,EACJ,YACA,mBAAmB,KACnB,aAAa,OACb,4BACE;AAGJ,yDAF6C,gBAAgB,CAG3D,OAAO,aAAa,CAAC,WAAW,MAAM,YAAY,WAAW,EAC7D,sBACD;EAED,MAAM,cAAc,WAAW,QAAQ,QAAQ,GAAG;AAclD,SAAO;GACL,OAbC,OAAO,SAAS,aAAa,GAAG,GAAG,aAAc;GAclD;GACA,cAdmB,0BACjB,iBACE;IAAE;IAAY;IAAkB;IAAY,EAC5C,wBACD,IACA,UACC,4CAAC;IAAI,GAAI;;KAAO;KACR;KAAY;KAAE;;KAChB;GAOX;;CAGH,SAAS,kBAAkB,IAAyC;EAElE,MAAM,QADU,sBAAsB,SAAS,KAAK,QAAQ,CACtC,KAAK;EAC3B,MAAM,aAAa,QACjB,SAAS,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC,SAAS,EACnE;AAED,MAAI,GACF,QAAO,GAAG,WAAW;AAGvB,SAAO;;CAGT,SAAS,iBAIP,SACA,IAIA;EACA,MAAM,QAAQ,OAAO,aAAa,CAAC,WAAW,MAAM,MAAM;EAC1D,MAAM,EAAE,YAAY,mBAAmB,KAAK,aAAa,UAAU;AAEnE,SAAO,gBAAgB;GAAE;GAAY;GAAkB;GAAY,CAAC,CAAC,GAAG;;CAG1E,SAAS,oBAIP,SACA,IACA;EACA,MAAM,EAAE,UAAU,OAAO,aAAa,CAAC;AAGvC,yDAF6C,wBAAwB,CAGnE,MAAM,YAAY,QAAQ,WAAW,GACpC,cACC,wBAAwB,QAAQ,WAAW,sBAAsB,UAAU,OAAO,MAAM,GAAG,uBAAuB,CAAC,GACtH;AAED,SAAO,gBAAgB,EAAE,YAAY,QAAQ,YAAY,CAAC,CAAC,GAAG;;AAGhE,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { CreateFunction, CreatedMultiStepFormComponent } from "./
|
|
2
|
-
import { AnyMultiStepFormSchema, MultiStepFormSchema } from "./schema.cjs";
|
|
1
|
+
import { CreateFunction, CreatedMultiStepFormComponent } from "./utils.cjs";
|
|
3
2
|
import { UseMultiStepFormData } from "./hooks/use-multi-step-form-data.cjs";
|
|
3
|
+
import { MultiStepFormSchema as MultiStepFormSchema$1 } from "./schema.cjs";
|
|
4
|
+
import { steps } from "@jfdevelops/multi-step-form-core";
|
|
5
|
+
import { StepSchema } from "@jfdevelops/multi-step-form-core/_internals";
|
|
4
6
|
import { ComponentProps, ReactNode } from "react";
|
|
5
7
|
|
|
6
8
|
//#region src/create-context.d.ts
|
|
7
|
-
type BaseOptions<
|
|
9
|
+
type BaseOptions<targetStep extends string> = {
|
|
8
10
|
/**
|
|
9
11
|
* The step to return data from.
|
|
10
12
|
*/
|
|
11
|
-
targetStep:
|
|
13
|
+
targetStep: targetStep;
|
|
12
14
|
};
|
|
13
|
-
type UseCurrentStepOptions<
|
|
15
|
+
type UseCurrentStepOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props, isDataGuaranteed extends boolean = false> = BaseOptions<targetStep> & {
|
|
14
16
|
/**
|
|
15
17
|
* Determines if the result should follow "strictness".
|
|
16
18
|
* The result will change based on the value for this option.
|
|
@@ -53,7 +55,7 @@ type UseCurrentStepOptions<TSchema extends AnyMultiStepFormSchema, TTargetStep e
|
|
|
53
55
|
/**
|
|
54
56
|
* An optional transformation function to provide a custom not found message.
|
|
55
57
|
*/
|
|
56
|
-
notFoundMessage?: CreateFunction<[ctx: BaseOptions<
|
|
58
|
+
notFoundMessage?: CreateFunction<[ctx: BaseOptions<targetStep>, props: props], ReactNode>;
|
|
57
59
|
};
|
|
58
60
|
interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {
|
|
59
61
|
/**
|
|
@@ -77,8 +79,8 @@ interface UseCurrentStepSuccessResult<TData = unknown, TProps = undefined> exten
|
|
|
77
79
|
data: TData;
|
|
78
80
|
hasData: true;
|
|
79
81
|
}
|
|
80
|
-
type UseCurrentStepResult<
|
|
81
|
-
type UseProgressBaseOptions<
|
|
82
|
+
type UseCurrentStepResult<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props, isDataGuaranteed extends boolean = false> = isDataGuaranteed extends true ? Omit<UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>, 'hasData'> : UseCurrentStepErrorResult<steps.getCurrent<value, targetStep>, props> | UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>;
|
|
83
|
+
type UseProgressBaseOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>> = BaseOptions<targetStep> & {
|
|
82
84
|
/**
|
|
83
85
|
* The total amount of steps that are in the form.
|
|
84
86
|
*
|
|
@@ -92,11 +94,11 @@ type UseProgressBaseOptions<TSchema extends AnyMultiStepFormSchema, TTargetStep
|
|
|
92
94
|
*/
|
|
93
95
|
maxProgressValue?: number;
|
|
94
96
|
};
|
|
95
|
-
type UseProgressOptions<
|
|
97
|
+
type UseProgressOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props> = UseProgressBaseOptions<def, value, targetStep> & {
|
|
96
98
|
/**
|
|
97
99
|
* An optional transformation function to provide a custom progress text.
|
|
98
100
|
*/
|
|
99
|
-
progressTextTransformer?: CreateFunction<[ctx: Required<UseProgressBaseOptions<
|
|
101
|
+
progressTextTransformer?: CreateFunction<[ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props], ReactNode>;
|
|
100
102
|
};
|
|
101
103
|
type UseProgressResult<props> = {
|
|
102
104
|
/**
|
|
@@ -112,15 +114,15 @@ type UseProgressResult<props> = {
|
|
|
112
114
|
ProgressText: CreatedMultiStepFormComponent<props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props>;
|
|
113
115
|
};
|
|
114
116
|
type CreateHOC<TContext, TProps> = (ctx: TContext, props: TProps) => CreatedMultiStepFormComponent<TProps>;
|
|
115
|
-
type MultiStepFormContextResult<
|
|
116
|
-
useMultiStepFormData: UseMultiStepFormData<
|
|
117
|
+
type MultiStepFormContextResult<def extends StepSchema.Config, value extends steps.instantiateSteps<def>> = {
|
|
118
|
+
useMultiStepFormData: UseMultiStepFormData<def, value>;
|
|
117
119
|
/**
|
|
118
120
|
* Gets the data for the specified step.
|
|
119
121
|
*
|
|
120
122
|
* @returns The data for the given step number.
|
|
121
123
|
*/
|
|
122
|
-
useCurrentStepData: <targetStep extends
|
|
123
|
-
useProgress: <targetStep extends
|
|
124
|
+
useCurrentStepData: <targetStep extends steps.StepNumbers<value>, props = undefined, isDataGuaranteed extends boolean = false>(options: UseCurrentStepOptions<def, value, targetStep, props, isDataGuaranteed>) => UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed>;
|
|
125
|
+
useProgress: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: UseProgressOptions<def, value, targetStep, props>) => UseProgressResult<props>;
|
|
124
126
|
/**
|
|
125
127
|
* A hook that can be used to check if the form can be restarted. If no {@linkcode cb}
|
|
126
128
|
* is provided, the return value will be dictated by if there is an object stored in
|
|
@@ -135,20 +137,16 @@ type MultiStepFormContextResult<TSchema extends AnyMultiStepFormSchema, TResolve
|
|
|
135
137
|
* @param cb The callback function for creating the HOC.
|
|
136
138
|
* @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.
|
|
137
139
|
*/
|
|
138
|
-
withProgressText: <targetStep extends
|
|
140
|
+
withProgressText: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: UseProgressBaseOptions<def, value, targetStep>, cb: (ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props: props) => ReactNode) => CreatedMultiStepFormComponent<props>;
|
|
139
141
|
/**
|
|
140
142
|
* A HOC for creating a custom not found component for when a step's data is `undefined`.
|
|
141
143
|
* @param options Options for creating the HOC.
|
|
142
144
|
* @param cb The callback function for creating the HOC.
|
|
143
145
|
* @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.
|
|
144
146
|
*/
|
|
145
|
-
withNoStepDataFound: <targetStep extends
|
|
147
|
+
withNoStepDataFound: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: BaseOptions<targetStep>, cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode) => CreatedMultiStepFormComponent<props>;
|
|
146
148
|
};
|
|
147
|
-
|
|
148
|
-
* Create multi step form context with a {@linkcode MultiStepFormSchema} instance.
|
|
149
|
-
* @param schema The {@linkcode MultiStepFormSchema} instance.
|
|
150
|
-
*/
|
|
151
|
-
declare function createMultiStepFormContext<schema extends AnyMultiStepFormSchema, resolvedStep extends MultiStepFormSchema.resolvedStep<schema> = MultiStepFormSchema.resolvedStep<schema>>(schema: schema): MultiStepFormContextResult<schema>;
|
|
149
|
+
declare function createMultiStepFormContext<def extends StepSchema.Config, value extends steps.instantiateSteps<def>>(schema: MultiStepFormSchema$1<def, value>): MultiStepFormContextResult<def, value>;
|
|
152
150
|
//#endregion
|
|
153
151
|
export { CreateHOC, MultiStepFormContextResult, UseCurrentStepBaseResult, UseCurrentStepErrorResult, UseCurrentStepOptions, UseCurrentStepResult, UseCurrentStepSuccessResult, UseProgressBaseOptions, UseProgressOptions, UseProgressResult, createMultiStepFormContext };
|
|
154
152
|
//# sourceMappingURL=create-context.d.cts.map
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { CreateFunction, CreatedMultiStepFormComponent } from "./
|
|
2
|
-
import { AnyMultiStepFormSchema, MultiStepFormSchema } from "./schema.mjs";
|
|
1
|
+
import { CreateFunction, CreatedMultiStepFormComponent } from "./utils.mjs";
|
|
3
2
|
import { UseMultiStepFormData } from "./hooks/use-multi-step-form-data.mjs";
|
|
3
|
+
import { MultiStepFormSchema as MultiStepFormSchema$1 } from "./schema.mjs";
|
|
4
|
+
import { steps } from "@jfdevelops/multi-step-form-core";
|
|
5
|
+
import { StepSchema } from "@jfdevelops/multi-step-form-core/_internals";
|
|
4
6
|
import { ComponentProps, ReactNode } from "react";
|
|
5
7
|
|
|
6
8
|
//#region src/create-context.d.ts
|
|
7
|
-
type BaseOptions<
|
|
9
|
+
type BaseOptions<targetStep extends string> = {
|
|
8
10
|
/**
|
|
9
11
|
* The step to return data from.
|
|
10
12
|
*/
|
|
11
|
-
targetStep:
|
|
13
|
+
targetStep: targetStep;
|
|
12
14
|
};
|
|
13
|
-
type UseCurrentStepOptions<
|
|
15
|
+
type UseCurrentStepOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props, isDataGuaranteed extends boolean = false> = BaseOptions<targetStep> & {
|
|
14
16
|
/**
|
|
15
17
|
* Determines if the result should follow "strictness".
|
|
16
18
|
* The result will change based on the value for this option.
|
|
@@ -53,7 +55,7 @@ type UseCurrentStepOptions<TSchema extends AnyMultiStepFormSchema, TTargetStep e
|
|
|
53
55
|
/**
|
|
54
56
|
* An optional transformation function to provide a custom not found message.
|
|
55
57
|
*/
|
|
56
|
-
notFoundMessage?: CreateFunction<[ctx: BaseOptions<
|
|
58
|
+
notFoundMessage?: CreateFunction<[ctx: BaseOptions<targetStep>, props: props], ReactNode>;
|
|
57
59
|
};
|
|
58
60
|
interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {
|
|
59
61
|
/**
|
|
@@ -77,8 +79,8 @@ interface UseCurrentStepSuccessResult<TData = unknown, TProps = undefined> exten
|
|
|
77
79
|
data: TData;
|
|
78
80
|
hasData: true;
|
|
79
81
|
}
|
|
80
|
-
type UseCurrentStepResult<
|
|
81
|
-
type UseProgressBaseOptions<
|
|
82
|
+
type UseCurrentStepResult<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props, isDataGuaranteed extends boolean = false> = isDataGuaranteed extends true ? Omit<UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>, 'hasData'> : UseCurrentStepErrorResult<steps.getCurrent<value, targetStep>, props> | UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>;
|
|
83
|
+
type UseProgressBaseOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>> = BaseOptions<targetStep> & {
|
|
82
84
|
/**
|
|
83
85
|
* The total amount of steps that are in the form.
|
|
84
86
|
*
|
|
@@ -92,11 +94,11 @@ type UseProgressBaseOptions<TSchema extends AnyMultiStepFormSchema, TTargetStep
|
|
|
92
94
|
*/
|
|
93
95
|
maxProgressValue?: number;
|
|
94
96
|
};
|
|
95
|
-
type UseProgressOptions<
|
|
97
|
+
type UseProgressOptions<def extends StepSchema.Config, value extends steps.instantiateSteps<def>, targetStep extends steps.StepNumbers<value>, props> = UseProgressBaseOptions<def, value, targetStep> & {
|
|
96
98
|
/**
|
|
97
99
|
* An optional transformation function to provide a custom progress text.
|
|
98
100
|
*/
|
|
99
|
-
progressTextTransformer?: CreateFunction<[ctx: Required<UseProgressBaseOptions<
|
|
101
|
+
progressTextTransformer?: CreateFunction<[ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props], ReactNode>;
|
|
100
102
|
};
|
|
101
103
|
type UseProgressResult<props> = {
|
|
102
104
|
/**
|
|
@@ -112,15 +114,15 @@ type UseProgressResult<props> = {
|
|
|
112
114
|
ProgressText: CreatedMultiStepFormComponent<props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props>;
|
|
113
115
|
};
|
|
114
116
|
type CreateHOC<TContext, TProps> = (ctx: TContext, props: TProps) => CreatedMultiStepFormComponent<TProps>;
|
|
115
|
-
type MultiStepFormContextResult<
|
|
116
|
-
useMultiStepFormData: UseMultiStepFormData<
|
|
117
|
+
type MultiStepFormContextResult<def extends StepSchema.Config, value extends steps.instantiateSteps<def>> = {
|
|
118
|
+
useMultiStepFormData: UseMultiStepFormData<def, value>;
|
|
117
119
|
/**
|
|
118
120
|
* Gets the data for the specified step.
|
|
119
121
|
*
|
|
120
122
|
* @returns The data for the given step number.
|
|
121
123
|
*/
|
|
122
|
-
useCurrentStepData: <targetStep extends
|
|
123
|
-
useProgress: <targetStep extends
|
|
124
|
+
useCurrentStepData: <targetStep extends steps.StepNumbers<value>, props = undefined, isDataGuaranteed extends boolean = false>(options: UseCurrentStepOptions<def, value, targetStep, props, isDataGuaranteed>) => UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed>;
|
|
125
|
+
useProgress: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: UseProgressOptions<def, value, targetStep, props>) => UseProgressResult<props>;
|
|
124
126
|
/**
|
|
125
127
|
* A hook that can be used to check if the form can be restarted. If no {@linkcode cb}
|
|
126
128
|
* is provided, the return value will be dictated by if there is an object stored in
|
|
@@ -135,20 +137,16 @@ type MultiStepFormContextResult<TSchema extends AnyMultiStepFormSchema, TResolve
|
|
|
135
137
|
* @param cb The callback function for creating the HOC.
|
|
136
138
|
* @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.
|
|
137
139
|
*/
|
|
138
|
-
withProgressText: <targetStep extends
|
|
140
|
+
withProgressText: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: UseProgressBaseOptions<def, value, targetStep>, cb: (ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props: props) => ReactNode) => CreatedMultiStepFormComponent<props>;
|
|
139
141
|
/**
|
|
140
142
|
* A HOC for creating a custom not found component for when a step's data is `undefined`.
|
|
141
143
|
* @param options Options for creating the HOC.
|
|
142
144
|
* @param cb The callback function for creating the HOC.
|
|
143
145
|
* @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.
|
|
144
146
|
*/
|
|
145
|
-
withNoStepDataFound: <targetStep extends
|
|
147
|
+
withNoStepDataFound: <targetStep extends steps.StepNumbers<value>, props = undefined>(options: BaseOptions<targetStep>, cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode) => CreatedMultiStepFormComponent<props>;
|
|
146
148
|
};
|
|
147
|
-
|
|
148
|
-
* Create multi step form context with a {@linkcode MultiStepFormSchema} instance.
|
|
149
|
-
* @param schema The {@linkcode MultiStepFormSchema} instance.
|
|
150
|
-
*/
|
|
151
|
-
declare function createMultiStepFormContext<schema extends AnyMultiStepFormSchema, resolvedStep extends MultiStepFormSchema.resolvedStep<schema> = MultiStepFormSchema.resolvedStep<schema>>(schema: schema): MultiStepFormContextResult<schema>;
|
|
149
|
+
declare function createMultiStepFormContext<def extends StepSchema.Config, value extends steps.instantiateSteps<def>>(schema: MultiStepFormSchema$1<def, value>): MultiStepFormContextResult<def, value>;
|
|
152
150
|
//#endregion
|
|
153
151
|
export { CreateHOC, MultiStepFormContextResult, UseCurrentStepBaseResult, UseCurrentStepErrorResult, UseCurrentStepOptions, UseCurrentStepResult, UseCurrentStepSuccessResult, UseProgressBaseOptions, UseProgressOptions, UseProgressResult, createMultiStepFormContext };
|
|
154
152
|
//# sourceMappingURL=create-context.d.mts.map
|
package/dist/create-context.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createMultiStepFormDataHook
|
|
2
|
-
import { MultiStepFormStepSchema } from "@jfdevelops/multi-step-form-core";
|
|
1
|
+
import { createMultiStepFormDataHook } from "./hooks/use-multi-step-form-data.mjs";
|
|
2
|
+
import { MultiStepFormStepSchema, createInvariant } from "@jfdevelops/multi-step-form-core";
|
|
3
3
|
import { jsxs } from "react/jsx-runtime";
|
|
4
4
|
|
|
5
5
|
//#region src/create-context.tsx
|
|
@@ -8,10 +8,6 @@ function createComponent(ctx) {
|
|
|
8
8
|
return ((props) => fn(ctx, props));
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Create multi step form context with a {@linkcode MultiStepFormSchema} instance.
|
|
13
|
-
* @param schema The {@linkcode MultiStepFormSchema} instance.
|
|
14
|
-
*/
|
|
15
11
|
function createMultiStepFormContext(schema) {
|
|
16
12
|
const useMultiStepFormData = createMultiStepFormDataHook(schema);
|
|
17
13
|
function useCurrentStepData(options) {
|
|
@@ -37,11 +33,12 @@ function createMultiStepFormContext(schema) {
|
|
|
37
33
|
};
|
|
38
34
|
}
|
|
39
35
|
function useProgress(options) {
|
|
40
|
-
const steps = useMultiStepFormData((data) => data.stepSchema.steps.value.length);
|
|
41
|
-
const { targetStep, maxProgressValue = 100, totalSteps = steps, progressTextTransformer } = options;
|
|
42
|
-
|
|
36
|
+
const steps$1 = useMultiStepFormData((data) => data.stepSchema.steps.value.length);
|
|
37
|
+
const { targetStep, maxProgressValue = 100, totalSteps = steps$1, progressTextTransformer } = options;
|
|
38
|
+
createInvariant("[useProgress]")(schema.getSnapshot().stepSchema.steps.isValidStep(targetStep), "Invalid step number");
|
|
39
|
+
const currentStep = targetStep.replace("step", "");
|
|
43
40
|
return {
|
|
44
|
-
value: currentStep / totalSteps * maxProgressValue,
|
|
41
|
+
value: Number.parseInt(currentStep, 10) / totalSteps * maxProgressValue,
|
|
45
42
|
maxProgressValue,
|
|
46
43
|
ProgressText: progressTextTransformer ? withProgressText({
|
|
47
44
|
targetStep,
|
|
@@ -65,8 +62,8 @@ function createMultiStepFormContext(schema) {
|
|
|
65
62
|
return canRestart;
|
|
66
63
|
}
|
|
67
64
|
function withProgressText(options, cb) {
|
|
68
|
-
const steps = schema.getSnapshot().stepSchema.steps.value.length;
|
|
69
|
-
const { targetStep, maxProgressValue = 100, totalSteps = steps } = options;
|
|
65
|
+
const steps$1 = schema.getSnapshot().stepSchema.steps.value.length;
|
|
66
|
+
const { targetStep, maxProgressValue = 100, totalSteps = steps$1 } = options;
|
|
70
67
|
return createComponent({
|
|
71
68
|
targetStep,
|
|
72
69
|
maxProgressValue,
|
|
@@ -74,8 +71,9 @@ function createMultiStepFormContext(schema) {
|
|
|
74
71
|
})(cb);
|
|
75
72
|
}
|
|
76
73
|
function withNoStepDataFound(options, cb) {
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
const { steps: steps$1 } = schema.getSnapshot().stepSchema;
|
|
75
|
+
createInvariant("[withNoStepDataFound]")(steps$1.isValidStep(options.targetStep), (formatter) => `Invalid step number "${options.targetStep}". Valid steps are: ${formatter.format(steps$1.as("array.string.untyped"))}`);
|
|
76
|
+
return createComponent({ targetStep: options.targetStep })(cb);
|
|
79
77
|
}
|
|
80
78
|
return {
|
|
81
79
|
useMultiStepFormData,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-context.mjs","names":[],"sources":["../src/create-context.tsx"],"sourcesContent":["import { MultiStepFormStepSchema } from '@jfdevelops/multi-step-form-core';\nimport { type ComponentProps, type ReactNode } from 'react';\nimport {\n createMultiStepFormDataHook,\n throwIfInvalidStepNumber,\n UseMultiStepFormData,\n} from './hooks/use-multi-step-form-data';\nimport { MultiStepFormSchema, type AnyMultiStepFormSchema } from './schema';\nimport type {\n CreatedMultiStepFormComponent,\n CreateFunction,\n} from './step-schema';\n\ntype BaseOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n /**\n * The step to return data from.\n */\n targetStep: TTargetStep;\n};\nexport type UseCurrentStepOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props,\n isDataGuaranteed extends boolean = false\n> = BaseOptions<TSchema, TTargetStep> & {\n /**\n * Determines if the result should follow \"strictness\".\n * The result will change based on the value for this option.\n *\n * - `true`: `data` is **defined** and `hasData` isn't available.\n * - `false`: `data` _can be_ `undefined`, but the `hasData` property is available\n * to help with type narrowing.\n *\n * @default false\n * @example\n * ### `true`\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData } = useCurrentStep({\n * stepNumber: 1,\n * isDataGuaranteed: true,\n * })\n *\n * // Notice how `NoCurrentData` is still available\n * // Do things with `data` here\n * }\n * ```\n *\n * ### `false` - The default\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData, hasData } = useCurrentStep({\n * stepNumber: 1,\n * })\n *\n * if (!hasData) {\n * return <NoCurrentData />\n * }\n *\n * // Do things with `data` here\n * }\n * ```\n */\n isDataGuaranteed?: isDataGuaranteed;\n /**\n * An optional transformation function to provide a custom not found message.\n */\n notFoundMessage?: CreateFunction<\n [ctx: BaseOptions<TSchema, TTargetStep>, props: props],\n ReactNode\n >;\n};\nexport interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {\n /**\n * The current step's data.\n */\n data: TData | undefined;\n /**\n * Boolean indicating if the current step has data.\n */\n hasData: boolean;\n /**\n * Component to render some sort of error if `data` isn't defined.\n */\n NoCurrentData: CreatedMultiStepFormComponent<\n TProps extends undefined ? Omit<ComponentProps<'div'>, 'children'> : TProps\n >;\n}\nexport interface UseCurrentStepErrorResult<TData = unknown, TProps = undefined>\n extends UseCurrentStepBaseResult<TData, TProps> {\n data: undefined;\n hasData: false;\n}\nexport interface UseCurrentStepSuccessResult<\n TData = unknown,\n TProps = undefined\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: TData;\n hasData: true;\n}\nexport type UseCurrentStepResult<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props,\n isDataGuaranteed extends boolean = false\n> = isDataGuaranteed extends true\n ? Omit<\n UseCurrentStepSuccessResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >,\n 'hasData'\n >\n :\n | UseCurrentStepErrorResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >\n | UseCurrentStepSuccessResult<\n MultiStepFormSchema.getData<TSchema, TTargetStep>,\n props\n >;\nexport type UseProgressBaseOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>\n> = BaseOptions<TSchema, TTargetStep> & {\n /**\n * The total amount of steps that are in the form.\n *\n * @default schema.stepData.steps.value.length\n */\n totalSteps?: number;\n /**\n * The highest value the progress indicator should go.\n *\n * @default 100\n */\n maxProgressValue?: number;\n};\nexport type UseProgressOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTargetStep extends keyof MultiStepFormSchema.resolvedStep<TSchema>,\n props\n> = UseProgressBaseOptions<TSchema, TTargetStep> & {\n /**\n * An optional transformation function to provide a custom progress text.\n */\n progressTextTransformer?: CreateFunction<\n [ctx: Required<UseProgressBaseOptions<TSchema, TTargetStep>>, props],\n ReactNode\n >;\n};\nexport type UseProgressResult<props> = {\n /**\n * The value of the progress indicator.\n */\n value: number;\n /**\n * The highest value the progress indicator can be.\n *\n * @default 100\n */\n maxProgressValue: number;\n ProgressText: CreatedMultiStepFormComponent<\n props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props\n >;\n};\nexport type CreateHOC<TContext, TProps> = (\n ctx: TContext,\n props: TProps\n) => CreatedMultiStepFormComponent<TProps>;\n\nexport type MultiStepFormContextResult<\n TSchema extends AnyMultiStepFormSchema,\n TResolvedStep extends MultiStepFormSchema.resolvedStep<TSchema> = MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n // MultiStepFormContext: schema;\n // MultiStepFormProvider: (props: { children: ReactNode }) => JSX.Element;\n // useMultiStepFormSchema: schema;\n useMultiStepFormData: UseMultiStepFormData<TSchema>;\n /**\n * Gets the data for the specified step.\n *\n * @returns The data for the given step number.\n */\n useCurrentStepData: <\n targetStep extends keyof TResolvedStep,\n props = undefined,\n isDataGuaranteed extends boolean = false\n >(\n options: UseCurrentStepOptions<TSchema, targetStep, props, isDataGuaranteed>\n ) => UseCurrentStepResult<TSchema, targetStep, props, isDataGuaranteed>;\n useProgress: <targetStep extends keyof TResolvedStep, props = undefined>(\n options: UseProgressOptions<TSchema, targetStep, props>\n ) => UseProgressResult<props>;\n /**\n * A hook that can be used to check if the form can be restarted. If no {@linkcode cb}\n * is provided, the return value will be dictated by if there is an object stored in\n * {@link MultiStepFormSchema#storage}.\n * @param cb A callback function to provide custom logic for if the form can restart.\n * @returns A boolean indicating if the form can restart.\n */\n useCanRestartForm: (cb?: (canRestart: boolean) => boolean) => boolean;\n /**\n * A HOC for creating a custom progress text for `useProgress`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.\n */\n withProgressText: <targetStep extends keyof TResolvedStep, props = undefined>(\n options: UseProgressBaseOptions<TSchema, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<TSchema, targetStep>>,\n props: props\n ) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n /**\n * A HOC for creating a custom not found component for when a step's data is `undefined`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.\n */\n withNoStepDataFound: <\n targetStep extends keyof TResolvedStep,\n props = undefined\n >(\n options: BaseOptions<TSchema, targetStep>,\n cb: (ctx: BaseOptions<TSchema, targetStep>, props: props) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n};\n\nfunction createComponent<ctx>(ctx: ctx) {\n return function <props>(fn: CreateFunction<[ctx, props], ReactNode>) {\n return ((props: props) =>\n fn(ctx, props)) as CreatedMultiStepFormComponent<props>;\n };\n}\n\n/**\n * Create multi step form context with a {@linkcode MultiStepFormSchema} instance.\n * @param schema The {@linkcode MultiStepFormSchema} instance.\n */\n// export function createMultiStepFormContext<\n// schema extends AnyMultiStepFormSchema\n// >(schema: schema): MultiStepFormContextResult<schema>;\n// /**\n// * Create multi step form context without a {@linkcode MultiStepFormSchema} instance.\n// *\n// * The {@linkcode MultiStepFormSchema} instance is returned.\n// * @param options Options to create a new instance of {@linkcode MultiStepFormSchema}.\n// */\n// export function createMultiStepFormContext<\n// step extends Step<casing>,\n// casing extends CasingType = DefaultCasing,\n// storageKey extends string = DefaultStorageKey,\n// resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n// stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n// schema extends MultiStepFormSchema<\n// step,\n// casing,\n// storageKey,\n// resolvedStep,\n// stepNumbers\n// > = MultiStepFormSchema<step, casing, storageKey, resolvedStep, stepNumbers>\n// >(\n// options: MultiStepFormSchemaConfig<\n// step,\n// Constrain<casing, CasingType>,\n// storageKey\n// >\n// ): MultiStepFormContextResult<schema> & {\n// schema: MultiStepFormSchema<step, casing, storageKey>;\n// };\nexport function createMultiStepFormContext<\n schema extends AnyMultiStepFormSchema,\n resolvedStep extends MultiStepFormSchema.resolvedStep<schema> = MultiStepFormSchema.resolvedStep<schema>\n>(schema: schema): MultiStepFormContextResult<schema> {\n // const isInstance = schemaOrOptions instanceof MultiStepFormSchema;\n // const schema: schema = isInstance\n // ? schemaOrOptions\n // : createMultiStepFormSchema(schemaOrOptions);\n // const Context = createContext(schema);\n\n // function Provider({ children }: { children: ReactNode }) {\n // const [observer] = useState(() => new MultiStepFormObserver({ schema }));\n\n // useEffect(() => {\n // const unmount = schema.mount();\n\n // return () => {\n // unmount();\n // observer.destroy();\n // };\n // }, [observer]);\n\n // return <Context.Provider value={observer}>{children}</Context.Provider>;\n // }\n\n // function throwIfInvalidStepNumber(\n // schema: MultiStepFormSchema<step, casing, storageKey>,\n // stepNumber: number\n // ) {\n // const formatter = new Intl.ListFormat('en', {\n // type: 'disjunction',\n // style: 'long',\n // });\n // const { as, isValidStepNumber } = schema.stepSchema.steps;\n\n // invariant(\n // isValidStepNumber(stepNumber),\n // `The step number \"${stepNumber}\" is not a valid step number. Valid step numbers include ${formatter.format(\n // as('array.string.untyped')\n // )}`,\n // TypeError\n // );\n // }\n\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n const useMultiStepFormData = createMultiStepFormDataHook(schema);\n\n function useCurrentStepData<\n targetStep extends keyof resolvedStep,\n props = undefined,\n isDataGuaranteed extends boolean = false\n >(\n options: UseCurrentStepOptions<schema, targetStep, props, isDataGuaranteed>\n ): UseCurrentStepResult<schema, targetStep, props, isDataGuaranteed> {\n const { targetStep, notFoundMessage, isDataGuaranteed } = options;\n const data = useMultiStepFormData({\n targetStep,\n });\n const NoDataFoundComponent = notFoundMessage\n ? withNoStepDataFound({ targetStep }, notFoundMessage)\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>No data found for step {String(targetStep)}</div>\n );\n\n if (isDataGuaranteed) {\n return {\n data,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n if (MultiStepFormStepSchema.hasData(data)) {\n return {\n data,\n hasData: true,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n return {\n data: undefined,\n hasData: false,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n function useProgress<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: UseProgressOptions<schema, targetStep, props>\n ): UseProgressResult<props> {\n const steps = useMultiStepFormData(\n (data) => data.stepSchema.steps.value.length\n );\n const {\n targetStep,\n maxProgressValue = 100,\n totalSteps = steps,\n progressTextTransformer,\n } = options;\n const currentStep = throwIfInvalidStepNumber(schema, targetStep);\n const value = (currentStep / totalSteps) * maxProgressValue;\n const ProgressText = progressTextTransformer\n ? withProgressText(\n { targetStep, maxProgressValue, totalSteps },\n progressTextTransformer\n )\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>\n Step {currentStep}/{totalSteps}\n </div>\n );\n\n return {\n value,\n maxProgressValue,\n ProgressText: ProgressText as never,\n };\n }\n\n function useCanRestartForm(cb?: CreateFunction<[boolean], boolean>) {\n const storage = useMultiStepFormData((data) => data.storage);\n const value = storage.get();\n const canRestart = Boolean(\n value && typeof value === 'object' && Object.keys(value).length > 0\n );\n\n if (cb) {\n return cb(canRestart);\n }\n\n return canRestart;\n }\n\n function withProgressText<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: UseProgressBaseOptions<schema, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<schema, targetStep>>,\n props: props\n ) => ReactNode\n ) {\n const steps = schema.getSnapshot().stepSchema.steps.value.length;\n const { targetStep, maxProgressValue = 100, totalSteps = steps } = options;\n\n return createComponent({ targetStep, maxProgressValue, totalSteps })(cb);\n }\n\n function withNoStepDataFound<\n targetStep extends keyof resolvedStep,\n props = undefined\n >(\n options: BaseOptions<schema, targetStep>,\n cb: (ctx: BaseOptions<schema, targetStep>, props: props) => ReactNode\n ) {\n throwIfInvalidStepNumber(schema, options.targetStep);\n\n return createComponent(options)(cb);\n }\n\n return {\n // MultiStepFormContext: Context,\n useMultiStepFormData,\n useCurrentStepData,\n useProgress,\n useCanRestartForm,\n withProgressText,\n withNoStepDataFound,\n };\n}\n"],"mappings":";;;;;AA0OA,SAAS,gBAAqB,KAAU;AACtC,QAAO,SAAiB,IAA6C;AACnE,WAAS,UACP,GAAG,KAAK,MAAM;;;;;;;AAuCpB,SAAgB,2BAGd,QAAoD;CA0CpD,MAAM,uBAAuB,4BAA4B,OAAO;CAEhE,SAAS,mBAKP,SACmE;EACnE,MAAM,EAAE,YAAY,iBAAiB,qBAAqB;EAC1D,MAAM,OAAO,qBAAqB,EAChC,YACD,CAAC;EACF,MAAM,uBAAuB,kBACzB,oBAAoB,EAAE,YAAY,EAAE,gBAAgB,IACnD,UACC,qBAAC;GAAI,GAAI;cAAO,2BAAwB,OAAO,WAAW;IAAO;AAGvE,MAAI,iBACF,QAAO;GACL;GACA,eAAe;GAChB;AAGH,MAAI,wBAAwB,QAAQ,KAAK,CACvC,QAAO;GACL;GACA,SAAS;GACT,eAAe;GAChB;AAGH,SAAO;GACL,MAAM;GACN,SAAS;GACT,eAAe;GAChB;;CAGH,SAAS,YAIP,SAC0B;EAC1B,MAAM,QAAQ,sBACX,SAAS,KAAK,WAAW,MAAM,MAAM,OACvC;EACD,MAAM,EACJ,YACA,mBAAmB,KACnB,aAAa,OACb,4BACE;EACJ,MAAM,cAAc,yBAAyB,QAAQ,WAAW;AAahE,SAAO;GACL,OAba,cAAc,aAAc;GAczC;GACA,cAdmB,0BACjB,iBACE;IAAE;IAAY;IAAkB;IAAY,EAC5C,wBACD,IACA,UACC,qBAAC;IAAI,GAAI;;KAAO;KACR;KAAY;KAAE;;KAChB;GAOX;;CAGH,SAAS,kBAAkB,IAAyC;EAElE,MAAM,QADU,sBAAsB,SAAS,KAAK,QAAQ,CACtC,KAAK;EAC3B,MAAM,aAAa,QACjB,SAAS,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC,SAAS,EACnE;AAED,MAAI,GACF,QAAO,GAAG,WAAW;AAGvB,SAAO;;CAGT,SAAS,iBAIP,SACA,IAIA;EACA,MAAM,QAAQ,OAAO,aAAa,CAAC,WAAW,MAAM,MAAM;EAC1D,MAAM,EAAE,YAAY,mBAAmB,KAAK,aAAa,UAAU;AAEnE,SAAO,gBAAgB;GAAE;GAAY;GAAkB;GAAY,CAAC,CAAC,GAAG;;CAG1E,SAAS,oBAIP,SACA,IACA;AACA,2BAAyB,QAAQ,QAAQ,WAAW;AAEpD,SAAO,gBAAgB,QAAQ,CAAC,GAAG;;AAGrC,QAAO;EAEL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
|
1
|
+
{"version":3,"file":"create-context.mjs","names":["steps"],"sources":["../src/create-context.tsx"],"sourcesContent":["import {\n createInvariant,\n MultiStepFormStepSchema,\n type Invariant,\n type steps,\n} from '@jfdevelops/multi-step-form-core';\nimport type { StepSchema } from '@jfdevelops/multi-step-form-core/_internals';\nimport { type ComponentProps, type ReactNode } from 'react';\nimport {\n createMultiStepFormDataHook,\n UseMultiStepFormData,\n} from './hooks/use-multi-step-form-data';\nimport { MultiStepFormSchema } from './schema';\nimport type { CreatedMultiStepFormComponent, CreateFunction } from './utils';\n\ntype BaseOptions<targetStep extends string> = {\n /**\n * The step to return data from.\n */\n targetStep: targetStep;\n};\nexport type UseCurrentStepOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n isDataGuaranteed extends boolean = false,\n> = BaseOptions<targetStep> & {\n /**\n * Determines if the result should follow \"strictness\".\n * The result will change based on the value for this option.\n *\n * - `true`: `data` is **defined** and `hasData` isn't available.\n * - `false`: `data` _can be_ `undefined`, but the `hasData` property is available\n * to help with type narrowing.\n *\n * @default false\n * @example\n * ### `true`\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData } = useCurrentStep({\n * stepNumber: 1,\n * isDataGuaranteed: true,\n * })\n *\n * // Notice how `NoCurrentData` is still available\n * // Do things with `data` here\n * }\n * ```\n *\n * ### `false` - The default\n * ```tsx\n * function MyComponent() {\n * const { data, NoCurrentData, hasData } = useCurrentStep({\n * stepNumber: 1,\n * })\n *\n * if (!hasData) {\n * return <NoCurrentData />\n * }\n *\n * // Do things with `data` here\n * }\n * ```\n */\n isDataGuaranteed?: isDataGuaranteed;\n /**\n * An optional transformation function to provide a custom not found message.\n */\n notFoundMessage?: CreateFunction<\n [ctx: BaseOptions<targetStep>, props: props],\n ReactNode\n >;\n};\nexport interface UseCurrentStepBaseResult<TData = unknown, TProps = undefined> {\n /**\n * The current step's data.\n */\n data: TData | undefined;\n /**\n * Boolean indicating if the current step has data.\n */\n hasData: boolean;\n /**\n * Component to render some sort of error if `data` isn't defined.\n */\n NoCurrentData: CreatedMultiStepFormComponent<\n TProps extends undefined ? Omit<ComponentProps<'div'>, 'children'> : TProps\n >;\n}\nexport interface UseCurrentStepErrorResult<\n TData = unknown,\n TProps = undefined,\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: undefined;\n hasData: false;\n}\nexport interface UseCurrentStepSuccessResult<\n TData = unknown,\n TProps = undefined,\n> extends UseCurrentStepBaseResult<TData, TProps> {\n data: TData;\n hasData: true;\n}\nexport type UseCurrentStepResult<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n isDataGuaranteed extends boolean = false,\n> = isDataGuaranteed extends true\n ? Omit<\n UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>,\n 'hasData'\n >\n :\n | UseCurrentStepErrorResult<steps.getCurrent<value, targetStep>, props>\n | UseCurrentStepSuccessResult<steps.getCurrent<value, targetStep>, props>;\nexport type UseProgressBaseOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n> = BaseOptions<targetStep> & {\n /**\n * The total amount of steps that are in the form.\n *\n * @default schema.stepData.steps.value.length\n */\n totalSteps?: number;\n /**\n * The highest value the progress indicator should go.\n *\n * @default 100\n */\n maxProgressValue?: number;\n};\nexport type UseProgressOptions<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n targetStep extends steps.StepNumbers<value>,\n props,\n> = UseProgressBaseOptions<def, value, targetStep> & {\n /**\n * An optional transformation function to provide a custom progress text.\n */\n progressTextTransformer?: CreateFunction<\n [ctx: Required<UseProgressBaseOptions<def, value, targetStep>>, props],\n ReactNode\n >;\n};\nexport type UseProgressResult<props> = {\n /**\n * The value of the progress indicator.\n */\n value: number;\n /**\n * The highest value the progress indicator can be.\n *\n * @default 100\n */\n maxProgressValue: number;\n ProgressText: CreatedMultiStepFormComponent<\n props extends undefined ? Omit<ComponentProps<'div'>, 'children'> : props\n >;\n};\nexport type CreateHOC<TContext, TProps> = (\n ctx: TContext,\n props: TProps\n) => CreatedMultiStepFormComponent<TProps>;\n\nexport type MultiStepFormContextResult<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n> = {\n useMultiStepFormData: UseMultiStepFormData<def, value>;\n /**\n * Gets the data for the specified step.\n *\n * @returns The data for the given step number.\n */\n useCurrentStepData: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n isDataGuaranteed extends boolean = false,\n >(\n options: UseCurrentStepOptions<\n def,\n value,\n targetStep,\n props,\n isDataGuaranteed\n >\n ) => UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed>;\n useProgress: <targetStep extends steps.StepNumbers<value>, props = undefined>(\n options: UseProgressOptions<def, value, targetStep, props>\n ) => UseProgressResult<props>;\n /**\n * A hook that can be used to check if the form can be restarted. If no {@linkcode cb}\n * is provided, the return value will be dictated by if there is an object stored in\n * {@link MultiStepFormSchema#storage}.\n * @param cb A callback function to provide custom logic for if the form can restart.\n * @returns A boolean indicating if the form can restart.\n */\n useCanRestartForm: (cb?: (canRestart: boolean) => boolean) => boolean;\n /**\n * A HOC for creating a custom progress text for `useProgress`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `progressTextTransformer` option of the `useProgress` hook.\n */\n withProgressText: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressBaseOptions<def, value, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<def, value, targetStep>>,\n props: props\n ) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n /**\n * A HOC for creating a custom not found component for when a step's data is `undefined`.\n * @param options Options for creating the HOC.\n * @param cb The callback function for creating the HOC.\n * @returns A HOC for the `notFoundMessage` option of the `useCurrentStep` hook.\n */\n withNoStepDataFound: <\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: BaseOptions<targetStep>,\n cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode\n ) => CreatedMultiStepFormComponent<props>;\n};\n\nfunction createComponent<ctx>(ctx: ctx) {\n return function <props>(fn: CreateFunction<[ctx, props], ReactNode>) {\n return ((props: props) =>\n fn(ctx, props)) as CreatedMultiStepFormComponent<props>;\n };\n}\n\nexport function createMultiStepFormContext<\n def extends StepSchema.Config,\n value extends steps.instantiateSteps<def>,\n>(\n schema: MultiStepFormSchema<def, value>\n): MultiStepFormContextResult<def, value> {\n const useMultiStepFormData = createMultiStepFormDataHook(schema);\n\n function useCurrentStepData<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n isDataGuaranteed extends boolean = false,\n >(\n options: UseCurrentStepOptions<\n def,\n value,\n targetStep,\n props,\n isDataGuaranteed\n >\n ): UseCurrentStepResult<def, value, targetStep, props, isDataGuaranteed> {\n const { targetStep, notFoundMessage, isDataGuaranteed } = options;\n const data = useMultiStepFormData({\n targetStep,\n });\n const NoDataFoundComponent = notFoundMessage\n ? withNoStepDataFound({ targetStep }, notFoundMessage)\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>No data found for step {String(targetStep)}</div>\n );\n\n if (isDataGuaranteed) {\n return {\n data,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n if (MultiStepFormStepSchema.hasData(data)) {\n return {\n data,\n hasData: true,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n return {\n data: undefined,\n hasData: false,\n NoCurrentData: NoDataFoundComponent as never,\n } as never;\n }\n\n function useProgress<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressOptions<def, value, targetStep, props>\n ): UseProgressResult<props> {\n const steps = useMultiStepFormData(\n (data) => data.stepSchema.steps.value.length\n );\n const {\n targetStep,\n maxProgressValue = 100,\n totalSteps = steps,\n progressTextTransformer,\n } = options;\n const invariant: Invariant = createInvariant('[useProgress]');\n\n invariant(\n schema.getSnapshot().stepSchema.steps.isValidStep(targetStep),\n 'Invalid step number'\n );\n\n const currentStep = targetStep.replace('step', '');\n const value =\n (Number.parseInt(currentStep, 10) / totalSteps) * maxProgressValue;\n const ProgressText = progressTextTransformer\n ? withProgressText(\n { targetStep, maxProgressValue, totalSteps },\n progressTextTransformer\n )\n : (props: Omit<ComponentProps<'div'>, 'children'>) => (\n <div {...props}>\n Step {currentStep}/{totalSteps}\n </div>\n );\n\n return {\n value,\n maxProgressValue,\n ProgressText: ProgressText as never,\n };\n }\n\n function useCanRestartForm(cb?: CreateFunction<[boolean], boolean>) {\n const storage = useMultiStepFormData((data) => data.storage);\n const value = storage.get();\n const canRestart = Boolean(\n value && typeof value === 'object' && Object.keys(value).length > 0\n );\n\n if (cb) {\n return cb(canRestart);\n }\n\n return canRestart;\n }\n\n function withProgressText<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: UseProgressBaseOptions<def, value, targetStep>,\n cb: (\n ctx: Required<UseProgressBaseOptions<def, value, targetStep>>,\n props: props\n ) => ReactNode\n ) {\n const steps = schema.getSnapshot().stepSchema.steps.value.length;\n const { targetStep, maxProgressValue = 100, totalSteps = steps } = options;\n\n return createComponent({ targetStep, maxProgressValue, totalSteps })(cb);\n }\n\n function withNoStepDataFound<\n targetStep extends steps.StepNumbers<value>,\n props = undefined,\n >(\n options: BaseOptions<targetStep>,\n cb: (ctx: BaseOptions<targetStep>, props: props) => ReactNode\n ) {\n const { steps } = schema.getSnapshot().stepSchema;\n const invariant: Invariant = createInvariant('[withNoStepDataFound]');\n\n invariant(\n steps.isValidStep(options.targetStep),\n (formatter) =>\n `Invalid step number \"${options.targetStep}\". Valid steps are: ${formatter.format(steps.as('array.string.untyped'))}`\n );\n\n return createComponent({ targetStep: options.targetStep })(cb);\n }\n\n return {\n useMultiStepFormData,\n useCurrentStepData,\n useProgress,\n useCanRestartForm,\n withProgressText,\n withNoStepDataFound,\n };\n}\n"],"mappings":";;;;;AA4OA,SAAS,gBAAqB,KAAU;AACtC,QAAO,SAAiB,IAA6C;AACnE,WAAS,UACP,GAAG,KAAK,MAAM;;;AAIpB,SAAgB,2BAId,QACwC;CACxC,MAAM,uBAAuB,4BAA4B,OAAO;CAEhE,SAAS,mBAKP,SAOuE;EACvE,MAAM,EAAE,YAAY,iBAAiB,qBAAqB;EAC1D,MAAM,OAAO,qBAAqB,EAChC,YACD,CAAC;EACF,MAAM,uBAAuB,kBACzB,oBAAoB,EAAE,YAAY,EAAE,gBAAgB,IACnD,UACC,qBAAC;GAAI,GAAI;cAAO,2BAAwB,OAAO,WAAW;IAAO;AAGvE,MAAI,iBACF,QAAO;GACL;GACA,eAAe;GAChB;AAGH,MAAI,wBAAwB,QAAQ,KAAK,CACvC,QAAO;GACL;GACA,SAAS;GACT,eAAe;GAChB;AAGH,SAAO;GACL,MAAM;GACN,SAAS;GACT,eAAe;GAChB;;CAGH,SAAS,YAIP,SAC0B;EAC1B,MAAMA,UAAQ,sBACX,SAAS,KAAK,WAAW,MAAM,MAAM,OACvC;EACD,MAAM,EACJ,YACA,mBAAmB,KACnB,aAAaA,SACb,4BACE;AAGJ,EAF6B,gBAAgB,gBAAgB,CAG3D,OAAO,aAAa,CAAC,WAAW,MAAM,YAAY,WAAW,EAC7D,sBACD;EAED,MAAM,cAAc,WAAW,QAAQ,QAAQ,GAAG;AAclD,SAAO;GACL,OAbC,OAAO,SAAS,aAAa,GAAG,GAAG,aAAc;GAclD;GACA,cAdmB,0BACjB,iBACE;IAAE;IAAY;IAAkB;IAAY,EAC5C,wBACD,IACA,UACC,qBAAC;IAAI,GAAI;;KAAO;KACR;KAAY;KAAE;;KAChB;GAOX;;CAGH,SAAS,kBAAkB,IAAyC;EAElE,MAAM,QADU,sBAAsB,SAAS,KAAK,QAAQ,CACtC,KAAK;EAC3B,MAAM,aAAa,QACjB,SAAS,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC,SAAS,EACnE;AAED,MAAI,GACF,QAAO,GAAG,WAAW;AAGvB,SAAO;;CAGT,SAAS,iBAIP,SACA,IAIA;EACA,MAAMA,UAAQ,OAAO,aAAa,CAAC,WAAW,MAAM,MAAM;EAC1D,MAAM,EAAE,YAAY,mBAAmB,KAAK,aAAaA,YAAU;AAEnE,SAAO,gBAAgB;GAAE;GAAY;GAAkB;GAAY,CAAC,CAAC,GAAG;;CAG1E,SAAS,oBAIP,SACA,IACA;EACA,MAAM,EAAE,mBAAU,OAAO,aAAa,CAAC;AAGvC,EAF6B,gBAAgB,wBAAwB,CAGnEA,QAAM,YAAY,QAAQ,WAAW,GACpC,cACC,wBAAwB,QAAQ,WAAW,sBAAsB,UAAU,OAAOA,QAAM,GAAG,uBAAuB,CAAC,GACtH;AAED,SAAO,gBAAgB,EAAE,YAAY,QAAQ,YAAY,CAAC,CAAC,GAAG;;AAGhE,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD"}
|
package/dist/field.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.cjs","names":["Field: field.component<
|
|
1
|
+
{"version":3,"file":"field.cjs","names":["Field: field.component<step>","selector"],"sources":["../src/field.tsx"],"sourcesContent":["import type {\n Expand,\n fields,\n HelperFn,\n Override,\n steps,\n UpdateFn,\n Updater,\n} from '@jfdevelops/multi-step-form-core';\nimport type { ReactNode } from 'react';\nimport { memo, useSyncExternalStore } from 'react';\nimport type { SelectorFn } from './hooks/use-selector';\nimport { selector } from './selector';\n\nexport namespace field {\n type sharedProps<TField extends string> = {\n /**\n * The name of the field.\n */\n name: TField;\n };\n\n export type onInputChangeOptions<\n TStrict extends boolean,\n TPartial extends boolean,\n > = UpdateFn.ModeOptions<{\n strict: TStrict;\n partial: TPartial;\n }> &\n UpdateFn.DebugOptions;\n\n export type childrenProps<\n steps extends steps.instantiateSteps,\n field extends fields.getDeepFields<steps, targetStep>,\n targetStep extends steps.StepNumbers<steps> = steps.StepNumbers<steps>,\n value extends fields.resolveDeepPath<steps, targetStep, field> =\n fields.resolveDeepPath<steps, targetStep, field>,\n TConfig extends fields.getConfig<steps, targetStep, field> =\n fields.getConfig<steps, targetStep, field>,\n > = sharedProps<field> &\n (TConfig extends { defaultValue: unknown }\n ? Override<TConfig, 'defaultValue', value>\n : {\n defaultValue: `An unknown error occurred while getting the \"defaultValue\" for ${field}`;\n }) & {\n /**\n * A useful wrapper around `update` to update the specific field.\n * @param value The new value for the field.\n * @param options The options for the update operation.\n */\n onInputChange: <\n strict extends boolean = true,\n partial extends boolean = false,\n >(\n value: Updater<\n UpdateFn.resolvedUpdaterReturnType<\n value,\n { strict: strict; partial: partial },\n {}\n >\n >,\n options?: onInputChangeOptions<strict, partial>\n ) => void;\n /**\n * Resets the field's value to the original value that was\n * defined in the config.\n */\n reset: (options?: UpdateFn.DebugOptions) => void;\n };\n\n export type childrenPropsWithSelected<\n steps extends steps.instantiateSteps,\n field extends fields.getDeepFields<steps, steps.StepNumbers<steps>>,\n TSelected,\n > = childrenProps<steps, field> & {\n selected: {\n /**\n * The result of the `selectorFn`.\n */\n value: TSelected;\n };\n };\n export type props<\n step extends steps.instantiateSteps,\n field extends fields.getDeepFields<step, steps.StepNumbers<step>>,\n selected,\n > = sharedProps<field> & {\n selectorFn?: SelectorFn<step, selected>;\n children: (\n props: [selected] extends [never]\n ? childrenProps<step, field>\n : childrenPropsWithSelected<step, field, selected>\n ) => ReactNode;\n };\n export type component<steps extends steps.instantiateSteps> = <\n field extends fields.getDeepFields<steps, steps.StepNumbers<steps>>,\n selected = never,\n >(\n props: props<steps, field, selected>\n ) => ReactNode;\n\n export type createOptions<step extends steps.instantiateSteps> = {\n propsCreator: <\n field extends fields.getDeepFields<step, steps.StepNumbers<step>>,\n >(\n name: field\n ) => field.childrenProps<step, field>;\n subscribe?: (listener: () => void) => () => void;\n getValue?: <\n field extends fields.getDeepFields<step, steps.StepNumbers<step>>,\n >(\n name: field\n ) => fields.resolveDeepPath<step, steps.StepNumbers<step>, field>;\n selectorCtx: Expand<HelperFn.buildCtx<step, [steps.StepNumbers<step>]>>;\n };\n\n /**\n * Create a field.\n * @param propsCreator\n * @param subscribe - Optional subscription function for reactivity\n * @param getValue - Optional function to get the current field value reactively\n * @returns\n */\n export function create<step extends steps.instantiateSteps>(\n options: createOptions<step>\n ) {\n const { propsCreator, subscribe, getValue, selectorCtx } = options;\n\n const Field: field.component<step> = (props) => {\n const { name, children, selectorFn } = props;\n\n // Always call the hook, but use no-op functions if subscribe/getValue aren't provided\n const subscribeFn = subscribe || (() => () => {});\n const getValueFn = getValue || (() => undefined);\n\n // Subscribe to changes to trigger rerenders\n const currentValue = useSyncExternalStore(\n subscribeFn,\n () => getValueFn(name),\n () => getValueFn(name)\n );\n\n let createdProps = propsCreator(name);\n\n // If getValue is provided, override defaultValue with the reactive value\n if (getValue) {\n createdProps = {\n ...createdProps,\n defaultValue: currentValue,\n } as never;\n }\n\n if (selectorFn) {\n const Selector = selector.create<step>(() => selectorCtx, subscribeFn);\n\n return (\n <Selector selector={selectorFn}>\n {(value) =>\n children({\n ...createdProps,\n selected: { value: value as never },\n } as never)\n }\n </Selector>\n );\n }\n\n return children(createdProps as never);\n };\n\n return memo(Field);\n }\n}\n"],"mappings":";;;;;;;CA2HS,SAAS,OACd,SACA;EACA,MAAM,EAAE,cAAc,WAAW,UAAU,gBAAgB;EAE3D,MAAMA,SAAgC,UAAU;GAC9C,MAAM,EAAE,MAAM,UAAU,eAAe;GAGvC,MAAM,cAAc,0BAA0B;GAC9C,MAAM,aAAa,mBAAmB;GAGtC,MAAM,+CACJ,mBACM,WAAW,KAAK,QAChB,WAAW,KAAK,CACvB;GAED,IAAI,eAAe,aAAa,KAAK;AAGrC,OAAI,SACF,gBAAe;IACb,GAAG;IACH,cAAc;IACf;AAGH,OAAI,WAGF,QACE,2CAHeC,0BAAS,aAAmB,aAAa,YAAY;IAG1D,UAAU;eAChB,UACA,SAAS;KACP,GAAG;KACH,UAAU,EAAS,OAAgB;KACpC,CAAU;KAEJ;AAIf,UAAO,SAAS,aAAsB;;AAGxC,yBAAY,MAAM"}
|
package/dist/field.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SelectorFn } from "./hooks/use-selector.cjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Expand, HelperFn, Override, UpdateFn, Updater, fields } from "@jfdevelops/multi-step-form-core";
|
|
3
3
|
import * as react0 from "react";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
5
|
|
|
@@ -15,17 +15,17 @@ declare namespace field {
|
|
|
15
15
|
strict: TStrict;
|
|
16
16
|
partial: TPartial;
|
|
17
17
|
}> & UpdateFn.DebugOptions;
|
|
18
|
-
export type childrenProps<
|
|
18
|
+
export type childrenProps<steps$1 extends steps$1.instantiateSteps, field$1 extends fields.getDeepFields<steps$1, targetStep>, targetStep extends steps$1.StepNumbers<steps$1> = steps$1.StepNumbers<steps$1>, value extends fields.resolveDeepPath<steps$1, targetStep, field$1> = fields.resolveDeepPath<steps$1, targetStep, field$1>, TConfig extends fields.getConfig<steps$1, targetStep, field$1> = fields.getConfig<steps$1, targetStep, field$1>> = sharedProps<field$1> & (TConfig extends {
|
|
19
19
|
defaultValue: unknown;
|
|
20
|
-
} ? Override<TConfig, 'defaultValue',
|
|
21
|
-
defaultValue: `An unknown error occurred while getting the "defaultValue" for ${
|
|
20
|
+
} ? Override<TConfig, 'defaultValue', value> : {
|
|
21
|
+
defaultValue: `An unknown error occurred while getting the "defaultValue" for ${field$1}`;
|
|
22
22
|
}) & {
|
|
23
23
|
/**
|
|
24
24
|
* A useful wrapper around `update` to update the specific field.
|
|
25
25
|
* @param value The new value for the field.
|
|
26
26
|
* @param options The options for the update operation.
|
|
27
27
|
*/
|
|
28
|
-
onInputChange: <strict extends boolean = true, partial extends boolean = false>(value: Updater<UpdateFn.resolvedUpdaterReturnType<
|
|
28
|
+
onInputChange: <strict extends boolean = true, partial extends boolean = false>(value: Updater<UpdateFn.resolvedUpdaterReturnType<value, {
|
|
29
29
|
strict: strict;
|
|
30
30
|
partial: partial;
|
|
31
31
|
}, {}>>, options?: onInputChangeOptions<strict, partial>) => void;
|
|
@@ -35,7 +35,7 @@ declare namespace field {
|
|
|
35
35
|
*/
|
|
36
36
|
reset: (options?: UpdateFn.DebugOptions) => void;
|
|
37
37
|
};
|
|
38
|
-
export type childrenPropsWithSelected<
|
|
38
|
+
export type childrenPropsWithSelected<steps$1 extends steps$1.instantiateSteps, field$1 extends fields.getDeepFields<steps$1, steps$1.StepNumbers<steps$1>>, TSelected> = childrenProps<steps$1, field$1> & {
|
|
39
39
|
selected: {
|
|
40
40
|
/**
|
|
41
41
|
* The result of the `selectorFn`.
|
|
@@ -43,16 +43,16 @@ declare namespace field {
|
|
|
43
43
|
value: TSelected;
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
|
-
export type props<
|
|
47
|
-
selectorFn?: SelectorFn<
|
|
48
|
-
children: (props: [
|
|
46
|
+
export type props<step extends steps$1.instantiateSteps, field$1 extends fields.getDeepFields<step, steps$1.StepNumbers<step>>, selected> = sharedProps<field$1> & {
|
|
47
|
+
selectorFn?: SelectorFn<step, selected>;
|
|
48
|
+
children: (props: [selected] extends [never] ? childrenProps<step, field$1> : childrenPropsWithSelected<step, field$1, selected>) => ReactNode;
|
|
49
49
|
};
|
|
50
|
-
export type component<
|
|
51
|
-
export type createOptions<
|
|
52
|
-
propsCreator: <
|
|
50
|
+
export type component<steps$1 extends steps$1.instantiateSteps> = <field$1 extends fields.getDeepFields<steps$1, steps$1.StepNumbers<steps$1>>, selected = never>(props: props<steps$1, field$1, selected>) => ReactNode;
|
|
51
|
+
export type createOptions<step extends steps$1.instantiateSteps> = {
|
|
52
|
+
propsCreator: <field$1 extends fields.getDeepFields<step, steps$1.StepNumbers<step>>>(name: field$1) => field$1.childrenProps<step, field$1>;
|
|
53
53
|
subscribe?: (listener: () => void) => () => void;
|
|
54
|
-
getValue?: <
|
|
55
|
-
selectorCtx: Expand<
|
|
54
|
+
getValue?: <field$1 extends fields.getDeepFields<step, steps$1.StepNumbers<step>>>(name: field$1) => fields.resolveDeepPath<step, steps$1.StepNumbers<step>, field$1>;
|
|
55
|
+
selectorCtx: Expand<HelperFn.buildCtx<step, [steps$1.StepNumbers<step>]>>;
|
|
56
56
|
};
|
|
57
57
|
/**
|
|
58
58
|
* Create a field.
|
|
@@ -61,7 +61,7 @@ declare namespace field {
|
|
|
61
61
|
* @param getValue - Optional function to get the current field value reactively
|
|
62
62
|
* @returns
|
|
63
63
|
*/
|
|
64
|
-
export function create<
|
|
64
|
+
export function create<step extends steps$1.instantiateSteps>(options: createOptions<step>): react0.MemoExoticComponent<component<step>>;
|
|
65
65
|
export {};
|
|
66
66
|
}
|
|
67
67
|
//#endregion
|