@genfeedai/workflow-ui 0.1.3 → 0.1.4

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.
Files changed (84) hide show
  1. package/dist/canvas.d.mts +16 -2
  2. package/dist/canvas.mjs +10 -8
  3. package/dist/chunk-6PSJTBNV.mjs +638 -0
  4. package/dist/chunk-7H3WJJYS.mjs +52 -0
  5. package/dist/{chunk-HCXI63ME.mjs → chunk-AUQGOJOQ.mjs} +27 -4
  6. package/dist/{chunk-AOTUCJMA.mjs → chunk-GWBGK3KL.mjs} +2 -2
  7. package/dist/chunk-JTPADIUO.mjs +130 -0
  8. package/dist/{chunk-SQK4JDYY.mjs → chunk-LT3ZJJL6.mjs} +9 -2
  9. package/dist/{chunk-7P2JWDC7.mjs → chunk-O5II6BOJ.mjs} +1198 -254
  10. package/dist/{chunk-AUZR6REQ.mjs → chunk-OQREHJXK.mjs} +1 -1
  11. package/dist/chunk-OY7BRSGG.mjs +60 -0
  12. package/dist/{chunk-E3YBVMYZ.mjs → chunk-PANZDSP6.mjs} +274 -305
  13. package/dist/chunk-PCIWWD37.mjs +90 -0
  14. package/dist/{chunk-RIGVIEYB.mjs → chunk-R727OFBR.mjs} +11 -1
  15. package/dist/chunk-ZD2BADZO.mjs +1294 -0
  16. package/dist/contextMenuStore-DMg0hJQ1.d.mts +22 -0
  17. package/dist/hooks.d.mts +53 -244
  18. package/dist/hooks.mjs +6 -6
  19. package/dist/index.d.mts +11 -7
  20. package/dist/index.mjs +13 -11
  21. package/dist/lib.d.mts +250 -4
  22. package/dist/lib.mjs +562 -2
  23. package/dist/nodes.d.mts +3 -1
  24. package/dist/nodes.mjs +6 -6
  25. package/dist/panels.mjs +3 -4
  26. package/dist/{promptLibraryStore-zqb59nsu.d.mts → promptLibraryStore-Bgw5LzvD.d.mts} +33 -5
  27. package/dist/provider.d.mts +2 -2
  28. package/dist/provider.mjs +0 -1
  29. package/dist/stores.d.mts +4 -3
  30. package/dist/stores.mjs +3 -40
  31. package/dist/toolbar.d.mts +3 -1
  32. package/dist/toolbar.mjs +5 -4
  33. package/dist/{types-ipAnBzAJ.d.mts → types-CF6DPx0P.d.mts} +8 -3
  34. package/dist/ui.d.mts +1 -1
  35. package/dist/ui.mjs +0 -1
  36. package/dist/{hooks.d.ts → useCommentNavigation-NzJjkaj2.d.mts} +15 -2
  37. package/dist/workflowStore-UAAKOOIK.mjs +2 -0
  38. package/package.json +30 -24
  39. package/dist/canvas.d.ts +0 -27
  40. package/dist/canvas.js +0 -45
  41. package/dist/chunk-3SPPKCWR.js +0 -458
  42. package/dist/chunk-3TMV3K34.js +0 -534
  43. package/dist/chunk-3YFFDHC5.js +0 -300
  44. package/dist/chunk-4MZ62VMF.js +0 -37
  45. package/dist/chunk-5HJFQVUR.js +0 -61
  46. package/dist/chunk-5LQ4QBR5.js +0 -2
  47. package/dist/chunk-6DOEUDD5.js +0 -254
  48. package/dist/chunk-AXFOCPPP.js +0 -998
  49. package/dist/chunk-BMFRA6GK.js +0 -1546
  50. package/dist/chunk-E323WAZG.mjs +0 -272
  51. package/dist/chunk-ECD5J2BA.js +0 -6022
  52. package/dist/chunk-EMGXUNBL.js +0 -120
  53. package/dist/chunk-EMUMKW5C.js +0 -107
  54. package/dist/chunk-FOMOOERN.js +0 -2
  55. package/dist/chunk-IASLG6IA.mjs +0 -118
  56. package/dist/chunk-IHF35QZD.js +0 -1095
  57. package/dist/chunk-JLWKW3G5.js +0 -2
  58. package/dist/chunk-KDIWRSYV.js +0 -375
  59. package/dist/chunk-L5TF4EHW.mjs +0 -1
  60. package/dist/chunk-RJ262NXS.js +0 -24
  61. package/dist/chunk-RXNEDWK2.js +0 -141
  62. package/dist/chunk-SEV2DWKF.js +0 -744
  63. package/dist/chunk-ZJWP5KGZ.mjs +0 -33
  64. package/dist/hooks.js +0 -56
  65. package/dist/index.d.ts +0 -29
  66. package/dist/index.js +0 -180
  67. package/dist/lib.d.ts +0 -164
  68. package/dist/lib.js +0 -144
  69. package/dist/nodes.d.ts +0 -128
  70. package/dist/nodes.js +0 -151
  71. package/dist/panels.d.ts +0 -22
  72. package/dist/panels.js +0 -21
  73. package/dist/promptLibraryStore-BZnfmEkc.d.ts +0 -464
  74. package/dist/provider.d.ts +0 -29
  75. package/dist/provider.js +0 -17
  76. package/dist/stores.d.ts +0 -96
  77. package/dist/stores.js +0 -113
  78. package/dist/toolbar.d.ts +0 -73
  79. package/dist/toolbar.js +0 -34
  80. package/dist/types-ipAnBzAJ.d.ts +0 -46
  81. package/dist/ui.d.ts +0 -67
  82. package/dist/ui.js +0 -84
  83. package/dist/workflowStore-7SDJC4UR.mjs +0 -3
  84. package/dist/workflowStore-LNJQ5RZG.js +0 -12
