npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

turiy-form

v2.3.5

Published

This package is built on shadcn, zod

Readme

Turiy Form Package

This package is made on react, react-dom, zod,tailwindcss, shadcn, radix-ui and react-hook-form.

This is actually help to create a form with validator.

Recommended to use inside react components .

Create your own FormxField and send it to Formx

//Example given for NextJS
"use client";
import React from "react";
import { Formx, FormxField, regex, equal, Button } from "turiy-form";
import { useToast } from "@/hooks/use-toast"; //toast from shadcn

const signupDefaultValue = {
  email: "",
  password: "",
  cpassword: "",
  uname: "",
  gender: "",
  mob: "",
};

const SignupForm = () => {
  const [busy, setBusy] = React.useState(false);

  function onSubmit(values: any) {
    if (equal(signupDefaultValue, values)) {
      toast({
        title: "😎 No change!",
        description: " You have not made any changes.",
        variant: "destructive",
      });
      return;
    }
    setBusy(true);
    //Todo: do your stuffs here
    setBusy(false);
  }

  return (
    <Formx
      className="grid grid-cols-1 gap-4 text-slate-950"
      onSubmit={onSubmit}
      submitButton={
        <Button type="submit" className="mx-auto px-8">
          Send reset link
        </Button>
      }
      refine={{
        //Compare on form fields
        on: (data: any) => data.password === data.cpassword,
        //Error message if above is false
        message: "Please confirm your password",
        //Field name where message will be shown
        path: ["cpassword"],
      }}
    >
      <FormxField
        name="email"
        label="Email"
        placeholder="[email protected]"
        type="email"
        required
        match={regex.email}
        defaultValue=""
      />
      <FormxField
        name="password"
        label="Password"
        placeholder="Password like $hRk25!n"
        type="password"
        required
        match={regex.password}
        defaultValue=""
      />
      <FormxField
        name="cpassword"
        label="Confirm Password"
        placeholder="Type the password again"
        type="password"
        required
        match={regex.password}
        defaultValue=""
      }
      />
      <FormxField
        name="uname"
        label="Your name"
        placeholder="Write your name"
        type="text"
        required
        match={{ type: "string", min: 3 }}
        defaultValue=""
      />
      <FormxField
        name="gender"
        label="Gender"
        placeholder="Gender"
        type="select"
        required
        defaultValue=""
        selectProps={{
          options: [
            { label: "Male", value: "1" },
            { label: "Female", value: "2" },
            { label: "Other", value: "3" },
          ],
        }}
      />
      <FormxField
        name="mob"
        label="Mobile no."
        placeholder="+91XXXXXXXXXX"
        type="tel"
        required
        match={regex.mobile}
        defaultValue=""
      />
    </Formx>
  );
};

export default SignupForm;

Formx - A Declarative Form Library for React

Formx is a powerful, declarative form library for React that simplifies form creation, validation, and state management. By leveraging the robustness of react-hook-form and the type-safety of zod, Formx allows you to build complex forms with minimal boilerplate. Simply define your fields, and Formx handles the rest.

Built with a modern stack including tailwindcss and shadcn/ui for styling, it's designed to be both highly functional and aesthetically pleasing out of the box.

Core Concepts

Formx follows a declarative "container-presenter" pattern:

  1. <Formx> (The Container): This is the main component that orchestrates everything. It reads the configuration from its children, dynamically generates a zod validation schema, manages the form's state using react-hook-form, and handles submissions.

  2. <FormxField> (The Declarative API): This component doesn't render any UI itself. Instead, it acts as a "marker" or a configuration object. You use it to define the properties of each form field, such as its name, label, type, and validation rules. <Formx> then uses this information to render the appropriate input (<FormxInput> or <FormxSelect>).

This approach keeps your form definitions clean, readable, and centralized.

Installation

npm install turiy-form

or if you use yarn:

yarn add turiy-form

Note: Formx relies on peer dependencies like react, react-hook-form, zod, and tailwindcss. Ensure these are correctly set up in your project.


Quick Start

Let's create a simple login form. This example demonstrates the basic usage of <Formx> and <FormxField>.

// components/LoginForm.tsx
"use client";
import React from "react";
import { Formx, FormxField, regex } from "turiy-form";
import { Button } from "@/components/ui/button"; // Your project's Button component

