@genfeedai/workflow-ui 0.1.2 → 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 +32 -26
  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
package/dist/lib.mjs CHANGED
@@ -1,3 +1,563 @@
1
- export { DEFAULT_IMAGE_MODEL, DEFAULT_LIPSYNC_MODEL, DEFAULT_LLM_MODEL, DEFAULT_VIDEO_MODEL, EASING_PRESETS, IMAGE_MODELS, IMAGE_MODEL_ID_MAP, IMAGE_MODEL_MAP, LIPSYNC_MODELS, LIPSYNC_SYNC_MODES, LLM_MODELS, LLM_MODEL_ID_MAP, LLM_MODEL_MAP, VIDEO_MODELS, VIDEO_MODEL_ID_MAP, VIDEO_MODEL_MAP, applySpeedCurve, evaluateBezier, generateHandlesFromSchema, getEasingDisplayName, getImageModelLabel, getLLMModelLabel, getLipSyncModelLabel, getMediaFromNode, getVideoModelLabel, isSchemaHandle, lipSyncModelSupportsImage } from './chunk-E323WAZG.mjs';
1
+ import { easing, getEasingFunction } from './chunk-6PSJTBNV.mjs';
2
+ export { CubicBezierEditor, DEFAULT_CUSTOM_BEZIER, DEFAULT_IMAGE_MODEL, DEFAULT_LIPSYNC_MODEL, DEFAULT_LLM_MODEL, DEFAULT_VIDEO_MODEL, EASING_BEZIER_MAP, EASING_PRESETS, IMAGE_MODELS, IMAGE_MODEL_ID_MAP, IMAGE_MODEL_MAP, LIPSYNC_MODELS, LIPSYNC_SYNC_MODES, LLM_MODELS, LLM_MODEL_ID_MAP, LLM_MODEL_MAP, PRESET_BEZIERS, VIDEO_MODELS, VIDEO_MODEL_ID_MAP, VIDEO_MODEL_MAP, applySpeedCurve, createAsymmetricEase, createBezierEasing, easing, evaluateBezier, generateHandlesFromSchema, getAllEasingNames, getEasingBezier, getEasingDisplayName, getEasingFunction, getImageModelLabel, getLLMModelLabel, getLipSyncModelLabel, getMediaFromNode, getPresetBezier, getVideoModelLabel, isSchemaHandle, lipSyncModelSupportsImage } from './chunk-6PSJTBNV.mjs';
3
+ export { calculateWorkflowCost, formatCost } from './chunk-JTPADIUO.mjs';
4
+ import './chunk-OY7BRSGG.mjs';
2
5
  export { CONNECTION_FIELDS, extractEnumValues, getImageDimensions, getSchemaDefaults, getVideoMetadata, supportsImageInput, validateRequiredSchemaFields } from './chunk-EFXQT23N.mjs';
