@procaaso/alphinity-ui-components 1.8.1 → 1.8.2

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.cjs CHANGED
@@ -3382,7 +3382,10 @@ var ThemeToggle = ({
3382
3382
  };
3383
3383
 
3384
3384
  // src/components/PIDCanvas/PIDCanvas.tsx
3385
- var import_react17 = require("react");
3385
+ var import_react20 = __toESM(require("react"), 1);
3386
+
3387
+ // src/components/PIDCanvas/NodeRenderer.tsx
3388
+ var import_react10 = __toESM(require("react"), 1);
3386
3389
 
3387
3390
  // src/diagram/symbols/mockSymbolLibrary.ts
3388
3391
  var mockSymbolLibrary = {
@@ -4604,7 +4607,7 @@ function getAvailableSymbols() {
4604
4607
 
4605
4608
  // src/components/PIDCanvas/NodeRenderer.tsx
4606
4609
  var import_jsx_runtime16 = require("react/jsx-runtime");
4607
- function NodeRenderer({
4610
+ function NodeRendererImpl({
4608
4611
  nodes: nodes2,
4609
4612
  selectedNodeIds,
4610
4613
  onNodeClick,
@@ -4750,10 +4753,12 @@ function NodeRenderer({
4750
4753
  );
4751
4754
  }) });
4752
4755
  }
4756
+ var NodeRenderer = import_react10.default.memo(NodeRendererImpl);
4753
4757
 
4754
4758
  // src/components/PIDCanvas/PipeRenderer.tsx
4759
+ var import_react11 = __toESM(require("react"), 1);
4755
4760
  var import_jsx_runtime17 = require("react/jsx-runtime");
4756
- function PipeRenderer({
4761
+ function PipeRendererImpl({
4757
4762
  pipes,
4758
4763
  selectedPipeIds,
4759
4764
  onPipeClick,
@@ -4930,8 +4935,10 @@ function PipeRenderer({
4930
4935
  );
4931
4936
  }) });
4932
4937
  }
4938
+ var PipeRenderer = import_react11.default.memo(PipeRendererImpl);
4933
4939
 
4934
4940
  // src/components/PIDCanvas/DataOverlay.tsx
4941
+ var import_react12 = __toESM(require("react"), 1);
4935
4942
  var import_jsx_runtime18 = require("react/jsx-runtime");
4936
4943
  var PULSE_KEYFRAME_ID = "pid-data-overlay-pulse-keyframes";
4937
4944
  var PULSE_ANIMATION = "pid-data-overlay-pulse 1.5s ease-in-out infinite";
@@ -4957,7 +4964,7 @@ function renderStatusDot(cx, cy, scale, fill) {
4957
4964
  }
4958
4965
  );
4959
4966
  }
4960
- function DataOverlay({
4967
+ function DataOverlayImpl({
4961
4968
  nodeId,
4962
4969
  x,
4963
4970
  y,
@@ -4977,6 +4984,24 @@ function DataOverlay({
4977
4984
  const backgroundColor = display?.backgroundColor;
4978
4985
  const offsetX = display?.offsetX ?? 0;
4979
4986
  const offsetY = display?.offsetY ?? 0;
4987
+ const sparklinePath = import_react12.default.useMemo(() => {
4988
+ if (!showSparkline || !history || history.length < 2) return "";
4989
+ const width = 70 * scale;
4990
+ const height = 20 * scale;
4991
+ const padding = 5 * scale;
4992
+ const effectiveWidth = width - padding * 2;
4993
+ const effectiveHeight = height - padding * 2;
4994
+ const hasEuRange = scaling?.euLow !== void 0 && scaling?.euHigh !== void 0 && scaling.euHigh !== scaling.euLow;
4995
+ const min = hasEuRange ? scaling.euLow : Math.min(...history);
4996
+ const max = hasEuRange ? scaling.euHigh : Math.max(...history);
4997
+ const range = max - min || 1;
4998
+ const points = history.map((val, i) => {
4999
+ const xPos = i / (history.length - 1) * effectiveWidth + padding;
5000
+ const yPos = height - padding - (val - min) / range * effectiveHeight;
5001
+ return `${xPos.toFixed(2)},${yPos.toFixed(2)}`;
5002
+ });
5003
+ return `M ${points.join(" L ")}`;
5004
+ }, [showSparkline, history, scaling, scale]);
4980
5005
  if (!showValue) {
4981
5006
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, {});
4982
5007
  }
@@ -4996,24 +5021,6 @@ function DataOverlay({
4996
5021
  const finalTextColor = textColor || colors.text;
4997
5022
  const formattedValue = formatValue(value.value);
4998
5023
  const displayText = unit ? `${formattedValue} ${unit}` : formattedValue;
4999
- const sparklinePath = (() => {
5000
- if (!showSparkline || !history || history.length < 2) return "";
5001
- const width = 70 * scale;
5002
- const height = 20 * scale;
5003
- const padding = 5 * scale;
5004
- const effectiveWidth = width - padding * 2;
5005
- const effectiveHeight = height - padding * 2;
5006
- const hasEuRange = scaling?.euLow !== void 0 && scaling?.euHigh !== void 0 && scaling.euHigh !== scaling.euLow;
5007
- const min = hasEuRange ? scaling.euLow : Math.min(...history);
5008
- const max = hasEuRange ? scaling.euHigh : Math.max(...history);
5009
- const range = max - min || 1;
5010
- const points = history.map((val, i) => {
5011
- const xPos = i / (history.length - 1) * effectiveWidth + padding;
5012
- const yPos = height - padding - (val - min) / range * effectiveHeight;
5013
- return `${xPos.toFixed(2)},${yPos.toFixed(2)}`;
5014
- });
5015
- return `M ${points.join(" L ")}`;
5016
- })();
5017
5024
  const hasSparkline = showSparkline && sparklinePath;
5018
5025
  const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
5019
5026
  const overlayWidth = 80 * scale;
@@ -5093,9 +5100,10 @@ function DataOverlay({
5093
5100
  ) })
5094
5101
  ] });
5095
5102
  }
5103
+ var DataOverlay = import_react12.default.memo(DataOverlayImpl);
5096
5104
 
5097
5105
  // src/components/PIDCanvas/PositionPanel.tsx
5098
- var import_react10 = require("react");
5106
+ var import_react13 = require("react");
5099
5107
  var import_jsx_runtime19 = require("react/jsx-runtime");
5100
5108
  function PositionPanel({
5101
5109
  selectedNode,
@@ -5104,9 +5112,9 @@ function PositionPanel({
5104
5112
  onWaypointPositionChange,
5105
5113
  position = "top-right"
5106
5114
  }) {
5107
- const [x, setX] = (0, import_react10.useState)("");
5108
- const [y, setY] = (0, import_react10.useState)("");
5109
- (0, import_react10.useEffect)(() => {
5115
+ const [x, setX] = (0, import_react13.useState)("");
5116
+ const [y, setY] = (0, import_react13.useState)("");
5117
+ (0, import_react13.useEffect)(() => {
5110
5118
  if (selectedNode) {
5111
5119
  setX(selectedNode.transform.x.toFixed(2));
5112
5120
  setY(selectedNode.transform.y.toFixed(2));
@@ -5232,7 +5240,7 @@ function PositionPanel({
5232
5240
  }
5233
5241
 
5234
5242
  // src/diagram/hooks/useViewBox.ts
5235
- var import_react11 = require("react");
5243
+ var import_react14 = require("react");
5236
5244
  function useViewBox(options) {
5237
5245
  const {
5238
5246
  initialViewBox,
@@ -5243,16 +5251,16 @@ function useViewBox(options) {
5243
5251
  zoomSensitivity = 1e-3,
5244
5252
  allowLeftClickPan = true
5245
5253
  } = options;
5246
- const [viewBox, setViewBox] = (0, import_react11.useState)(initialViewBox);
5247
- const svgRef = (0, import_react11.useRef)(null);
5248
- const isPanningRef = (0, import_react11.useRef)(false);
5249
- const lastMousePosRef = (0, import_react11.useRef)({ x: 0, y: 0 });
5250
- const spaceKeyDownRef = (0, import_react11.useRef)(false);
5251
- const lastTouchDistanceRef = (0, import_react11.useRef)(null);
5252
- const resetViewBox = (0, import_react11.useCallback)(() => {
5254
+ const [viewBox, setViewBox] = (0, import_react14.useState)(initialViewBox);
5255
+ const svgRef = (0, import_react14.useRef)(null);
5256
+ const isPanningRef = (0, import_react14.useRef)(false);
5257
+ const lastMousePosRef = (0, import_react14.useRef)({ x: 0, y: 0 });
5258
+ const spaceKeyDownRef = (0, import_react14.useRef)(false);
5259
+ const lastTouchDistanceRef = (0, import_react14.useRef)(null);
5260
+ const resetViewBox = (0, import_react14.useCallback)(() => {
5253
5261
  setViewBox(initialViewBox);
5254
5262
  }, [initialViewBox]);
5255
- const zoomIn = (0, import_react11.useCallback)(() => {
5263
+ const zoomIn = (0, import_react14.useCallback)(() => {
5256
5264
  setViewBox((prev) => {
5257
5265
  const currentZoom = initialViewBox.width / prev.width;
5258
5266
  const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
@@ -5269,7 +5277,7 @@ function useViewBox(options) {
5269
5277
  };
5270
5278
  });
5271
5279
  }, [initialViewBox, minZoom]);
5272
- const zoomOut = (0, import_react11.useCallback)(() => {
5280
+ const zoomOut = (0, import_react14.useCallback)(() => {
5273
5281
  setViewBox((prev) => {
5274
5282
  const currentZoom = initialViewBox.width / prev.width;
5275
5283
  const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
@@ -5286,7 +5294,7 @@ function useViewBox(options) {
5286
5294
  };
5287
5295
  });
5288
5296
  }, [initialViewBox, maxZoom]);
5289
- const fitToContent = (0, import_react11.useCallback)((bounds, padding = 50) => {
5297
+ const fitToContent = (0, import_react14.useCallback)((bounds, padding = 50) => {
5290
5298
  const contentWidth = bounds.maxX - bounds.minX;
5291
5299
  const contentHeight = bounds.maxY - bounds.minY;
5292
5300
  if (contentWidth === 0 || contentHeight === 0) {
@@ -5314,7 +5322,7 @@ function useViewBox(options) {
5314
5322
  height: newHeight
5315
5323
  });
5316
5324
  }, [initialViewBox]);
5317
- (0, import_react11.useEffect)(() => {
5325
+ (0, import_react14.useEffect)(() => {
5318
5326
  if (!enableZoom || !svgRef.current) return;
5319
5327
  const svg = svgRef.current;
5320
5328
  const handleWheel = (e) => {
@@ -5347,7 +5355,7 @@ function useViewBox(options) {
5347
5355
  svg.addEventListener("wheel", handleWheel, { passive: false });
5348
5356
  return () => svg.removeEventListener("wheel", handleWheel);
5349
5357
  }, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
5350
- (0, import_react11.useEffect)(() => {
5358
+ (0, import_react14.useEffect)(() => {
5351
5359
  if (!enablePan || !svgRef.current) return;
5352
5360
  const svg = svgRef.current;
5353
5361
  const handleMouseDown = (e) => {
@@ -5423,7 +5431,7 @@ function useViewBox(options) {
5423
5431
  window.removeEventListener("keyup", handleKeyUp);
5424
5432
  };
5425
5433
  }, [enablePan, allowLeftClickPan]);
5426
- (0, import_react11.useEffect)(() => {
5434
+ (0, import_react14.useEffect)(() => {
5427
5435
  if (!svgRef.current) return;
5428
5436
  if (!enablePan && !enableZoom) return;
5429
5437
  const svg = svgRef.current;
@@ -5514,7 +5522,7 @@ function useViewBox(options) {
5514
5522
  svg.removeEventListener("touchend", handleTouchEnd);
5515
5523
  };
5516
5524
  }, [enablePan, enableZoom, minZoom, initialViewBox]);
5517
- const screenToWorld = (0, import_react11.useCallback)(
5525
+ const screenToWorld = (0, import_react14.useCallback)(
5518
5526
  (screenX, screenY) => {
5519
5527
  const svg = svgRef.current;
5520
5528
  if (!svg) return { x: screenX, y: screenY };
@@ -5553,15 +5561,15 @@ function useViewBox(options) {
5553
5561
  }
5554
5562
 
5555
5563
  // src/diagram/hooks/useSelection.ts
5556
- var import_react12 = require("react");
5564
+ var import_react15 = require("react");
5557
5565
  function useSelection(options = {}) {
5558
5566
  const {
5559
5567
  multiSelect = true,
5560
5568
  initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
5561
5569
  onSelectionChange
5562
5570
  } = options;
5563
- const [selection, setSelection] = (0, import_react12.useState)(initialSelection);
5564
- const notifyChange = (0, import_react12.useCallback)(
5571
+ const [selection, setSelection] = (0, import_react15.useState)(initialSelection);
5572
+ const notifyChange = (0, import_react15.useCallback)(
5565
5573
  (newSelection) => {
5566
5574
  if (onSelectionChange) {
5567
5575
  onSelectionChange(newSelection);
@@ -5569,15 +5577,15 @@ function useSelection(options = {}) {
5569
5577
  },
5570
5578
  [onSelectionChange]
5571
5579
  );
5572
- const isNodeSelected = (0, import_react12.useCallback)(
5580
+ const isNodeSelected = (0, import_react15.useCallback)(
5573
5581
  (nodeId) => selection.selectedNodeIds.has(nodeId),
5574
5582
  [selection.selectedNodeIds]
5575
5583
  );
5576
- const isPipeSelected = (0, import_react12.useCallback)(
5584
+ const isPipeSelected = (0, import_react15.useCallback)(
5577
5585
  (pipeId) => selection.selectedPipeIds.has(pipeId),
5578
5586
  [selection.selectedPipeIds]
5579
5587
  );
5580
- const selectNode = (0, import_react12.useCallback)(
5588
+ const selectNode = (0, import_react15.useCallback)(
5581
5589
  (nodeId, isMultiSelect = false) => {
5582
5590
  setSelection((prev) => {
5583
5591
  const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
@@ -5596,7 +5604,7 @@ function useSelection(options = {}) {
5596
5604
  },
5597
5605
  [multiSelect, notifyChange]
5598
5606
  );
5599
- const selectPipe = (0, import_react12.useCallback)(
5607
+ const selectPipe = (0, import_react15.useCallback)(
5600
5608
  (pipeId, isMultiSelect = false) => {
5601
5609
  setSelection((prev) => {
5602
5610
  const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
@@ -5615,7 +5623,7 @@ function useSelection(options = {}) {
5615
5623
  },
5616
5624
  [multiSelect, notifyChange]
5617
5625
  );
5618
- const clearSelection = (0, import_react12.useCallback)(() => {
5626
+ const clearSelection = (0, import_react15.useCallback)(() => {
5619
5627
  const newSelection = {
5620
5628
  selectedNodeIds: /* @__PURE__ */ new Set(),
5621
5629
  selectedPipeIds: /* @__PURE__ */ new Set()
@@ -5623,7 +5631,7 @@ function useSelection(options = {}) {
5623
5631
  setSelection(newSelection);
5624
5632
  notifyChange(newSelection);
5625
5633
  }, [notifyChange]);
5626
- const selectNodes = (0, import_react12.useCallback)(
5634
+ const selectNodes = (0, import_react15.useCallback)(
5627
5635
  (nodeIds) => {
5628
5636
  const newSelection = {
5629
5637
  selectedNodeIds: new Set(nodeIds),
@@ -5634,7 +5642,7 @@ function useSelection(options = {}) {
5634
5642
  },
5635
5643
  [notifyChange]
5636
5644
  );
5637
- const selectPipes = (0, import_react12.useCallback)(
5645
+ const selectPipes = (0, import_react15.useCallback)(
5638
5646
  (pipeIds) => {
5639
5647
  const newSelection = {
5640
5648
  selectedNodeIds: /* @__PURE__ */ new Set(),
@@ -5658,23 +5666,23 @@ function useSelection(options = {}) {
5658
5666
  }
5659
5667
 
5660
5668
  // src/diagram/hooks/useTelemetry.ts
5661
- var import_react13 = require("react");
5669
+ var import_react16 = require("react");
5662
5670
  function useTelemetry(options = {}) {
5663
5671
  const {
5664
5672
  initialBindings = [],
5665
5673
  onTelemetryChange,
5666
5674
  refreshInterval = 0
5667
5675
  } = options;
5668
- const [telemetry, setTelemetry] = (0, import_react13.useState)(() => {
5676
+ const [telemetry, setTelemetry] = (0, import_react16.useState)(() => {
5669
5677
  const map = /* @__PURE__ */ new Map();
5670
5678
  initialBindings.forEach((binding) => {
5671
5679
  map.set(binding.nodeId, binding);
5672
5680
  });
5673
5681
  return map;
5674
5682
  });
5675
- const telemetryRef = (0, import_react13.useRef)(telemetry);
5683
+ const telemetryRef = (0, import_react16.useRef)(telemetry);
5676
5684
  telemetryRef.current = telemetry;
5677
- const notifyChange = (0, import_react13.useCallback)(
5685
+ const notifyChange = (0, import_react16.useCallback)(
5678
5686
  (newTelemetry) => {
5679
5687
  if (onTelemetryChange) {
5680
5688
  onTelemetryChange(newTelemetry);
@@ -5682,7 +5690,7 @@ function useTelemetry(options = {}) {
5682
5690
  },
5683
5691
  [onTelemetryChange]
5684
5692
  );
5685
- const updateTelemetry = (0, import_react13.useCallback)(
5693
+ const updateTelemetry = (0, import_react16.useCallback)(
5686
5694
  (nodeId, value) => {
5687
5695
  setTelemetry((prev) => {
5688
5696
  const newMap = new Map(prev);
@@ -5712,7 +5720,7 @@ function useTelemetry(options = {}) {
5712
5720
  },
5713
5721
  [notifyChange]
5714
5722
  );
5715
- const updateTelemetryBatch = (0, import_react13.useCallback)(
5723
+ const updateTelemetryBatch = (0, import_react16.useCallback)(
5716
5724
  (updates) => {
5717
5725
  setTelemetry((prev) => {
5718
5726
  const newMap = new Map(prev);
@@ -5766,16 +5774,16 @@ function useTelemetry(options = {}) {
5766
5774
  },
5767
5775
  [notifyChange]
5768
5776
  );
5769
- const getTelemetry = (0, import_react13.useCallback)(
5777
+ const getTelemetry = (0, import_react16.useCallback)(
5770
5778
  (nodeId) => telemetryRef.current.get(nodeId),
5771
5779
  []
5772
5780
  );
5773
- const clearTelemetry = (0, import_react13.useCallback)(() => {
5781
+ const clearTelemetry = (0, import_react16.useCallback)(() => {
5774
5782
  const newMap = /* @__PURE__ */ new Map();
5775
5783
  setTelemetry(newMap);
5776
5784
  notifyChange(newMap);
5777
5785
  }, [notifyChange]);
5778
- const setBindings = (0, import_react13.useCallback)(
5786
+ const setBindings = (0, import_react16.useCallback)(
5779
5787
  (bindings) => {
5780
5788
  const newMap = /* @__PURE__ */ new Map();
5781
5789
  bindings.forEach((binding) => {
@@ -5786,7 +5794,7 @@ function useTelemetry(options = {}) {
5786
5794
  },
5787
5795
  [notifyChange]
5788
5796
  );
5789
- (0, import_react13.useEffect)(() => {
5797
+ (0, import_react16.useEffect)(() => {
5790
5798
  if (refreshInterval <= 0) return;
5791
5799
  const intervalId = setInterval(() => {
5792
5800
  notifyChange(telemetryRef.current);
@@ -5804,10 +5812,10 @@ function useTelemetry(options = {}) {
5804
5812
  }
5805
5813
 
5806
5814
  // src/diagram/hooks/useTelemetryStatus.ts
5807
- var import_react14 = require("react");
5815
+ var import_react17 = require("react");
5808
5816
  function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5809
5817
  const { enabled = true, mapStatus } = options;
5810
- (0, import_react14.useEffect)(() => {
5818
+ (0, import_react17.useEffect)(() => {
5811
5819
  if (!enabled) return;
5812
5820
  const defaultMapStatus = (telemetryStatus) => {
5813
5821
  switch (telemetryStatus) {
@@ -5846,7 +5854,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5846
5854
  }
5847
5855
 
5848
5856
  // src/diagram/hooks/useDrag.ts
5849
- var import_react15 = require("react");
5857
+ var import_react18 = require("react");
5850
5858
  function useDrag(options = {}) {
5851
5859
  const {
5852
5860
  onDragStart,
@@ -5856,23 +5864,23 @@ function useDrag(options = {}) {
5856
5864
  dragThreshold = 3,
5857
5865
  screenToWorld = (x, y) => ({ x, y })
5858
5866
  } = options;
5859
- const [dragState, setDragState] = (0, import_react15.useState)({
5867
+ const [dragState, setDragState] = (0, import_react18.useState)({
5860
5868
  isDragging: false,
5861
5869
  startPosition: null,
5862
5870
  offset: { x: 0, y: 0 },
5863
5871
  draggedId: null
5864
5872
  });
5865
- const [isListening, setIsListening] = (0, import_react15.useState)(false);
5866
- const dragStartRef = (0, import_react15.useRef)(null);
5867
- const hasMovedRef = (0, import_react15.useRef)(false);
5868
- const applySnap = (0, import_react15.useCallback)(
5873
+ const [isListening, setIsListening] = (0, import_react18.useState)(false);
5874
+ const dragStartRef = (0, import_react18.useRef)(null);
5875
+ const hasMovedRef = (0, import_react18.useRef)(false);
5876
+ const applySnap = (0, import_react18.useCallback)(
5869
5877
  (value) => {
5870
5878
  if (snapToGrid <= 0) return value;
5871
5879
  return Math.round(value / snapToGrid) * snapToGrid;
5872
5880
  },
5873
5881
  [snapToGrid]
5874
5882
  );
5875
- const handleMouseMove = (0, import_react15.useCallback)(
5883
+ const handleMouseMove = (0, import_react18.useCallback)(
5876
5884
  (event) => {
5877
5885
  if (!dragStartRef.current) return;
5878
5886
  const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
@@ -5913,7 +5921,7 @@ function useDrag(options = {}) {
5913
5921
  },
5914
5922
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5915
5923
  );
5916
- const handleMouseUp = (0, import_react15.useCallback)(
5924
+ const handleMouseUp = (0, import_react18.useCallback)(
5917
5925
  (event) => {
5918
5926
  if (!dragStartRef.current || !hasMovedRef.current) {
5919
5927
  dragStartRef.current = null;
@@ -5950,7 +5958,7 @@ function useDrag(options = {}) {
5950
5958
  },
5951
5959
  [screenToWorld, applySnap, onDragEnd]
5952
5960
  );
5953
- const handleTouchMove = (0, import_react15.useCallback)(
5961
+ const handleTouchMove = (0, import_react18.useCallback)(
5954
5962
  (event) => {
5955
5963
  if (!dragStartRef.current || event.touches.length !== 1) return;
5956
5964
  const touch = event.touches[0];
@@ -5993,7 +6001,7 @@ function useDrag(options = {}) {
5993
6001
  },
5994
6002
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5995
6003
  );
5996
- const handleTouchEnd = (0, import_react15.useCallback)(
6004
+ const handleTouchEnd = (0, import_react18.useCallback)(
5997
6005
  (event) => {
5998
6006
  if (!dragStartRef.current || !hasMovedRef.current) {
5999
6007
  dragStartRef.current = null;
@@ -6031,7 +6039,7 @@ function useDrag(options = {}) {
6031
6039
  },
6032
6040
  [screenToWorld, applySnap, onDragEnd]
6033
6041
  );
6034
- (0, import_react15.useEffect)(() => {
6042
+ (0, import_react18.useEffect)(() => {
6035
6043
  if (!isListening) return;
6036
6044
  document.addEventListener("mousemove", handleMouseMove);
6037
6045
  document.addEventListener("mouseup", handleMouseUp);
@@ -6046,7 +6054,7 @@ function useDrag(options = {}) {
6046
6054
  document.removeEventListener("touchcancel", handleTouchEnd);
6047
6055
  };
6048
6056
  }, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
6049
- const startDrag = (0, import_react15.useCallback)(
6057
+ const startDrag = (0, import_react18.useCallback)(
6050
6058
  (id, event, itemPosition) => {
6051
6059
  event.stopPropagation();
6052
6060
  let clientX;
@@ -6076,7 +6084,7 @@ function useDrag(options = {}) {
6076
6084
  },
6077
6085
  [screenToWorld]
6078
6086
  );
6079
- const cancelDrag = (0, import_react15.useCallback)(() => {
6087
+ const cancelDrag = (0, import_react18.useCallback)(() => {
6080
6088
  dragStartRef.current = null;
6081
6089
  hasMovedRef.current = false;
6082
6090
  setIsListening(false);
@@ -6087,7 +6095,7 @@ function useDrag(options = {}) {
6087
6095
  draggedId: null
6088
6096
  });
6089
6097
  }, []);
6090
- const isDraggingItem = (0, import_react15.useCallback)(
6098
+ const isDraggingItem = (0, import_react18.useCallback)(
6091
6099
  (id) => dragState.isDragging && dragState.draggedId === id,
6092
6100
  [dragState.isDragging, dragState.draggedId]
6093
6101
  );
@@ -6100,7 +6108,7 @@ function useDrag(options = {}) {
6100
6108
  }
6101
6109
 
6102
6110
  // src/diagram/hooks/useKeyboardShortcuts.ts
6103
- var import_react16 = require("react");
6111
+ var import_react19 = require("react");
6104
6112
  function useKeyboardShortcuts(options) {
6105
6113
  const {
6106
6114
  onDelete,
@@ -6111,7 +6119,7 @@ function useKeyboardShortcuts(options) {
6111
6119
  onSelectAll,
6112
6120
  enabled = true
6113
6121
  } = options;
6114
- (0, import_react16.useEffect)(() => {
6122
+ (0, import_react19.useEffect)(() => {
6115
6123
  if (!enabled) return;
6116
6124
  const handleKeyDown = (event) => {
6117
6125
  const target = event.target;
@@ -6221,18 +6229,19 @@ function nodeHasPort(node, portId) {
6221
6229
 
6222
6230
  // src/components/PIDCanvas/PIDCanvas.tsx
6223
6231
  var import_jsx_runtime20 = require("react/jsx-runtime");
6224
- function PIDCanvas({
6232
+ var DEFAULT_FEATURES = {
6233
+ pan: true,
6234
+ zoom: true,
6235
+ selection: false,
6236
+ multiSelect: true,
6237
+ telemetry: false,
6238
+ dragNodes: false
6239
+ };
6240
+ function PIDCanvasImpl({
6225
6241
  diagram,
6226
6242
  className = "",
6227
6243
  style,
6228
- features = {
6229
- pan: true,
6230
- zoom: true,
6231
- selection: false,
6232
- multiSelect: true,
6233
- telemetry: false,
6234
- dragNodes: false
6235
- },
6244
+ features = DEFAULT_FEATURES,
6236
6245
  onSelectionChange,
6237
6246
  onNodeClick,
6238
6247
  onPipeClick,
@@ -6248,21 +6257,21 @@ function PIDCanvas({
6248
6257
  statusColorMap,
6249
6258
  ...props
6250
6259
  }) {
6251
- const [localDiagram, setLocalDiagram] = (0, import_react17.useState)(diagram);
6252
- const [dragOverPosition, setDragOverPosition] = (0, import_react17.useState)(null);
6253
- const [isConnecting, setIsConnecting] = (0, import_react17.useState)(false);
6254
- const [connectionSource, setConnectionSource] = (0, import_react17.useState)(null);
6255
- const [connectionSourcePort, setConnectionSourcePort] = (0, import_react17.useState)(null);
6256
- const [connectionCursor, setConnectionCursor] = (0, import_react17.useState)(null);
6257
- const [hoveredNode, setHoveredNode] = (0, import_react17.useState)(null);
6258
- const [hoveredPort, setHoveredPort] = (0, import_react17.useState)(null);
6259
- const [selectedWaypoint, setSelectedWaypoint] = (0, import_react17.useState)(null);
6260
- const historyStack = (0, import_react17.useRef)([]);
6261
- const redoStack = (0, import_react17.useRef)([]);
6262
- const isUndoRedoAction = (0, import_react17.useRef)(false);
6263
- const isInternalChange = (0, import_react17.useRef)(false);
6264
- const lastInternalDiagram = (0, import_react17.useRef)(null);
6265
- (0, import_react17.useEffect)(() => {
6260
+ const [localDiagram, setLocalDiagram] = (0, import_react20.useState)(diagram);
6261
+ const [dragOverPosition, setDragOverPosition] = (0, import_react20.useState)(null);
6262
+ const [isConnecting, setIsConnecting] = (0, import_react20.useState)(false);
6263
+ const [connectionSource, setConnectionSource] = (0, import_react20.useState)(null);
6264
+ const [connectionSourcePort, setConnectionSourcePort] = (0, import_react20.useState)(null);
6265
+ const [connectionCursor, setConnectionCursor] = (0, import_react20.useState)(null);
6266
+ const [hoveredNode, setHoveredNode] = (0, import_react20.useState)(null);
6267
+ const [hoveredPort, setHoveredPort] = (0, import_react20.useState)(null);
6268
+ const [selectedWaypoint, setSelectedWaypoint] = (0, import_react20.useState)(null);
6269
+ const historyStack = (0, import_react20.useRef)([]);
6270
+ const redoStack = (0, import_react20.useRef)([]);
6271
+ const isUndoRedoAction = (0, import_react20.useRef)(false);
6272
+ const isInternalChange = (0, import_react20.useRef)(false);
6273
+ const lastInternalDiagram = (0, import_react20.useRef)(null);
6274
+ (0, import_react20.useEffect)(() => {
6266
6275
  const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
6267
6276
  if (isExternal) {
6268
6277
  setLocalDiagram(diagram);
@@ -6284,7 +6293,7 @@ function PIDCanvas({
6284
6293
  enablePan: features.pan ?? true,
6285
6294
  enableZoom: features.zoom ?? true
6286
6295
  });
6287
- const calculateContentBounds = (0, import_react17.useCallback)(() => {
6296
+ const calculateContentBounds = (0, import_react20.useCallback)(() => {
6288
6297
  const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
6289
6298
  if (nodes2.length === 0) {
6290
6299
  return null;
@@ -6307,7 +6316,7 @@ function PIDCanvas({
6307
6316
  });
6308
6317
  return { minX, minY, maxX, maxY };
6309
6318
  }, [localDiagram.nodes]);
6310
- (0, import_react17.useEffect)(() => {
6319
+ (0, import_react20.useEffect)(() => {
6311
6320
  if (onMounted) {
6312
6321
  const controls = {
6313
6322
  fitToContent: (padding = 50) => {
@@ -6348,8 +6357,8 @@ function PIDCanvas({
6348
6357
  });
6349
6358
  const dragEnabled = features.dragNodes ?? false;
6350
6359
  const selectionEnabled = features.selection ?? false;
6351
- const containerRef = (0, import_react17.useRef)(null);
6352
- const pushToHistory = (0, import_react17.useCallback)((currentDiagram) => {
6360
+ const containerRef = (0, import_react20.useRef)(null);
6361
+ const pushToHistory = (0, import_react20.useCallback)((currentDiagram) => {
6353
6362
  if (isUndoRedoAction.current) return;
6354
6363
  const snapshot = JSON.parse(JSON.stringify(currentDiagram));
6355
6364
  historyStack.current.push(snapshot);
@@ -6358,7 +6367,7 @@ function PIDCanvas({
6358
6367
  }
6359
6368
  redoStack.current = [];
6360
6369
  }, []);
6361
- const undo = (0, import_react17.useCallback)(() => {
6370
+ const undo = (0, import_react20.useCallback)(() => {
6362
6371
  if (historyStack.current.length === 0) return;
6363
6372
  isUndoRedoAction.current = true;
6364
6373
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -6372,7 +6381,7 @@ function PIDCanvas({
6372
6381
  isUndoRedoAction.current = false;
6373
6382
  }, 0);
6374
6383
  }, [localDiagram, onDiagramChange]);
6375
- const redo = (0, import_react17.useCallback)(() => {
6384
+ const redo = (0, import_react20.useCallback)(() => {
6376
6385
  if (redoStack.current.length === 0) return;
6377
6386
  isUndoRedoAction.current = true;
6378
6387
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -6386,7 +6395,7 @@ function PIDCanvas({
6386
6395
  isUndoRedoAction.current = false;
6387
6396
  }, 0);
6388
6397
  }, [localDiagram, onDiagramChange]);
6389
- (0, import_react17.useEffect)(() => {
6398
+ (0, import_react20.useEffect)(() => {
6390
6399
  const handleKeyDown = (e) => {
6391
6400
  const isCtrlOrCmd = e.ctrlKey || e.metaKey;
6392
6401
  if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
@@ -6403,7 +6412,7 @@ function PIDCanvas({
6403
6412
  window.addEventListener("keydown", handleKeyDown);
6404
6413
  return () => window.removeEventListener("keydown", handleKeyDown);
6405
6414
  }, [undo, redo]);
6406
- (0, import_react17.useEffect)(() => {
6415
+ (0, import_react20.useEffect)(() => {
6407
6416
  if (!features.dragNodes) return;
6408
6417
  const handleKeyDown = (e) => {
6409
6418
  if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
@@ -6488,7 +6497,7 @@ function PIDCanvas({
6488
6497
  onNodeMove,
6489
6498
  pushToHistory
6490
6499
  ]);
6491
- const handlePositionChange = (0, import_react17.useCallback)(
6500
+ const handlePositionChange = (0, import_react20.useCallback)(
6492
6501
  (nodeId, x, y) => {
6493
6502
  pushToHistory(localDiagram);
6494
6503
  const updatedNodes = localDiagram.nodes.map(
@@ -6510,7 +6519,7 @@ function PIDCanvas({
6510
6519
  },
6511
6520
  [localDiagram, onDiagramChange, onNodeMove, pushToHistory]
6512
6521
  );
6513
- const handleWaypointPositionChange = (0, import_react17.useCallback)(
6522
+ const handleWaypointPositionChange = (0, import_react20.useCallback)(
6514
6523
  (pipeId, pointIndex, x, y) => {
6515
6524
  pushToHistory(localDiagram);
6516
6525
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6528,7 +6537,7 @@ function PIDCanvas({
6528
6537
  },
6529
6538
  [localDiagram, onDiagramChange, pushToHistory]
6530
6539
  );
6531
- const handleDragEnd = (0, import_react17.useCallback)(
6540
+ const handleDragEnd = (0, import_react20.useCallback)(
6532
6541
  (nodeId, offset, finalPosition) => {
6533
6542
  const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
6534
6543
  if (dragDistance < 2) {
@@ -6609,7 +6618,7 @@ function PIDCanvas({
6609
6618
  onDiagramChange?.(updatedDiagram);
6610
6619
  }
6611
6620
  });
6612
- const handleNodeDragStart = (0, import_react17.useCallback)(
6621
+ const handleNodeDragStart = (0, import_react20.useCallback)(
6613
6622
  (nodeId, event) => {
6614
6623
  const node = localDiagram.nodes.find((n) => n.id === nodeId);
6615
6624
  if (!node) return;
@@ -6617,7 +6626,7 @@ function PIDCanvas({
6617
6626
  },
6618
6627
  [localDiagram.nodes, startDrag]
6619
6628
  );
6620
- const handleWaypointClick = (0, import_react17.useCallback)(
6629
+ const handleWaypointClick = (0, import_react20.useCallback)(
6621
6630
  (pipeId, pointIndex) => {
6622
6631
  setSelectedWaypoint({ pipeId, pointIndex });
6623
6632
  if (selectionEnabled) {
@@ -6626,7 +6635,7 @@ function PIDCanvas({
6626
6635
  },
6627
6636
  [selectionEnabled, clearSelection]
6628
6637
  );
6629
- const handleWaypointDragStart = (0, import_react17.useCallback)(
6638
+ const handleWaypointDragStart = (0, import_react20.useCallback)(
6630
6639
  (pipeId, pointIndex, event) => {
6631
6640
  const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
6632
6641
  if (!pipe || pointIndex >= pipe.routePoints.length) return;
@@ -6635,7 +6644,7 @@ function PIDCanvas({
6635
6644
  },
6636
6645
  [localDiagram.pipes, startWaypointDrag]
6637
6646
  );
6638
- const handlePipeSegmentClick = (0, import_react17.useCallback)(
6647
+ const handlePipeSegmentClick = (0, import_react20.useCallback)(
6639
6648
  (pipeId, position, segmentIndex) => {
6640
6649
  pushToHistory(localDiagram);
6641
6650
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6654,7 +6663,7 @@ function PIDCanvas({
6654
6663
  [localDiagram, onDiagramChange, pushToHistory]
6655
6664
  );
6656
6665
  const telemetryEnabled = features.telemetry ?? false;
6657
- const handleDelete = (0, import_react17.useCallback)(() => {
6666
+ const handleDelete = (0, import_react20.useCallback)(() => {
6658
6667
  if (!selectionEnabled) return;
6659
6668
  const { selectedNodeIds, selectedPipeIds } = selection;
6660
6669
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
@@ -6683,62 +6692,81 @@ function PIDCanvas({
6683
6692
  onDelete,
6684
6693
  pushToHistory
6685
6694
  ]);
6686
- const handleCopy = (0, import_react17.useCallback)(() => {
6695
+ const handleCopy = (0, import_react20.useCallback)(() => {
6687
6696
  if (!selectionEnabled) return;
6688
6697
  const { selectedNodeIds, selectedPipeIds } = selection;
6689
6698
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
6690
6699
  onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
6691
6700
  }, [selection, selectionEnabled, onItemsCopied]);
6692
- const handlePaste = (0, import_react17.useCallback)(() => {
6701
+ const handlePaste = (0, import_react20.useCallback)(() => {
6693
6702
  if (!selectionEnabled) return;
6694
6703
  onPaste?.();
6695
6704
  }, [selectionEnabled, onPaste]);
6696
- const handleNodeDoubleClick = (nodeId, event) => {
6697
- if (!selectionEnabled) return;
6698
- console.log("Node double-clicked:", nodeId);
6699
- selectNode(nodeId, event.ctrlKey || event.metaKey);
6700
- };
6705
+ const handleNodeDoubleClick = (0, import_react20.useCallback)(
6706
+ (nodeId, event) => {
6707
+ if (!selectionEnabled) return;
6708
+ console.log("Node double-clicked:", nodeId);
6709
+ selectNode(nodeId, event.ctrlKey || event.metaKey);
6710
+ },
6711
+ [selectionEnabled, selectNode]
6712
+ );
6701
6713
  useKeyboardShortcuts({
6702
6714
  enabled: features.keyboardShortcuts ?? false,
6703
6715
  onDelete: handleDelete,
6704
6716
  onCopy: handleCopy,
6705
6717
  onPaste: handlePaste
6706
6718
  });
6707
- const handleNodeClick = (nodeId, event) => {
6708
- const connectionModeEnabled = features.connectionMode ?? false;
6709
- if (connectionModeEnabled && isConnecting) {
6710
- if (connectionSource && connectionSource !== nodeId) {
6711
- onPipeCreated?.(
6712
- connectionSource,
6713
- nodeId,
6714
- connectionSourcePort || void 0,
6715
- hoveredPort || void 0
6716
- );
6717
- setIsConnecting(false);
6718
- setConnectionSource(null);
6719
- setConnectionSourcePort(null);
6720
- setConnectionCursor(null);
6721
- setHoveredPort(null);
6719
+ const handleNodeClick = (0, import_react20.useCallback)(
6720
+ (nodeId, event) => {
6721
+ const connectionModeEnabled = features.connectionMode ?? false;
6722
+ if (connectionModeEnabled && isConnecting) {
6723
+ if (connectionSource && connectionSource !== nodeId) {
6724
+ onPipeCreated?.(
6725
+ connectionSource,
6726
+ nodeId,
6727
+ connectionSourcePort || void 0,
6728
+ hoveredPort || void 0
6729
+ );
6730
+ setIsConnecting(false);
6731
+ setConnectionSource(null);
6732
+ setConnectionSourcePort(null);
6733
+ setConnectionCursor(null);
6734
+ setHoveredPort(null);
6735
+ }
6736
+ return;
6722
6737
  }
6723
- return;
6724
- }
6725
- if (connectionModeEnabled && !isConnecting) {
6726
- setIsConnecting(true);
6727
- setConnectionSource(nodeId);
6728
- setConnectionSourcePort(hoveredPort);
6729
- return;
6730
- }
6731
- if (selectionEnabled) {
6732
- selectNode(nodeId, event.ctrlKey || event.metaKey);
6733
- }
6734
- onNodeClick?.(nodeId);
6735
- };
6736
- const handlePipeClick = (pipeId, event) => {
6737
- if (selectionEnabled) {
6738
- selectPipe(pipeId, event.ctrlKey || event.metaKey);
6739
- }
6740
- onPipeClick?.(pipeId);
6741
- };
6738
+ if (connectionModeEnabled && !isConnecting) {
6739
+ setIsConnecting(true);
6740
+ setConnectionSource(nodeId);
6741
+ setConnectionSourcePort(hoveredPort);
6742
+ return;
6743
+ }
6744
+ if (selectionEnabled) {
6745
+ selectNode(nodeId, event.ctrlKey || event.metaKey);
6746
+ }
6747
+ onNodeClick?.(nodeId);
6748
+ },
6749
+ [
6750
+ features.connectionMode,
6751
+ isConnecting,
6752
+ connectionSource,
6753
+ connectionSourcePort,
6754
+ hoveredPort,
6755
+ onPipeCreated,
6756
+ selectionEnabled,
6757
+ selectNode,
6758
+ onNodeClick
6759
+ ]
6760
+ );
6761
+ const handlePipeClick = (0, import_react20.useCallback)(
6762
+ (pipeId, event) => {
6763
+ if (selectionEnabled) {
6764
+ selectPipe(pipeId, event.ctrlKey || event.metaKey);
6765
+ }
6766
+ onPipeClick?.(pipeId);
6767
+ },
6768
+ [selectionEnabled, selectPipe, onPipeClick]
6769
+ );
6742
6770
  const handleCanvasClick = (e) => {
6743
6771
  const target = e.target;
6744
6772
  if (target.closest(".pipe-route-point")) {
@@ -6749,7 +6777,7 @@ function PIDCanvas({
6749
6777
  }
6750
6778
  setSelectedWaypoint(null);
6751
6779
  };
6752
- const handleDragOver = (0, import_react17.useCallback)(
6780
+ const handleDragOver = (0, import_react20.useCallback)(
6753
6781
  (event) => {
6754
6782
  if (!features.allowSymbolDrop) return;
6755
6783
  event.preventDefault();
@@ -6760,7 +6788,7 @@ function PIDCanvas({
6760
6788
  },
6761
6789
  [features.allowSymbolDrop, screenToWorld, svgRef]
6762
6790
  );
6763
- const handleDrop = (0, import_react17.useCallback)(
6791
+ const handleDrop = (0, import_react20.useCallback)(
6764
6792
  (event) => {
6765
6793
  if (!features.allowSymbolDrop) return;
6766
6794
  event.preventDefault();
@@ -6773,10 +6801,10 @@ function PIDCanvas({
6773
6801
  },
6774
6802
  [features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
6775
6803
  );
6776
- const handleDragLeave = (0, import_react17.useCallback)(() => {
6804
+ const handleDragLeave = (0, import_react20.useCallback)(() => {
6777
6805
  setDragOverPosition(null);
6778
6806
  }, []);
6779
- const handleMouseMove = (0, import_react17.useCallback)(
6807
+ const handleMouseMove = (0, import_react20.useCallback)(
6780
6808
  (event) => {
6781
6809
  const connectionModeEnabled = features.connectionMode ?? false;
6782
6810
  if (connectionModeEnabled) {
@@ -7086,9 +7114,10 @@ function PIDCanvas({
7086
7114
  }
7087
7115
  );
7088
7116
  }
7117
+ var PIDCanvas = import_react20.default.memo(PIDCanvasImpl);
7089
7118
 
7090
7119
  // src/components/SymbolLibrary/SymbolLibrary.tsx
7091
- var import_react18 = require("react");
7120
+ var import_react21 = require("react");
7092
7121
  var import_jsx_runtime21 = require("react/jsx-runtime");
7093
7122
  function SymbolLibrary({
7094
7123
  className = "",
@@ -7096,8 +7125,8 @@ function SymbolLibrary({
7096
7125
  showCategories = true,
7097
7126
  categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
7098
7127
  }) {
7099
- const [selectedCategory, setSelectedCategory] = (0, import_react18.useState)("all");
7100
- const [searchQuery, setSearchQuery] = (0, import_react18.useState)("");
7128
+ const [selectedCategory, setSelectedCategory] = (0, import_react21.useState)("all");
7129
+ const [searchQuery, setSearchQuery] = (0, import_react21.useState)("");
7101
7130
  const symbolIds = getAvailableSymbols();
7102
7131
  const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
7103
7132
  const categoryMap = {
@@ -8148,13 +8177,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
8148
8177
  }
8149
8178
 
8150
8179
  // src/hooks/useDeviceControls.ts
8151
- var import_react19 = require("react");
8180
+ var import_react22 = require("react");
8152
8181
  function commandKey(nodeId, kind, suffix) {
8153
8182
  return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
8154
8183
  }
8155
8184
  function useDeviceControls(initialBindings, options) {
8156
8185
  const { commandTimeoutMs } = options ?? {};
8157
- const [controls, setControls] = (0, import_react19.useState)(() => {
8186
+ const [controls, setControls] = (0, import_react22.useState)(() => {
8158
8187
  const map = /* @__PURE__ */ new Map();
8159
8188
  if (initialBindings) {
8160
8189
  initialBindings.forEach((binding) => {
@@ -8163,12 +8192,12 @@ function useDeviceControls(initialBindings, options) {
8163
8192
  }
8164
8193
  return map;
8165
8194
  });
8166
- const pendingRef = (0, import_react19.useRef)(/* @__PURE__ */ new Map());
8167
- const [pendingCommands, setPendingCommands] = (0, import_react19.useState)(() => /* @__PURE__ */ new Set());
8168
- const syncPending = (0, import_react19.useCallback)(() => {
8195
+ const pendingRef = (0, import_react22.useRef)(/* @__PURE__ */ new Map());
8196
+ const [pendingCommands, setPendingCommands] = (0, import_react22.useState)(() => /* @__PURE__ */ new Set());
8197
+ const syncPending = (0, import_react22.useCallback)(() => {
8169
8198
  setPendingCommands(new Set(pendingRef.current.keys()));
8170
8199
  }, []);
8171
- const updateControl = (0, import_react19.useCallback)((nodeId, updates) => {
8200
+ const updateControl = (0, import_react22.useCallback)((nodeId, updates) => {
8172
8201
  setControls((prev) => {
8173
8202
  const newMap = new Map(prev);
8174
8203
  const existing = newMap.get(nodeId);
@@ -8182,7 +8211,7 @@ function useDeviceControls(initialBindings, options) {
8182
8211
  return newMap;
8183
8212
  });
8184
8213
  }, []);
8185
- const updateControlBatch = (0, import_react19.useCallback)((updates) => {
8214
+ const updateControlBatch = (0, import_react22.useCallback)((updates) => {
8186
8215
  setControls((prev) => {
8187
8216
  const newMap = new Map(prev);
8188
8217
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -8194,7 +8223,7 @@ function useDeviceControls(initialBindings, options) {
8194
8223
  return newMap;
8195
8224
  });
8196
8225
  }, []);
8197
- const updateDeviceState = (0, import_react19.useCallback)(
8226
+ const updateDeviceState = (0, import_react22.useCallback)(
8198
8227
  (nodeId, stateUpdates) => {
8199
8228
  setControls((prev) => {
8200
8229
  const newMap = new Map(prev);
@@ -8210,7 +8239,7 @@ function useDeviceControls(initialBindings, options) {
8210
8239
  },
8211
8240
  []
8212
8241
  );
8213
- const updateParameter = (0, import_react19.useCallback)(
8242
+ const updateParameter = (0, import_react22.useCallback)(
8214
8243
  (nodeId, parameterId, value) => {
8215
8244
  setControls((prev) => {
8216
8245
  const newMap = new Map(prev);
@@ -8237,27 +8266,27 @@ function useDeviceControls(initialBindings, options) {
8237
8266
  },
8238
8267
  []
8239
8268
  );
8240
- const setControlBinding = (0, import_react19.useCallback)((binding) => {
8269
+ const setControlBinding = (0, import_react22.useCallback)((binding) => {
8241
8270
  setControls((prev) => {
8242
8271
  const newMap = new Map(prev);
8243
8272
  newMap.set(binding.nodeId, binding);
8244
8273
  return newMap;
8245
8274
  });
8246
8275
  }, []);
8247
- const removeControlBinding = (0, import_react19.useCallback)((nodeId) => {
8276
+ const removeControlBinding = (0, import_react22.useCallback)((nodeId) => {
8248
8277
  setControls((prev) => {
8249
8278
  const newMap = new Map(prev);
8250
8279
  newMap.delete(nodeId);
8251
8280
  return newMap;
8252
8281
  });
8253
8282
  }, []);
8254
- const getControlBinding = (0, import_react19.useCallback)(
8283
+ const getControlBinding = (0, import_react22.useCallback)(
8255
8284
  (nodeId) => {
8256
8285
  return controls.get(nodeId);
8257
8286
  },
8258
8287
  [controls]
8259
8288
  );
8260
- const isCommandPending = (0, import_react19.useCallback)(
8289
+ const isCommandPending = (0, import_react22.useCallback)(
8261
8290
  (nodeId, kind) => {
8262
8291
  if (kind) {
8263
8292
  const prefix2 = `${nodeId}:${kind}`;
@@ -8274,7 +8303,7 @@ function useDeviceControls(initialBindings, options) {
8274
8303
  },
8275
8304
  [pendingCommands]
8276
8305
  );
8277
- const markPending = (0, import_react19.useCallback)(
8306
+ const markPending = (0, import_react22.useCallback)(
8278
8307
  (key, delta) => {
8279
8308
  const next = (pendingRef.current.get(key) ?? 0) + delta;
8280
8309
  if (next > 0) pendingRef.current.set(key, next);
@@ -8283,7 +8312,7 @@ function useDeviceControls(initialBindings, options) {
8283
8312
  },
8284
8313
  [syncPending]
8285
8314
  );
8286
- const runCommand = (0, import_react19.useCallback)(
8315
+ const runCommand = (0, import_react22.useCallback)(
8287
8316
  async (nodeId, key, invoke, messages) => {
8288
8317
  const binding = controls.get(nodeId);
8289
8318
  if (!binding) return;
@@ -8323,7 +8352,7 @@ function useDeviceControls(initialBindings, options) {
8323
8352
  },
8324
8353
  [controls, updateDeviceState, markPending, commandTimeoutMs]
8325
8354
  );
8326
- const sendModeChange = (0, import_react19.useCallback)(
8355
+ const sendModeChange = (0, import_react22.useCallback)(
8327
8356
  (nodeId, mode) => runCommand(
8328
8357
  nodeId,
8329
8358
  commandKey(nodeId, "mode"),
@@ -8332,7 +8361,7 @@ function useDeviceControls(initialBindings, options) {
8332
8361
  ),
8333
8362
  [runCommand]
8334
8363
  );
8335
- const sendParameterChange = (0, import_react19.useCallback)(
8364
+ const sendParameterChange = (0, import_react22.useCallback)(
8336
8365
  (nodeId, parameterId, value) => runCommand(
8337
8366
  nodeId,
8338
8367
  commandKey(nodeId, "parameter", parameterId),
@@ -8341,21 +8370,21 @@ function useDeviceControls(initialBindings, options) {
8341
8370
  ),
8342
8371
  [runCommand]
8343
8372
  );
8344
- const sendStartCommand = (0, import_react19.useCallback)(
8373
+ const sendStartCommand = (0, import_react22.useCallback)(
8345
8374
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
8346
8375
  success: "Start command sent",
8347
8376
  failure: "Start command failed"
8348
8377
  }),
8349
8378
  [runCommand]
8350
8379
  );
8351
- const sendStopCommand = (0, import_react19.useCallback)(
8380
+ const sendStopCommand = (0, import_react22.useCallback)(
8352
8381
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
8353
8382
  success: "Stop command sent",
8354
8383
  failure: "Stop command failed"
8355
8384
  }),
8356
8385
  [runCommand]
8357
8386
  );
8358
- const sendCustomAction = (0, import_react19.useCallback)(
8387
+ const sendCustomAction = (0, import_react22.useCallback)(
8359
8388
  (nodeId, actionId) => runCommand(
8360
8389
  nodeId,
8361
8390
  commandKey(nodeId, "action", actionId),
@@ -8408,9 +8437,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
8408
8437
  }
8409
8438
 
8410
8439
  // src/hooks/useDeviceConfigs.ts
8411
- var import_react20 = require("react");
8440
+ var import_react23 = require("react");
8412
8441
  function useDeviceConfigs(initialConfigs) {
8413
- const [configs, setConfigs] = (0, import_react20.useState)(() => {
8442
+ const [configs, setConfigs] = (0, import_react23.useState)(() => {
8414
8443
  const map = /* @__PURE__ */ new Map();
8415
8444
  if (initialConfigs) {
8416
8445
  initialConfigs.forEach((config) => {
@@ -8419,13 +8448,13 @@ function useDeviceConfigs(initialConfigs) {
8419
8448
  }
8420
8449
  return map;
8421
8450
  });
8422
- const getConfig = (0, import_react20.useCallback)(
8451
+ const getConfig = (0, import_react23.useCallback)(
8423
8452
  (nodeId) => {
8424
8453
  return configs.get(nodeId);
8425
8454
  },
8426
8455
  [configs]
8427
8456
  );
8428
- const updateConfig = (0, import_react20.useCallback)((nodeId, updates) => {
8457
+ const updateConfig = (0, import_react23.useCallback)((nodeId, updates) => {
8429
8458
  setConfigs((prev) => {
8430
8459
  const newMap = new Map(prev);
8431
8460
  const existing = newMap.get(nodeId);
@@ -8439,7 +8468,7 @@ function useDeviceConfigs(initialConfigs) {
8439
8468
  return newMap;
8440
8469
  });
8441
8470
  }, []);
8442
- const updateConfigState = (0, import_react20.useCallback)((nodeId, stateUpdates) => {
8471
+ const updateConfigState = (0, import_react23.useCallback)((nodeId, stateUpdates) => {
8443
8472
  setConfigs((prev) => {
8444
8473
  const newMap = new Map(prev);
8445
8474
  const existing = newMap.get(nodeId);
@@ -8452,7 +8481,7 @@ function useDeviceConfigs(initialConfigs) {
8452
8481
  return newMap;
8453
8482
  });
8454
8483
  }, []);
8455
- const updateConfigBatch = (0, import_react20.useCallback)((updates) => {
8484
+ const updateConfigBatch = (0, import_react23.useCallback)((updates) => {
8456
8485
  setConfigs((prev) => {
8457
8486
  const newMap = new Map(prev);
8458
8487
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -8464,7 +8493,7 @@ function useDeviceConfigs(initialConfigs) {
8464
8493
  return newMap;
8465
8494
  });
8466
8495
  }, []);
8467
- const updateParameterValue = (0, import_react20.useCallback)((nodeId, parameterId, value) => {
8496
+ const updateParameterValue = (0, import_react23.useCallback)((nodeId, parameterId, value) => {
8468
8497
  setConfigs((prev) => {
8469
8498
  const newMap = new Map(prev);
8470
8499
  const existing = newMap.get(nodeId);
@@ -8481,7 +8510,7 @@ function useDeviceConfigs(initialConfigs) {
8481
8510
  return newMap;
8482
8511
  });
8483
8512
  }, []);
8484
- const applyConfig = (0, import_react20.useCallback)(
8513
+ const applyConfig = (0, import_react23.useCallback)(
8485
8514
  async (nodeId) => {
8486
8515
  const config = configs.get(nodeId);
8487
8516
  if (!config || !config.actions.onApply) {
@@ -8514,7 +8543,7 @@ function useDeviceConfigs(initialConfigs) {
8514
8543
  },
8515
8544
  [configs, updateConfigState]
8516
8545
  );
8517
- const saveConfig = (0, import_react20.useCallback)(
8546
+ const saveConfig = (0, import_react23.useCallback)(
8518
8547
  async (nodeId) => {
8519
8548
  const config = configs.get(nodeId);
8520
8549
  if (!config || !config.actions.onSave) {
@@ -8548,7 +8577,7 @@ function useDeviceConfigs(initialConfigs) {
8548
8577
  },
8549
8578
  [configs, updateConfigState]
8550
8579
  );
8551
- const resetConfig = (0, import_react20.useCallback)(
8580
+ const resetConfig = (0, import_react23.useCallback)(
8552
8581
  async (nodeId) => {
8553
8582
  const config = configs.get(nodeId);
8554
8583
  if (!config) {
@@ -8578,7 +8607,7 @@ function useDeviceConfigs(initialConfigs) {
8578
8607
  },
8579
8608
  [configs, updateConfig, updateConfigState]
8580
8609
  );
8581
- const cancelConfig = (0, import_react20.useCallback)(
8610
+ const cancelConfig = (0, import_react23.useCallback)(
8582
8611
  (nodeId) => {
8583
8612
  const config = configs.get(nodeId);
8584
8613
  if (config?.actions.onCancel) {
@@ -8587,7 +8616,7 @@ function useDeviceConfigs(initialConfigs) {
8587
8616
  },
8588
8617
  [configs]
8589
8618
  );
8590
- const validateConfig = (0, import_react20.useCallback)(
8619
+ const validateConfig = (0, import_react23.useCallback)(
8591
8620
  (nodeId) => {
8592
8621
  const config = configs.get(nodeId);
8593
8622
  if (!config) {
@@ -8629,21 +8658,21 @@ function useDeviceConfigs(initialConfigs) {
8629
8658
  },
8630
8659
  [configs, updateConfigState]
8631
8660
  );
8632
- const setConfig = (0, import_react20.useCallback)((config) => {
8661
+ const setConfig = (0, import_react23.useCallback)((config) => {
8633
8662
  setConfigs((prev) => {
8634
8663
  const newMap = new Map(prev);
8635
8664
  newMap.set(config.nodeId, config);
8636
8665
  return newMap;
8637
8666
  });
8638
8667
  }, []);
8639
- const removeConfig = (0, import_react20.useCallback)((nodeId) => {
8668
+ const removeConfig = (0, import_react23.useCallback)((nodeId) => {
8640
8669
  setConfigs((prev) => {
8641
8670
  const newMap = new Map(prev);
8642
8671
  newMap.delete(nodeId);
8643
8672
  return newMap;
8644
8673
  });
8645
8674
  }, []);
8646
- const clearConfigs = (0, import_react20.useCallback)(() => {
8675
+ const clearConfigs = (0, import_react23.useCallback)(() => {
8647
8676
  setConfigs(/* @__PURE__ */ new Map());
8648
8677
  }, []);
8649
8678
  return {
@@ -8665,7 +8694,7 @@ function useDeviceConfigs(initialConfigs) {
8665
8694
  }
8666
8695
 
8667
8696
  // src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
8668
- var import_react21 = require("react");
8697
+ var import_react24 = require("react");
8669
8698
  var import_jsx_runtime23 = require("react/jsx-runtime");
8670
8699
  function DeviceConfigPanel({
8671
8700
  binding,
@@ -8684,7 +8713,7 @@ function DeviceConfigPanel({
8684
8713
  showControlsButton = true,
8685
8714
  embedded = false
8686
8715
  }) {
8687
- const [localValues, setLocalValues] = (0, import_react21.useState)(() => {
8716
+ const [localValues, setLocalValues] = (0, import_react24.useState)(() => {
8688
8717
  if (binding) {
8689
8718
  const values = {};
8690
8719
  binding.parameters.forEach((param) => {
@@ -8694,7 +8723,7 @@ function DeviceConfigPanel({
8694
8723
  }
8695
8724
  return {};
8696
8725
  });
8697
- const [collapsedSections, setCollapsedSections] = (0, import_react21.useState)(() => {
8726
+ const [collapsedSections, setCollapsedSections] = (0, import_react24.useState)(() => {
8698
8727
  const collapsed = /* @__PURE__ */ new Set();
8699
8728
  if (binding?.sections) {
8700
8729
  binding.sections.forEach((section) => {
@@ -8705,9 +8734,9 @@ function DeviceConfigPanel({
8705
8734
  }
8706
8735
  return collapsed;
8707
8736
  });
8708
- const [showToast, setShowToast] = (0, import_react21.useState)(true);
8709
- const [bindingId, setBindingId] = (0, import_react21.useState)(binding?.nodeId || null);
8710
- const lastResultTimestampRef = (0, import_react21.useRef)(0);
8737
+ const [showToast, setShowToast] = (0, import_react24.useState)(true);
8738
+ const [bindingId, setBindingId] = (0, import_react24.useState)(binding?.nodeId || null);
8739
+ const lastResultTimestampRef = (0, import_react24.useRef)(0);
8711
8740
  if (binding && binding.nodeId !== bindingId) {
8712
8741
  const values = {};
8713
8742
  binding.parameters.forEach((param) => {
@@ -8723,7 +8752,7 @@ function DeviceConfigPanel({
8723
8752
  setCollapsedSections(collapsed);
8724
8753
  setBindingId(binding.nodeId);
8725
8754
  }
8726
- (0, import_react21.useEffect)(() => {
8755
+ (0, import_react24.useEffect)(() => {
8727
8756
  const currentTimestamp = binding?.state.lastSaved || 0;
8728
8757
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8729
8758
  lastResultTimestampRef.current = currentTimestamp;
@@ -8740,7 +8769,7 @@ function DeviceConfigPanel({
8740
8769
  };
8741
8770
  }
8742
8771
  }, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
8743
- const parametersBySection = (0, import_react21.useMemo)(() => {
8772
+ const parametersBySection = (0, import_react24.useMemo)(() => {
8744
8773
  if (!binding) return { _unsectioned: [] };
8745
8774
  const groups = { _unsectioned: [] };
8746
8775
  binding.parameters.forEach((param) => {
@@ -8755,7 +8784,7 @@ function DeviceConfigPanel({
8755
8784
  });
8756
8785
  return groups;
8757
8786
  }, [binding]);
8758
- const sortedSections = (0, import_react21.useMemo)(() => {
8787
+ const sortedSections = (0, import_react24.useMemo)(() => {
8759
8788
  if (!binding?.sections) return [];
8760
8789
  return [...binding.sections].sort((a, b) => (a.order || 0) - (b.order || 0));
8761
8790
  }, [binding]);
@@ -9371,7 +9400,7 @@ function DeviceConfigPanel({
9371
9400
  }
9372
9401
 
9373
9402
  // src/diagram/hooks/useSimulation.ts
9374
- var import_react22 = require("react");
9403
+ var import_react25 = require("react");
9375
9404
  function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
9376
9405
  const {
9377
9406
  interval = 2e3,
@@ -9382,7 +9411,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
9382
9411
  historyLength = 10,
9383
9412
  generateValue
9384
9413
  } = options;
9385
- (0, import_react22.useEffect)(() => {
9414
+ (0, import_react25.useEffect)(() => {
9386
9415
  if (!enabled) return;
9387
9416
  const intervalId = setInterval(() => {
9388
9417
  const updates = [];