@hlang-tech/editor-ui 0.2.2 → 0.4.0
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/lib/edges/FlowEdge.css +55 -0
- package/lib/index.d.mts +510 -28
- package/lib/index.d.ts +510 -28
- package/lib/index.js +1549 -382
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1487 -356
- package/lib/index.mjs.map +1 -1
- package/lib/live/LivePulse.css +21 -0
- package/lib/nodes/AssetNode.css +9 -7
- package/lib/nodes/HlangNode.css +9 -7
- package/lib/nodes/PillNode.css +9 -7
- package/lib/panels/InspectorPanel.css +59 -0
- package/lib/panels/ParamForm.css +11 -0
- package/lib/panels/RunLog.css +175 -0
- package/lib/shell/EditorShell.css +82 -0
- package/lib/styles.css +2 -0
- package/package.json +13 -12
package/lib/index.js
CHANGED
|
@@ -25,30 +25,45 @@ __export(index_exports, {
|
|
|
25
25
|
CanvasChrome: () => CanvasChrome,
|
|
26
26
|
CanvasDock: () => CanvasDock,
|
|
27
27
|
Cheatsheet: () => Cheatsheet,
|
|
28
|
+
ConnectionInspector: () => ConnectionInspector,
|
|
29
|
+
DEFAULT_EDGE_CAPACITY: () => DEFAULT_EDGE_CAPACITY,
|
|
30
|
+
DEFAULT_MIN_CANVAS_HEIGHT: () => DEFAULT_MIN_CANVAS_HEIGHT,
|
|
28
31
|
DiagnosticBadge: () => DiagnosticBadge,
|
|
29
32
|
EditorShell: () => EditorShell,
|
|
30
33
|
EditorUIThemeProvider: () => EditorUIThemeProvider,
|
|
31
34
|
EmptyState: () => EmptyState,
|
|
35
|
+
FOLLOW_SLACK_PX: () => FOLLOW_SLACK_PX,
|
|
36
|
+
FOOTER_KEY_STEP: () => FOOTER_KEY_STEP,
|
|
32
37
|
FlowEdge: () => FlowEdge,
|
|
38
|
+
FooterResizer: () => FooterResizer,
|
|
33
39
|
HlangNode: () => HlangNode,
|
|
34
40
|
InspectorPanel: () => InspectorPanel,
|
|
35
41
|
KIND_ROLE: () => KIND_ROLE,
|
|
36
42
|
KIND_TOKEN: () => KIND_TOKEN,
|
|
43
|
+
LivePulse: () => LivePulse,
|
|
37
44
|
LiveSignalProvider: () => LiveSignalProvider,
|
|
38
45
|
LiveSignalStore: () => LiveSignalStore,
|
|
39
46
|
NodeBodySlot: () => NodeBodySlot,
|
|
40
47
|
NodeChrome: () => NodeChrome,
|
|
41
48
|
NodeContextMenu: () => NodeContextMenu,
|
|
42
49
|
NodeInteractionProvider: () => NodeInteractionProvider,
|
|
50
|
+
NodeRunStats: () => NodeRunStats,
|
|
43
51
|
NodeSearch: () => NodeSearch,
|
|
44
52
|
OutlineTree: () => OutlineTree,
|
|
53
|
+
PREVIEW_LENGTH: () => PREVIEW_LENGTH,
|
|
45
54
|
ParamForm: () => ParamForm,
|
|
46
55
|
PillNodeChrome: () => PillNodeChrome,
|
|
47
56
|
PortRow: () => PortRow,
|
|
48
57
|
PositionPanel: () => PositionPanel,
|
|
49
58
|
PreviewPanel: () => PreviewPanel,
|
|
59
|
+
RUN_LOG_CAPACITY: () => RUN_LOG_CAPACITY,
|
|
50
60
|
RailTabs: () => RailTabs,
|
|
51
61
|
RunButton: () => RunButton,
|
|
62
|
+
RunLog: () => RunLog,
|
|
63
|
+
RunTrace: () => RunTrace,
|
|
64
|
+
RunTraceProvider: () => RunTraceProvider,
|
|
65
|
+
SELF_LOOP_CLEARANCE: () => SELF_LOOP_CLEARANCE,
|
|
66
|
+
SELF_LOOP_RADIUS: () => SELF_LOOP_RADIUS,
|
|
52
67
|
SignalBar: () => SignalBar,
|
|
53
68
|
TOKEN_NAMES: () => TOKEN_NAMES,
|
|
54
69
|
ToastProvider: () => ToastProvider,
|
|
@@ -57,26 +72,47 @@ __export(index_exports, {
|
|
|
57
72
|
ToolbarGhostButton: () => ToolbarGhostButton,
|
|
58
73
|
ToolbarStat: () => ToolbarStat,
|
|
59
74
|
UndoRedo: () => UndoRedo,
|
|
75
|
+
boundsFields: () => boundsFields,
|
|
76
|
+
capacityLabel: () => capacityLabel,
|
|
77
|
+
clampFooter: () => clampFooter,
|
|
60
78
|
connectableCandidates: () => connectableCandidates,
|
|
61
79
|
createHlangFlowTypes: () => createHlangFlowTypes,
|
|
62
80
|
createTheme: () => createTheme,
|
|
81
|
+
defaultLiveDeps: () => defaultLiveDeps,
|
|
63
82
|
deriveParamSchema: () => deriveParamSchema,
|
|
64
83
|
descriptorCandidates: () => descriptorCandidates,
|
|
84
|
+
footerBounds: () => footerBounds,
|
|
85
|
+
formatDuration: () => formatDuration,
|
|
86
|
+
formatElapsed: () => formatElapsed,
|
|
65
87
|
fuzzyRank: () => fuzzyRank,
|
|
66
88
|
fuzzyScore: () => fuzzyScore,
|
|
89
|
+
involves: () => involves,
|
|
67
90
|
isEditableTarget: () => isEditableTarget,
|
|
91
|
+
nextBounds: () => nextBounds,
|
|
92
|
+
previewValue: () => previewValue,
|
|
93
|
+
resizeByKey: () => resizeByKey,
|
|
68
94
|
searchNodes: () => searchNodes,
|
|
95
|
+
selfLoopPath: () => selfLoopPath,
|
|
96
|
+
toggleCollapsed: () => toggleCollapsed,
|
|
69
97
|
tokenVar: () => tokenVar,
|
|
98
|
+
useEdgeBounds: () => useEdgeBounds,
|
|
70
99
|
useEdgeFlowing: () => useEdgeFlowing,
|
|
100
|
+
useEdgePulse: () => useEdgePulse,
|
|
71
101
|
useEditorHotkeys: () => useEditorHotkeys,
|
|
102
|
+
useFollowScroll: () => useFollowScroll,
|
|
103
|
+
useFooterResize: () => useFooterResize,
|
|
72
104
|
useLiveSignalStore: () => useLiveSignalStore,
|
|
73
105
|
useLiveSignals: () => useLiveSignals,
|
|
74
106
|
useNodeContextMenu: () => useNodeContextMenu,
|
|
75
107
|
useNodeInteraction: () => useNodeInteraction,
|
|
76
108
|
useNodeLiveState: () => useNodeLiveState,
|
|
77
109
|
useNodeParams: () => useNodeParams,
|
|
110
|
+
useNodePulse: () => useNodePulse,
|
|
78
111
|
useNodeSearch: () => useNodeSearch,
|
|
79
112
|
useNodeSearchTriggers: () => useNodeSearchTriggers,
|
|
113
|
+
useRunTrace: () => useRunTrace,
|
|
114
|
+
useRunTraceStore: () => useRunTraceStore,
|
|
115
|
+
useRunTraceVersion: () => useRunTraceVersion,
|
|
80
116
|
useToast: () => useToast
|
|
81
117
|
});
|
|
82
118
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -92,11 +128,18 @@ var TOKEN_NAMES = [
|
|
|
92
128
|
"hl-silver",
|
|
93
129
|
"hl-silver-hi",
|
|
94
130
|
"hl-silver-lo",
|
|
131
|
+
"hl-glass",
|
|
132
|
+
"hl-glass-2",
|
|
133
|
+
"hl-glass-blur",
|
|
134
|
+
"hl-glass-sat",
|
|
135
|
+
"hl-glass-edge",
|
|
136
|
+
"hl-glass-edge-hi",
|
|
95
137
|
"hl-spark",
|
|
96
138
|
"hl-r",
|
|
97
139
|
"hl-t",
|
|
98
140
|
"hl-w",
|
|
99
141
|
"hl-error",
|
|
142
|
+
"hl-warning",
|
|
100
143
|
"hl-ink",
|
|
101
144
|
"hl-ink-2",
|
|
102
145
|
"hl-ink-3",
|
|
@@ -109,7 +152,9 @@ var TOKEN_NAMES = [
|
|
|
109
152
|
"hl-shadow-node",
|
|
110
153
|
"hl-shadow-glass",
|
|
111
154
|
"hl-glow-silver",
|
|
112
|
-
"hl-ease"
|
|
155
|
+
"hl-ease",
|
|
156
|
+
"hl-activity",
|
|
157
|
+
"hl-cost"
|
|
113
158
|
];
|
|
114
159
|
function tokenVar(name) {
|
|
115
160
|
return `var(--${name})`;
|
|
@@ -140,12 +185,12 @@ function createTheme(overrides) {
|
|
|
140
185
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
141
186
|
function EditorUIThemeProvider({
|
|
142
187
|
theme,
|
|
143
|
-
className,
|
|
188
|
+
className: className2,
|
|
144
189
|
style,
|
|
145
190
|
children
|
|
146
191
|
}) {
|
|
147
192
|
const themeStyle = theme ? createTheme(theme) : void 0;
|
|
148
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: { ...themeStyle, ...style }, children });
|
|
193
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: className2, style: { ...themeStyle, ...style }, children });
|
|
149
194
|
}
|
|
150
195
|
|
|
151
196
|
// src/nodes/SignalBar.tsx
|
|
@@ -195,7 +240,10 @@ var ACTIVE_WINDOW_MS = 700;
|
|
|
195
240
|
function portKey(nodeId, portId) {
|
|
196
241
|
return `${nodeId}@${portId}`;
|
|
197
242
|
}
|
|
198
|
-
|
|
243
|
+
function connectionKey(sourceNodeId, sourcePortId, targetNodeId, targetPortId) {
|
|
244
|
+
return `${portKey(sourceNodeId, sourcePortId)}->${portKey(targetNodeId, targetPortId)}`;
|
|
245
|
+
}
|
|
246
|
+
var defaultLiveDeps = {
|
|
199
247
|
now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
|
|
200
248
|
schedule: (cb) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(cb) : (
|
|
201
249
|
// `window.setTimeout` returns a numeric handle (the DOM overload),
|
|
@@ -206,11 +254,13 @@ var defaultDeps = {
|
|
|
206
254
|
cancel: (h) => typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame(h) : window.clearTimeout(h)
|
|
207
255
|
};
|
|
208
256
|
var LiveSignalStore = class {
|
|
209
|
-
constructor(deps =
|
|
257
|
+
constructor(deps = defaultLiveDeps) {
|
|
210
258
|
/** nodeId -> last-active timestamp. */
|
|
211
259
|
this.nodeActiveAt = /* @__PURE__ */ new Map();
|
|
212
260
|
/** nodeId set that errored during this run. */
|
|
213
261
|
this.erroredNodes = /* @__PURE__ */ new Set();
|
|
262
|
+
/** nodeId set that finished during this run (RFC 0001). */
|
|
263
|
+
this.finishedNodes = /* @__PURE__ */ new Set();
|
|
214
264
|
/** edgeId -> last-flowing timestamp. */
|
|
215
265
|
this.edgeFlowAt = /* @__PURE__ */ new Map();
|
|
216
266
|
/** Per-id listeners. */
|
|
@@ -221,12 +271,21 @@ var LiveSignalStore = class {
|
|
|
221
271
|
this.lastEdgeFlowing = /* @__PURE__ */ new Map();
|
|
222
272
|
/** Edges sourced by a given (nodeId@portId), for pulse -> edge mapping. */
|
|
223
273
|
this.edgesBySourcePort = /* @__PURE__ */ new Map();
|
|
274
|
+
/** Edges by the connection they carry (source port -> target port). */
|
|
275
|
+
this.edgesByConnection = /* @__PURE__ */ new Map();
|
|
276
|
+
/** How many messages each node has handled or sent, and each edge carried, this run. */
|
|
277
|
+
this.nodePulse = /* @__PURE__ */ new Map();
|
|
278
|
+
this.edgePulse = /* @__PURE__ */ new Map();
|
|
279
|
+
/** The pulse counts last notified, so a new message notifies even while the state stays active. */
|
|
280
|
+
this.lastNodePulse = /* @__PURE__ */ new Map();
|
|
281
|
+
this.lastEdgePulse = /* @__PURE__ */ new Map();
|
|
224
282
|
this.rafHandle = null;
|
|
225
283
|
this.running = false;
|
|
226
284
|
this.deps = deps;
|
|
227
285
|
}
|
|
228
286
|
/** Provide the current edge index (call whenever edges change). */
|
|
229
287
|
setEdgeIndex(edges) {
|
|
288
|
+
var _a;
|
|
230
289
|
const next = /* @__PURE__ */ new Map();
|
|
231
290
|
for (const edge of edges) {
|
|
232
291
|
const key = portKey(edge.sourceNodeId, edge.sourcePortId);
|
|
@@ -238,6 +297,44 @@ var LiveSignalStore = class {
|
|
|
238
297
|
}
|
|
239
298
|
}
|
|
240
299
|
this.edgesBySourcePort = next;
|
|
300
|
+
const byConnection = /* @__PURE__ */ new Map();
|
|
301
|
+
for (const edge of edges) {
|
|
302
|
+
if (edge.targetNodeId !== void 0 && edge.targetPortId !== void 0) {
|
|
303
|
+
const key = connectionKey(edge.sourceNodeId, edge.sourcePortId, edge.targetNodeId, edge.targetPortId);
|
|
304
|
+
byConnection.set(key, [...(_a = byConnection.get(key)) != null ? _a : [], edge]);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
this.edgesByConnection = byConnection;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Record a message delivered on a connection, when it happens: its source
|
|
311
|
+
* and its target each pulse once (each ran), and so does the edge that
|
|
312
|
+
* carried it, and only that edge. Subscribers are notified on the next
|
|
313
|
+
* frame, once however many messages arrived in it.
|
|
314
|
+
*/
|
|
315
|
+
markDelivery(signal) {
|
|
316
|
+
var _a;
|
|
317
|
+
const t = this.deps.now();
|
|
318
|
+
for (const nodeId of [signal.sourceNodeId, signal.targetNodeId]) {
|
|
319
|
+
this.nodeActiveAt.set(nodeId, t);
|
|
320
|
+
this.nodePulse.set(nodeId, this.getNodePulse(nodeId) + 1);
|
|
321
|
+
}
|
|
322
|
+
const key = connectionKey(signal.sourceNodeId, signal.sourcePortId, signal.targetNodeId, signal.targetPortId);
|
|
323
|
+
for (const edge of (_a = this.edgesByConnection.get(key)) != null ? _a : []) {
|
|
324
|
+
this.edgeFlowAt.set(edge.id, t);
|
|
325
|
+
this.edgePulse.set(edge.id, this.getEdgePulse(edge.id) + 1);
|
|
326
|
+
}
|
|
327
|
+
this.ensureLoop();
|
|
328
|
+
}
|
|
329
|
+
/** How many messages a node has handled or sent this run; it changes each time the node runs. */
|
|
330
|
+
getNodePulse(nodeId) {
|
|
331
|
+
var _a;
|
|
332
|
+
return (_a = this.nodePulse.get(nodeId)) != null ? _a : 0;
|
|
333
|
+
}
|
|
334
|
+
/** How many messages an edge has carried this run. */
|
|
335
|
+
getEdgePulse(edgeId) {
|
|
336
|
+
var _a;
|
|
337
|
+
return (_a = this.edgePulse.get(edgeId)) != null ? _a : 0;
|
|
241
338
|
}
|
|
242
339
|
/** Record a node emitting on an output port (drives node + edge activity). */
|
|
243
340
|
markActivity(nodeId, portId) {
|
|
@@ -251,6 +348,11 @@ var LiveSignalStore = class {
|
|
|
251
348
|
}
|
|
252
349
|
this.ensureLoop();
|
|
253
350
|
}
|
|
351
|
+
/** Record a node finishing (RFC 0001): shown once its last flash has faded. */
|
|
352
|
+
markFinished(nodeId) {
|
|
353
|
+
this.finishedNodes.add(nodeId);
|
|
354
|
+
this.ensureLoop();
|
|
355
|
+
}
|
|
254
356
|
/** Record a node erroring (sticky for the run). */
|
|
255
357
|
markError(nodeId) {
|
|
256
358
|
this.erroredNodes.add(nodeId);
|
|
@@ -260,7 +362,10 @@ var LiveSignalStore = class {
|
|
|
260
362
|
reset() {
|
|
261
363
|
this.nodeActiveAt.clear();
|
|
262
364
|
this.erroredNodes.clear();
|
|
365
|
+
this.finishedNodes.clear();
|
|
263
366
|
this.edgeFlowAt.clear();
|
|
367
|
+
this.nodePulse.clear();
|
|
368
|
+
this.edgePulse.clear();
|
|
264
369
|
this.stopLoop();
|
|
265
370
|
this.flushNotifications();
|
|
266
371
|
}
|
|
@@ -281,7 +386,7 @@ var LiveSignalStore = class {
|
|
|
281
386
|
if (at !== void 0 && this.deps.now() - at <= ACTIVE_WINDOW_MS) {
|
|
282
387
|
return "active";
|
|
283
388
|
}
|
|
284
|
-
return "idle";
|
|
389
|
+
return this.finishedNodes.has(nodeId) ? "finished" : "idle";
|
|
285
390
|
}
|
|
286
391
|
/** Whether an edge is currently flowing. */
|
|
287
392
|
isEdgeFlowing(edgeId) {
|
|
@@ -300,9 +405,14 @@ var LiveSignalStore = class {
|
|
|
300
405
|
}
|
|
301
406
|
};
|
|
302
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Arms the frame loop if it is not running. Signals only record state; the
|
|
410
|
+
* next frame notifies, so a burst of signals costs one pass over the
|
|
411
|
+
* subscribers per frame, not one per signal, and every change shows within a
|
|
412
|
+
* frame.
|
|
413
|
+
*/
|
|
303
414
|
ensureLoop() {
|
|
304
415
|
if (this.running) {
|
|
305
|
-
this.flushNotifications();
|
|
306
416
|
return;
|
|
307
417
|
}
|
|
308
418
|
this.running = true;
|
|
@@ -336,8 +446,10 @@ var LiveSignalStore = class {
|
|
|
336
446
|
if (state !== "idle") {
|
|
337
447
|
anyLive = anyLive || state === "active";
|
|
338
448
|
}
|
|
339
|
-
|
|
449
|
+
const pulse = this.getNodePulse(nodeId);
|
|
450
|
+
if (this.lastNodeState.get(nodeId) !== state || this.lastNodePulse.get(nodeId) !== pulse) {
|
|
340
451
|
this.lastNodeState.set(nodeId, state);
|
|
452
|
+
this.lastNodePulse.set(nodeId, pulse);
|
|
341
453
|
for (const listener of listeners) {
|
|
342
454
|
listener();
|
|
343
455
|
}
|
|
@@ -346,8 +458,10 @@ var LiveSignalStore = class {
|
|
|
346
458
|
for (const [edgeId, listeners] of this.edgeListeners) {
|
|
347
459
|
const flowing = this.isEdgeFlowing(edgeId);
|
|
348
460
|
anyLive = anyLive || flowing;
|
|
349
|
-
|
|
461
|
+
const pulse = this.getEdgePulse(edgeId);
|
|
462
|
+
if (this.lastEdgeFlowing.get(edgeId) !== flowing || this.lastEdgePulse.get(edgeId) !== pulse) {
|
|
350
463
|
this.lastEdgeFlowing.set(edgeId, flowing);
|
|
464
|
+
this.lastEdgePulse.set(edgeId, pulse);
|
|
351
465
|
for (const listener of listeners) {
|
|
352
466
|
listener();
|
|
353
467
|
}
|
|
@@ -375,6 +489,22 @@ function useNodeLiveState(nodeId) {
|
|
|
375
489
|
() => "idle"
|
|
376
490
|
);
|
|
377
491
|
}
|
|
492
|
+
function useNodePulse(nodeId) {
|
|
493
|
+
const store = (0, import_react2.useContext)(LiveSignalContext);
|
|
494
|
+
return (0, import_react2.useSyncExternalStore)(
|
|
495
|
+
(onChange) => store === null ? () => void 0 : store.subscribeNode(nodeId, onChange),
|
|
496
|
+
() => store === null ? 0 : store.getNodePulse(nodeId),
|
|
497
|
+
() => 0
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
function useEdgePulse(edgeId) {
|
|
501
|
+
const store = (0, import_react2.useContext)(LiveSignalContext);
|
|
502
|
+
return (0, import_react2.useSyncExternalStore)(
|
|
503
|
+
(onChange) => store === null ? () => void 0 : store.subscribeEdge(edgeId, onChange),
|
|
504
|
+
() => store === null ? 0 : store.getEdgePulse(edgeId),
|
|
505
|
+
() => 0
|
|
506
|
+
);
|
|
507
|
+
}
|
|
378
508
|
function useEdgeFlowing(edgeId) {
|
|
379
509
|
const store = (0, import_react2.useContext)(LiveSignalContext);
|
|
380
510
|
return (0, import_react2.useSyncExternalStore)(
|
|
@@ -384,8 +514,15 @@ function useEdgeFlowing(edgeId) {
|
|
|
384
514
|
);
|
|
385
515
|
}
|
|
386
516
|
|
|
387
|
-
// src/
|
|
517
|
+
// src/live/LivePulse.tsx
|
|
388
518
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
519
|
+
function LivePulse({ nodeId }) {
|
|
520
|
+
const pulse = useNodePulse(nodeId);
|
|
521
|
+
return pulse === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hl-live-pulse", "aria-hidden": "true" }, pulse);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/nodes/AssetNode.tsx
|
|
525
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
389
526
|
function stringParam(node, key) {
|
|
390
527
|
const v = node.params[key];
|
|
391
528
|
return typeof v === "string" ? v : void 0;
|
|
@@ -397,22 +534,24 @@ function AssetNodeChrome({ node, selected }) {
|
|
|
397
534
|
const role = stringParam(node, "role");
|
|
398
535
|
const live = useNodeLiveState(node.id);
|
|
399
536
|
const outputs = node.ports.filter((p) => p.direction === "O" && !p.isError);
|
|
400
|
-
const
|
|
537
|
+
const className2 = [
|
|
401
538
|
"hl-asset",
|
|
402
539
|
selected ? "is-selected" : "",
|
|
403
540
|
live === "active" ? "is-active" : "",
|
|
404
|
-
live === "error" ? "is-live-error" : ""
|
|
541
|
+
live === "error" ? "is-live-error" : "",
|
|
542
|
+
live === "finished" ? "is-finished" : ""
|
|
405
543
|
].filter(Boolean).join(" ");
|
|
406
|
-
return /* @__PURE__ */ (0,
|
|
407
|
-
/* @__PURE__ */ (0,
|
|
408
|
-
|
|
409
|
-
/* @__PURE__ */ (0,
|
|
410
|
-
/* @__PURE__ */ (0,
|
|
411
|
-
|
|
412
|
-
|
|
544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: className2, "data-kind": node.kind, children: [
|
|
545
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LivePulse, { nodeId: node.id }),
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hl-asset-frame", children: [
|
|
547
|
+
imageUrl.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { className: "hl-asset-img", src: imageUrl, alt: caption, draggable: false }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hl-asset-placeholder", "aria-hidden": true }),
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hl-asset-scrim" }),
|
|
549
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hl-asset-caption", children: [
|
|
550
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hl-asset-name", children: caption }),
|
|
551
|
+
role !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hl-asset-role hl-mono", children: role })
|
|
413
552
|
] })
|
|
414
553
|
] }),
|
|
415
|
-
/* @__PURE__ */ (0,
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: "hl-asset-ports", children: outputs.map((port) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PortRow, { port }, port.id)) })
|
|
416
555
|
] });
|
|
417
556
|
}
|
|
418
557
|
|
|
@@ -420,9 +559,9 @@ function AssetNodeChrome({ node, selected }) {
|
|
|
420
559
|
var import_react4 = require("react");
|
|
421
560
|
|
|
422
561
|
// src/icons/node-icons.tsx
|
|
423
|
-
var
|
|
562
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
424
563
|
function svg(size, children) {
|
|
425
|
-
return /* @__PURE__ */ (0,
|
|
564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
426
565
|
"svg",
|
|
427
566
|
{
|
|
428
567
|
width: size,
|
|
@@ -440,49 +579,49 @@ function svg(size, children) {
|
|
|
440
579
|
}
|
|
441
580
|
var BY_CODE = {
|
|
442
581
|
"image-source": (s) => svg(s, [
|
|
443
|
-
/* @__PURE__ */ (0,
|
|
444
|
-
/* @__PURE__ */ (0,
|
|
445
|
-
/* @__PURE__ */ (0,
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2.5" }, "r"),
|
|
583
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "8.5", cy: "9", r: "1.6" }, "c"),
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 17l5-5 4 4 3-2 4 4" }, "p")
|
|
446
585
|
]),
|
|
447
|
-
"text-source": (s) => svg(s, [/* @__PURE__ */ (0,
|
|
586
|
+
"text-source": (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M5 6h14M12 6v12M9 18h6" }, "p")]),
|
|
448
587
|
"interval-source": (s) => svg(s, [
|
|
449
|
-
/* @__PURE__ */ (0,
|
|
450
|
-
/* @__PURE__ */ (0,
|
|
588
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "8" }, "c"),
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 8v4l3 2" }, "h")
|
|
451
590
|
]),
|
|
452
591
|
"range-source": (s) => svg(s, [
|
|
453
|
-
/* @__PURE__ */ (0,
|
|
454
|
-
/* @__PURE__ */ (0,
|
|
455
|
-
/* @__PURE__ */ (0,
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 12h16" }, "l"),
|
|
593
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "6", cy: "12", r: "2" }, "a"),
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "18", cy: "12", r: "2" }, "b")
|
|
456
595
|
]),
|
|
457
|
-
"constant-source": (s) => svg(s, [/* @__PURE__ */ (0,
|
|
596
|
+
"constant-source": (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M6 12h12M9 8l-3 4 3 4M15 8l3 4-3 4" }, "p")]),
|
|
458
597
|
"map-scale": (s) => svg(s, [
|
|
459
|
-
/* @__PURE__ */ (0,
|
|
460
|
-
/* @__PURE__ */ (0,
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 20V8l8-4" }, "a"),
|
|
599
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 8l8 4 8-4M12 12v8" }, "b")
|
|
461
600
|
]),
|
|
462
|
-
uppercase: (s) => svg(s, [/* @__PURE__ */ (0,
|
|
463
|
-
"filter-threshold": (s) => svg(s, [/* @__PURE__ */ (0,
|
|
464
|
-
"scan-sum": (s) => svg(s, [/* @__PURE__ */ (0,
|
|
601
|
+
uppercase: (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M5 18L9 6l4 12M6.5 14h5M15 10v8M15 10c3 0 3 4 0 4" }, "p")]),
|
|
602
|
+
"filter-threshold": (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 5h16l-6 7v6l-4-2v-4z" }, "p")]),
|
|
603
|
+
"scan-sum": (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M17 6H7l6 6-6 6h10" }, "p")]),
|
|
465
604
|
delay: (s) => svg(s, [
|
|
466
|
-
/* @__PURE__ */ (0,
|
|
467
|
-
/* @__PURE__ */ (0,
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "13", r: "7" }, "c"),
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 10v3l2 2M9 3h6" }, "h")
|
|
468
607
|
]),
|
|
469
|
-
merge: (s) => svg(s, [/* @__PURE__ */ (0,
|
|
608
|
+
merge: (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M6 5v4c0 3 3 3 6 3s6 0 6-3V5M12 12v7" }, "p")]),
|
|
470
609
|
"console-sink": (s) => svg(s, [
|
|
471
|
-
/* @__PURE__ */ (0,
|
|
472
|
-
/* @__PURE__ */ (0,
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "4", y: "5", width: "16", height: "12", rx: "2" }, "r"),
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 10l2.5 2L8 14M13 14h3" }, "p")
|
|
473
612
|
]),
|
|
474
613
|
"collect-sink": (s) => svg(s, [
|
|
475
|
-
/* @__PURE__ */ (0,
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 7h16M4 12h16M4 17h10" }, "p")
|
|
476
615
|
])
|
|
477
616
|
};
|
|
478
617
|
var BY_KIND = {
|
|
479
|
-
R: (s) => svg(s, [/* @__PURE__ */ (0,
|
|
618
|
+
R: (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 5l10 7-10 7z" }, "p")]),
|
|
480
619
|
// source ▷ (play)
|
|
481
|
-
T: (s) => svg(s, [/* @__PURE__ */ (0,
|
|
620
|
+
T: (s) => svg(s, [/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 8h6l4 8h6M14 8h6M4 16h6" }, "p")]),
|
|
482
621
|
// transform
|
|
483
622
|
W: (s) => svg(s, [
|
|
484
|
-
/* @__PURE__ */ (0,
|
|
485
|
-
/* @__PURE__ */ (0,
|
|
623
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M5 4h11l3 3v13H5z" }, "p"),
|
|
624
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9 4v5h6" }, "q")
|
|
486
625
|
])
|
|
487
626
|
// sink (save)
|
|
488
627
|
};
|
|
@@ -493,61 +632,61 @@ function NodeIcon({ code, kind, size = 15 }) {
|
|
|
493
632
|
}
|
|
494
633
|
function EyeIcon({ size = 14 }) {
|
|
495
634
|
return svg(size, [
|
|
496
|
-
/* @__PURE__ */ (0,
|
|
497
|
-
/* @__PURE__ */ (0,
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M2 12s3.5-6.5 10-6.5S22 12 22 12s-3.5 6.5-10 6.5S2 12 2 12z" }, "p"),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "2.6" }, "c")
|
|
498
637
|
]);
|
|
499
638
|
}
|
|
500
639
|
function EyeOffIcon({ size = 14 }) {
|
|
501
640
|
return svg(size, [
|
|
502
|
-
/* @__PURE__ */ (0,
|
|
503
|
-
/* @__PURE__ */ (0,
|
|
504
|
-
/* @__PURE__ */ (0,
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M2 12s3.5-6.5 10-6.5c1.7 0 3.2.45 4.5 1.1M22 12s-3.5 6.5-10 6.5c-1.7 0-3.2-.45-4.5-1.1" }, "p"),
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9.9 9.9a2.6 2.6 0 003.7 3.7" }, "e"),
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3 3l18 18" }, "s")
|
|
505
644
|
]);
|
|
506
645
|
}
|
|
507
646
|
function UnlockIcon({ size = 14 }) {
|
|
508
647
|
return svg(size, [
|
|
509
|
-
/* @__PURE__ */ (0,
|
|
510
|
-
/* @__PURE__ */ (0,
|
|
648
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "5", y: "11", width: "14", height: "9", rx: "2" }, "r"),
|
|
649
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 11V7a4 4 0 017.9-1" }, "s")
|
|
511
650
|
]);
|
|
512
651
|
}
|
|
513
652
|
function LockIcon({ size = 14 }) {
|
|
514
653
|
return svg(size, [
|
|
515
|
-
/* @__PURE__ */ (0,
|
|
516
|
-
/* @__PURE__ */ (0,
|
|
654
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "5", y: "11", width: "14", height: "9", rx: "2" }, "r"),
|
|
655
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 11V7a4 4 0 018 0v4" }, "s")
|
|
517
656
|
]);
|
|
518
657
|
}
|
|
519
658
|
function WarningIcon({ size = 13 }) {
|
|
520
659
|
return svg(size, [
|
|
521
|
-
/* @__PURE__ */ (0,
|
|
522
|
-
/* @__PURE__ */ (0,
|
|
523
|
-
/* @__PURE__ */ (0,
|
|
660
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 4l9 15H3z" }, "t"),
|
|
661
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 10v4" }, "b"),
|
|
662
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 17v.5" }, "d")
|
|
524
663
|
]);
|
|
525
664
|
}
|
|
526
665
|
function ErrorIcon({ size = 13 }) {
|
|
527
666
|
return svg(size, [
|
|
528
|
-
/* @__PURE__ */ (0,
|
|
529
|
-
/* @__PURE__ */ (0,
|
|
530
|
-
/* @__PURE__ */ (0,
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "9" }, "c"),
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 7v6" }, "b"),
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 16v.5" }, "d")
|
|
531
670
|
]);
|
|
532
671
|
}
|
|
533
672
|
|
|
534
673
|
// src/panels/DiagnosticBadge.tsx
|
|
535
|
-
var
|
|
674
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
536
675
|
function DiagnosticBadge({ diagnostic, variant, size = 12 }) {
|
|
537
|
-
return /* @__PURE__ */ (0,
|
|
676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
538
677
|
"span",
|
|
539
678
|
{
|
|
540
679
|
className: `${variant} hl-diag-${diagnostic.severity}`,
|
|
541
680
|
title: diagnostic.message,
|
|
542
681
|
"aria-label": `${diagnostic.severity}: ${diagnostic.message}`,
|
|
543
|
-
children: diagnostic.severity === "error" ? /* @__PURE__ */ (0,
|
|
682
|
+
children: diagnostic.severity === "error" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorIcon, { size }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(WarningIcon, { size })
|
|
544
683
|
}
|
|
545
684
|
);
|
|
546
685
|
}
|
|
547
686
|
|
|
548
687
|
// src/nodes/NodeInteractionContext.tsx
|
|
549
688
|
var import_react3 = require("react");
|
|
550
|
-
var
|
|
689
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
551
690
|
var NoopInteraction = {
|
|
552
691
|
diagnosticFor: () => void 0,
|
|
553
692
|
rename: () => void 0
|
|
@@ -557,14 +696,14 @@ function NodeInteractionProvider({
|
|
|
557
696
|
value,
|
|
558
697
|
children
|
|
559
698
|
}) {
|
|
560
|
-
return /* @__PURE__ */ (0,
|
|
699
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NodeInteractionCtx.Provider, { value, children });
|
|
561
700
|
}
|
|
562
701
|
function useNodeInteraction() {
|
|
563
702
|
return (0, import_react3.useContext)(NodeInteractionCtx);
|
|
564
703
|
}
|
|
565
704
|
|
|
566
705
|
// src/nodes/PillNode.tsx
|
|
567
|
-
var
|
|
706
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
568
707
|
var DOUBLE_CLICK_MS = 320;
|
|
569
708
|
function PillNodeChrome({ node, selected }) {
|
|
570
709
|
const live = useNodeLiveState(node.id);
|
|
@@ -610,18 +749,20 @@ function PillNodeChrome({ node, selected }) {
|
|
|
610
749
|
}, []);
|
|
611
750
|
const inputs = node.ports.filter((p) => p.direction === "I" && !p.isError);
|
|
612
751
|
const outputs = node.ports.filter((p) => p.direction === "O" && !p.isError);
|
|
613
|
-
const
|
|
752
|
+
const className2 = [
|
|
614
753
|
"hl-pill",
|
|
615
754
|
`hl-pill-${node.kind.toLowerCase()}`,
|
|
616
755
|
selected ? "is-selected" : "",
|
|
617
756
|
live === "active" ? "is-active" : "",
|
|
618
757
|
live === "error" ? "is-live-error" : "",
|
|
758
|
+
live === "finished" ? "is-finished" : "",
|
|
619
759
|
(diagnostic == null ? void 0 : diagnostic.severity) === "error" ? "has-diag-error" : "",
|
|
620
760
|
(diagnostic == null ? void 0 : diagnostic.severity) === "warning" ? "has-diag-warning" : ""
|
|
621
761
|
].filter(Boolean).join(" ");
|
|
622
|
-
return /* @__PURE__ */ (0,
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
624
|
-
|
|
762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: className2, "data-kind": node.kind, children: [
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LivePulse, { nodeId: node.id }),
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "hl-pill-dot", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NodeIcon, { code: node.code, kind: node.kind, size: 13 }) }),
|
|
765
|
+
editing ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
625
766
|
"input",
|
|
626
767
|
{
|
|
627
768
|
ref: inputRef,
|
|
@@ -633,7 +774,7 @@ function PillNodeChrome({ node, selected }) {
|
|
|
633
774
|
spellCheck: false,
|
|
634
775
|
"aria-label": "Rename node"
|
|
635
776
|
}
|
|
636
|
-
) : /* @__PURE__ */ (0,
|
|
777
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
637
778
|
"span",
|
|
638
779
|
{
|
|
639
780
|
className: "hl-pill-name",
|
|
@@ -644,62 +785,167 @@ function PillNodeChrome({ node, selected }) {
|
|
|
644
785
|
children: node.name
|
|
645
786
|
}
|
|
646
787
|
),
|
|
647
|
-
diagnostic !== void 0 && /* @__PURE__ */ (0,
|
|
648
|
-
/* @__PURE__ */ (0,
|
|
649
|
-
/* @__PURE__ */ (0,
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
788
|
+
diagnostic !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DiagnosticBadge, { diagnostic, variant: "hl-pill-diag", size: 12 }),
|
|
789
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "hl-pill-status", "aria-hidden": true }),
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "hl-pill-ports hl-in", children: inputs.map((port) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PortRow, { port }, port.id)) }),
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "hl-pill-ports hl-out", children: outputs.map((port) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PortRow, { port }, port.id)) })
|
|
651
792
|
] });
|
|
652
793
|
}
|
|
653
794
|
|
|
654
795
|
// src/nodes/HlangNode.tsx
|
|
655
|
-
var
|
|
796
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
656
797
|
function NodeChrome({ node, selected, body }) {
|
|
657
798
|
const inputs = node.ports.filter((p) => p.direction === "I");
|
|
658
799
|
const outputs = node.ports.filter((p) => p.direction === "O");
|
|
659
800
|
const live = useNodeLiveState(node.id);
|
|
660
|
-
const
|
|
801
|
+
const className2 = [
|
|
661
802
|
"hl-node",
|
|
662
803
|
`hl-${node.kind.toLowerCase()}`,
|
|
663
804
|
selected ? "is-selected" : "",
|
|
664
805
|
live === "active" ? "is-active" : "",
|
|
665
|
-
live === "error" ? "is-live-error" : ""
|
|
806
|
+
live === "error" ? "is-live-error" : "",
|
|
807
|
+
live === "finished" ? "is-finished" : ""
|
|
666
808
|
].filter(Boolean).join(" ");
|
|
667
|
-
return /* @__PURE__ */ (0,
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
670
|
-
|
|
671
|
-
/* @__PURE__ */ (0,
|
|
672
|
-
/* @__PURE__ */ (0,
|
|
809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: className2, "data-kind": node.kind, children: [
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LivePulse, { nodeId: node.id }),
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SignalBar, {}),
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("header", { className: "hl-head", children: [
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "hl-kind", children: node.kind }),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "hl-name", children: node.name }),
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "hl-role", children: KIND_ROLE[node.kind] })
|
|
673
816
|
] }),
|
|
674
|
-
/* @__PURE__ */ (0,
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
676
|
-
/* @__PURE__ */ (0,
|
|
677
|
-
/* @__PURE__ */ (0,
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeBodySlot, { node, children: body }),
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "hl-ports", children: [
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className: "hl-col hl-in", children: inputs.map((port) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PortRow, { port }, port.id)) }),
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className: "hl-col hl-out", children: outputs.map((port) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PortRow, { port }, port.id)) })
|
|
678
821
|
] })
|
|
679
822
|
] });
|
|
680
823
|
}
|
|
681
824
|
function HlangNode({ data, selected }) {
|
|
682
825
|
const node = data.editorNode;
|
|
683
826
|
if (typeof node.params.imageUrl === "string" && node.params.imageUrl.length > 0) {
|
|
684
|
-
return /* @__PURE__ */ (0,
|
|
827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AssetNodeChrome, { node, selected });
|
|
685
828
|
}
|
|
686
|
-
return /* @__PURE__ */ (0,
|
|
829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PillNodeChrome, { node, selected });
|
|
687
830
|
}
|
|
688
831
|
|
|
689
832
|
// src/edges/FlowEdge.tsx
|
|
690
833
|
var import_react5 = require("@xyflow/react");
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
834
|
+
|
|
835
|
+
// src/edges/self-loop.ts
|
|
836
|
+
var SELF_LOOP_CLEARANCE = 28;
|
|
837
|
+
var SELF_LOOP_RADIUS = 16;
|
|
838
|
+
function format(value) {
|
|
839
|
+
return String(Math.round(value * 100) / 100);
|
|
840
|
+
}
|
|
841
|
+
function distance(a, b) {
|
|
842
|
+
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
843
|
+
}
|
|
844
|
+
function toward(from, to, length) {
|
|
845
|
+
const span = distance(from, to);
|
|
846
|
+
const share = span === 0 ? 0 : length / span;
|
|
847
|
+
return { x: from.x + (to.x - from.x) * share, y: from.y + (to.y - from.y) * share };
|
|
848
|
+
}
|
|
849
|
+
function selfLoopPath(input) {
|
|
850
|
+
var _a, _b, _c, _d, _e;
|
|
851
|
+
const clearance = (_a = input.clearance) != null ? _a : SELF_LOOP_CLEARANCE;
|
|
852
|
+
const radius = (_b = input.radius) != null ? _b : SELF_LOOP_RADIUS;
|
|
853
|
+
const { source, target, node } = input;
|
|
854
|
+
const right = Math.max(source.x, node.x + node.width) + clearance;
|
|
855
|
+
const left = Math.min(target.x, node.x) - clearance;
|
|
856
|
+
const below = node.y + node.height + clearance;
|
|
857
|
+
const points = [
|
|
858
|
+
source,
|
|
859
|
+
{ x: right, y: source.y },
|
|
860
|
+
{ x: right, y: below },
|
|
861
|
+
{ x: left, y: below },
|
|
862
|
+
{ x: left, y: target.y },
|
|
863
|
+
target
|
|
864
|
+
];
|
|
865
|
+
const parts = [`M ${format(source.x)} ${format(source.y)}`];
|
|
866
|
+
for (let i = 1; i < points.length - 1; i += 1) {
|
|
867
|
+
const before = (_c = points[i - 1]) != null ? _c : source;
|
|
868
|
+
const corner = (_d = points[i]) != null ? _d : source;
|
|
869
|
+
const after = (_e = points[i + 1]) != null ? _e : target;
|
|
870
|
+
const r = Math.min(radius, distance(before, corner) / 2, distance(corner, after) / 2);
|
|
871
|
+
if (r <= 0) {
|
|
872
|
+
parts.push(`L ${format(corner.x)} ${format(corner.y)}`);
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
const enter = toward(corner, before, r);
|
|
876
|
+
const leave = toward(corner, after, r);
|
|
877
|
+
parts.push(
|
|
878
|
+
`L ${format(enter.x)} ${format(enter.y)} Q ${format(corner.x)} ${format(corner.y)} ${format(leave.x)} ${format(leave.y)}`
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
parts.push(`L ${format(target.x)} ${format(target.y)}`);
|
|
882
|
+
return { path: parts.join(" "), labelX: (right + left) / 2, labelY: below };
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// src/edges/edge-bounds.ts
|
|
886
|
+
var DEFAULT_EDGE_CAPACITY = 10;
|
|
887
|
+
function boundsFields(bounds) {
|
|
888
|
+
var _a;
|
|
889
|
+
const bounded = bounds.capacity !== void 0;
|
|
890
|
+
return [
|
|
891
|
+
{ key: "bounded", label: "Bounded", type: "toggle", value: bounded },
|
|
892
|
+
{ key: "capacity", label: "Capacity", type: "number", value: (_a = bounds.capacity) != null ? _a : DEFAULT_EDGE_CAPACITY, disabled: !bounded },
|
|
893
|
+
{
|
|
894
|
+
key: "dropOldest",
|
|
895
|
+
label: "Drop oldest when full",
|
|
896
|
+
type: "toggle",
|
|
897
|
+
value: bounds.overflow === "drop-oldest",
|
|
898
|
+
disabled: !bounded
|
|
899
|
+
}
|
|
900
|
+
];
|
|
901
|
+
}
|
|
902
|
+
function nextBounds(bounds, key, value) {
|
|
903
|
+
const { capacity, overflow } = bounds;
|
|
904
|
+
if (key === "bounded") {
|
|
905
|
+
return value === true ? { capacity: capacity != null ? capacity : DEFAULT_EDGE_CAPACITY } : {};
|
|
906
|
+
}
|
|
907
|
+
if (capacity === void 0) {
|
|
908
|
+
return {};
|
|
909
|
+
}
|
|
910
|
+
const keep = overflow === void 0 ? {} : { overflow };
|
|
911
|
+
if (key === "capacity") {
|
|
912
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
913
|
+
return bounds;
|
|
914
|
+
}
|
|
915
|
+
return { capacity: Math.max(1, Math.round(value)), ...keep };
|
|
916
|
+
}
|
|
917
|
+
if (key === "dropOldest") {
|
|
918
|
+
return value === true ? { capacity, overflow: "drop-oldest" } : { capacity };
|
|
919
|
+
}
|
|
920
|
+
return bounds;
|
|
921
|
+
}
|
|
922
|
+
function capacityLabel(bounds) {
|
|
923
|
+
if (bounds.capacity === void 0) {
|
|
924
|
+
return void 0;
|
|
925
|
+
}
|
|
926
|
+
const label = `[${String(bounds.capacity)}]`;
|
|
927
|
+
return bounds.overflow === "drop-oldest" ? `${label} drop oldest` : label;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// src/edges/FlowEdge.tsx
|
|
931
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
932
|
+
function roleOf(node) {
|
|
933
|
+
const role = node == null ? void 0 : node.data.editorNode.params.role;
|
|
697
934
|
return typeof role === "string" && role.length > 0 ? role : void 0;
|
|
698
935
|
}
|
|
699
936
|
function FlowEdge(props) {
|
|
700
|
-
var _a;
|
|
701
|
-
const { id, source, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data } = props;
|
|
702
|
-
const
|
|
937
|
+
var _a, _b, _c, _d, _e, _f;
|
|
938
|
+
const { id, source, target, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, selected } = props;
|
|
939
|
+
const sourceNode = (0, import_react5.useInternalNode)(source);
|
|
940
|
+
const role = roleOf(sourceNode);
|
|
941
|
+
const width = sourceNode == null ? void 0 : sourceNode.measured.width;
|
|
942
|
+
const height = sourceNode == null ? void 0 : sourceNode.measured.height;
|
|
943
|
+
const loop = source === target && sourceNode !== void 0 && width !== void 0 && height !== void 0 ? selfLoopPath({
|
|
944
|
+
source: { x: sourceX, y: sourceY },
|
|
945
|
+
target: { x: targetX, y: targetY },
|
|
946
|
+
node: { ...sourceNode.internals.positionAbsolute, width, height }
|
|
947
|
+
}) : void 0;
|
|
948
|
+
const [curve] = (0, import_react5.getBezierPath)({
|
|
703
949
|
sourceX,
|
|
704
950
|
sourceY,
|
|
705
951
|
sourcePosition,
|
|
@@ -707,25 +953,39 @@ function FlowEdge(props) {
|
|
|
707
953
|
targetY,
|
|
708
954
|
targetPosition
|
|
709
955
|
});
|
|
956
|
+
const path = (_a = loop == null ? void 0 : loop.path) != null ? _a : curve;
|
|
710
957
|
const t = 0.62;
|
|
711
|
-
const labelX = sourceX + (targetX - sourceX) * t;
|
|
712
|
-
const labelY = sourceY + (targetY - sourceY) * t;
|
|
713
|
-
const
|
|
958
|
+
const labelX = (_b = loop == null ? void 0 : loop.labelX) != null ? _b : sourceX + (targetX - sourceX) * t;
|
|
959
|
+
const labelY = (_c = loop == null ? void 0 : loop.labelY) != null ? _c : sourceY + (targetY - sourceY) * t;
|
|
960
|
+
const capacity = capacityLabel(data != null ? data : {});
|
|
961
|
+
const capacityX = (_d = loop == null ? void 0 : loop.labelX) != null ? _d : sourceX + (targetX - sourceX) * 0.38;
|
|
962
|
+
const capacityY = (_e = loop == null ? void 0 : loop.labelY) != null ? _e : sourceY + (targetY - sourceY) * 0.38;
|
|
963
|
+
const isError = (_f = data == null ? void 0 : data.isError) != null ? _f : false;
|
|
714
964
|
const isValue = (data == null ? void 0 : data.stream) === "value";
|
|
715
965
|
const flowing = useEdgeFlowing(id);
|
|
716
|
-
const
|
|
717
|
-
const
|
|
966
|
+
const pulse = useEdgePulse(id);
|
|
967
|
+
const className2 = [
|
|
718
968
|
"hl-edge",
|
|
719
969
|
isError ? "is-error" : "",
|
|
720
970
|
isValue ? "is-value" : "is-live",
|
|
721
|
-
flowing ? "is-flowing" : ""
|
|
971
|
+
flowing ? "is-flowing" : "",
|
|
972
|
+
selected === true ? "is-selected" : ""
|
|
722
973
|
].filter(Boolean).join(" ");
|
|
723
|
-
return /* @__PURE__ */ (0,
|
|
724
|
-
/* @__PURE__ */ (0,
|
|
725
|
-
/* @__PURE__ */ (0,
|
|
726
|
-
/* @__PURE__ */ (0,
|
|
974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
975
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("g", { className: className2, children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react5.BaseEdge, { id, path, className: "hl-edge-base" }),
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: path, className: "hl-edge-flow" }),
|
|
978
|
+
pulse > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: path, className: "hl-edge-pulse" }, pulse)
|
|
727
979
|
] }),
|
|
728
|
-
|
|
980
|
+
capacity !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react5.EdgeLabelRenderer, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
981
|
+
"div",
|
|
982
|
+
{
|
|
983
|
+
className: `hl-edge-capacity hl-mono${(data == null ? void 0 : data.overflow) === "drop-oldest" ? " is-lossy" : ""}`,
|
|
984
|
+
style: { transform: `translate(-50%, -50%) translate(${String(capacityX)}px, ${String(capacityY)}px)` },
|
|
985
|
+
children: capacity
|
|
986
|
+
}
|
|
987
|
+
) }),
|
|
988
|
+
role !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react5.EdgeLabelRenderer, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
729
989
|
"div",
|
|
730
990
|
{
|
|
731
991
|
className: "hl-edge-label hl-mono",
|
|
@@ -747,49 +1007,257 @@ function createHlangFlowTypes() {
|
|
|
747
1007
|
}
|
|
748
1008
|
|
|
749
1009
|
// src/shell/EditorShell.tsx
|
|
750
|
-
var
|
|
1010
|
+
var import_react7 = require("react");
|
|
1011
|
+
|
|
1012
|
+
// src/shell/FooterResizer.tsx
|
|
1013
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1014
|
+
function FooterResizer({ resize, controls, label }) {
|
|
1015
|
+
const onPointerDown = (event) => {
|
|
1016
|
+
if (event.pointerType === "mouse" && event.button !== 0) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
event.preventDefault();
|
|
1020
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
1021
|
+
resize.startDrag(event.clientY);
|
|
1022
|
+
};
|
|
1023
|
+
const onPointerMove = (event) => {
|
|
1024
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1025
|
+
resize.drag(event.clientY);
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
const onPointerEnd = (event) => {
|
|
1029
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
1030
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1031
|
+
}
|
|
1032
|
+
resize.endDrag();
|
|
1033
|
+
};
|
|
1034
|
+
const onKeyDown = (event) => {
|
|
1035
|
+
if (resize.keyDown(event.key, event.shiftKey)) {
|
|
1036
|
+
event.preventDefault();
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1040
|
+
"div",
|
|
1041
|
+
{
|
|
1042
|
+
role: "separator",
|
|
1043
|
+
"aria-orientation": "horizontal",
|
|
1044
|
+
"aria-label": label,
|
|
1045
|
+
"aria-controls": controls,
|
|
1046
|
+
"aria-valuemin": resize.bounds.min,
|
|
1047
|
+
"aria-valuemax": resize.bounds.max,
|
|
1048
|
+
"aria-valuenow": resize.height,
|
|
1049
|
+
tabIndex: 0,
|
|
1050
|
+
className: `hl-footer-resizer${resize.dragging ? " is-dragging" : ""}`,
|
|
1051
|
+
onPointerDown,
|
|
1052
|
+
onPointerMove,
|
|
1053
|
+
onPointerUp: onPointerEnd,
|
|
1054
|
+
onPointerCancel: onPointerEnd,
|
|
1055
|
+
onLostPointerCapture: () => {
|
|
1056
|
+
resize.endDrag();
|
|
1057
|
+
},
|
|
1058
|
+
onDoubleClick: () => {
|
|
1059
|
+
resize.toggle();
|
|
1060
|
+
},
|
|
1061
|
+
onKeyDown
|
|
1062
|
+
}
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// src/shell/useFooterResize.ts
|
|
1067
|
+
var import_react6 = require("react");
|
|
1068
|
+
|
|
1069
|
+
// src/shell/footer-size.ts
|
|
1070
|
+
var FOOTER_KEY_STEP = 16;
|
|
1071
|
+
function footerBounds(options) {
|
|
1072
|
+
const { available, minHeight, minCanvasHeight } = options;
|
|
1073
|
+
return { min: minHeight, max: Math.max(minHeight, available - minCanvasHeight) };
|
|
1074
|
+
}
|
|
1075
|
+
function clampFooter(height, bounds) {
|
|
1076
|
+
return Math.round(Math.min(bounds.max, Math.max(bounds.min, height)));
|
|
1077
|
+
}
|
|
1078
|
+
function resizeByKey(height, key, shift, bounds) {
|
|
1079
|
+
const step = FOOTER_KEY_STEP * (shift ? 4 : 1);
|
|
1080
|
+
switch (key) {
|
|
1081
|
+
case "ArrowUp":
|
|
1082
|
+
return clampFooter(height + step, bounds);
|
|
1083
|
+
case "ArrowDown":
|
|
1084
|
+
return clampFooter(height - step, bounds);
|
|
1085
|
+
case "Home":
|
|
1086
|
+
return bounds.min;
|
|
1087
|
+
case "End":
|
|
1088
|
+
return bounds.max;
|
|
1089
|
+
default:
|
|
1090
|
+
return void 0;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function toggleCollapsed(size, bounds) {
|
|
1094
|
+
if (size.height > bounds.min) {
|
|
1095
|
+
return { height: bounds.min, restore: size.height };
|
|
1096
|
+
}
|
|
1097
|
+
return { height: clampFooter(size.restore, bounds), restore: size.restore };
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/shell/useFooterResize.ts
|
|
1101
|
+
var DEFAULT_MIN_CANVAS_HEIGHT = 160;
|
|
1102
|
+
function useFooterResize(options) {
|
|
1103
|
+
var _a;
|
|
1104
|
+
const { defaultHeight, minHeight } = options;
|
|
1105
|
+
const minCanvasHeight = (_a = options.minCanvasHeight) != null ? _a : DEFAULT_MIN_CANVAS_HEIGHT;
|
|
1106
|
+
const [available, setAvailable] = (0, import_react6.useState)(null);
|
|
1107
|
+
const [preferred, setPreferred] = (0, import_react6.useState)(defaultHeight);
|
|
1108
|
+
const [restore, setRestore] = (0, import_react6.useState)(defaultHeight);
|
|
1109
|
+
const [dragging, setDragging] = (0, import_react6.useState)(false);
|
|
1110
|
+
const dragStart = (0, import_react6.useRef)(null);
|
|
1111
|
+
const bounds = (0, import_react6.useMemo)(
|
|
1112
|
+
() => available === null ? { min: minHeight, max: Math.max(minHeight, defaultHeight) } : footerBounds({ available, minHeight, minCanvasHeight }),
|
|
1113
|
+
[available, minHeight, minCanvasHeight, defaultHeight]
|
|
1114
|
+
);
|
|
1115
|
+
const height = clampFooter(preferred, bounds);
|
|
1116
|
+
const choose = (0, import_react6.useCallback)(
|
|
1117
|
+
(next) => {
|
|
1118
|
+
setPreferred(next);
|
|
1119
|
+
if (next > bounds.min) {
|
|
1120
|
+
setRestore(next);
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
[bounds.min]
|
|
1124
|
+
);
|
|
1125
|
+
const measure = (0, import_react6.useCallback)((next) => {
|
|
1126
|
+
setAvailable(next);
|
|
1127
|
+
}, []);
|
|
1128
|
+
const startDrag = (0, import_react6.useCallback)(
|
|
1129
|
+
(clientY) => {
|
|
1130
|
+
dragStart.current = { clientY, height };
|
|
1131
|
+
setDragging(true);
|
|
1132
|
+
},
|
|
1133
|
+
[height]
|
|
1134
|
+
);
|
|
1135
|
+
const drag = (0, import_react6.useCallback)(
|
|
1136
|
+
(clientY) => {
|
|
1137
|
+
const start = dragStart.current;
|
|
1138
|
+
if (start === null) {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
choose(clampFooter(start.height + (start.clientY - clientY), bounds));
|
|
1142
|
+
},
|
|
1143
|
+
[bounds, choose]
|
|
1144
|
+
);
|
|
1145
|
+
const endDrag = (0, import_react6.useCallback)(() => {
|
|
1146
|
+
dragStart.current = null;
|
|
1147
|
+
setDragging(false);
|
|
1148
|
+
}, []);
|
|
1149
|
+
const toggle = (0, import_react6.useCallback)(() => {
|
|
1150
|
+
const next = toggleCollapsed({ height, restore }, bounds);
|
|
1151
|
+
setPreferred(next.height);
|
|
1152
|
+
setRestore(next.restore);
|
|
1153
|
+
}, [height, restore, bounds]);
|
|
1154
|
+
const keyDown = (0, import_react6.useCallback)(
|
|
1155
|
+
(key, shift) => {
|
|
1156
|
+
if (key === "Enter") {
|
|
1157
|
+
toggle();
|
|
1158
|
+
return true;
|
|
1159
|
+
}
|
|
1160
|
+
const next = resizeByKey(height, key, shift, bounds);
|
|
1161
|
+
if (next === void 0) {
|
|
1162
|
+
return false;
|
|
1163
|
+
}
|
|
1164
|
+
choose(next);
|
|
1165
|
+
return true;
|
|
1166
|
+
},
|
|
1167
|
+
[height, bounds, choose, toggle]
|
|
1168
|
+
);
|
|
1169
|
+
return { height, bounds, dragging, measure, startDrag, drag, endDrag, keyDown, toggle };
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// src/shell/EditorShell.tsx
|
|
1173
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
751
1174
|
function EditorShell({
|
|
752
1175
|
toolbar,
|
|
753
1176
|
left,
|
|
754
1177
|
right,
|
|
755
1178
|
canvas,
|
|
756
1179
|
footer,
|
|
1180
|
+
footerResize,
|
|
757
1181
|
leftCollapsed = false,
|
|
758
1182
|
rightCollapsed = false
|
|
759
1183
|
}) {
|
|
760
|
-
const
|
|
1184
|
+
const shellRef = (0, import_react7.useRef)(null);
|
|
1185
|
+
const toolbarRef = (0, import_react7.useRef)(null);
|
|
1186
|
+
const className2 = [
|
|
761
1187
|
"hl-shell",
|
|
762
1188
|
leftCollapsed ? "hl-left-collapsed" : "",
|
|
763
1189
|
rightCollapsed ? "hl-right-collapsed" : ""
|
|
764
1190
|
].filter(Boolean).join(" ");
|
|
765
|
-
return /* @__PURE__ */ (0,
|
|
766
|
-
toolbar !== void 0 && /* @__PURE__ */ (0,
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
768
|
-
left !== void 0 && !leftCollapsed && /* @__PURE__ */ (0,
|
|
769
|
-
/* @__PURE__ */ (0,
|
|
770
|
-
right !== void 0 && !rightCollapsed && /* @__PURE__ */ (0,
|
|
1191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: className2, ref: shellRef, children: [
|
|
1192
|
+
toolbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "hl-region-toolbar", ref: toolbarRef, children: toolbar }),
|
|
1193
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "hl-region-body", children: [
|
|
1194
|
+
left !== void 0 && !leftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("aside", { className: "hl-region-left", children: left }),
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("main", { className: "hl-region-canvas", children: canvas }),
|
|
1196
|
+
right !== void 0 && !rightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("aside", { className: "hl-region-right", children: right })
|
|
771
1197
|
] }),
|
|
772
|
-
footer !== void 0 && /* @__PURE__ */ (0,
|
|
1198
|
+
footer !== void 0 && (footerResize === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "hl-region-footer", children: footer }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ResizableFooter, { options: footerResize, shellRef, toolbarRef, children: footer }))
|
|
773
1199
|
] });
|
|
774
1200
|
}
|
|
1201
|
+
function ResizableFooter({
|
|
1202
|
+
options,
|
|
1203
|
+
shellRef,
|
|
1204
|
+
toolbarRef,
|
|
1205
|
+
children
|
|
1206
|
+
}) {
|
|
1207
|
+
var _a;
|
|
1208
|
+
const resize = useFooterResize(options);
|
|
1209
|
+
const id = (0, import_react7.useId)();
|
|
1210
|
+
const { measure } = resize;
|
|
1211
|
+
(0, import_react7.useEffect)(() => {
|
|
1212
|
+
const shell = shellRef.current;
|
|
1213
|
+
if (shell === null) {
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const update = () => {
|
|
1217
|
+
var _a2, _b;
|
|
1218
|
+
measure(shell.clientHeight - ((_b = (_a2 = toolbarRef.current) == null ? void 0 : _a2.offsetHeight) != null ? _b : 0));
|
|
1219
|
+
};
|
|
1220
|
+
update();
|
|
1221
|
+
const observer = new ResizeObserver(update);
|
|
1222
|
+
observer.observe(shell);
|
|
1223
|
+
if (toolbarRef.current !== null) {
|
|
1224
|
+
observer.observe(toolbarRef.current);
|
|
1225
|
+
}
|
|
1226
|
+
return () => {
|
|
1227
|
+
observer.disconnect();
|
|
1228
|
+
};
|
|
1229
|
+
}, [measure, shellRef, toolbarRef]);
|
|
1230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1231
|
+
"div",
|
|
1232
|
+
{
|
|
1233
|
+
id,
|
|
1234
|
+
className: `hl-region-footer is-resizable${resize.dragging ? " is-resizing" : ""}`,
|
|
1235
|
+
style: { height: resize.height },
|
|
1236
|
+
children: [
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FooterResizer, { resize, controls: id, label: (_a = options.label) != null ? _a : "Resize the panel" }),
|
|
1238
|
+
children
|
|
1239
|
+
]
|
|
1240
|
+
}
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
775
1243
|
|
|
776
1244
|
// src/toolbar/Toolbar.tsx
|
|
777
1245
|
var import_editor_react = require("@hlang-tech/editor-react");
|
|
778
|
-
var
|
|
1246
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
779
1247
|
function Toolbar({ title, center, actions }) {
|
|
780
|
-
return /* @__PURE__ */ (0,
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
782
|
-
/* @__PURE__ */ (0,
|
|
783
|
-
/* @__PURE__ */ (0,
|
|
1248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "hl-toolbar", children: [
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "hl-toolbar-brand", children: title != null ? title : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "hl-toolbar-glyph", "aria-hidden": "true" }),
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "hl-toolbar-wordmark", children: "hlang" })
|
|
784
1252
|
] }) }),
|
|
785
|
-
center !== void 0 && /* @__PURE__ */ (0,
|
|
786
|
-
/* @__PURE__ */ (0,
|
|
1253
|
+
center !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "hl-toolbar-center", children: center }),
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "hl-toolbar-actions", children: actions })
|
|
787
1255
|
] });
|
|
788
1256
|
}
|
|
789
1257
|
function UndoRedo({ core }) {
|
|
790
1258
|
const history = (0, import_editor_react.useHistory)(core);
|
|
791
|
-
return /* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
1259
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
793
1261
|
"button",
|
|
794
1262
|
{
|
|
795
1263
|
type: "button",
|
|
@@ -800,7 +1268,7 @@ function UndoRedo({ core }) {
|
|
|
800
1268
|
children: "Undo"
|
|
801
1269
|
}
|
|
802
1270
|
),
|
|
803
|
-
/* @__PURE__ */ (0,
|
|
1271
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
804
1272
|
"button",
|
|
805
1273
|
{
|
|
806
1274
|
type: "button",
|
|
@@ -819,7 +1287,7 @@ function RunButton({
|
|
|
819
1287
|
runLabel = "Run",
|
|
820
1288
|
stopLabel = "Stop"
|
|
821
1289
|
}) {
|
|
822
|
-
return /* @__PURE__ */ (0,
|
|
1290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
823
1291
|
"button",
|
|
824
1292
|
{
|
|
825
1293
|
type: "button",
|
|
@@ -827,7 +1295,7 @@ function RunButton({
|
|
|
827
1295
|
onClick: onRun,
|
|
828
1296
|
"aria-pressed": running,
|
|
829
1297
|
children: [
|
|
830
|
-
/* @__PURE__ */ (0,
|
|
1298
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
831
1299
|
"span",
|
|
832
1300
|
{
|
|
833
1301
|
className: `hl-toolbar-run-icon${running ? " is-stop" : ""}`,
|
|
@@ -840,22 +1308,22 @@ function RunButton({
|
|
|
840
1308
|
);
|
|
841
1309
|
}
|
|
842
1310
|
function ToolbarStat({ label, value }) {
|
|
843
|
-
return /* @__PURE__ */ (0,
|
|
1311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "hl-toolbar-stat hl-mono", title: label, children: value });
|
|
844
1312
|
}
|
|
845
1313
|
function ToolbarGhostButton({
|
|
846
1314
|
children,
|
|
847
1315
|
onClick,
|
|
848
1316
|
title
|
|
849
1317
|
}) {
|
|
850
|
-
return /* @__PURE__ */ (0,
|
|
1318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "hl-toolbar-btn", onClick, title, children });
|
|
851
1319
|
}
|
|
852
1320
|
|
|
853
1321
|
// src/toolbar/ToolCluster.tsx
|
|
854
|
-
var
|
|
1322
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
855
1323
|
function ToolCluster({ items }) {
|
|
856
|
-
return /* @__PURE__ */ (0,
|
|
857
|
-
item.separatorBefore === true && /* @__PURE__ */ (0,
|
|
858
|
-
/* @__PURE__ */ (0,
|
|
1324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "hl-toolcluster", role: "toolbar", "aria-label": "Canvas tools", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "hl-toolcluster-slot", children: [
|
|
1325
|
+
item.separatorBefore === true && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "hl-toolcluster-sep", "aria-hidden": true }),
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
859
1327
|
"button",
|
|
860
1328
|
{
|
|
861
1329
|
type: "button",
|
|
@@ -872,31 +1340,31 @@ function ToolCluster({ items }) {
|
|
|
872
1340
|
}
|
|
873
1341
|
|
|
874
1342
|
// src/canvas/CanvasChrome.tsx
|
|
875
|
-
var
|
|
876
|
-
var
|
|
1343
|
+
var import_react8 = require("@xyflow/react");
|
|
1344
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
877
1345
|
function CanvasChrome({ background = true }) {
|
|
878
|
-
return /* @__PURE__ */ (0,
|
|
1346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: background && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react8.Background, { variant: import_react8.BackgroundVariant.Dots, gap: 26, size: 1, color: "#242830" }) });
|
|
879
1347
|
}
|
|
880
1348
|
|
|
881
1349
|
// src/canvas/CanvasDock.tsx
|
|
882
|
-
var
|
|
1350
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
883
1351
|
function CursorIcon() {
|
|
884
|
-
return /* @__PURE__ */ (0,
|
|
1352
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M5 3l6 16 2-6 6-2z" }) });
|
|
885
1353
|
}
|
|
886
1354
|
function HandIcon() {
|
|
887
|
-
return /* @__PURE__ */ (0,
|
|
1355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M8 12V6a1.5 1.5 0 013 0v5m0-1V5a1.5 1.5 0 013 0v6m0-1V6.5a1.5 1.5 0 013 0V13c0 3.5-2 6-5.5 6H12c-2 0-3-.8-4.2-2.5L5 12.5c-.7-1 .6-2.3 1.6-1.6z" }) });
|
|
888
1356
|
}
|
|
889
1357
|
function PlusIcon() {
|
|
890
|
-
return /* @__PURE__ */ (0,
|
|
1358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 17, height: 17, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M12 5v14M5 12h14" }) });
|
|
891
1359
|
}
|
|
892
1360
|
function FitIcon() {
|
|
893
|
-
return /* @__PURE__ */ (0,
|
|
1361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 15, height: 15, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5" }) });
|
|
894
1362
|
}
|
|
895
1363
|
function UndoIcon() {
|
|
896
|
-
return /* @__PURE__ */ (0,
|
|
1364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 15, height: 15, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M9 7L4 12l5 5M4 12h11a5 5 0 010 10h-1" }) });
|
|
897
1365
|
}
|
|
898
1366
|
function RedoIcon() {
|
|
899
|
-
return /* @__PURE__ */ (0,
|
|
1367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 15, height: 15, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M15 7l5 5-5 5M20 12H9a5 5 0 000 10h1" }) });
|
|
900
1368
|
}
|
|
901
1369
|
function CanvasDock({
|
|
902
1370
|
zoom,
|
|
@@ -912,8 +1380,8 @@ function CanvasDock({
|
|
|
912
1380
|
canRedo
|
|
913
1381
|
}) {
|
|
914
1382
|
const pct = `${String(Math.round(zoom * 100))}%`;
|
|
915
|
-
return /* @__PURE__ */ (0,
|
|
916
|
-
/* @__PURE__ */ (0,
|
|
1383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "hl-dock", role: "toolbar", "aria-label": "Canvas tools", children: [
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
917
1385
|
"button",
|
|
918
1386
|
{
|
|
919
1387
|
className: "hl-dock-btn",
|
|
@@ -921,10 +1389,10 @@ function CanvasDock({
|
|
|
921
1389
|
disabled: !canUndo,
|
|
922
1390
|
title: "Undo (\u2318Z)",
|
|
923
1391
|
"aria-label": "Undo",
|
|
924
|
-
children: /* @__PURE__ */ (0,
|
|
1392
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(UndoIcon, {})
|
|
925
1393
|
}
|
|
926
1394
|
),
|
|
927
|
-
/* @__PURE__ */ (0,
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
928
1396
|
"button",
|
|
929
1397
|
{
|
|
930
1398
|
className: "hl-dock-btn",
|
|
@@ -932,48 +1400,48 @@ function CanvasDock({
|
|
|
932
1400
|
disabled: !canRedo,
|
|
933
1401
|
title: "Redo (\u2318\u21E7Z)",
|
|
934
1402
|
"aria-label": "Redo",
|
|
935
|
-
children: /* @__PURE__ */ (0,
|
|
1403
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(RedoIcon, {})
|
|
936
1404
|
}
|
|
937
1405
|
),
|
|
938
|
-
/* @__PURE__ */ (0,
|
|
939
|
-
/* @__PURE__ */ (0,
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "hl-dock-sep", "aria-hidden": true }),
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
940
1408
|
"button",
|
|
941
1409
|
{
|
|
942
1410
|
className: "hl-dock-btn" + (mode === "select" ? " is-active" : ""),
|
|
943
1411
|
onClick: () => onModeChange("select"),
|
|
944
1412
|
title: "Select (V)",
|
|
945
1413
|
"aria-pressed": mode === "select",
|
|
946
|
-
children: /* @__PURE__ */ (0,
|
|
1414
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CursorIcon, {})
|
|
947
1415
|
}
|
|
948
1416
|
),
|
|
949
|
-
/* @__PURE__ */ (0,
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
950
1418
|
"button",
|
|
951
1419
|
{
|
|
952
1420
|
className: "hl-dock-btn" + (mode === "pan" ? " is-active" : ""),
|
|
953
1421
|
onClick: () => onModeChange("pan"),
|
|
954
1422
|
title: "Pan (Space)",
|
|
955
1423
|
"aria-pressed": mode === "pan",
|
|
956
|
-
children: /* @__PURE__ */ (0,
|
|
1424
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(HandIcon, {})
|
|
957
1425
|
}
|
|
958
1426
|
),
|
|
959
|
-
/* @__PURE__ */ (0,
|
|
960
|
-
/* @__PURE__ */ (0,
|
|
961
|
-
/* @__PURE__ */ (0,
|
|
962
|
-
/* @__PURE__ */ (0,
|
|
963
|
-
/* @__PURE__ */ (0,
|
|
964
|
-
/* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "hl-dock-btn hl-dock-add", onClick: onAdd, title: "Add node", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PlusIcon, {}) }),
|
|
1428
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "hl-dock-sep", "aria-hidden": true }),
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "hl-dock-btn", onClick: onZoomOut, title: "Zoom out", "aria-label": "Zoom out", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "hl-dock-glyph", children: "\u2212" }) }),
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "hl-dock-zoom hl-mono", onClick: onFitView, title: "Fit view", children: pct }),
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "hl-dock-btn", onClick: onZoomIn, title: "Zoom in", "aria-label": "Zoom in", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "hl-dock-glyph", children: "+" }) }),
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "hl-dock-btn hl-dock-fit", onClick: onFitView, title: "Fit view", "aria-label": "Fit view", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FitIcon, {}) })
|
|
965
1433
|
] });
|
|
966
1434
|
}
|
|
967
1435
|
|
|
968
1436
|
// src/canvas/EmptyState.tsx
|
|
969
|
-
var
|
|
1437
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
970
1438
|
function EmptyState({
|
|
971
1439
|
title = "An empty canvas.",
|
|
972
1440
|
hint = "add a source \xB7 wire it to a sink \xB7 run"
|
|
973
1441
|
}) {
|
|
974
|
-
return /* @__PURE__ */ (0,
|
|
975
|
-
/* @__PURE__ */ (0,
|
|
976
|
-
/* @__PURE__ */ (0,
|
|
1442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "hl-empty", "aria-hidden": "true", children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "hl-empty-title", children: title }),
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "hl-empty-hint", children: hint })
|
|
977
1445
|
] });
|
|
978
1446
|
}
|
|
979
1447
|
|
|
@@ -1009,11 +1477,11 @@ function deriveParamSchema(descriptor, node) {
|
|
|
1009
1477
|
}
|
|
1010
1478
|
|
|
1011
1479
|
// src/hooks/useNodeParams.ts
|
|
1012
|
-
var
|
|
1480
|
+
var import_react9 = require("react");
|
|
1013
1481
|
var import_editor_core = require("@hlang-tech/editor-core");
|
|
1014
1482
|
function useNodeParams(core, nodeId) {
|
|
1015
|
-
const versionRef = (0,
|
|
1016
|
-
const subscribe = (0,
|
|
1483
|
+
const versionRef = (0, import_react9.useRef)(0);
|
|
1484
|
+
const subscribe = (0, import_react9.useCallback)(
|
|
1017
1485
|
(onStoreChange) => {
|
|
1018
1486
|
const disposable = core.events.on("nodeChanged", (event) => {
|
|
1019
1487
|
if (nodeId !== void 0 && event.node.id === nodeId) {
|
|
@@ -1027,9 +1495,9 @@ function useNodeParams(core, nodeId) {
|
|
|
1027
1495
|
},
|
|
1028
1496
|
[core, nodeId]
|
|
1029
1497
|
);
|
|
1030
|
-
const getSnapshot = (0,
|
|
1031
|
-
const version = (0,
|
|
1032
|
-
const setParams = (0,
|
|
1498
|
+
const getSnapshot = (0, import_react9.useCallback)(() => versionRef.current, []);
|
|
1499
|
+
const version = (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1500
|
+
const setParams = (0, import_react9.useCallback)(
|
|
1033
1501
|
(next) => {
|
|
1034
1502
|
if (nodeId === void 0) {
|
|
1035
1503
|
return;
|
|
@@ -1038,7 +1506,7 @@ function useNodeParams(core, nodeId) {
|
|
|
1038
1506
|
},
|
|
1039
1507
|
[core, nodeId]
|
|
1040
1508
|
);
|
|
1041
|
-
const setParam = (0,
|
|
1509
|
+
const setParam = (0, import_react9.useCallback)(
|
|
1042
1510
|
(key, value) => {
|
|
1043
1511
|
if (nodeId === void 0) {
|
|
1044
1512
|
return;
|
|
@@ -1051,7 +1519,7 @@ function useNodeParams(core, nodeId) {
|
|
|
1051
1519
|
},
|
|
1052
1520
|
[core, nodeId, setParams]
|
|
1053
1521
|
);
|
|
1054
|
-
return (0,
|
|
1522
|
+
return (0, import_react9.useMemo)(
|
|
1055
1523
|
() => ({
|
|
1056
1524
|
node: nodeId === void 0 ? void 0 : core.model.getNode(nodeId),
|
|
1057
1525
|
setParam,
|
|
@@ -1063,19 +1531,58 @@ function useNodeParams(core, nodeId) {
|
|
|
1063
1531
|
);
|
|
1064
1532
|
}
|
|
1065
1533
|
|
|
1534
|
+
// src/hooks/useEdgeBounds.ts
|
|
1535
|
+
var import_react10 = require("react");
|
|
1536
|
+
var import_editor_core2 = require("@hlang-tech/editor-core");
|
|
1537
|
+
function useEdgeBounds(core, edgeId) {
|
|
1538
|
+
const subscribe = (0, import_react10.useCallback)(
|
|
1539
|
+
(onStoreChange) => {
|
|
1540
|
+
const changed = core.events.on("edgeChanged", (event) => {
|
|
1541
|
+
if (event.edge.id === edgeId) {
|
|
1542
|
+
onStoreChange();
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
const removed = core.events.on("edgeRemoved", (event) => {
|
|
1546
|
+
if (event.edgeId === edgeId) {
|
|
1547
|
+
onStoreChange();
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
return () => {
|
|
1551
|
+
changed.dispose();
|
|
1552
|
+
removed.dispose();
|
|
1553
|
+
};
|
|
1554
|
+
},
|
|
1555
|
+
[core, edgeId]
|
|
1556
|
+
);
|
|
1557
|
+
const getSnapshot = (0, import_react10.useCallback)(
|
|
1558
|
+
() => edgeId === void 0 ? void 0 : core.model.getEdge(edgeId),
|
|
1559
|
+
[core, edgeId]
|
|
1560
|
+
);
|
|
1561
|
+
const edge = (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1562
|
+
const setBounds = (0, import_react10.useCallback)(
|
|
1563
|
+
(bounds) => {
|
|
1564
|
+
if (edgeId !== void 0) {
|
|
1565
|
+
core.commands.execute(new import_editor_core2.SetEdgeBoundsCommand(edgeId, bounds));
|
|
1566
|
+
}
|
|
1567
|
+
},
|
|
1568
|
+
[core, edgeId]
|
|
1569
|
+
);
|
|
1570
|
+
return { edge, setBounds };
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1066
1573
|
// src/panels/ParamForm.tsx
|
|
1067
|
-
var
|
|
1068
|
-
var
|
|
1574
|
+
var import_react11 = require("react");
|
|
1575
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1069
1576
|
function ParamForm({ fields, onCommit }) {
|
|
1070
|
-
return /* @__PURE__ */ (0,
|
|
1577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "hl-form", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FieldRow, { field, onCommit }, field.key)) });
|
|
1071
1578
|
}
|
|
1072
1579
|
function FieldRow({
|
|
1073
1580
|
field,
|
|
1074
1581
|
onCommit
|
|
1075
1582
|
}) {
|
|
1076
|
-
return /* @__PURE__ */ (0,
|
|
1077
|
-
/* @__PURE__ */ (0,
|
|
1078
|
-
/* @__PURE__ */ (0,
|
|
1583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "hl-field", children: [
|
|
1584
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "hl-field-label", children: field.label }),
|
|
1585
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FieldControl, { field, onCommit })
|
|
1079
1586
|
] });
|
|
1080
1587
|
}
|
|
1081
1588
|
function FieldControl({
|
|
@@ -1084,7 +1591,7 @@ function FieldControl({
|
|
|
1084
1591
|
}) {
|
|
1085
1592
|
switch (field.type) {
|
|
1086
1593
|
case "toggle":
|
|
1087
|
-
return /* @__PURE__ */ (0,
|
|
1594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1088
1595
|
"button",
|
|
1089
1596
|
{
|
|
1090
1597
|
type: "button",
|
|
@@ -1093,17 +1600,17 @@ function FieldControl({
|
|
|
1093
1600
|
className: `hl-toggle${field.value ? " is-on" : ""}`,
|
|
1094
1601
|
disabled: field.disabled,
|
|
1095
1602
|
onClick: () => onCommit(field.key, !field.value),
|
|
1096
|
-
children: /* @__PURE__ */ (0,
|
|
1603
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "hl-toggle-knob" })
|
|
1097
1604
|
}
|
|
1098
1605
|
);
|
|
1099
1606
|
case "number":
|
|
1100
|
-
return /* @__PURE__ */ (0,
|
|
1607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(NumberControl, { field, onCommit });
|
|
1101
1608
|
case "textarea":
|
|
1102
|
-
return /* @__PURE__ */ (0,
|
|
1609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TextControl, { field, onCommit, multiline: true });
|
|
1103
1610
|
case "text":
|
|
1104
|
-
return /* @__PURE__ */ (0,
|
|
1611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TextControl, { field, onCommit });
|
|
1105
1612
|
case "custom":
|
|
1106
|
-
return /* @__PURE__ */ (0,
|
|
1613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "hl-field-custom hl-mono", title: field.fieldType, children: describeCustom(field.value) });
|
|
1107
1614
|
}
|
|
1108
1615
|
}
|
|
1109
1616
|
function TextControl({
|
|
@@ -1111,7 +1618,7 @@ function TextControl({
|
|
|
1111
1618
|
onCommit,
|
|
1112
1619
|
multiline = false
|
|
1113
1620
|
}) {
|
|
1114
|
-
const [draft, setDraft] = (0,
|
|
1621
|
+
const [draft, setDraft] = (0, import_react11.useState)(field.value);
|
|
1115
1622
|
const commit = () => {
|
|
1116
1623
|
if (draft !== field.value) {
|
|
1117
1624
|
onCommit(field.key, draft);
|
|
@@ -1125,7 +1632,7 @@ function TextControl({
|
|
|
1125
1632
|
onBlur: commit
|
|
1126
1633
|
};
|
|
1127
1634
|
if (multiline) {
|
|
1128
|
-
return /* @__PURE__ */ (0,
|
|
1635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1129
1636
|
"textarea",
|
|
1130
1637
|
{
|
|
1131
1638
|
...shared,
|
|
@@ -1134,7 +1641,7 @@ function TextControl({
|
|
|
1134
1641
|
}
|
|
1135
1642
|
);
|
|
1136
1643
|
}
|
|
1137
|
-
return /* @__PURE__ */ (0,
|
|
1644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1138
1645
|
"input",
|
|
1139
1646
|
{
|
|
1140
1647
|
...shared,
|
|
@@ -1152,14 +1659,14 @@ function NumberControl({
|
|
|
1152
1659
|
field,
|
|
1153
1660
|
onCommit
|
|
1154
1661
|
}) {
|
|
1155
|
-
const [draft, setDraft] = (0,
|
|
1662
|
+
const [draft, setDraft] = (0, import_react11.useState)(String(field.value));
|
|
1156
1663
|
const commit = () => {
|
|
1157
1664
|
const parsed = Number(draft);
|
|
1158
1665
|
if (!Number.isNaN(parsed) && parsed !== field.value) {
|
|
1159
1666
|
onCommit(field.key, parsed);
|
|
1160
1667
|
}
|
|
1161
1668
|
};
|
|
1162
|
-
return /* @__PURE__ */ (0,
|
|
1669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1163
1670
|
"input",
|
|
1164
1671
|
{
|
|
1165
1672
|
className: "hl-input hl-mono",
|
|
@@ -1190,40 +1697,267 @@ function describeCustom(value) {
|
|
|
1190
1697
|
return String(value);
|
|
1191
1698
|
}
|
|
1192
1699
|
|
|
1700
|
+
// src/panels/ConnectionInspector.tsx
|
|
1701
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1702
|
+
function ConnectionInspector({ core, edgeId }) {
|
|
1703
|
+
const { edge, setBounds } = useEdgeBounds(core, edgeId);
|
|
1704
|
+
if (edge === void 0) {
|
|
1705
|
+
return null;
|
|
1706
|
+
}
|
|
1707
|
+
const end = (endpoint) => {
|
|
1708
|
+
var _a, _b;
|
|
1709
|
+
return `${(_b = (_a = core.model.getNode(endpoint.nodeId)) == null ? void 0 : _a.name) != null ? _b : endpoint.nodeId}.${endpoint.portId}`;
|
|
1710
|
+
};
|
|
1711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "hl-inspector", children: [
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("header", { className: "hl-inspector-head", children: [
|
|
1713
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "hl-inspector-kind hl-connection", children: "\u2192" }),
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "hl-inspector-titles", children: [
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "hl-inspector-name", children: "Connection" }),
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "hl-inspector-role hl-mono", children: [
|
|
1717
|
+
end(edge.source),
|
|
1718
|
+
" \u2192 ",
|
|
1719
|
+
end(edge.target)
|
|
1720
|
+
] })
|
|
1721
|
+
] })
|
|
1722
|
+
] }),
|
|
1723
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("section", { className: "hl-inspector-section", children: [
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { className: "hl-inspector-section-title", children: "Back-pressure" }),
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "hl-inspector-hint hl-inspector-note", children: "A bounded connection holds at most its capacity, counting the message being worked on. A sender to a full connection waits, unless it drops its oldest waiting message." }),
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1727
|
+
ParamForm,
|
|
1728
|
+
{
|
|
1729
|
+
fields: boundsFields(edge),
|
|
1730
|
+
onCommit: (key, value) => {
|
|
1731
|
+
setBounds(nextBounds(edge, key, value));
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
)
|
|
1735
|
+
] })
|
|
1736
|
+
] });
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
// src/live/format.ts
|
|
1740
|
+
function formatDuration(ms) {
|
|
1741
|
+
if (ms === 0) {
|
|
1742
|
+
return "0 ms";
|
|
1743
|
+
}
|
|
1744
|
+
if (ms < 0.01) {
|
|
1745
|
+
return "<0.01 ms";
|
|
1746
|
+
}
|
|
1747
|
+
if (ms < 1) {
|
|
1748
|
+
return `${ms.toFixed(2)} ms`;
|
|
1749
|
+
}
|
|
1750
|
+
if (ms < 10) {
|
|
1751
|
+
return `${ms.toFixed(1)} ms`;
|
|
1752
|
+
}
|
|
1753
|
+
if (ms < 1e3) {
|
|
1754
|
+
return `${Math.round(ms).toString()} ms`;
|
|
1755
|
+
}
|
|
1756
|
+
return `${(ms / 1e3).toFixed(2)} s`;
|
|
1757
|
+
}
|
|
1758
|
+
function formatElapsed(ms) {
|
|
1759
|
+
return `${(ms / 1e3).toFixed(3)}s`;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
// src/live/preview.ts
|
|
1763
|
+
var PREVIEW_LENGTH = 120;
|
|
1764
|
+
var CIRCULAR = "[Circular]";
|
|
1765
|
+
function functionPreview(value) {
|
|
1766
|
+
return `\u0192 ${value.name === "" ? "anonymous" : value.name}`;
|
|
1767
|
+
}
|
|
1768
|
+
function bigintPreview(value) {
|
|
1769
|
+
return `${value.toString()}n`;
|
|
1770
|
+
}
|
|
1771
|
+
function className(value) {
|
|
1772
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1773
|
+
if (prototype === null || prototype === Object.prototype) {
|
|
1774
|
+
return "Object";
|
|
1775
|
+
}
|
|
1776
|
+
const name = typeof prototype === "object" && "constructor" in prototype ? prototype.constructor : void 0;
|
|
1777
|
+
return typeof name === "function" && name.name !== "" ? name.name : "Object";
|
|
1778
|
+
}
|
|
1779
|
+
function nestedPreview(value) {
|
|
1780
|
+
if (typeof value === "bigint") {
|
|
1781
|
+
return bigintPreview(value);
|
|
1782
|
+
}
|
|
1783
|
+
if (typeof value === "function") {
|
|
1784
|
+
return functionPreview(value);
|
|
1785
|
+
}
|
|
1786
|
+
if (typeof value === "symbol") {
|
|
1787
|
+
return value.toString();
|
|
1788
|
+
}
|
|
1789
|
+
if (value instanceof Error) {
|
|
1790
|
+
return `${value.name}: ${value.message}`;
|
|
1791
|
+
}
|
|
1792
|
+
if (value instanceof Map || value instanceof Set) {
|
|
1793
|
+
return `${value instanceof Map ? "Map" : "Set"}(${String(value.size)})`;
|
|
1794
|
+
}
|
|
1795
|
+
return value;
|
|
1796
|
+
}
|
|
1797
|
+
function json(value) {
|
|
1798
|
+
const ancestors = [];
|
|
1799
|
+
return JSON.stringify(value, function replace(_key, nested) {
|
|
1800
|
+
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {
|
|
1801
|
+
ancestors.pop();
|
|
1802
|
+
}
|
|
1803
|
+
if (typeof nested === "object" && nested !== null) {
|
|
1804
|
+
if (ancestors.includes(nested)) {
|
|
1805
|
+
return CIRCULAR;
|
|
1806
|
+
}
|
|
1807
|
+
ancestors.push(nested);
|
|
1808
|
+
}
|
|
1809
|
+
return nestedPreview(nested);
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1812
|
+
function fullPreview(value) {
|
|
1813
|
+
switch (typeof value) {
|
|
1814
|
+
case "string":
|
|
1815
|
+
return JSON.stringify(value);
|
|
1816
|
+
case "bigint":
|
|
1817
|
+
case "function":
|
|
1818
|
+
case "symbol": {
|
|
1819
|
+
const preview = nestedPreview(value);
|
|
1820
|
+
return typeof preview === "string" ? preview : String(preview);
|
|
1821
|
+
}
|
|
1822
|
+
case "object":
|
|
1823
|
+
break;
|
|
1824
|
+
default:
|
|
1825
|
+
return String(value);
|
|
1826
|
+
}
|
|
1827
|
+
if (value === null) {
|
|
1828
|
+
return "null";
|
|
1829
|
+
}
|
|
1830
|
+
if (value instanceof Error || value instanceof Map || value instanceof Set) {
|
|
1831
|
+
return String(nestedPreview(value));
|
|
1832
|
+
}
|
|
1833
|
+
if (value instanceof Date) {
|
|
1834
|
+
return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
|
|
1835
|
+
}
|
|
1836
|
+
const name = Array.isArray(value) ? "Array" : className(value);
|
|
1837
|
+
let body;
|
|
1838
|
+
try {
|
|
1839
|
+
body = json(value);
|
|
1840
|
+
} catch {
|
|
1841
|
+
return name;
|
|
1842
|
+
}
|
|
1843
|
+
if (body === void 0) {
|
|
1844
|
+
return name;
|
|
1845
|
+
}
|
|
1846
|
+
return name === "Object" || name === "Array" ? body : `${name} ${body}`;
|
|
1847
|
+
}
|
|
1848
|
+
function previewValue(value, maxLength = PREVIEW_LENGTH) {
|
|
1849
|
+
const preview = fullPreview(value);
|
|
1850
|
+
return preview.length <= maxLength ? preview : `${preview.slice(0, maxLength - 1)}\u2026`;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
// src/live/RunTraceContext.tsx
|
|
1854
|
+
var import_react12 = require("react");
|
|
1855
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1856
|
+
var RunTraceContext = (0, import_react12.createContext)(null);
|
|
1857
|
+
function RunTraceProvider({ trace, children }) {
|
|
1858
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(RunTraceContext.Provider, { value: trace, children });
|
|
1859
|
+
}
|
|
1860
|
+
function useRunTraceStore() {
|
|
1861
|
+
return (0, import_react12.useContext)(RunTraceContext);
|
|
1862
|
+
}
|
|
1863
|
+
function useRunTraceVersion(trace) {
|
|
1864
|
+
return (0, import_react12.useSyncExternalStore)(
|
|
1865
|
+
(onChange) => trace === null ? () => void 0 : trace.subscribe(onChange),
|
|
1866
|
+
() => trace === null ? 0 : trace.getVersion(),
|
|
1867
|
+
() => 0
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
// src/panels/NodeRunStats.tsx
|
|
1872
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1873
|
+
function NodeRunStats({ nodeId }) {
|
|
1874
|
+
const trace = useRunTraceStore();
|
|
1875
|
+
useRunTraceVersion(trace);
|
|
1876
|
+
if (trace === null) {
|
|
1877
|
+
return null;
|
|
1878
|
+
}
|
|
1879
|
+
const stats = trace.statsOf(nodeId);
|
|
1880
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: "hl-inspector-section", children: [
|
|
1881
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "hl-inspector-section-title", children: "Run" }),
|
|
1882
|
+
stats === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "hl-inspector-hint hl-runstats-hint", children: "No activity in this run." }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("dl", { className: "hl-runstats", children: [
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell", children: [
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "In" }),
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.received })
|
|
1886
|
+
] }),
|
|
1887
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell", children: [
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Out" }),
|
|
1889
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.sent })
|
|
1890
|
+
] }),
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `hl-runstats-cell${stats.errors > 0 ? " is-error" : ""}`, children: [
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Errors" }),
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.errors })
|
|
1894
|
+
] }),
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell", children: [
|
|
1896
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Avg" }),
|
|
1897
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.received === 0 ? "\u2014" : formatDuration(stats.totalMs / stats.received) })
|
|
1898
|
+
] }),
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell", children: [
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Max" }),
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.received === 0 ? "\u2014" : formatDuration(stats.maxMs) })
|
|
1902
|
+
] }),
|
|
1903
|
+
stats.dropped > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell is-warning", children: [
|
|
1904
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Dropped" }),
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: stats.dropped })
|
|
1906
|
+
] }),
|
|
1907
|
+
stats.finished && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell is-done", children: [
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "State" }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { children: "Finished" })
|
|
1910
|
+
] }),
|
|
1911
|
+
stats.received > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell is-wide", children: [
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Last in" }),
|
|
1913
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: previewValue(stats.lastReceived) })
|
|
1914
|
+
] }),
|
|
1915
|
+
stats.sent > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "hl-runstats-cell is-wide", children: [
|
|
1916
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dt", { children: "Last out" }),
|
|
1917
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("dd", { className: "hl-mono", children: previewValue(stats.lastSent) })
|
|
1918
|
+
] })
|
|
1919
|
+
] })
|
|
1920
|
+
] });
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1193
1923
|
// src/panels/InspectorPanel.tsx
|
|
1194
|
-
var
|
|
1924
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1195
1925
|
function InspectorPanel({ core, emptyState }) {
|
|
1196
1926
|
const selection = (0, import_editor_react2.useSelection)(core);
|
|
1197
1927
|
const selectedNodes2 = selection.selectedNodes;
|
|
1198
1928
|
const singleId = selectedNodes2.length === 1 ? selectedNodes2[0] : void 0;
|
|
1199
1929
|
const params = useNodeParams(core, singleId);
|
|
1200
1930
|
const node = params.node;
|
|
1931
|
+
const singleEdgeId = selectedNodes2.length === 0 && selection.selectedEdges.length === 1 ? selection.selectedEdges[0] : void 0;
|
|
1932
|
+
if (node === void 0 && singleEdgeId !== void 0) {
|
|
1933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ConnectionInspector, { core, edgeId: singleEdgeId });
|
|
1934
|
+
}
|
|
1201
1935
|
if (node === void 0) {
|
|
1202
|
-
return /* @__PURE__ */ (0,
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1204
|
-
/* @__PURE__ */ (0,
|
|
1205
|
-
/* @__PURE__ */ (0,
|
|
1936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "hl-inspector hl-inspector-empty", children: emptyState != null ? emptyState : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "hl-inspector-blank", children: [
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "hl-inspector-blank-badge", "aria-hidden": true }),
|
|
1938
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "hl-inspector-blank-title", children: selectedNodes2.length > 1 ? `${String(selectedNodes2.length)} nodes selected` : "Nothing selected" }),
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "hl-inspector-hint", children: selectedNodes2.length > 1 ? "Select a single node to edit its parameters." : "Pick a node or a connection on the canvas to inspect and tune it." })
|
|
1206
1940
|
] }) });
|
|
1207
1941
|
}
|
|
1208
1942
|
const descriptor = core.registry.get(node.code);
|
|
1209
1943
|
const fields = descriptor === void 0 ? [] : deriveParamSchema(descriptor, node);
|
|
1210
1944
|
const imageUrl = typeof node.params.imageUrl === "string" && node.params.imageUrl.length > 0 ? node.params.imageUrl : void 0;
|
|
1211
|
-
return /* @__PURE__ */ (0,
|
|
1212
|
-
/* @__PURE__ */ (0,
|
|
1213
|
-
/* @__PURE__ */ (0,
|
|
1214
|
-
/* @__PURE__ */ (0,
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
/* @__PURE__ */ (0,
|
|
1217
|
-
/* @__PURE__ */ (0,
|
|
1945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "hl-inspector", children: [
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: `hl-inspector-preview hl-${node.kind.toLowerCase()}`, children: imageUrl !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("img", { className: "hl-inspector-preview-img", src: imageUrl, alt: node.name }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "hl-inspector-preview-badge hl-mono", children: node.kind }) }),
|
|
1947
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("header", { className: "hl-inspector-head", children: [
|
|
1948
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `hl-inspector-kind hl-${node.kind.toLowerCase()}`, children: node.kind }),
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "hl-inspector-titles", children: [
|
|
1950
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "hl-inspector-name", children: node.name }),
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "hl-inspector-role hl-mono", children: [
|
|
1218
1952
|
node.code,
|
|
1219
1953
|
" \xB7 ",
|
|
1220
1954
|
KIND_ROLE[node.kind]
|
|
1221
1955
|
] })
|
|
1222
1956
|
] })
|
|
1223
1957
|
] }),
|
|
1224
|
-
/* @__PURE__ */ (0,
|
|
1225
|
-
/* @__PURE__ */ (0,
|
|
1226
|
-
fields.length === 0 ? /* @__PURE__ */ (0,
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("section", { className: "hl-inspector-section", children: [
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "hl-inspector-section-title", children: "Parameters" }),
|
|
1960
|
+
fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "hl-inspector-hint", children: "This node has no parameters." }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1227
1961
|
ParamForm,
|
|
1228
1962
|
{
|
|
1229
1963
|
fields,
|
|
@@ -1231,16 +1965,17 @@ function InspectorPanel({ core, emptyState }) {
|
|
|
1231
1965
|
}
|
|
1232
1966
|
)
|
|
1233
1967
|
] }),
|
|
1234
|
-
/* @__PURE__ */ (0,
|
|
1235
|
-
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NodeRunStats, { nodeId: node.id }),
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("section", { className: "hl-inspector-section", children: [
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "hl-inspector-section-title", children: "Ports" }),
|
|
1971
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ul", { className: "hl-inspector-ports", children: node.ports.map((port) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1237
1972
|
"li",
|
|
1238
1973
|
{
|
|
1239
1974
|
className: `hl-inspector-port${port.isError ? " is-error" : ""}`,
|
|
1240
1975
|
children: [
|
|
1241
|
-
/* @__PURE__ */ (0,
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1976
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `hl-port-dot hl-dir-${port.direction.toLowerCase()}` }),
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "hl-mono", children: port.name }),
|
|
1978
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "hl-inspector-port-dir hl-mono", children: port.direction })
|
|
1244
1979
|
]
|
|
1245
1980
|
},
|
|
1246
1981
|
port.id
|
|
@@ -1250,14 +1985,14 @@ function InspectorPanel({ core, emptyState }) {
|
|
|
1250
1985
|
}
|
|
1251
1986
|
|
|
1252
1987
|
// src/panels/OutlineTree.tsx
|
|
1253
|
-
var
|
|
1254
|
-
var
|
|
1988
|
+
var import_react13 = require("react");
|
|
1989
|
+
var import_editor_core3 = require("@hlang-tech/editor-core");
|
|
1255
1990
|
var import_editor_react3 = require("@hlang-tech/editor-react");
|
|
1256
|
-
var
|
|
1991
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1257
1992
|
function useTopologyComponents(core) {
|
|
1258
|
-
const [tick, setTick] = (0,
|
|
1259
|
-
const bump = (0,
|
|
1260
|
-
(0,
|
|
1993
|
+
const [tick, setTick] = (0, import_react13.useState)(0);
|
|
1994
|
+
const bump = (0, import_react13.useCallback)(() => setTick((t) => t + 1), []);
|
|
1995
|
+
(0, import_react13.useEffect)(() => {
|
|
1261
1996
|
const kinds = ["nodeAdded", "nodeRemoved", "nodeChanged", "edgeAdded", "edgeRemoved"];
|
|
1262
1997
|
const disposers = kinds.map((k) => core.events.on(k, bump));
|
|
1263
1998
|
bump();
|
|
@@ -1267,9 +2002,9 @@ function useTopologyComponents(core) {
|
|
|
1267
2002
|
}
|
|
1268
2003
|
};
|
|
1269
2004
|
}, [core, bump]);
|
|
1270
|
-
return (0,
|
|
2005
|
+
return (0, import_react13.useMemo)(() => {
|
|
1271
2006
|
void tick;
|
|
1272
|
-
const topo = new
|
|
2007
|
+
const topo = new import_editor_core3.GraphTopology();
|
|
1273
2008
|
topo.reset(core.model.getNodes(), core.model.getEdges());
|
|
1274
2009
|
return topo.components();
|
|
1275
2010
|
}, [core, tick]);
|
|
@@ -1279,15 +2014,15 @@ function OutlineTree({ core, onFocus }) {
|
|
|
1279
2014
|
const selection = (0, import_editor_react3.useSelection)(core);
|
|
1280
2015
|
const viewState = (0, import_editor_react3.useViewState)(core);
|
|
1281
2016
|
const diagnostics = (0, import_editor_react3.useDiagnostics)(core);
|
|
1282
|
-
const [collapsed, setCollapsed] = (0,
|
|
1283
|
-
const nodeById = (0,
|
|
2017
|
+
const [collapsed, setCollapsed] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
|
|
2018
|
+
const nodeById = (0, import_react13.useMemo)(() => {
|
|
1284
2019
|
const m = /* @__PURE__ */ new Map();
|
|
1285
2020
|
for (const n of core.model.getNodes()) {
|
|
1286
2021
|
m.set(n.id, n);
|
|
1287
2022
|
}
|
|
1288
2023
|
return m;
|
|
1289
2024
|
}, [core, components]);
|
|
1290
|
-
const toggleGroup = (0,
|
|
2025
|
+
const toggleGroup = (0, import_react13.useCallback)((id) => {
|
|
1291
2026
|
setCollapsed((prev) => {
|
|
1292
2027
|
const next = new Set(prev);
|
|
1293
2028
|
if (next.has(id)) {
|
|
@@ -1298,7 +2033,7 @@ function OutlineTree({ core, onFocus }) {
|
|
|
1298
2033
|
return next;
|
|
1299
2034
|
});
|
|
1300
2035
|
}, []);
|
|
1301
|
-
const select = (0,
|
|
2036
|
+
const select = (0, import_react13.useCallback)(
|
|
1302
2037
|
(id) => {
|
|
1303
2038
|
selection.selectNodes([id], "replace");
|
|
1304
2039
|
onFocus == null ? void 0 : onFocus(id);
|
|
@@ -1306,79 +2041,80 @@ function OutlineTree({ core, onFocus }) {
|
|
|
1306
2041
|
[selection, onFocus]
|
|
1307
2042
|
);
|
|
1308
2043
|
if (components.length === 0) {
|
|
1309
|
-
return /* @__PURE__ */ (0,
|
|
2044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "hl-outline-empty hl-mono", children: "no layers yet" });
|
|
1310
2045
|
}
|
|
1311
2046
|
const groups = [...components].sort((a, b) => b.nodeIds.size - a.nodeIds.size);
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
2047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "hl-outline", role: "tree", "aria-label": "Outline", children: groups.map((group, gi) => {
|
|
1313
2048
|
const members = [...group.nodeIds].map((id) => nodeById.get(id)).filter((n) => n !== void 0);
|
|
1314
2049
|
const open = !collapsed.has(group.id);
|
|
1315
2050
|
const groupName = `Flow ${String(gi + 1)}`;
|
|
1316
|
-
return /* @__PURE__ */ (0,
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
2051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "hl-outline-group", role: "treeitem", "aria-expanded": open, children: [
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1318
2053
|
"button",
|
|
1319
2054
|
{
|
|
1320
2055
|
className: "hl-outline-grouphead",
|
|
1321
2056
|
onClick: () => toggleGroup(group.id),
|
|
1322
2057
|
children: [
|
|
1323
|
-
/* @__PURE__ */ (0,
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
2058
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-caret" + (open ? " is-open" : ""), "aria-hidden": true, children: "\u25B8" }),
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-groupname", children: groupName }),
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-count hl-mono", children: group.nodeIds.size })
|
|
1326
2061
|
]
|
|
1327
2062
|
}
|
|
1328
2063
|
),
|
|
1329
|
-
open && /* @__PURE__ */ (0,
|
|
2064
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "hl-outline-members", children: members.map((node) => {
|
|
1330
2065
|
const active = selection.isSelected(node.id);
|
|
1331
2066
|
const isHidden = viewState.isHidden(node.id);
|
|
1332
2067
|
const isLocked = viewState.isLocked(node.id);
|
|
1333
|
-
const
|
|
1334
|
-
|
|
2068
|
+
const { imageUrl } = node.params;
|
|
2069
|
+
const thumbnail = typeof imageUrl === "string" && imageUrl.length > 0 ? imageUrl : void 0;
|
|
2070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1335
2071
|
"div",
|
|
1336
2072
|
{
|
|
1337
2073
|
className: "hl-outline-row" + (active ? " is-active" : "") + (isHidden ? " is-hidden" : "") + (isLocked ? " is-locked" : ""),
|
|
1338
2074
|
children: [
|
|
1339
|
-
/* @__PURE__ */ (0,
|
|
1340
|
-
/* @__PURE__ */ (0,
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("button", { className: "hl-outline-main", onClick: () => select(node.id), children: [
|
|
2076
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1341
2077
|
"span",
|
|
1342
2078
|
{
|
|
1343
2079
|
className: `hl-outline-icon hl-kind-${node.kind.toLowerCase()}`,
|
|
1344
2080
|
"aria-hidden": true,
|
|
1345
|
-
children:
|
|
2081
|
+
children: thumbnail !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1346
2082
|
"img",
|
|
1347
2083
|
{
|
|
1348
2084
|
className: "hl-outline-thumb",
|
|
1349
|
-
src:
|
|
2085
|
+
src: thumbnail,
|
|
1350
2086
|
alt: ""
|
|
1351
2087
|
}
|
|
1352
|
-
) : /* @__PURE__ */ (0,
|
|
2088
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NodeIcon, { code: node.code, kind: node.kind, size: 13 })
|
|
1353
2089
|
}
|
|
1354
2090
|
),
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-name", children: node.name }),
|
|
1356
2092
|
(() => {
|
|
1357
2093
|
const diag = diagnostics.worstOf(node.id);
|
|
1358
|
-
return diag === void 0 ? null : /* @__PURE__ */ (0,
|
|
2094
|
+
return diag === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DiagnosticBadge, { diagnostic: diag, variant: "hl-outline-diag", size: 11 });
|
|
1359
2095
|
})(),
|
|
1360
|
-
isLocked && /* @__PURE__ */ (0,
|
|
1361
|
-
isHidden && /* @__PURE__ */ (0,
|
|
2096
|
+
isLocked && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-badge", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(LockIcon, { size: 11 }) }),
|
|
2097
|
+
isHidden && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hl-outline-badge", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EyeOffIcon, { size: 11 }) })
|
|
1362
2098
|
] }),
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "hl-outline-controls", children: [
|
|
2100
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1365
2101
|
"button",
|
|
1366
2102
|
{
|
|
1367
2103
|
className: "hl-outline-ctl" + (isHidden ? " is-active-ctl" : ""),
|
|
1368
2104
|
onClick: () => viewState.toggleHidden(node.id),
|
|
1369
2105
|
"aria-label": isHidden ? "Show layer" : "Hide layer",
|
|
1370
2106
|
title: isHidden ? "Show" : "Hide",
|
|
1371
|
-
children: isHidden ? /* @__PURE__ */ (0,
|
|
2107
|
+
children: isHidden ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EyeOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EyeIcon, {})
|
|
1372
2108
|
}
|
|
1373
2109
|
),
|
|
1374
|
-
/* @__PURE__ */ (0,
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1375
2111
|
"button",
|
|
1376
2112
|
{
|
|
1377
2113
|
className: "hl-outline-ctl" + (isLocked ? " is-active-ctl" : ""),
|
|
1378
2114
|
onClick: () => viewState.toggleLocked(node.id),
|
|
1379
2115
|
"aria-label": isLocked ? "Unlock layer" : "Lock layer",
|
|
1380
2116
|
title: isLocked ? "Unlock" : "Lock",
|
|
1381
|
-
children: isLocked ? /* @__PURE__ */ (0,
|
|
2117
|
+
children: isLocked ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(LockIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(UnlockIcon, {})
|
|
1382
2118
|
}
|
|
1383
2119
|
)
|
|
1384
2120
|
] })
|
|
@@ -1391,21 +2127,21 @@ function OutlineTree({ core, onFocus }) {
|
|
|
1391
2127
|
}
|
|
1392
2128
|
|
|
1393
2129
|
// src/panels/PreviewPanel.tsx
|
|
1394
|
-
var
|
|
2130
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1395
2131
|
function PreviewPanel({ imageUrl, title = "Preview", status }) {
|
|
1396
|
-
return /* @__PURE__ */ (0,
|
|
1397
|
-
/* @__PURE__ */ (0,
|
|
1398
|
-
/* @__PURE__ */ (0,
|
|
1399
|
-
status !== void 0 && /* @__PURE__ */ (0,
|
|
2132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("section", { className: "hl-preview", "aria-label": "Preview", children: [
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "hl-preview-head", children: [
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "hl-preview-title", children: title }),
|
|
2135
|
+
status !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "hl-preview-status hl-mono", children: status })
|
|
1400
2136
|
] }),
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "hl-preview-frame", children: imageUrl !== void 0 && imageUrl.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("img", { className: "hl-preview-img", src: imageUrl, alt: title, draggable: false }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "hl-preview-placeholder hl-mono", children: "no output yet" }) })
|
|
1402
2138
|
] });
|
|
1403
2139
|
}
|
|
1404
2140
|
|
|
1405
2141
|
// src/panels/RailTabs.tsx
|
|
1406
|
-
var
|
|
2142
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1407
2143
|
function RailTabs({ tabs, active, onChange }) {
|
|
1408
|
-
return /* @__PURE__ */ (0,
|
|
2144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "hl-railtabs", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1409
2145
|
"button",
|
|
1410
2146
|
{
|
|
1411
2147
|
role: "tab",
|
|
@@ -1419,20 +2155,20 @@ function RailTabs({ tabs, active, onChange }) {
|
|
|
1419
2155
|
}
|
|
1420
2156
|
|
|
1421
2157
|
// src/panels/AssetGrid.tsx
|
|
1422
|
-
var
|
|
2158
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1423
2159
|
function AssetGrid({ items, onSelect, emptyHint = "No assets yet" }) {
|
|
1424
2160
|
if (items.length === 0) {
|
|
1425
|
-
return /* @__PURE__ */ (0,
|
|
2161
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "hl-assetgrid-empty hl-mono", children: emptyHint });
|
|
1426
2162
|
}
|
|
1427
|
-
return /* @__PURE__ */ (0,
|
|
2163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "hl-assetgrid", children: items.map((item) => {
|
|
1428
2164
|
var _a;
|
|
1429
|
-
return /* @__PURE__ */ (0,
|
|
2165
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1430
2166
|
"button",
|
|
1431
2167
|
{
|
|
1432
2168
|
className: "hl-assetgrid-cell",
|
|
1433
2169
|
onClick: () => onSelect == null ? void 0 : onSelect(item.id),
|
|
1434
2170
|
title: item.label,
|
|
1435
|
-
children: /* @__PURE__ */ (0,
|
|
2171
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("img", { className: "hl-assetgrid-img", src: item.url, alt: (_a = item.label) != null ? _a : "", loading: "lazy" })
|
|
1436
2172
|
},
|
|
1437
2173
|
item.id
|
|
1438
2174
|
);
|
|
@@ -1440,10 +2176,10 @@ function AssetGrid({ items, onSelect, emptyHint = "No assets yet" }) {
|
|
|
1440
2176
|
}
|
|
1441
2177
|
|
|
1442
2178
|
// src/panels/PositionPanel.tsx
|
|
1443
|
-
var
|
|
1444
|
-
var
|
|
2179
|
+
var import_react14 = require("react");
|
|
2180
|
+
var import_editor_core4 = require("@hlang-tech/editor-core");
|
|
1445
2181
|
var import_editor_react4 = require("@hlang-tech/editor-react");
|
|
1446
|
-
var
|
|
2182
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1447
2183
|
function selectedNodes(core) {
|
|
1448
2184
|
const ids = core.selection.getSelectedNodes();
|
|
1449
2185
|
const out = [];
|
|
@@ -1458,8 +2194,8 @@ function selectedNodes(core) {
|
|
|
1458
2194
|
function PositionPanel({ core, livePosition }) {
|
|
1459
2195
|
var _a;
|
|
1460
2196
|
(0, import_editor_react4.useSelection)(core);
|
|
1461
|
-
const [, bump] = (0,
|
|
1462
|
-
(0,
|
|
2197
|
+
const [, bump] = (0, import_react14.useReducer)((n) => n + 1, 0);
|
|
2198
|
+
(0, import_react14.useEffect)(() => {
|
|
1463
2199
|
const kinds = ["nodeChanged", "nodeAdded", "nodeRemoved"];
|
|
1464
2200
|
const disposers = kinds.map((k) => core.events.on(k, bump));
|
|
1465
2201
|
return () => {
|
|
@@ -1471,7 +2207,7 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1471
2207
|
const nodes = selectedNodes(core);
|
|
1472
2208
|
const single = nodes.length === 1 ? nodes[0] : void 0;
|
|
1473
2209
|
const shownPos = single !== void 0 ? (_a = livePosition == null ? void 0 : livePosition(single.id)) != null ? _a : single.position : void 0;
|
|
1474
|
-
const moveAll = (0,
|
|
2210
|
+
const moveAll = (0, import_react14.useCallback)(
|
|
1475
2211
|
(fn) => {
|
|
1476
2212
|
const targets = selectedNodes(core);
|
|
1477
2213
|
if (targets.length === 0) {
|
|
@@ -1479,13 +2215,13 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1479
2215
|
}
|
|
1480
2216
|
core.history.transact("Align", () => {
|
|
1481
2217
|
for (const n of targets) {
|
|
1482
|
-
core.commands.execute(new
|
|
2218
|
+
core.commands.execute(new import_editor_core4.MoveNodeCommand(n.id, fn(n)));
|
|
1483
2219
|
}
|
|
1484
2220
|
});
|
|
1485
2221
|
},
|
|
1486
2222
|
[core]
|
|
1487
2223
|
);
|
|
1488
|
-
const align = (0,
|
|
2224
|
+
const align = (0, import_react14.useCallback)(
|
|
1489
2225
|
(kind) => {
|
|
1490
2226
|
const targets = selectedNodes(core);
|
|
1491
2227
|
if (targets.length === 0) {
|
|
@@ -1518,13 +2254,13 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1518
2254
|
},
|
|
1519
2255
|
[core, moveAll]
|
|
1520
2256
|
);
|
|
1521
|
-
const setCoord = (0,
|
|
2257
|
+
const setCoord = (0, import_react14.useCallback)(
|
|
1522
2258
|
(axis, value) => {
|
|
1523
2259
|
if (single === void 0 || Number.isNaN(value)) {
|
|
1524
2260
|
return;
|
|
1525
2261
|
}
|
|
1526
2262
|
const next = axis === "x" ? { x: value, y: single.position.y } : { x: single.position.x, y: value };
|
|
1527
|
-
core.commands.execute(new
|
|
2263
|
+
core.commands.execute(new import_editor_core4.MoveNodeCommand(single.id, next));
|
|
1528
2264
|
},
|
|
1529
2265
|
[core, single]
|
|
1530
2266
|
);
|
|
@@ -1537,9 +2273,9 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1537
2273
|
{ kind: "vcenter", label: "Align middle", d: "M4 12h16M9 8v8M15 9v6" },
|
|
1538
2274
|
{ kind: "bottom", label: "Align bottom", d: "M4 19h16M8 7v8M16 12v3" }
|
|
1539
2275
|
];
|
|
1540
|
-
return /* @__PURE__ */ (0,
|
|
1541
|
-
/* @__PURE__ */ (0,
|
|
1542
|
-
/* @__PURE__ */ (0,
|
|
2276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("section", { className: "hl-position", children: [
|
|
2277
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h3", { className: "hl-position-title hl-mono", children: "Position" }),
|
|
2278
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "hl-position-align", role: "group", "aria-label": "Align", children: alignButtons.map((b) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1543
2279
|
"button",
|
|
1544
2280
|
{
|
|
1545
2281
|
className: "hl-position-alignbtn",
|
|
@@ -1547,13 +2283,13 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1547
2283
|
disabled,
|
|
1548
2284
|
title: b.label,
|
|
1549
2285
|
"aria-label": b.label,
|
|
1550
|
-
children: /* @__PURE__ */ (0,
|
|
2286
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: b.d }) })
|
|
1551
2287
|
},
|
|
1552
2288
|
b.kind
|
|
1553
2289
|
)) }),
|
|
1554
|
-
/* @__PURE__ */ (0,
|
|
1555
|
-
/* @__PURE__ */ (0,
|
|
1556
|
-
/* @__PURE__ */ (0,
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "hl-position-coords", children: [
|
|
2291
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "hl-position-field", children: [
|
|
2292
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1557
2293
|
"input",
|
|
1558
2294
|
{
|
|
1559
2295
|
type: "number",
|
|
@@ -1564,10 +2300,10 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1564
2300
|
"aria-label": "X position"
|
|
1565
2301
|
}
|
|
1566
2302
|
),
|
|
1567
|
-
/* @__PURE__ */ (0,
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "hl-position-axis hl-mono", children: "X" })
|
|
1568
2304
|
] }),
|
|
1569
|
-
/* @__PURE__ */ (0,
|
|
1570
|
-
/* @__PURE__ */ (0,
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "hl-position-field", children: [
|
|
2306
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1571
2307
|
"input",
|
|
1572
2308
|
{
|
|
1573
2309
|
type: "number",
|
|
@@ -1578,24 +2314,24 @@ function PositionPanel({ core, livePosition }) {
|
|
|
1578
2314
|
"aria-label": "Y position"
|
|
1579
2315
|
}
|
|
1580
2316
|
),
|
|
1581
|
-
/* @__PURE__ */ (0,
|
|
2317
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "hl-position-axis hl-mono", children: "Y" })
|
|
1582
2318
|
] })
|
|
1583
2319
|
] })
|
|
1584
2320
|
] });
|
|
1585
2321
|
}
|
|
1586
2322
|
|
|
1587
2323
|
// src/command-palette/NodeSearch.tsx
|
|
1588
|
-
var
|
|
1589
|
-
var
|
|
2324
|
+
var import_react15 = require("react");
|
|
2325
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1590
2326
|
var PANEL_WIDTH = 320;
|
|
1591
2327
|
var PANEL_MAX_HEIGHT = 360;
|
|
1592
2328
|
function NodeSearch({ controller }) {
|
|
1593
2329
|
const { state } = controller;
|
|
1594
|
-
const [query, setQuery] = (0,
|
|
1595
|
-
const [active, setActive] = (0,
|
|
1596
|
-
const inputRef = (0,
|
|
2330
|
+
const [query, setQuery] = (0, import_react15.useState)("");
|
|
2331
|
+
const [active, setActive] = (0, import_react15.useState)(0);
|
|
2332
|
+
const inputRef = (0, import_react15.useRef)(null);
|
|
1597
2333
|
const isOpen = state !== void 0;
|
|
1598
|
-
(0,
|
|
2334
|
+
(0, import_react15.useEffect)(() => {
|
|
1599
2335
|
var _a;
|
|
1600
2336
|
if (isOpen) {
|
|
1601
2337
|
setQuery("");
|
|
@@ -1603,12 +2339,12 @@ function NodeSearch({ controller }) {
|
|
|
1603
2339
|
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
1604
2340
|
}
|
|
1605
2341
|
}, [isOpen]);
|
|
1606
|
-
const results = (0,
|
|
2342
|
+
const results = (0, import_react15.useMemo)(
|
|
1607
2343
|
() => state !== void 0 ? controller.results(query) : [],
|
|
1608
2344
|
[controller, state, query]
|
|
1609
2345
|
);
|
|
1610
2346
|
const clampedActive = results.length === 0 ? 0 : Math.min(active, results.length - 1);
|
|
1611
|
-
const choose = (0,
|
|
2347
|
+
const choose = (0, import_react15.useCallback)(
|
|
1612
2348
|
(view) => {
|
|
1613
2349
|
if (view !== void 0) {
|
|
1614
2350
|
controller.commit(view);
|
|
@@ -1616,7 +2352,7 @@ function NodeSearch({ controller }) {
|
|
|
1616
2352
|
},
|
|
1617
2353
|
[controller]
|
|
1618
2354
|
);
|
|
1619
|
-
const onKeyDown = (0,
|
|
2355
|
+
const onKeyDown = (0, import_react15.useCallback)(
|
|
1620
2356
|
(event) => {
|
|
1621
2357
|
switch (event.key) {
|
|
1622
2358
|
case "ArrowDown":
|
|
@@ -1646,8 +2382,8 @@ function NodeSearch({ controller }) {
|
|
|
1646
2382
|
}
|
|
1647
2383
|
const style = clampToViewport(state.screen.x, state.screen.y);
|
|
1648
2384
|
const connectMode = state.pending !== void 0;
|
|
1649
|
-
return /* @__PURE__ */ (0,
|
|
1650
|
-
/* @__PURE__ */ (0,
|
|
2385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
2386
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1651
2387
|
"div",
|
|
1652
2388
|
{
|
|
1653
2389
|
className: "hl-node-search-scrim",
|
|
@@ -1656,10 +2392,10 @@ function NodeSearch({ controller }) {
|
|
|
1656
2392
|
}
|
|
1657
2393
|
}
|
|
1658
2394
|
),
|
|
1659
|
-
/* @__PURE__ */ (0,
|
|
1660
|
-
/* @__PURE__ */ (0,
|
|
1661
|
-
/* @__PURE__ */ (0,
|
|
1662
|
-
/* @__PURE__ */ (0,
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "hl-node-search", style, role: "dialog", "aria-label": "Create node", children: [
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "hl-node-search-field", children: [
|
|
2397
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "hl-node-search-glyph", "aria-hidden": true, children: connectMode ? "\u2933" : "\uFF0B" }),
|
|
2398
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1663
2399
|
"input",
|
|
1664
2400
|
{
|
|
1665
2401
|
ref: inputRef,
|
|
@@ -1677,12 +2413,12 @@ function NodeSearch({ controller }) {
|
|
|
1677
2413
|
}
|
|
1678
2414
|
)
|
|
1679
2415
|
] }),
|
|
1680
|
-
/* @__PURE__ */ (0,
|
|
1681
|
-
results.length === 0 && /* @__PURE__ */ (0,
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("ul", { className: "hl-node-search-list", role: "listbox", children: [
|
|
2417
|
+
results.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("li", { className: "hl-node-search-empty hl-mono", children: "no matching nodes" }),
|
|
1682
2418
|
results.map((view, index) => {
|
|
1683
2419
|
const descriptor = view.result.value;
|
|
1684
2420
|
const kind = descriptor.kind;
|
|
1685
|
-
return /* @__PURE__ */ (0,
|
|
2421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1686
2422
|
"li",
|
|
1687
2423
|
{
|
|
1688
2424
|
role: "option",
|
|
@@ -1694,15 +2430,15 @@ function NodeSearch({ controller }) {
|
|
|
1694
2430
|
choose(view);
|
|
1695
2431
|
},
|
|
1696
2432
|
children: [
|
|
1697
|
-
/* @__PURE__ */ (0,
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1698
2434
|
"span",
|
|
1699
2435
|
{
|
|
1700
2436
|
className: `hl-node-search-kind hl-mono hl-kind-${kind.toLowerCase()}`,
|
|
1701
2437
|
children: kind
|
|
1702
2438
|
}
|
|
1703
2439
|
),
|
|
1704
|
-
/* @__PURE__ */ (0,
|
|
1705
|
-
view.connectPortId !== void 0 && /* @__PURE__ */ (0,
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "hl-node-search-label", children: highlight(descriptor.displayName, view.result.match) }),
|
|
2441
|
+
view.connectPortId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "hl-node-search-port hl-mono", children: view.connectPortId })
|
|
1706
2442
|
]
|
|
1707
2443
|
},
|
|
1708
2444
|
descriptor.code
|
|
@@ -1716,7 +2452,7 @@ function highlight(text, match) {
|
|
|
1716
2452
|
const hit = new Set(match.positions);
|
|
1717
2453
|
const chars = Array.from(text);
|
|
1718
2454
|
return chars.map(
|
|
1719
|
-
(ch, i) => hit.has(i) ? /* @__PURE__ */ (0,
|
|
2455
|
+
(ch, i) => hit.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("mark", { className: "hl-node-search-hit", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: ch }, i)
|
|
1720
2456
|
);
|
|
1721
2457
|
}
|
|
1722
2458
|
function clampToViewport(x, y) {
|
|
@@ -1729,8 +2465,8 @@ function clampToViewport(x, y) {
|
|
|
1729
2465
|
}
|
|
1730
2466
|
|
|
1731
2467
|
// src/command-palette/useNodeSearch.ts
|
|
1732
|
-
var
|
|
1733
|
-
var
|
|
2468
|
+
var import_react16 = require("react");
|
|
2469
|
+
var import_editor_core5 = require("@hlang-tech/editor-core");
|
|
1734
2470
|
|
|
1735
2471
|
// src/command-palette/fuzzy.ts
|
|
1736
2472
|
function fuzzyScore(query, target) {
|
|
@@ -1820,21 +2556,21 @@ function firstCompletingPort(ports, pending, validator) {
|
|
|
1820
2556
|
|
|
1821
2557
|
// src/command-palette/useNodeSearch.ts
|
|
1822
2558
|
function useNodeSearch(core) {
|
|
1823
|
-
const [state, setState] = (0,
|
|
1824
|
-
const openBlank = (0,
|
|
2559
|
+
const [state, setState] = (0, import_react16.useState)(void 0);
|
|
2560
|
+
const openBlank = (0, import_react16.useCallback)((screen, flow) => {
|
|
1825
2561
|
setState({ screen, flow });
|
|
1826
2562
|
}, []);
|
|
1827
|
-
const openFromConnection = (0,
|
|
2563
|
+
const openFromConnection = (0, import_react16.useCallback)(
|
|
1828
2564
|
(screen, flow, pending) => {
|
|
1829
2565
|
setState({ screen, flow, pending });
|
|
1830
2566
|
},
|
|
1831
2567
|
[]
|
|
1832
2568
|
);
|
|
1833
|
-
const close = (0,
|
|
2569
|
+
const close = (0, import_react16.useCallback)(() => {
|
|
1834
2570
|
setState(void 0);
|
|
1835
2571
|
}, []);
|
|
1836
2572
|
const descriptors = core.registry.list();
|
|
1837
|
-
const results = (0,
|
|
2573
|
+
const results = (0, import_react16.useCallback)(
|
|
1838
2574
|
(query) => {
|
|
1839
2575
|
if ((state == null ? void 0 : state.pending) !== void 0) {
|
|
1840
2576
|
return connectableCandidates(
|
|
@@ -1848,7 +2584,7 @@ function useNodeSearch(core) {
|
|
|
1848
2584
|
},
|
|
1849
2585
|
[state, descriptors, core]
|
|
1850
2586
|
);
|
|
1851
|
-
const commit = (0,
|
|
2587
|
+
const commit = (0, import_react16.useCallback)(
|
|
1852
2588
|
(view) => {
|
|
1853
2589
|
if (state === void 0) {
|
|
1854
2590
|
return;
|
|
@@ -1859,40 +2595,40 @@ function useNodeSearch(core) {
|
|
|
1859
2595
|
const pending = state.pending;
|
|
1860
2596
|
const connectPortId = view.connectPortId;
|
|
1861
2597
|
core.history.transact("Create & Connect Node", () => {
|
|
1862
|
-
core.commands.execute(new
|
|
2598
|
+
core.commands.execute(new import_editor_core5.AddNodeCommand(node));
|
|
1863
2599
|
const edgeId = core.idGenerator.nextEdgeId();
|
|
1864
2600
|
const newEndpoint = { nodeId: node.id, portId: connectPortId };
|
|
1865
2601
|
const [source, target] = pending.direction === "from-source" ? [pending.fromEndpoint, newEndpoint] : [newEndpoint, pending.fromEndpoint];
|
|
1866
|
-
core.commands.execute(new
|
|
2602
|
+
core.commands.execute(new import_editor_core5.ConnectCommand(edgeId, source, target));
|
|
1867
2603
|
});
|
|
1868
2604
|
} else {
|
|
1869
|
-
core.commands.execute(new
|
|
2605
|
+
core.commands.execute(new import_editor_core5.AddNodeCommand(node));
|
|
1870
2606
|
}
|
|
1871
2607
|
setState(void 0);
|
|
1872
2608
|
},
|
|
1873
2609
|
[state, core]
|
|
1874
2610
|
);
|
|
1875
|
-
return (0,
|
|
2611
|
+
return (0, import_react16.useMemo)(
|
|
1876
2612
|
() => ({ state, openBlank, openFromConnection, close, results, commit }),
|
|
1877
2613
|
[state, openBlank, openFromConnection, close, results, commit]
|
|
1878
2614
|
);
|
|
1879
2615
|
}
|
|
1880
2616
|
|
|
1881
2617
|
// src/command-palette/useNodeSearchTriggers.ts
|
|
1882
|
-
var
|
|
1883
|
-
var
|
|
2618
|
+
var import_react17 = require("react");
|
|
2619
|
+
var import_react18 = require("@xyflow/react");
|
|
1884
2620
|
var DEFAULT_DOUBLE_CLICK_MS = 350;
|
|
1885
2621
|
function useNodeSearchTriggers(core, search, options = {}) {
|
|
1886
2622
|
var _a, _b;
|
|
1887
|
-
const flow = (0,
|
|
2623
|
+
const flow = (0, import_react18.useReactFlow)();
|
|
1888
2624
|
const doubleClickMs = (_a = options.doubleClickMs) != null ? _a : DEFAULT_DOUBLE_CLICK_MS;
|
|
1889
2625
|
const now = (_b = options.now) != null ? _b : defaultNow;
|
|
1890
|
-
const startRef = (0,
|
|
1891
|
-
const lastPaneClickRef = (0,
|
|
1892
|
-
const onConnectStart = (0,
|
|
2626
|
+
const startRef = (0, import_react17.useRef)(null);
|
|
2627
|
+
const lastPaneClickRef = (0, import_react17.useRef)(Number.NEGATIVE_INFINITY);
|
|
2628
|
+
const onConnectStart = (0, import_react17.useCallback)((_event, params) => {
|
|
1893
2629
|
startRef.current = params;
|
|
1894
2630
|
}, []);
|
|
1895
|
-
const onConnectEnd = (0,
|
|
2631
|
+
const onConnectEnd = (0, import_react17.useCallback)(
|
|
1896
2632
|
(event, connectionState) => {
|
|
1897
2633
|
const start = startRef.current;
|
|
1898
2634
|
startRef.current = null;
|
|
@@ -1925,7 +2661,7 @@ function useNodeSearchTriggers(core, search, options = {}) {
|
|
|
1925
2661
|
},
|
|
1926
2662
|
[core, flow, search]
|
|
1927
2663
|
);
|
|
1928
|
-
const onPaneClick = (0,
|
|
2664
|
+
const onPaneClick = (0, import_react17.useCallback)(
|
|
1929
2665
|
(event) => {
|
|
1930
2666
|
const t = now();
|
|
1931
2667
|
const isDouble = t - lastPaneClickRef.current <= doubleClickMs;
|
|
@@ -1957,7 +2693,7 @@ function pointerOf(event) {
|
|
|
1957
2693
|
}
|
|
1958
2694
|
|
|
1959
2695
|
// src/hooks/useEditorHotkeys.ts
|
|
1960
|
-
var
|
|
2696
|
+
var import_react19 = require("react");
|
|
1961
2697
|
var import_editor_react5 = require("@hlang-tech/editor-react");
|
|
1962
2698
|
function isEditableTarget(target) {
|
|
1963
2699
|
if (!(target instanceof HTMLElement)) {
|
|
@@ -1976,7 +2712,7 @@ function withinScope(target, scope) {
|
|
|
1976
2712
|
function useEditorHotkeys(core, options = {}) {
|
|
1977
2713
|
const clipboard = (0, import_editor_react5.useClipboard)(core);
|
|
1978
2714
|
const { scope } = options;
|
|
1979
|
-
(0,
|
|
2715
|
+
(0, import_react19.useEffect)(() => {
|
|
1980
2716
|
const onKeyDown = (event) => {
|
|
1981
2717
|
if (!withinScope(event.target, scope) || isEditableTarget(event.target)) {
|
|
1982
2718
|
return;
|
|
@@ -2039,33 +2775,33 @@ function useEditorHotkeys(core, options = {}) {
|
|
|
2039
2775
|
}
|
|
2040
2776
|
|
|
2041
2777
|
// src/context-menu/NodeContextMenu.tsx
|
|
2042
|
-
var
|
|
2043
|
-
var
|
|
2778
|
+
var import_react20 = require("react");
|
|
2779
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2044
2780
|
var PANEL_WIDTH2 = 208;
|
|
2045
2781
|
var ITEM_HEIGHT = 34;
|
|
2046
2782
|
var VIEWPORT_MARGIN = 8;
|
|
2047
2783
|
var MENU_VPAD = 12;
|
|
2048
2784
|
function NodeContextMenu({ controller, items }) {
|
|
2049
2785
|
const { state } = controller;
|
|
2050
|
-
const [active, setActive] = (0,
|
|
2051
|
-
const menuRef = (0,
|
|
2786
|
+
const [active, setActive] = (0, import_react20.useState)(0);
|
|
2787
|
+
const menuRef = (0, import_react20.useRef)(null);
|
|
2052
2788
|
const isOpen = state !== void 0;
|
|
2053
|
-
(0,
|
|
2789
|
+
(0, import_react20.useEffect)(() => {
|
|
2054
2790
|
var _a;
|
|
2055
2791
|
if (isOpen) {
|
|
2056
2792
|
setActive(0);
|
|
2057
2793
|
(_a = menuRef.current) == null ? void 0 : _a.focus();
|
|
2058
2794
|
}
|
|
2059
2795
|
}, [isOpen]);
|
|
2060
|
-
const rows = (0,
|
|
2796
|
+
const rows = (0, import_react20.useMemo)(
|
|
2061
2797
|
() => state !== void 0 ? items(state.nodeId) : [],
|
|
2062
2798
|
[items, state]
|
|
2063
2799
|
);
|
|
2064
|
-
const enabledIndices = (0,
|
|
2800
|
+
const enabledIndices = (0, import_react20.useMemo)(
|
|
2065
2801
|
() => rows.map((r, i) => r.disabled ? -1 : i).filter((i) => i >= 0),
|
|
2066
2802
|
[rows]
|
|
2067
2803
|
);
|
|
2068
|
-
const move = (0,
|
|
2804
|
+
const move = (0, import_react20.useCallback)(
|
|
2069
2805
|
(delta) => {
|
|
2070
2806
|
if (enabledIndices.length === 0) {
|
|
2071
2807
|
return;
|
|
@@ -2079,7 +2815,7 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2079
2815
|
},
|
|
2080
2816
|
[enabledIndices]
|
|
2081
2817
|
);
|
|
2082
|
-
const choose = (0,
|
|
2818
|
+
const choose = (0, import_react20.useCallback)(
|
|
2083
2819
|
(item) => {
|
|
2084
2820
|
if (item === void 0 || item.disabled) {
|
|
2085
2821
|
return;
|
|
@@ -2089,7 +2825,7 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2089
2825
|
},
|
|
2090
2826
|
[controller]
|
|
2091
2827
|
);
|
|
2092
|
-
const onKeyDown = (0,
|
|
2828
|
+
const onKeyDown = (0, import_react20.useCallback)(
|
|
2093
2829
|
(event) => {
|
|
2094
2830
|
switch (event.key) {
|
|
2095
2831
|
case "ArrowDown":
|
|
@@ -2118,8 +2854,8 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2118
2854
|
return null;
|
|
2119
2855
|
}
|
|
2120
2856
|
const style = clampToViewport2(state.screen.x, state.screen.y, rows.length);
|
|
2121
|
-
return /* @__PURE__ */ (0,
|
|
2122
|
-
/* @__PURE__ */ (0,
|
|
2857
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2123
2859
|
"div",
|
|
2124
2860
|
{
|
|
2125
2861
|
className: "hl-ctx-scrim",
|
|
@@ -2132,7 +2868,7 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2132
2868
|
}
|
|
2133
2869
|
}
|
|
2134
2870
|
),
|
|
2135
|
-
/* @__PURE__ */ (0,
|
|
2871
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
2136
2872
|
"div",
|
|
2137
2873
|
{
|
|
2138
2874
|
ref: menuRef,
|
|
@@ -2142,7 +2878,7 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2142
2878
|
"aria-label": "Node actions",
|
|
2143
2879
|
tabIndex: -1,
|
|
2144
2880
|
onKeyDown,
|
|
2145
|
-
children: rows.map((item, index) => /* @__PURE__ */ (0,
|
|
2881
|
+
children: rows.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
2146
2882
|
"button",
|
|
2147
2883
|
{
|
|
2148
2884
|
type: "button",
|
|
@@ -2155,9 +2891,9 @@ function NodeContextMenu({ controller, items }) {
|
|
|
2155
2891
|
choose(item);
|
|
2156
2892
|
},
|
|
2157
2893
|
children: [
|
|
2158
|
-
/* @__PURE__ */ (0,
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2160
|
-
item.shortcut !== void 0 && /* @__PURE__ */ (0,
|
|
2894
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "hl-ctx-item-icon", "aria-hidden": true, children: item.icon }),
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "hl-ctx-item-label", children: item.label }),
|
|
2896
|
+
item.shortcut !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "hl-ctx-item-key hl-mono", children: item.shortcut })
|
|
2161
2897
|
]
|
|
2162
2898
|
},
|
|
2163
2899
|
item.id
|
|
@@ -2177,21 +2913,21 @@ function clampToViewport2(x, y, rowCount) {
|
|
|
2177
2913
|
}
|
|
2178
2914
|
|
|
2179
2915
|
// src/context-menu/useNodeContextMenu.ts
|
|
2180
|
-
var
|
|
2916
|
+
var import_react21 = require("react");
|
|
2181
2917
|
function useNodeContextMenu() {
|
|
2182
|
-
const [state, setState] = (0,
|
|
2183
|
-
const openForNode = (0,
|
|
2918
|
+
const [state, setState] = (0, import_react21.useState)(void 0);
|
|
2919
|
+
const openForNode = (0, import_react21.useCallback)((screen, nodeId) => {
|
|
2184
2920
|
setState({ screen, nodeId });
|
|
2185
2921
|
}, []);
|
|
2186
|
-
const close = (0,
|
|
2922
|
+
const close = (0, import_react21.useCallback)(() => {
|
|
2187
2923
|
setState(void 0);
|
|
2188
2924
|
}, []);
|
|
2189
|
-
return (0,
|
|
2925
|
+
return (0, import_react21.useMemo)(() => ({ state, openForNode, close }), [state, openForNode, close]);
|
|
2190
2926
|
}
|
|
2191
2927
|
|
|
2192
2928
|
// src/overlays/Cheatsheet.tsx
|
|
2193
|
-
var
|
|
2194
|
-
var
|
|
2929
|
+
var import_react22 = require("react");
|
|
2930
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2195
2931
|
var DEFAULT_GROUPS = [
|
|
2196
2932
|
{
|
|
2197
2933
|
title: "Edit",
|
|
@@ -2227,8 +2963,8 @@ var DEFAULT_GROUPS = [
|
|
|
2227
2963
|
}
|
|
2228
2964
|
];
|
|
2229
2965
|
function Cheatsheet({ open, onClose, groups = DEFAULT_GROUPS }) {
|
|
2230
|
-
const dialogRef = (0,
|
|
2231
|
-
(0,
|
|
2966
|
+
const dialogRef = (0, import_react22.useRef)(null);
|
|
2967
|
+
(0, import_react22.useEffect)(() => {
|
|
2232
2968
|
var _a;
|
|
2233
2969
|
if (!open) {
|
|
2234
2970
|
return;
|
|
@@ -2245,9 +2981,9 @@ function Cheatsheet({ open, onClose, groups = DEFAULT_GROUPS }) {
|
|
|
2245
2981
|
if (!open) {
|
|
2246
2982
|
return null;
|
|
2247
2983
|
}
|
|
2248
|
-
return /* @__PURE__ */ (0,
|
|
2249
|
-
/* @__PURE__ */ (0,
|
|
2250
|
-
/* @__PURE__ */ (0,
|
|
2984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "hl-cheat-scrim", onPointerDown: onClose }),
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
2251
2987
|
"div",
|
|
2252
2988
|
{
|
|
2253
2989
|
ref: dialogRef,
|
|
@@ -2257,18 +2993,18 @@ function Cheatsheet({ open, onClose, groups = DEFAULT_GROUPS }) {
|
|
|
2257
2993
|
"aria-label": "Keyboard shortcuts",
|
|
2258
2994
|
tabIndex: -1,
|
|
2259
2995
|
children: [
|
|
2260
|
-
/* @__PURE__ */ (0,
|
|
2261
|
-
/* @__PURE__ */ (0,
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "hl-cheat-head", children: [
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "hl-cheat-title", children: "Shortcuts" }),
|
|
2998
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { className: "hl-cheat-close", onClick: onClose, "aria-label": "Close", children: "\u2715" })
|
|
2263
2999
|
] }),
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
3000
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "hl-cheat-grid", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("section", { className: "hl-cheat-group", children: [
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("h3", { className: "hl-cheat-group-title hl-mono", children: group.title }),
|
|
3002
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "hl-cheat-rows", children: group.rows.map((row) => (
|
|
2267
3003
|
// A row is a binding: one action can have several (two ways to pan),
|
|
2268
3004
|
// so neither the label nor the keys alone identify it.
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
3005
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "hl-cheat-row", children: [
|
|
3006
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "hl-cheat-label", children: row.label }),
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("kbd", { className: "hl-cheat-keys hl-mono", children: row.keys })
|
|
2272
3008
|
] }, `${row.keys}\0${row.label}`)
|
|
2273
3009
|
)) })
|
|
2274
3010
|
] }, group.title)) })
|
|
@@ -2279,13 +3015,13 @@ function Cheatsheet({ open, onClose, groups = DEFAULT_GROUPS }) {
|
|
|
2279
3015
|
}
|
|
2280
3016
|
|
|
2281
3017
|
// src/overlays/Toast.tsx
|
|
2282
|
-
var
|
|
2283
|
-
var
|
|
2284
|
-
var ToastCtx = (0,
|
|
3018
|
+
var import_react23 = require("react");
|
|
3019
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
3020
|
+
var ToastCtx = (0, import_react23.createContext)({ show: () => void 0 });
|
|
2285
3021
|
function ToastProvider({ children, duration = 2200 }) {
|
|
2286
|
-
const [items, setItems] = (0,
|
|
2287
|
-
const seq = (0,
|
|
2288
|
-
const show = (0,
|
|
3022
|
+
const [items, setItems] = (0, import_react23.useState)([]);
|
|
3023
|
+
const seq = (0, import_react23.useRef)(0);
|
|
3024
|
+
const show = (0, import_react23.useCallback)(
|
|
2289
3025
|
(message) => {
|
|
2290
3026
|
seq.current += 1;
|
|
2291
3027
|
const id = seq.current;
|
|
@@ -2296,22 +3032,22 @@ function ToastProvider({ children, duration = 2200 }) {
|
|
|
2296
3032
|
},
|
|
2297
3033
|
[duration]
|
|
2298
3034
|
);
|
|
2299
|
-
const api = (0,
|
|
2300
|
-
return /* @__PURE__ */ (0,
|
|
3035
|
+
const api = (0, import_react23.useMemo)(() => ({ show }), [show]);
|
|
3036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(ToastCtx.Provider, { value: api, children: [
|
|
2301
3037
|
children,
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
3038
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "hl-toast-stack", "aria-live": "polite", children: items.map((t) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "hl-toast", children: t.message }, t.id)) })
|
|
2303
3039
|
] });
|
|
2304
3040
|
}
|
|
2305
3041
|
function useToast() {
|
|
2306
|
-
return (0,
|
|
3042
|
+
return (0, import_react23.useContext)(ToastCtx);
|
|
2307
3043
|
}
|
|
2308
3044
|
|
|
2309
3045
|
// src/hooks/useLiveSignals.ts
|
|
2310
|
-
var
|
|
3046
|
+
var import_react24 = require("react");
|
|
2311
3047
|
function useLiveSignals(core, handle, explicitStore) {
|
|
2312
3048
|
const contextStore = useLiveSignalStore();
|
|
2313
3049
|
const store = explicitStore != null ? explicitStore : contextStore;
|
|
2314
|
-
(0,
|
|
3050
|
+
(0, import_react24.useEffect)(() => {
|
|
2315
3051
|
if (store === null) {
|
|
2316
3052
|
return;
|
|
2317
3053
|
}
|
|
@@ -2320,6 +3056,8 @@ function useLiveSignals(core, handle, explicitStore) {
|
|
|
2320
3056
|
id: edge.id,
|
|
2321
3057
|
sourceNodeId: edge.source.nodeId,
|
|
2322
3058
|
sourcePortId: edge.source.portId,
|
|
3059
|
+
targetNodeId: edge.target.nodeId,
|
|
3060
|
+
targetPortId: edge.target.portId,
|
|
2323
3061
|
isError: edge.source.portId === "@node/error"
|
|
2324
3062
|
}));
|
|
2325
3063
|
store.setEdgeIndex(entries);
|
|
@@ -2332,7 +3070,8 @@ function useLiveSignals(core, handle, explicitStore) {
|
|
|
2332
3070
|
removed.dispose();
|
|
2333
3071
|
};
|
|
2334
3072
|
}, [core, store]);
|
|
2335
|
-
(0,
|
|
3073
|
+
(0, import_react24.useEffect)(() => {
|
|
3074
|
+
var _a, _b, _c;
|
|
2336
3075
|
if (store === null) {
|
|
2337
3076
|
return;
|
|
2338
3077
|
}
|
|
@@ -2340,15 +3079,407 @@ function useLiveSignals(core, handle, explicitStore) {
|
|
|
2340
3079
|
store.reset();
|
|
2341
3080
|
return;
|
|
2342
3081
|
}
|
|
2343
|
-
const
|
|
3082
|
+
const signalSub = (_b = (_a = handle.onDelivery) == null ? void 0 : _a.call(handle, (event) => {
|
|
3083
|
+
store.markDelivery(event);
|
|
3084
|
+
})) != null ? _b : handle.onActivity((e) => store.markActivity(e.nodeId, e.portId));
|
|
2344
3085
|
const errorSub = handle.onError((e) => store.markError(e.nodeId));
|
|
3086
|
+
const finishedSub = (_c = handle.onFinished) == null ? void 0 : _c.call(handle, (e) => {
|
|
3087
|
+
store.markFinished(e.nodeId);
|
|
3088
|
+
});
|
|
2345
3089
|
return () => {
|
|
2346
|
-
|
|
3090
|
+
signalSub.dispose();
|
|
2347
3091
|
errorSub.dispose();
|
|
3092
|
+
finishedSub == null ? void 0 : finishedSub.dispose();
|
|
2348
3093
|
store.reset();
|
|
2349
3094
|
};
|
|
2350
3095
|
}, [store, handle]);
|
|
2351
3096
|
}
|
|
3097
|
+
|
|
3098
|
+
// src/live/run-trace.ts
|
|
3099
|
+
var RUN_LOG_CAPACITY = 500;
|
|
3100
|
+
var RunTrace = class {
|
|
3101
|
+
constructor(options = {}) {
|
|
3102
|
+
/** The log as a ring: `ring[(head + i) % capacity]` is the i-th oldest entry. */
|
|
3103
|
+
this.ring = [];
|
|
3104
|
+
this.head = 0;
|
|
3105
|
+
this.droppedCount = 0;
|
|
3106
|
+
this.seq = 0;
|
|
3107
|
+
this.startedAt = 0;
|
|
3108
|
+
this.stats = /* @__PURE__ */ new Map();
|
|
3109
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
3110
|
+
/** Bumped by every change; the entries cache follows it. */
|
|
3111
|
+
this.revision = 0;
|
|
3112
|
+
/** Bumped once per notified frame; what subscribers compare. */
|
|
3113
|
+
this.version = 0;
|
|
3114
|
+
this.frame = null;
|
|
3115
|
+
/** The entries as an array, rebuilt only after a change. */
|
|
3116
|
+
this.entriesCache = [];
|
|
3117
|
+
this.entriesRevision = -1;
|
|
3118
|
+
var _a, _b;
|
|
3119
|
+
const capacity = (_a = options.capacity) != null ? _a : RUN_LOG_CAPACITY;
|
|
3120
|
+
if (!Number.isInteger(capacity) || capacity < 1) {
|
|
3121
|
+
throw new RangeError("RunTrace capacity must be a positive integer.");
|
|
3122
|
+
}
|
|
3123
|
+
this.capacity = capacity;
|
|
3124
|
+
this.deps = (_b = options.deps) != null ? _b : defaultLiveDeps;
|
|
3125
|
+
}
|
|
3126
|
+
/** Begins a run: clears everything and times entries from now. */
|
|
3127
|
+
start() {
|
|
3128
|
+
this.clear();
|
|
3129
|
+
this.startedAt = this.deps.now();
|
|
3130
|
+
}
|
|
3131
|
+
/** Forgets the log and the statistics. */
|
|
3132
|
+
clear() {
|
|
3133
|
+
this.ring.length = 0;
|
|
3134
|
+
this.head = 0;
|
|
3135
|
+
this.droppedCount = 0;
|
|
3136
|
+
this.stats.clear();
|
|
3137
|
+
this.changed();
|
|
3138
|
+
}
|
|
3139
|
+
recordDelivery(event) {
|
|
3140
|
+
this.append({
|
|
3141
|
+
kind: "delivery",
|
|
3142
|
+
seq: this.nextSeq(),
|
|
3143
|
+
at: this.elapsed(),
|
|
3144
|
+
sourceNodeId: event.sourceNodeId,
|
|
3145
|
+
sourcePortId: event.sourcePortId,
|
|
3146
|
+
targetNodeId: event.targetNodeId,
|
|
3147
|
+
targetPortId: event.targetPortId,
|
|
3148
|
+
message: event.message,
|
|
3149
|
+
duration: event.duration
|
|
3150
|
+
});
|
|
3151
|
+
const source = this.statsFor(event.sourceNodeId);
|
|
3152
|
+
source.sent += 1;
|
|
3153
|
+
source.lastSent = event.message;
|
|
3154
|
+
const target = this.statsFor(event.targetNodeId);
|
|
3155
|
+
target.received += 1;
|
|
3156
|
+
target.totalMs += event.duration;
|
|
3157
|
+
target.maxMs = Math.max(target.maxMs, event.duration);
|
|
3158
|
+
target.lastReceived = event.message;
|
|
3159
|
+
this.changed();
|
|
3160
|
+
}
|
|
3161
|
+
recordError(event) {
|
|
3162
|
+
this.append({ kind: "error", seq: this.nextSeq(), at: this.elapsed(), nodeId: event.nodeId, error: event.error });
|
|
3163
|
+
this.statsFor(event.nodeId).errors += 1;
|
|
3164
|
+
this.changed();
|
|
3165
|
+
}
|
|
3166
|
+
recordEnded(event) {
|
|
3167
|
+
this.append({ kind: "ended", seq: this.nextSeq(), at: this.elapsed(), nodeId: event.nodeId, portId: event.portId });
|
|
3168
|
+
this.statsFor(event.nodeId);
|
|
3169
|
+
this.changed();
|
|
3170
|
+
}
|
|
3171
|
+
recordFinished(event) {
|
|
3172
|
+
this.append({ kind: "finished", seq: this.nextSeq(), at: this.elapsed(), nodeId: event.nodeId });
|
|
3173
|
+
this.statsFor(event.nodeId).finished = true;
|
|
3174
|
+
this.changed();
|
|
3175
|
+
}
|
|
3176
|
+
recordDropped(event) {
|
|
3177
|
+
this.append({
|
|
3178
|
+
kind: "dropped",
|
|
3179
|
+
seq: this.nextSeq(),
|
|
3180
|
+
at: this.elapsed(),
|
|
3181
|
+
sourceNodeId: event.sourceNodeId,
|
|
3182
|
+
sourcePortId: event.sourcePortId,
|
|
3183
|
+
targetNodeId: event.targetNodeId,
|
|
3184
|
+
targetPortId: event.targetPortId,
|
|
3185
|
+
message: event.message
|
|
3186
|
+
});
|
|
3187
|
+
this.statsFor(event.sourceNodeId);
|
|
3188
|
+
this.statsFor(event.targetNodeId).dropped += 1;
|
|
3189
|
+
this.changed();
|
|
3190
|
+
}
|
|
3191
|
+
/** The log, oldest first. The same array is returned until something changes. */
|
|
3192
|
+
entries() {
|
|
3193
|
+
if (this.entriesRevision !== this.revision) {
|
|
3194
|
+
const count = this.ring.length;
|
|
3195
|
+
const ordered = [];
|
|
3196
|
+
for (let i = 0; i < count; i += 1) {
|
|
3197
|
+
const entry = this.ring[(this.head + i) % count];
|
|
3198
|
+
if (entry !== void 0) {
|
|
3199
|
+
ordered.push(entry);
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
this.entriesCache = ordered;
|
|
3203
|
+
this.entriesRevision = this.revision;
|
|
3204
|
+
}
|
|
3205
|
+
return this.entriesCache;
|
|
3206
|
+
}
|
|
3207
|
+
/** A node's statistics, or `undefined` when it has done nothing this run. */
|
|
3208
|
+
statsOf(nodeId) {
|
|
3209
|
+
const stats = this.stats.get(nodeId);
|
|
3210
|
+
return stats === void 0 ? void 0 : { ...stats };
|
|
3211
|
+
}
|
|
3212
|
+
/** How many entries the log has let go of to stay within its capacity. */
|
|
3213
|
+
get dropped() {
|
|
3214
|
+
return this.droppedCount;
|
|
3215
|
+
}
|
|
3216
|
+
/** Changes once per notified frame; a snapshot for `useSyncExternalStore`. */
|
|
3217
|
+
getVersion() {
|
|
3218
|
+
return this.version;
|
|
3219
|
+
}
|
|
3220
|
+
subscribe(listener) {
|
|
3221
|
+
this.listeners.add(listener);
|
|
3222
|
+
return () => {
|
|
3223
|
+
this.listeners.delete(listener);
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
append(entry) {
|
|
3227
|
+
if (this.ring.length < this.capacity) {
|
|
3228
|
+
this.ring.push(entry);
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
this.ring[this.head] = entry;
|
|
3232
|
+
this.head = (this.head + 1) % this.capacity;
|
|
3233
|
+
this.droppedCount += 1;
|
|
3234
|
+
}
|
|
3235
|
+
nextSeq() {
|
|
3236
|
+
this.seq += 1;
|
|
3237
|
+
return this.seq;
|
|
3238
|
+
}
|
|
3239
|
+
elapsed() {
|
|
3240
|
+
return this.deps.now() - this.startedAt;
|
|
3241
|
+
}
|
|
3242
|
+
statsFor(nodeId) {
|
|
3243
|
+
let stats = this.stats.get(nodeId);
|
|
3244
|
+
if (stats === void 0) {
|
|
3245
|
+
stats = {
|
|
3246
|
+
received: 0,
|
|
3247
|
+
sent: 0,
|
|
3248
|
+
errors: 0,
|
|
3249
|
+
totalMs: 0,
|
|
3250
|
+
maxMs: 0,
|
|
3251
|
+
lastReceived: void 0,
|
|
3252
|
+
lastSent: void 0,
|
|
3253
|
+
dropped: 0,
|
|
3254
|
+
finished: false
|
|
3255
|
+
};
|
|
3256
|
+
this.stats.set(nodeId, stats);
|
|
3257
|
+
}
|
|
3258
|
+
return stats;
|
|
3259
|
+
}
|
|
3260
|
+
/** Schedules one notification for the next frame, however many changes come before it. */
|
|
3261
|
+
changed() {
|
|
3262
|
+
this.revision += 1;
|
|
3263
|
+
if (this.frame !== null) {
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
this.frame = this.deps.schedule(() => {
|
|
3267
|
+
this.frame = null;
|
|
3268
|
+
this.version += 1;
|
|
3269
|
+
for (const listener of [...this.listeners]) {
|
|
3270
|
+
listener();
|
|
3271
|
+
}
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
};
|
|
3275
|
+
function involves(entry, nodeId) {
|
|
3276
|
+
switch (entry.kind) {
|
|
3277
|
+
case "delivery":
|
|
3278
|
+
case "dropped":
|
|
3279
|
+
return entry.sourceNodeId === nodeId || entry.targetNodeId === nodeId;
|
|
3280
|
+
case "error":
|
|
3281
|
+
case "ended":
|
|
3282
|
+
case "finished":
|
|
3283
|
+
return entry.nodeId === nodeId;
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
// src/hooks/useRunTrace.ts
|
|
3288
|
+
var import_react25 = require("react");
|
|
3289
|
+
function useRunTrace(trace, handle) {
|
|
3290
|
+
(0, import_react25.useEffect)(() => {
|
|
3291
|
+
var _a, _b, _c, _d;
|
|
3292
|
+
if (handle === void 0) {
|
|
3293
|
+
return;
|
|
3294
|
+
}
|
|
3295
|
+
trace.start();
|
|
3296
|
+
const deliveries = (_a = handle.onDelivery) == null ? void 0 : _a.call(handle, (event) => {
|
|
3297
|
+
trace.recordDelivery(event);
|
|
3298
|
+
});
|
|
3299
|
+
const errors = handle.onError((event) => {
|
|
3300
|
+
trace.recordError(event);
|
|
3301
|
+
});
|
|
3302
|
+
const ended = (_b = handle.onEnded) == null ? void 0 : _b.call(handle, (event) => {
|
|
3303
|
+
trace.recordEnded(event);
|
|
3304
|
+
});
|
|
3305
|
+
const finished = (_c = handle.onFinished) == null ? void 0 : _c.call(handle, (event) => {
|
|
3306
|
+
trace.recordFinished(event);
|
|
3307
|
+
});
|
|
3308
|
+
const dropped = (_d = handle.onDropped) == null ? void 0 : _d.call(handle, (event) => {
|
|
3309
|
+
trace.recordDropped(event);
|
|
3310
|
+
});
|
|
3311
|
+
return () => {
|
|
3312
|
+
deliveries == null ? void 0 : deliveries.dispose();
|
|
3313
|
+
errors.dispose();
|
|
3314
|
+
ended == null ? void 0 : ended.dispose();
|
|
3315
|
+
finished == null ? void 0 : finished.dispose();
|
|
3316
|
+
dropped == null ? void 0 : dropped.dispose();
|
|
3317
|
+
};
|
|
3318
|
+
}, [trace, handle]);
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
// src/hooks/useFollowScroll.ts
|
|
3322
|
+
var import_react26 = require("react");
|
|
3323
|
+
var FOLLOW_SLACK_PX = 24;
|
|
3324
|
+
function useFollowScroll() {
|
|
3325
|
+
const ref = (0, import_react26.useRef)(null);
|
|
3326
|
+
const [follow, setFollow] = (0, import_react26.useState)(true);
|
|
3327
|
+
(0, import_react26.useLayoutEffect)(() => {
|
|
3328
|
+
const element = ref.current;
|
|
3329
|
+
if (follow && element !== null) {
|
|
3330
|
+
element.scrollTop = element.scrollHeight;
|
|
3331
|
+
}
|
|
3332
|
+
});
|
|
3333
|
+
const onScroll = (0, import_react26.useCallback)((event) => {
|
|
3334
|
+
const element = event.currentTarget;
|
|
3335
|
+
setFollow(element.scrollHeight - element.scrollTop - element.clientHeight <= FOLLOW_SLACK_PX);
|
|
3336
|
+
}, []);
|
|
3337
|
+
return { ref, onScroll, follow, setFollow };
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
// src/panels/RunLog.tsx
|
|
3341
|
+
var import_react27 = require("react");
|
|
3342
|
+
var import_editor_react6 = require("@hlang-tech/editor-react");
|
|
3343
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
3344
|
+
function RunLog({ core, onSelectNode, title = "Run log", leading }) {
|
|
3345
|
+
const trace = useRunTraceStore();
|
|
3346
|
+
useRunTraceVersion(trace);
|
|
3347
|
+
const selection = (0, import_editor_react6.useSelection)(core);
|
|
3348
|
+
const [onlySelected, setOnlySelected] = (0, import_react27.useState)(false);
|
|
3349
|
+
const { ref: bodyRef, onScroll, follow, setFollow } = useFollowScroll();
|
|
3350
|
+
const all = trace === null ? [] : trace.entries();
|
|
3351
|
+
const selectedId = selection.selectedNodes.length === 1 ? selection.selectedNodes[0] : void 0;
|
|
3352
|
+
const filterId = onlySelected ? selectedId : void 0;
|
|
3353
|
+
const entries = filterId === void 0 ? all : all.filter((entry) => involves(entry, filterId));
|
|
3354
|
+
if (trace === null) {
|
|
3355
|
+
return null;
|
|
3356
|
+
}
|
|
3357
|
+
const label = (nodeId) => {
|
|
3358
|
+
var _a, _b;
|
|
3359
|
+
return (_b = (_a = core.model.getNode(nodeId)) == null ? void 0 : _a.name) != null ? _b : nodeId;
|
|
3360
|
+
};
|
|
3361
|
+
const choose = (nodeId) => {
|
|
3362
|
+
core.selection.selectNodes([nodeId], "replace");
|
|
3363
|
+
onSelectNode == null ? void 0 : onSelectNode(nodeId);
|
|
3364
|
+
};
|
|
3365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { className: "hl-runlog", "aria-label": title, children: [
|
|
3366
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("header", { className: "hl-runlog-head", children: [
|
|
3367
|
+
leading != null ? leading : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-title", children: title }),
|
|
3368
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "hl-runlog-count hl-mono", children: [
|
|
3369
|
+
entries.length === all.length ? `${String(all.length)} events` : `${String(entries.length)} of ${String(all.length)} events`,
|
|
3370
|
+
trace.dropped > 0 ? ` \xB7 ${String(trace.dropped)} earlier not kept` : ""
|
|
3371
|
+
] }),
|
|
3372
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "hl-runlog-actions", children: [
|
|
3373
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3374
|
+
"button",
|
|
3375
|
+
{
|
|
3376
|
+
type: "button",
|
|
3377
|
+
className: `hl-runlog-toggle${onlySelected ? " is-on" : ""}`,
|
|
3378
|
+
"aria-pressed": onlySelected,
|
|
3379
|
+
disabled: selectedId === void 0 && !onlySelected,
|
|
3380
|
+
title: selectedId === void 0 ? "Select a node to filter by it" : `Only ${label(selectedId)}`,
|
|
3381
|
+
onClick: () => {
|
|
3382
|
+
setOnlySelected((value) => !value);
|
|
3383
|
+
},
|
|
3384
|
+
children: onlySelected && selectedId !== void 0 ? `Only ${label(selectedId)}` : "Selected node"
|
|
3385
|
+
}
|
|
3386
|
+
),
|
|
3387
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3388
|
+
"button",
|
|
3389
|
+
{
|
|
3390
|
+
type: "button",
|
|
3391
|
+
className: `hl-runlog-toggle${follow ? " is-on" : ""}`,
|
|
3392
|
+
"aria-pressed": follow,
|
|
3393
|
+
onClick: () => {
|
|
3394
|
+
setFollow(!follow);
|
|
3395
|
+
},
|
|
3396
|
+
children: "Follow"
|
|
3397
|
+
}
|
|
3398
|
+
),
|
|
3399
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3400
|
+
"button",
|
|
3401
|
+
{
|
|
3402
|
+
type: "button",
|
|
3403
|
+
className: "hl-runlog-toggle",
|
|
3404
|
+
disabled: all.length === 0,
|
|
3405
|
+
onClick: () => {
|
|
3406
|
+
trace.clear();
|
|
3407
|
+
},
|
|
3408
|
+
children: "Clear"
|
|
3409
|
+
}
|
|
3410
|
+
)
|
|
3411
|
+
] })
|
|
3412
|
+
] }),
|
|
3413
|
+
entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "hl-runlog-empty", children: all.length === 0 ? "Run the graph to see every message as it moves through it." : "Nothing involving the selected node yet." }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ol", { className: "hl-runlog-body hl-mono", ref: bodyRef, onScroll, children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Row, { entry, label, onChoose: choose }, entry.seq)) })
|
|
3414
|
+
] });
|
|
3415
|
+
}
|
|
3416
|
+
function Row({
|
|
3417
|
+
entry,
|
|
3418
|
+
label,
|
|
3419
|
+
onChoose
|
|
3420
|
+
}) {
|
|
3421
|
+
switch (entry.kind) {
|
|
3422
|
+
case "error":
|
|
3423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Event, { className: "is-error", at: entry.at, onChoose: () => onChoose(entry.nodeId), ms: "", children: [
|
|
3424
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(NodePort, { node: label(entry.nodeId), port: "error" }),
|
|
3425
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-value", children: previewValue(entry.error) })
|
|
3426
|
+
] });
|
|
3427
|
+
case "ended":
|
|
3428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Event, { className: "is-end", at: entry.at, onChoose: () => onChoose(entry.nodeId), ms: "", children: [
|
|
3429
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(NodePort, { node: label(entry.nodeId), port: entry.portId }),
|
|
3430
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-value", children: "ended" })
|
|
3431
|
+
] });
|
|
3432
|
+
case "finished":
|
|
3433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Event, { className: "is-end", at: entry.at, onChoose: () => onChoose(entry.nodeId), ms: "", children: [
|
|
3434
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(NodePort, { node: label(entry.nodeId), port: "" }),
|
|
3435
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-value", children: "finished" })
|
|
3436
|
+
] });
|
|
3437
|
+
case "dropped":
|
|
3438
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Event, { className: "is-dropped", at: entry.at, onChoose: () => onChoose(entry.targetNodeId), ms: "", children: [
|
|
3439
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Route, { entry, label }),
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "hl-runlog-value", children: [
|
|
3441
|
+
"dropped ",
|
|
3442
|
+
previewValue(entry.message)
|
|
3443
|
+
] })
|
|
3444
|
+
] });
|
|
3445
|
+
case "delivery":
|
|
3446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Event, { className: "", at: entry.at, onChoose: () => onChoose(entry.targetNodeId), ms: formatDuration(entry.duration), children: [
|
|
3447
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Route, { entry, label }),
|
|
3448
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-value", children: previewValue(entry.message) })
|
|
3449
|
+
] });
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
function Event({
|
|
3453
|
+
className: className2,
|
|
3454
|
+
at,
|
|
3455
|
+
ms,
|
|
3456
|
+
onChoose,
|
|
3457
|
+
children
|
|
3458
|
+
}) {
|
|
3459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { className: `hl-runlog-row ${className2}`.trim(), children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("button", { type: "button", className: "hl-runlog-hit", onClick: onChoose, children: [
|
|
3460
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-at", children: formatElapsed(at) }),
|
|
3461
|
+
children,
|
|
3462
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-ms", children: ms })
|
|
3463
|
+
] }) });
|
|
3464
|
+
}
|
|
3465
|
+
function NodePort({ node, port }) {
|
|
3466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "hl-runlog-route", children: [
|
|
3467
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-node", children: node }),
|
|
3468
|
+
port === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-port", children: port })
|
|
3469
|
+
] });
|
|
3470
|
+
}
|
|
3471
|
+
function Route({
|
|
3472
|
+
entry,
|
|
3473
|
+
label
|
|
3474
|
+
}) {
|
|
3475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "hl-runlog-route", children: [
|
|
3476
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-node", children: label(entry.sourceNodeId) }),
|
|
3477
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-port", children: entry.sourcePortId }),
|
|
3478
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-arrow", "aria-label": "to", children: "\u2192" }),
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-node", children: label(entry.targetNodeId) }),
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "hl-runlog-port", children: entry.targetPortId })
|
|
3481
|
+
] });
|
|
3482
|
+
}
|
|
2352
3483
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2353
3484
|
0 && (module.exports = {
|
|
2354
3485
|
AssetGrid,
|
|
@@ -2356,30 +3487,45 @@ function useLiveSignals(core, handle, explicitStore) {
|
|
|
2356
3487
|
CanvasChrome,
|
|
2357
3488
|
CanvasDock,
|
|
2358
3489
|
Cheatsheet,
|
|
3490
|
+
ConnectionInspector,
|
|
3491
|
+
DEFAULT_EDGE_CAPACITY,
|
|
3492
|
+
DEFAULT_MIN_CANVAS_HEIGHT,
|
|
2359
3493
|
DiagnosticBadge,
|
|
2360
3494
|
EditorShell,
|
|
2361
3495
|
EditorUIThemeProvider,
|
|
2362
3496
|
EmptyState,
|
|
3497
|
+
FOLLOW_SLACK_PX,
|
|
3498
|
+
FOOTER_KEY_STEP,
|
|
2363
3499
|
FlowEdge,
|
|
3500
|
+
FooterResizer,
|
|
2364
3501
|
HlangNode,
|
|
2365
3502
|
InspectorPanel,
|
|
2366
3503
|
KIND_ROLE,
|
|
2367
3504
|
KIND_TOKEN,
|
|
3505
|
+
LivePulse,
|
|
2368
3506
|
LiveSignalProvider,
|
|
2369
3507
|
LiveSignalStore,
|
|
2370
3508
|
NodeBodySlot,
|
|
2371
3509
|
NodeChrome,
|
|
2372
3510
|
NodeContextMenu,
|
|
2373
3511
|
NodeInteractionProvider,
|
|
3512
|
+
NodeRunStats,
|
|
2374
3513
|
NodeSearch,
|
|
2375
3514
|
OutlineTree,
|
|
3515
|
+
PREVIEW_LENGTH,
|
|
2376
3516
|
ParamForm,
|
|
2377
3517
|
PillNodeChrome,
|
|
2378
3518
|
PortRow,
|
|
2379
3519
|
PositionPanel,
|
|
2380
3520
|
PreviewPanel,
|
|
3521
|
+
RUN_LOG_CAPACITY,
|
|
2381
3522
|
RailTabs,
|
|
2382
3523
|
RunButton,
|
|
3524
|
+
RunLog,
|
|
3525
|
+
RunTrace,
|
|
3526
|
+
RunTraceProvider,
|
|
3527
|
+
SELF_LOOP_CLEARANCE,
|
|
3528
|
+
SELF_LOOP_RADIUS,
|
|
2383
3529
|
SignalBar,
|
|
2384
3530
|
TOKEN_NAMES,
|
|
2385
3531
|
ToastProvider,
|
|
@@ -2388,26 +3534,47 @@ function useLiveSignals(core, handle, explicitStore) {
|
|
|
2388
3534
|
ToolbarGhostButton,
|
|
2389
3535
|
ToolbarStat,
|
|
2390
3536
|
UndoRedo,
|
|
3537
|
+
boundsFields,
|
|
3538
|
+
capacityLabel,
|
|
3539
|
+
clampFooter,
|
|
2391
3540
|
connectableCandidates,
|
|
2392
3541
|
createHlangFlowTypes,
|
|
2393
3542
|
createTheme,
|
|
3543
|
+
defaultLiveDeps,
|
|
2394
3544
|
deriveParamSchema,
|
|
2395
3545
|
descriptorCandidates,
|
|
3546
|
+
footerBounds,
|
|
3547
|
+
formatDuration,
|
|
3548
|
+
formatElapsed,
|
|
2396
3549
|
fuzzyRank,
|
|
2397
3550
|
fuzzyScore,
|
|
3551
|
+
involves,
|
|
2398
3552
|
isEditableTarget,
|
|
3553
|
+
nextBounds,
|
|
3554
|
+
previewValue,
|
|
3555
|
+
resizeByKey,
|
|
2399
3556
|
searchNodes,
|
|
3557
|
+
selfLoopPath,
|
|
3558
|
+
toggleCollapsed,
|
|
2400
3559
|
tokenVar,
|
|
3560
|
+
useEdgeBounds,
|
|
2401
3561
|
useEdgeFlowing,
|
|
3562
|
+
useEdgePulse,
|
|
2402
3563
|
useEditorHotkeys,
|
|
3564
|
+
useFollowScroll,
|
|
3565
|
+
useFooterResize,
|
|
2403
3566
|
useLiveSignalStore,
|
|
2404
3567
|
useLiveSignals,
|
|
2405
3568
|
useNodeContextMenu,
|
|
2406
3569
|
useNodeInteraction,
|
|
2407
3570
|
useNodeLiveState,
|
|
2408
3571
|
useNodeParams,
|
|
3572
|
+
useNodePulse,
|
|
2409
3573
|
useNodeSearch,
|
|
2410
3574
|
useNodeSearchTriggers,
|
|
3575
|
+
useRunTrace,
|
|
3576
|
+
useRunTraceStore,
|
|
3577
|
+
useRunTraceVersion,
|
|
2411
3578
|
useToast
|
|
2412
3579
|
});
|
|
2413
3580
|
//# sourceMappingURL=index.js.map
|