new-js-clock 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +405 -0
- package/dist/index.cjs +684 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +676 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/globalTicker.d.ts +11 -0
- package/dist/internal/globalTicker.d.ts.map +1 -0
- package/dist/internal/globalTicker.js +132 -0
- package/dist/internal/globalTicker.js.map +1 -0
- package/dist/new-js-clock.js +686 -0
- package/dist/new-js-clock.js.map +7 -0
- package/dist/new-js-clock.min.js +10 -0
- package/dist/new-js-clock.min.js.map +7 -0
- package/package.json +90 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/internal/globalTicker.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * New JS Clock - A modern TypeScript clock library\n * Copyright (c) Thiago Cavalcanti Pimenta\n * Licensed under MIT\n */\n\nimport { addClock, removeClock } from './internal/globalTicker.js';\nimport type { TickerClock } from './internal/globalTicker.js';\n\nexport type LapMode = 'splits' | 'laps' | 'both';\n\nexport interface LapRecord {\n lapNumber: number;\n lapTime: string;\n splitTime: string;\n /** High-resolution lap delta in milliseconds (from performance.now()) */\n preciseElapsedMs: number;\n timestamp: number;\n}\n\nexport interface ClockOptions {\n /** Whether to display centiseconds */\n showCenti?: boolean;\n /** Whether to run as countdown timer */\n countdown?: boolean;\n /** Callback function when countdown reaches zero */\n callback?: () => void;\n /** Whether to show hours */\n showHour?: boolean;\n /** Whether to show minutes */\n showMinute?: boolean;\n /** Whether to use 12-hour format with AM/PM */\n use12Hour?: boolean;\n /** Timezone offset in hours from UTC (e.g., -5 for EST, +1 for CET, +5.5 for IST). Does NOT handle DST. */\n timezoneOffset?: number;\n /** IANA timezone name for DST-aware timezone support (e.g., \"America/New_York\", \"Europe/London\") */\n timezone?: string;\n /** Run as stopwatch (counts up from 00:00:00) instead of using system time */\n stopwatch?: boolean;\n /** Enable lap/split mode - records lap times */\n lap?: boolean;\n /** Lap mode type: \"splits\" (total time since start), \"laps\" (time between laps), or \"both\" */\n lapMode?: LapMode;\n /** Custom word to display before lap number (default: \"Lap\" for laps, \"Split\" for splits). Set to \"\" for no word. */\n lapWord?: string;\n /** Use requestAnimationFrame for smoother updates. Falls back to setTimeout when page is hidden. */\n useAnimationFrame?: boolean;\n}\n\nexport interface ClockInstance {\n /** Get the current time string */\n getTime: () => string;\n /** Set a new time for the clock */\n setTime: (timeString: string) => void;\n /** Stop the clock */\n stopClock: () => void;\n /** Start the clock */\n startClock: () => void;\n /** Toggle the clock on/off */\n toggleClock: () => void;\n /** Destroy the clock instance and clean up */\n destroy: () => void;\n /** Check if the clock is currently running */\n isRunning: () => boolean;\n /** Reset the clock to its initial time (useful for countdown timers) */\n reset: () => void;\n /** Record a lap/split and return it (only works in lap mode) */\n lap: () => string;\n /** Get all recorded laps/splits (only works in lap mode) */\n getLaps: () => string[];\n /** Get all split times (only works in lap mode with lapMode: \"splits\" or \"both\") */\n getSplitTimes: () => string[];\n /** Get all lap times (only works in lap mode with lapMode: \"laps\" or \"both\") */\n getLapTimes: () => string[];\n /** Get all lap records with full details (only works in lap mode) */\n getLapRecords: () => LapRecord[];\n /** Clear all recorded laps/splits (only works in lap mode) */\n clearLaps: () => void;\n /** Get the best lap time (only works in lap mode with lapMode: \"laps\" or \"both\") */\n bestLap: () => LapRecord | null;\n /** Get the worst lap time (only works in lap mode with lapMode: \"laps\" or \"both\") */\n worstLap: () => LapRecord | null;\n}\n\ninterface TimeComponents {\n hours: number;\n minutes: number;\n seconds: number;\n centiseconds: number;\n}\n\ninterface InternalClockInstance extends ClockInstance, TickerClock {}\n\n/**\n * Validates a time string in HH:MM:SS or HH:MM:SS:CC format\n */\nfunction validateTimeString(timeString: string): boolean {\n const pattern = /^(([01][0-9])|(2[0-3])):[0-5][0-9]:[0-5][0-9](:[0-9][0-9])?$/;\n return pattern.test(timeString);\n}\n\n/**\n * Validates an IANA timezone name\n */\nfunction isValidTimezone(timezone: string): boolean {\n try {\n Intl.DateTimeFormat(undefined, { timeZone: timezone });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Parses a time string into its components\n */\nfunction parseTimeString(timeString: string): TimeComponents {\n const parts = timeString.split(':');\n return {\n hours: parseInt(parts[0], 10),\n minutes: parseInt(parts[1], 10),\n seconds: parseInt(parts[2], 10),\n centiseconds: parts[3] ? parseInt(parts[3], 10) : 0\n };\n}\n\n/**\n * Adds leading zero to single digit numbers\n */\nfunction padZero(num: number): string {\n return num < 10 ? `0${num}` : num.toString();\n}\n\n/**\n * Converts 24-hour format to 12-hour format\n */\nfunction to12Hour(hours: number): { hours: number; period: string } {\n const period = hours >= 12 ? 'PM' : 'AM';\n const convertedHours = hours % 12 || 12;\n return { hours: convertedHours, period };\n}\n\n/**\n * Formats time components into a display string\n */\nfunction formatTimeString(\n components: TimeComponents,\n showCenti: boolean,\n showHour: boolean,\n showMinute: boolean,\n use12Hour: boolean\n): string {\n const parts: string[] = [];\n let period = '';\n \n if (showHour) {\n let displayHours = components.hours;\n if (use12Hour) {\n const converted = to12Hour(components.hours);\n displayHours = converted.hours;\n period = converted.period;\n }\n parts.push(padZero(displayHours));\n }\n if (showMinute) {\n parts.push(padZero(components.minutes));\n }\n parts.push(padZero(components.seconds));\n \n if (showCenti) {\n parts.push(padZero(components.centiseconds));\n }\n \n let timeString = parts.join(':');\n if (period) {\n timeString += ' ' + period;\n }\n \n return timeString;\n}\n\n/**\n * Runtime guard for validating DOM element inputs from JavaScript consumers\n */\nfunction isHTMLelement(value: unknown): value is HTMLElement {\n return typeof HTMLElement !== 'undefined' && value instanceof HTMLElement;\n}\n\n/**\n * Creates a new clock instance attached to a DOM element\n * \n * @param element - The DOM element to render the clock in\n * @param initialTime - Optional initial time in HH:MM:SS or HH:MM:SS:CC format\n * @param options - Configuration options\n * @returns ClockInstance with control methods\n */\nexport function createClock(\n element: HTMLElement,\n initialTime?: string,\n options: ClockOptions = {}\n): ClockInstance {\n if (!isHTMLelement(element)) {\n throw new TypeError('Invalid element: must be an HTMLElement');\n }\n\n if (options === null || typeof options !== 'object' || Array.isArray(options)) {\n throw new TypeError('Invalid options: must be an object');\n }\n\n // Validate options\n if (options.countdown !== undefined && typeof options.countdown !== 'boolean') {\n throw new TypeError('Invalid countdown option: must be a boolean');\n }\n \n if (options.showCenti !== undefined && typeof options.showCenti !== 'boolean') {\n throw new TypeError('Invalid showCenti option: must be a boolean');\n }\n\n if (options.showHour !== undefined && typeof options.showHour !== 'boolean') {\n throw new TypeError('Invalid showHour option: must be a boolean');\n }\n\n if (options.showMinute !== undefined && typeof options.showMinute !== 'boolean') {\n throw new TypeError('Invalid showMinute option: must be a boolean');\n }\n \n if (options.callback !== undefined && typeof options.callback !== 'function') {\n throw new TypeError('Invalid callback: must be a function');\n }\n\n if (options.use12Hour !== undefined && typeof options.use12Hour !== 'boolean') {\n throw new TypeError('Invalid use12Hour option: must be a boolean');\n }\n\n if (options.timezoneOffset !== undefined && typeof options.timezoneOffset !== 'number') {\n throw new TypeError('Invalid timezoneOffset option: must be a number');\n }\n\n if (\n options.timezoneOffset !== undefined &&\n (!Number.isFinite(options.timezoneOffset) || options.timezoneOffset < -12 || options.timezoneOffset > 14)\n ) {\n throw new RangeError('Invalid timezoneOffset: must be between -12 and +14');\n }\n\n if (options.timezone !== undefined && typeof options.timezone !== 'string') {\n throw new TypeError('Invalid timezone option: must be a string');\n }\n\n if (options.timezone !== undefined && !isValidTimezone(options.timezone)) {\n throw new RangeError(`Invalid timezone: \"${options.timezone}\" is not a valid IANA timezone name`);\n }\n\n if (options.timezone !== undefined && options.timezoneOffset !== undefined) {\n throw new Error('Cannot use both timezone and timezoneOffset options; choose one');\n }\n\n if (options.stopwatch !== undefined && typeof options.stopwatch !== 'boolean') {\n throw new TypeError('Invalid stopwatch option: must be a boolean');\n }\n\n if (options.lap !== undefined && typeof options.lap !== 'boolean') {\n throw new TypeError('Invalid lap option: must be a boolean');\n }\n\n if (options.lapWord !== undefined && typeof options.lapWord !== 'string') {\n throw new TypeError('Invalid lapWord option: must be a string');\n }\n\n if (options.lapMode !== undefined && !['splits', 'laps', 'both'].includes(options.lapMode)) {\n throw new TypeError('Invalid lapMode option: must be \"splits\", \"laps\", or \"both\"');\n }\n\n if (options.useAnimationFrame !== undefined && typeof options.useAnimationFrame !== 'boolean') {\n throw new TypeError('Invalid useAnimationFrame option: must be a boolean');\n }\n\n // Lap mode requires stopwatch mode\n if (options.lap === true && options.stopwatch !== true) {\n throw new Error('Lap mode requires stopwatch mode to be enabled');\n }\n\n // lapMode requires lap to be enabled\n if (options.lapMode !== undefined && options.lap !== true) {\n throw new Error('lapMode requires lap mode to be enabled');\n }\n\n // State\n let time: TimeComponents = { hours: 0, minutes: 0, seconds: 0, centiseconds: 0 };\n let isStopped = false;\n let isDestroyed = false;\n let lapRecords: LapRecord[] = [];\n let lastLapPerfTime: number = performance.now();\n \n // Custom clock anchoring\n let customClockStartTimeMs: number = Date.now();\n let customClockElapsedMs: number = 0;\n let initialTimeMs: number = 0;\n\n // Animation frame state for this specific clock\n let lastTimestamp: number = 0;\n let accumulatedTime: number = 0;\n \n const useAnimationFrame = options.useAnimationFrame ?? false;\n const showCenti = options.showCenti ?? false;\n const showHour = options.showHour ?? true;\n const showMinute = options.showMinute ?? true;\n const isCountdown = options.countdown ?? false;\n const isStopwatch = options.stopwatch ?? false;\n const useLap = options.lap ?? false;\n const lapMode = options.lapMode ?? 'both';\n const lapWord = options.lapWord ?? (lapMode === 'splits' ? 'Split' : 'Lap');\n const callback = options.callback;\n const use12Hour = options.use12Hour ?? false;\n const timezoneOffset = options.timezoneOffset;\n const timezone = options.timezone;\n const isSystemDrivenClock = !isCountdown && !isStopwatch && !initialTime;\n\n // If countdown mode, require initial time\n if (isCountdown && !initialTime) {\n throw new Error('Initial time required for countdown mode');\n }\n\n // Stopwatch mode cannot be combined with timezone options\n if (isStopwatch && (timezone !== undefined || timezoneOffset !== undefined)) {\n throw new Error('Stopwatch mode cannot be combined with timezone options');\n }\n\n // Parse initial time if provided\n if (initialTime) {\n if (!validateTimeString(initialTime)) {\n throw new Error('Invalid time string format: must be HH:MM:SS or HH:MM:SS:CC with leading zeros');\n }\n time = parseTimeString(initialTime);\n initialTimeMs = time.hours * 3600000 + time.minutes * 60000 + time.seconds * 1000 + time.centiseconds * 10;\n } else if (isStopwatch) {\n // Stopwatch starts at 00:00:00 (or 00:00:00:00 if centiseconds)\n time = { hours: 0, minutes: 0, seconds: 0, centiseconds: 0 };\n initialTimeMs = 0;\n }\n\n /**\n * Updates the display with current time\n */\n function updateDisplay(): void {\n const timeString = formatTimeString(time, showCenti, showHour, showMinute, use12Hour);\n if (element.textContent !== timeString) {\n element.textContent = timeString;\n }\n }\n\n /**\n * Gets current time from system clock with optional timezone offset\n */\n function syncWithSystemTime(nowTime?: number): void {\n const now = nowTime ? new Date(nowTime) : new Date();\n \n // Use IANA timezone (DST-aware)\n if (timezone !== undefined) {\n const formatter = new Intl.DateTimeFormat('en-US', {\n timeZone: timezone,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n });\n \n const parts = formatter.formatToParts(now);\n const getPart = (type: string): number => {\n const part = parts.find(p => p.type === type);\n return part ? parseInt(part.value, 10) : 0;\n };\n const normalizedHour = getPart('hour') % 24;\n \n time = {\n hours: normalizedHour,\n minutes: getPart('minute'),\n seconds: getPart('second'),\n centiseconds: showCenti ? Math.floor(now.getMilliseconds() / 10) : 0\n };\n }\n // Apply static timezone offset\n else if (timezoneOffset !== undefined) {\n const offsetMs = timezoneOffset * 60 * 60 * 1000;\n const adjustedTime = new Date(now.getTime() + offsetMs);\n time = {\n hours: adjustedTime.getUTCHours(),\n minutes: adjustedTime.getUTCMinutes(),\n seconds: adjustedTime.getUTCSeconds(),\n centiseconds: showCenti ? Math.floor(adjustedTime.getUTCMilliseconds() / 10) : 0\n };\n }\n // Use local system time\n else {\n time = {\n hours: now.getHours(),\n minutes: now.getMinutes(),\n seconds: now.getSeconds(),\n centiseconds: showCenti ? Math.floor(now.getMilliseconds() / 10) : 0\n };\n }\n }\n\n /**\n * Syncs the custom clock time using the Date.now() anchor\n */\n function syncCustomTimeAnchor(now: number): void {\n const currentElapsedMs = customClockElapsedMs + (now - customClockStartTimeMs);\n const intervalMs = showCenti ? 10 : 1000;\n const elapsedIntervals = Math.floor(currentElapsedMs / intervalMs);\n const effectiveElapsedMs = elapsedIntervals * intervalMs;\n \n if (isCountdown) {\n // Use raw elapsed time for callback precision, even when display is quantized to seconds.\n const remainingRawMs = initialTimeMs - currentElapsedMs;\n if (remainingRawMs <= 0) {\n completeCountdown(true);\n return;\n }\n const currentMs = initialTimeMs - effectiveElapsedMs;\n const totalCs = Math.floor(currentMs / 10);\n time = {\n hours: Math.floor(totalCs / 360000) % 24,\n minutes: Math.floor((totalCs % 360000) / 6000),\n seconds: Math.floor((totalCs % 6000) / 100),\n centiseconds: totalCs % 100\n };\n } else {\n const currentMs = initialTimeMs + effectiveElapsedMs;\n const totalCs = Math.floor(currentMs / 10);\n time = {\n hours: Math.floor(totalCs / 360000) % 24,\n minutes: Math.floor((totalCs % 360000) / 6000),\n seconds: Math.floor((totalCs % 6000) / 100),\n centiseconds: totalCs % 100\n };\n }\n }\n\n function _getTimeoutDelay(now: number): number {\n if (showCenti) {\n return 10;\n }\n\n if (isSystemDrivenClock) {\n return 1000 - (now % 1000);\n }\n\n const elapsedMs = customClockElapsedMs + (now - customClockStartTimeMs);\n const elapsedRemainder = elapsedMs % 1000;\n const msToNextSecond = elapsedRemainder === 0 ? 1000 : 1000 - elapsedRemainder;\n\n if (isCountdown) {\n const remainingMs = initialTimeMs - elapsedMs;\n if (remainingMs <= 0) {\n return 0;\n }\n if (remainingMs < 1000) {\n return remainingMs;\n }\n return Math.min(msToNextSecond, remainingMs);\n }\n\n return msToNextSecond;\n }\n\n function setTimeToZero(): void {\n time = { hours: 0, minutes: 0, seconds: 0, centiseconds: 0 };\n }\n\n function completeCountdown(invokeCallback: boolean): void {\n stopClock();\n customClockElapsedMs = initialTimeMs;\n customClockStartTimeMs = Date.now();\n setTimeToZero();\n if (invokeCallback && callback) {\n callback();\n }\n }\n\n function finalizeZeroCountdown(invokeCallback: boolean): boolean {\n if (!isCountdown || initialTimeMs !== 0) {\n return false;\n }\n\n completeCountdown(invokeCallback);\n updateDisplay();\n return true;\n }\n\n /**\n * Internal tick logic driven by the global ticker\n */\n function _tick(now: number, timestamp?: number): void {\n if (isStopped || isDestroyed) return;\n\n if (isSystemDrivenClock) {\n syncWithSystemTime(now);\n updateDisplay();\n return;\n }\n\n if (useAnimationFrame && timestamp !== undefined) {\n // rAF path - calculate delta time\n if (lastTimestamp === 0) {\n lastTimestamp = timestamp;\n }\n const delta = timestamp - lastTimestamp;\n lastTimestamp = timestamp;\n accumulatedTime += delta;\n\n const tickInterval = showCenti ? 10 : 1000;\n let shouldUpdate = false;\n while (accumulatedTime >= tickInterval) {\n accumulatedTime -= tickInterval;\n shouldUpdate = true;\n }\n\n if (shouldUpdate) {\n syncCustomTimeAnchor(now);\n updateDisplay();\n }\n } else {\n // setTimeout path\n syncCustomTimeAnchor(now);\n updateDisplay();\n }\n }\n\n const internalInstance: InternalClockInstance = {\n getTime,\n setTime,\n stopClock,\n startClock,\n toggleClock,\n destroy,\n isRunning,\n reset,\n lap,\n getLaps,\n getSplitTimes,\n getLapTimes,\n getLapRecords,\n clearLaps,\n bestLap,\n worstLap,\n _tick,\n _requestsAnimationFrame: () => useAnimationFrame,\n _isSystemDriven: () => isSystemDrivenClock,\n _getTimeoutDelay\n };\n\n /**\n * Starts the system clock mode\n */\n function startSystemClock(): void {\n syncWithSystemTime();\n updateDisplay();\n\n addClock(internalInstance);\n }\n\n /**\n * Starts the custom time clock mode\n */\n function startCustomClock(): void {\n customClockStartTimeMs = Date.now();\n updateDisplay();\n\n addClock(internalInstance);\n }\n\n /**\n * Stops the clock\n */\n function stopClock(): void {\n if (!isStopped && !isSystemDrivenClock) {\n customClockElapsedMs += Date.now() - customClockStartTimeMs;\n }\n isStopped = true;\n removeClock(internalInstance);\n }\n\n /**\n * Starts the clock\n */\n function startClock(): void {\n if (isDestroyed || !isStopped) return;\n \n isStopped = false;\n \n if (!isSystemDrivenClock) {\n customClockStartTimeMs = Date.now();\n } else {\n // System clock mode - sync first\n syncWithSystemTime();\n }\n \n updateDisplay();\n \n addClock(internalInstance);\n }\n\n /**\n * Toggles the clock on/off\n */\n function toggleClock(): void {\n if (isStopped) {\n startClock();\n } else {\n stopClock();\n }\n }\n\n /**\n * Gets current time string\n */\n function getTime(): string {\n return formatTimeString(time, showCenti, showHour, showMinute, use12Hour);\n }\n\n /**\n * Checks if clock is running\n */\n function isRunning(): boolean {\n return !isStopped && !isDestroyed;\n }\n\n /**\n * Destroys the clock instance\n */\n function destroy(): void {\n isDestroyed = true;\n stopClock();\n element.textContent = '';\n }\n\n /**\n * Sets a new time for the clock\n */\n function setTime(timeString: string): void {\n if (isDestroyed) return;\n \n if (!validateTimeString(timeString)) {\n throw new Error('Invalid time string format: must be HH:MM:SS or HH:MM:SS:CC with leading zeros');\n }\n \n time = parseTimeString(timeString);\n initialTimeMs = time.hours * 3600000 + time.minutes * 60000 + time.seconds * 1000 + time.centiseconds * 10;\n customClockElapsedMs = 0;\n customClockStartTimeMs = Date.now();\n if (finalizeZeroCountdown(true)) {\n return;\n }\n updateDisplay();\n }\n\n /**\n * Resets the clock to its initial time\n */\n function reset(): void {\n if (isDestroyed) return;\n \n if (isStopwatch) {\n // Stopwatch always resets to 00:00:00\n time = { hours: 0, minutes: 0, seconds: 0, centiseconds: 0 };\n initialTimeMs = 0;\n customClockElapsedMs = 0;\n customClockStartTimeMs = Date.now();\n lapRecords = [];\n lastLapPerfTime = performance.now();\n } else if (initialTime) {\n time = parseTimeString(initialTime);\n initialTimeMs = time.hours * 3600000 + time.minutes * 60000 + time.seconds * 1000 + time.centiseconds * 10;\n customClockElapsedMs = 0;\n customClockStartTimeMs = Date.now();\n } else {\n syncWithSystemTime();\n }\n\n if (finalizeZeroCountdown(true)) {\n return;\n }\n \n isStopped = false;\n updateDisplay();\n \n addClock(internalInstance);\n }\n\n /**\n * Records a lap/split time (only works in lap mode)\n */\n function lap(): string {\n if (isDestroyed) return '';\n assertLapModeEnabled();\n\n const now = performance.now();\n const preciseElapsedMs = now - lastLapPerfTime;\n lastLapPerfTime = now;\n\n const splitTime = formatTimeString(time, showCenti, showHour, showMinute, use12Hour);\n const lapNumber = lapRecords.length + 1;\n\n // Derive lap time components from high-resolution elapsed measurement\n const totalCs = Math.round(preciseElapsedMs / 10);\n const lapDiff: TimeComponents = {\n hours: Math.floor(totalCs / 360000),\n minutes: Math.floor((totalCs % 360000) / 6000),\n seconds: Math.floor((totalCs % 6000) / 100),\n centiseconds: totalCs % 100\n };\n\n const lapTime = formatTimeString(lapDiff, showCenti, showHour, showMinute, use12Hour);\n const timestamp = Date.now();\n\n const record: LapRecord = {\n lapNumber,\n lapTime,\n splitTime,\n preciseElapsedMs,\n timestamp\n };\n\n lapRecords.push(record);\n \n if (lapMode === 'splits') {\n return lapWord ? `${lapWord} ${lapNumber}: ${splitTime}` : `${lapNumber}: ${splitTime}`;\n } else if (lapMode === 'laps') {\n return lapWord ? `${lapWord} ${lapNumber}: ${lapTime}` : `${lapNumber}: ${lapTime}`;\n } else {\n return lapWord ? `${lapWord} ${lapNumber}: ${lapTime} (${splitTime})` : `${lapNumber}: ${lapTime} (${splitTime})`;\n }\n }\n\n /**\n * Gets all recorded lap/split times based on lapMode\n */\n function getLaps(): string[] {\n if (isDestroyed) return [];\n assertLapModeEnabled();\n return lapRecords.map(record => {\n if (lapMode === 'splits') {\n return lapWord ? `${lapWord} ${record.lapNumber}: ${record.splitTime}` : `${record.lapNumber}: ${record.splitTime}`;\n } else if (lapMode === 'laps') {\n return lapWord ? `${lapWord} ${record.lapNumber}: ${record.lapTime}` : `${record.lapNumber}: ${record.lapTime}`;\n } else {\n return lapWord ? `${lapWord} ${record.lapNumber}: ${record.lapTime} (${record.splitTime})` : `${record.lapNumber}: ${record.lapTime} (${record.splitTime})`;\n }\n });\n }\n\n /**\n * Gets all split times\n */\n function getSplitTimes(): string[] {\n if (isDestroyed) return [];\n assertLapModeEnabled();\n if (lapMode === 'laps') {\n throw new Error('Split times are only available when lapMode is \"splits\" or \"both\"');\n }\n return lapRecords.map(record => \n lapWord ? `${lapWord} ${record.lapNumber}: ${record.splitTime}` : `${record.lapNumber}: ${record.splitTime}`\n );\n }\n\n /**\n * Gets all lap times\n */\n function getLapTimes(): string[] {\n if (isDestroyed) return [];\n assertLapModeEnabled();\n if (lapMode === 'splits') {\n throw new Error('Lap times are only available when lapMode is \"laps\" or \"both\"');\n }\n return lapRecords.map(record => \n lapWord ? `${lapWord} ${record.lapNumber}: ${record.lapTime}` : `${record.lapNumber}: ${record.lapTime}`\n );\n }\n\n /**\n * Gets all lap records with full details\n */\n function getLapRecords(): LapRecord[] {\n if (isDestroyed) return [];\n assertLapModeEnabled();\n return [...lapRecords];\n }\n\n /**\n * Gets the best (fastest) lap time\n */\n function bestLap(): LapRecord | null {\n if (isDestroyed) return null;\n assertLapModeEnabled();\n if (lapMode === 'splits') {\n throw new Error('bestLap() is only available when lapMode is \"laps\" or \"both\"');\n }\n if (lapRecords.length === 0) return null;\n return lapRecords.reduce((best, record) =>\n record.preciseElapsedMs < best.preciseElapsedMs ? record : best\n );\n }\n\n /**\n * Gets the worst (slowest) lap time\n */\n function worstLap(): LapRecord | null {\n if (isDestroyed) return null;\n assertLapModeEnabled();\n if (lapMode === 'splits') {\n throw new Error('worstLap() is only available when lapMode is \"laps\" or \"both\"');\n }\n if (lapRecords.length === 0) return null;\n return lapRecords.reduce((worst, record) =>\n record.preciseElapsedMs > worst.preciseElapsedMs ? record : worst\n );\n }\n\n /**\n * Clears all recorded lap/split times\n */\n function clearLaps(): void {\n if (isDestroyed) return;\n assertLapModeEnabled();\n lapRecords = [];\n lastLapPerfTime = performance.now();\n }\n\n function assertLapModeEnabled(): void {\n if (!useLap) {\n throw new Error('Lap mode is not enabled');\n }\n }\n\n // Initialize the clock\n if (finalizeZeroCountdown(true)) {\n // Countdown at zero completes immediately during initialization.\n } else if (isStopwatch) {\n // Stopwatch mode - start at 00:00:00 and count up\n startCustomClock();\n } else if (initialTime) {\n startCustomClock();\n } else {\n startSystemClock();\n }\n\n // Return the public API\n return internalInstance;\n}\n\n// Default export for easier importing\nexport default createClock;\n", "export interface TickerClock {\n _tick: (now: number, timestamp?: number) => void;\n _requestsAnimationFrame: () => boolean;\n _isSystemDriven: () => boolean;\n _getTimeoutDelay: (now: number) => number;\n}\n\nconst activeClocks = new Set<TickerClock>();\nlet globalTimeoutId: number | null = null;\nlet globalAnimationFrameId: number | null = null;\nlet isGlobalPageVisible = true;\n\nfunction getGlobalTimeoutDelay(now: number): number {\n let nextDelay = Infinity;\n\n for (const clock of activeClocks) {\n const delay = clock._getTimeoutDelay(now);\n if (Number.isFinite(delay) && delay >= 0 && delay < nextDelay) {\n nextDelay = delay;\n }\n }\n\n if (!Number.isFinite(nextDelay)) {\n return 1000;\n }\n\n return Math.max(nextDelay, 0);\n}\n\nfunction handleGlobalVisibilityChange(): void {\n isGlobalPageVisible = !document.hidden;\n\n if (!isGlobalPageVisible) {\n if (globalAnimationFrameId !== null) {\n window.cancelAnimationFrame(globalAnimationFrameId);\n globalAnimationFrameId = null;\n }\n // Schedule a setTimeout fallback (hidden tabs may still be clamped by the browser)\n if (globalTimeoutId === null) {\n globalTimeoutId = window.setTimeout(globalTick, getGlobalTimeoutDelay(Date.now()));\n }\n } else {\n // Page became visible\n window.clearTimeout(globalTimeoutId as number);\n globalTimeoutId = null;\n\n // Resync system clocks immediately\n const now = Date.now();\n for (const clock of activeClocks) {\n if (clock._isSystemDriven()) {\n clock._tick(now);\n }\n }\n\n const requestsRaf = Array.from(activeClocks).some(c => c._requestsAnimationFrame());\n if (requestsRaf) {\n window.cancelAnimationFrame(globalAnimationFrameId as number);\n globalAnimationFrameId = window.requestAnimationFrame(globalTick);\n } else {\n globalTimeoutId = window.setTimeout(globalTick, getGlobalTimeoutDelay(now));\n }\n }\n}\n\nexport function ensureVisibilityListener(): void {\n document.addEventListener('visibilitychange', handleGlobalVisibilityChange);\n}\n\nfunction detachVisibilityListener(): void {\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleGlobalVisibilityChange);\n }\n}\n\nfunction stopGlobalTicker(): void {\n if (globalTimeoutId !== null) {\n window.clearTimeout(globalTimeoutId);\n globalTimeoutId = null;\n }\n if (globalAnimationFrameId !== null) {\n window.cancelAnimationFrame(globalAnimationFrameId);\n globalAnimationFrameId = null;\n }\n}\n\nfunction startGlobalTicker(): void {\n const requestsRaf = Array.from(activeClocks).some(c => c._requestsAnimationFrame());\n\n if (requestsRaf && isGlobalPageVisible) {\n if (globalTimeoutId !== null) {\n window.clearTimeout(globalTimeoutId);\n globalTimeoutId = null;\n }\n if (globalAnimationFrameId === null) {\n globalAnimationFrameId = window.requestAnimationFrame(globalTick);\n }\n } else {\n if (globalAnimationFrameId !== null) {\n window.cancelAnimationFrame(globalAnimationFrameId);\n globalAnimationFrameId = null;\n }\n if (globalTimeoutId === null) {\n globalTimeoutId = window.setTimeout(globalTick, getGlobalTimeoutDelay(Date.now()));\n }\n }\n}\n\nfunction globalTick(timestamp?: number): void {\n if (activeClocks.size === 0) {\n stopGlobalTicker();\n return;\n }\n\n const now = Date.now();\n const requestsRaf = Array.from(activeClocks).some(c => c._requestsAnimationFrame());\n\n for (const clock of activeClocks) {\n clock._tick(now, timestamp);\n }\n\n if (requestsRaf && isGlobalPageVisible) {\n globalAnimationFrameId = window.requestAnimationFrame(globalTick);\n } else {\n globalTimeoutId = window.setTimeout(globalTick, getGlobalTimeoutDelay(now));\n }\n}\n\nexport function addClock(clock: TickerClock): void {\n activeClocks.add(clock);\n if (clock._requestsAnimationFrame()) {\n ensureVisibilityListener();\n }\n startGlobalTicker();\n}\n\nexport function removeClock(clock: TickerClock): void {\n activeClocks.delete(clock);\n\n if (activeClocks.size === 0) {\n stopGlobalTicker();\n detachVisibilityListener();\n return;\n }\n\n const hasRafClock = Array.from(activeClocks).some(c => c._requestsAnimationFrame());\n if (!hasRafClock) {\n detachVisibilityListener();\n }\n\n startGlobalTicker();\n}\n\nexport function resetGlobalStateForTesting(): void {\n activeClocks.clear();\n stopGlobalTicker();\n detachVisibilityListener();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New JS Clock - A modern TypeScript clock library
|
|
3
|
+
* Copyright (c) Thiago Cavalcanti Pimenta
|
|
4
|
+
* Licensed under MIT
|
|
5
|
+
*/
|
|
6
|
+
export type LapMode = 'splits' | 'laps' | 'both';
|
|
7
|
+
export interface LapRecord {
|
|
8
|
+
lapNumber: number;
|
|
9
|
+
lapTime: string;
|
|
10
|
+
splitTime: string;
|
|
11
|
+
/** High-resolution lap delta in milliseconds (from performance.now()) */
|
|
12
|
+
preciseElapsedMs: number;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ClockOptions {
|
|
16
|
+
/** Whether to display centiseconds */
|
|
17
|
+
showCenti?: boolean;
|
|
18
|
+
/** Whether to run as countdown timer */
|
|
19
|
+
countdown?: boolean;
|
|
20
|
+
/** Callback function when countdown reaches zero */
|
|
21
|
+
callback?: () => void;
|
|
22
|
+
/** Whether to show hours */
|
|
23
|
+
showHour?: boolean;
|
|
24
|
+
/** Whether to show minutes */
|
|
25
|
+
showMinute?: boolean;
|
|
26
|
+
/** Whether to use 12-hour format with AM/PM */
|
|
27
|
+
use12Hour?: boolean;
|
|
28
|
+
/** Timezone offset in hours from UTC (e.g., -5 for EST, +1 for CET, +5.5 for IST). Does NOT handle DST. */
|
|
29
|
+
timezoneOffset?: number;
|
|
30
|
+
/** IANA timezone name for DST-aware timezone support (e.g., "America/New_York", "Europe/London") */
|
|
31
|
+
timezone?: string;
|
|
32
|
+
/** Run as stopwatch (counts up from 00:00:00) instead of using system time */
|
|
33
|
+
stopwatch?: boolean;
|
|
34
|
+
/** Enable lap/split mode - records lap times */
|
|
35
|
+
lap?: boolean;
|
|
36
|
+
/** Lap mode type: "splits" (total time since start), "laps" (time between laps), or "both" */
|
|
37
|
+
lapMode?: LapMode;
|
|
38
|
+
/** Custom word to display before lap number (default: "Lap" for laps, "Split" for splits). Set to "" for no word. */
|
|
39
|
+
lapWord?: string;
|
|
40
|
+
/** Use requestAnimationFrame for smoother updates. Falls back to setTimeout when page is hidden. */
|
|
41
|
+
useAnimationFrame?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface ClockInstance {
|
|
44
|
+
/** Get the current time string */
|
|
45
|
+
getTime: () => string;
|
|
46
|
+
/** Set a new time for the clock */
|
|
47
|
+
setTime: (timeString: string) => void;
|
|
48
|
+
/** Stop the clock */
|
|
49
|
+
stopClock: () => void;
|
|
50
|
+
/** Start the clock */
|
|
51
|
+
startClock: () => void;
|
|
52
|
+
/** Toggle the clock on/off */
|
|
53
|
+
toggleClock: () => void;
|
|
54
|
+
/** Destroy the clock instance and clean up */
|
|
55
|
+
destroy: () => void;
|
|
56
|
+
/** Check if the clock is currently running */
|
|
57
|
+
isRunning: () => boolean;
|
|
58
|
+
/** Reset the clock to its initial time (useful for countdown timers) */
|
|
59
|
+
reset: () => void;
|
|
60
|
+
/** Record a lap/split and return it (only works in lap mode) */
|
|
61
|
+
lap: () => string;
|
|
62
|
+
/** Get all recorded laps/splits (only works in lap mode) */
|
|
63
|
+
getLaps: () => string[];
|
|
64
|
+
/** Get all split times (only works in lap mode with lapMode: "splits" or "both") */
|
|
65
|
+
getSplitTimes: () => string[];
|
|
66
|
+
/** Get all lap times (only works in lap mode with lapMode: "laps" or "both") */
|
|
67
|
+
getLapTimes: () => string[];
|
|
68
|
+
/** Get all lap records with full details (only works in lap mode) */
|
|
69
|
+
getLapRecords: () => LapRecord[];
|
|
70
|
+
/** Clear all recorded laps/splits (only works in lap mode) */
|
|
71
|
+
clearLaps: () => void;
|
|
72
|
+
/** Get the best lap time (only works in lap mode with lapMode: "laps" or "both") */
|
|
73
|
+
bestLap: () => LapRecord | null;
|
|
74
|
+
/** Get the worst lap time (only works in lap mode with lapMode: "laps" or "both") */
|
|
75
|
+
worstLap: () => LapRecord | null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new clock instance attached to a DOM element
|
|
79
|
+
*
|
|
80
|
+
* @param element - The DOM element to render the clock in
|
|
81
|
+
* @param initialTime - Optional initial time in HH:MM:SS or HH:MM:SS:CC format
|
|
82
|
+
* @param options - Configuration options
|
|
83
|
+
* @returns ClockInstance with control methods
|
|
84
|
+
*/
|
|
85
|
+
export declare function createClock(element: HTMLElement, initialTime?: string, options?: ClockOptions): ClockInstance;
|
|
86
|
+
export default createClock;
|
|
87
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2GAA2G;IAC3G,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gDAAgD;IAChD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,8FAA8F;IAC9F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qHAAqH;IACrH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oGAAoG;IACpG,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,mCAAmC;IACnC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,qBAAqB;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,sBAAsB;IACtB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,wEAAwE;IACxE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,gEAAgE;IAChE,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,MAAM,EAAE,CAAC;IACxB,oFAAoF;IACpF,aAAa,EAAE,MAAM,MAAM,EAAE,CAAC;IAC9B,gFAAgF;IAChF,WAAW,EAAE,MAAM,MAAM,EAAE,CAAC;IAC5B,qEAAqE;IACrE,aAAa,EAAE,MAAM,SAAS,EAAE,CAAC;IACjC,8DAA8D;IAC9D,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,oFAAoF;IACpF,OAAO,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC;IAChC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC;CAClC;AA0GD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,WAAW,EACpB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE,YAAiB,GACzB,aAAa,CAyoBf;AAGD,eAAe,WAAW,CAAC"}
|