From 640e8dccb994a3ab43c4e9f6ad11ea34e009e4b4 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Thu, 19 Feb 2026 11:59:27 +1300 Subject: [PATCH] feat(quick-007): wire VideoTrimNode into canvas, connection menu, and exports - Export VideoTrimNode from src/components/nodes/index.ts - Register videoTrim in nodeTypes map in WorkflowCanvas.tsx - Add videoTrim to getNodeHandles (video in, video out) - Add videoTrim to isValidConnection video target list - Add videoTrim connection drop handling (video input and output) - Add videoTrim minimap color: blue-400 (#60a5fa) - Add VideoTrim to VIDEO_TARGET_OPTIONS in ConnectionDropMenu (scissors icon) - Add VideoTrim to VIDEO_SOURCE_OPTIONS in ConnectionDropMenu (scissors icon) --- src/components/ConnectionDropMenu.tsx | 18 ++++++++++++++++++ src/components/WorkflowCanvas.tsx | 12 +++++++++++- src/components/nodes/index.ts | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/components/ConnectionDropMenu.tsx b/src/components/ConnectionDropMenu.tsx index 3b5bf4b9..c464751d 100644 --- a/src/components/ConnectionDropMenu.tsx +++ b/src/components/ConnectionDropMenu.tsx @@ -237,6 +237,15 @@ const VIDEO_TARGET_OPTIONS: MenuOption[] = [ ), }, + { + type: "videoTrim", + label: "Video Trim", + icon: ( + + + + ), + }, { type: "generateVideo", label: "Generate Video", @@ -286,6 +295,15 @@ const VIDEO_SOURCE_OPTIONS: MenuOption[] = [ ), }, + { + type: "videoTrim", + label: "Video Trim", + icon: ( + + + + ), + }, ]; // Audio target options (nodes that accept audio input) diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index 132acdb4..9327e1ad 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -37,6 +37,7 @@ import { ImageCompareNode, VideoStitchNode, EaseCurveNode, + VideoTrimNode, } from "./nodes"; // Lazy-load GLBViewerNode to avoid bundling three.js for users who don't use 3D nodes @@ -74,6 +75,7 @@ const nodeTypes: NodeTypes = { imageCompare: ImageCompareNode, videoStitch: VideoStitchNode, easeCurve: EaseCurveNode, + videoTrim: VideoTrimNode, glbViewer: GLBViewerNode, }; @@ -140,6 +142,8 @@ const getNodeHandles = (nodeType: string): { inputs: string[]; outputs: string[] return { inputs: ["video", "audio"], outputs: ["video"] }; case "easeCurve": return { inputs: ["video", "easeCurve"], outputs: ["video", "easeCurve"] }; + case "videoTrim": + return { inputs: ["video"], outputs: ["video"] }; case "glbViewer": return { inputs: ["3d"], outputs: ["image"] }; default: @@ -332,7 +336,7 @@ export function WorkflowCanvas() { if (!targetNode) return false; const targetNodeType = targetNode.type; - if (targetNodeType === "generateVideo" || targetNodeType === "videoStitch" || targetNodeType === "easeCurve" || targetNodeType === "output") { + if (targetNodeType === "generateVideo" || targetNodeType === "videoStitch" || targetNodeType === "easeCurve" || targetNodeType === "videoTrim" || targetNodeType === "output") { // For output node, we allow video even though its handle is typed as "image" // because output node can display both images and videos return true; @@ -841,6 +845,10 @@ export function WorkflowCanvas() { // EaseCurve accepts video input and outputs video targetHandleId = "video"; sourceHandleIdForNewNode = "video"; + } else if (nodeType === "videoTrim") { + // VideoTrim accepts video input and outputs video + targetHandleId = "video"; + sourceHandleIdForNewNode = "video"; } else if (nodeType === "generateVideo") { // GenerateVideo outputs video sourceHandleIdForNewNode = "video"; @@ -1714,6 +1722,8 @@ export function WorkflowCanvas() { return "#f97316"; case "easeCurve": return "#bef264"; // lime-300 (easy-peasy-ease) + case "videoTrim": + return "#60a5fa"; // blue-400 (trim/cut) case "glbViewer": return "#38bdf8"; // sky-400 (3D viewport) default: diff --git a/src/components/nodes/index.ts b/src/components/nodes/index.ts index 32462834..8d580db5 100644 --- a/src/components/nodes/index.ts +++ b/src/components/nodes/index.ts @@ -14,4 +14,5 @@ export { OutputGalleryNode } from "./OutputGalleryNode"; export { ImageCompareNode } from "./ImageCompareNode"; export { VideoStitchNode } from "./VideoStitchNode"; export { EaseCurveNode } from "./EaseCurveNode"; +export { VideoTrimNode } from "./VideoTrimNode"; export { GroupNode } from "./GroupNode";