@bian-womp/spark-workbench 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/index.cjs +31 -18
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/index.d.ts +1 -0
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/misc/DefaultNode.d.ts +1 -0
- package/lib/cjs/src/misc/DefaultNode.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts +4 -0
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts +4 -0
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/mapping.d.ts +4 -0
- package/lib/cjs/src/misc/mapping.d.ts.map +1 -1
- package/lib/esm/index.js +31 -20
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/index.d.ts +1 -0
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/misc/DefaultNode.d.ts +1 -0
- package/lib/esm/src/misc/DefaultNode.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts +4 -0
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts +4 -0
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/mapping.d.ts +4 -0
- package/lib/esm/src/misc/mapping.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -6,8 +6,8 @@ var React = require('react');
|
|
|
6
6
|
var react = require('@xyflow/react');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var react$1 = require('@phosphor-icons/react');
|
|
9
|
-
var isEqual = require('lodash/isEqual');
|
|
10
9
|
var cx = require('classnames');
|
|
10
|
+
var isEqual = require('lodash/isEqual');
|
|
11
11
|
|
|
12
12
|
class DefaultUIExtensionRegistry {
|
|
13
13
|
constructor() {
|
|
@@ -1122,8 +1122,10 @@ function toReactFlow(def, positions, registry, opts) {
|
|
|
1122
1122
|
const HEADER_SIZE = NODE_HEADER_HEIGHT_PX;
|
|
1123
1123
|
const ROW_SIZE = NODE_ROW_HEIGHT_PX;
|
|
1124
1124
|
const maxRows = Math.max(inputHandles.length, outputHandles.length);
|
|
1125
|
-
|
|
1126
|
-
const
|
|
1125
|
+
// Allow external override to dictate initial size
|
|
1126
|
+
const overrideSize = opts.getDefaultNodeSize?.(n.typeId);
|
|
1127
|
+
const initialWidth = overrideSize?.width ?? (opts.showValues ? 320 : 240);
|
|
1128
|
+
const initialHeight = overrideSize?.height ?? HEADER_SIZE + maxRows * ROW_SIZE;
|
|
1127
1129
|
// Precompute handle bounds so edges can render immediately without waiting for measurement
|
|
1128
1130
|
const handles = [
|
|
1129
1131
|
// Inputs on the left as targets
|
|
@@ -1392,8 +1394,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, children, }) {
|
|
|
1392
1394
|
layers.push(layer);
|
|
1393
1395
|
q.splice(0, q.length, ...next);
|
|
1394
1396
|
}
|
|
1395
|
-
const X =
|
|
1396
|
-
const Y =
|
|
1397
|
+
const X = 720;
|
|
1398
|
+
const Y = 600;
|
|
1397
1399
|
const pos = {};
|
|
1398
1400
|
layers.forEach((layer, layerIndex) => {
|
|
1399
1401
|
layer.forEach((id, itemIndex) => {
|
|
@@ -1987,7 +1989,7 @@ function NodeHandles({ data, isConnectable, inputClassName = "!w-2 !h-2 !bg-gray
|
|
|
1987
1989
|
const y = placed?.y;
|
|
1988
1990
|
const cls = getClassName?.({ kind: "output", id: h.id, type: "source" }) ??
|
|
1989
1991
|
outputClassName;
|
|
1990
|
-
return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(react.Handle, { id: h.id, type: "source", position: position, isConnectable: isConnectable, className: cls
|
|
1992
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(react.Handle, { id: h.id, type: "source", position: position, isConnectable: isConnectable, className: `${cls} wb-nodrag wb-nowheel`, style: y !== undefined ? { top: y } : undefined }), renderLabel && (jsxRuntime.jsx("div", { className: labelClassName + " right-2", style: {
|
|
1991
1993
|
top: (y ?? 0) - 8,
|
|
1992
1994
|
left: "50%",
|
|
1993
1995
|
textAlign: "right",
|
|
@@ -2000,7 +2002,7 @@ function NodeHandles({ data, isConnectable, inputClassName = "!w-2 !h-2 !bg-gray
|
|
|
2000
2002
|
|
|
2001
2003
|
const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConnectable, }) {
|
|
2002
2004
|
const updateNodeInternals = react.useUpdateNodeInternals();
|
|
2003
|
-
const { typeId, showValues
|
|
2005
|
+
const { typeId, showValues } = data;
|
|
2004
2006
|
const inputEntries = data.inputHandles ?? [];
|
|
2005
2007
|
const outputEntries = data.outputHandles ?? [];
|
|
2006
2008
|
React.useEffect(() => {
|
|
@@ -2018,14 +2020,11 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
|
|
|
2018
2020
|
outputs: [],
|
|
2019
2021
|
issues: [],
|
|
2020
2022
|
};
|
|
2021
|
-
const hasError = !!status.lastError;
|
|
2022
|
-
const isRunning = !!status.activeRuns;
|
|
2023
2023
|
const containerBorder = getNodeBorderClassNames({
|
|
2024
2024
|
selected,
|
|
2025
2025
|
status,
|
|
2026
2026
|
validation,
|
|
2027
2027
|
});
|
|
2028
|
-
const pct = Math.round(Math.max(0, Math.min(1, Number(status.progress) || 0)) * 100);
|
|
2029
2028
|
return (jsxRuntime.jsxs("div", { className: cx("rounded-lg bg-white/70 !dark:bg-stone-900", containerBorder), style: {
|
|
2030
2029
|
position: "relative",
|
|
2031
2030
|
minWidth: typeof data.renderWidth === "number" ? data.renderWidth : undefined,
|
|
@@ -2033,11 +2032,24 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
|
|
|
2033
2032
|
}, children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-center px-2 border-b border-solid border-gray-500 dark:border-gray-400 text-gray-600 dark:text-gray-300", style: {
|
|
2034
2033
|
maxHeight: NODE_HEADER_HEIGHT_PX,
|
|
2035
2034
|
minHeight: NODE_HEADER_HEIGHT_PX,
|
|
2036
|
-
}, children: [jsxRuntime.jsx("strong", { className: "flex-1 h-full text-sm", style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` }, children: typeId }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2035
|
+
}, children: [jsxRuntime.jsx("strong", { className: "flex-1 h-full text-sm", style: { lineHeight: `${NODE_HEADER_HEIGHT_PX}px` }, children: typeId }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [validation.issues && validation.issues.length > 0 && (jsxRuntime.jsx(IssueBadge, { level: validation.issues.some((i) => i.level === "error")
|
|
2037
2036
|
? "error"
|
|
2038
2037
|
: "warning", size: 12, className: "w-3 h-3", title: validation.issues
|
|
2039
2038
|
.map((v) => `${v.code}: ${v.message}`)
|
|
2040
|
-
.join("; ") })), jsxRuntime.jsxs("span", { className: "text-[10px] opacity-70", children: ["(", id, ")"] })] })] }), jsxRuntime.jsx(
|
|
2039
|
+
.join("; ") })), jsxRuntime.jsxs("span", { className: "text-[10px] opacity-70", children: ["(", id, ")"] })] })] }), jsxRuntime.jsx(DefaultNodeContent, { data: data, isConnectable: isConnectable })] }));
|
|
2040
|
+
});
|
|
2041
|
+
DefaultNode.displayName = "DefaultNode";
|
|
2042
|
+
function DefaultNodeContent({ data, isConnectable, }) {
|
|
2043
|
+
const { showValues, inputValues, outputValues, toString } = data;
|
|
2044
|
+
const inputEntries = data.inputHandles ?? [];
|
|
2045
|
+
const outputEntries = data.outputHandles ?? [];
|
|
2046
|
+
const status = data.status ?? { activeRuns: 0 };
|
|
2047
|
+
const validation = data.validation ?? {
|
|
2048
|
+
inputs: [],
|
|
2049
|
+
outputs: []};
|
|
2050
|
+
const isRunning = !!status.activeRuns;
|
|
2051
|
+
const pct = Math.round(Math.max(0, Math.min(1, Number(status.progress) || 0)) * 100);
|
|
2052
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: cx("h-px", (isRunning || pct > 0) && "bg-blue-200 dark:bg-blue-900"), children: jsxRuntime.jsx("div", { className: cx("h-px transition-all", (isRunning || pct > 0) && "bg-blue-500"), style: { width: isRunning || pct > 0 ? `${pct}%` : 0 } }) }), jsxRuntime.jsx(NodeHandles, { data: data, isConnectable: isConnectable, getClassName: ({ kind, id }) => {
|
|
2041
2053
|
const vIssues = (kind === "input" ? validation.inputs : validation.outputs).filter((v) => v.handle === id);
|
|
2042
2054
|
const hasAny = vIssues.length > 0;
|
|
2043
2055
|
const hasErr = vIssues.some((v) => v.level === "error");
|
|
@@ -2053,7 +2065,6 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
|
|
|
2053
2065
|
const title = vIssues
|
|
2054
2066
|
.map((v) => `${v.code}: ${v.message}`)
|
|
2055
2067
|
.join("; ");
|
|
2056
|
-
// Compose label with truncated value to prevent layout growth
|
|
2057
2068
|
const valueText = (() => {
|
|
2058
2069
|
if (!showValues)
|
|
2059
2070
|
return undefined;
|
|
@@ -2067,8 +2078,7 @@ const DefaultNode = React.memo(function DefaultNode({ id, data, selected, isConn
|
|
|
2067
2078
|
})();
|
|
2068
2079
|
return (jsxRuntime.jsxs("span", { className: "flex items-center gap-1 w-full", children: [kind === "output" ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [valueText !== undefined && (jsxRuntime.jsx("span", { className: "opacity-60 truncate pl-1", style: { flex: 1, minWidth: 0, maxWidth: "100%" }, children: valueText })), jsxRuntime.jsx("span", { className: "truncate shrink-0", style: { maxWidth: "40%" }, children: id })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "truncate shrink-0", style: { maxWidth: "40%" }, children: id }), valueText !== undefined && (jsxRuntime.jsx("span", { className: "opacity-60 truncate pr-1", style: { flex: 1, minWidth: 0, maxWidth: "100%" }, children: valueText }))] })), hasAny && (jsxRuntime.jsx(IssueBadge, { level: hasErr ? "error" : "warning", size: 12, className: "shrink-0", title: title }))] }));
|
|
2069
2080
|
} })] }));
|
|
2070
|
-
}
|
|
2071
|
-
DefaultNode.displayName = "DefaultNode";
|
|
2081
|
+
}
|
|
2072
2082
|
|
|
2073
2083
|
function DefaultContextMenu({ open, clientPos, onAdd, onClose, }) {
|
|
2074
2084
|
const { registry } = useWorkbenchContext();
|
|
@@ -2227,7 +2237,7 @@ function NodeContextMenu({ open, clientPos, nodeId, onClose, }) {
|
|
|
2227
2237
|
}, children: [jsxRuntime.jsxs("div", { className: "px-2 py-1 font-semibold text-gray-700", children: ["Node (", nodeId, ")"] }), jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleDelete, children: "Delete" }), jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleDuplicate, children: "Duplicate" }), canRunPull && (jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleRunPull, children: "Run (pull)" })), jsxRuntime.jsx("div", { className: "h-px bg-gray-200 my-1" }), jsxRuntime.jsx("button", { className: "block w-full text-left px-2 py-1 hover:bg-gray-100", onClick: handleCopyId, children: "Copy Node ID" })] }));
|
|
2228
2238
|
}
|
|
2229
2239
|
|
|
2230
|
-
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, ref) => {
|
|
2240
|
+
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
|
|
2231
2241
|
const { wb, registry, inputsMap, outputsMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, } = useWorkbenchContext();
|
|
2232
2242
|
const nodeValidation = validationByNode;
|
|
2233
2243
|
const edgeValidation = validationByEdge.errors;
|
|
@@ -2330,6 +2340,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, r
|
|
|
2330
2340
|
edgeValidation,
|
|
2331
2341
|
selectedNodeIds: new Set(sel.nodes),
|
|
2332
2342
|
selectedEdgeIds: new Set(sel.edges),
|
|
2343
|
+
getDefaultNodeSize,
|
|
2333
2344
|
});
|
|
2334
2345
|
// Retain references for unchanged items
|
|
2335
2346
|
const stableNodes = retainStabilityById(prevNodesRef.current, out.nodes, isSameNode);
|
|
@@ -2456,7 +2467,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement }, r
|
|
|
2456
2467
|
const addNodeAt = (typeId, pos) => {
|
|
2457
2468
|
wb.addNode({ typeId, position: pos });
|
|
2458
2469
|
};
|
|
2459
|
-
return (jsxRuntime.jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxRuntime.jsxs(react.ReactFlow, { nodes: throttled.nodes, edges: throttled.edges, nodeTypes: nodeTypes, onlyRenderVisibleElements: true, selectionOnDrag: true, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, deleteKeyCode: ["Backspace", "Delete"],
|
|
2470
|
+
return (jsxRuntime.jsx("div", { className: "w-full h-full", onContextMenu: onContextMenu, children: jsxRuntime.jsx(react.ReactFlowProvider, { children: jsxRuntime.jsxs(react.ReactFlow, { nodes: throttled.nodes, edges: throttled.edges, nodeTypes: nodeTypes, onlyRenderVisibleElements: true, selectionOnDrag: true, onInit: (inst) => (rfInstanceRef.current = inst), onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", fitView: true, children: [jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Dots, gap: 12, size: 1 }), jsxRuntime.jsx(react.MiniMap, {}), jsxRuntime.jsx(react.Controls, {}), jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, onAdd: addNodeAt, onClose: () => setMenuOpen(false) }), jsxRuntime.jsx(NodeContextMenu, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, onClose: () => setNodeMenuOpen(false) })] }) }) }));
|
|
2460
2471
|
});
|
|
2461
2472
|
|
|
2462
2473
|
function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
@@ -2910,7 +2921,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2910
2921
|
catch (err) {
|
|
2911
2922
|
alert(String(err?.message ?? err));
|
|
2912
2923
|
}
|
|
2913
|
-
}, disabled: !engine, children: "Start" })), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: runAutoLayout, children: "Auto Layout" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: downloadGraph, children: "Download Graph" }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Debug events" })] }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Show values in nodes" })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement, contextPanel: overrides?.contextPanel })] })] }));
|
|
2924
|
+
}, disabled: !engine, children: "Start" })), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: runAutoLayout, children: "Auto Layout" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: downloadGraph, children: "Download Graph" }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Debug events" })] }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Show values in nodes" })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement, getDefaultNodeSize: overrides?.getDefaultNodeSize }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement, contextPanel: overrides?.contextPanel })] })] }));
|
|
2914
2925
|
}
|
|
2915
2926
|
function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, onInit, onChange, }) {
|
|
2916
2927
|
const [registry, setRegistry] = React.useState(sparkGraph.createSimpleGraphRegistry());
|
|
@@ -2942,6 +2953,8 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
|
|
|
2942
2953
|
|
|
2943
2954
|
exports.AbstractWorkbench = AbstractWorkbench;
|
|
2944
2955
|
exports.CLIWorkbench = CLIWorkbench;
|
|
2956
|
+
exports.DefaultNode = DefaultNode;
|
|
2957
|
+
exports.DefaultNodeContent = DefaultNodeContent;
|
|
2945
2958
|
exports.DefaultUIExtensionRegistry = DefaultUIExtensionRegistry;
|
|
2946
2959
|
exports.InMemoryWorkbench = InMemoryWorkbench;
|
|
2947
2960
|
exports.Inspector = Inspector;
|