@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.
- package/dist/canvas.d.mts +16 -2
- package/dist/canvas.mjs +10 -8
- package/dist/chunk-6PSJTBNV.mjs +638 -0
- package/dist/chunk-7H3WJJYS.mjs +52 -0
- package/dist/{chunk-HCXI63ME.mjs → chunk-AUQGOJOQ.mjs} +27 -4
- package/dist/{chunk-AOTUCJMA.mjs → chunk-GWBGK3KL.mjs} +2 -2
- package/dist/chunk-JTPADIUO.mjs +130 -0
- package/dist/{chunk-SQK4JDYY.mjs → chunk-LT3ZJJL6.mjs} +9 -2
- package/dist/{chunk-7P2JWDC7.mjs → chunk-O5II6BOJ.mjs} +1198 -254
- package/dist/{chunk-AUZR6REQ.mjs → chunk-OQREHJXK.mjs} +1 -1
- package/dist/chunk-OY7BRSGG.mjs +60 -0
- package/dist/{chunk-E3YBVMYZ.mjs → chunk-PANZDSP6.mjs} +274 -305
- package/dist/chunk-PCIWWD37.mjs +90 -0
- package/dist/{chunk-RIGVIEYB.mjs → chunk-R727OFBR.mjs} +11 -1
- package/dist/chunk-ZD2BADZO.mjs +1294 -0
- package/dist/contextMenuStore-DMg0hJQ1.d.mts +22 -0
- package/dist/hooks.d.mts +53 -244
- package/dist/hooks.mjs +6 -6
- package/dist/index.d.mts +11 -7
- package/dist/index.mjs +13 -11
- package/dist/lib.d.mts +250 -4
- package/dist/lib.mjs +562 -2
- package/dist/nodes.d.mts +3 -1
- package/dist/nodes.mjs +6 -6
- package/dist/panels.mjs +3 -4
- package/dist/{promptLibraryStore-zqb59nsu.d.mts → promptLibraryStore-Bgw5LzvD.d.mts} +33 -5
- package/dist/provider.d.mts +2 -2
- package/dist/provider.mjs +0 -1
- package/dist/stores.d.mts +4 -3
- package/dist/stores.mjs +3 -40
- package/dist/toolbar.d.mts +3 -1
- package/dist/toolbar.mjs +5 -4
- package/dist/{types-ipAnBzAJ.d.mts → types-CF6DPx0P.d.mts} +8 -3
- package/dist/ui.d.mts +1 -1
- package/dist/ui.mjs +0 -1
- package/dist/{hooks.d.ts → useCommentNavigation-NzJjkaj2.d.mts} +15 -2
- package/dist/workflowStore-UAAKOOIK.mjs +2 -0
- package/package.json +32 -26
- package/dist/canvas.d.ts +0 -27
- package/dist/canvas.js +0 -45
- package/dist/chunk-3SPPKCWR.js +0 -458
- package/dist/chunk-3TMV3K34.js +0 -534
- package/dist/chunk-3YFFDHC5.js +0 -300
- package/dist/chunk-4MZ62VMF.js +0 -37
- package/dist/chunk-5HJFQVUR.js +0 -61
- package/dist/chunk-5LQ4QBR5.js +0 -2
- package/dist/chunk-6DOEUDD5.js +0 -254
- package/dist/chunk-AXFOCPPP.js +0 -998
- package/dist/chunk-BMFRA6GK.js +0 -1546
- package/dist/chunk-E323WAZG.mjs +0 -272
- package/dist/chunk-ECD5J2BA.js +0 -6022
- package/dist/chunk-EMGXUNBL.js +0 -120
- package/dist/chunk-EMUMKW5C.js +0 -107
- package/dist/chunk-FOMOOERN.js +0 -2
- package/dist/chunk-IASLG6IA.mjs +0 -118
- package/dist/chunk-IHF35QZD.js +0 -1095
- package/dist/chunk-JLWKW3G5.js +0 -2
- package/dist/chunk-KDIWRSYV.js +0 -375
- package/dist/chunk-L5TF4EHW.mjs +0 -1
- package/dist/chunk-RJ262NXS.js +0 -24
- package/dist/chunk-RXNEDWK2.js +0 -141
- package/dist/chunk-SEV2DWKF.js +0 -744
- package/dist/chunk-ZJWP5KGZ.mjs +0 -33
- package/dist/hooks.js +0 -56
- package/dist/index.d.ts +0 -29
- package/dist/index.js +0 -180
- package/dist/lib.d.ts +0 -164
- package/dist/lib.js +0 -144
- package/dist/nodes.d.ts +0 -128
- package/dist/nodes.js +0 -151
- package/dist/panels.d.ts +0 -22
- package/dist/panels.js +0 -21
- package/dist/promptLibraryStore-BZnfmEkc.d.ts +0 -464
- package/dist/provider.d.ts +0 -29
- package/dist/provider.js +0 -17
- package/dist/stores.d.ts +0 -96
- package/dist/stores.js +0 -113
- package/dist/toolbar.d.ts +0 -73
- package/dist/toolbar.js +0 -34
- package/dist/types-ipAnBzAJ.d.ts +0 -46
- package/dist/ui.d.ts +0 -67
- package/dist/ui.js +0 -84
- package/dist/workflowStore-7SDJC4UR.mjs +0 -3
- package/dist/workflowStore-LNJQ5RZG.js +0 -12
package/dist/lib.mjs
CHANGED
|
@@ -1,3 +1,563 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
4
|
-
import './chunk-
|
|
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-
|
|
10
|
-
import './chunk-
|
|
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-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-ZJWP5KGZ.mjs';
|
|
1
|
+
export { DebugPanel, NodePalette, PanelContainer } from './chunk-OQREHJXK.mjs';
|
|
2
|
+
import './chunk-LT3ZJJL6.mjs';
|
|
3
|
+
import './chunk-R727OFBR.mjs';
|