@procaaso/alphinity-ui-components 1.8.0 → 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.js CHANGED
@@ -3278,7 +3278,10 @@ var ThemeToggle = ({
3278
3278
  };
3279
3279
 
3280
3280
  // src/components/PIDCanvas/PIDCanvas.tsx
3281
- import { useCallback as useCallback8, useState as useState14, useEffect as useEffect12, useRef as useRef6 } from "react";
3281
+ import React13, { useCallback as useCallback8, useState as useState14, useEffect as useEffect12, useRef as useRef6 } from "react";
3282
+
3283
+ // src/components/PIDCanvas/NodeRenderer.tsx
3284
+ import React9 from "react";
3282
3285
 
3283
3286
  // src/diagram/symbols/mockSymbolLibrary.ts
3284
3287
  var mockSymbolLibrary = {
@@ -4500,7 +4503,7 @@ function getAvailableSymbols() {
4500
4503
 
4501
4504
  // src/components/PIDCanvas/NodeRenderer.tsx
4502
4505
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4503
- function NodeRenderer({
4506
+ function NodeRendererImpl({
4504
4507
  nodes: nodes2,
4505
4508
  selectedNodeIds,
4506
4509
  onNodeClick,
@@ -4646,10 +4649,12 @@ function NodeRenderer({
4646
4649
  );
4647
4650
  }) });
4648
4651
  }
4652
+ var NodeRenderer = React9.memo(NodeRendererImpl);
4649
4653
 
4650
4654
  // src/components/PIDCanvas/PipeRenderer.tsx
4655
+ import React10 from "react";
4651
4656
  import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4652
- function PipeRenderer({
4657
+ function PipeRendererImpl({
4653
4658
  pipes,
4654
4659
  selectedPipeIds,
4655
4660
  onPipeClick,
@@ -4826,10 +4831,36 @@ function PipeRenderer({
4826
4831
  );
4827
4832
  }) });
4828
4833
  }
4834
+ var PipeRenderer = React10.memo(PipeRendererImpl);
4829
4835
 
4830
4836
  // src/components/PIDCanvas/DataOverlay.tsx
4837
+ import React11 from "react";
4831
4838
  import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4832
- function DataOverlay({
4839
+ var PULSE_KEYFRAME_ID = "pid-data-overlay-pulse-keyframes";
4840
+ var PULSE_ANIMATION = "pid-data-overlay-pulse 1.5s ease-in-out infinite";
4841
+ function ensurePulseKeyframes() {
4842
+ if (typeof document === "undefined") return;
4843
+ if (document.getElementById(PULSE_KEYFRAME_ID)) return;
4844
+ const style = document.createElement("style");
4845
+ style.id = PULSE_KEYFRAME_ID;
4846
+ style.textContent = "@keyframes pid-data-overlay-pulse{0%{opacity:.9}50%{opacity:.3}100%{opacity:.9}}";
4847
+ document.head.appendChild(style);
4848
+ }
4849
+ function renderStatusDot(cx, cy, scale, fill) {
4850
+ ensurePulseKeyframes();
4851
+ return /* @__PURE__ */ jsx18(
4852
+ "circle",
4853
+ {
4854
+ className: "pid-data-overlay-status-dot",
4855
+ cx: cx + 35 * scale,
4856
+ cy: cy - 18 * scale,
4857
+ r: 3 * scale,
4858
+ fill,
4859
+ style: { animation: PULSE_ANIMATION }
4860
+ }
4861
+ );
4862
+ }
4863
+ function DataOverlayImpl({
4833
4864
  nodeId,
4834
4865
  x,
4835
4866
  y,
@@ -4849,6 +4880,24 @@ function DataOverlay({
4849
4880
  const backgroundColor = display?.backgroundColor;
4850
4881
  const offsetX = display?.offsetX ?? 0;
4851
4882
  const offsetY = display?.offsetY ?? 0;
4883
+ const sparklinePath = React11.useMemo(() => {
4884
+ if (!showSparkline || !history || history.length < 2) return "";
4885
+ const width = 70 * scale;
4886
+ const height = 20 * scale;
4887
+ const padding = 5 * scale;
4888
+ const effectiveWidth = width - padding * 2;
4889
+ const effectiveHeight = height - padding * 2;
4890
+ const hasEuRange = scaling?.euLow !== void 0 && scaling?.euHigh !== void 0 && scaling.euHigh !== scaling.euLow;
4891
+ const min = hasEuRange ? scaling.euLow : Math.min(...history);
4892
+ const max = hasEuRange ? scaling.euHigh : Math.max(...history);
4893
+ const range = max - min || 1;
4894
+ const points = history.map((val, i) => {
4895
+ const xPos = i / (history.length - 1) * effectiveWidth + padding;
4896
+ const yPos = height - padding - (val - min) / range * effectiveHeight;
4897
+ return `${xPos.toFixed(2)},${yPos.toFixed(2)}`;
4898
+ });
4899
+ return `M ${points.join(" L ")}`;
4900
+ }, [showSparkline, history, scaling, scale]);
4852
4901
  if (!showValue) {
4853
4902
  return /* @__PURE__ */ jsx18(Fragment6, {});
4854
4903
  }
@@ -4868,24 +4917,6 @@ function DataOverlay({
4868
4917
  const finalTextColor = textColor || colors.text;
4869
4918
  const formattedValue = formatValue(value.value);
4870
4919
  const displayText = unit ? `${formattedValue} ${unit}` : formattedValue;
4871
- const sparklinePath = (() => {
4872
- if (!showSparkline || !history || history.length < 2) return "";
4873
- const width = 70 * scale;
4874
- const height = 20 * scale;
4875
- const padding = 5 * scale;
4876
- const effectiveWidth = width - padding * 2;
4877
- const effectiveHeight = height - padding * 2;
4878
- const hasEuRange = scaling?.euLow !== void 0 && scaling?.euHigh !== void 0 && scaling.euHigh !== scaling.euLow;
4879
- const min = hasEuRange ? scaling.euLow : Math.min(...history);
4880
- const max = hasEuRange ? scaling.euHigh : Math.max(...history);
4881
- const range = max - min || 1;
4882
- const points = history.map((val, i) => {
4883
- const xPos = i / (history.length - 1) * effectiveWidth + padding;
4884
- const yPos = height - padding - (val - min) / range * effectiveHeight;
4885
- return `${xPos.toFixed(2)},${yPos.toFixed(2)}`;
4886
- });
4887
- return `M ${points.join(" L ")}`;
4888
- })();
4889
4920
  const hasSparkline = showSparkline && sparklinePath;
4890
4921
  const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
4891
4922
  const overlayWidth = 80 * scale;
@@ -4933,25 +4964,7 @@ function DataOverlay({
4933
4964
  children: displayText
4934
4965
  }
4935
4966
  ),
4936
- showStatus && value.status !== "normal" && /* @__PURE__ */ jsx18(
4937
- "circle",
4938
- {
4939
- cx: displayX + 35 * scale,
4940
- cy: displayY - 18 * scale,
4941
- r: 3 * scale,
4942
- fill: finalTextColor,
4943
- opacity: "0.9",
4944
- children: /* @__PURE__ */ jsx18(
4945
- "animate",
4946
- {
4947
- attributeName: "opacity",
4948
- values: "0.9;0.3;0.9",
4949
- dur: "1.5s",
4950
- repeatCount: "indefinite"
4951
- }
4952
- )
4953
- }
4954
- ),
4967
+ showStatus && value.status !== "normal" && renderStatusDot(displayX, displayY, scale, finalTextColor),
4955
4968
  value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs14(
4956
4969
  "text",
4957
4970
  {
@@ -4983,6 +4996,7 @@ function DataOverlay({
4983
4996
  ) })
4984
4997
  ] });
4985
4998
  }
4999
+ var DataOverlay = React11.memo(DataOverlayImpl);
4986
5000
 
4987
5001
  // src/components/PIDCanvas/PositionPanel.tsx
4988
5002
  import { useState as useState9, useEffect as useEffect6 } from "react";
@@ -6111,18 +6125,19 @@ function nodeHasPort(node, portId) {
6111
6125
 
6112
6126
  // src/components/PIDCanvas/PIDCanvas.tsx
6113
6127
  import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
6114
- function PIDCanvas({
6128
+ var DEFAULT_FEATURES = {
6129
+ pan: true,
6130
+ zoom: true,
6131
+ selection: false,
6132
+ multiSelect: true,
6133
+ telemetry: false,
6134
+ dragNodes: false
6135
+ };
6136
+ function PIDCanvasImpl({
6115
6137
  diagram,
6116
6138
  className = "",
6117
6139
  style,
6118
- features = {
6119
- pan: true,
6120
- zoom: true,
6121
- selection: false,
6122
- multiSelect: true,
6123
- telemetry: false,
6124
- dragNodes: false
6125
- },
6140
+ features = DEFAULT_FEATURES,
6126
6141
  onSelectionChange,
6127
6142
  onNodeClick,
6128
6143
  onPipeClick,
@@ -6583,52 +6598,71 @@ function PIDCanvas({
6583
6598
  if (!selectionEnabled) return;
6584
6599
  onPaste?.();
6585
6600
  }, [selectionEnabled, onPaste]);
6586
- const handleNodeDoubleClick = (nodeId, event) => {
6587
- if (!selectionEnabled) return;
6588
- console.log("Node double-clicked:", nodeId);
6589
- selectNode(nodeId, event.ctrlKey || event.metaKey);
6590
- };
6601
+ const handleNodeDoubleClick = useCallback8(
6602
+ (nodeId, event) => {
6603
+ if (!selectionEnabled) return;
6604
+ console.log("Node double-clicked:", nodeId);
6605
+ selectNode(nodeId, event.ctrlKey || event.metaKey);
6606
+ },
6607
+ [selectionEnabled, selectNode]
6608
+ );
6591
6609
  useKeyboardShortcuts({
6592
6610
  enabled: features.keyboardShortcuts ?? false,
6593
6611
  onDelete: handleDelete,
6594
6612
  onCopy: handleCopy,
6595
6613
  onPaste: handlePaste
6596
6614
  });
6597
- const handleNodeClick = (nodeId, event) => {
6598
- const connectionModeEnabled = features.connectionMode ?? false;
6599
- if (connectionModeEnabled && isConnecting) {
6600
- if (connectionSource && connectionSource !== nodeId) {
6601
- onPipeCreated?.(
6602
- connectionSource,
6603
- nodeId,
6604
- connectionSourcePort || void 0,
6605
- hoveredPort || void 0
6606
- );
6607
- setIsConnecting(false);
6608
- setConnectionSource(null);
6609
- setConnectionSourcePort(null);
6610
- setConnectionCursor(null);
6611
- setHoveredPort(null);
6615
+ const handleNodeClick = useCallback8(
6616
+ (nodeId, event) => {
6617
+ const connectionModeEnabled = features.connectionMode ?? false;
6618
+ if (connectionModeEnabled && isConnecting) {
6619
+ if (connectionSource && connectionSource !== nodeId) {
6620
+ onPipeCreated?.(
6621
+ connectionSource,
6622
+ nodeId,
6623
+ connectionSourcePort || void 0,
6624
+ hoveredPort || void 0
6625
+ );
6626
+ setIsConnecting(false);
6627
+ setConnectionSource(null);
6628
+ setConnectionSourcePort(null);
6629
+ setConnectionCursor(null);
6630
+ setHoveredPort(null);
6631
+ }
6632
+ return;
6612
6633
  }
6613
- return;
6614
- }
6615
- if (connectionModeEnabled && !isConnecting) {
6616
- setIsConnecting(true);
6617
- setConnectionSource(nodeId);
6618
- setConnectionSourcePort(hoveredPort);
6619
- return;
6620
- }
6621
- if (selectionEnabled) {
6622
- selectNode(nodeId, event.ctrlKey || event.metaKey);
6623
- }
6624
- onNodeClick?.(nodeId);
6625
- };
6626
- const handlePipeClick = (pipeId, event) => {
6627
- if (selectionEnabled) {
6628
- selectPipe(pipeId, event.ctrlKey || event.metaKey);
6629
- }
6630
- onPipeClick?.(pipeId);
6631
- };
6634
+ if (connectionModeEnabled && !isConnecting) {
6635
+ setIsConnecting(true);
6636
+ setConnectionSource(nodeId);
6637
+ setConnectionSourcePort(hoveredPort);
6638
+ return;
6639
+ }
6640
+ if (selectionEnabled) {
6641
+ selectNode(nodeId, event.ctrlKey || event.metaKey);
6642
+ }
6643
+ onNodeClick?.(nodeId);
6644
+ },
6645
+ [
6646
+ features.connectionMode,
6647
+ isConnecting,
6648
+ connectionSource,
6649
+ connectionSourcePort,
6650
+ hoveredPort,
6651
+ onPipeCreated,
6652
+ selectionEnabled,
6653
+ selectNode,
6654
+ onNodeClick
6655
+ ]
6656
+ );
6657
+ const handlePipeClick = useCallback8(
6658
+ (pipeId, event) => {
6659
+ if (selectionEnabled) {
6660
+ selectPipe(pipeId, event.ctrlKey || event.metaKey);
6661
+ }
6662
+ onPipeClick?.(pipeId);
6663
+ },
6664
+ [selectionEnabled, selectPipe, onPipeClick]
6665
+ );
6632
6666
  const handleCanvasClick = (e) => {
6633
6667
  const target = e.target;
6634
6668
  if (target.closest(".pipe-route-point")) {
@@ -6976,6 +7010,7 @@ function PIDCanvas({
6976
7010
  }
6977
7011
  );
6978
7012
  }
7013
+ var PIDCanvas = React13.memo(PIDCanvasImpl);
6979
7014
 
6980
7015
  // src/components/SymbolLibrary/SymbolLibrary.tsx
6981
7016
  import { useState as useState15 } from "react";
@@ -8617,14 +8652,17 @@ function DeviceConfigPanel({
8617
8652
  const currentTimestamp = binding?.state.lastSaved || 0;
8618
8653
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8619
8654
  lastResultTimestampRef.current = currentTimestamp;
8655
+ let hideTimer;
8620
8656
  const showTimer = setTimeout(() => {
8621
8657
  setShowToast(true);
8622
- const hideTimer = setTimeout(() => {
8658
+ hideTimer = setTimeout(() => {
8623
8659
  setShowToast(false);
8624
8660
  }, toastDuration);
8625
- return () => clearTimeout(hideTimer);
8626
8661
  }, 0);
8627
- return () => clearTimeout(showTimer);
8662
+ return () => {
8663
+ clearTimeout(showTimer);
8664
+ if (hideTimer) clearTimeout(hideTimer);
8665
+ };
8628
8666
  }
8629
8667
  }, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
8630
8668
  const parametersBySection = useMemo(() => {