New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

remix-forms

Package Overview
Dependencies
Maintainers
2
Versions
89
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

remix-forms - npm Package Compare versions

Comparing version 0.19.0 to 1.0.0

59

dist/index.d.ts
import * as React from 'react';
import { Fetcher, FormMethod, FormProps as FormProps$1 } from '@remix-run/react';
import { z, SomeZodObject, ZodTypeAny } from 'zod';
import { UseFormRegisterReturn, ValidationMode, UseFormReturn } from 'react-hook-form';
import { DomainFunction } from 'domain-functions';
import { Transition } from '@remix-run/react/dist/transition';

@@ -11,2 +9,4 @@ declare type FormSchema<T extends z.ZodTypeAny = z.SomeZodObject | z.ZodEffects<any>> = z.ZodEffects<T> | z.SomeZodObject;

declare type RedirectFunction = (url: string, init?: number | ResponseInit) => Response;
declare type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response;
declare type FormActionFailure<SchemaType> = {

@@ -37,3 +37,6 @@ errors: FormErrors<SchemaType>;

declare function performMutation<Schema extends FormSchema, D extends unknown>({ request, schema, mutation, environment, }: PerformMutationProps<Schema, D>): Promise<PerformMutation<z.infer<Schema>, D>>;
declare function formAction<Schema extends FormSchema, D extends unknown>({ request, schema, mutation, environment, beforeAction, beforeSuccess, successPath, }: FormActionProps<Schema, D>): Promise<Response>;
declare function createFormAction({ redirect, json, }: {
redirect: RedirectFunction;
json: JsonFunction;
}): <Schema extends FormSchema<z.SomeZodObject | z.ZodEffects<any, any, any>>, D extends unknown>({ request, schema, mutation, environment, beforeAction, beforeSuccess, successPath, }: FormActionProps<Schema, D>) => Promise<Response>;

@@ -73,2 +76,10 @@ declare type SmartInputProps = {

declare type FormMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
declare type BaseFormProps = {
method?: FormMethod;
onSubmit?: React.FormEventHandler<HTMLFormElement>;
children: React.ReactNode;
};
declare type BaseFormPropsWithHTMLAttributes = React.FormHTMLAttributes<HTMLFormElement> & BaseFormProps;
declare type FormComponent = React.ForwardRefExoticComponent<BaseFormProps>;
declare type Field<SchemaType> = {

@@ -97,3 +108,2 @@ shape: ZodTypeAny;

declare type Options<SchemaType> = Partial<Record<keyof SchemaType, Option[]>>;
declare type AllRemixFormProps = FormProps$1 & React.RefAttributes<HTMLFormElement>;
declare type Children<Schema extends SomeZodObject> = (helpers: {

@@ -104,19 +114,18 @@ Field: FieldComponent<Schema>;

Button: React.ComponentType<JSX.IntrinsicElements['button']> | string;
transition: FormTransition;
} & UseFormReturn<z.infer<Schema>, any>) => React.ReactNode;
declare type FormTransition = (Fetcher<any> & {
Form: any;
submit: any;
load: (href: string) => void;
}) | Transition;
declare type OnTransition<Schema extends SomeZodObject> = (helpers: {
transition: FormTransition;
} & UseFormReturn<z.infer<Schema>, any>) => void;
declare type Transition = {
state: 'idle' | 'loading' | 'submitting';
};
declare type OnTransition<Schema extends SomeZodObject> = (helpers: UseFormReturn<z.infer<Schema>, any>) => void;
declare type SubmitFunction = ({ target }: {
target: any;
}) => void;
declare type FetcherWithComponents = Transition & {
data: any;
Form: FormComponent;
submit: SubmitFunction;
};
declare type FormProps<Schema extends FormSchema> = {
component?: React.ForwardRefExoticComponent<AllRemixFormProps>;
fetcher?: Fetcher<any> & {
Form: ReturnType<any>;
submit: ReturnType<any>;
load: (href: string) => void;
};
component?: FormComponent;
fetcher?: FetcherWithComponents;
mode?: keyof ValidationMode;

@@ -137,3 +146,2 @@ renderField?: RenderField<ObjectFromSchema<Schema>>;

pendingButtonLabel?: string;
method?: FormMethod;
schema: Schema;

@@ -151,5 +159,10 @@ errors?: FormErrors<z.infer<Schema>>;

children?: Children<ObjectFromSchema<Schema>>;
} & Omit<AllRemixFormProps, 'method' | 'children'>;
declare function Form<Schema extends FormSchema>({ component, fetcher, mode, renderField, fieldComponent, globalErrorsComponent: Errors, errorComponent: Error, fieldErrorsComponent, labelComponent, inputComponent, multilineComponent, selectComponent, checkboxComponent, checkboxWrapperComponent, buttonComponent: Button, buttonLabel: rawButtonLabel, pendingButtonLabel, method, schema, beforeChildren, onTransition, parseActionData, children: childrenFn, labels, placeholders, options, hiddenFields, multiline, errors: errorsProp, values: valuesProp, ...props }: FormProps<Schema>): JSX.Element;
} & Omit<BaseFormPropsWithHTMLAttributes, 'children'>;
declare function createForm({ component: DefaultComponent, useNavigation, useSubmit, useActionData, }: {
component: FormComponent;
useNavigation: () => Transition;
useSubmit: () => SubmitFunction;
useActionData: () => unknown;
}): <Schema extends FormSchema<SomeZodObject | z.ZodEffects<any, any, any>>>({ component, fetcher, mode, renderField, fieldComponent, globalErrorsComponent: Errors, errorComponent: Error, fieldErrorsComponent, labelComponent, inputComponent, multilineComponent, selectComponent, checkboxComponent, checkboxWrapperComponent, buttonComponent: Button, buttonLabel: rawButtonLabel, pendingButtonLabel, method, schema, beforeChildren, onTransition, parseActionData, children: childrenFn, labels, placeholders, options, hiddenFields, multiline, errors: errorsProp, values: valuesProp, ...props }: FormProps<Schema>) => JSX.Element;
export { Callback, Form, FormActionProps, FormProps, FormSchema, PerformMutation, RenderField, RenderFieldProps, formAction, performMutation };
export { Callback, FormActionProps, FormProps, FormSchema, PerformMutation, RenderField, RenderFieldProps, createForm, createFormAction, performMutation };

@@ -20,3 +20,6 @@ "use strict";

};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

@@ -27,4 +30,4 @@

__export(src_exports, {
Form: () => Form,
formAction: () => formAction,
createForm: () => createForm,
createFormAction: () => createFormAction,
performMutation: () => performMutation

@@ -34,5 +37,4 @@ });

// src/Form.tsx
var React5 = __toESM(require("react"));
var import_react = require("@remix-run/react");
// src/createForm.tsx
var React3 = __toESM(require("react"));

@@ -44,3 +46,3 @@ // src/prelude.ts

// src/Form.tsx
// src/createForm.tsx
var import_react_hook_form = require("react-hook-form");

@@ -50,3 +52,3 @@ var import_zod = require("@hookform/resolvers/zod");

// src/createField.tsx
var React3 = __toESM(require("react"));
var React2 = __toESM(require("react"));

@@ -60,6 +62,8 @@ // src/mapChildren.ts

if (child.props.children && typeof child.props.children !== "function") {
return fn(React.cloneElement(child, {
...child.props,
children: mapChildren(child.props.children, fn)
}));
return fn(
React.cloneElement(child, {
...child.props,
children: mapChildren(child.props.children, fn)
})
);
}

@@ -77,12 +81,36 @@ return fn(child);

if (typeName === "ZodEffects") {
return shapeInfo(shape._def.schema, optional, nullable, getDefaultValue, enumValues);
return shapeInfo(
shape._def.schema,
optional,
nullable,
getDefaultValue,
enumValues
);
}
if (typeName === "ZodOptional") {
return shapeInfo(shape._def.innerType, true, nullable, getDefaultValue, enumValues);
return shapeInfo(
shape._def.innerType,
true,
nullable,
getDefaultValue,
enumValues
);
}
if (typeName === "ZodNullable") {
return shapeInfo(shape._def.innerType, optional, true, getDefaultValue, enumValues);
return shapeInfo(
shape._def.innerType,
optional,
true,
getDefaultValue,
enumValues
);
}
if (typeName === "ZodDefault") {
return shapeInfo(shape._def.innerType, optional, nullable, shape._def.defaultValue, enumValues);
return shapeInfo(
shape._def.innerType,
optional,
nullable,
shape._def.defaultValue,
enumValues
);
}

@@ -144,3 +172,3 @@ if (typeName === "ZodEnum") {

// src/createSmartInput.tsx
var React2 = __toESM(require("react"));
var import_jsx_runtime = require("react/jsx-runtime");
function createSmartInput({

@@ -168,3 +196,3 @@ inputComponent: Input = "input",

if (fieldType === "boolean") {
return /* @__PURE__ */ React2.createElement(Checkbox, {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Checkbox, {
id: name,

@@ -181,3 +209,3 @@ type,

if (selectChildren) {
return /* @__PURE__ */ React2.createElement(Select, {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Select, {
id: name,

@@ -188,7 +216,8 @@ ...registerProps,

...a11yProps,
...props
}, selectChildren);
...props,
children: selectChildren
});
}
if (multiline) {
return /* @__PURE__ */ React2.createElement(Multiline, {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Multiline, {
id: name,

@@ -203,3 +232,3 @@ ...registerProps,

}
return /* @__PURE__ */ React2.createElement(Input, {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, {
id: name,

@@ -218,2 +247,3 @@ type,

// src/createField.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var types = {

@@ -244,199 +274,222 @@ boolean: "checkbox",

}) {
return React3.forwardRef(({
fieldType = "string",
shape,
name,
label,
options,
errors,
type: typeProp,
required = false,
autoFocus = false,
value: rawValue,
multiline = false,
placeholder,
hidden = false,
children: childrenFn,
...props
}, ref) => {
const value = fieldType === "date" ? parseDate(rawValue) : rawValue;
const selectChildren = options ? options.map(({ name: name2, value: value2 }) => /* @__PURE__ */ React3.createElement("option", {
key: String(value2),
value: value2
}, name2)) : void 0;
const errorsChildren = (errors == null ? void 0 : errors.length) ? errors.map((error) => /* @__PURE__ */ React3.createElement(Error2, {
key: error
}, error)) : void 0;
const style = hidden ? { display: "none" } : void 0;
const type = typeProp || types[fieldType];
const registerProps = register(String(name), {
setValueAs: (value2) => coerceValue(value2, shape)
});
const labelId = `label-for-${name.toString()}`;
const errorsId = `errors-for-${name.toString()}`;
const a11yProps = {
"aria-labelledby": labelId,
"aria-invalid": Boolean(errors),
"aria-describedby": errors ? errorsId : void 0,
"aria-required": required
};
const SmartInput = React3.useMemo(() => createSmartInput({
inputComponent: Input,
multilineComponent: Multiline,
selectComponent: Select,
checkboxComponent: Checkbox
}), [Input, Multiline, Select, Checkbox]);
if (childrenFn) {
const children = childrenFn({
Label,
SmartInput,
Input,
Multiline,
Select,
Checkbox,
CheckboxWrapper,
Errors,
Error: Error2,
ref,
shape,
fieldType,
name,
required,
label,
type,
options,
errors,
autoFocus,
value,
hidden,
multiline,
placeholder
return React2.forwardRef(
({
fieldType = "string",
shape,
name,
label,
options,
errors,
type: typeProp,
required = false,
autoFocus = false,
value: rawValue,
multiline = false,
placeholder,
hidden = false,
children: childrenFn,
...props
}, ref) => {
const value = fieldType === "date" ? parseDate(rawValue) : rawValue;
const selectChildren = options ? options.map(({ name: name2, value: value2 }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", {
value: value2,
children: name2
}, String(value2))) : void 0;
const errorsChildren = (errors == null ? void 0 : errors.length) ? errors.map((error) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Error2, {
children: error
}, error)) : void 0;
const style = hidden ? { display: "none" } : void 0;
const type = typeProp || types[fieldType];
const registerProps = register(String(name), {
setValueAs: (value2) => coerceValue(value2, shape)
});
return /* @__PURE__ */ React3.createElement(Field, {
const labelId = `label-for-${name.toString()}`;
const errorsId = `errors-for-${name.toString()}`;
const a11yProps = {
"aria-labelledby": labelId,
"aria-invalid": Boolean(errors),
"aria-describedby": errors ? errorsId : void 0,
"aria-required": required
};
const SmartInput = React2.useMemo(
() => createSmartInput({
inputComponent: Input,
multilineComponent: Multiline,
selectComponent: Select,
checkboxComponent: Checkbox
}),
[Input, Multiline, Select, Checkbox]
);
if (childrenFn) {
const children = childrenFn({
Label,
SmartInput,
Input,
Multiline,
Select,
Checkbox,
CheckboxWrapper,
Errors,
Error: Error2,
ref,
shape,
fieldType,
name,
required,
label,
type,
options,
errors,
autoFocus,
value,
hidden,
multiline,
placeholder
});
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Field, {
hidden,
style,
...props,
children: mapChildren(children, (child) => {
if (!React2.isValidElement(child))
return child;
if (child.type === Label) {
return React2.cloneElement(child, {
id: labelId,
htmlFor: String(name),
children: label,
...child.props
});
} else if (child.type === SmartInput) {
return React2.cloneElement(child, {
fieldType,
type,
selectChildren,
multiline,
placeholder,
registerProps,
autoFocus,
value,
a11yProps,
...child.props
});
} else if (child.type === Input) {
return React2.cloneElement(child, {
id: String(name),
type,
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultValue: value,
...child.props
});
} else if (child.type === Multiline) {
return React2.cloneElement(child, {
id: String(name),
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultValue: value,
...child.props
});
} else if (child.type === Select) {
return React2.cloneElement(child, {
id: String(name),
...registerProps,
...a11yProps,
autoFocus,
defaultValue: value,
children: selectChildren,
...child.props
});
} else if (child.type === Checkbox) {
return React2.cloneElement(child, {
id: String(name),
type,
autoFocus,
...registerProps,
...a11yProps,
placeholder,
defaultChecked: Boolean(value),
...child.props
});
} else if (child.type === Errors) {
if (!child.props.children && !(errors == null ? void 0 : errors.length))
return null;
if (child.props.children || !(errors == null ? void 0 : errors.length)) {
return React2.cloneElement(child, {
id: errorsId,
role: "alert",
...child.props
});
}
return React2.cloneElement(child, {
id: errorsId,
role: "alert",
children: errorsChildren,
...child.props
});
} else {
return child;
}
})
});
}
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, {
hidden,
style,
...props
}, mapChildren(children, (child) => {
if (!React3.isValidElement(child))
return child;
if (child.type === Label) {
return React3.cloneElement(child, {
id: labelId,
htmlFor: String(name),
children: label,
...child.props
});
} else if (child.type === SmartInput) {
return React3.cloneElement(child, {
fieldType,
type,
selectChildren,
multiline,
placeholder,
registerProps,
autoFocus,
value,
a11yProps,
...child.props
});
} else if (child.type === Input) {
return React3.cloneElement(child, {
id: String(name),
type,
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultValue: value,
...child.props
});
} else if (child.type === Multiline) {
return React3.cloneElement(child, {
id: String(name),
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultValue: value,
...child.props
});
} else if (child.type === Select) {
return React3.cloneElement(child, {
id: String(name),
...registerProps,
...a11yProps,
autoFocus,
defaultValue: value,
children: selectChildren,
...child.props
});
} else if (child.type === Checkbox) {
return React3.cloneElement(child, {
id: String(name),
type,
autoFocus,
...registerProps,
...a11yProps,
placeholder,
defaultChecked: Boolean(value),
...child.props
});
} else if (child.type === Errors) {
if (!child.props.children && !(errors == null ? void 0 : errors.length))
return null;
if (child.props.children || !(errors == null ? void 0 : errors.length)) {
return React3.cloneElement(child, {
id: errorsId,
role: "alert",
...child.props
});
}
return React3.cloneElement(child, {
...props,
children: [
fieldType === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(CheckboxWrapper, {
children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Checkbox, {
id: String(name),
type,
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultChecked: Boolean(value)
}),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, {
id: labelId,
htmlFor: String(name),
children: label
})
]
}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, {
children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, {
id: labelId,
htmlFor: String(name),
children: label
}),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SmartInput, {
fieldType,
type,
selectChildren,
multiline,
placeholder,
registerProps,
autoFocus,
value,
a11yProps
})
]
}),
Boolean(errorsChildren) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Errors, {
role: "alert",
id: errorsId,
role: "alert",
children: errorsChildren,
...child.props
});
} else {
return child;
}
}));
children: errorsChildren
})
]
});
}
return /* @__PURE__ */ React3.createElement(Field, {
hidden,
style,
...props
}, fieldType === "boolean" ? /* @__PURE__ */ React3.createElement(CheckboxWrapper, null, /* @__PURE__ */ React3.createElement(Checkbox, {
id: String(name),
type,
...registerProps,
...a11yProps,
placeholder,
autoFocus,
defaultChecked: Boolean(value)
}), /* @__PURE__ */ React3.createElement(Label, {
id: labelId,
htmlFor: String(name)
}, label)) : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Label, {
id: labelId,
htmlFor: String(name)
}, label), /* @__PURE__ */ React3.createElement(SmartInput, {
fieldType,
type,
selectChildren,
multiline,
placeholder,
registerProps,
autoFocus,
value,
a11yProps
})), Boolean(errorsChildren) && /* @__PURE__ */ React3.createElement(Errors, {
role: "alert",
id: errorsId
}, errorsChildren));
});
);
}
// src/defaultRenderField.tsx
var React4 = __toESM(require("react"));
var import_jsx_runtime3 = require("react/jsx-runtime");
function defaultRenderField({

@@ -447,7 +500,6 @@ Field,

}) {
return /* @__PURE__ */ React4.createElement(Field, {
key: String(name),
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, {
name,
...props
});
}, String(name));
}

