@oomol-lab/open-flow 0.1.0-beta.81 → 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/README.md +35 -0
- package/dist/browser/{FlowCanvas-CrsiDHK8.js → FlowCanvas-ChbukrDh.js} +879 -535
- package/dist/browser/{createResourceDialog-CS3u9ga9.js → createResourceDialog-Bi4fUnbD.js} +5 -4
- package/dist/browser/{dialog-CFlvkliO.js → dialog-BzoSxhXQ.js} +1 -1
- package/dist/browser/{exportPng-BOPfjeEi.js → exportPng-CrAFfOaD.js} +187 -70
- package/dist/browser/{flowChanges-CFj5pL4Y.js → flowChanges-C567g-Pc.js} +2675 -93
- package/dist/browser/{flowWorkspace-BeQaeJ3e.js → flowWorkspace-rvcneG4q.js} +980 -2621
- package/dist/browser/licenses.md +2 -2
- package/dist/browser/{markdownContent-frwDfQQU.js → markdownContent-B-GLj5DU.js} +18 -40
- package/dist/browser/{markdownContent-CAG_CQfH.js → markdownContent-D8G_oNOe.js} +18 -41
- package/dist/browser/preview.css +125 -80
- package/dist/browser/preview.js +1093 -379
- package/dist/browser/{tooltip-BDcVTNpu.js → tooltip-DGj5pudg.js} +1 -1
- package/dist/browser/ui.css +45 -0
- package/dist/browser/{dist-CHwj9BhV.js → videoLink-NAWDmBtf.js} +35 -1
- package/dist/browser/workbench-contract.d.ts +6 -0
- package/dist/browser/workbench.css +296 -251
- package/dist/browser/workbench.d.ts +2 -0
- package/dist/browser/workbench.js +294 -141
- package/dist/browser/{workbenchSelect-Ci0KCYv9.js → workbenchSelect-BIaEVTx6.js} +2 -2
- package/dist/browser/{ContentIcon-CMn0c-kl.js → wrapLayout-C4moMKgb.js} +4400 -4148
- package/dist/command/index.js +43 -41
- package/dist/common/authoring.d.ts +1 -1
- package/dist/common/control-api-conformance.js +306 -2
- package/dist/common/control-api.d.ts +20 -0
- package/dist/common/control-api.js +306 -4
- package/dist/common/control-requests.d.ts +3 -5
- package/dist/common/control-requests.js +5 -7
- package/dist/common/flow-encoding.d.ts +1 -0
- package/dist/common/flow-encoding.js +167 -1
- package/dist/common/flow-semantics.js +20 -0
- package/dist/common/flow-workflowBundle.d.ts +27 -0
- package/dist/common/flow-workflowFile.d.ts +2 -0
- package/dist/common/flow-workflowReferences.d.ts +4 -0
- package/dist/common/mcp.d.ts +2 -0
- package/dist/common/mcp.js +312 -4
- package/dist/render/browser/licenses.md +4047 -0
- package/dist/render/browser/runtime.css +14914 -0
- package/dist/render/browser/runtime.js +267526 -0
- package/dist/render/common/png.d.ts +32 -0
- package/dist/render/node/index.d.ts +11 -0
- package/dist/render/node/index.js +9508 -0
- package/dist/render/node/licenses.md +75 -0
- package/package.json +12 -2
- package/src/control/common/api.ts +50 -0
- package/src/control/common/flowDecoders.ts +2 -0
- package/src/control/common/mcp.ts +4 -4
- package/src/control/common/requests.ts +12 -1
- package/src/flow/common/encoding.ts +1 -0
- package/src/flow/common/workflowBundle.ts +117 -0
- package/src/flow/common/workflowFile.ts +4 -0
- package/src/flow/common/workflowReferences.ts +20 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CEgmsyvS.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as waitBranchDescription, A as DropdownMenuItem, B as CompositeItem, D as DropdownMenuCheckboxItem, E as DropdownMenu, G as MenuPopup, H as MenuRoot, J as ContextMenuRootContext, K as MenuItem, M as DropdownMenuRadioGroup, N as DropdownMenuRadioItem, O as DropdownMenuContent, P as DropdownMenuSeparator, Q as uiLocales, R as DropdownMenuTrigger, U as MenuPositioner, W as MenuPortal, X as MenuRootContext, Y as useContextMenuRootContext, Z as useMenuRootContext, a as CompositeRoot, at as ja_default, c as PopoverContent, ct as I18n, dt as useAriaLabelledBy, f as PopoverTitle, ft as useFieldItemContext, h as ScrollArea, i as Textarea, it as ko_default, j as DropdownMenuLabel, k as DropdownMenuGroup, m as NativeScrollArea, n as wrapLayout, nt as zh_CN_default, o as ACTIVE_COMPOSITE_ITEM, ot as fr_default, p as PopoverTrigger, pt as IconThemeContext, q as MenuGroup, r as canvasDirection, rt as ru_default, s as Popover, st as en_default, t as layoutAxes, tt as zh_TW_default, ut as Checkbox, v as ContentIcon, z as findRootOwnerId } from "./wrapLayout-C4moMKgb.js";
|
|
3
3
|
import { a as derive, c as strictEqual, i as compute, l as val, n as attachSetter, r as combine, s as readonlyVal } from "./dist-bO8nvHFH.js";
|
|
4
4
|
import { c as useLang, i as isString, l as useTranslate, n as isBoolean, o as I18nProvider, r as isPlainObject, t as isArray$1, u as useVal } from "./dist-BFmpkX4P.js";
|
|
5
|
-
import { A as string,
|
|
5
|
+
import { A as string, Bn as transitionStatusMapping, Br as useStableCallback, C as literal, Cr as cn$1, Dn as getTarget, En as contains, Er as useRenderElement, Fn as createLucideIcon, Fr as formatErrorMessage, J as SHIFT, Kn as cancelOpen, Lr as useIsoLayoutEffect, Mn as ownerDocument, Mr as useButton, Nn as useLabelableId, Or as EMPTY_OBJECT, Sn as stopEvent$1, T as number, Tr as clsx, Un as useValueChanged, Wn as createChangeEventDetails, Yt as addEventListener, _r as fieldValidityMapping, br as useControlled, cr as triggerPress, dr as useFormContext, fr as useRegisterFieldControl, gt as serializeValue, hr as useId$1, i as TooltipTrigger, jr as useMergedRefs, k as strictObject, kr as NOOP, mr as useBaseUiId, n as TooltipContent, p as timeZoneOffsetMinutes, pr as useFieldRootContext, pt as pressableTriggerOpenStateMapping, r as TooltipProvider, rr as none$1, sn as useTimeout, t as Tooltip, tn as require_with_selector, ur as useLabelableContext, vr as visuallyHidden, xr as Button, y as discriminatedUnion, yr as visuallyHiddenInput } from "./tooltip-DGj5pudg.js";
|
|
6
6
|
import { r as resolveUiLanguage } from "./languages-gYzoQqCi.js";
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
import reactExports, { Children, Suspense, createContext, forwardRef, isValidElement, lazy, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
@@ -33,6 +33,234 @@ function useFieldsetRootContext(optional = false) {
|
|
|
33
33
|
return context;
|
|
34
34
|
}
|
|
35
35
|
//#endregion
|
|
36
|
+
//#region src/render/common/png.ts
|
|
37
|
+
var flowPngAspectRatios = [
|
|
38
|
+
"auto",
|
|
39
|
+
"1:1",
|
|
40
|
+
"4:3",
|
|
41
|
+
"3:4",
|
|
42
|
+
"16:9",
|
|
43
|
+
"9:16"
|
|
44
|
+
];
|
|
45
|
+
function getFlowPngAspectRatio(value) {
|
|
46
|
+
if (value == null || value === "auto") return void 0;
|
|
47
|
+
if (!flowPngAspectRatios.includes(value)) throw new TypeError("Unsupported PNG canvas aspect ratio.");
|
|
48
|
+
const [width, height] = value.split(":").map(Number);
|
|
49
|
+
return [width, height];
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region ../../node_modules/.bun/@wopjs+disposable@0.1.24/node_modules/@wopjs/disposable/dist/index.mjs
|
|
53
|
+
var isFn = (value) => !!(value && value.constructor && value.call && value.apply);
|
|
54
|
+
/**
|
|
55
|
+
* Check if a value is a {@link DisposableType}.
|
|
56
|
+
* @param value The value to check.
|
|
57
|
+
* @returns True if the value is a {@link DisposableType}, false otherwise.
|
|
58
|
+
*/
|
|
59
|
+
var isDisposable = (value) => isFn(value) || isFn(value?.dispose);
|
|
60
|
+
/**
|
|
61
|
+
* Dispose a disposable object or a disposer function. Log the error if any.
|
|
62
|
+
* @param disposable A disposable object or a disposer function. Do nothing otherwise.
|
|
63
|
+
*/
|
|
64
|
+
function dispose(disposable) {
|
|
65
|
+
try {
|
|
66
|
+
if (disposable) {
|
|
67
|
+
if (isFn(disposable.dispose)) disposable.dispose();
|
|
68
|
+
else if (isFn(disposable)) disposable();
|
|
69
|
+
}
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error(e);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
var isAbortable = (disposable) => isDisposable(disposable) && isFn(disposable.abortable);
|
|
75
|
+
/**
|
|
76
|
+
* Create a {@link DisposableStore} that manages {@link Disposer}s and {@link IDisposable}s.
|
|
77
|
+
*
|
|
78
|
+
* A {@link DisposableStore} is also a {@link Disposer}, which means it can be the `dispose` method of an {@link IDisposable}.
|
|
79
|
+
*
|
|
80
|
+
* A {@link DisposableStore} is also an {@link IDisposable}, which means it can be managed by another {@link DisposableStore}.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { type IDisposable, disposableStore } from "@wopjs/disposable";
|
|
85
|
+
*
|
|
86
|
+
* class A implements IDisposable {
|
|
87
|
+
* dispose = disposableStore()
|
|
88
|
+
* constructor() {
|
|
89
|
+
* this.dispose.add(...);
|
|
90
|
+
* }
|
|
91
|
+
* }
|
|
92
|
+
*
|
|
93
|
+
* class B implements IDisposable {
|
|
94
|
+
* dispose = disposableStore()
|
|
95
|
+
* a = this.dispose.add(new A())
|
|
96
|
+
* constructor() {
|
|
97
|
+
* this.dispose.add(...);
|
|
98
|
+
* }
|
|
99
|
+
* }
|
|
100
|
+
*
|
|
101
|
+
* const b = new B();
|
|
102
|
+
* b.dispose(); // dispose both `b` and `b.a`.
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @param disposables Optional array of {@link DisposableType}s added to the store.
|
|
106
|
+
* @returns A disposable store.
|
|
107
|
+
*/
|
|
108
|
+
function disposableStore(disposables) {
|
|
109
|
+
let isDisposing;
|
|
110
|
+
function disposableStore() {
|
|
111
|
+
if (!isDisposing) {
|
|
112
|
+
isDisposing = 1;
|
|
113
|
+
isDisposing = disposableStore._disposables_ = disposableStore._disposables_?.forEach(dispose);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
disposableStore.dispose = disposableStore;
|
|
117
|
+
disposableStore.size = size;
|
|
118
|
+
disposableStore.has = has;
|
|
119
|
+
disposableStore.add = add;
|
|
120
|
+
disposableStore.make = make;
|
|
121
|
+
disposableStore.remove = remove$1;
|
|
122
|
+
disposableStore.flush = flush;
|
|
123
|
+
if (disposables) disposableStore.add(disposables);
|
|
124
|
+
return disposableStore;
|
|
125
|
+
}
|
|
126
|
+
function _addOne(disposable) {
|
|
127
|
+
if (!this._disposables_?.has(disposable)) {
|
|
128
|
+
(this._disposables_ ??= /* @__PURE__ */ new Set()).add(disposable);
|
|
129
|
+
if (isAbortable(disposable)) disposable.abortable(remove$1.bind(this, disposable));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function add(disposables) {
|
|
133
|
+
Array.isArray(disposables) ? disposables.forEach(_addOne, this) : _addOne.call(this, disposables);
|
|
134
|
+
return disposables;
|
|
135
|
+
}
|
|
136
|
+
function flush(disposable) {
|
|
137
|
+
dispose(disposable ? this.remove(disposable) && disposable : this);
|
|
138
|
+
}
|
|
139
|
+
function has(disposable) {
|
|
140
|
+
return !!this._disposables_?.has(disposable);
|
|
141
|
+
}
|
|
142
|
+
function make(executor) {
|
|
143
|
+
const disposable = executor();
|
|
144
|
+
return disposable && this.add(disposable);
|
|
145
|
+
}
|
|
146
|
+
function remove$1(disposable) {
|
|
147
|
+
return !!this._disposables_?.delete(disposable);
|
|
148
|
+
}
|
|
149
|
+
function size() {
|
|
150
|
+
return this._disposables_?.size || 0;
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/collections.mjs
|
|
154
|
+
var ReactiveMapImpl = class extends Map {
|
|
155
|
+
constructor(entries, config) {
|
|
156
|
+
super();
|
|
157
|
+
if (config) this.#onDeleted = config.onDeleted;
|
|
158
|
+
const [$, set$] = readonlyVal(this, { equal: false });
|
|
159
|
+
this.$ = $;
|
|
160
|
+
this.#notify = () => set$(this);
|
|
161
|
+
if (entries) for (const [key, value] of entries) this.set(key, value);
|
|
162
|
+
}
|
|
163
|
+
$;
|
|
164
|
+
#notify;
|
|
165
|
+
#onDeleted;
|
|
166
|
+
#delete(key) {
|
|
167
|
+
if (this.#onDeleted) {
|
|
168
|
+
if (super.has(key)) {
|
|
169
|
+
const value = super.get(key);
|
|
170
|
+
super.delete(key);
|
|
171
|
+
this.#onDeleted(value);
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return super.delete(key);
|
|
177
|
+
}
|
|
178
|
+
#clear() {
|
|
179
|
+
if (this.#onDeleted) {
|
|
180
|
+
const deleted = new Set(this.values());
|
|
181
|
+
super.clear();
|
|
182
|
+
for (const value of deleted) this.#onDeleted(value);
|
|
183
|
+
} else super.clear();
|
|
184
|
+
}
|
|
185
|
+
delete(key) {
|
|
186
|
+
const deleted = this.#delete(key);
|
|
187
|
+
if (deleted) this.#notify();
|
|
188
|
+
return deleted;
|
|
189
|
+
}
|
|
190
|
+
batchDelete(keys) {
|
|
191
|
+
let deleted = false;
|
|
192
|
+
for (const key of keys) deleted = this.#delete(key) || deleted;
|
|
193
|
+
if (deleted) this.#notify();
|
|
194
|
+
return deleted;
|
|
195
|
+
}
|
|
196
|
+
clear() {
|
|
197
|
+
if (this.size > 0) {
|
|
198
|
+
this.#clear();
|
|
199
|
+
this.#notify();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
#set(key, value) {
|
|
203
|
+
if (this.has(key)) {
|
|
204
|
+
const oldValue = this.get(key);
|
|
205
|
+
if (strictEqual(oldValue, value)) return false;
|
|
206
|
+
super.set(key, value);
|
|
207
|
+
if (this.#onDeleted) this.#onDeleted(oldValue);
|
|
208
|
+
} else super.set(key, value);
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
set(key, value) {
|
|
212
|
+
if (this.#set(key, value)) this.#notify();
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
batchSet(entries) {
|
|
216
|
+
let isDirty = false;
|
|
217
|
+
for (const [key, value] of entries) isDirty = this.#set(key, value) || isDirty;
|
|
218
|
+
if (isDirty) this.#notify();
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
rename(oldKey, newKey) {
|
|
222
|
+
if (!strictEqual(oldKey, newKey)) {
|
|
223
|
+
const value = this.get(oldKey);
|
|
224
|
+
if (super.delete(oldKey)) {
|
|
225
|
+
this.set(newKey, value);
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
replace(entries) {
|
|
232
|
+
const oldMap = new Map(this);
|
|
233
|
+
const deletedValues = new Set(this.values());
|
|
234
|
+
let hasNewValue = false;
|
|
235
|
+
super.clear();
|
|
236
|
+
for (const [key, value] of entries) {
|
|
237
|
+
super.set(key, value);
|
|
238
|
+
deletedValues.delete(value);
|
|
239
|
+
hasNewValue = hasNewValue || !oldMap.has(key) || !Object.is(oldMap.get(key), value);
|
|
240
|
+
oldMap.delete(key);
|
|
241
|
+
}
|
|
242
|
+
if (hasNewValue || oldMap.size > 0 || deletedValues.size > 0) {
|
|
243
|
+
if (this.#onDeleted) for (const value of deletedValues) this.#onDeleted(value);
|
|
244
|
+
this.#notify();
|
|
245
|
+
}
|
|
246
|
+
return deletedValues.values();
|
|
247
|
+
}
|
|
248
|
+
toJSON() {
|
|
249
|
+
const result = {};
|
|
250
|
+
for (const [key, value] of this) if (key != null) {
|
|
251
|
+
const k = String(key);
|
|
252
|
+
const v = value;
|
|
253
|
+
result[k] = v && v.toJSON ? v.toJSON(k) : v;
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
dispose() {
|
|
258
|
+
this.$.dispose();
|
|
259
|
+
if (this.size > 0) this.#clear();
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
var reactiveMap = (entries, config) => new ReactiveMapImpl(entries, config);
|
|
263
|
+
//#endregion
|
|
36
264
|
//#region ../../node_modules/.bun/@dagrejs+dagre@3.1.1/node_modules/@dagrejs/dagre/dist/dagre.esm.js
|
|
37
265
|
var Te = Object.defineProperty;
|
|
38
266
|
var In = (e, n, t) => n in e ? Te(e, n, {
|
|
@@ -2269,105 +2497,463 @@ function _e(e) {
|
|
|
2269
2497
|
}
|
|
2270
2498
|
/*! For license information please see dagre.esm.js.LEGAL.txt */
|
|
2271
2499
|
//#endregion
|
|
2272
|
-
//#region
|
|
2273
|
-
var
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2500
|
+
//#region src/canvas/browser/base/routeLayout.ts
|
|
2501
|
+
var clearance = 16;
|
|
2502
|
+
var portOffset = 24;
|
|
2503
|
+
/** Orthogonal channels around the measured cards, in primary/cross coordinates. */
|
|
2504
|
+
function routeLayout(nodes, edges) {
|
|
2505
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
2506
|
+
const connections = edges.map((edge) => {
|
|
2507
|
+
const source = byId.get(edge.source);
|
|
2508
|
+
const target = byId.get(edge.target);
|
|
2509
|
+
const output = {
|
|
2510
|
+
x: source.x + (edge.sourceOffset?.x ?? source.width),
|
|
2511
|
+
y: source.y + (edge.sourceOffset?.y ?? source.height / 2)
|
|
2512
|
+
};
|
|
2513
|
+
const input = {
|
|
2514
|
+
x: target.x + (edge.targetOffset?.x ?? 0),
|
|
2515
|
+
y: target.y + (edge.targetOffset?.y ?? target.height / 2)
|
|
2516
|
+
};
|
|
2517
|
+
const offset = output.x < input.x ? Math.min(portOffset, (input.x - output.x) / 2) : portOffset;
|
|
2518
|
+
return {
|
|
2519
|
+
id: edge.id,
|
|
2520
|
+
source: output,
|
|
2521
|
+
target: input,
|
|
2522
|
+
returnSide: input.x <= output.x ? Math.sign(input.y - output.y) : 0,
|
|
2523
|
+
start: {
|
|
2524
|
+
x: output.x + offset,
|
|
2525
|
+
y: output.y
|
|
2526
|
+
},
|
|
2527
|
+
end: {
|
|
2528
|
+
x: input.x - offset,
|
|
2529
|
+
y: input.y
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
});
|
|
2533
|
+
const obstacles = nodes.map((node) => ({
|
|
2534
|
+
left: node.x - clearance,
|
|
2535
|
+
right: node.x + node.width + clearance,
|
|
2536
|
+
top: node.y - clearance,
|
|
2537
|
+
bottom: node.y + node.height + clearance
|
|
2538
|
+
}));
|
|
2539
|
+
const routes = /* @__PURE__ */ new Map();
|
|
2540
|
+
const pending = connections.filter((edge) => {
|
|
2541
|
+
if (edge.start.x > edge.end.x) return true;
|
|
2542
|
+
const middle = (edge.start.x + edge.end.x) / 2;
|
|
2543
|
+
const points = [
|
|
2544
|
+
edge.start,
|
|
2545
|
+
{
|
|
2546
|
+
x: middle,
|
|
2547
|
+
y: edge.start.y
|
|
2548
|
+
},
|
|
2549
|
+
{
|
|
2550
|
+
x: middle,
|
|
2551
|
+
y: edge.end.y
|
|
2552
|
+
},
|
|
2553
|
+
edge.end
|
|
2554
|
+
];
|
|
2555
|
+
for (let index = 1; index < points.length; index++) {
|
|
2556
|
+
const a = points[index - 1];
|
|
2557
|
+
const b = points[index];
|
|
2558
|
+
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;
|
|
2289
2559
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
*
|
|
2313
|
-
*
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
*
|
|
2317
|
-
*
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
*
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
*
|
|
2325
|
-
*
|
|
2326
|
-
*
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2560
|
+
routes.set(edge.id, [
|
|
2561
|
+
edge.source,
|
|
2562
|
+
points[1],
|
|
2563
|
+
points[2],
|
|
2564
|
+
edge.target
|
|
2565
|
+
]);
|
|
2566
|
+
return false;
|
|
2567
|
+
});
|
|
2568
|
+
if (!pending.length) return routes;
|
|
2569
|
+
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);
|
|
2570
|
+
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);
|
|
2571
|
+
const xIndex = new Map(xs.map((value, index) => [value, index]));
|
|
2572
|
+
const yIndex = new Map(ys.map((value, index) => [value, index]));
|
|
2573
|
+
const columns = xs.length;
|
|
2574
|
+
const size = columns * ys.length;
|
|
2575
|
+
const horizontal = new Uint8Array(size);
|
|
2576
|
+
const vertical = new Uint8Array(size);
|
|
2577
|
+
for (const rect of obstacles) {
|
|
2578
|
+
const left = xIndex.get(rect.left);
|
|
2579
|
+
const right = xIndex.get(rect.right);
|
|
2580
|
+
const top = yIndex.get(rect.top);
|
|
2581
|
+
const bottom = yIndex.get(rect.bottom);
|
|
2582
|
+
for (let y = top + 1; y < bottom; y++) for (let x = left; x < right; x++) horizontal[y * columns + x] = 1;
|
|
2583
|
+
for (let x = left + 1; x < right; x++) for (let y = top; y < bottom; y++) vertical[y * columns + x] = 1;
|
|
2584
|
+
}
|
|
2585
|
+
const distances = new Float64Array(size * 2);
|
|
2586
|
+
const previous = new Int32Array(size * 2);
|
|
2587
|
+
const visited = new Uint32Array(size * 2);
|
|
2588
|
+
for (const [routeIndex, edge] of pending.entries()) {
|
|
2589
|
+
const generation = routeIndex + 1;
|
|
2590
|
+
const start = yIndex.get(edge.start.y) * columns + xIndex.get(edge.start.x);
|
|
2591
|
+
const end = yIndex.get(edge.end.y) * columns + xIndex.get(edge.end.x);
|
|
2592
|
+
const queue = [];
|
|
2593
|
+
const heuristic = (vertex) => Math.abs(xs[vertex % columns] - edge.end.x) + Math.abs(ys[Math.floor(vertex / columns)] - edge.end.y);
|
|
2594
|
+
distances[start * 2] = 0;
|
|
2595
|
+
previous[start * 2] = -1;
|
|
2596
|
+
visited[start * 2] = generation;
|
|
2597
|
+
enqueue(queue, {
|
|
2598
|
+
state: start * 2,
|
|
2599
|
+
score: heuristic(start)
|
|
2600
|
+
});
|
|
2601
|
+
let finish = -1;
|
|
2602
|
+
while (queue.length) {
|
|
2603
|
+
const entry = dequeue(queue);
|
|
2604
|
+
const vertex = Math.floor(entry.state / 2);
|
|
2605
|
+
if (entry.score > distances[entry.state] + heuristic(vertex) + 1e-6) continue;
|
|
2606
|
+
if (vertex === end) {
|
|
2607
|
+
finish = entry.state;
|
|
2608
|
+
break;
|
|
2609
|
+
}
|
|
2610
|
+
const x = vertex % columns;
|
|
2611
|
+
const y = Math.floor(vertex / columns);
|
|
2612
|
+
const moves = [
|
|
2613
|
+
x > 0 && !horizontal[vertex - 1] ? vertex - 1 : -1,
|
|
2614
|
+
x + 1 < columns && !horizontal[vertex] ? vertex + 1 : -1,
|
|
2615
|
+
y > 0 && !vertical[vertex - columns] ? vertex - columns : -1,
|
|
2616
|
+
y + 1 < ys.length && !vertical[vertex] ? vertex + columns : -1
|
|
2617
|
+
];
|
|
2618
|
+
for (const [index, next] of moves.entries()) {
|
|
2619
|
+
if (next < 0 || vertex === start && index === 0 || next === end && index === 0) continue;
|
|
2620
|
+
if (edge.returnSide * (ys[Math.floor(next / columns)] - edge.start.y) < -1e-6) continue;
|
|
2621
|
+
const axis = index < 2 ? 0 : 1;
|
|
2622
|
+
const state = next * 2 + axis;
|
|
2623
|
+
const length = Math.abs(xs[next % columns] - xs[x]) + Math.abs(ys[Math.floor(next / columns)] - ys[y]);
|
|
2624
|
+
const distance = distances[entry.state] + length + (entry.state % 2 === axis ? 0 : 8);
|
|
2625
|
+
if (visited[state] === generation && distance >= distances[state]) continue;
|
|
2626
|
+
visited[state] = generation;
|
|
2627
|
+
distances[state] = distance;
|
|
2628
|
+
previous[state] = entry.state;
|
|
2629
|
+
enqueue(queue, {
|
|
2630
|
+
state,
|
|
2631
|
+
score: distance + heuristic(next)
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2334
2634
|
}
|
|
2635
|
+
if (finish < 0) throw new Error("Could not route the compact workflow connection.");
|
|
2636
|
+
const points = [];
|
|
2637
|
+
for (let state = finish; state >= 0; state = previous[state]) {
|
|
2638
|
+
const vertex = Math.floor(state / 2);
|
|
2639
|
+
points.push({
|
|
2640
|
+
x: xs[vertex % columns],
|
|
2641
|
+
y: ys[Math.floor(vertex / columns)]
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
points.reverse();
|
|
2645
|
+
const turns = points.filter((point, index) => {
|
|
2646
|
+
const before = points[index - 1];
|
|
2647
|
+
const after = points[index + 1];
|
|
2648
|
+
return !before || !after || !(before.x === point.x && point.x === after.x || before.y === point.y && point.y === after.y);
|
|
2649
|
+
});
|
|
2650
|
+
routes.set(edge.id, [
|
|
2651
|
+
edge.source,
|
|
2652
|
+
...turns,
|
|
2653
|
+
edge.target
|
|
2654
|
+
]);
|
|
2335
2655
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2656
|
+
return routes;
|
|
2657
|
+
}
|
|
2658
|
+
function enqueue(queue, entry) {
|
|
2659
|
+
let index = queue.length;
|
|
2660
|
+
queue.push(entry);
|
|
2661
|
+
while (index > 0) {
|
|
2662
|
+
const parent = Math.floor((index - 1) / 2);
|
|
2663
|
+
if (queue[parent].score <= entry.score) break;
|
|
2664
|
+
queue[index] = queue[parent];
|
|
2665
|
+
index = parent;
|
|
2666
|
+
}
|
|
2667
|
+
queue[index] = entry;
|
|
2668
|
+
}
|
|
2669
|
+
function dequeue(queue) {
|
|
2670
|
+
const first = queue[0];
|
|
2671
|
+
const last = queue.pop();
|
|
2672
|
+
if (!queue.length) return first;
|
|
2673
|
+
let index = 0;
|
|
2674
|
+
while (index * 2 + 1 < queue.length) {
|
|
2675
|
+
let child = index * 2 + 1;
|
|
2676
|
+
if (child + 1 < queue.length && queue[child + 1].score < queue[child].score) child++;
|
|
2677
|
+
if (last.score <= queue[child].score) break;
|
|
2678
|
+
queue[index] = queue[child];
|
|
2679
|
+
index = child;
|
|
2680
|
+
}
|
|
2681
|
+
queue[index] = last;
|
|
2682
|
+
return first;
|
|
2345
2683
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2684
|
+
//#endregion
|
|
2685
|
+
//#region src/canvas/browser/base/compactLayout.ts
|
|
2686
|
+
function bounds(nodes, routes = /* @__PURE__ */ new Map()) {
|
|
2687
|
+
const points = [...routes.values()].flat();
|
|
2688
|
+
for (const node of nodes) points.push(node, {
|
|
2689
|
+
x: node.x + node.width,
|
|
2690
|
+
y: node.y + node.height
|
|
2691
|
+
});
|
|
2692
|
+
const x = Math.min(...points.map((point) => point.x));
|
|
2693
|
+
const y = Math.min(...points.map((point) => point.y));
|
|
2694
|
+
return {
|
|
2695
|
+
x,
|
|
2696
|
+
y,
|
|
2697
|
+
width: Math.max(...points.map((point) => point.x)) - x,
|
|
2698
|
+
height: Math.max(...points.map((point) => point.y)) - y
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
/** Place branches at their earliest dependency level, rather than delaying short
|
|
2702
|
+
* branches until the longest sibling reaches a shared join. Cycles remain one
|
|
2703
|
+
* component whose internal order follows the measured base layout. */
|
|
2704
|
+
function dependencyLevels(nodes, edges, gap) {
|
|
2705
|
+
const graph = new ie.Graph();
|
|
2706
|
+
for (const node of nodes) graph.setNode(node.id);
|
|
2707
|
+
for (const edge of edges) graph.setEdge(edge.source, edge.target);
|
|
2708
|
+
const components = ie.alg.tarjan(graph);
|
|
2709
|
+
const componentOf = new Map(components.flatMap((members, index) => members.map((id) => [id, String(index)])));
|
|
2710
|
+
const dependencies = new ie.Graph();
|
|
2711
|
+
for (let index = 0; index < components.length; index++) dependencies.setNode(String(index));
|
|
2712
|
+
for (const edge of edges) {
|
|
2713
|
+
const source = componentOf.get(edge.source);
|
|
2714
|
+
const target = componentOf.get(edge.target);
|
|
2715
|
+
if (source !== target) dependencies.setEdge(source, target);
|
|
2716
|
+
}
|
|
2717
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
2718
|
+
const levels = /* @__PURE__ */ new Map();
|
|
2719
|
+
const ends = /* @__PURE__ */ new Map();
|
|
2720
|
+
for (const id of ie.alg.topsort(dependencies)) {
|
|
2721
|
+
const start = Math.max(0, ...(dependencies.predecessors(id) ?? []).map((parent) => ends.get(parent) + 1));
|
|
2722
|
+
const members = components[Number(id)].map((member) => byId.get(member)).toSorted((a, b) => a.column - b.column || a.y - b.y);
|
|
2723
|
+
for (const [index, member] of members.entries()) levels.set(member.id, start + index);
|
|
2724
|
+
ends.set(id, start + members.length - 1);
|
|
2725
|
+
}
|
|
2726
|
+
const isolated = nodes.filter((node) => graph.nodeEdges(node.id)?.length === 0);
|
|
2727
|
+
const isolatedColumns = [...new Set(isolated.map((node) => node.column))].toSorted((a, b) => a - b);
|
|
2728
|
+
for (const node of isolated) levels.set(node.id, isolatedColumns.indexOf(node.column));
|
|
2729
|
+
let primary = 0;
|
|
2730
|
+
const groups = [...Map.groupBy(nodes, (node) => levels.get(node.id)).entries()].toSorted(([a], [b]) => a - b);
|
|
2731
|
+
for (const [level, members] of groups) {
|
|
2732
|
+
const size = Math.max(...members.map((node) => node.width));
|
|
2733
|
+
for (const node of members) Object.assign(node, {
|
|
2734
|
+
column: level,
|
|
2735
|
+
x: primary + (size - node.width) / 2
|
|
2736
|
+
});
|
|
2737
|
+
primary += size + gap;
|
|
2350
2738
|
}
|
|
2351
2739
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
}
|
|
2366
|
-
|
|
2367
|
-
|
|
2740
|
+
/** Compact each connected subgraph, then wrap the forest to the requested ratio. */
|
|
2741
|
+
function compactLayout(graph, insets = {
|
|
2742
|
+
width: 0,
|
|
2743
|
+
height: 0
|
|
2744
|
+
}, aspectRatio = 1) {
|
|
2745
|
+
if (!graph.nodes.length) return {
|
|
2746
|
+
positions: {},
|
|
2747
|
+
routes: /* @__PURE__ */ new Map(),
|
|
2748
|
+
bounds: {
|
|
2749
|
+
x: 0,
|
|
2750
|
+
y: 0,
|
|
2751
|
+
width: 320,
|
|
2752
|
+
height: 120
|
|
2753
|
+
}
|
|
2754
|
+
};
|
|
2755
|
+
const connected = new ie.Graph();
|
|
2756
|
+
for (const node of graph.nodes) connected.setNode(node.id);
|
|
2757
|
+
for (const edge of graph.edges) connected.setEdge(edge.source, edge.target);
|
|
2758
|
+
const members = ie.alg.components(connected);
|
|
2759
|
+
if (members.length === 1) return compactComponent(graph, insets, aspectRatio);
|
|
2760
|
+
const componentOf = new Map(members.flatMap((ids, index) => ids.map((id) => [id, index])));
|
|
2761
|
+
const edges = Map.groupBy(graph.edges, (edge) => componentOf.get(edge.source));
|
|
2762
|
+
return packComponents([...Map.groupBy(graph.nodes, (node) => componentOf.get(node.id))].map(([id, nodes]) => ({
|
|
2763
|
+
nodes,
|
|
2764
|
+
edges: edges.get(id) ?? [],
|
|
2765
|
+
bounds: bounds(nodes)
|
|
2766
|
+
})).toSorted((a, b) => a.bounds.x - b.bounds.x || a.bounds.y - b.bounds.y).map((component) => component.nodes.length === 1 && !component.edges.length ? {
|
|
2767
|
+
positions: { [component.nodes[0].id]: component.nodes[0] },
|
|
2768
|
+
routes: /* @__PURE__ */ new Map(),
|
|
2769
|
+
bounds: component.bounds
|
|
2770
|
+
} : compactComponent(component, {
|
|
2771
|
+
width: 0,
|
|
2772
|
+
height: 0
|
|
2773
|
+
}, aspectRatio)), insets, aspectRatio);
|
|
2774
|
+
}
|
|
2775
|
+
/** Keep reading order, with a larger gap between independent trees than within one. */
|
|
2776
|
+
function packComponents(layouts, insets, aspectRatio) {
|
|
2777
|
+
const gap = 96;
|
|
2778
|
+
const largestWidth = Math.max(...layouts.map((layout) => layout.bounds.width));
|
|
2779
|
+
const contentArea = layouts.reduce((sum, layout) => sum + layout.bounds.width * layout.bounds.height, 0);
|
|
2780
|
+
const limits = /* @__PURE__ */ new Set([largestWidth, Math.max(largestWidth, Math.sqrt(contentArea * aspectRatio))]);
|
|
2781
|
+
let prefixWidth = -96;
|
|
2782
|
+
for (const layout of layouts) {
|
|
2783
|
+
prefixWidth += layout.bounds.width + gap;
|
|
2784
|
+
limits.add(Math.max(largestWidth, prefixWidth));
|
|
2785
|
+
}
|
|
2786
|
+
let best;
|
|
2787
|
+
for (const limit of limits) {
|
|
2788
|
+
let x = 0;
|
|
2789
|
+
let y = 0;
|
|
2790
|
+
let width = 0;
|
|
2791
|
+
let rowHeight = 0;
|
|
2792
|
+
let rows = 1;
|
|
2793
|
+
const positions = layouts.map((layout) => {
|
|
2794
|
+
if (x > 0 && x + layout.bounds.width > limit + 1e-6) {
|
|
2795
|
+
y += rowHeight + gap;
|
|
2796
|
+
x = rowHeight = 0;
|
|
2797
|
+
rows++;
|
|
2798
|
+
}
|
|
2799
|
+
const position = {
|
|
2800
|
+
x: x - layout.bounds.x,
|
|
2801
|
+
y: y - layout.bounds.y
|
|
2802
|
+
};
|
|
2803
|
+
width = Math.max(width, x + layout.bounds.width);
|
|
2804
|
+
rowHeight = Math.max(rowHeight, layout.bounds.height);
|
|
2805
|
+
x += layout.bounds.width + gap;
|
|
2806
|
+
return position;
|
|
2807
|
+
});
|
|
2808
|
+
const height = y + rowHeight;
|
|
2809
|
+
const score = Math.max((width + insets.width) / aspectRatio, height + insets.height);
|
|
2810
|
+
const area = (width + insets.width) * (height + insets.height);
|
|
2811
|
+
if (!best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && (area < best.area || area === best.area && rows < best.rows)) best = {
|
|
2812
|
+
positions,
|
|
2813
|
+
width,
|
|
2814
|
+
height,
|
|
2815
|
+
score,
|
|
2816
|
+
area,
|
|
2817
|
+
rows
|
|
2818
|
+
};
|
|
2819
|
+
}
|
|
2820
|
+
const translate = (point, index) => ({
|
|
2821
|
+
x: point.x + best.positions[index].x,
|
|
2822
|
+
y: point.y + best.positions[index].y
|
|
2823
|
+
});
|
|
2824
|
+
return {
|
|
2825
|
+
positions: Object.fromEntries(layouts.flatMap((layout, index) => Object.entries(layout.positions).map(([id, point]) => [id, translate(point, index)]))),
|
|
2826
|
+
routes: new Map(layouts.flatMap((layout, index) => [...layout.routes].map(([id, points]) => [id, points.map((point) => translate(point, index))]))),
|
|
2827
|
+
bounds: {
|
|
2828
|
+
x: 0,
|
|
2829
|
+
y: 0,
|
|
2830
|
+
width: best.width,
|
|
2831
|
+
height: best.height
|
|
2832
|
+
}
|
|
2833
|
+
};
|
|
2368
2834
|
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2835
|
+
/** Bend dependency paths continuously; the ports retain their original orientation. */
|
|
2836
|
+
function compactComponent(graph, insets, aspectRatio) {
|
|
2837
|
+
const normalized = graph.nodes.map((node) => ({
|
|
2838
|
+
...node,
|
|
2839
|
+
...layoutAxes(node, "vertical"),
|
|
2840
|
+
width: node.height,
|
|
2841
|
+
height: node.width
|
|
2842
|
+
}));
|
|
2843
|
+
dependencyLevels(normalized, graph.edges, 48);
|
|
2844
|
+
const incoming = new Set(graph.edges.map((edge) => edge.target));
|
|
2845
|
+
const outgoing = new Set(graph.edges.map((edge) => edge.source));
|
|
2846
|
+
const roots = normalized.filter((node) => !incoming.has(node.id) && outgoing.has(node.id));
|
|
2847
|
+
const centers = (roots.length ? roots : normalized).map((node) => node.y + node.height / 2);
|
|
2848
|
+
const center = centers.reduce((sum, value) => sum + value, 0) / centers.length;
|
|
2849
|
+
const gap = 48;
|
|
2850
|
+
const pathNodes = normalized.filter((node) => incoming.has(node.id) || outgoing.has(node.id));
|
|
2851
|
+
const crossSize = Math.max(...(pathNodes.length ? pathNodes : normalized).map((node) => node.height));
|
|
2852
|
+
const bow = crossSize * .75;
|
|
2853
|
+
const separation = crossSize + 48;
|
|
2854
|
+
const bucketSize = Math.max(...normalized.map((node) => node.width)) + gap;
|
|
2855
|
+
const byId = new Map(normalized.map((node) => [node.id, node]));
|
|
2856
|
+
const forwardEdges = graph.edges.filter((edge) => byId.get(edge.source).column < byId.get(edge.target).column);
|
|
2857
|
+
const parents = Map.groupBy(forwardEdges, (edge) => edge.target);
|
|
2858
|
+
const children = Map.groupBy(forwardEdges, (edge) => edge.source);
|
|
2859
|
+
const ordered = normalized.toSorted((a, b) => a.column - b.column || a.y - b.y);
|
|
2860
|
+
const remaining = /* @__PURE__ */ new Map();
|
|
2861
|
+
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))));
|
|
2862
|
+
const rankEnds = new Map([...Map.groupBy(normalized, (node) => node.column)].map(([rank, nodes]) => [rank, Math.max(...nodes.map((node) => node.x + node.width))]));
|
|
2863
|
+
const spans = /* @__PURE__ */ new Set([Infinity, ...rankEnds.values()]);
|
|
2864
|
+
let best;
|
|
2865
|
+
for (const span of spans) {
|
|
2866
|
+
const placed = /* @__PURE__ */ new Map();
|
|
2867
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2868
|
+
let turns = 0;
|
|
2869
|
+
for (const original of ordered) {
|
|
2870
|
+
const upstream = parents.get(original.id)?.map((edge) => placed.get(edge.source)) ?? [];
|
|
2871
|
+
const parent = upstream[0];
|
|
2872
|
+
const side = original.y + original.height / 2 < center - 1e-6 ? -1 : 1;
|
|
2873
|
+
let primary = upstream.length ? Math.max(...upstream.map(({ node }) => {
|
|
2874
|
+
const source = byId.get(node.id);
|
|
2875
|
+
return node.x + rankEnds.get(source.column) - source.x;
|
|
2876
|
+
})) + gap : original.x;
|
|
2877
|
+
let shift = 0;
|
|
2878
|
+
let start = 0;
|
|
2879
|
+
if (upstream.length > 1) {
|
|
2880
|
+
primary = Math.max(...upstream.map((entry) => entry.extent)) + gap;
|
|
2881
|
+
shift = upstream.reduce((sum, { node }) => sum + node.y + node.height / 2, 0) / upstream.length - original.y - original.height / 2;
|
|
2882
|
+
start = primary;
|
|
2883
|
+
} else if (parent) {
|
|
2884
|
+
shift = parent.shift;
|
|
2885
|
+
start = parent.start;
|
|
2886
|
+
if ((children.get(parent.node.id)?.length ?? 0) > 1) {
|
|
2887
|
+
shift = parent.node.y - byId.get(parent.node.id).y;
|
|
2888
|
+
start = primary;
|
|
2889
|
+
} else if (primary + original.width > span && remaining.get(original.id) > 2) {
|
|
2890
|
+
primary = Math.max(0, start - span / 3);
|
|
2891
|
+
shift = parent.shift + side * separation;
|
|
2892
|
+
start = primary;
|
|
2893
|
+
turns++;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
const progress = Number.isFinite(span) && span > start ? Math.min(1, Math.max(0, (primary - start) / (span - start))) : 0;
|
|
2897
|
+
const drift = side * bow * Math.sin(progress * Math.PI);
|
|
2898
|
+
const node = {
|
|
2899
|
+
...original,
|
|
2900
|
+
x: primary,
|
|
2901
|
+
y: original.y + shift + drift
|
|
2902
|
+
};
|
|
2903
|
+
const firstBucket = Math.floor(node.x / bucketSize);
|
|
2904
|
+
const lastBucket = Math.floor((node.x + node.width + gap) / bucketSize);
|
|
2905
|
+
const nearby = /* @__PURE__ */ new Set();
|
|
2906
|
+
for (let bucket = firstBucket; bucket <= lastBucket; bucket++) for (const entry of buckets.get(bucket) ?? []) nearby.add(entry);
|
|
2907
|
+
const candidates = [...nearby].toSorted((a, b) => a.order - b.order);
|
|
2908
|
+
while (true) {
|
|
2909
|
+
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);
|
|
2910
|
+
if (!collision) break;
|
|
2911
|
+
node.y = side < 0 ? collision.node.y - node.height - 48 : collision.node.y + collision.node.height + 48;
|
|
2912
|
+
}
|
|
2913
|
+
const placement = {
|
|
2914
|
+
node,
|
|
2915
|
+
order: placed.size,
|
|
2916
|
+
shift: node.y - original.y - drift,
|
|
2917
|
+
start,
|
|
2918
|
+
extent: Math.max(node.x + node.width, ...upstream.map((entry) => entry.extent))
|
|
2919
|
+
};
|
|
2920
|
+
placed.set(node.id, placement);
|
|
2921
|
+
for (let bucket = firstBucket; bucket <= lastBucket; bucket++) {
|
|
2922
|
+
const entries = buckets.get(bucket);
|
|
2923
|
+
if (entries) entries.push(placement);
|
|
2924
|
+
else buckets.set(bucket, [placement]);
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
const nodes = [...placed.values()].map((entry) => entry.node);
|
|
2928
|
+
const extent = bounds(nodes);
|
|
2929
|
+
const width = extent.height + insets.width + 48;
|
|
2930
|
+
const height = extent.width + insets.height + 48;
|
|
2931
|
+
const area = width * height;
|
|
2932
|
+
const score = Math.max(width / aspectRatio, height);
|
|
2933
|
+
if (!best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && (area < best.area || area === best.area && turns < best.turns)) best = {
|
|
2934
|
+
nodes,
|
|
2935
|
+
score,
|
|
2936
|
+
area,
|
|
2937
|
+
turns
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2940
|
+
const routes = routeLayout(best.nodes, graph.edges.map((edge) => Object.assign({}, edge, {
|
|
2941
|
+
sourceOffset: edge.sourceOffset && layoutAxes(edge.sourceOffset, "vertical"),
|
|
2942
|
+
targetOffset: edge.targetOffset && layoutAxes(edge.targetOffset, "vertical")
|
|
2943
|
+
})));
|
|
2944
|
+
const physicalNodes = best.nodes.map((node) => Object.assign({}, node, layoutAxes(node, "vertical"), {
|
|
2945
|
+
width: node.height,
|
|
2946
|
+
height: node.width
|
|
2947
|
+
}));
|
|
2948
|
+
const physicalRoutes = new Map([...routes].map(([id, points]) => [id, points.map((point) => layoutAxes(point, "vertical"))]));
|
|
2949
|
+
return {
|
|
2950
|
+
positions: Object.fromEntries(physicalNodes.map(({ id, x, y }) => [id, {
|
|
2951
|
+
x,
|
|
2952
|
+
y
|
|
2953
|
+
}])),
|
|
2954
|
+
routes: physicalRoutes,
|
|
2955
|
+
bounds: bounds(physicalNodes, physicalRoutes)
|
|
2956
|
+
};
|
|
2371
2957
|
}
|
|
2372
2958
|
Array.isArray;
|
|
2373
2959
|
var isNumber = (value) => {
|
|
@@ -2389,117 +2975,6 @@ var cluster = (list2, size = 2) => {
|
|
|
2389
2975
|
});
|
|
2390
2976
|
};
|
|
2391
2977
|
//#endregion
|
|
2392
|
-
//#region ../../node_modules/.bun/value-enhancer@5.7.2/node_modules/value-enhancer/dist/collections.mjs
|
|
2393
|
-
var ReactiveMapImpl = class extends Map {
|
|
2394
|
-
constructor(entries, config) {
|
|
2395
|
-
super();
|
|
2396
|
-
if (config) this.#onDeleted = config.onDeleted;
|
|
2397
|
-
const [$, set$] = readonlyVal(this, { equal: false });
|
|
2398
|
-
this.$ = $;
|
|
2399
|
-
this.#notify = () => set$(this);
|
|
2400
|
-
if (entries) for (const [key, value] of entries) this.set(key, value);
|
|
2401
|
-
}
|
|
2402
|
-
$;
|
|
2403
|
-
#notify;
|
|
2404
|
-
#onDeleted;
|
|
2405
|
-
#delete(key) {
|
|
2406
|
-
if (this.#onDeleted) {
|
|
2407
|
-
if (super.has(key)) {
|
|
2408
|
-
const value = super.get(key);
|
|
2409
|
-
super.delete(key);
|
|
2410
|
-
this.#onDeleted(value);
|
|
2411
|
-
return true;
|
|
2412
|
-
}
|
|
2413
|
-
return false;
|
|
2414
|
-
}
|
|
2415
|
-
return super.delete(key);
|
|
2416
|
-
}
|
|
2417
|
-
#clear() {
|
|
2418
|
-
if (this.#onDeleted) {
|
|
2419
|
-
const deleted = new Set(this.values());
|
|
2420
|
-
super.clear();
|
|
2421
|
-
for (const value of deleted) this.#onDeleted(value);
|
|
2422
|
-
} else super.clear();
|
|
2423
|
-
}
|
|
2424
|
-
delete(key) {
|
|
2425
|
-
const deleted = this.#delete(key);
|
|
2426
|
-
if (deleted) this.#notify();
|
|
2427
|
-
return deleted;
|
|
2428
|
-
}
|
|
2429
|
-
batchDelete(keys) {
|
|
2430
|
-
let deleted = false;
|
|
2431
|
-
for (const key of keys) deleted = this.#delete(key) || deleted;
|
|
2432
|
-
if (deleted) this.#notify();
|
|
2433
|
-
return deleted;
|
|
2434
|
-
}
|
|
2435
|
-
clear() {
|
|
2436
|
-
if (this.size > 0) {
|
|
2437
|
-
this.#clear();
|
|
2438
|
-
this.#notify();
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
#set(key, value) {
|
|
2442
|
-
if (this.has(key)) {
|
|
2443
|
-
const oldValue = this.get(key);
|
|
2444
|
-
if (strictEqual(oldValue, value)) return false;
|
|
2445
|
-
super.set(key, value);
|
|
2446
|
-
if (this.#onDeleted) this.#onDeleted(oldValue);
|
|
2447
|
-
} else super.set(key, value);
|
|
2448
|
-
return true;
|
|
2449
|
-
}
|
|
2450
|
-
set(key, value) {
|
|
2451
|
-
if (this.#set(key, value)) this.#notify();
|
|
2452
|
-
return this;
|
|
2453
|
-
}
|
|
2454
|
-
batchSet(entries) {
|
|
2455
|
-
let isDirty = false;
|
|
2456
|
-
for (const [key, value] of entries) isDirty = this.#set(key, value) || isDirty;
|
|
2457
|
-
if (isDirty) this.#notify();
|
|
2458
|
-
return this;
|
|
2459
|
-
}
|
|
2460
|
-
rename(oldKey, newKey) {
|
|
2461
|
-
if (!strictEqual(oldKey, newKey)) {
|
|
2462
|
-
const value = this.get(oldKey);
|
|
2463
|
-
if (super.delete(oldKey)) {
|
|
2464
|
-
this.set(newKey, value);
|
|
2465
|
-
return true;
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
return false;
|
|
2469
|
-
}
|
|
2470
|
-
replace(entries) {
|
|
2471
|
-
const oldMap = new Map(this);
|
|
2472
|
-
const deletedValues = new Set(this.values());
|
|
2473
|
-
let hasNewValue = false;
|
|
2474
|
-
super.clear();
|
|
2475
|
-
for (const [key, value] of entries) {
|
|
2476
|
-
super.set(key, value);
|
|
2477
|
-
deletedValues.delete(value);
|
|
2478
|
-
hasNewValue = hasNewValue || !oldMap.has(key) || !Object.is(oldMap.get(key), value);
|
|
2479
|
-
oldMap.delete(key);
|
|
2480
|
-
}
|
|
2481
|
-
if (hasNewValue || oldMap.size > 0 || deletedValues.size > 0) {
|
|
2482
|
-
if (this.#onDeleted) for (const value of deletedValues) this.#onDeleted(value);
|
|
2483
|
-
this.#notify();
|
|
2484
|
-
}
|
|
2485
|
-
return deletedValues.values();
|
|
2486
|
-
}
|
|
2487
|
-
toJSON() {
|
|
2488
|
-
const result = {};
|
|
2489
|
-
for (const [key, value] of this) if (key != null) {
|
|
2490
|
-
const k = String(key);
|
|
2491
|
-
const v = value;
|
|
2492
|
-
result[k] = v && v.toJSON ? v.toJSON(k) : v;
|
|
2493
|
-
}
|
|
2494
|
-
return result;
|
|
2495
|
-
}
|
|
2496
|
-
dispose() {
|
|
2497
|
-
this.$.dispose();
|
|
2498
|
-
if (this.size > 0) this.#clear();
|
|
2499
|
-
}
|
|
2500
|
-
};
|
|
2501
|
-
var reactiveMap = (entries, config) => new ReactiveMapImpl(entries, config);
|
|
2502
|
-
//#endregion
|
|
2503
2978
|
//#region src/canvas/browser/base/compare.ts
|
|
2504
2979
|
var isSameXYPosition = (p1, p2) => !p1 || !p2 ? p1 === p2 : p1.x === p2.x && p1.y === p2.y;
|
|
2505
2980
|
var isSize = (s) => isPlainObject(s) && isNumber(s.width) && isNumber(s.height);
|
|
@@ -2550,6 +3025,63 @@ function isInside(target, selector) {
|
|
|
2550
3025
|
return target?.closest?.(selector) != null;
|
|
2551
3026
|
}
|
|
2552
3027
|
//#endregion
|
|
3028
|
+
//#region src/canvas/browser/base/graphLayout.ts
|
|
3029
|
+
/** The measured dependency layout shared by canvas arrangement and image export. */
|
|
3030
|
+
function graphLayout(nodes, edges, direction) {
|
|
3031
|
+
if (!nodes.length) return {
|
|
3032
|
+
nodes: [],
|
|
3033
|
+
edges: []
|
|
3034
|
+
};
|
|
3035
|
+
const graph = new ie.Graph().setDefaultEdgeLabel(() => ({}));
|
|
3036
|
+
graph.setGraph({
|
|
3037
|
+
rankdir: direction === "vertical" ? "TB" : "LR",
|
|
3038
|
+
ranksep: direction === "vertical" ? 48 : 80
|
|
3039
|
+
});
|
|
3040
|
+
const singles = new Set(nodes.map((node) => node.id));
|
|
3041
|
+
for (const node of nodes) graph.setNode(node.id, {
|
|
3042
|
+
width: node.width,
|
|
3043
|
+
height: node.height
|
|
3044
|
+
});
|
|
3045
|
+
const connections = edges.filter((edge) => graph.hasNode(edge.source) && graph.hasNode(edge.target));
|
|
3046
|
+
for (const edge of connections) {
|
|
3047
|
+
singles.delete(edge.source);
|
|
3048
|
+
singles.delete(edge.target);
|
|
3049
|
+
graph.setEdge(edge.source, edge.target);
|
|
3050
|
+
}
|
|
3051
|
+
const isolated = [...singles];
|
|
3052
|
+
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]);
|
|
3053
|
+
const constraints = [];
|
|
3054
|
+
const ordering = new ie.Graph();
|
|
3055
|
+
for (const node of nodes) {
|
|
3056
|
+
const targets = [...new Set(node.branchHandles?.flatMap((handle) => connections.filter((edge) => edge.source === node.id && edge.sourceHandle === handle).map((edge) => edge.target)))];
|
|
3057
|
+
for (let index = 1; index < targets.length; index++) {
|
|
3058
|
+
const left = targets[index - 1];
|
|
3059
|
+
const right = targets[index];
|
|
3060
|
+
ordering.setEdge(left, right);
|
|
3061
|
+
if (ie.alg.isAcyclic(ordering)) constraints.push({
|
|
3062
|
+
left,
|
|
3063
|
+
right
|
|
3064
|
+
});
|
|
3065
|
+
else ordering.removeEdge(left, right);
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
Oe(graph, { constraints });
|
|
3069
|
+
return {
|
|
3070
|
+
nodes: nodes.map((node) => {
|
|
3071
|
+
const { x, y, width, height, rank } = graph.node(node.id);
|
|
3072
|
+
return {
|
|
3073
|
+
id: node.id,
|
|
3074
|
+
column: rank,
|
|
3075
|
+
x: x - width / 2,
|
|
3076
|
+
y: y - height / 2,
|
|
3077
|
+
width,
|
|
3078
|
+
height
|
|
3079
|
+
};
|
|
3080
|
+
}),
|
|
3081
|
+
edges: connections.map((edge) => Object.assign({}, edge, { points: graph.edge(edge.source, edge.target).points }))
|
|
3082
|
+
};
|
|
3083
|
+
}
|
|
3084
|
+
//#endregion
|
|
2553
3085
|
//#region src/canvas/browser/stores/node/constants.ts
|
|
2554
3086
|
var NODE_TYPE = /* @__PURE__ */ function(NODE_TYPE) {
|
|
2555
3087
|
NODE_TYPE["TaskNode"] = "task_node";
|
|
@@ -3183,6 +3715,7 @@ var CanvasStore = class {
|
|
|
3183
3715
|
constructor(model, editable, language, callbacks, autoLayout = false, interactiveMode$) {
|
|
3184
3716
|
this.canDeleteNodes = true;
|
|
3185
3717
|
this.dispose = disposableStore();
|
|
3718
|
+
this.connectionRoutes = this.dispose.add(val(/* @__PURE__ */ new Map()));
|
|
3186
3719
|
this.ignoredNodeIds = this.dispose.add(val([]));
|
|
3187
3720
|
this.ignoreNodes = (nodeIds, ignored) => {
|
|
3188
3721
|
if (this.$.editable.value) this.#callbacks.onIgnoreNodes?.(nodeIds, ignored);
|
|
@@ -3422,7 +3955,7 @@ var CanvasStore = class {
|
|
|
3422
3955
|
this.$$.changingDirection.set(false);
|
|
3423
3956
|
}
|
|
3424
3957
|
allLayoutNodes() {
|
|
3425
|
-
return [...this.$.nodes.values()];
|
|
3958
|
+
return [...this.$.nodes.values(), ...this.$.commentNodes?.values() ?? []];
|
|
3426
3959
|
}
|
|
3427
3960
|
/** Deletes nodes programmatically, such as from a menu action. */
|
|
3428
3961
|
async deleteNodes(nodes, skipConfirm) {
|
|
@@ -3447,7 +3980,7 @@ var CanvasStore = class {
|
|
|
3447
3980
|
}
|
|
3448
3981
|
doRelayout(availableWidth) {
|
|
3449
3982
|
const selected = this.$.selectedNodes.value.length > 1 ? this.$.selectedNodes.value : [];
|
|
3450
|
-
const nodes = selected.length > 0 ? selected
|
|
3983
|
+
const nodes = selected.length > 0 ? selected : this.allLayoutNodes();
|
|
3451
3984
|
if (nodes.length === 0) return;
|
|
3452
3985
|
let positions = this.layoutPositions(nodes, availableWidth);
|
|
3453
3986
|
if (selected.length > 0) {
|
|
@@ -3467,65 +4000,52 @@ var CanvasStore = class {
|
|
|
3467
4000
|
if (position) node.$$.position.set(position);
|
|
3468
4001
|
}
|
|
3469
4002
|
}
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
ranksep: 80
|
|
3475
|
-
});
|
|
3476
|
-
const singles = /* @__PURE__ */ new Set();
|
|
3477
|
-
for (const node of nodes) {
|
|
3478
|
-
const { id, measured } = node.$.rfNode.value;
|
|
3479
|
-
singles.add(id);
|
|
3480
|
-
g.setNode(id, {
|
|
3481
|
-
width: measured?.width ?? 0,
|
|
3482
|
-
height: measured?.height ?? 0
|
|
3483
|
-
});
|
|
3484
|
-
}
|
|
3485
|
-
for (const rfEdge of this.$.rfEdges.value) {
|
|
3486
|
-
if (!g.hasNode(rfEdge.source) || !g.hasNode(rfEdge.target)) continue;
|
|
3487
|
-
singles.delete(rfEdge.source);
|
|
3488
|
-
singles.delete(rfEdge.target);
|
|
3489
|
-
g.setEdge(rfEdge.source, rfEdge.target);
|
|
3490
|
-
}
|
|
3491
|
-
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]);
|
|
3492
|
-
const constraints = [];
|
|
3493
|
-
const ordering = new ie.Graph();
|
|
3494
|
-
for (const node of nodes) {
|
|
3495
|
-
const content = node.content$.value;
|
|
3496
|
-
if (content.kind !== "condition" && content.kind !== "approval" && content.kind !== "wait") continue;
|
|
3497
|
-
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) => {
|
|
3498
|
-
const target = this.$.nodes.get(edge.target);
|
|
3499
|
-
return target && g.hasNode(target.rfNodeId) ? [target.rfNodeId] : [];
|
|
3500
|
-
}) : []))];
|
|
3501
|
-
for (let index = 1; index < targets.length; index++) {
|
|
3502
|
-
const left = targets[index - 1];
|
|
3503
|
-
const right = targets[index];
|
|
3504
|
-
ordering.setEdge(left, right);
|
|
3505
|
-
if (ie.alg.isAcyclic(ordering)) constraints.push({
|
|
3506
|
-
left,
|
|
3507
|
-
right
|
|
3508
|
-
});
|
|
3509
|
-
else ordering.removeEdge(left, right);
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
Oe(g, { constraints });
|
|
3513
|
-
const layoutNodes = nodes.map((node) => {
|
|
3514
|
-
const { x, y, width, height, rank } = g.node(node.rfNodeId);
|
|
4003
|
+
measuredLayout(nodes) {
|
|
4004
|
+
return graphLayout(nodes.map((node) => {
|
|
4005
|
+
const measured = node.$.measured.value;
|
|
4006
|
+
const content = NodeStore.is(node) ? node.content$.value : void 0;
|
|
3515
4007
|
return {
|
|
3516
4008
|
id: node.nodeId,
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
width,
|
|
3521
|
-
height
|
|
4009
|
+
width: measured?.width ?? 0,
|
|
4010
|
+
height: measured?.height ?? 0,
|
|
4011
|
+
branchHandles: content?.kind === "condition" || content?.kind === "approval" || content?.kind === "wait" ? content.outputs.flatMap((port) => "handle" in port ? ["$branch:" + port.handle] : []) : void 0
|
|
3522
4012
|
};
|
|
3523
|
-
})
|
|
4013
|
+
}), this.#connections.value.map((edge) => ({
|
|
4014
|
+
...edge,
|
|
4015
|
+
id: getRFEdgeId(edge)
|
|
4016
|
+
})), this.$.direction.value);
|
|
4017
|
+
}
|
|
4018
|
+
layoutPositions(nodes, availableWidth) {
|
|
4019
|
+
const { nodes: layoutNodes } = this.measuredLayout(nodes);
|
|
3524
4020
|
return this.$.direction.value === "horizontal" ? wrapLayout(layoutNodes, availableWidth) : Object.fromEntries(layoutNodes.map(({ id, x, y }) => [id, {
|
|
3525
4021
|
x,
|
|
3526
4022
|
y
|
|
3527
4023
|
}]));
|
|
3528
4024
|
}
|
|
4025
|
+
/** Arrange the isolated export store without saving presentation or history. */
|
|
4026
|
+
compactForExport(insets, instance, aspectRatio = 1) {
|
|
4027
|
+
const graph = this.measuredLayout(this.allLayoutNodes());
|
|
4028
|
+
const port = (id, handle, type) => {
|
|
4029
|
+
const node = this.$.nodes.get(id);
|
|
4030
|
+
const measured = (node && instance?.getInternalNode(node.rfNodeId)?.internals.handleBounds?.[type])?.find((entry) => entry.id === `h:${handle}`);
|
|
4031
|
+
return measured && {
|
|
4032
|
+
x: measured.x + measured.width / 2,
|
|
4033
|
+
y: measured.y + (type === "source" ? measured.height : 0)
|
|
4034
|
+
};
|
|
4035
|
+
};
|
|
4036
|
+
const connections = new Map(this.#connections.value.map((edge) => [getRFEdgeId(edge), edge]));
|
|
4037
|
+
const edges = graph.edges.map((edge) => Object.assign({}, edge, {
|
|
4038
|
+
sourceOffset: port(edge.source, connections.get(edge.id)?.sourceHandle, "source"),
|
|
4039
|
+
targetOffset: port(edge.target, connections.get(edge.id)?.targetHandle, "target")
|
|
4040
|
+
}));
|
|
4041
|
+
const result = compactLayout({
|
|
4042
|
+
nodes: graph.nodes,
|
|
4043
|
+
edges
|
|
4044
|
+
}, insets, aspectRatio);
|
|
4045
|
+
this.applyPositions(result.positions);
|
|
4046
|
+
this.connectionRoutes.set(result.routes);
|
|
4047
|
+
return result.bounds;
|
|
4048
|
+
}
|
|
3529
4049
|
doRemoveNodes(nodes) {
|
|
3530
4050
|
if (this.disposed || !nodes?.size) return;
|
|
3531
4051
|
for (const node of nodes) this.pendingNodeDeletes.add(node);
|
|
@@ -14698,11 +15218,47 @@ function connectionNodeBounds(node) {
|
|
|
14698
15218
|
};
|
|
14699
15219
|
}
|
|
14700
15220
|
/** Align arrows with their ports and route returns outside both cards. */
|
|
14701
|
-
function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
|
|
15221
|
+
function getConnectionPath({ sourceBounds, targetBounds, waypoints, ...params }) {
|
|
14702
15222
|
const { sourcePosition = Position.Bottom, targetPosition = Position.Top } = params;
|
|
14703
15223
|
const vertical = sourcePosition === Position.Bottom && targetPosition === Position.Top || sourcePosition === Position.Top && targetPosition === Position.Bottom;
|
|
14704
15224
|
const reverse = sourcePosition === Position.Left && targetPosition === Position.Right || sourcePosition === Position.Top && targetPosition === Position.Bottom;
|
|
14705
15225
|
const horizontal = sourcePosition === Position.Right && targetPosition === Position.Left || sourcePosition === Position.Left && targetPosition === Position.Right;
|
|
15226
|
+
if (waypoints && waypoints.length > 2) {
|
|
15227
|
+
const interior = waypoints.slice(1, -1);
|
|
15228
|
+
const first = interior[0];
|
|
15229
|
+
const last = interior.at(-1);
|
|
15230
|
+
const points = [
|
|
15231
|
+
{
|
|
15232
|
+
x: params.sourceX,
|
|
15233
|
+
y: params.sourceY
|
|
15234
|
+
},
|
|
15235
|
+
vertical ? {
|
|
15236
|
+
x: params.sourceX,
|
|
15237
|
+
y: first.y
|
|
15238
|
+
} : {
|
|
15239
|
+
x: first.x,
|
|
15240
|
+
y: params.sourceY
|
|
15241
|
+
},
|
|
15242
|
+
...interior,
|
|
15243
|
+
vertical ? {
|
|
15244
|
+
x: params.targetX,
|
|
15245
|
+
y: last.y
|
|
15246
|
+
} : {
|
|
15247
|
+
x: last.x,
|
|
15248
|
+
y: params.targetY
|
|
15249
|
+
},
|
|
15250
|
+
{
|
|
15251
|
+
x: params.targetX,
|
|
15252
|
+
y: params.targetY
|
|
15253
|
+
}
|
|
15254
|
+
];
|
|
15255
|
+
const label = interior[Math.floor(interior.length / 2)];
|
|
15256
|
+
return [
|
|
15257
|
+
roundedConnectionPath(points),
|
|
15258
|
+
label.x,
|
|
15259
|
+
label.y
|
|
15260
|
+
];
|
|
15261
|
+
}
|
|
14706
15262
|
const primary = (x, y) => vertical ? y : x;
|
|
14707
15263
|
const cross = (x, y) => vertical ? x : y;
|
|
14708
15264
|
const sourceX = primary(params.sourceX, params.sourceY);
|
|
@@ -14787,6 +15343,15 @@ function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
|
|
|
14787
15343
|
y: point.x
|
|
14788
15344
|
} : point);
|
|
14789
15345
|
if (reverse) points.reverse();
|
|
15346
|
+
const middle = (left + right) / 2;
|
|
15347
|
+
return [
|
|
15348
|
+
roundedConnectionPath(points),
|
|
15349
|
+
vertical ? laneY : middle,
|
|
15350
|
+
vertical ? middle : laneY
|
|
15351
|
+
];
|
|
15352
|
+
}
|
|
15353
|
+
function roundedConnectionPath(input) {
|
|
15354
|
+
const points = input.filter((point, index) => index === 0 || point.x !== input[index - 1].x || point.y !== input[index - 1].y);
|
|
14790
15355
|
const radius = 16;
|
|
14791
15356
|
let path = `M ${points[0].x} ${points[0].y}`;
|
|
14792
15357
|
for (let i = 1; i < points.length - 1; i++) {
|
|
@@ -14800,12 +15365,7 @@ function getConnectionPath({ sourceBounds, targetBounds, ...params }) {
|
|
|
14800
15365
|
path += ` Q ${corner.x} ${corner.y} ${corner.x + (next.x - corner.x) * r / after} ${corner.y + (next.y - corner.y) * r / after}`;
|
|
14801
15366
|
}
|
|
14802
15367
|
const end = points.at(-1);
|
|
14803
|
-
|
|
14804
|
-
return [
|
|
14805
|
-
`${path} L ${end.x} ${end.y}`,
|
|
14806
|
-
vertical ? laneY : middle,
|
|
14807
|
-
vertical ? middle : laneY
|
|
14808
|
-
];
|
|
15368
|
+
return `${path} L ${end.x} ${end.y}`;
|
|
14809
15369
|
}
|
|
14810
15370
|
//#endregion
|
|
14811
15371
|
//#region src/canvas/browser/graph/Edges/EdgeGradient.tsx
|
|
@@ -14834,12 +15394,14 @@ function BasicEdge(props) {
|
|
|
14834
15394
|
const error = useVal(edgeStore?.$.error);
|
|
14835
15395
|
const canvasStore = useCanvasStore();
|
|
14836
15396
|
const scale = useVal(canvasStore.$.scale);
|
|
15397
|
+
const routes = useVal(canvasStore.connectionRoutes);
|
|
14837
15398
|
const gap = 3;
|
|
14838
15399
|
const targetX = props.targetX + (props.targetPosition == Position.Left ? -3 : props.targetPosition == Position.Right ? gap : 0);
|
|
14839
15400
|
const targetY = props.targetY + (props.targetPosition == Position.Top ? -3 : props.targetPosition == Position.Bottom ? gap : 0);
|
|
14840
15401
|
const sourceNode = useInternalNode(props.source);
|
|
14841
15402
|
const targetNode = useInternalNode(props.target);
|
|
14842
15403
|
const [path, labelX, labelY] = getConnectionPath({
|
|
15404
|
+
waypoints: routes.get(props.id),
|
|
14843
15405
|
sourceBounds: connectionNodeBounds(sourceNode),
|
|
14844
15406
|
targetBounds: connectionNodeBounds(targetNode),
|
|
14845
15407
|
sourceX: props.sourceX,
|
|
@@ -20228,31 +20790,55 @@ function CommentNodeActions({ canvasStore, nodeStore }) {
|
|
|
20228
20790
|
});
|
|
20229
20791
|
}
|
|
20230
20792
|
var CommentNodeContent_module_default = {
|
|
20231
|
-
body: "
|
|
20232
|
-
container: "
|
|
20233
|
-
resizeButton: "
|
|
20234
|
-
sourceCode: "
|
|
20235
|
-
markdown: "
|
|
20236
|
-
taskCheckbox: "
|
|
20793
|
+
body: "CommentNodeContent_body_7c741",
|
|
20794
|
+
container: "CommentNodeContent_container_7c741",
|
|
20795
|
+
resizeButton: "CommentNodeContent_resizeButton_7c741",
|
|
20796
|
+
sourceCode: "CommentNodeContent_sourceCode_7c741",
|
|
20797
|
+
markdown: "CommentNodeContent_markdown_7c741",
|
|
20798
|
+
taskCheckbox: "CommentNodeContent_taskCheckbox_7c741"
|
|
20237
20799
|
};
|
|
20238
20800
|
//#endregion
|
|
20239
|
-
//#region src/ui/browser/
|
|
20240
|
-
|
|
20241
|
-
|
|
20242
|
-
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
|
|
20246
|
-
}
|
|
20247
|
-
|
|
20801
|
+
//#region src/ui/browser/markdown/videoLink.ts
|
|
20802
|
+
function getVideoLink(href) {
|
|
20803
|
+
let url;
|
|
20804
|
+
try {
|
|
20805
|
+
url = new URL(href);
|
|
20806
|
+
} catch {
|
|
20807
|
+
return;
|
|
20808
|
+
}
|
|
20809
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return;
|
|
20810
|
+
const host = url.hostname.replace(/^www\./, "");
|
|
20811
|
+
const youtubeId = host === "youtube.com" && url.pathname === "/watch" ? url.searchParams.get("v") : host === "youtu.be" ? url.pathname.slice(1) : null;
|
|
20812
|
+
if (youtubeId && /^[a-zA-Z0-9_-]+$/.test(youtubeId)) return {
|
|
20813
|
+
src: `https://www.youtube.com/embed/${youtubeId}`,
|
|
20814
|
+
titleKey: "markdown.videoYouTube"
|
|
20815
|
+
};
|
|
20816
|
+
const bilibiliId = host === "bilibili.com" ? url.pathname.match(/^\/video\/(BV[a-zA-Z0-9]+)\/?$/)?.[1] : void 0;
|
|
20817
|
+
if (bilibiliId) return {
|
|
20818
|
+
src: `https://player.bilibili.com/player.html?bvid=${bilibiliId}&autoplay=0`,
|
|
20819
|
+
titleKey: "markdown.videoBilibili"
|
|
20820
|
+
};
|
|
20821
|
+
}
|
|
20822
|
+
function pasteVideoLink(event, t) {
|
|
20823
|
+
const textarea = event.currentTarget;
|
|
20824
|
+
if (event.defaultPrevented || textarea.readOnly || textarea.disabled) return;
|
|
20825
|
+
const href = event.clipboardData.getData("text/plain").trim();
|
|
20826
|
+
if (/\s/.test(href)) return;
|
|
20827
|
+
const video = getVideoLink(href);
|
|
20828
|
+
if (!video) return;
|
|
20829
|
+
const destination = href.replaceAll("(", "%28").replaceAll(")", "%29");
|
|
20830
|
+
const markdown = `[](${destination})`;
|
|
20831
|
+
event.preventDefault();
|
|
20832
|
+
textarea.ownerDocument.execCommand("insertText", false, markdown);
|
|
20833
|
+
}
|
|
20248
20834
|
var markdownPreview_module_default = {
|
|
20249
|
-
container: "
|
|
20250
|
-
body: "
|
|
20251
|
-
draggable: "
|
|
20835
|
+
container: "markdownPreview_container_2a1d9",
|
|
20836
|
+
body: "markdownPreview_body_2a1d9",
|
|
20837
|
+
draggable: "markdownPreview_draggable_2a1d9"
|
|
20252
20838
|
};
|
|
20253
20839
|
//#endregion
|
|
20254
20840
|
//#region src/canvas/browser/preview/markdownPreview.tsx
|
|
20255
|
-
var MarkdownContent = lazy(() => import("./markdownContent-
|
|
20841
|
+
var MarkdownContent = lazy(() => import("./markdownContent-B-GLj5DU.js"));
|
|
20256
20842
|
var MarkdownPreview = /* @__PURE__ */ memo(({ dark, unstyled, components, contentClassName, content, draggable, onDoubleClick }) => {
|
|
20257
20843
|
const [focus, setFocus] = useState(false);
|
|
20258
20844
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -20261,8 +20847,9 @@ var MarkdownPreview = /* @__PURE__ */ memo(({ dark, unstyled, components, conten
|
|
|
20261
20847
|
onFocus: () => setFocus(true),
|
|
20262
20848
|
onBlur: () => setFocus(false),
|
|
20263
20849
|
onDoubleClick,
|
|
20264
|
-
children: /* @__PURE__ */ jsx(
|
|
20850
|
+
children: /* @__PURE__ */ jsx(ScrollArea, {
|
|
20265
20851
|
className: `${markdownPreview_module_default.body} markdown-body`,
|
|
20852
|
+
autoHide: "leave",
|
|
20266
20853
|
children: /* @__PURE__ */ jsx(Suspense, {
|
|
20267
20854
|
fallback: /* @__PURE__ */ jsx("span", {
|
|
20268
20855
|
hidden: true,
|
|
@@ -20440,6 +21027,7 @@ function CommentNodeContent({ store }) {
|
|
|
20440
21027
|
setComposing(false);
|
|
20441
21028
|
},
|
|
20442
21029
|
onChange: (event) => store.$$.content.set(event.target.value),
|
|
21030
|
+
onPaste: (event) => pasteVideoLink(event, t),
|
|
20443
21031
|
onBlur: (event) => {
|
|
20444
21032
|
setFocused(false);
|
|
20445
21033
|
if (editable && !composing) store.saveContent(event.target.value);
|
|
@@ -20694,9 +21282,6 @@ function CommentTitle({ store }) {
|
|
|
20694
21282
|
});
|
|
20695
21283
|
}
|
|
20696
21284
|
//#endregion
|
|
20697
|
-
//#region src/canvas/browser/nodeActions.tsx
|
|
20698
|
-
var NodeHistoryContext = createContext(void 0);
|
|
20699
|
-
//#endregion
|
|
20700
21285
|
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/context-menu/root/ContextMenuRoot.js
|
|
20701
21286
|
/**
|
|
20702
21287
|
* A component that creates a context menu activated by right clicking or long pressing.
|
|
@@ -20965,16 +21550,7 @@ function NodeHeadContextMenu({ canvasStore, children }) {
|
|
|
20965
21550
|
function useNodeMenuItems({ t, nodeStore, onDelete, editable }) {
|
|
20966
21551
|
const skip = useVal(NodeStore.to(nodeStore)?.ignore);
|
|
20967
21552
|
const { duplicateNode } = nodeStore;
|
|
20968
|
-
const history = useContext(NodeHistoryContext)?.(nodeStore.nodeId);
|
|
20969
21553
|
return coalesce([
|
|
20970
|
-
history && {
|
|
20971
|
-
...history,
|
|
20972
|
-
key: "$history",
|
|
20973
|
-
icon: /* @__PURE__ */ jsx("i", {
|
|
20974
|
-
"aria-hidden": "true",
|
|
20975
|
-
className: "i-lucide-light:database"
|
|
20976
|
-
})
|
|
20977
|
-
},
|
|
20978
21554
|
editable && duplicateNode && {
|
|
20979
21555
|
label: t("nodeActions.duplicate"),
|
|
20980
21556
|
key: "$duplicate",
|
|
@@ -21720,9 +22296,6 @@ var stateAttributesMapping = {
|
|
|
21720
22296
|
...fieldValidityMapping
|
|
21721
22297
|
};
|
|
21722
22298
|
//#endregion
|
|
21723
|
-
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/constants.js
|
|
21724
|
-
var ACTIVE_COMPOSITE_ITEM = "data-composite-item-active";
|
|
21725
|
-
//#endregion
|
|
21726
22299
|
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio-group/RadioGroupContext.js
|
|
21727
22300
|
var RadioGroupContext = /*#__PURE__*/ React.createContext(void 0);
|
|
21728
22301
|
if (process.env.NODE_ENV !== "production") RadioGroupContext.displayName = "RadioGroupContext";
|
|
@@ -21904,238 +22477,6 @@ var RadioRoot = /*#__PURE__*/ React.forwardRef(function RadioRoot(componentProps
|
|
|
21904
22477
|
});
|
|
21905
22478
|
if (process.env.NODE_ENV !== "production") RadioRoot.displayName = "RadioRoot";
|
|
21906
22479
|
//#endregion
|
|
21907
|
-
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/useCompositeRoot.js
|
|
21908
|
-
var EMPTY_ARRAY = [];
|
|
21909
|
-
function useCompositeRoot(params) {
|
|
21910
|
-
const { itemSizes, cols = 1, loopFocus = true, onLoop, dense = false, orientation = "both", direction, highlightedIndex: externalHighlightedIndex, onHighlightedIndexChange: externalSetHighlightedIndex, rootRef: externalRef, enableHomeAndEndKeys = false, stopEventPropagation = false, disabledIndices, modifierKeys = EMPTY_ARRAY } = params;
|
|
21911
|
-
const [internalHighlightedIndex, internalSetHighlightedIndex] = React.useState(0);
|
|
21912
|
-
const isGrid = cols > 1;
|
|
21913
|
-
const rootRef = React.useRef(null);
|
|
21914
|
-
const mergedRef = useMergedRefs(rootRef, externalRef);
|
|
21915
|
-
const elementsRef = React.useRef([]);
|
|
21916
|
-
const hasSetDefaultIndexRef = React.useRef(false);
|
|
21917
|
-
const highlightedIndex = externalHighlightedIndex ?? internalHighlightedIndex;
|
|
21918
|
-
const onHighlightedIndexChange = useStableCallback((index, shouldScrollIntoView = false) => {
|
|
21919
|
-
(externalSetHighlightedIndex ?? internalSetHighlightedIndex)(index);
|
|
21920
|
-
if (shouldScrollIntoView) {
|
|
21921
|
-
const newActiveItem = elementsRef.current[index];
|
|
21922
|
-
scrollIntoViewIfNeeded(rootRef.current, newActiveItem, direction, orientation);
|
|
21923
|
-
}
|
|
21924
|
-
});
|
|
21925
|
-
const onMapChange = useStableCallback((map) => {
|
|
21926
|
-
if (map.size === 0 || hasSetDefaultIndexRef.current) return;
|
|
21927
|
-
hasSetDefaultIndexRef.current = true;
|
|
21928
|
-
const sortedElements = Array.from(map.keys());
|
|
21929
|
-
const activeItem = sortedElements.find((compositeElement) => compositeElement?.hasAttribute("data-composite-item-active")) ?? null;
|
|
21930
|
-
const activeIndex = activeItem ? sortedElements.indexOf(activeItem) : -1;
|
|
21931
|
-
if (activeIndex !== -1) onHighlightedIndexChange(activeIndex);
|
|
21932
|
-
scrollIntoViewIfNeeded(rootRef.current, activeItem, direction, orientation);
|
|
21933
|
-
});
|
|
21934
|
-
const wrappedOnLoop = useStableCallback((event, prevIndex, nextIndex) => {
|
|
21935
|
-
if (!onLoop) return nextIndex;
|
|
21936
|
-
return onLoop?.(event, prevIndex, nextIndex, elementsRef);
|
|
21937
|
-
});
|
|
21938
|
-
const props = React.useMemo(() => ({
|
|
21939
|
-
"aria-orientation": orientation === "both" ? void 0 : orientation,
|
|
21940
|
-
ref: mergedRef,
|
|
21941
|
-
onFocus(event) {
|
|
21942
|
-
const element = rootRef.current;
|
|
21943
|
-
const target = getTarget(event.nativeEvent);
|
|
21944
|
-
if (!element || target == null || !isNativeInput(target)) return;
|
|
21945
|
-
target.setSelectionRange(0, target.value.length ?? 0);
|
|
21946
|
-
},
|
|
21947
|
-
onKeyDown(event) {
|
|
21948
|
-
const RELEVANT_KEYS = enableHomeAndEndKeys ? ALL_KEYS : ARROW_KEYS;
|
|
21949
|
-
if (!RELEVANT_KEYS.has(event.key)) return;
|
|
21950
|
-
if (isModifierKeySet(event, modifierKeys)) return;
|
|
21951
|
-
if (!rootRef.current) return;
|
|
21952
|
-
const isRtl = direction === "rtl";
|
|
21953
|
-
const horizontalForwardKey = isRtl ? ARROW_LEFT : ARROW_RIGHT;
|
|
21954
|
-
const forwardKey = {
|
|
21955
|
-
horizontal: horizontalForwardKey,
|
|
21956
|
-
vertical: ARROW_DOWN,
|
|
21957
|
-
both: horizontalForwardKey
|
|
21958
|
-
}[orientation];
|
|
21959
|
-
const horizontalBackwardKey = isRtl ? ARROW_RIGHT : ARROW_LEFT;
|
|
21960
|
-
const backwardKey = {
|
|
21961
|
-
horizontal: horizontalBackwardKey,
|
|
21962
|
-
vertical: ARROW_UP,
|
|
21963
|
-
both: horizontalBackwardKey
|
|
21964
|
-
}[orientation];
|
|
21965
|
-
const target = getTarget(event.nativeEvent);
|
|
21966
|
-
if (target != null && isNativeInput(target) && !isElementDisabled(target)) {
|
|
21967
|
-
const selectionStart = target.selectionStart;
|
|
21968
|
-
const selectionEnd = target.selectionEnd;
|
|
21969
|
-
const textContent = target.value ?? "";
|
|
21970
|
-
if (selectionStart == null || event.shiftKey || selectionStart !== selectionEnd) return;
|
|
21971
|
-
if (event.key !== backwardKey && selectionStart < textContent.length) return;
|
|
21972
|
-
if (event.key !== forwardKey && selectionStart > 0) return;
|
|
21973
|
-
}
|
|
21974
|
-
let nextIndex = highlightedIndex;
|
|
21975
|
-
const minIndex = getMinListIndex(elementsRef, disabledIndices);
|
|
21976
|
-
const maxIndex = getMaxListIndex(elementsRef, disabledIndices);
|
|
21977
|
-
if (isGrid) {
|
|
21978
|
-
const sizes = itemSizes || Array.from({ length: elementsRef.current.length }, () => ({
|
|
21979
|
-
width: 1,
|
|
21980
|
-
height: 1
|
|
21981
|
-
}));
|
|
21982
|
-
const cellMap = createGridCellMap(sizes, cols, dense);
|
|
21983
|
-
const minGridIndex = cellMap.findIndex((index) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices));
|
|
21984
|
-
const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(elementsRef.current, index, disabledIndices) ? cellIndex : foundIndex, -1);
|
|
21985
|
-
nextIndex = cellMap[getGridNavigatedIndex(cellMap.map((itemIndex) => itemIndex != null ? elementsRef.current[itemIndex] : null), {
|
|
21986
|
-
event,
|
|
21987
|
-
orientation,
|
|
21988
|
-
loopFocus,
|
|
21989
|
-
onLoop: wrappedOnLoop,
|
|
21990
|
-
cols,
|
|
21991
|
-
disabledIndices: getGridCellIndices([...disabledIndices || elementsRef.current.map((_, index) => isListIndexDisabled(elementsRef.current, index) ? index : void 0), void 0], cellMap),
|
|
21992
|
-
minIndex: minGridIndex,
|
|
21993
|
-
maxIndex: maxGridIndex,
|
|
21994
|
-
prevIndex: getGridCellIndexOfCorner(highlightedIndex > maxIndex ? minIndex : highlightedIndex, sizes, cellMap, cols, event.key === "ArrowDown" ? "bl" : event.key === "ArrowRight" ? "tr" : "tl"),
|
|
21995
|
-
rtl: isRtl
|
|
21996
|
-
})];
|
|
21997
|
-
}
|
|
21998
|
-
const forwardKeys = {
|
|
21999
|
-
horizontal: [horizontalForwardKey],
|
|
22000
|
-
vertical: [ARROW_DOWN],
|
|
22001
|
-
both: [horizontalForwardKey, ARROW_DOWN]
|
|
22002
|
-
}[orientation];
|
|
22003
|
-
const backwardKeys = {
|
|
22004
|
-
horizontal: [horizontalBackwardKey],
|
|
22005
|
-
vertical: [ARROW_UP],
|
|
22006
|
-
both: [horizontalBackwardKey, ARROW_UP]
|
|
22007
|
-
}[orientation];
|
|
22008
|
-
const preventedKeys = isGrid ? RELEVANT_KEYS : {
|
|
22009
|
-
horizontal: enableHomeAndEndKeys ? HORIZONTAL_KEYS_WITH_EXTRA_KEYS : HORIZONTAL_KEYS,
|
|
22010
|
-
vertical: enableHomeAndEndKeys ? VERTICAL_KEYS_WITH_EXTRA_KEYS : VERTICAL_KEYS,
|
|
22011
|
-
both: RELEVANT_KEYS
|
|
22012
|
-
}[orientation];
|
|
22013
|
-
if (enableHomeAndEndKeys) {
|
|
22014
|
-
if (event.key === "Home") nextIndex = minIndex;
|
|
22015
|
-
else if (event.key === "End") nextIndex = maxIndex;
|
|
22016
|
-
}
|
|
22017
|
-
if (nextIndex === highlightedIndex && (forwardKeys.includes(event.key) || backwardKeys.includes(event.key))) {
|
|
22018
|
-
if (loopFocus && nextIndex === maxIndex && forwardKeys.includes(event.key)) {
|
|
22019
|
-
nextIndex = minIndex;
|
|
22020
|
-
if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
|
|
22021
|
-
} else if (loopFocus && nextIndex === minIndex && backwardKeys.includes(event.key)) {
|
|
22022
|
-
nextIndex = maxIndex;
|
|
22023
|
-
if (onLoop) nextIndex = onLoop(event, highlightedIndex, nextIndex, elementsRef);
|
|
22024
|
-
} else nextIndex = findNonDisabledListIndex(elementsRef.current, {
|
|
22025
|
-
startingIndex: nextIndex,
|
|
22026
|
-
decrement: backwardKeys.includes(event.key),
|
|
22027
|
-
disabledIndices
|
|
22028
|
-
});
|
|
22029
|
-
}
|
|
22030
|
-
if (nextIndex !== highlightedIndex && !isIndexOutOfListBounds(elementsRef.current, nextIndex)) {
|
|
22031
|
-
if (stopEventPropagation) event.stopPropagation();
|
|
22032
|
-
if (preventedKeys.has(event.key)) event.preventDefault();
|
|
22033
|
-
onHighlightedIndexChange(nextIndex, true);
|
|
22034
|
-
queueMicrotask(() => {
|
|
22035
|
-
elementsRef.current[nextIndex]?.focus();
|
|
22036
|
-
});
|
|
22037
|
-
}
|
|
22038
|
-
}
|
|
22039
|
-
}), [
|
|
22040
|
-
cols,
|
|
22041
|
-
dense,
|
|
22042
|
-
direction,
|
|
22043
|
-
disabledIndices,
|
|
22044
|
-
elementsRef,
|
|
22045
|
-
enableHomeAndEndKeys,
|
|
22046
|
-
highlightedIndex,
|
|
22047
|
-
isGrid,
|
|
22048
|
-
itemSizes,
|
|
22049
|
-
loopFocus,
|
|
22050
|
-
onLoop,
|
|
22051
|
-
wrappedOnLoop,
|
|
22052
|
-
mergedRef,
|
|
22053
|
-
modifierKeys,
|
|
22054
|
-
onHighlightedIndexChange,
|
|
22055
|
-
orientation,
|
|
22056
|
-
stopEventPropagation
|
|
22057
|
-
]);
|
|
22058
|
-
return React.useMemo(() => ({
|
|
22059
|
-
props,
|
|
22060
|
-
highlightedIndex,
|
|
22061
|
-
onHighlightedIndexChange,
|
|
22062
|
-
elementsRef,
|
|
22063
|
-
disabledIndices,
|
|
22064
|
-
onMapChange,
|
|
22065
|
-
relayKeyboardEvent: props.onKeyDown
|
|
22066
|
-
}), [
|
|
22067
|
-
props,
|
|
22068
|
-
highlightedIndex,
|
|
22069
|
-
onHighlightedIndexChange,
|
|
22070
|
-
elementsRef,
|
|
22071
|
-
disabledIndices,
|
|
22072
|
-
onMapChange
|
|
22073
|
-
]);
|
|
22074
|
-
}
|
|
22075
|
-
function isModifierKeySet(event, ignoredModifierKeys) {
|
|
22076
|
-
for (const key of MODIFIER_KEYS$1.values()) {
|
|
22077
|
-
if (ignoredModifierKeys.includes(key)) continue;
|
|
22078
|
-
if (event.getModifierState(key)) return true;
|
|
22079
|
-
}
|
|
22080
|
-
return false;
|
|
22081
|
-
}
|
|
22082
|
-
//#endregion
|
|
22083
|
-
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/internals/composite/root/CompositeRoot.js
|
|
22084
|
-
/**
|
|
22085
|
-
* @internal
|
|
22086
|
-
*/
|
|
22087
|
-
function CompositeRoot(componentProps) {
|
|
22088
|
-
const { render, className, style, refs = EMPTY_ARRAY$1, props = EMPTY_ARRAY$1, state = EMPTY_OBJECT, stateAttributesMapping, highlightedIndex: highlightedIndexProp, onHighlightedIndexChange: onHighlightedIndexChangeProp, orientation, dense, itemSizes, loopFocus, onLoop, cols, enableHomeAndEndKeys, onMapChange: onMapChangeProp, stopEventPropagation = true, rootRef, disabledIndices, modifierKeys, highlightItemOnHover = false, tag = "div", ...elementProps } = componentProps;
|
|
22089
|
-
const { props: defaultProps, highlightedIndex, onHighlightedIndexChange, elementsRef, onMapChange: onMapChangeUnwrapped, relayKeyboardEvent } = useCompositeRoot({
|
|
22090
|
-
itemSizes,
|
|
22091
|
-
cols,
|
|
22092
|
-
loopFocus,
|
|
22093
|
-
onLoop,
|
|
22094
|
-
dense,
|
|
22095
|
-
orientation,
|
|
22096
|
-
highlightedIndex: highlightedIndexProp,
|
|
22097
|
-
onHighlightedIndexChange: onHighlightedIndexChangeProp,
|
|
22098
|
-
rootRef,
|
|
22099
|
-
stopEventPropagation,
|
|
22100
|
-
enableHomeAndEndKeys,
|
|
22101
|
-
direction: useDirection(),
|
|
22102
|
-
disabledIndices,
|
|
22103
|
-
modifierKeys
|
|
22104
|
-
});
|
|
22105
|
-
const element = useRenderElement(tag, componentProps, {
|
|
22106
|
-
state,
|
|
22107
|
-
ref: refs,
|
|
22108
|
-
props: [
|
|
22109
|
-
defaultProps,
|
|
22110
|
-
...props,
|
|
22111
|
-
elementProps
|
|
22112
|
-
],
|
|
22113
|
-
stateAttributesMapping
|
|
22114
|
-
});
|
|
22115
|
-
const contextValue = React.useMemo(() => ({
|
|
22116
|
-
highlightedIndex,
|
|
22117
|
-
onHighlightedIndexChange,
|
|
22118
|
-
highlightItemOnHover,
|
|
22119
|
-
relayKeyboardEvent
|
|
22120
|
-
}), [
|
|
22121
|
-
highlightedIndex,
|
|
22122
|
-
onHighlightedIndexChange,
|
|
22123
|
-
highlightItemOnHover,
|
|
22124
|
-
relayKeyboardEvent
|
|
22125
|
-
]);
|
|
22126
|
-
return /*#__PURE__*/ jsx(CompositeRootContext.Provider, {
|
|
22127
|
-
value: contextValue,
|
|
22128
|
-
children: /*#__PURE__*/ jsx(CompositeList, {
|
|
22129
|
-
elementsRef,
|
|
22130
|
-
onMapChange: (newMap) => {
|
|
22131
|
-
onMapChangeProp?.(newMap);
|
|
22132
|
-
onMapChangeUnwrapped(newMap);
|
|
22133
|
-
},
|
|
22134
|
-
children: element
|
|
22135
|
-
})
|
|
22136
|
-
});
|
|
22137
|
-
}
|
|
22138
|
-
//#endregion
|
|
22139
22480
|
//#region ../../node_modules/.bun/@base-ui+react@1.4.1+fa6c2f29eeb10566/node_modules/@base-ui/react/esm/radio-group/RadioGroup.js
|
|
22140
22481
|
var MODIFIER_KEYS = [SHIFT];
|
|
22141
22482
|
/**
|
|
@@ -23722,7 +24063,7 @@ function tooShort(from, to) {
|
|
|
23722
24063
|
}
|
|
23723
24064
|
//#endregion
|
|
23724
24065
|
//#region src/canvas/browser/graph/FlowCanvas/FlowCanvas.tsx
|
|
23725
|
-
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 }) => {
|
|
24066
|
+
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 }) => {
|
|
23726
24067
|
const editable = useVal(flowCanvasStore.$.editable);
|
|
23727
24068
|
const direction = useVal(flowCanvasStore.$.direction);
|
|
23728
24069
|
const changingDirection = useVal(flowCanvasStore.$.changingDirection);
|
|
@@ -23786,7 +24127,10 @@ var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onS
|
|
|
23786
24127
|
onRelayout: editable ? flowCanvasStore.onRelayout : void 0,
|
|
23787
24128
|
onLayoutMeasured: flowCanvasStore.completeLayout,
|
|
23788
24129
|
onInstance: flowCanvasStore.rfCommand.onRFInstance,
|
|
23789
|
-
onInit:
|
|
24130
|
+
onInit: (instance) => {
|
|
24131
|
+
flowCanvasStore.onInit();
|
|
24132
|
+
onInit?.(instance);
|
|
24133
|
+
},
|
|
23790
24134
|
onCopy: flowCanvasStore.onCopy,
|
|
23791
24135
|
onPaste: flowCanvasStore.onPaste,
|
|
23792
24136
|
waitNode: flowCanvasStore.waitNode,
|
|
@@ -23798,4 +24142,4 @@ var FlowCanvas = ({ flowCanvasStore, annotationContext, onActivateSelection, onS
|
|
|
23798
24142
|
});
|
|
23799
24143
|
};
|
|
23800
24144
|
//#endregion
|
|
23801
|
-
export {
|
|
24145
|
+
export { isMac as C, getFlowPngAspectRatio as E, toManifestNodeId as S, flowPngAspectRatios as T, E as _, CanvasNodeIcon as a, toViewEdge as b, collapseAllNested as c, IconStack as d, selectableTimeZones as f, cronDescription as g, timeZoneOffset as h, pasteVideoLink as i, formatDuration as l, timeZoneLongLabel as m, setAddItemId as n, defaultTriggerIcon as o, timeZoneLabel as p, getVideoLink as r, JSONViewer as s, FlowCanvas as t, useDebouncedValue as u, CanvasTooltip as v, isSameViewport as w, toManifestHandleName as x, CanvasStore as y };
|