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.
TouchEvent 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"Material Design 3 Ripple Effect - Interactive ripple animation on buttons and inputs
::before pseudo-elementdata-md3-ripple attributeMaterial Design 3 Color System - Complete M3 color token implementation
--timepicker-primary-container, --timepicker-on-primary-container--timepicker-tertiary-container, --timepicker-on-tertiary-container--timepicker-am-pm-text-selected, --timepicker-am-pm-text-unselectedNew Theme: M2 (Legacy) - Material Design 2 theme with original color scheme
theme: 'm2' optionModular SCSS Architecture - Better maintainability and organization
main.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' importMobile Clock Face Toggle - New interactive mobile view expansion feature
isAnimating flag to prevent animation conflictsDesktop to Mobile View Switching - enableSwitchIcon functionality
.desktop-to-mobile transition class_isMobileView flag for accurate renderingLocal SVG Icon Assets - No external dependencies required
keyboard.svg and schedule.svg to project assetstype: 'asset/source' for inline SVGfs.readFileSync()custom.d.ts for SVG importsDynamic Label and Icon Switching - Context-aware UI updates
timeLabel ↔ mobileTimeLabel based on active vieweditable: true)New ClockSystem Architecture - Complete refactor of clock rendering engine
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 modeTheme naming - Renamed m3 theme to m3-green for clarity
theme: 'm3' to theme: 'm3-green' in your codeOption naming - Renamed switchToMinutesAfterSelectHour to autoSwitchToMinutes for consistency
switchToMinutesAfterSelectHour: true to autoSwitchToMinutes: true in your code24-hour clock layout - Improved spacing for inner ring numbers
AM/PM styling - Enhanced visual feedback with M3 colors
--timepicker-am-pm-text-selected: #633B48)--timepicker-am-pm-text-unselected: #49454F)--timepicker-am-pm-active background colorInput wrapper structure - Better ripple effect support
.timepicker-ui-input-wrapper divposition: relative for ripple positioningTemplate Unification - Merged mobile and desktop templates
getModalTemplate() function with mobileClass conditionaldisplay controls visibility)wrapper-landscape class, unified to mobile-clock-wrapperClock Face Rendering - Improved state synchronization
_isMobileView flag must be set before calling setHoursToClock/setMinutesToClockclockFace, tipsWrapper, clockHand) branch on _isMobileViewsetHoursToClock/setMinutesToClock instead of just transformConfigManager Refactoring - Modular architecture (KISS/DRY principles)
TimeoutManager (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 linesCode Quality Improvements - KISS and DRY optimization
switchToMobileView/switchToDesktopView → switchView(isMobile: boolean)updateIconAndLabel(), toggleViewClasses(), updateReadonlyState()getDisabledTimeForClock() helper methodclassList[isMobile ? 'add' : 'remove']('class')Mobile landscape CSS selectors - Fixed :not() pseudo-class usage
:not(.timepicker-ui-wrapper + .mobile) to :not(.mobile)Clock Face State Bugs - Synchronization and rendering issues
_isMobileView not being synchronized with UI stateAnimation Performance - Removed performance bottlenecks
will-change CSS properties causing resize lag (“przy rezsie strasznie mi się tnie”)Template Rendering - Edge cases and initialization
data-clock-initialized attribute prevents re-initialization_isMobileView properly clearedClockSystem Critical Bugs - Complete fix of clock rendering issues
Math.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 !isInner24h Click Area Overlap: Fixed accidental selection of wrong hours
isInnerCircle threshold from 0.6 to 0.5 for precise detectionClockFace Disappears Before Modal Close: Fixed poor UX during closing
destroyClockSystem() to setTimeout(300ms) after animation24h Wrapper Shows on Minutes: Fixed mobile/desktop toggle bug
tipsWrapperFor24h in switchToHours/switchToMinutesswitchToMinutes() always hides 24h wrapper (minutes don’t need dual circles)switchToHours() shows 24h wrapper only when clockType === '24h'CSS organization - Faster build times with modular SCSS
Modular Code Structure - Better maintainability and testing
Animation Optimization - Smooth 60fps transitions
isAnimating flag prevents concurrent animation conflictsClockSystem Performance Gains - 75-80% improvement in clock operations
destroy() chainacquire(), release(), clear() calls from old pooling systemBetter theming API - More intuitive theme naming
Improved CSS maintainability - Modular SCSS structure
Better Code Organization - Folder structure for large managers
configmanager/ subfolder following EventManager patternimport { TimeoutManager } from './configmanager'TypeScript Best Practices - Type safety improvements
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.New OptionTypes:
inline mode (inline.enabled, containerId, showButtons, autoUpdate)cssClass – allows adding custom class to wrapperai, cyberpunk, glassmorphic, pastel, dark, m3New Callback API:
onConfirm, onCancel, onOpen, onUpdate, onSelectHour, onSelectMinute, onSelectAM, onSelectPM, onErrorNew DOM events (replacing old ones):
timepicker: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