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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@instructure/quiz-number-input

v21.0.1

Published

Number input with i18n support

Downloads

7,267

Readme


category: packages

An internationalized, controlled number input:

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    number: 0.1
  }

  handleChange = (event, number) => this.setState({ number })

  render () {
    return (
      <div>
        <NumberInput
          {...this.props}
          value={this.state.number}
          onChange={this.handleChange}
        />
        <br />
        <Button onClick={() => this.handleChange({}, '5')}>
          Go with 5
        </Button>
      </div>
    )
  }
}

render(<Example label="Battery capacity in Amp-hrs" step={0.1} min={0.1} />)

With precision:

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    number: 9.99,
    precisionType: 'decimalPrecision',
    precisionValue: 2,
    precision: 2
  }

  handleNumberChange = (event, number) => this.setState({ number })

  handlePrecisionChange = (event, precisionValue, precision) => {
    this.setState({
      precisionValue,
      precision: precision ? Number(precision) : null
    })
  }

  render () {
    return (
      <div>
        <SimpleSelect label="Precision type" onChange={(e, o) => this.setState({ precisionType: o.value })}>
          <SimpleSelect.Option id="decimal" value="decimalPrecision">Decimal</SimpleSelect.Option>
          <SimpleSelect.Option id="significant-digit" value="significantDigits">Significant digits</SimpleSelect.Option>
        </SimpleSelect>
        <br />
        <NumberInput
          label={this.state.precisionType}
          min={0}
          max={10}
          decimalPrecision={0}
          value={this.state.precisionValue}
          onChange={this.handlePrecisionChange}
        />
        <br />
        <NumberInput
          label="Value"
          decimalPrecision={this.state.precisionType === 'decimalPrecision' ?  this.state.precision : null}
          significantDigits={this.state.precisionType === 'significantDigits' ?  this.state.precision : null}
          value={this.state.number}
          onChange={this.handleNumberChange}
        />
      </div>
    )
  }
}

render(<Example />)

The number input accepts and displays values according to the specified locale, which can be supplied either as a property or with ApplyLocale. If a locale is not specified, it will be inferred from the browser.

If the min, max, or step props are given as strings, they will be parsed according to the rules of the en-US locale (with . decimal separator). This is for backward-compatibility only; it is recommended to pass numbers, not strings, for these props.

The onChange prop receives the content of the input as a second argument, and a normalized string parsed according to the current locale as the third argument. For example, if the locale is fr and the input value is set to 1,5, the third argument to onChange will be "1.5". Note that this third argument will be null if the input string cannot be parsed.

If the value prop is a number, it will be formatted according to the locale on render; if a string is given, make sure it is already in the correct format for the locale.

The number input will attempt to format the string on blur. The onChange handler will be called before the onBlur handler.

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    locale: 'de',
    messages: [],
    normalizedValue: '2.4',
    value: 2.4
  }

  handleChange = (event, value, normalizedValue) => {
    this.setState({ value, normalizedValue, messages: [] })
  }

  handleBlur = () => {
    if (this.state.value && !this.state.normalizedValue) {
      this.setState({ messages: [{ text: 'Invalid number', type: 'error' }] })
    } else {
      this.setState({ messages: [] })
    }
  }

  render () {
    const label = this.state.locale === 'de' ? "Comma separator" : "Period separator"
    return (
      <div>
        <SimpleSelect
          renderLabel="Choose locale"
          onChange={(e, o) => this.setState({ locale: o.value })}
        >
          <SimpleSelect.Option id="de" key="de" value="de">de</SimpleSelect.Option>
          <SimpleSelect.Option id="en" key="en" value="en">en</SimpleSelect.Option>
        </SimpleSelect>
        <View padding="small">
          <NumberInput
            renderLabel={label}
            locale={this.state.locale}
            messages={this.state.messages}
            onBlur={this.handleBlur}
            onChange={this.handleChange}
            step={0.1}
            value={this.state.value}
          />
          <p>Normalized value: <code>{JSON.stringify(this.state.normalizedValue)}</code></p>
        </View>
      </div>
    )
  }
}