@@ -457,3 +509,5 @@

function startCase(str) {
const matches = str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) ?? [""];
const matches = str.match(
/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g
) ?? [""];
return matches.map((x) => x.charAt(0).toUpperCase() + x.slice(1)).join(" ");

@@ -467,3 +521,4 @@ }

// src/Form.tsx
// src/createForm.tsx
var import_jsx_runtime4 = require("react/jsx-runtime");
var fieldTypes = {

@@ -476,72 +531,17 @@ ZodString: "string",

};
function Form({
component = import_react.Form,
fetcher,
mode = "onSubmit",
renderField = defaultRenderField,
fieldComponent,
globalErrorsComponent: Errors = "div",
errorComponent: Error2 = "div",
fieldErrorsComponent,
labelComponent,
inputComponent,
multilineComponent,
selectComponent,
checkboxComponent,
checkboxWrapperComponent,
buttonComponent: Button = "button",
buttonLabel: rawButtonLabel = "OK",
pendingButtonLabel = "OK",
method = "post",
schema,
beforeChildren,
onTransition,
parseActionData,
children: childrenFn,
labels,
placeholders,
options,
hiddenFields,
multiline,
errors: errorsProp,
values: valuesProp,
...props
function createForm({
component: DefaultComponent,
useNavigation,
useSubmit,
useActionData
}) {
var _a;
const Component = (fetcher == null ? void 0 : fetcher.Form) ?? component;
const submit = (fetcher == null ? void 0 : fetcher.submit) ?? (0, import_react.useSubmit)();
const transition = fetcher ?? (0, import_react.useTransition)();
const unparsedActionData = (fetcher == null ? void 0 : fetcher.data) ?? (0, import_react.useActionData)();
const actionData = parseActionData && unparsedActionData ? parseActionData(unparsedActionData) : unparsedActionData;
const actionErrors = actionData == null ? void 0 : actionData.errors;
const actionValues = actionData == null ? void 0 : actionData.values;
const errors = { ...errorsProp, ...actionErrors };
const values = { ...valuesProp, ...actionValues };
const form = (0, import_react_hook_form.useForm)({ resolver: (0, import_zod.zodResolver)(schema), mode });
const { formState } = form;
const { errors: formErrors, isValid } = formState;
const [disabled, setDisabled] = React5.useState(false);
React5.useEffect(() => {
const shouldDisable = mode === "onChange" || mode === "all" ? transition.state === "submitting" || !isValid : transition.state === "submitting";
setDisabled(shouldDisable);
}, [transition.state, formState]);
React5.useEffect(() => {
onTransition && onTransition({ transition, ...form });
}, [transition.state]);
const onSubmit = (event) => {
form.handleSubmit(() => submit(event.target))(event);
};
const Field = React5.useMemo(() => createField({
register: form.register,
function Form({
component = DefaultComponent,
fetcher,
mode = "onSubmit",
renderField = defaultRenderField,
fieldComponent,
labelComponent,
inputComponent,
multilineComponent,
selectComponent,
checkboxComponent,
checkboxWrapperComponent,
globalErrorsComponent: Errors = "div",
errorComponent: Error2 = "div",
fieldErrorsComponent,
errorComponent: Error2
}), [
fieldComponent,
labelComponent,

@@ -553,139 +553,219 @@ inputComponent,

checkboxWrapperComponent,
fieldErrorsComponent,
Error2
]);
const schemaShape = objectFromSchema(schema).shape;
React5.useEffect(() => {
var _a2;
buttonComponent: Button = "button",
buttonLabel: rawButtonLabel = "OK",
pendingButtonLabel = "OK",
method = "post",
schema,
beforeChildren,
onTransition,
parseActionData,
children: childrenFn,
labels,
placeholders,
options,
hiddenFields,
multiline,
errors: errorsProp,
values: valuesProp,
...props
}) {
var _a;
const Component = (fetcher == null ? void 0 : fetcher.Form) ?? component;
const submit = (fetcher == null ? void 0 : fetcher.submit) ?? useSubmit();
const transition = fetcher ?? useNavigation();
const unparsedActionData = (fetcher == null ? void 0 : fetcher.data) ?? useActionData();
const actionData = parseActionData && unparsedActionData ? parseActionData(unparsedActionData) : unparsedActionData;
const actionErrors = actionData == null ? void 0 : actionData.errors;
const actionValues = actionData == null ? void 0 : actionData.values;
const errors = { ...errorsProp, ...actionErrors };
const values = { ...valuesProp, ...actionValues };
const form = (0, import_react_hook_form.useForm)({ resolver: (0, import_zod.zodResolver)(schema), mode });
const { formState } = form;
const { errors: formErrors, isValid } = formState;
const [disabled, setDisabled] = React3.useState(false);
React3.useEffect(() => {
const shouldDisable = mode === "onChange" || mode === "all" ? transition.state === "submitting" || !isValid : transition.state === "submitting";
setDisabled(shouldDisable);
}, [transition.state, formState]);
React3.useEffect(() => {
onTransition && onTransition(form);
}, [transition.state]);
const onSubmit = (event) => {
form.handleSubmit(() => submit(event.target))(event);
};
const Field = React3.useMemo(
() => createField({
register: form.register,
fieldComponent,
labelComponent,
inputComponent,
multilineComponent,
selectComponent,
checkboxComponent,
checkboxWrapperComponent,
fieldErrorsComponent,
errorComponent: Error2
}),
[
fieldComponent,
labelComponent,
inputComponent,
multilineComponent,
selectComponent,
checkboxComponent,
checkboxWrapperComponent,
fieldErrorsComponent,
Error2
]
);
const schemaShape = objectFromSchema(schema).shape;
React3.useEffect(() => {
var _a2;
for (const stringKey in schemaShape) {
const key = stringKey;
if (errors && ((_a2 = errors[key]) == null ? void 0 : _a2.length)) {
try {
form.setFocus(key);
} catch {
}
}
}
}, [errorsProp, unparsedActionData]);
let autoFocused = false;
let fields = [];
for (const stringKey in schemaShape) {
const key = stringKey;
if (errors && ((_a2 = errors[key]) == null ? void 0 : _a2.length)) {
try {
form.setFocus(key);
} catch {
}
}
const message = (_a = formErrors[key]) == null ? void 0 : _a.message;
const shape = schemaShape[stringKey];
const errorsArray = message && [message] || errors && errors[key];
const fieldErrors = errorsArray && errorsArray.length ? errorsArray : void 0;
const autoFocus = Boolean(fieldErrors && !autoFocused);
if (autoFocus)
autoFocused = true;
const { typeName, optional, nullable, getDefaultValue, enumValues } = shapeInfo(shape);
const fieldType = typeName ? fieldTypes[typeName] : "string";
const required = !(optional || nullable);
const propOptions = options && options[key];
const enumOptions = enumValues ? enumValues.map((value2) => ({
name: inferLabel(value2),
value: value2
})) : void 0;
const rawOptions = propOptions || enumOptions;
const fieldOptions = rawOptions && !required ? [{ name: "", value: "" }, ...rawOptions ?? []] : rawOptions;
const label = labels && labels[key] || inferLabel(String(stringKey));
const value = values && values[key];
fields.push({
shape,
fieldType,
name: stringKey,
required,
label,
options: fieldOptions,
errors: fieldErrors,
autoFocus,
value: value === void 0 ? getDefaultValue && getDefaultValue() : value,
hidden: hiddenFields && Boolean(hiddenFields.find((item) => item === key)),
multiline: multiline && Boolean(multiline.find((item) => item === key)),
placeholder: placeholders && placeholders[key]
});
}
}, [errorsProp, unparsedActionData]);
let autoFocused = false;
let fields = [];
for (const stringKey in schemaShape) {
const key = stringKey;
const message = (_a = formErrors[key]) == null ? void 0 : _a.message;
const shape = schemaShape[stringKey];
const errorsArray = message && [message] || errors && errors[key];
const fieldErrors = errorsArray && errorsArray.length ? errorsArray : void 0;
const autoFocus = Boolean(fieldErrors && !autoFocused);
if (autoFocus)
autoFocused = true;
const { typeName, optional, nullable, getDefaultValue, enumValues } = shapeInfo(shape);
const fieldType = typeName ? fieldTypes[typeName] : "string";
const required = !(optional || nullable);
const propOptions = options && options[key];
const enumOptions = enumValues ? enumValues.map((value2) => ({
name: inferLabel(value2),
value: value2
})) : void 0;
const rawOptions = propOptions || enumOptions;
const fieldOptions = rawOptions && !required ? [{ name: "", value: "" }, ...rawOptions ?? []] : rawOptions;
const label = labels && labels[key] || inferLabel(String(stringKey));
const value = values && values[key];
fields.push({
shape,
fieldType,
name: stringKey,
required,
label,
options: fieldOptions,
errors: fieldErrors,
autoFocus,
value: value === void 0 ? getDefaultValue && getDefaultValue() : value,
hidden: hiddenFields && Boolean(hiddenFields.find((item) => item === key)),
multiline: multiline && Boolean(multiline.find((item) => item === key)),
placeholder: placeholders && placeholders[key]
});
}
const globalErrors = errors == null ? void 0 : errors._global;
const buttonLabel = transition.state === "submitting" ? pendingButtonLabel : rawButtonLabel;
if (childrenFn) {
const children = childrenFn({
Field,
Errors,
Error: Error2,
Button,
transition,
...form
});
return /* @__PURE__ */ React5.createElement(Component, {
const globalErrors = errors == null ? void 0 : errors._global;
const buttonLabel = transition.state === "submitting" ? pendingButtonLabel : rawButtonLabel;
if (childrenFn) {
const children = childrenFn({
Field,
Errors,
Error: Error2,
Button,
...form
});
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Component, {
method,
onSubmit,
...props,
children: [
beforeChildren,
mapChildren(children, (child) => {
if (!React3.isValidElement(child))
return child;
if (child.type === Field) {
const { name } = child.props;
const field = fields.find((field2) => field2.name === name);
const autoFocus = autoFocused ? field == null ? void 0 : field.autoFocus : child.props.autoFocus;
if (!child.props.children && field) {
return renderField({
Field,
...field,
...child.props,
autoFocus
});
}
return React3.cloneElement(child, {
shape: field == null ? void 0 : field.shape,
fieldType: field == null ? void 0 : field.fieldType,
label: field == null ? void 0 : field.label,
placeholder: field == null ? void 0 : field.placeholder,
required: field == null ? void 0 : field.required,
options: field == null ? void 0 : field.options,
value: field == null ? void 0 : field.value,
errors: field == null ? void 0 : field.errors,
hidden: field == null ? void 0 : field.hidden,
multiline: field == null ? void 0 : field.multiline,
...child.props,
autoFocus
});
} else if (child.type === Errors) {
if (!child.props.children && !(globalErrors == null ? void 0 : globalErrors.length))
return null;
if (child.props.children || !(globalErrors == null ? void 0 : globalErrors.length)) {
return React3.cloneElement(child, {
role: "alert",
...child.props
});
}
return React3.cloneElement(child, {
role: "alert",
children: globalErrors.map((error) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Error2, {
children: error
}, error)),
...child.props
});
} else if (child.type === Button) {
return React3.cloneElement(child, {
disabled,
children: buttonLabel,
...child.props
});
} else {
return child;
}
})
]
});
}
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Component, {
method,
onSubmit,
...props
}, beforeChildren, mapChildren(children, (child) => {
if (!React5.isValidElement(child))
return child;
if (child.type === Field) {
const { name } = child.props;
const field = fields.find((field2) => field2.name === name);
const autoFocus = autoFocused ? field == null ? void 0 : field.autoFocus : child.props.autoFocus;
if (!child.props.children && field) {
return renderField({ Field, ...field, ...child.props, autoFocus });
}
return React5.cloneElement(child, {
shape: field == null ? void 0 : field.shape,
fieldType: field == null ? void 0 : field.fieldType,
label: field == null ? void 0 : field.label,
placeholder: field == null ? void 0 : field.placeholder,
required: field == null ? void 0 : field.required,
options: field == null ? void 0 : field.options,
value: field == null ? void 0 : field.value,
errors: field == null ? void 0 : field.errors,
hidden: field == null ? void 0 : field.hidden,
multiline: field == null ? void 0 : field.multiline,
...child.props,
autoFocus
});
} else if (child.type === Errors) {
if (!child.props.children && !(globalErrors == null ? void 0 : globalErrors.length))
return null;
if (child.props.children || !(globalErrors == null ? void 0 : globalErrors.length)) {
return React5.cloneElement(child, {
role: "alert",
...child.props
});
}
return React5.cloneElement(child, {
...props,
children: [
beforeChildren,
fields.map((field) => renderField({ Field, ...field })),
(globalErrors == null ? void 0 : globalErrors.length) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Errors, {
role: "alert",
children: globalErrors.map((error) => /* @__PURE__ */ React5.createElement(Error2, {
key: error
}, error)),
...child.props
});
} else if (child.type === Button) {
return React5.cloneElement(child, {
children: globalErrors.map((error) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Error2, {
children: error
}, error))
}),
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, {
disabled,
children: buttonLabel,
...child.props
});
} else {
return child;
}
}));
children: buttonLabel
})
]
});
}
return /* @__PURE__ */ React5.createElement(Component, {
method,
onSubmit,
...props
}, beforeChildren, fields.map((field) => renderField({ Field, ...field })), (globalErrors == null ? void 0 : globalErrors.length) && /* @__PURE__ */ React5.createElement(Errors, {
role: "alert"
}, globalErrors.map((error) => /* @__PURE__ */ React5.createElement(Error2, {
key: error
}, error))), /* @__PURE__ */ React5.createElement(Button, {
disabled
}, buttonLabel));
return Form;
}
// src/formAction.server.ts
var import_server_runtime = require("@remix-run/server-runtime");
// src/mutations.ts
var import_domain_functions = require("domain-functions");
var import_domain_functions2 = require("domain-functions");
async function getFormValues(request, schema) {

@@ -715,4 +795,6 @@ const shape = objectFromSchema(schema).shape;

errors: {
...(0, import_domain_functions2.errorMessagesForSchema)(result.inputErrors, schema),
_global: result.errors.length || result.environmentErrors.length ? [...result.errors, ...result.environmentErrors].map((error) => error.message) : void 0
...(0, import_domain_functions.errorMessagesForSchema)(result.inputErrors, schema),
_global: result.errors.length || result.environmentErrors.length ? [...result.errors, ...result.environmentErrors].map(
(error) => error.message
) : void 0
},

@@ -723,39 +805,45 @@ values

}
async function formAction({
request,
schema,
mutation,
environment,
beforeAction,
beforeSuccess,
successPath
function createFormAction({
redirect,
json
}) {
if (beforeAction) {
const beforeActionResponse = await beforeAction(request);
if (beforeActionResponse)
return beforeActionResponse;
}
const result = await performMutation({
async function formAction({
request,
schema,
mutation,
environment
});
if (result.success) {
if (beforeSuccess) {
const beforeSuccessResponse = await beforeSuccess(request);
if (beforeSuccessResponse)
return beforeSuccessResponse;
environment,
beforeAction,
beforeSuccess,
successPath
}) {
if (beforeAction) {
const beforeActionResponse = await beforeAction(request);
if (beforeActionResponse)
return beforeActionResponse;
}
const path = typeof successPath === "function" ? successPath(result.data) : successPath;
return path ? (0, import_server_runtime.redirect)(path) : (0, import_server_runtime.json)(result.data);
} else {
return (0, import_server_runtime.json)({ errors: result.errors, values: result.values });
const result = await performMutation({
request,
schema,
mutation,
environment
});
if (result.success) {
if (beforeSuccess) {
const beforeSuccessResponse = await beforeSuccess(request);
if (beforeSuccessResponse)
return beforeSuccessResponse;
}
const path = typeof successPath === "function" ? successPath(result.data) : successPath;
return path ? redirect(path) : json(result.data);
} else {
return json({ errors: result.errors, values: result.values });
}
}
return formAction;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Form,
formAction,
createForm,
createFormAction,
performMutation
});
{
"name": "remix-forms",
"version": "0.19.0",
"description": "Magically create forms + actions in Remix!",
"version": "1.0.0",
"description": "The full-stack form library for Remix and React Router",
"main": "./dist/index.js",

@@ -9,3 +9,3 @@ "module": "./dist/index.mjs",

"files": [
"*",
"README.md",
"./dist/*"

@@ -35,26 +35,22 @@ ],

"lint": "eslint *.ts*",
"tsc": "tsc",
"test": "vitest run"
},
"peerDependencies": {
"@remix-run/react": ">=1.2",
"@remix-run/server-runtime": ">=1.2",
"domain-functions": ">=1.0.0",
"react": ">=16.8",
"react-hook-form": ">=7.27",
"domain-functions": ">=1.0.0",
"zod": ">=3.12"
},
"devDependencies": {
"@remix-run/dev": "^1.4.1",
"@remix-run/node": "^1.4.1",
"@remix-run/react": "^1.4.1",
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"@types/react": ">=16.8",
"@types/react-dom": ">=16.8",
"c8": "^7.11.2",
"eslint": "^7.32.0",
"eslint-config-custom": "*",
"react": "^17.0.2",
"react": ">=16.8",
"tsconfig": "*",
"tsup": "^6.1.3",
"typescript": "^4.5.2",
"vitest": "^0.10.0"
"typescript": "~4.5.5",
"vitest": "~0.10.0"
},

@@ -61,0 +57,0 @@ "dependencies": {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc