@bian-womp/spark-workbench 0.2.86 → 0.2.88

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 CHANGED
@@ -2190,19 +2190,26 @@ function createHandleLayout(args) {
2190
2190
  };
2191
2191
  }
2192
2192
  function layoutNode(args, overrides) {
2193
- const { node, registry, showValues, overrides: sizeOverrides } = args;
2193
+ const { node, registry, showValues, overrides: sizeOverrides, missingInputs = [], missingOutputs = [], } = args;
2194
2194
  const { inputs, outputs } = computeEffectiveHandles(node, registry);
2195
2195
  const inputOrder = Object.keys(inputs).filter((k) => !sparkGraph.isInputPrivate(inputs, k));
2196
2196
  const outputOrder = Object.keys(outputs);
2197
2197
  const estimateNodeSizeFn = overrides?.estimateNodeSize ?? estimateNodeSize;
2198
2198
  const createHandleBoundsFn = overrides?.createHandleBounds ?? createHandleBounds;
2199
2199
  const createHandleLayoutFn = overrides?.createHandleLayout ?? createHandleLayout;
2200
- const { width, height } = estimateNodeSizeFn({
2200
+ // Calculate base dimensions
2201
+ const baseRows = Math.max(inputOrder.length, outputOrder.length);
2202
+ const { width: baseWidth, height: baseHeight } = estimateNodeSizeFn({
2201
2203
  node,
2202
2204
  registry,
2203
2205
  showValues,
2204
2206
  overrides: sizeOverrides,
2205
2207
  });
2208
+ // Calculate final dimensions accounting for missing handles
2209
+ const finalRows = Math.max(inputOrder.length + missingInputs.length, outputOrder.length + missingOutputs.length);
2210
+ const width = baseWidth;
2211
+ const height = baseHeight + Math.max(0, finalRows - baseRows) * NODE_ROW_HEIGHT_PX;
2212
+ // Create bounds and layouts for regular handles
2206
2213
  const handles = [
2207
2214
  ...inputOrder.map((id, i) => createHandleBoundsFn({
2208
2215
  id,
@@ -2233,7 +2240,51 @@ function layoutNode(args, overrides) {
2233
2240
  rowIndex: i,
2234
2241
  })),
2235
2242
  ];
2236
- return { width, height, inputOrder, outputOrder, handles, handleLayout };
2243
+ // Create bounds and layouts for missing handles
2244
+ const missingHandleBounds = [
2245
+ ...missingInputs.map((id, i) => createHandleBoundsFn({
2246
+ id,
2247
+ type: "target",
2248
+ position: react.Position.Left,
2249
+ rowIndex: inputOrder.length + i,
2250
+ nodeWidth: width,
2251
+ })),
2252
+ ...missingOutputs.map((id, i) => createHandleBoundsFn({
2253
+ id,
2254
+ type: "source",
2255
+ position: react.Position.Right,
2256
+ rowIndex: outputOrder.length + i,
2257
+ nodeWidth: width,
2258
+ })),
2259
+ ];
2260
+ const missingHandleLayout = [
2261
+ ...missingInputs.map((id, i) => ({
2262
+ ...createHandleLayoutFn({
2263
+ id,
2264
+ type: "target",
2265
+ position: react.Position.Left,
2266
+ rowIndex: inputOrder.length + i,
2267
+ }),
2268
+ missing: true,
2269
+ })),
2270
+ ...missingOutputs.map((id, i) => ({
2271
+ ...createHandleLayoutFn({
2272
+ id,
2273
+ type: "source",
2274
+ position: react.Position.Right,
2275
+ rowIndex: outputOrder.length + i,
2276
+ }),
2277
+ missing: true,
2278
+ })),
2279
+ ];
2280
+ return {
2281
+ width,
2282
+ height,
2283
+ inputOrder,
2284
+ outputOrder,
2285
+ handles: [...handles, ...missingHandleBounds],
2286
+ handleLayout: [...handleLayout, ...missingHandleLayout],
2287
+ };
2237
2288
  }
2238
2289
 
2239
2290
  function useWorkbenchBridge(wb) {
@@ -2505,10 +2556,13 @@ function toReactFlow(def, positions, sizes, registry, opts) {
2505
2556
  const EDGE_STYLE_MISSING = { stroke: "#f59e0b", strokeWidth: 2 }; // amber-500
2506
2557
  const EDGE_STYLE_ERROR = { stroke: "#ef4444", strokeWidth: 2 };
2507
2558
  const EDGE_STYLE_RUNNING = { stroke: "#3b82f6" };
2508
- // Build a map of valid handles per node up-front
2559
+ // Build a map of valid handles per node up-front and cache handle data
2509
2560
  const validHandleMap = {};
2561
+ const nodeHandlesCache = {};
2510
2562
  for (const n of def.nodes) {
2511
- const { inputs, outputs } = computeEffectiveHandles(n, registry);
2563
+ const handles = computeEffectiveHandles(n, registry);
2564
+ nodeHandlesCache[n.nodeId] = handles;
2565
+ const { inputs, outputs } = handles;
2512
2566
  const inputOrder = Object.keys(inputs).filter((k) => !sparkGraph.isInputPrivate(inputs, k));
2513
2567
  const outputOrder = Object.keys(outputs);
2514
2568
  validHandleMap[n.nodeId] = {
@@ -2537,87 +2591,36 @@ function toReactFlow(def, positions, sizes, registry, opts) {
2537
2591
  (missingOutputsByNode[srcId] || (missingOutputsByNode[srcId] = new Set())).add(srcHandle);
2538
2592
  }
2539
2593
  }
2540
- // This map is still used later for certain checks; align with valid handles
2541
- const nodeHandleMap = {};
2542
- Object.assign(nodeHandleMap, validHandleMap);
2543
2594
  // Get layout function overrides from UI registry
2544
2595
  const layoutNodeOverride = opts.ui?.getLayoutNode() ?? layoutNode;
2545
2596
  const createHandleBoundsFn = opts.ui?.getCreateHandleBounds() ?? createHandleBounds;
2546
2597
  const createHandleLayoutFn = opts.ui?.getCreateHandleLayout() ?? createHandleLayout;
2547
2598
  const estimateNodeSizeFn = opts.ui?.getEstimateNodeSize() ?? estimateNodeSize;
2548
- const computeLayout = (node, overrides) => {
2599
+ const computeLayout = (node, overrides, missingInputs, missingOutputs) => {
2549
2600
  return layoutNodeOverride
2550
2601
  ? layoutNodeOverride({
2551
2602
  node,
2552
2603
  registry,
2553
2604
  showValues: opts.showValues,
2554
2605
  overrides,
2606
+ missingInputs,
2607
+ missingOutputs,
2555
2608
  })
2556
2609
  : layoutNode({
2557
2610
  node,
2558
2611
  registry,
2559
2612
  showValues: opts.showValues,
2560
2613
  overrides,
2614
+ missingInputs,
2615
+ missingOutputs,
2561
2616
  }, {
2562
2617
  estimateNodeSize: estimateNodeSizeFn,
2563
2618
  createHandleBounds: createHandleBoundsFn,
2564
2619
  createHandleLayout: createHandleLayoutFn,
2565
2620
  });
2566
2621
  };
2567
- const calculateDimensionsWithMissingHandles = (geom, extraInputs, extraOutputs) => {
2568
- const baseLeftCount = geom.inputOrder.length;
2569
- const baseRightCount = geom.outputOrder.length;
2570
- const baseRows = Math.max(baseLeftCount, baseRightCount);
2571
- const newRows = Math.max(baseLeftCount + extraInputs.length, baseRightCount + extraOutputs.length);
2572
- return {
2573
- baseLeftCount,
2574
- baseRightCount,
2575
- baseRows,
2576
- newRows,
2577
- width: geom.width,
2578
- height: geom.height + Math.max(0, newRows - baseRows) * NODE_ROW_HEIGHT_PX,
2579
- };
2580
- };
2581
- const createMissingHandleLayouts = (extraInputs, extraOutputs, baseLeftCount, baseRightCount) => {
2582
- const left = extraInputs.map((id, i) => ({
2583
- ...createHandleLayoutFn({
2584
- id,
2585
- type: "target",
2586
- position: react.Position.Left,
2587
- rowIndex: baseLeftCount + i,
2588
- }),
2589
- missing: true,
2590
- }));
2591
- const right = extraOutputs.map((id, i) => ({
2592
- ...createHandleLayoutFn({
2593
- id,
2594
- type: "source",
2595
- position: react.Position.Right,
2596
- rowIndex: baseRightCount + i,
2597
- }),
2598
- missing: true,
2599
- }));
2600
- return [...left, ...right];
2601
- };
2602
- const createMissingHandleBounds = (extraInputs, extraOutputs, baseLeftCount, baseRightCount, nodeWidth) => {
2603
- const left = extraInputs.map((id, i) => createHandleBoundsFn({
2604
- id,
2605
- type: "target",
2606
- position: react.Position.Left,
2607
- rowIndex: baseLeftCount + i,
2608
- nodeWidth,
2609
- }));
2610
- const right = extraOutputs.map((id, i) => createHandleBoundsFn({
2611
- id,
2612
- type: "source",
2613
- position: react.Position.Right,
2614
- rowIndex: baseRightCount + i,
2615
- nodeWidth,
2616
- }));
2617
- return [...left, ...right];
2618
- };
2619
2622
  const nodes = def.nodes.map((n) => {
2620
- const { inputs: inputSource, outputs: outputSource } = computeEffectiveHandles(n, registry);
2623
+ const { inputs: inputSource, outputs: outputSource } = nodeHandlesCache[n.nodeId];
2621
2624
  const overrideSize = opts.getDefaultNodeSize?.(n.typeId);
2622
2625
  const customSize = sizes?.[n.nodeId];
2623
2626
  const sizeOverrides = customSize
@@ -2625,14 +2628,12 @@ function toReactFlow(def, positions, sizes, registry, opts) {
2625
2628
  : overrideSize;
2626
2629
  const extraInputs = Array.from(missingInputsByNode[n.nodeId] || []);
2627
2630
  const extraOutputs = Array.from(missingOutputsByNode[n.nodeId] || []);
2628
- const geom = computeLayout(n, sizeOverrides);
2629
- const finalDims = calculateDimensionsWithMissingHandles(geom, extraInputs, extraOutputs);
2630
- const renderWidth = customSize?.width ?? finalDims.width;
2631
- const renderHeight = customSize?.height ?? finalDims.height;
2632
- const initialGeom = customSize ? computeLayout(n, overrideSize) : geom;
2633
- const initialDims = customSize
2634
- ? calculateDimensionsWithMissingHandles(initialGeom, extraInputs, extraOutputs)
2635
- : finalDims;
2631
+ const geom = computeLayout(n, sizeOverrides, extraInputs, extraOutputs);
2632
+ const renderWidth = customSize?.width ?? geom.width;
2633
+ const renderHeight = customSize?.height ?? geom.height;
2634
+ const initialGeom = customSize
2635
+ ? computeLayout(n, overrideSize, extraInputs, extraOutputs)
2636
+ : geom;
2636
2637
  const inputHandles = geom.inputOrder.map((id) => ({
2637
2638
  id,
2638
2639
  typeId: sparkGraph.getInputTypeId(inputSource, id),
@@ -2641,14 +2642,8 @@ function toReactFlow(def, positions, sizes, registry, opts) {
2641
2642
  id,
2642
2643
  typeId: formatDeclaredTypeSignature(outputSource[id]),
2643
2644
  }));
2644
- nodeHandleMap[n.nodeId] = {
2645
- inputs: new Set(inputHandles.map((h) => h.id)),
2646
- outputs: new Set(outputHandles.map((h) => h.id)),
2647
- };
2648
- const missingHandleLayouts = createMissingHandleLayouts(extraInputs, extraOutputs, finalDims.baseLeftCount, finalDims.baseRightCount);
2649
- const handleLayout = [...geom.handleLayout, ...missingHandleLayouts];
2650
- const missingHandleBounds = createMissingHandleBounds(extraInputs, extraOutputs, finalDims.baseLeftCount, finalDims.baseRightCount, renderWidth);
2651
- const handles = [...geom.handles, ...missingHandleBounds];
2645
+ const handleLayout = geom.handleLayout;
2646
+ const handles = geom.handles;
2652
2647
  return {
2653
2648
  id: n.nodeId,
2654
2649
  data: {
@@ -2664,8 +2659,8 @@ function toReactFlow(def, positions, sizes, registry, opts) {
2664
2659
  showValues: opts.showValues,
2665
2660
  renderWidth,
2666
2661
  renderHeight,
2667
- initialWidth: initialDims.width,
2668
- initialHeight: initialDims.height,
2662
+ initialWidth: initialGeom.width,
2663
+ initialHeight: initialGeom.height,
2669
2664
  inputValues: opts.inputs?.[n.nodeId],
2670
2665
  inputDefaults: opts.inputDefaults?.[n.nodeId],
2671
2666
  outputValues: opts.outputs?.[n.nodeId],