2.0.2 • Published 11 months ago

@time-input-polyfill/react v2.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
11 months ago

TO DO

// These are critical for a successful release

  • set up node scripts for generating the .js and .d.ts files form the TS files and then removing them automatically after publishing
  • TODO item in TimeInputPolyFill.tsx

// These can be done after releasing v2.0.0, not essential for release

  • Apply tests to Class component version
  • convert the Cypress test suite into a separate package
  • Move the forced example version to the top and update the example code sample

@time-input-polyfill/react

hits per month badge

This is a pre-built, plug-and-play, fully accessible React component that will produce an <input type="time"> element with a built in polyfill for IE and Safari support.

  • ✔️ Modeled after the Chrome 78 and Firefox 70 desktop implementations.
  • ✔️ Fully keyboard and screen reader accessible.
  • ✔️ Sends back the same values as real time inputs (24 hour time).
  • ✔️ Only downloads the full polyfill code in the browsers that need it

You may have already come across the plain JavaScript version. This is not just a wrapper component though. This package was built from the ground up in React, for React.

You can view a demo of the time input polyfill in action here: https://dan503.github.io/react-time-input-polyfill/

You can view a demo of the original plain javascript version here: https://dan503.github.io/time-input-polyfill/

Install

The component needs an ES6 compatible environment to run in. It also needs React installed on the project. Take a look at create-react-app to get started with React.

You can then install this polyfill component with npm:

npm i @time-input-polyfill/react

Usage

/* TimeInput.js */

import React from 'react'

// Import the component into your project
import TimeInputPolyfill from '@time-input-polyfill/react'

export function TimeInput({ label, value, setValue }) {
	return (
		<label>
			<span>{label}</span>
			<TimeInputPolyfill
				// Set the value through props
				value={value}
				// Pass the state setter
				setValue={setValue}
			/>
		</label>
	)
}
/* ExampleForm.js */

import React, { useState, useEffect } from 'react'

// import your local time input component into your form component
import { TimeInput } from './TimeInput'

export function ExampleForm() {
	// Use state to keep track of the value
	const [inputValue, setInputValue] = useState('20:30') // default to 8:30 PM

	// Use useEffect to trigger functionality when the value changes
	useEffect(() => {
		console.log({ inputValue })
	}, [inputValue])

	return (
		<form>
			<TimeInput
				label="Label text"
				// Use the state value to set the time
				value={inputValue}
				// Pass the state setter function into the component
				setValue={setInputValue}
			/>
			<button type="submit">Submit</button>
		</form>
	)
}

You can also force-enable the polyfill so that it is active in modern browsers that support <input type="time"> natively. This is helpful when it comes to debugging since it gives you access to modern dev tools (just make sure to disable it again when you are done).

/* TimeInput.js */

import React from 'react'
import TimeInputPolyfill from '@time-input-polyfill/react'

export function TimeInput({ label, currentValue, onInputChange }) {
	return (
		<label>
			<span>{label}</span>
			<TimeInputPolyfill
				value={currentValue}
				/* Force browsers that support input[type=time]
					to use the polyfill.
					(useful for testing and debugging)
				*/ forcePolyfill={true}
				onChange={({ value, element }) => {
					onInputChange(value)
				}}
			/>
		</label>
	)
}

Content Security Policy (CSP) work around

The way that the polyfill avoids downloading the full polyfill code in modern browsers is by injecting the following script tag onto the page:

<script src="https://cdn.jsdelivr.net/npm/@time-input-polyfill/react@1/dist/timePolyfillUtils.js"></script>

That downloads the extra helper functions that the polyfill needs to function.

Your CSP might not allow for this.

To work around the issue, first create a timePolyfillUtils.js file and ensure that whatever you are using to compile your JS also compiles this file as it's own separate thing. Don't import it into your main js file.

// timePolyfillUtils.js

// ES5
require('@time-input-polyfill/react/dist/timePolyfillUtils.js')

// ES6
import '@time-input-polyfill/react/dist/timePolyfillUtils.js'

Then when using the component, add a polyfillSource prop that points to the compiled helpers file on your server.

<TimeInput
	value={currentValue}
	setValue={setCurrentValue}
	polyfillSource="/path/to/timePolyfillUtils.js"
/>

Breaking changes in v2

In v1 you updated the value using an onChange event. This was really clunky though.

// v1 syntax

const [value, setValue] = useState()
// ...
<TimeInput value={value} onChange={({ value }) => setValue(value)} />

In v2, the syntax has been simplified down to this:

// v2 syntax

const [value, setValue] = useState()
// ...
<TimeInput value={value} setValue={setValue} />