const LoginForm = () => {
  const handleLogin = (data) => {
    console.log("Form Submitted:", data);
    // API call to your backend would go here
    alert(JSON.stringify(data, null, 2));
  };

  return (
    <Formx
      onSubmit={handleLogin}
      submitButton={<Button type="submit">Log In</Button>}
      className="space-y-4"
    >
      <FormxField
        name="email"
        label="Email Address"
        placeholder="Enter your email"
        type="email"
        required
        match={regex.email}
        defaultValue=""
      />
      <FormxField
        name="password"
        label="Password"
        placeholder="Enter your password"
        type="password"
        required
        match={{ type: "string", min: 6 }}
        defaultValue=""
        description="Password must be at least 6 characters."
      />
    </Formx>
  );
};

export default LoginForm;

API Reference

<Formx /> Props

The main container component that wraps your form fields.

| Prop | Type | Required | Description | | -------------- | ------------------------------------------------------------------------ | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | children | ReactElement<FormxFieldProps> \| ReactElement<FormxFieldProps>[] | Yes | One or more <FormxField> components that define the form structure. | | onSubmit | (data: { [name: string]: string; }) => void | Yes | Callback executed with the form data when submission is successful and validation passes. | | submitButton | ReactNode | No | A React component to render as the submit button. It will be automatically wired to the form's submission. | | resetButton | ReactNode | No | A React component to render as the reset button. | | onChange | (data: { [name: string]: string; selectedFieldName: string; }) => void | No | Callback triggered on any field value change. It receives the complete form data and the name of the field that was just changed. | | onInit | (form: UseFormReturn) => void | No | Callback executed once the form is initialized, providing direct access to the react-hook-form instance for advanced control (e.g., form.setValue). | | refine | { on: (data: object) => boolean; message: string; path: string[]; } | No | Defines a complex cross-field validation rule that runs after individual field validations. See the advanced example below. | | className | string | No | CSS class names to apply to the div that wraps all form fields. |

<FormxField /> Props

The configuration component for each field in your form.

| Prop | Type | Required | Description | | -------------- | ------------------------------------------------------------------- | :----------------------------: | ------------------------------------------------------------------------------------------------------------------------ | | name | string | Yes | The unique identifier for the field. This becomes the key in the form data object. | | label | string | Yes | The text label displayed above the form field. | | placeholder | string | Yes | The placeholder text for the input. | | defaultValue | string | Yes | The initial value of the field. | | type | HTMLInputTypeAttribute \| "select" | Yes | The input type (e.g., 'text', 'password', 'email') or "select" for a dropdown menu. | | required | boolean | No | If true, the field is mandatory. An asterisk * is automatically added to the label. | | match | RegExp \| {type: 'string' \| 'number', min?, max?, eq?} | No | Validation rules for the field. Accepts a RegExp or a validation object. See Validation examples. | | selectProps | { options: { label: string; value: string }[], onAdd?: () => {} } | No (Yes if type is 'select') | Configuration for a select input, including the options array and an optional onAdd function. | | description | ReactNode | No | Helper text or description displayed below the input field. | | cached | boolean | No | If true, the field's value is automatically saved to localStorage and reloaded on mount. Great for multi-step forms. | | disabled | boolean | No | If true, the input field will be disabled. | | autoFocus | boolean | No | If true, the input field will be focused automatically when the component mounts. | | className | string | No | Custom CSS classes to apply to the field's wrapper element, allowing for custom layouts (e.g., in a grid). |


Examples

Select Fields

To create a dropdown menu, set type="select" and provide selectProps.

<FormxField
  name="gender"
  label="Gender"
  placeholder="Select your gender"
  type="select"
  required
  defaultValue=""
  selectProps={{
    options: [
      { label: "Male", value: "male" },
      { label: "Female", value: "female" },
      { label: "Other", value: "other" },
    ],
  }}
/>

Select Field with "Add" Button

You can add a + button next to a select input by providing an onAdd callback. This is useful for triggering a modal to create a new option.

const handleAddNewCategory = () => {
  // Logic to open a dialog or navigate to a new page
  alert("Opening modal to add a new category!");
};

