All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
ui.inline.embedded renders the inline picker as a role="group" with no aria-modal, shadow or minimum height. It never takes or traps focus. Default falsesetRange({ from, to }), getRange() and setActivePart(part). They need RangePlugin, and setRange emits range:validation. The types TimeOfDay, RangeTimeValue and RangeTimeState are exportedrange.linked: false makes From and To independent: no To-before-From limit, no minDuration / maxDuration check, and the To tab is enabled at once. Default trueclock.isTimeDisabled(time) disables times with a function (hour 0-23), combined with clock.disabledTime. A function that throws counts as enabled, and its error is rethrownrefreshDisabledTime() re-applies disabled times after the data behind isTimeDisabled changes, without re-renderingon() and once() return a function that removes the handlerThese changes can affect an existing setup. Each one is described under Changed.
.tp-ui-ripple / .tp-ui-ripple-effect classes and the ripple keyframes are removed--tp-wheel-highlight-radius, --tp-popover-radius and --tp-btn-radius are no longer defined on :root--tp-focus-ring-halo is no longer read, and --tp-shadow-focus-ring defaults to noneAM / PM, whatever labels.am / labels.pm are set toclock.disabledTime.interval edges such as 25:00 are now rejected and reported through error / callbacks.onErrorsetValue() with a string that is not a time now emits error / callbacks.onError instead of being ignored<html>, and <body> only when it scrolls. CSS that relied on the padding-right added to body should use --tp-scrollbar-gaptp-ui-popover-anchored and no inline top, left or width. Review CSS that positions .tp-ui-popover by handui.inline.showButtons: true, inline OK and Cancel no longer remove the picker from its containerbehavior.delayHandler defaults to 0 instead of 300, so the picker closes without a pauselabels.*, range.fromLabel / range.toLabel and timezone.label is now HTML-escaped, so it cannot inject markup. The icon options ui.keyboardIcon and ui.clockIcon (ui.iconTemplate / ui.iconTemplateMobile) still accept HTMLclock.showSeconds: true adds a seconds field, face and wheel column, and values become HH:MM:SS (HH:MM:SS AM in 12h). Off by default, with no change when offclock.incrementSeconds (1, 5, 10, 15, 20 or 30, default 1) sets the seconds step, and clock.autoSwitchToSeconds (default true) moves to the seconds face after a minute is pickedclock.disabledTime.seconds disables the listed seconds in every minute, and clock.disabledTime.interval edges can include seconds. Edges without seconds cover the whole minute, so existing intervals still worklabels.second (default "Second") names the seconds field, its caption in the keyboard view, its wheel column and its announcementselect:second event and callbacks.onSelectSecond, with the SelectSecondEventData typegetValue() and the open, confirm and update payloads include seconds, the error payload includes inputSecond, and setValue() accepts '14:30:15'. Values without seconds read as :00range:confirm and range:validation include durationSeconds. duration stays in whole minutes, and range.minDuration / range.maxDuration are compared with the exact lengthtp-ui-has-seconds class when seconds are shown, and new CSS tokens such as --tp-wheel-column-width-seconds size the seconds layoutui.initialView: 'keyboard' for ui.mobile: true and ui.viewSwitch for ui.enableSwitchIcon. The old names work until 5.0, and the options page lists every pairsetOptions(), the select:period and switch:face events with callbacks.onSelectPeriod and callbacks.onSwitchFace, and clock.type: 'auto', which picks 12h or 24h from the browser localeui.appendTo (where the modal goes) and ui.inline.container (where the inline picker renders) accept an element as well as a CSS selector--tp-mobile-landscape-width, --tp-mobile-landscape-height, --tp-mobile-landscape-height-range and --tp-mobile-landscape-height-timezone set the mobile keyboard view size in landscape--tp-focus-ring sets the focus ring color, falling back to --tp-primarylabels.announceCleared (default "Time cleared") sets the text announced after Clearui.inline.autoUpdate now works: an inline picker updates its input as you pickcallbacks.onShow, callbacks.onSwitchView, callbacks.onWheelScrollStart and callbacks.onWheelScrollEnd, so every public event now has a matching callback--tp-state-hover-opacity, --tp-state-focus-opacity, --tp-state-pressed-opacity and --tp-ripple-opacity. With prefers-reduced-motion, a press shows the pressed layer without the ripple--tp-dropdown-option-hover-text sets the text color of a hovered or focused timezone option--tp-scrollbar-gap on <html> holds the removed scrollbar width while a picker locks the page. Use it to pad fixed or sticky elements--tp-popover-edge-margin (default 4px) sets the smallest gap between the compact-wheel popover and the viewport’s side edgesAM or PM. labels.am / labels.pm only change the shown and announced text, not the input value or getValue().typeupdate({ options }) now applies every option group, including range, timezone, wheel and clearBehavior, and inline pickers re-render with new labelsui.inline.showButtons: true) keep the picker visible. OK writes the value to the input and emits confirm. Cancel restores the input’s value and emits cancel. close() still removes itclock.disabledTime.interval rejects out-of-range edges such as 13:00 PM and reports them through error / callbacks.onError. On create() the picker does not open, and update() keeps the old options. Lowercase am / pm are acceptedsetValue() converts a time in the other clock format ('14:30' becomes 02:30 PM in 12h). A string that is not a time emits error / callbacks.onError. An empty string is still ignoredclock.disabledTime.hours / minutes apply toopastel, ai, m2, m3-green, crane and crane-straight, and dark accents follow --tp-primary--tp-focus-ring-halo is no longer read and --tp-shadow-focus-ring defaults to nonebox-sizing: border-box on its own elements, so it no longer depends on a page-wide reset--tp-wheel-highlight-radius, --tp-popover-radius and --tp-btn-radius are no longer defined on :root, so theme values reach them. Setting them still works, but reading them with var() outside the picker gets no value.tp-ui-ripple, .tp-ui-ripple-effect and the ripple keyframes are removed. Move custom CSS to the new state and ripple tokenswheel.placement) uses the Popover API and CSS anchor positioning, so a parent’s overflow: hidden or z-index no longer clips or covers it. Browsers without anchor positioning use a script fallback--tp-popover-gap, --tp-popover-min-width and --tp-popover-max-width now take effect. New popover styling hooks: the tp-ui-popover-anchored and tp-ui-popover-constrained classes and the data-popover-request attributeui.enableScrollbar: false, the default) now sets overflow-y: hidden on <html>, and on <body> only when it scrolls. Only the element that lost its scrollbar gets padding-right'Spacebar' key value no longer counts as Space. Only very old browsers, such as old Edge and Internet Explorer, send itprefers-reduced-motion or ui.animation: false, the picker opens and closes at once, with no waitbehavior.delayHandler now defaults to 0 instead of 300. Set it to 300 to keep the old pause before closingui.animation: false and prefers-reduced-motion now also stop the clock hand from animating when the face switchesEach item below still works unless its entry says otherwise. All of them are removed in 5.0.
ui.mobile or labels.hourLabel: use the new names listed on the options page. select:am / select:pm: use select:period. update(): use setOptions()OptionTypes type: use TimepickerOptionsclock.currentTime.locales: has no effect, the library formats the valuegetValue().degreesHours / getValue().degreesMinutes: internal clock-hand angles. Use hour / minuteslabels.toggleLabel: has no effect now that the view switch is one button. Use labels.switchToKeyboard / labels.switchToClocklabels.format24Label and labels.timezoneSelectorLabel: they never had an effect. The timezone selector label comes from labels.timezonefocusInputAfterCloseModal in the legacy option type: use behavior.returnFocushide event and the HideEventData type: never emittedrange:get-disabled-time and range:update-disabled events: never emittedErrorEventData.rejectedHour and ErrorEventData.rejectedMinute: always undefinedcallbacks.onClear fires once per clear instead of twiceclose(true) commits the current selection to the input, like the OK buttonconfirm / cancel twicegetValue() returns the input value and destroy() cancels the pending closeshow / callbacks.onShow without opening the pickerwheel.commitOnScroll: Cancel right after a scroll no longer fires confirm / callbacks.onConfirm after cancelupdate({ options: { callbacks } }) take effect, replaced callbacks stop firing, and inline pickers no longer fire onOpen again after update()clock.type or clock.showSeconds through update() rewrites the input in the new format, range values (from - to) included, so getValue() reads it correctlyupdate() on an open modal or popover re-renders it with the new options right away. An unconfirmed selection resets to the input valueshow / callbacks.onShow now fire before open / callbacks.onOpen. picker.open() still emits only openlabels.invalidTimeFormat) inside the dialog, and the input gets aria-invalid and aria-describedbyclock.disabledTime, including an interval without -, is reported through error / callbacks.onError instead of silently breaking the pickerdata-open value no longer break the pickernew TimepickerUI() makes the wrapper the picker root, so data-open buttons inside it open the pickersetValue() accepts zero-padded 12h hours such as '03:45 PM' and 12h values longer than 8 characters. While the clock is open, it updates the whole face, not only the handgetValue().degreesHours / degreesMinutes and the open payload degrees now follow clicks and drags on the clockclock.currentTime: true keeps the AM/PM part in 12h localesclock.smoothHourSnap: on release, the hand animates to the hour instead of jumping. With reduced motion it moves without animationupdate events afterwardsclock.incrementMinutes. Arrow keys and typed values on the time fields skip disabled times, and OK stays disabled while the shown time is disabledclock.incrementHours now works with the default clock.smoothHourSnap: true, in wheel and compact-wheel modes, and with the hour field’s arrow keys, PageUp / PageDown and Home / Endui.iconTemplateMobile goes inside the view-switch button, like ui.iconTemplate, instead of replacing it on the first mobile renderlabels.announceHour / labels.announceMinutearia-valuenow / aria-valuetext and the AM/PM aria-pressed now stay in sync with the shown time--:-- placeholder aloud, also after Clearlabels.mobileHour / mobileMinute in the keyboard view, labels.hourLabel / minuteLabel in the clock viewprefers-contrast: more. They used prefers-contrast: high, which browsers never matchGrayText--tp-font-family now sets the picker font as documented, and the time fields and buttons inherit it: separator is visible in the basic and m2 themesaria-disabled="true", and zero-padded clock.disabledTime.minutes strings such as '05' work10:07 with clock.incrementMinutes: 5, now lands on the nearest item instead of a wrong onecrane-straight: the wheel selection highlight and the popover are square again, and the m2 popover uses its 4px radiuslabels.am / labels.pm and opens on the input’s period, and interval-disabled minutes follow the selected hour and periodgetValue() while the picker is open returns the wheel selectionclearBehavior.clearInput: falsewheel.placement: 'top' or 'bottom', the popover switches sides when fewer than three wheel rows fit, instead of covering the inputdir="rtl" set only on a container, the popover lines up with the input’s right edge, with or without CSS anchor positioning--tp-popover-* gap, margin and width tokens now work in rem, em or calc(), not only pxwheel.placement has no default (the JSDoc said 'auto'). Without it, compact-wheel opens as a modal, as beforerange.minDuration / range.maxDuration, also when picked with the pointertimezone.default missing from the list falls back to the browser’s zone if listed, otherwise the first option, instead of an empty labeltimezone.label instead of the English “Timezone…” or undefined...crane / crane-straight and the pastel footer buttons are now readablepadding-right, and pages that scroll on <html> are locked tooui.inline.showButtons: falseupdate() sets ui.mobile: false, the desktop time fields are no longer left editable5.0 will change how plugins are built and registered, and will rename the part of each CSS class after the tp-ui- prefix to follow Material Design component naming. It also removes the items deprecated above and other unused API, and ships with a migration guide. See the roadmap for details.
In 5.0, behavior.returnFocus defaults to true: on close, focus goes back to the input, or to the data-open element that opened the picker. Set behavior.returnFocus: true now to return focus to the input.
blueprint (light precision-instrument look: cobalt-blue accent, white surfaces, hairline borders) and blueprint-dark (cobalt accent on near-black neutrals). Enable via ui.theme: 'blueprint' / 'blueprint-dark' and import the matching timepicker-ui/theme-blueprint.css / timepicker-ui/theme-blueprint-dark.css stylesheet. Brings the bundled theme count from 10 to 12, each still tree-shakeable as a separate CSS filelabels.* options for fully localizable screen-reader and ARIA text: hourLabel, minuteLabel, clockLabel, periodLabel, timeLabel, format24Label, rangeSelectionLabel, switchToKeyboardLabel, switchToClockLabel, toggleLabel, timezoneSelectorLabel, announceHour, announceMinute, announceAmSelected, announcePmSelected, and invalidTimeFormat. All optional, with English defaults - previously these strings were hardcodedlabels group instead of hardcoded English, so all assistive-technology text can be localizedaria-valuetext and keep it in sync on every change for more accurate screen-reader outputaria-disabled / aria-hidden, so keyboard tabbing only lands on genuinely actionable controls-moz-appearance: textfield + -webkit-appearance reset). Thanks to @in-omnibus for reporting and proposing the fix (#166)theme-crane-straight.css entry in the package exports map - the documented import 'timepicker-ui/theme-crane-straight.css' subpath now resolves instead of throwing ERR_PACKAGE_PATH_NOT_EXPORTEDtemplateProvider hook allowing plugins to register their own modal templates without core static importsclearHandler hook allowing plugins to register custom clear logic executed when the clear button is pressedTemplateProvider and ClearHandler types from the public APIgetTemplateProvider() and getClearHandler() methods on PluginRegistrysideEffects field corrected to exclude plugin files, enabling bundlers to eliminate unused plugin codeWheelOptions was not exported from the public API - wheel mode configuration type is now accessible for TypeScript consumersrange.d.ts, timezone.d.ts, wheel.d.ts) used never for factory parameters, causing PluginRegistry.register() to reject plugins in strict TypeScript projectsui.mode: 'wheel'ui.mode: 'compact-wheel'select:hour, select:minute, update, confirm, cancel, clear, select:am, select:pm, error) - no separate API neededwheel:scroll:start event - fires when a wheel column starts scrolling (includes column field)wheel:scroll:end event - fires when a wheel column snaps to a value (includes column, value, previousValue fields)WheelScrollStartEventData and WheelScrollEndEventData typeswheel.placement option ('auto' |
'top' |
'bottom') for popover positioning in compact-wheel mode |
wheel.hideDisabled option to completely remove disabled hours/minutes from the wheel list instead of dimming them (wheel and compact-wheel modes only)wheel.commitOnScroll option to auto-commit time at the end of wheel scrolling without pressing OKwheel.ignoreOutsideClick option to prevent the picker from closing when clicking outside its area (wheel and compact-wheel modes only)autoCommit field on ConfirmEventData to distinguish auto-committed from manual confirmationsui.clearButton optionclearBehavior.clearInput option to control whether clearing also empties the input field valuelabels.clear option to customize the clear button textonClear callback and clear event with previousValue payloadClearEventData and ClearBehaviorOptions typesWheelOptions is now a top-level key (wheel) instead of being nested inside ui.wheelvar(--tp-border) variablewindow.innerHeight to document.documentElement.clientHeight for accurate visible viewport measurement, and improved fallback to prefer the side with more available spacePluginFactory type now correctly accepts CoreState and EventEmitter parameters instead of using any or never workarounds. Removed internal PluginInput interface and unsafe type assertions from the plugin registryRange Plugin - New! Select time ranges with start/end pickers, duration calculation, min/max validation, and automatic time blocking when “from” is selected
import { PluginRegistry } from "timepicker-ui";
import { RangePlugin } from "timepicker-ui/plugins/range";
PluginRegistry.register(RangePlugin);
const picker = new TimepickerUI(input, {
range: { enabled: true, minDuration: 30, maxDuration: 480 },
});
Timezone Plugin - New! Timezone selector with searchable dropdown, UTC offset display, and CSS variable theming
import { PluginRegistry } from "timepicker-ui";
import { TimezonePlugin } from "timepicker-ui/plugins/timezone";
PluginRegistry.register(TimezonePlugin);
const picker = new TimepickerUI(input, {
timezone: { enabled: true, default: "America/New_York" },
});
smoothHourSnap option (default: true) enables fluid hour dragging with animation. Clock hand moves continuously between hours and snaps to nearest hour on releasesmoothHourSnap defaults to true for better UX. Set to false for legacy discrete jump behaviorenableSwitchIcon toggle not updating label text, icon, and Hour/Minute labels. Now correctly switches between “Select time” ↔ “Enter time”, keyboard ↔ schedule icons, and shows/hides Hour/Minute labels when toggling viewsTouchEvent is not defined error in DragHandlers. Changed from instanceof TouchEvent to 'touches' in event check for cross-browser compatibilityTimepickerOptions, ClockOptions, UIOptions, LabelsOptions, BehaviorOptions, CallbacksOptions to support type-safe option compositiononUpdate event emissions in EventManager and ClockManager for real-time value synchronizationCallbacksOptions now have proper generic types instead of unknownonConfirm, onOpen, onUpdate, and other callbacks now correctly infer event data typesBefore (4.0.0):
// Callbacks had unknown types
onConfirm?: TimepickerEventCallback; // eventData: unknown
After (4.0.1):
// Callbacks are now properly typed
onConfirm?: TimepickerEventCallback<ConfirmEventData>; // eventData: { hour?: string, minutes?: string, type?: string }
Impact: Developers now get full type safety and IntelliSense for callback parameters without needing manual type assertions.
All CSS classes have been renamed from timepicker-ui-* to tp-ui-* for shorter, cleaner class names.
Migration:
/* v3 */
.timepicker-ui-wrapper {
}
.timepicker-ui-modal {
}
.timepicker-ui-clock-face {
}
.timepicker-ui-hour {
}
.timepicker-ui-minutes {
}
/* v4 */
.tp-ui-wrapper {
}
.tp-ui-modal {
}
.tp-ui-clock-face {
}
.tp-ui-hour {
}
.tp-ui-minutes {
}
Impact: If you have custom CSS targeting timepicker classes, you must update all class names.
All options are now organized into logical groups (clock, ui, labels, behavior, callbacks) for better maintainability and clarity.
Migration:
// v3
new TimepickerUI(input, {
clockType: "12h",
theme: "dark",
enableSwitchIcon: true,
onConfirm: (data) => console.log(data),
});
// v4
new TimepickerUI(input, {
clock: { type: "12h" },
ui: { theme: "dark", enableSwitchIcon: true },
callbacks: { onConfirm: (data) => console.log(data) },
});
Custom DOM events (timepicker:confirm, timepicker:open, etc.) have been completely removed. Use EventEmitter API or callback options instead.
Migration:
// v3 - Removed
input.addEventListener("timepicker:confirm", (e) => console.log(e.detail));
// v4 - EventEmitter API
picker.on("confirm", (data) => console.log(data));
// v4 - Or callback options
new TimepickerUI(input, {
callbacks: { onConfirm: (data) => console.log(data) },
});
Programmatic theme customization via setTheme() has been removed. Use CSS classes with CSS variable overrides instead.
Migration:
// v3 - Removed
picker.setTheme({ primaryColor: "#ff0000" });
// v4 - Use CSS classes
new TimepickerUI(input, { ui: { cssClass: "my-theme" } });
/* Define theme in CSS */
.tp-ui-wrapper.my-theme {
--tp-primary: #ff0000;
--tp-bg: #000000;
}
onOpen, onCancel, onConfirm, onUpdate, onSelectHour, onSelectMinute, onSelectAM, onSelectPM, onError) automatically bridge to EventEmitteron(), off(), once() methodstypeof window !== "undefined"extends, no class hierarchies, fully testableautoSwitchToMinutes
autoSwitchToMinutes enabled, minute input receives focus automaticallyany types in codebase (strict TypeScript)ClockOptions, UIOptions, LabelsOptions, BehaviorOptions, CallbacksOptionsextends usagecore: CoreState and emitter: EventEmittertheme-custom from production (users create custom themes via CSS variables)basic, crane, crane-straight, m3-green, m2, dark, glassmorphic, pastel, ai, cyberpunksetupCallbackBridge()clock, ui, labels, behavior, callbackstimepicker:* custom events no longer dispatched
timepicker:open, timepicker:cancel, timepicker:confirm, timepicker:updatetimepicker:select-hour, timepicker:select-minute, timepicker:select-am, timepicker:select-pm, timepicker:errorpicker.on() EventEmitter API or callback optionspicker.setTheme({ primaryColor, backgroundColor, ... })applyThemeToWrapper() private methodpendingThemeConfig state propertyautoSwitchToMinutes now properly focuses minute input
autoSwitchToMinutes: true, minute input receives focusminutesElement?.focus() after minutesElement?.click()typeof window !== "undefined"::before pseudo-elementdata-md3-ripple attribute--timepicker-primary-container, --timepicker-on-primary-container--timepicker-tertiary-container, --timepicker-on-tertiary-container--timepicker-am-pm-text-selected, --timepicker-am-pm-text-unselectedtheme: 'm2' optionmain.scss into 14 focused partial files_modal, _wrapper, _header, _body, _footer, _clock, _time-inputs, _am-pm, _buttons, _keyboard-icon, _utilities, _animations, _inline, _accessibility, _ripple@use '../variables.scss' importisAnimating flag to prevent animation conflictsenableSwitchIcon functionality
.desktop-to-mobile transition class_isMobileView flag for accurate renderingkeyboard.svg and schedule.svg to project assetstype: 'asset/source' for inline SVGfs.readFileSync()custom.d.ts for SVG importstimeLabel ↔ mobileTimeLabel based on active vieweditable: true)AngleEngine - Angle calculations with proper atan2() usageHourEngine - Hour value conversions with 12h/24h logicMinuteEngine - Minute value conversions with interval supportClockEngine - Coordinator for pointer input processingClockRenderer - DOM element creation, positioning, and state updatesClockController - Manages hour/minute/AM-PM stateonHourChange, onMinuteChange) for loose couplingDragHandlers - Cross-platform mouse/touch event handlingClockSystem
switchToHours(), switchToMinutes(), setHour(), setMinute(), setAmPm()tipsWrapper (outer) + tipsWrapperFor24h (inner) for 24h modem3 theme to m3-green for clarity
theme: 'm3' to theme: 'm3-green' in your codeswitchToMinutesAfterSelectHour to autoSwitchToMinutes for consistency
switchToMinutesAfterSelectHour: true to autoSwitchToMinutes: true in your code--timepicker-am-pm-text-selected: #633B48)--timepicker-am-pm-text-unselected: #49454F)--timepicker-am-pm-active background color.timepicker-ui-input-wrapper divposition: relative for ripple positioninggetModalTemplate() function with mobileClass conditionaldisplay controls visibility)wrapper-landscape class, unified to mobile-clock-wrapper_isMobileView flag must be set before calling setHoursToClock/setMinutesToClockclockFace, tipsWrapper, clockHand) branch on _isMobileViewsetHoursToClock/setMinutesToClock instead of just transformTimeoutManager (22 lines) - Timeout and RAF managementViewSwitcher (58 lines) - Mobile ↔ desktop view switching logicMobileClockFaceToggler (243 lines) - Clock face expand/collapse logicInitializationManager (106 lines) - Timepicker initializationConfigManager.ts reduced from 433 to 56 linesswitchToMobileView/switchToDesktopView → switchView(isMobile: boolean)updateIconAndLabel(), toggleViewClasses(), updateReadonlyState()getDisabledTimeForClock() helper methodclassList[isMobile ? 'add' : 'remove']('class'):not() pseudo-class usage
:not(.timepicker-ui-wrapper + .mobile) to :not(.mobile)_isMobileView not being synchronized with UI statewill-change CSS properties causing resize lag (“przy rezsie strasznie mi się tnie”)data-clock-initialized attribute prevents re-initialization_isMobileView properly clearedMath.atan2() parameter order
atan2(deltaX, deltaY) to atan2(deltaY, deltaX) + 90°targetWrapper.offsetWidth not clockFacehourValue === 0 || hourValue >= 13 (00, 13-23)baseIndex === 0 ? 12 : baseIndex (12, 1-11)true when time IS in interval (disabled)false when time NOT in interval (enabled)setAmPm() triggers renderTips() + setHandAngle() + setActiveValue()setCircleSize(true) for all hours, not !isInnerisInnerCircle threshold from 0.6 to 0.5 for precise detectiondestroyClockSystem() to setTimeout(300ms) after animationtipsWrapperFor24h in switchToHours/switchToMinutesswitchToMinutes() always hides 24h wrapper (minutes don’t need dual circles)switchToHours() shows 24h wrapper only when clockType === '24h'isAnimating flag prevents concurrent animation conflictsdestroy() chainacquire(), release(), clear() calls from old pooling systemconfigmanager/ subfolder following EventManager patternimport { TimeoutManager } from './configmanager'Breaking Change:
// Old (v3.1.x and earlier)
const picker = new TimepickerUI(input, {
theme: "m3",
});
// New (v3.2.0+)
const picker = new TimepickerUI(input, {
theme: "m3-green", // Renamed for clarity
});
New Features (Optional):
// Mobile clock face toggle (automatic on mobile view)
// Click keyboard icon to expand/collapse clock face
// Desktop to mobile switching
const picker = new TimepickerUI(input, {
enableSwitchIcon: true, // Shows toggle icon
});
// Custom icons (optional, defaults to built-in SVGs)
const picker = new TimepickerUI(input, {
iconTemplate: "<svg>...</svg>", // Desktop icon
iconTemplateMobile: "<svg>...</svg>", // Mobile icon
});
// Custom labels (optional)
const picker = new TimepickerUI(input, {
timeLabel: "Select time", // Desktop label
mobileTimeLabel: "Enter Time", // Mobile label
});
Bundler Configuration:
type: 'asset/source' (inline)fs.readFileSync()var(--timepicker-text);on(), once(), and off() methods
picker.on('confirm', callback)picker.once('open', callback)picker.off('confirm', callback)confirm, cancel, open, update, select:hour, select:minute, select:am, select:pm, errortimepicker:*) are now considered legacy and will be removed in v4.0.0timepicker:confirm, timepicker:cancel) - Use EventEmitter API insteadundefined checks for optional managers (clockManager, animationManager, configManager)_disabledTime interface - added missing minutes propertyopenElement iteration// Old way (deprecated, will be removed in v4)
input.addEventListener("timepicker:confirm", (e) => {
console.log(e.detail);
});
// New way (recommended)
picker.on("confirm", (data) => {
console.log(data);
});
destroy() method was incorrectly called during the transition, unintentionally removing the instance.OptionTypes:
inline mode (inline.enabled, containerId, showButtons, autoUpdate)cssClass – allows adding custom class to wrapperai, cyberpunk, glassmorphic, pastel, dark, m3onConfirm, onCancel, onOpen, onUpdate, onSelectHour, onSelectMinute, onSelectAM, onSelectPM, onErrortimepicker:open, timepicker:confirm, timepicker:cancel, timepicker:update, timepicker:error, timepicker:select-hour, etc.OptionTypes, TimepickerUI, event payloads.create(), .open(), .close(), .update(), .destroy(), .getValue(), .setValue()confirm, cancel) have been replaced with namespaced events (timepicker:*)destroy() no longer removes original input element (breaking change fix)confirm, cancel, update, etc.)theme optiontheme called m3.
Theme m3 based on the new Material Design v3. Material Design 3 is still not release in offical version for WEB but you can use it if you want.
There is new version of Material Design 3.
If new version M3 will be released this design will get improve.close() method. These method has to invoke with double parentheses close()(). The first parentheses doesn’t have any parameters, the second has the same what had in the previous method.delayHandler prop to avoid delay on buttonshour and minutes. Previous version used divs as buttons, the current version is using inputs instead divs.preventDefault option, to use editable option is enough to set this option to truedebounce function to close/open timepickeredtiable options durning change hour/minutes on desktop/mobiledisable TimefocusTrap with React about eval errorminutes option in currentTimefocusTrap to turn off/on focus traping on picker. The default value is set to truecurrentTime about displaying wrong hour in the pickereditable option when switch during desktop/mobile optionsOptionTypes to allows to import types from packagecurrentTime optiondisabledTime that allows to set to timepicker disabled timeselectLabelTime to labelTimemobileTimeLabel to change time label on mobile versionanimated to turn on/off animations on picker on start/close.editable to edit hour/minutes on the web mode.preventDefault to turn on/off defaults events to clock face events.inputTemplate from options types.type in the events