@jfdevelops/react-multi-step-form 1.0.0-alpha.22 → 1.0.0-alpha.24
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 +92 -0
- package/dist/create-context.cjs.map +1 -0
- package/dist/create-context.d.cts +154 -0
- package/dist/create-context.d.mts +154 -0
- package/dist/create-context.mjs +92 -0
- package/dist/create-context.mjs.map +1 -0
- package/dist/field.cjs +30 -0
- package/dist/field.cjs.map +1 -0
- package/dist/field.d.cts +40 -0
- package/dist/field.d.mts +40 -0
- package/dist/field.mjs +25 -0
- package/dist/field.mjs.map +1 -0
- package/dist/form-config.cjs +32 -0
- package/dist/form-config.cjs.map +1 -0
- package/dist/form-config.d.cts +160 -0
- package/dist/form-config.d.mts +160 -0
- package/dist/form-config.mjs +27 -0
- package/dist/form-config.mjs.map +1 -0
- package/dist/hooks/use-multi-step-form-data.cjs +41 -0
- package/dist/hooks/use-multi-step-form-data.cjs.map +1 -0
- package/dist/hooks/use-multi-step-form-data.d.cts +28 -0
- package/dist/hooks/use-multi-step-form-data.d.mts +28 -0
- package/dist/hooks/use-multi-step-form-data.mjs +39 -0
- package/dist/hooks/use-multi-step-form-data.mjs.map +1 -0
- package/dist/hooks/use-selector.cjs +16 -0
- package/dist/hooks/use-selector.cjs.map +1 -0
- package/dist/hooks/use-selector.d.cts +9 -0
- package/dist/hooks/use-selector.d.mts +9 -0
- package/dist/hooks/use-selector.mjs +16 -0
- package/dist/hooks/use-selector.mjs.map +1 -0
- package/dist/index.cjs +17 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +6 -0
- package/dist/schema.cjs +45 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +34 -0
- package/dist/schema.d.mts +34 -0
- package/dist/schema.mjs +44 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/selector.cjs +27 -0
- package/dist/selector.cjs.map +1 -0
- package/dist/selector.d.cts +30 -0
- package/dist/selector.d.mts +30 -0
- package/dist/selector.mjs +22 -0
- package/dist/selector.mjs.map +1 -0
- package/dist/step-schema.cjs +229 -0
- package/dist/step-schema.cjs.map +1 -0
- package/dist/step-schema.d.cts +164 -0
- package/dist/step-schema.d.mts +164 -0
- package/dist/step-schema.mjs +222 -0
- package/dist/step-schema.mjs.map +1 -0
- package/dist/utils.cjs +34 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.mjs +33 -0
- package/dist/utils.mjs.map +1 -0
- package/package.json +2 -2
package/dist/field.d.cts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AnyResolvedStep, Override, Updater, fields } from "@jfdevelops/multi-step-form-core";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/field.d.ts
|
|
5
|
+
declare namespace field {
|
|
6
|
+
type sharedProps<TField extends string> = {
|
|
7
|
+
/**
|
|
8
|
+
* The name of the field.
|
|
9
|
+
*/
|
|
10
|
+
name: TField;
|
|
11
|
+
};
|
|
12
|
+
export type childrenProps<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep, TField extends fields.getDeep<TResolvedStep, TTargetStep>, TValue extends fields.resolveDeepPath<TResolvedStep, TTargetStep, TField> = fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>> = sharedProps<TField> & Override<fields.get<TResolvedStep, TTargetStep>[fields.parentOf<TField>], 'defaultValue', TValue> & {
|
|
13
|
+
/**
|
|
14
|
+
* A useful wrapper around `update` to update the specific field.
|
|
15
|
+
* @param value The new value for the field.
|
|
16
|
+
*/
|
|
17
|
+
onInputChange: (value: Updater<TValue>) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Resets the field's value to the original value that was
|
|
20
|
+
* defined in the config.
|
|
21
|
+
*/
|
|
22
|
+
reset: () => void;
|
|
23
|
+
};
|
|
24
|
+
export type props<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep, TField extends fields.getDeep<TResolvedStep, TTargetStep>> = sharedProps<TField> & {
|
|
25
|
+
children: (props: childrenProps<TResolvedStep, TTargetStep, TField>) => ReactNode;
|
|
26
|
+
};
|
|
27
|
+
export type component<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep> = <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(props: props<TResolvedStep, TTargetStep, TField>) => ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Create a field.
|
|
30
|
+
* @param propsCreator
|
|
31
|
+
* @param subscribe - Optional subscription function for reactivity
|
|
32
|
+
* @param getValue - Optional function to get the current field value reactively
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
export function create<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep>(propsCreator: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(name: TField) => field.childrenProps<TResolvedStep, TTargetStep, TField>, subscribe?: (listener: () => void) => () => void, getValue?: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(name: TField) => fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>): component<TResolvedStep, TTargetStep>;
|
|
36
|
+
export {};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { field };
|
|
40
|
+
//# sourceMappingURL=field.d.cts.map
|
package/dist/field.d.mts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AnyResolvedStep, Override, Updater, fields } from "@jfdevelops/multi-step-form-core";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/field.d.ts
|
|
5
|
+
declare namespace field {
|
|
6
|
+
type sharedProps<TField extends string> = {
|
|
7
|
+
/**
|
|
8
|
+
* The name of the field.
|
|
9
|
+
*/
|
|
10
|
+
name: TField;
|
|
11
|
+
};
|
|
12
|
+
export type childrenProps<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep, TField extends fields.getDeep<TResolvedStep, TTargetStep>, TValue extends fields.resolveDeepPath<TResolvedStep, TTargetStep, TField> = fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>> = sharedProps<TField> & Override<fields.get<TResolvedStep, TTargetStep>[fields.parentOf<TField>], 'defaultValue', TValue> & {
|
|
13
|
+
/**
|
|
14
|
+
* A useful wrapper around `update` to update the specific field.
|
|
15
|
+
* @param value The new value for the field.
|
|
16
|
+
*/
|
|
17
|
+
onInputChange: (value: Updater<TValue>) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Resets the field's value to the original value that was
|
|
20
|
+
* defined in the config.
|
|
21
|
+
*/
|
|
22
|
+
reset: () => void;
|
|
23
|
+
};
|
|
24
|
+
export type props<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep, TField extends fields.getDeep<TResolvedStep, TTargetStep>> = sharedProps<TField> & {
|
|
25
|
+
children: (props: childrenProps<TResolvedStep, TTargetStep, TField>) => ReactNode;
|
|
26
|
+
};
|
|
27
|
+
export type component<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep> = <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(props: props<TResolvedStep, TTargetStep, TField>) => ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Create a field.
|
|
30
|
+
* @param propsCreator
|
|
31
|
+
* @param subscribe - Optional subscription function for reactivity
|
|
32
|
+
* @param getValue - Optional function to get the current field value reactively
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
export function create<TResolvedStep extends AnyResolvedStep, TTargetStep extends keyof TResolvedStep>(propsCreator: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(name: TField) => field.childrenProps<TResolvedStep, TTargetStep, TField>, subscribe?: (listener: () => void) => () => void, getValue?: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(name: TField) => fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>): component<TResolvedStep, TTargetStep>;
|
|
36
|
+
export {};
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { field };
|
|
40
|
+
//# sourceMappingURL=field.d.mts.map
|
package/dist/field.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { memo, useSyncExternalStore } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/field.tsx
|
|
4
|
+
let field;
|
|
5
|
+
(function(_field) {
|
|
6
|
+
function create(propsCreator, subscribe, getValue) {
|
|
7
|
+
return memo((props) => {
|
|
8
|
+
const { children, name } = props;
|
|
9
|
+
const subscribeFn = subscribe || (() => () => {});
|
|
10
|
+
const getValueFn = getValue || (() => void 0);
|
|
11
|
+
const currentValue = useSyncExternalStore(subscribeFn, () => getValueFn(name), () => getValueFn(name));
|
|
12
|
+
let createdProps = propsCreator(name);
|
|
13
|
+
if (getValue) createdProps = {
|
|
14
|
+
...createdProps,
|
|
15
|
+
defaultValue: currentValue
|
|
16
|
+
};
|
|
17
|
+
return children(createdProps);
|
|
18
|
+
}, (prevProps, nextProps) => prevProps.name === nextProps.name);
|
|
19
|
+
}
|
|
20
|
+
_field.create = create;
|
|
21
|
+
})(field || (field = {}));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { field };
|
|
25
|
+
//# sourceMappingURL=field.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.mjs","names":[],"sources":["../src/field.tsx"],"sourcesContent":["import type {\n AnyResolvedStep,\n fields,\n Override,\n Updater,\n} from '@jfdevelops/multi-step-form-core';\nimport type { ReactNode } from 'react';\nimport { memo, useSyncExternalStore } from 'react';\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 childrenProps<\n TResolvedStep extends AnyResolvedStep,\n TTargetStep extends keyof TResolvedStep,\n TField extends fields.getDeep<TResolvedStep, TTargetStep>,\n TValue extends fields.resolveDeepPath<\n TResolvedStep,\n TTargetStep,\n TField\n > = fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>\n > = sharedProps<TField> &\n Override<\n fields.get<TResolvedStep, TTargetStep>[fields.parentOf<TField>],\n 'defaultValue',\n TValue\n > & {\n /**\n * A useful wrapper around `update` to update the specific field.\n * @param value The new value for the field.\n */\n onInputChange: (value: Updater<TValue>) => void;\n /**\n * Resets the field's value to the original value that was\n * defined in the config.\n */\n reset: () => void;\n };\n export type props<\n TResolvedStep extends AnyResolvedStep,\n TTargetStep extends keyof TResolvedStep,\n TField extends fields.getDeep<TResolvedStep, TTargetStep>\n > = sharedProps<TField> & {\n children: (\n props: childrenProps<TResolvedStep, TTargetStep, TField>\n ) => ReactNode;\n };\n export type component<\n TResolvedStep extends AnyResolvedStep,\n TTargetStep extends keyof TResolvedStep\n > = <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(\n props: props<TResolvedStep, TTargetStep, TField>\n ) => ReactNode;\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<\n TResolvedStep extends AnyResolvedStep,\n TTargetStep extends keyof TResolvedStep\n >(\n propsCreator: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(\n name: TField\n ) => field.childrenProps<TResolvedStep, TTargetStep, TField>,\n subscribe?: (listener: () => void) => () => void,\n getValue?: <TField extends fields.getDeep<TResolvedStep, TTargetStep>>(\n name: TField\n ) => fields.resolveDeepPath<TResolvedStep, TTargetStep, TField>\n ) {\n const Field: field.component<TResolvedStep, TTargetStep> = memo(\n (props) => {\n const { children, name } = 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 typeof createdProps;\n }\n\n return children(createdProps);\n },\n // Custom comparison: only compare the `name` prop\n // The `children` function will always be a new reference, but that's okay\n // because we only re-render when the field value changes (via useSyncExternalStore)\n // or when the `name` prop changes\n (prevProps, nextProps) => prevProps.name === nextProps.name\n );\n\n return Field;\n }\n}\n"],"mappings":";;;;;CAkES,SAAS,OAId,cAGA,WACA,UAGA;AAmCA,SAlC2D,MACxD,UAAU;GACT,MAAM,EAAE,UAAU,SAAS;GAG3B,MAAM,cAAc,0BAA0B;GAC9C,MAAM,aAAa,mBAAmB;GAGtC,MAAM,eAAe,qBACnB,mBACM,WAAW,KAAK,QAChB,WAAW,KAAK,CACvB;GAED,IAAI,eAAe,aAAa,KAAK;AAGrC,OAAI,SACF,gBAAe;IACb,GAAG;IACH,cAAc;IACf;AAGH,UAAO,SAAS,aAAa;MAM9B,WAAW,cAAc,UAAU,SAAS,UAAU,KACxD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
2
|
+
|
|
3
|
+
//#region src/form-config.tsx
|
|
4
|
+
let MultiStepFormSchemaConfig;
|
|
5
|
+
(function(_MultiStepFormSchemaConfig) {
|
|
6
|
+
_MultiStepFormSchemaConfig.DEFAULT_FORM_ALIAS = "Form";
|
|
7
|
+
function isFormAvailable(target, enabledFor) {
|
|
8
|
+
if (Array.isArray(target)) {
|
|
9
|
+
if (enabledFor === "all") return true;
|
|
10
|
+
if (typeof enabledFor === "object" && !Array.isArray(enabledFor)) return Object.keys(enabledFor).some((key) => target.includes(key));
|
|
11
|
+
if (Array.isArray(enabledFor)) return enabledFor.some((key) => target.includes(key));
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
_MultiStepFormSchemaConfig.isFormAvailable = isFormAvailable;
|
|
16
|
+
function createDefaultForm(id) {
|
|
17
|
+
return (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("form", {
|
|
18
|
+
id,
|
|
19
|
+
...props
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
_MultiStepFormSchemaConfig.createDefaultForm = createDefaultForm;
|
|
23
|
+
})(MultiStepFormSchemaConfig || (MultiStepFormSchemaConfig = {}));
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
Object.defineProperty(exports, 'MultiStepFormSchemaConfig', {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function () {
|
|
29
|
+
return MultiStepFormSchemaConfig;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=form-config.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-config.cjs","names":[],"sources":["../src/form-config.tsx"],"sourcesContent":["import type {\n Expand,\n HelperFnChosenSteps,\n StepNumbers,\n ValidStepKey,\n} from '@jfdevelops/multi-step-form-core';\nimport type { ComponentPropsWithRef, JSX } from 'react';\nimport type {\n AnyResolvedStep,\n CreatedMultiStepFormComponent,\n} from './step-schema';\n\nexport namespace MultiStepFormSchemaConfig {\n export const DEFAULT_FORM_ALIAS = 'Form';\n export type defaultEnabledFor = HelperFnChosenSteps.defaultStringOption;\n export type defaultFormAlias = typeof DEFAULT_FORM_ALIAS;\n export type formEnabledFor<TResolvedStep extends AnyResolvedStep> =\n HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>;\n type strippedResolvedSteps<T extends AnyResolvedStep> = {\n [_ in keyof T]: Expand<Omit<T[_], 'createComponent' | 'createHelperFn'>>;\n };\n export type AvailableStepForForm<\n TResolvedStep extends AnyResolvedStep,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n > = TEnabledFor extends defaultEnabledFor\n ? strippedResolvedSteps<TResolvedStep>\n : TEnabledFor extends [\n ValidStepKey<StepNumbers<TResolvedStep>>,\n ...ValidStepKey<StepNumbers<TResolvedStep>>[]\n ]\n ? TEnabledFor[number] extends keyof TResolvedStep\n ? Pick<strippedResolvedSteps<TResolvedStep>, TEnabledFor[number]>\n : never\n : keyof TEnabledFor extends keyof TResolvedStep\n ? Expand<\n Pick<\n strippedResolvedSteps<TResolvedStep>,\n Extract<keyof TResolvedStep, keyof TEnabledFor>\n >\n >\n : never;\n export type formCtx<TAlias extends string, TProps> = {\n [_ in TAlias]: CreatedMultiStepFormComponent<TProps>;\n };\n export type renderFnData<\n TResolvedStep extends AnyResolvedStep,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n > = {\n /**\n * The id for the form, either a custom one or the default one.\n */\n id: string;\n /**\n * The chosen steps that are available.\n */\n steps: Expand<AvailableStepForForm<TResolvedStep, TEnabledFor>>;\n };\n\n /**\n * The configuration options for the `form` option.\n */\n export interface FormConfig<\n TResolvedStep extends AnyResolvedStep,\n TAlias extends string,\n TFormEnabledFor extends formEnabledFor<TResolvedStep>,\n TCustomFormProps extends object\n > {\n /**\n * The `id` for the form component.\n *\n * If there is no value provided, the default id will the **current step key**.\n *\n * @default `${currentStep}`\n */\n id?: string;\n /**\n * The \"name\" of the form component.\n * @default 'Form'\n * @example\n * ```tsx\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render() {\n * // return custom form component here\n * }\n * }\n * }\n * })\n *\n * const Step1 = schema.stepSchema.step1.createComponent(\n * ({ ctx, MyCustomForm }, props: { children: ReactNode }) =>\n * // Notice how the form is available with its alias\n * <MyCustomFormName>{children}</MyCustomFormName>\n * )\n * ```\n */\n alias?: TAlias;\n /**\n * If the form component should be accessible for each step when calling `createComponent`.\n *\n * If no value is given, the form will be accessible for all the steps.\n */\n enabledForSteps?: TFormEnabledFor;\n /**\n *\n * @param data The data that is available for creating the custom form.\n * @param props Props that can be used for the custom form.\n * @returns An {@see JSX.Element} that is the custom form.\n * @example\n * ### With custom props\n * ```tsx\n * type CustomProps = {\n * title: string;\n * description?: string;\n * children: ReactNode;\n * };\n *\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render(data, props: CustomProps) {\n * return (\n * <div>\n * <h1>{props.title}</h1>\n * <p>{props.description}</p>\n * <form>{props.children}</form>\n * </div>\n * );\n * }\n * }\n * }\n * })\n * ```\n * ### Without custom props\n * ```tsx\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render(data, props) {\n * // The default type for `props` will be `ComponentPropsWithRef<'form'>`\n * // return custom form component here\n * }\n * }\n * }\n * })\n * ```\n */\n render: (\n data: renderFnData<TResolvedStep, TFormEnabledFor>,\n props: TCustomFormProps\n ) => JSX.Element;\n }\n\n export interface Form<\n TResolvedStep extends AnyResolvedStep,\n TAlias extends string,\n TFormEnabledFor extends formEnabledFor<TResolvedStep>,\n TCustomFormProps extends object\n > {\n form?: FormConfig<TResolvedStep, TAlias, TFormEnabledFor, TCustomFormProps>;\n }\n\n /**\n * Compares {@linkcode enabledFor} to the {@linkcode target} to determine if the form\n * should be available.\n * @param target The target steps the form _should_ be available for.\n * @param enabledFor The steps that the form _is_ enabled for.\n * @returns A boolean representing if the form should be available.\n */\n // Note: the implementation is specific to `MultiStepFormStepSchema.createComponentForStep`\n // because the `target` will always be an `Array` in `MultiStepFormStepSchema.createComponentForStep`.\n // TODO add validation to keys\n export function isFormAvailable<\n TResolvedStep extends AnyResolvedStep,\n TTarget extends HelperFnChosenSteps<\n TResolvedStep,\n StepNumbers<TResolvedStep>\n >,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n >(target: TTarget, enabledFor: TEnabledFor) {\n if (Array.isArray(target)) {\n if (enabledFor === 'all') {\n return true;\n }\n\n if (typeof enabledFor === 'object' && !Array.isArray(enabledFor)) {\n return Object.keys(enabledFor).some((key) =>\n target.includes(key as `step${StepNumbers<TResolvedStep>}`)\n );\n }\n\n if (Array.isArray(enabledFor)) {\n return enabledFor.some((key) => target.includes(key));\n }\n }\n\n return false;\n }\n\n /**\n * Creates a form component with a default id.\n * @param id The default id for the form.\n * @returns A form component with a default {@linkcode id}.\n */\n export function createDefaultForm(id: string) {\n return (props: Omit<ComponentPropsWithRef<'form'>, 'id'>) => (\n <form id={id} {...props} />\n );\n }\n}\n"],"mappings":";;;;;iDAaoC;CA2L3B,SAAS,gBAOd,QAAiB,YAAyB;AAC1C,MAAI,MAAM,QAAQ,OAAO,EAAE;AACzB,OAAI,eAAe,MACjB,QAAO;AAGT,OAAI,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,WAAW,CAC9D,QAAO,OAAO,KAAK,WAAW,CAAC,MAAM,QACnC,OAAO,SAAS,IAA2C,CAC5D;AAGH,OAAI,MAAM,QAAQ,WAAW,CAC3B,QAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,IAAI,CAAC;;AAIzD,SAAO;;;CAQF,SAAS,kBAAkB,IAAY;AAC5C,UAAQ,UACN,2CAAC;GAAS;GAAI,GAAI;IAAS"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { AnyResolvedStep as AnyResolvedStep$1, CreatedMultiStepFormComponent } from "./step-schema.cjs";
|
|
2
|
+
import { Expand, HelperFnChosenSteps, StepNumbers, ValidStepKey } from "@jfdevelops/multi-step-form-core";
|
|
3
|
+
import { ComponentPropsWithRef, JSX } from "react";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/form-config.d.ts
|
|
7
|
+
declare namespace MultiStepFormSchemaConfig {
|
|
8
|
+
export const DEFAULT_FORM_ALIAS = "Form";
|
|
9
|
+
export type defaultEnabledFor = HelperFnChosenSteps.defaultStringOption;
|
|
10
|
+
export type defaultFormAlias = typeof DEFAULT_FORM_ALIAS;
|
|
11
|
+
export type formEnabledFor<TResolvedStep extends AnyResolvedStep$1> = HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>;
|
|
12
|
+
type strippedResolvedSteps<T extends AnyResolvedStep$1> = { [_ in keyof T]: Expand<Omit<T[_], 'createComponent' | 'createHelperFn'>> };
|
|
13
|
+
export type AvailableStepForForm<TResolvedStep extends AnyResolvedStep$1, TEnabledFor extends formEnabledFor<TResolvedStep>> = TEnabledFor extends defaultEnabledFor ? strippedResolvedSteps<TResolvedStep> : TEnabledFor extends [ValidStepKey<StepNumbers<TResolvedStep>>, ...ValidStepKey<StepNumbers<TResolvedStep>>[]] ? TEnabledFor[number] extends keyof TResolvedStep ? Pick<strippedResolvedSteps<TResolvedStep>, TEnabledFor[number]> : never : keyof TEnabledFor extends keyof TResolvedStep ? Expand<Pick<strippedResolvedSteps<TResolvedStep>, Extract<keyof TResolvedStep, keyof TEnabledFor>>> : never;
|
|
14
|
+
export type formCtx<TAlias extends string, TProps> = { [_ in TAlias]: CreatedMultiStepFormComponent<TProps> };
|
|
15
|
+
export type renderFnData<TResolvedStep extends AnyResolvedStep$1, TEnabledFor extends formEnabledFor<TResolvedStep>> = {
|
|
16
|
+
/**
|
|
17
|
+
* The id for the form, either a custom one or the default one.
|
|
18
|
+
*/
|
|
19
|
+
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* The chosen steps that are available.
|
|
22
|
+
*/
|
|
23
|
+
steps: Expand<AvailableStepForForm<TResolvedStep, TEnabledFor>>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The configuration options for the `form` option.
|
|
27
|
+
*/
|
|
28
|
+
export interface FormConfig<TResolvedStep extends AnyResolvedStep$1, TAlias extends string, TFormEnabledFor extends formEnabledFor<TResolvedStep>, TCustomFormProps extends object> {
|
|
29
|
+
/**
|
|
30
|
+
* The `id` for the form component.
|
|
31
|
+
*
|
|
32
|
+
* If there is no value provided, the default id will the **current step key**.
|
|
33
|
+
*
|
|
34
|
+
* @default `${currentStep}`
|
|
35
|
+
*/
|
|
36
|
+
id?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The "name" of the form component.
|
|
39
|
+
* @default 'Form'
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* const schema = createMultiStepFormSchema({
|
|
43
|
+
* steps: {
|
|
44
|
+
* step1: {
|
|
45
|
+
* title: 'Step 1',
|
|
46
|
+
* fields: {
|
|
47
|
+
* firstName: {
|
|
48
|
+
* defaultValue: ''
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* },
|
|
52
|
+
* form: {
|
|
53
|
+
* alias: 'MyCustomForm',
|
|
54
|
+
* render() {
|
|
55
|
+
* // return custom form component here
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* })
|
|
60
|
+
*
|
|
61
|
+
* const Step1 = schema.stepSchema.step1.createComponent(
|
|
62
|
+
* ({ ctx, MyCustomForm }, props: { children: ReactNode }) =>
|
|
63
|
+
* // Notice how the form is available with its alias
|
|
64
|
+
* <MyCustomFormName>{children}</MyCustomFormName>
|
|
65
|
+
* )
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
alias?: TAlias;
|
|
69
|
+
/**
|
|
70
|
+
* If the form component should be accessible for each step when calling `createComponent`.
|
|
71
|
+
*
|
|
72
|
+
* If no value is given, the form will be accessible for all the steps.
|
|
73
|
+
*/
|
|
74
|
+
enabledForSteps?: TFormEnabledFor;
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param data The data that is available for creating the custom form.
|
|
78
|
+
* @param props Props that can be used for the custom form.
|
|
79
|
+
* @returns An {@see JSX.Element} that is the custom form.
|
|
80
|
+
* @example
|
|
81
|
+
* ### With custom props
|
|
82
|
+
* ```tsx
|
|
83
|
+
* type CustomProps = {
|
|
84
|
+
* title: string;
|
|
85
|
+
* description?: string;
|
|
86
|
+
* children: ReactNode;
|
|
87
|
+
* };
|
|
88
|
+
*
|
|
89
|
+
* const schema = createMultiStepFormSchema({
|
|
90
|
+
* steps: {
|
|
91
|
+
* step1: {
|
|
92
|
+
* title: 'Step 1',
|
|
93
|
+
* fields: {
|
|
94
|
+
* firstName: {
|
|
95
|
+
* defaultValue: ''
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* },
|
|
99
|
+
* form: {
|
|
100
|
+
* alias: 'MyCustomForm',
|
|
101
|
+
* render(data, props: CustomProps) {
|
|
102
|
+
* return (
|
|
103
|
+
* <div>
|
|
104
|
+
* <h1>{props.title}</h1>
|
|
105
|
+
* <p>{props.description}</p>
|
|
106
|
+
* <form>{props.children}</form>
|
|
107
|
+
* </div>
|
|
108
|
+
* );
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
* })
|
|
113
|
+
* ```
|
|
114
|
+
* ### Without custom props
|
|
115
|
+
* ```tsx
|
|
116
|
+
* const schema = createMultiStepFormSchema({
|
|
117
|
+
* steps: {
|
|
118
|
+
* step1: {
|
|
119
|
+
* title: 'Step 1',
|
|
120
|
+
* fields: {
|
|
121
|
+
* firstName: {
|
|
122
|
+
* defaultValue: ''
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* },
|
|
126
|
+
* form: {
|
|
127
|
+
* alias: 'MyCustomForm',
|
|
128
|
+
* render(data, props) {
|
|
129
|
+
* // The default type for `props` will be `ComponentPropsWithRef<'form'>`
|
|
130
|
+
* // return custom form component here
|
|
131
|
+
* }
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
* })
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
render: (data: renderFnData<TResolvedStep, TFormEnabledFor>, props: TCustomFormProps) => JSX.Element;
|
|
138
|
+
}
|
|
139
|
+
export interface Form<TResolvedStep extends AnyResolvedStep$1, TAlias extends string, TFormEnabledFor extends formEnabledFor<TResolvedStep>, TCustomFormProps extends object> {
|
|
140
|
+
form?: FormConfig<TResolvedStep, TAlias, TFormEnabledFor, TCustomFormProps>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Compares {@linkcode enabledFor} to the {@linkcode target} to determine if the form
|
|
144
|
+
* should be available.
|
|
145
|
+
* @param target The target steps the form _should_ be available for.
|
|
146
|
+
* @param enabledFor The steps that the form _is_ enabled for.
|
|
147
|
+
* @returns A boolean representing if the form should be available.
|
|
148
|
+
*/
|
|
149
|
+
export function isFormAvailable<TResolvedStep extends AnyResolvedStep$1, TTarget extends HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>, TEnabledFor extends formEnabledFor<TResolvedStep>>(target: TTarget, enabledFor: TEnabledFor): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Creates a form component with a default id.
|
|
152
|
+
* @param id The default id for the form.
|
|
153
|
+
* @returns A form component with a default {@linkcode id}.
|
|
154
|
+
*/
|
|
155
|
+
export function createDefaultForm(id: string): (props: Omit<ComponentPropsWithRef<"form">, "id">) => react_jsx_runtime0.JSX.Element;
|
|
156
|
+
export {};
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { MultiStepFormSchemaConfig };
|
|
160
|
+
//# sourceMappingURL=form-config.d.cts.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { AnyResolvedStep as AnyResolvedStep$1, CreatedMultiStepFormComponent } from "./step-schema.mjs";
|
|
2
|
+
import { Expand, HelperFnChosenSteps, StepNumbers, ValidStepKey } from "@jfdevelops/multi-step-form-core";
|
|
3
|
+
import { ComponentPropsWithRef, JSX } from "react";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/form-config.d.ts
|
|
7
|
+
declare namespace MultiStepFormSchemaConfig {
|
|
8
|
+
export const DEFAULT_FORM_ALIAS = "Form";
|
|
9
|
+
export type defaultEnabledFor = HelperFnChosenSteps.defaultStringOption;
|
|
10
|
+
export type defaultFormAlias = typeof DEFAULT_FORM_ALIAS;
|
|
11
|
+
export type formEnabledFor<TResolvedStep extends AnyResolvedStep$1> = HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>;
|
|
12
|
+
type strippedResolvedSteps<T extends AnyResolvedStep$1> = { [_ in keyof T]: Expand<Omit<T[_], 'createComponent' | 'createHelperFn'>> };
|
|
13
|
+
export type AvailableStepForForm<TResolvedStep extends AnyResolvedStep$1, TEnabledFor extends formEnabledFor<TResolvedStep>> = TEnabledFor extends defaultEnabledFor ? strippedResolvedSteps<TResolvedStep> : TEnabledFor extends [ValidStepKey<StepNumbers<TResolvedStep>>, ...ValidStepKey<StepNumbers<TResolvedStep>>[]] ? TEnabledFor[number] extends keyof TResolvedStep ? Pick<strippedResolvedSteps<TResolvedStep>, TEnabledFor[number]> : never : keyof TEnabledFor extends keyof TResolvedStep ? Expand<Pick<strippedResolvedSteps<TResolvedStep>, Extract<keyof TResolvedStep, keyof TEnabledFor>>> : never;
|
|
14
|
+
export type formCtx<TAlias extends string, TProps> = { [_ in TAlias]: CreatedMultiStepFormComponent<TProps> };
|
|
15
|
+
export type renderFnData<TResolvedStep extends AnyResolvedStep$1, TEnabledFor extends formEnabledFor<TResolvedStep>> = {
|
|
16
|
+
/**
|
|
17
|
+
* The id for the form, either a custom one or the default one.
|
|
18
|
+
*/
|
|
19
|
+
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* The chosen steps that are available.
|
|
22
|
+
*/
|
|
23
|
+
steps: Expand<AvailableStepForForm<TResolvedStep, TEnabledFor>>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The configuration options for the `form` option.
|
|
27
|
+
*/
|
|
28
|
+
export interface FormConfig<TResolvedStep extends AnyResolvedStep$1, TAlias extends string, TFormEnabledFor extends formEnabledFor<TResolvedStep>, TCustomFormProps extends object> {
|
|
29
|
+
/**
|
|
30
|
+
* The `id` for the form component.
|
|
31
|
+
*
|
|
32
|
+
* If there is no value provided, the default id will the **current step key**.
|
|
33
|
+
*
|
|
34
|
+
* @default `${currentStep}`
|
|
35
|
+
*/
|
|
36
|
+
id?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The "name" of the form component.
|
|
39
|
+
* @default 'Form'
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* const schema = createMultiStepFormSchema({
|
|
43
|
+
* steps: {
|
|
44
|
+
* step1: {
|
|
45
|
+
* title: 'Step 1',
|
|
46
|
+
* fields: {
|
|
47
|
+
* firstName: {
|
|
48
|
+
* defaultValue: ''
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* },
|
|
52
|
+
* form: {
|
|
53
|
+
* alias: 'MyCustomForm',
|
|
54
|
+
* render() {
|
|
55
|
+
* // return custom form component here
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* })
|
|
60
|
+
*
|
|
61
|
+
* const Step1 = schema.stepSchema.step1.createComponent(
|
|
62
|
+
* ({ ctx, MyCustomForm }, props: { children: ReactNode }) =>
|
|
63
|
+
* // Notice how the form is available with its alias
|
|
64
|
+
* <MyCustomFormName>{children}</MyCustomFormName>
|
|
65
|
+
* )
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
alias?: TAlias;
|
|
69
|
+
/**
|
|
70
|
+
* If the form component should be accessible for each step when calling `createComponent`.
|
|
71
|
+
*
|
|
72
|
+
* If no value is given, the form will be accessible for all the steps.
|
|
73
|
+
*/
|
|
74
|
+
enabledForSteps?: TFormEnabledFor;
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param data The data that is available for creating the custom form.
|
|
78
|
+
* @param props Props that can be used for the custom form.
|
|
79
|
+
* @returns An {@see JSX.Element} that is the custom form.
|
|
80
|
+
* @example
|
|
81
|
+
* ### With custom props
|
|
82
|
+
* ```tsx
|
|
83
|
+
* type CustomProps = {
|
|
84
|
+
* title: string;
|
|
85
|
+
* description?: string;
|
|
86
|
+
* children: ReactNode;
|
|
87
|
+
* };
|
|
88
|
+
*
|
|
89
|
+
* const schema = createMultiStepFormSchema({
|
|
90
|
+
* steps: {
|
|
91
|
+
* step1: {
|
|
92
|
+
* title: 'Step 1',
|
|
93
|
+
* fields: {
|
|
94
|
+
* firstName: {
|
|
95
|
+
* defaultValue: ''
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* },
|
|
99
|
+
* form: {
|
|
100
|
+
* alias: 'MyCustomForm',
|
|
101
|
+
* render(data, props: CustomProps) {
|
|
102
|
+
* return (
|
|
103
|
+
* <div>
|
|
104
|
+
* <h1>{props.title}</h1>
|
|
105
|
+
* <p>{props.description}</p>
|
|
106
|
+
* <form>{props.children}</form>
|
|
107
|
+
* </div>
|
|
108
|
+
* );
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* }
|
|
112
|
+
* })
|
|
113
|
+
* ```
|
|
114
|
+
* ### Without custom props
|
|
115
|
+
* ```tsx
|
|
116
|
+
* const schema = createMultiStepFormSchema({
|
|
117
|
+
* steps: {
|
|
118
|
+
* step1: {
|
|
119
|
+
* title: 'Step 1',
|
|
120
|
+
* fields: {
|
|
121
|
+
* firstName: {
|
|
122
|
+
* defaultValue: ''
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* },
|
|
126
|
+
* form: {
|
|
127
|
+
* alias: 'MyCustomForm',
|
|
128
|
+
* render(data, props) {
|
|
129
|
+
* // The default type for `props` will be `ComponentPropsWithRef<'form'>`
|
|
130
|
+
* // return custom form component here
|
|
131
|
+
* }
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
* })
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
render: (data: renderFnData<TResolvedStep, TFormEnabledFor>, props: TCustomFormProps) => JSX.Element;
|
|
138
|
+
}
|
|
139
|
+
export interface Form<TResolvedStep extends AnyResolvedStep$1, TAlias extends string, TFormEnabledFor extends formEnabledFor<TResolvedStep>, TCustomFormProps extends object> {
|
|
140
|
+
form?: FormConfig<TResolvedStep, TAlias, TFormEnabledFor, TCustomFormProps>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Compares {@linkcode enabledFor} to the {@linkcode target} to determine if the form
|
|
144
|
+
* should be available.
|
|
145
|
+
* @param target The target steps the form _should_ be available for.
|
|
146
|
+
* @param enabledFor The steps that the form _is_ enabled for.
|
|
147
|
+
* @returns A boolean representing if the form should be available.
|
|
148
|
+
*/
|
|
149
|
+
export function isFormAvailable<TResolvedStep extends AnyResolvedStep$1, TTarget extends HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>, TEnabledFor extends formEnabledFor<TResolvedStep>>(target: TTarget, enabledFor: TEnabledFor): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Creates a form component with a default id.
|
|
152
|
+
* @param id The default id for the form.
|
|
153
|
+
* @returns A form component with a default {@linkcode id}.
|
|
154
|
+
*/
|
|
155
|
+
export function createDefaultForm(id: string): (props: Omit<ComponentPropsWithRef<"form">, "id">) => react_jsx_runtime0.JSX.Element;
|
|
156
|
+
export {};
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { MultiStepFormSchemaConfig };
|
|
160
|
+
//# sourceMappingURL=form-config.d.mts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/form-config.tsx
|
|
4
|
+
let MultiStepFormSchemaConfig;
|
|
5
|
+
(function(_MultiStepFormSchemaConfig) {
|
|
6
|
+
_MultiStepFormSchemaConfig.DEFAULT_FORM_ALIAS = "Form";
|
|
7
|
+
function isFormAvailable(target, enabledFor) {
|
|
8
|
+
if (Array.isArray(target)) {
|
|
9
|
+
if (enabledFor === "all") return true;
|
|
10
|
+
if (typeof enabledFor === "object" && !Array.isArray(enabledFor)) return Object.keys(enabledFor).some((key) => target.includes(key));
|
|
11
|
+
if (Array.isArray(enabledFor)) return enabledFor.some((key) => target.includes(key));
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
_MultiStepFormSchemaConfig.isFormAvailable = isFormAvailable;
|
|
16
|
+
function createDefaultForm(id) {
|
|
17
|
+
return (props) => /* @__PURE__ */ jsx("form", {
|
|
18
|
+
id,
|
|
19
|
+
...props
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
_MultiStepFormSchemaConfig.createDefaultForm = createDefaultForm;
|
|
23
|
+
})(MultiStepFormSchemaConfig || (MultiStepFormSchemaConfig = {}));
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { MultiStepFormSchemaConfig };
|
|
27
|
+
//# sourceMappingURL=form-config.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-config.mjs","names":[],"sources":["../src/form-config.tsx"],"sourcesContent":["import type {\n Expand,\n HelperFnChosenSteps,\n StepNumbers,\n ValidStepKey,\n} from '@jfdevelops/multi-step-form-core';\nimport type { ComponentPropsWithRef, JSX } from 'react';\nimport type {\n AnyResolvedStep,\n CreatedMultiStepFormComponent,\n} from './step-schema';\n\nexport namespace MultiStepFormSchemaConfig {\n export const DEFAULT_FORM_ALIAS = 'Form';\n export type defaultEnabledFor = HelperFnChosenSteps.defaultStringOption;\n export type defaultFormAlias = typeof DEFAULT_FORM_ALIAS;\n export type formEnabledFor<TResolvedStep extends AnyResolvedStep> =\n HelperFnChosenSteps<TResolvedStep, StepNumbers<TResolvedStep>>;\n type strippedResolvedSteps<T extends AnyResolvedStep> = {\n [_ in keyof T]: Expand<Omit<T[_], 'createComponent' | 'createHelperFn'>>;\n };\n export type AvailableStepForForm<\n TResolvedStep extends AnyResolvedStep,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n > = TEnabledFor extends defaultEnabledFor\n ? strippedResolvedSteps<TResolvedStep>\n : TEnabledFor extends [\n ValidStepKey<StepNumbers<TResolvedStep>>,\n ...ValidStepKey<StepNumbers<TResolvedStep>>[]\n ]\n ? TEnabledFor[number] extends keyof TResolvedStep\n ? Pick<strippedResolvedSteps<TResolvedStep>, TEnabledFor[number]>\n : never\n : keyof TEnabledFor extends keyof TResolvedStep\n ? Expand<\n Pick<\n strippedResolvedSteps<TResolvedStep>,\n Extract<keyof TResolvedStep, keyof TEnabledFor>\n >\n >\n : never;\n export type formCtx<TAlias extends string, TProps> = {\n [_ in TAlias]: CreatedMultiStepFormComponent<TProps>;\n };\n export type renderFnData<\n TResolvedStep extends AnyResolvedStep,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n > = {\n /**\n * The id for the form, either a custom one or the default one.\n */\n id: string;\n /**\n * The chosen steps that are available.\n */\n steps: Expand<AvailableStepForForm<TResolvedStep, TEnabledFor>>;\n };\n\n /**\n * The configuration options for the `form` option.\n */\n export interface FormConfig<\n TResolvedStep extends AnyResolvedStep,\n TAlias extends string,\n TFormEnabledFor extends formEnabledFor<TResolvedStep>,\n TCustomFormProps extends object\n > {\n /**\n * The `id` for the form component.\n *\n * If there is no value provided, the default id will the **current step key**.\n *\n * @default `${currentStep}`\n */\n id?: string;\n /**\n * The \"name\" of the form component.\n * @default 'Form'\n * @example\n * ```tsx\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render() {\n * // return custom form component here\n * }\n * }\n * }\n * })\n *\n * const Step1 = schema.stepSchema.step1.createComponent(\n * ({ ctx, MyCustomForm }, props: { children: ReactNode }) =>\n * // Notice how the form is available with its alias\n * <MyCustomFormName>{children}</MyCustomFormName>\n * )\n * ```\n */\n alias?: TAlias;\n /**\n * If the form component should be accessible for each step when calling `createComponent`.\n *\n * If no value is given, the form will be accessible for all the steps.\n */\n enabledForSteps?: TFormEnabledFor;\n /**\n *\n * @param data The data that is available for creating the custom form.\n * @param props Props that can be used for the custom form.\n * @returns An {@see JSX.Element} that is the custom form.\n * @example\n * ### With custom props\n * ```tsx\n * type CustomProps = {\n * title: string;\n * description?: string;\n * children: ReactNode;\n * };\n *\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render(data, props: CustomProps) {\n * return (\n * <div>\n * <h1>{props.title}</h1>\n * <p>{props.description}</p>\n * <form>{props.children}</form>\n * </div>\n * );\n * }\n * }\n * }\n * })\n * ```\n * ### Without custom props\n * ```tsx\n * const schema = createMultiStepFormSchema({\n * steps: {\n * step1: {\n * title: 'Step 1',\n * fields: {\n * firstName: {\n * defaultValue: ''\n * }\n * }\n * },\n * form: {\n * alias: 'MyCustomForm',\n * render(data, props) {\n * // The default type for `props` will be `ComponentPropsWithRef<'form'>`\n * // return custom form component here\n * }\n * }\n * }\n * })\n * ```\n */\n render: (\n data: renderFnData<TResolvedStep, TFormEnabledFor>,\n props: TCustomFormProps\n ) => JSX.Element;\n }\n\n export interface Form<\n TResolvedStep extends AnyResolvedStep,\n TAlias extends string,\n TFormEnabledFor extends formEnabledFor<TResolvedStep>,\n TCustomFormProps extends object\n > {\n form?: FormConfig<TResolvedStep, TAlias, TFormEnabledFor, TCustomFormProps>;\n }\n\n /**\n * Compares {@linkcode enabledFor} to the {@linkcode target} to determine if the form\n * should be available.\n * @param target The target steps the form _should_ be available for.\n * @param enabledFor The steps that the form _is_ enabled for.\n * @returns A boolean representing if the form should be available.\n */\n // Note: the implementation is specific to `MultiStepFormStepSchema.createComponentForStep`\n // because the `target` will always be an `Array` in `MultiStepFormStepSchema.createComponentForStep`.\n // TODO add validation to keys\n export function isFormAvailable<\n TResolvedStep extends AnyResolvedStep,\n TTarget extends HelperFnChosenSteps<\n TResolvedStep,\n StepNumbers<TResolvedStep>\n >,\n TEnabledFor extends formEnabledFor<TResolvedStep>\n >(target: TTarget, enabledFor: TEnabledFor) {\n if (Array.isArray(target)) {\n if (enabledFor === 'all') {\n return true;\n }\n\n if (typeof enabledFor === 'object' && !Array.isArray(enabledFor)) {\n return Object.keys(enabledFor).some((key) =>\n target.includes(key as `step${StepNumbers<TResolvedStep>}`)\n );\n }\n\n if (Array.isArray(enabledFor)) {\n return enabledFor.some((key) => target.includes(key));\n }\n }\n\n return false;\n }\n\n /**\n * Creates a form component with a default id.\n * @param id The default id for the form.\n * @returns A form component with a default {@linkcode id}.\n */\n export function createDefaultForm(id: string) {\n return (props: Omit<ComponentPropsWithRef<'form'>, 'id'>) => (\n <form id={id} {...props} />\n );\n }\n}\n"],"mappings":";;;;;iDAaoC;CA2L3B,SAAS,gBAOd,QAAiB,YAAyB;AAC1C,MAAI,MAAM,QAAQ,OAAO,EAAE;AACzB,OAAI,eAAe,MACjB,QAAO;AAGT,OAAI,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,WAAW,CAC9D,QAAO,OAAO,KAAK,WAAW,CAAC,MAAM,QACnC,OAAO,SAAS,IAA2C,CAC5D;AAGH,OAAI,MAAM,QAAQ,WAAW,CAC3B,QAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,IAAI,CAAC;;AAIzD,SAAO;;;CAQF,SAAS,kBAAkB,IAAY;AAC5C,UAAQ,UACN,oBAAC;GAAS;GAAI,GAAI;IAAS"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
let __jfdevelops_multi_step_form_core = require("@jfdevelops/multi-step-form-core");
|
|
2
|
+
let use_sync_external_store_shim_with_selector = require("use-sync-external-store/shim/with-selector");
|
|
3
|
+
|
|
4
|
+
//#region src/hooks/use-multi-step-form-data.ts
|
|
5
|
+
function throwIfInvalidStepNumber(schema, targetStep) {
|
|
6
|
+
(0, __jfdevelops_multi_step_form_core.invariant)(typeof targetStep === "string", `The target step must be a string, was ${typeof targetStep}`);
|
|
7
|
+
const { as, isValidStepNumber } = schema.stepSchema.steps;
|
|
8
|
+
const formattedStepNumbersList = new Intl.ListFormat("en", {
|
|
9
|
+
type: "disjunction",
|
|
10
|
+
style: "long"
|
|
11
|
+
}).format(as("array.string.untyped"));
|
|
12
|
+
(0, __jfdevelops_multi_step_form_core.invariant)(__jfdevelops_multi_step_form_core.VALIDATED_STEP_REGEX.test(targetStep), `The target step must match the following format: "step{number}". Available steps are ${formattedStepNumbersList}`);
|
|
13
|
+
const stepNumber = Number.parseInt(targetStep.replace("step", ""));
|
|
14
|
+
(0, __jfdevelops_multi_step_form_core.invariant)(isValidStepNumber(stepNumber), `The step number "${stepNumber}" is not a valid step number. Valid step numbers include ${formattedStepNumbersList}`, TypeError);
|
|
15
|
+
return stepNumber;
|
|
16
|
+
}
|
|
17
|
+
function createMultiStepFormDataHook(schema) {
|
|
18
|
+
function useMultiStepFormData$1(optionsOrSelector) {
|
|
19
|
+
return (0, use_sync_external_store_shim_with_selector.useSyncExternalStoreWithSelector)(schema.subscribe, () => schema.getSnapshot(), () => schema.getSnapshot(), (snapshot) => {
|
|
20
|
+
if (typeof optionsOrSelector === "object") {
|
|
21
|
+
const stepNumber = throwIfInvalidStepNumber(snapshot, optionsOrSelector.targetStep);
|
|
22
|
+
return snapshot.stepSchema.get({ step: stepNumber }).data;
|
|
23
|
+
}
|
|
24
|
+
if (typeof optionsOrSelector === "function") return optionsOrSelector(snapshot);
|
|
25
|
+
return snapshot;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return useMultiStepFormData$1;
|
|
29
|
+
}
|
|
30
|
+
function useMultiStepFormData(schema, optionsOrSelector) {
|
|
31
|
+
const hook = createMultiStepFormDataHook(schema);
|
|
32
|
+
if (typeof optionsOrSelector === "object") return hook(optionsOrSelector);
|
|
33
|
+
if (typeof optionsOrSelector === "function") return hook(optionsOrSelector);
|
|
34
|
+
return hook();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
exports.createMultiStepFormDataHook = createMultiStepFormDataHook;
|
|
39
|
+
exports.throwIfInvalidStepNumber = throwIfInvalidStepNumber;
|
|
40
|
+
exports.useMultiStepFormData = useMultiStepFormData;
|
|
41
|
+
//# sourceMappingURL=use-multi-step-form-data.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-multi-step-form-data.cjs","names":["VALIDATED_STEP_REGEX","useMultiStepFormData"],"sources":["../../src/hooks/use-multi-step-form-data.ts"],"sourcesContent":["import type { AnyMultiStepFormSchema, MultiStepFormSchema } from '@/schema';\nimport {\n invariant,\n VALIDATED_STEP_REGEX,\n} from '@jfdevelops/multi-step-form-core';\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';\n\nexport type UseMultiStepFormDataOptions<\n TSchema extends AnyMultiStepFormSchema,\n TTarget extends keyof MultiStepFormSchema.resolvedStep<TSchema> = keyof MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n targetStep: TTarget;\n};\nexport type UseMultiStepFormData<\n // step extends Step<casing>,\n // casing extends CasingType,\n // storageKey extends string,\n // resolvedStep extends ResolvedStep<step, casing>,\n // schema extends MultiStepFormSchema<\n // step,\n // casing,\n // storageKey\n // > = MultiStepFormSchema<step, casing, storageKey>,\n TSchema extends AnyMultiStepFormSchema,\n TResolvedStep extends MultiStepFormSchema.resolvedStep<TSchema> = MultiStepFormSchema.resolvedStep<TSchema>\n> = {\n /**\n * Returns the entire {@linkcode MultiStepFormSchema instance}.\n */\n (): TSchema;\n /**\n * Returns the data for the target step.\n * @param stepNumber The step number to return.\n * @throws {TypeError} If `options.stepNumber` is invalid.\n */\n <targetStep extends keyof TResolvedStep>(\n options: UseMultiStepFormDataOptions<TSchema, targetStep>\n ): MultiStepFormSchema.getData<TSchema, targetStep>;\n /**\n * Returns the specified data from the {@linkcode MultiStepFormSchema} instance via the callback's return.\n */\n <data>(selector: (schema: TSchema) => data): data;\n};\n\nexport function throwIfInvalidStepNumber<\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 AnyMultiStepFormSchema\n>(schema: schema, targetStep: unknown) {\n invariant(\n typeof targetStep === 'string',\n `The target step must be a string, was ${typeof targetStep}`\n );\n\n const { as, isValidStepNumber } = schema.stepSchema.steps;\n const formatter = new Intl.ListFormat('en', {\n type: 'disjunction',\n style: 'long',\n });\n const formattedStepNumbersList = formatter.format(as('array.string.untyped'));\n\n invariant(\n VALIDATED_STEP_REGEX.test(targetStep),\n `The target step must match the following format: \"step{number}\". Available steps are ${formattedStepNumbersList}`\n );\n\n const stepNumber = Number.parseInt(targetStep.replace('step', ''));\n\n invariant(\n isValidStepNumber(stepNumber),\n `The step number \"${stepNumber}\" is not a valid step number. Valid step numbers include ${formattedStepNumbersList}`,\n TypeError\n );\n\n return stepNumber as MultiStepFormSchema.stepNumbers<schema>;\n}\n\nexport function createMultiStepFormDataHook<\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 AnyMultiStepFormSchema\n>(schema: schema): UseMultiStepFormData<schema> {\n function useMultiStepFormData(\n optionsOrSelector?:\n | UseMultiStepFormDataOptions<schema>\n | ((data: schema) => unknown)\n ) {\n return useSyncExternalStoreWithSelector(\n schema.subscribe,\n () => schema.getSnapshot(),\n () => schema.getSnapshot(),\n (snapshot) => {\n if (typeof optionsOrSelector === 'object') {\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n const stepNumber = throwIfInvalidStepNumber(\n snapshot,\n optionsOrSelector.targetStep\n );\n\n return snapshot.stepSchema.get({ step: stepNumber as never }).data;\n }\n\n if (typeof optionsOrSelector === 'function') {\n return optionsOrSelector(snapshot);\n }\n\n return snapshot;\n }\n );\n }\n\n return useMultiStepFormData as any;\n}\n\nfunction useMultiStepFormData<schema extends AnyMultiStepFormSchema>(\n schema: schema\n): schema;\nfunction useMultiStepFormData<\n schema extends AnyMultiStepFormSchema,\n targetStep extends keyof MultiStepFormSchema.resolvedStep<schema>\n>(\n schema: schema,\n options: UseMultiStepFormDataOptions<schema, targetStep>\n): MultiStepFormSchema.getData<schema, targetStep>;\nfunction useMultiStepFormData<schema extends AnyMultiStepFormSchema, data>(\n schema: schema,\n selector: (schema: schema) => data\n): data;\nfunction useMultiStepFormData<\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 AnyMultiStepFormSchema\n>(\n schema: schema,\n optionsOrSelector?:\n | UseMultiStepFormDataOptions<schema>\n | ((data: schema) => unknown)\n) {\n const hook = createMultiStepFormDataHook(schema);\n\n if (typeof optionsOrSelector === 'object') {\n return hook(optionsOrSelector);\n }\n\n if (typeof optionsOrSelector === 'function') {\n return hook(optionsOrSelector);\n }\n\n return hook();\n}\n\nexport { useMultiStepFormData };\n"],"mappings":";;;;AA4CA,SAAgB,yBAOd,QAAgB,YAAqB;AACrC,kDACE,OAAO,eAAe,UACtB,yCAAyC,OAAO,aACjD;CAED,MAAM,EAAE,IAAI,sBAAsB,OAAO,WAAW;CAKpD,MAAM,2BAJY,IAAI,KAAK,WAAW,MAAM;EAC1C,MAAM;EACN,OAAO;EACR,CAAC,CACyC,OAAO,GAAG,uBAAuB,CAAC;AAE7E,kDACEA,uDAAqB,KAAK,WAAW,EACrC,wFAAwF,2BACzF;CAED,MAAM,aAAa,OAAO,SAAS,WAAW,QAAQ,QAAQ,GAAG,CAAC;AAElE,kDACE,kBAAkB,WAAW,EAC7B,oBAAoB,WAAW,2DAA2D,4BAC1F,UACD;AAED,QAAO;;AAGT,SAAgB,4BAOd,QAA8C;CAC9C,SAASC,uBACP,mBAGA;AACA,0FACE,OAAO,iBACD,OAAO,aAAa,QACpB,OAAO,aAAa,GACzB,aAAa;AACZ,OAAI,OAAO,sBAAsB,UAAU;IAEzC,MAAM,aAAa,yBACjB,UACA,kBAAkB,WACnB;AAED,WAAO,SAAS,WAAW,IAAI,EAAE,MAAM,YAAqB,CAAC,CAAC;;AAGhE,OAAI,OAAO,sBAAsB,WAC/B,QAAO,kBAAkB,SAAS;AAGpC,UAAO;IAEV;;AAGH,QAAOA;;AAiBT,SAAS,qBAQP,QACA,mBAGA;CACA,MAAM,OAAO,4BAA4B,OAAO;AAEhD,KAAI,OAAO,sBAAsB,SAC/B,QAAO,KAAK,kBAAkB;AAGhC,KAAI,OAAO,sBAAsB,WAC/B,QAAO,KAAK,kBAAkB;AAGhC,QAAO,MAAM"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AnyMultiStepFormSchema, MultiStepFormSchema } from "../schema.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/use-multi-step-form-data.d.ts
|
|
4
|
+
type UseMultiStepFormDataOptions<TSchema extends AnyMultiStepFormSchema, TTarget extends keyof MultiStepFormSchema.resolvedStep<TSchema> = keyof MultiStepFormSchema.resolvedStep<TSchema>> = {
|
|
5
|
+
targetStep: TTarget;
|
|
6
|
+
};
|
|
7
|
+
type UseMultiStepFormData<TSchema extends AnyMultiStepFormSchema, TResolvedStep extends MultiStepFormSchema.resolvedStep<TSchema> = MultiStepFormSchema.resolvedStep<TSchema>> = {
|
|
8
|
+
/**
|
|
9
|
+
* Returns the entire {@linkcode MultiStepFormSchema instance}.
|
|
10
|
+
*/
|
|
11
|
+
(): TSchema;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the data for the target step.
|
|
14
|
+
* @param stepNumber The step number to return.
|
|
15
|
+
* @throws {TypeError} If `options.stepNumber` is invalid.
|
|
16
|
+
*/
|
|
17
|
+
<targetStep extends keyof TResolvedStep>(options: UseMultiStepFormDataOptions<TSchema, targetStep>): MultiStepFormSchema.getData<TSchema, targetStep>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the specified data from the {@linkcode MultiStepFormSchema} instance via the callback's return.
|
|
20
|
+
*/
|
|
21
|
+
<data>(selector: (schema: TSchema) => data): data;
|
|
22
|
+
};
|
|
23
|
+
declare function useMultiStepFormData<schema extends AnyMultiStepFormSchema>(schema: schema): schema;
|
|
24
|
+
declare function useMultiStepFormData<schema extends AnyMultiStepFormSchema, targetStep extends keyof MultiStepFormSchema.resolvedStep<schema>>(schema: schema, options: UseMultiStepFormDataOptions<schema, targetStep>): MultiStepFormSchema.getData<schema, targetStep>;
|
|
25
|
+
declare function useMultiStepFormData<schema extends AnyMultiStepFormSchema, data>(schema: schema, selector: (schema: schema) => data): data;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { UseMultiStepFormData, useMultiStepFormData };
|
|
28
|
+
//# sourceMappingURL=use-multi-step-form-data.d.cts.map
|