@@ -1,302 +1,24 @@
1
1
  import { Checkbox, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Slider, Label, Input, GridPositionSelector, ComparisonSlider } from './chunk-ZJD5WMR3.mjs';
2
- import { generateHandlesFromSchema, DEFAULT_IMAGE_MODEL, IMAGE_MODEL_MAP, IMAGE_MODEL_ID_MAP, IMAGE_MODELS, LIPSYNC_MODELS, LIPSYNC_SYNC_MODES, DEFAULT_LLM_MODEL, LLM_MODEL_MAP, LLM_MODEL_ID_MAP, LLM_MODELS, DEFAULT_VIDEO_MODEL, VIDEO_MODEL_MAP, VIDEO_MODEL_ID_MAP, VIDEO_MODELS, EASING_PRESETS, getMediaFromNode } from './chunk-E323WAZG.mjs';
3
- import { useNodeExecution, useCanGenerate, useModelSelection, useAutoLoadModelSchema, useAIGenNode, useAIGenNodeHeader, useMediaUpload, usePromptAutocomplete, useRequiredInputs } from './chunk-AOTUCJMA.mjs';
2
+ import { generateHandlesFromSchema, DEFAULT_IMAGE_MODEL, IMAGE_MODEL_MAP, IMAGE_MODEL_ID_MAP, IMAGE_MODELS, LIPSYNC_MODELS, LIPSYNC_SYNC_MODES, DEFAULT_LLM_MODEL, LLM_MODEL_MAP, LLM_MODEL_ID_MAP, LLM_MODELS, DEFAULT_VIDEO_MODEL, VIDEO_MODEL_MAP, VIDEO_MODEL_ID_MAP, VIDEO_MODELS, EASING_PRESETS, CubicBezierEditor, getMediaFromNode } from './chunk-6PSJTBNV.mjs';
3
+ import { LUMA_ASPECT_RATIOS } from './chunk-OY7BRSGG.mjs';
4
+ import { useNodeExecution, useCanGenerate, useModelSelection, useAutoLoadModelSchema, useAIGenNode, useAIGenNodeHeader, useMediaUpload, usePromptAutocomplete, useRequiredInputs } from './chunk-GWBGK3KL.mjs';
4
5
  import { Button } from './chunk-7SKSRSS7.mjs';
5
6
  import { getImageDimensions, getVideoMetadata } from './chunk-EFXQT23N.mjs';
6
7
  import { usePromptEditorStore, useAnnotationStore } from './chunk-CV4M7CNU.mjs';
7
- import { useUIStore, useExecutionStore } from './chunk-SQK4JDYY.mjs';
8
- import { useWorkflowStore } from './chunk-RIGVIEYB.mjs';
8
+ import { useUIStore, useExecutionStore } from './chunk-LT3ZJJL6.mjs';
9
+ import { useWorkflowStore } from './chunk-R727OFBR.mjs';
9
10
  import { useWorkflowUIConfig } from './chunk-FT33LFII.mjs';
10
11
  import { usePromptLibraryStore } from './chunk-VRN3UWE5.mjs';
11
- import { __commonJS, __require, __toESM } from './chunk-ZJWP5KGZ.mjs';
12
12
  import { NODE_DEFINITIONS, NodeStatusEnum } from '@genfeedai/types';
13
13
  import { useUpdateNodeInternals, NodeResizer, Handle, Position } from '@xyflow/react';
14
14
  import { clsx } from 'clsx';
15
- import { GitBranch, ArrowLeftFromLine, ArrowRightToLine, Subtitles, Pencil, Columns2, LayoutGrid, Grid3X3, Puzzle, Navigation, Volume2, AudioLines, Mic, Maximize, Crop, RefreshCw, AtSign, Download, Eye, CheckCircle, Share2, Scissors, Layers, Wand2, Maximize2, Brain, Video, Sparkles, Film, FileVideo, FileText, MessageSquare, Image as Image$1, Square, Lock, Unlock, Copy, RotateCcw, Loader2, ChevronDown, ChevronRight, AlertCircle, ImageIcon, Expand, Play, AlertTriangle, CheckCircle2, Upload, Link, X, Music, Save, Clock, Shapes, ChevronLeft, SplitSquareHorizontal, Zap } from 'lucide-react';
15
+ import { GitBranch, ArrowLeftFromLine, ArrowRightToLine, Subtitles, Pencil, Columns2, LayoutGrid, Grid3X3, Puzzle, Navigation, Volume2, AudioLines, Mic, Maximize, Crop, RefreshCw, AtSign, Download, Eye, CheckCircle, Share2, Scissors, Layers, Wand2, Maximize2, Brain, Video, Sparkles, Film, FileVideo, FileText, MessageSquare, Image as Image$1, Square, Lock, Unlock, Copy, RotateCcw, Loader2, ChevronDown, ChevronRight, AlertCircle, ImageIcon, Expand, Play, AlertTriangle, CheckCircle2, Upload, Link, X, Music, Save, Clock, Shapes, ChevronLeft, SplitSquareHorizontal, Zap, ZoomOut, ZoomIn } from 'lucide-react';
16
16
  import { memo, forwardRef, useRef, useState, useCallback, useEffect, useImperativeHandle, useMemo, useLayoutEffect, Component } from 'react';
17
17
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
18
18
  import Image4 from 'next/image';
19
19
  import { createPortal } from 'react-dom';
20
20
  import { useShallow } from 'zustand/react/shallow';
21
21
 
