TypeScript
Full TypeScript support with type definitions
Installation
#TypeScript definitions are included with the package:
npm install timepicker-ui// Types are automatically availableimport { TimepickerUI } from 'timepicker-ui';import type { TimepickerOptions, ConfirmEventData } from 'timepicker-ui';
Main Interfaces
#TimepickerOptions
The grouped options object (v4.0.0+). Each group has its own exported interface: ClockOptions, UIOptions, LabelsOptions, BehaviorOptions, CallbacksOptions, TimezoneOptions, RangeOptions, WheelOptions and the deprecated ClearBehaviorOptions.
interface TimepickerOptions {clock?: ClockOptions; // type, increments, showSeconds, disabledTime, defaultTime, ...ui?: UIOptions; // theme, mode, animation, backdrop, inline, clearButton, ...labels?: LabelsOptions; // all UI text and accessibility labelsbehavior?: BehaviorOptions; // focusTrap, returnFocus, delayHandler, idcallbacks?: CallbacksOptions; // onConfirm, onCancel, onOpen, onUpdate, ...timezone?: TimezoneOptions; // timezone plugin configrange?: RangeOptions; // range plugin configwheel?: WheelOptions; // wheel / compact-wheel mode configclearBehavior?: ClearBehaviorOptions; // deprecated, use ui.clearButton}// All group interfaces are exported:import type {TimepickerOptions,ClockOptions,UIOptions,LabelsOptions,BehaviorOptions,CallbacksOptions,TimezoneOptions,RangeOptions,WheelOptions,ClearBehaviorOptions,} from 'timepicker-ui';
Event data types
Each event/callback has its own payload type. All of them are exported from 'timepicker-ui'. Fields marked showSeconds are present only when clock.showSeconds is on.
type OpenEventData = {hour: string;minutes: string;seconds?: string; // showSecondstype?: string; // 'AM' or 'PM' (12h mode)degreesHours: number | null; // deprecated, removed in 5.0degreesMinutes: number | null; // deprecated, removed in 5.0};type ConfirmEventData = {hour?: string;minutes?: string;seconds?: string; // showSecondstype?: string;autoCommit?: boolean; // true when triggered by wheel.commitOnScroll};type UpdateEventData = {hour?: string;minutes?: string;seconds?: string; // showSecondstype?: string;};type SelectSecondEventData = { // payload of 'select:second'seconds: string;};type SelectPeriodEventData = { // payload of 'select:period'type: 'AM' | 'PM';};type SwitchFaceEventData = { // payload of 'switch:face'face: 'hours' | 'minutes' | 'seconds';};type CancelEventData = Record<string, never>; // empty payloadtype ClearEventData = {previousValue: string | null;};type ErrorEventData = {error: string;rejectedHour?: string; // deprecated, always undefinedrejectedMinute?: string; // deprecated, always undefinedinputHour?: string | number;inputMinute?: string | number;inputSecond?: string | number; // showSecondsinputType?: string;inputLength?: string | number;};type RangeConfirmEventData = {from: string;to: string;duration: number; // whole minutesdurationSeconds?: number; // showSeconds, exact length in secondsautoCommit?: boolean; // true when triggered by wheel.commitOnScroll};type RangeValidationEventData = {valid: boolean;duration: number; // whole minutesdurationSeconds?: number; // showSeconds, exact length in secondsminDuration?: number;maxDuration?: number;};type WheelScrollEndEventData = {column: 'hours' | 'minutes' | 'seconds' | 'ampm';value: string;previousValue: string | null;};// Also exported: SelectHourEventData, SelectMinuteEventData,// SelectAMEventData and SelectPMEventData (deprecated), ShowEventData,// HideEventData (deprecated),// TimezoneChangeEventData, RangeSwitchEventData,// WheelScrollStartEventDatatype SwitchViewEventData = { // payload of 'switch:view'view: TimepickerView;};type RangeChangeEventData = { // payload of 'range:change'part: 'from' | 'to';from: RangeTimeValue | null;to: RangeTimeValue | null;};
TimepickerEventMap
Maps every event name to its payload type. picker.on / once / off are typed against this map, so handlers get the correct payload type automatically.
import type { TimepickerEventMap } from 'timepicker-ui';interface TimepickerEventMap {open: OpenEventData;cancel: CancelEventData;confirm: ConfirmEventData;clear: ClearEventData;show: ShowEventData;hide: HideEventData; // deprecated, never emittedupdate: UpdateEventData;'select:hour': SelectHourEventData;'select:minute': SelectMinuteEventData;'select:second': SelectSecondEventData;'select:period': SelectPeriodEventData;'select:am': SelectAMEventData; // deprecated, use 'select:period''select:pm': SelectPMEventData; // deprecated, use 'select:period''switch:face': SwitchFaceEventData;'switch:view': SwitchViewEventData;'timezone:change': TimezoneChangeEventData;'range:confirm': RangeConfirmEventData;'range:switch': RangeSwitchEventData;'range:validation': RangeValidationEventData;'range:change': RangeChangeEventData; // new in 4.7.0'wheel:scroll:start': WheelScrollStartEventData;'wheel:scroll:end': WheelScrollEndEventData;error: ErrorEventData;// ...plus internal animation/range coordination events}
getValue() return shape
The object returned by picker.getValue(). seconds is present only with clock.showSeconds, and time then includes it.
{hour: string;minutes: string;seconds?: string; // showSecondstype?: string; // 'AM' or 'PM' (12h mode)time: string; // '14:30', '02:30 PM', '14:30:15', '02:30:15 PM'degreesHours: number | null; // deprecated, removed in 5.0degreesMinutes: number | null; // deprecated, removed in 5.0}
Inline mode shape (ui.inline)
Inline configuration shape, defined inline on UIOptions (not a separately exported type):
ui: {inline?: {enabled: boolean;container?: string | HTMLElement; // required when enabled is truecontainerId?: string; // deprecated, use containershowButtons?: boolean;autoUpdate?: boolean;embedded?: boolean; // part of a host component, default falseshowTitle?: boolean; // default true, new in 4.7.0};}
TimeOfDay
The argument of clock.isTimeDisabled. hour is always 0 to 23, in both clock types. seconds is 0 unless clock.showSeconds is on.
import type { TimeOfDay } from 'timepicker-ui';interface TimeOfDay {hour: number;minutes: number;seconds: number;}const isTimeDisabled = ({ hour }: TimeOfDay): boolean => hour < 9 || hour >= 17;
RangeTimeValue and RangeTimeState
What picker.getRange() returns. An end is null until it has a full time.
import type { RangeTimeValue, RangeTimeState } from 'timepicker-ui';interface RangeTimeValue {hour: string;minutes: string;seconds?: string; // showSecondstype?: string; // 'AM' or 'PM' (12h mode)}interface RangeTimeState {from: RangeTimeValue | null;to: RangeTimeValue | null;}const range: RangeTimeState | null = picker.getRange();
TimepickerView
The two views of the picker. ui.initialView, setView(), getView() and the switch:view payload use it. New in 4.7.0.
import type { TimepickerView } from 'timepicker-ui';type TimepickerView = 'clock' | 'keyboard';
RangeTimeInput and RangeCaptionInput
The arguments of setRange() and setRangeCaptions(). Leave an end out to keep it. null or '' clears a time or removes a caption. New in 4.7.0.
import type { RangeTimeInput, RangeCaptionInput } from 'timepicker-ui';interface RangeTimeInput {from?: string | null; // setValue() format: '09:00', '9:00 AM'to?: string | null;}interface RangeCaptionInput {from?: string | null; // plain text under the tab labelto?: string | null;}picker.setRange({ from: '09:00' });picker.setRangeCaptions({ from: 'Wed Oct 21', to: null });
RangeChangeEventData
The payload of range:change and callbacks.onRangeChange. New in 4.7.0.
import type { RangeChangeEventData } from 'timepicker-ui';interface RangeChangeEventData {part: 'from' | 'to'; // the end that changedfrom: RangeTimeValue | null; // both ends after the changeto: RangeTimeValue | null;}
TimeValue, TimeFormatOptions and DisabledTimeCheckOptions
Types of the parseTime(), formatTime() and createDisabledTimeCheck() helpers. TimeValue is the shape of a time that getValue() and getRange() use. New in 4.7.0.
import type {TimeValue,TimeFormatOptions,DisabledTimeCheckOptions} from 'timepicker-ui';interface TimeValue {hour: string;minutes: string;seconds?: string; // showSecondstype?: string; // 'AM' or 'PM' (12h mode)}interface TimeFormatOptions {clockType?: '12h' | '24h'; // default '12h'showSeconds?: boolean; // default false}type DisabledTimeCheckOptions = Pick<ClockOptions,'type' | 'disabledTime' | 'isTimeDisabled' | 'showSeconds'>;
TimepickerEventName
The names of the events the picker emits, as a union. on(), once() and off() are typed with it, and the handler gets the payload type from TimepickerEventMap. Internal events are not in the union. New in 4.7.0.
import type { TimepickerEventName, TimepickerEventMap } from 'timepicker-ui';function listen<K extends TimepickerEventName>(picker: TimepickerUI,name: K,handler: (data: TimepickerEventMap[K]) => void) {return picker.on(name, handler);}listen(picker, 'range:change', (data) => console.log(data.part));
PluginManager and PluginTimeView
Types for code that builds on the plugin system. PluginManager.setTimeView is optional and new in 4.7.0. The core calls it on the range plugin before init() and hands it a PluginTimeView, a port to the clock or wheel. In the wheel modes, view.show(value) moves the wheel to that time without emitting update, select:* or wheel:scroll:* events. Both types are exported from 'timepicker-ui' and change in 5.0.0, with the rest of the plugin API.
import type { PluginManager, PluginTimeView } from 'timepicker-ui';interface PluginTimeView {show(value: { hour: string; minutes: string; seconds?: string; type?: string }): void;}interface PluginManager {init(): void;destroy(): void;attachPopover?(): void;detachPopover?(): void;scrollToValue?(hour: string, minute: string, type?: string, second?: string): void;getSelection?(): { hour: string; minutes: string; seconds?: string; type?: string } | null;setTimeView?(view: PluginTimeView): void; // new in 4.7.0}
Timezone plugin exports
Exported from 'timepicker-ui/plugins/timezone', not from 'timepicker-ui'. DEFAULT_TIMEZONES is the built-in list of IDs. getTimezoneList(list?) returns one TimezoneInfo for each ID the browser knows, and the built-in list when you pass none. New in 4.7.0.
import {getTimezoneList,DEFAULT_TIMEZONES,type TimezoneInfo} from 'timepicker-ui/plugins/timezone';interface TimezoneInfo {readonly id: string; // 'Asia/Tokyo'readonly label: string; // 'Tokyo (+09:00)'readonly offset: string; // '+09:00'}const DEFAULT_TIMEZONES: readonly string[];function getTimezoneList(list?: readonly string[]): TimezoneInfo[];const zones = getTimezoneList([...DEFAULT_TIMEZONES, 'Europe/Warsaw']);
Disabled time shape (clock.disabledTime)
Disabled time configuration shape, defined inline on ClockOptions. When ranges is set, the hours, minutes and seconds lists are ignored.
clock: {disabledTime?: {hours?: Array<string | number>;minutes?: Array<string | number>;seconds?: Array<string | number>; // used with showSecondsranges?: string | string[]; // e.g. "10:00 AM - 12:00 PM", "10:00:30 AM - 10:05 AM"interval?: string | string[]; // deprecated, use ranges};isTimeDisabled?: (time: TimeOfDay) => boolean; // union with disabledTime}
Default time shape (clock.defaultTime)
Default time configuration shape, defined inline on ClockOptions. 'now' also writes the time to the input. The object form writes it only with updateInput: true.
clock: {defaultTime?:| 'now'| {time?: Date | 'now';updateInput?: boolean;};}
Inline Unions
#ui.theme
Available theme names. The union is defined inline on UIOptions (the library does not export a separate Theme alias).
theme?:| 'basic'| 'crane'| 'crane-straight'| 'm2'| 'm3-green'| 'dark'| 'glassmorphic'| 'pastel'| 'ai'| 'cyberpunk'| 'blueprint'| 'blueprint-dark';
clock.type
Clock format, defined inline on ClockOptions (no exported ClockType alias).
type?: '12h' | '24h' | 'auto'; // 'auto' follows the browser locale
clock.incrementSeconds
Seconds step, defined inline on ClockOptions.
incrementSeconds?: 1 | 5 | 10 | 15 | 20 | 30;
Deprecated Types and Fields
#These are marked @deprecated in the type definitions and will be removed in 5.0. They still compile, so existing code keeps working until then.
| Type or field | Note |
|---|---|
Option names renamed in 4.5.0, e.g. UIOptions.mobile, LabelsOptions.hourLabel | Use the new names. The Options page lists every pair under Renamed in 4.5.0. |
ClearBehaviorOptions and the clearBehavior group | Use ui.clearButton: { clearInput }. |
SelectAMEventData, SelectPMEventData, 'select:am', 'select:pm' | Use SelectPeriodEventData and 'select:period'. |
CallbacksOptions.onSelectAM / onSelectPM | Use onSelectPeriod. |
TimepickerUI.update() | Use setOptions(options). |
OptionTypes | Use TimepickerOptions. |
HideEventData and the 'hide' event | Never emitted. |
OpenEventData.degreesHours / degreesMinutes | Internal clock-hand angles. Use hour and minutes. |
getValue().degreesHours / degreesMinutes | Internal clock-hand angles. Use hour and minutes. |
ErrorEventData.rejectedHour / rejectedMinute | Always undefined. |
ClockOptions.currentTime.locales | Has no effect. The library formats the value. |
LabelsOptions.format24Label | Has no effect. |
LabelsOptions.toggleLabel | Has no effect. The view switch is labelled by switchToKeyboard and switchToClock. |
LabelsOptions.timezoneSelectorLabel | Has no effect. Use labels.timezone. |
'range:get-disabled-time' and 'range:update-disabled' events | Never emitted or read. |
Usage Examples
#Basic TypeScript Usage
import { TimepickerUI } from 'timepicker-ui';import type { TimepickerOptions, ConfirmEventData } from 'timepicker-ui';const options: TimepickerOptions = {ui: { theme: 'dark' },clock: { type: '24h' },callbacks: {onConfirm: (data: ConfirmEventData) => {console.log(`Time: ${data.hour}:${data.minutes}`);}}};const input = document.querySelector<HTMLInputElement>('#timepicker');if (input) {const picker = new TimepickerUI(input, options);picker.create();}
Typed Event Subscriptions
import { TimepickerUI } from 'timepicker-ui';const picker = new TimepickerUI('#timepicker', {clock: { showSeconds: true }});picker.create();// picker.on is typed against TimepickerEventMap -// the handler payload type is inferred from the event namepicker.on('confirm', (data) => {// data: ConfirmEventDataconsole.log(data.hour, data.minutes, data.seconds, data.type, data.autoCommit);});picker.on('select:second', (data) => {// data: SelectSecondEventDataconsole.log(data.seconds);});picker.on('select:period', (data) => {// data: SelectPeriodEventDataconsole.log(data.type); // 'AM' | 'PM'});picker.on('switch:face', (data) => {// data: SwitchFaceEventDataconsole.log(data.face); // 'hours' | 'minutes' | 'seconds'});picker.on('update', (data) => {// data: UpdateEventDataconsole.log(data.hour, data.minutes, data.seconds, data.type);});picker.on('error', (data) => {// data: ErrorEventDataconsole.error(data.error, data.inputHour, data.inputMinute, data.inputSecond);});picker.once('open', (data) => {// data: OpenEventDataconsole.log(data.hour, data.minutes, data.seconds);});
Typed on() overloads
import { TimepickerUI } from 'timepicker-ui';const picker = new TimepickerUI('#timepicker', { range: { enabled: true } });picker.create();picker.on('range:change', (data) => {// data: RangeChangeEventDataconsole.log(data.part, data.from, data.to);});picker.on('switch:view', (data) => {// data: SwitchViewEventDataconsole.log(data.view); // 'clock' | 'keyboard'});// A name outside TimepickerEventName still compiles; data is unknownpicker.on('my:custom', (data) => console.log(data));
React with TypeScript
import { useEffect, useRef } from 'react';import { TimepickerUI } from 'timepicker-ui';import type { TimepickerOptions } from 'timepicker-ui';interface TimePickerProps {onTimeSelect?: (time: string) => void;theme?: 'basic' | 'dark' | 'cyberpunk';}export function TimePicker({ onTimeSelect, theme = 'basic' }: TimePickerProps) {const inputRef = useRef<HTMLInputElement>(null);useEffect(() => {if (!inputRef.current) return;const options: TimepickerOptions = {ui: { theme },callbacks: {onConfirm: (data) => {if (onTimeSelect && data.hour && data.minutes) {const time = `${data.hour}:${data.minutes}`;onTimeSelect(time);}}}};const picker = new TimepickerUI(inputRef.current, options);picker.create();return () => picker.destroy();}, [theme, onTimeSelect]);return <input ref={inputRef} type="text" placeholder="Select time" />;}
Error Handling
import type { ConfirmEventData, ErrorEventData } from 'timepicker-ui';import { TimepickerUI } from 'timepicker-ui';const picker = new TimepickerUI('#timepicker', {callbacks: {onError: (data: ErrorEventData) => {console.error('Timepicker error:', data.error);alert(`Invalid time format: ${data.error}`);},onConfirm: (data: ConfirmEventData) => {console.log('Time confirmed:', `${data.hour}:${data.minutes}`);}}});
Extending Types
import type { TimepickerOptions, ConfirmEventData } from 'timepicker-ui';import { TimepickerUI } from 'timepicker-ui';// Extend options with custom propertiesinterface CustomTimepickerOptions extends TimepickerOptions {analyticsEnabled?: boolean;}// Create wrapper with custom logicclass CustomTimepicker {private picker: TimepickerUI;private analyticsEnabled: boolean;constructor(input: HTMLInputElement,options: CustomTimepickerOptions) {const { analyticsEnabled, ...pickerOptions } = options;this.analyticsEnabled = analyticsEnabled ?? false;const finalOptions: TimepickerOptions = {...pickerOptions,callbacks: {...pickerOptions.callbacks,onConfirm: (data: ConfirmEventData) => {if (this.analyticsEnabled) {this.trackEvent('time_confirmed', data);}pickerOptions.callbacks?.onConfirm?.(data);}}};this.picker = new TimepickerUI(input, finalOptions);}private trackEvent(event: string, data: ConfirmEventData) {console.log('Analytics:', event, data);}create() {this.picker.create();}destroy() {this.picker.destroy();}}
IntelliSense Support