@oomol-lab/open-flow 0.1.0-beta.82 → 0.1.0-beta.83
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/browser/{FlowCanvas-Dew2fmoT.js → FlowCanvas-ChbukrDh.js} +832 -269
- package/dist/browser/{createResourceDialog-bdOJa5Zk.js → createResourceDialog-Bi4fUnbD.js} +3 -3
- package/dist/browser/{dialog-CFlvkliO.js → dialog-BzoSxhXQ.js} +1 -1
- package/dist/browser/{exportPng-Cjdb6COo.js → exportPng-CrAFfOaD.js} +187 -70
- package/dist/browser/{flowChanges-URBEd4DI.js → flowChanges-C567g-Pc.js} +94 -24
- package/dist/browser/{flowWorkspace-BlXx-yAn.js → flowWorkspace-rvcneG4q.js} +706 -209
- package/dist/browser/licenses.md +2 -2
- package/dist/browser/{markdownContent-IS8xXDoc.js → markdownContent-B-GLj5DU.js} +1 -1
- package/dist/browser/preview.css +37 -0
- package/dist/browser/preview.js +947 -323
- package/dist/browser/{tooltip-BDcVTNpu.js → tooltip-DGj5pudg.js} +1 -1
- package/dist/browser/ui.css +37 -0
- package/dist/browser/workbench.css +37 -0
- package/dist/browser/workbench.js +11 -10
- package/dist/browser/{workbenchSelect-Ci0KCYv9.js → workbenchSelect-BIaEVTx6.js} +2 -2
- package/dist/browser/{wrapLayout-DZvW9dBs.js → wrapLayout-C4moMKgb.js} +9 -2
- package/dist/command/index.js +1 -1
- package/dist/render/browser/licenses.md +2 -2
- package/dist/render/browser/runtime.css +37 -0
- package/dist/render/browser/runtime.js +1684 -923
- package/dist/render/common/png.d.ts +8 -0
- package/dist/render/node/index.d.ts +1 -1
- package/dist/render/node/index.js +17 -0
- package/package.json +1 -1
|
@@ -40,7 +40,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
40
40
|
enumerable: true
|
|
41
41
|
}) : target, mod));
|
|
42
42
|
//#endregion
|
|
43
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
43
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/util.js
|
|
44
44
|
function resolveUrl(url, baseUrl) {
|
|
45
45
|
if (url.match(/^[a-z]+:\/\//i)) return url;
|
|
46
46
|
if (url.match(/^\/\//)) return window.location.protocol + url;
|
|
@@ -67,6 +67,13 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
67
67
|
for (let i = 0, l = arrayLike.length; i < l; i++) arr.push(arrayLike[i]);
|
|
68
68
|
return arr;
|
|
69
69
|
}
|
|
70
|
+
var styleProps = null;
|
|
71
|
+
function getStyleProperties(options = {}) {
|
|
72
|
+
if (options.includeStyleProperties) return options.includeStyleProperties;
|
|
73
|
+
if (styleProps) return styleProps;
|
|
74
|
+
styleProps = toArray(window.getComputedStyle(document.documentElement));
|
|
75
|
+
return styleProps;
|
|
76
|
+
}
|
|
70
77
|
function px(node, styleProperty) {
|
|
71
78
|
const val = (node.ownerDocument.defaultView || window).getComputedStyle(node).getPropertyValue(styleProperty);
|
|
72
79
|
return val ? parseFloat(val.replace("px", "")) : 0;
|
|
@@ -90,8 +97,11 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
90
97
|
function createImage(url) {
|
|
91
98
|
return new Promise((resolve, reject) => {
|
|
92
99
|
const img = new Image();
|
|
93
|
-
img.
|
|
94
|
-
|
|
100
|
+
img.onload = () => {
|
|
101
|
+
img.decode().then(() => {
|
|
102
|
+
requestAnimationFrame(() => resolve(img));
|
|
103
|
+
});
|
|
104
|
+
};
|
|
95
105
|
img.onerror = reject;
|
|
96
106
|
img.crossOrigin = "anonymous";
|
|
97
107
|
img.decoding = "async";
|
|
@@ -124,22 +134,22 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
124
134
|
return nodePrototype.constructor.name === instance.name || isInstanceOfElement(nodePrototype, instance);
|
|
125
135
|
};
|
|
126
136
|
//#endregion
|
|
127
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
137
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/clone-pseudos.js
|
|
128
138
|
function formatCSSText(style) {
|
|
129
139
|
const content = style.getPropertyValue("content");
|
|
130
140
|
return `${style.cssText} content: '${content.replace(/'|"/g, "")}';`;
|
|
131
141
|
}
|
|
132
|
-
function formatCSSProperties(style) {
|
|
133
|
-
return
|
|
142
|
+
function formatCSSProperties(style, options) {
|
|
143
|
+
return getStyleProperties(options).map((name) => {
|
|
134
144
|
return `${name}: ${style.getPropertyValue(name)}${style.getPropertyPriority(name) ? " !important" : ""};`;
|
|
135
145
|
}).join(" ");
|
|
136
146
|
}
|
|
137
|
-
function getPseudoElementStyle(className, pseudo, style) {
|
|
147
|
+
function getPseudoElementStyle(className, pseudo, style, options) {
|
|
138
148
|
const selector = `.${className}:${pseudo}`;
|
|
139
|
-
const cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style);
|
|
149
|
+
const cssText = style.cssText ? formatCSSText(style) : formatCSSProperties(style, options);
|
|
140
150
|
return document.createTextNode(`${selector}{${cssText}}`);
|
|
141
151
|
}
|
|
142
|
-
function clonePseudoElement(nativeNode, clonedNode, pseudo) {
|
|
152
|
+
function clonePseudoElement(nativeNode, clonedNode, pseudo, options) {
|
|
143
153
|
const style = window.getComputedStyle(nativeNode, pseudo);
|
|
144
154
|
const content = style.getPropertyValue("content");
|
|
145
155
|
if (content === "" || content === "none") return;
|
|
@@ -150,15 +160,15 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
150
160
|
return;
|
|
151
161
|
}
|
|
152
162
|
const styleElement = document.createElement("style");
|
|
153
|
-
styleElement.appendChild(getPseudoElementStyle(className, pseudo, style));
|
|
163
|
+
styleElement.appendChild(getPseudoElementStyle(className, pseudo, style, options));
|
|
154
164
|
clonedNode.appendChild(styleElement);
|
|
155
165
|
}
|
|
156
|
-
function clonePseudoElements(nativeNode, clonedNode) {
|
|
157
|
-
clonePseudoElement(nativeNode, clonedNode, ":before");
|
|
158
|
-
clonePseudoElement(nativeNode, clonedNode, ":after");
|
|
166
|
+
function clonePseudoElements(nativeNode, clonedNode, options) {
|
|
167
|
+
clonePseudoElement(nativeNode, clonedNode, ":before", options);
|
|
168
|
+
clonePseudoElement(nativeNode, clonedNode, ":after", options);
|
|
159
169
|
}
|
|
160
170
|
//#endregion
|
|
161
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
171
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/mimes.js
|
|
162
172
|
var WOFF = "application/font-woff";
|
|
163
173
|
var JPEG = "image/jpeg";
|
|
164
174
|
var mimes = {
|
|
@@ -182,7 +192,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
182
192
|
return mimes[getExtension(url).toLowerCase()] || "";
|
|
183
193
|
}
|
|
184
194
|
//#endregion
|
|
185
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
195
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/dataurl.js
|
|
186
196
|
function getContentFromDataUrl(dataURL) {
|
|
187
197
|
return dataURL.split(/,/)[1];
|
|
188
198
|
}
|
|
@@ -239,7 +249,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
239
249
|
return dataURL;
|
|
240
250
|
}
|
|
241
251
|
//#endregion
|
|
242
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
252
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/clone-node.js
|
|
243
253
|
async function cloneCanvasElement(canvas) {
|
|
244
254
|
const dataURL = canvas.toDataURL();
|
|
245
255
|
if (dataURL === "data:,") return canvas.cloneNode(false);
|
|
@@ -257,17 +267,17 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
257
267
|
const poster = video.poster;
|
|
258
268
|
return createImage(await resourceToDataURL(poster, getMimeType(poster), options));
|
|
259
269
|
}
|
|
260
|
-
async function cloneIFrameElement(iframe) {
|
|
270
|
+
async function cloneIFrameElement(iframe, options) {
|
|
261
271
|
var _a;
|
|
262
272
|
try {
|
|
263
|
-
if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) return await cloneNode(iframe.contentDocument.body,
|
|
273
|
+
if ((_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentDocument) === null || _a === void 0 ? void 0 : _a.body) return await cloneNode(iframe.contentDocument.body, options, true);
|
|
264
274
|
} catch (_b) {}
|
|
265
275
|
return iframe.cloneNode(false);
|
|
266
276
|
}
|
|
267
277
|
async function cloneSingleNode(node, options) {
|
|
268
278
|
if (isInstanceOfElement(node, HTMLCanvasElement)) return cloneCanvasElement(node);
|
|
269
279
|
if (isInstanceOfElement(node, HTMLVideoElement)) return cloneVideoElement(node, options);
|
|
270
|
-
if (isInstanceOfElement(node, HTMLIFrameElement)) return cloneIFrameElement(node);
|
|
280
|
+
if (isInstanceOfElement(node, HTMLIFrameElement)) return cloneIFrameElement(node, options);
|
|
271
281
|
return node.cloneNode(false);
|
|
272
282
|
}
|
|
273
283
|
var isSlotElement = (node) => node.tagName != null && node.tagName.toUpperCase() === "SLOT";
|
|
@@ -283,14 +293,14 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
283
293
|
}), Promise.resolve());
|
|
284
294
|
return clonedNode;
|
|
285
295
|
}
|
|
286
|
-
function cloneCSSStyle(nativeNode, clonedNode) {
|
|
296
|
+
function cloneCSSStyle(nativeNode, clonedNode, options) {
|
|
287
297
|
const targetStyle = clonedNode.style;
|
|
288
298
|
if (!targetStyle) return;
|
|
289
299
|
const sourceStyle = window.getComputedStyle(nativeNode);
|
|
290
300
|
if (sourceStyle.cssText) {
|
|
291
301
|
targetStyle.cssText = sourceStyle.cssText;
|
|
292
302
|
targetStyle.transformOrigin = sourceStyle.transformOrigin;
|
|
293
|
-
} else
|
|
303
|
+
} else getStyleProperties(options).forEach((name) => {
|
|
294
304
|
let value = sourceStyle.getPropertyValue(name);
|
|
295
305
|
if (name === "font-size" && value.endsWith("px")) value = `${Math.floor(parseFloat(value.substring(0, value.length - 2))) - .1}px`;
|
|
296
306
|
if (isInstanceOfElement(nativeNode, HTMLIFrameElement) && name === "display" && value === "inline") value = "block";
|
|
@@ -309,10 +319,10 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
309
319
|
if (selectedOption) selectedOption.setAttribute("selected", "");
|
|
310
320
|
}
|
|
311
321
|
}
|
|
312
|
-
function decorate(nativeNode, clonedNode) {
|
|
322
|
+
function decorate(nativeNode, clonedNode, options) {
|
|
313
323
|
if (isInstanceOfElement(clonedNode, Element)) {
|
|
314
|
-
cloneCSSStyle(nativeNode, clonedNode);
|
|
315
|
-
clonePseudoElements(nativeNode, clonedNode);
|
|
324
|
+
cloneCSSStyle(nativeNode, clonedNode, options);
|
|
325
|
+
clonePseudoElements(nativeNode, clonedNode, options);
|
|
316
326
|
cloneInputValue(nativeNode, clonedNode);
|
|
317
327
|
cloneSelectValue(nativeNode, clonedNode);
|
|
318
328
|
}
|
|
@@ -349,10 +359,10 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
349
359
|
}
|
|
350
360
|
async function cloneNode(node, options, isRoot) {
|
|
351
361
|
if (!isRoot && options.filter && !options.filter(node)) return null;
|
|
352
|
-
return Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode)).then((clonedNode) => ensureSVGSymbols(clonedNode, options));
|
|
362
|
+
return Promise.resolve(node).then((clonedNode) => cloneSingleNode(clonedNode, options)).then((clonedNode) => cloneChildren(node, clonedNode, options)).then((clonedNode) => decorate(node, clonedNode, options)).then((clonedNode) => ensureSVGSymbols(clonedNode, options));
|
|
353
363
|
}
|
|
354
364
|
//#endregion
|
|
355
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
365
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-resources.js
|
|
356
366
|
var URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g;
|
|
357
367
|
var URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g;
|
|
358
368
|
var FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
|
|
@@ -397,7 +407,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
397
407
|
return parseURLs(filteredCSSText).reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText));
|
|
398
408
|
}
|
|
399
409
|
//#endregion
|
|
400
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
410
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-images.js
|
|
401
411
|
async function embedProp(propName, node, options) {
|
|
402
412
|
var _a;
|
|
403
413
|
const propValue = (_a = node.style) === null || _a === void 0 ? void 0 : _a.getPropertyValue(propName);
|
|
@@ -409,8 +419,8 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
409
419
|
return false;
|
|
410
420
|
}
|
|
411
421
|
async function embedBackground(clonedNode, options) {
|
|
412
|
-
|
|
413
|
-
|
|
422
|
+
await embedProp("background", clonedNode, options) || await embedProp("background-image", clonedNode, options);
|
|
423
|
+
await embedProp("mask", clonedNode, options) || await embedProp("-webkit-mask", clonedNode, options) || await embedProp("mask-image", clonedNode, options) || await embedProp("-webkit-mask-image", clonedNode, options);
|
|
414
424
|
}
|
|
415
425
|
async function embedImageNode(clonedNode, options) {
|
|
416
426
|
const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement);
|
|
@@ -419,7 +429,13 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
419
429
|
const dataURL = await resourceToDataURL(url, getMimeType(url), options);
|
|
420
430
|
await new Promise((resolve, reject) => {
|
|
421
431
|
clonedNode.onload = resolve;
|
|
422
|
-
clonedNode.onerror =
|
|
432
|
+
clonedNode.onerror = options.onImageErrorHandler ? (...attributes) => {
|
|
433
|
+
try {
|
|
434
|
+
resolve(options.onImageErrorHandler(...attributes));
|
|
435
|
+
} catch (error) {
|
|
436
|
+
reject(error);
|
|
437
|
+
}
|
|
438
|
+
} : reject;
|
|
423
439
|
const image = clonedNode;
|
|
424
440
|
if (image.decode) image.decode = resolve;
|
|
425
441
|
if (image.loading === "lazy") image.loading = "eager";
|
|
@@ -441,7 +457,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
441
457
|
}
|
|
442
458
|
}
|
|
443
459
|
//#endregion
|
|
444
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
460
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/apply-style.js
|
|
445
461
|
function applyStyle(node, options) {
|
|
446
462
|
const { style } = node;
|
|
447
463
|
if (options.backgroundColor) style.backgroundColor = options.backgroundColor;
|
|
@@ -454,7 +470,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
454
470
|
return node;
|
|
455
471
|
}
|
|
456
472
|
//#endregion
|
|
457
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
473
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/embed-webfonts.js
|
|
458
474
|
var cssFetchCache = {};
|
|
459
475
|
async function fetchCSS(url) {
|
|
460
476
|
let cache = cssFetchCache[url];
|
|
@@ -530,7 +546,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
530
546
|
} catch (e) {
|
|
531
547
|
const inline = styleSheets.find((a) => a.href == null) || document.styleSheets[0];
|
|
532
548
|
if (sheet.href != null) deferreds.push(fetchCSS(sheet.href).then((metadata) => embedFonts(metadata, options)).then((cssText) => parseCSS(cssText).forEach((rule) => {
|
|
533
|
-
inline.insertRule(rule,
|
|
549
|
+
inline.insertRule(rule, inline.cssRules.length);
|
|
534
550
|
})).catch((err) => {
|
|
535
551
|
console.error("Error loading remote stylesheet", err);
|
|
536
552
|
}));
|
|
@@ -557,9 +573,26 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
557
573
|
if (node.ownerDocument == null) throw new Error("Provided element is not within a Document");
|
|
558
574
|
return getWebFontRules(await getCSSRules(toArray(node.ownerDocument.styleSheets), options));
|
|
559
575
|
}
|
|
576
|
+
function normalizeFontFamily(font) {
|
|
577
|
+
return font.trim().replace(/["']/g, "");
|
|
578
|
+
}
|
|
579
|
+
function getUsedFonts(node) {
|
|
580
|
+
const fonts = /* @__PURE__ */ new Set();
|
|
581
|
+
function traverse(node) {
|
|
582
|
+
(node.style.fontFamily || getComputedStyle(node).fontFamily).split(",").forEach((font) => {
|
|
583
|
+
fonts.add(normalizeFontFamily(font));
|
|
584
|
+
});
|
|
585
|
+
Array.from(node.children).forEach((child) => {
|
|
586
|
+
if (child instanceof HTMLElement) traverse(child);
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
traverse(node);
|
|
590
|
+
return fonts;
|
|
591
|
+
}
|
|
560
592
|
async function getWebFontCSS(node, options) {
|
|
561
593
|
const rules = await parseWebFontRules(node, options);
|
|
562
|
-
|
|
594
|
+
const usedFonts = getUsedFonts(node);
|
|
595
|
+
return (await Promise.all(rules.filter((rule) => usedFonts.has(normalizeFontFamily(rule.style.fontFamily))).map((rule) => {
|
|
563
596
|
const baseUrl = rule.parentStyleSheet ? rule.parentStyleSheet.href : null;
|
|
564
597
|
return embedResources(rule.cssText, baseUrl, options);
|
|
565
598
|
}))).join("\n");
|
|
@@ -575,7 +608,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
575
608
|
}
|
|
576
609
|
}
|
|
577
610
|
//#endregion
|
|
578
|
-
//#region ../../node_modules/.bun/html-to-image@1.11.
|
|
611
|
+
//#region ../../node_modules/.bun/html-to-image@1.11.13/node_modules/html-to-image/es/index.js
|
|
579
612
|
async function toSvg(node, options = {}) {
|
|
580
613
|
const { width, height } = getImageSize(node, options);
|
|
581
614
|
const clonedNode = await cloneNode(node, options, true);
|
|
@@ -8070,9 +8103,23 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
8070
8103
|
exports.hydrateRoot = m.hydrateRoot;
|
|
8071
8104
|
}));
|
|
8072
8105
|
//#endregion
|
|
8073
|
-
//#region src/
|
|
8106
|
+
//#region src/render/common/png.ts
|
|
8074
8107
|
var import_react$4 = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
8075
8108
|
var import_client = require_client();
|
|
8109
|
+
var flowPngAspectRatios = [
|
|
8110
|
+
"auto",
|
|
8111
|
+
"1:1",
|
|
8112
|
+
"4:3",
|
|
8113
|
+
"3:4",
|
|
8114
|
+
"16:9",
|
|
8115
|
+
"9:16"
|
|
8116
|
+
];
|
|
8117
|
+
function getFlowPngAspectRatio(value) {
|
|
8118
|
+
if (value == null || value === "auto") return void 0;
|
|
8119
|
+
if (!flowPngAspectRatios.includes(value)) throw new TypeError("Unsupported PNG canvas aspect ratio.");
|
|
8120
|
+
const [width, height] = value.split(":").map(Number);
|
|
8121
|
+
return [width, height];
|
|
8122
|
+
}
|
|
8076
8123
|
var ContentIcon_module_default = {
|
|
8077
8124
|
img: "ContentIcon_img_4e5d2",
|
|
8078
8125
|
initials: "ContentIcon_initials_4e5d2",
|
|
@@ -23766,6 +23813,578 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
23766
23813
|
return theme === "dark" ? open_flow_dark_default : open_flow_light_default;
|
|
23767
23814
|
}
|
|
23768
23815
|
//#endregion
|
|
23816
|
+
//#region ../../node_modules/.bun/@wopjs+disposable@0.1.24/node_modules/@wopjs/disposable/dist/index.mjs
|
|
23817
|
+
var isFn = (value) => !!(value && value.constructor && value.call && value.apply);
|
|
23818
|
+
/**
|
|
23819
|
+
* Check if a value is a {@link DisposableType}.
|
|
23820
|
+
* @param value The value to check.
|
|
23821
|
+
* @returns True if the value is a {@link DisposableType}, false otherwise.
|
|
23822
|
+
*/
|
|
23823
|
+
var isDisposable = (value) => isFn(value) || isFn(value?.dispose);
|
|
23824
|
+
/**
|
|
23825
|
+
* Dispose a disposable object or a disposer function. Log the error if any.
|
|
23826
|
+
* @param disposable A disposable object or a disposer function. Do nothing otherwise.
|
|
23827
|
+
*/
|
|
23828
|
+
function dispose(disposable) {
|
|
23829
|
+
try {
|
|
23830
|
+
if (disposable) {
|
|
23831
|
+
if (isFn(disposable.dispose)) disposable.dispose();
|
|
23832
|
+
else if (isFn(disposable)) disposable();
|
|
23833
|
+
}
|
|
23834
|
+
} catch (e) {
|
|
23835
|
+
console.error(e);
|
|
23836
|
+
}
|
|
23837
|
+
}
|
|
23838
|
+
var isAbortable = (disposable) => isDisposable(disposable) && isFn(disposable.abortable);
|
|
23839
|
+
/**
|
|
23840
|
+
* Create a {@link DisposableStore} that manages {@link Disposer}s and {@link IDisposable}s.
|
|
23841
|
+
*
|
|
23842
|
+
* A {@link DisposableStore} is also a {@link Disposer}, which means it can be the `dispose` method of an {@link IDisposable}.
|
|
23843
|
+
*
|
|
23844
|
+
* A {@link DisposableStore} is also an {@link IDisposable}, which means it can be managed by another {@link DisposableStore}.
|
|
23845
|
+
*
|
|
23846
|
+
* @example
|
|
23847
|
+
* ```ts
|
|
23848
|
+
* import { type IDisposable, disposableStore } from "@wopjs/disposable";
|
|
23849
|
+
*
|
|
23850
|
+
* class A implements IDisposable {
|
|
23851
|
+
* dispose = disposableStore()
|
|
23852
|
+
* constructor() {
|
|
23853
|
+
* this.dispose.add(...);
|
|
23854
|
+
* }
|
|
23855
|
+
* }
|
|
23856
|
+
*
|
|
23857
|
+
* class B implements IDisposable {
|
|
23858
|
+
* dispose = disposableStore()
|
|
23859
|
+
* a = this.dispose.add(new A())
|
|
23860
|
+
* constructor() {
|
|
23861
|
+
* this.dispose.add(...);
|
|
23862
|
+
* }
|
|
23863
|
+
* }
|
|
23864
|
+
*
|
|
23865
|
+
* const b = new B();
|
|
23866
|
+
* b.dispose(); // dispose both `b` and `b.a`.
|
|
23867
|
+
* ```
|
|
23868
|
+
*
|
|
23869
|
+
* @param disposables Optional array of {@link DisposableType}s added to the store.
|
|
23870
|
+
* @returns A disposable store.
|
|
23871
|
+
*/
|
|
23872
|
+
function disposableStore(disposables) {
|
|
23873
|
+
let isDisposing;
|
|
23874
|
+
function disposableStore() {
|
|
23875
|
+
if (!isDisposing) {
|
|
23876
|
+
isDisposing = 1;
|
|
23877
|
+
isDisposing = disposableStore._disposables_ = disposableStore._disposables_?.forEach(dispose);
|
|
23878
|
+
}
|
|
23879
|
+
}
|
|
23880
|
+
disposableStore.dispose = disposableStore;
|
|
23881
|
+
disposableStore.size = size$3;
|
|
23882
|
+
disposableStore.has = has$2;
|
|
23883
|
+
disposableStore.add = add$1;
|
|
23884
|
+
disposableStore.make = make;
|
|
23885
|
+
disposableStore.remove = remove$1;
|
|
23886
|
+
disposableStore.flush = flush$1;
|
|
23887
|
+
if (disposables) disposableStore.add(disposables);
|
|
23888
|
+
return disposableStore;
|
|
23889
|
+
}
|
|
23890
|
+
function _addOne(disposable) {
|
|
23891
|
+
if (!this._disposables_?.has(disposable)) {
|
|
23892
|
+
(this._disposables_ ??= /* @__PURE__ */ new Set()).add(disposable);
|
|
23893
|
+
if (isAbortable(disposable)) disposable.abortable(remove$1.bind(this, disposable));
|
|
23894
|
+
}
|
|
23895
|
+
}
|
|
23896
|
+
function add$1(disposables) {
|
|
23897
|
+
Array.isArray(disposables) ? disposables.forEach(_addOne, this) : _addOne.call(this, disposables);
|
|
23898
|
+
return disposables;
|
|
23899
|
+
}
|
|
23900
|
+
function flush$1(disposable) {
|
|
23901
|
+
dispose(disposable ? this.remove(disposable) && disposable : this);
|
|
23902
|
+
}
|
|
23903
|
+
function has$2(disposable) {
|
|
23904
|
+
return !!this._disposables_?.has(disposable);
|
|
23905
|
+
}
|
|
23906
|
+
function make(executor) {
|
|
23907
|
+
const disposable = executor();
|
|
23908
|
+
return disposable && this.add(disposable);
|
|
23909
|
+
}
|
|
23910
|
+
function remove$1(disposable) {
|
|
23911
|
+
return !!this._disposables_?.delete(disposable);
|
|
23912
|
+
}
|
|
23913
|
+
function size$3() {
|
|
23914
|
+
return this._disposables_?.size || 0;
|
|
23915
|
+
}
|
|
23916
|
+
//#endregion
|
|
23917
|
+
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/index.mjs
|
|
23918
|
+
var INIT_VALUE, identity$4, strictEqual, arrayShallowEqual, getValue, getValues, getValVersion, invoke, attachSetter, isVal, tick, pendingTasks1, pendingTasks2, pendingTasks, pending, flush, schedule, cancelTask, registry$1, ValAgent, RefValAgent, ValImpl, readonlyVal, val, from$1, combine$1, compute, derive;
|
|
23919
|
+
var init_dist$3 = __esmMin((() => {
|
|
23920
|
+
INIT_VALUE = {};
|
|
23921
|
+
identity$4 = (value) => value;
|
|
23922
|
+
strictEqual = Object.is;
|
|
23923
|
+
arrayShallowEqual = (arrA, arrB) => {
|
|
23924
|
+
if (strictEqual(arrA, arrB)) return true;
|
|
23925
|
+
if (!Array.isArray(arrA) || !Array.isArray(arrB)) return false;
|
|
23926
|
+
const len = arrA.length;
|
|
23927
|
+
if (arrB.length !== len) return false;
|
|
23928
|
+
for (let i = 0; i < len; i++) if (!strictEqual(arrA[i], arrB[i])) return false;
|
|
23929
|
+
return true;
|
|
23930
|
+
};
|
|
23931
|
+
getValue = (val2) => val2.value;
|
|
23932
|
+
getValues = (valInputs) => valInputs.map(getValue);
|
|
23933
|
+
getValVersion = (val$) => val$.$version;
|
|
23934
|
+
invoke = (fn, value) => {
|
|
23935
|
+
try {
|
|
23936
|
+
fn(value);
|
|
23937
|
+
} catch (e) {
|
|
23938
|
+
console.error(e);
|
|
23939
|
+
}
|
|
23940
|
+
};
|
|
23941
|
+
attachSetter = (val$, set) => (val$.set = set, val$);
|
|
23942
|
+
isVal = (val$) => !!val$?.$valCompute;
|
|
23943
|
+
tick = /* @__PURE__ */ Promise.resolve();
|
|
23944
|
+
pendingTasks1 = /* @__PURE__ */ new Set();
|
|
23945
|
+
pendingTasks2 = /* @__PURE__ */ new Set();
|
|
23946
|
+
pendingTasks = pendingTasks1;
|
|
23947
|
+
flush = () => {
|
|
23948
|
+
const currentPendingTasks = pendingTasks;
|
|
23949
|
+
pendingTasks = pendingTasks === pendingTasks1 ? pendingTasks2 : pendingTasks1;
|
|
23950
|
+
pending = false;
|
|
23951
|
+
for (const subs of currentPendingTasks) subs.t();
|
|
23952
|
+
currentPendingTasks.clear();
|
|
23953
|
+
};
|
|
23954
|
+
schedule = (task) => {
|
|
23955
|
+
pendingTasks.add(task);
|
|
23956
|
+
pending = pending || tick.then(flush);
|
|
23957
|
+
};
|
|
23958
|
+
cancelTask = (task) => pendingTasks.delete(task);
|
|
23959
|
+
registry$1 = /* @__PURE__ */ new FinalizationRegistry(invoke);
|
|
23960
|
+
ValAgent = class {
|
|
23961
|
+
constructor(getValue2, config, onChange) {
|
|
23962
|
+
this.#getValue = getValue2;
|
|
23963
|
+
this.q = (config?.equal ?? strictEqual) || void 0;
|
|
23964
|
+
this.e = config?.eager;
|
|
23965
|
+
this.m = config?.name;
|
|
23966
|
+
this.#onDisposeValue = config?.onDisposeValue;
|
|
23967
|
+
if (onChange) {
|
|
23968
|
+
const ref = new WeakRef(this);
|
|
23969
|
+
const disposeEffect = () => {
|
|
23970
|
+
if (disposeListen) {
|
|
23971
|
+
const dispose = disposeListen;
|
|
23972
|
+
disposeListen = void 0;
|
|
23973
|
+
dispose();
|
|
23974
|
+
}
|
|
23975
|
+
};
|
|
23976
|
+
let disposeListen = onChange(() => {
|
|
23977
|
+
const agent = ref.deref();
|
|
23978
|
+
if (agent) agent.n();
|
|
23979
|
+
else disposeEffect();
|
|
23980
|
+
});
|
|
23981
|
+
if (disposeListen) registry$1.register(this, this.#disposeEffect = disposeEffect);
|
|
23982
|
+
}
|
|
23983
|
+
}
|
|
23984
|
+
g = this;
|
|
23985
|
+
b = /* @__PURE__ */ new Map();
|
|
23986
|
+
s = 4;
|
|
23987
|
+
v;
|
|
23988
|
+
c = INIT_VALUE;
|
|
23989
|
+
q;
|
|
23990
|
+
e;
|
|
23991
|
+
m;
|
|
23992
|
+
u = () => {
|
|
23993
|
+
if (this.s & 4) {
|
|
23994
|
+
this.s &= -5;
|
|
23995
|
+
const newValue = this.#getValue();
|
|
23996
|
+
if (this.c === INIT_VALUE) this.w(newValue);
|
|
23997
|
+
else if (!this.q?.(newValue, this.c)) {
|
|
23998
|
+
this.w(newValue);
|
|
23999
|
+
if (this.s & 1) this.s |= 2;
|
|
24000
|
+
}
|
|
24001
|
+
}
|
|
24002
|
+
return this.c;
|
|
24003
|
+
};
|
|
24004
|
+
n = () => {
|
|
24005
|
+
if (this.#disposed) console.error(this.c, /* @__PURE__ */ new Error(`${this.m || ""} disposed`));
|
|
24006
|
+
this.s |= 4;
|
|
24007
|
+
if (this.b.size) {
|
|
24008
|
+
this.s |= 1;
|
|
24009
|
+
if (this[3]) this.#invoke(3);
|
|
24010
|
+
if (this[2]) {
|
|
24011
|
+
this.u();
|
|
24012
|
+
if (this.s & 2) this.#invoke(2);
|
|
24013
|
+
}
|
|
24014
|
+
if (this[1]) schedule(this);
|
|
24015
|
+
else this.s &= -4;
|
|
24016
|
+
}
|
|
24017
|
+
};
|
|
24018
|
+
a(subscriber, mode) {
|
|
24019
|
+
const currentMode = this.b.get(subscriber);
|
|
24020
|
+
if (currentMode) this[currentMode]--;
|
|
24021
|
+
this.b.set(subscriber, mode);
|
|
24022
|
+
this[mode]++;
|
|
24023
|
+
return () => this.r(subscriber);
|
|
24024
|
+
}
|
|
24025
|
+
r(subscriber) {
|
|
24026
|
+
if (subscriber) {
|
|
24027
|
+
const mode = this.b.get(subscriber);
|
|
24028
|
+
if (mode) {
|
|
24029
|
+
this.b.delete(subscriber);
|
|
24030
|
+
this[mode]--;
|
|
24031
|
+
}
|
|
24032
|
+
} else {
|
|
24033
|
+
this.b.clear();
|
|
24034
|
+
this[1] = this[2] = this[3] = 0;
|
|
24035
|
+
cancelTask(this);
|
|
24036
|
+
}
|
|
24037
|
+
}
|
|
24038
|
+
t() {
|
|
24039
|
+
if (this[1]) {
|
|
24040
|
+
this.u();
|
|
24041
|
+
if (this.s & 2) this.#invoke(1);
|
|
24042
|
+
}
|
|
24043
|
+
this.s &= -4;
|
|
24044
|
+
}
|
|
24045
|
+
d() {
|
|
24046
|
+
const oldValue = this.c;
|
|
24047
|
+
this.r();
|
|
24048
|
+
registry$1.unregister(this);
|
|
24049
|
+
this.#disposeEffect?.();
|
|
24050
|
+
this.#disposed = true;
|
|
24051
|
+
if (this.#onDisposeValue && oldValue !== INIT_VALUE) this.#onDisposeValue(oldValue);
|
|
24052
|
+
}
|
|
24053
|
+
w(value) {
|
|
24054
|
+
this.w = this.q?.(value, value) ? this.y : this.x;
|
|
24055
|
+
this.w(value);
|
|
24056
|
+
}
|
|
24057
|
+
x(value) {
|
|
24058
|
+
const oldValue = this.c;
|
|
24059
|
+
this.c = value;
|
|
24060
|
+
this.v = Symbol();
|
|
24061
|
+
if (this.#onDisposeValue && oldValue !== INIT_VALUE && oldValue !== value) this.#onDisposeValue(oldValue);
|
|
24062
|
+
}
|
|
24063
|
+
y(value) {
|
|
24064
|
+
const oldValue = this.c;
|
|
24065
|
+
this.c = this.v = value;
|
|
24066
|
+
if (this.#onDisposeValue && oldValue !== INIT_VALUE && oldValue !== value) this.#onDisposeValue(oldValue);
|
|
24067
|
+
}
|
|
24068
|
+
[1] = 0;
|
|
24069
|
+
[2] = 0;
|
|
24070
|
+
[3] = 0;
|
|
24071
|
+
#disposeEffect;
|
|
24072
|
+
#onDisposeValue;
|
|
24073
|
+
#getValue;
|
|
24074
|
+
#invoke(mode) {
|
|
24075
|
+
for (const [sub, subMode] of this.b) if (subMode === mode) invoke(sub, this.c);
|
|
24076
|
+
}
|
|
24077
|
+
#disposed;
|
|
24078
|
+
};
|
|
24079
|
+
RefValAgent = class {
|
|
24080
|
+
#subs = /* @__PURE__ */ new WeakSet();
|
|
24081
|
+
constructor(agent) {
|
|
24082
|
+
this.g = agent.g;
|
|
24083
|
+
this.e = agent.e;
|
|
24084
|
+
this.u = agent.u;
|
|
24085
|
+
this.n = agent.n;
|
|
24086
|
+
this.b = agent.b;
|
|
24087
|
+
}
|
|
24088
|
+
get v() {
|
|
24089
|
+
return this.g.v;
|
|
24090
|
+
}
|
|
24091
|
+
g;
|
|
24092
|
+
b;
|
|
24093
|
+
e;
|
|
24094
|
+
u;
|
|
24095
|
+
n;
|
|
24096
|
+
a(subscriber, mode) {
|
|
24097
|
+
this.#subs.add(subscriber);
|
|
24098
|
+
return this.g.a(subscriber, mode);
|
|
24099
|
+
}
|
|
24100
|
+
r(subscriber) {
|
|
24101
|
+
if (subscriber) {
|
|
24102
|
+
if (this.#subs.has(subscriber)) {
|
|
24103
|
+
this.#subs.delete(subscriber);
|
|
24104
|
+
this.g.r(subscriber);
|
|
24105
|
+
}
|
|
24106
|
+
} else for (const sub of this.g.b.keys()) this.r(sub);
|
|
24107
|
+
}
|
|
24108
|
+
d() {
|
|
24109
|
+
this.r();
|
|
24110
|
+
}
|
|
24111
|
+
};
|
|
24112
|
+
ValImpl = class {
|
|
24113
|
+
/**
|
|
24114
|
+
* Manage subscribers for a val.
|
|
24115
|
+
*/
|
|
24116
|
+
#agent;
|
|
24117
|
+
constructor(agent) {
|
|
24118
|
+
this.#agent = agent;
|
|
24119
|
+
this.get = agent.u;
|
|
24120
|
+
agent.u();
|
|
24121
|
+
}
|
|
24122
|
+
/** Debug display name. */
|
|
24123
|
+
get name() {
|
|
24124
|
+
return this.#agent.m;
|
|
24125
|
+
}
|
|
24126
|
+
get $version() {
|
|
24127
|
+
this.get();
|
|
24128
|
+
return this.#agent.v;
|
|
24129
|
+
}
|
|
24130
|
+
get value() {
|
|
24131
|
+
return this.get();
|
|
24132
|
+
}
|
|
24133
|
+
set value(value) {
|
|
24134
|
+
this.set?.(value);
|
|
24135
|
+
}
|
|
24136
|
+
set;
|
|
24137
|
+
get;
|
|
24138
|
+
ref(writable) {
|
|
24139
|
+
const val$ = new ValImpl(new RefValAgent(this.#agent));
|
|
24140
|
+
return writable && this.set ? attachSetter(val$, this.set) : val$;
|
|
24141
|
+
}
|
|
24142
|
+
reaction(subscriber, eager = this.#agent.e) {
|
|
24143
|
+
return this.#agent.a(subscriber, eager ? 2 : 1);
|
|
24144
|
+
}
|
|
24145
|
+
subscribe(subscriber, eager = this.#agent.e) {
|
|
24146
|
+
const disposer = this.reaction(subscriber, eager);
|
|
24147
|
+
invoke(subscriber, this.get());
|
|
24148
|
+
return disposer;
|
|
24149
|
+
}
|
|
24150
|
+
$valCompute(subscriber) {
|
|
24151
|
+
return this.#agent.a(subscriber, 3);
|
|
24152
|
+
}
|
|
24153
|
+
unsubscribe(subscriber) {
|
|
24154
|
+
this.#agent.r(subscriber);
|
|
24155
|
+
}
|
|
24156
|
+
dispose() {
|
|
24157
|
+
this.#agent.d();
|
|
24158
|
+
}
|
|
24159
|
+
/**
|
|
24160
|
+
* @returns the string representation of `this.value`.
|
|
24161
|
+
*
|
|
24162
|
+
* @example
|
|
24163
|
+
* ```js
|
|
24164
|
+
* const v$ = val(val(val(1)));
|
|
24165
|
+
* console.log(`${v$}`); // "1"
|
|
24166
|
+
* ```
|
|
24167
|
+
*/
|
|
24168
|
+
toString() {
|
|
24169
|
+
return String(this.get());
|
|
24170
|
+
}
|
|
24171
|
+
/**
|
|
24172
|
+
* @returns the JSON representation of `this.value`.
|
|
24173
|
+
*
|
|
24174
|
+
* @example
|
|
24175
|
+
* ```js
|
|
24176
|
+
* const v$ = val(val(val({ a: 1 })));
|
|
24177
|
+
* JSON.stringify(v$); // '{"a":1}'
|
|
24178
|
+
* ```
|
|
24179
|
+
*/
|
|
24180
|
+
toJSON(key) {
|
|
24181
|
+
const value = this.get();
|
|
24182
|
+
return value && value.toJSON ? value.toJSON(key) : value;
|
|
24183
|
+
}
|
|
24184
|
+
};
|
|
24185
|
+
readonlyVal = (value, config) => {
|
|
24186
|
+
let currentValue = value;
|
|
24187
|
+
const get = () => currentValue;
|
|
24188
|
+
const subs = new ValAgent(get, config);
|
|
24189
|
+
const set = (value2) => {
|
|
24190
|
+
if (!subs.q?.(value2, currentValue)) {
|
|
24191
|
+
currentValue = value2;
|
|
24192
|
+
subs.n();
|
|
24193
|
+
}
|
|
24194
|
+
};
|
|
24195
|
+
return [new ValImpl(subs), set];
|
|
24196
|
+
};
|
|
24197
|
+
val = (value, config) => attachSetter(...readonlyVal(value, config));
|
|
24198
|
+
from$1 = (getValue2, onChange, config) => new ValImpl(new ValAgent(getValue2, config, onChange));
|
|
24199
|
+
combine$1 = (valInputs, transform = identity$4, config) => {
|
|
24200
|
+
let cachedValue;
|
|
24201
|
+
let cachedSrcVersions;
|
|
24202
|
+
return from$1(() => {
|
|
24203
|
+
const versions = valInputs.map(getValVersion);
|
|
24204
|
+
if (!cachedSrcVersions || !arrayShallowEqual(versions, cachedSrcVersions)) {
|
|
24205
|
+
cachedSrcVersions = versions;
|
|
24206
|
+
cachedValue = transform(getValues(valInputs));
|
|
24207
|
+
}
|
|
24208
|
+
return cachedValue;
|
|
24209
|
+
}, (notify) => {
|
|
24210
|
+
const disposers = valInputs.map((val2) => val2.$valCompute(notify));
|
|
24211
|
+
return () => disposers.forEach(invoke);
|
|
24212
|
+
}, config);
|
|
24213
|
+
};
|
|
24214
|
+
compute = (effect, config) => {
|
|
24215
|
+
let scopeLevel = 0;
|
|
24216
|
+
let currentDeps = /* @__PURE__ */ new Map();
|
|
24217
|
+
let oldDeps = /* @__PURE__ */ new Map();
|
|
24218
|
+
const get = (val$) => {
|
|
24219
|
+
if (!isVal(val$)) {
|
|
24220
|
+
if (!isVal(val$?.$)) return val$;
|
|
24221
|
+
val$ = val$.$;
|
|
24222
|
+
}
|
|
24223
|
+
if (currentDeps.has(val$)) {
|
|
24224
|
+
if (!strictEqual(val$.$version, currentDeps.get(val$))) currentDeps.set(val$, INIT_VALUE);
|
|
24225
|
+
} else {
|
|
24226
|
+
if (!oldDeps.delete(val$)) val$.$valCompute(agent.n);
|
|
24227
|
+
currentDeps.set(val$, val$.$version);
|
|
24228
|
+
}
|
|
24229
|
+
return val$.value;
|
|
24230
|
+
};
|
|
24231
|
+
let currentValue;
|
|
24232
|
+
const agent = new ValAgent(() => {
|
|
24233
|
+
if (!scopeLevel) {
|
|
24234
|
+
if (currentDeps.size) x: {
|
|
24235
|
+
for (const [dep, version] of currentDeps) if (!strictEqual(dep.$version, version)) break x;
|
|
24236
|
+
return currentValue;
|
|
24237
|
+
}
|
|
24238
|
+
const tmp = currentDeps;
|
|
24239
|
+
currentDeps = oldDeps;
|
|
24240
|
+
oldDeps = tmp;
|
|
24241
|
+
scopeLevel++;
|
|
24242
|
+
}
|
|
24243
|
+
currentValue = effect(get);
|
|
24244
|
+
if (!--scopeLevel && oldDeps.size) {
|
|
24245
|
+
for (const dep of oldDeps.keys()) dep.unsubscribe(agent.n);
|
|
24246
|
+
oldDeps.clear();
|
|
24247
|
+
}
|
|
24248
|
+
return currentValue;
|
|
24249
|
+
}, config, () => () => {
|
|
24250
|
+
if (currentDeps.size) {
|
|
24251
|
+
for (const dep of currentDeps.keys()) dep.unsubscribe(agent.n);
|
|
24252
|
+
currentDeps.clear();
|
|
24253
|
+
}
|
|
24254
|
+
});
|
|
24255
|
+
return new ValImpl(agent);
|
|
24256
|
+
};
|
|
24257
|
+
derive = (val2, transform = identity$4, config) => {
|
|
24258
|
+
let cachedValue;
|
|
24259
|
+
let cachedSrcVersion = INIT_VALUE;
|
|
24260
|
+
return from$1(() => {
|
|
24261
|
+
const version = val2.$version;
|
|
24262
|
+
if (!strictEqual(version, cachedSrcVersion)) {
|
|
24263
|
+
cachedSrcVersion = version;
|
|
24264
|
+
cachedValue = transform(val2.value);
|
|
24265
|
+
}
|
|
24266
|
+
return cachedValue;
|
|
24267
|
+
}, (notify) => val2.$valCompute(notify), config);
|
|
24268
|
+
};
|
|
24269
|
+
}));
|
|
24270
|
+
//#endregion
|
|
24271
|
+
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/collections.mjs
|
|
24272
|
+
init_dist$3();
|
|
24273
|
+
var ReactiveMapImpl = class extends Map {
|
|
24274
|
+
constructor(entries, config) {
|
|
24275
|
+
super();
|
|
24276
|
+
if (config) this.#onDeleted = config.onDeleted;
|
|
24277
|
+
const [$, set$] = readonlyVal(this, { equal: false });
|
|
24278
|
+
this.$ = $;
|
|
24279
|
+
this.#notify = () => set$(this);
|
|
24280
|
+
if (entries) for (const [key, value] of entries) this.set(key, value);
|
|
24281
|
+
}
|
|
24282
|
+
$;
|
|
24283
|
+
#notify;
|
|
24284
|
+
#onDeleted;
|
|
24285
|
+
#delete(key) {
|
|
24286
|
+
if (this.#onDeleted) {
|
|
24287
|
+
if (super.has(key)) {
|
|
24288
|
+
const value = super.get(key);
|
|
24289
|
+
super.delete(key);
|
|
24290
|
+
this.#onDeleted(value);
|
|
24291
|
+
return true;
|
|
24292
|
+
}
|
|
24293
|
+
return false;
|
|
24294
|
+
}
|
|
24295
|
+
return super.delete(key);
|
|
24296
|
+
}
|
|
24297
|
+
#clear() {
|
|
24298
|
+
if (this.#onDeleted) {
|
|
24299
|
+
const deleted = new Set(this.values());
|
|
24300
|
+
super.clear();
|
|
24301
|
+
for (const value of deleted) this.#onDeleted(value);
|
|
24302
|
+
} else super.clear();
|
|
24303
|
+
}
|
|
24304
|
+
delete(key) {
|
|
24305
|
+
const deleted = this.#delete(key);
|
|
24306
|
+
if (deleted) this.#notify();
|
|
24307
|
+
return deleted;
|
|
24308
|
+
}
|
|
24309
|
+
batchDelete(keys) {
|
|
24310
|
+
let deleted = false;
|
|
24311
|
+
for (const key of keys) deleted = this.#delete(key) || deleted;
|
|
24312
|
+
if (deleted) this.#notify();
|
|
24313
|
+
return deleted;
|
|
24314
|
+
}
|
|
24315
|
+
clear() {
|
|
24316
|
+
if (this.size > 0) {
|
|
24317
|
+
this.#clear();
|
|
24318
|
+
this.#notify();
|
|
24319
|
+
}
|
|
24320
|
+
}
|
|
24321
|
+
#set(key, value) {
|
|
24322
|
+
if (this.has(key)) {
|
|
24323
|
+
const oldValue = this.get(key);
|
|
24324
|
+
if (strictEqual(oldValue, value)) return false;
|
|
24325
|
+
super.set(key, value);
|
|
24326
|
+
if (this.#onDeleted) this.#onDeleted(oldValue);
|
|
24327
|
+
} else super.set(key, value);
|
|
24328
|
+
return true;
|
|
24329
|
+
}
|
|
24330
|
+
set(key, value) {
|
|
24331
|
+
if (this.#set(key, value)) this.#notify();
|
|
24332
|
+
return this;
|
|
24333
|
+
}
|
|
24334
|
+
batchSet(entries) {
|
|
24335
|
+
let isDirty = false;
|
|
24336
|
+
for (const [key, value] of entries) isDirty = this.#set(key, value) || isDirty;
|
|
24337
|
+
if (isDirty) this.#notify();
|
|
24338
|
+
return this;
|
|
24339
|
+
}
|
|
24340
|
+
rename(oldKey, newKey) {
|
|
24341
|
+
if (!strictEqual(oldKey, newKey)) {
|
|
24342
|
+
const value = this.get(oldKey);
|
|
24343
|
+
if (super.delete(oldKey)) {
|
|
24344
|
+
this.set(newKey, value);
|
|
24345
|
+
return true;
|
|
24346
|
+
}
|
|
24347
|
+
}
|
|
24348
|
+
return false;
|
|
24349
|
+
}
|
|
24350
|
+
replace(entries) {
|
|
24351
|
+
const oldMap = new Map(this);
|
|
24352
|
+
const deletedValues = new Set(this.values());
|
|
24353
|
+
let hasNewValue = false;
|
|
24354
|
+
super.clear();
|
|
24355
|
+
for (const [key, value] of entries) {
|
|
24356
|
+
super.set(key, value);
|
|
24357
|
+
deletedValues.delete(value);
|
|
24358
|
+
hasNewValue = hasNewValue || !oldMap.has(key) || !Object.is(oldMap.get(key), value);
|
|
24359
|
+
oldMap.delete(key);
|
|
24360
|
+
}
|
|
24361
|
+
if (hasNewValue || oldMap.size > 0 || deletedValues.size > 0) {
|
|
24362
|
+
if (this.#onDeleted) for (const value of deletedValues) this.#onDeleted(value);
|
|
24363
|
+
this.#notify();
|
|
24364
|
+
}
|
|
24365
|
+
return deletedValues.values();
|
|
24366
|
+
}
|
|
24367
|
+
toJSON() {
|
|
24368
|
+
const result = {};
|
|
24369
|
+
for (const [key, value] of this) if (key != null) {
|
|
24370
|
+
const k = String(key);
|
|
24371
|
+
const v = value;
|
|
24372
|
+
result[k] = v && v.toJSON ? v.toJSON(k) : v;
|
|
24373
|
+
}
|
|
24374
|
+
return result;
|
|
24375
|
+
}
|
|
24376
|
+
dispose() {
|
|
24377
|
+
this.$.dispose();
|
|
24378
|
+
if (this.size > 0) this.#clear();
|
|
24379
|
+
}
|
|
24380
|
+
};
|
|
24381
|
+
var reactiveMap = (entries, config) => new ReactiveMapImpl(entries, config);
|
|
24382
|
+
//#endregion
|
|
24383
|
+
//#region src/canvas/common/direction.ts
|
|
24384
|
+
function canvasDirection(value) {
|
|
24385
|
+
return value === "vertical" ? "vertical" : "horizontal";
|
|
24386
|
+
}
|
|
24387
|
+
//#endregion
|
|
23769
24388
|
//#region ../../node_modules/.bun/@dagrejs+dagre@3.1.1/node_modules/@dagrejs/dagre/dist/dagre.esm.js
|
|
23770
24389
|
var Te = Object.defineProperty;
|
|
23771
24390
|
var In = (e, n, t) => n in e ? Te(e, n, {
|
|
@@ -26002,801 +26621,199 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
26002
26621
|
}
|
|
26003
26622
|
/*! For license information please see dagre.esm.js.LEGAL.txt */
|
|
26004
26623
|
//#endregion
|
|
26005
|
-
//#region
|
|
26006
|
-
var
|
|
26007
|
-
|
|
26008
|
-
|
|
26009
|
-
|
|
26010
|
-
|
|
26011
|
-
|
|
26012
|
-
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
26017
|
-
function dispose(disposable) {
|
|
26018
|
-
try {
|
|
26019
|
-
if (disposable) {
|
|
26020
|
-
if (isFn(disposable.dispose)) disposable.dispose();
|
|
26021
|
-
else if (isFn(disposable)) disposable();
|
|
26022
|
-
}
|
|
26023
|
-
} catch (e) {
|
|
26024
|
-
console.error(e);
|
|
26025
|
-
}
|
|
26026
|
-
}
|
|
26027
|
-
var isAbortable = (disposable) => isDisposable(disposable) && isFn(disposable.abortable);
|
|
26028
|
-
/**
|
|
26029
|
-
* Create a {@link DisposableStore} that manages {@link Disposer}s and {@link IDisposable}s.
|
|
26030
|
-
*
|
|
26031
|
-
* A {@link DisposableStore} is also a {@link Disposer}, which means it can be the `dispose` method of an {@link IDisposable}.
|
|
26032
|
-
*
|
|
26033
|
-
* A {@link DisposableStore} is also an {@link IDisposable}, which means it can be managed by another {@link DisposableStore}.
|
|
26034
|
-
*
|
|
26035
|
-
* @example
|
|
26036
|
-
* ```ts
|
|
26037
|
-
* import { type IDisposable, disposableStore } from "@wopjs/disposable";
|
|
26038
|
-
*
|
|
26039
|
-
* class A implements IDisposable {
|
|
26040
|
-
* dispose = disposableStore()
|
|
26041
|
-
* constructor() {
|
|
26042
|
-
* this.dispose.add(...);
|
|
26043
|
-
* }
|
|
26044
|
-
* }
|
|
26045
|
-
*
|
|
26046
|
-
* class B implements IDisposable {
|
|
26047
|
-
* dispose = disposableStore()
|
|
26048
|
-
* a = this.dispose.add(new A())
|
|
26049
|
-
* constructor() {
|
|
26050
|
-
* this.dispose.add(...);
|
|
26051
|
-
* }
|
|
26052
|
-
* }
|
|
26053
|
-
*
|
|
26054
|
-
* const b = new B();
|
|
26055
|
-
* b.dispose(); // dispose both `b` and `b.a`.
|
|
26056
|
-
* ```
|
|
26057
|
-
*
|
|
26058
|
-
* @param disposables Optional array of {@link DisposableType}s added to the store.
|
|
26059
|
-
* @returns A disposable store.
|
|
26060
|
-
*/
|
|
26061
|
-
function disposableStore(disposables) {
|
|
26062
|
-
let isDisposing;
|
|
26063
|
-
function disposableStore() {
|
|
26064
|
-
if (!isDisposing) {
|
|
26065
|
-
isDisposing = 1;
|
|
26066
|
-
isDisposing = disposableStore._disposables_ = disposableStore._disposables_?.forEach(dispose);
|
|
26067
|
-
}
|
|
26068
|
-
}
|
|
26069
|
-
disposableStore.dispose = disposableStore;
|
|
26070
|
-
disposableStore.size = size$3;
|
|
26071
|
-
disposableStore.has = has$2;
|
|
26072
|
-
disposableStore.add = add$1;
|
|
26073
|
-
disposableStore.make = make;
|
|
26074
|
-
disposableStore.remove = remove$1;
|
|
26075
|
-
disposableStore.flush = flush$1;
|
|
26076
|
-
if (disposables) disposableStore.add(disposables);
|
|
26077
|
-
return disposableStore;
|
|
26078
|
-
}
|
|
26079
|
-
function _addOne(disposable) {
|
|
26080
|
-
if (!this._disposables_?.has(disposable)) {
|
|
26081
|
-
(this._disposables_ ??= /* @__PURE__ */ new Set()).add(disposable);
|
|
26082
|
-
if (isAbortable(disposable)) disposable.abortable(remove$1.bind(this, disposable));
|
|
26083
|
-
}
|
|
26084
|
-
}
|
|
26085
|
-
function add$1(disposables) {
|
|
26086
|
-
Array.isArray(disposables) ? disposables.forEach(_addOne, this) : _addOne.call(this, disposables);
|
|
26087
|
-
return disposables;
|
|
26088
|
-
}
|
|
26089
|
-
function flush$1(disposable) {
|
|
26090
|
-
dispose(disposable ? this.remove(disposable) && disposable : this);
|
|
26091
|
-
}
|
|
26092
|
-
function has$2(disposable) {
|
|
26093
|
-
return !!this._disposables_?.has(disposable);
|
|
26094
|
-
}
|
|
26095
|
-
function make(executor) {
|
|
26096
|
-
const disposable = executor();
|
|
26097
|
-
return disposable && this.add(disposable);
|
|
26098
|
-
}
|
|
26099
|
-
function remove$1(disposable) {
|
|
26100
|
-
return !!this._disposables_?.delete(disposable);
|
|
26101
|
-
}
|
|
26102
|
-
function size$3() {
|
|
26103
|
-
return this._disposables_?.size || 0;
|
|
26104
|
-
}
|
|
26105
|
-
Array.isArray;
|
|
26106
|
-
var isNumber$5 = (value) => {
|
|
26107
|
-
try {
|
|
26108
|
-
return Number(value) === value;
|
|
26109
|
-
} catch {
|
|
26110
|
-
return false;
|
|
26111
|
-
}
|
|
26112
|
-
};
|
|
26113
|
-
var isDate = (value) => {
|
|
26114
|
-
return Object.prototype.toString.call(value) === "[object Date]";
|
|
26115
|
-
};
|
|
26116
|
-
//#endregion
|
|
26117
|
-
//#region ../../node_modules/.bun/radash@12.1.1/node_modules/radash/dist/esm/array.mjs
|
|
26118
|
-
var cluster = (list2, size = 2) => {
|
|
26119
|
-
const clusterCount = Math.ceil(list2.length / size);
|
|
26120
|
-
return new Array(clusterCount).fill(null).map((_c, i) => {
|
|
26121
|
-
return list2.slice(i * size, i * size + size);
|
|
26122
|
-
});
|
|
26123
|
-
};
|
|
26124
|
-
//#endregion
|
|
26125
|
-
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/index.mjs
|
|
26126
|
-
var INIT_VALUE, identity$4, strictEqual, arrayShallowEqual, getValue, getValues, getValVersion, invoke, attachSetter, isVal, tick, pendingTasks1, pendingTasks2, pendingTasks, pending, flush, schedule, cancelTask, registry$1, ValAgent, RefValAgent, ValImpl, readonlyVal, val, from$1, combine$1, compute, derive;
|
|
26127
|
-
var init_dist$3 = __esmMin((() => {
|
|
26128
|
-
INIT_VALUE = {};
|
|
26129
|
-
identity$4 = (value) => value;
|
|
26130
|
-
strictEqual = Object.is;
|
|
26131
|
-
arrayShallowEqual = (arrA, arrB) => {
|
|
26132
|
-
if (strictEqual(arrA, arrB)) return true;
|
|
26133
|
-
if (!Array.isArray(arrA) || !Array.isArray(arrB)) return false;
|
|
26134
|
-
const len = arrA.length;
|
|
26135
|
-
if (arrB.length !== len) return false;
|
|
26136
|
-
for (let i = 0; i < len; i++) if (!strictEqual(arrA[i], arrB[i])) return false;
|
|
26137
|
-
return true;
|
|
26138
|
-
};
|
|
26139
|
-
getValue = (val2) => val2.value;
|
|
26140
|
-
getValues = (valInputs) => valInputs.map(getValue);
|
|
26141
|
-
getValVersion = (val$) => val$.$version;
|
|
26142
|
-
invoke = (fn, value) => {
|
|
26143
|
-
try {
|
|
26144
|
-
fn(value);
|
|
26145
|
-
} catch (e) {
|
|
26146
|
-
console.error(e);
|
|
26147
|
-
}
|
|
26148
|
-
};
|
|
26149
|
-
attachSetter = (val$, set) => (val$.set = set, val$);
|
|
26150
|
-
isVal = (val$) => !!val$?.$valCompute;
|
|
26151
|
-
tick = /* @__PURE__ */ Promise.resolve();
|
|
26152
|
-
pendingTasks1 = /* @__PURE__ */ new Set();
|
|
26153
|
-
pendingTasks2 = /* @__PURE__ */ new Set();
|
|
26154
|
-
pendingTasks = pendingTasks1;
|
|
26155
|
-
flush = () => {
|
|
26156
|
-
const currentPendingTasks = pendingTasks;
|
|
26157
|
-
pendingTasks = pendingTasks === pendingTasks1 ? pendingTasks2 : pendingTasks1;
|
|
26158
|
-
pending = false;
|
|
26159
|
-
for (const subs of currentPendingTasks) subs.t();
|
|
26160
|
-
currentPendingTasks.clear();
|
|
26161
|
-
};
|
|
26162
|
-
schedule = (task) => {
|
|
26163
|
-
pendingTasks.add(task);
|
|
26164
|
-
pending = pending || tick.then(flush);
|
|
26165
|
-
};
|
|
26166
|
-
cancelTask = (task) => pendingTasks.delete(task);
|
|
26167
|
-
registry$1 = /* @__PURE__ */ new FinalizationRegistry(invoke);
|
|
26168
|
-
ValAgent = class {
|
|
26169
|
-
constructor(getValue2, config, onChange) {
|
|
26170
|
-
this.#getValue = getValue2;
|
|
26171
|
-
this.q = (config?.equal ?? strictEqual) || void 0;
|
|
26172
|
-
this.e = config?.eager;
|
|
26173
|
-
this.m = config?.name;
|
|
26174
|
-
this.#onDisposeValue = config?.onDisposeValue;
|
|
26175
|
-
if (onChange) {
|
|
26176
|
-
const ref = new WeakRef(this);
|
|
26177
|
-
const disposeEffect = () => {
|
|
26178
|
-
if (disposeListen) {
|
|
26179
|
-
const dispose = disposeListen;
|
|
26180
|
-
disposeListen = void 0;
|
|
26181
|
-
dispose();
|
|
26182
|
-
}
|
|
26183
|
-
};
|
|
26184
|
-
let disposeListen = onChange(() => {
|
|
26185
|
-
const agent = ref.deref();
|
|
26186
|
-
if (agent) agent.n();
|
|
26187
|
-
else disposeEffect();
|
|
26188
|
-
});
|
|
26189
|
-
if (disposeListen) registry$1.register(this, this.#disposeEffect = disposeEffect);
|
|
26190
|
-
}
|
|
26191
|
-
}
|
|
26192
|
-
g = this;
|
|
26193
|
-
b = /* @__PURE__ */ new Map();
|
|
26194
|
-
s = 4;
|
|
26195
|
-
v;
|
|
26196
|
-
c = INIT_VALUE;
|
|
26197
|
-
q;
|
|
26198
|
-
e;
|
|
26199
|
-
m;
|
|
26200
|
-
u = () => {
|
|
26201
|
-
if (this.s & 4) {
|
|
26202
|
-
this.s &= -5;
|
|
26203
|
-
const newValue = this.#getValue();
|
|
26204
|
-
if (this.c === INIT_VALUE) this.w(newValue);
|
|
26205
|
-
else if (!this.q?.(newValue, this.c)) {
|
|
26206
|
-
this.w(newValue);
|
|
26207
|
-
if (this.s & 1) this.s |= 2;
|
|
26208
|
-
}
|
|
26209
|
-
}
|
|
26210
|
-
return this.c;
|
|
26624
|
+
//#region src/canvas/browser/base/routeLayout.ts
|
|
26625
|
+
var clearance = 16;
|
|
26626
|
+
var portOffset = 24;
|
|
26627
|
+
/** Orthogonal channels around the measured cards, in primary/cross coordinates. */
|
|
26628
|
+
function routeLayout(nodes, edges) {
|
|
26629
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
26630
|
+
const connections = edges.map((edge) => {
|
|
26631
|
+
const source = byId.get(edge.source);
|
|
26632
|
+
const target = byId.get(edge.target);
|
|
26633
|
+
const output = {
|
|
26634
|
+
x: source.x + (edge.sourceOffset?.x ?? source.width),
|
|
26635
|
+
y: source.y + (edge.sourceOffset?.y ?? source.height / 2)
|
|
26211
26636
|
};
|
|
26212
|
-
|
|
26213
|
-
|
|
26214
|
-
|
|
26215
|
-
if (this.b.size) {
|
|
26216
|
-
this.s |= 1;
|
|
26217
|
-
if (this[3]) this.#invoke(3);
|
|
26218
|
-
if (this[2]) {
|
|
26219
|
-
this.u();
|
|
26220
|
-
if (this.s & 2) this.#invoke(2);
|
|
26221
|
-
}
|
|
26222
|
-
if (this[1]) schedule(this);
|
|
26223
|
-
else this.s &= -4;
|
|
26224
|
-
}
|
|
26637
|
+
const input = {
|
|
26638
|
+
x: target.x + (edge.targetOffset?.x ?? 0),
|
|
26639
|
+
y: target.y + (edge.targetOffset?.y ?? target.height / 2)
|
|
26225
26640
|
};
|
|
26226
|
-
|
|
26227
|
-
|
|
26228
|
-
|
|
26229
|
-
|
|
26230
|
-
|
|
26231
|
-
|
|
26232
|
-
|
|
26233
|
-
|
|
26234
|
-
|
|
26235
|
-
|
|
26236
|
-
|
|
26237
|
-
|
|
26238
|
-
|
|
26239
|
-
}
|
|
26240
|
-
} else {
|
|
26241
|
-
this.b.clear();
|
|
26242
|
-
this[1] = this[2] = this[3] = 0;
|
|
26243
|
-
cancelTask(this);
|
|
26244
|
-
}
|
|
26245
|
-
}
|
|
26246
|
-
t() {
|
|
26247
|
-
if (this[1]) {
|
|
26248
|
-
this.u();
|
|
26249
|
-
if (this.s & 2) this.#invoke(1);
|
|
26250
|
-
}
|
|
26251
|
-
this.s &= -4;
|
|
26252
|
-
}
|
|
26253
|
-
d() {
|
|
26254
|
-
const oldValue = this.c;
|
|
26255
|
-
this.r();
|
|
26256
|
-
registry$1.unregister(this);
|
|
26257
|
-
this.#disposeEffect?.();
|
|
26258
|
-
this.#disposed = true;
|
|
26259
|
-
if (this.#onDisposeValue && oldValue !== INIT_VALUE) this.#onDisposeValue(oldValue);
|
|
26260
|
-
}
|
|
26261
|
-
w(value) {
|
|
26262
|
-
this.w = this.q?.(value, value) ? this.y : this.x;
|
|
26263
|
-
this.w(value);
|
|
26264
|
-
}
|
|
26265
|
-
x(value) {
|
|
26266
|
-
const oldValue = this.c;
|
|
26267
|
-
this.c = value;
|
|
26268
|
-
this.v = Symbol();
|
|
26269
|
-
if (this.#onDisposeValue && oldValue !== INIT_VALUE && oldValue !== value) this.#onDisposeValue(oldValue);
|
|
26270
|
-
}
|
|
26271
|
-
y(value) {
|
|
26272
|
-
const oldValue = this.c;
|
|
26273
|
-
this.c = this.v = value;
|
|
26274
|
-
if (this.#onDisposeValue && oldValue !== INIT_VALUE && oldValue !== value) this.#onDisposeValue(oldValue);
|
|
26275
|
-
}
|
|
26276
|
-
[1] = 0;
|
|
26277
|
-
[2] = 0;
|
|
26278
|
-
[3] = 0;
|
|
26279
|
-
#disposeEffect;
|
|
26280
|
-
#onDisposeValue;
|
|
26281
|
-
#getValue;
|
|
26282
|
-
#invoke(mode) {
|
|
26283
|
-
for (const [sub, subMode] of this.b) if (subMode === mode) invoke(sub, this.c);
|
|
26284
|
-
}
|
|
26285
|
-
#disposed;
|
|
26286
|
-
};
|
|
26287
|
-
RefValAgent = class {
|
|
26288
|
-
#subs = /* @__PURE__ */ new WeakSet();
|
|
26289
|
-
constructor(agent) {
|
|
26290
|
-
this.g = agent.g;
|
|
26291
|
-
this.e = agent.e;
|
|
26292
|
-
this.u = agent.u;
|
|
26293
|
-
this.n = agent.n;
|
|
26294
|
-
this.b = agent.b;
|
|
26295
|
-
}
|
|
26296
|
-
get v() {
|
|
26297
|
-
return this.g.v;
|
|
26298
|
-
}
|
|
26299
|
-
g;
|
|
26300
|
-
b;
|
|
26301
|
-
e;
|
|
26302
|
-
u;
|
|
26303
|
-
n;
|
|
26304
|
-
a(subscriber, mode) {
|
|
26305
|
-
this.#subs.add(subscriber);
|
|
26306
|
-
return this.g.a(subscriber, mode);
|
|
26307
|
-
}
|
|
26308
|
-
r(subscriber) {
|
|
26309
|
-
if (subscriber) {
|
|
26310
|
-
if (this.#subs.has(subscriber)) {
|
|
26311
|
-
this.#subs.delete(subscriber);
|
|
26312
|
-
this.g.r(subscriber);
|
|
26313
|
-
}
|
|
26314
|
-
} else for (const sub of this.g.b.keys()) this.r(sub);
|
|
26315
|
-
}
|
|
26316
|
-
d() {
|
|
26317
|
-
this.r();
|
|
26318
|
-
}
|
|
26319
|
-
};
|
|
26320
|
-
ValImpl = class {
|
|
26321
|
-
/**
|
|
26322
|
-
* Manage subscribers for a val.
|
|
26323
|
-
*/
|
|
26324
|
-
#agent;
|
|
26325
|
-
constructor(agent) {
|
|
26326
|
-
this.#agent = agent;
|
|
26327
|
-
this.get = agent.u;
|
|
26328
|
-
agent.u();
|
|
26329
|
-
}
|
|
26330
|
-
/** Debug display name. */
|
|
26331
|
-
get name() {
|
|
26332
|
-
return this.#agent.m;
|
|
26333
|
-
}
|
|
26334
|
-
get $version() {
|
|
26335
|
-
this.get();
|
|
26336
|
-
return this.#agent.v;
|
|
26337
|
-
}
|
|
26338
|
-
get value() {
|
|
26339
|
-
return this.get();
|
|
26340
|
-
}
|
|
26341
|
-
set value(value) {
|
|
26342
|
-
this.set?.(value);
|
|
26343
|
-
}
|
|
26344
|
-
set;
|
|
26345
|
-
get;
|
|
26346
|
-
ref(writable) {
|
|
26347
|
-
const val$ = new ValImpl(new RefValAgent(this.#agent));
|
|
26348
|
-
return writable && this.set ? attachSetter(val$, this.set) : val$;
|
|
26349
|
-
}
|
|
26350
|
-
reaction(subscriber, eager = this.#agent.e) {
|
|
26351
|
-
return this.#agent.a(subscriber, eager ? 2 : 1);
|
|
26352
|
-
}
|
|
26353
|
-
subscribe(subscriber, eager = this.#agent.e) {
|
|
26354
|
-
const disposer = this.reaction(subscriber, eager);
|
|
26355
|
-
invoke(subscriber, this.get());
|
|
26356
|
-
return disposer;
|
|
26357
|
-
}
|
|
26358
|
-
$valCompute(subscriber) {
|
|
26359
|
-
return this.#agent.a(subscriber, 3);
|
|
26360
|
-
}
|
|
26361
|
-
unsubscribe(subscriber) {
|
|
26362
|
-
this.#agent.r(subscriber);
|
|
26363
|
-
}
|
|
26364
|
-
dispose() {
|
|
26365
|
-
this.#agent.d();
|
|
26366
|
-
}
|
|
26367
|
-
/**
|
|
26368
|
-
* @returns the string representation of `this.value`.
|
|
26369
|
-
*
|
|
26370
|
-
* @example
|
|
26371
|
-
* ```js
|
|
26372
|
-
* const v$ = val(val(val(1)));
|
|
26373
|
-
* console.log(`${v$}`); // "1"
|
|
26374
|
-
* ```
|
|
26375
|
-
*/
|
|
26376
|
-
toString() {
|
|
26377
|
-
return String(this.get());
|
|
26378
|
-
}
|
|
26379
|
-
/**
|
|
26380
|
-
* @returns the JSON representation of `this.value`.
|
|
26381
|
-
*
|
|
26382
|
-
* @example
|
|
26383
|
-
* ```js
|
|
26384
|
-
* const v$ = val(val(val({ a: 1 })));
|
|
26385
|
-
* JSON.stringify(v$); // '{"a":1}'
|
|
26386
|
-
* ```
|
|
26387
|
-
*/
|
|
26388
|
-
toJSON(key) {
|
|
26389
|
-
const value = this.get();
|
|
26390
|
-
return value && value.toJSON ? value.toJSON(key) : value;
|
|
26391
|
-
}
|
|
26392
|
-
};
|
|
26393
|
-
readonlyVal = (value, config) => {
|
|
26394
|
-
let currentValue = value;
|
|
26395
|
-
const get = () => currentValue;
|
|
26396
|
-
const subs = new ValAgent(get, config);
|
|
26397
|
-
const set = (value2) => {
|
|
26398
|
-
if (!subs.q?.(value2, currentValue)) {
|
|
26399
|
-
currentValue = value2;
|
|
26400
|
-
subs.n();
|
|
26401
|
-
}
|
|
26402
|
-
};
|
|
26403
|
-
return [new ValImpl(subs), set];
|
|
26404
|
-
};
|
|
26405
|
-
val = (value, config) => attachSetter(...readonlyVal(value, config));
|
|
26406
|
-
from$1 = (getValue2, onChange, config) => new ValImpl(new ValAgent(getValue2, config, onChange));
|
|
26407
|
-
combine$1 = (valInputs, transform = identity$4, config) => {
|
|
26408
|
-
let cachedValue;
|
|
26409
|
-
let cachedSrcVersions;
|
|
26410
|
-
return from$1(() => {
|
|
26411
|
-
const versions = valInputs.map(getValVersion);
|
|
26412
|
-
if (!cachedSrcVersions || !arrayShallowEqual(versions, cachedSrcVersions)) {
|
|
26413
|
-
cachedSrcVersions = versions;
|
|
26414
|
-
cachedValue = transform(getValues(valInputs));
|
|
26415
|
-
}
|
|
26416
|
-
return cachedValue;
|
|
26417
|
-
}, (notify) => {
|
|
26418
|
-
const disposers = valInputs.map((val2) => val2.$valCompute(notify));
|
|
26419
|
-
return () => disposers.forEach(invoke);
|
|
26420
|
-
}, config);
|
|
26421
|
-
};
|
|
26422
|
-
compute = (effect, config) => {
|
|
26423
|
-
let scopeLevel = 0;
|
|
26424
|
-
let currentDeps = /* @__PURE__ */ new Map();
|
|
26425
|
-
let oldDeps = /* @__PURE__ */ new Map();
|
|
26426
|
-
const get = (val$) => {
|
|
26427
|
-
if (!isVal(val$)) {
|
|
26428
|
-
if (!isVal(val$?.$)) return val$;
|
|
26429
|
-
val$ = val$.$;
|
|
26430
|
-
}
|
|
26431
|
-
if (currentDeps.has(val$)) {
|
|
26432
|
-
if (!strictEqual(val$.$version, currentDeps.get(val$))) currentDeps.set(val$, INIT_VALUE);
|
|
26433
|
-
} else {
|
|
26434
|
-
if (!oldDeps.delete(val$)) val$.$valCompute(agent.n);
|
|
26435
|
-
currentDeps.set(val$, val$.$version);
|
|
26641
|
+
const offset = output.x < input.x ? Math.min(portOffset, (input.x - output.x) / 2) : portOffset;
|
|
26642
|
+
return {
|
|
26643
|
+
id: edge.id,
|
|
26644
|
+
source: output,
|
|
26645
|
+
target: input,
|
|
26646
|
+
returnSide: input.x <= output.x ? Math.sign(input.y - output.y) : 0,
|
|
26647
|
+
start: {
|
|
26648
|
+
x: output.x + offset,
|
|
26649
|
+
y: output.y
|
|
26650
|
+
},
|
|
26651
|
+
end: {
|
|
26652
|
+
x: input.x - offset,
|
|
26653
|
+
y: input.y
|
|
26436
26654
|
}
|
|
26437
|
-
return val$.value;
|
|
26438
26655
|
};
|
|
26439
|
-
|
|
26440
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26443
|
-
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
|
|
26448
|
-
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
|
|
26454
|
-
|
|
26455
|
-
}
|
|
26456
|
-
|
|
26457
|
-
|
|
26458
|
-
|
|
26459
|
-
|
|
26460
|
-
|
|
26461
|
-
|
|
26656
|
+
});
|
|
26657
|
+
const obstacles = nodes.map((node) => ({
|
|
26658
|
+
left: node.x - clearance,
|
|
26659
|
+
right: node.x + node.width + clearance,
|
|
26660
|
+
top: node.y - clearance,
|
|
26661
|
+
bottom: node.y + node.height + clearance
|
|
26662
|
+
}));
|
|
26663
|
+
const routes = /* @__PURE__ */ new Map();
|
|
26664
|
+
const pending = connections.filter((edge) => {
|
|
26665
|
+
if (edge.start.x > edge.end.x) return true;
|
|
26666
|
+
const middle = (edge.start.x + edge.end.x) / 2;
|
|
26667
|
+
const points = [
|
|
26668
|
+
edge.start,
|
|
26669
|
+
{
|
|
26670
|
+
x: middle,
|
|
26671
|
+
y: edge.start.y
|
|
26672
|
+
},
|
|
26673
|
+
{
|
|
26674
|
+
x: middle,
|
|
26675
|
+
y: edge.end.y
|
|
26676
|
+
},
|
|
26677
|
+
edge.end
|
|
26678
|
+
];
|
|
26679
|
+
for (let index = 1; index < points.length; index++) {
|
|
26680
|
+
const a = points[index - 1];
|
|
26681
|
+
const b = points[index];
|
|
26682
|
+
if (obstacles.some((rect) => a.x === b.x ? a.x > rect.left && a.x < rect.right && Math.max(a.y, b.y) > rect.top && Math.min(a.y, b.y) < rect.bottom : a.y > rect.top && a.y < rect.bottom && Math.max(a.x, b.x) > rect.left && Math.min(a.x, b.x) < rect.right)) return true;
|
|
26683
|
+
}
|
|
26684
|
+
routes.set(edge.id, [
|
|
26685
|
+
edge.source,
|
|
26686
|
+
points[1],
|
|
26687
|
+
points[2],
|
|
26688
|
+
edge.target
|
|
26689
|
+
]);
|
|
26690
|
+
return false;
|
|
26691
|
+
});
|
|
26692
|
+
if (!pending.length) return routes;
|
|
26693
|
+
const xs = [.../* @__PURE__ */ new Set([...obstacles.flatMap((rect) => [rect.left, rect.right]), ...pending.flatMap((edge) => [edge.start.x, edge.end.x])])].toSorted((a, b) => a - b);
|
|
26694
|
+
const ys = [.../* @__PURE__ */ new Set([...obstacles.flatMap((rect) => [rect.top, rect.bottom]), ...pending.flatMap((edge) => [edge.start.y, edge.end.y])])].toSorted((a, b) => a - b);
|
|
26695
|
+
const xIndex = new Map(xs.map((value, index) => [value, index]));
|
|
26696
|
+
const yIndex = new Map(ys.map((value, index) => [value, index]));
|
|
26697
|
+
const columns = xs.length;
|
|
26698
|
+
const size = columns * ys.length;
|
|
26699
|
+
const horizontal = new Uint8Array(size);
|
|
26700
|
+
const vertical = new Uint8Array(size);
|
|
26701
|
+
for (const rect of obstacles) {
|
|
26702
|
+
const left = xIndex.get(rect.left);
|
|
26703
|
+
const right = xIndex.get(rect.right);
|
|
26704
|
+
const top = yIndex.get(rect.top);
|
|
26705
|
+
const bottom = yIndex.get(rect.bottom);
|
|
26706
|
+
for (let y = top + 1; y < bottom; y++) for (let x = left; x < right; x++) horizontal[y * columns + x] = 1;
|
|
26707
|
+
for (let x = left + 1; x < right; x++) for (let y = top; y < bottom; y++) vertical[y * columns + x] = 1;
|
|
26708
|
+
}
|
|
26709
|
+
const distances = new Float64Array(size * 2);
|
|
26710
|
+
const previous = new Int32Array(size * 2);
|
|
26711
|
+
const visited = new Uint32Array(size * 2);
|
|
26712
|
+
for (const [routeIndex, edge] of pending.entries()) {
|
|
26713
|
+
const generation = routeIndex + 1;
|
|
26714
|
+
const start = yIndex.get(edge.start.y) * columns + xIndex.get(edge.start.x);
|
|
26715
|
+
const end = yIndex.get(edge.end.y) * columns + xIndex.get(edge.end.x);
|
|
26716
|
+
const queue = [];
|
|
26717
|
+
const heuristic = (vertex) => Math.abs(xs[vertex % columns] - edge.end.x) + Math.abs(ys[Math.floor(vertex / columns)] - edge.end.y);
|
|
26718
|
+
distances[start * 2] = 0;
|
|
26719
|
+
previous[start * 2] = -1;
|
|
26720
|
+
visited[start * 2] = generation;
|
|
26721
|
+
enqueue(queue, {
|
|
26722
|
+
state: start * 2,
|
|
26723
|
+
score: heuristic(start)
|
|
26462
26724
|
});
|
|
26463
|
-
|
|
26464
|
-
|
|
26465
|
-
|
|
26466
|
-
|
|
26467
|
-
|
|
26468
|
-
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
cachedSrcVersion = version;
|
|
26472
|
-
cachedValue = transform(val2.value);
|
|
26473
|
-
}
|
|
26474
|
-
return cachedValue;
|
|
26475
|
-
}, (notify) => val2.$valCompute(notify), config);
|
|
26476
|
-
};
|
|
26477
|
-
}));
|
|
26478
|
-
//#endregion
|
|
26479
|
-
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/collections.mjs
|
|
26480
|
-
init_dist$3();
|
|
26481
|
-
var ReactiveMapImpl = class extends Map {
|
|
26482
|
-
constructor(entries, config) {
|
|
26483
|
-
super();
|
|
26484
|
-
if (config) this.#onDeleted = config.onDeleted;
|
|
26485
|
-
const [$, set$] = readonlyVal(this, { equal: false });
|
|
26486
|
-
this.$ = $;
|
|
26487
|
-
this.#notify = () => set$(this);
|
|
26488
|
-
if (entries) for (const [key, value] of entries) this.set(key, value);
|
|
26489
|
-
}
|
|
26490
|
-
$;
|
|
26491
|
-
#notify;
|
|
26492
|
-
#onDeleted;
|
|
26493
|
-
#delete(key) {
|
|
26494
|
-
if (this.#onDeleted) {
|
|
26495
|
-
if (super.has(key)) {
|
|
26496
|
-
const value = super.get(key);
|
|
26497
|
-
super.delete(key);
|
|
26498
|
-
this.#onDeleted(value);
|
|
26499
|
-
return true;
|
|
26725
|
+
let finish = -1;
|
|
26726
|
+
while (queue.length) {
|
|
26727
|
+
const entry = dequeue(queue);
|
|
26728
|
+
const vertex = Math.floor(entry.state / 2);
|
|
26729
|
+
if (entry.score > distances[entry.state] + heuristic(vertex) + 1e-6) continue;
|
|
26730
|
+
if (vertex === end) {
|
|
26731
|
+
finish = entry.state;
|
|
26732
|
+
break;
|
|
26500
26733
|
}
|
|
26501
|
-
|
|
26502
|
-
|
|
26503
|
-
|
|
26504
|
-
|
|
26505
|
-
|
|
26506
|
-
|
|
26507
|
-
|
|
26508
|
-
|
|
26509
|
-
for (const
|
|
26510
|
-
|
|
26511
|
-
|
|
26512
|
-
|
|
26513
|
-
|
|
26514
|
-
|
|
26515
|
-
|
|
26516
|
-
|
|
26517
|
-
|
|
26518
|
-
|
|
26519
|
-
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
if (this.size > 0) {
|
|
26525
|
-
this.#clear();
|
|
26526
|
-
this.#notify();
|
|
26527
|
-
}
|
|
26528
|
-
}
|
|
26529
|
-
#set(key, value) {
|
|
26530
|
-
if (this.has(key)) {
|
|
26531
|
-
const oldValue = this.get(key);
|
|
26532
|
-
if (strictEqual(oldValue, value)) return false;
|
|
26533
|
-
super.set(key, value);
|
|
26534
|
-
if (this.#onDeleted) this.#onDeleted(oldValue);
|
|
26535
|
-
} else super.set(key, value);
|
|
26536
|
-
return true;
|
|
26537
|
-
}
|
|
26538
|
-
set(key, value) {
|
|
26539
|
-
if (this.#set(key, value)) this.#notify();
|
|
26540
|
-
return this;
|
|
26541
|
-
}
|
|
26542
|
-
batchSet(entries) {
|
|
26543
|
-
let isDirty = false;
|
|
26544
|
-
for (const [key, value] of entries) isDirty = this.#set(key, value) || isDirty;
|
|
26545
|
-
if (isDirty) this.#notify();
|
|
26546
|
-
return this;
|
|
26547
|
-
}
|
|
26548
|
-
rename(oldKey, newKey) {
|
|
26549
|
-
if (!strictEqual(oldKey, newKey)) {
|
|
26550
|
-
const value = this.get(oldKey);
|
|
26551
|
-
if (super.delete(oldKey)) {
|
|
26552
|
-
this.set(newKey, value);
|
|
26553
|
-
return true;
|
|
26734
|
+
const x = vertex % columns;
|
|
26735
|
+
const y = Math.floor(vertex / columns);
|
|
26736
|
+
const moves = [
|
|
26737
|
+
x > 0 && !horizontal[vertex - 1] ? vertex - 1 : -1,
|
|
26738
|
+
x + 1 < columns && !horizontal[vertex] ? vertex + 1 : -1,
|
|
26739
|
+
y > 0 && !vertical[vertex - columns] ? vertex - columns : -1,
|
|
26740
|
+
y + 1 < ys.length && !vertical[vertex] ? vertex + columns : -1
|
|
26741
|
+
];
|
|
26742
|
+
for (const [index, next] of moves.entries()) {
|
|
26743
|
+
if (next < 0 || vertex === start && index === 0 || next === end && index === 0) continue;
|
|
26744
|
+
if (edge.returnSide * (ys[Math.floor(next / columns)] - edge.start.y) < -1e-6) continue;
|
|
26745
|
+
const axis = index < 2 ? 0 : 1;
|
|
26746
|
+
const state = next * 2 + axis;
|
|
26747
|
+
const length = Math.abs(xs[next % columns] - xs[x]) + Math.abs(ys[Math.floor(next / columns)] - ys[y]);
|
|
26748
|
+
const distance = distances[entry.state] + length + (entry.state % 2 === axis ? 0 : 8);
|
|
26749
|
+
if (visited[state] === generation && distance >= distances[state]) continue;
|
|
26750
|
+
visited[state] = generation;
|
|
26751
|
+
distances[state] = distance;
|
|
26752
|
+
previous[state] = entry.state;
|
|
26753
|
+
enqueue(queue, {
|
|
26754
|
+
state,
|
|
26755
|
+
score: distance + heuristic(next)
|
|
26756
|
+
});
|
|
26554
26757
|
}
|
|
26555
26758
|
}
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
|
|
26560
|
-
|
|
26561
|
-
|
|
26562
|
-
|
|
26563
|
-
|
|
26564
|
-
super.set(key, value);
|
|
26565
|
-
deletedValues.delete(value);
|
|
26566
|
-
hasNewValue = hasNewValue || !oldMap.has(key) || !Object.is(oldMap.get(key), value);
|
|
26567
|
-
oldMap.delete(key);
|
|
26568
|
-
}
|
|
26569
|
-
if (hasNewValue || oldMap.size > 0 || deletedValues.size > 0) {
|
|
26570
|
-
if (this.#onDeleted) for (const value of deletedValues) this.#onDeleted(value);
|
|
26571
|
-
this.#notify();
|
|
26572
|
-
}
|
|
26573
|
-
return deletedValues.values();
|
|
26574
|
-
}
|
|
26575
|
-
toJSON() {
|
|
26576
|
-
const result = {};
|
|
26577
|
-
for (const [key, value] of this) if (key != null) {
|
|
26578
|
-
const k = String(key);
|
|
26579
|
-
const v = value;
|
|
26580
|
-
result[k] = v && v.toJSON ? v.toJSON(k) : v;
|
|
26759
|
+
if (finish < 0) throw new Error("Could not route the compact workflow connection.");
|
|
26760
|
+
const points = [];
|
|
26761
|
+
for (let state = finish; state >= 0; state = previous[state]) {
|
|
26762
|
+
const vertex = Math.floor(state / 2);
|
|
26763
|
+
points.push({
|
|
26764
|
+
x: xs[vertex % columns],
|
|
26765
|
+
y: ys[Math.floor(vertex / columns)]
|
|
26766
|
+
});
|
|
26581
26767
|
}
|
|
26582
|
-
|
|
26583
|
-
|
|
26584
|
-
|
|
26585
|
-
|
|
26586
|
-
|
|
26587
|
-
}
|
|
26588
|
-
};
|
|
26589
|
-
var reactiveMap = (entries, config) => new ReactiveMapImpl(entries, config);
|
|
26590
|
-
//#endregion
|
|
26591
|
-
//#region src/canvas/common/direction.ts
|
|
26592
|
-
function canvasDirection(value) {
|
|
26593
|
-
return value === "vertical" ? "vertical" : "horizontal";
|
|
26594
|
-
}
|
|
26595
|
-
//#endregion
|
|
26596
|
-
//#region ../../node_modules/.bun/@wopjs+cast@0.1.16/node_modules/@wopjs/cast/dist/index.mjs
|
|
26597
|
-
var isBoolean$1, isString$1, isArray$1, isObject$2, isPlainObject$3, toPlainObject;
|
|
26598
|
-
var init_dist$2 = __esmMin((() => {
|
|
26599
|
-
isBoolean$1 = (x) => x === true || x === false;
|
|
26600
|
-
isString$1 = (x) => typeof x === "string";
|
|
26601
|
-
isArray$1 = Array.isArray;
|
|
26602
|
-
isObject$2 = (x) => x !== null && typeof x === "object";
|
|
26603
|
-
isPlainObject$3 = (x) => isObject$2(x) && !isArray$1(x);
|
|
26604
|
-
toPlainObject = (x) => isPlainObject$3(x) ? x : void 0;
|
|
26605
|
-
}));
|
|
26606
|
-
//#endregion
|
|
26607
|
-
//#region src/canvas/browser/base/compare.ts
|
|
26608
|
-
init_dist$2();
|
|
26609
|
-
var isSameXYPosition = (p1, p2) => !p1 || !p2 ? p1 === p2 : p1.x === p2.x && p1.y === p2.y;
|
|
26610
|
-
var isSize = (s) => isPlainObject$3(s) && isNumber$5(s.width) && isNumber$5(s.height);
|
|
26611
|
-
var isSameSize = (s1, s2) => !s1 || !s2 ? s1 === s2 : s1.width === s2.width && s1.height === s2.height;
|
|
26612
|
-
var isSameViewport = (v1, v2) => !v1 || !v2 ? v1 === v2 : v1.x === v2.x && v1.y === v2.y && v1.zoom === v2.zoom;
|
|
26613
|
-
function isFunction$1(value) {
|
|
26614
|
-
return typeof value === "function";
|
|
26615
|
-
}
|
|
26616
|
-
function asArray(value) {
|
|
26617
|
-
return value == null ? [] : Array.isArray(value) ? value : [value];
|
|
26618
|
-
}
|
|
26619
|
-
function coalesce(array) {
|
|
26620
|
-
return array.filter((e) => e != null);
|
|
26621
|
-
}
|
|
26622
|
-
function toTrue(value) {
|
|
26623
|
-
return value === true ? true : void 0;
|
|
26624
|
-
}
|
|
26625
|
-
/**
|
|
26626
|
-
* Skips the update when the object has already been removed from the reactive value.
|
|
26627
|
-
*
|
|
26628
|
-
* ```js
|
|
26629
|
-
* const setName = updatePartial(object$, "name")
|
|
26630
|
-
* ```
|
|
26631
|
-
*/
|
|
26632
|
-
function updatePartial(val, field, equal = Object.is) {
|
|
26633
|
-
return (fieldValue) => {
|
|
26634
|
-
if (val.value && !equal(val.value[field], fieldValue)) val.set({
|
|
26635
|
-
...val.value,
|
|
26636
|
-
[field]: fieldValue
|
|
26768
|
+
points.reverse();
|
|
26769
|
+
const turns = points.filter((point, index) => {
|
|
26770
|
+
const before = points[index - 1];
|
|
26771
|
+
const after = points[index + 1];
|
|
26772
|
+
return !before || !after || !(before.x === point.x && point.x === after.x || before.y === point.y && point.y === after.y);
|
|
26637
26773
|
});
|
|
26638
|
-
|
|
26639
|
-
|
|
26640
|
-
|
|
26641
|
-
|
|
26642
|
-
|
|
26643
|
-
var isMac$1 = /*#__PURE__*/ /Mac/.test(nav$1.platform);
|
|
26644
|
-
function stopEvent$1(event, cancelBubble) {
|
|
26645
|
-
event.preventDefault();
|
|
26646
|
-
if (cancelBubble) event.stopPropagation();
|
|
26647
|
-
}
|
|
26648
|
-
/**
|
|
26649
|
-
* @example
|
|
26650
|
-
* ```js
|
|
26651
|
-
* onClick(ev => isInside(ev.target, '.class1, .class2'))
|
|
26652
|
-
* ```
|
|
26653
|
-
*/
|
|
26654
|
-
function isInside(target, selector) {
|
|
26655
|
-
return target?.closest?.(selector) != null;
|
|
26656
|
-
}
|
|
26657
|
-
//#endregion
|
|
26658
|
-
//#region src/canvas/browser/stores/node/constants.ts
|
|
26659
|
-
var NODE_TYPE = /* @__PURE__ */ function(NODE_TYPE) {
|
|
26660
|
-
NODE_TYPE["TaskNode"] = "task_node";
|
|
26661
|
-
NODE_TYPE["ValueNode"] = "value_node";
|
|
26662
|
-
NODE_TYPE["ConditionNode"] = "condition_node";
|
|
26663
|
-
NODE_TYPE["CommentNode"] = "comment_node";
|
|
26664
|
-
NODE_TYPE["TriggerNode"] = "trigger_node";
|
|
26665
|
-
return NODE_TYPE;
|
|
26666
|
-
}({});
|
|
26667
|
-
//#endregion
|
|
26668
|
-
//#region src/canvas/browser/base/canvas.ts
|
|
26669
|
-
var CANVAS_CLASSNAME = "open-flow-canvas";
|
|
26670
|
-
function minimumCanvasCardWidth(direction, branchCount) {
|
|
26671
|
-
return direction === "vertical" && branchCount > 0 ? Math.max(320, branchCount * 96 + (branchCount - 1) * 6 + 16 + 2) : 320;
|
|
26672
|
-
}
|
|
26673
|
-
function canvasCardWidth(direction, branchCount, preferredWidth) {
|
|
26674
|
-
const minimum = minimumCanvasCardWidth(direction, branchCount);
|
|
26675
|
-
return direction === "vertical" && preferredWidth != null && Number.isFinite(preferredWidth) ? Math.max(minimum, preferredWidth) : minimum;
|
|
26676
|
-
}
|
|
26677
|
-
/** Marks an area that React Flow can drag. */
|
|
26678
|
-
var NODE_HANDLE_CLASSNAME = "open-flow-canvas-node-handle";
|
|
26679
|
-
var DEFAULT_POSITION = /* @__PURE__ */ Object.freeze({
|
|
26680
|
-
x: 0,
|
|
26681
|
-
y: 0
|
|
26682
|
-
});
|
|
26683
|
-
//#endregion
|
|
26684
|
-
//#region src/canvas/browser/base/rfHelpers.ts
|
|
26685
|
-
init_dist$2();
|
|
26686
|
-
/** Converts a manifest node identifier to a React Flow identifier. */
|
|
26687
|
-
function toRFNodeId(nodeId, nodeType) {
|
|
26688
|
-
return (nodeType === NODE_TYPE.CommentNode ? "c:" : "m:") + nodeId;
|
|
26689
|
-
}
|
|
26690
|
-
function getRFNodeType(rfNodeId) {
|
|
26691
|
-
if (rfNodeId[1] === ":") switch (rfNodeId[0]) {
|
|
26692
|
-
case "m": return "manifest_node";
|
|
26693
|
-
case "c": return "comment_node";
|
|
26694
|
-
}
|
|
26695
|
-
}
|
|
26696
|
-
function toManifestNodeId(rfNodeId) {
|
|
26697
|
-
if (rfNodeId[1] === ":") switch (rfNodeId[0]) {
|
|
26698
|
-
case "m":
|
|
26699
|
-
case "c": return rfNodeId.slice(2);
|
|
26774
|
+
routes.set(edge.id, [
|
|
26775
|
+
edge.source,
|
|
26776
|
+
...turns,
|
|
26777
|
+
edge.target
|
|
26778
|
+
]);
|
|
26700
26779
|
}
|
|
26701
|
-
return
|
|
26702
|
-
}
|
|
26703
|
-
function toRFHandleName(handleName) {
|
|
26704
|
-
return `h:${handleName}`;
|
|
26780
|
+
return routes;
|
|
26705
26781
|
}
|
|
26706
|
-
function
|
|
26707
|
-
|
|
26708
|
-
|
|
26782
|
+
function enqueue(queue, entry) {
|
|
26783
|
+
let index = queue.length;
|
|
26784
|
+
queue.push(entry);
|
|
26785
|
+
while (index > 0) {
|
|
26786
|
+
const parent = Math.floor((index - 1) / 2);
|
|
26787
|
+
if (queue[parent].score <= entry.score) break;
|
|
26788
|
+
queue[index] = queue[parent];
|
|
26789
|
+
index = parent;
|
|
26709
26790
|
}
|
|
26710
|
-
|
|
26791
|
+
queue[index] = entry;
|
|
26711
26792
|
}
|
|
26712
|
-
function
|
|
26713
|
-
|
|
26714
|
-
|
|
26715
|
-
|
|
26716
|
-
|
|
26717
|
-
|
|
26718
|
-
let
|
|
26719
|
-
|
|
26720
|
-
if (
|
|
26721
|
-
|
|
26722
|
-
|
|
26723
|
-
} else if (rfNodeType === "manifest_node") {
|
|
26724
|
-
nodeId = toManifestNodeId(rfNodeId);
|
|
26725
|
-
nodeStore = nodes.get(nodeId);
|
|
26726
|
-
}
|
|
26727
|
-
if (!nodeStore || toRemove?.has(nodeStore)) continue;
|
|
26728
|
-
switch (change.type) {
|
|
26729
|
-
case "add":
|
|
26730
|
-
console.error(/* @__PURE__ */ new Error("Should not happen: add node change should be handled by flow store"));
|
|
26731
|
-
break;
|
|
26732
|
-
case "remove":
|
|
26733
|
-
if (editable$.value) (toRemove ??= /* @__PURE__ */ new Set()).add(nodeStore);
|
|
26734
|
-
break;
|
|
26735
|
-
case "select":
|
|
26736
|
-
nodeStore.$$.selected.set(change.selected);
|
|
26737
|
-
break;
|
|
26738
|
-
case "position": {
|
|
26739
|
-
const current = nodeStore.$.rfNode.value;
|
|
26740
|
-
const position = change.position ?? current.position ?? DEFAULT_POSITION;
|
|
26741
|
-
if (!isSameXYPosition(current.position, position) || current.dragging !== change.dragging) nodeStore.$$.rfNode.set({
|
|
26742
|
-
...current,
|
|
26743
|
-
position,
|
|
26744
|
-
dragging: change.dragging
|
|
26745
|
-
});
|
|
26746
|
-
break;
|
|
26747
|
-
}
|
|
26748
|
-
case "dimensions": {
|
|
26749
|
-
const current = nodeStore.$.rfNode.value;
|
|
26750
|
-
const update = { ...current };
|
|
26751
|
-
if (isSize(change.dimensions)) {
|
|
26752
|
-
update.measured = change.dimensions;
|
|
26753
|
-
if (change.setAttributes) {
|
|
26754
|
-
update.width = change.dimensions.width;
|
|
26755
|
-
update.height = change.dimensions.height;
|
|
26756
|
-
}
|
|
26757
|
-
}
|
|
26758
|
-
if (isBoolean$1(change.resizing)) update.resizing = change.resizing;
|
|
26759
|
-
if (current.measured?.width != update.measured?.width || current.measured?.height != update.measured?.height || current.width != update.width || current.height != update.height || current.resizing != update.resizing) nodeStore.$$.rfNode.set(update);
|
|
26760
|
-
break;
|
|
26761
|
-
}
|
|
26762
|
-
case "replace":
|
|
26763
|
-
if (editable$.value) nodeStore.$$.rfNode.set(change.item);
|
|
26764
|
-
break;
|
|
26765
|
-
default: console.error(/* @__PURE__ */ new Error("Unknown node change type"), change);
|
|
26766
|
-
}
|
|
26767
|
-
}
|
|
26768
|
-
return toRemove;
|
|
26769
|
-
}
|
|
26770
|
-
function applyEdgeChanges$1(changes, edges, editable$) {
|
|
26771
|
-
let toRemoveConnections;
|
|
26772
|
-
for (const change of changes) {
|
|
26773
|
-
const edgeId = change.id;
|
|
26774
|
-
if (!edgeId) continue;
|
|
26775
|
-
const edgeStore = edges.find((edge) => edge.id === edgeId)?.data?.store;
|
|
26776
|
-
if (!edgeStore || toRemoveConnections?.has(edgeStore.connection)) continue;
|
|
26777
|
-
switch (change.type) {
|
|
26778
|
-
case "add":
|
|
26779
|
-
console.error(/* @__PURE__ */ new Error("Should not happen: add edge change should be handled by flow store"));
|
|
26780
|
-
break;
|
|
26781
|
-
case "remove":
|
|
26782
|
-
if (editable$.value) (toRemoveConnections ??= /* @__PURE__ */ new Set()).add(edgeStore.connection);
|
|
26783
|
-
break;
|
|
26784
|
-
case "select":
|
|
26785
|
-
edgeStore.$$.selected.set(change.selected);
|
|
26786
|
-
break;
|
|
26787
|
-
case "replace":
|
|
26788
|
-
if (editable$.value) edgeStore.$$.selected.set(change.item.selected);
|
|
26789
|
-
break;
|
|
26790
|
-
default: console.error(/* @__PURE__ */ new Error("Unknown edge change type"), change);
|
|
26791
|
-
}
|
|
26793
|
+
function dequeue(queue) {
|
|
26794
|
+
const first = queue[0];
|
|
26795
|
+
const last = queue.pop();
|
|
26796
|
+
if (!queue.length) return first;
|
|
26797
|
+
let index = 0;
|
|
26798
|
+
while (index * 2 + 1 < queue.length) {
|
|
26799
|
+
let child = index * 2 + 1;
|
|
26800
|
+
if (child + 1 < queue.length && queue[child + 1].score < queue[child].score) child++;
|
|
26801
|
+
if (last.score <= queue[child].score) break;
|
|
26802
|
+
queue[index] = queue[child];
|
|
26803
|
+
index = child;
|
|
26792
26804
|
}
|
|
26793
|
-
|
|
26794
|
-
|
|
26795
|
-
function isRectIntersect(a, b) {
|
|
26796
|
-
return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
26805
|
+
queue[index] = last;
|
|
26806
|
+
return first;
|
|
26797
26807
|
}
|
|
26798
26808
|
//#endregion
|
|
26799
26809
|
//#region src/canvas/browser/base/wrapLayout.ts
|
|
26810
|
+
/** Normalize primary/cross coordinates without rotating cards. */
|
|
26811
|
+
function layoutAxes(point, direction) {
|
|
26812
|
+
return direction === "vertical" ? {
|
|
26813
|
+
x: point.y,
|
|
26814
|
+
y: point.x
|
|
26815
|
+
} : point;
|
|
26816
|
+
}
|
|
26800
26817
|
var columnsPerRow = 6;
|
|
26801
26818
|
var rowGap = 160;
|
|
26802
26819
|
/** Wrap whole dependency columns; unmeasured default placement keeps six columns per row. */
|
|
@@ -26842,6 +26859,559 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
26842
26859
|
return positions;
|
|
26843
26860
|
}
|
|
26844
26861
|
//#endregion
|
|
26862
|
+
//#region src/canvas/browser/base/compactLayout.ts
|
|
26863
|
+
function bounds(nodes, routes = /* @__PURE__ */ new Map()) {
|
|
26864
|
+
const points = [...routes.values()].flat();
|
|
26865
|
+
for (const node of nodes) points.push(node, {
|
|
26866
|
+
x: node.x + node.width,
|
|
26867
|
+
y: node.y + node.height
|
|
26868
|
+
});
|
|
26869
|
+
const x = Math.min(...points.map((point) => point.x));
|
|
26870
|
+
const y = Math.min(...points.map((point) => point.y));
|
|
26871
|
+
return {
|
|
26872
|
+
x,
|
|
26873
|
+
y,
|
|
26874
|
+
width: Math.max(...points.map((point) => point.x)) - x,
|
|
26875
|
+
height: Math.max(...points.map((point) => point.y)) - y
|
|
26876
|
+
};
|
|
26877
|
+
}
|
|
26878
|
+
/** Place branches at their earliest dependency level, rather than delaying short
|
|
26879
|
+
* branches until the longest sibling reaches a shared join. Cycles remain one
|
|
26880
|
+
* component whose internal order follows the measured base layout. */
|
|
26881
|
+
function dependencyLevels(nodes, edges, gap) {
|
|
26882
|
+
const graph = new ie.Graph();
|
|
26883
|
+
for (const node of nodes) graph.setNode(node.id);
|
|
26884
|
+
for (const edge of edges) graph.setEdge(edge.source, edge.target);
|
|
26885
|
+
const components = ie.alg.tarjan(graph);
|
|
26886
|
+
const componentOf = new Map(components.flatMap((members, index) => members.map((id) => [id, String(index)])));
|
|
26887
|
+
const dependencies = new ie.Graph();
|
|
26888
|
+
for (let index = 0; index < components.length; index++) dependencies.setNode(String(index));
|
|
26889
|
+
for (const edge of edges) {
|
|
26890
|
+
const source = componentOf.get(edge.source);
|
|
26891
|
+
const target = componentOf.get(edge.target);
|
|
26892
|
+
if (source !== target) dependencies.setEdge(source, target);
|
|
26893
|
+
}
|
|
26894
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
26895
|
+
const levels = /* @__PURE__ */ new Map();
|
|
26896
|
+
const ends = /* @__PURE__ */ new Map();
|
|
26897
|
+
for (const id of ie.alg.topsort(dependencies)) {
|
|
26898
|
+
const start = Math.max(0, ...(dependencies.predecessors(id) ?? []).map((parent) => ends.get(parent) + 1));
|
|
26899
|
+
const members = components[Number(id)].map((member) => byId.get(member)).toSorted((a, b) => a.column - b.column || a.y - b.y);
|
|
26900
|
+
for (const [index, member] of members.entries()) levels.set(member.id, start + index);
|
|
26901
|
+
ends.set(id, start + members.length - 1);
|
|
26902
|
+
}
|
|
26903
|
+
const isolated = nodes.filter((node) => graph.nodeEdges(node.id)?.length === 0);
|
|
26904
|
+
const isolatedColumns = [...new Set(isolated.map((node) => node.column))].toSorted((a, b) => a - b);
|
|
26905
|
+
for (const node of isolated) levels.set(node.id, isolatedColumns.indexOf(node.column));
|
|
26906
|
+
let primary = 0;
|
|
26907
|
+
const groups = [...Map.groupBy(nodes, (node) => levels.get(node.id)).entries()].toSorted(([a], [b]) => a - b);
|
|
26908
|
+
for (const [level, members] of groups) {
|
|
26909
|
+
const size = Math.max(...members.map((node) => node.width));
|
|
26910
|
+
for (const node of members) Object.assign(node, {
|
|
26911
|
+
column: level,
|
|
26912
|
+
x: primary + (size - node.width) / 2
|
|
26913
|
+
});
|
|
26914
|
+
primary += size + gap;
|
|
26915
|
+
}
|
|
26916
|
+
}
|
|
26917
|
+
/** Compact each connected subgraph, then wrap the forest to the requested ratio. */
|
|
26918
|
+
function compactLayout(graph, insets = {
|
|
26919
|
+
width: 0,
|
|
26920
|
+
height: 0
|
|
26921
|
+
}, aspectRatio = 1) {
|
|
26922
|
+
if (!graph.nodes.length) return {
|
|
26923
|
+
positions: {},
|
|
26924
|
+
routes: /* @__PURE__ */ new Map(),
|
|
26925
|
+
bounds: {
|
|
26926
|
+
x: 0,
|
|
26927
|
+
y: 0,
|
|
26928
|
+
width: 320,
|
|
26929
|
+
height: 120
|
|
26930
|
+
}
|
|
26931
|
+
};
|
|
26932
|
+
const connected = new ie.Graph();
|
|
26933
|
+
for (const node of graph.nodes) connected.setNode(node.id);
|
|
26934
|
+
for (const edge of graph.edges) connected.setEdge(edge.source, edge.target);
|
|
26935
|
+
const members = ie.alg.components(connected);
|
|
26936
|
+
if (members.length === 1) return compactComponent(graph, insets, aspectRatio);
|
|
26937
|
+
const componentOf = new Map(members.flatMap((ids, index) => ids.map((id) => [id, index])));
|
|
26938
|
+
const edges = Map.groupBy(graph.edges, (edge) => componentOf.get(edge.source));
|
|
26939
|
+
return packComponents([...Map.groupBy(graph.nodes, (node) => componentOf.get(node.id))].map(([id, nodes]) => ({
|
|
26940
|
+
nodes,
|
|
26941
|
+
edges: edges.get(id) ?? [],
|
|
26942
|
+
bounds: bounds(nodes)
|
|
26943
|
+
})).toSorted((a, b) => a.bounds.x - b.bounds.x || a.bounds.y - b.bounds.y).map((component) => component.nodes.length === 1 && !component.edges.length ? {
|
|
26944
|
+
positions: { [component.nodes[0].id]: component.nodes[0] },
|
|
26945
|
+
routes: /* @__PURE__ */ new Map(),
|
|
26946
|
+
bounds: component.bounds
|
|
26947
|
+
} : compactComponent(component, {
|
|
26948
|
+
width: 0,
|
|
26949
|
+
height: 0
|
|
26950
|
+
}, aspectRatio)), insets, aspectRatio);
|
|
26951
|
+
}
|
|
26952
|
+
/** Keep reading order, with a larger gap between independent trees than within one. */
|
|
26953
|
+
function packComponents(layouts, insets, aspectRatio) {
|
|
26954
|
+
const gap = 96;
|
|
26955
|
+
const largestWidth = Math.max(...layouts.map((layout) => layout.bounds.width));
|
|
26956
|
+
const contentArea = layouts.reduce((sum, layout) => sum + layout.bounds.width * layout.bounds.height, 0);
|
|
26957
|
+
const limits = /* @__PURE__ */ new Set([largestWidth, Math.max(largestWidth, Math.sqrt(contentArea * aspectRatio))]);
|
|
26958
|
+
let prefixWidth = -96;
|
|
26959
|
+
for (const layout of layouts) {
|
|
26960
|
+
prefixWidth += layout.bounds.width + gap;
|
|
26961
|
+
limits.add(Math.max(largestWidth, prefixWidth));
|
|
26962
|
+
}
|
|
26963
|
+
let best;
|
|
26964
|
+
for (const limit of limits) {
|
|
26965
|
+
let x = 0;
|
|
26966
|
+
let y = 0;
|
|
26967
|
+
let width = 0;
|
|
26968
|
+
let rowHeight = 0;
|
|
26969
|
+
let rows = 1;
|
|
26970
|
+
const positions = layouts.map((layout) => {
|
|
26971
|
+
if (x > 0 && x + layout.bounds.width > limit + 1e-6) {
|
|
26972
|
+
y += rowHeight + gap;
|
|
26973
|
+
x = rowHeight = 0;
|
|
26974
|
+
rows++;
|
|
26975
|
+
}
|
|
26976
|
+
const position = {
|
|
26977
|
+
x: x - layout.bounds.x,
|
|
26978
|
+
y: y - layout.bounds.y
|
|
26979
|
+
};
|
|
26980
|
+
width = Math.max(width, x + layout.bounds.width);
|
|
26981
|
+
rowHeight = Math.max(rowHeight, layout.bounds.height);
|
|
26982
|
+
x += layout.bounds.width + gap;
|
|
26983
|
+
return position;
|
|
26984
|
+
});
|
|
26985
|
+
const height = y + rowHeight;
|
|
26986
|
+
const score = Math.max((width + insets.width) / aspectRatio, height + insets.height);
|
|
26987
|
+
const area = (width + insets.width) * (height + insets.height);
|
|
26988
|
+
if (!best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && (area < best.area || area === best.area && rows < best.rows)) best = {
|
|
26989
|
+
positions,
|
|
26990
|
+
width,
|
|
26991
|
+
height,
|
|
26992
|
+
score,
|
|
26993
|
+
area,
|
|
26994
|
+
rows
|
|
26995
|
+
};
|
|
26996
|
+
}
|
|
26997
|
+
const translate = (point, index) => ({
|
|
26998
|
+
x: point.x + best.positions[index].x,
|
|
26999
|
+
y: point.y + best.positions[index].y
|
|
27000
|
+
});
|
|
27001
|
+
return {
|
|
27002
|
+
positions: Object.fromEntries(layouts.flatMap((layout, index) => Object.entries(layout.positions).map(([id, point]) => [id, translate(point, index)]))),
|
|
27003
|
+
routes: new Map(layouts.flatMap((layout, index) => [...layout.routes].map(([id, points]) => [id, points.map((point) => translate(point, index))]))),
|
|
27004
|
+
bounds: {
|
|
27005
|
+
x: 0,
|
|
27006
|
+
y: 0,
|
|
27007
|
+
width: best.width,
|
|
27008
|
+
height: best.height
|
|
27009
|
+
}
|
|
27010
|
+
};
|
|
27011
|
+
}
|
|
27012
|
+
/** Bend dependency paths continuously; the ports retain their original orientation. */
|
|
27013
|
+
function compactComponent(graph, insets, aspectRatio) {
|
|
27014
|
+
const normalized = graph.nodes.map((node) => ({
|
|
27015
|
+
...node,
|
|
27016
|
+
...layoutAxes(node, "vertical"),
|
|
27017
|
+
width: node.height,
|
|
27018
|
+
height: node.width
|
|
27019
|
+
}));
|
|
27020
|
+
dependencyLevels(normalized, graph.edges, 48);
|
|
27021
|
+
const incoming = new Set(graph.edges.map((edge) => edge.target));
|
|
27022
|
+
const outgoing = new Set(graph.edges.map((edge) => edge.source));
|
|
27023
|
+
const roots = normalized.filter((node) => !incoming.has(node.id) && outgoing.has(node.id));
|
|
27024
|
+
const centers = (roots.length ? roots : normalized).map((node) => node.y + node.height / 2);
|
|
27025
|
+
const center = centers.reduce((sum, value) => sum + value, 0) / centers.length;
|
|
27026
|
+
const gap = 48;
|
|
27027
|
+
const pathNodes = normalized.filter((node) => incoming.has(node.id) || outgoing.has(node.id));
|
|
27028
|
+
const crossSize = Math.max(...(pathNodes.length ? pathNodes : normalized).map((node) => node.height));
|
|
27029
|
+
const bow = crossSize * .75;
|
|
27030
|
+
const separation = crossSize + 48;
|
|
27031
|
+
const bucketSize = Math.max(...normalized.map((node) => node.width)) + gap;
|
|
27032
|
+
const byId = new Map(normalized.map((node) => [node.id, node]));
|
|
27033
|
+
const forwardEdges = graph.edges.filter((edge) => byId.get(edge.source).column < byId.get(edge.target).column);
|
|
27034
|
+
const parents = Map.groupBy(forwardEdges, (edge) => edge.target);
|
|
27035
|
+
const children = Map.groupBy(forwardEdges, (edge) => edge.source);
|
|
27036
|
+
const ordered = normalized.toSorted((a, b) => a.column - b.column || a.y - b.y);
|
|
27037
|
+
const remaining = /* @__PURE__ */ new Map();
|
|
27038
|
+
for (const node of ordered.toReversed()) remaining.set(node.id, 1 + Math.max(0, ...(children.get(node.id) ?? []).filter((edge) => parents.get(edge.target)?.length === 1).map((edge) => remaining.get(edge.target))));
|
|
27039
|
+
const rankEnds = new Map([...Map.groupBy(normalized, (node) => node.column)].map(([rank, nodes]) => [rank, Math.max(...nodes.map((node) => node.x + node.width))]));
|
|
27040
|
+
const spans = /* @__PURE__ */ new Set([Infinity, ...rankEnds.values()]);
|
|
27041
|
+
let best;
|
|
27042
|
+
for (const span of spans) {
|
|
27043
|
+
const placed = /* @__PURE__ */ new Map();
|
|
27044
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
27045
|
+
let turns = 0;
|
|
27046
|
+
for (const original of ordered) {
|
|
27047
|
+
const upstream = parents.get(original.id)?.map((edge) => placed.get(edge.source)) ?? [];
|
|
27048
|
+
const parent = upstream[0];
|
|
27049
|
+
const side = original.y + original.height / 2 < center - 1e-6 ? -1 : 1;
|
|
27050
|
+
let primary = upstream.length ? Math.max(...upstream.map(({ node }) => {
|
|
27051
|
+
const source = byId.get(node.id);
|
|
27052
|
+
return node.x + rankEnds.get(source.column) - source.x;
|
|
27053
|
+
})) + gap : original.x;
|
|
27054
|
+
let shift = 0;
|
|
27055
|
+
let start = 0;
|
|
27056
|
+
if (upstream.length > 1) {
|
|
27057
|
+
primary = Math.max(...upstream.map((entry) => entry.extent)) + gap;
|
|
27058
|
+
shift = upstream.reduce((sum, { node }) => sum + node.y + node.height / 2, 0) / upstream.length - original.y - original.height / 2;
|
|
27059
|
+
start = primary;
|
|
27060
|
+
} else if (parent) {
|
|
27061
|
+
shift = parent.shift;
|
|
27062
|
+
start = parent.start;
|
|
27063
|
+
if ((children.get(parent.node.id)?.length ?? 0) > 1) {
|
|
27064
|
+
shift = parent.node.y - byId.get(parent.node.id).y;
|
|
27065
|
+
start = primary;
|
|
27066
|
+
} else if (primary + original.width > span && remaining.get(original.id) > 2) {
|
|
27067
|
+
primary = Math.max(0, start - span / 3);
|
|
27068
|
+
shift = parent.shift + side * separation;
|
|
27069
|
+
start = primary;
|
|
27070
|
+
turns++;
|
|
27071
|
+
}
|
|
27072
|
+
}
|
|
27073
|
+
const progress = Number.isFinite(span) && span > start ? Math.min(1, Math.max(0, (primary - start) / (span - start))) : 0;
|
|
27074
|
+
const drift = side * bow * Math.sin(progress * Math.PI);
|
|
27075
|
+
const node = {
|
|
27076
|
+
...original,
|
|
27077
|
+
x: primary,
|
|
27078
|
+
y: original.y + shift + drift
|
|
27079
|
+
};
|
|
27080
|
+
const firstBucket = Math.floor(node.x / bucketSize);
|
|
27081
|
+
const lastBucket = Math.floor((node.x + node.width + gap) / bucketSize);
|
|
27082
|
+
const nearby = /* @__PURE__ */ new Set();
|
|
27083
|
+
for (let bucket = firstBucket; bucket <= lastBucket; bucket++) for (const entry of buckets.get(bucket) ?? []) nearby.add(entry);
|
|
27084
|
+
const candidates = [...nearby].toSorted((a, b) => a.order - b.order);
|
|
27085
|
+
while (true) {
|
|
27086
|
+
const collision = candidates.find(({ node: other }) => node.x < other.x + other.width + 48 - 1e-6 && other.x < node.x + node.width + 48 - 1e-6 && node.y < other.y + other.height + 48 - 1e-6 && other.y < node.y + node.height + 48 - 1e-6);
|
|
27087
|
+
if (!collision) break;
|
|
27088
|
+
node.y = side < 0 ? collision.node.y - node.height - 48 : collision.node.y + collision.node.height + 48;
|
|
27089
|
+
}
|
|
27090
|
+
const placement = {
|
|
27091
|
+
node,
|
|
27092
|
+
order: placed.size,
|
|
27093
|
+
shift: node.y - original.y - drift,
|
|
27094
|
+
start,
|
|
27095
|
+
extent: Math.max(node.x + node.width, ...upstream.map((entry) => entry.extent))
|
|
27096
|
+
};
|
|
27097
|
+
placed.set(node.id, placement);
|
|
27098
|
+
for (let bucket = firstBucket; bucket <= lastBucket; bucket++) {
|
|
27099
|
+
const entries = buckets.get(bucket);
|
|
27100
|
+
if (entries) entries.push(placement);
|
|
27101
|
+
else buckets.set(bucket, [placement]);
|
|
27102
|
+
}
|
|
27103
|
+
}
|
|
27104
|
+
const nodes = [...placed.values()].map((entry) => entry.node);
|
|
27105
|
+
const extent = bounds(nodes);
|
|
27106
|
+
const width = extent.height + insets.width + 48;
|
|
27107
|
+
const height = extent.width + insets.height + 48;
|
|
27108
|
+
const area = width * height;
|
|
27109
|
+
const score = Math.max(width / aspectRatio, height);
|
|
27110
|
+
if (!best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && (area < best.area || area === best.area && turns < best.turns)) best = {
|
|
27111
|
+
nodes,
|
|
27112
|
+
score,
|
|
27113
|
+
area,
|
|
27114
|
+
turns
|
|
27115
|
+
};
|
|
27116
|
+
}
|
|
27117
|
+
const routes = routeLayout(best.nodes, graph.edges.map((edge) => Object.assign({}, edge, {
|
|
27118
|
+
sourceOffset: edge.sourceOffset && layoutAxes(edge.sourceOffset, "vertical"),
|
|
27119
|
+
targetOffset: edge.targetOffset && layoutAxes(edge.targetOffset, "vertical")
|
|
27120
|
+
})));
|
|
27121
|
+
const physicalNodes = best.nodes.map((node) => Object.assign({}, node, layoutAxes(node, "vertical"), {
|
|
27122
|
+
width: node.height,
|
|
27123
|
+
height: node.width
|
|
27124
|
+
}));
|
|
27125
|
+
const physicalRoutes = new Map([...routes].map(([id, points]) => [id, points.map((point) => layoutAxes(point, "vertical"))]));
|
|
27126
|
+
return {
|
|
27127
|
+
positions: Object.fromEntries(physicalNodes.map(({ id, x, y }) => [id, {
|
|
27128
|
+
x,
|
|
27129
|
+
y
|
|
27130
|
+
}])),
|
|
27131
|
+
routes: physicalRoutes,
|
|
27132
|
+
bounds: bounds(physicalNodes, physicalRoutes)
|
|
27133
|
+
};
|
|
27134
|
+
}
|
|
27135
|
+
//#endregion
|
|
27136
|
+
//#region ../../node_modules/.bun/@wopjs+cast@0.1.16/node_modules/@wopjs/cast/dist/index.mjs
|
|
27137
|
+
var isBoolean$1, isString$1, isArray$2, isObject$2, isPlainObject$3, toPlainObject;
|
|
27138
|
+
var init_dist$2 = __esmMin((() => {
|
|
27139
|
+
isBoolean$1 = (x) => x === true || x === false;
|
|
27140
|
+
isString$1 = (x) => typeof x === "string";
|
|
27141
|
+
isArray$2 = Array.isArray;
|
|
27142
|
+
isObject$2 = (x) => x !== null && typeof x === "object";
|
|
27143
|
+
isPlainObject$3 = (x) => isObject$2(x) && !isArray$2(x);
|
|
27144
|
+
toPlainObject = (x) => isPlainObject$3(x) ? x : void 0;
|
|
27145
|
+
}));
|
|
27146
|
+
Array.isArray;
|
|
27147
|
+
var isNumber$5 = (value) => {
|
|
27148
|
+
try {
|
|
27149
|
+
return Number(value) === value;
|
|
27150
|
+
} catch {
|
|
27151
|
+
return false;
|
|
27152
|
+
}
|
|
27153
|
+
};
|
|
27154
|
+
var isDate = (value) => {
|
|
27155
|
+
return Object.prototype.toString.call(value) === "[object Date]";
|
|
27156
|
+
};
|
|
27157
|
+
//#endregion
|
|
27158
|
+
//#region ../../node_modules/.bun/radash@12.1.1/node_modules/radash/dist/esm/array.mjs
|
|
27159
|
+
var cluster = (list2, size = 2) => {
|
|
27160
|
+
const clusterCount = Math.ceil(list2.length / size);
|
|
27161
|
+
return new Array(clusterCount).fill(null).map((_c, i) => {
|
|
27162
|
+
return list2.slice(i * size, i * size + size);
|
|
27163
|
+
});
|
|
27164
|
+
};
|
|
27165
|
+
//#endregion
|
|
27166
|
+
//#region src/canvas/browser/base/compare.ts
|
|
27167
|
+
init_dist$2();
|
|
27168
|
+
var isSameXYPosition = (p1, p2) => !p1 || !p2 ? p1 === p2 : p1.x === p2.x && p1.y === p2.y;
|
|
27169
|
+
var isSize = (s) => isPlainObject$3(s) && isNumber$5(s.width) && isNumber$5(s.height);
|
|
27170
|
+
var isSameSize = (s1, s2) => !s1 || !s2 ? s1 === s2 : s1.width === s2.width && s1.height === s2.height;
|
|
27171
|
+
var isSameViewport = (v1, v2) => !v1 || !v2 ? v1 === v2 : v1.x === v2.x && v1.y === v2.y && v1.zoom === v2.zoom;
|
|
27172
|
+
function isFunction$1(value) {
|
|
27173
|
+
return typeof value === "function";
|
|
27174
|
+
}
|
|
27175
|
+
function asArray(value) {
|
|
27176
|
+
return value == null ? [] : Array.isArray(value) ? value : [value];
|
|
27177
|
+
}
|
|
27178
|
+
function coalesce(array) {
|
|
27179
|
+
return array.filter((e) => e != null);
|
|
27180
|
+
}
|
|
27181
|
+
function toTrue(value) {
|
|
27182
|
+
return value === true ? true : void 0;
|
|
27183
|
+
}
|
|
27184
|
+
/**
|
|
27185
|
+
* Skips the update when the object has already been removed from the reactive value.
|
|
27186
|
+
*
|
|
27187
|
+
* ```js
|
|
27188
|
+
* const setName = updatePartial(object$, "name")
|
|
27189
|
+
* ```
|
|
27190
|
+
*/
|
|
27191
|
+
function updatePartial(val, field, equal = Object.is) {
|
|
27192
|
+
return (fieldValue) => {
|
|
27193
|
+
if (val.value && !equal(val.value[field], fieldValue)) val.set({
|
|
27194
|
+
...val.value,
|
|
27195
|
+
[field]: fieldValue
|
|
27196
|
+
});
|
|
27197
|
+
};
|
|
27198
|
+
}
|
|
27199
|
+
//#endregion
|
|
27200
|
+
//#region src/canvas/browser/base/dom.ts
|
|
27201
|
+
var nav$1 = typeof navigator !== "undefined" ? navigator : { platform: "" };
|
|
27202
|
+
var isMac$1 = /*#__PURE__*/ /Mac/.test(nav$1.platform);
|
|
27203
|
+
function stopEvent$1(event, cancelBubble) {
|
|
27204
|
+
event.preventDefault();
|
|
27205
|
+
if (cancelBubble) event.stopPropagation();
|
|
27206
|
+
}
|
|
27207
|
+
/**
|
|
27208
|
+
* @example
|
|
27209
|
+
* ```js
|
|
27210
|
+
* onClick(ev => isInside(ev.target, '.class1, .class2'))
|
|
27211
|
+
* ```
|
|
27212
|
+
*/
|
|
27213
|
+
function isInside(target, selector) {
|
|
27214
|
+
return target?.closest?.(selector) != null;
|
|
27215
|
+
}
|
|
27216
|
+
//#endregion
|
|
27217
|
+
//#region src/canvas/browser/base/graphLayout.ts
|
|
27218
|
+
/** The measured dependency layout shared by canvas arrangement and image export. */
|
|
27219
|
+
function graphLayout(nodes, edges, direction) {
|
|
27220
|
+
if (!nodes.length) return {
|
|
27221
|
+
nodes: [],
|
|
27222
|
+
edges: []
|
|
27223
|
+
};
|
|
27224
|
+
const graph = new ie.Graph().setDefaultEdgeLabel(() => ({}));
|
|
27225
|
+
graph.setGraph({
|
|
27226
|
+
rankdir: direction === "vertical" ? "TB" : "LR",
|
|
27227
|
+
ranksep: direction === "vertical" ? 48 : 80
|
|
27228
|
+
});
|
|
27229
|
+
const singles = new Set(nodes.map((node) => node.id));
|
|
27230
|
+
for (const node of nodes) graph.setNode(node.id, {
|
|
27231
|
+
width: node.width,
|
|
27232
|
+
height: node.height
|
|
27233
|
+
});
|
|
27234
|
+
const connections = edges.filter((edge) => graph.hasNode(edge.source) && graph.hasNode(edge.target));
|
|
27235
|
+
for (const edge of connections) {
|
|
27236
|
+
singles.delete(edge.source);
|
|
27237
|
+
singles.delete(edge.target);
|
|
27238
|
+
graph.setEdge(edge.source, edge.target);
|
|
27239
|
+
}
|
|
27240
|
+
const isolated = [...singles];
|
|
27241
|
+
for (let start = 0; start < isolated.length; start += 10) for (let index = start; index < Math.min(start + 9, isolated.length - 1); index++) graph.setEdge(isolated[index], isolated[index + 1]);
|
|
27242
|
+
const constraints = [];
|
|
27243
|
+
const ordering = new ie.Graph();
|
|
27244
|
+
for (const node of nodes) {
|
|
27245
|
+
const targets = [...new Set(node.branchHandles?.flatMap((handle) => connections.filter((edge) => edge.source === node.id && edge.sourceHandle === handle).map((edge) => edge.target)))];
|
|
27246
|
+
for (let index = 1; index < targets.length; index++) {
|
|
27247
|
+
const left = targets[index - 1];
|
|
27248
|
+
const right = targets[index];
|
|
27249
|
+
ordering.setEdge(left, right);
|
|
27250
|
+
if (ie.alg.isAcyclic(ordering)) constraints.push({
|
|
27251
|
+
left,
|
|
27252
|
+
right
|
|
27253
|
+
});
|
|
27254
|
+
else ordering.removeEdge(left, right);
|
|
27255
|
+
}
|
|
27256
|
+
}
|
|
27257
|
+
Oe(graph, { constraints });
|
|
27258
|
+
return {
|
|
27259
|
+
nodes: nodes.map((node) => {
|
|
27260
|
+
const { x, y, width, height, rank } = graph.node(node.id);
|
|
27261
|
+
return {
|
|
27262
|
+
id: node.id,
|
|
27263
|
+
column: rank,
|
|
27264
|
+
x: x - width / 2,
|
|
27265
|
+
y: y - height / 2,
|
|
27266
|
+
width,
|
|
27267
|
+
height
|
|
27268
|
+
};
|
|
27269
|
+
}),
|
|
27270
|
+
edges: connections.map((edge) => Object.assign({}, edge, { points: graph.edge(edge.source, edge.target).points }))
|
|
27271
|
+
};
|
|
27272
|
+
}
|
|
27273
|
+
//#endregion
|
|
27274
|
+
//#region src/canvas/browser/stores/node/constants.ts
|
|
27275
|
+
var NODE_TYPE = /* @__PURE__ */ function(NODE_TYPE) {
|
|
27276
|
+
NODE_TYPE["TaskNode"] = "task_node";
|
|
27277
|
+
NODE_TYPE["ValueNode"] = "value_node";
|
|
27278
|
+
NODE_TYPE["ConditionNode"] = "condition_node";
|
|
27279
|
+
NODE_TYPE["CommentNode"] = "comment_node";
|
|
27280
|
+
NODE_TYPE["TriggerNode"] = "trigger_node";
|
|
27281
|
+
return NODE_TYPE;
|
|
27282
|
+
}({});
|
|
27283
|
+
//#endregion
|
|
27284
|
+
//#region src/canvas/browser/base/canvas.ts
|
|
27285
|
+
var CANVAS_CLASSNAME = "open-flow-canvas";
|
|
27286
|
+
function minimumCanvasCardWidth(direction, branchCount) {
|
|
27287
|
+
return direction === "vertical" && branchCount > 0 ? Math.max(320, branchCount * 96 + (branchCount - 1) * 6 + 16 + 2) : 320;
|
|
27288
|
+
}
|
|
27289
|
+
function canvasCardWidth(direction, branchCount, preferredWidth) {
|
|
27290
|
+
const minimum = minimumCanvasCardWidth(direction, branchCount);
|
|
27291
|
+
return direction === "vertical" && preferredWidth != null && Number.isFinite(preferredWidth) ? Math.max(minimum, preferredWidth) : minimum;
|
|
27292
|
+
}
|
|
27293
|
+
/** Marks an area that React Flow can drag. */
|
|
27294
|
+
var NODE_HANDLE_CLASSNAME = "open-flow-canvas-node-handle";
|
|
27295
|
+
var DEFAULT_POSITION = /* @__PURE__ */ Object.freeze({
|
|
27296
|
+
x: 0,
|
|
27297
|
+
y: 0
|
|
27298
|
+
});
|
|
27299
|
+
//#endregion
|
|
27300
|
+
//#region src/canvas/browser/base/rfHelpers.ts
|
|
27301
|
+
init_dist$2();
|
|
27302
|
+
/** Converts a manifest node identifier to a React Flow identifier. */
|
|
27303
|
+
function toRFNodeId(nodeId, nodeType) {
|
|
27304
|
+
return (nodeType === NODE_TYPE.CommentNode ? "c:" : "m:") + nodeId;
|
|
27305
|
+
}
|
|
27306
|
+
function getRFNodeType(rfNodeId) {
|
|
27307
|
+
if (rfNodeId[1] === ":") switch (rfNodeId[0]) {
|
|
27308
|
+
case "m": return "manifest_node";
|
|
27309
|
+
case "c": return "comment_node";
|
|
27310
|
+
}
|
|
27311
|
+
}
|
|
27312
|
+
function toManifestNodeId(rfNodeId) {
|
|
27313
|
+
if (rfNodeId[1] === ":") switch (rfNodeId[0]) {
|
|
27314
|
+
case "m":
|
|
27315
|
+
case "c": return rfNodeId.slice(2);
|
|
27316
|
+
}
|
|
27317
|
+
return rfNodeId;
|
|
27318
|
+
}
|
|
27319
|
+
function toRFHandleName(handleName) {
|
|
27320
|
+
return `h:${handleName}`;
|
|
27321
|
+
}
|
|
27322
|
+
function toManifestHandleName(rfHandleName) {
|
|
27323
|
+
if (rfHandleName[1] === ":") {
|
|
27324
|
+
if (rfHandleName[0] === "h") return rfHandleName.slice(2);
|
|
27325
|
+
}
|
|
27326
|
+
return rfHandleName;
|
|
27327
|
+
}
|
|
27328
|
+
function applyNodeChanges$1(changes, nodes, commentNodes, editable$) {
|
|
27329
|
+
let toRemove;
|
|
27330
|
+
for (const change of changes) {
|
|
27331
|
+
const rfNodeId = change.id;
|
|
27332
|
+
if (!rfNodeId) continue;
|
|
27333
|
+
let nodeId;
|
|
27334
|
+
let nodeStore;
|
|
27335
|
+
const rfNodeType = getRFNodeType(rfNodeId);
|
|
27336
|
+
if (rfNodeType === "comment_node") {
|
|
27337
|
+
nodeId = toManifestNodeId(rfNodeId);
|
|
27338
|
+
nodeStore = commentNodes?.get(nodeId);
|
|
27339
|
+
} else if (rfNodeType === "manifest_node") {
|
|
27340
|
+
nodeId = toManifestNodeId(rfNodeId);
|
|
27341
|
+
nodeStore = nodes.get(nodeId);
|
|
27342
|
+
}
|
|
27343
|
+
if (!nodeStore || toRemove?.has(nodeStore)) continue;
|
|
27344
|
+
switch (change.type) {
|
|
27345
|
+
case "add":
|
|
27346
|
+
console.error(/* @__PURE__ */ new Error("Should not happen: add node change should be handled by flow store"));
|
|
27347
|
+
break;
|
|
27348
|
+
case "remove":
|
|
27349
|
+
if (editable$.value) (toRemove ??= /* @__PURE__ */ new Set()).add(nodeStore);
|
|
27350
|
+
break;
|
|
27351
|
+
case "select":
|
|
27352
|
+
nodeStore.$$.selected.set(change.selected);
|
|
27353
|
+
break;
|
|
27354
|
+
case "position": {
|
|
27355
|
+
const current = nodeStore.$.rfNode.value;
|
|
27356
|
+
const position = change.position ?? current.position ?? DEFAULT_POSITION;
|
|
27357
|
+
if (!isSameXYPosition(current.position, position) || current.dragging !== change.dragging) nodeStore.$$.rfNode.set({
|
|
27358
|
+
...current,
|
|
27359
|
+
position,
|
|
27360
|
+
dragging: change.dragging
|
|
27361
|
+
});
|
|
27362
|
+
break;
|
|
27363
|
+
}
|
|
27364
|
+
case "dimensions": {
|
|
27365
|
+
const current = nodeStore.$.rfNode.value;
|
|
27366
|
+
const update = { ...current };
|
|
27367
|
+
if (isSize(change.dimensions)) {
|
|
27368
|
+
update.measured = change.dimensions;
|
|
27369
|
+
if (change.setAttributes) {
|
|
27370
|
+
update.width = change.dimensions.width;
|
|
27371
|
+
update.height = change.dimensions.height;
|
|
27372
|
+
}
|
|
27373
|
+
}
|
|
27374
|
+
if (isBoolean$1(change.resizing)) update.resizing = change.resizing;
|
|
27375
|
+
if (current.measured?.width != update.measured?.width || current.measured?.height != update.measured?.height || current.width != update.width || current.height != update.height || current.resizing != update.resizing) nodeStore.$$.rfNode.set(update);
|
|
27376
|
+
break;
|
|
27377
|
+
}
|
|
27378
|
+
case "replace":
|
|
27379
|
+
if (editable$.value) nodeStore.$$.rfNode.set(change.item);
|
|
27380
|
+
break;
|
|
27381
|
+
default: console.error(/* @__PURE__ */ new Error("Unknown node change type"), change);
|
|
27382
|
+
}
|
|
27383
|
+
}
|
|
27384
|
+
return toRemove;
|
|
27385
|
+
}
|
|
27386
|
+
function applyEdgeChanges$1(changes, edges, editable$) {
|
|
27387
|
+
let toRemoveConnections;
|
|
27388
|
+
for (const change of changes) {
|
|
27389
|
+
const edgeId = change.id;
|
|
27390
|
+
if (!edgeId) continue;
|
|
27391
|
+
const edgeStore = edges.find((edge) => edge.id === edgeId)?.data?.store;
|
|
27392
|
+
if (!edgeStore || toRemoveConnections?.has(edgeStore.connection)) continue;
|
|
27393
|
+
switch (change.type) {
|
|
27394
|
+
case "add":
|
|
27395
|
+
console.error(/* @__PURE__ */ new Error("Should not happen: add edge change should be handled by flow store"));
|
|
27396
|
+
break;
|
|
27397
|
+
case "remove":
|
|
27398
|
+
if (editable$.value) (toRemoveConnections ??= /* @__PURE__ */ new Set()).add(edgeStore.connection);
|
|
27399
|
+
break;
|
|
27400
|
+
case "select":
|
|
27401
|
+
edgeStore.$$.selected.set(change.selected);
|
|
27402
|
+
break;
|
|
27403
|
+
case "replace":
|
|
27404
|
+
if (editable$.value) edgeStore.$$.selected.set(change.item.selected);
|
|
27405
|
+
break;
|
|
27406
|
+
default: console.error(/* @__PURE__ */ new Error("Unknown edge change type"), change);
|
|
27407
|
+
}
|
|
27408
|
+
}
|
|
27409
|
+
return toRemoveConnections;
|
|
27410
|
+
}
|
|
27411
|
+
function isRectIntersect(a, b) {
|
|
27412
|
+
return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
27413
|
+
}
|
|
27414
|
+
//#endregion
|
|
26845
27415
|
//#region src/canvas/browser/graph/FlowCanvas/model.ts
|
|
26846
27416
|
function toViewEdge(source, sourceHandle, target, targetHandle) {
|
|
26847
27417
|
return {
|
|
@@ -32530,6 +33100,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
32530
33100
|
constructor(model, editable, language, callbacks, autoLayout = false, interactiveMode$) {
|
|
32531
33101
|
this.canDeleteNodes = true;
|
|
32532
33102
|
this.dispose = disposableStore();
|
|
33103
|
+
this.connectionRoutes = this.dispose.add(val(/* @__PURE__ */ new Map()));
|
|
32533
33104
|
this.ignoredNodeIds = this.dispose.add(val([]));
|
|
32534
33105
|
this.ignoreNodes = (nodeIds, ignored) => {
|
|
32535
33106
|
if (this.$.editable.value) this.#callbacks.onIgnoreNodes?.(nodeIds, ignored);
|
|
@@ -32814,67 +33385,52 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
32814
33385
|
if (position) node.$$.position.set(position);
|
|
32815
33386
|
}
|
|
32816
33387
|
}
|
|
32817
|
-
|
|
32818
|
-
|
|
32819
|
-
|
|
32820
|
-
|
|
32821
|
-
rankdir: vertical ? "TB" : "LR",
|
|
32822
|
-
ranksep: vertical ? 48 : 80
|
|
32823
|
-
});
|
|
32824
|
-
const singles = /* @__PURE__ */ new Set();
|
|
32825
|
-
for (const node of nodes) {
|
|
32826
|
-
const { id, measured } = node.$.rfNode.value;
|
|
32827
|
-
singles.add(id);
|
|
32828
|
-
g.setNode(id, {
|
|
32829
|
-
width: measured?.width ?? 0,
|
|
32830
|
-
height: measured?.height ?? 0
|
|
32831
|
-
});
|
|
32832
|
-
}
|
|
32833
|
-
for (const rfEdge of this.$.rfEdges.value) {
|
|
32834
|
-
if (!g.hasNode(rfEdge.source) || !g.hasNode(rfEdge.target)) continue;
|
|
32835
|
-
singles.delete(rfEdge.source);
|
|
32836
|
-
singles.delete(rfEdge.target);
|
|
32837
|
-
g.setEdge(rfEdge.source, rfEdge.target);
|
|
32838
|
-
}
|
|
32839
|
-
if (singles.size > 0) for (const list of cluster([...singles], 10)) for (let i = 0; i < list.length - 1; i++) g.setEdge(list[i], list[i + 1]);
|
|
32840
|
-
const constraints = [];
|
|
32841
|
-
const ordering = new ie.Graph();
|
|
32842
|
-
for (const node of nodes) {
|
|
32843
|
-
if (!NodeStore.is(node)) continue;
|
|
32844
|
-
const content = node.content$.value;
|
|
32845
|
-
if (content.kind !== "condition" && content.kind !== "approval" && content.kind !== "wait") continue;
|
|
32846
|
-
const targets = [...new Set(content.outputs.flatMap((port) => "handle" in port ? this.#connections.value.filter((edge) => edge.source === node.nodeId && edge.sourceHandle === `$branch:${port.handle}`).flatMap((edge) => {
|
|
32847
|
-
const target = this.$.nodes.get(edge.target);
|
|
32848
|
-
return target && g.hasNode(target.rfNodeId) ? [target.rfNodeId] : [];
|
|
32849
|
-
}) : []))];
|
|
32850
|
-
for (let index = 1; index < targets.length; index++) {
|
|
32851
|
-
const left = targets[index - 1];
|
|
32852
|
-
const right = targets[index];
|
|
32853
|
-
ordering.setEdge(left, right);
|
|
32854
|
-
if (ie.alg.isAcyclic(ordering)) constraints.push({
|
|
32855
|
-
left,
|
|
32856
|
-
right
|
|
32857
|
-
});
|
|
32858
|
-
else ordering.removeEdge(left, right);
|
|
32859
|
-
}
|
|
32860
|
-
}
|
|
32861
|
-
Oe(g, { constraints });
|
|
32862
|
-
const layoutNodes = nodes.map((node) => {
|
|
32863
|
-
const { x, y, width, height, rank } = g.node(node.rfNodeId);
|
|
33388
|
+
measuredLayout(nodes) {
|
|
33389
|
+
return graphLayout(nodes.map((node) => {
|
|
33390
|
+
const measured = node.$.measured.value;
|
|
33391
|
+
const content = NodeStore.is(node) ? node.content$.value : void 0;
|
|
32864
33392
|
return {
|
|
32865
33393
|
id: node.nodeId,
|
|
32866
|
-
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
width,
|
|
32870
|
-
height
|
|
33394
|
+
width: measured?.width ?? 0,
|
|
33395
|
+
height: measured?.height ?? 0,
|
|
33396
|
+
branchHandles: content?.kind === "condition" || content?.kind === "approval" || content?.kind === "wait" ? content.outputs.flatMap((port) => "handle" in port ? ["$branch:" + port.handle] : []) : void 0
|
|
32871
33397
|
};
|
|
32872
|
-
})
|
|
33398
|
+
}), this.#connections.value.map((edge) => ({
|
|
33399
|
+
...edge,
|
|
33400
|
+
id: getRFEdgeId(edge)
|
|
33401
|
+
})), this.$.direction.value);
|
|
33402
|
+
}
|
|
33403
|
+
layoutPositions(nodes, availableWidth) {
|
|
33404
|
+
const { nodes: layoutNodes } = this.measuredLayout(nodes);
|
|
32873
33405
|
return this.$.direction.value === "horizontal" ? wrapLayout(layoutNodes, availableWidth) : Object.fromEntries(layoutNodes.map(({ id, x, y }) => [id, {
|
|
32874
33406
|
x,
|
|
32875
33407
|
y
|
|
32876
33408
|
}]));
|
|
32877
33409
|
}
|
|
33410
|
+
/** Arrange the isolated export store without saving presentation or history. */
|
|
33411
|
+
compactForExport(insets, instance, aspectRatio = 1) {
|
|
33412
|
+
const graph = this.measuredLayout(this.allLayoutNodes());
|
|
33413
|
+
const port = (id, handle, type) => {
|
|
33414
|
+
const node = this.$.nodes.get(id);
|
|
33415
|
+
const measured = (node && instance?.getInternalNode(node.rfNodeId)?.internals.handleBounds?.[type])?.find((entry) => entry.id === `h:${handle}`);
|
|
33416
|
+
return measured && {
|
|
33417
|
+
x: measured.x + measured.width / 2,
|
|
33418
|
+
y: measured.y + (type === "source" ? measured.height : 0)
|
|
33419
|
+
};
|
|
33420
|
+
};
|
|
33421
|
+
const connections = new Map(this.#connections.value.map((edge) => [getRFEdgeId(edge), edge]));
|
|
33422
|
+
const edges = graph.edges.map((edge) => Object.assign({}, edge, {
|
|
33423
|
+
sourceOffset: port(edge.source, connections.get(edge.id)?.sourceHandle, "source"),
|
|
33424
|
+
targetOffset: port(edge.target, connections.get(edge.id)?.targetHandle, "target")
|
|
33425
|
+
}));
|
|
33426
|
+
const result = compactLayout({
|
|
33427
|
+
nodes: graph.nodes,
|
|
33428
|
+
edges
|
|
33429
|
+
}, insets, aspectRatio);
|
|
33430
|
+
this.applyPositions(result.positions);
|
|
33431
|
+
this.connectionRoutes.set(result.routes);
|
|
33432
|
+
return result.bounds;
|
|
33433
|
+
}
|
|
32878
33434
|
doRemoveNodes(nodes) {
|
|
32879
33435
|
if (this.disposed || !nodes?.size) return;
|
|
32880
33436
|
for (const node of nodes) this.pendingNodeDeletes.add(node);
|
|
@@ -32970,6 +33526,49 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
32970
33526
|
}
|
|
32971
33527
|
};
|
|
32972
33528
|
//#endregion
|
|
33529
|
+
//#region src/canvas/browser/graph/FlowCanvas/captureStyles.ts
|
|
33530
|
+
/** Capture authored properties instead of hundreds of unrelated browser defaults. */
|
|
33531
|
+
function captureStyleProperties(root) {
|
|
33532
|
+
const complete = () => Array.from(getComputedStyle(root)).filter((name) => !name.startsWith("--"));
|
|
33533
|
+
const properties = /* @__PURE__ */ new Set(["width", "height"]);
|
|
33534
|
+
const add = (style) => {
|
|
33535
|
+
for (const name of Array.from(style)) {
|
|
33536
|
+
if (name === "all") return false;
|
|
33537
|
+
if (!name.startsWith("--")) properties.add(name);
|
|
33538
|
+
}
|
|
33539
|
+
return true;
|
|
33540
|
+
};
|
|
33541
|
+
const collect = (rules) => {
|
|
33542
|
+
for (const rule of rules) {
|
|
33543
|
+
const style = rule.style;
|
|
33544
|
+
if (style) {
|
|
33545
|
+
const selector = rule.selectorText?.replace(/::[\w-]+(?:\([^)]*\))?/g, "");
|
|
33546
|
+
let matches = true;
|
|
33547
|
+
if (selector) try {
|
|
33548
|
+
matches = root.closest(selector) != null || root.querySelector(selector) != null;
|
|
33549
|
+
} catch {}
|
|
33550
|
+
if (matches && !add(style)) return false;
|
|
33551
|
+
}
|
|
33552
|
+
if ("cssRules" in rule && !collect(rule.cssRules)) return false;
|
|
33553
|
+
const imported = rule.styleSheet;
|
|
33554
|
+
if (imported && !collect(imported.cssRules)) return false;
|
|
33555
|
+
}
|
|
33556
|
+
return true;
|
|
33557
|
+
};
|
|
33558
|
+
try {
|
|
33559
|
+
const doc = root.ownerDocument;
|
|
33560
|
+
for (const sheet of [...doc.styleSheets, ...doc.adoptedStyleSheets]) if (!collect(sheet.cssRules)) return complete();
|
|
33561
|
+
} catch {
|
|
33562
|
+
return complete();
|
|
33563
|
+
}
|
|
33564
|
+
for (let ancestor = root; ancestor; ancestor = ancestor.parentElement) if (!add(ancestor.style)) return complete();
|
|
33565
|
+
for (const node of [root, ...root.querySelectorAll("*")]) {
|
|
33566
|
+
if (node.style && !add(node.style)) return complete();
|
|
33567
|
+
for (const attribute of node.attributes) if (CSS.supports(attribute.name, "initial")) properties.add(attribute.name);
|
|
33568
|
+
}
|
|
33569
|
+
return [...properties].toSorted();
|
|
33570
|
+
}
|
|
33571
|
+
//#endregion
|
|
32973
33572
|
//#region ../../node_modules/.bun/use-value-enhancer@5.0.7+5fffd67310d91248/node_modules/use-value-enhancer/dist/use-value-enhancer.mjs
|
|
32974
33573
|
var import_react$3, getVal, noop$3, returnsNoop, defaultArgs, useValWithUseSyncExternalStore, useValWithUseEffect, useVal;
|
|
32975
33574
|
var init_use_value_enhancer = __esmMin((() => {
|
|
@@ -55741,11 +56340,47 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
55741
56340
|
};
|
|
55742
56341
|
}
|
|
55743
56342
|
/** Align arrows with their ports and route returns outside both cards. */
|
|
55744
|
-
function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
|
|
56343
|
+
function getConnectionPath({ sourceBounds, targetBounds, waypoints, ...params }) {
|
|
55745
56344
|
const { sourcePosition = Position$1.Bottom, targetPosition = Position$1.Top } = params;
|
|
55746
56345
|
const vertical = sourcePosition === Position$1.Bottom && targetPosition === Position$1.Top || sourcePosition === Position$1.Top && targetPosition === Position$1.Bottom;
|
|
55747
56346
|
const reverse = sourcePosition === Position$1.Left && targetPosition === Position$1.Right || sourcePosition === Position$1.Top && targetPosition === Position$1.Bottom;
|
|
55748
56347
|
const horizontal = sourcePosition === Position$1.Right && targetPosition === Position$1.Left || sourcePosition === Position$1.Left && targetPosition === Position$1.Right;
|
|
56348
|
+
if (waypoints && waypoints.length > 2) {
|
|
56349
|
+
const interior = waypoints.slice(1, -1);
|
|
56350
|
+
const first = interior[0];
|
|
56351
|
+
const last = interior.at(-1);
|
|
56352
|
+
const points = [
|
|
56353
|
+
{
|
|
56354
|
+
x: params.sourceX,
|
|
56355
|
+
y: params.sourceY
|
|
56356
|
+
},
|
|
56357
|
+
vertical ? {
|
|
56358
|
+
x: params.sourceX,
|
|
56359
|
+
y: first.y
|
|
56360
|
+
} : {
|
|
56361
|
+
x: first.x,
|
|
56362
|
+
y: params.sourceY
|
|
56363
|
+
},
|
|
56364
|
+
...interior,
|
|
56365
|
+
vertical ? {
|
|
56366
|
+
x: params.targetX,
|
|
56367
|
+
y: last.y
|
|
56368
|
+
} : {
|
|
56369
|
+
x: last.x,
|
|
56370
|
+
y: params.targetY
|
|
56371
|
+
},
|
|
56372
|
+
{
|
|
56373
|
+
x: params.targetX,
|
|
56374
|
+
y: params.targetY
|
|
56375
|
+
}
|
|
56376
|
+
];
|
|
56377
|
+
const label = interior[Math.floor(interior.length / 2)];
|
|
56378
|
+
return [
|
|
56379
|
+
roundedConnectionPath(points),
|
|
56380
|
+
label.x,
|
|
56381
|
+
label.y
|
|
56382
|
+
];
|
|
56383
|
+
}
|
|
55749
56384
|
const primary = (x, y) => vertical ? y : x;
|
|
55750
56385
|
const cross = (x, y) => vertical ? x : y;
|
|
55751
56386
|
const sourceX = primary(params.sourceX, params.sourceY);
|
|
@@ -55830,6 +56465,15 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
55830
56465
|
y: point.x
|
|
55831
56466
|
} : point);
|
|
55832
56467
|
if (reverse) points.reverse();
|
|
56468
|
+
const middle = (left + right) / 2;
|
|
56469
|
+
return [
|
|
56470
|
+
roundedConnectionPath(points),
|
|
56471
|
+
vertical ? laneY : middle,
|
|
56472
|
+
vertical ? middle : laneY
|
|
56473
|
+
];
|
|
56474
|
+
}
|
|
56475
|
+
function roundedConnectionPath(input) {
|
|
56476
|
+
const points = input.filter((point, index) => index === 0 || point.x !== input[index - 1].x || point.y !== input[index - 1].y);
|
|
55833
56477
|
const radius = 16;
|
|
55834
56478
|
let path = `M ${points[0].x} ${points[0].y}`;
|
|
55835
56479
|
for (let i = 1; i < points.length - 1; i++) {
|
|
@@ -55843,12 +56487,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
55843
56487
|
path += ` Q ${corner.x} ${corner.y} ${corner.x + (next.x - corner.x) * r / after} ${corner.y + (next.y - corner.y) * r / after}`;
|
|
55844
56488
|
}
|
|
55845
56489
|
const end = points.at(-1);
|
|
55846
|
-
|
|
55847
|
-
return [
|
|
55848
|
-
`${path} L ${end.x} ${end.y}`,
|
|
55849
|
-
vertical ? laneY : middle,
|
|
55850
|
-
vertical ? middle : laneY
|
|
55851
|
-
];
|
|
56490
|
+
return `${path} L ${end.x} ${end.y}`;
|
|
55852
56491
|
}
|
|
55853
56492
|
//#endregion
|
|
55854
56493
|
//#region src/canvas/browser/graph/Edges/EdgeGradient.tsx
|
|
@@ -55877,12 +56516,14 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
55877
56516
|
const error = useVal(edgeStore?.$.error);
|
|
55878
56517
|
const canvasStore = useCanvasStore();
|
|
55879
56518
|
const scale = useVal(canvasStore.$.scale);
|
|
56519
|
+
const routes = useVal(canvasStore.connectionRoutes);
|
|
55880
56520
|
const gap = 3;
|
|
55881
56521
|
const targetX = props.targetX + (props.targetPosition == Position$1.Left ? -3 : props.targetPosition == Position$1.Right ? gap : 0);
|
|
55882
56522
|
const targetY = props.targetY + (props.targetPosition == Position$1.Top ? -3 : props.targetPosition == Position$1.Bottom ? gap : 0);
|
|
55883
56523
|
const sourceNode = useInternalNode(props.source);
|
|
55884
56524
|
const targetNode = useInternalNode(props.target);
|
|
55885
56525
|
const [path, labelX, labelY] = getConnectionPath({
|
|
56526
|
+
waypoints: routes.get(props.id),
|
|
55886
56527
|
sourceBounds: connectionNodeBounds(sourceNode),
|
|
55887
56528
|
targetBounds: connectionNodeBounds(targetNode),
|
|
55888
56529
|
sourceX: props.sourceX,
|
|
@@ -60827,7 +61468,7 @@ var OpenFlowRenderer = (function(exports) {
|
|
|
60827
61468
|
}
|
|
60828
61469
|
function DataRender(props) {
|
|
60829
61470
|
const value = props.value;
|
|
60830
|
-
if (isArray$
|
|
61471
|
+
if (isArray$2(value)) return /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)(JsonArray, { ...props });
|
|
60831
61472
|
if (isPlainObject$3(value) && !isDate(value)) return /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)(JsonObject, { ...props });
|
|
60832
61473
|
return /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)(JsonPrimitiveValue, { ...props });
|
|
60833
61474
|
}
|
|
@@ -249336,7 +249977,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249336
249977
|
//#endregion
|
|
249337
249978
|
//#region src/canvas/browser/graph/FlowCanvas/FlowCanvas.tsx
|
|
249338
249979
|
init_use_value_enhancer();
|
|
249339
|
-
var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onSelectionStart, onSelectionEnd, onInspectSelection, inspectorOpen = false, onRequestAddNode, cornerTools, cornerLeading, topLeftTools, bottomRightTools, toolbar, dark, dottedBackground, fitView, nodesDraggable, layoutMotion, className, addNodeRequest, addItemRequest, onMove, onMoveEnd, onNodeDragStop, onSelectionChange, isValidConnection, onDropAddItem }) => {
|
|
249980
|
+
var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onSelectionStart, onSelectionEnd, onInspectSelection, inspectorOpen = false, onRequestAddNode, cornerTools, cornerLeading, topLeftTools, bottomRightTools, toolbar, dark, dottedBackground, fitView, nodesDraggable, layoutMotion, className, addNodeRequest, addItemRequest, onInit, onMove, onMoveEnd, onNodeDragStop, onSelectionChange, isValidConnection, onDropAddItem }) => {
|
|
249340
249981
|
const editable = useVal(flowCanvasStore.$.editable);
|
|
249341
249982
|
const direction = useVal(flowCanvasStore.$.direction);
|
|
249342
249983
|
const changingDirection = useVal(flowCanvasStore.$.changingDirection);
|
|
@@ -249400,7 +250041,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249400
250041
|
onRelayout: editable ? flowCanvasStore.onRelayout : void 0,
|
|
249401
250042
|
onLayoutMeasured: flowCanvasStore.completeLayout,
|
|
249402
250043
|
onInstance: flowCanvasStore.rfCommand.onRFInstance,
|
|
249403
|
-
onInit:
|
|
250044
|
+
onInit: (instance) => {
|
|
250045
|
+
flowCanvasStore.onInit();
|
|
250046
|
+
onInit?.(instance);
|
|
250047
|
+
},
|
|
249404
250048
|
onCopy: flowCanvasStore.onCopy,
|
|
249405
250049
|
onPaste: flowCanvasStore.onPaste,
|
|
249406
250050
|
waitNode: flowCanvasStore.waitNode,
|
|
@@ -249518,10 +250162,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249518
250162
|
if (performance.now() > deadline) throw new Error("Timed out preparing workflow images.");
|
|
249519
250163
|
}
|
|
249520
250164
|
}
|
|
249521
|
-
async function renderPng(dataUrl, width, height, background, frame) {
|
|
250165
|
+
async function renderPng(dataUrl, width, height, background, frame, aspectRatio) {
|
|
249522
250166
|
const ratio = Math.min(2, maximumDimension / width, maximumDimension / height, Math.sqrt(maximumPixels / (width * height)));
|
|
249523
|
-
|
|
249524
|
-
|
|
250167
|
+
const dimensions = (scale) => {
|
|
250168
|
+
if (aspectRatio) {
|
|
250169
|
+
const units = Math.max(1, Math.floor(Math.min(width * scale / aspectRatio[0], height * scale / aspectRatio[1])));
|
|
250170
|
+
return {
|
|
250171
|
+
width: units * aspectRatio[0],
|
|
250172
|
+
height: units * aspectRatio[1]
|
|
250173
|
+
};
|
|
250174
|
+
}
|
|
250175
|
+
return {
|
|
250176
|
+
width: Math.max(1, Math.floor(width * scale)),
|
|
250177
|
+
height: Math.max(1, Math.floor(height * scale))
|
|
250178
|
+
};
|
|
250179
|
+
};
|
|
250180
|
+
let output = dimensions(ratio);
|
|
249525
250181
|
const image = new Image();
|
|
249526
250182
|
const logo = frame ? new Image() : void 0;
|
|
249527
250183
|
image.decoding = "async";
|
|
@@ -249535,28 +250191,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249535
250191
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
249536
250192
|
const canvas = document.createElement("canvas");
|
|
249537
250193
|
try {
|
|
249538
|
-
canvas.width =
|
|
249539
|
-
canvas.height =
|
|
249540
|
-
const context = canvas.getContext("2d", { alpha:
|
|
250194
|
+
canvas.width = output.width;
|
|
250195
|
+
canvas.height = output.height;
|
|
250196
|
+
const context = canvas.getContext("2d", { alpha: !!frame });
|
|
249541
250197
|
if (!context) throw new Error("Unable to allocate the workflow image.");
|
|
249542
|
-
context.fillStyle = frame?.outerBackground ?? background;
|
|
249543
|
-
context.fillRect(0, 0, outputWidth, outputHeight);
|
|
249544
250198
|
if (frame && logo) {
|
|
249545
|
-
context.scale(
|
|
250199
|
+
context.scale(output.width / width, output.height / height);
|
|
249546
250200
|
drawFrame(context, image, logo, width, height, background, frame);
|
|
249547
|
-
} else
|
|
250201
|
+
} else {
|
|
250202
|
+
context.fillStyle = background;
|
|
250203
|
+
context.fillRect(0, 0, output.width, output.height);
|
|
250204
|
+
context.drawImage(image, 0, 0, output.width, output.height);
|
|
250205
|
+
}
|
|
249548
250206
|
if (context.isContextLost?.()) throw new Error("The workflow image context was lost.");
|
|
249549
250207
|
const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
|
|
249550
250208
|
if (!blob || context.isContextLost?.()) throw new Error("Unable to encode the workflow image.");
|
|
249551
250209
|
return {
|
|
249552
250210
|
blob,
|
|
249553
|
-
|
|
249554
|
-
height: outputHeight
|
|
250211
|
+
...output
|
|
249555
250212
|
};
|
|
249556
250213
|
} catch (error) {
|
|
249557
|
-
if (attempt === 2 ||
|
|
249558
|
-
|
|
249559
|
-
outputHeight = Math.max(1, Math.floor(outputHeight / 2));
|
|
250214
|
+
if (attempt === 2 || output.width === 1 && output.height === 1) throw error;
|
|
250215
|
+
output = dimensions(ratio / 2 ** (attempt + 1));
|
|
249560
250216
|
} finally {
|
|
249561
250217
|
canvas.width = canvas.height = 0;
|
|
249562
250218
|
}
|
|
@@ -249568,7 +250224,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249568
250224
|
}
|
|
249569
250225
|
}
|
|
249570
250226
|
/** Render the real canvas at full detail without moving or changing the user's canvas. */
|
|
249571
|
-
async function captureFlowImage(model, language, options) {
|
|
250227
|
+
async function captureFlowImage(model, language, options, aspectRatio) {
|
|
249572
250228
|
const contentPadding = options.frame ? padding / 2 : padding;
|
|
249573
250229
|
const positions = model.nodes.map((node) => node.position);
|
|
249574
250230
|
const minX = Math.min(0, ...positions.map((position) => position.x));
|
|
@@ -249595,6 +250251,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249595
250251
|
host.setAttribute("aria-hidden", "true");
|
|
249596
250252
|
document.body.append(host);
|
|
249597
250253
|
const root = (0, import_client.createRoot)(host);
|
|
250254
|
+
let instance;
|
|
249598
250255
|
const store = new CanvasStore(snapshot, false, language, {
|
|
249599
250256
|
onMoveNodes: () => {},
|
|
249600
250257
|
onChangeComment: () => {}
|
|
@@ -249606,12 +250263,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249606
250263
|
dark: options.dark ?? false,
|
|
249607
250264
|
fitView: false,
|
|
249608
250265
|
layoutMotion: false,
|
|
249609
|
-
nodesDraggable: false
|
|
250266
|
+
nodesDraggable: false,
|
|
250267
|
+
onInit: (value) => {
|
|
250268
|
+
instance = value;
|
|
250269
|
+
}
|
|
249610
250270
|
}))));
|
|
249611
250271
|
const deadline = performance.now() + 15e3;
|
|
249612
250272
|
await waitFor(() => store.$.initialized.value && store.$.rfNodes.value.every((node) => !!node.measured?.width && !!node.measured.height), deadline);
|
|
249613
250273
|
let hasImagePlaceholders = await prepareImages(host, deadline);
|
|
249614
250274
|
await waitFor(() => document.fonts.status === "loaded", deadline);
|
|
250275
|
+
if (options.layout === "compact" && store.$.direction.value === "vertical") {
|
|
250276
|
+
await nextFrame();
|
|
250277
|
+
await nextFrame();
|
|
250278
|
+
const bounds = store.compactForExport({
|
|
250279
|
+
width: contentPadding * 2 + (options.frame ? 40 : 0),
|
|
250280
|
+
height: contentPadding * 2 + (options.frame ? 72 : 0)
|
|
250281
|
+
}, instance, aspectRatio ? aspectRatio[0] / aspectRatio[1] : 1);
|
|
250282
|
+
host.style.width = Math.ceil(bounds.width + contentPadding * 2 + 1e3) + "px";
|
|
250283
|
+
host.style.height = Math.ceil(bounds.height + contentPadding * 2 + 1e3) + "px";
|
|
250284
|
+
store.$$.viewport.set({
|
|
250285
|
+
x: contentPadding - bounds.x,
|
|
250286
|
+
y: contentPadding - bounds.y,
|
|
250287
|
+
zoom: 1
|
|
250288
|
+
});
|
|
250289
|
+
await nextFrame();
|
|
250290
|
+
await nextFrame();
|
|
250291
|
+
hasImagePlaceholders = await prepareImages(host, deadline) || hasImagePlaceholders;
|
|
250292
|
+
await waitFor(() => document.fonts.status === "loaded", deadline);
|
|
250293
|
+
}
|
|
249615
250294
|
const viewport = host.querySelector(".react-flow__viewport");
|
|
249616
250295
|
const origin = viewport.getBoundingClientRect();
|
|
249617
250296
|
const bounds = [...viewport.querySelectorAll(".react-flow__node, [data-canvas-bounds]")].map((node) => {
|
|
@@ -249628,8 +250307,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249628
250307
|
const top = bounds.length ? Math.min(...bounds.map((rect) => rect.y)) : 0;
|
|
249629
250308
|
const right = bounds.length ? Math.max(...bounds.map((rect) => rect.x + rect.width)) : 320;
|
|
249630
250309
|
const bottom = bounds.length ? Math.max(...bounds.map((rect) => rect.y + rect.height)) : 120;
|
|
249631
|
-
const
|
|
249632
|
-
const
|
|
250310
|
+
const naturalWidth = Math.ceil(right - left + contentPadding * 2);
|
|
250311
|
+
const naturalHeight = Math.ceil(bottom - top + contentPadding * 2);
|
|
250312
|
+
const frameWidth = options.frame ? 40 : 0;
|
|
250313
|
+
const frameHeight = options.frame ? 72 : 0;
|
|
250314
|
+
const units = aspectRatio ? Math.ceil(Math.max((naturalWidth + frameWidth) / aspectRatio[0], (naturalHeight + frameHeight) / aspectRatio[1])) : 0;
|
|
250315
|
+
const width = aspectRatio ? units * aspectRatio[0] - frameWidth : naturalWidth;
|
|
250316
|
+
const height = aspectRatio ? units * aspectRatio[1] - frameHeight : naturalHeight;
|
|
249633
250317
|
const background = getComputedStyle(host.querySelector(".react-flow")).backgroundColor;
|
|
249634
250318
|
const dataUrl = await toSvg(viewport, {
|
|
249635
250319
|
width,
|
|
@@ -249637,8 +250321,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249637
250321
|
imagePlaceholder,
|
|
249638
250322
|
preferredFontFormat: "woff2",
|
|
249639
250323
|
includeQueryParams: true,
|
|
250324
|
+
includeStyleProperties: captureStyleProperties(viewport),
|
|
250325
|
+
filter: (node) => {
|
|
250326
|
+
if (!(node instanceof HTMLElement)) return true;
|
|
250327
|
+
const style = getComputedStyle(node);
|
|
250328
|
+
return style.display !== "none" && style.opacity !== "0";
|
|
250329
|
+
},
|
|
249640
250330
|
style: {
|
|
249641
|
-
transform: `translate(${contentPadding - left}px, ${contentPadding - top}px)`,
|
|
250331
|
+
transform: `translate(${contentPadding + (width - naturalWidth) / 2 - left}px, ${contentPadding + (height - naturalHeight) / 2 - top}px)`,
|
|
249642
250332
|
transformOrigin: "0 0"
|
|
249643
250333
|
}
|
|
249644
250334
|
});
|
|
@@ -249655,13 +250345,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249655
250345
|
});
|
|
249656
250346
|
host.append(palette);
|
|
249657
250347
|
const style = getComputedStyle(palette);
|
|
249658
|
-
const outerBackground = style.backgroundColor;
|
|
249659
250348
|
if (options.dark) palette.style.backgroundColor = "var(--ui-card)";
|
|
249660
250349
|
frame = {
|
|
249661
250350
|
title: options.title ?? "",
|
|
249662
250351
|
logo: openFlowLogoSource(options.dark ? "dark" : "light"),
|
|
249663
250352
|
background: getComputedStyle(palette).backgroundColor,
|
|
249664
|
-
outerBackground,
|
|
249665
250353
|
foreground: style.color,
|
|
249666
250354
|
border: style.borderColor,
|
|
249667
250355
|
fontFamily: getComputedStyle(viewport).fontFamily || "sans-serif"
|
|
@@ -249669,8 +250357,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249669
250357
|
}
|
|
249670
250358
|
return {
|
|
249671
250359
|
dataUrl,
|
|
249672
|
-
width: width +
|
|
249673
|
-
height: height +
|
|
250360
|
+
width: width + frameWidth,
|
|
250361
|
+
height: height + frameHeight,
|
|
249674
250362
|
background,
|
|
249675
250363
|
frame,
|
|
249676
250364
|
hasImagePlaceholders
|
|
@@ -249682,9 +250370,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
249682
250370
|
}
|
|
249683
250371
|
}
|
|
249684
250372
|
async function flowToPng(model, language = "en", options = {}) {
|
|
249685
|
-
const
|
|
250373
|
+
const aspectRatio = getFlowPngAspectRatio(options.aspectRatio);
|
|
250374
|
+
const { dataUrl, width, height, background, frame, hasImagePlaceholders } = await captureFlowImage(model, language, options, aspectRatio);
|
|
249686
250375
|
return {
|
|
249687
|
-
...await renderPng(dataUrl, width, height, background, frame),
|
|
250376
|
+
...await renderPng(dataUrl, width, height, background, frame, aspectRatio),
|
|
249688
250377
|
hasImagePlaceholders
|
|
249689
250378
|
};
|
|
249690
250379
|
}
|
|
@@ -250630,14 +251319,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
250630
251319
|
"exportFlow": "Export workflow",
|
|
250631
251320
|
"exportPng": "Export PNG image",
|
|
250632
251321
|
"exportPngFrame": "Show frame",
|
|
251322
|
+
"exportPngCompact": "Compact layout",
|
|
250633
251323
|
"exportPngLight": "Light",
|
|
250634
251324
|
"exportPngDark": "Dark",
|
|
250635
|
-
"exportPngPending": "Exporting PNG…",
|
|
250636
|
-
"exportPngPendingDescription": "Preparing the workflow and image resources. Large images may take a little longer.",
|
|
250637
251325
|
"exportPngComplete": "PNG image exported.",
|
|
250638
251326
|
"exportPngPartial": "PNG image exported. Some images were replaced with placeholders.",
|
|
250639
251327
|
"exportPngFailed": "Could not export the PNG image. Please try again.",
|
|
250640
|
-
"importInvalid": "Invalid or unsupported workflow file."
|
|
251328
|
+
"importInvalid": "Invalid or unsupported workflow file.",
|
|
251329
|
+
"exportPngAspectRatio": "Canvas ratio",
|
|
251330
|
+
"exportPngAuto": "Auto",
|
|
251331
|
+
"exportPngLayout": "Layout",
|
|
251332
|
+
"exportPngOriginal": "Original",
|
|
251333
|
+
"exportPngTheme": "Theme",
|
|
251334
|
+
"exportPngPreview": "Preview",
|
|
251335
|
+
"exportPngPreviewPending": "Generating preview…",
|
|
251336
|
+
"exportPngPreviewFailed": "Could not generate the preview.",
|
|
251337
|
+
"exportPngPreviewPartial": "Some images could not load and were replaced with placeholders.",
|
|
251338
|
+
"exportPngDownload": "Download PNG",
|
|
251339
|
+
"exportPngPreviewRetry": "Retry"
|
|
250641
251340
|
},
|
|
250642
251341
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Node outline\",\"backToOutline\":\"Back to node outline\",\"emptyOutline\":\"No nodes yet\",\"triggers\":\"Triggers\",\"nodes\":\"Nodes\",\"multipleSelected\":\"{{count}} nodes selected\",\"account\":{\"contactAdmin\":\"You do not have permission to perform this operation. Contact an administrator.\",\"accessTitle\":\"Access permissions\",\"manageFlowAccess\":\"Connections available to Code\",\"configureAccess\":\"Choose an account\",\"manageAccount\":\"Manage accounts\",\"required\":\"Account connection required\",\"addAccount\":\"Add account\",\"manage\":\"Manage\",\"authorizationPending\":\"Finish authorization in the Connection page, then return here to refresh this account.\",\"chooseAccount\":\"Choose an account\",\"deferred\":\"Not configured for now\",\"clearDeferred\":\"Clear selection\",\"noAccounts\":\"No accounts available\",\"connectBeforeRun\":\"Connect {{service}} before this block can run or be published.\",\"connectService\":\"Connect {{service}}\",\"connection\":\"Connection\",\"loading\":\"Loading connections…\",\"oomolBuiltIn\":\"OOMOL Built-in\",\"missing\":\"The account selected for this node is unavailable. Choose another account or manage connections.\",\"refreshFailed\":\"Connections could not be refreshed.\",\"retry\":\"Retry\",\"status\":{\"disconnected\":\"This Connection is disconnected. Reconnect it or choose another account.\",\"error\":\"This Connection has an error. Repair it or choose another account.\",\"reauth_required\":\"This Connection needs authorization again. Reconnect it or choose another account.\"},\"statusUnavailable\":\"Connection status is unavailable for {{action}}.\",\"teamDefault\":\"Team default\",\"title\":\"Account\",\"unavailable\":\"unavailable\"},\"close\":\"Close inspector\",\"configurationRequired\":\"Configuration required\",\"diagnostics\":\"Diagnostics\",\"errors\":{\"jsonObject\":\"{{label}} must be a JSON object.\",\"portDefinitions\":\"Enter valid port definitions.\"},\"node\":{\"nameDuplicate\":\"A node with this name already exists in this graph.\",\"nameEmpty\":\"Node name cannot be empty.\",\"timeout\":\"Timeout (ms)\",\"maxExecutions\":\"Node execution limit\",\"maxExecutionsError\":\"Node execution limit must be a positive integer.\",\"timeoutError\":\"Timeout must be a positive integer in milliseconds.\",\"title\":\"Node settings\",\"description\":\"Purpose\",\"describe\":\"Describe what this step does.\",\"icon\":\"Icon\",\"name\":\"Title\",\"retry\":\"Retry on error\",\"retryCount\":\"Up to {{count}} retries\",\"retryInterval\":\"Retry interval\",\"retryError\":\"Use an interval of 1–60 whole seconds.\",\"retryHint\":\"The retry count is the number of additional attempts after the first execution. Retries repeat the entire node and may repeat external operations. The timeout includes all attempts and intervals.\",\"retryNone\":\"No retries\",\"retrySeconds\":\"seconds\",\"retryHelp\":\"About retries\",\"retryOnce\":\"Retry once\",\"onError\":\"On failure\",\"onErrorStop\":\"Stop workflow\",\"onErrorOutput\":\"Output to error port\",\"onErrorHelp\":\"About failure handling\",\"onErrorHint\":\"After retries fail, write the error to the system error output and continue along existing connections. On success, error is null. Cancellation, timeouts, resource limits and indeterminate outcomes still stop execution.\",\"systemOutputs\":\"System outputs\",\"systemError\":\"Error information (system)\",\"errorFields\":{\"error\":\"Error information when the node fails; null on success.\",\"code\":\"A code identifying the type of error.\",\"message\":\"A description of the error, with sensitive content redacted.\",\"nodeId\":\"The ID of the node that failed.\",\"nodeName\":\"The node name at the time of failure.\",\"runId\":\"The ID of this workflow run.\",\"executionId\":\"The ID of this node execution, shared across its retry attempts.\"}},\"selectNode\":\"Select one Draft node to inspect and edit it.\",\"locateNode\":\"Locate this node on the canvas\",\"task\":{\"sharedPermissions\":\"Use Flow shared permission group\",\"sharedPermissionsHint\":\"Use all Actions authorized by the Flow permission group. No need to add them to this node.\",\"httpHosts\":\"HTTP hosts\",\"httpHostsHint\":\"One host per line. *.example.com includes subdomains.\",\"httpHostsInvalid\":\"\\\"{{host}}\\\" is not a valid host. Use a host name such as api.example.com.\",\"httpHostsLimit\":\"Declare at most {{count}} hosts.\",\"addAction\":\"Add Action\",\"removeAction\":\"Remove Action\",\"actionAccount\":\"Account\",\"chooseAccount\":\"Choose an account\",\"permissionSaveFailed\":\"Could not save Code permissions. Retry the change.\",\"chatText\":\"Chat text\",\"connectorAction\":\"Connector action\",\"definition\":\"Task definition\",\"discardCode\":\"Discard changes\",\"editorLoading\":\"Loading editor…\",\"editorUnavailable\":\"The code editor couldn’t be loaded.\",\"inputPorts\":\"Input ports\",\"javascriptModule\":\"Code\",\"missing\":\"The referenced Task does not exist.\",\"outputPorts\":\"Output ports\",\"responseMode\":\"Response mode\",\"source\":\"Source\",\"structuredJson\":\"Structured JSON\",\"retrySave\":\"Retry save\",\"additionalInputs\":\"Additional inputs\",\"httpHostsUpdated\":\"Hosts changed elsewhere. The latest configuration is loaded; review it before saving.\"},\"wait\":{\"approval\":\"Approve or reject\",\"changeNotification\":\"Change\",\"continue\":\"Continue\",\"mode\":\"Resolution\",\"inputsLoading\":\"Loading notification parameters…\",\"pendingDescription\":\"The pending output fires once when waiting begins and provides confirmation links and related data. Connect it to send a message or run other steps.\",\"prompt\":\"Prompt\",\"promptError\":\"Prompt must contain 1 to 1,000 characters.\",\"autoContinue\":\"Automatic continuation\",\"autoOff\":\"Off\",\"autoAfter\":\"After a duration\",\"autoAt\":\"At a specific time\",\"autoSeconds\":\"Duration (seconds)\",\"autoDate\":\"Date and time\",\"autoInvalid\":\"Enter a positive duration or a valid date and time.\",\"autoDescription\":\"You can continue manually before the scheduled time.\"},\"title\":\"Inspector\",\"sources\":{\"loading\":\"Loading input sources…\",\"loadFailed\":\"Could not load input sources. Reopen the menu to retry.\",\"checkFailed\":\"Could not check this source.\",\"select\":\"Select input source\",\"title\":\"Input source\",\"sourceMissing\":\"The original input source no longer exists. Choose again.\",\"outputMissing\":\"“{{output}}” could not be found in “{{source}}”. Choose again.\",\"wholeObject\":\"Whole object\",\"fieldMissing\":\"Field {{field}} is no longer declared in “{{output}}”. Choose again.\",\"notReady\":\"“{{source}} {{handle}}” may not have a value when this step runs.\",\"sourceConflict\":\"These fields may have values at the same time: {{sources}}. Only one can be used here.\",\"incompatibleRight\":\"The right value type is incompatible with this comparison.\",\"incompatible\":\"Mismatch\",\"unverified\":\"Unverified\",\"schemaIncompatible\":\"The data format does not match.\",\"schemaPathIncompatible\":\"The data format of “{{path}}” does not match.\",\"schemaCompareFailed\":\"Could not check the data format. Check the JSON Schema.\",\"binaryIncompatible\":\"Binary data cannot be used here.\",\"artifactIncompatible\":\"File data cannot be used here.\",\"nullableIncompatible\":\"A value is required, but the selected field may be empty.\",\"typeIncompatible\":\"Expected {{target}}, but the selected field is {{source}}.\",\"propertyTypeIncompatible\":\"“{{path}}” must be {{target}}, but it is {{source}}.\",\"requiredIncompatible\":\"The required property “{{property}}” may be missing.\",\"enumIncompatible\":\"Some possible values are not accepted: {{values}}.\",\"constIncompatible\":\"Only {{target}} is accepted, but the selected field is always {{source}}.\",\"constraintSubject\":\"“{{path}}” \",\"minLength\":\"{{subject}}must contain at least {{value}} characters.\",\"maxLength\":\"{{subject}}must contain at most {{value}} characters.\",\"pattern\":\"{{subject}}must match {{value}}.\",\"minimum\":\"{{subject}}cannot be less than {{value}}.\",\"exclusiveMinimum\":\"{{subject}}must be greater than {{value}}.\",\"maximum\":\"{{subject}}cannot be greater than {{value}}.\",\"exclusiveMaximum\":\"{{subject}}must be less than {{value}}.\",\"multipleOf\":\"{{subject}}must be a multiple of {{value}}.\",\"minItems\":\"{{subject}}must contain at least {{value}} items.\",\"maxItems\":\"{{subject}}must contain at most {{value}} items.\",\"minProperties\":\"{{subject}}must contain at least {{value}} properties.\",\"maxProperties\":\"{{subject}}must contain at most {{value}} properties.\",\"integer\":\"Integer\",\"unknownType\":\"unknown type\",\"typeSeparator\":\" or \"},\"actions\":{\"flowAccess\":\"Available services\",\"flowAccessHint\":\"Manage connections shared by all Code nodes in this Flow\",\"chooseConnection\":\"Choose a {{provider}} connection\",\"connectionDescription\":\"The connection is inserted into this call. Flow provider access still controls whether it may be used.\",\"title\":\"Actions available to this code\",\"search\":\"Search actions\",\"description\":\"Choose the actions and accounts this code can use.\",\"empty\":\"No matching actions.\",\"remove\":\"Remove\",\"default\":\"Default account\",\"defaultHint\":\"Used when the call does not specify an account.\",\"removeAction\":\"Remove action\",\"explicit\":\"Choose explicitly in code\",\"connect\":\"Connect account\",\"refresh\":\"Refresh accounts\",\"aliases\":\"Update saved aliases\",\"add\":\"Add action\",\"cancel\":\"Cancel\",\"loading\":\"Searching…\",\"needsAccount\":\"Connect an account\",\"accounts\":\"{{count}} accounts\",\"public\":\"No account needed\",\"allowed\":\"Allowed accounts\",\"unavailable\":\"Unavailable\",\"details\":\"Connection details\",\"example\":\"Call example\",\"syntax\":\"Call syntax\",\"nested\":\"Provider method\",\"fullId\":\"Full ID\",\"copy\":\"Copy\",\"copied\":\"Copied\",\"copyError\":\"Copy failed. Select the code and copy it manually.\",\"introDescription\":\"Add actions as needed to call external apps through {{context}}.\",\"insertAction\":\"Insert code\",\"chooseAccounts\":\"Manage accounts\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Preview\"},\"ports\":{\"reorder\":\"Reorder {{name}}\",\"reorderHint\":\"Drag to reorder within the group, or use Up / Down while focused.\",\"moved\":\"{{name}} moved to position {{position}}.\",\"groupSettings\":\"Group settings\",\"connected\":\"Connected\",\"sort\":\"Sort\",\"finishSorting\":\"Done sorting\",\"inputsTitle\":\"Inputs\",\"requiredInputs\":\"Required\",\"optionalInputs\":\"Optional\",\"noInputs\":\"This node does not require input data.\",\"noOutputs\":\"This node does not provide output data.\",\"outputsTitle\":\"Outputs\",\"valuesTitle\":\"Values\",\"columnHandle\":\"Handle\",\"columnName\":\"Name\",\"columnType\":\"Type\",\"columnValue\":\"Value\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"The scheduled time that triggered this run, in ISO 8601 format.\"},\"webhook\":{\"headers\":\"The headers received with this Webhook request.\",\"query\":\"The URL query parameters received with this Webhook request.\",\"body\":\"The body received with this Webhook request.\",\"webhookUrl\":\"The Webhook URL that received this request, without query parameters.\"}},\"startParametersTitle\":\"Start parameters\"}}"),
|
|
250643
251342
|
language: { "label": "Language" },
|
|
@@ -252010,14 +252709,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
252010
252709
|
"exportFlow": "导出工作流",
|
|
252011
252710
|
"exportPng": "导出 PNG 图片",
|
|
252012
252711
|
"exportPngFrame": "显示外框",
|
|
252712
|
+
"exportPngCompact": "紧凑布局",
|
|
252013
252713
|
"exportPngLight": "浅色",
|
|
252014
252714
|
"exportPngDark": "深色",
|
|
252015
|
-
"exportPngPending": "正在导出 PNG…",
|
|
252016
|
-
"exportPngPendingDescription": "正在处理工作流和图片资源,图片较大时可能需要一些时间。",
|
|
252017
252715
|
"exportPngComplete": "PNG 图片已导出。",
|
|
252018
252716
|
"exportPngPartial": "PNG 图片已导出,部分图片已用占位图替代。",
|
|
252019
252717
|
"exportPngFailed": "PNG 图片导出失败,请重试。",
|
|
252020
|
-
"importInvalid": "文件损坏或工作流格式不受支持。"
|
|
252718
|
+
"importInvalid": "文件损坏或工作流格式不受支持。",
|
|
252719
|
+
"exportPngAspectRatio": "画布比例",
|
|
252720
|
+
"exportPngAuto": "自动",
|
|
252721
|
+
"exportPngLayout": "布局",
|
|
252722
|
+
"exportPngOriginal": "原布局",
|
|
252723
|
+
"exportPngTheme": "主题",
|
|
252724
|
+
"exportPngPreview": "预览",
|
|
252725
|
+
"exportPngPreviewPending": "正在生成预览…",
|
|
252726
|
+
"exportPngPreviewFailed": "预览生成失败,请重试。",
|
|
252727
|
+
"exportPngPreviewPartial": "部分图片加载失败,已使用占位图。",
|
|
252728
|
+
"exportPngDownload": "下载 PNG",
|
|
252729
|
+
"exportPngPreviewRetry": "重试"
|
|
252021
252730
|
},
|
|
252022
252731
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"节点大纲\",\"backToOutline\":\"返回节点大纲\",\"emptyOutline\":\"暂无节点\",\"triggers\":\"触发器\",\"nodes\":\"节点\",\"multipleSelected\":\"已选择 {{count}} 个节点\",\"account\":{\"contactAdmin\":\"你没有执行此操作的权限,请联系管理员。\",\"accessTitle\":\"访问权限\",\"manageFlowAccess\":\"Code 允许使用的连接\",\"configureAccess\":\"选择可用账号\",\"manageAccount\":\"管理账号\",\"required\":\"待连接账号\",\"addAccount\":\"添加账号\",\"manage\":\"管理\",\"authorizationPending\":\"请在 Connection 页面完成授权,返回这里后会刷新当前账号。\",\"chooseAccount\":\"选择账号\",\"deferred\":\"暂不设置\",\"clearDeferred\":\"清除选择\",\"noAccounts\":\"暂无可用账号\",\"connectBeforeRun\":\"请先连接 {{service}},此节点才能运行或发布。\",\"connectService\":\"连接 {{service}}\",\"connection\":\"连接\",\"loading\":\"正在加载连接…\",\"oomolBuiltIn\":\"OOMOL 内置账号\",\"missing\":\"此节点选择的账号当前不可用,请选择其他账号或管理账号。\",\"refreshFailed\":\"无法刷新 Connection。\",\"retry\":\"重试\",\"status\":{\"disconnected\":\"此 Connection 已断开,请重新连接或选择其他账号。\",\"error\":\"此 Connection 状态异常,请修复后重试或选择其他账号。\",\"reauth_required\":\"此 Connection 需要重新授权,请重新连接或选择其他账号。\"},\"statusUnavailable\":\"暂时无法获取 {{action}} 的连接状态。\",\"teamDefault\":\"团队默认\",\"title\":\"账号\",\"unavailable\":\"不可用\"},\"close\":\"关闭检查器\",\"configurationRequired\":\"配置待完成\",\"diagnostics\":\"诊断\",\"errors\":{\"jsonObject\":\"{{label}} 必须是 JSON 对象。\",\"portDefinitions\":\"请输入有效的端口定义。\"},\"node\":{\"nameDuplicate\":\"当前图中已存在同名节点。\",\"nameEmpty\":\"节点名称不能为空。\",\"timeout\":\"超时时间(毫秒)\",\"maxExecutions\":\"节点执行上限\",\"maxExecutionsError\":\"节点执行上限必须是正整数。\",\"timeoutError\":\"超时时间必须是以毫秒为单位的正整数。\",\"title\":\"节点设置\",\"description\":\"用途说明\",\"describe\":\"描述这一步要完成什么。\",\"icon\":\"图标\",\"name\":\"标题\",\"retry\":\"失败重试\",\"retryCount\":\"最多重试 {{count}} 次\",\"retryInterval\":\"重试间隔\",\"retryError\":\"间隔须为 1~60 整数秒。\",\"retryHint\":\"重试次数是首次执行失败后的追加次数。重试会重新执行整个节点,可能重复外部操作。超时包含全部尝试和等待间隔。\",\"retryNone\":\"不重试\",\"retrySeconds\":\"秒\",\"retryHelp\":\"重试说明\",\"retryOnce\":\"最多重试 1 次\",\"onError\":\"失败处理\",\"onErrorStop\":\"终止工作流\",\"onErrorOutput\":\"输出到 error 端口\",\"onErrorHelp\":\"失败处理说明\",\"onErrorHint\":\"重试后仍失败时,将错误写入系统 error 并沿现有连线继续。成功时 error 为 null。取消、超时、资源限制和结果不确定仍终止工作流。\",\"systemOutputs\":\"系统输出\",\"systemError\":\"错误信息(系统)\",\"errorFields\":{\"error\":\"节点失败时的错误信息;成功时为 null。\",\"code\":\"用于识别错误类型的错误码。\",\"message\":\"错误的说明信息,敏感内容已脱敏。\",\"nodeId\":\"发生错误的节点 ID。\",\"nodeName\":\"发生错误时的节点名称。\",\"runId\":\"本次工作流运行的 ID。\",\"executionId\":\"本次节点执行的 ID,多次重试共用此 ID。\"}},\"selectNode\":\"选择一个草稿节点以查看和编辑。\",\"locateNode\":\"在画布上定位该节点\",\"task\":{\"sharedPermissions\":\"使用 Flow 共享权限组\",\"sharedPermissionsHint\":\"直接使用 Flow 共享权限组已授权的全部 Actions,无需逐个添加。\",\"httpHosts\":\"HTTP 主机\",\"httpHostsHint\":\"每行一个主机,支持 *.example.com 子域名匹配。\",\"httpHostsInvalid\":\"“{{host}}”不是有效的主机,请填写 api.example.com 这样的主机名。\",\"httpHostsLimit\":\"最多声明 {{count}} 个主机。\",\"addAction\":\"添加 Action\",\"removeAction\":\"移除 Action\",\"actionAccount\":\"账号\",\"chooseAccount\":\"选择账号\",\"permissionSaveFailed\":\"无法保存 Code 权限,请重试。\",\"chatText\":\"对话文本\",\"connectorAction\":\"连接器操作\",\"definition\":\"任务定义\",\"discardCode\":\"放弃修改\",\"editorLoading\":\"正在加载编辑器…\",\"editorUnavailable\":\"代码编辑器加载失败。\",\"inputPorts\":\"输入端口\",\"javascriptModule\":\"代码\",\"missing\":\"引用的任务不存在。\",\"outputPorts\":\"输出端口\",\"responseMode\":\"响应模式\",\"source\":\"源代码\",\"structuredJson\":\"结构化 JSON\",\"retrySave\":\"重试保存\",\"additionalInputs\":\"附加输入\",\"httpHostsUpdated\":\"主机配置已在别处更新。已加载最新配置,请检查后再保存。\"},\"wait\":{\"approval\":\"通过或拒绝\",\"changeNotification\":\"更换\",\"continue\":\"继续\",\"mode\":\"处理方式\",\"inputsLoading\":\"正在加载通知参数…\",\"pendingDescription\":\"待确认出口在开始等待时触发一次,提供确认链接及相关数据。连接此出口可发送消息或执行其他步骤。\",\"prompt\":\"提示\",\"promptError\":\"提示必须包含 1 到 1,000 个字符。\",\"autoContinue\":\"自动继续\",\"autoOff\":\"关闭\",\"autoAfter\":\"等待一段时间\",\"autoAt\":\"到指定时间\",\"autoSeconds\":\"等待时长(秒)\",\"autoDate\":\"日期和时间\",\"autoInvalid\":\"请输入正数时长或有效的日期和时间。\",\"autoDescription\":\"可提前手动继续。\"},\"title\":\"检查器\",\"sources\":{\"loading\":\"正在加载输入来源…\",\"loadFailed\":\"无法加载输入来源,请重新打开菜单重试。\",\"checkFailed\":\"无法检查此来源。\",\"select\":\"选择输入来源\",\"title\":\"输入来源\",\"sourceMissing\":\"原输入来源已不存在,请重新选择。\",\"outputMissing\":\"“{{source}}”中找不到“{{output}}”,请重新选择。\",\"wholeObject\":\"整个对象\",\"fieldMissing\":\"“{{output}}”中已不再声明字段 {{field}},请重新选择。\",\"notReady\":\"运行到这里时,“{{source}} {{handle}}”可能还没有值。\",\"sourceConflict\":\"这些字段可能同时有值:{{sources}}。这里只能取一个。\",\"incompatibleRight\":\"右值类型不符合此比较的要求。\",\"incompatible\":\"不兼容\",\"unverified\":\"无法验证\",\"schemaIncompatible\":\"数据格式不匹配。\",\"schemaPathIncompatible\":\"“{{path}}”的数据格式不匹配。\",\"schemaCompareFailed\":\"无法检查数据格式,请检查 JSON Schema。\",\"binaryIncompatible\":\"不能使用二进制数据。\",\"artifactIncompatible\":\"不能使用文件数据。\",\"nullableIncompatible\":\"不能为空,但所选字段可能为空。\",\"typeIncompatible\":\"需要{{target}},但所选字段是{{source}}。\",\"propertyTypeIncompatible\":\"“{{path}}”需要{{target}},实际是{{source}}。\",\"requiredIncompatible\":\"不一定包含必填属性“{{property}}”。\",\"enumIncompatible\":\"可能出现不接受的值:{{values}}。\",\"constIncompatible\":\"只接受 {{target}},所选字段固定为 {{source}}。\",\"constraintSubject\":\"“{{path}}”\",\"minLength\":\"{{subject}}至少需要 {{value}} 个字符。\",\"maxLength\":\"{{subject}}最多接受 {{value}} 个字符。\",\"pattern\":\"{{subject}}文本格式应符合 {{value}}。\",\"minimum\":\"{{subject}}不能小于 {{value}}。\",\"exclusiveMinimum\":\"{{subject}}必须大于 {{value}}。\",\"maximum\":\"{{subject}}不能大于 {{value}}。\",\"exclusiveMaximum\":\"{{subject}}必须小于 {{value}}。\",\"multipleOf\":\"{{subject}}必须是 {{value}} 的倍数。\",\"minItems\":\"{{subject}}至少需要 {{value}} 项。\",\"maxItems\":\"{{subject}}最多接受 {{value}} 项。\",\"minProperties\":\"{{subject}}至少需要 {{value}} 个属性。\",\"maxProperties\":\"{{subject}}最多接受 {{value}} 个属性。\",\"integer\":\"整数\",\"unknownType\":\"未知类型\",\"typeSeparator\":\"或\"},\"actions\":{\"flowAccess\":\"可用服务\",\"flowAccessHint\":\"管理整个工作流的 Code 共享使用的连接\",\"chooseConnection\":\"选择 {{provider}} Connection\",\"connectionDescription\":\"Connection 将写入本次调用;是否允许使用仍由工作流 Provider Access 决定。\",\"title\":\"代码可调用的动作\",\"search\":\"搜索应用或动作…\",\"description\":\"搜索并添加这段代码需要调用的动作。\",\"empty\":\"没有匹配的 Action。\",\"remove\":\"移除\",\"default\":\"默认账号\",\"defaultHint\":\"调用时未指定账号,将使用此账号。\",\"removeAction\":\"移除动作\",\"explicit\":\"每次调用时指定\",\"connect\":\"连接账号\",\"refresh\":\"刷新账号\",\"aliases\":\"同步账号别名\",\"add\":\"添加动作\",\"cancel\":\"取消\",\"loading\":\"搜索中…\",\"needsAccount\":\"待连接账号\",\"accounts\":\"{{count}} 个账号\",\"public\":\"无需账号\",\"allowed\":\"允许使用的账号\",\"unavailable\":\"不可用\",\"details\":\"账号详情\",\"example\":\"调用示例\",\"syntax\":\"调用写法\",\"nested\":\"分层写法\",\"fullId\":\"完整 ID\",\"copy\":\"复制\",\"copied\":\"已复制\",\"copyError\":\"复制失败,请选中示例代码手动复制。\",\"introDescription\":\"按需添加动作,通过 {{context}} 调用外部应用。\",\"insertAction\":\"插入代码\",\"chooseAccounts\":\"管理账号\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"预览\"},\"ports\":{\"reorder\":\"调整 {{name}} 的顺序\",\"reorderHint\":\"拖动调整组内顺序,或聚焦后使用上、下方向键。\",\"moved\":\"{{name}} 已移至第 {{position}} 位。\",\"groupSettings\":\"分组设置\",\"connected\":\"已连接\",\"sort\":\"排序\",\"finishSorting\":\"完成排序\",\"inputsTitle\":\"输入\",\"requiredInputs\":\"必填\",\"optionalInputs\":\"选填\",\"noInputs\":\"此节点不需要输入数据\",\"noOutputs\":\"此节点不提供输出数据\",\"outputsTitle\":\"输出\",\"valuesTitle\":\"数据\",\"columnHandle\":\"Handle\",\"columnName\":\"名称\",\"columnType\":\"类型\",\"columnValue\":\"值\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"本次运行的计划触发时间,采用 ISO 8601 格式。\"},\"webhook\":{\"headers\":\"此 Webhook 请求携带的请求头。\",\"query\":\"此 Webhook 请求携带的 URL 查询参数。\",\"body\":\"此 Webhook 请求携带的请求体。\",\"webhookUrl\":\"接收此次请求的 Webhook URL,不含查询参数。\"}},\"startParametersTitle\":\"启动参数\"}}"),
|
|
252023
252732
|
language: { "label": "语言" },
|
|
@@ -253390,14 +254099,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
253390
254099
|
"exportFlow": "匯出工作流",
|
|
253391
254100
|
"exportPng": "匯出 PNG 圖片",
|
|
253392
254101
|
"exportPngFrame": "顯示外框",
|
|
254102
|
+
"exportPngCompact": "緊湊配置",
|
|
253393
254103
|
"exportPngLight": "淺色",
|
|
253394
254104
|
"exportPngDark": "深色",
|
|
253395
|
-
"exportPngPending": "正在匯出 PNG…",
|
|
253396
|
-
"exportPngPendingDescription": "正在處理工作流程和圖片資源,圖片較大時可能需要一些時間。",
|
|
253397
254105
|
"exportPngComplete": "PNG 圖片已匯出。",
|
|
253398
254106
|
"exportPngPartial": "PNG 圖片已匯出,部分圖片已用佔位圖替代。",
|
|
253399
254107
|
"exportPngFailed": "PNG 圖片匯出失敗,請重試。",
|
|
253400
|
-
"importInvalid": "檔案損壞或工作流格式不受支援。"
|
|
254108
|
+
"importInvalid": "檔案損壞或工作流格式不受支援。",
|
|
254109
|
+
"exportPngAspectRatio": "畫布比例",
|
|
254110
|
+
"exportPngAuto": "自動",
|
|
254111
|
+
"exportPngLayout": "配置",
|
|
254112
|
+
"exportPngOriginal": "原配置",
|
|
254113
|
+
"exportPngTheme": "主題",
|
|
254114
|
+
"exportPngPreview": "預覽",
|
|
254115
|
+
"exportPngPreviewPending": "正在產生預覽…",
|
|
254116
|
+
"exportPngPreviewFailed": "無法產生預覽,請重試。",
|
|
254117
|
+
"exportPngPreviewPartial": "部分圖片載入失敗,已使用預留位置圖片。",
|
|
254118
|
+
"exportPngDownload": "下載 PNG",
|
|
254119
|
+
"exportPngPreviewRetry": "重試"
|
|
253401
254120
|
},
|
|
253402
254121
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"節點大綱\",\"backToOutline\":\"返回節點大綱\",\"emptyOutline\":\"暫無節點\",\"triggers\":\"觸發器\",\"nodes\":\"節點\",\"multipleSelected\":\"已選擇 {{count}} 個節點\",\"account\":{\"contactAdmin\":\"你沒有執行此操作的權限,請聯絡管理員。\",\"accessTitle\":\"存取權限\",\"manageFlowAccess\":\"Code 允許使用的連線\",\"configureAccess\":\"選擇可用帳號\",\"manageAccount\":\"管理帳號\",\"required\":\"待連線帳號\",\"addAccount\":\"新增帳號\",\"manage\":\"管理\",\"authorizationPending\":\"請在 Connection 頁面完成授權,再回到這裡重新整理這個帳號。\",\"chooseAccount\":\"選擇帳號\",\"deferred\":\"暫不設定\",\"clearDeferred\":\"清除選擇\",\"noAccounts\":\"暫無可用帳號\",\"connectBeforeRun\":\"請先連接 {{service}},這個節點才能執行或發布。\",\"connectService\":\"連接 {{service}}\",\"connection\":\"Connection\",\"loading\":\"正在載入 Connection…\",\"oomolBuiltIn\":\"OOMOL 內建帳號\",\"missing\":\"此節點選擇的帳號目前無法使用,請選擇其他帳號或管理帳號。\",\"refreshFailed\":\"無法重新整理 Connection。\",\"retry\":\"重試\",\"status\":{\"disconnected\":\"這個 Connection 已中斷。請重新連接或選擇其他帳號。\",\"error\":\"這個 Connection 發生錯誤。請修復它或選擇其他帳號。\",\"reauth_required\":\"這個 Connection 需要重新授權。請重新連接或選擇其他帳號。\"},\"statusUnavailable\":\"無法取得 {{action}} 的 Connection 狀態。\",\"teamDefault\":\"團隊預設\",\"title\":\"帳號\",\"unavailable\":\"無法使用\"},\"close\":\"關閉檢查器\",\"configurationRequired\":\"尚未完成設定\",\"diagnostics\":\"診斷\",\"errors\":{\"jsonObject\":\"{{label}} 必須是 JSON 物件。\",\"portDefinitions\":\"請輸入有效的埠定義。\"},\"node\":{\"nameDuplicate\":\"目前圖中已存在同名節點。\",\"nameEmpty\":\"節點名稱不能為空。\",\"timeout\":\"逾時時間(毫秒)\",\"maxExecutions\":\"節點執行上限\",\"maxExecutionsError\":\"節點執行上限必須是正整數。\",\"timeoutError\":\"逾時時間必須是以毫秒為單位的正整數。\",\"title\":\"節點設定\",\"description\":\"用途說明\",\"describe\":\"描述這個步驟要完成什麼。\",\"icon\":\"圖示\",\"name\":\"標題\",\"retry\":\"失敗重試\",\"retryCount\":\"最多重試 {{count}} 次\",\"retryInterval\":\"重試間隔\",\"retryError\":\"間隔須為 1~60 整數秒。\",\"retryHint\":\"重試次數是首次執行失敗後的追加次數。重試會重新執行整個節點,可能重複外部操作。逾時包含全部嘗試和等待間隔。\",\"retryNone\":\"不重試\",\"retrySeconds\":\"秒\",\"retryHelp\":\"重試說明\",\"retryOnce\":\"最多重試 1 次\",\"onError\":\"失敗處理\",\"onErrorStop\":\"終止工作流程\",\"onErrorOutput\":\"輸出至 error 連接埠\",\"onErrorHelp\":\"失敗處理說明\",\"onErrorHint\":\"重試後仍失敗時,將錯誤寫入系統 error 並沿現有連線繼續。成功時 error 為 null。取消、逾時、資源限制及結果不確定仍終止工作流程。\",\"systemOutputs\":\"系統輸出\",\"systemError\":\"錯誤資訊(系統)\",\"errorFields\":{\"error\":\"節點失敗時的錯誤資訊;成功時為 null。\",\"code\":\"用於識別錯誤類型的錯誤碼。\",\"message\":\"錯誤的說明資訊,敏感內容已遮蔽。\",\"nodeId\":\"發生錯誤的節點 ID。\",\"nodeName\":\"發生錯誤時的節點名稱。\",\"runId\":\"本次工作流程執行的 ID。\",\"executionId\":\"本次節點執行的 ID,多次重試共用此 ID。\"}},\"selectNode\":\"選取一個草稿節點即可檢視並編輯它。\",\"locateNode\":\"在畫布上定位此節點\",\"task\":{\"sharedPermissions\":\"使用 Flow 共用權限群組\",\"sharedPermissionsHint\":\"直接使用 Flow 共用權限群組已授權的所有 Actions,無需逐一新增。\",\"httpHosts\":\"HTTP 主機\",\"httpHostsHint\":\"每行一個主機,支援 *.example.com 子網域比對。\",\"httpHostsInvalid\":\"「{{host}}」不是有效的主機,請填寫 api.example.com 這類主機名稱。\",\"httpHostsLimit\":\"最多宣告 {{count}} 個主機。\",\"addAction\":\"新增 Action\",\"removeAction\":\"移除 Action\",\"actionAccount\":\"帳號\",\"chooseAccount\":\"選擇帳號\",\"permissionSaveFailed\":\"無法儲存 Code 權限,請重試。\",\"chatText\":\"對話文字\",\"connectorAction\":\"Connector 操作\",\"definition\":\"任務定義\",\"discardCode\":\"放棄變更\",\"editorLoading\":\"正在載入編輯器…\",\"editorUnavailable\":\"無法載入程式碼編輯器。\",\"inputPorts\":\"輸入埠\",\"javascriptModule\":\"程式碼\",\"missing\":\"引用的任務不存在。\",\"outputPorts\":\"輸出埠\",\"responseMode\":\"回應模式\",\"source\":\"原始碼\",\"structuredJson\":\"結構化 JSON\",\"retrySave\":\"重試儲存\",\"additionalInputs\":\"附加輸入\",\"httpHostsUpdated\":\"主機設定已在別處更新。已載入最新設定,請檢查後再儲存。\"},\"wait\":{\"approval\":\"通過或拒絕\",\"changeNotification\":\"更換\",\"continue\":\"繼續\",\"mode\":\"處理方式\",\"inputsLoading\":\"正在載入通知參數…\",\"pendingDescription\":\"待確認出口在開始等待時觸發一次,提供確認連結及相關資料。連接此出口可傳送訊息或執行其他步驟。\",\"prompt\":\"提示\",\"promptError\":\"提示必須包含 1 到 1,000 個字元。\",\"autoContinue\":\"自動繼續\",\"autoOff\":\"關閉\",\"autoAfter\":\"等待一段時間\",\"autoAt\":\"到指定時間\",\"autoSeconds\":\"等待時長(秒)\",\"autoDate\":\"日期和時間\",\"autoInvalid\":\"請輸入正數時長或有效的日期和時間。\",\"autoDescription\":\"可提前手動繼續。\"},\"title\":\"檢查器\",\"sources\":{\"loading\":\"正在載入輸入來源…\",\"loadFailed\":\"無法載入輸入來源,請重新開啟選單重試。\",\"checkFailed\":\"無法檢查此來源。\",\"select\":\"選擇輸入來源\",\"title\":\"輸入來源\",\"sourceMissing\":\"原輸入來源已不存在,請重新選擇。\",\"outputMissing\":\"「{{source}}」中找不到「{{output}}」,請重新選擇。\",\"wholeObject\":\"整個物件\",\"fieldMissing\":\"「{{output}}」中已不再宣告欄位 {{field}},請重新選擇。\",\"notReady\":\"執行到這裡時,「{{source}} {{handle}}」可能還沒有值。\",\"sourceConflict\":\"這些欄位可能同時有值:{{sources}}。這裡只能取一個。\",\"incompatibleRight\":\"右值類型不符合此比較的要求。\",\"incompatible\":\"不相容\",\"unverified\":\"無法驗證\",\"schemaIncompatible\":\"資料格式不符。\",\"schemaPathIncompatible\":\"「{{path}}」的資料格式不符。\",\"schemaCompareFailed\":\"無法檢查資料格式,請檢查 JSON Schema。\",\"binaryIncompatible\":\"不能使用二進位資料。\",\"artifactIncompatible\":\"不能使用檔案資料。\",\"nullableIncompatible\":\"不能為空,但所選欄位可能為空。\",\"typeIncompatible\":\"需要{{target}},但所選欄位是{{source}}。\",\"propertyTypeIncompatible\":\"「{{path}}」需要{{target}},實際是{{source}}。\",\"requiredIncompatible\":\"不一定包含必填屬性「{{property}}」。\",\"enumIncompatible\":\"可能出現不接受的值:{{values}}。\",\"constIncompatible\":\"只接受 {{target}},所選欄位固定為 {{source}}。\",\"constraintSubject\":\"「{{path}}」\",\"minLength\":\"{{subject}}至少需要 {{value}} 個字元。\",\"maxLength\":\"{{subject}}最多接受 {{value}} 個字元。\",\"pattern\":\"{{subject}}文字格式應符合 {{value}}。\",\"minimum\":\"{{subject}}不能小於 {{value}}。\",\"exclusiveMinimum\":\"{{subject}}必須大於 {{value}}。\",\"maximum\":\"{{subject}}不能大於 {{value}}。\",\"exclusiveMaximum\":\"{{subject}}必須小於 {{value}}。\",\"multipleOf\":\"{{subject}}必須是 {{value}} 的倍數。\",\"minItems\":\"{{subject}}至少需要 {{value}} 項。\",\"maxItems\":\"{{subject}}最多接受 {{value}} 項。\",\"minProperties\":\"{{subject}}至少需要 {{value}} 個屬性。\",\"maxProperties\":\"{{subject}}最多接受 {{value}} 個屬性。\",\"integer\":\"整數\",\"unknownType\":\"未知類型\",\"typeSeparator\":\"或\"},\"actions\":{\"flowAccess\":\"可用服務\",\"flowAccessHint\":\"管理此 Flow 中所有 Code 節點共用的連線\",\"chooseConnection\":\"選擇 {{provider}} Connection\",\"connectionDescription\":\"Connection 將寫入這次呼叫;是否允許使用仍由 Flow Provider Access 決定。\",\"title\":\"程式碼可呼叫的動作\",\"search\":\"搜尋應用程式或動作…\",\"description\":\"搜尋並新增這段程式碼需要呼叫的動作。\",\"empty\":\"沒有符合的 Action。\",\"remove\":\"移除\",\"default\":\"預設帳號\",\"defaultHint\":\"呼叫時未指定帳號,將使用此帳號。\",\"removeAction\":\"移除動作\",\"explicit\":\"在程式碼中明確選擇\",\"connect\":\"連接帳號\",\"refresh\":\"重新整理帳號\",\"aliases\":\"同步帳號別名\",\"add\":\"新增動作\",\"cancel\":\"取消\",\"loading\":\"搜尋中…\",\"needsAccount\":\"待連接帳號\",\"accounts\":\"{{count}} 個帳號\",\"public\":\"無需帳號\",\"allowed\":\"可用帳號\",\"unavailable\":\"無法使用\",\"details\":\"帳號詳情\",\"example\":\"呼叫範例\",\"syntax\":\"呼叫寫法\",\"nested\":\"分層寫法\",\"fullId\":\"完整 ID\",\"copy\":\"複製\",\"copied\":\"已複製\",\"copyError\":\"複製失敗,請選取範例程式碼手動複製。\",\"introDescription\":\"依需求新增動作,透過 {{context}} 呼叫外部應用程式。\",\"insertAction\":\"插入程式碼\",\"chooseAccounts\":\"管理帳號\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"預覽\"},\"ports\":{\"reorder\":\"調整 {{name}} 的順序\",\"reorderHint\":\"拖動調整組內順序,或聚焦後使用上、下方向鍵。\",\"moved\":\"{{name}} 已移至第 {{position}} 位。\",\"groupSettings\":\"群組設定\",\"connected\":\"已連接\",\"sort\":\"排序\",\"finishSorting\":\"完成排序\",\"inputsTitle\":\"輸入\",\"requiredInputs\":\"必填\",\"optionalInputs\":\"選填\",\"noInputs\":\"此節點不需要輸入資料\",\"noOutputs\":\"此節點不提供輸出資料\",\"outputsTitle\":\"輸出\",\"valuesTitle\":\"資料\",\"columnHandle\":\"Handle\",\"columnName\":\"名稱\",\"columnType\":\"類型\",\"columnValue\":\"值\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"本次執行的排程觸發時間,採用 ISO 8601 格式。\"},\"webhook\":{\"headers\":\"此 Webhook 請求攜帶的請求標頭。\",\"query\":\"此 Webhook 請求攜帶的 URL 查詢參數。\",\"body\":\"此 Webhook 請求攜帶的請求本文。\",\"webhookUrl\":\"接收此次請求的 Webhook URL,不含查詢參數。\"}},\"startParametersTitle\":\"啟動參數\"}}"),
|
|
253403
254122
|
language: { "label": "語言" },
|
|
@@ -254770,14 +255489,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
254770
255489
|
"exportFlow": "ワークフローをエクスポート",
|
|
254771
255490
|
"exportPng": "PNG 画像をエクスポート",
|
|
254772
255491
|
"exportPngFrame": "フレームを表示",
|
|
255492
|
+
"exportPngCompact": "コンパクトな配置",
|
|
254773
255493
|
"exportPngLight": "ライト",
|
|
254774
255494
|
"exportPngDark": "ダーク",
|
|
254775
|
-
"exportPngPending": "PNG をエクスポート中…",
|
|
254776
|
-
"exportPngPendingDescription": "ワークフローと画像を準備しています。画像が大きい場合は時間がかかることがあります。",
|
|
254777
255495
|
"exportPngComplete": "PNG 画像をエクスポートしました。",
|
|
254778
255496
|
"exportPngPartial": "PNG 画像をエクスポートしました。一部の画像はプレースホルダーに置き換えられました。",
|
|
254779
255497
|
"exportPngFailed": "PNG 画像をエクスポートできませんでした。もう一度お試しください。",
|
|
254780
|
-
"importInvalid": "無効または未対応のワークフローファイルです。"
|
|
255498
|
+
"importInvalid": "無効または未対応のワークフローファイルです。",
|
|
255499
|
+
"exportPngAspectRatio": "キャンバス比率",
|
|
255500
|
+
"exportPngAuto": "自動",
|
|
255501
|
+
"exportPngLayout": "レイアウト",
|
|
255502
|
+
"exportPngOriginal": "元の配置",
|
|
255503
|
+
"exportPngTheme": "テーマ",
|
|
255504
|
+
"exportPngPreview": "プレビュー",
|
|
255505
|
+
"exportPngPreviewPending": "プレビューを生成中…",
|
|
255506
|
+
"exportPngPreviewFailed": "プレビューを生成できませんでした。",
|
|
255507
|
+
"exportPngPreviewPartial": "一部の画像を読み込めず、代替画像に置き換えました。",
|
|
255508
|
+
"exportPngDownload": "PNG をダウンロード",
|
|
255509
|
+
"exportPngPreviewRetry": "再試行"
|
|
254781
255510
|
},
|
|
254782
255511
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"ノード一覧\",\"backToOutline\":\"ノード一覧に戻る\",\"emptyOutline\":\"ノードはまだありません\",\"triggers\":\"トリガー\",\"nodes\":\"ノード\",\"multipleSelected\":\"{{count}} 個のノードを選択中\",\"account\":{\"contactAdmin\":\"この操作を実行する権限がありません。管理者にお問い合わせください。\",\"accessTitle\":\"アクセス権限\",\"manageFlowAccess\":\"Code で使用できる接続\",\"configureAccess\":\"アカウントを選択\",\"manageAccount\":\"アカウントを管理\",\"required\":\"アカウント接続が必要\",\"addAccount\":\"アカウントを追加\",\"manage\":\"管理\",\"authorizationPending\":\"Connection ページで認証を完了してください。ここに戻ると、このアカウントが更新されます。\",\"chooseAccount\":\"アカウントを選択\",\"deferred\":\"今は設定しない\",\"clearDeferred\":\"選択をクリア\",\"noAccounts\":\"利用可能なアカウントがありません\",\"connectBeforeRun\":\"このノードを実行または公開するには、先に {{service}} を接続してください。\",\"connectService\":\"{{service}} を接続\",\"connection\":\"Connection\",\"loading\":\"Connection を読み込み中…\",\"oomolBuiltIn\":\"OOMOL 組み込みアカウント\",\"missing\":\"このノードで選択されたアカウントは現在利用できません。別のアカウントを選択するか、アカウントを管理してください。\",\"refreshFailed\":\"Connection を更新できませんでした。\",\"retry\":\"再試行\",\"status\":{\"disconnected\":\"この Connection は切断されています。再接続するか、別のアカウントを選択してください。\",\"error\":\"この Connection にエラーがあります。修復するか、別のアカウントを選択してください。\",\"reauth_required\":\"この Connection は再認証が必要です。再接続するか、別のアカウントを選択してください。\"},\"statusUnavailable\":\"{{action}} の Connection 状態を取得できません。\",\"teamDefault\":\"チームのデフォルト\",\"title\":\"アカウント\",\"unavailable\":\"利用不可\"},\"close\":\"インスペクターを閉じる\",\"configurationRequired\":\"設定が必要\",\"diagnostics\":\"診断\",\"errors\":{\"jsonObject\":\"{{label}} は JSON オブジェクトである必要があります。\",\"portDefinitions\":\"有効なポート定義を入力してください。\"},\"node\":{\"nameDuplicate\":\"このグラフには同じ名前のノードが既に存在します。\",\"nameEmpty\":\"ノード名を空にすることはできません。\",\"timeout\":\"タイムアウト(ミリ秒)\",\"maxExecutions\":\"ノード実行上限\",\"maxExecutionsError\":\"ノード実行上限は正の整数で指定してください。\",\"timeoutError\":\"タイムアウトはミリ秒単位の正の整数で指定してください。\",\"title\":\"ノード設定\",\"description\":\"目的\",\"describe\":\"このステップの目的を記述します。\",\"icon\":\"アイコン\",\"name\":\"タイトル\",\"retry\":\"失敗時の再試行\",\"retryCount\":\"最大 {{count}} 回再試行\",\"retryInterval\":\"再試行の間隔\",\"retryError\":\"間隔は 1~60 の整数秒で指定してください。\",\"retryHint\":\"再試行回数は、初回の実行に失敗した後に追加する試行の回数です。再試行はノード全体を再実行するため、外部操作が重複する場合があります。タイムアウトには全試行と待機時間を含みます。\",\"retryNone\":\"再試行しない\",\"retrySeconds\":\"秒\",\"retryHelp\":\"再試行について\",\"retryOnce\":\"最大 1 回再試行\",\"onError\":\"失敗時の処理\",\"onErrorStop\":\"ワークフローを停止\",\"onErrorOutput\":\"error ポートに出力\",\"onErrorHelp\":\"失敗時の処理について\",\"onErrorHint\":\"再試行後も失敗した場合、システム error にエラーを出力して既存の接続で続行します。成功時は null です。キャンセル、タイムアウト、リソース制限、結果不明の場合は停止します。\",\"systemOutputs\":\"システム出力\",\"systemError\":\"エラー情報(システム)\",\"errorFields\":{\"error\":\"ノードが失敗した場合のエラー情報。成功時は null です。\",\"code\":\"エラーの種類を識別するコード。\",\"message\":\"機密情報をマスクしたエラーの説明。\",\"nodeId\":\"エラーが発生したノードの ID。\",\"nodeName\":\"エラー発生時のノード名。\",\"runId\":\"今回のワークフロー実行の ID。\",\"executionId\":\"今回のノード実行の ID。再試行でも同じ ID を使用します。\"}},\"selectNode\":\"ドラフトのノードを 1 つ選択すると、内容を確認して編集できます。\",\"locateNode\":\"キャンバス上でこのノードを表示\",\"task\":{\"sharedPermissions\":\"Flow の共有権限グループを使用\",\"sharedPermissionsHint\":\"Flow の共有権限グループで許可されたすべての Action を使用します。個別の追加は不要です。\",\"httpHosts\":\"HTTP ホスト\",\"httpHostsHint\":\"1 行に 1 ホスト。*.example.com はサブドメインに一致します。\",\"httpHostsInvalid\":\"「{{host}}」は有効なホストではありません。api.example.com のようなホスト名を入力してください。\",\"httpHostsLimit\":\"宣言できるホストは最大 {{count}} 個です。\",\"addAction\":\"Action を追加\",\"removeAction\":\"Action を削除\",\"actionAccount\":\"アカウント\",\"chooseAccount\":\"アカウントを選択\",\"permissionSaveFailed\":\"Code の権限を保存できませんでした。再試行してください。\",\"chatText\":\"チャットテキスト\",\"connectorAction\":\"Connector アクション\",\"definition\":\"タスク定義\",\"discardCode\":\"変更を破棄\",\"editorLoading\":\"エディターを読み込み中…\",\"editorUnavailable\":\"コードエディターを読み込めませんでした。\",\"inputPorts\":\"入力ポート\",\"javascriptModule\":\"コード\",\"missing\":\"参照しているタスクが存在しません。\",\"outputPorts\":\"出力ポート\",\"responseMode\":\"応答モード\",\"source\":\"ソースコード\",\"structuredJson\":\"構造化 JSON\",\"retrySave\":\"保存を再試行\",\"additionalInputs\":\"追加入力\",\"httpHostsUpdated\":\"ホスト設定が別の場所で更新されました。最新の設定を読み込みました。確認してから保存してください。\"},\"wait\":{\"approval\":\"承認または拒否\",\"changeNotification\":\"変更\",\"continue\":\"続行\",\"mode\":\"処理方法\",\"inputsLoading\":\"通知パラメーターを読み込んでいます…\",\"pendingDescription\":\"確認待ち出力は待機開始時に一度だけ発火し、確認リンクと関連データを提供します。接続先でメッセージの送信や他のステップを実行できます。\",\"prompt\":\"プロンプト\",\"promptError\":\"プロンプトは1〜1,000文字で入力してください。\",\"autoContinue\":\"自動続行\",\"autoOff\":\"オフ\",\"autoAfter\":\"一定時間後\",\"autoAt\":\"指定日時\",\"autoSeconds\":\"待機時間(秒)\",\"autoDate\":\"日時\",\"autoInvalid\":\"正の待機時間または有効な日時を入力してください。\",\"autoDescription\":\"予定時刻前に手動で続行できます。\"},\"title\":\"インスペクター\",\"sources\":{\"loading\":\"入力元を読み込み中…\",\"loadFailed\":\"入力元を読み込めません。メニューを開き直してください。\",\"checkFailed\":\"このソースを確認できませんでした。\",\"select\":\"入力元を選択\",\"title\":\"入力元\",\"sourceMissing\":\"元の入力元は存在しません。選択し直してください。\",\"outputMissing\":\"「{{source}}」に「{{output}}」が見つかりません。選択し直してください。\",\"wholeObject\":\"オブジェクト全体\",\"fieldMissing\":\"「{{output}}」にフィールド {{field}} が宣言されていません。選択し直してください。\",\"notReady\":\"ここを実行するとき、「{{source}} {{handle}}」にまだ値がない可能性があります。\",\"sourceConflict\":\"同時に値を持つ可能性があります:{{sources}}。ここでは 1 つだけ使用できます。\",\"incompatibleRight\":\"右辺の値の型はこの比較に対応していません。\",\"incompatible\":\"非互換\",\"unverified\":\"未検証\",\"schemaIncompatible\":\"データ形式が一致しません。\",\"schemaPathIncompatible\":\"「{{path}}」のデータ形式が一致しません。\",\"schemaCompareFailed\":\"データ形式を確認できません。JSON Schema を確認してください。\",\"binaryIncompatible\":\"バイナリデータは使用できません。\",\"artifactIncompatible\":\"ファイルデータは使用できません。\",\"nullableIncompatible\":\"値が必要ですが、選択したフィールドは空になる可能性があります。\",\"typeIncompatible\":\"{{target}}が必要ですが、選択したフィールドは{{source}}です。\",\"propertyTypeIncompatible\":\"「{{path}}」は{{target}}である必要がありますが、実際は{{source}}です。\",\"requiredIncompatible\":\"必須プロパティ「{{property}}」がない可能性があります。\",\"enumIncompatible\":\"使用できない値が含まれる可能性があります:{{values}}。\",\"constIncompatible\":\"{{target}}のみ使用できますが、選択したフィールドは常に {{source}} です。\",\"constraintSubject\":\"「{{path}}」は\",\"minLength\":\"{{subject}}少なくとも {{value}} 文字必要です。\",\"maxLength\":\"{{subject}}最大 {{value}} 文字です。\",\"pattern\":\"{{subject}}{{value}} に一致する必要があります。\",\"minimum\":\"{{subject}}{{value}} 未満にできません。\",\"exclusiveMinimum\":\"{{subject}}{{value}} より大きい必要があります。\",\"maximum\":\"{{subject}}{{value}} を超えられません。\",\"exclusiveMaximum\":\"{{subject}}{{value}} より小さい必要があります。\",\"multipleOf\":\"{{subject}}{{value}} の倍数である必要があります。\",\"minItems\":\"{{subject}}少なくとも {{value}} 項必要です。\",\"maxItems\":\"{{subject}}最大 {{value}} 項です。\",\"minProperties\":\"{{subject}}少なくとも {{value}} 個のプロパティが必要です。\",\"maxProperties\":\"{{subject}}最大 {{value}} 個のプロパティです。\",\"integer\":\"整数\",\"unknownType\":\"不明な型\",\"typeSeparator\":\"または\"},\"actions\":{\"flowAccess\":\"利用可能なサービス\",\"flowAccessHint\":\"この Flow のすべての Code ノードで共有する接続を管理\",\"chooseConnection\":\"{{provider}} Connection を選択\",\"connectionDescription\":\"Connection はこの呼び出しに挿入されます。使用可否は引き続き Flow Provider Access によって制御されます。\",\"title\":\"このコードから呼び出せるアクション\",\"search\":\"Action を検索\",\"description\":\"このコードで使用する Action とアカウントを選択します。\",\"empty\":\"一致する Action はありません。\",\"remove\":\"削除\",\"default\":\"既定のアカウント\",\"defaultHint\":\"呼び出し時にアカウントを指定しない場合に使用します。\",\"removeAction\":\"アクションを削除\",\"explicit\":\"コード内で明示的に選択\",\"connect\":\"アカウントを接続\",\"refresh\":\"アカウントを更新\",\"aliases\":\"保存済みの別名を更新\",\"add\":\"アクションを追加\",\"cancel\":\"キャンセル\",\"loading\":\"検索中…\",\"needsAccount\":\"アカウントを接続\",\"accounts\":\"{{count}} アカウント\",\"public\":\"アカウント不要\",\"allowed\":\"使用するアカウント\",\"unavailable\":\"利用不可\",\"details\":\"接続の詳細\",\"example\":\"呼び出し例\",\"syntax\":\"呼び出し形式\",\"nested\":\"プロバイダー形式\",\"fullId\":\"完全な ID\",\"copy\":\"コピー\",\"copied\":\"コピー済み\",\"copyError\":\"コピーできませんでした。コードを選択して手動でコピーしてください。\",\"introDescription\":\"必要に応じてアクションを追加し、{{context}} から外部アプリを呼び出せます。\",\"insertAction\":\"コードを挿入\",\"chooseAccounts\":\"アカウントを管理\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"プレビュー\"},\"ports\":{\"reorder\":\"{{name}} の順序を変更\",\"reorderHint\":\"ドラッグでグループ内の順序を変更。フォーカス時は上下キーでも移動できます。\",\"moved\":\"{{name}} を {{position}} 番目に移動しました。\",\"groupSettings\":\"グループ設定\",\"connected\":\"接続済み\",\"sort\":\"並べ替え\",\"finishSorting\":\"並べ替えを完了\",\"inputsTitle\":\"入力\",\"requiredInputs\":\"必須\",\"optionalInputs\":\"任意\",\"noInputs\":\"このノードには入力データが必要ありません。\",\"noOutputs\":\"このノードは出力データを提供しません。\",\"outputsTitle\":\"出力\",\"valuesTitle\":\"値\",\"columnHandle\":\"Handle\",\"columnName\":\"名前\",\"columnType\":\"型\",\"columnValue\":\"値\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"この実行をトリガーした予定時刻(ISO 8601 形式)です。\"},\"webhook\":{\"headers\":\"この Webhook リクエストで受信したリクエストヘッダーです。\",\"query\":\"この Webhook リクエストで受信した URL クエリパラメーターです。\",\"body\":\"この Webhook リクエストで受信したリクエストボディです。\",\"webhookUrl\":\"このリクエストを受信した Webhook URL(クエリパラメーターを除く)です。\"}},\"startParametersTitle\":\"開始パラメーター\"}}"),
|
|
254783
255512
|
language: { "label": "言語" },
|
|
@@ -256150,14 +256879,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
256150
256879
|
"exportFlow": "워크플로 내보내기",
|
|
256151
256880
|
"exportPng": "PNG 이미지 내보내기",
|
|
256152
256881
|
"exportPngFrame": "프레임 표시",
|
|
256882
|
+
"exportPngCompact": "간결한 배치",
|
|
256153
256883
|
"exportPngLight": "라이트",
|
|
256154
256884
|
"exportPngDark": "다크",
|
|
256155
|
-
"exportPngPending": "PNG 내보내는 중…",
|
|
256156
|
-
"exportPngPendingDescription": "워크플로와 이미지를 준비하고 있습니다. 이미지가 크면 시간이 더 걸릴 수 있습니다.",
|
|
256157
256885
|
"exportPngComplete": "PNG 이미지를 내보냈습니다.",
|
|
256158
256886
|
"exportPngPartial": "PNG 이미지를 내보냈습니다. 일부 이미지는 자리 표시자로 대체되었습니다.",
|
|
256159
256887
|
"exportPngFailed": "PNG 이미지를 내보내지 못했습니다. 다시 시도해 주세요.",
|
|
256160
|
-
"importInvalid": "잘못되었거나 지원하지 않는 워크플로 파일입니다."
|
|
256888
|
+
"importInvalid": "잘못되었거나 지원하지 않는 워크플로 파일입니다.",
|
|
256889
|
+
"exportPngAspectRatio": "캔버스 비율",
|
|
256890
|
+
"exportPngAuto": "자동",
|
|
256891
|
+
"exportPngLayout": "레이아웃",
|
|
256892
|
+
"exportPngOriginal": "원래 배치",
|
|
256893
|
+
"exportPngTheme": "테마",
|
|
256894
|
+
"exportPngPreview": "미리보기",
|
|
256895
|
+
"exportPngPreviewPending": "미리보기 생성 중…",
|
|
256896
|
+
"exportPngPreviewFailed": "미리보기를 생성하지 못했습니다.",
|
|
256897
|
+
"exportPngPreviewPartial": "일부 이미지를 불러오지 못해 대체 이미지로 표시했습니다.",
|
|
256898
|
+
"exportPngDownload": "PNG 다운로드",
|
|
256899
|
+
"exportPngPreviewRetry": "다시 시도"
|
|
256161
256900
|
},
|
|
256162
256901
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"노드 목록\",\"backToOutline\":\"노드 목록으로 돌아가기\",\"emptyOutline\":\"아직 노드가 없습니다\",\"triggers\":\"트리거\",\"nodes\":\"노드\",\"multipleSelected\":\"노드 {{count}}개 선택됨\",\"account\":{\"contactAdmin\":\"이 작업을 실행할 권한이 없습니다. 관리자에게 문의하세요.\",\"accessTitle\":\"접근 권한\",\"manageFlowAccess\":\"Code에서 사용할 수 있는 연결\",\"configureAccess\":\"계정 선택\",\"manageAccount\":\"계정 관리\",\"required\":\"계정 연결 필요\",\"addAccount\":\"계정 추가\",\"manage\":\"관리\",\"authorizationPending\":\"Connection 페이지에서 인증을 마친 뒤 여기로 돌아와 이 계정을 새로 고치세요.\",\"chooseAccount\":\"계정 선택\",\"deferred\":\"지금은 설정하지 않음\",\"clearDeferred\":\"선택 지우기\",\"noAccounts\":\"사용 가능한 계정이 없습니다\",\"connectBeforeRun\":\"이 블록을 실행하거나 게시하려면 먼저 {{service}}에 연결하세요.\",\"connectService\":\"{{service}} 연결\",\"connection\":\"Connection\",\"loading\":\"Connection 불러오는 중…\",\"oomolBuiltIn\":\"OOMOL 기본 제공 계정\",\"missing\":\"이 노드에서 선택한 계정을 현재 사용할 수 없습니다. 다른 계정을 선택하거나 계정을 관리하세요.\",\"refreshFailed\":\"Connection을 새로 고치지 못했습니다.\",\"retry\":\"다시 시도\",\"status\":{\"disconnected\":\"이 Connection은 연결이 끊어졌습니다. 다시 연결하거나 다른 계정을 선택하세요.\",\"error\":\"이 Connection에 오류가 있습니다. 문제를 해결하거나 다른 계정을 선택하세요.\",\"reauth_required\":\"이 Connection은 다시 인증해야 합니다. 다시 연결하거나 다른 계정을 선택하세요.\"},\"statusUnavailable\":\"{{action}}의 Connection 상태를 확인할 수 없습니다.\",\"teamDefault\":\"팀 기본값\",\"title\":\"계정\",\"unavailable\":\"사용할 수 없음\"},\"close\":\"인스펙터 닫기\",\"configurationRequired\":\"설정 필요\",\"diagnostics\":\"진단\",\"errors\":{\"jsonObject\":\"{{label}} 값은 JSON 객체여야 합니다.\",\"portDefinitions\":\"올바른 포트 정의를 입력하세요.\"},\"node\":{\"nameDuplicate\":\"이 그래프에 같은 이름의 노드가 이미 있습니다.\",\"nameEmpty\":\"노드 이름은 비워 둘 수 없습니다.\",\"timeout\":\"제한 시간(ms)\",\"maxExecutions\":\"노드 실행 한도\",\"maxExecutionsError\":\"노드 실행 한도는 양의 정수여야 합니다.\",\"timeoutError\":\"제한 시간은 밀리초 단위의 양의 정수여야 합니다.\",\"title\":\"노드 설정\",\"description\":\"목적\",\"describe\":\"이 단계의 목적을 설명하세요.\",\"icon\":\"아이콘\",\"name\":\"제목\",\"retry\":\"실패 시 재시도\",\"retryCount\":\"최대 {{count}}회 재시도\",\"retryInterval\":\"재시도 간격\",\"retryError\":\"간격은 1~60초의 정수로 입력하세요.\",\"retryHint\":\"재시도 횟수는 최초 실행 실패 후 추가로 시도하는 횟수입니다. 노드 전체를 다시 실행하므로 외부 작업이 중복될 수 있습니다. 제한 시간에는 모든 시도와 대기 시간이 포함됩니다.\",\"retryNone\":\"재시도 안 함\",\"retrySeconds\":\"초\",\"retryHelp\":\"재시도 안내\",\"retryOnce\":\"최대 1회 재시도\",\"onError\":\"실패 처리\",\"onErrorStop\":\"워크플로 중지\",\"onErrorOutput\":\"error 포트로 출력\",\"onErrorHelp\":\"실패 처리 안내\",\"onErrorHint\":\"재시도 후에도 실패하면 시스템 error에 오류를 기록하고 기존 연결을 따라 계속합니다. 성공 시 null입니다. 취소, 시간 초과, 리소스 제한 및 결과 불명 상태는 실행을 중지합니다.\",\"systemOutputs\":\"시스템 출력\",\"systemError\":\"오류 정보(시스템)\",\"errorFields\":{\"error\":\"노드 실패 시 오류 정보입니다. 성공 시 null입니다.\",\"code\":\"오류 유형을 식별하는 코드입니다.\",\"message\":\"민감한 내용이 가려진 오류 설명입니다.\",\"nodeId\":\"오류가 발생한 노드의 ID입니다.\",\"nodeName\":\"오류 발생 시점의 노드 이름입니다.\",\"runId\":\"이번 워크플로 실행의 ID입니다.\",\"executionId\":\"이번 노드 실행의 ID입니다. 재시도에서도 같은 ID를 사용합니다.\"}},\"selectNode\":\"확인하고 편집할 초안 노드를 하나 선택하세요.\",\"locateNode\":\"캔버스에서 이 노드 위치 보기\",\"task\":{\"sharedPermissions\":\"Flow 공유 권한 그룹 사용\",\"sharedPermissionsHint\":\"Flow 공유 권한 그룹에서 승인한 모든 Action을 사용합니다. 개별적으로 추가할 필요가 없습니다.\",\"httpHosts\":\"HTTP 호스트\",\"httpHostsHint\":\"한 줄에 호스트 하나. *.example.com은 하위 도메인과 일치합니다.\",\"httpHostsInvalid\":\"\\\"{{host}}\\\"은(는) 올바른 호스트가 아닙니다. api.example.com 같은 호스트 이름을 입력하세요.\",\"httpHostsLimit\":\"호스트는 최대 {{count}}개까지 선언할 수 있습니다.\",\"addAction\":\"Action 추가\",\"removeAction\":\"Action 제거\",\"actionAccount\":\"계정\",\"chooseAccount\":\"계정 선택\",\"permissionSaveFailed\":\"Code 권한을 저장하지 못했습니다. 다시 시도하세요.\",\"chatText\":\"대화 텍스트\",\"connectorAction\":\"Connector 액션\",\"definition\":\"태스크 정의\",\"discardCode\":\"변경 사항 버리기\",\"editorLoading\":\"편집기 불러오는 중…\",\"editorUnavailable\":\"코드 편집기를 불러오지 못했습니다.\",\"inputPorts\":\"입력 포트\",\"javascriptModule\":\"코드\",\"missing\":\"참조된 태스크가 존재하지 않습니다.\",\"outputPorts\":\"출력 포트\",\"responseMode\":\"응답 모드\",\"source\":\"소스\",\"structuredJson\":\"구조화된 JSON\",\"retrySave\":\"저장 재시도\",\"additionalInputs\":\"추가 입력\",\"httpHostsUpdated\":\"다른 곳에서 호스트 설정이 변경되었습니다. 최신 설정을 불러왔습니다. 확인 후 저장하세요.\"},\"wait\":{\"approval\":\"승인 또는 거부\",\"changeNotification\":\"변경\",\"continue\":\"계속\",\"mode\":\"처리 방식\",\"inputsLoading\":\"알림 매개변수를 불러오는 중…\",\"pendingDescription\":\"확인 대기 출력은 대기가 시작될 때 한 번 실행되어 확인 링크와 관련 데이터를 제공합니다. 연결하여 메시지를 보내거나 다른 단계를 실행할 수 있습니다.\",\"prompt\":\"프롬프트\",\"promptError\":\"프롬프트는 1~1,000자여야 합니다.\",\"autoContinue\":\"자동 계속\",\"autoOff\":\"끄기\",\"autoAfter\":\"일정 시간 후\",\"autoAt\":\"지정 시간에\",\"autoSeconds\":\"대기 시간(초)\",\"autoDate\":\"날짜 및 시간\",\"autoInvalid\":\"양수 대기 시간 또는 유효한 날짜와 시간을 입력하세요.\",\"autoDescription\":\"예정 시간 전에 수동으로 계속할 수 있습니다.\"},\"title\":\"인스펙터\",\"sources\":{\"loading\":\"입력 소스 불러오는 중…\",\"loadFailed\":\"입력 소스를 불러올 수 없습니다. 메뉴를 다시 열어 주세요.\",\"checkFailed\":\"이 소스를 확인할 수 없습니다.\",\"select\":\"입력 소스 선택\",\"title\":\"입력 소스\",\"sourceMissing\":\"기존 입력 소스가 더 이상 존재하지 않습니다. 다시 선택하세요.\",\"outputMissing\":\"“{{source}}”에서 “{{output}}”을(를) 찾을 수 없습니다. 다시 선택하세요.\",\"wholeObject\":\"전체 객체\",\"fieldMissing\":\"“{{output}}”에 {{field}} 필드가 선언되어 있지 않습니다. 다시 선택하세요.\",\"notReady\":\"여기까지 실행될 때 “{{source}} {{handle}}”에 아직 값이 없을 수 있습니다.\",\"sourceConflict\":\"다음 필드에 값이 동시에 있을 수 있습니다: {{sources}}. 여기서는 하나만 사용할 수 있습니다.\",\"incompatibleRight\":\"오른쪽 값의 형식이 이 비교와 호환되지 않습니다.\",\"incompatible\":\"호환되지 않음\",\"unverified\":\"확인되지 않음\",\"schemaIncompatible\":\"데이터 형식이 일치하지 않습니다.\",\"schemaPathIncompatible\":\"“{{path}}”의 데이터 형식이 일치하지 않습니다.\",\"schemaCompareFailed\":\"데이터 형식을 확인할 수 없습니다. JSON Schema를 확인하세요.\",\"binaryIncompatible\":\"바이너리 데이터는 사용할 수 없습니다.\",\"artifactIncompatible\":\"파일 데이터는 사용할 수 없습니다.\",\"nullableIncompatible\":\"값이 필요하지만 선택한 필드는 비어 있을 수 있습니다.\",\"typeIncompatible\":\"{{target}}이(가) 필요하지만 선택한 필드는 {{source}}입니다.\",\"propertyTypeIncompatible\":\"“{{path}}”은(는) {{target}}이어야 하지만 실제로는 {{source}}입니다.\",\"requiredIncompatible\":\"필수 속성 “{{property}}”이(가) 없을 수 있습니다.\",\"enumIncompatible\":\"허용되지 않는 값이 포함될 수 있습니다: {{values}}.\",\"constIncompatible\":\"{{target}}만 허용되지만 선택한 필드는 항상 {{source}}입니다.\",\"constraintSubject\":\"“{{path}}”은(는) \",\"minLength\":\"{{subject}}최소 {{value}}자여야 합니다.\",\"maxLength\":\"{{subject}}최대 {{value}}자여야 합니다.\",\"pattern\":\"{{subject}}{{value}} 형식과 일치해야 합니다.\",\"minimum\":\"{{subject}}{{value}}보다 작을 수 없습니다.\",\"exclusiveMinimum\":\"{{subject}}{{value}}보다 커야 합니다.\",\"maximum\":\"{{subject}}{{value}}보다 클 수 없습니다.\",\"exclusiveMaximum\":\"{{subject}}{{value}}보다 작아야 합니다.\",\"multipleOf\":\"{{subject}}{{value}}의 배수여야 합니다.\",\"minItems\":\"{{subject}}최소 {{value}}개 항목이 필요합니다.\",\"maxItems\":\"{{subject}}최대 {{value}}개 항목을 허용합니다.\",\"minProperties\":\"{{subject}}최소 {{value}}개 속성이 필요합니다.\",\"maxProperties\":\"{{subject}}최대 {{value}}개 속성을 허용합니다.\",\"integer\":\"정수\",\"unknownType\":\"알 수 없는 유형\",\"typeSeparator\":\" 또는 \"},\"actions\":{\"flowAccess\":\"사용 가능한 서비스\",\"flowAccessHint\":\"이 Flow의 모든 Code 노드가 공유하는 연결 관리\",\"chooseConnection\":\"{{provider}} Connection 선택\",\"connectionDescription\":\"Connection이 이 호출에 삽입됩니다. 사용 가능 여부는 계속 Flow Provider Access에서 제어합니다.\",\"title\":\"이 코드에서 호출할 수 있는 작업\",\"search\":\"Action 검색\",\"description\":\"이 코드에서 사용할 Action과 계정을 선택하세요.\",\"empty\":\"일치하는 Action이 없습니다.\",\"remove\":\"제거\",\"default\":\"기본 계정\",\"defaultHint\":\"호출 시 계정을 지정하지 않으면 이 계정을 사용합니다.\",\"removeAction\":\"액션 제거\",\"explicit\":\"코드에서 명시적으로 선택\",\"connect\":\"계정 연결\",\"refresh\":\"계정 새로 고침\",\"aliases\":\"저장된 별칭 업데이트\",\"add\":\"액션 추가\",\"cancel\":\"취소\",\"loading\":\"검색 중…\",\"needsAccount\":\"계정 연결 필요\",\"accounts\":\"계정 {{count}}개\",\"public\":\"계정 불필요\",\"allowed\":\"사용할 계정\",\"unavailable\":\"사용 불가\",\"details\":\"연결 세부 정보\",\"example\":\"호출 예제\",\"syntax\":\"호출 형식\",\"nested\":\"계층형\",\"fullId\":\"전체 ID\",\"copy\":\"복사\",\"copied\":\"복사됨\",\"copyError\":\"복사하지 못했습니다. 코드를 선택하여 직접 복사하세요.\",\"introDescription\":\"필요한 작업을 추가하고 {{context}}로 외부 앱을 호출하세요.\",\"insertAction\":\"코드 삽입\",\"chooseAccounts\":\"계정 관리\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"미리보기\"},\"ports\":{\"reorder\":\"{{name}} 순서 변경\",\"reorderHint\":\"그룹 안에서 드래그하거나 포커스 후 위 / 아래 키로 순서를 변경하세요.\",\"moved\":\"{{name}}이(가) {{position}}번째로 이동했습니다.\",\"groupSettings\":\"그룹 설정\",\"connected\":\"연결됨\",\"sort\":\"순서 변경\",\"finishSorting\":\"순서 변경 완료\",\"inputsTitle\":\"입력\",\"requiredInputs\":\"필수\",\"optionalInputs\":\"선택\",\"noInputs\":\"이 노드에는 입력 데이터가 필요하지 않습니다.\",\"noOutputs\":\"이 노드는 출력 데이터를 제공하지 않습니다.\",\"outputsTitle\":\"출력\",\"valuesTitle\":\"값\",\"columnHandle\":\"Handle\",\"columnName\":\"이름\",\"columnType\":\"유형\",\"columnValue\":\"값\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"이 실행을 트리거한 예약 시간이며 ISO 8601 형식입니다.\"},\"webhook\":{\"headers\":\"이 Webhook 요청과 함께 수신된 요청 헤더입니다.\",\"query\":\"이 Webhook 요청과 함께 수신된 URL 쿼리 매개변수입니다.\",\"body\":\"이 Webhook 요청과 함께 수신된 요청 본문입니다.\",\"webhookUrl\":\"이 요청을 수신한 Webhook URL이며 쿼리 매개변수는 포함하지 않습니다.\"}},\"startParametersTitle\":\"시작 매개변수\"}}"),
|
|
256163
256902
|
language: { "label": "언어" },
|
|
@@ -257530,14 +258269,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
257530
258269
|
"exportFlow": "Экспортировать процесс",
|
|
257531
258270
|
"exportPng": "Экспорт изображения PNG",
|
|
257532
258271
|
"exportPngFrame": "Показать рамку",
|
|
258272
|
+
"exportPngCompact": "Компактная компоновка",
|
|
257533
258273
|
"exportPngLight": "Светлая",
|
|
257534
258274
|
"exportPngDark": "Тёмная",
|
|
257535
|
-
"exportPngPending": "Экспорт PNG…",
|
|
257536
|
-
"exportPngPendingDescription": "Подготовка рабочего процесса и изображений. Большие изображения могут потребовать больше времени.",
|
|
257537
258275
|
"exportPngComplete": "Изображение PNG экспортировано.",
|
|
257538
258276
|
"exportPngPartial": "Изображение PNG экспортировано. Некоторые изображения заменены заглушками.",
|
|
257539
258277
|
"exportPngFailed": "Не удалось экспортировать изображение PNG. Повторите попытку.",
|
|
257540
|
-
"importInvalid": "Некорректный или неподдерживаемый файл процесса."
|
|
258278
|
+
"importInvalid": "Некорректный или неподдерживаемый файл процесса.",
|
|
258279
|
+
"exportPngAspectRatio": "Пропорции холста",
|
|
258280
|
+
"exportPngAuto": "Авто",
|
|
258281
|
+
"exportPngLayout": "Компоновка",
|
|
258282
|
+
"exportPngOriginal": "Исходная",
|
|
258283
|
+
"exportPngTheme": "Тема",
|
|
258284
|
+
"exportPngPreview": "Предпросмотр",
|
|
258285
|
+
"exportPngPreviewPending": "Создание предпросмотра…",
|
|
258286
|
+
"exportPngPreviewFailed": "Не удалось создать предпросмотр.",
|
|
258287
|
+
"exportPngPreviewPartial": "Некоторые изображения заменены заглушками.",
|
|
258288
|
+
"exportPngDownload": "Скачать PNG",
|
|
258289
|
+
"exportPngPreviewRetry": "Повторить"
|
|
257541
258290
|
},
|
|
257542
258291
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Список узлов\",\"backToOutline\":\"Вернуться к списку узлов\",\"emptyOutline\":\"Узлов пока нет\",\"triggers\":\"Триггеры\",\"nodes\":\"Узлы\",\"multipleSelected\":\"Выбрано узлов: {{count}}\",\"account\":{\"contactAdmin\":\"У вас нет прав для выполнения этой операции. Обратитесь к администратору.\",\"accessTitle\":\"Права доступа\",\"manageFlowAccess\":\"Подключения, доступные Code\",\"configureAccess\":\"Выбрать аккаунт\",\"manageAccount\":\"Управление аккаунтами\",\"required\":\"Требуется подключение аккаунта\",\"addAccount\":\"Добавить аккаунт\",\"manage\":\"Управление\",\"authorizationPending\":\"Завершите авторизацию на странице Connection, затем вернитесь сюда, чтобы обновить этот аккаунт.\",\"chooseAccount\":\"Выберите аккаунт\",\"deferred\":\"Пока не настраивать\",\"clearDeferred\":\"Сбросить выбор\",\"noAccounts\":\"Нет доступных аккаунтов\",\"connectBeforeRun\":\"Подключите {{service}}, чтобы этот узел можно было запускать и публиковать.\",\"connectService\":\"Подключить {{service}}\",\"connection\":\"Connection\",\"loading\":\"Загрузка Connection…\",\"oomolBuiltIn\":\"Встроенный аккаунт OOMOL\",\"missing\":\"Выбранный для этого узла аккаунт недоступен. Выберите другой аккаунт или откройте управление подключениями.\",\"refreshFailed\":\"Не удалось обновить Connection.\",\"retry\":\"Повторить\",\"status\":{\"disconnected\":\"Этот Connection отключён. Подключите его заново или выберите другой аккаунт.\",\"error\":\"В этом Connection ошибка. Исправьте её или выберите другой аккаунт.\",\"reauth_required\":\"Этому Connection нужна повторная авторизация. Подключите его заново или выберите другой аккаунт.\"},\"statusUnavailable\":\"Статус Connection недоступен для {{action}}.\",\"teamDefault\":\"По умолчанию для команды\",\"title\":\"Аккаунт\",\"unavailable\":\"недоступно\"},\"close\":\"Закрыть инспектор\",\"configurationRequired\":\"Требуется настройка\",\"diagnostics\":\"Диагностика\",\"errors\":{\"jsonObject\":\"{{label}} должен быть JSON-объектом.\",\"portDefinitions\":\"Введите корректные определения портов.\"},\"node\":{\"nameDuplicate\":\"Узел с таким именем уже существует в этом графе.\",\"nameEmpty\":\"Имя узла не может быть пустым.\",\"timeout\":\"Время ожидания (мс)\",\"maxExecutions\":\"Лимит выполнений узла\",\"maxExecutionsError\":\"Лимит выполнений узла должен быть положительным целым числом.\",\"timeoutError\":\"Время ожидания должно быть положительным целым числом в миллисекундах.\",\"title\":\"Настройки узла\",\"description\":\"Назначение\",\"describe\":\"Опишите назначение этого шага.\",\"icon\":\"Значок\",\"name\":\"Заголовок\",\"retry\":\"Повторять при ошибке\",\"retryCount\":\"До {{count}} повторов\",\"retryInterval\":\"Интервал повторов\",\"retryError\":\"Укажите целый интервал от 1 до 60 секунд.\",\"retryHint\":\"Число повторов означает дополнительные попытки после неудачной первой попытки. Повтор запускает весь узел заново и может повторить внешние операции. Тайм-аут включает все попытки и интервалы.\",\"retryNone\":\"Без повторов\",\"retrySeconds\":\"сек.\",\"retryHelp\":\"О повторах\",\"retryOnce\":\"Не более 1 повтора\",\"onError\":\"При ошибке\",\"onErrorStop\":\"Остановить процесс\",\"onErrorOutput\":\"Вывод в порт error\",\"onErrorHelp\":\"Обработка ошибок\",\"onErrorHint\":\"После неудачных повторов записать ошибку в системный выход error и продолжить по существующим связям. При успехе error равен null. Отмена, тайм-ауты, ограничения ресурсов и неопределённые результаты останавливают выполнение.\",\"systemOutputs\":\"Системные выходы\",\"systemError\":\"Ошибка (системная)\",\"errorFields\":{\"error\":\"Информация об ошибке узла; при успешном выполнении — null.\",\"code\":\"Код, определяющий тип ошибки.\",\"message\":\"Описание ошибки со скрытыми конфиденциальными данными.\",\"nodeId\":\"Идентификатор узла, в котором произошла ошибка.\",\"nodeName\":\"Имя узла на момент ошибки.\",\"runId\":\"Идентификатор этого запуска рабочего процесса.\",\"executionId\":\"Идентификатор этого выполнения узла, общий для всех повторных попыток.\"}},\"selectNode\":\"Выберите один узел черновика, чтобы просмотреть и изменить его.\",\"locateNode\":\"Найти этот узел на холсте\",\"task\":{\"sharedPermissions\":\"Использовать общую группу разрешений Flow\",\"sharedPermissionsHint\":\"Используйте все Actions, разрешённые общей группой Flow. Добавлять их в узел по отдельности не нужно.\",\"httpHosts\":\"HTTP-хосты\",\"httpHostsHint\":\"Один хост на строку. *.example.com включает поддомены.\",\"httpHostsInvalid\":\"«{{host}}» — недопустимый хост. Укажите имя хоста, например api.example.com.\",\"httpHostsLimit\":\"Можно объявить не более {{count}} хостов.\",\"addAction\":\"Добавить Action\",\"removeAction\":\"Удалить Action\",\"actionAccount\":\"Аккаунт\",\"chooseAccount\":\"Выбрать аккаунт\",\"permissionSaveFailed\":\"Не удалось сохранить разрешения Code. Повторите попытку.\",\"chatText\":\"Текст чата\",\"connectorAction\":\"Действие Connector\",\"definition\":\"Определение задачи\",\"discardCode\":\"Отменить изменения\",\"editorLoading\":\"Загрузка редактора…\",\"editorUnavailable\":\"Не удалось загрузить редактор кода.\",\"inputPorts\":\"Входные порты\",\"javascriptModule\":\"Код\",\"missing\":\"Указанная задача не существует.\",\"outputPorts\":\"Выходные порты\",\"responseMode\":\"Режим ответа\",\"source\":\"Исходный код\",\"structuredJson\":\"Структурированный JSON\",\"retrySave\":\"Повторить сохранение\",\"additionalInputs\":\"Дополнительные входы\",\"httpHostsUpdated\":\"Настройки хостов изменены в другом месте. Загружена новая конфигурация; проверьте её перед сохранением.\"},\"wait\":{\"approval\":\"Одобрить или отклонить\",\"changeNotification\":\"Изменить\",\"continue\":\"Продолжить\",\"mode\":\"Обработка\",\"inputsLoading\":\"Загрузка параметров уведомления…\",\"pendingDescription\":\"Выход ожидания срабатывает один раз при начале ожидания и передаёт ссылки подтверждения и связанные данные. Подключите его для отправки сообщения или выполнения других шагов.\",\"prompt\":\"Запрос\",\"promptError\":\"Запрос должен содержать от 1 до 1 000 символов.\",\"autoContinue\":\"Автоматическое продолжение\",\"autoOff\":\"Выключено\",\"autoAfter\":\"Через интервал\",\"autoAt\":\"В указанное время\",\"autoSeconds\":\"Длительность (секунды)\",\"autoDate\":\"Дата и время\",\"autoInvalid\":\"Введите положительную длительность или корректные дату и время.\",\"autoDescription\":\"До указанного времени можно продолжить вручную.\"},\"title\":\"Инспектор\",\"sources\":{\"loading\":\"Загрузка источников входных данных…\",\"loadFailed\":\"Не удалось загрузить источники входных данных. Откройте меню ещё раз.\",\"checkFailed\":\"Не удалось проверить этот источник.\",\"select\":\"Выбрать источник входных данных\",\"title\":\"Источник входных данных\",\"sourceMissing\":\"Исходный источник входных данных больше не существует. Выберите другой.\",\"outputMissing\":\"«{{output}}» не найден в «{{source}}». Выберите снова.\",\"wholeObject\":\"Весь объект\",\"fieldMissing\":\"Поле {{field}} больше не объявлено в «{{output}}». Выберите снова.\",\"notReady\":\"К моменту выполнения этого шага у «{{source}} {{handle}}» может ещё не быть значения.\",\"sourceConflict\":\"Эти поля могут иметь значения одновременно: {{sources}}. Здесь можно использовать только одно.\",\"incompatibleRight\":\"Тип правого значения несовместим с этим сравнением.\",\"incompatible\":\"Несовместимо\",\"unverified\":\"Не проверено\",\"schemaIncompatible\":\"Формат данных не совпадает.\",\"schemaPathIncompatible\":\"Формат данных «{{path}}» не совпадает.\",\"schemaCompareFailed\":\"Не удалось проверить формат данных. Проверьте схему JSON.\",\"binaryIncompatible\":\"Двоичные данные здесь использовать нельзя.\",\"artifactIncompatible\":\"Файловые данные здесь использовать нельзя.\",\"nullableIncompatible\":\"Требуется значение, но выбранное поле может быть пустым.\",\"typeIncompatible\":\"Ожидается {{target}}, но выбранное поле имеет тип {{source}}.\",\"propertyTypeIncompatible\":\"«{{path}}» должно иметь тип {{target}}, но имеет тип {{source}}.\",\"requiredIncompatible\":\"Обязательное свойство «{{property}}» может отсутствовать.\",\"enumIncompatible\":\"Некоторые возможные значения не принимаются: {{values}}.\",\"constIncompatible\":\"Принимается только {{target}}, но выбранное поле всегда равно {{source}}.\",\"constraintSubject\":\"«{{path}}» \",\"minLength\":\"{{subject}}должно содержать не менее {{value}} символов.\",\"maxLength\":\"{{subject}}должно содержать не более {{value}} символов.\",\"pattern\":\"{{subject}}должно соответствовать {{value}}.\",\"minimum\":\"{{subject}}не может быть меньше {{value}}.\",\"exclusiveMinimum\":\"{{subject}}должно быть больше {{value}}.\",\"maximum\":\"{{subject}}не может быть больше {{value}}.\",\"exclusiveMaximum\":\"{{subject}}должно быть меньше {{value}}.\",\"multipleOf\":\"{{subject}}должно быть кратно {{value}}.\",\"minItems\":\"{{subject}}должно содержать не менее {{value}} элементов.\",\"maxItems\":\"{{subject}}должно содержать не более {{value}} элементов.\",\"minProperties\":\"{{subject}}должно содержать не менее {{value}} свойств.\",\"maxProperties\":\"{{subject}}должно содержать не более {{value}} свойств.\",\"integer\":\"Целое число\",\"unknownType\":\"неизвестный тип\",\"typeSeparator\":\" или \"},\"actions\":{\"flowAccess\":\"Доступные сервисы\",\"flowAccessHint\":\"Управлять подключениями, общими для всех узлов Code в этом Flow\",\"chooseConnection\":\"Выбрать подключение {{provider}}\",\"connectionDescription\":\"Подключение будет вставлено в этот вызов. Возможность его использования по-прежнему контролирует Flow Provider Access.\",\"title\":\"Действия, доступные коду\",\"search\":\"Поиск действий\",\"description\":\"Выберите действия и аккаунты, доступные этому коду.\",\"empty\":\"Подходящих действий нет.\",\"remove\":\"Удалить\",\"default\":\"Аккаунт по умолчанию\",\"defaultHint\":\"Используется, если при вызове не указан аккаунт.\",\"removeAction\":\"Удалить действие\",\"explicit\":\"Выбирать явно в коде\",\"connect\":\"Подключить аккаунт\",\"refresh\":\"Обновить аккаунты\",\"aliases\":\"Обновить сохранённые псевдонимы\",\"add\":\"Добавить действие\",\"cancel\":\"Отмена\",\"loading\":\"Поиск…\",\"needsAccount\":\"Подключите аккаунт\",\"accounts\":\"Аккаунты: {{count}}\",\"public\":\"Без аккаунта\",\"allowed\":\"Разрешённые аккаунты\",\"unavailable\":\"Недоступен\",\"details\":\"Данные подключений\",\"example\":\"Пример вызова\",\"syntax\":\"Синтаксис вызова\",\"nested\":\"Через провайдера\",\"fullId\":\"Полный ID\",\"copy\":\"Копировать\",\"copied\":\"Скопировано\",\"copyError\":\"Не удалось скопировать. Выделите код и скопируйте вручную.\",\"introDescription\":\"При необходимости добавьте действия для вызова внешних приложений через {{context}}.\",\"insertAction\":\"Вставить код\",\"chooseAccounts\":\"Управление аккаунтами\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Предпросмотр\"},\"ports\":{\"reorder\":\"Изменить порядок {{name}}\",\"reorderHint\":\"Перетащите внутри группы или используйте стрелки вверх / вниз при фокусе.\",\"moved\":\"{{name}} перемещён на позицию {{position}}.\",\"groupSettings\":\"Настройки группы\",\"connected\":\"Подключено\",\"sort\":\"Изменить порядок\",\"finishSorting\":\"Готово\",\"inputsTitle\":\"Входы\",\"requiredInputs\":\"Обязательные\",\"optionalInputs\":\"Необязательные\",\"noInputs\":\"Этому узлу не требуются входные данные.\",\"noOutputs\":\"Этот узел не предоставляет выходных данных.\",\"outputsTitle\":\"Выходы\",\"valuesTitle\":\"Значения\",\"columnHandle\":\"Handle\",\"columnName\":\"Имя\",\"columnType\":\"Тип\",\"columnValue\":\"Значение\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"Запланированное время этого запуска в формате ISO 8601.\"},\"webhook\":{\"headers\":\"Заголовки, полученные с этим Webhook-запросом.\",\"query\":\"Параметры URL-запроса, полученные с этим Webhook-запросом.\",\"body\":\"Тело, полученное с этим Webhook-запросом.\",\"webhookUrl\":\"URL Webhook, получивший этот запрос, без параметров запроса.\"}},\"startParametersTitle\":\"Параметры запуска\"}}"),
|
|
257543
258292
|
language: { "label": "Язык" },
|
|
@@ -258910,14 +259659,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
258910
259659
|
"exportFlow": "Exporter le workflow",
|
|
258911
259660
|
"exportPng": "Exporter une image PNG",
|
|
258912
259661
|
"exportPngFrame": "Afficher le cadre",
|
|
259662
|
+
"exportPngCompact": "Disposition compacte",
|
|
258913
259663
|
"exportPngLight": "Clair",
|
|
258914
259664
|
"exportPngDark": "Sombre",
|
|
258915
|
-
"exportPngPending": "Exportation du PNG…",
|
|
258916
|
-
"exportPngPendingDescription": "Préparation du workflow et des images. Les images volumineuses peuvent prendre un peu plus de temps.",
|
|
258917
259665
|
"exportPngComplete": "Image PNG exportée.",
|
|
258918
259666
|
"exportPngPartial": "Image PNG exportée. Certaines images ont été remplacées par des espaces réservés.",
|
|
258919
259667
|
"exportPngFailed": "Impossible d’exporter l’image PNG. Veuillez réessayer.",
|
|
258920
|
-
"importInvalid": "Fichier de workflow invalide ou non pris en charge."
|
|
259668
|
+
"importInvalid": "Fichier de workflow invalide ou non pris en charge.",
|
|
259669
|
+
"exportPngAspectRatio": "Format du canevas",
|
|
259670
|
+
"exportPngAuto": "Auto",
|
|
259671
|
+
"exportPngLayout": "Disposition",
|
|
259672
|
+
"exportPngOriginal": "Originale",
|
|
259673
|
+
"exportPngTheme": "Thème",
|
|
259674
|
+
"exportPngPreview": "Aperçu",
|
|
259675
|
+
"exportPngPreviewPending": "Génération de l’aperçu…",
|
|
259676
|
+
"exportPngPreviewFailed": "Impossible de générer l’aperçu.",
|
|
259677
|
+
"exportPngPreviewPartial": "Certaines images ont été remplacées par des espaces réservés.",
|
|
259678
|
+
"exportPngDownload": "Télécharger le PNG",
|
|
259679
|
+
"exportPngPreviewRetry": "Réessayer"
|
|
258921
259680
|
},
|
|
258922
259681
|
inspector: /* @__PURE__ */ JSON.parse("{\"outline\":\"Liste des nœuds\",\"backToOutline\":\"Retour à la liste des nœuds\",\"emptyOutline\":\"Aucun nœud pour le moment\",\"triggers\":\"Déclencheurs\",\"nodes\":\"Nœuds\",\"multipleSelected\":\"{{count}} nœuds sélectionnés\",\"account\":{\"contactAdmin\":\"Vous n’avez pas l’autorisation d’effectuer cette opération. Contactez un administrateur.\",\"accessTitle\":\"Autorisations d’accès\",\"manageFlowAccess\":\"Connexions disponibles pour Code\",\"configureAccess\":\"Choisir un compte\",\"manageAccount\":\"Gérer les comptes\",\"required\":\"Compte à connecter\",\"addAccount\":\"Ajouter un compte\",\"manage\":\"Gérer\",\"authorizationPending\":\"Terminez l'autorisation sur la page Connection, puis revenez ici pour actualiser ce compte.\",\"chooseAccount\":\"Choisir un compte\",\"deferred\":\"Ne pas configurer maintenant\",\"clearDeferred\":\"Effacer la sélection\",\"noAccounts\":\"Aucun compte disponible\",\"connectBeforeRun\":\"Connectez {{service}} pour que ce bloc puisse être exécuté ou publié.\",\"connectService\":\"Connecter {{service}}\",\"connection\":\"Connection\",\"loading\":\"Chargement des Connections…\",\"oomolBuiltIn\":\"Compte intégré OOMOL\",\"missing\":\"Le compte sélectionné pour ce nœud est indisponible. Choisissez un autre compte ou gérez les connexions.\",\"refreshFailed\":\"Impossible d'actualiser les Connections.\",\"retry\":\"Réessayer\",\"status\":{\"disconnected\":\"Cette Connection est déconnectée. Reconnectez-la ou choisissez un autre compte.\",\"error\":\"Cette Connection présente une erreur. Réparez-la ou choisissez un autre compte.\",\"reauth_required\":\"Cette Connection doit être autorisée à nouveau. Reconnectez-la ou choisissez un autre compte.\"},\"statusUnavailable\":\"Le statut de la Connection est indisponible pour {{action}}.\",\"teamDefault\":\"Par défaut de l'équipe\",\"title\":\"Compte\",\"unavailable\":\"indisponible\"},\"close\":\"Fermer l'inspecteur\",\"configurationRequired\":\"Configuration requise\",\"diagnostics\":\"Diagnostics\",\"errors\":{\"jsonObject\":\"{{label}} doit être un objet JSON.\",\"portDefinitions\":\"Saisissez des définitions de ports valides.\"},\"node\":{\"nameDuplicate\":\"Un nœud portant ce nom existe déjà dans ce graphe.\",\"nameEmpty\":\"Le nom du nœud ne peut pas être vide.\",\"timeout\":\"Délai d'expiration (ms)\",\"maxExecutions\":\"Limite d’exécutions du nœud\",\"maxExecutionsError\":\"La limite d’exécutions du nœud doit être un entier positif.\",\"timeoutError\":\"Le délai d'expiration doit être un entier positif exprimé en millisecondes.\",\"title\":\"Paramètres du nœud\",\"description\":\"Objectif\",\"describe\":\"Décrivez le rôle de cette étape.\",\"icon\":\"Icône\",\"name\":\"Titre\",\"retry\":\"Réessayer en cas d’erreur\",\"retryCount\":\"Nouvelles tentatives : {{count}} max.\",\"retryInterval\":\"Intervalle\",\"retryError\":\"Indiquez un intervalle entier de 1 à 60 secondes.\",\"retryHint\":\"Le nombre de nouvelles tentatives s’ajoute à la première exécution en cas d’échec. Chaque tentative réexécute le nœud entier et peut répéter des opérations externes. Le délai maximal inclut toutes les tentatives et les intervalles.\",\"retryNone\":\"Aucune nouvelle tentative\",\"retrySeconds\":\"secondes\",\"retryHelp\":\"À propos des nouvelles tentatives\",\"retryOnce\":\"Une nouvelle tentative max.\",\"onError\":\"En cas d’échec\",\"onErrorStop\":\"Arrêter le workflow\",\"onErrorOutput\":\"Sortir vers le port error\",\"onErrorHelp\":\"Gestion des échecs\",\"onErrorHint\":\"Après les nouvelles tentatives, placer l’erreur dans la sortie système error et continuer par les connexions existantes. En cas de succès, error vaut null. Annulation, délais, limites de ressources et résultats indéterminés arrêtent toujours l’exécution.\",\"systemOutputs\":\"Sorties système\",\"systemError\":\"Erreur (système)\",\"errorFields\":{\"error\":\"Informations sur l’erreur en cas d’échec du nœud ; null en cas de réussite.\",\"code\":\"Code identifiant le type d’erreur.\",\"message\":\"Description de l’erreur, avec les informations sensibles masquées.\",\"nodeId\":\"Identifiant du nœud ayant échoué.\",\"nodeName\":\"Nom du nœud au moment de l’échec.\",\"runId\":\"Identifiant de cette exécution du workflow.\",\"executionId\":\"Identifiant de cette exécution du nœud, commun à toutes ses tentatives.\"}},\"selectNode\":\"Sélectionnez un nœud du Brouillon pour l'inspecter et le modifier.\",\"locateNode\":\"Localiser ce nœud sur le canevas\",\"task\":{\"sharedPermissions\":\"Utiliser le groupe d’autorisations partagé du Flow\",\"sharedPermissionsHint\":\"Utilisez toutes les Actions autorisées par le groupe du Flow, sans les ajouter à ce nœud.\",\"httpHosts\":\"Hôtes HTTP\",\"httpHostsHint\":\"Un hôte par ligne. *.example.com inclut les sous-domaines.\",\"httpHostsInvalid\":\"« {{host}} » n’est pas un hôte valide. Utilisez un nom d’hôte comme api.example.com.\",\"httpHostsLimit\":\"Déclarez au plus {{count}} hôtes.\",\"addAction\":\"Ajouter une action\",\"removeAction\":\"Supprimer l’action\",\"actionAccount\":\"Compte\",\"chooseAccount\":\"Choisir un compte\",\"permissionSaveFailed\":\"Impossible d’enregistrer les autorisations Code. Réessayez.\",\"chatText\":\"Texte de conversation\",\"connectorAction\":\"Action Connector\",\"definition\":\"Définition de la tâche\",\"discardCode\":\"Abandonner les modifications\",\"editorLoading\":\"Chargement de l'éditeur…\",\"editorUnavailable\":\"Impossible de charger l'éditeur de code.\",\"inputPorts\":\"Ports d'entrée\",\"javascriptModule\":\"Code\",\"missing\":\"La tâche référencée n'existe pas.\",\"outputPorts\":\"Ports de sortie\",\"responseMode\":\"Mode de réponse\",\"source\":\"Source\",\"structuredJson\":\"JSON structuré\",\"retrySave\":\"Réessayer\",\"additionalInputs\":\"Entrées supplémentaires\",\"httpHostsUpdated\":\"Les hôtes ont été modifiés ailleurs. La dernière configuration est chargée ; vérifiez-la avant d’enregistrer.\"},\"wait\":{\"approval\":\"Approuver ou refuser\",\"changeNotification\":\"Changer\",\"continue\":\"Continuer\",\"mode\":\"Traitement\",\"inputsLoading\":\"Chargement des paramètres de notification…\",\"pendingDescription\":\"La sortie en attente se déclenche une fois au début de l’attente et fournit les liens de confirmation et les données associées. Reliez-la pour envoyer un message ou exécuter d’autres étapes.\",\"prompt\":\"Invite\",\"promptError\":\"L’invite doit contenir entre 1 et 1 000 caractères.\",\"autoContinue\":\"Reprise automatique\",\"autoOff\":\"Désactivée\",\"autoAfter\":\"Après une durée\",\"autoAt\":\"À une date précise\",\"autoSeconds\":\"Durée (secondes)\",\"autoDate\":\"Date et heure\",\"autoInvalid\":\"Saisissez une durée positive ou une date et une heure valides.\",\"autoDescription\":\"Vous pouvez reprendre manuellement avant l’heure prévue.\"},\"title\":\"Inspecteur\",\"sources\":{\"loading\":\"Chargement des sources d’entrée…\",\"loadFailed\":\"Impossible de charger les sources d’entrée. Rouvrez le menu pour réessayer.\",\"checkFailed\":\"Impossible de vérifier cette source.\",\"select\":\"Sélectionner la source d’entrée\",\"title\":\"Source d’entrée\",\"sourceMissing\":\"La source d’entrée d’origine n’existe plus. Choisissez-en une autre.\",\"outputMissing\":\"« {{output}} » est introuvable dans « {{source}} ». Choisissez à nouveau.\",\"wholeObject\":\"Objet entier\",\"fieldMissing\":\"Le champ {{field}} n’est plus déclaré dans « {{output}} ». Choisissez à nouveau.\",\"notReady\":\"« {{source}} {{handle}} » peut ne pas avoir de valeur lors de cette étape.\",\"sourceConflict\":\"Ces champs peuvent avoir une valeur en même temps : {{sources}}. Un seul peut être utilisé ici.\",\"incompatibleRight\":\"Le type de la valeur de droite est incompatible avec cette comparaison.\",\"incompatible\":\"Incompatible\",\"unverified\":\"Non vérifié\",\"schemaIncompatible\":\"Le format des données ne correspond pas.\",\"schemaPathIncompatible\":\"Le format de « {{path}} » ne correspond pas.\",\"schemaCompareFailed\":\"Impossible de vérifier le format. Vérifiez le schéma JSON.\",\"binaryIncompatible\":\"Les données binaires ne peuvent pas être utilisées ici.\",\"artifactIncompatible\":\"Les données de fichier ne peuvent pas être utilisées ici.\",\"nullableIncompatible\":\"Une valeur est requise, mais le champ sélectionné peut être vide.\",\"typeIncompatible\":\"Le type attendu est {{target}}, mais le champ sélectionné est de type {{source}}.\",\"propertyTypeIncompatible\":\"« {{path}} » doit être de type {{target}}, mais est de type {{source}}.\",\"requiredIncompatible\":\"La propriété requise « {{property}} » peut être absente.\",\"enumIncompatible\":\"Certaines valeurs possibles ne sont pas acceptées : {{values}}.\",\"constIncompatible\":\"Seul {{target}} est accepté, mais le champ sélectionné vaut toujours {{source}}.\",\"constraintSubject\":\"« {{path}} » \",\"minLength\":\"{{subject}}doit contenir au moins {{value}} caractères.\",\"maxLength\":\"{{subject}}doit contenir au plus {{value}} caractères.\",\"pattern\":\"{{subject}}doit correspondre à {{value}}.\",\"minimum\":\"{{subject}}ne peut pas être inférieur à {{value}}.\",\"exclusiveMinimum\":\"{{subject}}doit être supérieur à {{value}}.\",\"maximum\":\"{{subject}}ne peut pas être supérieur à {{value}}.\",\"exclusiveMaximum\":\"{{subject}}doit être inférieur à {{value}}.\",\"multipleOf\":\"{{subject}}doit être un multiple de {{value}}.\",\"minItems\":\"{{subject}}doit contenir au moins {{value}} éléments.\",\"maxItems\":\"{{subject}}doit contenir au plus {{value}} éléments.\",\"minProperties\":\"{{subject}}doit contenir au moins {{value}} propriétés.\",\"maxProperties\":\"{{subject}}doit contenir au plus {{value}} propriétés.\",\"integer\":\"Entier\",\"unknownType\":\"type inconnu\",\"typeSeparator\":\" ou \"},\"actions\":{\"flowAccess\":\"Services disponibles\",\"flowAccessHint\":\"Gérer les connexions partagées par tous les nœuds Code de ce Flow\",\"chooseConnection\":\"Choisir une connexion {{provider}}\",\"connectionDescription\":\"La connexion est insérée dans cet appel. L’accès Provider du Flow détermine toujours si elle peut être utilisée.\",\"title\":\"Actions accessibles au code\",\"search\":\"Rechercher des actions\",\"description\":\"Choisissez les actions et les comptes autorisés pour ce code.\",\"empty\":\"Aucune action correspondante.\",\"remove\":\"Retirer\",\"default\":\"Compte par défaut\",\"defaultHint\":\"Compte utilisé si aucun compte n’est précisé lors de l’appel.\",\"removeAction\":\"Retirer l’action\",\"explicit\":\"Choisir explicitement dans le code\",\"connect\":\"Connecter un compte\",\"refresh\":\"Actualiser les comptes\",\"aliases\":\"Mettre à jour les alias enregistrés\",\"add\":\"Ajouter une action\",\"cancel\":\"Annuler\",\"loading\":\"Recherche…\",\"needsAccount\":\"Connecter un compte\",\"accounts\":\"{{count}} comptes\",\"public\":\"Sans compte\",\"allowed\":\"Comptes autorisés\",\"unavailable\":\"Indisponible\",\"details\":\"Détails des connexions\",\"example\":\"Exemple d’appel\",\"syntax\":\"Syntaxe d’appel\",\"nested\":\"Par fournisseur\",\"fullId\":\"ID complet\",\"copy\":\"Copier\",\"copied\":\"Copié\",\"copyError\":\"Échec de la copie. Sélectionnez le code pour le copier manuellement.\",\"introDescription\":\"Ajoutez des actions au besoin pour appeler des applications externes via {{context}}.\",\"insertAction\":\"Insérer le code\",\"chooseAccounts\":\"Gérer les comptes\"},\"comment\":{\"markdown\":\"Markdown\",\"preview\":\"Aperçu\"},\"ports\":{\"reorder\":\"Réordonner {{name}}\",\"reorderHint\":\"Glissez dans le groupe ou utilisez les flèches haut / bas au clavier.\",\"moved\":\"{{name}} déplacé en position {{position}}.\",\"groupSettings\":\"Paramètres du groupe\",\"connected\":\"Connecté\",\"sort\":\"Réordonner\",\"finishSorting\":\"Terminer\",\"inputsTitle\":\"Entrées\",\"requiredInputs\":\"Obligatoires\",\"optionalInputs\":\"Facultatifs\",\"noInputs\":\"Ce nœud ne nécessite pas de données d’entrée.\",\"noOutputs\":\"Ce nœud ne fournit pas de données de sortie.\",\"outputsTitle\":\"Sorties\",\"valuesTitle\":\"Valeurs\",\"columnHandle\":\"Handle\",\"columnName\":\"Nom\",\"columnType\":\"Type\",\"columnValue\":\"Valeur\",\"builtIn\":{\"cron\":{\"scheduledAt\":\"Heure planifiée ayant déclenché cette exécution, au format ISO 8601.\"},\"webhook\":{\"headers\":\"Les en-têtes reçus avec cette requête Webhook.\",\"query\":\"Les paramètres de requête URL reçus avec cette requête Webhook.\",\"body\":\"Le corps reçu avec cette requête Webhook.\",\"webhookUrl\":\"L’URL Webhook ayant reçu cette requête, sans les paramètres de requête.\"}},\"startParametersTitle\":\"Paramètres de démarrage\"}}"),
|
|
258923
259682
|
language: { "label": "Langue" },
|
|
@@ -266740,6 +267499,8 @@ export function identity(value) { return value }
|
|
|
266740
267499
|
const i18n = createI18n(language);
|
|
266741
267500
|
try {
|
|
266742
267501
|
const result = await flowToPng(designerGraph(workflow, workflow.presentation, [], {}, {}, i18n.t), language, {
|
|
267502
|
+
layout: options.layout,
|
|
267503
|
+
aspectRatio: options.aspectRatio,
|
|
266743
267504
|
dark: options.dark,
|
|
266744
267505
|
frame: options.frame,
|
|
266745
267506
|
title: options.title ?? workflow.name ?? "Workflow"
|