22
- // ../core/dist/chunk-OAAW6BNW.js
23
- var require_chunk_OAAW6BNW = __commonJS({
24
- "../core/dist/chunk-OAAW6BNW.js"(exports$1) {
25
- function topologicalSort(nodes, edges) {
26
- const inDegree = /* @__PURE__ */ new Map();
27
- const adjList = /* @__PURE__ */ new Map();
28
- for (const node of nodes) {
29
- inDegree.set(node.id, 0);
30
- adjList.set(node.id, []);
31
- }
32
- for (const edge of edges) {
33
- adjList.get(edge.source)?.push(edge.target);
34
- inDegree.set(edge.target, (inDegree.get(edge.target) ?? 0) + 1);
35
- }
36
- const queue = [];
37
- for (const [nodeId, degree] of inDegree) {
38
- if (degree === 0) {
39
- queue.push(nodeId);
40
- }
41
- }
42
- const result = [];
43
- while (queue.length > 0) {
44
- const node = queue.shift();
45
- result.push(node);
46
- for (const neighbor of adjList.get(node) ?? []) {
47
- inDegree.set(neighbor, (inDegree.get(neighbor) ?? 1) - 1);
48
- if (inDegree.get(neighbor) === 0) {
49
- queue.push(neighbor);
50
- }
51
- }
52
- }
53
- return result;
54
- }
55
- function buildDependencyMap(nodes, edges) {
56
- const deps = /* @__PURE__ */ new Map();
57
- for (const node of nodes) {
58
- deps.set(node.id, []);
59
- }
60
- for (const edge of edges) {
61
- const existing = deps.get(edge.target) ?? [];
62
- deps.set(edge.target, [...existing, edge.source]);
63
- }
64
- return deps;
65
- }
66
- exports$1.buildDependencyMap = buildDependencyMap;
67
- exports$1.topologicalSort = topologicalSort;
68
- }
69
- });
70
-
71
- // ../core/dist/chunk-FZCK5A7S.js
72
- var require_chunk_FZCK5A7S = __commonJS({
73
- "../core/dist/chunk-FZCK5A7S.js"(exports$1) {
74
- var types = __require("@genfeedai/types");
75
- function detectCycles(nodes, edges) {
76
- const visited = /* @__PURE__ */ new Set();
77
- const recStack = /* @__PURE__ */ new Set();
78
- function hasCycle(nodeId) {
79
- if (recStack.has(nodeId)) return true;
80
- if (visited.has(nodeId)) return false;
81
- visited.add(nodeId);
82
- recStack.add(nodeId);
83
- const outgoing = edges.filter((e) => e.source === nodeId);
84
- for (const edge of outgoing) {
85
- if (hasCycle(edge.target)) return true;
86
- }
87
- recStack.delete(nodeId);
88
- return false;
89
- }
90
- for (const node of nodes) {
91
- if (hasCycle(node.id)) return true;
92
- }
93
- return false;
94
- }
95
- function validateWorkflow(nodes, edges) {
96
- const errors = [];
97
- const warnings = [];
98
- for (const node of nodes) {
99
- const nodeDef = types.NODE_DEFINITIONS[node.type];
100
- if (!nodeDef) continue;
101
- const incomingEdges = edges.filter((e) => e.target === node.id);
102
- for (const input of nodeDef.inputs) {
103
- if (input.required) {
104
- const hasConnection = incomingEdges.some((e) => e.targetHandle === input.id);
105
- if (!hasConnection) {
106
- errors.push({
107
- nodeId: node.id,
108
- message: `Missing required input: ${input.label}`,
109
- severity: "error"
110
- });
111
- }
112
- }
113
- }
114
- if (node.type === "download") {
115
- const hasMediaInput = incomingEdges.some(
116
- (e) => e.targetHandle === "image" || e.targetHandle === "video"
117
- );
118
- if (!hasMediaInput) {
119
- errors.push({
120
- nodeId: node.id,
121
- message: "Output node requires at least one Media input (image or video)",
122
- severity: "error"
123
- });
124
- }
125
- }
126
- }
127
- if (detectCycles(nodes, edges)) {
128
- errors.push({
129
- nodeId: nodes[0]?.id ?? "unknown",
130
- message: "Workflow contains a cycle",
131
- severity: "error"
132
- });
133
- }
134
- return {
135
- isValid: errors.length === 0,
136
- errors,
137
- warnings
138
- };
139
- }
140
- function getHandleType(nodeType, handleId, direction) {
141
- const nodeDef = types.NODE_DEFINITIONS[nodeType];
142
- if (!nodeDef) return null;
143
- const handles = direction === "source" ? nodeDef.outputs : nodeDef.inputs;
144
- const handle = handles.find((h) => h.id === handleId);
145
- return handle?.type ?? null;
146
- }
147
- function isValidConnection(sourceNodeType, sourceHandle, targetNodeType, targetHandle) {
148
- const sourceType = getHandleType(sourceNodeType, sourceHandle, "source");
149
- const targetType = getHandleType(targetNodeType, targetHandle, "target");
150
- if (!sourceType || !targetType) return false;
151
- return types.CONNECTION_RULES[sourceType]?.includes(targetType) ?? false;
152
- }
153
- function getCompatibleHandles(handleType) {
154
- return types.CONNECTION_RULES[handleType] ?? [];
155
- }
156
- exports$1.detectCycles = detectCycles;
157
- exports$1.getCompatibleHandles = getCompatibleHandles;
158
- exports$1.getHandleType = getHandleType;
159
- exports$1.isValidConnection = isValidConnection;
160
- exports$1.validateWorkflow = validateWorkflow;
161
- }
162
- });
163
-
164
- // ../core/dist/index.js
165
- var require_dist = __commonJS({
166
- "../core/dist/index.js"(exports$1) {
167
- var chunkOAAW6BNW_js = require_chunk_OAAW6BNW();
168
- var chunkFZCK5A7S_js = require_chunk_FZCK5A7S();
169
- var PRICING = {
170
- // Image generation (per image)
171
- "nano-banana": 0.039,
172
- "nano-banana-pro": {
173
- "1K": 0.15,
174
- "2K": 0.15,
175
- "4K": 0.3
176
- },
177
- // Legacy aliases
178
- "imagen-4-fast": 0.039,
179
- "imagen-4": 0.15,
180
- // Video generation (per second)
181
- "veo-3.1-fast": { withAudio: 0.15, withoutAudio: 0.1 },
182
- "veo-3.1": { withAudio: 0.4, withoutAudio: 0.2 },
183
- // Legacy aliases
184
- "veo-3-fast": { withAudio: 0.15, withoutAudio: 0.1 },
185
- "veo-3": { withAudio: 0.4, withoutAudio: 0.2 },
186
- // LLM (per token, derived from $9.50/million)
187
- llama: 95e-7,
188
- // Luma Reframe
189
- "luma-reframe-image": {
190
- "photon-flash-1": 0.01,
191
- "photon-1": 0.03
192
- },
193
- "luma-reframe-video": 0.06,
194
- // per second
195
- // Topaz Upscale (tiered by megapixels)
196
- "topaz-image-upscale": [
197
- { maxMP: 1, price: 0.05 },
198
- { maxMP: 4, price: 0.08 },
199
- { maxMP: 9, price: 0.16 },
200
- { maxMP: 16, price: 0.27 },
201
- { maxMP: 25, price: 0.41 },
202
- { maxMP: Infinity, price: 0.82 }
203
- ],
204
- // Topaz Video (per 5 seconds based on resolution and fps)
205
- "topaz-video-upscale": {
206
- "720p-15": 0.014,
207
- "720p-24": 0.022,
208
- "720p-30": 0.027,
209
- "720p-60": 0.054,
210
- "1080p-15": 0.051,
211
- "1080p-24": 0.081,
212
- "1080p-30": 0.101,
213
- "1080p-60": 0.203,
214
- "4k-15": 0.187,
215
- "4k-24": 0.299,
216
- "4k-30": 0.373,
217
- "4k-60": 0.747
218
- }
219
- };
220
- var IMAGE_NODE_TYPES = ["imageGen", "image-gen", "ImageGenNode"];
221
- var VIDEO_NODE_TYPES = ["videoGen", "video-gen", "VideoGenNode"];
222
- var LUMA_NODE_TYPES = ["reframe", "lumaReframeImage", "lumaReframeVideo"];
223
- var TOPAZ_NODE_TYPES = ["upscale", "topazImageUpscale", "topazVideoUpscale"];
224
- var DEFAULT_VIDEO_DURATION = 8;
225
- var ASPECT_RATIOS3 = [
226
- "1:1",
227
- "16:9",
228
- "9:16",
229
- "4:3",
230
- "3:4",
231
- "4:5",
232
- "5:4",
233
- "2:3",
234
- "3:2",
235
- "21:9"
236
- ];
237
- var VIDEO_ASPECT_RATIOS = ["16:9", "9:16"];
238
- var RESOLUTIONS2 = ["1K", "2K", "4K"];
239
- var VIDEO_RESOLUTIONS = ["720p", "1080p"];
240
- var VIDEO_DURATIONS = [4, 6, 8];
241
- var OUTPUT_FORMATS2 = ["jpg", "png", "webp"];
242
- var LUMA_ASPECT_RATIOS2 = ["1:1", "3:4", "4:3", "9:16", "16:9", "9:21", "21:9"];
243
- Object.defineProperty(exports$1, "buildDependencyMap", {
244
- enumerable: true,
245
- get: function() {
246
- return chunkOAAW6BNW_js.buildDependencyMap;
247
- }
248
- });
249
- Object.defineProperty(exports$1, "topologicalSort", {
250
- enumerable: true,
251
- get: function() {
252
- return chunkOAAW6BNW_js.topologicalSort;
253
- }
254
- });
255
- Object.defineProperty(exports$1, "detectCycles", {
256
- enumerable: true,
257
- get: function() {
258
- return chunkFZCK5A7S_js.detectCycles;
259
- }
260
- });
261
- Object.defineProperty(exports$1, "getCompatibleHandles", {
262
- enumerable: true,
263
- get: function() {
264
- return chunkFZCK5A7S_js.getCompatibleHandles;
265
- }
266
- });
267
- Object.defineProperty(exports$1, "getHandleType", {
268
- enumerable: true,
269
- get: function() {
270
- return chunkFZCK5A7S_js.getHandleType;
271
- }
272
- });
273
- Object.defineProperty(exports$1, "isValidConnection", {
274
- enumerable: true,
275
- get: function() {
276
- return chunkFZCK5A7S_js.isValidConnection;
277
- }
278
- });
279
- Object.defineProperty(exports$1, "validateWorkflow", {
280
- enumerable: true,
281
- get: function() {
282
- return chunkFZCK5A7S_js.validateWorkflow;
283
- }
284
- });
285
- exports$1.ASPECT_RATIOS = ASPECT_RATIOS3;
286
- exports$1.DEFAULT_VIDEO_DURATION = DEFAULT_VIDEO_DURATION;
287
- exports$1.IMAGE_NODE_TYPES = IMAGE_NODE_TYPES;
288
- exports$1.LUMA_ASPECT_RATIOS = LUMA_ASPECT_RATIOS2;
289
- exports$1.LUMA_NODE_TYPES = LUMA_NODE_TYPES;
290
- exports$1.OUTPUT_FORMATS = OUTPUT_FORMATS2;
291
- exports$1.PRICING = PRICING;
292
- exports$1.RESOLUTIONS = RESOLUTIONS2;
293
- exports$1.TOPAZ_NODE_TYPES = TOPAZ_NODE_TYPES;
294
- exports$1.VIDEO_ASPECT_RATIOS = VIDEO_ASPECT_RATIOS;
295
- exports$1.VIDEO_DURATIONS = VIDEO_DURATIONS;
296
- exports$1.VIDEO_NODE_TYPES = VIDEO_NODE_TYPES;
297
- exports$1.VIDEO_RESOLUTIONS = VIDEO_RESOLUTIONS;
298
- }
299
- });
300
22
  var NodeErrorBoundary = class extends Component {
301
23
  constructor(props) {
302
24
  super(props);
@@ -917,7 +639,7 @@ function NegativePromptSelectorComponent({ value, onChange }) {
917
639
  value: customText,
918
640
  onChange: (e) => handleCustomChange(e.target.value),
919
641
  placeholder: "ugly, deformed, ...",
920
- className: "w-full h-7 rounded-md border border-input bg-background px-2 text-xs shadow-sm placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
642
+ className: "nodrag nopan w-full h-7 rounded-md border border-input bg-background px-2 text-xs shadow-sm placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
921
643
  }
922
644
  )
923
645
  ] })
