@formzk/core
v1.1.1
Published
A powerful and flexible core library for form management in React applications, providing a headless form state management solution
Downloads
350
Maintainers
Readme
@formzk/core
@formzk/core was born out of the necessity to overcome the limitations of existing form solutions that often tightly couple form logic with UI components. This coupling can lead to duplicated code and hinder the flexibility needed to adapt to different use cases. By leveraging the power of react-hook-form and introducing a headless architecture, @formzk/core allows developers to register and manage form components globally, ensuring consistency and reducing redundancy. This results in cleaner, more maintainable code and a more efficient development process.
Full documentation: https://louiskhenghao.github.io/formzk/
Table of contents
- Compatibility
- Installation
- Getting Started
- Without declaration merging
- Reference
- Quick Implementation
- Extending with Other UI Libraries
Compatibility
| Peer | Supported range |
| ----------------- | --------------- |
| React | >= 18 |
| react-hook-form | >= 7.40 |
| Node.js (tooling) | >= 18 |
lodash is a runtime dependency of @formzk/core — you do not need to install it yourself.
Installation
yarn add @formzk/core react-hook-form
# or
npm install @formzk/core react-hook-form
# install yup validation (optional)
yarn add yup @hookform/resolvers
# or
npm install yup @hookform/resolversGetting Started
Registering components
Registering components with @formzk/core is straightforward and can be done at the entry point of your application (e.g: app.tsx) or any other preferred location. This flexibility means that there are no restrictions on which UI library you can use. You can seamlessly integrate any UI library that best suits your business needs, allowing for a highly adaptable and customizable form management system. This approach ensures that @formzk/core can fit into any project, regardless of the UI framework in use, providing developers with the freedom to choose the tools that work best for them.
The snippet below uses @mui/material as an example:
import { Formzk } from '@formzk/core';
import Checkbox, { CheckboxProps } from '@mui/material/Checkbox';
import OutlinedInput, { OutlinedInputProps } from '@mui/material/OutlinedInput';
<Formzk.Provider
config={[
{
name: 'MyTextField',
component: OutlinedInput,
props: {
size: 'small',
fullWidth: true,
} as OutlinedInputProps,
},
{
name: 'MyCheckbox',
component: Checkbox,
props: {} as CheckboxProps,
},
]}
>
{/* ... your component */}
</Formzk.Provider>;Module Augmentation
To extend and customize the @formzk/core library with your own component props, use TypeScript's module augmentation feature. This gives you full autocomplete and type-safety on every component="..." usage inside Formzk.Input.
In your project, create a type definition file (e.g. index.d.ts). This file will contain the type augmentations for @formzk:
import { ComponentPropsMap as LibraryComponentPropsMap } from '@formzk/core';
import { OutlinedInputProps } from '@mui/material/OutlinedInput';
import { CheckboxProps } from '@mui/material/Checkbox';
declare module '@formzk/core' {
export interface ComponentPropsMap extends LibraryComponentPropsMap {
MyTextField: OutlinedInputProps;
MyCheckbox: CheckboxProps;
// register over here
}
}NOTE: If your TypeScript configuration isn't picking up the typings by default, you might have to adjust the
includeortypesfields in yourtsconfig.json.
Basic Usage
The following example demonstrates how to use @formzk/core to create a form with validation using yup, integrate custom components, and handle form submission and reset actions. This example shows the flexibility and power of @formzk/core in managing form components and configurations:
import { Formzk, CloneElement } from '@formzk/core';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
// define type for form input
type InputPayload = {
email: string;
password: string;
};
// define form validation schema
const schema = yup.object().shape({
email: yup.string().required('Email is required').email('Invalid email address'),
password: yup.string().required('Password is required').min(8, 'Minimum length is 8 characters'),
});
// create the form
<Formzk.Form<InputPayload>
options={{
resolver: yupResolver(schema),
defaultValues: {
email: '[email protected]',
password: '',
},
}}
onSubmit={(values) => {
console.log('Formzk.Form submission ---->', values);
}}
>
<Formzk.Input name="email" component="MyTextField" />
<Formzk.Input
name="password"
component="MyTextField"
render={(comp, { fieldState }) => {
const error = fieldState.error?.message;
return (
<CloneElement placeholder="Password" error={!!error} helperText={error}>
{comp}
</CloneElement>
);
}}
/>
<Formzk.Input name="rememberMe" component="MyCheckbox" props={{ label: 'Remember Me?' }} />
<Formzk.Submit render={(e) => <button onClick={e}>Submit</button>} />
<Formzk.Reset render={(e) => <button onClick={e}>Reset</button>} />
</Formzk.Form>;Since
@formzk/coreis headless, the layout and styling are left to the developer's discretion — this package focuses on form validation, input field rendering, form submission, and other form-related functionality. Developers can build on top of this package to further extend its features and customize it to fit their needs.
Without declaration merging
You don't strictly have to augment ComponentPropsMap. If you skip that step, @formzk/core falls back to relaxed typing so your form still works:
ComponentPropsOf<K>resolves toanywhenComponentPropsMapis empty, so<Formzk.Input component="MyInput" props={...} />does not collapse tonever.ComponentNameresolves tostringin the unaugmented case, sogetComponent('MyInput')/isRegistered('MyInput')accept any string.
Once you add the declare module '@formzk/core' block above, the same helpers tighten back down to a union of your registered names for full autocomplete.
Reference
This section provides a brief overview of each component provided by @formzk/core and their respective props. Each component is designed to facilitate form management — including validation, input field rendering, form submission, and reset functionality.
Formzk.Provider
The Provider component is used to register and expose form components throughout your application.
Refer
Formzk.Providerdocumentation here
Formzk.Form
The Form component wraps the form logic and integrates with react-hook-form. It handles validation, form submission, and provides a ref to the form instance.
Refer
Formzk.Formdocumentation here
Formzk.Input
The Input component registers an input field with the form. It connects the input field to the form state and validation logic.
Refer
Formzk.Inputdocumentation here
Formzk.Submit
The Submit component renders a button that triggers form submission.
Refer
Formzk.Submitdocumentation here
Formzk.Reset
The Reset component renders a button that resets the form to its default values.
Refer
Formzk.Resetdocumentation here
Formzk.Errors
The Errors component displays a list of form validation errors. It provides a customizable way to render error messages.
Refer
Formzk.Errorsdocumentation here
Quick Implementation
For those who prefer to use Material-UI, we've created a companion package called @formzk/mui. This package provides pre-configured Material-UI components that seamlessly integrate with @formzk/core, making it quick and easy to implement forms with consistency.
Extending with Other UI Libraries
If you would like to implement support for other UI libraries (Tamagui, Mantine, Chakra, etc.), we encourage you to open a PR. See CONTRIBUTING.md for the checklist on how to add a new adapter package. Your efforts will help expand the flexibility and usability of @formzk for everyone.
