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