@toankhontech/arctimer-core 0.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/dist/index.cjs +801 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +252 -0
- package/dist/index.d.ts +252 -0
- package/dist/index.js +773 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/engine/timerMachine.ts","../src/engine/rafLoop.ts","../src/engine/colorInterpolation.ts","../src/svg/pathCalculation.ts","../src/animation/spring.ts","../src/animation/easings.ts","../src/animation/effects.ts","../src/useCountdown.ts","../src/useTimerGroup.ts","../src/accessibility/ariaLabels.ts","../src/accessibility/announcer.ts","../src/accessibility/reducedMotion.ts"],"names":["useReducer","useState","useRef","useMemo","useCallback","useEffect","createContext","useContext"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { TimerState, TimerEvent, TimerStatus } from '../types'\n\nexport function createInitialState(\n duration: number,\n initialRemainingTime?: number\n): TimerState {\n const elapsed =\n initialRemainingTime !== undefined\n ? duration - initialRemainingTime\n : 0\n\n return {\n status: 'idle',\n duration,\n elapsed: Math.max(0, Math.min(elapsed, duration)),\n startedAt: null,\n pausedAt: null,\n }\n}\n\nexport function timerReducer(\n state: TimerState,\n event: TimerEvent\n): TimerState {\n switch (event.type) {\n case 'PLAY': {\n if (state.status === 'playing') return state\n\n const now = performance.now()\n\n if (state.status === 'completed') {\n return {\n ...state,\n status: 'playing',\n elapsed: 0,\n startedAt: now,\n pausedAt: null,\n }\n }\n\n return {\n ...state,\n status: 'playing',\n startedAt: now - state.elapsed * 1000,\n pausedAt: null,\n }\n }\n\n case 'PAUSE': {\n if (state.status !== 'playing') return state\n\n return {\n ...state,\n status: 'paused',\n pausedAt: performance.now(),\n }\n }\n\n case 'COMPLETE': {\n if (state.status !== 'playing') return state\n\n return {\n ...state,\n status: 'completed',\n elapsed: state.duration,\n startedAt: null,\n pausedAt: null,\n }\n }\n\n case 'RESET': {\n const newDuration = event.duration ?? state.duration\n return createInitialState(newDuration)\n }\n\n default:\n return state\n }\n}\n\nexport function getStatusFromState(state: TimerState): TimerStatus {\n return state.status\n}\n","type TickCallback = (timestamp: number) => void\n\nconst subscribers = new Map<string, TickCallback>()\nlet rafId: number | null = null\nlet isRunning = false\n\nfunction tick(timestamp: number): void {\n subscribers.forEach((cb) => {\n try {\n cb(timestamp)\n } catch (_e) {\n // Prevent one subscriber from breaking others\n }\n })\n\n if (subscribers.size > 0) {\n rafId = requestAnimationFrame(tick)\n } else {\n isRunning = false\n rafId = null\n }\n}\n\nfunction startLoop(): void {\n if (isRunning) return\n isRunning = true\n rafId = requestAnimationFrame(tick)\n}\n\nfunction stopLoop(): void {\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n rafId = null\n }\n isRunning = false\n}\n\nexport function subscribe(id: string, callback: TickCallback): () => void {\n subscribers.set(id, callback)\n\n if (subscribers.size === 1) {\n startLoop()\n }\n\n return () => {\n subscribers.delete(id)\n if (subscribers.size === 0) {\n stopLoop()\n }\n }\n}\n\nexport function getSubscriberCount(): number {\n return subscribers.size\n}\n\nexport function isLoopRunning(): boolean {\n return isRunning\n}\n\nexport function _resetForTesting(): void {\n subscribers.clear()\n stopLoop()\n}\n","import type { ColorFormat } from '../types'\n\nexport function hexToRgb(hex: string): [number, number, number] {\n const cleaned = hex.replace('#', '')\n const fullHex =\n cleaned.length === 3\n ? cleaned\n .split('')\n .map((c) => c + c)\n .join('')\n : cleaned\n\n const num = parseInt(fullHex, 16)\n return [(num >> 16) & 255, (num >> 8) & 255, num & 255]\n}\n\nexport function rgbToHex(r: number, g: number, b: number): string {\n const toHex = (n: number) =>\n Math.round(Math.max(0, Math.min(255, n)))\n .toString(16)\n .padStart(2, '0')\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`\n}\n\nexport function interpolateColor(\n color1: string,\n color2: string,\n factor: number\n): string {\n const clampedFactor = Math.max(0, Math.min(1, factor))\n const [r1, g1, b1] = hexToRgb(color1)\n const [r2, g2, b2] = hexToRgb(color2)\n\n return rgbToHex(\n r1 + (r2 - r1) * clampedFactor,\n g1 + (g2 - g1) * clampedFactor,\n b1 + (b2 - b1) * clampedFactor\n )\n}\n\nexport function getStrokeColor(\n colors: ColorFormat | undefined,\n colorsTime: number[] | undefined,\n remainingTime: number,\n duration: number\n): string {\n const defaultColor = '#3498DB'\n\n if (!colors) return defaultColor\n\n if (typeof colors === 'string') return colors\n\n if (colors.length === 0) return defaultColor\n if (colors.length === 1) return colors[0]\n\n const times =\n colorsTime ??\n colors.map((_, i) => duration - (duration / (colors.length - 1)) * i)\n\n for (let i = 0; i < times.length - 1; i++) {\n const currentTime = times[i]\n const nextTime = times[i + 1]\n\n if (remainingTime <= currentTime && remainingTime >= nextTime) {\n const range = currentTime - nextTime\n if (range === 0) return colors[i]\n\n const factor = (currentTime - remainingTime) / range\n return interpolateColor(colors[i], colors[i + 1], factor)\n }\n }\n\n if (remainingTime >= times[0]) return colors[0]\n return colors[colors.length - 1]\n}\n","import type { Rotation } from '../types'\n\nexport function getCirclePath(\n size: number,\n strokeWidth: number,\n rotation: Rotation = 'clockwise'\n): string {\n const halfSize = size / 2\n const radius = halfSize - strokeWidth / 2\n\n const isClockwise = rotation === 'clockwise'\n const sweepFlag = isClockwise ? 1 : 0\n\n return [\n `M ${halfSize},${strokeWidth / 2}`,\n `A ${radius},${radius} 0 1,${sweepFlag} ${halfSize},${size - strokeWidth / 2}`,\n `A ${radius},${radius} 0 1,${sweepFlag} ${halfSize},${strokeWidth / 2}`,\n ].join(' ')\n}\n\nexport function getPathLength(size: number, strokeWidth: number): number {\n const radius = (size - strokeWidth) / 2\n return 2 * Math.PI * radius\n}\n\nexport function getStrokeDashoffset(\n pathLength: number,\n progress: number\n): number {\n const clampedProgress = Math.max(0, Math.min(1, progress))\n return pathLength * (1 - clampedProgress)\n}\n","import type { SpringConfig, EasingFn } from '../types'\n\ninterface SpringState {\n position: number\n velocity: number\n}\n\nfunction springStep(\n state: SpringState,\n stiffness: number,\n damping: number,\n mass: number,\n dt: number\n): SpringState {\n // RK4 integration for damped harmonic oscillator\n function acceleration(pos: number, vel: number): number {\n return (-stiffness * (pos - 1) - damping * vel) / mass\n }\n\n // k1\n const k1v = acceleration(state.position, state.velocity)\n const k1x = state.velocity\n\n // k2\n const k2v = acceleration(\n state.position + k1x * dt * 0.5,\n state.velocity + k1v * dt * 0.5\n )\n const k2x = state.velocity + k1v * dt * 0.5\n\n // k3\n const k3v = acceleration(\n state.position + k2x * dt * 0.5,\n state.velocity + k2v * dt * 0.5\n )\n const k3x = state.velocity + k2v * dt * 0.5\n\n // k4\n const k4v = acceleration(\n state.position + k3x * dt,\n state.velocity + k3v * dt\n )\n const k4x = state.velocity + k3v * dt\n\n const newPosition =\n state.position + (dt / 6) * (k1x + 2 * k2x + 2 * k3x + k4x)\n const newVelocity =\n state.velocity + (dt / 6) * (k1v + 2 * k2v + 2 * k3v + k4v)\n\n return { position: newPosition, velocity: newVelocity }\n}\n\nexport function createSpringEasing(config: SpringConfig): EasingFn {\n const tension = config.tension ?? 170\n const friction = config.friction ?? 26\n const mass = config.mass ?? 1\n\n // Pre-compute spring trajectory\n const samples: number[] = []\n const sampleCount = 1000\n const dt = 0.001 // 1ms steps\n\n let state: SpringState = { position: 0, velocity: 0 }\n let totalTime = 0\n const threshold = 0.0001\n\n // Simulate until settled\n for (let i = 0; i < 10000; i++) {\n state = springStep(state, tension, friction, mass, dt)\n totalTime += dt\n\n if (\n Math.abs(state.position - 1) < threshold &&\n Math.abs(state.velocity) < threshold\n ) {\n break\n }\n }\n\n const settleDuration = totalTime\n\n // Re-simulate and sample at regular intervals\n state = { position: 0, velocity: 0 }\n for (let i = 0; i <= sampleCount; i++) {\n const targetTime = (i / sampleCount) * settleDuration\n\n while (totalTime < targetTime) {\n state = springStep(state, tension, friction, mass, dt)\n totalTime += dt\n }\n\n samples.push(state.position)\n if (i === 0) {\n totalTime = 0\n state = { position: 0, velocity: 0 }\n }\n }\n\n // Re-build properly: sequential simulation\n const properSamples: number[] = []\n state = { position: 0, velocity: 0 }\n\n for (let i = 0; i <= sampleCount; i++) {\n const stepsPerSample = Math.ceil(settleDuration / dt / sampleCount)\n for (let j = 0; j < stepsPerSample; j++) {\n state = springStep(state, tension, friction, mass, dt)\n }\n properSamples.push(Math.max(0, Math.min(state.position, 1.5)))\n }\n\n return (t: number): number => {\n if (t <= 0) return 0\n if (t >= 1) return 1\n\n const index = t * sampleCount\n const lower = Math.floor(index)\n const upper = Math.min(Math.ceil(index), sampleCount)\n const fraction = index - lower\n\n const lowerVal = properSamples[lower] ?? 0\n const upperVal = properSamples[upper] ?? 1\n\n return lowerVal + (upperVal - lowerVal) * fraction\n }\n}\n","import type { EasingName, EasingFn, EasingConfig } from '../types'\nimport { createSpringEasing } from './spring'\n\nexport const easings: Record<EasingName, EasingFn> = {\n linear: (t) => t,\n easeIn: (t) => t * t,\n easeOut: (t) => t * (2 - t),\n easeInOut: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),\n easeInCubic: (t) => t * t * t,\n easeOutCubic: (t) => {\n const t1 = t - 1\n return t1 * t1 * t1 + 1\n },\n easeInOutCubic: (t) =>\n t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,\n}\n\nexport function resolveEasing(easing: EasingConfig | undefined): EasingFn {\n if (!easing) return easings.linear\n\n if (typeof easing === 'function') return easing\n\n if (typeof easing === 'string') {\n return easings[easing] ?? easings.linear\n }\n\n if (typeof easing === 'object' && easing.type === 'spring') {\n return createSpringEasing(easing)\n }\n\n return easings.linear\n}\n\nexport function getEasingNames(): EasingName[] {\n return Object.keys(easings) as EasingName[]\n}\n","import type { PulseConfig } from '../types'\n\nexport interface BounceResult {\n scale: number\n active: boolean\n}\n\nexport function computeBounce(\n remainingTime: number,\n prevRemainingTime: number,\n bounceAt: number[],\n bounceOnComplete: boolean,\n isComplete: boolean,\n elapsedSinceBounce: number\n): BounceResult {\n const bounceDuration = 300 // ms\n\n // Check if we just crossed a bounce threshold\n const shouldBounce =\n (bounceOnComplete && isComplete) ||\n bounceAt.some(\n (threshold) =>\n prevRemainingTime > threshold && remainingTime <= threshold\n )\n\n if (!shouldBounce && elapsedSinceBounce > bounceDuration) {\n return { scale: 1, active: false }\n }\n\n if (shouldBounce || elapsedSinceBounce <= bounceDuration) {\n // Bounce animation: scale up then back down\n const progress = Math.min(elapsedSinceBounce / bounceDuration, 1)\n const bounceScale = 1 + 0.1 * Math.sin(progress * Math.PI)\n return { scale: bounceScale, active: progress < 1 }\n }\n\n return { scale: 1, active: false }\n}\n\nexport interface PulseResult {\n scale: number\n opacity: number\n}\n\nexport function computePulse(\n elapsedTime: number,\n config: PulseConfig | false | undefined\n): PulseResult {\n if (!config) {\n return { scale: 1, opacity: 1 }\n }\n\n const { interval, scale = 1.05, opacity = 1 } = config\n\n if (interval <= 0) {\n return { scale: 1, opacity: 1 }\n }\n\n const cycleProgress = (elapsedTime % interval) / interval\n const sinValue = Math.sin(cycleProgress * 2 * Math.PI)\n\n // Normalize sin from [-1, 1] to [0, 1]\n const normalized = (sinValue + 1) / 2\n\n const currentScale = 1 + (scale - 1) * normalized\n const minOpacity = Math.max(0, 2 * opacity - 1)\n const currentOpacity = minOpacity + (1 - minOpacity) * normalized\n\n return {\n scale: currentScale,\n opacity: currentOpacity,\n }\n}\n","import {\n useReducer,\n useRef,\n useEffect,\n useMemo,\n useState,\n useCallback,\n} from 'react'\nimport { timerReducer, createInitialState } from './engine/timerMachine'\nimport { subscribe } from './engine/rafLoop'\nimport { getStrokeColor } from './engine/colorInterpolation'\nimport {\n getCirclePath,\n getPathLength,\n getStrokeDashoffset,\n} from './svg/pathCalculation'\nimport { resolveEasing } from './animation/easings'\nimport { computeBounce, computePulse } from './animation/effects'\nimport type {\n CountdownProps,\n UseCountdownReturn,\n OnCompleteResult,\n} from './types'\n\nlet idCounter = 0\nfunction generateId(): string {\n return `arc-timer-${++idCounter}`\n}\n\nexport function useCountdown(props: CountdownProps): UseCountdownReturn {\n const {\n duration,\n isPlaying = false,\n colors,\n colorsTime,\n size = 180,\n strokeWidth = 12,\n rotation = 'clockwise',\n isCountUp = false,\n initialRemainingTime,\n updateInterval = 1,\n easing,\n bounceOnComplete = false,\n bounceAt = [],\n pulse,\n onComplete,\n onUpdate,\n onAnimationFrame,\n } = props\n\n const [state, dispatch] = useReducer(\n timerReducer,\n { duration, initialRemainingTime },\n ({ duration: d, initialRemainingTime: irt }) => createInitialState(d, irt)\n )\n\n // Integer display time (for text rendering - updates per second)\n const [displayTime, setDisplayTime] = useState(() => {\n if (initialRemainingTime !== undefined) {\n return isCountUp\n ? duration - initialRemainingTime\n : initialRemainingTime\n }\n return isCountUp ? 0 : duration\n })\n\n // Continuous smooth progress [0..1] (for arc animation - updates every frame)\n const [smoothProgress, setSmoothProgress] = useState(0)\n\n // Animation effects state\n const [animationScale, setAnimationScale] = useState(1)\n const [animationOpacity, setAnimationOpacity] = useState(1)\n\n const idRef = useRef(generateId())\n const prevDisplayTimeRef = useRef(displayTime)\n const onCompleteRef = useRef(onComplete)\n const onUpdateRef = useRef(onUpdate)\n const onAnimationFrameRef = useRef(onAnimationFrame)\n const repeatTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n // Bounce tracking\n const bounceStartRef = useRef<number | null>(null)\n const prevRemainingForBounceRef = useRef(displayTime)\n\n // Resolve easing function\n const easingFn = useMemo(() => resolveEasing(easing), [easing])\n\n onCompleteRef.current = onComplete\n onUpdateRef.current = onUpdate\n onAnimationFrameRef.current = onAnimationFrame\n\n // Imperative API methods\n const play = useCallback(() => {\n dispatch({ type: 'PLAY' })\n }, [])\n\n const pause = useCallback(() => {\n dispatch({ type: 'PAUSE' })\n }, [])\n\n const reset = useCallback(\n (newDuration?: number) => {\n dispatch({ type: 'RESET', duration: newDuration })\n const dur = newDuration ?? duration\n setDisplayTime(isCountUp ? 0 : dur)\n setSmoothProgress(0)\n setAnimationScale(1)\n setAnimationOpacity(1)\n bounceStartRef.current = null\n },\n [duration, isCountUp]\n )\n\n // Handle isPlaying prop changes\n useEffect(() => {\n if (isPlaying) {\n if (state.status !== 'playing') {\n dispatch({ type: 'PLAY' })\n }\n } else {\n if (state.status === 'playing') {\n dispatch({ type: 'PAUSE' })\n }\n }\n }, [isPlaying, state.status])\n\n // Handle duration changes\n useEffect(() => {\n if (duration !== state.duration) {\n dispatch({ type: 'RESET', duration })\n }\n }, [duration, state.duration])\n\n // RAF subscription - updates EVERY FRAME for smooth animation\n useEffect(() => {\n if (state.status !== 'playing' || state.startedAt === null) return\n\n const startedAt = state.startedAt\n let lastUpdateTime = 0\n\n const unsubscribe = subscribe(idRef.current, (timestamp: number) => {\n const elapsedMs = timestamp - startedAt\n const elapsedSeconds = elapsedMs / 1000\n const clampedElapsed = Math.min(elapsedSeconds, duration)\n\n // Compute continuous eased progress (0 to 1) - updates EVERY FRAME\n const linearProgress = duration > 0 ? clampedElapsed / duration : 1\n const easedProgress = easingFn(linearProgress)\n\n // Update smooth progress for arc animation (every frame = 60fps)\n setSmoothProgress(easedProgress)\n\n onAnimationFrameRef.current?.(easedProgress)\n\n // Compute integer remaining time for display\n const rawRemainingTime = Math.max(\n 0,\n duration - duration * easedProgress\n )\n const remainingTimeInt = Math.ceil(rawRemainingTime)\n\n // Bounce effect\n const hasBounceConfig =\n bounceOnComplete || (bounceAt && bounceAt.length > 0)\n if (hasBounceConfig) {\n const prevRemaining = prevRemainingForBounceRef.current\n const shouldStartBounce =\n (bounceOnComplete && rawRemainingTime <= 0 && prevRemaining > 0) ||\n bounceAt.some(\n (t) => prevRemaining > t && remainingTimeInt <= t\n )\n\n if (shouldStartBounce) {\n bounceStartRef.current = timestamp\n }\n\n if (bounceStartRef.current !== null) {\n const bounceElapsed = timestamp - bounceStartRef.current\n const result = computeBounce(\n remainingTimeInt,\n prevRemaining,\n bounceAt,\n bounceOnComplete,\n rawRemainingTime <= 0,\n bounceElapsed\n )\n setAnimationScale(result.scale)\n if (!result.active) {\n bounceStartRef.current = null\n }\n }\n\n prevRemainingForBounceRef.current = remainingTimeInt\n }\n\n // Pulse effect\n if (pulse) {\n const pulseResult = computePulse(clampedElapsed, pulse)\n setAnimationScale((prev) =>\n bounceStartRef.current !== null ? prev : pulseResult.scale\n )\n setAnimationOpacity(pulseResult.opacity)\n }\n\n // Update integer display time at the configured interval\n const shouldUpdate =\n updateInterval === 0 ||\n timestamp - lastUpdateTime >= updateInterval * 1000\n\n if (shouldUpdate) {\n lastUpdateTime = timestamp\n const newDisplayTime = isCountUp\n ? Math.floor(clampedElapsed)\n : remainingTimeInt\n\n setDisplayTime((prev) => {\n if (prev !== newDisplayTime) {\n return newDisplayTime\n }\n return prev\n })\n }\n\n if (clampedElapsed >= duration) {\n dispatch({ type: 'COMPLETE' })\n }\n })\n\n return unsubscribe\n }, [\n state.status,\n state.startedAt,\n duration,\n updateInterval,\n isCountUp,\n easingFn,\n bounceOnComplete,\n bounceAt,\n pulse,\n ])\n\n // Handle completion\n useEffect(() => {\n if (state.status !== 'completed') return\n\n const result = onCompleteRef.current?.(state.duration) as\n | OnCompleteResult\n | void\n\n if (result?.shouldRepeat) {\n const delay = (result.delay ?? 0) * 1000\n\n repeatTimeoutRef.current = setTimeout(() => {\n if (result.newInitialRemainingTime !== undefined) {\n dispatch({ type: 'RESET' })\n setDisplayTime(\n isCountUp\n ? duration - result.newInitialRemainingTime\n : result.newInitialRemainingTime\n )\n } else {\n dispatch({ type: 'RESET' })\n setDisplayTime(isCountUp ? 0 : duration)\n }\n setSmoothProgress(0)\n dispatch({ type: 'PLAY' })\n }, delay)\n }\n\n return () => {\n if (repeatTimeoutRef.current) {\n clearTimeout(repeatTimeoutRef.current)\n }\n }\n }, [state.status, state.duration, duration, isCountUp])\n\n // Call onUpdate when display time changes\n useEffect(() => {\n if (prevDisplayTimeRef.current !== displayTime) {\n prevDisplayTimeRef.current = displayTime\n const rt = isCountUp ? duration - displayTime : displayTime\n onUpdateRef.current?.(rt)\n }\n }, [displayTime, duration, isCountUp])\n\n // Compute SVG values\n const path = useMemo(\n () => getCirclePath(size, strokeWidth, rotation),\n [size, strokeWidth, rotation]\n )\n\n const pathLength = useMemo(\n () => getPathLength(size, strokeWidth),\n [size, strokeWidth]\n )\n\n // Use integer values for text display\n const elapsedTime = isCountUp ? displayTime : duration - displayTime\n const remainingTime = isCountUp ? duration - displayTime : displayTime\n const isComplete = state.status === 'completed'\n\n // Use SMOOTH continuous progress for SVG arc (this is the key fix!)\n const arcProgress = isCountUp ? smoothProgress : 1 - smoothProgress\n const strokeDashoffset = getStrokeDashoffset(pathLength, arcProgress)\n\n // Color uses remaining time (integer) for threshold matching\n const color = getStrokeColor(colors, colorsTime, remainingTime, duration)\n\n // Progress for external consumers (continuous)\n const progress = smoothProgress\n\n return {\n path,\n pathLength,\n stroke: color,\n strokeDashoffset,\n remainingTime,\n elapsedTime,\n progress,\n color,\n size,\n strokeWidth,\n isComplete,\n isPlaying: state.status === 'playing',\n animationScale,\n animationOpacity,\n _play: play,\n _pause: pause,\n _reset: reset,\n _getState: () => ({\n remainingTime,\n elapsedTime,\n isPlaying: state.status === 'playing',\n progress,\n isComplete,\n }),\n } as UseCountdownReturn\n}\n","import {\n useState,\n useCallback,\n useRef,\n useEffect,\n createContext,\n useContext,\n} from 'react'\nimport type {\n TimerGroupMode,\n UseTimerGroupReturn,\n} from './types'\n\nexport interface UseTimerGroupOptions {\n mode?: TimerGroupMode\n staggerDelay?: number\n isPlaying?: boolean\n timerCount: number\n onGroupComplete?: () => void\n onTimerComplete?: (index: number) => void\n}\n\ninterface TimerGroupContextValue {\n mode: TimerGroupMode\n isTimerPlaying: (index: number) => boolean\n onTimerDone: (index: number) => void\n registerTimer: (index: number) => void\n}\n\nexport const TimerGroupContext = createContext<TimerGroupContextValue | null>(\n null\n)\n\nexport function useTimerGroupContext(): TimerGroupContextValue | null {\n return useContext(TimerGroupContext)\n}\n\nexport function useTimerGroup(\n options: UseTimerGroupOptions\n): UseTimerGroupReturn {\n const {\n mode = 'sequential',\n staggerDelay: _staggerDelay = 0,\n isPlaying = false,\n timerCount,\n onGroupComplete,\n onTimerComplete,\n } = options\n\n const [activeIndex, setActiveIndex] = useState(0)\n const [groupState, setGroupState] = useState<\n 'idle' | 'playing' | 'paused' | 'completed'\n >('idle')\n const [completedTimers, setCompletedTimers] = useState<Set<number>>(\n () => new Set()\n )\n const [timerStates, setTimerStates] = useState<\n Array<{ isPlaying: boolean; isComplete: boolean }>\n >(() =>\n Array.from({ length: timerCount }, () => ({\n isPlaying: false,\n isComplete: false,\n }))\n )\n\n const onGroupCompleteRef = useRef(onGroupComplete)\n const onTimerCompleteRef = useRef(onTimerComplete)\n onGroupCompleteRef.current = onGroupComplete\n onTimerCompleteRef.current = onTimerComplete\n\n // Handle isPlaying prop changes\n useEffect(() => {\n if (isPlaying) {\n setGroupState('playing')\n } else if (groupState === 'playing') {\n setGroupState('paused')\n }\n }, [isPlaying, groupState])\n\n // Compute timer playing states based on mode\n useEffect(() => {\n if (groupState !== 'playing') {\n setTimerStates((prev) =>\n prev.map((t) => ({ ...t, isPlaying: false }))\n )\n return\n }\n\n setTimerStates((prev) =>\n prev.map((t, i) => {\n if (completedTimers.has(i)) {\n return { ...t, isPlaying: false, isComplete: true }\n }\n\n switch (mode) {\n case 'sequential':\n return { ...t, isPlaying: i === activeIndex }\n case 'parallel':\n return { ...t, isPlaying: true }\n case 'staggered':\n return { ...t, isPlaying: true }\n default:\n return t\n }\n })\n )\n }, [groupState, mode, activeIndex, completedTimers, timerCount])\n\n const handleTimerComplete = useCallback(\n (index: number) => {\n onTimerCompleteRef.current?.(index)\n\n setCompletedTimers((prev) => {\n const next = new Set(prev)\n next.add(index)\n\n if (next.size >= timerCount) {\n setGroupState('completed')\n onGroupCompleteRef.current?.()\n }\n\n return next\n })\n\n if (mode === 'sequential') {\n setActiveIndex((prev) => Math.min(prev + 1, timerCount - 1))\n }\n },\n [mode, timerCount]\n )\n\n const playAll = useCallback(() => {\n setGroupState('playing')\n }, [])\n\n const pauseAll = useCallback(() => {\n setGroupState('paused')\n }, [])\n\n const resetAll = useCallback(() => {\n setActiveIndex(0)\n setGroupState('idle')\n setCompletedTimers(new Set())\n setTimerStates(\n Array.from({ length: timerCount }, () => ({\n isPlaying: false,\n isComplete: false,\n }))\n )\n }, [timerCount])\n\n return {\n timers: timerStates,\n activeIndex,\n playAll,\n pauseAll,\n resetAll,\n groupState,\n _handleTimerComplete: handleTimerComplete,\n } as UseTimerGroupReturn & { _handleTimerComplete: (index: number) => void }\n}\n","import type { RenderInfo } from '../types'\n\nexport function generateAriaLabel(\n remainingTime: number,\n isCountUp: boolean\n): string {\n const minutes = Math.floor(remainingTime / 60)\n const seconds = remainingTime % 60\n\n const timeStr =\n minutes > 0\n ? `${minutes} minute${minutes !== 1 ? 's' : ''} and ${seconds} second${seconds !== 1 ? 's' : ''}`\n : `${seconds} second${seconds !== 1 ? 's' : ''}`\n\n return isCountUp\n ? `${timeStr} elapsed`\n : `${timeStr} remaining`\n}\n\nexport function resolveAriaLabel(\n ariaLabel: string | ((info: RenderInfo) => string) | undefined,\n info: RenderInfo,\n isCountUp: boolean\n): string {\n if (typeof ariaLabel === 'function') {\n return ariaLabel(info)\n }\n\n if (typeof ariaLabel === 'string') {\n return ariaLabel\n }\n\n return generateAriaLabel(info.remainingTime, isCountUp)\n}\n","import { useRef, useEffect } from 'react'\n\nexport interface AnnouncementConfig {\n announceInterval: number\n duration: number\n thresholds?: number[]\n}\n\nconst DEFAULT_THRESHOLDS_PERCENT = [50, 25, 10]\nconst DEFAULT_THRESHOLDS_SECONDS = [5]\n\nexport function getAnnouncementText(\n remainingTime: number,\n isCountUp: boolean\n): string {\n if (remainingTime <= 0) {\n return isCountUp ? 'Timer complete' : 'Time is up'\n }\n\n const minutes = Math.floor(remainingTime / 60)\n const seconds = remainingTime % 60\n\n if (minutes > 0) {\n return isCountUp\n ? `${minutes} minutes and ${seconds} seconds elapsed`\n : `${minutes} minutes and ${seconds} seconds remaining`\n }\n\n return isCountUp\n ? `${seconds} seconds elapsed`\n : `${seconds} seconds remaining`\n}\n\nexport function shouldAnnounce(\n remainingTime: number,\n prevRemainingTime: number,\n duration: number,\n announceInterval: number\n): boolean {\n if (remainingTime === prevRemainingTime) return false\n\n // Announce at completion\n if (remainingTime <= 0 && prevRemainingTime > 0) return true\n\n // Announce at regular intervals\n if (announceInterval > 0) {\n const prevBucket = Math.floor(prevRemainingTime / announceInterval)\n const currentBucket = Math.floor(remainingTime / announceInterval)\n if (prevBucket !== currentBucket) return true\n }\n\n // Announce at percentage thresholds\n for (const percent of DEFAULT_THRESHOLDS_PERCENT) {\n const threshold = Math.floor(duration * (percent / 100))\n if (\n prevRemainingTime > threshold &&\n remainingTime <= threshold\n ) {\n return true\n }\n }\n\n // Announce at specific second thresholds\n for (const threshold of DEFAULT_THRESHOLDS_SECONDS) {\n if (\n prevRemainingTime > threshold &&\n remainingTime <= threshold\n ) {\n return true\n }\n }\n\n return false\n}\n\nexport function useAnnouncer(\n remainingTime: number,\n duration: number,\n announceInterval: number,\n isCountUp: boolean\n): {\n announcement: string\n announcerProps: {\n role: 'status'\n 'aria-live': 'polite'\n 'aria-atomic': true\n style: React.CSSProperties\n }\n} {\n const prevTimeRef = useRef(remainingTime)\n const announcementRef = useRef('')\n\n useEffect(() => {\n if (\n shouldAnnounce(\n remainingTime,\n prevTimeRef.current,\n duration,\n announceInterval\n )\n ) {\n announcementRef.current = getAnnouncementText(\n remainingTime,\n isCountUp\n )\n }\n prevTimeRef.current = remainingTime\n }, [remainingTime, duration, announceInterval, isCountUp])\n\n return {\n announcement: announcementRef.current,\n announcerProps: {\n role: 'status' as const,\n 'aria-live': 'polite' as const,\n 'aria-atomic': true as const,\n style: {\n position: 'absolute' as const,\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden' as const,\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap' as const,\n borderWidth: 0,\n },\n },\n }\n}\n","import { useState, useEffect } from 'react'\n\nconst QUERY = '(prefers-reduced-motion: reduce)'\n\nfunction getInitialState(): boolean {\n if (typeof window === 'undefined') return false\n if (typeof window.matchMedia !== 'function') return false\n return window.matchMedia(QUERY).matches\n}\n\nexport function useReducedMotion(): boolean {\n const [prefersReducedMotion, setPrefersReducedMotion] =\n useState(getInitialState)\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n if (typeof window.matchMedia !== 'function') return\n\n const mediaQuery = window.matchMedia(QUERY)\n\n const handler = (event: MediaQueryListEvent) => {\n setPrefersReducedMotion(event.matches)\n }\n\n mediaQuery.addEventListener('change', handler)\n return () => {\n mediaQuery.removeEventListener('change', handler)\n }\n }, [])\n\n return prefersReducedMotion\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type TimerStatus = 'idle' | 'playing' | 'paused' | 'completed';
|
|
5
|
+
type TimerEvent = {
|
|
6
|
+
type: 'PLAY';
|
|
7
|
+
} | {
|
|
8
|
+
type: 'PAUSE';
|
|
9
|
+
} | {
|
|
10
|
+
type: 'RESET';
|
|
11
|
+
duration?: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'COMPLETE';
|
|
14
|
+
};
|
|
15
|
+
interface TimerState {
|
|
16
|
+
status: TimerStatus;
|
|
17
|
+
duration: number;
|
|
18
|
+
elapsed: number;
|
|
19
|
+
startedAt: number | null;
|
|
20
|
+
pausedAt: number | null;
|
|
21
|
+
}
|
|
22
|
+
type Color = string;
|
|
23
|
+
type ColorFormat = Color | Color[];
|
|
24
|
+
type EasingName = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic';
|
|
25
|
+
interface SpringConfig {
|
|
26
|
+
type: 'spring';
|
|
27
|
+
tension?: number;
|
|
28
|
+
friction?: number;
|
|
29
|
+
mass?: number;
|
|
30
|
+
}
|
|
31
|
+
type EasingFn = (t: number) => number;
|
|
32
|
+
type EasingConfig = EasingName | SpringConfig | EasingFn;
|
|
33
|
+
interface PulseConfig {
|
|
34
|
+
interval: number;
|
|
35
|
+
scale?: number;
|
|
36
|
+
opacity?: number;
|
|
37
|
+
}
|
|
38
|
+
interface RenderInfo {
|
|
39
|
+
remainingTime: number;
|
|
40
|
+
elapsedTime: number;
|
|
41
|
+
color: string;
|
|
42
|
+
progress: number;
|
|
43
|
+
isComplete: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface OnCompleteResult {
|
|
46
|
+
shouldRepeat?: boolean;
|
|
47
|
+
delay?: number;
|
|
48
|
+
newInitialRemainingTime?: number;
|
|
49
|
+
}
|
|
50
|
+
type Rotation = 'clockwise' | 'counterclockwise';
|
|
51
|
+
interface CountdownProps {
|
|
52
|
+
duration: number;
|
|
53
|
+
isPlaying?: boolean;
|
|
54
|
+
colors?: ColorFormat;
|
|
55
|
+
colorsTime?: number[];
|
|
56
|
+
size?: number;
|
|
57
|
+
strokeWidth?: number;
|
|
58
|
+
trailColor?: string;
|
|
59
|
+
trailStrokeWidth?: number;
|
|
60
|
+
strokeLinecap?: 'round' | 'butt' | 'square';
|
|
61
|
+
rotation?: Rotation;
|
|
62
|
+
isCountUp?: boolean;
|
|
63
|
+
initialRemainingTime?: number;
|
|
64
|
+
updateInterval?: number;
|
|
65
|
+
easing?: EasingConfig;
|
|
66
|
+
bounceOnComplete?: boolean;
|
|
67
|
+
bounceAt?: number[];
|
|
68
|
+
pulse?: PulseConfig | false;
|
|
69
|
+
onComplete?: (elapsed: number) => OnCompleteResult | void;
|
|
70
|
+
onUpdate?: (remainingTime: number) => void;
|
|
71
|
+
onAnimationFrame?: (progress: number) => void;
|
|
72
|
+
ariaLabel?: string | ((info: RenderInfo) => string);
|
|
73
|
+
announceInterval?: number;
|
|
74
|
+
children?: (info: RenderInfo) => ReactNode;
|
|
75
|
+
}
|
|
76
|
+
interface TimerRef {
|
|
77
|
+
play: () => void;
|
|
78
|
+
pause: () => void;
|
|
79
|
+
reset: (newDuration?: number) => void;
|
|
80
|
+
getState: () => {
|
|
81
|
+
remainingTime: number;
|
|
82
|
+
elapsedTime: number;
|
|
83
|
+
isPlaying: boolean;
|
|
84
|
+
progress: number;
|
|
85
|
+
isComplete: boolean;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
interface UseCountdownReturn {
|
|
89
|
+
path: string;
|
|
90
|
+
pathLength: number;
|
|
91
|
+
stroke: string;
|
|
92
|
+
strokeDashoffset: number;
|
|
93
|
+
remainingTime: number;
|
|
94
|
+
elapsedTime: number;
|
|
95
|
+
progress: number;
|
|
96
|
+
color: string;
|
|
97
|
+
size: number;
|
|
98
|
+
strokeWidth: number;
|
|
99
|
+
isComplete: boolean;
|
|
100
|
+
isPlaying: boolean;
|
|
101
|
+
/** Smooth animation scale (for bounce/pulse effects) */
|
|
102
|
+
animationScale: number;
|
|
103
|
+
/** Smooth animation opacity (for pulse effect) */
|
|
104
|
+
animationOpacity: number;
|
|
105
|
+
/** @internal Imperative play method */
|
|
106
|
+
_play: () => void;
|
|
107
|
+
/** @internal Imperative pause method */
|
|
108
|
+
_pause: () => void;
|
|
109
|
+
/** @internal Imperative reset method */
|
|
110
|
+
_reset: (newDuration?: number) => void;
|
|
111
|
+
/** @internal Imperative getState method */
|
|
112
|
+
_getState: () => {
|
|
113
|
+
remainingTime: number;
|
|
114
|
+
elapsedTime: number;
|
|
115
|
+
isPlaying: boolean;
|
|
116
|
+
progress: number;
|
|
117
|
+
isComplete: boolean;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
type TimerGroupMode = 'sequential' | 'parallel' | 'staggered';
|
|
121
|
+
interface TimerGroupProps {
|
|
122
|
+
mode?: TimerGroupMode;
|
|
123
|
+
staggerDelay?: number;
|
|
124
|
+
isPlaying?: boolean;
|
|
125
|
+
onGroupComplete?: () => void;
|
|
126
|
+
onTimerComplete?: (index: number) => void;
|
|
127
|
+
children: ReactNode;
|
|
128
|
+
}
|
|
129
|
+
interface TimerGroupRef {
|
|
130
|
+
playAll: () => void;
|
|
131
|
+
pauseAll: () => void;
|
|
132
|
+
resetAll: () => void;
|
|
133
|
+
}
|
|
134
|
+
interface UseTimerGroupReturn {
|
|
135
|
+
timers: Array<{
|
|
136
|
+
isPlaying: boolean;
|
|
137
|
+
isComplete: boolean;
|
|
138
|
+
}>;
|
|
139
|
+
activeIndex: number;
|
|
140
|
+
playAll: () => void;
|
|
141
|
+
pauseAll: () => void;
|
|
142
|
+
resetAll: () => void;
|
|
143
|
+
groupState: 'idle' | 'playing' | 'paused' | 'completed';
|
|
144
|
+
}
|
|
145
|
+
interface ThemeColors {
|
|
146
|
+
primary: string;
|
|
147
|
+
trail: string;
|
|
148
|
+
text: string;
|
|
149
|
+
background: string;
|
|
150
|
+
success: string;
|
|
151
|
+
warning: string;
|
|
152
|
+
danger: string;
|
|
153
|
+
}
|
|
154
|
+
interface ThemeSizes {
|
|
155
|
+
default: number;
|
|
156
|
+
strokeWidth: number;
|
|
157
|
+
trailStrokeWidth?: number;
|
|
158
|
+
}
|
|
159
|
+
interface ThemeAnimation {
|
|
160
|
+
defaultEasing: EasingConfig;
|
|
161
|
+
}
|
|
162
|
+
interface ThemeAccessibility {
|
|
163
|
+
focusRingColor: string;
|
|
164
|
+
focusRingWidth: number;
|
|
165
|
+
focusRingOffset: number;
|
|
166
|
+
}
|
|
167
|
+
interface Theme {
|
|
168
|
+
name: string;
|
|
169
|
+
colors: ThemeColors;
|
|
170
|
+
sizes: ThemeSizes;
|
|
171
|
+
animation: ThemeAnimation;
|
|
172
|
+
accessibility: ThemeAccessibility;
|
|
173
|
+
strokeLinecap: 'round' | 'butt' | 'square';
|
|
174
|
+
}
|
|
175
|
+
type DeepPartial<T> = {
|
|
176
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
177
|
+
};
|
|
178
|
+
interface ThemeOverride extends DeepPartial<Theme> {
|
|
179
|
+
extends?: Theme;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
declare function useCountdown(props: CountdownProps): UseCountdownReturn;
|
|
183
|
+
|
|
184
|
+
interface UseTimerGroupOptions {
|
|
185
|
+
mode?: TimerGroupMode;
|
|
186
|
+
staggerDelay?: number;
|
|
187
|
+
isPlaying?: boolean;
|
|
188
|
+
timerCount: number;
|
|
189
|
+
onGroupComplete?: () => void;
|
|
190
|
+
onTimerComplete?: (index: number) => void;
|
|
191
|
+
}
|
|
192
|
+
interface TimerGroupContextValue {
|
|
193
|
+
mode: TimerGroupMode;
|
|
194
|
+
isTimerPlaying: (index: number) => boolean;
|
|
195
|
+
onTimerDone: (index: number) => void;
|
|
196
|
+
registerTimer: (index: number) => void;
|
|
197
|
+
}
|
|
198
|
+
declare const TimerGroupContext: react.Context<TimerGroupContextValue | null>;
|
|
199
|
+
declare function useTimerGroupContext(): TimerGroupContextValue | null;
|
|
200
|
+
declare function useTimerGroup(options: UseTimerGroupOptions): UseTimerGroupReturn;
|
|
201
|
+
|
|
202
|
+
declare function createInitialState(duration: number, initialRemainingTime?: number): TimerState;
|
|
203
|
+
declare function timerReducer(state: TimerState, event: TimerEvent): TimerState;
|
|
204
|
+
|
|
205
|
+
type TickCallback = (timestamp: number) => void;
|
|
206
|
+
declare function subscribe(id: string, callback: TickCallback): () => void;
|
|
207
|
+
declare function _resetForTesting(): void;
|
|
208
|
+
|
|
209
|
+
declare function hexToRgb(hex: string): [number, number, number];
|
|
210
|
+
declare function rgbToHex(r: number, g: number, b: number): string;
|
|
211
|
+
declare function interpolateColor(color1: string, color2: string, factor: number): string;
|
|
212
|
+
declare function getStrokeColor(colors: ColorFormat | undefined, colorsTime: number[] | undefined, remainingTime: number, duration: number): string;
|
|
213
|
+
|
|
214
|
+
declare function getCirclePath(size: number, strokeWidth: number, rotation?: Rotation): string;
|
|
215
|
+
declare function getPathLength(size: number, strokeWidth: number): number;
|
|
216
|
+
declare function getStrokeDashoffset(pathLength: number, progress: number): number;
|
|
217
|
+
|
|
218
|
+
declare const easings: Record<EasingName, EasingFn>;
|
|
219
|
+
declare function resolveEasing(easing: EasingConfig | undefined): EasingFn;
|
|
220
|
+
declare function getEasingNames(): EasingName[];
|
|
221
|
+
|
|
222
|
+
declare function createSpringEasing(config: SpringConfig): EasingFn;
|
|
223
|
+
|
|
224
|
+
interface BounceResult {
|
|
225
|
+
scale: number;
|
|
226
|
+
active: boolean;
|
|
227
|
+
}
|
|
228
|
+
declare function computeBounce(remainingTime: number, prevRemainingTime: number, bounceAt: number[], bounceOnComplete: boolean, isComplete: boolean, elapsedSinceBounce: number): BounceResult;
|
|
229
|
+
interface PulseResult {
|
|
230
|
+
scale: number;
|
|
231
|
+
opacity: number;
|
|
232
|
+
}
|
|
233
|
+
declare function computePulse(elapsedTime: number, config: PulseConfig | false | undefined): PulseResult;
|
|
234
|
+
|
|
235
|
+
declare function generateAriaLabel(remainingTime: number, isCountUp: boolean): string;
|
|
236
|
+
declare function resolveAriaLabel(ariaLabel: string | ((info: RenderInfo) => string) | undefined, info: RenderInfo, isCountUp: boolean): string;
|
|
237
|
+
|
|
238
|
+
declare function getAnnouncementText(remainingTime: number, isCountUp: boolean): string;
|
|
239
|
+
declare function shouldAnnounce(remainingTime: number, prevRemainingTime: number, duration: number, announceInterval: number): boolean;
|
|
240
|
+
declare function useAnnouncer(remainingTime: number, duration: number, announceInterval: number, isCountUp: boolean): {
|
|
241
|
+
announcement: string;
|
|
242
|
+
announcerProps: {
|
|
243
|
+
role: 'status';
|
|
244
|
+
'aria-live': 'polite';
|
|
245
|
+
'aria-atomic': true;
|
|
246
|
+
style: React.CSSProperties;
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
declare function useReducedMotion(): boolean;
|
|
251
|
+
|
|
252
|
+
export { type Color, type ColorFormat, type CountdownProps, type DeepPartial, type EasingConfig, type EasingFn, type EasingName, type OnCompleteResult, type PulseConfig, type RenderInfo, type Rotation, type SpringConfig, type Theme, type ThemeAccessibility, type ThemeAnimation, type ThemeColors, type ThemeOverride, type ThemeSizes, type TimerEvent, TimerGroupContext, type TimerGroupMode, type TimerGroupProps, type TimerGroupRef, type TimerRef, type TimerState, type TimerStatus, type UseCountdownReturn, type UseTimerGroupReturn, _resetForTesting, computeBounce, computePulse, createInitialState, createSpringEasing, easings, generateAriaLabel, getAnnouncementText, getCirclePath, getEasingNames, getPathLength, getStrokeColor, getStrokeDashoffset, hexToRgb, interpolateColor, resolveAriaLabel, resolveEasing, rgbToHex, shouldAnnounce, subscribe, timerReducer, useAnnouncer, useCountdown, useReducedMotion, useTimerGroup, useTimerGroupContext };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type TimerStatus = 'idle' | 'playing' | 'paused' | 'completed';
|
|
5
|
+
type TimerEvent = {
|
|
6
|
+
type: 'PLAY';
|
|
7
|
+
} | {
|
|
8
|
+
type: 'PAUSE';
|
|
9
|
+
} | {
|
|
10
|
+
type: 'RESET';
|
|
11
|
+
duration?: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'COMPLETE';
|
|
14
|
+
};
|
|
15
|
+
interface TimerState {
|
|
16
|
+
status: TimerStatus;
|
|
17
|
+
duration: number;
|
|
18
|
+
elapsed: number;
|
|
19
|
+
startedAt: number | null;
|
|
20
|
+
pausedAt: number | null;
|
|
21
|
+
}
|
|
22
|
+
type Color = string;
|
|
23
|
+
type ColorFormat = Color | Color[];
|
|
24
|
+
type EasingName = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic';
|
|
25
|
+
interface SpringConfig {
|
|
26
|
+
type: 'spring';
|
|
27
|
+
tension?: number;
|
|
28
|
+
friction?: number;
|
|
29
|
+
mass?: number;
|
|
30
|
+
}
|
|
31
|
+
type EasingFn = (t: number) => number;
|
|
32
|
+
type EasingConfig = EasingName | SpringConfig | EasingFn;
|
|
33
|
+
interface PulseConfig {
|
|
34
|
+
interval: number;
|
|
35
|
+
scale?: number;
|
|
36
|
+
opacity?: number;
|
|
37
|
+
}
|
|
38
|
+
interface RenderInfo {
|
|
39
|
+
remainingTime: number;
|
|
40
|
+
elapsedTime: number;
|
|
41
|
+
color: string;
|
|
42
|
+
progress: number;
|
|
43
|
+
isComplete: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface OnCompleteResult {
|
|
46
|
+
shouldRepeat?: boolean;
|
|
47
|
+
delay?: number;
|
|
48
|
+
newInitialRemainingTime?: number;
|
|
49
|
+
}
|
|
50
|
+
type Rotation = 'clockwise' | 'counterclockwise';
|
|
51
|
+
interface CountdownProps {
|
|
52
|
+
duration: number;
|
|
53
|
+
isPlaying?: boolean;
|
|
54
|
+
colors?: ColorFormat;
|
|
55
|
+
colorsTime?: number[];
|
|
56
|
+
size?: number;
|
|
57
|
+
strokeWidth?: number;
|
|
58
|
+
trailColor?: string;
|
|
59
|
+
trailStrokeWidth?: number;
|
|
60
|
+
strokeLinecap?: 'round' | 'butt' | 'square';
|
|
61
|
+
rotation?: Rotation;
|
|
62
|
+
isCountUp?: boolean;
|
|
63
|
+
initialRemainingTime?: number;
|
|
64
|
+
updateInterval?: number;
|
|
65
|
+
easing?: EasingConfig;
|
|
66
|
+
bounceOnComplete?: boolean;
|
|
67
|
+
bounceAt?: number[];
|
|
68
|
+
pulse?: PulseConfig | false;
|
|
69
|
+
onComplete?: (elapsed: number) => OnCompleteResult | void;
|
|
70
|
+
onUpdate?: (remainingTime: number) => void;
|
|
71
|
+
onAnimationFrame?: (progress: number) => void;
|
|
72
|
+
ariaLabel?: string | ((info: RenderInfo) => string);
|
|
73
|
+
announceInterval?: number;
|
|
74
|
+
children?: (info: RenderInfo) => ReactNode;
|
|
75
|
+
}
|
|
76
|
+
interface TimerRef {
|
|
77
|
+
play: () => void;
|
|
78
|
+
pause: () => void;
|
|
79
|
+
reset: (newDuration?: number) => void;
|
|
80
|
+
getState: () => {
|
|
81
|
+
remainingTime: number;
|
|
82
|
+
elapsedTime: number;
|
|
83
|
+
isPlaying: boolean;
|
|
84
|
+
progress: number;
|
|
85
|
+
isComplete: boolean;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
interface UseCountdownReturn {
|
|
89
|
+
path: string;
|
|
90
|
+
pathLength: number;
|
|
91
|
+
stroke: string;
|
|
92
|
+
strokeDashoffset: number;
|
|
93
|
+
remainingTime: number;
|
|
94
|
+
elapsedTime: number;
|
|
95
|
+
progress: number;
|
|
96
|
+
color: string;
|
|
97
|
+
size: number;
|
|
98
|
+
strokeWidth: number;
|
|
99
|
+
isComplete: boolean;
|
|
100
|
+
isPlaying: boolean;
|
|
101
|
+
/** Smooth animation scale (for bounce/pulse effects) */
|
|
102
|
+
animationScale: number;
|
|
103
|
+
/** Smooth animation opacity (for pulse effect) */
|
|
104
|
+
animationOpacity: number;
|
|
105
|
+
/** @internal Imperative play method */
|
|
106
|
+
_play: () => void;
|
|
107
|
+
/** @internal Imperative pause method */
|
|
108
|
+
_pause: () => void;
|
|
109
|
+
/** @internal Imperative reset method */
|
|
110
|
+
_reset: (newDuration?: number) => void;
|
|
111
|
+
/** @internal Imperative getState method */
|
|
112
|
+
_getState: () => {
|
|
113
|
+
remainingTime: number;
|
|
114
|
+
elapsedTime: number;
|
|
115
|
+
isPlaying: boolean;
|
|
116
|
+
progress: number;
|
|
117
|
+
isComplete: boolean;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
type TimerGroupMode = 'sequential' | 'parallel' | 'staggered';
|
|
121
|
+
interface TimerGroupProps {
|
|
122
|
+
mode?: TimerGroupMode;
|
|
123
|
+
staggerDelay?: number;
|
|
124
|
+
isPlaying?: boolean;
|
|
125
|
+
onGroupComplete?: () => void;
|
|
126
|
+
onTimerComplete?: (index: number) => void;
|
|
127
|
+
children: ReactNode;
|
|
128
|
+
}
|
|
129
|
+
interface TimerGroupRef {
|
|
130
|
+
playAll: () => void;
|
|
131
|
+
pauseAll: () => void;
|
|
132
|
+
resetAll: () => void;
|
|
133
|
+
}
|
|
134
|
+
interface UseTimerGroupReturn {
|
|
135
|
+
timers: Array<{
|
|
136
|
+
isPlaying: boolean;
|
|
137
|
+
isComplete: boolean;
|
|
138
|
+
}>;
|
|
139
|
+
activeIndex: number;
|
|
140
|
+
playAll: () => void;
|
|
141
|
+
pauseAll: () => void;
|
|
142
|
+
resetAll: () => void;
|
|
143
|
+
groupState: 'idle' | 'playing' | 'paused' | 'completed';
|
|
144
|
+
}
|
|
145
|
+
interface ThemeColors {
|
|
146
|
+
primary: string;
|
|
147
|
+
trail: string;
|
|
148
|
+
text: string;
|
|
149
|
+
background: string;
|
|
150
|
+
success: string;
|
|
151
|
+
warning: string;
|
|
152
|
+
danger: string;
|
|
153
|
+
}
|
|
154
|
+
interface ThemeSizes {
|
|
155
|
+
default: number;
|
|
156
|
+
strokeWidth: number;
|
|
157
|
+
trailStrokeWidth?: number;
|
|
158
|
+
}
|
|
159
|
+
interface ThemeAnimation {
|
|
160
|
+
defaultEasing: EasingConfig;
|
|
161
|
+
}
|
|
162
|
+
interface ThemeAccessibility {
|
|
163
|
+
focusRingColor: string;
|
|
164
|
+
focusRingWidth: number;
|
|
165
|
+
focusRingOffset: number;
|
|
166
|
+
}
|
|
167
|
+
interface Theme {
|
|
168
|
+
name: string;
|
|
169
|
+
colors: ThemeColors;
|
|
170
|
+
sizes: ThemeSizes;
|
|
171
|
+
animation: ThemeAnimation;
|
|
172
|
+
accessibility: ThemeAccessibility;
|
|
173
|
+
strokeLinecap: 'round' | 'butt' | 'square';
|
|
174
|
+
}
|
|
175
|
+
type DeepPartial<T> = {
|
|
176
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
177
|
+
};
|
|
178
|
+
interface ThemeOverride extends DeepPartial<Theme> {
|
|
179
|
+
extends?: Theme;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
declare function useCountdown(props: CountdownProps): UseCountdownReturn;
|
|
183
|
+
|
|
184
|
+
interface UseTimerGroupOptions {
|
|
185
|
+
mode?: TimerGroupMode;
|
|
186
|
+
staggerDelay?: number;
|
|
187
|
+
isPlaying?: boolean;
|
|
188
|
+
timerCount: number;
|
|
189
|
+
onGroupComplete?: () => void;
|
|
190
|
+
onTimerComplete?: (index: number) => void;
|
|
191
|
+
}
|
|
192
|
+
interface TimerGroupContextValue {
|
|
193
|
+
mode: TimerGroupMode;
|
|
194
|
+
isTimerPlaying: (index: number) => boolean;
|
|
195
|
+
onTimerDone: (index: number) => void;
|
|
196
|
+
registerTimer: (index: number) => void;
|
|
197
|
+
}
|
|
198
|
+
declare const TimerGroupContext: react.Context<TimerGroupContextValue | null>;
|
|
199
|
+
declare function useTimerGroupContext(): TimerGroupContextValue | null;
|
|
200
|
+
declare function useTimerGroup(options: UseTimerGroupOptions): UseTimerGroupReturn;
|
|
201
|
+
|
|
202
|
+
declare function createInitialState(duration: number, initialRemainingTime?: number): TimerState;
|
|
203
|
+
declare function timerReducer(state: TimerState, event: TimerEvent): TimerState;
|
|
204
|
+
|
|
205
|
+
type TickCallback = (timestamp: number) => void;
|
|
206
|
+
declare function subscribe(id: string, callback: TickCallback): () => void;
|
|
207
|
+
declare function _resetForTesting(): void;
|
|
208
|
+
|
|
209
|
+
declare function hexToRgb(hex: string): [number, number, number];
|
|
210
|
+
declare function rgbToHex(r: number, g: number, b: number): string;
|
|
211
|
+
declare function interpolateColor(color1: string, color2: string, factor: number): string;
|
|
212
|
+
declare function getStrokeColor(colors: ColorFormat | undefined, colorsTime: number[] | undefined, remainingTime: number, duration: number): string;
|
|
213
|
+
|
|
214
|
+
declare function getCirclePath(size: number, strokeWidth: number, rotation?: Rotation): string;
|
|
215
|
+
declare function getPathLength(size: number, strokeWidth: number): number;
|
|
216
|
+
declare function getStrokeDashoffset(pathLength: number, progress: number): number;
|
|
217
|
+
|
|
218
|
+
declare const easings: Record<EasingName, EasingFn>;
|
|
219
|
+
declare function resolveEasing(easing: EasingConfig | undefined): EasingFn;
|
|
220
|
+
declare function getEasingNames(): EasingName[];
|
|
221
|
+
|
|
222
|
+
declare function createSpringEasing(config: SpringConfig): EasingFn;
|
|
223
|
+
|
|
224
|
+
interface BounceResult {
|
|
225
|
+
scale: number;
|
|
226
|
+
active: boolean;
|
|
227
|
+
}
|
|
228
|
+
declare function computeBounce(remainingTime: number, prevRemainingTime: number, bounceAt: number[], bounceOnComplete: boolean, isComplete: boolean, elapsedSinceBounce: number): BounceResult;
|
|
229
|
+
interface PulseResult {
|
|
230
|
+
scale: number;
|
|
231
|
+
opacity: number;
|
|
232
|
+
}
|
|
233
|
+
declare function computePulse(elapsedTime: number, config: PulseConfig | false | undefined): PulseResult;
|
|
234
|
+
|
|
235
|
+
declare function generateAriaLabel(remainingTime: number, isCountUp: boolean): string;
|
|
236
|
+
declare function resolveAriaLabel(ariaLabel: string | ((info: RenderInfo) => string) | undefined, info: RenderInfo, isCountUp: boolean): string;
|
|
237
|
+
|
|
238
|
+
declare function getAnnouncementText(remainingTime: number, isCountUp: boolean): string;
|
|
239
|
+
declare function shouldAnnounce(remainingTime: number, prevRemainingTime: number, duration: number, announceInterval: number): boolean;
|
|
240
|
+
declare function useAnnouncer(remainingTime: number, duration: number, announceInterval: number, isCountUp: boolean): {
|
|
241
|
+
announcement: string;
|
|
242
|
+
announcerProps: {
|
|
243
|
+
role: 'status';
|
|
244
|
+
'aria-live': 'polite';
|
|
245
|
+
'aria-atomic': true;
|
|
246
|
+
style: React.CSSProperties;
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
declare function useReducedMotion(): boolean;
|
|
251
|
+
|
|
252
|
+
export { type Color, type ColorFormat, type CountdownProps, type DeepPartial, type EasingConfig, type EasingFn, type EasingName, type OnCompleteResult, type PulseConfig, type RenderInfo, type Rotation, type SpringConfig, type Theme, type ThemeAccessibility, type ThemeAnimation, type ThemeColors, type ThemeOverride, type ThemeSizes, type TimerEvent, TimerGroupContext, type TimerGroupMode, type TimerGroupProps, type TimerGroupRef, type TimerRef, type TimerState, type TimerStatus, type UseCountdownReturn, type UseTimerGroupReturn, _resetForTesting, computeBounce, computePulse, createInitialState, createSpringEasing, easings, generateAriaLabel, getAnnouncementText, getCirclePath, getEasingNames, getPathLength, getStrokeColor, getStrokeDashoffset, hexToRgb, interpolateColor, resolveAriaLabel, resolveEasing, rgbToHex, shouldAnnounce, subscribe, timerReducer, useAnnouncer, useCountdown, useReducedMotion, useTimerGroup, useTimerGroupContext };
|