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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-ios-style-time-picker

v0.1.0

Published

A lightweight, customizable iOS-style rolling wheel time picker component for React.

Readme

npm

React iOS Style Time Picker

React iOS style time picker demo

A lightweight, customizable iOS-style rolling wheel time picker component for your next React app — supports 12/24-hour format, infinite scroll, and multiple locales.

Demo

Check out the live demo here: Live Demo

install

npm i react-ios-style-time-picker

Usage

12 hours format

import { useState } from 'react';
import { TimePicker } from 'react-ios-style-time-picker';
import 'react-ios-style-time-picker/style.css';

function App() {
  const [time, setTime] = useState<{ hour: number; minute: number }>({
    hour: new Date().getHours(),
    minute: new Date().getMinutes(),
  });

  const handleTimeChange = (hour: number, minute: number) => {
    setTime({ hour, minute });
  };

  return (
    <div>
      <TimePicker onChange={handleTimeChange} hourFormat='12' />
    </div>
  );
}

24 hours format

import { useState } from 'react';
import { TimePicker } from 'react-ios-style-time-picker';
import 'react-ios-style-time-picker/style.css';

function App() {
  const [time, setTime] = useState<{ hour: number; minute: number }>({
    hour: new Date().getHours(),
    minute: new Date().getMinutes(),
  });

  const handleTimeChange = (hour: number, minute: number) => {
    setTime({ hour, minute });
  };

  return (
    <div>
      <TimePicker onChange={handleTimeChange} hourFormat='24' />
    </div>
  );
}

Controlled

Pass value and update it from onChange, like a React <input>. Changing value from outside (buttons, API responses, resets) moves the wheels without recreating the picker and without calling onChange.

import { useState } from 'react';
import { TimePicker, type TimePickerValue } from 'react-ios-style-time-picker';
import 'react-ios-style-time-picker/style.css';

function App() {
  const [time, setTime] = useState<TimePickerValue>({ hour: 9, minute: 0 });

  return (
    <div>
      <TimePicker
        value={time}
        onChange={(hour, minute) => setTime({ hour, minute })}
      />
      <button onClick={() => setTime({ hour: 18, minute: 30 })}>6:30 PM</button>
    </div>
  );
}

Uncontrolled

<TimePicker
  defaultValue={{ hour: 7, minute: 30 }}
  onChange={(hour, minute) => console.log(hour, minute)}
/>

Props

| Prop | Type | Required | Default | Description | | :------------- | :--------------------------------------- | :------- | :----------- | :--------------------------------------------------------------------------------------------------- | | onChange | (hour: number, minute: number) => void | ✅ | - | Called (debounced 100ms) when the user changes the time. hour is always 0-23 | | value | { hour: number; minute: number } | ❌ | undefined | Controlled time (hour 0-23, minute 0-59). Changes move the wheels without firing onChange | | defaultValue | { hour: number; minute: number } | ❌ | current time | Initial time for uncontrolled usage. Ignored when value is set | | initTime | Date | ❌ | new Date() | Deprecated — alias of defaultValue, kept for backward compatibility | | infinite | boolean | ❌ | false | Enables infinite scroll style | | className | string | ❌ | undefined | Custom class name for styling | | hourFormat | '12' | '24' | ❌ | '12' | Time format (12-hour/24-hour) | | locale | 'en' | 'ko' | 'ja' | 'zh' | ❌ | 'en' | Language for AM/PM (English, Korean, Japanese, Chinese). Changes are applied in place |

Exported types: TimePickerProps, TimePickerValue, TimePickerLocale.

Behavior notes

  • Initial value priority: value → defaultValue → initTime → current time. defaultValue / initTime are read on mount only.
  • onChange on mount: in uncontrolled mode onChange is called once after mount with the initial time (same as previous versions). In controlled mode it is not.
  • Controlled mode: user gestures move the wheels immediately and report through onChange; update value with the reported time. Setting value to the time the picker already shows is a no-op, so echoing onChange back never loops. If you do not update value, the wheels keep the user's selection until value changes. A value change during a drag is overridden when the drag ends. Invalid values are ignored with a console warning.
  • Rebuilds: changing hourFormat or infinite re-renders the wheels (their DOM structure differs) and keeps the currently selected time. locale only swaps the AM/PM labels and does not rebuild.

Migrating from initTime

initTime still works but is deprecated and may be removed in a future major version.

- <TimePicker initTime={new Date(2025, 0, 1, 7, 30)} onChange={handleChange} />
+ <TimePicker defaultValue={{ hour: 7, minute: 30 }} onChange={handleChange} />

Performance

While a wheel moves, only items that enter or leave the visible range have their visibility updated, instead of every item on every animation frame. For a 60-item minute wheel, a 60-frame flick went from 3,600 to 60 style.visibility writes. See BENCHMARK.md for the method, all scenarios and how to reproduce.

Time Format (hourFormat)

  • 12: Displays AM/PM notation
  • 24: Displays 0-23 hour format

Get involved!

We appreciate your feedback and contributions. If you have feature requests, questions, or want to contribute code or config files, please don't hesitate to use the GitHub Issue tracker.

We welcome all individual contributors, regardless of their level of experience or skill set. Your contributions are valuable, and we are excited to see what you can accomplish in this collaborative and supportive environment.

Reference

Inspired by ios-style-picker

It's forked from this gist

License

The MIT License.