{"version":3,"file":"timer.mjs","names":[],"sources":["../../../../package/common/timer/timer.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faPlus, faMinus, faPause, faPlay, faXmark } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport Button from '../button';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport { DEFAULT_CHIME_DATA_URI } from './timer.chime';\nimport type { TimerLabels, TimerProps, TimerStatus } from './timer.types';\nimport styles from './timer.module.pcss';\n\nconst TICK_MS = 200;\nconst RIPPLE_SPAWN_INTERVAL_MS = 1000;\n\nconst DEFAULT_LABELS: Required<TimerLabels> = {\n  cancel: 'Cancel timer',\n};\n\nfunction prefersReducedMotion(): boolean {\n  return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\nfunction formatTimeDefault(remainingMs: number) {\n  const totalSeconds = Math.ceil(remainingMs / 1000);\n  const hours = Math.floor(totalSeconds / 3600);\n  const minutes = Math.floor((totalSeconds % 3600) / 60);\n  const seconds = totalSeconds % 60;\n  const mm = String(minutes).padStart(2, '0');\n  const ss = String(seconds).padStart(2, '0');\n  return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nfunction Timer(props: TimerProps) {\n  const {\n    ref,\n    durationSeconds,\n    autoStart = true,\n    resetOnDurationChange = true,\n\n    onTick,\n    onComplete,\n    onStart,\n    onPause,\n    onResume,\n    onCancel,\n    onAddTime,\n    onRemoveTime,\n\n    showControls = true,\n    hideAddButton = false,\n    hideRemoveButton = false,\n    hidePauseButton = false,\n    hideCancelButton = false,\n    adjustSeconds = 30,\n    maxSeconds,\n\n    label,\n    formatTime = formatTimeDefault,\n    size,\n    strokeWidth = 10,\n    counterClockwise = false,\n\n    urgentThreshold = 0.1,\n    urgentMinSeconds = 3,\n    pulseOnUrgent = true,\n    showRunningRipples = false,\n\n    playSoundOnComplete = false,\n    soundUrl,\n    soundVolume = 0.5,\n    notifyOnComplete = false,\n    notificationTitle,\n    notificationBody,\n\n    className,\n    style,\n    classNames,\n    styles: slotStyles,\n    labels,\n    ...rest\n  } = useComponentDefaults('Timer', props);\n  const text = useLabels('Timer', labels, DEFAULT_LABELS);\n\n  const initialMs = durationSeconds * 1000;\n  const [status, setStatusState] = useState<TimerStatus>(autoStart ? 'running' : 'idle');\n  const [remainingMs, setRemainingMsState] = useState(initialMs);\n  const [epoch, setEpoch] = useState(0);\n  const [ripples, setRipples] = useState<number[]>([]);\n\n  const remainingRef = useRef(remainingMs);\n  const statusRef = useRef(status);\n  const totalMsRef = useRef(initialMs);\n  const completedFiredRef = useRef(false);\n  const notifyPermissionRequestedRef = useRef(false);\n  const mountedRef = useRef(false);\n  const rippleIdRef = useRef(0);\n\n  function setRemaining(next: number) {\n    remainingRef.current = next;\n    setRemainingMsState(next);\n  }\n\n  function setStatus(next: TimerStatus) {\n    statusRef.current = next;\n    setStatusState(next);\n  }\n\n  function bumpEpoch() {\n    setEpoch((e) => e + 1);\n  }\n\n  // Ticking effect. Re-derives the remaining time from Date.now() every tick (rather than\n  // accumulating setInterval's own drift), so it stays accurate over long countdowns. Any\n  // external mutation of remainingRef (addTime/removeTime while already running, or a resume)\n  // must bump `epoch` so this effect re-arms and re-captures a fresh start/startRemaining —\n  // without that, a stale `startRemaining` captured before the mutation would silently\n  // overwrite it on the next tick.\n  useEffect(() => {\n    if (status !== 'running') return undefined;\n    const start = Date.now();\n    const startRemaining = remainingRef.current;\n    const id = setInterval(() => {\n      const next = Math.max(0, startRemaining - (Date.now() - start));\n      setRemaining(next);\n      onTick?.(next);\n      if (next <= 0) setStatus('completed');\n    }, TICK_MS);\n    return () => clearInterval(id);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [status, epoch]);\n\n  // Fires onComplete exactly once per completion, plus the opt-in sound/notification.\n  useEffect(() => {\n    if (status === 'completed' && !completedFiredRef.current) {\n      completedFiredRef.current = true;\n      onComplete?.();\n      if (playSoundOnComplete) {\n        try {\n          const audio = new Audio(soundUrl || DEFAULT_CHIME_DATA_URI);\n          audio.volume = soundVolume;\n          // play() can reject (autoplay policy) or, in some environments, return undefined\n          // instead of a Promise — never let a blocked/unsupported playback surface as an error.\n          audio.play()?.catch(() => {});\n        } catch {\n          // Audio unavailable/unsupported — fail silently.\n        }\n      }\n      if (notifyOnComplete && typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n        try {\n          new Notification(notificationTitle ?? 'Timer done', {\n            body: notificationBody ?? (typeof label === 'string' ? label : undefined),\n          });\n        } catch {\n          // Some browsers (e.g. certain mobile Safari versions) throw constructing\n          // Notification outside specific contexts — fail silently, as documented.\n        }\n      }\n    }\n    if (status !== 'completed') completedFiredRef.current = false;\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [status]);\n\n  // durationSeconds prop change: reset (and optionally restart) at the new duration. Skips\n  // the initial mount, since autoStart/initial state already cover that.\n  useEffect(() => {\n    if (!mountedRef.current) {\n      mountedRef.current = true;\n      return;\n    }\n    const nextMs = durationSeconds * 1000;\n    totalMsRef.current = nextMs;\n    setRemaining(nextMs);\n    completedFiredRef.current = false;\n    bumpEpoch();\n    if (resetOnDurationChange) {\n      setStatus(autoStart ? 'running' : 'idle');\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [durationSeconds]);\n\n  // Running-ripple spawner: spawns a new ripple roughly every RIPPLE_SPAWN_INTERVAL_MS while\n  // running, each animating once (via CSS, `forwards`) and removing itself on `onAnimationEnd`.\n  // Pausing (or otherwise leaving `running`) only stops new spawns here — it doesn't touch\n  // `ripples` — so whichever ripples are already mid-flight keep animating to completion\n  // instead of vanishing mid-cycle.\n  useEffect(() => {\n    if (!showRunningRipples || status !== 'running' || prefersReducedMotion()) return undefined;\n    function spawnRipple() {\n      // Read now, not in the updater: two spawns before a render would both see the later id.\n      const rippleId = ++rippleIdRef.current;\n      setRipples((prev) => [...prev, rippleId]);\n    }\n    // A timer, so the cleanup cancels it too: StrictMode's second mount stacked a second ripple.\n    const first = setTimeout(spawnRipple, 0);\n    const id = setInterval(spawnRipple, RIPPLE_SPAWN_INTERVAL_MS);\n    return () => {\n      clearTimeout(first);\n      clearInterval(id);\n    };\n  }, [showRunningRipples, status]);\n\n  function handleRippleAnimationEnd(id: number) {\n    setRipples((prev) => prev.filter((existingId) => existingId !== id));\n  }\n\n  function requestNotificationPermissionIfNeeded() {\n    if (!notifyOnComplete || notifyPermissionRequestedRef.current) return;\n    if (typeof Notification === 'undefined' || Notification.permission !== 'default') return;\n    notifyPermissionRequestedRef.current = true;\n    Notification.requestPermission().catch(() => {});\n  }\n\n  function start() {\n    requestNotificationPermissionIfNeeded();\n    if (statusRef.current === 'completed' || statusRef.current === 'cancelled') {\n      setRemaining(totalMsRef.current);\n      completedFiredRef.current = false;\n    }\n    bumpEpoch();\n    setStatus('running');\n    onStart?.();\n  }\n\n  function pause() {\n    if (statusRef.current !== 'running') return;\n    setStatus('paused');\n    onPause?.();\n  }\n\n  function resume() {\n    if (statusRef.current !== 'paused') return;\n    bumpEpoch();\n    setStatus('running');\n    onResume?.();\n  }\n\n  function addTime(seconds: number) {\n    const capped = maxSeconds != null ? maxSeconds * 1000 : Infinity;\n    const next = Math.min(remainingRef.current + seconds * 1000, capped);\n    setRemaining(next);\n    bumpEpoch();\n    onAddTime?.(seconds, Math.round(next / 1000));\n    if (statusRef.current === 'completed' && next > 0) {\n      completedFiredRef.current = false;\n      setStatus('running');\n    }\n  }\n\n  function removeTime(seconds: number) {\n    const next = Math.max(0, remainingRef.current - seconds * 1000);\n    setRemaining(next);\n    bumpEpoch();\n    onRemoveTime?.(seconds, Math.round(next / 1000));\n    if (next <= 0 && statusRef.current === 'running') setStatus('completed');\n  }\n\n  function cancel() {\n    setRemaining(totalMsRef.current);\n    setStatus('cancelled');\n    onCancel?.();\n  }\n\n  function reset() {\n    setRemaining(totalMsRef.current);\n    completedFiredRef.current = false;\n    setStatus('idle');\n  }\n\n  useImperativeHandle(ref, () => ({\n    start,\n    pause,\n    resume,\n    addTime,\n    removeTime,\n    cancel,\n    reset,\n    getStatus: () => statusRef.current,\n    getRemainingMs: () => remainingRef.current,\n  }));\n\n  const radius = 50 - strokeWidth / 2;\n  const circumference = useMemo(() => 2 * Math.PI * radius, [radius]);\n  const clampedFraction = totalMsRef.current > 0 ? Math.min(1, remainingMs / totalMsRef.current) : 0;\n  const dashOffset = circumference * (1 - clampedFraction);\n  const urgentMs = Math.max(totalMsRef.current * urgentThreshold, urgentMinSeconds * 1000);\n  const isUrgent = status === 'running' && remainingMs <= urgentMs;\n  const isCritical = isUrgent && remainingMs <= Math.min(5000, urgentMs);\n  const isPaused = status === 'paused';\n\n  // The pause button doubles as a play/restart button whenever there's nothing to pause —\n  // idle (autoStart={false}), completed, or cancelled — rather than hiding itself, so there's\n  // always a way to (re)start the countdown from the built-in controls alone.\n  const showAddButton = showControls && !hideAddButton;\n  const showRemoveButton = showControls && !hideRemoveButton;\n  const showPauseButton = showControls && !hidePauseButton;\n  const pauseButtonIcon = status === 'running' ? faPause : faPlay;\n  const pauseButtonTitle =\n    status === 'running' ? 'Pause' : isPaused ? 'Resume' : status === 'idle' ? 'Start' : 'Restart';\n  const handlePauseButtonClick = status === 'running' ? pause : isPaused ? resume : start;\n  const showCancelButton = showControls && !hideCancelButton;\n\n  return (\n    <div\n      {...rest}\n      className={cx(\n        styles.timer,\n        pulseOnUrgent && isUrgent && styles.timerPulsing,\n        isCritical && styles.timerCritical,\n        className,\n        classNames?.root,\n      )}\n      style={\n        {\n          ...(size ? { '--timer-size': size } : null),\n          '--timer-stroke-width': `${strokeWidth}px`,\n          ...style,\n          ...slotStyles?.root,\n        } as React.CSSProperties\n      }\n    >\n      <div className={cx(styles.timerRingWrapper, classNames?.ringWrapper)} style={slotStyles?.ringWrapper}>\n        {ripples.length > 0 && (\n          <div className={cx(styles.timerRipples, classNames?.ripples)} style={slotStyles?.ripples}>\n            {ripples.map((id) => (\n              <span\n                key={id}\n                className={cx(styles.timerRipple, classNames?.ripple)}\n                style={slotStyles?.ripple}\n                onAnimationEnd={() => handleRippleAnimationEnd(id)}\n              />\n            ))}\n          </div>\n        )}\n        <svg className={cx(styles.timerRingSvg, classNames?.ringSvg)} viewBox='0 0 100 100' style={slotStyles?.ringSvg}>\n          <circle\n            className={cx(styles.timerRingTrack, classNames?.ringTrack)}\n            cx='50'\n            cy='50'\n            r={radius}\n            style={slotStyles?.ringTrack}\n          />\n          <circle\n            className={cx(\n              styles.timerRingProgress,\n              isUrgent && styles.timerRingProgressUrgent,\n              classNames?.ringProgress,\n            )}\n            cx='50'\n            cy='50'\n            r={radius}\n            strokeDasharray={circumference}\n            strokeDashoffset={dashOffset}\n            style={{\n              transition: isPaused ? 'none' : undefined,\n              transform: counterClockwise ? 'rotate(-90deg)' : undefined,\n              ...slotStyles?.ringProgress,\n            }}\n          />\n        </svg>\n        <div className={cx(styles.timerDisplay, classNames?.display)} style={slotStyles?.display}>\n          <span className={cx(styles.timerTime, classNames?.time)} style={slotStyles?.time}>\n            {formatTime(remainingMs)}\n          </span>\n          {label && (\n            <span className={cx(styles.timerLabel, classNames?.label)} style={slotStyles?.label}>\n              {label}\n            </span>\n          )}\n        </div>\n      </div>\n\n      {showControls && (\n        <div className={cx(styles.timerControls, classNames?.controls)} style={slotStyles?.controls}>\n          <div className={styles.timerControlsRow}>\n            {showRemoveButton && (\n              <ActionIcon\n                icon={faMinus}\n                title={`Remove ${adjustSeconds}s`}\n                onClick={() => removeTime(adjustSeconds)}\n                className={classNames?.removeButton}\n                style={slotStyles?.removeButton}\n              />\n            )}\n            {showPauseButton && (\n              <Button\n                size={ButtonSize.Small}\n                icon={pauseButtonIcon}\n                title={pauseButtonTitle}\n                onClick={handlePauseButtonClick}\n                className={classNames?.pauseButton}\n                style={slotStyles?.pauseButton}\n              />\n            )}\n            {showAddButton && (\n              <ActionIcon\n                icon={faPlus}\n                title={`Add ${adjustSeconds}s`}\n                onClick={() => addTime(adjustSeconds)}\n                className={classNames?.addButton}\n                style={slotStyles?.addButton}\n              />\n            )}\n          </div>\n          {showCancelButton && (\n            <ActionIcon\n              icon={faXmark}\n              title={text.cancel}\n              onClick={cancel}\n              className={cx(styles.timerCancelButton, classNames?.cancelButton)}\n              style={slotStyles?.cancelButton}\n            />\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport default Timer;\n"],"mappings":"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"}