render(<Example />)

Using a text input

By default, NumberInput will use a numeric input field. This causes mobile Chrome to use a numeric keypad input instead of a regular keyboard input. This may not be the desired behavior, for example if you don't want to indicate to the user that a number is expected, or you want to allow users to type in numbers in scientific notation (see below), but you still need the internationalization features described above.

In this case, pass inputType="text" to the component to use a plain text input instead of a numeric input field:

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    value: '1.23',
    normalizedValue: '1.23'
  }

  handleChange = (event, value, normalizedValue) => this.setState({ value, normalizedValue })

  render () {
    return (
      <View padding="small">
        <NumberInput
          inputType="text"
          label="Text input"
          value={this.state.value}
          onChange={this.handleChange}
        />
        <p>Normalized value: <code>{JSON.stringify(this.state.normalizedValue)}</code></p>
      </View>
    )
  }
}

render(<Example />)

Scientific Notation

The ScientificNumberInput component wraps NumberInput, passing numbers given in scientific notation as the third argument to the onChange handler. The scientific notation format is mantissa * 10 ^ exponent (whitespace-insensitive), e.g. 1.25*10^-3.

Note that numbers in scientific notation are not localized. If you are in a locale that uses commas as the decimal separator, you will still need to use a decimal point . for scientific notation. Thousands separators are not allowed, and the exponent must be an integer.

If the significantDigits or decimalPrecision props are given, they apply to the mantissa. The min, max and step props are ignored (for now).

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    messages: [],
    normalizedValue: '1.175*10^-3',
    value: '1.175*10^-3'
  }

  handleChange = (event, value, normalizedValue) => {
    this.setState({ value, normalizedValue, messages: [] })
  }

  handleBlur = () => {
    if (this.state.value && !this.state.normalizedValue) {
      this.setState({ messages: [{ text: 'Invalid number', type: 'error' }] })
    } else {
      this.setState({ messages: [] })
    }
  }

  render () {
    return (
      <View padding="small">
        <ScientificNumberInput
          inputType="text"
          renderLabel="Scientific notation allowed"
          messages={this.state.messages}
          onBlur={this.handleBlur}
          onChange={this.handleChange}
          value={this.state.value}
        />
        <p>Normalized value: <code>{JSON.stringify(this.state.normalizedValue)}</code></p>
      </View>
    )
  }
}

render(<Example />)

When precision is specified for ScientificNumberInput, it applies to the mantissa only. The exponent must be an integer.

---
example: true
render: false
---
class Example extends React.Component {
  state = {
    value: '1.23*10^2',
    normalizedValue: '1.23*10^2',
    precisionType: 'decimalPrecision',
    precisionValue: 2,
    precision: 2
  }

  handleNumberChange = (event, value, normalizedValue) => this.setState({ value, normalizedValue })

  handlePrecisionChange = (event, precisionValue, precision) => {
    this.setState({
      precisionValue,
      precision: precision ? Number(precision) : null
    })
  }

  render () {
    return (
      <div>
        <SimpleSelect renderLabel="Precision type" onChange={(e, o) => this.setState({ precisionType: o.value })}>
          <SimpleSelect.Option id="decimal-precision" value="decimalPrecision">Decimal</SimpleSelect.Option>
          <SimpleSelect.Option id="significant-digits" value="significantDigits">Significant digits</SimpleSelect.Option>
        </SimpleSelect>
        <br />
        <NumberInput
          label={this.state.precisionType}
          min={0}
          max={10}
          decimalPrecision={0}
          value={this.state.precisionValue}
          onChange={this.handlePrecisionChange}
        />
        <br />
        <ScientificNumberInput
          label="Value"
          inputType="text"
          decimalPrecision={this.state.precisionType === 'decimalPrecision' ?  this.state.precision : null}
          significantDigits={this.state.precisionType === 'significantDigits' ?  this.state.precision : null}
          value={this.state.value}
          onChange={this.handleNumberChange}
        />
        <p>Normalized value: <code>{JSON.stringify(this.state.normalizedValue)}</code></p>
      </div>
    )
  }
}

render(<Example />)