@elicdavis/node-flow 0.2.2 → 0.2.4

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/dist/index.js CHANGED
@@ -58,12 +58,15 @@ __export(index_exports, {
58
58
  formatNumber: () => formatNumber,
59
59
  onThemeChange: () => onThemeChange,
60
60
  portConfigTypes: () => portConfigTypes,
61
+ portTypeColor: () => portTypeColor,
61
62
  portsCompatible: () => portsCompatible,
63
+ portsConnect: () => portsConnect,
62
64
  renderContinuously: () => renderContinuously,
63
65
  requestRender: () => requestRender,
64
66
  setTheme: () => setTheme,
65
67
  themeVersion: () => themeVersion,
66
68
  typeSetsCompatible: () => typeSetsCompatible,
69
+ typeSetsConnect: () => typeSetsConnect,
67
70
  widgetFont: () => widgetFont
68
71
  });
69
72
  module.exports = __toCommonJS(index_exports);
@@ -125,7 +128,8 @@ var defaults = {
125
128
  Idle: "#1c1c1c",
126
129
  MouseOver: "#8e8e8e",
127
130
  Grabbed: "white",
128
- Selected: "#6e6e6e"
131
+ Selected: "#6e6e6e",
132
+ Highlighted: "#ffc95c"
129
133
  },
130
134
  Bevel: null,
