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

@habx/lib-form-helper

v8.2.0

Published

Wrappers for react-final-form

Downloads

100

Readme

lib-form-helper

Helpers and wrappers for React Final Form built with @habx/ui-core


Components

Form: React.VoidFunctionComponent<HabxFormProps>

The Form component is a wrapper around the Form component of react-final-form. It allows advanced error and disabled management.

Example

import * as React from 'react'
import { Form, withFinalForm } from '@habx/lib-form-helper'
import { TextInput } from '@habx/ui-core'

const WrappedTextInput = withFinalForm()(TextInput)

export const MyForm = ({ onSubmit }) => (
  <Form
    initialValues={{ firstName: 'Victor', familyName: 'Hugo' }}
    onSubmit={onSubmit}
    render={(
      <React.Fragment>
        <WrappedTextInput name='firstName' />
        <WrappedTextInput name='familyName' />
      </React.Fragment>
    )}
  />
)

FormSection

Component allowing you to build custom feedback for your errors. Each FormSection is aware of the errors of the fields inside them.

Example

Change the style of your section if some fields inside it have an error (e.g: put the title of the card in red)

import * as React from 'react'
import { Form, FormSection, withFinalForm } from '@habx/lib-form-helper'
import { Card, TextInput } from '@habx/ui-core'

const WrappedTextInput = withFinalForm()(TextInput)

const FormCard = ({ name, title, children }) => (
  <FormSection>
    {({ hasError }) => (
      <Card error={hasError} title={title}>
        { children }
      </Card>
    )}
  </FormSection>
)

export const MyForm = ({ onSubmit }) => (
  <Form
    initialValues={{ firstName: 'Victor', familyName: 'Hugo' }}
    onSubmit={onSubmit}
    render={(
      <FormCard name='basic-informations' title='Basic Informations'>
        <WrappedTextInput name='firstName' />
        <WrappedTextInput name='familyName' />
      </FormCard>
    )}
  />
)

FormSectionWatcher

Component allowing you to listen to your section state.

Example

Build a navigation panel for your sections

import * as React from 'react'
import { Form, FormSection, StatusContext, withFinalForm } from '@habx/lib-form-helper'
import { Card, TextInput, Title } from '@habx/ui-core'

const WrappedTextInput = withFinalForm()(TextInput)

const FormCard = ({ name, title, children }) => (
  <FormSection>
    {({ hasError }) => (
      <Card error={hasError} title={title}>
        { children }
      </Card>
    )}
  </FormSection>
)

const NavigationPanel = () => (
  <FormSectionWatcher id="basic-informations">
    {({ hasError }) => (
      <Title type="regular" error={hasError}>Basic Informations</Title>
    )}
  </FormSectionWatcher>
)

export const MyForm = ({ onSubmit }) => (
  <Form
    initialValues={{ firstName: 'Victor', familyName: 'Hugo' }}
    onSubmit={onSubmit}
    render={(
      <React.Fragment>
        <NavigationPanel />
        <FormCard name='basic-informations' title='Basic Informations'>
          <WrappedTextInput name='firstName' />
          <WrappedTextInput name='familyName' />
        </FormCard>
      </React.Fragment>
    )}
  />
)

Hooks

useFinalFormField

Hook wrapping the useField hook of React Final Form If allows advanced behaviors such as :

  • Describes when to display the errors of on the field
  • Automatically disable the field when the form is disabled
  • Nested sections (see FormSection)
  • Only update field value in form state on blur
  • Set the field as required

We recommend to directly use useFinalFormField only when your use case is too specific for withFinalFormField Most of the time, you should be able to build reusable wrappers with withFinalForm

Example

import { FormatterCallback, ParserCallback, FieldError, useFinalFormField } from '@habx/lib-form-helper'
import { Slider } from '@habx/ui-core'

export const surfaceFormat: FormatterCallback<number, number> = (value) =>
  value ? value / 10000 : value

export const surfaceParse: ParserCallback<number, number> = (value) =>
  value ? value * 10000 : value

export const MyField = () => {
  const {
    input,
    error,
    label,
    disabled,
    shouldDisplayInlineError,
    shouldBeInErrorMode,
    errorBehavior,
  } = useFinalFormField<number>(name, {
    label: "Garden surface",
    parse: surfaceParse,
    format: surfaceFormat,
  })
  
  return (
    <React.Fragment>
      <Slider {...input} error={shouldBeInErrorMode} />
      <FieldError
        showError={shouldDisplayInlineError}
        value={error}
        errorBehavior={errorBehavior}
      />
    </React.Fragment>
  )
}

useFormAutoSubmitDecorator

Allow to submit the form whenever a field value changes Handles debouncing of a list of fields.

Example

import * as React from 'react'
import { Form, useFormAutoSubmitDecorator } from '@habx/lib-form-helper'

import { EmailInput } from '@components/final-form/EmailInput'
import { Select } from '@components/final-form/Select'

export const MyForm = ({ onSubmit }) => {
  const autoSubmitDecorator = useFormAutoSubmitDecorator({
    debouncedFields: ['email']
  })
  
  return (
    <Form
      initialValues={{ email: '', role: 'user' }}
      decorators={[autoSubmitDecorator]}
      onSubmit={onSubmit}
      render={(
        <React.Fragment>
          <EmailInput name='email' required />
          <Select name='role' options={USER_ROLES} required />
        </React.Fragment>
      )}
    />
  )
}

useFormKeyboardSubmitDecorator

Allow to submit the form by hitting Ctrl + S or Cmd + S

Example

import * as React from 'react'
import { Form, useFormAutoSubmitDecorator } from '@habx/lib-form-helper'

import { EmailInput } from '@components/final-form/EmailInput'

export const MyForm = ({ onSubmit }) => {
  const keyboardSubmitDecorator = useFormKeyboardSubmitDecorator()
  
  return (
    <Form
      decorators={[keyboardSubmitDecorator]}
      onSubmit={onSubmit}
      render={<EmailInput name='email' required />}
    />
  )
}

useFormattedNumber

Hook to have a formatted string in the input, but a valid number in the form state

Example

const InnerNumberInput = ({
  factor,
  onChange,
  value,
  ...props
}) => {
  const [formatted, handleChange] = useFormattedNumber({
    factor,
    intl: 'fr',
    onChange,
    value,
  })

  return (
    <TextInput
      {...props}
      value={formatted}
      onChange={(event) => handleChange(event.target.value)}
    />
  )
}

export const NumberInput = withFinalForm<number>()(InnerNumberInput)

High Order Components

withFinalForm

High Order Component internally calling useFinalFormField and allowing defining reusable fields with common validation and parsing / formatting.

Example: EmailInput

import { withFinalForm, ValidationCallback } from '@habx/lib-form-helper'
import { TextInput } from '@habx/ui-core'

import { isEmail } from '@lib/validator'

const validate: ValidationCallback<string, any> = (
  email: string | undefined
) => {
  if (email && !isEmail(email)) {
    return 'Email non valide'
  }

  return undefined
}

export const EmailInput = withFinalForm<string>({
  validate,
  errorBehavior: 'dirty',
})(TextInput)

Example : SurfaceSlider

import { FormatterCallback, ParserCallback, withFinalForm } from '@habx/lib-form-helper'
import { Slider } from '@habx/ui-core'

export const surfaceFormat: FormatterCallback<number, number> = (value) =>
  value ? value / 10000 : value

export const surfaceParse: ParserCallback<number, number> = (value) =>
  value ? value * 10000 : value

export const SurfaceSlider = withFinalForm<number>({
  parse: surfaceParse,
  format: surfaceFormat,
})(Slider)