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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@caldwell619/mui-form-generator

v0.1.0

Published

An API for crafting MUI powered forms.

Downloads

19

Readme

MUI Form Generator

An API for crafting MUI powered forms.

NPM NPM

Demo

GH Pages

Prerequisite

You'll need to fully setup MUI, following this guide.

This is based on MUI v5, using only v4 will not work with this.

Getting Started

yarn add @caldwell619/mui-form-generator

Quick Exmple

The following will render a single text input with a label of "One".

Highlights

  • The name property must match one of your object keys. This is the same behavior as react-hook-form.
  • Each type of input has their own config. The specifics are determined by the type property. For example, select requires you to pass options.

Proivider

**You must add a provider that wraps your form FOR EACH FORM YOU USE. **

This is not shown in this example, but is shown in this one, with just the single form.

Code

import { FC, useContext } from 'react'
import { MuiForm, Config, MuiFormContext } from '@caldwell619/mui-form-generator'
import { Button } from '@mui/material'
import { UseFormReturn } from 'react-hook-form'
import { diff } from 'deep-object-diff'

export const defaultValues: SomeObject = {
  one: 'Rex',
  two: 'Cody',
  three: 'Wolffe'
}

const inputs: Config<SomeObject>[] = [
  {
    type: 'text',
    config: {
      control: {
        name: 'one',
        label: 'One'
      }
    }
  }
]

export const Form: FC = () => {
  const { handleSubmit } = useContext<UseFormReturn<SomeObject>>(MuiFormContext)
  const onSubmit = (data: SomeObject) => {
    console.log('Current state of form', data)
  }
  return (
    <form>
      <MuiForm inputs={inputs} />
      <Button variant='outlined' onClick={handleSubmit(onSubmit)}>
        Submit
      </Button>
    </form>
  )
}

export interface SomeObject {
  one: string
  two: string
  three: string
}

Result

The result is just a single input and your button under it. Clicking submit will console log an object showing your defaults:

{
  one: 'Rex',
  two: 'Cody',
  three: 'Wolffe'
}

Detailed Example

There is a working example with a select input and a text field that can be found here

Supported Inputs

Currently, there are only 2 supported inputs, but this list will grow with time.

  • Single Checkbox
  • Custom Overrides
  • Radio
  • Select
  • Switch
  • Text
  • Multi Checkbox ( Select all that apply )
  • Checkbox Radio ( Many options, can only choose one )

Custom Overrides

If an input you want is not supported, you can "easily" pass your own custom input into the render. For an example, see the Date override.

This is an example of using a Date picker, which is not supported natively by this tool, because they are so specific. There are many different kinds, as well as requiring @mui/lab as a peer dependency.

Component

import { CustomOverrideRenderArgs } from '@caldwell619/mui-form-generator'

export const FormInputDate: FC<CustomOverrideRenderArgs<SomeObject>> = ({
  field: { value, onChange },
  fieldState: { error }
}) => {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DateTimePicker
        value={value}
        onChange={onChange}
        renderInput={params => <TextField fullWidth {...params} error={!!error} />}
      />
    </LocalizationProvider>
  )
}

Schema API

{
  type: 'custom',
  config: {
    control: {
      name: 'startDate',
      children: props => <FormInputDate {...props} />
    }
  }
}

All the inputs together from the example

Validation

You may pass rules to each form component that act as validation. You can read more about the validation rules on react hook form under the "Register Options".

These rules are optional, and will be applied to the unit they are applied to. If none are given, it is assumed the input can be empty upon submission.

There is also validation in the example, here.

rules: {
  required: { value: true, message: 'This is required' },
  pattern: { value: /^[0-9]*$/, message: 'Must be a number' }
},

When the error state is met, the message you provide will be shown as the helper text.

If there is not an error, and you do not provide helperText, it will be set to an empty string to prevent layout shift should an error occur. This means inputs might be sapced further apart because they essentially have an empty helperText to maintain the layout.

Bundle Size

The bundle size is a bit deceptive, as the published version is unminified JS. I haven't found the best way to go about this, but it seems as if the best way is to just provide the source, and let you bundle it.

However you React will also tree shake and minify this library. I'm seeing an average of 3-5kb depending on which inputs are used. This will be less if you are already using these inputs elsewhere in the bundle.

HoC to hook into the Form Provider

Sometime wrapping the consumer is tedious, you don't really need it at the next level, but it has to go somewhere.

import { UseFormReturn } from 'react-hook-form'
import { MuiFormContext, MuiForm } from '@caldwell619/mui-form-generator'

const Form = () => {
  const { handleSubmit } = useContext<UseFormReturn<SomeObject>>(MuiFormContext)
  return (
    <MuiForm inputs={inputs} gridSpacing={1} />
  )
}

const WrappedForm: FC = () => {
  return (
    <MuiFormProvider>
      <Form>
    </MuiFormProvider>
  )
}

In the above, WrappedForm is uneccesary.

Usage

Using withMuiForm, you can access the form config from the same component. It's similar to using MuiFormContext.Consumer, but a bit more conveinient.

import { UseFormReturn } from 'react-hook-form'
import { withMuiForm, MuiFormContext, MuiForm } from '@caldwell619/mui-form-generator'

export const Home = withMuiForm({ defaultValues }, () => {
  const { handleSubmit } = useContext<UseFormReturn<SomeObject>>(MuiFormContext)
  return <MuiForm inputs={inputs} gridSpacing={1} />
})