3
- import './chunk-ZJWP5KGZ.mjs';
6
+
7
+ // src/lib/speedCurve.ts
8
+ var INVERSE_TOLERANCE = 1e-6;
9
+ var INVERSE_MAX_ITERATIONS = 32;
10
+ var MONOTONICITY_SAMPLES = 256;
11
+ var MONOTONICITY_TOLERANCE = 1e-6;
12
+ var inverseCache = /* @__PURE__ */ new WeakMap();
13
+ var monotonicityCache = /* @__PURE__ */ new WeakMap();
14
+ function isMonotonicIncreasing(func) {
15
+ const cached = monotonicityCache.get(func);
16
+ if (cached !== void 0) {
17
+ return cached;
18
+ }
19
+ let prev = func(0);
20
+ for (let i = 1; i <= MONOTONICITY_SAMPLES; i++) {
21
+ const value = func(i / MONOTONICITY_SAMPLES);
22
+ if (value + MONOTONICITY_TOLERANCE < prev) {
23
+ monotonicityCache.set(func, false);
24
+ return false;
25
+ }
26
+ prev = value;
27
+ }
28
+ monotonicityCache.set(func, true);
29
+ return true;
30
+ }
31
+ function invertEasingValue(target, func) {
32
+ if (target <= INVERSE_TOLERANCE) {
33
+ return 0;
34
+ }
35
+ if (target >= 1 - INVERSE_TOLERANCE) {
36
+ return 1;
37
+ }
38
+ let low = 0;
39
+ let high = 1;
40
+ let mid = 0.5;
41
+ for (let i = 0; i < INVERSE_MAX_ITERATIONS; i++) {
42
+ mid = (low + high) / 2;
43
+ const value = func(mid);
44
+ const diff = value - target;
45
+ if (Math.abs(diff) <= INVERSE_TOLERANCE) {
46
+ break;
47
+ }
48
+ if (diff < 0) {
49
+ low = mid;
50
+ } else {
51
+ high = mid;
52
+ }
53
+ }
54
+ return Math.min(1, Math.max(0, mid));
55
+ }
56
+ function getInverseEasing(func) {
57
+ if (inverseCache.has(func)) {
58
+ return inverseCache.get(func);
59
+ }
60
+ if (!isMonotonicIncreasing(func)) {
61
+ inverseCache.set(func, null);
62
+ return null;
63
+ }
64
+ const inverse = (value) => {
65
+ const clamped = Math.max(0, Math.min(1, value));
66
+ return invertEasingValue(clamped, func);
67
+ };
68
+ inverseCache.set(func, inverse);
69
+ return inverse;
70
+ }
71
+ function mapTimeWithEasing(normalizedTime, func) {
72
+ const inverse = getInverseEasing(func);
73
+ if (!inverse) {
74
+ return func(normalizedTime);
75
+ }
76
+ return inverse(normalizedTime);
77
+ }
78
+ function warpTime(originalTime, inputDuration = 5, outputDuration = 1.5, easingFunction = easing.easeInOutCubic) {
79
+ const easingFunc = typeof easingFunction === "string" ? getEasingFunction(easingFunction) : easingFunction;
80
+ const t = originalTime / inputDuration;
81
+ const clamped = Math.max(0, Math.min(1, t));
82
+ const eased = mapTimeWithEasing(clamped, easingFunc);
83
+ return eased * outputDuration;
84
+ }
85
+ function calculateWarpedDuration(originalStart, originalDuration, inputDuration = 5, outputDuration = 1.5, easingFunction = easing.easeInOutCubic) {
86
+ const warpedStart = warpTime(originalStart, inputDuration, outputDuration, easingFunction);
87
+ const warpedEnd = warpTime(
88
+ originalStart + originalDuration,
89
+ inputDuration,
90
+ outputDuration,
91
+ easingFunction
92
+ );
93
+ return warpedEnd - warpedStart;
94
+ }
95
+ function validateWarpFunction(easingFunction = easing.easeInOutCubic, inputDuration = 5, outputDuration = 1.5, tolerance = 1e-3) {
96
+ const errors = [];
97
+ const startWarp = warpTime(0, inputDuration, outputDuration, easingFunction);
98
+ if (Math.abs(startWarp - 0) > tolerance) {
99
+ errors.push(`Start point should be 0, got ${startWarp}`);
100
+ }
101
+ const endWarp = warpTime(inputDuration, inputDuration, outputDuration, easingFunction);
102
+ if (Math.abs(endWarp - outputDuration) > tolerance) {
103
+ errors.push(`End point should be ${outputDuration}, got ${endWarp}`);
104
+ }
105
+ let prevWarp = 0;
106
+ for (let t = 0; t <= inputDuration; t += inputDuration / 100) {
107
+ const warp = warpTime(t, inputDuration, outputDuration, easingFunction);
108
+ if (warp < prevWarp) {
109
+ errors.push(`Monotonicity violation at t=${t.toFixed(2)}: ${warp} < ${prevWarp}`);
110
+ break;
111
+ }
112
+ prevWarp = warp;
113
+ }
114
+ return { valid: errors.length === 0, errors };
115
+ }
116
+ function analyzeWarpCurve(easingFunction = easing.easeInOutCubic, inputDuration = 5, outputDuration = 1.5, samples = 100) {
117
+ const speedMultipliers = [];
118
+ const averageSpeed = inputDuration / outputDuration;
119
+ for (let i = 0; i < samples; i++) {
120
+ const t1 = i / samples * inputDuration;
121
+ const t2 = (i + 1) / samples * inputDuration;
122
+ const warp1 = warpTime(t1, inputDuration, outputDuration, easingFunction);
123
+ const warp2 = warpTime(t2, inputDuration, outputDuration, easingFunction);
124
+ const inputSegmentDuration = t2 - t1;
125
+ const outputSegmentDuration = warp2 - warp1;
126
+ const absoluteSpeed = inputSegmentDuration / (outputSegmentDuration + 1e-10);
127
+ const speedMultiplier = absoluteSpeed / averageSpeed;
128
+ speedMultipliers.push(speedMultiplier);
129
+ }
130
+ const minSpeed = Math.min(...speedMultipliers);
131
+ const maxSpeed = Math.max(...speedMultipliers);
132
+ const avgSpeed = speedMultipliers.reduce((a, b) => a + b, 0) / speedMultipliers.length;
133
+ return { speedMultipliers, minSpeed, maxSpeed, avgSpeed };
134
+ }
135
+
136
+ // src/lib/gridSplitter.ts
137
+ var COMMON_ASPECT_RATIOS = [
138
+ 16 / 9,
139
+ // 1.778 - Widescreen video
140
+ 4 / 3,
141
+ // 1.333 - Standard photo/video
142
+ 3 / 2,
143
+ // 1.5 - DSLR photos
144
+ 1.85,
145
+ // 1.85:1 - Cinema flat
146
+ 2.39,
147
+ // 2.39:1 - Cinema scope
148
+ 1,
149
+ // 1:1 - Square
150
+ 9 / 16,
151
+ // 0.5625 - Portrait video
152
+ 3 / 4,
153
+ // 0.75 - Portrait photo
154
+ 2 / 3
155
+ // 0.667 - Portrait DSLR
156
+ ];
157
+ async function detectGrid(imageDataUrl) {
158
+ return new Promise((resolve, reject) => {
159
+ const img = new Image();
160
+ img.crossOrigin = "anonymous";
161
+ img.onload = () => {
162
+ try {
163
+ const canvas = document.createElement("canvas");
164
+ const ctx = canvas.getContext("2d");
165
+ if (!ctx) {
166
+ reject(new Error("Could not get canvas context"));
167
+ return;
168
+ }
169
+ canvas.width = img.width;
170
+ canvas.height = img.height;
171
+ ctx.drawImage(img, 0, 0);
172
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
173
+ const result = analyzeGridFromImageData(imageData);
174
+ resolve(result);
175
+ } catch (error) {
176
+ reject(error);
177
+ }
178
+ };
179
+ img.onerror = () => {
180
+ reject(new Error("Failed to load image"));
181
+ };
182
+ img.src = imageDataUrl;
183
+ });
184
+ }
185
+ function createGridForDimensions(width, height, rows, cols) {
186
+ const cellWidth = width / cols;
187
+ const cellHeight = height / rows;
188
+ const cells = [];
189
+ for (let row = 0; row < rows; row++) {
190
+ for (let col = 0; col < cols; col++) {
191
+ cells.push({
192
+ x: Math.round(col * cellWidth),
193
+ y: Math.round(row * cellHeight),
194
+ width: Math.round(cellWidth),
195
+ height: Math.round(cellHeight)
196
+ });
197
+ }
198
+ }
199
+ return { rows, cols, cells, confidence: 1 };
200
+ }
201
+ async function detectGridWithDimensions(imageDataUrl, rows, cols) {
202
+ return new Promise((resolve, reject) => {
203
+ const img = new Image();
204
+ img.crossOrigin = "anonymous";
205
+ img.onload = () => {
206
+ const result = createGridForDimensions(img.width, img.height, rows, cols);
207
+ resolve(result);
208
+ };
209
+ img.onerror = () => {
210
+ reject(new Error("Failed to load image"));
211
+ };
212
+ img.src = imageDataUrl;
213
+ });
214
+ }
215
+ function aspectRatioScore(aspectRatio) {
216
+ let bestMatch = Infinity;
217
+ for (const commonAR of COMMON_ASPECT_RATIOS) {
218
+ const ratio = aspectRatio > commonAR ? aspectRatio / commonAR : commonAR / aspectRatio;
219
+ const distance = ratio - 1;
220
+ bestMatch = Math.min(bestMatch, distance);
221
+ }
222
+ return Math.exp(-bestMatch * 3);
223
+ }
224
+ function getGridCandidates(width, height) {
225
+ const candidates = [];
226
+ const imageAspectRatio = width / height;
227
+ for (let rows = 1; rows <= 6; rows++) {
228
+ for (let cols = 1; cols <= 6; cols++) {
229
+ if (rows === 1 && cols === 1) continue;
230
+ const cellWidth = width / cols;
231
+ const cellHeight = height / rows;
232
+ const cellAspectRatio = cellWidth / cellHeight;
233
+ const cellARScore = aspectRatioScore(cellAspectRatio);
234
+ const gridAspectRatio = cols / rows;
235
+ const layoutRatio = imageAspectRatio > gridAspectRatio ? imageAspectRatio / gridAspectRatio : gridAspectRatio / imageAspectRatio;
236
+ const layoutScore = Math.exp(-(layoutRatio - 1) * 2);
237
+ const cellCount = rows * cols;
238
+ const cellCountScore = Math.min(cellCount / 6, 1);
239
+ const gridSymmetry = 1 - Math.abs(rows - cols) / Math.max(rows, cols);
240
+ const score = cellARScore * 0.45 + layoutScore * 0.25 + cellCountScore * 0.15 + gridSymmetry * 0.15;
241
+ candidates.push({
242
+ rows,
243
+ cols,
244
+ cellWidth,
245
+ cellHeight,
246
+ cellAspectRatio,
247
+ score
248
+ });
249
+ }
250
+ }
251
+ return candidates.sort((a, b) => b.score - a.score);
252
+ }
253
+ function analyzeGridFromImageData(imageData) {
254
+ const { width, height, data } = imageData;
255
+ const candidates = getGridCandidates(width, height);
256
+ const verticalEdgeStrength = calculateVerticalEdgeProfile(data, width, height);
257
+ const horizontalEdgeStrength = calculateHorizontalEdgeProfile(data, width, height);
258
+ let bestCandidate = candidates[0];
259
+ let bestCombinedScore = -Infinity;
260
+ for (const candidate of candidates.slice(0, 8)) {
261
+ const edgeScore = scoreGridByEdges(
262
+ candidate.rows,
263
+ candidate.cols,
264
+ width,
265
+ height,
266
+ verticalEdgeStrength,
267
+ horizontalEdgeStrength
268
+ );
269
+ const combinedScore = candidate.score * 0.7 + edgeScore * 0.3;
270
+ if (combinedScore > bestCombinedScore) {
271
+ bestCombinedScore = combinedScore;
272
+ bestCandidate = candidate;
273
+ }
274
+ }
275
+ const result = createGridForDimensions(width, height, bestCandidate.rows, bestCandidate.cols);
276
+ result.confidence = bestCombinedScore;
277
+ return result;
278
+ }
279
+ function calculateVerticalEdgeProfile(data, width, height) {
280
+ const profile = new Float32Array(width);
281
+ for (let x = 1; x < width - 1; x++) {
282
+ let totalGradient = 0;
283
+ for (let y = 0; y < height; y++) {
284
+ const idxLeft = (y * width + (x - 1)) * 4;
285
+ const idxRight = (y * width + (x + 1)) * 4;
286
+ const gradR = Math.abs(data[idxRight] - data[idxLeft]);
287
+ const gradG = Math.abs(data[idxRight + 1] - data[idxLeft + 1]);
288
+ const gradB = Math.abs(data[idxRight + 2] - data[idxLeft + 2]);
289
+ totalGradient += (gradR + gradG + gradB) / 3;
290
+ }
291
+ profile[x] = totalGradient / height;
292
+ }
293
+ return profile;
294
+ }
295
+ function calculateHorizontalEdgeProfile(data, width, height) {
296
+ const profile = new Float32Array(height);
297
+ for (let y = 1; y < height - 1; y++) {
298
+ let totalGradient = 0;
299
+ for (let x = 0; x < width; x++) {
300
+ const idxUp = ((y - 1) * width + x) * 4;
301
+ const idxDown = ((y + 1) * width + x) * 4;
302
+ const gradR = Math.abs(data[idxDown] - data[idxUp]);
303
+ const gradG = Math.abs(data[idxDown + 1] - data[idxUp + 1]);
304
+ const gradB = Math.abs(data[idxDown + 2] - data[idxUp + 2]);
305
+ totalGradient += (gradR + gradG + gradB) / 3;
306
+ }
307
+ profile[y] = totalGradient / width;
308
+ }
309
+ return profile;
310
+ }
311
+ function scoreGridByEdges(rows, cols, width, height, verticalProfile, horizontalProfile) {
312
+ let verticalSum = 0;
313
+ for (let i = 0; i < verticalProfile.length; i++) {
314
+ verticalSum += verticalProfile[i];
315
+ }
316
+ const verticalBaseline = verticalSum / verticalProfile.length;
317
+ let horizontalSum = 0;
318
+ for (let i = 0; i < horizontalProfile.length; i++) {
319
+ horizontalSum += horizontalProfile[i];
320
+ }
321
+ const horizontalBaseline = horizontalSum / horizontalProfile.length;
322
+ let totalRatio = 0;
323
+ let divisions = 0;
324
+ const searchWindow = Math.max(3, Math.floor(Math.min(width / cols, height / rows) * 0.03));
325
+ if (cols > 1) {
326
+ const cellWidth = width / cols;
327
+ for (let i = 1; i < cols; i++) {
328
+ const expectedPos = Math.round(cellWidth * i);
329
+ let maxStrength = 0;
330
+ for (let offset = -searchWindow; offset <= searchWindow; offset++) {
331
+ const pos = expectedPos + offset;
332
+ if (pos > 0 && pos < width - 1) {
333
+ maxStrength = Math.max(maxStrength, verticalProfile[pos]);
334
+ }
335
+ }
336
+ const ratio = verticalBaseline > 0 ? maxStrength / verticalBaseline : 1;
337
+ totalRatio += Math.min(ratio, 3);
338
+ divisions++;
339
+ }
340
+ }
341
+ if (rows > 1) {
342
+ const cellHeight = height / rows;
343
+ for (let i = 1; i < rows; i++) {
344
+ const expectedPos = Math.round(cellHeight * i);
345
+ let maxStrength = 0;
346
+ for (let offset = -searchWindow; offset <= searchWindow; offset++) {
347
+ const pos = expectedPos + offset;
348
+ if (pos > 0 && pos < height - 1) {
349
+ maxStrength = Math.max(maxStrength, horizontalProfile[pos]);
350
+ }
351
+ }
352
+ const ratio = horizontalBaseline > 0 ? maxStrength / horizontalBaseline : 1;
353
+ totalRatio += Math.min(ratio, 3);
354
+ divisions++;
355
+ }
356
+ }
357
+ if (divisions === 0) return 0;
358
+ const avgRatio = totalRatio / divisions;
359
+ return Math.min((avgRatio - 1) / 2, 1);
360
+ }
361
+ async function splitImage(imageDataUrl, grid) {
362
+ return new Promise((resolve, reject) => {
363
+ const img = new Image();
364
+ img.crossOrigin = "anonymous";
365
+ img.onload = () => {
366
+ try {
367
+ const results = [];
368
+ for (const cell of grid.cells) {
369
+ const canvas = document.createElement("canvas");
370
+ const ctx = canvas.getContext("2d");
371
+ if (!ctx) {
372
+ reject(new Error("Could not get canvas context"));
373
+ return;
374
+ }
375
+ canvas.width = cell.width;
376
+ canvas.height = cell.height;
377
+ ctx.drawImage(
378
+ img,
379
+ cell.x,
380
+ cell.y,
381
+ cell.width,
382
+ cell.height,
383
+ 0,
384
+ 0,
385
+ cell.width,
386
+ cell.height
387
+ );
388
+ results.push(canvas.toDataURL("image/png"));
389
+ }
390
+ resolve(results);
391
+ } catch (error) {
392
+ reject(error);
393
+ }
394
+ };
395
+ img.onerror = () => {
396
+ reject(new Error("Failed to load image"));
397
+ };
398
+ img.src = imageDataUrl;
399
+ });
400
+ }
401
+ async function detectAndSplitGrid(imageDataUrl) {
402
+ const grid = await detectGrid(imageDataUrl);
403
+ const images = await splitImage(imageDataUrl, grid);
404
+ return { grid, images };
405
+ }
406
+ async function splitWithDimensions(imageDataUrl, rows, cols) {
407
+ const grid = await detectGridWithDimensions(imageDataUrl, rows, cols);
408
+ const images = await splitImage(imageDataUrl, grid);
409
+ return { grid, images };
410
+ }
411
+
412
+ // src/lib/nodeDimensions.ts
413
+ function getImageDimensions2(base64DataUrl) {
414
+ return new Promise((resolve) => {
415
+ if (!base64DataUrl || !base64DataUrl.startsWith("data:image")) {
416
+ resolve(null);
417
+ return;
418
+ }
419
+ const img = new Image();
420
+ img.onload = () => {
421
+ resolve({ width: img.naturalWidth, height: img.naturalHeight });
422
+ };
423
+ img.onerror = () => {
424
+ resolve(null);
425
+ };
426
+ img.src = base64DataUrl;
427
+ });
428
+ }
429
+ function getVideoDimensions(videoUrl) {
430
+ return new Promise((resolve) => {
431
+ if (!videoUrl) {
432
+ resolve(null);
433
+ return;
434
+ }
435
+ const video = document.createElement("video");
436
+ video.onloadedmetadata = () => {
437
+ resolve({ width: video.videoWidth, height: video.videoHeight });
438
+ };
439
+ video.onerror = () => {
440
+ resolve(null);
441
+ };
442
+ video.src = videoUrl;
443
+ });
444
+ }
445
+ var MIN_WIDTH = 200;
446
+ var MAX_WIDTH = 500;
447
+ var MIN_HEIGHT = 200;
448
+ var MAX_HEIGHT = 600;
449
+ var NODE_CHROME_HEIGHT = 100;
450
+ function calculateNodeSize(aspectRatio, baseWidth = 300) {
451
+ if (!aspectRatio || aspectRatio <= 0 || !Number.isFinite(aspectRatio)) {
452
+ return { width: 300, height: 300 };
453
+ }
454
+ let width = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, baseWidth));
455
+ let contentHeight = width / aspectRatio;
456
+ let totalHeight = contentHeight + NODE_CHROME_HEIGHT;
457
+ if (totalHeight > MAX_HEIGHT) {
458
+ contentHeight = MAX_HEIGHT - NODE_CHROME_HEIGHT;
459
+ width = contentHeight * aspectRatio;
460
+ totalHeight = MAX_HEIGHT;
461
+ }
462
+ if (totalHeight < MIN_HEIGHT) {
463
+ contentHeight = MIN_HEIGHT - NODE_CHROME_HEIGHT;
464
+ width = contentHeight * aspectRatio;
465
+ totalHeight = MIN_HEIGHT;
466
+ }
467
+ if (width > MAX_WIDTH) {
468
+ width = MAX_WIDTH;
469
+ contentHeight = width / aspectRatio;
470
+ totalHeight = contentHeight + NODE_CHROME_HEIGHT;
471
+ totalHeight = Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, totalHeight));
472
+ }
473
+ if (width < MIN_WIDTH) {
474
+ width = MIN_WIDTH;
475
+ contentHeight = width / aspectRatio;
476
+ totalHeight = contentHeight + NODE_CHROME_HEIGHT;
477
+ totalHeight = Math.max(MIN_HEIGHT, Math.min(MAX_HEIGHT, totalHeight));
478
+ }
479
+ return {
480
+ width: Math.round(width),
481
+ height: Math.round(totalHeight)
482
+ };
483
+ }
484
+ function calculateNodeSizePreservingHeight(aspectRatio, currentHeight) {
485
+ if (!aspectRatio || aspectRatio <= 0 || !Number.isFinite(aspectRatio)) {
486
+ return { width: 300, height: currentHeight ?? 300 };
487
+ }
488
+ if (currentHeight !== void 0 && currentHeight >= MIN_HEIGHT && currentHeight <= MAX_HEIGHT) {
489
+ const contentHeight = currentHeight - NODE_CHROME_HEIGHT;
490
+ let width = contentHeight * aspectRatio;
491
+ width = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, width));
492
+ return {
493
+ width: Math.round(width),
494
+ height: Math.round(currentHeight)
495
+ };
496
+ }
497
+ return calculateNodeSize(aspectRatio);
498
+ }
499
+
500
+ // src/lib/deduplicatedFetch.ts
501
+ var inFlightRequests = /* @__PURE__ */ new Map();
502
+ var responseCache = /* @__PURE__ */ new Map();
503
+ var CACHE_TTL = 5e3;
504
+ var pendingTimeouts = /* @__PURE__ */ new Map();
505
+ function getCacheKey(url, headers) {
506
+ if (!headers) return url;
507
+ const headerObj = headers instanceof Headers ? Object.fromEntries(headers.entries()) : Array.isArray(headers) ? Object.fromEntries(headers) : headers;
508
+ const sortedHeaders = Object.keys(headerObj).sort().map((k) => `${k}:${headerObj[k]}`).join("|");
509
+ return `${url}|${sortedHeaders}`;
510
+ }
511
+ async function deduplicatedFetch(url, options) {
512
+ const cacheKey = getCacheKey(url, options?.headers);
513
+ const cached = responseCache.get(cacheKey);
514
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
515
+ return new Response(cached.bodyText, {
516
+ status: cached.status,
517
+ headers: cached.headers
518
+ });
519
+ }
520
+ const existingRequest = inFlightRequests.get(cacheKey);
521
+ if (existingRequest) {
522
+ await existingRequest;
523
+ const cachedData = responseCache.get(cacheKey);
524
+ if (cachedData) {
525
+ return new Response(cachedData.bodyText, {
526
+ status: cachedData.status,
527
+ headers: cachedData.headers
528
+ });
529
+ }
530
+ return new Response(JSON.stringify({ error: "Cache miss" }), { status: 500 });
531
+ }
532
+ const requestPromise = fetch(url, options).then(async (response) => {
533
+ try {
534
+ const bodyText = await response.clone().text();
535
+ responseCache.set(cacheKey, {
536
+ status: response.status,
537
+ headers: Object.fromEntries(response.headers.entries()),
538
+ bodyText,
539
+ timestamp: Date.now()
540
+ });
541
+ } catch {
542
+ }
543
+ return response;
544
+ }).finally(() => {
545
+ const timeoutId = setTimeout(() => {
546
+ inFlightRequests.delete(cacheKey);
547
+ pendingTimeouts.delete(cacheKey);
548
+ }, 50);
549
+ pendingTimeouts.set(cacheKey, timeoutId);
550
+ });
551
+ inFlightRequests.set(cacheKey, requestPromise);
552
+ return requestPromise;
553
+ }
554
+ function clearFetchCache() {
555
+ responseCache.clear();
556
+ inFlightRequests.clear();
557
+ for (const timeoutId of pendingTimeouts.values()) {
558
+ clearTimeout(timeoutId);
559
+ }
560
+ pendingTimeouts.clear();
561
+ }
562
+
563
+ export { analyzeWarpCurve, calculateNodeSize, calculateNodeSizePreservingHeight, calculateWarpedDuration, clearFetchCache, createGridForDimensions, deduplicatedFetch, detectAndSplitGrid, detectGrid, detectGridWithDimensions, getGridCandidates, getImageDimensions2 as getImageDimensionsFromDataUrl, getVideoDimensions as getVideoDimensionsFromUrl, splitImage, splitWithDimensions, validateWarpFunction, warpTime };
package/dist/nodes.d.mts CHANGED
@@ -41,6 +41,8 @@ interface BaseNodeProps extends NodeProps {
41
41
  declare function BaseNodeComponent({ id, type, data, selected, children, headerActions, title, titleElement, hideStatusIndicator, width, height, disabledInputs, }: BaseNodeProps): react_jsx_runtime.JSX.Element | null;
42
42
  declare const BaseNode: react.MemoExoticComponent<typeof BaseNodeComponent>;
43
43
 
44
+ declare function NodeDetailModal(): react_jsx_runtime.JSX.Element | null;
45
+
44
46
  declare function WorkflowInputNodeComponent(props: NodeProps): react_jsx_runtime.JSX.Element;
45
47
  declare const WorkflowInputNode: react.MemoExoticComponent<typeof WorkflowInputNodeComponent>;
46
48
 
@@ -125,4 +127,4 @@ declare const VideoTrimNode: react.MemoExoticComponent<typeof VideoTrimNodeCompo
125
127
 
126
128
  declare const nodeTypes: NodeTypes;
127
129
 
128
- export { AnimationNode, AnnotationNode, AudioInputNode, BaseNode, DownloadNode, ImageCompareNode, ImageGenNode, ImageGridSplitNode, ImageInputNode, LLMNode, LipSyncNode, MotionControlNode, OutputGalleryNode, OutputNode, PromptConstructorNode, PromptNode, type ReferencableWorkflow, ReframeNode, ResizeNode, SubtitleNode, TextToSpeechNode, TranscribeNode, UpscaleNode, VideoFrameExtractNode, VideoGenNode, VideoInputNode, VideoStitchNode, VideoTrimNode, VoiceChangeNode, WorkflowInputNode, WorkflowOutputNode, type WorkflowRefApi, WorkflowRefNode, nodeTypes, setWorkflowRefApi };
130
+ export { AnimationNode, AnnotationNode, AudioInputNode, BaseNode, DownloadNode, ImageCompareNode, ImageGenNode, ImageGridSplitNode, ImageInputNode, LLMNode, LipSyncNode, MotionControlNode, NodeDetailModal, OutputGalleryNode, OutputNode, PromptConstructorNode, PromptNode, type ReferencableWorkflow, ReframeNode, ResizeNode, SubtitleNode, TextToSpeechNode, TranscribeNode, UpscaleNode, VideoFrameExtractNode, VideoGenNode, VideoInputNode, VideoStitchNode, VideoTrimNode, VoiceChangeNode, WorkflowInputNode, WorkflowOutputNode, type WorkflowRefApi, WorkflowRefNode, nodeTypes, setWorkflowRefApi };
package/dist/nodes.mjs CHANGED
@@ -1,14 +1,14 @@
1
- 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 } from './chunk-E3YBVMYZ.mjs';
1
+ 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 } from './chunk-PANZDSP6.mjs';
2
2
  import './chunk-ZJD5WMR3.mjs';
