import { DragEvent, DragEventHandler } from "react"; import { RationalTime } from "@techsquidtv/canvas-timeline-utils"; import { TimelineClipGroupPlacement, TimelineCommandFailureReason, TimelineCommandResult, TimelineEditCommitResult, TimelineInteractionGeometry, TimelineReadonly, Track } from "@techsquidtv/canvas-timeline-core"; //#region src/hooks/clips/useTimelineExternalClipDrop.d.ts /** External-drop edit operation selected by app chrome or drop context. */ type TimelineExternalClipDropEditMode = 'insert' | 'overwrite'; /** Metadata applied when an external drop creates a multi-clip group. */ interface TimelineExternalClipDropGroupOptions { /** Optional stable group id. A random id is generated by the engine when omitted. */ groupId?: string; /** Optional visible group label for app chrome. */ label?: string; } /** * Context passed to external clip drop callbacks. * * @remarks * * The context combines app-owned drag data with the resolved timeline target. * Use it to build clip placements from a media bin, asset browser, file picker, * or generated content panel. Times are already converted from pointer position * into {@link RationalTime} so placement factories do not need to duplicate * timeline geometry math. * * @template DragData - App-owned payload resolved from the native drag event. * surface. */ interface TimelineExternalClipDropContext { /** App-owned drag payload resolved from the native drag event. */ data: DragData; /** Native React drag event for advanced app integrations. */ event: DragEvent; /** Native browser data transfer payload. */ dataTransfer: DataTransfer; /** Track currently under the pointer. */ targetTrack: TimelineReadonly; /** Zero-based index of the target track. */ targetTrackIndex: number; /** Timeline time under the pointer. */ dropTime: RationalTime; /** Timeline seconds under the pointer. */ dropSeconds: number; /** Horizontal pointer position inside the drop surface. */ viewportX: number; /** Vertical pointer position inside the drop surface. */ viewportY: number; /** Edit operation selected for this drop. */ editMode: TimelineExternalClipDropEditMode; } /** Result of an app-owned external drop guard. */ interface TimelineExternalClipDropGuardResult { /** Whether this payload can drop on the resolved target. */ canDrop: boolean; /** Machine-readable failure reason when rejected. */ reason?: TimelineCommandFailureReason; /** Optional human-readable failure detail. */ message?: string; } /** * Custom policy for accepting or rejecting an external drop target. * * @template DragData - App-owned payload resolved from the native drag event. */ type TimelineExternalClipDropGuard = (context: TimelineExternalClipDropContext) => boolean | TimelineExternalClipDropGuardResult; /** * Props spread onto the timeline element that receives native external drops. * * @remarks * * Spread these onto the same viewport element whose bounds should define * pointer-to-time and pointer-to-track hit testing. The hook handles native drag * events; applications provide payload parsing and placement creation. */ interface TimelineExternalClipDropRootProps { /** Registers a native drag entering the timeline drop surface. */ onDragEnter: DragEventHandler; /** Updates target track, drop time, validity, and browser drop feedback. */ onDragOver: DragEventHandler; /** Clears transient hover feedback when the drag leaves the drop surface. */ onDragLeave: DragEventHandler; /** Commits the resolved insert or overwrite edit for the app-owned payload. */ onDrop: DragEventHandler; } /** * Options accepted by `useTimelineExternalClipDrop`. * * @remarks * * `resolveDragData` converts a browser drag event into app data. `createPlacements` * turns that data into one or more timeline clip placements. The hook resolves * target track, drop time, snapping, edit mode, grouped drops, and command * results around those app callbacks. * * @template DragData - App-owned payload resolved from the native drag event. * * @see {@link TimelineExternalClipDropContext} * @see {@link https://canvastimeline.com/demos/external-clip-drop | External clip drop demo} */ interface UseTimelineExternalClipDropOptions extends TimelineInteractionGeometry { /** Optional viewport width used for track hit testing. Defaults to the drop surface width. */ viewportWidth?: number; /** Edit mode for committed drops. Defaults to overwrite. */ editMode?: TimelineExternalClipDropEditMode | ((context: Omit, 'editMode'>) => TimelineExternalClipDropEditMode); /** Resolves app-owned drag data from the native drag event. */ resolveDragData: (event: DragEvent) => DragData | null; /** Creates one or more clip placements from the resolved drop context. */ createPlacements: (context: TimelineExternalClipDropContext) => readonly TimelineClipGroupPlacement[] | null; /** Optional app policy for rejecting target tracks before placement creation. */ canDropOnTrack?: TimelineExternalClipDropGuard; /** Optional metadata applied when a drop creates a grouped multi-placement edit. */ group?: TimelineExternalClipDropGroupOptions | ((context: TimelineExternalClipDropContext) => TimelineExternalClipDropGroupOptions | null | undefined); /** Whether to resolve magnetic snapping for placed clips. Multi-placement drops share one group delta. Defaults to true. */ snap?: boolean; } /** * Result returned by `useTimelineExternalClipDrop`. * * @remarks * * Use `rootProps` on the drop surface, then render the feedback fields in * timeline chrome such as target-row highlighting, invalid-drop messages, or a * preview badge. `lastResult` keeps the last command outcome available after * hover feedback clears. * * target track. */ interface UseTimelineExternalClipDropResult { /** Props for the element that should accept native external drops. */ rootProps: TimelineExternalClipDropRootProps; /** Whether an external drag is currently over the drop surface. */ dragging: boolean; /** Track currently under the pointer, including invalid targets. */ hoveredTrackId: string | null; /** Valid target track id currently accepting the payload. */ targetTrackId: string | null; /** Valid target track currently accepting the payload. */ targetTrack: TimelineReadonly | null; /** Timeline time under the pointer, when a track is resolved. */ dropTime: RationalTime | null; /** Timeline seconds under the pointer, when a track is resolved. */ dropSeconds: number | null; /** Whether the current external payload can be dropped. */ valid: boolean; /** Machine-readable reason for invalid feedback. */ reason: TimelineCommandFailureReason | null; /** Last committed or rejected drop result. */ lastResult: TimelineCommandResult | null; /** Clears current hover feedback while preserving the last result. */ clearDropFeedback: () => void; } /** * Adds native browser drag-and-drop support for app-owned clip data. * * @remarks * * The hook owns browser event handling, track/time resolution, and local * feedback state. Apps own payload parsing and clip placement factories; the * engine owns validation, policy, history, grouped edits, and undo/redo. * * @param options - Drop geometry, app payload callbacks, edit mode, and optional policy. * @returns Root props, feedback state, and the last drop command result. * @template DragData - App-owned payload resolved from the native drag event. * * @example * ```tsx * import { addRational, fromSeconds } from '@techsquidtv/canvas-timeline-utils'; * import { useTimelineExternalClipDrop } from '@techsquidtv/canvas-timeline-react'; * * interface MediaAsset { * id: string; * durationSeconds: number; * } * * export function AssetDropSurface() { * const drop = useTimelineExternalClipDrop({ * resolveDragData: (event) => { * const id = event.dataTransfer.getData('text/plain'); * return id ? { id, durationSeconds: 5 } : null; * }, * createPlacements: ({ data, dropTime, targetTrack }) => { * const duration = fromSeconds(data.durationSeconds, dropTime.r); * * return [ * { * trackId: targetTrack.id, * clip: { * id: `clip-${data.id}`, * sourceId: data.id, * timelineStart: dropTime, * timelineEnd: addRational(dropTime, duration), * sourceStart: fromSeconds(0, dropTime.r), * sourceEnd: duration, * }, * }, * ]; * }, * }); * * return
{drop.valid ? 'Drop media' : 'Drag media here'}
; * } * ``` * * @see {@link TimelineExternalClipDropContext} * @see {@link useTimelineClipDropFeedback} * @see {@link https://canvastimeline.com/docs/tracks-and-clips | Tracks and clips} */ declare function useTimelineExternalClipDrop(options: UseTimelineExternalClipDropOptions): UseTimelineExternalClipDropResult; //#endregion export { TimelineExternalClipDropContext, TimelineExternalClipDropEditMode, TimelineExternalClipDropGroupOptions, TimelineExternalClipDropGuard, TimelineExternalClipDropGuardResult, TimelineExternalClipDropRootProps, UseTimelineExternalClipDropOptions, UseTimelineExternalClipDropResult, useTimelineExternalClipDrop }; //# sourceMappingURL=useTimelineExternalClipDrop.d.mts.map