@@ -1042,7 +764,7 @@ function SliderInput({
1042
764
  step,
1043
765
  value: currentValue,
1044
766
  onChange: (e) => onChange(Number(e.target.value)),
1045
- className: "w-16 h-7 rounded-md border border-input bg-background px-2 text-xs text-center shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
767
+ className: "nodrag nopan w-16 h-7 rounded-md border border-input bg-background px-2 text-xs text-center shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
1046
768
  }
1047
769
  )
1048
770
  ] })
@@ -1091,7 +813,7 @@ function NumberInput({
1091
813
  const val = e.target.value;
1092
814
  onChange(val === "" ? null : Number(val));
1093
815
  },
1094
- className: "w-full h-8 rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
816
+ className: "nodrag nopan w-full h-8 rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
1095
817
  }
1096
818
  )
1097
819
  ] });
@@ -2516,6 +2238,254 @@ function VoiceChangeNodeComponent(props) {
2516
2238
  ] }) });
2517
2239
  }
2518
2240
  var VoiceChangeNode = memo(VoiceChangeNodeComponent);
2241
+ var PROMPT_NODE_TYPES = ["prompt"];
2242
+ function NodeDetailModal() {
2243
+ const { activeModal, nodeDetailNodeId, nodeDetailStartIndex, closeNodeDetailModal } = useUIStore();
2244
+ const { getNodeById } = useWorkflowStore();
2245
+ const { openEditor } = usePromptEditorStore();
2246
+ const [zoomLevel, setZoomLevel] = useState(1);
2247
+ const [panOffset, setPanOffset] = useState({ x: 0, y: 0 });
2248
+ const [isPanning, setIsPanning] = useState(false);
2249
+ const [panStart, setPanStart] = useState({ x: 0, y: 0 });
2250
+ const [currentIndex, setCurrentIndex] = useState(0);
2251
+ const node = useMemo(() => {
2252
+ if (!nodeDetailNodeId) return null;
2253
+ return getNodeById(nodeDetailNodeId);
2254
+ }, [nodeDetailNodeId, getNodeById]);
2255
+ useEffect(() => {
2256
+ if (activeModal !== "nodeDetail" || !node) return;
2257
+ if (PROMPT_NODE_TYPES.includes(node.type)) {
2258
+ const promptData = node.data;
2259
+ closeNodeDetailModal();
2260
+ openEditor(node.id, promptData.prompt ?? "");
2261
+ }
2262
+ }, [activeModal, node, closeNodeDetailModal, openEditor]);
2263
+ const mediaInfo = useMemo(() => {
2264
+ if (!node) return { url: null, type: null };
2265
+ return getMediaFromNode(node.type, node.data);
2266
+ }, [node]);
2267
+ const nodeDef = useMemo(() => {
2268
+ if (!node) return null;
2269
+ return NODE_DEFINITIONS[node.type];
2270
+ }, [node]);
2271
+ const imageUrls = mediaInfo.urls ?? [];
2272
+ const hasMultipleImages = imageUrls.length > 1;
2273
+ const displayUrl = hasMultipleImages ? imageUrls[currentIndex] ?? mediaInfo.url : mediaInfo.url;
2274
+ const goToPrevious = useCallback(() => {
2275
+ setCurrentIndex((prev) => Math.max(prev - 1, 0));
2276
+ setZoomLevel(1);
2277
+ setPanOffset({ x: 0, y: 0 });
2278
+ }, []);
2279
+ const goToNext = useCallback(() => {
2280
+ setCurrentIndex((prev) => Math.min(prev + 1, imageUrls.length - 1));
2281
+ setZoomLevel(1);
2282
+ setPanOffset({ x: 0, y: 0 });
2283
+ }, [imageUrls.length]);
2284
+ useEffect(() => {
2285
+ setZoomLevel(1);
2286
+ setPanOffset({ x: 0, y: 0 });
2287
+ setCurrentIndex(nodeDetailStartIndex);
2288
+ }, [nodeDetailNodeId, nodeDetailStartIndex]);
2289
+ useEffect(() => {
2290
+ const handleKeyDown = (e) => {
2291
+ if (activeModal !== "nodeDetail") return;
2292
+ if (e.key === "Escape") {
2293
+ closeNodeDetailModal();
2294
+ }
2295
+ if (e.key === "+" || e.key === "=") {
2296
+ setZoomLevel((prev) => Math.min(prev + 0.25, 4));
2297
+ }
2298
+ if (e.key === "-") {
2299
+ setZoomLevel((prev) => Math.max(prev - 0.25, 0.25));
2300
+ }
2301
+ if (e.key === "0") {
2302
+ setZoomLevel(1);
2303
+ setPanOffset({ x: 0, y: 0 });
2304
+ }
2305
+ if (e.key === "ArrowLeft") {
2306
+ goToPrevious();
2307
+ }
2308
+ if (e.key === "ArrowRight") {
2309
+ goToNext();
2310
+ }
2311
+ };
2312
+ window.addEventListener("keydown", handleKeyDown);
2313
+ return () => window.removeEventListener("keydown", handleKeyDown);
2314
+ }, [activeModal, closeNodeDetailModal, goToPrevious, goToNext]);
2315
+ const handleMouseDown = useCallback(
2316
+ (e) => {
2317
+ if (zoomLevel > 1) {
2318
+ setIsPanning(true);
2319
+ setPanStart({ x: e.clientX - panOffset.x, y: e.clientY - panOffset.y });
2320
+ }
2321
+ },
2322
+ [zoomLevel, panOffset]
2323
+ );
2324
+ const handleMouseMove = useCallback(
2325
+ (e) => {
2326
+ if (isPanning) {
2327
+ setPanOffset({
2328
+ x: e.clientX - panStart.x,
2329
+ y: e.clientY - panStart.y
2330
+ });
2331
+ }
2332
+ },
2333
+ [isPanning, panStart]
2334
+ );
2335
+ const handleMouseUp = useCallback(() => {
2336
+ setIsPanning(false);
2337
+ }, []);
2338
+ const handleDownload = useCallback(() => {
2339
+ const url = displayUrl ?? mediaInfo.url;
2340
+ if (!url) return;
2341
+ const link = document.createElement("a");
2342
+ link.href = url;
2343
+ const suffix = hasMultipleImages ? `_${currentIndex + 1}` : "";
2344
+ link.download = `${node?.data.label || "output"}${suffix}.${mediaInfo.type === "video" ? "mp4" : "png"}`;
2345
+ document.body.appendChild(link);
2346
+ link.click();
2347
+ document.body.removeChild(link);
2348
+ }, [displayUrl, mediaInfo, node, hasMultipleImages, currentIndex]);
2349
+ if (activeModal !== "nodeDetail" || !node || !nodeDef) {
2350
+ return null;
2351
+ }
2352
+ if (PROMPT_NODE_TYPES.includes(node.type)) {
2353
+ return null;
2354
+ }
2355
+ const nodeData = node.data;
2356
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2357
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 bg-black/80", onClick: closeNodeDetailModal }),
2358
+ /* @__PURE__ */ jsxs("div", { className: "fixed inset-4 z-50 flex flex-col bg-card rounded-lg border border-border shadow-xl overflow-hidden", children: [
2359
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border", children: [
2360
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2361
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-medium text-foreground", children: nodeData.label }),
2362
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground bg-secondary px-2 py-0.5 rounded", children: nodeDef.label })
2363
+ ] }),
2364
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2365
+ displayUrl && /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: handleDownload, children: [
2366
+ /* @__PURE__ */ jsx(Download, { className: "h-4 w-4 mr-1" }),
2367
+ "Download"
2368
+ ] }),
2369
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: closeNodeDetailModal, children: /* @__PURE__ */ jsx(X, { className: "w-5 h-5" }) })
2370
+ ] })
2371
+ ] }),
2372
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxs(
2373
+ "div",
2374
+ {
2375
+ className: "relative w-full h-full flex items-center justify-center bg-background overflow-hidden",
2376
+ onMouseDown: handleMouseDown,
2377
+ onMouseMove: handleMouseMove,
2378
+ onMouseUp: handleMouseUp,
2379
+ onMouseLeave: handleMouseUp,
2380
+ style: { cursor: zoomLevel > 1 ? isPanning ? "grabbing" : "grab" : "default" },
2381
+ children: [
2382
+ displayUrl ? /* @__PURE__ */ jsxs(
2383
+ "div",
2384
+ {
2385
+ className: "transition-transform duration-100",
2386
+ style: {
2387
+ transform: `scale(${zoomLevel}) translate(${panOffset.x / zoomLevel}px, ${panOffset.y / zoomLevel}px)`
2388
+ },
2389
+ children: [
2390
+ mediaInfo.type === "image" && /* @__PURE__ */ jsx(
2391
+ Image4,
2392
+ {
2393
+ src: displayUrl,
2394
+ alt: nodeData.label,
2395
+ width: 800,
2396
+ height: 600,
2397
+ className: "max-h-[calc(100vh-200px)] max-w-[calc(100vw-100px)] object-contain rounded-lg",
2398
+ unoptimized: true
2399
+ }
2400
+ ),
2401
+ mediaInfo.type === "video" && /* @__PURE__ */ jsx(
2402
+ "video",
2403
+ {
2404
+ src: displayUrl,
2405
+ controls: true,
2406
+ autoPlay: true,
2407
+ loop: true,
2408
+ className: "max-h-[calc(100vh-200px)] max-w-[calc(100vw-100px)] rounded-lg"
2409
+ }
2410
+ )
2411
+ ]
2412
+ }
2413
+ ) : /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground text-center", children: [
2414
+ /* @__PURE__ */ jsx("p", { className: "text-lg", children: "No preview available" }),
2415
+ /* @__PURE__ */ jsx("p", { className: "text-sm mt-2", children: "Generate content to see the preview" })
2416
+ ] }),
2417
+ hasMultipleImages && currentIndex > 0 && /* @__PURE__ */ jsx(
2418
+ Button,
2419
+ {
2420
+ variant: "ghost",
2421
+ size: "icon-sm",
2422
+ onClick: goToPrevious,
2423
+ className: "absolute left-4 top-1/2 -translate-y-1/2 bg-card/80 hover:bg-card border border-border shadow-md",
2424
+ title: "Previous image (\u2190)",
2425
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-5 h-5" })
2426
+ }
2427
+ ),
2428
+ hasMultipleImages && currentIndex < imageUrls.length - 1 && /* @__PURE__ */ jsx(
2429
+ Button,
2430
+ {
2431
+ variant: "ghost",
2432
+ size: "icon-sm",
2433
+ onClick: goToNext,
2434
+ className: "absolute right-4 top-1/2 -translate-y-1/2 bg-card/80 hover:bg-card border border-border shadow-md",
2435
+ title: "Next image (\u2192)",
2436
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-5 h-5" })
2437
+ }
2438
+ ),
2439
+ hasMultipleImages && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 bg-card/80 border border-border rounded-full px-3 py-1 text-xs text-muted-foreground shadow-md", children: [
2440
+ currentIndex + 1,
2441
+ " / ",
2442
+ imageUrls.length
2443
+ ] }),
2444
+ displayUrl && mediaInfo.type === "image" && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-4 right-4 flex items-center gap-2 bg-card border border-border rounded-lg p-1", children: [
2445
+ /* @__PURE__ */ jsx(
2446
+ Button,
2447
+ {
2448
+ variant: "ghost",
2449
+ size: "icon-sm",
2450
+ onClick: () => setZoomLevel((prev) => Math.max(prev - 0.25, 0.25)),
2451
+ title: "Zoom out (-)",
2452
+ children: /* @__PURE__ */ jsx(ZoomOut, { className: "w-4 h-4" })
2453
+ }
2454
+ ),
2455
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground w-12 text-center", children: [
2456
+ Math.round(zoomLevel * 100),
2457
+ "%"
2458
+ ] }),
2459
+ /* @__PURE__ */ jsx(
2460
+ Button,
2461
+ {
2462
+ variant: "ghost",
2463
+ size: "icon-sm",
2464
+ onClick: () => setZoomLevel((prev) => Math.min(prev + 0.25, 4)),
2465
+ title: "Zoom in (+)",
2466
+ children: /* @__PURE__ */ jsx(ZoomIn, { className: "w-4 h-4" })
2467
+ }
2468
+ ),
2469
+ /* @__PURE__ */ jsx(
2470
+ Button,
2471
+ {
2472
+ variant: "ghost",
2473
+ size: "sm",
2474
+ onClick: () => {
2475
+ setZoomLevel(1);
2476
+ setPanOffset({ x: 0, y: 0 });
2477
+ },
2478
+ title: "Reset zoom (0)",
2479
+ children: "Reset"
2480
+ }
2481
+ )
2482
+ ] })
2483
+ ]
2484
+ }
2485
+ ) })
2486
+ ] })
2487
+ ] });
2488
+ }
2519
2489
  var INPUT_TYPES = [
2520
2490
  { value: "image", label: "Image" },
2521
2491
  { value: "video", label: "Video" },
@@ -3150,7 +3120,7 @@ function AudioInputNodeComponent(props) {
3150
3120
  onChange: (e) => setUrlValue(e.target.value),
3151
3121
  onKeyDown: handleUrlKeyDown,
3152
3122
  placeholder: "https://...",
3153
- className: "flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3123
+ className: "nodrag nopan flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3154
3124
  }
3155
3125
  ),
