{"version":3,"file":"useActiveMarkers.mjs","names":[],"sources":["../../../src/hooks/markers/useActiveMarkers.ts"],"sourcesContent":["import { useTimelineSelector } from '#react/hooks/core/useTimelineSelector';\nimport { useTimelinePlayheadTime } from '#react/hooks/playback/useTimelinePlayheadTime';\nimport type { Marker, TimelineReadonly } from '@techsquidtv/canvas-timeline-core';\nimport { compareRational, toSeconds } from '@techsquidtv/canvas-timeline-utils';\nimport { useMemo } from 'react';\n/** Result returned by `useActiveMarkers`. */\nexport interface UseActiveMarkersResult {\n  /** Marker exactly at the playhead, or null when none is active. */\n  activeMarker: TimelineReadonly<Marker> | null;\n  /** Marker nearest to the playhead, or null when no markers exist. */\n  nearestMarker: TimelineReadonly<Marker> | null;\n  /** Next marker after the playhead, or null when none exists. */\n  nextMarker: TimelineReadonly<Marker> | null;\n  /** Previous marker before the playhead, or null when none exists. */\n  previousMarker: TimelineReadonly<Marker> | null;\n}\n\n/**\n * Subscribes to live marker proximity derived from the current playhead.\n *\n * Use this focused live hook for readouts and marker navigation UI that should\n * update during playback or scrubbing. Use `useTimelineMarkers` for ordinary\n * marker lists and marker editing commands.\n *\n * @returns Active, nearest, previous, and next markers for the live playhead time.\n */\nexport function useActiveMarkers(): UseActiveMarkersResult {\n  const state = useTimelineSelector((state) => ({ markers: state.markers }));\n  const playheadTime = useTimelinePlayheadTime();\n  const markers = useMemo(\n    () => [...(state.markers || [])].sort((left, right) => compareRational(left.time, right.time)),\n    [state.markers]\n  );\n\n  return useMemo(() => {\n    const activeMarker =\n      markers.find((marker) => compareRational(marker.time, playheadTime) === 0) ?? null;\n    const previousMarker =\n      [...markers].reverse().find((marker) => compareRational(marker.time, playheadTime) < 0) ??\n      null;\n    const nextMarker =\n      markers.find((marker) => compareRational(marker.time, playheadTime) > 0) ?? null;\n    const nearestMarker =\n      markers.reduce<TimelineReadonly<Marker> | null>((nearest, marker) => {\n        if (!nearest) {\n          return marker;\n        }\n        const markerDistance = Math.abs(toSeconds(marker.time) - toSeconds(playheadTime));\n        const nearestDistance = Math.abs(toSeconds(nearest.time) - toSeconds(playheadTime));\n        return markerDistance < nearestDistance ? marker : nearest;\n      }, null) ?? null;\n\n    return {\n      activeMarker,\n      nearestMarker,\n      nextMarker,\n      previousMarker,\n    };\n  }, [markers, playheadTime]);\n}\n"],"mappings":";;;;;;;;;;;;;;AA0BA,SAAgB,mBAA2C;CACzD,MAAM,QAAQ,qBAAqB,WAAW,EAAE,SAAS,MAAM,QAAQ,EAAE;CACzE,MAAM,eAAe,wBAAwB;CAC7C,MAAM,UAAU,cACR,CAAC,GAAI,MAAM,WAAW,CAAC,CAAE,CAAC,CAAC,MAAM,MAAM,UAAU,gBAAgB,KAAK,MAAM,MAAM,IAAI,CAAC,GAC7F,CAAC,MAAM,OAAO,CAChB;CAEA,OAAO,cAAc;EACnB,MAAM,eACJ,QAAQ,MAAM,WAAW,gBAAgB,OAAO,MAAM,YAAY,MAAM,CAAC,KAAK;EAChF,MAAM,iBACJ,CAAC,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,WAAW,gBAAgB,OAAO,MAAM,YAAY,IAAI,CAAC,KACtF;EACF,MAAM,aACJ,QAAQ,MAAM,WAAW,gBAAgB,OAAO,MAAM,YAAY,IAAI,CAAC,KAAK;EAW9E,OAAO;GACL;GACA,eAXA,QAAQ,QAAyC,SAAS,WAAW;IACnE,IAAI,CAAC,SACH,OAAO;IAIT,OAFuB,KAAK,IAAI,UAAU,OAAO,IAAI,IAAI,UAAU,YAAY,CAE3D,IADI,KAAK,IAAI,UAAU,QAAQ,IAAI,IAAI,UAAU,YAAY,CAC3C,IAAI,SAAS;GACrD,GAAG,IAAI,KAAK;GAKZ;GACA;EACF;CACF,GAAG,CAAC,SAAS,YAAY,CAAC;AAC5B"}