@procaaso/alphinity-ui-components 1.0.5 → 1.0.7
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 +1428 -387
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +326 -3
- package/dist/index.d.ts +326 -3
- package/dist/index.js +1361 -326
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(index_exports, {
|
|
|
38
38
|
ControlPanel: () => ControlPanel,
|
|
39
39
|
DEFAULT_THRESHOLDS: () => DEFAULT_THRESHOLDS,
|
|
40
40
|
DashboardCard: () => DashboardCard,
|
|
41
|
+
DeviceControlPanel: () => DeviceControlPanel,
|
|
41
42
|
DisplayModeToggle: () => DisplayModeToggle,
|
|
42
43
|
EquipmentIndicator: () => EquipmentIndicator,
|
|
43
44
|
EquipmentIndicatorWithSparkline: () => EquipmentIndicatorWithSparkline,
|
|
@@ -49,6 +50,7 @@ __export(index_exports, {
|
|
|
49
50
|
LeftToggleButton: () => LeftToggleButton,
|
|
50
51
|
LegacyValueEntry: () => LegacyValueEntry,
|
|
51
52
|
NodeConfigPanel: () => NodeConfigPanel,
|
|
53
|
+
NodeControlsPanel: () => NodeControlsPanel,
|
|
52
54
|
PIDCanvas: () => PIDCanvas,
|
|
53
55
|
PanelContent: () => PanelContent,
|
|
54
56
|
PanelTabs: () => PanelTabs,
|
|
@@ -68,6 +70,7 @@ __export(index_exports, {
|
|
|
68
70
|
ZoomButton: () => ZoomButton,
|
|
69
71
|
ZoomControls: () => ZoomControls,
|
|
70
72
|
calculateThresholdStatus: () => calculateThresholdStatus,
|
|
73
|
+
createControlBinding: () => createControlBinding,
|
|
71
74
|
exampleDiagram: () => exampleDiagram,
|
|
72
75
|
exportDiagram: () => exportDiagram,
|
|
73
76
|
generateRoutePoints: () => generateRoutePoints,
|
|
@@ -78,6 +81,9 @@ __export(index_exports, {
|
|
|
78
81
|
mockSymbolLibrary: () => mockSymbolLibrary,
|
|
79
82
|
nodeHasPort: () => nodeHasPort,
|
|
80
83
|
overlayStyles: () => overlayStyles,
|
|
84
|
+
registerSymbol: () => registerSymbol,
|
|
85
|
+
registerSymbols: () => registerSymbols,
|
|
86
|
+
useDeviceControls: () => useDeviceControls,
|
|
81
87
|
useDrag: () => useDrag,
|
|
82
88
|
useKeyboardShortcuts: () => useKeyboardShortcuts,
|
|
83
89
|
useSelection: () => useSelection,
|
|
@@ -799,14 +805,721 @@ var StatusIndicator = ({
|
|
|
799
805
|
] });
|
|
800
806
|
};
|
|
801
807
|
|
|
808
|
+
// src/components/NodeControlsPanel/NodeControlsPanel.tsx
|
|
809
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
810
|
+
var NodeControlsPanel = ({
|
|
811
|
+
config,
|
|
812
|
+
onClose,
|
|
813
|
+
position = "bottom",
|
|
814
|
+
touchOptimized = true,
|
|
815
|
+
className = "",
|
|
816
|
+
style,
|
|
817
|
+
...props
|
|
818
|
+
}) => {
|
|
819
|
+
if (!config) return null;
|
|
820
|
+
const isBottom = position === "bottom";
|
|
821
|
+
const touchClass = touchOptimized ? "touch-optimized" : "";
|
|
822
|
+
const containerStyle = {
|
|
823
|
+
position: "fixed",
|
|
824
|
+
zIndex: 9999,
|
|
825
|
+
background: "white",
|
|
826
|
+
boxShadow: "0 -4px 16px rgba(0, 0, 0, 0.15)",
|
|
827
|
+
borderRadius: isBottom ? "16px 16px 0 0" : "0",
|
|
828
|
+
animation: isBottom ? "slideUp 0.3s ease-out" : "slideInRight 0.3s ease-out",
|
|
829
|
+
display: "flex",
|
|
830
|
+
flexDirection: "column",
|
|
831
|
+
...isBottom ? {
|
|
832
|
+
left: 0,
|
|
833
|
+
right: 0,
|
|
834
|
+
bottom: 0,
|
|
835
|
+
maxHeight: "70vh",
|
|
836
|
+
borderTop: "1px solid #e5e7eb"
|
|
837
|
+
} : {
|
|
838
|
+
right: 0,
|
|
839
|
+
top: 0,
|
|
840
|
+
bottom: 0,
|
|
841
|
+
width: touchOptimized ? "400px" : "320px",
|
|
842
|
+
borderLeft: "1px solid #e5e7eb"
|
|
843
|
+
},
|
|
844
|
+
...style
|
|
845
|
+
};
|
|
846
|
+
const headerStyle = {
|
|
847
|
+
display: "flex",
|
|
848
|
+
alignItems: "center",
|
|
849
|
+
justifyContent: "space-between",
|
|
850
|
+
padding: touchOptimized ? "1.25rem 1.5rem" : "1rem",
|
|
851
|
+
borderBottom: "2px solid #e5e7eb",
|
|
852
|
+
background: "#f9fafb",
|
|
853
|
+
flexShrink: 0
|
|
854
|
+
};
|
|
855
|
+
const titleStyle = {
|
|
856
|
+
margin: 0,
|
|
857
|
+
fontSize: touchOptimized ? "1.5rem" : "1.25rem",
|
|
858
|
+
fontWeight: 600,
|
|
859
|
+
color: "#111827"
|
|
860
|
+
};
|
|
861
|
+
const closeButtonStyle = {
|
|
862
|
+
background: "#ef4444",
|
|
863
|
+
color: "white",
|
|
864
|
+
border: "none",
|
|
865
|
+
borderRadius: "8px",
|
|
866
|
+
width: touchOptimized ? "56px" : "44px",
|
|
867
|
+
height: touchOptimized ? "56px" : "44px",
|
|
868
|
+
fontSize: touchOptimized ? "1.75rem" : "1.5rem",
|
|
869
|
+
fontWeight: "bold",
|
|
870
|
+
cursor: "pointer",
|
|
871
|
+
display: "flex",
|
|
872
|
+
alignItems: "center",
|
|
873
|
+
justifyContent: "center",
|
|
874
|
+
transition: "all 0.2s ease",
|
|
875
|
+
flexShrink: 0
|
|
876
|
+
};
|
|
877
|
+
const contentStyle = {
|
|
878
|
+
padding: touchOptimized ? "1.5rem" : "1rem",
|
|
879
|
+
overflowY: "auto",
|
|
880
|
+
flex: 1
|
|
881
|
+
};
|
|
882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
884
|
+
"div",
|
|
885
|
+
{
|
|
886
|
+
style: {
|
|
887
|
+
position: "fixed",
|
|
888
|
+
inset: 0,
|
|
889
|
+
background: "rgba(0, 0, 0, 0.3)",
|
|
890
|
+
zIndex: 9998,
|
|
891
|
+
animation: "fadeIn 0.3s ease-out"
|
|
892
|
+
},
|
|
893
|
+
onClick: onClose
|
|
894
|
+
}
|
|
895
|
+
),
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
897
|
+
"div",
|
|
898
|
+
{
|
|
899
|
+
className: `node-controls-panel ${touchClass} ${className}`.trim(),
|
|
900
|
+
style: containerStyle,
|
|
901
|
+
...props,
|
|
902
|
+
children: [
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: headerStyle, children: [
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { style: titleStyle, children: config.title }),
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
906
|
+
"button",
|
|
907
|
+
{
|
|
908
|
+
style: closeButtonStyle,
|
|
909
|
+
onClick: onClose,
|
|
910
|
+
onMouseEnter: (e) => {
|
|
911
|
+
e.currentTarget.style.background = "#dc2626";
|
|
912
|
+
e.currentTarget.style.transform = "scale(1.05)";
|
|
913
|
+
},
|
|
914
|
+
onMouseLeave: (e) => {
|
|
915
|
+
e.currentTarget.style.background = "#ef4444";
|
|
916
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
917
|
+
},
|
|
918
|
+
"aria-label": "Close",
|
|
919
|
+
children: "\u2715"
|
|
920
|
+
}
|
|
921
|
+
)
|
|
922
|
+
] }),
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: contentStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
924
|
+
ControlPanel,
|
|
925
|
+
{
|
|
926
|
+
title: config.nodeId,
|
|
927
|
+
selectedMode: config.currentMode,
|
|
928
|
+
modeOptions: config.modes,
|
|
929
|
+
onModeChange: config.onModeChange,
|
|
930
|
+
setpointValue: config.setpoint,
|
|
931
|
+
onSetpointChange: config.onSetpointChange,
|
|
932
|
+
secondSetpointValue: config.secondSetpoint,
|
|
933
|
+
onSecondSetpointChange: config.onSecondSetpointChange,
|
|
934
|
+
modeConfigs: config.modeConfigs,
|
|
935
|
+
status: config.status,
|
|
936
|
+
setpointReadOnly: config.readOnly,
|
|
937
|
+
showStartStopButtons: !!(config.onStart || config.onStop),
|
|
938
|
+
isRunning: config.isRunning,
|
|
939
|
+
onStart: config.onStart,
|
|
940
|
+
onStop: config.onStop,
|
|
941
|
+
startButtonText: config.startButtonText,
|
|
942
|
+
stopButtonText: config.stopButtonText,
|
|
943
|
+
size: touchOptimized ? "large" : "medium"
|
|
944
|
+
}
|
|
945
|
+
) })
|
|
946
|
+
]
|
|
947
|
+
}
|
|
948
|
+
),
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
|
|
950
|
+
@keyframes slideUp {
|
|
951
|
+
from {
|
|
952
|
+
transform: translateY(100%);
|
|
953
|
+
opacity: 0;
|
|
954
|
+
}
|
|
955
|
+
to {
|
|
956
|
+
transform: translateY(0);
|
|
957
|
+
opacity: 1;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
@keyframes slideInRight {
|
|
962
|
+
from {
|
|
963
|
+
transform: translateX(100%);
|
|
964
|
+
opacity: 0;
|
|
965
|
+
}
|
|
966
|
+
to {
|
|
967
|
+
transform: translateX(0);
|
|
968
|
+
opacity: 1;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
@keyframes fadeIn {
|
|
973
|
+
from {
|
|
974
|
+
opacity: 0;
|
|
975
|
+
}
|
|
976
|
+
to {
|
|
977
|
+
opacity: 1;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.node-controls-panel.touch-optimized button {
|
|
982
|
+
min-height: 56px;
|
|
983
|
+
font-size: 1.125rem;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.node-controls-panel.touch-optimized input {
|
|
987
|
+
min-height: 56px;
|
|
988
|
+
font-size: 1.125rem;
|
|
989
|
+
}
|
|
990
|
+
` })
|
|
991
|
+
] });
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
// src/components/DeviceControlPanel/DeviceControlPanel.tsx
|
|
995
|
+
var import_react5 = require("react");
|
|
996
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
997
|
+
function DeviceControlPanel({
|
|
998
|
+
binding,
|
|
999
|
+
onClose,
|
|
1000
|
+
position = "bottom",
|
|
1001
|
+
touchOptimized = true,
|
|
1002
|
+
onModeChange,
|
|
1003
|
+
onParameterChange,
|
|
1004
|
+
onStart,
|
|
1005
|
+
onStop,
|
|
1006
|
+
onCustomAction
|
|
1007
|
+
}) {
|
|
1008
|
+
const [localParameterValues, setLocalParameterValues] = (0, import_react5.useState)({});
|
|
1009
|
+
(0, import_react5.useEffect)(() => {
|
|
1010
|
+
if (binding) {
|
|
1011
|
+
const currentParams2 = binding.parameters[binding.state.currentMode] || [];
|
|
1012
|
+
const values = {};
|
|
1013
|
+
currentParams2.forEach((param) => {
|
|
1014
|
+
values[param.id] = param.value;
|
|
1015
|
+
});
|
|
1016
|
+
setLocalParameterValues(values);
|
|
1017
|
+
}
|
|
1018
|
+
}, [binding, binding?.state.currentMode]);
|
|
1019
|
+
if (!binding) return null;
|
|
1020
|
+
const currentMode = binding.state.currentMode;
|
|
1021
|
+
const currentParams = binding.parameters[currentMode] || [];
|
|
1022
|
+
const touchSize = touchOptimized ? 56 : 40;
|
|
1023
|
+
const backgroundColor = binding.theme?.backgroundColor || "#edeeef";
|
|
1024
|
+
const surfaceColor = "#f5f6f7";
|
|
1025
|
+
const borderColor = "#d2d2d2";
|
|
1026
|
+
const textColor = binding.theme?.textColor || "#000000";
|
|
1027
|
+
const mutedTextColor = "#666666";
|
|
1028
|
+
const selectedColor = "#b4d0fe";
|
|
1029
|
+
const statusColors = {
|
|
1030
|
+
normal: binding.theme?.statusColors?.normal || "#888888",
|
|
1031
|
+
// Gray (no alarm)
|
|
1032
|
+
warning: binding.theme?.statusColors?.warning || "#FFD700",
|
|
1033
|
+
// Yellow
|
|
1034
|
+
alarm: binding.theme?.statusColors?.alarm || "#FF0000",
|
|
1035
|
+
// Red
|
|
1036
|
+
fault: binding.theme?.statusColors?.fault || "#FF0000",
|
|
1037
|
+
// Red
|
|
1038
|
+
off: binding.theme?.statusColors?.off || "#666666",
|
|
1039
|
+
// Dark gray
|
|
1040
|
+
starting: binding.theme?.statusColors?.starting || "#90EE90",
|
|
1041
|
+
// Light green
|
|
1042
|
+
stopping: binding.theme?.statusColors?.stopping || "#FFD700"
|
|
1043
|
+
// Yellow
|
|
1044
|
+
};
|
|
1045
|
+
const statusColor = statusColors[binding.state.status || "normal"];
|
|
1046
|
+
const handleModeChange = (mode) => {
|
|
1047
|
+
onModeChange?.(mode);
|
|
1048
|
+
};
|
|
1049
|
+
const handleParameterCommit = (parameterId, value) => {
|
|
1050
|
+
onParameterChange?.(parameterId, value);
|
|
1051
|
+
};
|
|
1052
|
+
const handleParameterInput = (parameterId, value) => {
|
|
1053
|
+
setLocalParameterValues((prev) => ({ ...prev, [parameterId]: value }));
|
|
1054
|
+
};
|
|
1055
|
+
const panelStyle = {
|
|
1056
|
+
position: "fixed",
|
|
1057
|
+
...position === "bottom" ? {
|
|
1058
|
+
bottom: 0,
|
|
1059
|
+
left: 0,
|
|
1060
|
+
right: 0,
|
|
1061
|
+
animation: "slideUp 0.3s ease-out"
|
|
1062
|
+
} : {
|
|
1063
|
+
right: 0,
|
|
1064
|
+
top: 0,
|
|
1065
|
+
bottom: 0,
|
|
1066
|
+
width: "400px",
|
|
1067
|
+
animation: "slideIn 0.3s ease-out"
|
|
1068
|
+
},
|
|
1069
|
+
backgroundColor,
|
|
1070
|
+
color: textColor,
|
|
1071
|
+
borderRadius: position === "bottom" ? "8px 8px 0 0" : "8px 0 0 8px",
|
|
1072
|
+
boxShadow: "none",
|
|
1073
|
+
border: `2px solid ${borderColor}`,
|
|
1074
|
+
padding: "20px",
|
|
1075
|
+
zIndex: 9999,
|
|
1076
|
+
maxHeight: position === "bottom" ? "70vh" : "100vh",
|
|
1077
|
+
overflowY: "auto",
|
|
1078
|
+
...binding.display?.style
|
|
1079
|
+
};
|
|
1080
|
+
const titleText = binding.display?.title || binding.deviceName || binding.tag || binding.nodeId;
|
|
1081
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1083
|
+
"div",
|
|
1084
|
+
{
|
|
1085
|
+
style: {
|
|
1086
|
+
display: "flex",
|
|
1087
|
+
justifyContent: "space-between",
|
|
1088
|
+
alignItems: "center",
|
|
1089
|
+
marginBottom: "16px",
|
|
1090
|
+
paddingBottom: "12px",
|
|
1091
|
+
borderBottom: `2px solid ${borderColor}`
|
|
1092
|
+
},
|
|
1093
|
+
children: [
|
|
1094
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
1095
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1096
|
+
"h3",
|
|
1097
|
+
{
|
|
1098
|
+
style: {
|
|
1099
|
+
margin: 0,
|
|
1100
|
+
fontSize: "14px",
|
|
1101
|
+
fontWeight: 600,
|
|
1102
|
+
fontFamily: "Arial, sans-serif",
|
|
1103
|
+
letterSpacing: "0.5px",
|
|
1104
|
+
textTransform: "uppercase",
|
|
1105
|
+
color: textColor
|
|
1106
|
+
},
|
|
1107
|
+
children: titleText
|
|
1108
|
+
}
|
|
1109
|
+
),
|
|
1110
|
+
binding.deviceType && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1111
|
+
"div",
|
|
1112
|
+
{
|
|
1113
|
+
style: {
|
|
1114
|
+
fontSize: "11px",
|
|
1115
|
+
color: mutedTextColor,
|
|
1116
|
+
marginTop: "4px",
|
|
1117
|
+
fontFamily: "Arial, sans-serif"
|
|
1118
|
+
},
|
|
1119
|
+
children: binding.deviceType
|
|
1120
|
+
}
|
|
1121
|
+
)
|
|
1122
|
+
] }),
|
|
1123
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1124
|
+
"button",
|
|
1125
|
+
{
|
|
1126
|
+
onClick: onClose,
|
|
1127
|
+
style: {
|
|
1128
|
+
width: touchSize * 0.7,
|
|
1129
|
+
height: touchSize * 0.7,
|
|
1130
|
+
backgroundColor: surfaceColor,
|
|
1131
|
+
color: textColor,
|
|
1132
|
+
border: `2px solid ${borderColor}`,
|
|
1133
|
+
borderRadius: "2px",
|
|
1134
|
+
fontSize: "18px",
|
|
1135
|
+
cursor: "pointer",
|
|
1136
|
+
fontWeight: "bold",
|
|
1137
|
+
fontFamily: "Arial, sans-serif"
|
|
1138
|
+
},
|
|
1139
|
+
children: "\xD7"
|
|
1140
|
+
}
|
|
1141
|
+
)
|
|
1142
|
+
]
|
|
1143
|
+
}
|
|
1144
|
+
),
|
|
1145
|
+
binding.state.status && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1146
|
+
"div",
|
|
1147
|
+
{
|
|
1148
|
+
style: {
|
|
1149
|
+
display: "flex",
|
|
1150
|
+
alignItems: "center",
|
|
1151
|
+
gap: "12px",
|
|
1152
|
+
padding: "10px 12px",
|
|
1153
|
+
backgroundColor: surfaceColor,
|
|
1154
|
+
border: `1px solid ${borderColor}`,
|
|
1155
|
+
borderRadius: "6px",
|
|
1156
|
+
marginBottom: "16px"
|
|
1157
|
+
},
|
|
1158
|
+
children: [
|
|
1159
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1160
|
+
"div",
|
|
1161
|
+
{
|
|
1162
|
+
style: {
|
|
1163
|
+
width: "10px",
|
|
1164
|
+
height: "10px",
|
|
1165
|
+
borderRadius: "50%",
|
|
1166
|
+
backgroundColor: statusColor,
|
|
1167
|
+
border: "1px solid #333"
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
),
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1 }, children: [
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1173
|
+
"div",
|
|
1174
|
+
{
|
|
1175
|
+
style: {
|
|
1176
|
+
fontWeight: 600,
|
|
1177
|
+
textTransform: "uppercase",
|
|
1178
|
+
fontSize: "11px",
|
|
1179
|
+
fontFamily: "Arial, sans-serif",
|
|
1180
|
+
letterSpacing: "0.5px",
|
|
1181
|
+
color: textColor
|
|
1182
|
+
},
|
|
1183
|
+
children: binding.state.status
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
1186
|
+
binding.state.statusMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1187
|
+
"div",
|
|
1188
|
+
{
|
|
1189
|
+
style: {
|
|
1190
|
+
fontSize: "10px",
|
|
1191
|
+
color: mutedTextColor,
|
|
1192
|
+
marginTop: "2px",
|
|
1193
|
+
fontFamily: "Arial, sans-serif"
|
|
1194
|
+
},
|
|
1195
|
+
children: binding.state.statusMessage
|
|
1196
|
+
}
|
|
1197
|
+
)
|
|
1198
|
+
] }),
|
|
1199
|
+
binding.state.isRunning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1200
|
+
"div",
|
|
1201
|
+
{
|
|
1202
|
+
style: {
|
|
1203
|
+
padding: "4px 10px",
|
|
1204
|
+
backgroundColor: binding.state.isRunning ? selectedColor : surfaceColor,
|
|
1205
|
+
border: `1px solid ${borderColor}`,
|
|
1206
|
+
borderRadius: "2px",
|
|
1207
|
+
fontSize: "10px",
|
|
1208
|
+
fontWeight: 600,
|
|
1209
|
+
fontFamily: "Arial, sans-serif",
|
|
1210
|
+
letterSpacing: "0.5px",
|
|
1211
|
+
color: textColor
|
|
1212
|
+
},
|
|
1213
|
+
children: binding.state.isRunning ? "RUNNING" : "STOPPED"
|
|
1214
|
+
}
|
|
1215
|
+
)
|
|
1216
|
+
]
|
|
1217
|
+
}
|
|
1218
|
+
),
|
|
1219
|
+
binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: "16px" }, children: [
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1221
|
+
"label",
|
|
1222
|
+
{
|
|
1223
|
+
style: {
|
|
1224
|
+
display: "block",
|
|
1225
|
+
marginBottom: "8px",
|
|
1226
|
+
fontSize: "11px",
|
|
1227
|
+
fontWeight: 600,
|
|
1228
|
+
textTransform: "uppercase",
|
|
1229
|
+
letterSpacing: "0.5px",
|
|
1230
|
+
fontFamily: "Arial, sans-serif",
|
|
1231
|
+
color: mutedTextColor
|
|
1232
|
+
},
|
|
1233
|
+
children: "Mode"
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: binding.modes.map((mode) => {
|
|
1237
|
+
const isSelected = mode.value === currentMode;
|
|
1238
|
+
const isEnabled = mode.enabled !== false;
|
|
1239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1240
|
+
"button",
|
|
1241
|
+
{
|
|
1242
|
+
onClick: () => isEnabled && handleModeChange(mode.value),
|
|
1243
|
+
disabled: !isEnabled,
|
|
1244
|
+
style: {
|
|
1245
|
+
flex: 1,
|
|
1246
|
+
minWidth: "80px",
|
|
1247
|
+
height: touchSize,
|
|
1248
|
+
backgroundColor: isSelected ? selectedColor : surfaceColor,
|
|
1249
|
+
color: isSelected ? "#000000" : textColor,
|
|
1250
|
+
border: `1px solid ${isSelected ? "#b4d0fe" : borderColor}`,
|
|
1251
|
+
borderRadius: "6px",
|
|
1252
|
+
fontSize: "11px",
|
|
1253
|
+
fontWeight: 600,
|
|
1254
|
+
fontFamily: "Arial, sans-serif",
|
|
1255
|
+
letterSpacing: "0.5px",
|
|
1256
|
+
textTransform: "uppercase",
|
|
1257
|
+
cursor: isEnabled ? "pointer" : "not-allowed",
|
|
1258
|
+
opacity: isEnabled ? 1 : 0.4
|
|
1259
|
+
},
|
|
1260
|
+
children: mode.label
|
|
1261
|
+
},
|
|
1262
|
+
mode.value
|
|
1263
|
+
);
|
|
1264
|
+
}) })
|
|
1265
|
+
] }),
|
|
1266
|
+
currentParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: "16px" }, children: [
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1268
|
+
"label",
|
|
1269
|
+
{
|
|
1270
|
+
style: {
|
|
1271
|
+
display: "block",
|
|
1272
|
+
marginBottom: "8px",
|
|
1273
|
+
fontSize: "11px",
|
|
1274
|
+
fontWeight: 600,
|
|
1275
|
+
textTransform: "uppercase",
|
|
1276
|
+
letterSpacing: "0.5px",
|
|
1277
|
+
fontFamily: "Arial, sans-serif",
|
|
1278
|
+
color: mutedTextColor
|
|
1279
|
+
},
|
|
1280
|
+
children: "Parameters"
|
|
1281
|
+
}
|
|
1282
|
+
),
|
|
1283
|
+
currentParams.map((param) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1284
|
+
"div",
|
|
1285
|
+
{
|
|
1286
|
+
style: {
|
|
1287
|
+
marginBottom: "10px",
|
|
1288
|
+
padding: "10px",
|
|
1289
|
+
backgroundColor: surfaceColor,
|
|
1290
|
+
border: `1px solid ${borderColor}`,
|
|
1291
|
+
borderRadius: "6px"
|
|
1292
|
+
},
|
|
1293
|
+
children: [
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1295
|
+
"div",
|
|
1296
|
+
{
|
|
1297
|
+
style: { display: "flex", justifyContent: "space-between", marginBottom: "8px" },
|
|
1298
|
+
children: [
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1300
|
+
"span",
|
|
1301
|
+
{
|
|
1302
|
+
style: {
|
|
1303
|
+
fontSize: "11px",
|
|
1304
|
+
fontWeight: 600,
|
|
1305
|
+
textTransform: "uppercase",
|
|
1306
|
+
letterSpacing: "0.5px",
|
|
1307
|
+
fontFamily: "Arial, sans-serif",
|
|
1308
|
+
color: mutedTextColor
|
|
1309
|
+
},
|
|
1310
|
+
children: param.label
|
|
1311
|
+
}
|
|
1312
|
+
),
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1314
|
+
"span",
|
|
1315
|
+
{
|
|
1316
|
+
style: {
|
|
1317
|
+
fontSize: "13px",
|
|
1318
|
+
fontWeight: 700,
|
|
1319
|
+
fontFamily: "Arial, sans-serif",
|
|
1320
|
+
color: textColor
|
|
1321
|
+
},
|
|
1322
|
+
children: [
|
|
1323
|
+
localParameterValues[param.id] ?? param.value,
|
|
1324
|
+
" ",
|
|
1325
|
+
param.unit && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: mutedTextColor, fontSize: "10px", fontWeight: 600 }, children: param.unit })
|
|
1326
|
+
]
|
|
1327
|
+
}
|
|
1328
|
+
)
|
|
1329
|
+
]
|
|
1330
|
+
}
|
|
1331
|
+
),
|
|
1332
|
+
param.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1333
|
+
"button",
|
|
1334
|
+
{
|
|
1335
|
+
onClick: () => {
|
|
1336
|
+
const newValue = !localParameterValues[param.id];
|
|
1337
|
+
handleParameterInput(param.id, newValue);
|
|
1338
|
+
handleParameterCommit(param.id, newValue);
|
|
1339
|
+
},
|
|
1340
|
+
disabled: param.readOnly,
|
|
1341
|
+
style: {
|
|
1342
|
+
width: "100%",
|
|
1343
|
+
height: touchSize,
|
|
1344
|
+
backgroundColor: localParameterValues[param.id] ? "#3f3f46" : surfaceColor,
|
|
1345
|
+
color: localParameterValues[param.id] ? textColor : mutedTextColor,
|
|
1346
|
+
border: `1px solid ${localParameterValues[param.id] ? "#52525b" : borderColor}`,
|
|
1347
|
+
borderRadius: "4px",
|
|
1348
|
+
fontSize: "12px",
|
|
1349
|
+
fontWeight: 600,
|
|
1350
|
+
fontFamily: "monospace",
|
|
1351
|
+
letterSpacing: "0.5px",
|
|
1352
|
+
cursor: param.readOnly ? "not-allowed" : "pointer",
|
|
1353
|
+
transition: "all 0.15s"
|
|
1354
|
+
},
|
|
1355
|
+
children: localParameterValues[param.id] ? "ON" : "OFF"
|
|
1356
|
+
}
|
|
1357
|
+
) : param.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1358
|
+
"select",
|
|
1359
|
+
{
|
|
1360
|
+
value: localParameterValues[param.id] || param.value,
|
|
1361
|
+
onChange: (e) => {
|
|
1362
|
+
handleParameterInput(param.id, e.target.value);
|
|
1363
|
+
handleParameterCommit(param.id, e.target.value);
|
|
1364
|
+
},
|
|
1365
|
+
disabled: param.readOnly,
|
|
1366
|
+
style: {
|
|
1367
|
+
width: "100%",
|
|
1368
|
+
height: touchSize,
|
|
1369
|
+
backgroundColor: surfaceColor,
|
|
1370
|
+
color: textColor,
|
|
1371
|
+
border: `1px solid ${borderColor}`,
|
|
1372
|
+
borderRadius: "4px",
|
|
1373
|
+
padding: "0 12px",
|
|
1374
|
+
fontSize: "12px",
|
|
1375
|
+
fontFamily: "monospace",
|
|
1376
|
+
cursor: "pointer"
|
|
1377
|
+
},
|
|
1378
|
+
children: param.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1379
|
+
}
|
|
1380
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1381
|
+
"input",
|
|
1382
|
+
{
|
|
1383
|
+
type: param.type === "number" ? "number" : "text",
|
|
1384
|
+
value: localParameterValues[param.id] ?? param.value,
|
|
1385
|
+
onChange: (e) => handleParameterInput(
|
|
1386
|
+
param.id,
|
|
1387
|
+
param.type === "number" ? +e.target.value : e.target.value
|
|
1388
|
+
),
|
|
1389
|
+
onBlur: () => handleParameterCommit(param.id, localParameterValues[param.id]),
|
|
1390
|
+
disabled: param.readOnly,
|
|
1391
|
+
min: param.min,
|
|
1392
|
+
max: param.max,
|
|
1393
|
+
step: param.step,
|
|
1394
|
+
style: {
|
|
1395
|
+
width: "100%",
|
|
1396
|
+
height: touchSize,
|
|
1397
|
+
backgroundColor: "#ffffff",
|
|
1398
|
+
color: textColor,
|
|
1399
|
+
border: `1px solid ${borderColor}`,
|
|
1400
|
+
borderRadius: "6px",
|
|
1401
|
+
padding: "0 12px",
|
|
1402
|
+
fontSize: "14px",
|
|
1403
|
+
fontFamily: "Arial, sans-serif",
|
|
1404
|
+
fontWeight: 600
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
)
|
|
1408
|
+
]
|
|
1409
|
+
},
|
|
1410
|
+
param.id
|
|
1411
|
+
))
|
|
1412
|
+
] }),
|
|
1413
|
+
binding.display?.showStartStop !== false && (binding.capabilities?.canStart || binding.capabilities?.canStop) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: "8px", marginBottom: "16px" }, children: [
|
|
1414
|
+
binding.capabilities?.canStart && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1415
|
+
"button",
|
|
1416
|
+
{
|
|
1417
|
+
onClick: onStart,
|
|
1418
|
+
disabled: binding.state.isRunning,
|
|
1419
|
+
style: {
|
|
1420
|
+
flex: 1,
|
|
1421
|
+
height: touchSize,
|
|
1422
|
+
backgroundColor: binding.state.isRunning ? "#a3a3a3" : "#10b981",
|
|
1423
|
+
color: "#ffffff",
|
|
1424
|
+
border: "none",
|
|
1425
|
+
borderRadius: "6px",
|
|
1426
|
+
fontSize: "12px",
|
|
1427
|
+
fontWeight: 700,
|
|
1428
|
+
fontFamily: "Arial, sans-serif",
|
|
1429
|
+
letterSpacing: "0.5px",
|
|
1430
|
+
cursor: binding.state.isRunning ? "not-allowed" : "pointer",
|
|
1431
|
+
opacity: binding.state.isRunning ? 0.5 : 1
|
|
1432
|
+
},
|
|
1433
|
+
children: "START"
|
|
1434
|
+
}
|
|
1435
|
+
),
|
|
1436
|
+
binding.capabilities?.canStop && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1437
|
+
"button",
|
|
1438
|
+
{
|
|
1439
|
+
onClick: onStop,
|
|
1440
|
+
disabled: !binding.state.isRunning,
|
|
1441
|
+
style: {
|
|
1442
|
+
flex: 1,
|
|
1443
|
+
height: touchSize,
|
|
1444
|
+
backgroundColor: !binding.state.isRunning ? "#a3a3a3" : "#ef4444",
|
|
1445
|
+
color: "#ffffff",
|
|
1446
|
+
border: "none",
|
|
1447
|
+
borderRadius: "6px",
|
|
1448
|
+
fontSize: "12px",
|
|
1449
|
+
fontWeight: 700,
|
|
1450
|
+
fontFamily: "Arial, sans-serif",
|
|
1451
|
+
letterSpacing: "0.5px",
|
|
1452
|
+
cursor: !binding.state.isRunning ? "not-allowed" : "pointer",
|
|
1453
|
+
opacity: !binding.state.isRunning ? 0.5 : 1
|
|
1454
|
+
},
|
|
1455
|
+
children: "STOP"
|
|
1456
|
+
}
|
|
1457
|
+
)
|
|
1458
|
+
] }),
|
|
1459
|
+
binding.capabilities?.customActions && binding.capabilities.customActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: binding.capabilities.customActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1460
|
+
"button",
|
|
1461
|
+
{
|
|
1462
|
+
onClick: () => onCustomAction?.(action.id),
|
|
1463
|
+
style: {
|
|
1464
|
+
flex: 1,
|
|
1465
|
+
minWidth: "120px",
|
|
1466
|
+
height: touchSize,
|
|
1467
|
+
backgroundColor: surfaceColor,
|
|
1468
|
+
color: textColor,
|
|
1469
|
+
border: `1px solid ${borderColor}`,
|
|
1470
|
+
borderRadius: "6px",
|
|
1471
|
+
fontSize: "11px",
|
|
1472
|
+
fontWeight: 600,
|
|
1473
|
+
fontFamily: "monospace",
|
|
1474
|
+
letterSpacing: "0.5px",
|
|
1475
|
+
textTransform: "uppercase",
|
|
1476
|
+
cursor: "pointer",
|
|
1477
|
+
transition: "all 0.15s"
|
|
1478
|
+
},
|
|
1479
|
+
children: [
|
|
1480
|
+
action.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { marginRight: "6px" }, children: action.icon }),
|
|
1481
|
+
action.label
|
|
1482
|
+
]
|
|
1483
|
+
},
|
|
1484
|
+
action.id
|
|
1485
|
+
)) }),
|
|
1486
|
+
binding.state.lastCommandResult && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1487
|
+
"div",
|
|
1488
|
+
{
|
|
1489
|
+
style: {
|
|
1490
|
+
marginTop: "16px",
|
|
1491
|
+
padding: "10px 12px",
|
|
1492
|
+
backgroundColor: surfaceColor,
|
|
1493
|
+
border: `1px solid ${binding.state.lastCommandResult.success ? "#52525b" : borderColor}`,
|
|
1494
|
+
borderRadius: "4px",
|
|
1495
|
+
fontSize: "11px",
|
|
1496
|
+
fontFamily: "monospace",
|
|
1497
|
+
color: binding.state.lastCommandResult.success ? textColor : mutedTextColor
|
|
1498
|
+
},
|
|
1499
|
+
children: binding.state.lastCommandResult.message
|
|
1500
|
+
}
|
|
1501
|
+
),
|
|
1502
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
|
|
1503
|
+
@keyframes slideUp {
|
|
1504
|
+
from { transform: translateY(100%); }
|
|
1505
|
+
to { transform: translateY(0); }
|
|
1506
|
+
}
|
|
1507
|
+
@keyframes slideIn {
|
|
1508
|
+
from { transform: translateX(100%); }
|
|
1509
|
+
to { transform: translateX(0); }
|
|
1510
|
+
}
|
|
1511
|
+
` })
|
|
1512
|
+
] }) });
|
|
1513
|
+
}
|
|
1514
|
+
|
|
802
1515
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
803
|
-
var
|
|
1516
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
804
1517
|
var import_material3 = require("@mui/material");
|
|
805
1518
|
|
|
806
1519
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
|
|
807
1520
|
var import_material = require("@mui/material");
|
|
808
1521
|
var import_styled = __toESM(require("@emotion/styled"), 1);
|
|
809
|
-
var
|
|
1522
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
810
1523
|
var FullscreenContainer = (0, import_styled.default)(import_material.Box)(
|
|
811
1524
|
({ leftCollapsed, rightCollapsed }) => {
|
|
812
1525
|
const getGridTemplateAreas = () => {
|
|
@@ -931,7 +1644,7 @@ var DisplayModeToggle = (0, import_styled.default)(import_material.IconButton)((
|
|
|
931
1644
|
transform: "translateX(-50%) scale(1.05)"
|
|
932
1645
|
}
|
|
933
1646
|
}));
|
|
934
|
-
var ChevronLeft = () => /* @__PURE__ */ (0,
|
|
1647
|
+
var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
935
1648
|
"div",
|
|
936
1649
|
{
|
|
937
1650
|
style: {
|
|
@@ -943,7 +1656,7 @@ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
|
943
1656
|
}
|
|
944
1657
|
}
|
|
945
1658
|
);
|
|
946
|
-
var ChevronRight = () => /* @__PURE__ */ (0,
|
|
1659
|
+
var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
947
1660
|
"div",
|
|
948
1661
|
{
|
|
949
1662
|
style: {
|
|
@@ -1054,10 +1767,10 @@ var ScrollableSVGWrapper = (0, import_styled.default)("div")({
|
|
|
1054
1767
|
});
|
|
1055
1768
|
|
|
1056
1769
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
|
|
1057
|
-
var
|
|
1770
|
+
var import_react6 = require("react");
|
|
1058
1771
|
var import_material2 = require("@mui/material");
|
|
1059
1772
|
var import_styled2 = __toESM(require("@emotion/styled"), 1);
|
|
1060
|
-
var
|
|
1773
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1061
1774
|
var baseOverlayStyles = {
|
|
1062
1775
|
tank: {
|
|
1063
1776
|
background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
|
|
@@ -1119,8 +1832,8 @@ var SVGLockedOverlay = ({
|
|
|
1119
1832
|
onClick,
|
|
1120
1833
|
containerSelector = ".tff-svg-container"
|
|
1121
1834
|
}) => {
|
|
1122
|
-
const [svgOffset, setSvgOffset] = (0,
|
|
1123
|
-
(0,
|
|
1835
|
+
const [svgOffset, setSvgOffset] = (0, import_react6.useState)({ x: 0, y: 0 });
|
|
1836
|
+
(0, import_react6.useEffect)(() => {
|
|
1124
1837
|
const updateSvgOffset = () => {
|
|
1125
1838
|
const containerElement = document.querySelector(containerSelector);
|
|
1126
1839
|
const svgElement = containerElement?.querySelector("svg");
|
|
@@ -1140,7 +1853,7 @@ var SVGLockedOverlay = ({
|
|
|
1140
1853
|
const pixelX = svgX + svgOffset.x;
|
|
1141
1854
|
const pixelY = svgY + svgOffset.y;
|
|
1142
1855
|
const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
|
|
1143
|
-
return /* @__PURE__ */ (0,
|
|
1856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1144
1857
|
import_material2.Box,
|
|
1145
1858
|
{
|
|
1146
1859
|
className: `svg-locked-overlay ${className}`.trim(),
|
|
@@ -1204,7 +1917,7 @@ var CardUnit = (0, import_styled2.default)("div")({
|
|
|
1204
1917
|
});
|
|
1205
1918
|
|
|
1206
1919
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
|
|
1207
|
-
var
|
|
1920
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1208
1921
|
var TrendLine = ({
|
|
1209
1922
|
values,
|
|
1210
1923
|
width = 60,
|
|
@@ -1214,7 +1927,7 @@ var TrendLine = ({
|
|
|
1214
1927
|
backgroundColor = "rgba(255, 255, 255, 0.1)"
|
|
1215
1928
|
}) => {
|
|
1216
1929
|
if (!values || values.length < 2) {
|
|
1217
|
-
return /* @__PURE__ */ (0,
|
|
1930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1218
1931
|
"div",
|
|
1219
1932
|
{
|
|
1220
1933
|
style: {
|
|
@@ -1226,7 +1939,7 @@ var TrendLine = ({
|
|
|
1226
1939
|
alignItems: "center",
|
|
1227
1940
|
justifyContent: "center"
|
|
1228
1941
|
},
|
|
1229
|
-
children: /* @__PURE__ */ (0,
|
|
1942
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
|
|
1230
1943
|
}
|
|
1231
1944
|
);
|
|
1232
1945
|
}
|
|
@@ -1238,7 +1951,7 @@ var TrendLine = ({
|
|
|
1238
1951
|
const x = 4 + i / (values.length - 1) * (width - 8);
|
|
1239
1952
|
return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
|
|
1240
1953
|
}).join(" ");
|
|
1241
|
-
return /* @__PURE__ */ (0,
|
|
1954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1242
1955
|
"div",
|
|
1243
1956
|
{
|
|
1244
1957
|
style: {
|
|
@@ -1249,8 +1962,8 @@ var TrendLine = ({
|
|
|
1249
1962
|
position: "relative",
|
|
1250
1963
|
overflow: "hidden"
|
|
1251
1964
|
},
|
|
1252
|
-
children: /* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1965
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
|
|
1966
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1254
1967
|
"path",
|
|
1255
1968
|
{
|
|
1256
1969
|
d: pathData,
|
|
@@ -1261,7 +1974,7 @@ var TrendLine = ({
|
|
|
1261
1974
|
strokeLinejoin: "round"
|
|
1262
1975
|
}
|
|
1263
1976
|
),
|
|
1264
|
-
/* @__PURE__ */ (0,
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1265
1978
|
"circle",
|
|
1266
1979
|
{
|
|
1267
1980
|
cx: 4 + (width - 8),
|
|
@@ -1299,7 +2012,7 @@ var CircularGauge = ({
|
|
|
1299
2012
|
const borderColor = isHex ? hexToRgba(color, 0.9) : color;
|
|
1300
2013
|
const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
|
|
1301
2014
|
const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
|
|
1302
|
-
return /* @__PURE__ */ (0,
|
|
2015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1303
2016
|
"div",
|
|
1304
2017
|
{
|
|
1305
2018
|
style: {
|
|
@@ -1308,7 +2021,7 @@ var CircularGauge = ({
|
|
|
1308
2021
|
alignItems: "center"
|
|
1309
2022
|
},
|
|
1310
2023
|
children: [
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
2024
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1312
2025
|
"div",
|
|
1313
2026
|
{
|
|
1314
2027
|
style: {
|
|
@@ -1320,8 +2033,8 @@ var CircularGauge = ({
|
|
|
1320
2033
|
border: `1px solid ${borderStrokeColor}`
|
|
1321
2034
|
},
|
|
1322
2035
|
children: [
|
|
1323
|
-
/* @__PURE__ */ (0,
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
2036
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
|
|
2037
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1325
2038
|
"circle",
|
|
1326
2039
|
{
|
|
1327
2040
|
cx: size / 2,
|
|
@@ -1332,7 +2045,7 @@ var CircularGauge = ({
|
|
|
1332
2045
|
strokeWidth: 1
|
|
1333
2046
|
}
|
|
1334
2047
|
),
|
|
1335
|
-
/* @__PURE__ */ (0,
|
|
2048
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1336
2049
|
"circle",
|
|
1337
2050
|
{
|
|
1338
2051
|
cx: size / 2,
|
|
@@ -1343,7 +2056,7 @@ var CircularGauge = ({
|
|
|
1343
2056
|
fill: "transparent"
|
|
1344
2057
|
}
|
|
1345
2058
|
),
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1347
2060
|
"circle",
|
|
1348
2061
|
{
|
|
1349
2062
|
cx: size / 2,
|
|
@@ -1359,7 +2072,7 @@ var CircularGauge = ({
|
|
|
1359
2072
|
}
|
|
1360
2073
|
)
|
|
1361
2074
|
] }),
|
|
1362
|
-
/* @__PURE__ */ (0,
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1363
2076
|
"div",
|
|
1364
2077
|
{
|
|
1365
2078
|
style: {
|
|
@@ -1375,14 +2088,14 @@ var CircularGauge = ({
|
|
|
1375
2088
|
},
|
|
1376
2089
|
children: [
|
|
1377
2090
|
value.toFixed(1),
|
|
1378
|
-
/* @__PURE__ */ (0,
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
|
|
1379
2092
|
]
|
|
1380
2093
|
}
|
|
1381
2094
|
)
|
|
1382
2095
|
]
|
|
1383
2096
|
}
|
|
1384
2097
|
),
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
2098
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1386
2099
|
"div",
|
|
1387
2100
|
{
|
|
1388
2101
|
style: {
|
|
@@ -1413,7 +2126,7 @@ var Sparkline = ({ data, width, height, color }) => {
|
|
|
1413
2126
|
const y = height - 8 - (value - min) / range * (height - 8);
|
|
1414
2127
|
return `${x + 4},${y + 4}`;
|
|
1415
2128
|
}).join(" ");
|
|
1416
|
-
return /* @__PURE__ */ (0,
|
|
2129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1417
2130
|
"div",
|
|
1418
2131
|
{
|
|
1419
2132
|
style: {
|
|
@@ -1427,7 +2140,7 @@ var Sparkline = ({ data, width, height, color }) => {
|
|
|
1427
2140
|
justifyContent: "center",
|
|
1428
2141
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
1429
2142
|
},
|
|
1430
|
-
children: /* @__PURE__ */ (0,
|
|
2143
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { width, height, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
|
|
1431
2144
|
}
|
|
1432
2145
|
);
|
|
1433
2146
|
};
|
|
@@ -1441,8 +2154,8 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
1441
2154
|
sparklineOffset = { x: 40, y: 0 }
|
|
1442
2155
|
}) => {
|
|
1443
2156
|
const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
|
|
1444
|
-
return /* @__PURE__ */ (0,
|
|
1445
|
-
/* @__PURE__ */ (0,
|
|
2157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2158
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1446
2159
|
"div",
|
|
1447
2160
|
{
|
|
1448
2161
|
style: {
|
|
@@ -1463,7 +2176,7 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
1463
2176
|
children: label
|
|
1464
2177
|
}
|
|
1465
2178
|
) }),
|
|
1466
|
-
hasSparkline && /* @__PURE__ */ (0,
|
|
2179
|
+
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
|
|
1467
2180
|
] });
|
|
1468
2181
|
};
|
|
1469
2182
|
var EquipmentIndicator = ({
|
|
@@ -1476,7 +2189,7 @@ var EquipmentIndicator = ({
|
|
|
1476
2189
|
className
|
|
1477
2190
|
}) => {
|
|
1478
2191
|
const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
|
|
1479
|
-
return /* @__PURE__ */ (0,
|
|
2192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1480
2193
|
"div",
|
|
1481
2194
|
{
|
|
1482
2195
|
style: {
|
|
@@ -1500,7 +2213,7 @@ var EquipmentIndicator = ({
|
|
|
1500
2213
|
};
|
|
1501
2214
|
|
|
1502
2215
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
1503
|
-
var
|
|
2216
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1504
2217
|
function FullscreenWorkspace({
|
|
1505
2218
|
svgContent,
|
|
1506
2219
|
overlays,
|
|
@@ -1528,10 +2241,10 @@ function FullscreenWorkspace({
|
|
|
1528
2241
|
className = "",
|
|
1529
2242
|
...rest
|
|
1530
2243
|
}) {
|
|
1531
|
-
const [leftCollapsedState, setLeftCollapsedState] =
|
|
1532
|
-
const [rightCollapsedState, setRightCollapsedState] =
|
|
1533
|
-
const [internalDisplayMode, setInternalDisplayMode] =
|
|
1534
|
-
const [internalTab, setInternalTab] =
|
|
2244
|
+
const [leftCollapsedState, setLeftCollapsedState] = import_react7.default.useState(defaultLeftCollapsed);
|
|
2245
|
+
const [rightCollapsedState, setRightCollapsedState] = import_react7.default.useState(defaultRightCollapsed);
|
|
2246
|
+
const [internalDisplayMode, setInternalDisplayMode] = import_react7.default.useState(displayMode ?? defaultDisplayMode);
|
|
2247
|
+
const [internalTab, setInternalTab] = import_react7.default.useState(
|
|
1535
2248
|
tabs && tabs.length > 0 ? tabs[0].value : ""
|
|
1536
2249
|
);
|
|
1537
2250
|
const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
|
|
@@ -1539,10 +2252,10 @@ function FullscreenWorkspace({
|
|
|
1539
2252
|
const isDisplayModeControlled = displayMode !== void 0;
|
|
1540
2253
|
const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
|
|
1541
2254
|
const isTabControlled = activeTab !== void 0 && activeTab !== null;
|
|
1542
|
-
const resolvedTabs =
|
|
2255
|
+
const resolvedTabs = import_react7.default.useMemo(() => tabs ?? [], [tabs]);
|
|
1543
2256
|
const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
|
|
1544
2257
|
const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
|
|
1545
|
-
|
|
2258
|
+
import_react7.default.useEffect(() => {
|
|
1546
2259
|
if (resolvedTabs.length > 0) {
|
|
1547
2260
|
const values = resolvedTabs.map((tab) => tab.value);
|
|
1548
2261
|
if (!values.includes(currentTab)) {
|
|
@@ -1551,7 +2264,7 @@ function FullscreenWorkspace({
|
|
|
1551
2264
|
}
|
|
1552
2265
|
}
|
|
1553
2266
|
}, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
|
|
1554
|
-
|
|
2267
|
+
import_react7.default.useEffect(() => {
|
|
1555
2268
|
if (displayMode !== void 0) {
|
|
1556
2269
|
setInternalDisplayMode(displayMode);
|
|
1557
2270
|
}
|
|
@@ -1586,7 +2299,7 @@ function FullscreenWorkspace({
|
|
|
1586
2299
|
const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
|
|
1587
2300
|
const showLeftToggle = Boolean(leftPanel);
|
|
1588
2301
|
const showRightToggle = Boolean(rightPanel);
|
|
1589
|
-
return /* @__PURE__ */ (0,
|
|
2302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1590
2303
|
FullscreenContainer,
|
|
1591
2304
|
{
|
|
1592
2305
|
leftCollapsed,
|
|
@@ -1594,25 +2307,25 @@ function FullscreenWorkspace({
|
|
|
1594
2307
|
className: `tff-svg-container ${className}`.trim(),
|
|
1595
2308
|
...rest,
|
|
1596
2309
|
children: [
|
|
1597
|
-
showLeftToggle && /* @__PURE__ */ (0,
|
|
2310
|
+
showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1598
2311
|
LeftToggleButton,
|
|
1599
2312
|
{
|
|
1600
2313
|
collapsed: leftCollapsed,
|
|
1601
2314
|
onClick: handleLeftToggle,
|
|
1602
2315
|
"aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
|
|
1603
|
-
children: leftCollapsed ? /* @__PURE__ */ (0,
|
|
2316
|
+
children: leftCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRight, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronLeft, {})
|
|
1604
2317
|
}
|
|
1605
2318
|
),
|
|
1606
|
-
showRightToggle && /* @__PURE__ */ (0,
|
|
2319
|
+
showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1607
2320
|
RightToggleButton,
|
|
1608
2321
|
{
|
|
1609
2322
|
collapsed: rightCollapsed,
|
|
1610
2323
|
onClick: handleRightToggle,
|
|
1611
2324
|
"aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
|
|
1612
|
-
children: rightCollapsed ? /* @__PURE__ */ (0,
|
|
2325
|
+
children: rightCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronLeft, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRight, {})
|
|
1613
2326
|
}
|
|
1614
2327
|
),
|
|
1615
|
-
showDisplayModeToggle && /* @__PURE__ */ (0,
|
|
2328
|
+
showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1616
2329
|
DisplayModeToggle,
|
|
1617
2330
|
{
|
|
1618
2331
|
mode: currentDisplayMode,
|
|
@@ -1621,9 +2334,9 @@ function FullscreenWorkspace({
|
|
|
1621
2334
|
children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
|
|
1622
2335
|
}
|
|
1623
2336
|
),
|
|
1624
|
-
/* @__PURE__ */ (0,
|
|
1625
|
-
showZoomControls && /* @__PURE__ */ (0,
|
|
1626
|
-
/* @__PURE__ */ (0,
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SVGArea, { children: [
|
|
2338
|
+
showZoomControls && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(ZoomControls, { children: [
|
|
2339
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1627
2340
|
ZoomButton,
|
|
1628
2341
|
{
|
|
1629
2342
|
onClick: onZoomIn,
|
|
@@ -1633,7 +2346,7 @@ function FullscreenWorkspace({
|
|
|
1633
2346
|
children: "+"
|
|
1634
2347
|
}
|
|
1635
2348
|
),
|
|
1636
|
-
/* @__PURE__ */ (0,
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1637
2350
|
ZoomButton,
|
|
1638
2351
|
{
|
|
1639
2352
|
onClick: onZoomOut,
|
|
@@ -1643,7 +2356,7 @@ function FullscreenWorkspace({
|
|
|
1643
2356
|
children: "-"
|
|
1644
2357
|
}
|
|
1645
2358
|
),
|
|
1646
|
-
onResetZoom && /* @__PURE__ */ (0,
|
|
2359
|
+
onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1647
2360
|
ZoomButton,
|
|
1648
2361
|
{
|
|
1649
2362
|
onClick: onResetZoom,
|
|
@@ -1654,44 +2367,44 @@ function FullscreenWorkspace({
|
|
|
1654
2367
|
}
|
|
1655
2368
|
)
|
|
1656
2369
|
] }),
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
2370
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(FixedSVGContainer, { className: "svg-container", children: [
|
|
1658
2371
|
svgContent,
|
|
1659
2372
|
overlays
|
|
1660
2373
|
] }) })
|
|
1661
2374
|
] }),
|
|
1662
|
-
/* @__PURE__ */ (0,
|
|
1663
|
-
/* @__PURE__ */ (0,
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1664
2377
|
PanelTabs,
|
|
1665
2378
|
{
|
|
1666
2379
|
value: currentTab,
|
|
1667
2380
|
onChange: handleTabChangeInternal,
|
|
1668
2381
|
"aria-label": "Left panel tabs",
|
|
1669
|
-
children: resolvedTabs.map((tab) => /* @__PURE__ */ (0,
|
|
2382
|
+
children: resolvedTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material3.Tab, { label: tab.label, value: tab.value }, tab.value))
|
|
1670
2383
|
}
|
|
1671
2384
|
),
|
|
1672
|
-
/* @__PURE__ */ (0,
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PanelContent, { children: currentTabContent })
|
|
1673
2386
|
] }) : leftPanel }),
|
|
1674
|
-
/* @__PURE__ */ (0,
|
|
1675
|
-
/* @__PURE__ */ (0,
|
|
2387
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FooterPanel, { children: footer })
|
|
1676
2389
|
]
|
|
1677
2390
|
}
|
|
1678
2391
|
);
|
|
1679
2392
|
}
|
|
1680
2393
|
|
|
1681
2394
|
// src/theme/ThemeContext.tsx
|
|
1682
|
-
var
|
|
1683
|
-
var
|
|
1684
|
-
var ThemeContext = (0,
|
|
2395
|
+
var import_react8 = require("react");
|
|
2396
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2397
|
+
var ThemeContext = (0, import_react8.createContext)(void 0);
|
|
1685
2398
|
var useTheme = () => {
|
|
1686
|
-
const context = (0,
|
|
2399
|
+
const context = (0, import_react8.useContext)(ThemeContext);
|
|
1687
2400
|
if (!context) {
|
|
1688
2401
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
1689
2402
|
}
|
|
1690
2403
|
return context;
|
|
1691
2404
|
};
|
|
1692
2405
|
var ThemeProvider = ({ children }) => {
|
|
1693
|
-
const [theme, setThemeState] = (0,
|
|
1694
|
-
(0,
|
|
2406
|
+
const [theme, setThemeState] = (0, import_react8.useState)("modern");
|
|
2407
|
+
(0, import_react8.useEffect)(() => {
|
|
1695
2408
|
document.body.className = "";
|
|
1696
2409
|
document.body.classList.add(`theme-${theme}`);
|
|
1697
2410
|
document.documentElement.className = "";
|
|
@@ -1703,11 +2416,11 @@ var ThemeProvider = ({ children }) => {
|
|
|
1703
2416
|
const setTheme = (newTheme) => {
|
|
1704
2417
|
setThemeState(newTheme);
|
|
1705
2418
|
};
|
|
1706
|
-
return /* @__PURE__ */ (0,
|
|
2419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
|
|
1707
2420
|
};
|
|
1708
2421
|
|
|
1709
2422
|
// src/theme/ThemeToggle.tsx
|
|
1710
|
-
var
|
|
2423
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1711
2424
|
var ThemeToggle = ({
|
|
1712
2425
|
size = "medium",
|
|
1713
2426
|
position = "top-right",
|
|
@@ -1778,15 +2491,15 @@ var ThemeToggle = ({
|
|
|
1778
2491
|
transition: "all 0.2s ease",
|
|
1779
2492
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
|
|
1780
2493
|
};
|
|
1781
|
-
return /* @__PURE__ */ (0,
|
|
1782
|
-
/* @__PURE__ */ (0,
|
|
1783
|
-
/* @__PURE__ */ (0,
|
|
1784
|
-
/* @__PURE__ */ (0,
|
|
2494
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
|
|
2495
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: toggleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: thumbStyle }) }),
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
|
|
1785
2498
|
] });
|
|
1786
2499
|
};
|
|
1787
2500
|
|
|
1788
2501
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
1789
|
-
var
|
|
2502
|
+
var import_react16 = require("react");
|
|
1790
2503
|
|
|
1791
2504
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
1792
2505
|
var mockSymbolLibrary = {
|
|
@@ -1794,13 +2507,13 @@ var mockSymbolLibrary = {
|
|
|
1794
2507
|
id: "valve-gate",
|
|
1795
2508
|
name: "Gate Valve (Powered)",
|
|
1796
2509
|
category: "valve",
|
|
1797
|
-
viewBox: { x: 0, y: 0, width:
|
|
2510
|
+
viewBox: { x: 0, y: 0, width: 26, height: 26 },
|
|
1798
2511
|
ports: [
|
|
1799
|
-
{ id: "inlet", x: 0, y:
|
|
1800
|
-
{ id: "outlet", x:
|
|
2512
|
+
{ id: "inlet", x: 0, y: 18, type: "inlet", direction: "in" },
|
|
2513
|
+
{ id: "outlet", x: 26, y: 18, type: "outlet", direction: "out" }
|
|
1801
2514
|
],
|
|
1802
2515
|
svgContent: `
|
|
1803
|
-
<g>
|
|
2516
|
+
<g transform="scale(0.5)">
|
|
1804
2517
|
<!-- Actuator box -->
|
|
1805
2518
|
<rect x="16.74" y="0" width="18.02" height="18.02" fill="var(--symbol-fill, #edeeef)" stroke="var(--symbol-stroke, #666666)" pointer-events="all"/>
|
|
1806
2519
|
<!-- Actuator stem -->
|
|
@@ -1818,13 +2531,13 @@ var mockSymbolLibrary = {
|
|
|
1818
2531
|
id: "pump-positive-displacement",
|
|
1819
2532
|
name: "Positive Displacement Pump",
|
|
1820
2533
|
category: "pump",
|
|
1821
|
-
viewBox: { x: 0, y: 0, width:
|
|
2534
|
+
viewBox: { x: 0, y: 0, width: 28.125, height: 28.125 },
|
|
1822
2535
|
ports: [
|
|
1823
|
-
{ id: "inlet", x: 0, y:
|
|
1824
|
-
{ id: "outlet", x:
|
|
2536
|
+
{ id: "inlet", x: 0, y: 14.0625, type: "inlet", direction: "in" },
|
|
2537
|
+
{ id: "outlet", x: 28.125, y: 14.0625, type: "outlet", direction: "out" }
|
|
1825
2538
|
],
|
|
1826
2539
|
svgContent: `
|
|
1827
|
-
<g transform="scale(0.
|
|
2540
|
+
<g transform="scale(0.28125)">
|
|
1828
2541
|
<!-- Outer circle -->
|
|
1829
2542
|
<ellipse
|
|
1830
2543
|
cx="50"
|
|
@@ -1866,13 +2579,13 @@ var mockSymbolLibrary = {
|
|
|
1866
2579
|
id: "vannefold-bottom",
|
|
1867
2580
|
name: "Vannefold Block (Bottom)",
|
|
1868
2581
|
category: "valve",
|
|
1869
|
-
viewBox: { x: -0.
|
|
2582
|
+
viewBox: { x: -0.25, y: -0.25, width: 44, height: 33.892578 },
|
|
1870
2583
|
ports: [
|
|
1871
|
-
{ id: "bottom-inlet", x: 0, y:
|
|
1872
|
-
{ id: "top-outlet", x:
|
|
2584
|
+
{ id: "bottom-inlet", x: 0, y: 12.5, type: "control", direction: "in" },
|
|
2585
|
+
{ id: "top-outlet", x: 24, y: 32.5, type: "control", direction: "out" }
|
|
1873
2586
|
],
|
|
1874
2587
|
svgContent: `
|
|
1875
|
-
<g>
|
|
2588
|
+
<g transform="scale(0.5)">
|
|
1876
2589
|
<!-- Bottom inlet pipe -->
|
|
1877
2590
|
<path
|
|
1878
2591
|
d="M 3,29.785156 H 0 v -10 h 3 m 14,10 h 3 v -10 h -3 m -15,8 h 16 m -16,-6 h 16"
|
|
@@ -1930,13 +2643,13 @@ var mockSymbolLibrary = {
|
|
|
1930
2643
|
id: "vannefold-middle",
|
|
1931
2644
|
name: "Vannefold Block (Middle)",
|
|
1932
2645
|
category: "valve",
|
|
1933
|
-
viewBox: { x: -0.
|
|
2646
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 26.548828 },
|
|
1934
2647
|
ports: [
|
|
1935
|
-
{ id: "left-inlet", x: 0, y:
|
|
1936
|
-
{ id: "right-outlet", x:
|
|
2648
|
+
{ id: "left-inlet", x: 0, y: 13.65625, type: "control", direction: "in" },
|
|
2649
|
+
{ id: "right-outlet", x: 47.5, y: 13.65625, type: "control", direction: "out" }
|
|
1937
2650
|
],
|
|
1938
2651
|
svgContent: `
|
|
1939
|
-
<g>
|
|
2652
|
+
<g transform="scale(0.5)">
|
|
1940
2653
|
<!-- Left inlet pipe -->
|
|
1941
2654
|
<path
|
|
1942
2655
|
d="M 3,22.3125 H 0 v 10 H 3 m 14,-10 h 3 v 10 h -3 m -15,-8 h 16 m -16,6 h 16"
|
|
@@ -1985,13 +2698,13 @@ var mockSymbolLibrary = {
|
|
|
1985
2698
|
id: "vannefold-top",
|
|
1986
2699
|
name: "Vannefold Block (Top)",
|
|
1987
2700
|
category: "valve",
|
|
1988
|
-
viewBox: { x: -0.
|
|
2701
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 30.392578 },
|
|
1989
2702
|
ports: [
|
|
1990
|
-
{ id: "bottom-inlet", x: 0, y:
|
|
1991
|
-
{ id: "top-outlet", x:
|
|
2703
|
+
{ id: "bottom-inlet", x: 0, y: 17.5, type: "control", direction: "in" },
|
|
2704
|
+
{ id: "top-outlet", x: 24, y: 0, type: "control", direction: "out" }
|
|
1992
2705
|
],
|
|
1993
2706
|
svgContent: `
|
|
1994
|
-
<g>
|
|
2707
|
+
<g transform="scale(0.5)">
|
|
1995
2708
|
<!-- Bottom inlet pipe -->
|
|
1996
2709
|
<path
|
|
1997
2710
|
d="M 3,30 H 0 V 40 H 3 M 17,30 h 3 V 40 H 17 M 2,32 H 18 M 2,38 H 18"
|
|
@@ -2041,13 +2754,13 @@ var mockSymbolLibrary = {
|
|
|
2041
2754
|
id: "vannefold-top-top-inlet",
|
|
2042
2755
|
name: "Vannefold Block (Top, Top Inlet)",
|
|
2043
2756
|
category: "valve",
|
|
2044
|
-
viewBox: { x: 0, y: 0, width:
|
|
2757
|
+
viewBox: { x: 0, y: 0, width: 44, height: 33.788002 },
|
|
2045
2758
|
ports: [
|
|
2046
|
-
{ id: "top-inlet", x:
|
|
2047
|
-
{ id: "bottom-outlet", x: 0, y:
|
|
2759
|
+
{ id: "top-inlet", x: 23.5, y: 0, type: "control", direction: "in" },
|
|
2760
|
+
{ id: "bottom-outlet", x: 0, y: 21, type: "control", direction: "out" }
|
|
2048
2761
|
],
|
|
2049
2762
|
svgContent: `
|
|
2050
|
-
<g>
|
|
2763
|
+
<g transform="scale(0.5)">
|
|
2051
2764
|
<!-- Top inlet pipe flange -->
|
|
2052
2765
|
<path
|
|
2053
2766
|
d="M 52,3 V 1.3598666e-8 H 42 V 3 m 10,14 v 3 H 42 V 17 M 50,2 V 18 M 44,2 v 16"
|
|
@@ -2105,13 +2818,13 @@ var mockSymbolLibrary = {
|
|
|
2105
2818
|
id: "vannefold-left",
|
|
2106
2819
|
name: "Vannefold Block (Left)",
|
|
2107
2820
|
category: "valve",
|
|
2108
|
-
viewBox: { x: 0, y: 0, width:
|
|
2821
|
+
viewBox: { x: 0, y: 0, width: 33.892578, height: 44.25 },
|
|
2109
2822
|
ports: [
|
|
2110
|
-
{ id: "left-inlet", x: 0, y:
|
|
2111
|
-
{ id: "right-outlet", x:
|
|
2823
|
+
{ id: "left-inlet", x: 0, y: 20.75, type: "control", direction: "in" },
|
|
2824
|
+
{ id: "right-outlet", x: 21, y: 43.5, type: "control", direction: "out" }
|
|
2112
2825
|
],
|
|
2113
2826
|
svgContent: `
|
|
2114
|
-
<g>
|
|
2827
|
+
<g transform="scale(0.5)">
|
|
2115
2828
|
<!-- Left inlet pipe flange -->
|
|
2116
2829
|
<path
|
|
2117
2830
|
d="M 3,46.5 H 2.8789924e-8 v -10 H 3 m 14,10 h 3 v -10 h -3 m -15,8 h 16 m -16,-6 h 16"
|
|
@@ -2168,13 +2881,13 @@ var mockSymbolLibrary = {
|
|
|
2168
2881
|
id: "vannefold-right",
|
|
2169
2882
|
name: "Vannefold Block (Right)",
|
|
2170
2883
|
category: "valve",
|
|
2171
|
-
viewBox: { x: 0, y: 0, width:
|
|
2884
|
+
viewBox: { x: 0, y: 0, width: 33.892578, height: 44.25 },
|
|
2172
2885
|
ports: [
|
|
2173
|
-
{ id: "right-inlet", x:
|
|
2174
|
-
{ id: "left-outlet", x:
|
|
2886
|
+
{ id: "right-inlet", x: 33.892578, y: 20.75, type: "control", direction: "in" },
|
|
2887
|
+
{ id: "left-outlet", x: 12.392578, y: 43.75, type: "control", direction: "out" }
|
|
2175
2888
|
],
|
|
2176
2889
|
svgContent: `
|
|
2177
|
-
<g>
|
|
2890
|
+
<g transform="scale(0.5)">
|
|
2178
2891
|
<!-- Right inlet pipe flange -->
|
|
2179
2892
|
<path
|
|
2180
2893
|
d="m 63.785156,46.5 h 3 v -10 h -3 m -14,10 h -3 v -10 h 3 m 15,8 h -16 m 16,-6 h -16"
|
|
@@ -2231,16 +2944,16 @@ var mockSymbolLibrary = {
|
|
|
2231
2944
|
id: "pixer",
|
|
2232
2945
|
name: "Pixer",
|
|
2233
2946
|
category: "pump",
|
|
2234
|
-
viewBox: { x: 0, y: 0, width:
|
|
2947
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
2235
2948
|
ports: [
|
|
2236
|
-
{ id: "right-outlet", x:
|
|
2237
|
-
{ id: "left-outlet", x: 0, y:
|
|
2238
|
-
{ id: "left-inlet", x:
|
|
2239
|
-
{ id: "right-inlet", x: 0, y:
|
|
2240
|
-
{ id: "top-inlet", x:
|
|
2949
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
2950
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
2951
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
2952
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
2953
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
2241
2954
|
],
|
|
2242
2955
|
svgContent: `
|
|
2243
|
-
<g transform="scale(0.
|
|
2956
|
+
<g transform="scale(0.0984375) translate(-195, -186)">
|
|
2244
2957
|
<!-- Top mounting flange -->
|
|
2245
2958
|
<rect
|
|
2246
2959
|
width="141.313"
|
|
@@ -2505,16 +3218,16 @@ var mockSymbolLibrary = {
|
|
|
2505
3218
|
id: "pixer-barb",
|
|
2506
3219
|
name: "Pixer (Hose Barb)",
|
|
2507
3220
|
category: "pump",
|
|
2508
|
-
viewBox: { x: 0, y: 0, width:
|
|
3221
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
2509
3222
|
ports: [
|
|
2510
|
-
{ id: "right-outlet", x:
|
|
2511
|
-
{ id: "left-outlet", x: 0, y:
|
|
2512
|
-
{ id: "left-inlet", x:
|
|
2513
|
-
{ id: "right-inlet", x: 0, y:
|
|
2514
|
-
{ id: "top-inlet", x:
|
|
3223
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
3224
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
3225
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
3226
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
3227
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
2515
3228
|
],
|
|
2516
3229
|
svgContent: `
|
|
2517
|
-
<g transform="scale(0.
|
|
3230
|
+
<g transform="scale(0.0984375) translate(-195, -186)">
|
|
2518
3231
|
<!-- Hose barb ridges at top -->
|
|
2519
3232
|
<rect
|
|
2520
3233
|
width="20"
|
|
@@ -2796,15 +3509,15 @@ var mockSymbolLibrary = {
|
|
|
2796
3509
|
id: "vessel-balloon",
|
|
2797
3510
|
name: "Vessel",
|
|
2798
3511
|
category: "vessel",
|
|
2799
|
-
viewBox: { x: 0, y: 0, width:
|
|
3512
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 45.5 },
|
|
2800
3513
|
ports: [
|
|
2801
|
-
{ id: "top", type: "inlet", x:
|
|
2802
|
-
{ id: "left", type: "inlet", x: 5, y:
|
|
2803
|
-
{ id: "right", type: "outlet", x:
|
|
2804
|
-
{ id: "bottom", type: "outlet", x:
|
|
3514
|
+
{ id: "top", type: "inlet", x: 12.65625, y: 0 },
|
|
3515
|
+
{ id: "left", type: "inlet", x: 2.5, y: 19.5 },
|
|
3516
|
+
{ id: "right", type: "outlet", x: 22.8125, y: 19.5 },
|
|
3517
|
+
{ id: "bottom", type: "outlet", x: 12.65625, y: 45.5 }
|
|
2805
3518
|
],
|
|
2806
3519
|
svgContent: `
|
|
2807
|
-
<g transform="scale(0.
|
|
3520
|
+
<g transform="scale(0.0984375) translate(-195, -100)">
|
|
2808
3521
|
<!-- Top opening nozzle -->
|
|
2809
3522
|
<rect
|
|
2810
3523
|
width="65"
|
|
@@ -2869,19 +3582,53 @@ var mockSymbolLibrary = {
|
|
|
2869
3582
|
tags: ["vessel", "storage", "tank", "balloon"]
|
|
2870
3583
|
}
|
|
2871
3584
|
},
|
|
3585
|
+
"hollow-fiber": {
|
|
3586
|
+
id: "hollow-fiber",
|
|
3587
|
+
name: "Hollow Fiber",
|
|
3588
|
+
category: "other",
|
|
3589
|
+
viewBox: { x: 0, y: 0, width: 30, height: 109 },
|
|
3590
|
+
ports: [
|
|
3591
|
+
{ id: "top-left", type: "outlet", x: 10, y: 2.75 },
|
|
3592
|
+
{ id: "top-right", type: "outlet", x: 24.5, y: 22.25 },
|
|
3593
|
+
{ id: "bottom-left", type: "inlet", x: 10, y: 106.25 },
|
|
3594
|
+
{ id: "bottom-right", type: "inlet", x: 24.5, y: 87.25 }
|
|
3595
|
+
],
|
|
3596
|
+
svgContent: `
|
|
3597
|
+
<g transform="scale(0.5)">
|
|
3598
|
+
<!-- Top left flange -->
|
|
3599
|
+
<rect x="10.5" y="0.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
3600
|
+
|
|
3601
|
+
<!-- Top right flange -->
|
|
3602
|
+
<rect x="39.5" y="39.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
3603
|
+
|
|
3604
|
+
<!-- Bottom left flange -->
|
|
3605
|
+
<rect x="10.5" y="207.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
3606
|
+
|
|
3607
|
+
<!-- Bottom right flange -->
|
|
3608
|
+
<rect x="39.5" y="169.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
3609
|
+
|
|
3610
|
+
<!-- Main vessel body -->
|
|
3611
|
+
<rect x="0.5" y="9.5" width="40" height="199.5" rx="6" ry="6" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
3612
|
+
</g>
|
|
3613
|
+
`,
|
|
3614
|
+
metadata: {
|
|
3615
|
+
description: "Hollow fiber filter module with multiple inlet/outlet connections",
|
|
3616
|
+
tags: ["filter", "hollow-fiber", "filtration", "separation", "membrane"]
|
|
3617
|
+
}
|
|
3618
|
+
},
|
|
2872
3619
|
"psr-f": {
|
|
2873
3620
|
id: "psr-f",
|
|
2874
3621
|
name: "PSR F",
|
|
2875
3622
|
category: "instrument",
|
|
2876
|
-
viewBox: { x: 0, y: 0, width:
|
|
3623
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
2877
3624
|
ports: [
|
|
2878
|
-
{ id: "top", type: "signal", x:
|
|
2879
|
-
{ id: "right", type: "signal", x:
|
|
2880
|
-
{ id: "bottom", type: "signal", x:
|
|
2881
|
-
{ id: "left", type: "signal", x:
|
|
3625
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
3626
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
3627
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
3628
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
2882
3629
|
],
|
|
2883
3630
|
svgContent: `
|
|
2884
|
-
<g transform="scale(0.
|
|
3631
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2885
3632
|
<!-- Circle background -->
|
|
2886
3633
|
<ellipse
|
|
2887
3634
|
cx="28.5"
|
|
@@ -2915,15 +3662,15 @@ var mockSymbolLibrary = {
|
|
|
2915
3662
|
id: "psr-p",
|
|
2916
3663
|
name: "PSR P",
|
|
2917
3664
|
category: "instrument",
|
|
2918
|
-
viewBox: { x: 0, y: 0, width:
|
|
3665
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
2919
3666
|
ports: [
|
|
2920
|
-
{ id: "top", type: "signal", x:
|
|
2921
|
-
{ id: "right", type: "signal", x:
|
|
2922
|
-
{ id: "bottom", type: "signal", x:
|
|
2923
|
-
{ id: "left", type: "signal", x:
|
|
3667
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
3668
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
3669
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
3670
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
2924
3671
|
],
|
|
2925
3672
|
svgContent: `
|
|
2926
|
-
<g transform="scale(0.
|
|
3673
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2927
3674
|
<!-- Circle background -->
|
|
2928
3675
|
<ellipse
|
|
2929
3676
|
cx="28.5"
|
|
@@ -2954,15 +3701,26 @@ var mockSymbolLibrary = {
|
|
|
2954
3701
|
}
|
|
2955
3702
|
}
|
|
2956
3703
|
};
|
|
3704
|
+
var customSymbols = {};
|
|
3705
|
+
function registerSymbol(symbol) {
|
|
3706
|
+
customSymbols[symbol.id] = symbol;
|
|
3707
|
+
}
|
|
3708
|
+
function registerSymbols(symbols) {
|
|
3709
|
+
if (Array.isArray(symbols)) {
|
|
3710
|
+
symbols.forEach((symbol) => registerSymbol(symbol));
|
|
3711
|
+
} else {
|
|
3712
|
+
Object.values(symbols).forEach((symbol) => registerSymbol(symbol));
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
2957
3715
|
function getSymbolDefinition(symbolId) {
|
|
2958
|
-
return mockSymbolLibrary[symbolId];
|
|
3716
|
+
return customSymbols[symbolId] ?? mockSymbolLibrary[symbolId];
|
|
2959
3717
|
}
|
|
2960
3718
|
function getAvailableSymbols() {
|
|
2961
|
-
return Object.keys(mockSymbolLibrary);
|
|
3719
|
+
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
2962
3720
|
}
|
|
2963
3721
|
|
|
2964
3722
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
2965
|
-
var
|
|
3723
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2966
3724
|
function NodeRenderer({
|
|
2967
3725
|
nodes: nodes2,
|
|
2968
3726
|
selectedNodeIds,
|
|
@@ -2973,13 +3731,13 @@ function NodeRenderer({
|
|
|
2973
3731
|
dragOffset = { x: 0, y: 0 },
|
|
2974
3732
|
enableDrag = false
|
|
2975
3733
|
}) {
|
|
2976
|
-
return /* @__PURE__ */ (0,
|
|
3734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
|
|
2977
3735
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
2978
3736
|
const isSelected = selectedNodeIds?.has(node.id) ?? false;
|
|
2979
3737
|
const isDragging = draggingNodeId === node.id;
|
|
2980
3738
|
if (!symbol) {
|
|
2981
|
-
return /* @__PURE__ */ (0,
|
|
2982
|
-
/* @__PURE__ */ (0,
|
|
3739
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { children: [
|
|
3740
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2983
3741
|
"circle",
|
|
2984
3742
|
{
|
|
2985
3743
|
cx: node.transform.x,
|
|
@@ -2991,7 +3749,7 @@ function NodeRenderer({
|
|
|
2991
3749
|
strokeWidth: "2"
|
|
2992
3750
|
}
|
|
2993
3751
|
),
|
|
2994
|
-
/* @__PURE__ */ (0,
|
|
3752
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2995
3753
|
"text",
|
|
2996
3754
|
{
|
|
2997
3755
|
x: node.transform.x,
|
|
@@ -3048,7 +3806,7 @@ function NodeRenderer({
|
|
|
3048
3806
|
};
|
|
3049
3807
|
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
3050
3808
|
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
3051
|
-
return /* @__PURE__ */ (0,
|
|
3809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
3052
3810
|
"g",
|
|
3053
3811
|
{
|
|
3054
3812
|
"data-node-id": node.id,
|
|
@@ -3081,7 +3839,7 @@ function NodeRenderer({
|
|
|
3081
3839
|
}
|
|
3082
3840
|
},
|
|
3083
3841
|
children: [
|
|
3084
|
-
isSelected && /* @__PURE__ */ (0,
|
|
3842
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3085
3843
|
"rect",
|
|
3086
3844
|
{
|
|
3087
3845
|
x: "-5",
|
|
@@ -3096,7 +3854,7 @@ function NodeRenderer({
|
|
|
3096
3854
|
pointerEvents: "none"
|
|
3097
3855
|
}
|
|
3098
3856
|
),
|
|
3099
|
-
/* @__PURE__ */ (0,
|
|
3857
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3100
3858
|
"g",
|
|
3101
3859
|
{
|
|
3102
3860
|
dangerouslySetInnerHTML: { __html: symbol.svgContent },
|
|
@@ -3104,7 +3862,7 @@ function NodeRenderer({
|
|
|
3104
3862
|
style: { pointerEvents: "auto" }
|
|
3105
3863
|
}
|
|
3106
3864
|
),
|
|
3107
|
-
/* @__PURE__ */ (0,
|
|
3865
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3108
3866
|
"text",
|
|
3109
3867
|
{
|
|
3110
3868
|
x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
|
|
@@ -3125,7 +3883,7 @@ function NodeRenderer({
|
|
|
3125
3883
|
}
|
|
3126
3884
|
|
|
3127
3885
|
// src/components/PIDCanvas/PipeRenderer.tsx
|
|
3128
|
-
var
|
|
3886
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3129
3887
|
function PipeRenderer({
|
|
3130
3888
|
pipes,
|
|
3131
3889
|
selectedPipeIds,
|
|
@@ -3140,7 +3898,7 @@ function PipeRenderer({
|
|
|
3140
3898
|
waypointDragOffset,
|
|
3141
3899
|
onPipeSegmentClick
|
|
3142
3900
|
}) {
|
|
3143
|
-
return /* @__PURE__ */ (0,
|
|
3901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
|
|
3144
3902
|
const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
|
|
3145
3903
|
const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
|
|
3146
3904
|
const showEditingControls = enableWaypointEditing && isSelected;
|
|
@@ -3159,7 +3917,7 @@ function PipeRenderer({
|
|
|
3159
3917
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
3160
3918
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
3161
3919
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
3162
|
-
return /* @__PURE__ */ (0,
|
|
3920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
3163
3921
|
"g",
|
|
3164
3922
|
{
|
|
3165
3923
|
"data-pipe-id": pipe.id,
|
|
@@ -3172,8 +3930,8 @@ function PipeRenderer({
|
|
|
3172
3930
|
cursor: onPipeClick ? "pointer" : "default"
|
|
3173
3931
|
},
|
|
3174
3932
|
children: [
|
|
3175
|
-
!enableWaypointEditing && /* @__PURE__ */ (0,
|
|
3176
|
-
onPipeClick && /* @__PURE__ */ (0,
|
|
3933
|
+
!enableWaypointEditing && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
3934
|
+
onPipeClick && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3177
3935
|
"polyline",
|
|
3178
3936
|
{
|
|
3179
3937
|
points: pointsString,
|
|
@@ -3185,7 +3943,7 @@ function PipeRenderer({
|
|
|
3185
3943
|
pointerEvents: "stroke"
|
|
3186
3944
|
}
|
|
3187
3945
|
),
|
|
3188
|
-
/* @__PURE__ */ (0,
|
|
3946
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3189
3947
|
"polyline",
|
|
3190
3948
|
{
|
|
3191
3949
|
points: pointsString,
|
|
@@ -3209,7 +3967,7 @@ function PipeRenderer({
|
|
|
3209
3967
|
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3210
3968
|
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3211
3969
|
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
3212
|
-
return /* @__PURE__ */ (0,
|
|
3970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3213
3971
|
"circle",
|
|
3214
3972
|
{
|
|
3215
3973
|
cx: point.x,
|
|
@@ -3246,12 +4004,12 @@ function PipeRenderer({
|
|
|
3246
4004
|
`${pipe.id}-point-${idx}`
|
|
3247
4005
|
);
|
|
3248
4006
|
}),
|
|
3249
|
-
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0,
|
|
4007
|
+
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: displayPoints.slice(0, -1).map((point, idx) => {
|
|
3250
4008
|
const nextPoint = displayPoints[idx + 1];
|
|
3251
4009
|
const midX = (point.x + nextPoint.x) / 2;
|
|
3252
4010
|
const midY = (point.y + nextPoint.y) / 2;
|
|
3253
|
-
return /* @__PURE__ */ (0,
|
|
3254
|
-
/* @__PURE__ */ (0,
|
|
4011
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3255
4013
|
"circle",
|
|
3256
4014
|
{
|
|
3257
4015
|
cx: midX,
|
|
@@ -3267,7 +4025,7 @@ function PipeRenderer({
|
|
|
3267
4025
|
}
|
|
3268
4026
|
}
|
|
3269
4027
|
),
|
|
3270
|
-
/* @__PURE__ */ (0,
|
|
4028
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3271
4029
|
"circle",
|
|
3272
4030
|
{
|
|
3273
4031
|
cx: midX,
|
|
@@ -3283,7 +4041,7 @@ function PipeRenderer({
|
|
|
3283
4041
|
)
|
|
3284
4042
|
] }, `${pipe.id}-segment-${idx}`);
|
|
3285
4043
|
}) }),
|
|
3286
|
-
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0,
|
|
4044
|
+
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3287
4045
|
"text",
|
|
3288
4046
|
{
|
|
3289
4047
|
x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
|
|
@@ -3305,7 +4063,7 @@ function PipeRenderer({
|
|
|
3305
4063
|
}
|
|
3306
4064
|
|
|
3307
4065
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
3308
|
-
var
|
|
4066
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3309
4067
|
function DataOverlay({
|
|
3310
4068
|
nodeId,
|
|
3311
4069
|
x,
|
|
@@ -3325,7 +4083,7 @@ function DataOverlay({
|
|
|
3325
4083
|
const offsetX = display?.offsetX ?? 0;
|
|
3326
4084
|
const offsetY = display?.offsetY ?? 0;
|
|
3327
4085
|
if (!showValue) {
|
|
3328
|
-
return /* @__PURE__ */ (0,
|
|
4086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, {});
|
|
3329
4087
|
}
|
|
3330
4088
|
const formatValue = (val) => {
|
|
3331
4089
|
if (typeof val === "number") {
|
|
@@ -3343,9 +4101,14 @@ function DataOverlay({
|
|
|
3343
4101
|
fault: { bg: "#dc2626", text: "#ffffff", border: "#b91c1c" },
|
|
3344
4102
|
off: { bg: "#6b7280", text: "#ffffff", border: "#4b5563" }
|
|
3345
4103
|
};
|
|
3346
|
-
const
|
|
3347
|
-
|
|
3348
|
-
|
|
4104
|
+
const getStatusColors = () => {
|
|
4105
|
+
const customColor = telemetry.statusColors?.[value.status];
|
|
4106
|
+
if (customColor) {
|
|
4107
|
+
return { bg: customColor, text: "#ffffff", border: customColor };
|
|
4108
|
+
}
|
|
4109
|
+
return defaultStatusColors[value.status] || defaultStatusColors.normal;
|
|
4110
|
+
};
|
|
4111
|
+
const statusColors = getStatusColors();
|
|
3349
4112
|
const colors = backgroundColor && backgroundColor !== "status" ? { bg: backgroundColor, text: textColor || "#ffffff", border: backgroundColor } : statusColors;
|
|
3350
4113
|
const finalTextColor = textColor || colors.text;
|
|
3351
4114
|
const formattedValue = formatValue(value.value);
|
|
@@ -3372,8 +4135,8 @@ function DataOverlay({
|
|
|
3372
4135
|
const overlayWidth = 80 * scale;
|
|
3373
4136
|
const displayX = x + offsetX;
|
|
3374
4137
|
const displayY = y + offsetY;
|
|
3375
|
-
return /* @__PURE__ */ (0,
|
|
3376
|
-
/* @__PURE__ */ (0,
|
|
4138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
4139
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3377
4140
|
"rect",
|
|
3378
4141
|
{
|
|
3379
4142
|
x: displayX - overlayWidth / 2,
|
|
@@ -3388,7 +4151,7 @@ function DataOverlay({
|
|
|
3388
4151
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
3389
4152
|
}
|
|
3390
4153
|
),
|
|
3391
|
-
label && /* @__PURE__ */ (0,
|
|
4154
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3392
4155
|
"text",
|
|
3393
4156
|
{
|
|
3394
4157
|
x: displayX,
|
|
@@ -3401,7 +4164,7 @@ function DataOverlay({
|
|
|
3401
4164
|
children: label
|
|
3402
4165
|
}
|
|
3403
4166
|
),
|
|
3404
|
-
/* @__PURE__ */ (0,
|
|
4167
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3405
4168
|
"text",
|
|
3406
4169
|
{
|
|
3407
4170
|
x: displayX,
|
|
@@ -3414,7 +4177,7 @@ function DataOverlay({
|
|
|
3414
4177
|
children: displayText
|
|
3415
4178
|
}
|
|
3416
4179
|
),
|
|
3417
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */ (0,
|
|
4180
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3418
4181
|
"circle",
|
|
3419
4182
|
{
|
|
3420
4183
|
cx: displayX + 35 * scale,
|
|
@@ -3422,7 +4185,7 @@ function DataOverlay({
|
|
|
3422
4185
|
r: 3 * scale,
|
|
3423
4186
|
fill: finalTextColor,
|
|
3424
4187
|
opacity: "0.9",
|
|
3425
|
-
children: /* @__PURE__ */ (0,
|
|
4188
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3426
4189
|
"animate",
|
|
3427
4190
|
{
|
|
3428
4191
|
attributeName: "opacity",
|
|
@@ -3433,7 +4196,7 @@ function DataOverlay({
|
|
|
3433
4196
|
)
|
|
3434
4197
|
}
|
|
3435
4198
|
),
|
|
3436
|
-
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0,
|
|
4199
|
+
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3437
4200
|
"text",
|
|
3438
4201
|
{
|
|
3439
4202
|
x: displayX,
|
|
@@ -3450,7 +4213,7 @@ function DataOverlay({
|
|
|
3450
4213
|
]
|
|
3451
4214
|
}
|
|
3452
4215
|
),
|
|
3453
|
-
hasSparkline && /* @__PURE__ */ (0,
|
|
4216
|
+
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3454
4217
|
"path",
|
|
3455
4218
|
{
|
|
3456
4219
|
d: sparklinePath,
|
|
@@ -3466,8 +4229,8 @@ function DataOverlay({
|
|
|
3466
4229
|
}
|
|
3467
4230
|
|
|
3468
4231
|
// src/components/PIDCanvas/PositionPanel.tsx
|
|
3469
|
-
var
|
|
3470
|
-
var
|
|
4232
|
+
var import_react9 = require("react");
|
|
4233
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3471
4234
|
function PositionPanel({
|
|
3472
4235
|
selectedNode,
|
|
3473
4236
|
selectedWaypoint,
|
|
@@ -3475,9 +4238,9 @@ function PositionPanel({
|
|
|
3475
4238
|
onWaypointPositionChange,
|
|
3476
4239
|
position = "top-right"
|
|
3477
4240
|
}) {
|
|
3478
|
-
const [x, setX] = (0,
|
|
3479
|
-
const [y, setY] = (0,
|
|
3480
|
-
(0,
|
|
4241
|
+
const [x, setX] = (0, import_react9.useState)("");
|
|
4242
|
+
const [y, setY] = (0, import_react9.useState)("");
|
|
4243
|
+
(0, import_react9.useEffect)(() => {
|
|
3481
4244
|
if (selectedNode) {
|
|
3482
4245
|
setX(selectedNode.transform.x.toFixed(2));
|
|
3483
4246
|
setY(selectedNode.transform.y.toFixed(2));
|
|
@@ -3536,7 +4299,7 @@ function PositionPanel({
|
|
|
3536
4299
|
"bottom-left": { bottom: 10, left: 10 },
|
|
3537
4300
|
"bottom-right": { bottom: 10, right: 10 }
|
|
3538
4301
|
};
|
|
3539
|
-
return /* @__PURE__ */ (0,
|
|
4302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3540
4303
|
"div",
|
|
3541
4304
|
{
|
|
3542
4305
|
style: {
|
|
@@ -3553,11 +4316,11 @@ function PositionPanel({
|
|
|
3553
4316
|
fontSize: "13px"
|
|
3554
4317
|
},
|
|
3555
4318
|
children: [
|
|
3556
|
-
/* @__PURE__ */ (0,
|
|
3557
|
-
/* @__PURE__ */ (0,
|
|
3558
|
-
/* @__PURE__ */ (0,
|
|
3559
|
-
/* @__PURE__ */ (0,
|
|
3560
|
-
/* @__PURE__ */ (0,
|
|
4319
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
4320
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
4322
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3561
4324
|
"input",
|
|
3562
4325
|
{
|
|
3563
4326
|
type: "number",
|
|
@@ -3575,9 +4338,9 @@ function PositionPanel({
|
|
|
3575
4338
|
}
|
|
3576
4339
|
)
|
|
3577
4340
|
] }),
|
|
3578
|
-
/* @__PURE__ */ (0,
|
|
3579
|
-
/* @__PURE__ */ (0,
|
|
3580
|
-
/* @__PURE__ */ (0,
|
|
4341
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
4342
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
4343
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3581
4344
|
"input",
|
|
3582
4345
|
{
|
|
3583
4346
|
type: "number",
|
|
@@ -3596,14 +4359,14 @@ function PositionPanel({
|
|
|
3596
4359
|
)
|
|
3597
4360
|
] })
|
|
3598
4361
|
] }),
|
|
3599
|
-
/* @__PURE__ */ (0,
|
|
4362
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3600
4363
|
]
|
|
3601
4364
|
}
|
|
3602
4365
|
);
|
|
3603
4366
|
}
|
|
3604
4367
|
|
|
3605
4368
|
// src/diagram/hooks/useViewBox.ts
|
|
3606
|
-
var
|
|
4369
|
+
var import_react10 = require("react");
|
|
3607
4370
|
function useViewBox(options) {
|
|
3608
4371
|
const {
|
|
3609
4372
|
initialViewBox,
|
|
@@ -3614,16 +4377,16 @@ function useViewBox(options) {
|
|
|
3614
4377
|
zoomSensitivity = 1e-3,
|
|
3615
4378
|
allowLeftClickPan = true
|
|
3616
4379
|
} = options;
|
|
3617
|
-
const [viewBox, setViewBox] = (0,
|
|
3618
|
-
const svgRef = (0,
|
|
3619
|
-
const isPanningRef = (0,
|
|
3620
|
-
const lastMousePosRef = (0,
|
|
3621
|
-
const spaceKeyDownRef = (0,
|
|
3622
|
-
const lastTouchDistanceRef = (0,
|
|
3623
|
-
const resetViewBox = (0,
|
|
4380
|
+
const [viewBox, setViewBox] = (0, import_react10.useState)(initialViewBox);
|
|
4381
|
+
const svgRef = (0, import_react10.useRef)(null);
|
|
4382
|
+
const isPanningRef = (0, import_react10.useRef)(false);
|
|
4383
|
+
const lastMousePosRef = (0, import_react10.useRef)({ x: 0, y: 0 });
|
|
4384
|
+
const spaceKeyDownRef = (0, import_react10.useRef)(false);
|
|
4385
|
+
const lastTouchDistanceRef = (0, import_react10.useRef)(null);
|
|
4386
|
+
const resetViewBox = (0, import_react10.useCallback)(() => {
|
|
3624
4387
|
setViewBox(initialViewBox);
|
|
3625
4388
|
}, [initialViewBox]);
|
|
3626
|
-
const zoomIn = (0,
|
|
4389
|
+
const zoomIn = (0, import_react10.useCallback)(() => {
|
|
3627
4390
|
setViewBox((prev) => {
|
|
3628
4391
|
const currentZoom = initialViewBox.width / prev.width;
|
|
3629
4392
|
const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
|
|
@@ -3640,7 +4403,7 @@ function useViewBox(options) {
|
|
|
3640
4403
|
};
|
|
3641
4404
|
});
|
|
3642
4405
|
}, [initialViewBox, minZoom]);
|
|
3643
|
-
const zoomOut = (0,
|
|
4406
|
+
const zoomOut = (0, import_react10.useCallback)(() => {
|
|
3644
4407
|
setViewBox((prev) => {
|
|
3645
4408
|
const currentZoom = initialViewBox.width / prev.width;
|
|
3646
4409
|
const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
|
|
@@ -3657,7 +4420,7 @@ function useViewBox(options) {
|
|
|
3657
4420
|
};
|
|
3658
4421
|
});
|
|
3659
4422
|
}, [initialViewBox, maxZoom]);
|
|
3660
|
-
const fitToContent = (0,
|
|
4423
|
+
const fitToContent = (0, import_react10.useCallback)((bounds, padding = 50) => {
|
|
3661
4424
|
const contentWidth = bounds.maxX - bounds.minX;
|
|
3662
4425
|
const contentHeight = bounds.maxY - bounds.minY;
|
|
3663
4426
|
if (contentWidth === 0 || contentHeight === 0) {
|
|
@@ -3685,7 +4448,7 @@ function useViewBox(options) {
|
|
|
3685
4448
|
height: newHeight
|
|
3686
4449
|
});
|
|
3687
4450
|
}, [initialViewBox]);
|
|
3688
|
-
(0,
|
|
4451
|
+
(0, import_react10.useEffect)(() => {
|
|
3689
4452
|
if (!enableZoom || !svgRef.current) return;
|
|
3690
4453
|
const svg = svgRef.current;
|
|
3691
4454
|
const handleWheel = (e) => {
|
|
@@ -3718,7 +4481,7 @@ function useViewBox(options) {
|
|
|
3718
4481
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
3719
4482
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
3720
4483
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
3721
|
-
(0,
|
|
4484
|
+
(0, import_react10.useEffect)(() => {
|
|
3722
4485
|
if (!enablePan || !svgRef.current) return;
|
|
3723
4486
|
const svg = svgRef.current;
|
|
3724
4487
|
const handleMouseDown = (e) => {
|
|
@@ -3794,7 +4557,7 @@ function useViewBox(options) {
|
|
|
3794
4557
|
window.removeEventListener("keyup", handleKeyUp);
|
|
3795
4558
|
};
|
|
3796
4559
|
}, [enablePan, allowLeftClickPan]);
|
|
3797
|
-
(0,
|
|
4560
|
+
(0, import_react10.useEffect)(() => {
|
|
3798
4561
|
if (!svgRef.current) return;
|
|
3799
4562
|
if (!enablePan && !enableZoom) return;
|
|
3800
4563
|
const svg = svgRef.current;
|
|
@@ -3885,7 +4648,7 @@ function useViewBox(options) {
|
|
|
3885
4648
|
svg.removeEventListener("touchend", handleTouchEnd);
|
|
3886
4649
|
};
|
|
3887
4650
|
}, [enablePan, enableZoom, minZoom, initialViewBox]);
|
|
3888
|
-
const screenToWorld = (0,
|
|
4651
|
+
const screenToWorld = (0, import_react10.useCallback)(
|
|
3889
4652
|
(screenX, screenY) => {
|
|
3890
4653
|
const svg = svgRef.current;
|
|
3891
4654
|
if (!svg) return { x: screenX, y: screenY };
|
|
@@ -3924,15 +4687,15 @@ function useViewBox(options) {
|
|
|
3924
4687
|
}
|
|
3925
4688
|
|
|
3926
4689
|
// src/diagram/hooks/useSelection.ts
|
|
3927
|
-
var
|
|
4690
|
+
var import_react11 = require("react");
|
|
3928
4691
|
function useSelection(options = {}) {
|
|
3929
4692
|
const {
|
|
3930
4693
|
multiSelect = true,
|
|
3931
4694
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
3932
4695
|
onSelectionChange
|
|
3933
4696
|
} = options;
|
|
3934
|
-
const [selection, setSelection] = (0,
|
|
3935
|
-
const notifyChange = (0,
|
|
4697
|
+
const [selection, setSelection] = (0, import_react11.useState)(initialSelection);
|
|
4698
|
+
const notifyChange = (0, import_react11.useCallback)(
|
|
3936
4699
|
(newSelection) => {
|
|
3937
4700
|
if (onSelectionChange) {
|
|
3938
4701
|
onSelectionChange(newSelection);
|
|
@@ -3940,15 +4703,15 @@ function useSelection(options = {}) {
|
|
|
3940
4703
|
},
|
|
3941
4704
|
[onSelectionChange]
|
|
3942
4705
|
);
|
|
3943
|
-
const isNodeSelected = (0,
|
|
4706
|
+
const isNodeSelected = (0, import_react11.useCallback)(
|
|
3944
4707
|
(nodeId) => selection.selectedNodeIds.has(nodeId),
|
|
3945
4708
|
[selection.selectedNodeIds]
|
|
3946
4709
|
);
|
|
3947
|
-
const isPipeSelected = (0,
|
|
4710
|
+
const isPipeSelected = (0, import_react11.useCallback)(
|
|
3948
4711
|
(pipeId) => selection.selectedPipeIds.has(pipeId),
|
|
3949
4712
|
[selection.selectedPipeIds]
|
|
3950
4713
|
);
|
|
3951
|
-
const selectNode = (0,
|
|
4714
|
+
const selectNode = (0, import_react11.useCallback)(
|
|
3952
4715
|
(nodeId, isMultiSelect = false) => {
|
|
3953
4716
|
setSelection((prev) => {
|
|
3954
4717
|
const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
|
|
@@ -3967,7 +4730,7 @@ function useSelection(options = {}) {
|
|
|
3967
4730
|
},
|
|
3968
4731
|
[multiSelect, notifyChange]
|
|
3969
4732
|
);
|
|
3970
|
-
const selectPipe = (0,
|
|
4733
|
+
const selectPipe = (0, import_react11.useCallback)(
|
|
3971
4734
|
(pipeId, isMultiSelect = false) => {
|
|
3972
4735
|
setSelection((prev) => {
|
|
3973
4736
|
const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
|
|
@@ -3986,7 +4749,7 @@ function useSelection(options = {}) {
|
|
|
3986
4749
|
},
|
|
3987
4750
|
[multiSelect, notifyChange]
|
|
3988
4751
|
);
|
|
3989
|
-
const clearSelection = (0,
|
|
4752
|
+
const clearSelection = (0, import_react11.useCallback)(() => {
|
|
3990
4753
|
const newSelection = {
|
|
3991
4754
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
3992
4755
|
selectedPipeIds: /* @__PURE__ */ new Set()
|
|
@@ -3994,7 +4757,7 @@ function useSelection(options = {}) {
|
|
|
3994
4757
|
setSelection(newSelection);
|
|
3995
4758
|
notifyChange(newSelection);
|
|
3996
4759
|
}, [notifyChange]);
|
|
3997
|
-
const selectNodes = (0,
|
|
4760
|
+
const selectNodes = (0, import_react11.useCallback)(
|
|
3998
4761
|
(nodeIds) => {
|
|
3999
4762
|
const newSelection = {
|
|
4000
4763
|
selectedNodeIds: new Set(nodeIds),
|
|
@@ -4005,7 +4768,7 @@ function useSelection(options = {}) {
|
|
|
4005
4768
|
},
|
|
4006
4769
|
[notifyChange]
|
|
4007
4770
|
);
|
|
4008
|
-
const selectPipes = (0,
|
|
4771
|
+
const selectPipes = (0, import_react11.useCallback)(
|
|
4009
4772
|
(pipeIds) => {
|
|
4010
4773
|
const newSelection = {
|
|
4011
4774
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
@@ -4029,23 +4792,23 @@ function useSelection(options = {}) {
|
|
|
4029
4792
|
}
|
|
4030
4793
|
|
|
4031
4794
|
// src/diagram/hooks/useTelemetry.ts
|
|
4032
|
-
var
|
|
4795
|
+
var import_react12 = require("react");
|
|
4033
4796
|
function useTelemetry(options = {}) {
|
|
4034
4797
|
const {
|
|
4035
4798
|
initialBindings = [],
|
|
4036
4799
|
onTelemetryChange,
|
|
4037
4800
|
refreshInterval = 0
|
|
4038
4801
|
} = options;
|
|
4039
|
-
const [telemetry, setTelemetry] = (0,
|
|
4802
|
+
const [telemetry, setTelemetry] = (0, import_react12.useState)(() => {
|
|
4040
4803
|
const map = /* @__PURE__ */ new Map();
|
|
4041
4804
|
initialBindings.forEach((binding) => {
|
|
4042
4805
|
map.set(binding.nodeId, binding);
|
|
4043
4806
|
});
|
|
4044
4807
|
return map;
|
|
4045
4808
|
});
|
|
4046
|
-
const telemetryRef = (0,
|
|
4809
|
+
const telemetryRef = (0, import_react12.useRef)(telemetry);
|
|
4047
4810
|
telemetryRef.current = telemetry;
|
|
4048
|
-
const notifyChange = (0,
|
|
4811
|
+
const notifyChange = (0, import_react12.useCallback)(
|
|
4049
4812
|
(newTelemetry) => {
|
|
4050
4813
|
if (onTelemetryChange) {
|
|
4051
4814
|
onTelemetryChange(newTelemetry);
|
|
@@ -4053,7 +4816,7 @@ function useTelemetry(options = {}) {
|
|
|
4053
4816
|
},
|
|
4054
4817
|
[onTelemetryChange]
|
|
4055
4818
|
);
|
|
4056
|
-
const updateTelemetry = (0,
|
|
4819
|
+
const updateTelemetry = (0, import_react12.useCallback)(
|
|
4057
4820
|
(nodeId, value) => {
|
|
4058
4821
|
setTelemetry((prev) => {
|
|
4059
4822
|
const newMap = new Map(prev);
|
|
@@ -4083,7 +4846,7 @@ function useTelemetry(options = {}) {
|
|
|
4083
4846
|
},
|
|
4084
4847
|
[notifyChange]
|
|
4085
4848
|
);
|
|
4086
|
-
const updateTelemetryBatch = (0,
|
|
4849
|
+
const updateTelemetryBatch = (0, import_react12.useCallback)(
|
|
4087
4850
|
(updates) => {
|
|
4088
4851
|
setTelemetry((prev) => {
|
|
4089
4852
|
const newMap = new Map(prev);
|
|
@@ -4137,16 +4900,16 @@ function useTelemetry(options = {}) {
|
|
|
4137
4900
|
},
|
|
4138
4901
|
[notifyChange]
|
|
4139
4902
|
);
|
|
4140
|
-
const getTelemetry = (0,
|
|
4903
|
+
const getTelemetry = (0, import_react12.useCallback)(
|
|
4141
4904
|
(nodeId) => telemetryRef.current.get(nodeId),
|
|
4142
4905
|
[]
|
|
4143
4906
|
);
|
|
4144
|
-
const clearTelemetry = (0,
|
|
4907
|
+
const clearTelemetry = (0, import_react12.useCallback)(() => {
|
|
4145
4908
|
const newMap = /* @__PURE__ */ new Map();
|
|
4146
4909
|
setTelemetry(newMap);
|
|
4147
4910
|
notifyChange(newMap);
|
|
4148
4911
|
}, [notifyChange]);
|
|
4149
|
-
const setBindings = (0,
|
|
4912
|
+
const setBindings = (0, import_react12.useCallback)(
|
|
4150
4913
|
(bindings) => {
|
|
4151
4914
|
const newMap = /* @__PURE__ */ new Map();
|
|
4152
4915
|
bindings.forEach((binding) => {
|
|
@@ -4157,7 +4920,7 @@ function useTelemetry(options = {}) {
|
|
|
4157
4920
|
},
|
|
4158
4921
|
[notifyChange]
|
|
4159
4922
|
);
|
|
4160
|
-
(0,
|
|
4923
|
+
(0, import_react12.useEffect)(() => {
|
|
4161
4924
|
if (refreshInterval <= 0) return;
|
|
4162
4925
|
const intervalId = setInterval(() => {
|
|
4163
4926
|
notifyChange(telemetryRef.current);
|
|
@@ -4175,10 +4938,10 @@ function useTelemetry(options = {}) {
|
|
|
4175
4938
|
}
|
|
4176
4939
|
|
|
4177
4940
|
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4178
|
-
var
|
|
4941
|
+
var import_react13 = require("react");
|
|
4179
4942
|
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4180
4943
|
const { enabled = true, mapStatus } = options;
|
|
4181
|
-
(0,
|
|
4944
|
+
(0, import_react13.useEffect)(() => {
|
|
4182
4945
|
if (!enabled) return;
|
|
4183
4946
|
const defaultMapStatus = (telemetryStatus) => {
|
|
4184
4947
|
switch (telemetryStatus) {
|
|
@@ -4217,7 +4980,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
4217
4980
|
}
|
|
4218
4981
|
|
|
4219
4982
|
// src/diagram/hooks/useDrag.ts
|
|
4220
|
-
var
|
|
4983
|
+
var import_react14 = require("react");
|
|
4221
4984
|
function useDrag(options = {}) {
|
|
4222
4985
|
const {
|
|
4223
4986
|
onDragStart,
|
|
@@ -4227,23 +4990,23 @@ function useDrag(options = {}) {
|
|
|
4227
4990
|
dragThreshold = 3,
|
|
4228
4991
|
screenToWorld = (x, y) => ({ x, y })
|
|
4229
4992
|
} = options;
|
|
4230
|
-
const [dragState, setDragState] = (0,
|
|
4993
|
+
const [dragState, setDragState] = (0, import_react14.useState)({
|
|
4231
4994
|
isDragging: false,
|
|
4232
4995
|
startPosition: null,
|
|
4233
4996
|
offset: { x: 0, y: 0 },
|
|
4234
4997
|
draggedId: null
|
|
4235
4998
|
});
|
|
4236
|
-
const [isListening, setIsListening] = (0,
|
|
4237
|
-
const dragStartRef = (0,
|
|
4238
|
-
const hasMovedRef = (0,
|
|
4239
|
-
const applySnap = (0,
|
|
4999
|
+
const [isListening, setIsListening] = (0, import_react14.useState)(false);
|
|
5000
|
+
const dragStartRef = (0, import_react14.useRef)(null);
|
|
5001
|
+
const hasMovedRef = (0, import_react14.useRef)(false);
|
|
5002
|
+
const applySnap = (0, import_react14.useCallback)(
|
|
4240
5003
|
(value) => {
|
|
4241
5004
|
if (snapToGrid <= 0) return value;
|
|
4242
5005
|
return Math.round(value / snapToGrid) * snapToGrid;
|
|
4243
5006
|
},
|
|
4244
5007
|
[snapToGrid]
|
|
4245
5008
|
);
|
|
4246
|
-
const handleMouseMove = (0,
|
|
5009
|
+
const handleMouseMove = (0, import_react14.useCallback)(
|
|
4247
5010
|
(event) => {
|
|
4248
5011
|
if (!dragStartRef.current) return;
|
|
4249
5012
|
const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
|
|
@@ -4284,7 +5047,7 @@ function useDrag(options = {}) {
|
|
|
4284
5047
|
},
|
|
4285
5048
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
4286
5049
|
);
|
|
4287
|
-
const handleMouseUp = (0,
|
|
5050
|
+
const handleMouseUp = (0, import_react14.useCallback)(
|
|
4288
5051
|
(event) => {
|
|
4289
5052
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
4290
5053
|
dragStartRef.current = null;
|
|
@@ -4321,7 +5084,7 @@ function useDrag(options = {}) {
|
|
|
4321
5084
|
},
|
|
4322
5085
|
[screenToWorld, applySnap, onDragEnd]
|
|
4323
5086
|
);
|
|
4324
|
-
const handleTouchMove = (0,
|
|
5087
|
+
const handleTouchMove = (0, import_react14.useCallback)(
|
|
4325
5088
|
(event) => {
|
|
4326
5089
|
if (!dragStartRef.current || event.touches.length !== 1) return;
|
|
4327
5090
|
const touch = event.touches[0];
|
|
@@ -4364,7 +5127,7 @@ function useDrag(options = {}) {
|
|
|
4364
5127
|
},
|
|
4365
5128
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
4366
5129
|
);
|
|
4367
|
-
const handleTouchEnd = (0,
|
|
5130
|
+
const handleTouchEnd = (0, import_react14.useCallback)(
|
|
4368
5131
|
(event) => {
|
|
4369
5132
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
4370
5133
|
dragStartRef.current = null;
|
|
@@ -4402,7 +5165,7 @@ function useDrag(options = {}) {
|
|
|
4402
5165
|
},
|
|
4403
5166
|
[screenToWorld, applySnap, onDragEnd]
|
|
4404
5167
|
);
|
|
4405
|
-
(0,
|
|
5168
|
+
(0, import_react14.useEffect)(() => {
|
|
4406
5169
|
if (!isListening) return;
|
|
4407
5170
|
document.addEventListener("mousemove", handleMouseMove);
|
|
4408
5171
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -4417,7 +5180,7 @@ function useDrag(options = {}) {
|
|
|
4417
5180
|
document.removeEventListener("touchcancel", handleTouchEnd);
|
|
4418
5181
|
};
|
|
4419
5182
|
}, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
|
|
4420
|
-
const startDrag = (0,
|
|
5183
|
+
const startDrag = (0, import_react14.useCallback)(
|
|
4421
5184
|
(id, event, itemPosition) => {
|
|
4422
5185
|
event.stopPropagation();
|
|
4423
5186
|
let clientX;
|
|
@@ -4447,7 +5210,7 @@ function useDrag(options = {}) {
|
|
|
4447
5210
|
},
|
|
4448
5211
|
[screenToWorld]
|
|
4449
5212
|
);
|
|
4450
|
-
const cancelDrag = (0,
|
|
5213
|
+
const cancelDrag = (0, import_react14.useCallback)(() => {
|
|
4451
5214
|
dragStartRef.current = null;
|
|
4452
5215
|
hasMovedRef.current = false;
|
|
4453
5216
|
setIsListening(false);
|
|
@@ -4458,7 +5221,7 @@ function useDrag(options = {}) {
|
|
|
4458
5221
|
draggedId: null
|
|
4459
5222
|
});
|
|
4460
5223
|
}, []);
|
|
4461
|
-
const isDraggingItem = (0,
|
|
5224
|
+
const isDraggingItem = (0, import_react14.useCallback)(
|
|
4462
5225
|
(id) => dragState.isDragging && dragState.draggedId === id,
|
|
4463
5226
|
[dragState.isDragging, dragState.draggedId]
|
|
4464
5227
|
);
|
|
@@ -4471,7 +5234,7 @@ function useDrag(options = {}) {
|
|
|
4471
5234
|
}
|
|
4472
5235
|
|
|
4473
5236
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
4474
|
-
var
|
|
5237
|
+
var import_react15 = require("react");
|
|
4475
5238
|
function useKeyboardShortcuts(options) {
|
|
4476
5239
|
const {
|
|
4477
5240
|
onDelete,
|
|
@@ -4482,7 +5245,7 @@ function useKeyboardShortcuts(options) {
|
|
|
4482
5245
|
onSelectAll,
|
|
4483
5246
|
enabled = true
|
|
4484
5247
|
} = options;
|
|
4485
|
-
(0,
|
|
5248
|
+
(0, import_react15.useEffect)(() => {
|
|
4486
5249
|
if (!enabled) return;
|
|
4487
5250
|
const handleKeyDown = (event) => {
|
|
4488
5251
|
const target = event.target;
|
|
@@ -4591,7 +5354,7 @@ function nodeHasPort(node, portId) {
|
|
|
4591
5354
|
}
|
|
4592
5355
|
|
|
4593
5356
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
4594
|
-
var
|
|
5357
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4595
5358
|
function PIDCanvas({
|
|
4596
5359
|
diagram,
|
|
4597
5360
|
className = "",
|
|
@@ -4618,21 +5381,21 @@ function PIDCanvas({
|
|
|
4618
5381
|
telemetry,
|
|
4619
5382
|
...props
|
|
4620
5383
|
}) {
|
|
4621
|
-
const [localDiagram, setLocalDiagram] = (0,
|
|
4622
|
-
const [dragOverPosition, setDragOverPosition] = (0,
|
|
4623
|
-
const [isConnecting, setIsConnecting] = (0,
|
|
4624
|
-
const [connectionSource, setConnectionSource] = (0,
|
|
4625
|
-
const [connectionSourcePort, setConnectionSourcePort] = (0,
|
|
4626
|
-
const [connectionCursor, setConnectionCursor] = (0,
|
|
4627
|
-
const [hoveredNode, setHoveredNode] = (0,
|
|
4628
|
-
const [hoveredPort, setHoveredPort] = (0,
|
|
4629
|
-
const [selectedWaypoint, setSelectedWaypoint] = (0,
|
|
4630
|
-
const historyStack = (0,
|
|
4631
|
-
const redoStack = (0,
|
|
4632
|
-
const isUndoRedoAction = (0,
|
|
4633
|
-
const isInternalChange = (0,
|
|
4634
|
-
const lastInternalDiagram = (0,
|
|
4635
|
-
(0,
|
|
5384
|
+
const [localDiagram, setLocalDiagram] = (0, import_react16.useState)(diagram);
|
|
5385
|
+
const [dragOverPosition, setDragOverPosition] = (0, import_react16.useState)(null);
|
|
5386
|
+
const [isConnecting, setIsConnecting] = (0, import_react16.useState)(false);
|
|
5387
|
+
const [connectionSource, setConnectionSource] = (0, import_react16.useState)(null);
|
|
5388
|
+
const [connectionSourcePort, setConnectionSourcePort] = (0, import_react16.useState)(null);
|
|
5389
|
+
const [connectionCursor, setConnectionCursor] = (0, import_react16.useState)(null);
|
|
5390
|
+
const [hoveredNode, setHoveredNode] = (0, import_react16.useState)(null);
|
|
5391
|
+
const [hoveredPort, setHoveredPort] = (0, import_react16.useState)(null);
|
|
5392
|
+
const [selectedWaypoint, setSelectedWaypoint] = (0, import_react16.useState)(null);
|
|
5393
|
+
const historyStack = (0, import_react16.useRef)([]);
|
|
5394
|
+
const redoStack = (0, import_react16.useRef)([]);
|
|
5395
|
+
const isUndoRedoAction = (0, import_react16.useRef)(false);
|
|
5396
|
+
const isInternalChange = (0, import_react16.useRef)(false);
|
|
5397
|
+
const lastInternalDiagram = (0, import_react16.useRef)(null);
|
|
5398
|
+
(0, import_react16.useEffect)(() => {
|
|
4636
5399
|
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4637
5400
|
if (isExternal) {
|
|
4638
5401
|
setLocalDiagram(diagram);
|
|
@@ -4654,7 +5417,7 @@ function PIDCanvas({
|
|
|
4654
5417
|
enablePan: features.pan ?? true,
|
|
4655
5418
|
enableZoom: features.zoom ?? true
|
|
4656
5419
|
});
|
|
4657
|
-
const calculateContentBounds = (0,
|
|
5420
|
+
const calculateContentBounds = (0, import_react16.useCallback)(() => {
|
|
4658
5421
|
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
4659
5422
|
if (nodes2.length === 0) {
|
|
4660
5423
|
return null;
|
|
@@ -4677,7 +5440,7 @@ function PIDCanvas({
|
|
|
4677
5440
|
});
|
|
4678
5441
|
return { minX, minY, maxX, maxY };
|
|
4679
5442
|
}, [localDiagram.nodes]);
|
|
4680
|
-
(0,
|
|
5443
|
+
(0, import_react16.useEffect)(() => {
|
|
4681
5444
|
if (onMounted) {
|
|
4682
5445
|
const controls = {
|
|
4683
5446
|
fitToContent: (padding = 50) => {
|
|
@@ -4718,8 +5481,8 @@ function PIDCanvas({
|
|
|
4718
5481
|
});
|
|
4719
5482
|
const dragEnabled = features.dragNodes ?? false;
|
|
4720
5483
|
const selectionEnabled = features.selection ?? false;
|
|
4721
|
-
const containerRef = (0,
|
|
4722
|
-
const pushToHistory = (0,
|
|
5484
|
+
const containerRef = (0, import_react16.useRef)(null);
|
|
5485
|
+
const pushToHistory = (0, import_react16.useCallback)((currentDiagram) => {
|
|
4723
5486
|
if (isUndoRedoAction.current) return;
|
|
4724
5487
|
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
4725
5488
|
historyStack.current.push(snapshot);
|
|
@@ -4728,7 +5491,7 @@ function PIDCanvas({
|
|
|
4728
5491
|
}
|
|
4729
5492
|
redoStack.current = [];
|
|
4730
5493
|
}, []);
|
|
4731
|
-
const undo = (0,
|
|
5494
|
+
const undo = (0, import_react16.useCallback)(() => {
|
|
4732
5495
|
if (historyStack.current.length === 0) return;
|
|
4733
5496
|
isUndoRedoAction.current = true;
|
|
4734
5497
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -4742,7 +5505,7 @@ function PIDCanvas({
|
|
|
4742
5505
|
isUndoRedoAction.current = false;
|
|
4743
5506
|
}, 0);
|
|
4744
5507
|
}, [localDiagram, onDiagramChange]);
|
|
4745
|
-
const redo = (0,
|
|
5508
|
+
const redo = (0, import_react16.useCallback)(() => {
|
|
4746
5509
|
if (redoStack.current.length === 0) return;
|
|
4747
5510
|
isUndoRedoAction.current = true;
|
|
4748
5511
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -4756,7 +5519,7 @@ function PIDCanvas({
|
|
|
4756
5519
|
isUndoRedoAction.current = false;
|
|
4757
5520
|
}, 0);
|
|
4758
5521
|
}, [localDiagram, onDiagramChange]);
|
|
4759
|
-
(0,
|
|
5522
|
+
(0, import_react16.useEffect)(() => {
|
|
4760
5523
|
const handleKeyDown = (e) => {
|
|
4761
5524
|
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4762
5525
|
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
@@ -4773,7 +5536,7 @@ function PIDCanvas({
|
|
|
4773
5536
|
window.addEventListener("keydown", handleKeyDown);
|
|
4774
5537
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4775
5538
|
}, [undo, redo]);
|
|
4776
|
-
(0,
|
|
5539
|
+
(0, import_react16.useEffect)(() => {
|
|
4777
5540
|
if (!features.dragNodes) return;
|
|
4778
5541
|
const handleKeyDown = (e) => {
|
|
4779
5542
|
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
@@ -4858,7 +5621,7 @@ function PIDCanvas({
|
|
|
4858
5621
|
onNodeMove,
|
|
4859
5622
|
pushToHistory
|
|
4860
5623
|
]);
|
|
4861
|
-
const handlePositionChange = (0,
|
|
5624
|
+
const handlePositionChange = (0, import_react16.useCallback)(
|
|
4862
5625
|
(nodeId, x, y) => {
|
|
4863
5626
|
pushToHistory(localDiagram);
|
|
4864
5627
|
const updatedNodes = localDiagram.nodes.map(
|
|
@@ -4880,7 +5643,7 @@ function PIDCanvas({
|
|
|
4880
5643
|
},
|
|
4881
5644
|
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
4882
5645
|
);
|
|
4883
|
-
const handleWaypointPositionChange = (0,
|
|
5646
|
+
const handleWaypointPositionChange = (0, import_react16.useCallback)(
|
|
4884
5647
|
(pipeId, pointIndex, x, y) => {
|
|
4885
5648
|
pushToHistory(localDiagram);
|
|
4886
5649
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -4898,7 +5661,7 @@ function PIDCanvas({
|
|
|
4898
5661
|
},
|
|
4899
5662
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
4900
5663
|
);
|
|
4901
|
-
const handleDragEnd = (0,
|
|
5664
|
+
const handleDragEnd = (0, import_react16.useCallback)(
|
|
4902
5665
|
(nodeId, offset, finalPosition) => {
|
|
4903
5666
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
4904
5667
|
if (dragDistance < 2) {
|
|
@@ -4979,7 +5742,7 @@ function PIDCanvas({
|
|
|
4979
5742
|
onDiagramChange?.(updatedDiagram);
|
|
4980
5743
|
}
|
|
4981
5744
|
});
|
|
4982
|
-
const handleNodeDragStart = (0,
|
|
5745
|
+
const handleNodeDragStart = (0, import_react16.useCallback)(
|
|
4983
5746
|
(nodeId, event) => {
|
|
4984
5747
|
const node = localDiagram.nodes.find((n) => n.id === nodeId);
|
|
4985
5748
|
if (!node) return;
|
|
@@ -4987,7 +5750,7 @@ function PIDCanvas({
|
|
|
4987
5750
|
},
|
|
4988
5751
|
[localDiagram.nodes, startDrag]
|
|
4989
5752
|
);
|
|
4990
|
-
const handleWaypointClick = (0,
|
|
5753
|
+
const handleWaypointClick = (0, import_react16.useCallback)(
|
|
4991
5754
|
(pipeId, pointIndex) => {
|
|
4992
5755
|
setSelectedWaypoint({ pipeId, pointIndex });
|
|
4993
5756
|
if (selectionEnabled) {
|
|
@@ -4996,7 +5759,7 @@ function PIDCanvas({
|
|
|
4996
5759
|
},
|
|
4997
5760
|
[selectionEnabled, clearSelection]
|
|
4998
5761
|
);
|
|
4999
|
-
const handleWaypointDragStart = (0,
|
|
5762
|
+
const handleWaypointDragStart = (0, import_react16.useCallback)(
|
|
5000
5763
|
(pipeId, pointIndex, event) => {
|
|
5001
5764
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
5002
5765
|
if (!pipe || pointIndex >= pipe.routePoints.length) return;
|
|
@@ -5005,7 +5768,7 @@ function PIDCanvas({
|
|
|
5005
5768
|
},
|
|
5006
5769
|
[localDiagram.pipes, startWaypointDrag]
|
|
5007
5770
|
);
|
|
5008
|
-
const handlePipeSegmentClick = (0,
|
|
5771
|
+
const handlePipeSegmentClick = (0, import_react16.useCallback)(
|
|
5009
5772
|
(pipeId, position, segmentIndex) => {
|
|
5010
5773
|
pushToHistory(localDiagram);
|
|
5011
5774
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -5024,7 +5787,7 @@ function PIDCanvas({
|
|
|
5024
5787
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
5025
5788
|
);
|
|
5026
5789
|
const telemetryEnabled = features.telemetry ?? false;
|
|
5027
|
-
const handleDelete = (0,
|
|
5790
|
+
const handleDelete = (0, import_react16.useCallback)(() => {
|
|
5028
5791
|
if (!selectionEnabled) return;
|
|
5029
5792
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
5030
5793
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
@@ -5053,13 +5816,13 @@ function PIDCanvas({
|
|
|
5053
5816
|
onDelete,
|
|
5054
5817
|
pushToHistory
|
|
5055
5818
|
]);
|
|
5056
|
-
const handleCopy = (0,
|
|
5819
|
+
const handleCopy = (0, import_react16.useCallback)(() => {
|
|
5057
5820
|
if (!selectionEnabled) return;
|
|
5058
5821
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
5059
5822
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
5060
5823
|
onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
5061
5824
|
}, [selection, selectionEnabled, onItemsCopied]);
|
|
5062
|
-
const handlePaste = (0,
|
|
5825
|
+
const handlePaste = (0, import_react16.useCallback)(() => {
|
|
5063
5826
|
if (!selectionEnabled) return;
|
|
5064
5827
|
onPaste?.();
|
|
5065
5828
|
}, [selectionEnabled, onPaste]);
|
|
@@ -5119,7 +5882,7 @@ function PIDCanvas({
|
|
|
5119
5882
|
}
|
|
5120
5883
|
setSelectedWaypoint(null);
|
|
5121
5884
|
};
|
|
5122
|
-
const handleDragOver = (0,
|
|
5885
|
+
const handleDragOver = (0, import_react16.useCallback)(
|
|
5123
5886
|
(event) => {
|
|
5124
5887
|
if (!features.allowSymbolDrop) return;
|
|
5125
5888
|
event.preventDefault();
|
|
@@ -5130,7 +5893,7 @@ function PIDCanvas({
|
|
|
5130
5893
|
},
|
|
5131
5894
|
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
5132
5895
|
);
|
|
5133
|
-
const handleDrop = (0,
|
|
5896
|
+
const handleDrop = (0, import_react16.useCallback)(
|
|
5134
5897
|
(event) => {
|
|
5135
5898
|
if (!features.allowSymbolDrop) return;
|
|
5136
5899
|
event.preventDefault();
|
|
@@ -5143,10 +5906,10 @@ function PIDCanvas({
|
|
|
5143
5906
|
},
|
|
5144
5907
|
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
5145
5908
|
);
|
|
5146
|
-
const handleDragLeave = (0,
|
|
5909
|
+
const handleDragLeave = (0, import_react16.useCallback)(() => {
|
|
5147
5910
|
setDragOverPosition(null);
|
|
5148
5911
|
}, []);
|
|
5149
|
-
const handleMouseMove = (0,
|
|
5912
|
+
const handleMouseMove = (0, import_react16.useCallback)(
|
|
5150
5913
|
(event) => {
|
|
5151
5914
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
5152
5915
|
if (connectionModeEnabled) {
|
|
@@ -5183,7 +5946,7 @@ function PIDCanvas({
|
|
|
5183
5946
|
const viewBox = controlledViewBox;
|
|
5184
5947
|
const displayDiagram = localDiagram;
|
|
5185
5948
|
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5186
|
-
return /* @__PURE__ */ (0,
|
|
5949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5187
5950
|
"div",
|
|
5188
5951
|
{
|
|
5189
5952
|
ref: containerRef,
|
|
@@ -5198,7 +5961,7 @@ function PIDCanvas({
|
|
|
5198
5961
|
},
|
|
5199
5962
|
...props,
|
|
5200
5963
|
children: [
|
|
5201
|
-
/* @__PURE__ */ (0,
|
|
5964
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5202
5965
|
"svg",
|
|
5203
5966
|
{
|
|
5204
5967
|
ref: svgRef,
|
|
@@ -5217,15 +5980,15 @@ function PIDCanvas({
|
|
|
5217
5980
|
onDrop: handleDrop,
|
|
5218
5981
|
onDragLeave: handleDragLeave,
|
|
5219
5982
|
children: [
|
|
5220
|
-
features.showGrid !== false ? /* @__PURE__ */ (0,
|
|
5221
|
-
/* @__PURE__ */ (0,
|
|
5222
|
-
/* @__PURE__ */ (0,
|
|
5223
|
-
/* @__PURE__ */ (0,
|
|
5224
|
-
/* @__PURE__ */ (0,
|
|
5225
|
-
/* @__PURE__ */ (0,
|
|
5983
|
+
features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5984
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("defs", { children: [
|
|
5985
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
5986
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5987
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5988
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5226
5989
|
] })
|
|
5227
5990
|
] }),
|
|
5228
|
-
/* @__PURE__ */ (0,
|
|
5991
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5229
5992
|
"rect",
|
|
5230
5993
|
{
|
|
5231
5994
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -5235,7 +5998,7 @@ function PIDCanvas({
|
|
|
5235
5998
|
fill: "url(#grid-major)"
|
|
5236
5999
|
}
|
|
5237
6000
|
)
|
|
5238
|
-
] }) : /* @__PURE__ */ (0,
|
|
6001
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5239
6002
|
"rect",
|
|
5240
6003
|
{
|
|
5241
6004
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -5245,7 +6008,7 @@ function PIDCanvas({
|
|
|
5245
6008
|
fill: features.backgroundColor ?? "#ffffff"
|
|
5246
6009
|
}
|
|
5247
6010
|
),
|
|
5248
|
-
/* @__PURE__ */ (0,
|
|
6011
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5249
6012
|
PipeRenderer,
|
|
5250
6013
|
{
|
|
5251
6014
|
pipes: displayDiagram.pipes,
|
|
@@ -5259,12 +6022,12 @@ function PIDCanvas({
|
|
|
5259
6022
|
onPipeSegmentClick: void 0
|
|
5260
6023
|
}
|
|
5261
6024
|
),
|
|
5262
|
-
/* @__PURE__ */ (0,
|
|
6025
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5263
6026
|
NodeRenderer,
|
|
5264
6027
|
{
|
|
5265
6028
|
nodes: displayDiagram.nodes,
|
|
5266
6029
|
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5267
|
-
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
6030
|
+
onNodeClick: onNodeClick ? handleNodeClick : selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5268
6031
|
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5269
6032
|
enableDrag: dragEnabled && !isConnecting,
|
|
5270
6033
|
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
@@ -5272,7 +6035,7 @@ function PIDCanvas({
|
|
|
5272
6035
|
dragOffset: dragState.offset
|
|
5273
6036
|
}
|
|
5274
6037
|
),
|
|
5275
|
-
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0,
|
|
6038
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5276
6039
|
PipeRenderer,
|
|
5277
6040
|
{
|
|
5278
6041
|
pipes: displayDiagram.pipes,
|
|
@@ -5289,14 +6052,14 @@ function PIDCanvas({
|
|
|
5289
6052
|
onPipeSegmentClick: handlePipeSegmentClick
|
|
5290
6053
|
}
|
|
5291
6054
|
),
|
|
5292
|
-
telemetryEnabled && telemetry && /* @__PURE__ */ (0,
|
|
6055
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5293
6056
|
const binding = telemetry.get(node.id);
|
|
5294
6057
|
if (!binding) return null;
|
|
5295
6058
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
5296
6059
|
if (!symbol) return null;
|
|
5297
6060
|
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5298
6061
|
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5299
|
-
return /* @__PURE__ */ (0,
|
|
6062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5300
6063
|
DataOverlay,
|
|
5301
6064
|
{
|
|
5302
6065
|
nodeId: node.id,
|
|
@@ -5308,7 +6071,7 @@ function PIDCanvas({
|
|
|
5308
6071
|
`telemetry-${node.id}`
|
|
5309
6072
|
);
|
|
5310
6073
|
}) }),
|
|
5311
|
-
dragOverPosition && /* @__PURE__ */ (0,
|
|
6074
|
+
dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5312
6075
|
"circle",
|
|
5313
6076
|
{
|
|
5314
6077
|
cx: dragOverPosition.x,
|
|
@@ -5321,7 +6084,7 @@ function PIDCanvas({
|
|
|
5321
6084
|
pointerEvents: "none"
|
|
5322
6085
|
}
|
|
5323
6086
|
),
|
|
5324
|
-
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0,
|
|
6087
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5325
6088
|
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5326
6089
|
if (!sourceNode) return null;
|
|
5327
6090
|
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
@@ -5337,8 +6100,8 @@ function PIDCanvas({
|
|
|
5337
6100
|
}
|
|
5338
6101
|
}
|
|
5339
6102
|
}
|
|
5340
|
-
return /* @__PURE__ */ (0,
|
|
5341
|
-
/* @__PURE__ */ (0,
|
|
6103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
6104
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5342
6105
|
"circle",
|
|
5343
6106
|
{
|
|
5344
6107
|
cx: lineStartX,
|
|
@@ -5350,7 +6113,7 @@ function PIDCanvas({
|
|
|
5350
6113
|
opacity: 0.6
|
|
5351
6114
|
}
|
|
5352
6115
|
),
|
|
5353
|
-
/* @__PURE__ */ (0,
|
|
6116
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5354
6117
|
"line",
|
|
5355
6118
|
{
|
|
5356
6119
|
x1: lineStartX,
|
|
@@ -5363,7 +6126,7 @@ function PIDCanvas({
|
|
|
5363
6126
|
opacity: 0.8
|
|
5364
6127
|
}
|
|
5365
6128
|
),
|
|
5366
|
-
/* @__PURE__ */ (0,
|
|
6129
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5367
6130
|
"circle",
|
|
5368
6131
|
{
|
|
5369
6132
|
cx: connectionCursor.x,
|
|
@@ -5375,7 +6138,7 @@ function PIDCanvas({
|
|
|
5375
6138
|
)
|
|
5376
6139
|
] });
|
|
5377
6140
|
})() }),
|
|
5378
|
-
features.connectionMode && /* @__PURE__ */ (0,
|
|
6141
|
+
features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5379
6142
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
5380
6143
|
if (!symbol?.ports) return null;
|
|
5381
6144
|
return symbol.ports.map((port) => {
|
|
@@ -5383,8 +6146,8 @@ function PIDCanvas({
|
|
|
5383
6146
|
if (!portPos) return null;
|
|
5384
6147
|
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5385
6148
|
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5386
|
-
return /* @__PURE__ */ (0,
|
|
5387
|
-
/* @__PURE__ */ (0,
|
|
6149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("g", { children: [
|
|
6150
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5388
6151
|
"circle",
|
|
5389
6152
|
{
|
|
5390
6153
|
cx: portPos.x,
|
|
@@ -5417,7 +6180,7 @@ function PIDCanvas({
|
|
|
5417
6180
|
}
|
|
5418
6181
|
}
|
|
5419
6182
|
),
|
|
5420
|
-
/* @__PURE__ */ (0,
|
|
6183
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5421
6184
|
"circle",
|
|
5422
6185
|
{
|
|
5423
6186
|
cx: portPos.x,
|
|
@@ -5436,7 +6199,7 @@ function PIDCanvas({
|
|
|
5436
6199
|
]
|
|
5437
6200
|
}
|
|
5438
6201
|
),
|
|
5439
|
-
features.dragNodes && /* @__PURE__ */ (0,
|
|
6202
|
+
features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5440
6203
|
PositionPanel,
|
|
5441
6204
|
{
|
|
5442
6205
|
selectedNode,
|
|
@@ -5456,16 +6219,16 @@ function PIDCanvas({
|
|
|
5456
6219
|
}
|
|
5457
6220
|
|
|
5458
6221
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
5459
|
-
var
|
|
5460
|
-
var
|
|
6222
|
+
var import_react17 = require("react");
|
|
6223
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5461
6224
|
function SymbolLibrary({
|
|
5462
6225
|
className = "",
|
|
5463
6226
|
onSymbolDragStart,
|
|
5464
6227
|
showCategories = true,
|
|
5465
6228
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
5466
6229
|
}) {
|
|
5467
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
5468
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
6230
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react17.useState)("all");
|
|
6231
|
+
const [searchQuery, setSearchQuery] = (0, import_react17.useState)("");
|
|
5469
6232
|
const symbolIds = getAvailableSymbols();
|
|
5470
6233
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5471
6234
|
const categoryMap = {
|
|
@@ -5486,9 +6249,9 @@ function SymbolLibrary({
|
|
|
5486
6249
|
event.dataTransfer.effectAllowed = "copy";
|
|
5487
6250
|
onSymbolDragStart?.(symbol.id, event);
|
|
5488
6251
|
};
|
|
5489
|
-
return /* @__PURE__ */ (0,
|
|
5490
|
-
/* @__PURE__ */ (0,
|
|
5491
|
-
/* @__PURE__ */ (0,
|
|
6252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
6253
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
6254
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5492
6255
|
"input",
|
|
5493
6256
|
{
|
|
5494
6257
|
type: "text",
|
|
@@ -5498,8 +6261,8 @@ function SymbolLibrary({
|
|
|
5498
6261
|
style: styles.searchInput
|
|
5499
6262
|
}
|
|
5500
6263
|
) }),
|
|
5501
|
-
showCategories && /* @__PURE__ */ (0,
|
|
5502
|
-
/* @__PURE__ */ (0,
|
|
6264
|
+
showCategories && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: styles.categories, children: [
|
|
6265
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5503
6266
|
"button",
|
|
5504
6267
|
{
|
|
5505
6268
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -5510,7 +6273,7 @@ function SymbolLibrary({
|
|
|
5510
6273
|
children: "All"
|
|
5511
6274
|
}
|
|
5512
6275
|
),
|
|
5513
|
-
categories.map((category) => /* @__PURE__ */ (0,
|
|
6276
|
+
categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5514
6277
|
"button",
|
|
5515
6278
|
{
|
|
5516
6279
|
onClick: () => setSelectedCategory(category),
|
|
@@ -5523,7 +6286,7 @@ function SymbolLibrary({
|
|
|
5523
6286
|
category
|
|
5524
6287
|
))
|
|
5525
6288
|
] }),
|
|
5526
|
-
/* @__PURE__ */ (0,
|
|
6289
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5527
6290
|
"div",
|
|
5528
6291
|
{
|
|
5529
6292
|
draggable: true,
|
|
@@ -5531,15 +6294,15 @@ function SymbolLibrary({
|
|
|
5531
6294
|
style: styles.symbolCard,
|
|
5532
6295
|
title: symbol.metadata?.description || symbol.name,
|
|
5533
6296
|
children: [
|
|
5534
|
-
/* @__PURE__ */ (0,
|
|
6297
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5535
6298
|
"svg",
|
|
5536
6299
|
{
|
|
5537
6300
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
5538
6301
|
style: styles.symbolSvg,
|
|
5539
|
-
children: /* @__PURE__ */ (0,
|
|
6302
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
5540
6303
|
}
|
|
5541
6304
|
) }),
|
|
5542
|
-
/* @__PURE__ */ (0,
|
|
6305
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolName, children: symbol.name })
|
|
5543
6306
|
]
|
|
5544
6307
|
},
|
|
5545
6308
|
symbol.id
|
|
@@ -5648,7 +6411,7 @@ var styles = {
|
|
|
5648
6411
|
};
|
|
5649
6412
|
|
|
5650
6413
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
5651
|
-
var
|
|
6414
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
5652
6415
|
function NodeConfigPanel({
|
|
5653
6416
|
node,
|
|
5654
6417
|
binding,
|
|
@@ -5667,15 +6430,15 @@ function NodeConfigPanel({
|
|
|
5667
6430
|
padding: "20px",
|
|
5668
6431
|
...style
|
|
5669
6432
|
};
|
|
5670
|
-
return /* @__PURE__ */ (0,
|
|
5671
|
-
/* @__PURE__ */ (0,
|
|
6433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, style: defaultStyle, children: [
|
|
6434
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
5672
6435
|
"Configure: ",
|
|
5673
6436
|
node.id
|
|
5674
6437
|
] }),
|
|
5675
|
-
/* @__PURE__ */ (0,
|
|
5676
|
-
/* @__PURE__ */ (0,
|
|
5677
|
-
/* @__PURE__ */ (0,
|
|
5678
|
-
/* @__PURE__ */ (0,
|
|
6438
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6439
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
6440
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
6441
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5679
6442
|
"input",
|
|
5680
6443
|
{
|
|
5681
6444
|
type: "text",
|
|
@@ -5691,10 +6454,10 @@ function NodeConfigPanel({
|
|
|
5691
6454
|
}
|
|
5692
6455
|
}
|
|
5693
6456
|
),
|
|
5694
|
-
/* @__PURE__ */ (0,
|
|
5695
|
-
/* @__PURE__ */ (0,
|
|
5696
|
-
/* @__PURE__ */ (0,
|
|
5697
|
-
/* @__PURE__ */ (0,
|
|
6457
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
6458
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6459
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
6460
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5698
6461
|
"input",
|
|
5699
6462
|
{
|
|
5700
6463
|
type: "number",
|
|
@@ -5715,9 +6478,9 @@ function NodeConfigPanel({
|
|
|
5715
6478
|
}
|
|
5716
6479
|
)
|
|
5717
6480
|
] }),
|
|
5718
|
-
/* @__PURE__ */ (0,
|
|
5719
|
-
/* @__PURE__ */ (0,
|
|
5720
|
-
/* @__PURE__ */ (0,
|
|
6481
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6482
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
6483
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5721
6484
|
"input",
|
|
5722
6485
|
{
|
|
5723
6486
|
type: "number",
|
|
@@ -5739,9 +6502,9 @@ function NodeConfigPanel({
|
|
|
5739
6502
|
)
|
|
5740
6503
|
] })
|
|
5741
6504
|
] }),
|
|
5742
|
-
/* @__PURE__ */ (0,
|
|
5743
|
-
/* @__PURE__ */ (0,
|
|
5744
|
-
/* @__PURE__ */ (0,
|
|
6505
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6506
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
6507
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5745
6508
|
"input",
|
|
5746
6509
|
{
|
|
5747
6510
|
type: "number",
|
|
@@ -5761,9 +6524,9 @@ function NodeConfigPanel({
|
|
|
5761
6524
|
}
|
|
5762
6525
|
)
|
|
5763
6526
|
] }),
|
|
5764
|
-
/* @__PURE__ */ (0,
|
|
5765
|
-
/* @__PURE__ */ (0,
|
|
5766
|
-
/* @__PURE__ */ (0,
|
|
6527
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6528
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
6529
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5767
6530
|
"input",
|
|
5768
6531
|
{
|
|
5769
6532
|
type: "number",
|
|
@@ -5788,9 +6551,9 @@ function NodeConfigPanel({
|
|
|
5788
6551
|
)
|
|
5789
6552
|
] })
|
|
5790
6553
|
] }),
|
|
5791
|
-
/* @__PURE__ */ (0,
|
|
5792
|
-
/* @__PURE__ */ (0,
|
|
5793
|
-
!binding ? /* @__PURE__ */ (0,
|
|
6554
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6555
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
6556
|
+
!binding ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5794
6557
|
"button",
|
|
5795
6558
|
{
|
|
5796
6559
|
onClick: () => {
|
|
@@ -5833,9 +6596,9 @@ function NodeConfigPanel({
|
|
|
5833
6596
|
},
|
|
5834
6597
|
children: "+ Add Telemetry"
|
|
5835
6598
|
}
|
|
5836
|
-
) : /* @__PURE__ */ (0,
|
|
5837
|
-
/* @__PURE__ */ (0,
|
|
5838
|
-
/* @__PURE__ */ (0,
|
|
6599
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
6600
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
6601
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5839
6602
|
"input",
|
|
5840
6603
|
{
|
|
5841
6604
|
type: "number",
|
|
@@ -5857,8 +6620,8 @@ function NodeConfigPanel({
|
|
|
5857
6620
|
}
|
|
5858
6621
|
}
|
|
5859
6622
|
),
|
|
5860
|
-
/* @__PURE__ */ (0,
|
|
5861
|
-
/* @__PURE__ */ (0,
|
|
6623
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
6624
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5862
6625
|
"input",
|
|
5863
6626
|
{
|
|
5864
6627
|
type: "text",
|
|
@@ -5880,8 +6643,8 @@ function NodeConfigPanel({
|
|
|
5880
6643
|
}
|
|
5881
6644
|
}
|
|
5882
6645
|
),
|
|
5883
|
-
/* @__PURE__ */ (0,
|
|
5884
|
-
/* @__PURE__ */ (0,
|
|
6646
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
6647
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5885
6648
|
"input",
|
|
5886
6649
|
{
|
|
5887
6650
|
type: "checkbox",
|
|
@@ -5903,8 +6666,8 @@ function NodeConfigPanel({
|
|
|
5903
6666
|
),
|
|
5904
6667
|
"Show Sparkline"
|
|
5905
6668
|
] }),
|
|
5906
|
-
/* @__PURE__ */ (0,
|
|
5907
|
-
/* @__PURE__ */ (0,
|
|
6669
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "12px" }, children: [
|
|
6670
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5908
6671
|
"label",
|
|
5909
6672
|
{
|
|
5910
6673
|
style: {
|
|
@@ -5916,10 +6679,10 @@ function NodeConfigPanel({
|
|
|
5916
6679
|
children: "Telemetry Position Offset:"
|
|
5917
6680
|
}
|
|
5918
6681
|
),
|
|
5919
|
-
/* @__PURE__ */ (0,
|
|
5920
|
-
/* @__PURE__ */ (0,
|
|
5921
|
-
/* @__PURE__ */ (0,
|
|
5922
|
-
/* @__PURE__ */ (0,
|
|
6682
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
6683
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6684
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
6685
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5923
6686
|
"input",
|
|
5924
6687
|
{
|
|
5925
6688
|
type: "number",
|
|
@@ -5946,9 +6709,9 @@ function NodeConfigPanel({
|
|
|
5946
6709
|
}
|
|
5947
6710
|
)
|
|
5948
6711
|
] }),
|
|
5949
|
-
/* @__PURE__ */ (0,
|
|
5950
|
-
/* @__PURE__ */ (0,
|
|
5951
|
-
/* @__PURE__ */ (0,
|
|
6712
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
6713
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
6714
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5952
6715
|
"input",
|
|
5953
6716
|
{
|
|
5954
6717
|
type: "number",
|
|
@@ -5976,8 +6739,8 @@ function NodeConfigPanel({
|
|
|
5976
6739
|
)
|
|
5977
6740
|
] })
|
|
5978
6741
|
] }),
|
|
5979
|
-
/* @__PURE__ */ (0,
|
|
5980
|
-
/* @__PURE__ */ (0,
|
|
6742
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "16px" }, children: [
|
|
6743
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5981
6744
|
"label",
|
|
5982
6745
|
{
|
|
5983
6746
|
style: {
|
|
@@ -5989,10 +6752,10 @@ function NodeConfigPanel({
|
|
|
5989
6752
|
children: "Display Colors:"
|
|
5990
6753
|
}
|
|
5991
6754
|
),
|
|
5992
|
-
/* @__PURE__ */ (0,
|
|
5993
|
-
/* @__PURE__ */ (0,
|
|
5994
|
-
/* @__PURE__ */ (0,
|
|
5995
|
-
/* @__PURE__ */ (0,
|
|
6755
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6756
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
6757
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6758
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5996
6759
|
"input",
|
|
5997
6760
|
{
|
|
5998
6761
|
type: "color",
|
|
@@ -6018,7 +6781,7 @@ function NodeConfigPanel({
|
|
|
6018
6781
|
}
|
|
6019
6782
|
}
|
|
6020
6783
|
),
|
|
6021
|
-
/* @__PURE__ */ (0,
|
|
6784
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6022
6785
|
"input",
|
|
6023
6786
|
{
|
|
6024
6787
|
type: "text",
|
|
@@ -6048,10 +6811,10 @@ function NodeConfigPanel({
|
|
|
6048
6811
|
)
|
|
6049
6812
|
] })
|
|
6050
6813
|
] }),
|
|
6051
|
-
binding.display?.showSparkline && /* @__PURE__ */ (0,
|
|
6052
|
-
/* @__PURE__ */ (0,
|
|
6053
|
-
/* @__PURE__ */ (0,
|
|
6054
|
-
/* @__PURE__ */ (0,
|
|
6814
|
+
binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6815
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
6816
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6817
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6055
6818
|
"input",
|
|
6056
6819
|
{
|
|
6057
6820
|
type: "color",
|
|
@@ -6077,7 +6840,7 @@ function NodeConfigPanel({
|
|
|
6077
6840
|
}
|
|
6078
6841
|
}
|
|
6079
6842
|
),
|
|
6080
|
-
/* @__PURE__ */ (0,
|
|
6843
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6081
6844
|
"input",
|
|
6082
6845
|
{
|
|
6083
6846
|
type: "text",
|
|
@@ -6107,9 +6870,9 @@ function NodeConfigPanel({
|
|
|
6107
6870
|
)
|
|
6108
6871
|
] })
|
|
6109
6872
|
] }),
|
|
6110
|
-
/* @__PURE__ */ (0,
|
|
6111
|
-
/* @__PURE__ */ (0,
|
|
6112
|
-
/* @__PURE__ */ (0,
|
|
6873
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6874
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6875
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6113
6876
|
"input",
|
|
6114
6877
|
{
|
|
6115
6878
|
type: "text",
|
|
@@ -6137,20 +6900,20 @@ function NodeConfigPanel({
|
|
|
6137
6900
|
}
|
|
6138
6901
|
}
|
|
6139
6902
|
),
|
|
6140
|
-
/* @__PURE__ */ (0,
|
|
6903
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
6141
6904
|
] })
|
|
6142
6905
|
] }),
|
|
6143
6906
|
" "
|
|
6144
6907
|
] })
|
|
6145
6908
|
] })
|
|
6146
6909
|
] }),
|
|
6147
|
-
binding && /* @__PURE__ */ (0,
|
|
6148
|
-
/* @__PURE__ */ (0,
|
|
6910
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6911
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
6149
6912
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
6150
6913
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
6151
|
-
return /* @__PURE__ */ (0,
|
|
6152
|
-
/* @__PURE__ */ (0,
|
|
6153
|
-
/* @__PURE__ */ (0,
|
|
6914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6915
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6916
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6154
6917
|
"input",
|
|
6155
6918
|
{
|
|
6156
6919
|
type: "number",
|
|
@@ -6174,8 +6937,8 @@ function NodeConfigPanel({
|
|
|
6174
6937
|
] }, key);
|
|
6175
6938
|
})
|
|
6176
6939
|
] }),
|
|
6177
|
-
binding && /* @__PURE__ */ (0,
|
|
6178
|
-
/* @__PURE__ */ (0,
|
|
6940
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6941
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
6179
6942
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
6180
6943
|
const defaultColors = {
|
|
6181
6944
|
normal: "#10b981",
|
|
@@ -6185,13 +6948,13 @@ function NodeConfigPanel({
|
|
|
6185
6948
|
off: "#6b7280"
|
|
6186
6949
|
};
|
|
6187
6950
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
6188
|
-
return /* @__PURE__ */ (0,
|
|
6189
|
-
/* @__PURE__ */ (0,
|
|
6951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6952
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
6190
6953
|
label,
|
|
6191
6954
|
":"
|
|
6192
6955
|
] }),
|
|
6193
|
-
/* @__PURE__ */ (0,
|
|
6194
|
-
/* @__PURE__ */ (0,
|
|
6956
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6957
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6195
6958
|
"input",
|
|
6196
6959
|
{
|
|
6197
6960
|
type: "color",
|
|
@@ -6212,7 +6975,7 @@ function NodeConfigPanel({
|
|
|
6212
6975
|
}
|
|
6213
6976
|
}
|
|
6214
6977
|
),
|
|
6215
|
-
/* @__PURE__ */ (0,
|
|
6978
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6216
6979
|
"input",
|
|
6217
6980
|
{
|
|
6218
6981
|
type: "text",
|
|
@@ -6239,7 +7002,7 @@ function NodeConfigPanel({
|
|
|
6239
7002
|
] }, status);
|
|
6240
7003
|
})
|
|
6241
7004
|
] }),
|
|
6242
|
-
/* @__PURE__ */ (0,
|
|
7005
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6243
7006
|
"button",
|
|
6244
7007
|
{
|
|
6245
7008
|
onClick: onRemove,
|
|
@@ -6478,8 +7241,280 @@ var DEFAULT_THRESHOLDS = {
|
|
|
6478
7241
|
lowLow: 15
|
|
6479
7242
|
};
|
|
6480
7243
|
|
|
7244
|
+
// src/diagram/schema/DeviceControlBinding.ts
|
|
7245
|
+
function createControlBinding(nodeId, deviceConfig, actions) {
|
|
7246
|
+
const parametersByMode = {};
|
|
7247
|
+
deviceConfig.parameters.forEach((param) => {
|
|
7248
|
+
const modes = param.modes || deviceConfig.modes.map((m) => m.value);
|
|
7249
|
+
modes.forEach((mode) => {
|
|
7250
|
+
if (!parametersByMode[mode]) {
|
|
7251
|
+
parametersByMode[mode] = [];
|
|
7252
|
+
}
|
|
7253
|
+
parametersByMode[mode].push({
|
|
7254
|
+
id: param.id,
|
|
7255
|
+
label: param.label,
|
|
7256
|
+
unit: param.unit,
|
|
7257
|
+
min: param.min,
|
|
7258
|
+
max: param.max,
|
|
7259
|
+
value: param.value,
|
|
7260
|
+
type: typeof param.value === "number" ? "number" : "string"
|
|
7261
|
+
});
|
|
7262
|
+
});
|
|
7263
|
+
});
|
|
7264
|
+
return {
|
|
7265
|
+
nodeId,
|
|
7266
|
+
tag: deviceConfig.tag,
|
|
7267
|
+
deviceName: deviceConfig.name,
|
|
7268
|
+
deviceType: deviceConfig.type,
|
|
7269
|
+
modes: deviceConfig.modes,
|
|
7270
|
+
state: {
|
|
7271
|
+
currentMode: deviceConfig.currentMode,
|
|
7272
|
+
isRunning: deviceConfig.isRunning,
|
|
7273
|
+
status: deviceConfig.status
|
|
7274
|
+
},
|
|
7275
|
+
parameters: parametersByMode,
|
|
7276
|
+
capabilities: deviceConfig.capabilities,
|
|
7277
|
+
actions
|
|
7278
|
+
};
|
|
7279
|
+
}
|
|
7280
|
+
|
|
7281
|
+
// src/hooks/useDeviceControls.ts
|
|
7282
|
+
var import_react18 = require("react");
|
|
7283
|
+
function useDeviceControls(initialBindings) {
|
|
7284
|
+
const [controls, setControls] = (0, import_react18.useState)(() => {
|
|
7285
|
+
const map = /* @__PURE__ */ new Map();
|
|
7286
|
+
if (initialBindings) {
|
|
7287
|
+
initialBindings.forEach((binding) => {
|
|
7288
|
+
map.set(binding.nodeId, binding);
|
|
7289
|
+
});
|
|
7290
|
+
}
|
|
7291
|
+
return map;
|
|
7292
|
+
});
|
|
7293
|
+
const updateControl = (0, import_react18.useCallback)((nodeId, updates) => {
|
|
7294
|
+
setControls((prev) => {
|
|
7295
|
+
const newMap = new Map(prev);
|
|
7296
|
+
const existing = newMap.get(nodeId);
|
|
7297
|
+
if (existing) {
|
|
7298
|
+
newMap.set(nodeId, { ...existing, ...updates });
|
|
7299
|
+
} else {
|
|
7300
|
+
if ("tag" in updates && "modes" in updates && "state" in updates && "parameters" in updates && "actions" in updates) {
|
|
7301
|
+
newMap.set(nodeId, { nodeId, ...updates });
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7304
|
+
return newMap;
|
|
7305
|
+
});
|
|
7306
|
+
}, []);
|
|
7307
|
+
const updateControlBatch = (0, import_react18.useCallback)((updates) => {
|
|
7308
|
+
setControls((prev) => {
|
|
7309
|
+
const newMap = new Map(prev);
|
|
7310
|
+
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
7311
|
+
const existing = newMap.get(nodeId);
|
|
7312
|
+
if (existing) {
|
|
7313
|
+
newMap.set(nodeId, { ...existing, ...update });
|
|
7314
|
+
}
|
|
7315
|
+
});
|
|
7316
|
+
return newMap;
|
|
7317
|
+
});
|
|
7318
|
+
}, []);
|
|
7319
|
+
const updateDeviceState = (0, import_react18.useCallback)(
|
|
7320
|
+
(nodeId, stateUpdates) => {
|
|
7321
|
+
setControls((prev) => {
|
|
7322
|
+
const newMap = new Map(prev);
|
|
7323
|
+
const existing = newMap.get(nodeId);
|
|
7324
|
+
if (existing) {
|
|
7325
|
+
newMap.set(nodeId, {
|
|
7326
|
+
...existing,
|
|
7327
|
+
state: { ...existing.state, ...stateUpdates }
|
|
7328
|
+
});
|
|
7329
|
+
}
|
|
7330
|
+
return newMap;
|
|
7331
|
+
});
|
|
7332
|
+
},
|
|
7333
|
+
[]
|
|
7334
|
+
);
|
|
7335
|
+
const updateParameter = (0, import_react18.useCallback)(
|
|
7336
|
+
(nodeId, parameterId, value) => {
|
|
7337
|
+
setControls((prev) => {
|
|
7338
|
+
const newMap = new Map(prev);
|
|
7339
|
+
const existing = newMap.get(nodeId);
|
|
7340
|
+
if (existing) {
|
|
7341
|
+
const updatedParameters = { ...existing.parameters };
|
|
7342
|
+
Object.keys(updatedParameters).forEach((mode) => {
|
|
7343
|
+
const paramIndex = updatedParameters[mode].findIndex((p) => p.id === parameterId);
|
|
7344
|
+
if (paramIndex !== -1) {
|
|
7345
|
+
updatedParameters[mode] = [...updatedParameters[mode]];
|
|
7346
|
+
updatedParameters[mode][paramIndex] = {
|
|
7347
|
+
...updatedParameters[mode][paramIndex],
|
|
7348
|
+
value
|
|
7349
|
+
};
|
|
7350
|
+
}
|
|
7351
|
+
});
|
|
7352
|
+
newMap.set(nodeId, {
|
|
7353
|
+
...existing,
|
|
7354
|
+
parameters: updatedParameters
|
|
7355
|
+
});
|
|
7356
|
+
}
|
|
7357
|
+
return newMap;
|
|
7358
|
+
});
|
|
7359
|
+
},
|
|
7360
|
+
[]
|
|
7361
|
+
);
|
|
7362
|
+
const setControlBinding = (0, import_react18.useCallback)((binding) => {
|
|
7363
|
+
setControls((prev) => {
|
|
7364
|
+
const newMap = new Map(prev);
|
|
7365
|
+
newMap.set(binding.nodeId, binding);
|
|
7366
|
+
return newMap;
|
|
7367
|
+
});
|
|
7368
|
+
}, []);
|
|
7369
|
+
const removeControlBinding = (0, import_react18.useCallback)((nodeId) => {
|
|
7370
|
+
setControls((prev) => {
|
|
7371
|
+
const newMap = new Map(prev);
|
|
7372
|
+
newMap.delete(nodeId);
|
|
7373
|
+
return newMap;
|
|
7374
|
+
});
|
|
7375
|
+
}, []);
|
|
7376
|
+
const getControlBinding = (0, import_react18.useCallback)(
|
|
7377
|
+
(nodeId) => {
|
|
7378
|
+
return controls.get(nodeId);
|
|
7379
|
+
},
|
|
7380
|
+
[controls]
|
|
7381
|
+
);
|
|
7382
|
+
const sendModeChange = (0, import_react18.useCallback)(
|
|
7383
|
+
async (nodeId, mode) => {
|
|
7384
|
+
const binding = controls.get(nodeId);
|
|
7385
|
+
if (!binding) return;
|
|
7386
|
+
updateDeviceState(nodeId, { currentMode: mode });
|
|
7387
|
+
try {
|
|
7388
|
+
await binding.actions.onModeChange?.(mode);
|
|
7389
|
+
updateDeviceState(nodeId, {
|
|
7390
|
+
lastCommandTime: Date.now(),
|
|
7391
|
+
lastCommandResult: { success: true, message: `Mode changed to ${mode}` }
|
|
7392
|
+
});
|
|
7393
|
+
} catch (error) {
|
|
7394
|
+
updateDeviceState(nodeId, {
|
|
7395
|
+
currentMode: binding.state.currentMode,
|
|
7396
|
+
lastCommandResult: {
|
|
7397
|
+
success: false,
|
|
7398
|
+
message: error instanceof Error ? error.message : "Mode change failed"
|
|
7399
|
+
}
|
|
7400
|
+
});
|
|
7401
|
+
}
|
|
7402
|
+
},
|
|
7403
|
+
[controls, updateDeviceState]
|
|
7404
|
+
);
|
|
7405
|
+
const sendParameterChange = (0, import_react18.useCallback)(
|
|
7406
|
+
async (nodeId, parameterId, value) => {
|
|
7407
|
+
const binding = controls.get(nodeId);
|
|
7408
|
+
if (!binding) return;
|
|
7409
|
+
updateParameter(nodeId, parameterId, value);
|
|
7410
|
+
try {
|
|
7411
|
+
await binding.actions.onParameterChange?.(parameterId, value);
|
|
7412
|
+
updateDeviceState(nodeId, {
|
|
7413
|
+
lastCommandTime: Date.now(),
|
|
7414
|
+
lastCommandResult: { success: true, message: `Parameter ${parameterId} updated` }
|
|
7415
|
+
});
|
|
7416
|
+
} catch (error) {
|
|
7417
|
+
updateDeviceState(nodeId, {
|
|
7418
|
+
lastCommandResult: {
|
|
7419
|
+
success: false,
|
|
7420
|
+
message: error instanceof Error ? error.message : "Parameter change failed"
|
|
7421
|
+
}
|
|
7422
|
+
});
|
|
7423
|
+
}
|
|
7424
|
+
},
|
|
7425
|
+
[controls, updateParameter, updateDeviceState]
|
|
7426
|
+
);
|
|
7427
|
+
const sendStartCommand = (0, import_react18.useCallback)(
|
|
7428
|
+
async (nodeId) => {
|
|
7429
|
+
const binding = controls.get(nodeId);
|
|
7430
|
+
if (!binding) return;
|
|
7431
|
+
updateDeviceState(nodeId, { isRunning: true, status: "starting" });
|
|
7432
|
+
try {
|
|
7433
|
+
await binding.actions.onStart?.();
|
|
7434
|
+
updateDeviceState(nodeId, {
|
|
7435
|
+
status: "normal",
|
|
7436
|
+
lastCommandTime: Date.now(),
|
|
7437
|
+
lastCommandResult: { success: true, message: "Device started" }
|
|
7438
|
+
});
|
|
7439
|
+
} catch (error) {
|
|
7440
|
+
updateDeviceState(nodeId, {
|
|
7441
|
+
isRunning: false,
|
|
7442
|
+
status: "fault",
|
|
7443
|
+
lastCommandResult: {
|
|
7444
|
+
success: false,
|
|
7445
|
+
message: error instanceof Error ? error.message : "Start failed"
|
|
7446
|
+
}
|
|
7447
|
+
});
|
|
7448
|
+
}
|
|
7449
|
+
},
|
|
7450
|
+
[controls, updateDeviceState]
|
|
7451
|
+
);
|
|
7452
|
+
const sendStopCommand = (0, import_react18.useCallback)(
|
|
7453
|
+
async (nodeId) => {
|
|
7454
|
+
const binding = controls.get(nodeId);
|
|
7455
|
+
if (!binding) return;
|
|
7456
|
+
updateDeviceState(nodeId, { isRunning: false, status: "stopping" });
|
|
7457
|
+
try {
|
|
7458
|
+
await binding.actions.onStop?.();
|
|
7459
|
+
updateDeviceState(nodeId, {
|
|
7460
|
+
status: "off",
|
|
7461
|
+
lastCommandTime: Date.now(),
|
|
7462
|
+
lastCommandResult: { success: true, message: "Device stopped" }
|
|
7463
|
+
});
|
|
7464
|
+
} catch (error) {
|
|
7465
|
+
updateDeviceState(nodeId, {
|
|
7466
|
+
isRunning: true,
|
|
7467
|
+
status: "fault",
|
|
7468
|
+
lastCommandResult: {
|
|
7469
|
+
success: false,
|
|
7470
|
+
message: error instanceof Error ? error.message : "Stop failed"
|
|
7471
|
+
}
|
|
7472
|
+
});
|
|
7473
|
+
}
|
|
7474
|
+
},
|
|
7475
|
+
[controls, updateDeviceState]
|
|
7476
|
+
);
|
|
7477
|
+
const sendCustomAction = (0, import_react18.useCallback)(
|
|
7478
|
+
async (nodeId, actionId) => {
|
|
7479
|
+
const binding = controls.get(nodeId);
|
|
7480
|
+
if (!binding) return;
|
|
7481
|
+
try {
|
|
7482
|
+
await binding.actions.onCustomAction?.(actionId);
|
|
7483
|
+
updateDeviceState(nodeId, {
|
|
7484
|
+
lastCommandTime: Date.now(),
|
|
7485
|
+
lastCommandResult: { success: true, message: `Action ${actionId} executed` }
|
|
7486
|
+
});
|
|
7487
|
+
} catch (error) {
|
|
7488
|
+
updateDeviceState(nodeId, {
|
|
7489
|
+
lastCommandResult: {
|
|
7490
|
+
success: false,
|
|
7491
|
+
message: error instanceof Error ? error.message : "Action failed"
|
|
7492
|
+
}
|
|
7493
|
+
});
|
|
7494
|
+
}
|
|
7495
|
+
},
|
|
7496
|
+
[controls, updateDeviceState]
|
|
7497
|
+
);
|
|
7498
|
+
return {
|
|
7499
|
+
controls,
|
|
7500
|
+
updateControl,
|
|
7501
|
+
updateControlBatch,
|
|
7502
|
+
updateDeviceState,
|
|
7503
|
+
updateParameter,
|
|
7504
|
+
setControlBinding,
|
|
7505
|
+
removeControlBinding,
|
|
7506
|
+
getControlBinding,
|
|
7507
|
+
// Command helpers
|
|
7508
|
+
sendModeChange,
|
|
7509
|
+
sendParameterChange,
|
|
7510
|
+
sendStartCommand,
|
|
7511
|
+
sendStopCommand,
|
|
7512
|
+
sendCustomAction
|
|
7513
|
+
};
|
|
7514
|
+
}
|
|
7515
|
+
|
|
6481
7516
|
// src/diagram/hooks/useSimulation.ts
|
|
6482
|
-
var
|
|
7517
|
+
var import_react19 = require("react");
|
|
6483
7518
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
6484
7519
|
const {
|
|
6485
7520
|
interval = 2e3,
|
|
@@ -6490,7 +7525,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6490
7525
|
historyLength = 10,
|
|
6491
7526
|
generateValue
|
|
6492
7527
|
} = options;
|
|
6493
|
-
(0,
|
|
7528
|
+
(0, import_react19.useEffect)(() => {
|
|
6494
7529
|
if (!enabled) return;
|
|
6495
7530
|
const intervalId = setInterval(() => {
|
|
6496
7531
|
const updates = [];
|
|
@@ -6548,6 +7583,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6548
7583
|
ControlPanel,
|
|
6549
7584
|
DEFAULT_THRESHOLDS,
|
|
6550
7585
|
DashboardCard,
|
|
7586
|
+
DeviceControlPanel,
|
|
6551
7587
|
DisplayModeToggle,
|
|
6552
7588
|
EquipmentIndicator,
|
|
6553
7589
|
EquipmentIndicatorWithSparkline,
|
|
@@ -6559,6 +7595,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6559
7595
|
LeftToggleButton,
|
|
6560
7596
|
LegacyValueEntry,
|
|
6561
7597
|
NodeConfigPanel,
|
|
7598
|
+
NodeControlsPanel,
|
|
6562
7599
|
PIDCanvas,
|
|
6563
7600
|
PanelContent,
|
|
6564
7601
|
PanelTabs,
|
|
@@ -6578,6 +7615,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6578
7615
|
ZoomButton,
|
|
6579
7616
|
ZoomControls,
|
|
6580
7617
|
calculateThresholdStatus,
|
|
7618
|
+
createControlBinding,
|
|
6581
7619
|
exampleDiagram,
|
|
6582
7620
|
exportDiagram,
|
|
6583
7621
|
generateRoutePoints,
|
|
@@ -6588,6 +7626,9 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6588
7626
|
mockSymbolLibrary,
|
|
6589
7627
|
nodeHasPort,
|
|
6590
7628
|
overlayStyles,
|
|
7629
|
+
registerSymbol,
|
|
7630
|
+
registerSymbols,
|
|
7631
|
+
useDeviceControls,
|
|
6591
7632
|
useDrag,
|
|
6592
7633
|
useKeyboardShortcuts,
|
|
6593
7634
|
useSelection,
|