3
- import './chunk-E323WAZG.mjs';
4
- import './chunk-AOTUCJMA.mjs';
3
+ import './chunk-6PSJTBNV.mjs';
4
+ import './chunk-OY7BRSGG.mjs';
5
+ import './chunk-GWBGK3KL.mjs';
5
6
  import './chunk-7SKSRSS7.mjs';
6
7
  import './chunk-EFXQT23N.mjs';
7
8
  import './chunk-CV4M7CNU.mjs';
8
9
  import './chunk-LDN7IX4Y.mjs';
9
- import './chunk-SQK4JDYY.mjs';
10
- import './chunk-RIGVIEYB.mjs';
10
+ import './chunk-LT3ZJJL6.mjs';
11
+ import './chunk-R727OFBR.mjs';
11
12
  import './chunk-MLJJBBTB.mjs';
12
13
  import './chunk-FT33LFII.mjs';
13
14
  import './chunk-VRN3UWE5.mjs';
14
- import './chunk-ZJWP5KGZ.mjs';
package/dist/panels.mjs CHANGED
@@ -1,4 +1,3 @@
1
- export { DebugPanel, NodePalette, PanelContainer } from './chunk-AUZR6REQ.mjs';
2
- import './chunk-SQK4JDYY.mjs';
3
- import './chunk-RIGVIEYB.mjs';
4
- import './chunk-ZJWP5KGZ.mjs';
1
+ export { DebugPanel, NodePalette, PanelContainer } from './chunk-OQREHJXK.mjs';
2
+ import './chunk-LT3ZJJL6.mjs';
3
+ import './chunk-R727OFBR.mjs';