useTimePicker

Low-level hook for the scroll-wheel time picker. Manages scroll-based hour/minute/second selection with snap behavior. This hook is typically used internally by the time panel UI, but can be used directly for custom time picker implementations.

Import

import { useTimePicker } from "react-date-range-picker-headless";

Usage

import { useState } from "react";
import { useTimePicker } from "react-date-range-picker-headless";
function MyTimePicker() {
const [hour, setHour] = useState(12);
const [minute, setMinute] = useState(0);
const picker = useTimePicker({
hour,
minute,
onHourChange: setHour,
onMinuteChange: setMinute,
precision: "minute",
hourFormat: "24",
minuteStep: 5,
});
return (
<div style={{ display: "flex", gap: 8 }}>
{/* Hour column */}
<div
ref={picker.hourListRef}
onScroll={picker.handleHourScroll}
style={{ height: picker.itemHeight * 5, overflow: "auto" }}
>
{picker.hours.map((h) => (
<div
key={h}
onClick={() => picker.handleHourClick(h)}
style={{
height: picker.itemHeight,
fontWeight: h === hour ? "bold" : "normal",
}}
>
{String(h).padStart(2, "0")}
</div>
))}
</div>
{/* Minute column */}
{picker.showMinutes && (
<div
ref={picker.minuteListRef}
onScroll={picker.handleMinuteScroll}
style={{ height: picker.itemHeight * 5, overflow: "auto" }}
>
{picker.minutes.map((m) => (
<div
key={m}
onClick={() => picker.handleMinuteClick(m)}
style={{
height: picker.itemHeight,
fontWeight: m === minute ? "bold" : "normal",
}}
>
{String(m).padStart(2, "0")}
</div>
))}
</div>
)}
{/* Period toggle (12-hour mode) */}
{picker.is12Hour && <button onClick={picker.handlePeriodToggle}>{picker.period}</button>}
</div>
);
}

Options

OptionTypeDefaultDescription
hournumberRequired. Current hour. 24h mode: 0-23, 12h mode: 1-12.
minutenumberRequired. Current minute.
secondnumberCurrent second.
periodTimePeriodCurrent AM/PM period (required for 12h mode).
onHourChange(hour: number) => voidRequired. Hour change handler.
onMinuteChange(minute: number) => voidRequired. Minute change handler.
onSecondChange(second: number) => voidSecond change handler.
onPeriodChange(period: TimePeriod) => voidAM/PM change handler.
precisionTimePrecision"minute"Time precision: "hour", "minute", or "second".
hourFormatHourFormat"24""12" or "24" hour format.
minuteStepMinuteStep5Minute increment step.
secondStepSecondStep1Second increment step.
itemHeightnumber32Height (in px) of each scroll item.

Return Values

NameTypeDescription
hoursnumber[]Array of hour values. 24h: [0..23], 12h: [1..12].
minutesnumber[]Array of minute values based on minuteStep (e.g. [0, 5, 10, ...]).
secondsnumber[]Array of second values based on secondStep.
hourIndexnumberIndex of current hour in the hours array.
minuteIndexnumberIndex of current minute in the minutes array.
secondIndexnumberIndex of current second in the seconds array.
showMinutesbooleanWhether minute column should be shown (precision is "minute" or "second").
showSecondsbooleanWhether second column should be shown (precision is "second").
is12HourbooleanWhether using 12-hour format.
periodTimePeriodCurrent AM/PM period.
handlePeriodToggle() => voidToggle between AM and PM.
hourListRefRefObject<HTMLDivElement | null>Ref for the hour scroll container.
minuteListRefRefObject<HTMLDivElement | null>Ref for the minute scroll container.
secondListRefRefObject<HTMLDivElement | null>Ref for the second scroll container.
handleHourScroll() => voidScroll handler for hour column — snaps to nearest item.
handleMinuteScroll() => voidScroll handler for minute column.
handleSecondScroll() => voidScroll handler for second column.
handleHourClick(hour: number) => voidDirectly select an hour value.
handleMinuteClick(minute: number) => voidDirectly select a minute value.
handleSecondClick(second: number) => voidDirectly select a second value.
scrollToValues() => voidProgrammatically scroll all columns to their current values.
itemHeightnumberThe resolved item height (px).
centerIndexnumberIndex of the center visible item (for scroll snap calculations).

Key Behaviors

Scroll Snap

The scroll containers use snap behavior: when the user scrolls and releases, the hook automatically snaps to the nearest valid value and fires the corresponding change callback.

12-Hour Mode

When hourFormat is "12", the hours array contains [1, 2, ..., 12] instead of [0, 1, ..., 23]. The period and handlePeriodToggle return values manage AM/PM state.

Step Values

Minutes and seconds are filtered by their respective step values. For example, minuteStep: 15 produces [0, 15, 30, 45].

scrollToValues

Call scrollToValues() after mount or when programmatically changing values to ensure the scroll containers are positioned correctly.