3156
3126
  /* @__PURE__ */ jsx(
@@ -3289,7 +3259,7 @@ function ImageInputNodeComponent(props) {
3289
3259
  onChange: (e) => setUrlValue(e.target.value),
3290
3260
  onKeyDown: handleUrlKeyDown,
3291
3261
  placeholder: "https://...",
3292
- className: "flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3262
+ className: "nodrag nopan flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3293
3263
  }
3294
3264
  ),
3295
3265
  /* @__PURE__ */ jsx(
@@ -3554,7 +3524,7 @@ function PromptNodeComponent(props) {
3554
3524
  value: nodeData.prompt || "",
3555
3525
  onChange: handlePromptChange,
3556
3526
  placeholder: "Enter your prompt...",
3557
- className: "w-full flex-1 min-h-[80px] px-2 py-1.5 text-sm bg-background border border-border rounded resize-none focus:outline-none focus:ring-1 focus:ring-primary"
3527
+ className: "nodrag nopan w-full flex-1 min-h-[80px] px-2 py-1.5 text-sm bg-background border border-border rounded resize-none focus:outline-none focus:ring-1 focus:ring-primary"
3558
3528
  }
3559
3529
  ) });
3560
3530
  }
@@ -3676,7 +3646,7 @@ function VideoInputNodeComponent(props) {
3676
3646
  onChange: (e) => setUrlValue(e.target.value),
3677
3647
  onKeyDown: handleUrlKeyDown,
3678
3648
  placeholder: "https://...",
3679
- className: "flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3649
+ className: "nodrag nopan flex-1 h-7 px-2 text-xs rounded-md border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
3680
3650
  }
