{"version":3,"file":"PlayheadGrabber.mjs","names":[],"sources":["../../../src/components/playhead/PlayheadGrabber.tsx"],"sourcesContent":["import { consumeTimelineDoubleTap } from '#react/components/interactions/tapState';\nimport { TimeGrabber } from '#react/components/playhead/TimeGrabber';\nimport type { TimeGrabberChildren, TimeGrabberProps } from '#react/components/playhead/TimeGrabber';\nimport { useTimelineEngine } from '#react/hooks/core/useTimelineEngine';\nimport type { TimelineEngine } from '@techsquidtv/canvas-timeline-core';\nimport { toSeconds } from '@techsquidtv/canvas-timeline-utils';\nimport type { RationalTime } from '@techsquidtv/canvas-timeline-utils';\nimport React from 'react';\nconst PLAYHEAD_PART_CLASS_NAMES: TimeGrabberProps['partClassNames'] = {\n  highlight: 'timeline-playhead-grabber-highlight',\n  line: 'timeline-playhead-grabber-line',\n  handle: 'timeline-playhead-grabber-handle',\n};\n\nconst PLAYHEAD_POSITION_EVENTS: TimeGrabberProps['positionEvents'] = ['render', 'playhead:scrub'];\n\n/**\n * Props for the draggable playhead handle.\n */\nexport interface PlayheadGrabberProps {\n  /** Additional class names applied to the draggable playhead handle. */\n  className?: string;\n  /** Custom handler for double-click or double-tap marker behavior at the playhead. */\n  onDoubleClick?: (time: RationalTime, engine: TimelineEngine, e: React.PointerEvent) => void;\n  /** Custom composable children node or render prop function. */\n  children?: TimeGrabberChildren;\n}\n\nexport const PlayheadGrabber = React.forwardRef<\n  HTMLDivElement,\n  PlayheadGrabberProps & Omit<React.HTMLAttributes<HTMLDivElement>, 'onDoubleClick' | 'children'>\n>(\n  (\n    {\n      className = '',\n      onDoubleClick,\n      children,\n      onDragEnd: _onDragEnd,\n      onDragStart: _onDragStart,\n      onPointerDown,\n      ...props\n    },\n    forwardedRef\n  ) => {\n    const engine = useTimelineEngine();\n\n    const triggerDoubleClick = React.useCallback(\n      (e: React.PointerEvent) => {\n        if (onDoubleClick) {\n          onDoubleClick(engine.playheadTime, engine, e);\n        } else {\n          const clickRadiusSec = 10 / engine.zoomScale;\n          const clickedMarker = engine.markers.find(\n            (m) => Math.abs(toSeconds(m.time) - toSeconds(engine.playheadTime)) <= clickRadiusSec\n          );\n\n          if (clickedMarker) {\n            engine.removeMarker(clickedMarker.id);\n          } else {\n            const label = `M${engine.markers.length + 1}`;\n            engine.addMarker(engine.playheadTime, label);\n          }\n        }\n      },\n      [engine, onDoubleClick]\n    );\n\n    const getPlayheadTime = React.useCallback(() => engine.playheadTime, [engine]);\n\n    const handleDragTimeChange = React.useCallback(\n      (time: RationalTime) => {\n        engine.updatePlayhead(time);\n      },\n      [engine]\n    );\n\n    const handleDragStart = React.useCallback(() => {\n      engine.pause();\n    }, [engine]);\n\n    const handlePointerDown = React.useCallback(\n      (e: React.PointerEvent<HTMLDivElement>) => {\n        onPointerDown?.(e);\n        if (e.defaultPrevented) {\n          return;\n        }\n        if (e.pointerType !== 'touch' && e.button !== 0) {\n          return;\n        }\n        e.stopPropagation();\n\n        if (consumeTimelineDoubleTap(e)) {\n          triggerDoubleClick(e);\n          e.preventDefault();\n          return;\n        }\n      },\n      [onPointerDown, triggerDoubleClick]\n    );\n\n    return (\n      <TimeGrabber\n        ref={forwardedRef}\n        className={['timeline-playhead-grabber', className].filter(Boolean).join(' ')}\n        engine={engine}\n        getTime={getPlayheadTime}\n        onDragStart={handleDragStart}\n        onDragTimeChange={handleDragTimeChange}\n        onPointerDown={handlePointerDown}\n        partClassNames={PLAYHEAD_PART_CLASS_NAMES}\n        positionEvents={PLAYHEAD_POSITION_EVENTS}\n        time={engine.playheadTime}\n        {...props}\n      >\n        {children}\n      </TimeGrabber>\n    );\n  }\n);\n\nPlayheadGrabber.displayName = 'Timeline.PlayheadGrabber';\n"],"mappings":";;;;;;;AAQA,MAAM,4BAAgE;CACpE,WAAW;CACX,MAAM;CACN,QAAQ;AACV;AAEA,MAAM,2BAA+D,CAAC,UAAU,gBAAgB;AAchG,MAAa,kBAAkB,MAAM,YAKjC,EACE,YAAY,IACZ,eACA,UACA,WAAW,YACX,aAAa,cACb,eACA,GAAG,SAEL,iBACG;CACH,MAAM,SAAS,kBAAkB;CAEjC,MAAM,qBAAqB,MAAM,aAC9B,MAA0B;EACzB,IAAI,eACF,cAAc,OAAO,cAAc,QAAQ,CAAC;OACvC;GACL,MAAM,iBAAiB,KAAK,OAAO;GACnC,MAAM,gBAAgB,OAAO,QAAQ,MAClC,MAAM,KAAK,IAAI,UAAU,EAAE,IAAI,IAAI,UAAU,OAAO,YAAY,CAAC,KAAK,cACzE;GAEA,IAAI,eACF,OAAO,aAAa,cAAc,EAAE;QAC/B;IACL,MAAM,QAAQ,IAAI,OAAO,QAAQ,SAAS;IAC1C,OAAO,UAAU,OAAO,cAAc,KAAK;GAC7C;EACF;CACF,GACA,CAAC,QAAQ,aAAa,CACxB;CAEA,MAAM,kBAAkB,MAAM,kBAAkB,OAAO,cAAc,CAAC,MAAM,CAAC;CAE7E,MAAM,uBAAuB,MAAM,aAChC,SAAuB;EACtB,OAAO,eAAe,IAAI;CAC5B,GACA,CAAC,MAAM,CACT;CAEA,MAAM,kBAAkB,MAAM,kBAAkB;EAC9C,OAAO,MAAM;CACf,GAAG,CAAC,MAAM,CAAC;CAEX,MAAM,oBAAoB,MAAM,aAC7B,MAA0C;EACzC,gBAAgB,CAAC;EACjB,IAAI,EAAE,kBACJ;EAEF,IAAI,EAAE,gBAAgB,WAAW,EAAE,WAAW,GAC5C;EAEF,EAAE,gBAAgB;EAElB,IAAI,yBAAyB,CAAC,GAAG;GAC/B,mBAAmB,CAAC;GACpB,EAAE,eAAe;GACjB;EACF;CACF,GACA,CAAC,eAAe,kBAAkB,CACpC;CAEA,OACE,oBAAC,aAAD;EACE,KAAK;EACL,WAAW,CAAC,6BAA6B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACpE;EACR,SAAS;EACT,aAAa;EACb,kBAAkB;EAClB,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB,MAAM,OAAO;EACb,GAAI;EAEH;CACU,CAAA;AAEjB,CACF;AAEA,gBAAgB,cAAc"}