131
135
  Port: {
@@ -212,6 +216,7 @@ var defaults = {
212
216
  H3: {
213
217
  FontSize: 16
214
218
  },
219
+ CodeFontFamily: null,
215
220
  CodeBlock: {
216
221
  BackgroundColor: "#0c2b35",
217
222
  FontColor: "#afb9bb",
@@ -661,11 +666,11 @@ var ContextMenu = class _ContextMenu {
661
666
  #tempBox = { Position: Zero(), Size: Zero() };
662
667
  #openSubMenu;
663
668
  #bounds = null;
664
- #contains(point) {
669
+ contains(point) {
665
670
  if (this.#bounds !== null && InBox(this.#bounds, point)) {
666
671
  return true;
667
672
  }
668
- return this.#openSubMenu !== void 0 && this.#openSubMenu.#contains(point);
673
+ return this.#openSubMenu !== void 0 && this.#openSubMenu.contains(point);
669
674
  }
670
675
  /**
671
676
  * A submenu is anchored to its parent's left edge and told the parent's
@@ -708,7 +713,7 @@ var ContextMenu = class _ContextMenu {
708
713
  Position: { x: position.x, y: position.y },
709
714
  Size: { x: scaledEntryWidth, y: totalScaledHeight }
710
715
  };
711
- const pointer = mousePosition !== void 0 && this.#openSubMenu !== void 0 && this.#openSubMenu.#contains(mousePosition) ? void 0 : mousePosition;
716
+ const pointer = mousePosition !== void 0 && this.#openSubMenu !== void 0 && this.#openSubMenu.contains(mousePosition) ? void 0 : mousePosition;
712
717
  this.#tempBox.Size.x = scaledEntryWidth;
713
718
  this.#tempBox.Size.y = scaledEntryHeight;
714
719
  CopyVector2(this.#tempBox.Position, position);
@@ -818,12 +823,14 @@ var MouseObserver = class {
818
823
  #clickStop;
819
824
  #contextMenu;
820
825
  #zoomCallback;
826
+ #leaveCallback;
827
+ #inside = false;
821
828
  #longPressTimer = null;
822
829
  #longPressOrigin = Zero();
823
830
  #longPressFired = false;
824
831
  #pinchDist = 0;
825
832
  #lastTouchAt = 0;
826
- constructor(ele, dragCallback, moveCallback, clickStart, clickStop, contextMenu, fileDrop, zoomCallback) {
833
+ constructor(ele, dragCallback, moveCallback, clickStart, clickStop, contextMenu, fileDrop, zoomCallback, leaveCallback) {
827
834
  this.#ele = ele;
828
835
  this.#dragCallback = dragCallback;
829
836
  this.#moveCallback = moveCallback;
@@ -831,6 +838,7 @@ var MouseObserver = class {
831
838
  this.#clickStop = clickStop;
832
839
  this.#contextMenu = contextMenu;
833
840
  this.#zoomCallback = zoomCallback;
841
+ this.#leaveCallback = leaveCallback;
834
842
  this.#clicked = false;
835
843
  this.#lastTouch = Zero();
836
844
  this.#lastMousePosition = Zero();
@@ -845,6 +853,12 @@ var MouseObserver = class {
845
853
  document.addEventListener("touchend", redraws(this.#touchEnd.bind(this)), false);
846
854
  document.addEventListener("touchcancel", redraws(this.#touchEnd.bind(this)), false);
847
855
  ele.addEventListener("mousemove", redraws(this.#move.bind(this)), false);
856
+ ele.addEventListener("mouseleave", redraws(() => {
857
+ this.#inside = false;
858
+ if (!this.#clicked) {
859
+ this.#leaveCallback?.();
860
+ }
861
+ }), false);
848
862
  ele.addEventListener("touchmove", redraws(this.#touchMove.bind(this)), { passive: false });
849
863
  ele.addEventListener("wheel", redraws(this.#wheel.bind(this)), { passive: false });
850
864
  ele.addEventListener("drop", redraws((ev) => {
@@ -914,6 +928,7 @@ var MouseObserver = class {
914
928
  if (this.#fromTouch()) {
915
929
  return;
916
930
  }
931
+ this.#inside = true;
917
932
  const pos = this.#mousePos(event);
918
933
  if (this.#clicked) {
919
934
  const delta = Zero();
@@ -927,6 +942,7 @@ var MouseObserver = class {
927
942
  if (event.button !== 0 || this.#fromTouch()) {
928
943
  return;
929
944
  }
945
+ this.#inside = true;
930
946
  this.#clicked = true;
931
947
  this.#clickStart(this.#mousePos(event), event.ctrlKey || event.shiftKey);
932
948
  }
@@ -934,8 +950,12 @@ var MouseObserver = class {
934
950
  if (event.button !== 0 || this.#fromTouch()) {
935
951
  return;
936
952
  }
953
+ const wasClicked = this.#clicked;
937
954
  this.#clicked = false;
938
955
  this.#clickStop();
956
+ if (wasClicked && !this.#inside) {
957
+ this.#leaveCallback?.();
958
+ }
939
959
  }
940
960
  #touchStart(event) {
941
961
  this.#lastTouchAt = Date.now();
@@ -1625,6 +1645,18 @@ function typeSetsCompatible(a, b) {
1625
1645
  }
1626
1646
  return a.some((type) => b.includes(type));
1627
1647
  }
1648
+ function portsConnect(output, input, casts) {
1649
+ if (!output || !input) {
1650
+ return false;
1651
+ }
1652
+ return typeSetsConnect(output.acceptedTypes(), input.acceptedTypes(), casts);
1653
+ }
1654
+ function typeSetsConnect(output, input, casts) {
1655
+ if (typeSetsCompatible(output, input)) {
1656
+ return true;
1657
+ }
1658
+ return (casts ?? []).some((cast) => output.includes(cast.from) && input.includes(cast.to));
1659
+ }
1628
1660
  function portConfigTypes(config) {
1629
1661
  if (config.anyType === true) {
1630
1662
  return [];
@@ -1661,6 +1693,9 @@ function fallbackColor(type, s) {
1661
1693
  HSV2RGB(hsv, color);
1662
1694
  return RgbToHex(color);
1663
1695
  }
1696
+ function portTypeColor(type) {
1697
+ return fallbackColor(type, 1);
1698
+ }
1664
1699
  var Port = class {
1665
1700
  #node;
1666
1701
  #displayName;
@@ -1679,6 +1714,7 @@ var Port = class {
1679
1714
  #dataTypePopupElement;
1680
1715
  #onConnectionAdded;
1681
1716
  #onConnectionRemoved;
1717
+ #widget = null;
1682
1718
  constructor(node, portType, config) {
1683
1719
  this.#node = node;
1684
1720
  this.#connections = new Array();
@@ -1829,10 +1865,23 @@ var Port = class {
1829
1865
  this.#visibilityMayHaveChanged(was);
1830
1866
  }
1831
1867
  #visibilityMayHaveChanged(was) {
1832
- if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */) {
1868
+ if (was !== this.hidden() || this.#portType === "INPUTARRAY" /* InputArray */ || this.#widget !== null) {
1833
1869
  this.#node?.invalidateLayout();
1834
1870
  }
1835
1871
  }
1872
+ setWidget(widget) {
1873
+ this.#widget = widget;
1874
+ this.#node?.invalidateLayout();
1875
+ }
1876
+ widget() {
1877
+ return this.#widget;
1878
+ }
1879
+ /**
1880
+ * The widget stands in for a wire, so it leaves once one is connected.
1881
+ */
1882
+ widgetShown() {
1883
+ return this.#widget !== null && this.#portType !== "OUTPUT" /* Output */ && this.#connections.length === 0 && !this.hidden() && !(this.#widget.Hidden?.() ?? false);
1884
+ }
1836
1885
  /**
1837
1886
  * A port asked to hide still shows while anything is connected to it,
1838
1887
  * and while its node is showing its hidden ports.
@@ -3955,11 +4004,10 @@ function TimeExecution(name, callback) {
3955
4004
 
3956
4005
  // src/nodes/publisher.ts
3957
4006
  function offersMatchingPort(config, filter) {
3958
- const ports = filter.needs === "INPUT" /* Input */ ? config.inputs : config.outputs;
3959
- if (ports === void 0) {
3960
- return false;
4007
+ if (filter.needs === "INPUT" /* Input */) {
4008
+ return (config.inputs ?? []).some((port) => typeSetsConnect(filter.types, portConfigTypes(port), filter.casts));
3961
4009
  }
3962
- return ports.some((port) => typeSetsCompatible(portConfigTypes(port), filter.types));
4010
+ return (config.outputs ?? []).some((port) => typeSetsConnect(portConfigTypes(port), filter.types, filter.casts));
3963
4011
  }
3964
4012
  var Publisher = class {
3965
4013
  #name;
@@ -4140,11 +4188,14 @@ var NodeSubsystem2 = class {
4140
4188
  #boxSelectStart_graphSpace;
4141
4189
  #boxSelectEnd_graphSpace;
4142
4190
  #boxSelectionNodes;
4191
+ #casts;
4143
4192
  #lastCtx;
4144
4193
  #lastMousePosition;
4145
4194
  // LISTENERS ==============================================================
4146
4195
  #nodeRemovedCallbacks;
4147
4196
  #registeredNodeAddedCallbacks;
4197
+ #nodeHoverCallbacks = new Array();
4198
+ #hoveredNode = null;
4148
4199
  // ========================================================================
4149
4200
  constructor(postProcessPass, config) {
4150
4201
  this.#postProcessPass = postProcessPass;
@@ -4166,6 +4217,13 @@ var NodeSubsystem2 = class {
4166
4217
  this.#boxSelectEnd_graphSpace = Zero();
4167
4218
  this.#boxSelectionNodes = new List();
4168
4219
  this.#lastCtx = null;
4220
+ this.#casts = config?.casts ?? [];
4221
+ }
4222
+ setCasts(casts) {
4223
+ this.#casts = casts;
4224
+ }
4225
+ casts() {
4226
+ return this.#casts;
4169
4227
  }
4170
4228
  addPublisher(identifier, publisher) {
4171
4229
  this.#nodeFactory.addPublisher(identifier, publisher);
@@ -4188,6 +4246,18 @@ var NodeSubsystem2 = class {
4188
4246
  }
4189
4247
  this.#nodeRemovedCallbacks.push(callback);
4190
4248
  }
4249
+ addNodeHoverListener(callback) {
4250
+ this.#nodeHoverCallbacks.push(callback);
4251
+ }
4252
+ #setHoveredNode(node) {
4253
+ if (this.#hoveredNode === node) {
4254
+ return;
4255
+ }
4256
+ this.#hoveredNode = node;
4257
+ for (let i = 0; i < this.#nodeHoverCallbacks.length; i++) {
4258
+ this.#nodeHoverCallbacks[i](node);
4259
+ }
4260
+ }
4191
4261
  clickStart(mousePosition, camera, ctrlKey) {
4192
4262
  this.#boxSelect = false;
4193
4263
  this.#nodesGrabbed.Clear();
@@ -4407,7 +4477,8 @@ var NodeSubsystem2 = class {
4407
4477
  let firstHidden = -1;
4408
4478
  for (let i = 0; i < count; i++) {
4409
4479
  const port = side === "INPUT" /* Input */ ? node.inputPort(i) : node.outputPort(i);
4410
- if (!portsCompatible(port, against)) {
4480
+ const compatible = side === "INPUT" /* Input */ ? portsConnect(against, port, this.#casts) : portsConnect(port, against, this.#casts);
4481
+ if (!compatible) {
4411
4482
  continue;
4412
4483
  }
4413
4484
  if (!port.hidden()) {
@@ -4464,11 +4535,11 @@ var NodeSubsystem2 = class {
4464
4535
  this.#clearCurrentlySelectedConnection();
4465
4536
  return;
4466
4537
  }
4467
- if (this.#portHovering.InputPort && !portsCompatible(this.#portHovering.Port, conn.outPort())) {
4538
+ if (this.#portHovering.InputPort && !portsConnect(conn.outPort(), this.#portHovering.Port, this.#casts)) {
4468
4539
  this.#clearCurrentlySelectedConnection();
4469
4540
  return;
4470
4541
  }
4471
- if (!this.#portHovering.InputPort && !portsCompatible(this.#portHovering.Port, conn.inPort())) {
4542
+ if (!this.#portHovering.InputPort && !portsConnect(this.#portHovering.Port, conn.inPort(), this.#casts)) {
4472
4543
  this.#clearCurrentlySelectedConnection();
4473
4544
  return;
4474
4545
  }
@@ -4491,7 +4562,7 @@ var NodeSubsystem2 = class {
4491
4562
  connectNodes(nodeOut, outPort, nodeIn, inPort) {
4492
4563
  const from = nodeOut.outputPort(outPort);
4493
4564
  const to = nodeIn.inputPort(inPort);
4494
- if (!portsCompatible(from, to)) {
4565
+ if (!portsConnect(from, to, this.#casts)) {
4495
4566
  console.error("can't connect nodes of different types", from.getDataType(), to.getDataType());
4496
4567
  return;
4497
4568
  }
@@ -4834,6 +4905,7 @@ var NodeSubsystem2 = class {
4834
4905
  this.#widgetHovering = null;
4835
4906
  this.#nodeHovering = -1;
4836
4907
  this.#boxSelectionNodes.Clear();
4908
+ let hovered = null;
4837
4909
  const selectedBox_Screenspace = this.#boxSelectionScreenspaceBox(camera);
4838
4910
  const canvas = {
4839
4911
  Position: { x: 0, y: 0 },
@@ -4847,6 +4919,9 @@ var NodeSubsystem2 = class {
4847
4919
  }
4848
4920
  if (mousePosition !== void 0 && !this.#boxSelect) {
4849
4921
  const intersection = this.#nodes[i].inBounds(ctx, camera, mousePosition);
4922
+ if (intersection.Node !== void 0) {
4923
+ hovered = intersection.Node;
4924
+ }
4850
4925
  if (intersection.Node !== void 0 && intersection.PortIndex === void 0 && intersection.Widget === void 0) {
4851
4926
  state = 1 /* MouseOver */;
4852
4927
  this.#nodeHovering = i;
@@ -4878,6 +4953,7 @@ var NodeSubsystem2 = class {
4878
4953
  }
4879
4954
  this.#nodes[i].render(ctx, camera, state, mousePosition, this.#postProcessPass);
4880
4955
  }
4956
+ this.#setHoveredNode(hovered);
4881
4957
  if (this.#widgetCurrentlyClicking !== null) {
4882
4958
  this.#cursor = this.#widgetCurrentlyClicking.Cursor?.() ?? "pointer" /* Pointer */;
4883
4959
  }
@@ -5183,9 +5259,11 @@ var FlowNode = class {
5183
5259
  #elementSpacing;
5184
5260
  // Runtime ================================================================
5185
5261
  #selected;
5262
+ #highlighted = false;
5186
5263
  #inputPortPositions;
5187
5264
  #outputPortPositions;
5188
5265
  #widgetPositions;
5266
+ #portWidgetPositions = new List();
5189
5267
  #data;
5190
5268
  #registeredAnyPropertyChangeCallbacks;
5191
5269
  #registeredPropertyChangeCallbacks;
@@ -5285,6 +5363,16 @@ var FlowNode = class {
5285
5363
  this.#onSelect[i]();
5286
5364
  }
5287
5365
  }
5366
+ highlighted() {
5367
+ return this.#highlighted;
5368
+ }
5369
+ setHighlighted(highlighted) {
5370
+ if (this.#highlighted === highlighted) {
5371
+ return;
5372
+ }
5373
+ this.#highlighted = highlighted;
5374
+ requestRender();
5375
+ }
5288
5376
  raiseDragStoppedEvent() {
5289
5377
  for (let i = 0; i < this.#onDragStop.length; i++) {
5290
5378
  this.#onDragStop[i](this);
@@ -5673,7 +5761,7 @@ var FlowNode = class {
5673
5761
  }
5674
5762
  this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
5675
5763
  size.y += this.#portRowHeight(port, tempMeasurement.y) + this.#elementSpacing;
5676
- size.x = Math.max(size.x, tempMeasurement.x + doublePadding);
5764
+ size.x = Math.max(size.x, this.#portRowWidth(port, tempMeasurement.x) + doublePadding);
5677
5765
  }
5678
5766
  const widgets = this.#hasHiddenPortsToggle() ? [this.#hiddenPortsToggle, ...this.#widgets] : this.#widgets;
5679
5767
  for (const widget of widgets) {
@@ -5694,6 +5782,9 @@ var FlowNode = class {
5694
5782
  }
5695
5783
  addInput(config) {
5696
5784
  const port = new Port(this, config.array ? "INPUTARRAY" /* InputArray */ : "INPUT" /* Input */, config);
5785
+ if (config.widget !== void 0) {
5786
+ port.setWidget(GlobalWidgetFactory.createFromConfig(this, config.widget));
5787
+ }
5697
5788
  this.#input.push(port);
5698
5789
  return port;
5699
5790
  }
@@ -5819,6 +5910,17 @@ var FlowNode = class {
5819
5910
  intersection.WidgetBox = this.#widgetPositions.At(i);
5820
5911
  }
5821
5912
  }
5913
+ for (let i = 0; i < this.#portWidgetPositions.Count(); i++) {
5914
+ const port = this.#input[i];
5915
+ if (port !== void 0 && port.widgetShown() && InBox(this.#portWidgetPositions.At(i), position)) {
5916
+ intersection.Node = this;
5917
+ intersection.Widget = port.widget();
5918
+ intersection.WidgetBox = this.#portWidgetPositions.At(i);
5919
+ intersection.Port = void 0;
5920
+ intersection.PortIndex = void 0;
5921
+ intersection.PortIsInput = void 0;
5922
+ }
5923
+ }
5822
5924
  return intersection;
5823
5925
  }
5824
5926
  canEditTitle() {
@@ -5933,7 +6035,14 @@ var FlowNode = class {
5933
6035
  }
5934
6036
  #portRowHeight(port, textHeight) {
5935
6037
  const slots = port.slots();
5936
- return slots > 1 ? Math.max(textHeight, slots * ARRAY_SLOT_PITCH) : textHeight;
6038
+ const widget = port.widgetShown() ? port.widget().Size().y : 0;
6039
+ return Math.max(slots > 1 ? slots * ARRAY_SLOT_PITCH : 0, textHeight, widget);
6040
+ }
6041
+ #portRowWidth(port, textWidth) {
6042
+ if (!port.widgetShown()) {
6043
+ return textWidth;
6044
+ }
6045
+ return textWidth + this.#elementSpacing + port.widget().Size().x;
5937
6046
  }
5938
6047
  hasBeenLaidOut() {
5939
6048
  return this.#laidOut;
@@ -5955,11 +6064,28 @@ var FlowNode = class {
5955
6064
  this.#inputPortPositions.Clear();
5956
6065
  this.#outputPortPositions.Clear();
5957
6066
  this.#widgetPositions.Clear();
6067
+ this.#portWidgetPositions.Clear();
5958
6068
  const scaledPadding = this.#padding * camera.zoom;
5959
6069
  const scaledElementSpacing = this.#elementSpacing * camera.zoom;
5960
6070
  const nodeBounds = this.calculateBounds(ctx, camera);
5961
6071
  const nodeStyle = this.#calculateStyle(state);
5962
6072
  nodeStyle.Draw(ctx, nodeBounds, camera.zoom);
6073
+ if (this.#highlighted) {
6074
+ const gap = 3;
6075
+ ctx.save();
6076
+ ctx.strokeStyle = Theme.Node.Border.Highlighted;
6077
+ ctx.lineWidth = 2;
6078
+ ctx.beginPath();
6079
+ ctx.roundRect(
6080
+ nodeBounds.Position.x - gap,
6081
+ nodeBounds.Position.y - gap,
6082
+ nodeBounds.Size.x + gap * 2,
6083
+ nodeBounds.Size.y + gap * 2,
6084
+ nodeStyle.radius() * camera.zoom + gap
6085
+ );
6086
+ ctx.stroke();
6087
+ ctx.restore();
6088
+ }
5963
6089
  const borderSize = nodeStyle.borderSize();
5964
6090
  ctx.textAlign = "center" /* Center */;
5965
6091
  ctx.textBaseline = "middle" /* Middle */;
@@ -6049,6 +6175,7 @@ var FlowNode = class {
6049
6175
  const port = this.#input[i];
6050
6176
  if (port.hidden()) {
6051
6177
  this.#inputPortPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
6178
+ this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
6052
6179
  continue;
6053
6180
  }
6054
6181
  this.#portTextStyle.measure(ctx, 1, port.getDisplayName(), tempMeasurement);
@@ -6058,6 +6185,19 @@ var FlowNode = class {
6058
6185
  position.y = startY + portHeight / 2;
6059
6186
  this.#portTextStyle.setupStyle(ctx, camera.zoom);
6060
6187
  ctx.fillText(port.getDisplayName(), leftSide, position.y);
6188
+ if (port.widgetShown()) {
6189
+ const widget = port.widget();
6190
+ const widgetHeight = widget.Size().y * camera.zoom;
6191
+ const widgetLeft = leftSide + tempMeasurement.x * camera.zoom + scaledElementSpacing;
6192
+ const box = {
6193
+ Position: { x: widgetLeft, y: startY + (portHeight - widgetHeight) / 2 },
6194
+ Size: { x: nodeBounds.Position.x + nodeBounds.Size.x - scaledPadding - widgetLeft, y: widgetHeight }
6195
+ };
6196
+ widget.Draw(ctx, box, camera.zoom, mousePosition);
6197
+ this.#portWidgetPositions.Push(box);
6198
+ } else {
6199
+ this.#portWidgetPositions.Push({ Position: { x: nodeBounds.Position.x, y: startY }, Size: { x: 0, y: 0 } });
6200
+ }
6061
6201
  this.#inputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
6062
6202
  startY += portHeight + scaledElementSpacing;
6063
6203
  }
@@ -6143,6 +6283,7 @@ var FlowNode = class {
6143
6283
  return false;
6144
6284
  }
6145
6285
  this.#widgetPositions.Clear();
6286
+ this.#portWidgetPositions.Clear();
6146
6287
  this.#hiddenPortsTogglePosition = null;
6147
6288
  return true;
6148
6289
  }
@@ -6650,7 +6791,7 @@ var MarkdownSyntaxParser = class {
6650
6791
  content += token.lexeme();
6651
6792
  this.#inc();
6652
6793
  }
6653
- return [new Text(content, { font: "monospace" })];
6794
+ return [new Text(content, { font: Theme.Note.CodeFontFamily ?? "monospace" })];
6654
6795
  }
6655
6796
  #text() {
6656
6797
  let contents = new Array();
@@ -6764,7 +6905,7 @@ var MarkdownSyntaxParser = class {
6764
6905
  this.#inc();
6765
6906
  this.#inc();
6766
6907
  const codeBlockText = this.#originalText.substring(start, end).replace(/\r?\n$/, "");
6767
- const entryText = new Text(codeBlockText);
6908
+ const entryText = new Text(codeBlockText, { font: Theme.Note.CodeFontFamily ?? void 0 });
6768
6909
  this.#assignStandardStyling([entryText]);
6769
6910
  entryText.setColor(Theme.Note.CodeBlock.FontColor);
6770
6911
  return new CodeBlockEntry(entryText);
@@ -7526,8 +7667,16 @@ var QuickMenu = class {
7526
7667
  pos.x = 0;
7527
7668
  }
7528
7669
  this.#container.render(ctx, pos, 1, this.renderSize);
7670
+ this.#bounds = {
7671
+ Position: { x: pos.x, y: pos.y },
7672
+ Size: { x: this.renderSize.x, y: this.renderSize.y }
7673
+ };
7529
7674
  return null;
7530
7675
  }
7676
+ #bounds = null;
7677
+ contains(point) {
7678
+ return this.#bounds !== null && InBox(this.#bounds, point);
7679
+ }
7531
7680
  };
7532
7681
 
7533
7682
  // src/minimap.ts
@@ -7738,6 +7887,7 @@ var NodeFlowGraph = class {
7738
7887
  #backgroundRenderer;
7739
7888
  #contextMenuConfig;
7740
7889
  #mousePosition;
7890
+ #mouseOverCanvas = false;
7741
7891
  #camera;
7742
7892
  #openedContextMenu;
7743
7893
  #openQuickMenu;
@@ -7750,7 +7900,8 @@ var NodeFlowGraph = class {
7750
7900
  const postProcessPass = new PassSubsystem();
7751
7901
  this.#mainNodeSubsystem = new NodeSubsystem2(postProcessPass, {
7752
7902
  nodes: config?.nodes,
7753
- idleConnection: config?.idleConnection
7903
+ idleConnection: config?.idleConnection,
7904
+ casts: config?.casts
7754
7905
  });
7755
7906
  this.#lastFrameCursor = "default" /* Default */;
7756
7907
  this.#cursor = "default" /* Default */;
@@ -7799,6 +7950,7 @@ var NodeFlowGraph = class {
7799
7950
  this.#mouseDragEvent.bind(this),
7800
7951
  (mousePosition) => {
7801
7952
  this.#mousePosition = mousePosition;
7953
+ this.#mouseOverCanvas = true;
7802
7954
  },
7803
7955
  this.#clickStart.bind(this),
7804
7956
  this.#clickEnd.bind(this),
@@ -7806,6 +7958,9 @@ var NodeFlowGraph = class {
7806
7958
  this.#fileDrop.bind(this),
7807
7959
  (factor, anchor) => {
7808
7960
  this.#zoomBy(factor, anchor);
7961
+ },
7962
+ () => {
7963
+ this.#mouseOverCanvas = false;
7809
7964
  }
7810
7965
  );
7811
7966
  document.addEventListener(
@@ -7963,6 +8118,7 @@ var NodeFlowGraph = class {
7963
8118
  this.#openQuickMenu = null;
7964
8119
  this.#contextMenuEntryHovering = null;
7965
8120
  this.#mousePosition = mousePosition;
8121
+ this.#mouseOverCanvas = true;
7966
8122
  if (this.#minimap.contains(mousePosition)) {
7967
8123
  this.#lookAtFromMinimap(mousePosition);
7968
8124
  this.#draggingMinimap = true;
@@ -7991,6 +8147,9 @@ var NodeFlowGraph = class {
7991
8147
  addPublisher(identifier, publisher) {
7992
8148
  this.#mainNodeSubsystem.addPublisher(identifier, publisher);
7993
8149
  }
8150
+ setCasts(casts) {
8151
+ this.#mainNodeSubsystem.setCasts(casts);
8152
+ }
7994
8153
  getNodes() {
7995
8154
  return this.#mainNodeSubsystem.getNodes();
7996
8155
  }
@@ -8111,6 +8270,9 @@ var NodeFlowGraph = class {
8111
8270
  addOnNodeRemovedListener(callback) {
8112
8271
  this.#mainNodeSubsystem.addOnNodeRemovedListener(callback);
8113
8272
  }
8273
+ addNodeHoverListener(callback) {
8274
+ this.#mainNodeSubsystem.addNodeHoverListener(callback);
8275
+ }
8114
8276
  #sceenPositionToGraphPosition(screenPosition) {
8115
8277
  const out = Zero();
8116
8278
  this.#camera.screenSpaceToGraphSpace(screenPosition, out);
@@ -8136,6 +8298,7 @@ var NodeFlowGraph = class {
8136
8298
  {
8137
8299
  needs: dangling.needs,
8138
8300
  types: dangling.types,
8301
+ casts: this.#mainNodeSubsystem.casts(),
8139
8302
  onCreated: dangling.connectTo
8140
8303
  }
8141
8304
  );
@@ -8207,7 +8370,7 @@ var NodeFlowGraph = class {
8207
8370
  TimeExecution("Render_Background", this.#renderBackground.bind(this));
8208
8371
  TimeExecution("Render_View_" + this.#currentView, () => {
8209
8372
  placeEditsDuring(this.#canvas, () => {
8210
- let results = this.currentView().render(this.#ctx, this.#camera, this.#mousePosition);
8373
+ let results = this.currentView().render(this.#ctx, this.#camera, this.#pointerOnGraph());
8211
8374
  if (results?.cursorStyle) {
8212
8375
  this.#cursor = results?.cursorStyle;
8213
8376
  }
@@ -8223,6 +8386,19 @@ var NodeFlowGraph = class {
8223
8386
  }
8224
8387
  this.#lastFrameCursor = this.#cursor;
8225
8388
  }
8389
+ #pointer() {
8390
+ return this.#mouseOverCanvas ? this.#mousePosition : void 0;
8391
+ }
8392
+ #pointerOnGraph() {
8393
+ const pointer = this.#pointer();
8394
+ if (pointer === void 0) {
8395
+ return void 0;
8396
+ }
8397
+ if (this.#openedContextMenu?.Menu.contains(pointer) || this.#openQuickMenu?.Menu.contains(pointer)) {
8398
+ return void 0;
8399
+ }
8400
+ return pointer;
8401
+ }
8226
8402
  #renderBackground() {
8227
8403
  this.#backgroundRenderer(this.#canvas, this.#ctx, this.#camera.position, this.#camera.zoom);
8228
8404
  }
@@ -8231,7 +8407,7 @@ var NodeFlowGraph = class {
8231
8407
  if (this.#openedContextMenu !== null) {
8232
8408
  const pos = VectorPool.get();
8233
8409
  this.#camera.graphSpaceToScreenSpace(this.#openedContextMenu.Position, pos);
8234
- this.#contextMenuEntryHovering = this.#openedContextMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#mousePosition, true);
8410
+ this.#contextMenuEntryHovering = this.#openedContextMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#pointer(), true);
8235
8411
  if (this.#contextMenuEntryHovering !== null) {
8236
8412
  this.#cursor = "pointer" /* Pointer */;
8237
8413
  }
@@ -8243,7 +8419,7 @@ var NodeFlowGraph = class {
8243
8419
  if (this.#openQuickMenu !== null) {
8244
8420
  const pos = VectorPool.get();
8245
8421
  this.#camera.graphSpaceToScreenSpace(this.#openQuickMenu.Position, pos);
8246
- this.#contextMenuEntryHovering = this.#openQuickMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#mousePosition);
8422
+ this.#contextMenuEntryHovering = this.#openQuickMenu.Menu.render(this.#ctx, pos, this.#camera.zoom, this.#pointer());
8247
8423
  if (this.#contextMenuEntryHovering !== null) {
8248
8424
  this.#cursor = "pointer" /* Pointer */;
8249
8425
  }
@@ -8291,12 +8467,15 @@ var NodeFlowGraph = class {
8291
8467
  formatNumber,
8292
8468
  onThemeChange,
8293
8469
  portConfigTypes,
8470
+ portTypeColor,
8294
8471
  portsCompatible,
8472
+ portsConnect,
8295
8473
  renderContinuously,
8296
8474
  requestRender,
8297
8475
  setTheme,
8298
8476
  themeVersion,
8299
8477
  typeSetsCompatible,
8478
+ typeSetsConnect,
8300
8479
  widgetFont
8301
8480
  });
8302
8481
  //# sourceMappingURL=index.js.map