3681
3651
  ),
3682
3652
  /* @__PURE__ */ jsx(
@@ -3938,13 +3908,15 @@ function AnimationNodeComponent(props) {
3938
3908
  /* @__PURE__ */ jsx(SelectContent, { children: PRESET_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
3939
3909
  ] })
3940
3910
  ] }),
3941
- nodeData.curveType === "custom" && /* @__PURE__ */ jsxs("div", { className: "text-xs text-[var(--muted-foreground)]", children: [
3942
- "Bezier: [",
3943
- curve.map((v) => v.toFixed(2)).join(", "),
3944
- "]",
3945
- /* @__PURE__ */ jsx("div", { className: "mt-1 text-[var(--primary)] cursor-pointer hover:underline", children: "Edit in panel \u2192" })
3946
- ] }),
3947
- /* @__PURE__ */ jsx("div", { className: "h-20 bg-[var(--background)] rounded border border-[var(--border)] p-2", children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 100 100", className: "w-full h-full", children: [
3911
+ nodeData.curveType === "custom" && /* @__PURE__ */ jsx(
3912
+ CubicBezierEditor,
3913
+ {
3914
+ value: curve,
3915
+ onChange: (v) => updateNodeData(id, { customCurve: v }),
3916
+ disabled: nodeData.status === "processing"
3917
+ }
3918
+ ),
3919
+ nodeData.curveType === "preset" && /* @__PURE__ */ jsx("div", { className: "h-20 bg-[var(--background)] rounded border border-[var(--border)] p-2", children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 100 100", className: "w-full h-full", children: [
3948
3920
  /* @__PURE__ */ jsx("path", { d: pathD, fill: "none", stroke: "var(--primary)", strokeWidth: "2" }),
3949
3921
  /* @__PURE__ */ jsx("circle", { cx: "0", cy: "100", r: "3", fill: "var(--foreground)" }),
3950
3922
  /* @__PURE__ */ jsx("circle", { cx: "100", cy: "0", r: "3", fill: "var(--foreground)" }),
@@ -4129,7 +4101,7 @@ var ie = (e, t) => {
4129
4101
  }), [t, o]);
4130
4102
  };
4131
4103
  var I = { capture: false, passive: true };
4132
- var X4 = { capture: true, passive: false };
4104
+ var X5 = { capture: true, passive: false };
4133
4105
  var Me = (e) => {
4134
4106
  e.preventDefault(), e.currentTarget.focus();
4135
4107
  };
@@ -4173,7 +4145,7 @@ var se = forwardRef(({ boundsPadding: e = 0, browsingContext: t = globalThis, ch
4173
4145
  }), [v, T, L, t]), useImperativeHandle(de, () => ({ rootContainer: p.current, handleContainer: f.current, setPosition(n) {
4174
4146
  let { width: s, height: c } = p.current.getBoundingClientRect();
4175
4147
  l({ x: s / 100 * n, y: c / 100 * n });
4176
- } }), [l]), ie(p, Se), U("keydown", Ce, f.current, X4), U("click", Me, f.current, X4), U("pointerdown", Re, ue, X4);
4148
+ } }), [l]), ie(p, Se), U("keydown", Ce, f.current, X5), U("click", Me, f.current, X5), U("pointerdown", Re, ue, X5);
4177
4149
  let ve = i || jsx(F, { disabled: o, portrait: a }), K = me ? ce : void 0, he = { position: "relative", display: "flex", overflow: "hidden", cursor: L ? a ? "ns-resize" : "ew-resize" : void 0, touchAction: "none", userSelect: "none", KhtmlUserSelect: "none", msUserSelect: "none", MozUserSelect: "none", WebkitUserSelect: "none", ...le };
