{"version":3,"file":"useTimelineSnapping.mjs","names":[],"sources":["../../../src/hooks/editing/useTimelineSnapping.ts"],"sourcesContent":["import { runTimelineCommand } from '#react/hooks/core/runTimelineCommand';\nimport { timelineCommandOk } from '@techsquidtv/canvas-timeline-core';\nimport type {\n  TimelineCommandResult,\n  TimelineReadonly,\n  SnapPreparationOptions,\n  TimelineSnapFeedback,\n  TimelineSnapResult,\n  TimelineSnapTarget,\n} from '@techsquidtv/canvas-timeline-core';\nimport { useTimelineEngine } from '#react/hooks/core/useTimelineEngine';\nimport { useTimelineSelector } from '#react/hooks/core/useTimelineSelector';\nimport type { RationalTime } from '@techsquidtv/canvas-timeline-utils';\nimport { useCallback, useMemo } from 'react';\n/** Result returned by `useTimelineSnapping`. */\nexport interface UseTimelineSnappingResult {\n  /** Whether magnetic snapping is enabled. */\n  enabled: boolean;\n  /** Magnetic snap radius in screen pixels. */\n  thresholdPixels: number;\n  /** Current transient snap feedback for canvas guides and UI status. */\n  feedback: TimelineReadonly<TimelineSnapFeedback>;\n  /** Currently active snap target, or null when nothing is snapped. */\n  activeTarget: TimelineSnapTarget | null;\n  /** Enables or disables magnetic snapping. */\n  setEnabled: (enabled: boolean) => TimelineCommandResult;\n  /** Sets the magnetic snap radius in screen pixels. */\n  setThresholdPixels: (thresholdPixels: number) => TimelineCommandResult;\n  /** Prepares snap targets for an upcoming interaction. */\n  prepareSnapping: (options?: string | SnapPreparationOptions) => TimelineCommandResult;\n  /** Resolves a candidate time against the prepared snap target index. */\n  resolveSnap: (time: RationalTime, publishFeedback?: boolean) => TimelineSnapResult | null;\n  /** Finalizes an interaction and clears transient snap feedback. */\n  settle: () => TimelineCommandResult;\n}\n\n/**\n * Provides the canonical snapping state and commands for editor UI.\n *\n * @returns Snap settings, active feedback, and commands for preparing/resolving snap targets.\n */\nexport function useTimelineSnapping(): UseTimelineSnappingResult {\n  const engine = useTimelineEngine();\n  const state = useTimelineSelector((state) => ({\n    snapEnabled: state.snapEnabled,\n    snapFeedback: state.snapFeedback,\n    snapThresholdPixels: state.snapThresholdPixels,\n  }));\n\n  const setEnabled = useCallback(\n    (enabled: boolean) =>\n      runTimelineCommand(() => {\n        engine.setSnappingEnabled(enabled);\n        return timelineCommandOk();\n      }),\n    [engine]\n  );\n\n  const setThresholdPixels = useCallback(\n    (thresholdPixels: number) =>\n      runTimelineCommand(() => {\n        engine.setSnapThresholdPixels(thresholdPixels);\n        return timelineCommandOk();\n      }),\n    [engine]\n  );\n\n  const prepareSnapping = useCallback(\n    (options?: string | SnapPreparationOptions) =>\n      runTimelineCommand(() => {\n        engine.prepareSnapping(options);\n        return timelineCommandOk();\n      }),\n    [engine]\n  );\n\n  const resolveSnap = useCallback(\n    (time: RationalTime, publishFeedback?: boolean) => engine.resolveSnap(time, publishFeedback),\n    [engine]\n  );\n\n  const settle = useCallback(\n    () =>\n      runTimelineCommand(() => {\n        engine.settle();\n        return timelineCommandOk();\n      }),\n    [engine]\n  );\n\n  return useMemo(\n    () => ({\n      enabled: state.snapEnabled,\n      thresholdPixels: state.snapThresholdPixels,\n      feedback: state.snapFeedback,\n      activeTarget: state.snapFeedback.target,\n      setEnabled,\n      setThresholdPixels,\n      prepareSnapping,\n      resolveSnap,\n      settle,\n    }),\n    [\n      prepareSnapping,\n      resolveSnap,\n      setEnabled,\n      setThresholdPixels,\n      settle,\n      state.snapEnabled,\n      state.snapFeedback,\n      state.snapThresholdPixels,\n    ]\n  );\n}\n"],"mappings":";;;;;;;;;;;AAyCA,SAAgB,sBAAiD;CAC/D,MAAM,SAAS,kBAAkB;CACjC,MAAM,QAAQ,qBAAqB,WAAW;EAC5C,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,qBAAqB,MAAM;CAC7B,EAAE;CAEF,MAAM,aAAa,aAChB,YACC,yBAAyB;EACvB,OAAO,mBAAmB,OAAO;EACjC,OAAO,kBAAkB;CAC3B,CAAC,GACH,CAAC,MAAM,CACT;CAEA,MAAM,qBAAqB,aACxB,oBACC,yBAAyB;EACvB,OAAO,uBAAuB,eAAe;EAC7C,OAAO,kBAAkB;CAC3B,CAAC,GACH,CAAC,MAAM,CACT;CAEA,MAAM,kBAAkB,aACrB,YACC,yBAAyB;EACvB,OAAO,gBAAgB,OAAO;EAC9B,OAAO,kBAAkB;CAC3B,CAAC,GACH,CAAC,MAAM,CACT;CAEA,MAAM,cAAc,aACjB,MAAoB,oBAA8B,OAAO,YAAY,MAAM,eAAe,GAC3F,CAAC,MAAM,CACT;CAEA,MAAM,SAAS,kBAEX,yBAAyB;EACvB,OAAO,OAAO;EACd,OAAO,kBAAkB;CAC3B,CAAC,GACH,CAAC,MAAM,CACT;CAEA,OAAO,eACE;EACL,SAAS,MAAM;EACf,iBAAiB,MAAM;EACvB,UAAU,MAAM;EAChB,cAAc,MAAM,aAAa;EACjC;EACA;EACA;EACA;EACA;CACF,IACA;EACE;EACA;EACA;EACA;EACA;EACA,MAAM;EACN,MAAM;EACN,MAAM;CACR,CACF;AACF"}