@pixerate/editor-react 0.57.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/video-editor/useVideoEditor.ts","../../src/video-editor/VideoPreview.tsx","../../src/video-editor/VideoScopes.tsx","../../src/video-editor/VideoTransport.tsx","../../src/video-editor/VideoTimeline.tsx","../../src/video-editor/ClipInspector.tsx","../../src/video-editor/MediaBin.tsx","../../src/video-editor/TranscriptPanel.tsx","../../src/video-editor/VideoEditor.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VideoEditorController,\n createVideoEditorToolProvider,\n type VideoEditResult,\n type VideoEditorOptions,\n type VideoEditorState,\n type VideoEditorToolProviderOptions,\n} from '@pixerate/editor/video-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** A `VideoEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVideoEditorController(options: VideoEditorOptions = {}): VideoEditorController {\n const ref = useRef<VideoEditorController | null>(null);\n if (!ref.current) ref.current = new VideoEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useVideoEditorState(controller: VideoEditorController): VideoEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVideoEditorResult {\n controller: VideoEditorController;\n state: VideoEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n /** Moves the playhead (ms). */\n seek: (time: number) => void;\n /** Moves the playhead by whole frames (negative steps back), pausing. */\n step: (frames: number) => void;\n undo: () => void;\n redo: () => void;\n /** Splits the selected clips (or every clip) under the playhead, as one undo step. */\n splitAtPlayhead: () => VideoEditResult;\n /** Deletes the selected clips; `ripple` closes the gaps they leave. */\n deleteSelection: (options?: { ripple?: boolean }) => VideoEditResult;\n}\n\n/**\n * Subscribes to a video editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useVideoEditor(controllerOrOptions: VideoEditorController | VideoEditorOptions = {}): UseVideoEditorResult {\n const own = useRef<VideoEditorController | null>(null);\n let controller: VideoEditorController;\n if (controllerOrOptions instanceof VideoEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VideoEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useVideoEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n step: (frames: number) => controller.step(frames),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n splitAtPlayhead: () => controller.splitAtPlayhead(),\n deleteSelection: (options?: { ripple?: boolean }) => controller.deleteSelection(options),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the video editor's agent tools (`get_video_project`, `add_video_clip`,\n * `trim_video_clip`, …) in `registry` while mounted.\n */\nexport function useVideoEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: VideoEditorController,\n options: VideoEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVideoEditorToolProvider(controller, { id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout }));\n }, [registry, controller, id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout]);\n}\n","import React, { useEffect, useRef } from 'react';\nimport { VideoPreviewEngine, type VideoEditorController, type VideoPreviewOptions } from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoPreviewProps {\n controller: VideoEditorController;\n /** Canvas pixels per frame pixel (default: fits the displayed width at the device pixel ratio, at most 1). */\n resolution?: number;\n /** Called after each frame is drawn. */\n onFrame?: VideoPreviewOptions['onFrame'];\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Plays the controller's project on a canvas the shape of its frame: a `VideoPreviewEngine` keeps\n * one `<video>` / `<audio>` element per playing clip in step with the playhead and draws each frame.\n * The engine is created when the canvas mounts and destroyed on unmount or when the controller changes.\n */\nexport function VideoPreview({ controller, resolution, onFrame, className = '', style }: VideoPreviewProps) {\n const { project } = useVideoEditorState(controller);\n const canvas = useRef<HTMLCanvasElement>(null);\n const frameRef = useRef(onFrame);\n frameRef.current = onFrame;\n useEffect(() => {\n const el = canvas.current;\n if (!el) return;\n const engine = new VideoPreviewEngine(controller, el, { resolution, onFrame: (frame) => frameRef.current?.(frame) });\n return () => engine.destroy();\n }, [controller, resolution]);\n return (\n <canvas\n ref={canvas}\n className={className}\n style={{ display: 'block', width: '100%', aspectRatio: `${project.width} / ${project.height}`, background: project.background ?? '#000', ...style }}\n role=\"img\"\n aria-label={`Preview of ${project.name ?? 'the video'}`}\n data-video-preview=\"\"\n />\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { readVideoScopesPanel, VIDEO_SCOPE_KINDS, type VideoEditorController, type VideoScopeKind, type VideoScopesPanelReading } from '@pixerate/editor/video-editor';\n\nexport interface VideoScopesProps {\n controller: VideoEditorController;\n /** Which scopes to show, in order (default histogram, waveform and vectorscope). */\n scopes?: readonly VideoScopeKind[];\n /** Size of the histogram and waveform in pixels (default 256 × 128); the vectorscope is square, `height` a side. */\n width?: number;\n height?: number;\n className?: string;\n}\n\nconst LABELS: Record<VideoScopeKind, string> = { histogram: 'Histogram', waveform: 'Luma waveform', vectorscope: 'Vectorscope' };\nconst pct = (v: number) => `${Math.round(v * 1000) / 10}%`;\n\n/**\n * Colour scopes of what the controller's `<VideoPreview>` draws: a histogram, a luma waveform and a\n * vectorscope, redrawn after each frame, with exposure and clipping figures and notes. Reads the\n * preview through `controller.previewPixels`, so it needs a preview of the same controller.\n */\nexport function VideoScopes({ controller, scopes = VIDEO_SCOPE_KINDS, width = 256, height = 128, className = '' }: VideoScopesProps) {\n const canvases = useRef<Partial<Record<VideoScopeKind, HTMLCanvasElement | null>>>({});\n const [reading, setReading] = useState<VideoScopesPanelReading>(() => ({ ok: false, message: 'Show the preview to see its scopes.' }));\n const key = scopes.join(',');\n useEffect(() => {\n const feed = controller.previewPixels;\n let frame = 0;\n const raf = typeof requestAnimationFrame === 'function' ? requestAnimationFrame : (fn: () => void) => setTimeout(fn, 16) as unknown as number;\n const caf = typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame : (id: number) => clearTimeout(id);\n const draw = () => {\n frame = 0;\n const next = readVideoScopesPanel(feed, scopes, { width, height });\n setReading(next);\n if (!next.ok) return;\n for (const kind of scopes) {\n const img = next.images[kind];\n const ctx = canvases.current[kind]?.getContext('2d');\n if (img && ctx && typeof ImageData !== 'undefined') ctx.putImageData(new ImageData(img.data, img.width, img.height), 0, 0);\n }\n };\n // At most one reading a frame, however often the preview draws.\n const schedule = () => {\n if (!frame) frame = raf(draw);\n };\n schedule();\n const off = feed.subscribe(schedule);\n return () => {\n off();\n if (frame) caf(frame);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [controller, key, width, height]);\n\n return (\n <div className={`flex flex-col gap-2 text-xs ${className}`} data-video-scopes=\"\">\n <div className=\"flex flex-wrap gap-2\">\n {scopes.map((kind) => {\n const w = kind === 'vectorscope' ? height : width;\n return (\n <figure key={kind} className=\"m-0 flex min-w-0 max-w-full flex-col gap-1\">\n <canvas ref={(el) => void (canvases.current[kind] = el)} width={w} height={height} className=\"rounded border border-border bg-black\" style={{ width: w, maxWidth: '100%', height: 'auto', aspectRatio: `${w} / ${height}` }} aria-label={LABELS[kind]} data-scope={kind} />\n <figcaption className=\"text-[11px] text-muted-foreground\">{LABELS[kind]}</figcaption>\n </figure>\n );\n })}\n </div>\n {reading.ok ? (\n <div className=\"flex flex-col gap-0.5\" data-scope-stats=\"\">\n <div className=\"tabular-nums\">\n Luma {reading.stats.luma.mean.toFixed(2)} mean · {reading.stats.luma.p1.toFixed(2)}–{reading.stats.luma.p99.toFixed(2)} · crushed {pct(reading.stats.clipped.shadows)} · blown {pct(reading.stats.clipped.highlights)} · average{' '}\n <span className=\"inline-block h-2.5 w-2.5 rounded-sm align-middle\" style={{ background: reading.stats.average }} /> {reading.stats.average}\n {!reading.complete && <span className=\"text-muted-foreground\"> · loading</span>}\n </div>\n {reading.notes.map((n) => (\n <div key={n} className=\"text-amber-500\">\n {n}\n </div>\n ))}\n </div>\n ) : (\n <div className=\"text-muted-foreground\" data-scope-message=\"\">\n {reading.message}\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport { formatVideoTimecode, type VideoEditorController } from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoTransportProps {\n controller: VideoEditorController;\n /** Show the editing buttons (split, delete, ripple delete, undo, redo; default true). */\n editable?: boolean;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * Play / pause, a frame back and forward, the playhead and total length as timecode, and the\n * edits that work on the playhead and the selection: split, delete, ripple delete, undo and redo.\n */\nexport function VideoTransport({ controller, editable = true, className = '' }: VideoTransportProps) {\n const state = useVideoEditorState(controller);\n const { time, duration, playing, project, selection, readOnly } = state;\n const canEdit = editable && !readOnly;\n return (\n <div className={`flex flex-wrap items-center gap-1.5 text-xs ${className}`} data-video-transport=\"\">\n <button type=\"button\" className={btn} onClick={() => controller.step(-1)} aria-label=\"Previous frame\" title=\"Previous frame (←)\" data-step-back=\"\">\n ◀|\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} title=\"Play / pause (Space)\" disabled={duration <= 0} data-play=\"\">\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.step(1)} aria-label=\"Next frame\" title=\"Next frame (→)\" data-step-forward=\"\">\n |▶\n </button>\n <span className=\"px-1 tabular-nums text-muted-foreground\" data-timecode=\"\">\n {formatVideoTimecode(time, project.fps)} / {formatVideoTimecode(duration, project.fps)}\n </span>\n {editable && (\n <>\n <span className=\"mx-1 h-4 w-px bg-border\" />\n <button type=\"button\" className={btn} onClick={() => controller.splitAtPlayhead()} disabled={!canEdit} title=\"Split at the playhead (S)\" data-split=\"\">\n Split\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.deleteSelection()} disabled={!canEdit || !selection.length} title=\"Delete the selected clips (Delete)\" data-delete=\"\">\n Delete\n </button>\n <button\n type=\"button\"\n className={btn}\n onClick={() => controller.deleteSelection({ ripple: true })}\n disabled={!canEdit || !selection.length}\n title=\"Delete the selected clips and close the gaps (Shift+Delete)\"\n data-ripple-delete=\"\"\n >\n Ripple delete\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!canEdit || !state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!canEdit || !state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n </>\n )}\n </div>\n );\n}\n","import React, { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport {\n planVideoClipDrag,\n videoDragLabel,\n videoAssetMap,\n videoClipLabel,\n videoClipShowsWaveform,\n videoClipWaveformPath,\n videoClipTint,\n videoDropTracks,\n videoRulerTicks,\n formatVideoSeconds,\n type VideoClip,\n type VideoClipDragMode,\n type VideoAsset,\n type VideoClipDragPlan,\n type VideoMediaClip,\n type VideoEditorController,\n type VideoTrack,\n type VideoWaveformMode,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoTimelineProps {\n controller: VideoEditorController;\n /** Zoom: pixels per second of timeline. With `onPxPerSecondChange` the host owns it; otherwise it is the starting zoom (default 100). */\n pxPerSecond?: number;\n /** Called when the zoom control changes. Without it the timeline keeps its own zoom and shows a zoom slider. */\n onPxPerSecondChange?: (pxPerSecond: number) => void;\n /** Allow selecting, dragging, trimming and the track toggles (default true). */\n editable?: boolean;\n /** Draw waveforms in audio clips (default), in every clip with sound (`all`), or not at all. Sound is decoded once per asset through `controller.audioPeaks`. */\n waveforms?: VideoWaveformMode;\n className?: string;\n}\n\nconst HEADER = 150;\nconst RULER = 24;\nconst ROW = 44;\nconst HANDLE = 6;\nconst DRAG_THRESHOLD = 3;\nconst MIN_ZOOM = 10;\nconst MAX_ZOOM = 400;\n\ninterface Drag {\n clip: string;\n mode: VideoClipDragMode;\n x: number;\n pointer: number;\n moved: boolean;\n plan: VideoClipDragPlan | null;\n}\n\n/** A clip's sound drawn behind its label, once its asset's peaks have loaded. */\nfunction ClipWaveform({ controller, clip, asset, width, height }: { controller: VideoEditorController; clip: VideoMediaClip; asset: VideoAsset; width: number; height: number }) {\n const peaks = useSyncExternalStore(\n (notify) => controller.audioPeaks.subscribe(notify),\n () => controller.audioPeaks.peek(asset),\n () => undefined,\n );\n useEffect(() => {\n controller.audioPeaks.load(asset).catch(() => {});\n }, [controller, asset]);\n const d = useMemo(() => (peaks ? videoClipWaveformPath(clip, peaks, width, height) : ''), [peaks, clip, width, height]);\n if (!d) return null;\n return (\n <svg className=\"pointer-events-none absolute inset-0\" width={width} height={height} aria-hidden=\"true\" data-waveform={clip.id}>\n <path d={d} fill=\"currentColor\" fillOpacity={0.45} />\n </svg>\n );\n}\n\nconst isField = (el: EventTarget | null) => el instanceof HTMLElement && /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName);\n\n/**\n * The tracks of a `VideoEditorController` laid out in time: a ruler with markers (click or drag it\n * to scrub), a playhead, and one row per track with its toggles (mute, hide, lock) and its clips.\n * Click a clip to select it (Shift / Cmd to add or remove it), drag it to move it (onto another\n * track of the same kind too; hold Alt to insert, pushing later material along on every sync-locked\n * track, or Shift to overwrite what is underneath), drag an edge to trim it (Alt to ripple). Moves snap to clip edges,\n * markers, the playhead and frames. Every edit is one undo step; refused edits show why.\n *\n * Keyboard (when focused): Space plays, ←/→ step a frame, S splits at the playhead, Delete removes\n * the selection (Shift to ripple), Cmd/Ctrl+Z undoes, Shift+Cmd/Ctrl+Z redoes.\n */\nexport function VideoTimeline({ controller, pxPerSecond, onPxPerSecondChange, editable = true, waveforms = 'audio', className = '' }: VideoTimelineProps) {\n const state = useVideoEditorState(controller);\n const { project, duration, time, selection, readOnly, error } = state;\n const [ownZoom, setOwnZoom] = useState(pxPerSecond ?? 100);\n const px = onPxPerSecondChange ? (pxPerSecond ?? 100) : ownZoom;\n const canEdit = editable && !readOnly;\n const [drag, setDrag] = useState<Drag | null>(null);\n const dragRef = useRef<Drag | null>(null);\n const rows = useRef(new Map<string, HTMLDivElement>());\n const ruler = useRef<HTMLDivElement>(null);\n const assets = videoAssetMap(project);\n const msToPx = (ms: number) => (ms * px) / 1000;\n const span = Math.max(duration + 5000, 10000);\n const width = msToPx(span);\n const ticks = videoRulerTicks(span, px, project.fps);\n\n const seekAt = (clientX: number) => {\n const box = ruler.current!.getBoundingClientRect();\n controller.seek(Math.max(0, ((clientX - box.left) * 1000) / px));\n };\n\n const trackAt = (clipId: string, clientY: number): string | undefined => {\n const allowed = videoDropTracks(project, clipId);\n for (const [id, el] of rows.current) {\n const box = el.getBoundingClientRect();\n if (clientY >= box.top && clientY < box.bottom && allowed.includes(id)) return id;\n }\n return undefined;\n };\n\n const planFor = (d: Drag, e: { clientX: number; clientY: number; altKey: boolean; shiftKey: boolean }) =>\n planVideoClipDrag(project, {\n clip: d.clip,\n mode: d.mode,\n delta: ((e.clientX - d.x) * 1000) / px,\n track: d.mode === 'move' ? trackAt(d.clip, e.clientY) : undefined,\n ripple: e.altKey,\n placement: e.altKey ? 'insert' : e.shiftKey ? 'overwrite' : 'refuse',\n snap: (t) => controller.snap(t, { exclude: [d.clip] }).time,\n });\n\n const update = (next: Drag | null) => {\n dragRef.current = next;\n setDrag(next);\n };\n\n // The latest render's values, for the window listeners of a drag in progress.\n const live = useRef({ planFor, selection });\n live.current = { planFor, selection };\n const stopDrag = useRef<(() => void) | null>(null);\n useEffect(() => () => stopDrag.current?.(), []);\n\n const onClipPointerDown = (e: React.PointerEvent<HTMLDivElement>, clip: VideoClip, track: VideoTrack) => {\n if (e.button !== undefined && e.button !== 0) return;\n e.stopPropagation();\n if (!editable) return;\n try {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n } catch {\n // No pointer to capture (synthetic events).\n }\n const handle = (e.target as HTMLElement).closest('[data-handle]')?.getAttribute('data-handle');\n const mode: VideoClipDragMode = handle === 'start' ? 'trim-start' : handle === 'end' ? 'trim-end' : 'move';\n const fixed = !canEdit || !!track.locked;\n stopDrag.current?.();\n update({ clip: clip.id, mode, x: e.clientX, pointer: e.pointerId, moved: false, plan: null });\n // Follow the pointer on the window: the block may move to another track's row (a new element) mid-drag.\n const move = (ev: PointerEvent) => {\n const d = dragRef.current;\n if (!d || fixed) return;\n if (!d.moved && Math.abs(ev.clientX - d.x) < DRAG_THRESHOLD) return;\n if (!d.moved && !live.current.selection.includes(d.clip)) controller.select([d.clip]);\n update({ ...d, moved: true, plan: live.current.planFor(d, ev) });\n };\n const up = (ev: PointerEvent) => {\n stop();\n const d = dragRef.current;\n if (!d) return;\n update(null);\n if (!d.moved) {\n if (ev.shiftKey || ev.metaKey || ev.ctrlKey) controller.select([d.clip], { add: true });\n else controller.select([d.clip]);\n return;\n }\n const plan = live.current.planFor(d, ev);\n if (plan?.edit) controller.apply(plan.edit, videoDragLabel(plan.edit));\n };\n const cancel = () => {\n stop();\n update(null);\n };\n const stop = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n window.removeEventListener('pointercancel', cancel);\n stopDrag.current = null;\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n window.addEventListener('pointercancel', cancel);\n stopDrag.current = stop;\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (isField(e.target)) return;\n const mod = e.metaKey || e.ctrlKey;\n const key = e.key.toLowerCase();\n if (e.key === ' ') {\n if ((e.target as HTMLElement).tagName === 'BUTTON') return;\n controller.toggle();\n } else if (e.key === 'ArrowLeft' && !mod) controller.step(-1);\n else if (e.key === 'ArrowRight' && !mod) controller.step(1);\n else if (e.key === 'Escape') controller.select(null);\n else if (!canEdit) return;\n else if (key === 's' && !mod) controller.splitAtPlayhead();\n else if ((e.key === 'Delete' || e.key === 'Backspace') && !mod) controller.deleteSelection({ ripple: e.shiftKey });\n else if (key === 'z' && mod) {\n if (e.shiftKey) controller.redo();\n else controller.undo();\n } else return;\n e.preventDefault();\n };\n\n // Where each clip is drawn: the dragged one follows the plan (possibly on another track).\n const placed = project.tracks.map((track) => ({\n track,\n clips: project.tracks.flatMap((t) =>\n t.clips\n .map((clip) => {\n const plan = drag?.moved && drag.clip === clip.id ? drag.plan : null;\n const on = plan ? plan.track : t.id;\n return on === track.id ? { clip, home: t, start: plan ? plan.start : clip.start, duration: plan ? plan.duration : clip.duration, dragging: !!plan } : null;\n })\n .filter((x): x is NonNullable<typeof x> => x !== null),\n ),\n }));\n\n const toggle = (track: VideoTrack, field: 'muted' | 'hidden' | 'locked', label: string) => (\n <button\n type=\"button\"\n className={`rounded border px-1 text-[10px] leading-4 ${track[field] ? 'border-rose-500 bg-rose-500/15 text-rose-600' : 'border-border text-muted-foreground'} disabled:opacity-40`}\n aria-pressed={!!track[field]}\n aria-label={`${label} ${track.name ?? track.id}`}\n title={label}\n disabled={!canEdit}\n data-track-toggle={field}\n onClick={() => controller.apply({ op: 'update_track', track: track.id, set: { [field]: !track[field] } }, `${track[field] ? 'Un' : ''}${field === 'muted' ? 'mute' : field === 'hidden' ? 'hide' : 'lock'} track`)}\n >\n {field === 'muted' ? 'M' : field === 'hidden' ? 'H' : 'L'}\n </button>\n );\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-video-timeline-wrapper=\"\">\n {!onPxPerSecondChange && (\n <label className=\"flex items-center gap-2 self-end text-xs text-muted-foreground\">\n Zoom\n <input type=\"range\" min={MIN_ZOOM} max={MAX_ZOOM} step={5} value={ownZoom} aria-label=\"Timeline zoom\" onChange={(e) => setOwnZoom(Number(e.target.value))} data-zoom=\"\" />\n </label>\n )}\n <div\n className=\"relative overflow-x-auto rounded border border-border outline-none focus-visible:ring-2 focus-visible:ring-rose-500/50\"\n tabIndex={0}\n role=\"group\"\n aria-label=\"Video timeline\"\n onKeyDown={onKeyDown}\n data-video-timeline=\"\"\n >\n <div className=\"relative\" style={{ width: HEADER + width }}>\n <div className=\"flex\" style={{ height: RULER }}>\n <div className=\"sticky left-0 z-20 shrink-0 border-b border-r border-border bg-background\" style={{ width: HEADER }} />\n <div\n ref={ruler}\n className=\"relative shrink-0 cursor-ew-resize select-none touch-none border-b border-border text-[10px] text-muted-foreground\"\n style={{ width }}\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n data-ruler=\"\"\n onPointerDown={(e) => {\n try {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n } catch {\n // No pointer to capture (synthetic events).\n }\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n >\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: t.x }} data-tick={t.time}>\n {t.label && <span className=\"absolute -top-3.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n {(project.markers ?? []).map((m) => (\n <div\n key={m.id}\n className=\"absolute top-0 h-2.5 w-2.5 -translate-x-1/2 rotate-45\"\n style={{ left: msToPx(m.time), background: m.color ?? '#f59e0b' }}\n title={`${m.label ?? m.id} at ${formatVideoSeconds(m.time)}`}\n data-marker={m.id}\n />\n ))}\n </div>\n </div>\n {placed.map(({ track, clips }) => (\n <div key={track.id} className=\"flex border-b border-border last:border-b-0\" style={{ height: ROW }} data-track={track.id}>\n <div className=\"sticky left-0 z-20 flex shrink-0 flex-col justify-center gap-0.5 border-r border-border bg-background px-2 text-xs\" style={{ width: HEADER }} data-track-header=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"truncate font-medium\">{track.name ?? track.id}</span>\n <span className=\"rounded bg-muted px-1 text-[10px] uppercase text-muted-foreground\" data-track-kind=\"\">\n {track.kind}\n </span>\n </div>\n {editable && (\n <div className=\"flex gap-1\">\n {toggle(track, 'muted', 'Mute')}\n {track.kind === 'video' && toggle(track, 'hidden', 'Hide')}\n {toggle(track, 'locked', 'Lock')}\n </div>\n )}\n </div>\n <div\n ref={(el) => {\n if (el) rows.current.set(track.id, el);\n else rows.current.delete(track.id);\n }}\n className={`relative shrink-0 ${track.hidden ? 'opacity-50' : ''} ${track.locked ? 'bg-muted/40' : ''}`}\n style={{ width }}\n data-track-lane={track.id}\n onPointerDown={(e) => {\n if (e.target === e.currentTarget && editable) controller.select(null);\n }}\n >\n {clips.map(({ clip, home, start, duration: length, dragging }) => {\n const asset = clip.type === 'media' ? assets.get(clip.asset) : undefined;\n const selected = selection.includes(clip.id);\n const label = videoClipLabel(clip, asset);\n return (\n <div\n key={clip.id}\n className={`absolute top-1 bottom-1 select-none touch-none overflow-hidden rounded text-[11px] text-white ${canEdit && !home.locked ? 'cursor-grab' : 'cursor-default'} ${dragging ? 'opacity-80 shadow-lg' : ''}`}\n style={{\n left: msToPx(start),\n width: Math.max(2, msToPx(length)),\n background: videoClipTint(clip, asset),\n outline: selected ? '2px solid #f43f5e' : undefined,\n outlineOffset: selected ? 1 : undefined,\n zIndex: dragging ? 10 : selected ? 2 : 1,\n }}\n title={`${label} · ${formatVideoSeconds(start)}–${formatVideoSeconds(start + length)}`}\n data-clip={clip.id}\n data-selected={selected ? '' : undefined}\n data-dragging={dragging ? '' : undefined}\n aria-selected={selected}\n onPointerDown={(e) => onClipPointerDown(e, clip, home)}\n >\n {videoClipShowsWaveform(clip, asset, waveforms) && <ClipWaveform controller={controller} clip={clip as VideoMediaClip} asset={asset} width={Math.max(2, msToPx(clip.duration))} height={ROW - 8} />}\n <span className=\"pointer-events-none relative block truncate px-1.5 py-0.5 leading-4\">{label}</span>\n {clip.transition && (\n <span className=\"pointer-events-none absolute left-1 bottom-0.5 rounded bg-black/40 px-1 text-[9px] leading-3\" title={`${clip.transition.type} ${clip.transition.duration} ms`} data-transition={clip.transition.type}>\n ⧓ {clip.transition.type}\n </span>\n )}\n {canEdit && !home.locked && (\n <>\n <div className=\"absolute inset-y-0 left-0 cursor-ew-resize bg-white/0 hover:bg-white/40\" style={{ width: HANDLE }} data-handle=\"start\" aria-hidden=\"true\" />\n <div className=\"absolute inset-y-0 right-0 cursor-ew-resize bg-white/0 hover:bg-white/40\" style={{ width: HANDLE }} data-handle=\"end\" aria-hidden=\"true\" />\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n ))}\n <div className=\"pointer-events-none absolute top-0 bottom-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: HEADER + msToPx(time), zIndex: 15 }} data-playhead=\"\" />\n </div>\n </div>\n {error && (\n <p className=\"text-xs text-red-500\" role=\"alert\" data-edit-error=\"\">\n {error}\n </p>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport {\n findVideoClip,\n formatVideoSeconds,\n VIDEO_CLIP_ANIMATION_EFFECTS,\n VIDEO_CLIP_ANIMATION_LABELS,\n normalizeVideoGrade,\n VIDEO_GRADE_CONTROLS,\n VIDEO_GRADE_PRESET_NAMES,\n videoGradePreset,\n VIDEO_BLEND_MODE_LABELS,\n VIDEO_BLEND_MODES,\n VIDEO_FADE_CURVE_LABELS,\n VIDEO_FADE_CURVES,\n VIDEO_TRANSITION_LABELS,\n VIDEO_TRANSITION_TYPES,\n VIDEO_WIPE_DIRECTIONS,\n videoTransitionHasDirection,\n videoFreezeFrameEdit,\n videoKeyframeRows,\n videoSlowMotionRamp,\n videoSpeedRampEdit,\n videoTransitionAudioCurve,\n videoKeyframeToggleEdit,\n videoKeyframeValueEdit,\n type VideoClip,\n type VideoClipAnimationEffect,\n type VideoEditorController,\n type VideoFadeCurve,\n type VideoGradePreset,\n type VideoTransitionType,\n type VideoWipeDirection,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface ClipInspectorProps {\n controller: VideoEditorController;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst field = 'w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs disabled:opacity-50';\nconst DEFAULT_TRANSITION = 500;\n\n/** An input (or textarea) that commits on blur or Enter, and resets when its value changes from outside. */\nfunction Commit({\n value,\n onCommit,\n multiline,\n ...rest\n}: { value: string; onCommit: (raw: string) => void; multiline?: boolean } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n const commit = (raw: string) => {\n if (raw !== value) onCommit(raw);\n };\n if (multiline)\n return (\n <textarea\n key={value}\n className={field}\n rows={2}\n defaultValue={value}\n disabled={rest.disabled}\n aria-label={rest['aria-label']}\n onBlur={(e) => commit(e.currentTarget.value)}\n />\n );\n return <input key={value} className={field} {...rest} defaultValue={value} onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()} onBlur={(e) => commit(e.currentTarget.value)} />;\n}\n\nfunction Row({ label, name, children }: { label: string; name: string; children: React.ReactNode }) {\n return (\n <label className=\"grid grid-cols-[5.5rem_minmax(0,1fr)] items-center gap-2 text-xs\" data-field={name}>\n <span className=\"text-muted-foreground\">{label}</span>\n {children}\n </label>\n );\n}\n\n/**\n * Edits the one selected clip: its name, fades, opacity, volume and transform (each with a keyframe\n * toggle at the playhead: ◆ adds a key holding the value there or removes the one there; typing a\n * value on a keyed property sets the key at the playhead); volume, speed and mute for media;\n * text, colour, size and background for titles; colour for colour clips; and the transition into\n * it. Each change is one undo step (`update_clip` / `set_transition`), committed on blur or change.\n */\nexport function ClipInspector({ controller, className = '' }: ClipInspectorProps) {\n const state = useVideoEditorState(controller);\n const { project, selection, readOnly, time } = state;\n if (selection.length !== 1)\n return (\n <p className={`text-xs text-muted-foreground ${className}`} data-clip-inspector=\"\">\n {selection.length ? `${selection.length} clips selected. Select one clip to edit it.` : 'Select a clip on the timeline to edit it.'}\n </p>\n );\n const at = findVideoClip(project, selection[0]);\n if (!at) return null;\n const clip: VideoClip = at.clip;\n const disabled = readOnly || !!at.track.locked;\n\n const set = (key: string, value: unknown, label = `Change ${key}`) => {\n if (value === undefined || value === '') controller.apply({ op: 'update_clip', clip: clip.id, remove: [key] }, label);\n else controller.apply({ op: 'update_clip', clip: clip.id, set: { [key]: value } }, label);\n };\n const num = (key: string, raw: string, label?: string) => {\n const trimmed = raw.trim();\n if (!trimmed) return set(key, undefined, label);\n const n = Number(trimmed);\n if (Number.isFinite(n)) set(key, n, label);\n };\n const text = (key: string, label?: string) => {\n const value = (clip as unknown as Record<string, unknown>)[key];\n return (\n <Commit value={value === undefined ? '' : String(value)} aria-label={label ?? key} disabled={disabled} onCommit={(raw) => set(key, raw.trim() || undefined, `Change ${label ?? key}`)} />\n );\n };\n const number = (key: string, label: string, attrs: { min?: number; max?: number; step?: number } = {}) => {\n const value = (clip as unknown as Record<string, unknown>)[key];\n return <Commit type=\"number\" value={value === undefined ? '' : String(value)} aria-label={label} disabled={disabled} onCommit={(raw) => num(key, raw, `Change ${label.toLowerCase()}`)} {...attrs} />;\n };\n\n const transition = clip.transition;\n return (\n <div className={`flex flex-col gap-1.5 ${className}`} data-clip-inspector=\"\" data-clip-id={clip.id}>\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"font-medium\">{clip.type === 'media' ? 'Media clip' : clip.type === 'text' ? 'Title' : 'Colour clip'}</span>\n <code className=\"text-muted-foreground\">{clip.id}</code>\n {at.track.locked && <span className=\"text-amber-500\">locked track</span>}\n </div>\n <Row label=\"Name\" name=\"name\">\n {text('name', 'Name')}\n </Row>\n <Row label=\"Start\" name=\"start\">\n <span className=\"tabular-nums text-xs\">{formatVideoSeconds(clip.start)}</span>\n </Row>\n <Row label=\"Duration\" name=\"duration\">\n <span className=\"tabular-nums text-xs\">{formatVideoSeconds(clip.duration)}</span>\n </Row>\n {videoKeyframeRows(project, clip.id, time).map((row) => (\n <Row key={row.property} label={row.label} name={row.property}>\n <span className=\"flex min-w-0 items-center gap-1\" data-keyframe-row={row.property}>\n <Commit\n type=\"number\"\n value={row.keyed || (row.property === 'opacity' ? clip.opacity : row.property === 'volume' ? (clip as { volume?: unknown }).volume : clip.transform?.[row.property]) !== undefined ? String(row.value) : ''}\n placeholder={String(row.value)}\n aria-label={row.label}\n disabled={disabled}\n min={row.min}\n max={row.max}\n step={row.step}\n onCommit={(raw) => {\n const n = Number(raw);\n if (raw.trim() && !Number.isFinite(n)) return;\n const edit = videoKeyframeValueEdit(project, clip.id, row.property, time, raw.trim() ? n : undefined);\n if (edit) controller.apply(edit, row.keyed ? `Keyframe ${row.label.toLowerCase()}` : `Change ${row.label.toLowerCase()}`);\n }}\n />\n <button\n type=\"button\"\n className={`shrink-0 rounded px-1 text-xs disabled:opacity-50 ${row.onKey ? 'text-amber-500' : row.keyed ? 'text-foreground' : 'text-muted-foreground'}`}\n aria-label={`${row.onKey ? 'Remove' : 'Add'} ${row.label.toLowerCase()} keyframe at playhead`}\n aria-pressed={row.onKey}\n title={row.keyed ? `${row.keys} key${row.keys === 1 ? '' : 's'}; ${row.onKey ? 'remove the one' : 'add one'} at the playhead` : 'Animate: add a key at the playhead'}\n disabled={disabled}\n data-keyframe-toggle={row.property}\n onClick={() => {\n const edit = videoKeyframeToggleEdit(project, clip.id, row.property, time);\n if (edit) controller.apply(edit, `${row.onKey ? 'Remove' : 'Add'} ${row.label.toLowerCase()} keyframe`);\n }}\n >\n {row.onKey ? '◆' : '◇'}\n </button>\n {row.keyed && (\n <span className=\"shrink-0 text-[10px] tabular-nums text-muted-foreground\" data-keyframe-count={row.property}>\n {row.keys}\n </span>\n )}\n </span>\n </Row>\n ))}\n {at.track.kind === 'video' && (\n <Row label=\"Blend\" name=\"blend\">\n <select className={field} value={clip.blend ?? 'normal'} disabled={disabled} aria-label=\"Blend mode\" onChange={(e) => set('blend', e.target.value === 'normal' ? undefined : e.target.value, 'Change blend mode')}>\n {VIDEO_BLEND_MODES.map((m) => (\n <option key={m} value={m}>\n {VIDEO_BLEND_MODE_LABELS[m]}\n </option>\n ))}\n </select>\n </Row>\n )}\n {at.track.kind === 'video' && (\n <>\n <Row label=\"Look\" name=\"gradePreset\">\n <select\n className={field}\n value=\"\"\n disabled={disabled}\n aria-label=\"Apply a look\"\n onChange={(e) => {\n const grade = videoGradePreset(e.target.value as VideoGradePreset);\n if (grade) controller.apply({ op: 'update_clip', clip: clip.id, set: { grade } }, `Apply ${e.target.value} look`);\n }}\n >\n <option value=\"\">{clip.grade ? 'Graded' : 'None'}</option>\n {VIDEO_GRADE_PRESET_NAMES.map((name) => (\n <option key={name} value={name}>\n {name.replace(/-/g, ' ')}\n </option>\n ))}\n </select>\n </Row>\n {VIDEO_GRADE_CONTROLS.map((c) => (\n <Row key={c.key} label={c.label} name={`grade.${c.key}`}>\n <Commit\n type=\"number\"\n min={c.min}\n max={c.max}\n step={c.step}\n value={clip.grade?.[c.key] === undefined ? '' : String(clip.grade[c.key])}\n placeholder=\"0\"\n aria-label={c.label}\n disabled={disabled}\n onCommit={(raw) => {\n const n = raw.trim() ? Number(raw) : 0;\n if (!Number.isFinite(n)) return;\n // Out-of-range values are clamped to the control's range.\n const grade = normalizeVideoGrade({ ...clip.grade, [c.key]: n });\n set('grade', grade, `Change ${c.label.toLowerCase()}`);\n }}\n />\n </Row>\n ))}\n </>\n )}\n {at.track.kind === 'video' &&\n (['animateIn', 'animateOut'] as const).map((key) => (\n <Row key={key} label={key === 'animateIn' ? 'Animate in' : 'Animate out'} name={key}>\n <select\n className={field}\n value={clip[key]?.effect ?? ''}\n disabled={disabled}\n aria-label={key === 'animateIn' ? 'Animate in' : 'Animate out'}\n onChange={(e) => {\n const effect = e.target.value as VideoClipAnimationEffect | '';\n set(key, effect ? { ...clip[key], effect } : undefined, key === 'animateIn' ? 'Change entrance' : 'Change exit');\n }}\n >\n <option value=\"\">None</option>\n {VIDEO_CLIP_ANIMATION_EFFECTS.map((effect) => (\n <option key={effect} value={effect}>\n {VIDEO_CLIP_ANIMATION_LABELS[effect]}\n </option>\n ))}\n </select>\n </Row>\n ))}\n <Row label=\"Fade in (ms)\" name=\"fadeIn\">\n {number('fadeIn', 'Fade in', { min: 0, step: 100 })}\n </Row>\n <Row label=\"Fade out (ms)\" name=\"fadeOut\">\n {number('fadeOut', 'Fade out', { min: 0, step: 100 })}\n </Row>\n {clip.type === 'media' && (\n <>\n <Row label=\"Speed\" name=\"speed\">\n {clip.timeRemap ? (\n <span className=\"flex items-center gap-1\" data-ramped=\"\">\n <span className=\"text-muted-foreground\">ramped</span>\n <button type=\"button\" className={btn} disabled={disabled} onClick={() => controller.apply({ op: 'set_time_remap', clip: clip.id, keys: null, ripple: true }, 'Remove speed ramp')}>\n Remove ramp\n </button>\n </span>\n ) : (\n number('speed', 'Speed', { min: 0.1, step: 0.25 })\n )}\n </Row>\n {project.assets.find((a) => a.id === clip.asset)?.kind !== 'image' && (\n <Row label=\"Retime\" name=\"retime\">\n <span className=\"flex flex-wrap gap-1\">\n <button\n type=\"button\"\n className={btn}\n disabled={disabled || time < clip.start || time > clip.start + clip.duration}\n title=\"Hold the frame at the playhead for a second, pushing later clips along\"\n onClick={() => controller.apply(videoFreezeFrameEdit(clip, time - clip.start, 1000), 'Freeze frame')}\n >\n Freeze 1 s here\n </button>\n <button type=\"button\" className={btn} disabled={disabled} title=\"Normal speed, then a glide into 0.3× slow motion\" onClick={() => controller.apply(videoSpeedRampEdit(clip, videoSlowMotionRamp(clip.duration)), 'Speed ramp')}>\n Slow-mo ramp\n </button>\n </span>\n </Row>\n )}\n <Row label=\"Muted\" name=\"muted\">\n <input type=\"checkbox\" className=\"justify-self-start\" checked={!!clip.muted} disabled={disabled} aria-label=\"Muted\" onChange={(e) => set('muted', e.target.checked || undefined, e.target.checked ? 'Mute clip' : 'Unmute clip')} />\n </Row>\n {(['fadeInCurve', 'fadeOutCurve'] as const).map((key) =>\n (key === 'fadeInCurve' ? clip.fadeIn : clip.fadeOut) ? (\n <Row key={key} label={key === 'fadeInCurve' ? 'Fade in sound' : 'Fade out sound'} name={key}>\n <select\n className={field}\n value={clip[key] ?? 'linear'}\n disabled={disabled}\n aria-label={key === 'fadeInCurve' ? 'Fade in curve' : 'Fade out curve'}\n onChange={(e) => {\n const curve = e.target.value as VideoFadeCurve;\n set(key, curve === 'linear' ? undefined : curve, key === 'fadeInCurve' ? 'Change fade in curve' : 'Change fade out curve');\n }}\n >\n {VIDEO_FADE_CURVES.map((c) => (\n <option key={c} value={c}>\n {VIDEO_FADE_CURVE_LABELS[c]}\n </option>\n ))}\n </select>\n </Row>\n ) : null,\n )}\n </>\n )}\n {clip.type === 'text' && (\n <>\n <Row label=\"Text\" name=\"text\">\n <Commit multiline value={clip.text} aria-label=\"Text\" disabled={disabled} onCommit={(raw) => set('text', raw, 'Change text')} />\n </Row>\n <Row label=\"Colour\" name=\"color\">\n {text('color', 'Colour')}\n </Row>\n <Row label=\"Font size\" name=\"fontSize\">\n {number('fontSize', 'Font size', { min: 1, step: 2 })}\n </Row>\n <Row label=\"Background\" name=\"background\">\n {text('background', 'Background')}\n </Row>\n </>\n )}\n {clip.type === 'color' && (\n <Row label=\"Colour\" name=\"color\">\n <Commit value={clip.color} aria-label=\"Colour\" disabled={disabled} onCommit={(raw) => raw.trim() && set('color', raw.trim(), 'Change colour')} />\n </Row>\n )}\n <Row label=\"Transition in\" name=\"transition\">\n <select\n className={field}\n value={transition?.type ?? ''}\n disabled={disabled}\n aria-label=\"Transition\"\n onChange={(e) => {\n const type = e.target.value as VideoTransitionType | '';\n controller.apply(\n { op: 'set_transition', clip: clip.id, transition: type ? { ...transition, type, duration: transition?.duration ?? DEFAULT_TRANSITION } : null },\n type ? 'Set transition' : 'Remove transition',\n );\n }}\n >\n <option value=\"\">None</option>\n {VIDEO_TRANSITION_TYPES.map((t) => (\n <option key={t} value={t}>\n {VIDEO_TRANSITION_LABELS[t]}\n </option>\n ))}\n </select>\n </Row>\n {transition && (\n <Row label=\"Length (ms)\" name=\"transitionDuration\">\n <Commit\n type=\"number\"\n min={1}\n step={100}\n value={String(transition.duration)}\n aria-label=\"Transition length\"\n disabled={disabled}\n onCommit={(raw) => {\n const n = Number(raw);\n if (raw.trim() && Number.isFinite(n) && n > 0) controller.apply({ op: 'set_transition', clip: clip.id, transition: { ...transition, duration: n } }, 'Change transition length');\n }}\n />\n </Row>\n )}\n {transition && videoTransitionHasDirection(transition.type) && (\n <Row label=\"Direction\" name=\"transitionDirection\">\n <select\n className={field}\n value={transition.direction ?? 'right'}\n disabled={disabled}\n aria-label=\"Transition direction\"\n onChange={(e) => controller.apply({ op: 'set_transition', clip: clip.id, transition: { ...transition, direction: e.target.value as VideoWipeDirection } }, 'Change transition direction')}\n >\n {VIDEO_WIPE_DIRECTIONS.map((d) => (\n <option key={d} value={d}>\n {d}\n </option>\n ))}\n </select>\n </Row>\n )}\n {transition && (\n <Row label=\"Transition sound\" name=\"transitionAudioCurve\">\n <select\n className={field}\n value={videoTransitionAudioCurve(transition)}\n disabled={disabled}\n aria-label=\"Transition sound curve\"\n onChange={(e) => {\n const { audioCurve: _, ...rest } = transition;\n const curve = e.target.value as VideoFadeCurve;\n // The type's own default is stored as no curve, so it follows the type if that changes.\n const next = curve === videoTransitionAudioCurve(rest) ? rest : { ...rest, audioCurve: curve };\n controller.apply({ op: 'set_transition', clip: clip.id, transition: next }, 'Change transition sound');\n }}\n >\n {VIDEO_FADE_CURVES.map((c) => (\n <option key={c} value={c}>\n {VIDEO_FADE_CURVE_LABELS[c]}\n </option>\n ))}\n </select>\n </Row>\n )}\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport {\n formatVideoSeconds,\n probeVideoMedia,\n videoAssetDropEdit,\n videoAssetKindOf,\n type VideoAsset,\n type VideoAssetKind,\n type VideoEditorController,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface MediaBinProps {\n controller: VideoEditorController;\n /** Show the import controls and \"Add to timeline\" buttons (default true). */\n editable?: boolean;\n /** Turns a file into a URL the preview and exporter can open (default `URL.createObjectURL`). */\n fileToUrl?: (file: File) => string;\n /** Reads a source's length and size (default `probeVideoMedia`). */\n probe?: typeof probeVideoMedia;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * The project's assets (name, kind, length), each with an \"Add to timeline\" button that puts it at\n * the end of the first unlocked track of its kind. Import media by choosing or dropping files (read\n * as object URLs and probed for their length and size) or by URL. Each import is one undo step.\n */\nexport function MediaBin({ controller, editable = true, fileToUrl, probe = probeVideoMedia, className = '' }: MediaBinProps) {\n const { project, readOnly } = useVideoEditorState(controller);\n const canEdit = editable && !readOnly;\n const [url, setUrl] = useState('');\n const [urlKind, setUrlKind] = useState<VideoAssetKind | ''>('');\n const [busy, setBusy] = useState(0);\n const [problem, setProblem] = useState<string | null>(null);\n const [over, setOver] = useState(false);\n\n const addSource = async (src: string, kind: VideoAssetKind, name: string) => {\n setBusy((n) => n + 1);\n try {\n const found = await probe(src, kind).catch(() => null);\n const result = controller.apply({ op: 'add_asset', asset: { kind, src, name, ...(found ?? {}) } }, `Import ${name}`);\n if (!result.ok) setProblem(result.error);\n } finally {\n setBusy((n) => n - 1);\n }\n };\n\n const addFiles = async (files: FileList | File[] | null) => {\n setProblem(null);\n for (const file of Array.from(files ?? [])) {\n const kind = videoAssetKindOf(file.type || file.name);\n if (!kind) {\n setProblem(`\"${file.name}\" is not a video, audio or image file.`);\n continue;\n }\n const src = fileToUrl ? fileToUrl(file) : URL.createObjectURL(file);\n await addSource(src, kind, file.name);\n }\n };\n\n const addUrl = async () => {\n const src = url.trim();\n if (!src) return;\n const kind = urlKind || videoAssetKindOf(src.replace(/[?#].*$/, ''));\n if (!kind) {\n setProblem(`Can't tell whether \"${src}\" is video, audio or an image; choose its kind.`);\n return;\n }\n setProblem(null);\n await addSource(src, kind, src.replace(/[?#].*$/, '').replace(/^.*[\\\\/]/, '') || src);\n setUrl('');\n };\n\n const addToTimeline = (asset: VideoAsset) => {\n const edit = videoAssetDropEdit(project, asset.id);\n if (!edit) {\n setProblem(`There is no unlocked ${asset.kind === 'audio' ? 'audio' : 'video'} track to put \"${asset.name ?? asset.id}\" on.`);\n return;\n }\n setProblem(null);\n const result = controller.apply(edit, `Add ${asset.name ?? asset.id}`);\n if (result.ok) {\n const added = result.outcomes[0]?.clip;\n if (added) controller.select([added]);\n }\n };\n\n return (\n <div\n className={`flex flex-col gap-2 rounded ${over ? 'ring-2 ring-rose-500/60' : ''} ${className}`}\n data-media-bin=\"\"\n onDragOver={(e) => {\n if (!canEdit || !e.dataTransfer?.types?.includes('Files')) return;\n e.preventDefault();\n setOver(true);\n }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => {\n setOver(false);\n if (!canEdit || !e.dataTransfer?.files?.length) return;\n e.preventDefault();\n void addFiles(e.dataTransfer.files);\n }}\n >\n <div className=\"text-xs font-medium\">Media</div>\n {project.assets.length ? (\n <ul className=\"flex flex-col gap-1\" aria-label=\"Media assets\">\n {project.assets.map((asset) => (\n <li key={asset.id} className=\"flex items-center gap-2 text-xs\" data-asset={asset.id}>\n <span className=\"rounded bg-muted px-1 text-[10px] uppercase text-muted-foreground\" data-asset-kind=\"\">\n {asset.kind}\n </span>\n <span className=\"min-w-0 flex-1 truncate\" title={asset.src}>\n {asset.name ?? asset.id}\n </span>\n {asset.duration !== undefined && <span className=\"tabular-nums text-muted-foreground\">{formatVideoSeconds(asset.duration)}</span>}\n {editable && (\n <button type=\"button\" className={btn} disabled={!canEdit} onClick={() => addToTimeline(asset)} data-add-to-timeline=\"\">\n Add to timeline\n </button>\n )}\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"text-xs text-muted-foreground\">No media yet.{editable ? ' Choose or drop files, or add a URL.' : ''}</p>\n )}\n {editable && (\n <>\n <label className=\"flex flex-col gap-1 rounded border border-dashed border-border p-2 text-xs text-muted-foreground\">\n Choose or drop video, audio or image files\n <input\n type=\"file\"\n multiple\n accept=\"video/*,audio/*,image/*\"\n disabled={!canEdit}\n aria-label=\"Import media files\"\n data-import-files=\"\"\n onChange={(e) => {\n const files = e.currentTarget.files ? Array.from(e.currentTarget.files) : [];\n e.currentTarget.value = '';\n void addFiles(files);\n }}\n />\n </label>\n <form\n className=\"flex items-center gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void addUrl();\n }}\n >\n <input\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n placeholder=\"https://…/clip.mp4\"\n value={url}\n disabled={!canEdit}\n aria-label=\"Media URL\"\n onChange={(e) => setUrl(e.target.value)}\n />\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-xs\" value={urlKind} disabled={!canEdit} aria-label=\"Media kind\" onChange={(e) => setUrlKind(e.target.value as VideoAssetKind | '')}>\n <option value=\"\">Auto</option>\n <option value=\"video\">Video</option>\n <option value=\"audio\">Audio</option>\n <option value=\"image\">Image</option>\n </select>\n <button type=\"submit\" className={btn} disabled={!canEdit || !url.trim()} data-add-url=\"\">\n Add\n </button>\n </form>\n </>\n )}\n {busy > 0 && <p className=\"text-xs text-muted-foreground\">Reading media…</p>}\n {problem && (\n <p className=\"text-xs text-red-500\" role=\"alert\" data-media-error=\"\">\n {problem}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n findVideoFillers,\n findVideoTranscriptPauses,\n videoRemoveRangesEdits,\n videoTimelineTranscript,\n videoTranscriptEdit,\n videoWordAt,\n videoWordsRange,\n type VideoEditorController,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface TranscriptPanelProps {\n controller: VideoEditorController;\n /** Track whose words to show (default: the first audio track with a transcribed clip, else the first video track with one). */\n track?: string;\n /** Allow cutting by text and loading transcripts (default true). */\n editable?: boolean;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * Edit by text: the words the timeline plays, from its media's transcripts. Click a word to go to\n * it, Shift-click to select a run of words, then delete them to cut that stretch out (closing it up\n * on every sync-locked track). \"Remove fillers\" and \"Tighten pauses\" cut every um and every long gap\n * at once. Each cut is one undo step. Transcripts (Whisper JSON, .srt, .vtt) load per asset below.\n */\nexport function TranscriptPanel({ controller, track, editable = true, className = '' }: TranscriptPanelProps) {\n const state = useVideoEditorState(controller);\n const { project, time, readOnly } = state;\n const canEdit = editable && !readOnly;\n const [anchor, setAnchor] = useState<number | null>(null);\n const [focus, setFocus] = useState<number | null>(null);\n const [message, setMessage] = useState<string | null>(null);\n const words = useMemo(() => {\n try {\n return videoTimelineTranscript(project, { track });\n } catch {\n return [];\n }\n }, [project, track]);\n const current = videoWordAt(words, time);\n const selected = anchor !== null && focus !== null && anchor < words.length && focus < words.length ? ([Math.min(anchor, focus), Math.max(anchor, focus)] as const) : null;\n const sound = project.assets.filter((a) => a.kind !== 'image');\n\n const cut = (ranges: { from: number; to: number }[], label: string, none: string) => {\n if (!ranges.length) return setMessage(none);\n const r = controller.apply(videoRemoveRangesEdits(ranges), label);\n setMessage(r.ok ? null : r.error);\n setAnchor(null);\n setFocus(null);\n };\n const load = async (assetId: string, file: File | undefined) => {\n if (!file) return;\n try {\n const r = controller.apply(videoTranscriptEdit(assetId, await file.text()), 'Attach transcript');\n setMessage(r.ok ? null : r.error);\n } catch (e) {\n setMessage(e instanceof Error ? e.message : String(e));\n }\n };\n\n return (\n <div className={`flex flex-col gap-2 text-xs ${className}`} data-transcript-panel=\"\">\n {words.length > 0 ? (\n <>\n <div\n className=\"max-h-48 overflow-y-auto leading-6\"\n role=\"listbox\"\n aria-label=\"Transcript\"\n aria-multiselectable=\"true\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (canEdit && selected && (e.key === 'Delete' || e.key === 'Backspace')) {\n e.preventDefault();\n cut([videoWordsRange(words, selected[0], selected[1])], 'Cut words', 'Select words to cut.');\n }\n }}\n >\n {words.map((w, i) => {\n const inSelection = selected !== null && i >= selected[0] && i <= selected[1];\n return (\n <React.Fragment key={`${w.clip}:${w.index}`}>\n <span\n role=\"option\"\n aria-selected={inSelection}\n tabIndex={-1}\n className={`cursor-pointer rounded px-0.5 ${inSelection ? 'bg-rose-500/30' : i === current ? 'bg-amber-400/40' : 'hover:bg-muted'}`}\n data-word={i}\n data-current={i === current ? '' : undefined}\n data-selected={inSelection ? '' : undefined}\n onClick={(e) => {\n if (e.shiftKey && anchor !== null) setFocus(i);\n else {\n setAnchor(i);\n setFocus(i);\n controller.seek(w.start);\n }\n }}\n >\n {w.word}\n </span>{' '}\n </React.Fragment>\n );\n })}\n </div>\n {canEdit && (\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={btn} disabled={!selected} onClick={() => selected && cut([videoWordsRange(words, selected[0], selected[1])], 'Cut words', 'Select words to cut.')}>\n Delete selected words\n </button>\n <button type=\"button\" className={btn} onClick={() => cut(findVideoFillers(words), 'Remove fillers', 'No filler words found.')}>\n Remove fillers\n </button>\n <button type=\"button\" className={btn} onClick={() => cut(findVideoTranscriptPauses(words, { fps: project.fps }), 'Tighten pauses', 'No long pauses found.')}>\n Tighten pauses\n </button>\n </div>\n )}\n </>\n ) : (\n <p className=\"text-muted-foreground\" data-transcript-empty=\"\">\n No transcribed media on the timeline. Load a transcript (Whisper JSON, .srt or .vtt) for a video or audio asset to edit by text.\n </p>\n )}\n {canEdit && sound.length > 0 && (\n <details>\n <summary className=\"cursor-pointer text-muted-foreground\">Transcripts</summary>\n <ul className=\"mt-1 space-y-1\">\n {sound.map((a) => (\n <li key={a.id} className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate\">\n {a.name ?? a.id} {a.transcript ? `· ${a.transcript.length} words` : ''}\n </span>\n <input type=\"file\" accept=\".json,.srt,.vtt,application/json,text/vtt\" aria-label={`Load a transcript for ${a.name ?? a.id}`} className=\"w-40 text-[10px]\" onChange={(e) => void load(a.id, e.target.files?.[0])} />\n </li>\n ))}\n </ul>\n </details>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-transcript-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect } from 'react';\nimport type { VideoEditorController, VideoEditorOptions } from '@pixerate/editor/video-editor';\nimport { ClipInspector } from './ClipInspector';\nimport { MediaBin } from './MediaBin';\nimport { TranscriptPanel } from './TranscriptPanel';\nimport { useVideoEditor } from './useVideoEditor';\nimport { VideoPreview } from './VideoPreview';\nimport { VideoScopes } from './VideoScopes';\nimport { VideoTimeline } from './VideoTimeline';\nimport { VideoTransport } from './VideoTransport';\n\nexport interface VideoEditorProps {\n /** The controller to edit. Without it one is created from `options` for the component's lifetime. */\n controller?: VideoEditorController;\n /** Options for the controller created when `controller` is not given. */\n options?: VideoEditorOptions;\n /**\n * Show the editing UI: the media bin's imports, the transport's edit buttons, timeline dragging\n * and track toggles, and the clip inspector (default true). False also makes the project read-only\n * while mounted.\n */\n editable?: boolean;\n /** Timeline zoom in pixels per second (with `onPxPerSecondChange` the host owns it). */\n pxPerSecond?: number;\n onPxPerSecondChange?: (pxPerSecond: number) => void;\n /** Canvas pixels per frame pixel for the preview (see `<VideoPreview resolution>`). */\n resolution?: number;\n /** List the project's issues under the timeline (default true). */\n showIssues?: boolean;\n /** Show the transcript panel for editing by text (default true). */\n showTranscript?: boolean;\n /** Show colour scopes (histogram, luma waveform, vectorscope) of the preview under it (default false). */\n showScopes?: boolean;\n className?: string;\n}\n\n/**\n * A whole non-linear video editor for a `VideoEditorController`: the media bin, the preview, the\n * transport, the timeline and the clip inspector, with the project's issues listed under the\n * timeline. Every edit is one undo step; the controller's agent tools edit the same project.\n */\nexport function VideoEditor({ controller: given, options, editable = true, pxPerSecond, onPxPerSecondChange, resolution, showIssues = true, showTranscript = true, showScopes = false, className = '' }: VideoEditorProps) {\n const { controller, state } = useVideoEditor(given ?? options ?? {});\n useEffect(() => {\n if (editable) return;\n const was = controller.getState().readOnly;\n controller.setReadOnly(true);\n return () => controller.setReadOnly(was);\n }, [controller, editable]);\n const { issues } = state;\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Video issues\" data-video-issues=\"\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'} data-issue={issue.code}>\n {issue.message}\n </li>\n ))}\n </ul>\n );\n return (\n <div className={`flex flex-col gap-3 ${className}`} data-video-editor=\"\">\n <div className={`grid gap-3 ${editable ? 'lg:grid-cols-[16rem_minmax(0,1fr)_18rem]' : ''}`}>\n {editable && <MediaBin controller={controller} className=\"min-w-0\" />}\n <div className=\"flex min-w-0 flex-col gap-2\">\n <VideoPreview controller={controller} resolution={resolution} className=\"rounded-md border border-border\" />\n <VideoTransport controller={controller} editable={editable} />\n {showScopes && <VideoScopes controller={controller} />}\n </div>\n {editable && <ClipInspector controller={controller} className=\"min-w-0\" />}\n </div>\n <VideoTimeline controller={controller} editable={editable} pxPerSecond={pxPerSecond} onPxPerSecondChange={onPxPerSecondChange} />\n {showTranscript && <TranscriptPanel controller={controller} editable={editable} />}\n {issueList}\n </div>\n );\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","useEffect","useRef","jsx","jsx","jsxs","useEffect","useMemo","useRef","useState","useSyncExternalStore","Fragment","jsx","jsxs","useSyncExternalStore","useEffect","useMemo","useState","useRef","field","formatVideoSeconds","Fragment","jsx","jsxs","btn","formatVideoSeconds","useState","formatVideoSeconds","Fragment","jsx","jsxs","btn","useState","formatVideoSeconds","React","useMemo","useState","Fragment","jsx","jsxs","btn","useState","useMemo","React","useEffect","jsx","jsxs","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../../src/video-editor/useVideoEditor.ts","../../src/video-editor/VideoPreview.tsx","../../src/video-editor/VideoScopes.tsx","../../src/video-editor/VideoTransport.tsx","../../src/video-editor/VideoTimeline.tsx","../../src/video-editor/ClipInspector.tsx","../../src/video-editor/MediaBin.tsx","../../src/video-editor/TranscriptPanel.tsx","../../src/video-editor/VideoEditor.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VideoEditorController,\n createVideoEditorToolProvider,\n type VideoEditResult,\n type VideoEditorOptions,\n type VideoEditorState,\n type VideoEditorToolProviderOptions,\n} from '@pixerate/editor/video-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** A `VideoEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVideoEditorController(options: VideoEditorOptions = {}): VideoEditorController {\n const ref = useRef<VideoEditorController | null>(null);\n if (!ref.current) ref.current = new VideoEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useVideoEditorState(controller: VideoEditorController): VideoEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVideoEditorResult {\n controller: VideoEditorController;\n state: VideoEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n /** Moves the playhead (ms). */\n seek: (time: number) => void;\n /** Moves the playhead by whole frames (negative steps back), pausing. */\n step: (frames: number) => void;\n undo: () => void;\n redo: () => void;\n /** Splits the selected clips (or every clip) under the playhead, as one undo step. */\n splitAtPlayhead: () => VideoEditResult;\n /** Deletes the selected clips; `ripple` closes the gaps they leave. */\n deleteSelection: (options?: { ripple?: boolean }) => VideoEditResult;\n}\n\n/**\n * Subscribes to a video editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useVideoEditor(controllerOrOptions: VideoEditorController | VideoEditorOptions = {}): UseVideoEditorResult {\n const own = useRef<VideoEditorController | null>(null);\n let controller: VideoEditorController;\n if (controllerOrOptions instanceof VideoEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VideoEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useVideoEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n step: (frames: number) => controller.step(frames),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n splitAtPlayhead: () => controller.splitAtPlayhead(),\n deleteSelection: (options?: { ripple?: boolean }) => controller.deleteSelection(options),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the video editor's agent tools (`get_video_project`, `add_video_clip`,\n * `trim_video_clip`, …) in `registry` while mounted.\n */\nexport function useVideoEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: VideoEditorController,\n options: VideoEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVideoEditorToolProvider(controller, { id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout }));\n }, [registry, controller, id, namespace, readOnly, rasterize, framePixels, framePixelsTimeout]);\n}\n","import React, { useEffect, useRef } from 'react';\nimport { VideoPreviewEngine, type VideoEditorController, type VideoPreviewOptions } from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoPreviewProps {\n controller: VideoEditorController;\n /** Canvas pixels per frame pixel (default: fits the displayed width at the device pixel ratio, at most 1). */\n resolution?: number;\n /** Called after each frame is drawn. */\n onFrame?: VideoPreviewOptions['onFrame'];\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Plays the controller's project on a canvas the shape of its frame: a `VideoPreviewEngine` keeps\n * one `<video>` / `<audio>` element per playing clip in step with the playhead and draws each frame.\n * The engine is created when the canvas mounts and destroyed on unmount or when the controller changes.\n */\nexport function VideoPreview({ controller, resolution, onFrame, className = '', style }: VideoPreviewProps) {\n const { project } = useVideoEditorState(controller);\n const canvas = useRef<HTMLCanvasElement>(null);\n const frameRef = useRef(onFrame);\n frameRef.current = onFrame;\n useEffect(() => {\n const el = canvas.current;\n if (!el) return;\n const engine = new VideoPreviewEngine(controller, el, { resolution, onFrame: (frame) => frameRef.current?.(frame) });\n return () => engine.destroy();\n }, [controller, resolution]);\n return (\n <canvas\n ref={canvas}\n className={className}\n style={{ display: 'block', width: '100%', aspectRatio: `${project.width} / ${project.height}`, background: project.background ?? '#000', ...style }}\n role=\"img\"\n aria-label={`Preview of ${project.name ?? 'the video'}`}\n data-video-preview=\"\"\n />\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { readVideoScopesPanel, VIDEO_SCOPE_KINDS, type VideoEditorController, type VideoScopeKind, type VideoScopesPanelReading } from '@pixerate/editor/video-editor';\n\nexport interface VideoScopesProps {\n controller: VideoEditorController;\n /** Which scopes to show, in order (default histogram, waveform and vectorscope). */\n scopes?: readonly VideoScopeKind[];\n /** Size of the histogram and waveform in pixels (default 256 × 128); the vectorscope is square, `height` a side. */\n width?: number;\n height?: number;\n className?: string;\n}\n\nconst LABELS: Record<VideoScopeKind, string> = { histogram: 'Histogram', waveform: 'Luma waveform', vectorscope: 'Vectorscope' };\nconst pct = (v: number) => `${Math.round(v * 1000) / 10}%`;\n\n/**\n * Colour scopes of what the controller's `<VideoPreview>` draws: a histogram, a luma waveform and a\n * vectorscope, redrawn after each frame, with exposure and clipping figures and notes. Reads the\n * preview through `controller.previewPixels`, so it needs a preview of the same controller.\n */\nexport function VideoScopes({ controller, scopes = VIDEO_SCOPE_KINDS, width = 256, height = 128, className = '' }: VideoScopesProps) {\n const canvases = useRef<Partial<Record<VideoScopeKind, HTMLCanvasElement | null>>>({});\n const [reading, setReading] = useState<VideoScopesPanelReading>(() => ({ ok: false, message: 'Show the preview to see its scopes.' }));\n const key = scopes.join(',');\n useEffect(() => {\n const feed = controller.previewPixels;\n let frame = 0;\n const raf = typeof requestAnimationFrame === 'function' ? requestAnimationFrame : (fn: () => void) => setTimeout(fn, 16) as unknown as number;\n const caf = typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame : (id: number) => clearTimeout(id);\n const draw = () => {\n frame = 0;\n const next = readVideoScopesPanel(feed, scopes, { width, height });\n setReading(next);\n if (!next.ok) return;\n for (const kind of scopes) {\n const img = next.images[kind];\n const ctx = canvases.current[kind]?.getContext('2d');\n if (img && ctx && typeof ImageData !== 'undefined') ctx.putImageData(new ImageData(img.data, img.width, img.height), 0, 0);\n }\n };\n // At most one reading a frame, however often the preview draws.\n const schedule = () => {\n if (!frame) frame = raf(draw);\n };\n schedule();\n const off = feed.subscribe(schedule);\n return () => {\n off();\n if (frame) caf(frame);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [controller, key, width, height]);\n\n return (\n <div className={`flex flex-col gap-2 text-xs ${className}`} data-video-scopes=\"\">\n <div className=\"flex flex-wrap gap-2\">\n {scopes.map((kind) => {\n const w = kind === 'vectorscope' ? height : width;\n return (\n <figure key={kind} className=\"m-0 flex min-w-0 max-w-full flex-col gap-1\">\n <canvas ref={(el) => void (canvases.current[kind] = el)} width={w} height={height} className=\"rounded border border-border bg-black\" style={{ width: w, maxWidth: '100%', height: 'auto', aspectRatio: `${w} / ${height}` }} aria-label={LABELS[kind]} data-scope={kind} />\n <figcaption className=\"text-[11px] text-muted-foreground\">{LABELS[kind]}</figcaption>\n </figure>\n );\n })}\n </div>\n {reading.ok ? (\n <div className=\"flex flex-col gap-0.5\" data-scope-stats=\"\">\n <div className=\"tabular-nums\">\n Luma {reading.stats.luma.mean.toFixed(2)} mean · {reading.stats.luma.p1.toFixed(2)}–{reading.stats.luma.p99.toFixed(2)} · crushed {pct(reading.stats.clipped.shadows)} · blown {pct(reading.stats.clipped.highlights)} · average{' '}\n <span className=\"inline-block h-2.5 w-2.5 rounded-sm align-middle\" style={{ background: reading.stats.average }} /> {reading.stats.average}\n {!reading.complete && <span className=\"text-muted-foreground\"> · loading</span>}\n </div>\n {reading.notes.map((n) => (\n <div key={n} className=\"text-amber-500\">\n {n}\n </div>\n ))}\n </div>\n ) : (\n <div className=\"text-muted-foreground\" data-scope-message=\"\">\n {reading.message}\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport { formatVideoTimecode, type VideoEditorController } from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoTransportProps {\n controller: VideoEditorController;\n /** Show the editing buttons (split, delete, ripple delete, undo, redo; default true). */\n editable?: boolean;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * Play / pause, a frame back and forward, the playhead and total length as timecode, and the\n * edits that work on the playhead and the selection: split, delete, ripple delete, undo and redo.\n */\nexport function VideoTransport({ controller, editable = true, className = '' }: VideoTransportProps) {\n const state = useVideoEditorState(controller);\n const { time, duration, playing, project, selection, readOnly } = state;\n const canEdit = editable && !readOnly;\n return (\n <div className={`flex flex-wrap items-center gap-1.5 text-xs ${className}`} data-video-transport=\"\">\n <button type=\"button\" className={btn} onClick={() => controller.step(-1)} aria-label=\"Previous frame\" title=\"Previous frame (←)\" data-step-back=\"\">\n ◀|\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} title=\"Play / pause (Space)\" disabled={duration <= 0} data-play=\"\">\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.step(1)} aria-label=\"Next frame\" title=\"Next frame (→)\" data-step-forward=\"\">\n |▶\n </button>\n <span className=\"px-1 tabular-nums text-muted-foreground\" data-timecode=\"\">\n {formatVideoTimecode(time, project.fps)} / {formatVideoTimecode(duration, project.fps)}\n </span>\n {editable && (\n <>\n <span className=\"mx-1 h-4 w-px bg-border\" />\n <button type=\"button\" className={btn} onClick={() => controller.splitAtPlayhead()} disabled={!canEdit} title=\"Split at the playhead (S)\" data-split=\"\">\n Split\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.deleteSelection()} disabled={!canEdit || !selection.length} title=\"Delete the selected clips (Delete)\" data-delete=\"\">\n Delete\n </button>\n <button\n type=\"button\"\n className={btn}\n onClick={() => controller.deleteSelection({ ripple: true })}\n disabled={!canEdit || !selection.length}\n title=\"Delete the selected clips and close the gaps (Shift+Delete)\"\n data-ripple-delete=\"\"\n >\n Ripple delete\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!canEdit || !state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!canEdit || !state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n </>\n )}\n </div>\n );\n}\n","import React, { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport {\n planVideoClipDrag,\n videoDragLabel,\n videoAssetMap,\n videoClipLabel,\n videoClipShowsWaveform,\n videoClipWaveformPath,\n videoClipTint,\n videoDropTracks,\n videoRulerTicks,\n formatVideoSeconds,\n type VideoClip,\n type VideoClipDragMode,\n type VideoAsset,\n type VideoClipDragPlan,\n type VideoMediaClip,\n type VideoEditorController,\n type VideoTrack,\n type VideoWaveformMode,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface VideoTimelineProps {\n controller: VideoEditorController;\n /** Zoom: pixels per second of timeline. With `onPxPerSecondChange` the host owns it; otherwise it is the starting zoom (default 100). */\n pxPerSecond?: number;\n /** Called when the zoom control changes. Without it the timeline keeps its own zoom and shows a zoom slider. */\n onPxPerSecondChange?: (pxPerSecond: number) => void;\n /** Allow selecting, dragging, trimming and the track toggles (default true). */\n editable?: boolean;\n /** Draw waveforms in audio clips (default), in every clip with sound (`all`), or not at all. Sound is decoded once per asset through `controller.audioPeaks`. */\n waveforms?: VideoWaveformMode;\n className?: string;\n}\n\nconst HEADER = 150;\nconst RULER = 24;\nconst ROW = 44;\nconst HANDLE = 6;\nconst DRAG_THRESHOLD = 3;\nconst MIN_ZOOM = 10;\nconst MAX_ZOOM = 400;\n\ninterface Drag {\n clip: string;\n mode: VideoClipDragMode;\n x: number;\n pointer: number;\n moved: boolean;\n plan: VideoClipDragPlan | null;\n}\n\n/** A clip's sound drawn behind its label, once its asset's peaks have loaded. */\nfunction ClipWaveform({ controller, clip, asset, width, height }: { controller: VideoEditorController; clip: VideoMediaClip; asset: VideoAsset; width: number; height: number }) {\n const peaks = useSyncExternalStore(\n (notify) => controller.audioPeaks.subscribe(notify),\n () => controller.audioPeaks.peek(asset),\n () => undefined,\n );\n useEffect(() => {\n controller.audioPeaks.load(asset).catch(() => {});\n }, [controller, asset]);\n const d = useMemo(() => (peaks ? videoClipWaveformPath(clip, peaks, width, height) : ''), [peaks, clip, width, height]);\n if (!d) return null;\n return (\n <svg className=\"pointer-events-none absolute inset-0\" width={width} height={height} aria-hidden=\"true\" data-waveform={clip.id}>\n <path d={d} fill=\"currentColor\" fillOpacity={0.45} />\n </svg>\n );\n}\n\nconst isField = (el: EventTarget | null) => el instanceof HTMLElement && /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName);\n\n/**\n * The tracks of a `VideoEditorController` laid out in time: a ruler with markers (click or drag it\n * to scrub), a playhead, and one row per track with its toggles (mute, hide, lock) and its clips.\n * Click a clip to select it (Shift / Cmd to add or remove it), drag it to move it (onto another\n * track of the same kind too; hold Alt to insert, pushing later material along on every sync-locked\n * track, or Shift to overwrite what is underneath), drag an edge to trim it (Alt to ripple). Moves snap to clip edges,\n * markers, the playhead and frames. Every edit is one undo step; refused edits show why.\n *\n * Keyboard (when focused): Space plays, ←/→ step a frame, S splits at the playhead, Delete removes\n * the selection (Shift to ripple), Cmd/Ctrl+Z undoes, Shift+Cmd/Ctrl+Z redoes.\n */\nexport function VideoTimeline({ controller, pxPerSecond, onPxPerSecondChange, editable = true, waveforms = 'audio', className = '' }: VideoTimelineProps) {\n const state = useVideoEditorState(controller);\n const { project, duration, time, selection, readOnly, error } = state;\n const [ownZoom, setOwnZoom] = useState(pxPerSecond ?? 100);\n const px = onPxPerSecondChange ? (pxPerSecond ?? 100) : ownZoom;\n const canEdit = editable && !readOnly;\n const [drag, setDrag] = useState<Drag | null>(null);\n const dragRef = useRef<Drag | null>(null);\n const rows = useRef(new Map<string, HTMLDivElement>());\n const ruler = useRef<HTMLDivElement>(null);\n const assets = videoAssetMap(project);\n const msToPx = (ms: number) => (ms * px) / 1000;\n const span = Math.max(duration + 5000, 10000);\n const width = msToPx(span);\n const ticks = videoRulerTicks(span, px, project.fps);\n\n const seekAt = (clientX: number) => {\n const box = ruler.current!.getBoundingClientRect();\n controller.seek(Math.max(0, ((clientX - box.left) * 1000) / px));\n };\n\n const trackAt = (clipId: string, clientY: number): string | undefined => {\n const allowed = videoDropTracks(project, clipId);\n for (const [id, el] of rows.current) {\n const box = el.getBoundingClientRect();\n if (clientY >= box.top && clientY < box.bottom && allowed.includes(id)) return id;\n }\n return undefined;\n };\n\n const planFor = (d: Drag, e: { clientX: number; clientY: number; altKey: boolean; shiftKey: boolean }) =>\n planVideoClipDrag(project, {\n clip: d.clip,\n mode: d.mode,\n delta: ((e.clientX - d.x) * 1000) / px,\n track: d.mode === 'move' ? trackAt(d.clip, e.clientY) : undefined,\n ripple: e.altKey,\n placement: e.altKey ? 'insert' : e.shiftKey ? 'overwrite' : 'refuse',\n snap: (t) => controller.snap(t, { exclude: [d.clip] }).time,\n });\n\n const update = (next: Drag | null) => {\n dragRef.current = next;\n setDrag(next);\n };\n\n // The latest render's values, for the window listeners of a drag in progress.\n const live = useRef({ planFor, selection });\n live.current = { planFor, selection };\n const stopDrag = useRef<(() => void) | null>(null);\n useEffect(() => () => stopDrag.current?.(), []);\n\n const onClipPointerDown = (e: React.PointerEvent<HTMLDivElement>, clip: VideoClip, track: VideoTrack) => {\n if (e.button !== undefined && e.button !== 0) return;\n e.stopPropagation();\n if (!editable) return;\n try {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n } catch {\n // No pointer to capture (synthetic events).\n }\n const handle = (e.target as HTMLElement).closest('[data-handle]')?.getAttribute('data-handle');\n const mode: VideoClipDragMode = handle === 'start' ? 'trim-start' : handle === 'end' ? 'trim-end' : 'move';\n const fixed = !canEdit || !!track.locked;\n stopDrag.current?.();\n update({ clip: clip.id, mode, x: e.clientX, pointer: e.pointerId, moved: false, plan: null });\n // Follow the pointer on the window: the block may move to another track's row (a new element) mid-drag.\n const move = (ev: PointerEvent) => {\n const d = dragRef.current;\n if (!d || fixed) return;\n if (!d.moved && Math.abs(ev.clientX - d.x) < DRAG_THRESHOLD) return;\n if (!d.moved && !live.current.selection.includes(d.clip)) controller.select([d.clip]);\n update({ ...d, moved: true, plan: live.current.planFor(d, ev) });\n };\n const up = (ev: PointerEvent) => {\n stop();\n const d = dragRef.current;\n if (!d) return;\n update(null);\n if (!d.moved) {\n if (ev.shiftKey || ev.metaKey || ev.ctrlKey) controller.select([d.clip], { add: true });\n else controller.select([d.clip]);\n return;\n }\n const plan = live.current.planFor(d, ev);\n if (plan?.edit) controller.apply(plan.edit, videoDragLabel(plan.edit));\n };\n const cancel = () => {\n stop();\n update(null);\n };\n const stop = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n window.removeEventListener('pointercancel', cancel);\n stopDrag.current = null;\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n window.addEventListener('pointercancel', cancel);\n stopDrag.current = stop;\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (isField(e.target)) return;\n const mod = e.metaKey || e.ctrlKey;\n const key = e.key.toLowerCase();\n if (e.key === ' ') {\n if ((e.target as HTMLElement).tagName === 'BUTTON') return;\n controller.toggle();\n } else if (e.key === 'ArrowLeft' && !mod) controller.step(-1);\n else if (e.key === 'ArrowRight' && !mod) controller.step(1);\n else if (e.key === 'Escape') controller.select(null);\n else if (!canEdit) return;\n else if (key === 's' && !mod) controller.splitAtPlayhead();\n else if ((e.key === 'Delete' || e.key === 'Backspace') && !mod) controller.deleteSelection({ ripple: e.shiftKey });\n else if (key === 'z' && mod) {\n if (e.shiftKey) controller.redo();\n else controller.undo();\n } else return;\n e.preventDefault();\n };\n\n // Where each clip is drawn: the dragged one follows the plan (possibly on another track).\n const placed = project.tracks.map((track) => ({\n track,\n clips: project.tracks.flatMap((t) =>\n t.clips\n .map((clip) => {\n const plan = drag?.moved && drag.clip === clip.id ? drag.plan : null;\n const on = plan ? plan.track : t.id;\n return on === track.id ? { clip, home: t, start: plan ? plan.start : clip.start, duration: plan ? plan.duration : clip.duration, dragging: !!plan } : null;\n })\n .filter((x): x is NonNullable<typeof x> => x !== null),\n ),\n }));\n\n const toggle = (track: VideoTrack, field: 'muted' | 'hidden' | 'locked', label: string) => (\n <button\n type=\"button\"\n className={`rounded border px-1 text-[10px] leading-4 ${track[field] ? 'border-rose-500 bg-rose-500/15 text-rose-600' : 'border-border text-muted-foreground'} disabled:opacity-40`}\n aria-pressed={!!track[field]}\n aria-label={`${label} ${track.name ?? track.id}`}\n title={label}\n disabled={!canEdit}\n data-track-toggle={field}\n onClick={() => controller.apply({ op: 'update_track', track: track.id, set: { [field]: !track[field] } }, `${track[field] ? 'Un' : ''}${field === 'muted' ? 'mute' : field === 'hidden' ? 'hide' : 'lock'} track`)}\n >\n {field === 'muted' ? 'M' : field === 'hidden' ? 'H' : 'L'}\n </button>\n );\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-video-timeline-wrapper=\"\">\n {!onPxPerSecondChange && (\n <label className=\"flex items-center gap-2 self-end text-xs text-muted-foreground\">\n Zoom\n <input type=\"range\" min={MIN_ZOOM} max={MAX_ZOOM} step={5} value={ownZoom} aria-label=\"Timeline zoom\" onChange={(e) => setOwnZoom(Number(e.target.value))} data-zoom=\"\" />\n </label>\n )}\n <div\n className=\"relative overflow-x-auto rounded border border-border outline-none focus-visible:ring-2 focus-visible:ring-rose-500/50\"\n tabIndex={0}\n role=\"group\"\n aria-label=\"Video timeline\"\n onKeyDown={onKeyDown}\n data-video-timeline=\"\"\n >\n <div className=\"relative\" style={{ width: HEADER + width }}>\n <div className=\"flex\" style={{ height: RULER }}>\n <div className=\"sticky left-0 z-20 shrink-0 border-b border-r border-border bg-background\" style={{ width: HEADER }} />\n <div\n ref={ruler}\n className=\"relative shrink-0 cursor-ew-resize select-none touch-none border-b border-border text-[10px] text-muted-foreground\"\n style={{ width }}\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n data-ruler=\"\"\n onPointerDown={(e) => {\n try {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n } catch {\n // No pointer to capture (synthetic events).\n }\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n >\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: t.x }} data-tick={t.time}>\n {t.label && <span className=\"absolute -top-3.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n {(project.markers ?? []).map((m) => (\n <div\n key={m.id}\n className=\"absolute top-0 h-2.5 w-2.5 -translate-x-1/2 rotate-45\"\n style={{ left: msToPx(m.time), background: m.color ?? '#f59e0b' }}\n title={`${m.label ?? m.id} at ${formatVideoSeconds(m.time)}`}\n data-marker={m.id}\n />\n ))}\n </div>\n </div>\n {placed.map(({ track, clips }) => (\n <div key={track.id} className=\"flex border-b border-border last:border-b-0\" style={{ height: ROW }} data-track={track.id}>\n <div className=\"sticky left-0 z-20 flex shrink-0 flex-col justify-center gap-0.5 border-r border-border bg-background px-2 text-xs\" style={{ width: HEADER }} data-track-header=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"truncate font-medium\">{track.name ?? track.id}</span>\n <span className=\"rounded bg-muted px-1 text-[10px] uppercase text-muted-foreground\" data-track-kind=\"\">\n {track.kind}\n </span>\n </div>\n {editable && (\n <div className=\"flex gap-1\">\n {toggle(track, 'muted', 'Mute')}\n {track.kind === 'video' && toggle(track, 'hidden', 'Hide')}\n {toggle(track, 'locked', 'Lock')}\n </div>\n )}\n </div>\n <div\n ref={(el) => {\n if (el) rows.current.set(track.id, el);\n else rows.current.delete(track.id);\n }}\n className={`relative shrink-0 ${track.hidden ? 'opacity-50' : ''} ${track.locked ? 'bg-muted/40' : ''}`}\n style={{ width }}\n data-track-lane={track.id}\n onPointerDown={(e) => {\n if (e.target === e.currentTarget && editable) controller.select(null);\n }}\n >\n {clips.map(({ clip, home, start, duration: length, dragging }) => {\n const asset = clip.type === 'media' ? assets.get(clip.asset) : undefined;\n const selected = selection.includes(clip.id);\n const label = videoClipLabel(clip, asset);\n return (\n <div\n key={clip.id}\n className={`absolute top-1 bottom-1 select-none touch-none overflow-hidden rounded text-[11px] text-white ${canEdit && !home.locked ? 'cursor-grab' : 'cursor-default'} ${dragging ? 'opacity-80 shadow-lg' : ''}`}\n style={{\n left: msToPx(start),\n width: Math.max(2, msToPx(length)),\n background: videoClipTint(clip, asset),\n outline: selected ? '2px solid #f43f5e' : undefined,\n outlineOffset: selected ? 1 : undefined,\n zIndex: dragging ? 10 : selected ? 2 : 1,\n }}\n title={`${label} · ${formatVideoSeconds(start)}–${formatVideoSeconds(start + length)}`}\n data-clip={clip.id}\n data-selected={selected ? '' : undefined}\n data-dragging={dragging ? '' : undefined}\n aria-selected={selected}\n onPointerDown={(e) => onClipPointerDown(e, clip, home)}\n >\n {videoClipShowsWaveform(clip, asset, waveforms) && <ClipWaveform controller={controller} clip={clip as VideoMediaClip} asset={asset} width={Math.max(2, msToPx(clip.duration))} height={ROW - 8} />}\n <span className=\"pointer-events-none relative block truncate px-1.5 py-0.5 leading-4\">{label}</span>\n {clip.transition && (\n <span className=\"pointer-events-none absolute left-1 bottom-0.5 rounded bg-black/40 px-1 text-[9px] leading-3\" title={`${clip.transition.type} ${clip.transition.duration} ms`} data-transition={clip.transition.type}>\n ⧓ {clip.transition.type}\n </span>\n )}\n {canEdit && !home.locked && (\n <>\n <div className=\"absolute inset-y-0 left-0 cursor-ew-resize bg-white/0 hover:bg-white/40\" style={{ width: HANDLE }} data-handle=\"start\" aria-hidden=\"true\" />\n <div className=\"absolute inset-y-0 right-0 cursor-ew-resize bg-white/0 hover:bg-white/40\" style={{ width: HANDLE }} data-handle=\"end\" aria-hidden=\"true\" />\n </>\n )}\n </div>\n );\n })}\n </div>\n </div>\n ))}\n <div className=\"pointer-events-none absolute top-0 bottom-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: HEADER + msToPx(time), zIndex: 15 }} data-playhead=\"\" />\n </div>\n </div>\n {error && (\n <p className=\"text-xs text-red-500\" role=\"alert\" data-edit-error=\"\">\n {error}\n </p>\n )}\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport {\n findVideoClip,\n formatVideoSeconds,\n VIDEO_CLIP_ANIMATION_EFFECTS,\n VIDEO_CLIP_ANIMATION_LABELS,\n normalizeVideoGrade,\n VIDEO_GRADE_CONTROLS,\n VIDEO_GRADE_PRESET_NAMES,\n videoGradeLook,\n videoLutEdits,\n VIDEO_BLEND_MODE_LABELS,\n VIDEO_BLEND_MODES,\n VIDEO_FADE_CURVE_LABELS,\n VIDEO_FADE_CURVES,\n VIDEO_TRANSITION_LABELS,\n VIDEO_TRANSITION_TYPES,\n VIDEO_WIPE_DIRECTIONS,\n videoTransitionHasDirection,\n videoFreezeFrameEdit,\n videoKeyframeRows,\n videoSlowMotionRamp,\n videoSpeedRampEdit,\n videoTransitionAudioCurve,\n videoKeyframeToggleEdit,\n videoKeyframeValueEdit,\n type VideoClip,\n type VideoClipAnimationEffect,\n type VideoEditorController,\n type VideoFadeCurve,\n type VideoGradeLut,\n type VideoGradePreset,\n type VideoTransitionType,\n type VideoWipeDirection,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface ClipInspectorProps {\n controller: VideoEditorController;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst field = 'w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs disabled:opacity-50';\nconst DEFAULT_TRANSITION = 500;\n\n/** An input (or textarea) that commits on blur or Enter, and resets when its value changes from outside. */\nfunction Commit({\n value,\n onCommit,\n multiline,\n ...rest\n}: { value: string; onCommit: (raw: string) => void; multiline?: boolean } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n const commit = (raw: string) => {\n if (raw !== value) onCommit(raw);\n };\n if (multiline)\n return (\n <textarea\n key={value}\n className={field}\n rows={2}\n defaultValue={value}\n disabled={rest.disabled}\n aria-label={rest['aria-label']}\n onBlur={(e) => commit(e.currentTarget.value)}\n />\n );\n return <input key={value} className={field} {...rest} defaultValue={value} onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()} onBlur={(e) => commit(e.currentTarget.value)} />;\n}\n\n/**\n * A grade's LUT: a `.cube` path or URL (checked by loading it), or a file read in place (its name\n * becomes the `src`, so keep the file beside the export), its strength, and a button to remove it.\n */\nfunction LutControls({ controller, clip, disabled }: { controller: VideoEditorController; clip: VideoClip; disabled: boolean }) {\n const [message, setMessage] = useState<string | null>(null);\n const lut = clip.grade?.lut;\n const apply = (setting: VideoGradeLut | null, label: string) => {\n const r = controller.apply(videoLutEdits(controller.getProject(), [clip.id], setting), label);\n setMessage(r.ok ? null : r.error);\n };\n const choose = async (src: string) => {\n if (!src) return lut && apply(null, 'Remove LUT');\n try {\n const table = await controller.luts.load(src);\n apply({ src, ...(lut?.strength !== undefined ? { strength: lut.strength } : {}), ...(table.title ? { name: table.title } : {}) }, 'Apply LUT');\n } catch (e) {\n setMessage(e instanceof Error ? e.message : String(e));\n }\n };\n const readFile = async (file: File | undefined) => {\n if (!file) return;\n try {\n const table = controller.luts.set(file.name, await file.text());\n apply({ src: file.name, ...(lut?.strength !== undefined ? { strength: lut.strength } : {}), ...(table.title ? { name: table.title } : {}) }, 'Apply LUT');\n } catch (e) {\n setMessage(`${file.name}: ${e instanceof Error ? e.message : String(e)}`);\n }\n };\n return (\n <>\n <Row label=\"LUT\" name=\"grade.lut\">\n <div className=\"flex min-w-0 gap-1\">\n <Commit value={lut?.src ?? ''} placeholder=\"look.cube\" aria-label=\"LUT file\" disabled={disabled} onCommit={(raw) => void choose(raw.trim())} />\n <label className={`${btn} cursor-pointer whitespace-nowrap`} title=\"Load a .cube file\">\n Load\n <input type=\"file\" accept=\".cube\" className=\"sr-only\" disabled={disabled} aria-label=\"Load a .cube LUT\" onChange={(e) => void readFile(e.currentTarget.files?.[0])} />\n </label>\n {lut && (\n <button type=\"button\" className={btn} disabled={disabled} aria-label=\"Remove LUT\" onClick={() => apply(null, 'Remove LUT')}>\n ✕\n </button>\n )}\n </div>\n </Row>\n {lut && (\n <Row label=\"LUT strength\" name=\"grade.lut.strength\">\n <Commit\n type=\"number\"\n min={0}\n max={1}\n step={0.05}\n value={String(lut.strength ?? 1)}\n aria-label=\"LUT strength\"\n disabled={disabled}\n onCommit={(raw) => {\n const n = Number(raw);\n // A strength of 0 changes nothing, so it takes the LUT off.\n if (raw.trim() && Number.isFinite(n)) apply(n > 0 ? { ...lut, strength: Math.min(1, n) } : null, n > 0 ? 'Change LUT strength' : 'Remove LUT');\n }}\n />\n </Row>\n )}\n {message && (\n <p className=\"text-xs text-red-500\" role=\"alert\" data-lut-error=\"\">\n {message}\n </p>\n )}\n </>\n );\n}\n\nfunction Row({ label, name, children }: { label: string; name: string; children: React.ReactNode }) {\n return (\n <label className=\"grid grid-cols-[5.5rem_minmax(0,1fr)] items-center gap-2 text-xs\" data-field={name}>\n <span className=\"text-muted-foreground\">{label}</span>\n {children}\n </label>\n );\n}\n\n/**\n * Edits the one selected clip: its name, fades, opacity, volume and transform (each with a keyframe\n * toggle at the playhead: ◆ adds a key holding the value there or removes the one there; typing a\n * value on a keyed property sets the key at the playhead); volume, speed and mute for media;\n * text, colour, size and background for titles; colour for colour clips; and the transition into\n * it. Each change is one undo step (`update_clip` / `set_transition`), committed on blur or change.\n */\nexport function ClipInspector({ controller, className = '' }: ClipInspectorProps) {\n const state = useVideoEditorState(controller);\n const { project, selection, readOnly, time } = state;\n if (selection.length !== 1)\n return (\n <p className={`text-xs text-muted-foreground ${className}`} data-clip-inspector=\"\">\n {selection.length ? `${selection.length} clips selected. Select one clip to edit it.` : 'Select a clip on the timeline to edit it.'}\n </p>\n );\n const at = findVideoClip(project, selection[0]);\n if (!at) return null;\n const clip: VideoClip = at.clip;\n const disabled = readOnly || !!at.track.locked;\n\n const set = (key: string, value: unknown, label = `Change ${key}`) => {\n if (value === undefined || value === '') controller.apply({ op: 'update_clip', clip: clip.id, remove: [key] }, label);\n else controller.apply({ op: 'update_clip', clip: clip.id, set: { [key]: value } }, label);\n };\n const num = (key: string, raw: string, label?: string) => {\n const trimmed = raw.trim();\n if (!trimmed) return set(key, undefined, label);\n const n = Number(trimmed);\n if (Number.isFinite(n)) set(key, n, label);\n };\n const text = (key: string, label?: string) => {\n const value = (clip as unknown as Record<string, unknown>)[key];\n return (\n <Commit value={value === undefined ? '' : String(value)} aria-label={label ?? key} disabled={disabled} onCommit={(raw) => set(key, raw.trim() || undefined, `Change ${label ?? key}`)} />\n );\n };\n const number = (key: string, label: string, attrs: { min?: number; max?: number; step?: number } = {}) => {\n const value = (clip as unknown as Record<string, unknown>)[key];\n return <Commit type=\"number\" value={value === undefined ? '' : String(value)} aria-label={label} disabled={disabled} onCommit={(raw) => num(key, raw, `Change ${label.toLowerCase()}`)} {...attrs} />;\n };\n\n const transition = clip.transition;\n return (\n <div className={`flex flex-col gap-1.5 ${className}`} data-clip-inspector=\"\" data-clip-id={clip.id}>\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"font-medium\">{clip.type === 'media' ? 'Media clip' : clip.type === 'text' ? 'Title' : 'Colour clip'}</span>\n <code className=\"text-muted-foreground\">{clip.id}</code>\n {at.track.locked && <span className=\"text-amber-500\">locked track</span>}\n </div>\n <Row label=\"Name\" name=\"name\">\n {text('name', 'Name')}\n </Row>\n <Row label=\"Start\" name=\"start\">\n <span className=\"tabular-nums text-xs\">{formatVideoSeconds(clip.start)}</span>\n </Row>\n <Row label=\"Duration\" name=\"duration\">\n <span className=\"tabular-nums text-xs\">{formatVideoSeconds(clip.duration)}</span>\n </Row>\n {videoKeyframeRows(project, clip.id, time).map((row) => (\n <Row key={row.property} label={row.label} name={row.property}>\n <span className=\"flex min-w-0 items-center gap-1\" data-keyframe-row={row.property}>\n <Commit\n type=\"number\"\n value={row.keyed || (row.property === 'opacity' ? clip.opacity : row.property === 'volume' ? (clip as { volume?: unknown }).volume : clip.transform?.[row.property]) !== undefined ? String(row.value) : ''}\n placeholder={String(row.value)}\n aria-label={row.label}\n disabled={disabled}\n min={row.min}\n max={row.max}\n step={row.step}\n onCommit={(raw) => {\n const n = Number(raw);\n if (raw.trim() && !Number.isFinite(n)) return;\n const edit = videoKeyframeValueEdit(project, clip.id, row.property, time, raw.trim() ? n : undefined);\n if (edit) controller.apply(edit, row.keyed ? `Keyframe ${row.label.toLowerCase()}` : `Change ${row.label.toLowerCase()}`);\n }}\n />\n <button\n type=\"button\"\n className={`shrink-0 rounded px-1 text-xs disabled:opacity-50 ${row.onKey ? 'text-amber-500' : row.keyed ? 'text-foreground' : 'text-muted-foreground'}`}\n aria-label={`${row.onKey ? 'Remove' : 'Add'} ${row.label.toLowerCase()} keyframe at playhead`}\n aria-pressed={row.onKey}\n title={row.keyed ? `${row.keys} key${row.keys === 1 ? '' : 's'}; ${row.onKey ? 'remove the one' : 'add one'} at the playhead` : 'Animate: add a key at the playhead'}\n disabled={disabled}\n data-keyframe-toggle={row.property}\n onClick={() => {\n const edit = videoKeyframeToggleEdit(project, clip.id, row.property, time);\n if (edit) controller.apply(edit, `${row.onKey ? 'Remove' : 'Add'} ${row.label.toLowerCase()} keyframe`);\n }}\n >\n {row.onKey ? '◆' : '◇'}\n </button>\n {row.keyed && (\n <span className=\"shrink-0 text-[10px] tabular-nums text-muted-foreground\" data-keyframe-count={row.property}>\n {row.keys}\n </span>\n )}\n </span>\n </Row>\n ))}\n {at.track.kind === 'video' && (\n <Row label=\"Blend\" name=\"blend\">\n <select className={field} value={clip.blend ?? 'normal'} disabled={disabled} aria-label=\"Blend mode\" onChange={(e) => set('blend', e.target.value === 'normal' ? undefined : e.target.value, 'Change blend mode')}>\n {VIDEO_BLEND_MODES.map((m) => (\n <option key={m} value={m}>\n {VIDEO_BLEND_MODE_LABELS[m]}\n </option>\n ))}\n </select>\n </Row>\n )}\n {at.track.kind === 'video' && (\n <>\n <Row label=\"Look\" name=\"gradePreset\">\n <select\n className={field}\n value=\"\"\n disabled={disabled}\n aria-label=\"Apply a look\"\n onChange={(e) => {\n const grade = videoGradeLook(clip.grade, e.target.value as VideoGradePreset);\n if (grade) controller.apply({ op: 'update_clip', clip: clip.id, set: { grade } }, `Apply ${e.target.value} look`);\n }}\n >\n <option value=\"\">{clip.grade ? 'Graded' : 'None'}</option>\n {VIDEO_GRADE_PRESET_NAMES.map((name) => (\n <option key={name} value={name}>\n {name.replace(/-/g, ' ')}\n </option>\n ))}\n </select>\n </Row>\n {VIDEO_GRADE_CONTROLS.map((c) => (\n <Row key={c.key} label={c.label} name={`grade.${c.key}`}>\n <Commit\n type=\"number\"\n min={c.min}\n max={c.max}\n step={c.step}\n value={clip.grade?.[c.key] === undefined ? '' : String(clip.grade[c.key])}\n placeholder=\"0\"\n aria-label={c.label}\n disabled={disabled}\n onCommit={(raw) => {\n const n = raw.trim() ? Number(raw) : 0;\n if (!Number.isFinite(n)) return;\n // Out-of-range values are clamped to the control's range.\n const grade = normalizeVideoGrade({ ...clip.grade, [c.key]: n });\n set('grade', grade, `Change ${c.label.toLowerCase()}`);\n }}\n />\n </Row>\n ))}\n <LutControls controller={controller} clip={clip} disabled={disabled} />\n </>\n )}\n {at.track.kind === 'video' &&\n (['animateIn', 'animateOut'] as const).map((key) => (\n <Row key={key} label={key === 'animateIn' ? 'Animate in' : 'Animate out'} name={key}>\n <select\n className={field}\n value={clip[key]?.effect ?? ''}\n disabled={disabled}\n aria-label={key === 'animateIn' ? 'Animate in' : 'Animate out'}\n onChange={(e) => {\n const effect = e.target.value as VideoClipAnimationEffect | '';\n set(key, effect ? { ...clip[key], effect } : undefined, key === 'animateIn' ? 'Change entrance' : 'Change exit');\n }}\n >\n <option value=\"\">None</option>\n {VIDEO_CLIP_ANIMATION_EFFECTS.map((effect) => (\n <option key={effect} value={effect}>\n {VIDEO_CLIP_ANIMATION_LABELS[effect]}\n </option>\n ))}\n </select>\n </Row>\n ))}\n <Row label=\"Fade in (ms)\" name=\"fadeIn\">\n {number('fadeIn', 'Fade in', { min: 0, step: 100 })}\n </Row>\n <Row label=\"Fade out (ms)\" name=\"fadeOut\">\n {number('fadeOut', 'Fade out', { min: 0, step: 100 })}\n </Row>\n {clip.type === 'media' && (\n <>\n <Row label=\"Speed\" name=\"speed\">\n {clip.timeRemap ? (\n <span className=\"flex items-center gap-1\" data-ramped=\"\">\n <span className=\"text-muted-foreground\">ramped</span>\n <button type=\"button\" className={btn} disabled={disabled} onClick={() => controller.apply({ op: 'set_time_remap', clip: clip.id, keys: null, ripple: true }, 'Remove speed ramp')}>\n Remove ramp\n </button>\n </span>\n ) : (\n number('speed', 'Speed', { min: 0.1, step: 0.25 })\n )}\n </Row>\n {project.assets.find((a) => a.id === clip.asset)?.kind !== 'image' && (\n <Row label=\"Retime\" name=\"retime\">\n <span className=\"flex flex-wrap gap-1\">\n <button\n type=\"button\"\n className={btn}\n disabled={disabled || time < clip.start || time > clip.start + clip.duration}\n title=\"Hold the frame at the playhead for a second, pushing later clips along\"\n onClick={() => controller.apply(videoFreezeFrameEdit(clip, time - clip.start, 1000), 'Freeze frame')}\n >\n Freeze 1 s here\n </button>\n <button type=\"button\" className={btn} disabled={disabled} title=\"Normal speed, then a glide into 0.3× slow motion\" onClick={() => controller.apply(videoSpeedRampEdit(clip, videoSlowMotionRamp(clip.duration)), 'Speed ramp')}>\n Slow-mo ramp\n </button>\n </span>\n </Row>\n )}\n <Row label=\"Muted\" name=\"muted\">\n <input type=\"checkbox\" className=\"justify-self-start\" checked={!!clip.muted} disabled={disabled} aria-label=\"Muted\" onChange={(e) => set('muted', e.target.checked || undefined, e.target.checked ? 'Mute clip' : 'Unmute clip')} />\n </Row>\n {(['fadeInCurve', 'fadeOutCurve'] as const).map((key) =>\n (key === 'fadeInCurve' ? clip.fadeIn : clip.fadeOut) ? (\n <Row key={key} label={key === 'fadeInCurve' ? 'Fade in sound' : 'Fade out sound'} name={key}>\n <select\n className={field}\n value={clip[key] ?? 'linear'}\n disabled={disabled}\n aria-label={key === 'fadeInCurve' ? 'Fade in curve' : 'Fade out curve'}\n onChange={(e) => {\n const curve = e.target.value as VideoFadeCurve;\n set(key, curve === 'linear' ? undefined : curve, key === 'fadeInCurve' ? 'Change fade in curve' : 'Change fade out curve');\n }}\n >\n {VIDEO_FADE_CURVES.map((c) => (\n <option key={c} value={c}>\n {VIDEO_FADE_CURVE_LABELS[c]}\n </option>\n ))}\n </select>\n </Row>\n ) : null,\n )}\n </>\n )}\n {clip.type === 'text' && (\n <>\n <Row label=\"Text\" name=\"text\">\n <Commit multiline value={clip.text} aria-label=\"Text\" disabled={disabled} onCommit={(raw) => set('text', raw, 'Change text')} />\n </Row>\n <Row label=\"Colour\" name=\"color\">\n {text('color', 'Colour')}\n </Row>\n <Row label=\"Font size\" name=\"fontSize\">\n {number('fontSize', 'Font size', { min: 1, step: 2 })}\n </Row>\n <Row label=\"Background\" name=\"background\">\n {text('background', 'Background')}\n </Row>\n </>\n )}\n {clip.type === 'color' && (\n <Row label=\"Colour\" name=\"color\">\n <Commit value={clip.color} aria-label=\"Colour\" disabled={disabled} onCommit={(raw) => raw.trim() && set('color', raw.trim(), 'Change colour')} />\n </Row>\n )}\n <Row label=\"Transition in\" name=\"transition\">\n <select\n className={field}\n value={transition?.type ?? ''}\n disabled={disabled}\n aria-label=\"Transition\"\n onChange={(e) => {\n const type = e.target.value as VideoTransitionType | '';\n controller.apply(\n { op: 'set_transition', clip: clip.id, transition: type ? { ...transition, type, duration: transition?.duration ?? DEFAULT_TRANSITION } : null },\n type ? 'Set transition' : 'Remove transition',\n );\n }}\n >\n <option value=\"\">None</option>\n {VIDEO_TRANSITION_TYPES.map((t) => (\n <option key={t} value={t}>\n {VIDEO_TRANSITION_LABELS[t]}\n </option>\n ))}\n </select>\n </Row>\n {transition && (\n <Row label=\"Length (ms)\" name=\"transitionDuration\">\n <Commit\n type=\"number\"\n min={1}\n step={100}\n value={String(transition.duration)}\n aria-label=\"Transition length\"\n disabled={disabled}\n onCommit={(raw) => {\n const n = Number(raw);\n if (raw.trim() && Number.isFinite(n) && n > 0) controller.apply({ op: 'set_transition', clip: clip.id, transition: { ...transition, duration: n } }, 'Change transition length');\n }}\n />\n </Row>\n )}\n {transition && videoTransitionHasDirection(transition.type) && (\n <Row label=\"Direction\" name=\"transitionDirection\">\n <select\n className={field}\n value={transition.direction ?? 'right'}\n disabled={disabled}\n aria-label=\"Transition direction\"\n onChange={(e) => controller.apply({ op: 'set_transition', clip: clip.id, transition: { ...transition, direction: e.target.value as VideoWipeDirection } }, 'Change transition direction')}\n >\n {VIDEO_WIPE_DIRECTIONS.map((d) => (\n <option key={d} value={d}>\n {d}\n </option>\n ))}\n </select>\n </Row>\n )}\n {transition && (\n <Row label=\"Transition sound\" name=\"transitionAudioCurve\">\n <select\n className={field}\n value={videoTransitionAudioCurve(transition)}\n disabled={disabled}\n aria-label=\"Transition sound curve\"\n onChange={(e) => {\n const { audioCurve: _, ...rest } = transition;\n const curve = e.target.value as VideoFadeCurve;\n // The type's own default is stored as no curve, so it follows the type if that changes.\n const next = curve === videoTransitionAudioCurve(rest) ? rest : { ...rest, audioCurve: curve };\n controller.apply({ op: 'set_transition', clip: clip.id, transition: next }, 'Change transition sound');\n }}\n >\n {VIDEO_FADE_CURVES.map((c) => (\n <option key={c} value={c}>\n {VIDEO_FADE_CURVE_LABELS[c]}\n </option>\n ))}\n </select>\n </Row>\n )}\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport {\n formatVideoSeconds,\n probeVideoMedia,\n videoAssetDropEdit,\n videoAssetKindOf,\n type VideoAsset,\n type VideoAssetKind,\n type VideoEditorController,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface MediaBinProps {\n controller: VideoEditorController;\n /** Show the import controls and \"Add to timeline\" buttons (default true). */\n editable?: boolean;\n /** Turns a file into a URL the preview and exporter can open (default `URL.createObjectURL`). */\n fileToUrl?: (file: File) => string;\n /** Reads a source's length and size (default `probeVideoMedia`). */\n probe?: typeof probeVideoMedia;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * The project's assets (name, kind, length), each with an \"Add to timeline\" button that puts it at\n * the end of the first unlocked track of its kind. Import media by choosing or dropping files (read\n * as object URLs and probed for their length and size) or by URL. Each import is one undo step.\n */\nexport function MediaBin({ controller, editable = true, fileToUrl, probe = probeVideoMedia, className = '' }: MediaBinProps) {\n const { project, readOnly } = useVideoEditorState(controller);\n const canEdit = editable && !readOnly;\n const [url, setUrl] = useState('');\n const [urlKind, setUrlKind] = useState<VideoAssetKind | ''>('');\n const [busy, setBusy] = useState(0);\n const [problem, setProblem] = useState<string | null>(null);\n const [over, setOver] = useState(false);\n\n const addSource = async (src: string, kind: VideoAssetKind, name: string) => {\n setBusy((n) => n + 1);\n try {\n const found = await probe(src, kind).catch(() => null);\n const result = controller.apply({ op: 'add_asset', asset: { kind, src, name, ...(found ?? {}) } }, `Import ${name}`);\n if (!result.ok) setProblem(result.error);\n } finally {\n setBusy((n) => n - 1);\n }\n };\n\n const addFiles = async (files: FileList | File[] | null) => {\n setProblem(null);\n for (const file of Array.from(files ?? [])) {\n const kind = videoAssetKindOf(file.type || file.name);\n if (!kind) {\n setProblem(`\"${file.name}\" is not a video, audio or image file.`);\n continue;\n }\n const src = fileToUrl ? fileToUrl(file) : URL.createObjectURL(file);\n await addSource(src, kind, file.name);\n }\n };\n\n const addUrl = async () => {\n const src = url.trim();\n if (!src) return;\n const kind = urlKind || videoAssetKindOf(src.replace(/[?#].*$/, ''));\n if (!kind) {\n setProblem(`Can't tell whether \"${src}\" is video, audio or an image; choose its kind.`);\n return;\n }\n setProblem(null);\n await addSource(src, kind, src.replace(/[?#].*$/, '').replace(/^.*[\\\\/]/, '') || src);\n setUrl('');\n };\n\n const addToTimeline = (asset: VideoAsset) => {\n const edit = videoAssetDropEdit(project, asset.id);\n if (!edit) {\n setProblem(`There is no unlocked ${asset.kind === 'audio' ? 'audio' : 'video'} track to put \"${asset.name ?? asset.id}\" on.`);\n return;\n }\n setProblem(null);\n const result = controller.apply(edit, `Add ${asset.name ?? asset.id}`);\n if (result.ok) {\n const added = result.outcomes[0]?.clip;\n if (added) controller.select([added]);\n }\n };\n\n return (\n <div\n className={`flex flex-col gap-2 rounded ${over ? 'ring-2 ring-rose-500/60' : ''} ${className}`}\n data-media-bin=\"\"\n onDragOver={(e) => {\n if (!canEdit || !e.dataTransfer?.types?.includes('Files')) return;\n e.preventDefault();\n setOver(true);\n }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => {\n setOver(false);\n if (!canEdit || !e.dataTransfer?.files?.length) return;\n e.preventDefault();\n void addFiles(e.dataTransfer.files);\n }}\n >\n <div className=\"text-xs font-medium\">Media</div>\n {project.assets.length ? (\n <ul className=\"flex flex-col gap-1\" aria-label=\"Media assets\">\n {project.assets.map((asset) => (\n <li key={asset.id} className=\"flex items-center gap-2 text-xs\" data-asset={asset.id}>\n <span className=\"rounded bg-muted px-1 text-[10px] uppercase text-muted-foreground\" data-asset-kind=\"\">\n {asset.kind}\n </span>\n <span className=\"min-w-0 flex-1 truncate\" title={asset.src}>\n {asset.name ?? asset.id}\n </span>\n {asset.duration !== undefined && <span className=\"tabular-nums text-muted-foreground\">{formatVideoSeconds(asset.duration)}</span>}\n {editable && (\n <button type=\"button\" className={btn} disabled={!canEdit} onClick={() => addToTimeline(asset)} data-add-to-timeline=\"\">\n Add to timeline\n </button>\n )}\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"text-xs text-muted-foreground\">No media yet.{editable ? ' Choose or drop files, or add a URL.' : ''}</p>\n )}\n {editable && (\n <>\n <label className=\"flex flex-col gap-1 rounded border border-dashed border-border p-2 text-xs text-muted-foreground\">\n Choose or drop video, audio or image files\n <input\n type=\"file\"\n multiple\n accept=\"video/*,audio/*,image/*\"\n disabled={!canEdit}\n aria-label=\"Import media files\"\n data-import-files=\"\"\n onChange={(e) => {\n const files = e.currentTarget.files ? Array.from(e.currentTarget.files) : [];\n e.currentTarget.value = '';\n void addFiles(files);\n }}\n />\n </label>\n <form\n className=\"flex items-center gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void addUrl();\n }}\n >\n <input\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n placeholder=\"https://…/clip.mp4\"\n value={url}\n disabled={!canEdit}\n aria-label=\"Media URL\"\n onChange={(e) => setUrl(e.target.value)}\n />\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-xs\" value={urlKind} disabled={!canEdit} aria-label=\"Media kind\" onChange={(e) => setUrlKind(e.target.value as VideoAssetKind | '')}>\n <option value=\"\">Auto</option>\n <option value=\"video\">Video</option>\n <option value=\"audio\">Audio</option>\n <option value=\"image\">Image</option>\n </select>\n <button type=\"submit\" className={btn} disabled={!canEdit || !url.trim()} data-add-url=\"\">\n Add\n </button>\n </form>\n </>\n )}\n {busy > 0 && <p className=\"text-xs text-muted-foreground\">Reading media…</p>}\n {problem && (\n <p className=\"text-xs text-red-500\" role=\"alert\" data-media-error=\"\">\n {problem}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n findVideoFillers,\n findVideoTranscriptPauses,\n videoRemoveRangesEdits,\n videoTimelineTranscript,\n videoTranscriptEdit,\n videoWordAt,\n videoWordsRange,\n type VideoEditorController,\n} from '@pixerate/editor/video-editor';\nimport { useVideoEditorState } from './useVideoEditor';\n\nexport interface TranscriptPanelProps {\n controller: VideoEditorController;\n /** Track whose words to show (default: the first audio track with a transcribed clip, else the first video track with one). */\n track?: string;\n /** Allow cutting by text and loading transcripts (default true). */\n editable?: boolean;\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * Edit by text: the words the timeline plays, from its media's transcripts. Click a word to go to\n * it, Shift-click to select a run of words, then delete them to cut that stretch out (closing it up\n * on every sync-locked track). \"Remove fillers\" and \"Tighten pauses\" cut every um and every long gap\n * at once. Each cut is one undo step. Transcripts (Whisper JSON, .srt, .vtt) load per asset below.\n */\nexport function TranscriptPanel({ controller, track, editable = true, className = '' }: TranscriptPanelProps) {\n const state = useVideoEditorState(controller);\n const { project, time, readOnly } = state;\n const canEdit = editable && !readOnly;\n const [anchor, setAnchor] = useState<number | null>(null);\n const [focus, setFocus] = useState<number | null>(null);\n const [message, setMessage] = useState<string | null>(null);\n const words = useMemo(() => {\n try {\n return videoTimelineTranscript(project, { track });\n } catch {\n return [];\n }\n }, [project, track]);\n const current = videoWordAt(words, time);\n const selected = anchor !== null && focus !== null && anchor < words.length && focus < words.length ? ([Math.min(anchor, focus), Math.max(anchor, focus)] as const) : null;\n const sound = project.assets.filter((a) => a.kind !== 'image');\n\n const cut = (ranges: { from: number; to: number }[], label: string, none: string) => {\n if (!ranges.length) return setMessage(none);\n const r = controller.apply(videoRemoveRangesEdits(ranges), label);\n setMessage(r.ok ? null : r.error);\n setAnchor(null);\n setFocus(null);\n };\n const load = async (assetId: string, file: File | undefined) => {\n if (!file) return;\n try {\n const r = controller.apply(videoTranscriptEdit(assetId, await file.text()), 'Attach transcript');\n setMessage(r.ok ? null : r.error);\n } catch (e) {\n setMessage(e instanceof Error ? e.message : String(e));\n }\n };\n\n return (\n <div className={`flex flex-col gap-2 text-xs ${className}`} data-transcript-panel=\"\">\n {words.length > 0 ? (\n <>\n <div\n className=\"max-h-48 overflow-y-auto leading-6\"\n role=\"listbox\"\n aria-label=\"Transcript\"\n aria-multiselectable=\"true\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (canEdit && selected && (e.key === 'Delete' || e.key === 'Backspace')) {\n e.preventDefault();\n cut([videoWordsRange(words, selected[0], selected[1])], 'Cut words', 'Select words to cut.');\n }\n }}\n >\n {words.map((w, i) => {\n const inSelection = selected !== null && i >= selected[0] && i <= selected[1];\n return (\n <React.Fragment key={`${w.clip}:${w.index}`}>\n <span\n role=\"option\"\n aria-selected={inSelection}\n tabIndex={-1}\n className={`cursor-pointer rounded px-0.5 ${inSelection ? 'bg-rose-500/30' : i === current ? 'bg-amber-400/40' : 'hover:bg-muted'}`}\n data-word={i}\n data-current={i === current ? '' : undefined}\n data-selected={inSelection ? '' : undefined}\n onClick={(e) => {\n if (e.shiftKey && anchor !== null) setFocus(i);\n else {\n setAnchor(i);\n setFocus(i);\n controller.seek(w.start);\n }\n }}\n >\n {w.word}\n </span>{' '}\n </React.Fragment>\n );\n })}\n </div>\n {canEdit && (\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={btn} disabled={!selected} onClick={() => selected && cut([videoWordsRange(words, selected[0], selected[1])], 'Cut words', 'Select words to cut.')}>\n Delete selected words\n </button>\n <button type=\"button\" className={btn} onClick={() => cut(findVideoFillers(words), 'Remove fillers', 'No filler words found.')}>\n Remove fillers\n </button>\n <button type=\"button\" className={btn} onClick={() => cut(findVideoTranscriptPauses(words, { fps: project.fps }), 'Tighten pauses', 'No long pauses found.')}>\n Tighten pauses\n </button>\n </div>\n )}\n </>\n ) : (\n <p className=\"text-muted-foreground\" data-transcript-empty=\"\">\n No transcribed media on the timeline. Load a transcript (Whisper JSON, .srt or .vtt) for a video or audio asset to edit by text.\n </p>\n )}\n {canEdit && sound.length > 0 && (\n <details>\n <summary className=\"cursor-pointer text-muted-foreground\">Transcripts</summary>\n <ul className=\"mt-1 space-y-1\">\n {sound.map((a) => (\n <li key={a.id} className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate\">\n {a.name ?? a.id} {a.transcript ? `· ${a.transcript.length} words` : ''}\n </span>\n <input type=\"file\" accept=\".json,.srt,.vtt,application/json,text/vtt\" aria-label={`Load a transcript for ${a.name ?? a.id}`} className=\"w-40 text-[10px]\" onChange={(e) => void load(a.id, e.target.files?.[0])} />\n </li>\n ))}\n </ul>\n </details>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-transcript-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect } from 'react';\nimport type { VideoEditorController, VideoEditorOptions } from '@pixerate/editor/video-editor';\nimport { ClipInspector } from './ClipInspector';\nimport { MediaBin } from './MediaBin';\nimport { TranscriptPanel } from './TranscriptPanel';\nimport { useVideoEditor } from './useVideoEditor';\nimport { VideoPreview } from './VideoPreview';\nimport { VideoScopes } from './VideoScopes';\nimport { VideoTimeline } from './VideoTimeline';\nimport { VideoTransport } from './VideoTransport';\n\nexport interface VideoEditorProps {\n /** The controller to edit. Without it one is created from `options` for the component's lifetime. */\n controller?: VideoEditorController;\n /** Options for the controller created when `controller` is not given. */\n options?: VideoEditorOptions;\n /**\n * Show the editing UI: the media bin's imports, the transport's edit buttons, timeline dragging\n * and track toggles, and the clip inspector (default true). False also makes the project read-only\n * while mounted.\n */\n editable?: boolean;\n /** Timeline zoom in pixels per second (with `onPxPerSecondChange` the host owns it). */\n pxPerSecond?: number;\n onPxPerSecondChange?: (pxPerSecond: number) => void;\n /** Canvas pixels per frame pixel for the preview (see `<VideoPreview resolution>`). */\n resolution?: number;\n /** List the project's issues under the timeline (default true). */\n showIssues?: boolean;\n /** Show the transcript panel for editing by text (default true). */\n showTranscript?: boolean;\n /** Show colour scopes (histogram, luma waveform, vectorscope) of the preview under it (default false). */\n showScopes?: boolean;\n className?: string;\n}\n\n/**\n * A whole non-linear video editor for a `VideoEditorController`: the media bin, the preview, the\n * transport, the timeline and the clip inspector, with the project's issues listed under the\n * timeline. Every edit is one undo step; the controller's agent tools edit the same project.\n */\nexport function VideoEditor({ controller: given, options, editable = true, pxPerSecond, onPxPerSecondChange, resolution, showIssues = true, showTranscript = true, showScopes = false, className = '' }: VideoEditorProps) {\n const { controller, state } = useVideoEditor(given ?? options ?? {});\n useEffect(() => {\n if (editable) return;\n const was = controller.getState().readOnly;\n controller.setReadOnly(true);\n return () => controller.setReadOnly(was);\n }, [controller, editable]);\n const { issues } = state;\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Video issues\" data-video-issues=\"\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'} data-issue={issue.code}>\n {issue.message}\n </li>\n ))}\n </ul>\n );\n return (\n <div className={`flex flex-col gap-3 ${className}`} data-video-editor=\"\">\n <div className={`grid gap-3 ${editable ? 'lg:grid-cols-[16rem_minmax(0,1fr)_18rem]' : ''}`}>\n {editable && <MediaBin controller={controller} className=\"min-w-0\" />}\n <div className=\"flex min-w-0 flex-col gap-2\">\n <VideoPreview controller={controller} resolution={resolution} className=\"rounded-md border border-border\" />\n <VideoTransport controller={controller} editable={editable} />\n {showScopes && <VideoScopes controller={controller} />}\n </div>\n {editable && <ClipInspector controller={controller} className=\"min-w-0\" />}\n </div>\n <VideoTimeline controller={controller} editable={editable} pxPerSecond={pxPerSecond} onPxPerSecondChange={onPxPerSecondChange} />\n {showTranscript && <TranscriptPanel controller={controller} editable={editable} />}\n {issueList}\n </div>\n );\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","useEffect","useRef","jsx","jsx","jsxs","useEffect","useMemo","useRef","useState","useSyncExternalStore","Fragment","jsx","jsxs","useSyncExternalStore","useEffect","useMemo","useState","useRef","field","useState","formatVideoSeconds","Fragment","jsx","jsxs","btn","useState","formatVideoSeconds","useState","formatVideoSeconds","Fragment","jsx","jsxs","btn","useState","formatVideoSeconds","React","useMemo","useState","Fragment","jsx","jsxs","btn","useState","useMemo","React","useEffect","jsx","jsxs","useEffect"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "React bindings and prompt/rich-text components for @pixerate/editor",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|
|
133
133
|
"@dagrejs/dagre": "^1.1.8",
|
|
134
|
-
"@pixerate/editor": ">=0.
|
|
134
|
+
"@pixerate/editor": ">=0.88.0 <1.0.0-0",
|
|
135
135
|
"@tiptap/core": "^2.11.5",
|
|
136
136
|
"@tiptap/pm": "^2.11.5",
|
|
137
137
|
"@tiptap/react": "^2.11.5",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"tsup": "^8.4.0",
|
|
159
159
|
"typescript": "^5.7.3",
|
|
160
160
|
"vitest": "^4.1.11",
|
|
161
|
-
"@pixerate/editor": "0.
|
|
161
|
+
"@pixerate/editor": "0.88.0"
|
|
162
162
|
},
|
|
163
163
|
"scripts": {
|
|
164
164
|
"build": "tsup",
|