4178
4150
  return jsxs("div", { ...pe, ref: p, style: he, "data-rcs": "root", children: [m, jsx(B, { ref: j, transition: K, children: C }), jsx(W, { disabled: o, portrait: a, position: Math.round(d.current), ref: f, transition: K, children: ve })] });
4179
4151
  });
@@ -4888,9 +4860,6 @@ function ReframeNodeComponent(props) {
4888
4860
  ] }) });
4889
4861
  }
4890
4862
  var ReframeNode = memo(ReframeNodeComponent);
4891
-
4892
- // src/nodes/processing/ResizeNode.tsx
4893
- var import_core = __toESM(require_dist());
4894
4863
  var MODELS2 = {
4895
4864
  image: { id: "photon-flash-1", label: "Luma Photon Flash", price: "$0.01" },
4896
4865
  video: { id: "luma-reframe", label: "Luma Reframe", price: "$0.05" }
@@ -4954,7 +4923,7 @@ function ResizeNodeComponent(props) {
4954
4923
  /* @__PURE__ */ jsx(Label, { className: "text-xs", children: "Target Aspect Ratio" }),
4955
4924
  /* @__PURE__ */ jsxs(Select, { value: nodeData.targetAspectRatio, onValueChange: handleAspectRatioChange, children: [
4956
4925
  /* @__PURE__ */ jsx(SelectTrigger, { className: "nodrag h-9 w-full", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
4957
- /* @__PURE__ */ jsx(SelectContent, { children: import_core.LUMA_ASPECT_RATIOS.map((ratio) => /* @__PURE__ */ jsx(SelectItem, { value: ratio, children: ratio }, ratio)) })
4926
+ /* @__PURE__ */ jsx(SelectContent, { children: LUMA_ASPECT_RATIOS.map((ratio) => /* @__PURE__ */ jsx(SelectItem, { value: ratio, children: ratio }, ratio)) })
4958
4927
  ] })
4959
4928
  ] }),
4960
4929
  /* @__PURE__ */ jsx(
@@ -5981,4 +5950,4 @@ var nodeTypes = {
5981
5950
  workflowRef: WorkflowRefNode
5982
5951
  };
5983
5952
 
5984
- export { AnimationNode, AnnotationNode, AudioInputNode, BaseNode, DownloadNode, ImageCompareNode, ImageGenNode, ImageGridSplitNode, ImageInputNode, LLMNode, LipSyncNode, MotionControlNode, OutputGalleryNode, OutputNode, PromptConstructorNode, PromptNode, ReframeNode, ResizeNode, SubtitleNode, TextToSpeechNode, TranscribeNode, UpscaleNode, VideoFrameExtractNode, VideoGenNode, VideoInputNode, VideoStitchNode, VideoTrimNode, VoiceChangeNode, WorkflowInputNode, WorkflowOutputNode, WorkflowRefNode, nodeTypes, setWorkflowRefApi };
5953
+ export { AnimationNode, AnnotationNode, AudioInputNode, BaseNode, DownloadNode, ImageCompareNode, ImageGenNode, ImageGridSplitNode, ImageInputNode, LLMNode, LipSyncNode, MotionControlNode, NodeDetailModal, OutputGalleryNode, OutputNode, PromptConstructorNode, PromptNode, ReframeNode, ResizeNode, SubtitleNode, TextToSpeechNode, TranscribeNode, UpscaleNode, VideoFrameExtractNode, VideoGenNode, VideoInputNode, VideoStitchNode, VideoTrimNode, VoiceChangeNode, WorkflowInputNode, WorkflowOutputNode, WorkflowRefNode, nodeTypes, setWorkflowRefApi };