<FormxField
  name="category"
  label="Category"
  placeholder="Select a category"
  type="select"
  defaultValue="tech"
  selectProps={{
    options: [
      { label: "Technology", value: "tech" },
      { label: "Health", value: "health" },
    ],
    onAdd: handleAddNewCategory,
  }}
/>;

Validation

The match prop is a powerful way to define validation rules.

1. Regex Validation

Use one of the pre-built regular expressions from the regex object or provide your own.

import { regex } from "turiy-form";

<FormxField
  name="mobile"
  label="Mobile No."
  placeholder="+1-555-555-5555"
  type="tel"
  required
  match={regex.mobile} // Use a predefined regex
  defaultValue=""
/>;

2. Length & Range Validation

Use a validation object for constraints like minimum/maximum length for strings or a numeric range.

// String length validation
<FormxField
  name="username"
  label="Username"
  placeholder="Choose a username"
  type="text"
  required
  match={{ type: "string", min: 4, max: 20 }}
  defaultValue=""
/>

// Numeric range validation
<FormxField
  name="age"
  label="Age"
  placeholder="Enter your age"
  type="number"
  required
  match={{ type: "number", min: 18 }}
  defaultValue=""
/>

3. Cross-Field Validation (Password Confirmation)

Use the refine prop on <Formx> for validation that depends on multiple fields. This is perfect for password confirmation.

<Formx
  onSubmit={handleSignup}
  submitButton={<Button type="submit">Sign Up</Button>}
  refine={{
    // 1. The validation logic. Return true if valid.
    on: (data) => data.password === data.confirmPassword,
    // 2. The error message to show.
    message: "Passwords do not match!",
    // 3. The field where the error message should be displayed.
    path: ["confirmPassword"],
  }}
>
  <FormxField
    name="password"
    label="Password"
    type="password"
    placeholder="Create a strong password"
    required
    defaultValue=""
  />
  <FormxField
    name="confirmPassword"
    label="Confirm Password"
    type="password"
    placeholder="Type the password again"
    required
    defaultValue=""
  />
</Formx>

Field Value Caching

Set the cached prop to true to automatically save a field's value in localStorage. The next time the form renders, the value will be restored. This is ideal for long forms or multi-step wizards where users might accidentally navigate away.

<FormxField
  name="feedback"
  label="Your Feedback"
  placeholder="Share your thoughts..."
  type="text" // Works with any field type
  cached // This enables localStorage caching for this field
  defaultValue="I think this form is..."
/>

Event Handling

You can tap into the form's lifecycle with onChange and onInit.

"use client";
import React, { useState } from "react";
import { Formx, FormxField } from "turiy-form";
import { Button } from "@/components/ui/button";

const EventForm = () => {
  const [liveData, setLiveData] = useState({});

  const handleSubmit = (data) => {
    alert("Submitted!");
  };

  return (
    <div>
      <Formx
        onSubmit={handleSubmit}
        submitButton={<Button type="submit">Submit</Button>}
        onChange={(data) => {
          console.log("Form changed!", data);
          setLiveData(data);
        }}
        onInit={(form) => {
          console.log(
            "Formx initialized! You can access the react-hook-form instance:",
            form
          );
        }}
      >
        <FormxField
          name="first_name"
          label="First Name"
          placeholder="John"
          defaultValue=""
        />
        <FormxField
          name="last_name"
          label="Last Name"
          placeholder="Doe"
          defaultValue=""
        />
      </Formx>

      <div className="mt-8 p-4 border rounded bg-slate-100">
        <h3 className="font-bold">Live Form Data:</h3>
        <pre>{JSON.stringify(liveData, null, 2)}</pre>
      </div>
    </div>
  );
};

export default EventForm;

Utility Functions

The package also exports a few helpful utility functions.

| Function | Description | | :------- | :--------------------------------------------------------------------------------------------------------------------------------------- | | regex | An object containing pre-defined regular expressions for common validations like email, mobile, password, url, etc. | | equal | A deep equality check function. Useful for comparing the current form state with its initial state to see if any changes have been made. | | reset | A function to programmatically reset the form to its default values. Requires access to the react-hook-form instance via onInit. |


Contributing

Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, please fork the repository and open a pull request.

Author

turiy-form © Abhijit Das, Released under the MIT License. Authored and maintained by Abhijit Das.

GitHub

License

This project is licensed under the MIT License.