@eaze/input

React components:

Stats

stars 🌟issues ⚠️updated 🛠created 🐣size 🏋️‍♀️
@eaze/input
Minified + gzip package size for @eaze/input in KB

Readme

Automated inputs and forms

This is a new (as of Jan 2017) set of input/form components.

import {
  Checkbox,
  Password,
  Email,
  Zipcode,
  PhoneNumber,
  Form,
  Input,
  InputWithLabel,
  TextField,
  Select
} from '@eaze/input'

Motivation

We need a set of controlled inputs and forms that allow for autocompletion in mobile and enough built-in management that forms come with the following:

  • Field-level errors
  • Float labels
  • Self-managed submit buttons that correctly trigger the Go on Safari mobile keyboards and manage their disabled states

Changes

Changes from old inputs (made by @ghigo):

  • Form state is now in React state, not in Redux
  • Inputs are not copied using React's cloneElement, so they are safe to modify after construction
  • Inputs self-register and update through React's context methods
  • Because the inputs require the context methods, these inputs are not usable outside of the Form component

How to use

Here are some examples of how to use/create the new inputs and forms.

Creating a Form

Example:

  <Form
    // define an onSubmit, which will receive an object with
    // keys equal to the `name` supplied to each input
    // ex: {email: { value: 'john@smith.com', valid: true }, password: { value: '123', valid: false }}
    onSubmit={this.onSubmit}
    // This submit text will appear on the submit button
    // automatically included with and managed by the form
    // unless you set the `includeButton` prop to false,
    // in which case you'll have to supply your own button.
    submitText={'Sign up'}
    // `includeButton` defaults to true.
    // If you set it to false, supply your own buttons, as in this example
    includeButton={false}
  >
    // A higher level component that consumes `./input-with-label.js`
    <EmailInput
      name='email'
      placeholder='Email'
      eagerValidate
      required
    />
    // ... Other inputs like EmailInput
    // Because we declared `includeButton` prop as false, we set buttons here
    <div className={style.buttons}>
      // Use FormButton when making custom form buttons
      // This consumes EazeButton and overwrites props with
      // the correct props taken in through React `context` methods
      <FormButton
        buttonProps={{
          loading: this.props.loading,
          title: 'Sign up',
          type: buttonTypes.PRIMARY
        }}
      />
      <div className={style.border}>
        <Border />
      </div>
      <div className={style.logIn}>
        Already have an account?
        <div className={style.logInButton}>
          <FormButton
            buttonProps={{
              title: 'Log In',
              type: buttonTypes.TERTIARY
            }}
          />
        </div>
      </div>
    </div>
  </Form>

Creating a new input

Inputs self-register through context methods. Required methods/properties for a new higher-level input include the following:

  • <Component>.contextTypes: Must include #register and #onChange context methods to be used in the constructor and when the input updates.
  • Validators: in the constructor, make a this.validators array of functions that are used by the consumed Input
  • #componentDidMount: Must register using the this.context.register function
  • #onChange: Must make a function that takes the input's change event and abstracts its value into the context.onChange method

Generally you'll want to consume and use InputWithLabel, as that comes with float labels.

Example:

  import React from 'react'
  import PropTypes from 'prop-types'
  import zip from 'zippo'

  import InputWithLabel from './input-with-label'

  class Zipcode extends React.Component {
    constructor () {
      super()

      this.onChange = this.onChange.bind(this)
      // This array should have functions that either return null when there are no errors
      // and return strings of error messages when there are errors
      this.validators = [
        // check for null if required
        (value) => {
          if (!this.props.required) return null
          if (!value) return 'Zipcode is required.'
        },
        (value) => {
          if (!value) return null
          return zip.validate(value) ? null : 'Please enter a valid zipcode'
        }
      ]
    }

    onChange (e) {
      this.context.onChange(this.props.name, e.target.value, this.wrapper.inputContainer.isValid())
    }

    componentDidMount () {
      this.context.register(this.props.name, this.props.initialValue)
    }

    // if you want to provide a parser to be used by Input, define it here and pass it down.
    // Make it a function that takes and returns a string.
    parser (value) {
      return zip.parse(value || '')
    }

    render () {
      // Use phone type input to force number keyboard on mobile devices
      return (
        <InputWithLabel
          {...this.props}
          name={this.props.name}
          type='phone'
          parser={this.parser}
          validators={this.validators}
          onChange={this.onChange}
          ref={(wrapper) => { this.wrapper = wrapper }}
          eagerValidate
        />
      )
    }
  }

  Zipcode.contextTypes = {
    onChange: PropTypes.func,
    register: PropTypes.func
  }

  export default Zipcode

Where is @eaze/input used?

Disclaimer: This is not a complete list

If you find any bugs or have a feature request, please open an issue on github!

The npm package download data comes from npm's download counts api and package details come from npms.io.