@procaaso/alphinity-ui-components 1.0.6 → 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 +1313 -321
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +305 -1
- package/dist/index.d.ts +305 -1
- package/dist/index.js +1248 -260
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -707,14 +707,721 @@ var StatusIndicator = ({
|
|
|
707
707
|
] });
|
|
708
708
|
};
|
|
709
709
|
|
|
710
|
+
// src/components/NodeControlsPanel/NodeControlsPanel.tsx
|
|
711
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
712
|
+
var NodeControlsPanel = ({
|
|
713
|
+
config,
|
|
714
|
+
onClose,
|
|
715
|
+
position = "bottom",
|
|
716
|
+
touchOptimized = true,
|
|
717
|
+
className = "",
|
|
718
|
+
style,
|
|
719
|
+
...props
|
|
720
|
+
}) => {
|
|
721
|
+
if (!config) return null;
|
|
722
|
+
const isBottom = position === "bottom";
|
|
723
|
+
const touchClass = touchOptimized ? "touch-optimized" : "";
|
|
724
|
+
const containerStyle = {
|
|
725
|
+
position: "fixed",
|
|
726
|
+
zIndex: 9999,
|
|
727
|
+
background: "white",
|
|
728
|
+
boxShadow: "0 -4px 16px rgba(0, 0, 0, 0.15)",
|
|
729
|
+
borderRadius: isBottom ? "16px 16px 0 0" : "0",
|
|
730
|
+
animation: isBottom ? "slideUp 0.3s ease-out" : "slideInRight 0.3s ease-out",
|
|
731
|
+
display: "flex",
|
|
732
|
+
flexDirection: "column",
|
|
733
|
+
...isBottom ? {
|
|
734
|
+
left: 0,
|
|
735
|
+
right: 0,
|
|
736
|
+
bottom: 0,
|
|
737
|
+
maxHeight: "70vh",
|
|
738
|
+
borderTop: "1px solid #e5e7eb"
|
|
739
|
+
} : {
|
|
740
|
+
right: 0,
|
|
741
|
+
top: 0,
|
|
742
|
+
bottom: 0,
|
|
743
|
+
width: touchOptimized ? "400px" : "320px",
|
|
744
|
+
borderLeft: "1px solid #e5e7eb"
|
|
745
|
+
},
|
|
746
|
+
...style
|
|
747
|
+
};
|
|
748
|
+
const headerStyle = {
|
|
749
|
+
display: "flex",
|
|
750
|
+
alignItems: "center",
|
|
751
|
+
justifyContent: "space-between",
|
|
752
|
+
padding: touchOptimized ? "1.25rem 1.5rem" : "1rem",
|
|
753
|
+
borderBottom: "2px solid #e5e7eb",
|
|
754
|
+
background: "#f9fafb",
|
|
755
|
+
flexShrink: 0
|
|
756
|
+
};
|
|
757
|
+
const titleStyle = {
|
|
758
|
+
margin: 0,
|
|
759
|
+
fontSize: touchOptimized ? "1.5rem" : "1.25rem",
|
|
760
|
+
fontWeight: 600,
|
|
761
|
+
color: "#111827"
|
|
762
|
+
};
|
|
763
|
+
const closeButtonStyle = {
|
|
764
|
+
background: "#ef4444",
|
|
765
|
+
color: "white",
|
|
766
|
+
border: "none",
|
|
767
|
+
borderRadius: "8px",
|
|
768
|
+
width: touchOptimized ? "56px" : "44px",
|
|
769
|
+
height: touchOptimized ? "56px" : "44px",
|
|
770
|
+
fontSize: touchOptimized ? "1.75rem" : "1.5rem",
|
|
771
|
+
fontWeight: "bold",
|
|
772
|
+
cursor: "pointer",
|
|
773
|
+
display: "flex",
|
|
774
|
+
alignItems: "center",
|
|
775
|
+
justifyContent: "center",
|
|
776
|
+
transition: "all 0.2s ease",
|
|
777
|
+
flexShrink: 0
|
|
778
|
+
};
|
|
779
|
+
const contentStyle = {
|
|
780
|
+
padding: touchOptimized ? "1.5rem" : "1rem",
|
|
781
|
+
overflowY: "auto",
|
|
782
|
+
flex: 1
|
|
783
|
+
};
|
|
784
|
+
return /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
785
|
+
/* @__PURE__ */ jsx7(
|
|
786
|
+
"div",
|
|
787
|
+
{
|
|
788
|
+
style: {
|
|
789
|
+
position: "fixed",
|
|
790
|
+
inset: 0,
|
|
791
|
+
background: "rgba(0, 0, 0, 0.3)",
|
|
792
|
+
zIndex: 9998,
|
|
793
|
+
animation: "fadeIn 0.3s ease-out"
|
|
794
|
+
},
|
|
795
|
+
onClick: onClose
|
|
796
|
+
}
|
|
797
|
+
),
|
|
798
|
+
/* @__PURE__ */ jsxs6(
|
|
799
|
+
"div",
|
|
800
|
+
{
|
|
801
|
+
className: `node-controls-panel ${touchClass} ${className}`.trim(),
|
|
802
|
+
style: containerStyle,
|
|
803
|
+
...props,
|
|
804
|
+
children: [
|
|
805
|
+
/* @__PURE__ */ jsxs6("div", { style: headerStyle, children: [
|
|
806
|
+
/* @__PURE__ */ jsx7("h2", { style: titleStyle, children: config.title }),
|
|
807
|
+
/* @__PURE__ */ jsx7(
|
|
808
|
+
"button",
|
|
809
|
+
{
|
|
810
|
+
style: closeButtonStyle,
|
|
811
|
+
onClick: onClose,
|
|
812
|
+
onMouseEnter: (e) => {
|
|
813
|
+
e.currentTarget.style.background = "#dc2626";
|
|
814
|
+
e.currentTarget.style.transform = "scale(1.05)";
|
|
815
|
+
},
|
|
816
|
+
onMouseLeave: (e) => {
|
|
817
|
+
e.currentTarget.style.background = "#ef4444";
|
|
818
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
819
|
+
},
|
|
820
|
+
"aria-label": "Close",
|
|
821
|
+
children: "\u2715"
|
|
822
|
+
}
|
|
823
|
+
)
|
|
824
|
+
] }),
|
|
825
|
+
/* @__PURE__ */ jsx7("div", { style: contentStyle, children: /* @__PURE__ */ jsx7(
|
|
826
|
+
ControlPanel,
|
|
827
|
+
{
|
|
828
|
+
title: config.nodeId,
|
|
829
|
+
selectedMode: config.currentMode,
|
|
830
|
+
modeOptions: config.modes,
|
|
831
|
+
onModeChange: config.onModeChange,
|
|
832
|
+
setpointValue: config.setpoint,
|
|
833
|
+
onSetpointChange: config.onSetpointChange,
|
|
834
|
+
secondSetpointValue: config.secondSetpoint,
|
|
835
|
+
onSecondSetpointChange: config.onSecondSetpointChange,
|
|
836
|
+
modeConfigs: config.modeConfigs,
|
|
837
|
+
status: config.status,
|
|
838
|
+
setpointReadOnly: config.readOnly,
|
|
839
|
+
showStartStopButtons: !!(config.onStart || config.onStop),
|
|
840
|
+
isRunning: config.isRunning,
|
|
841
|
+
onStart: config.onStart,
|
|
842
|
+
onStop: config.onStop,
|
|
843
|
+
startButtonText: config.startButtonText,
|
|
844
|
+
stopButtonText: config.stopButtonText,
|
|
845
|
+
size: touchOptimized ? "large" : "medium"
|
|
846
|
+
}
|
|
847
|
+
) })
|
|
848
|
+
]
|
|
849
|
+
}
|
|
850
|
+
),
|
|
851
|
+
/* @__PURE__ */ jsx7("style", { children: `
|
|
852
|
+
@keyframes slideUp {
|
|
853
|
+
from {
|
|
854
|
+
transform: translateY(100%);
|
|
855
|
+
opacity: 0;
|
|
856
|
+
}
|
|
857
|
+
to {
|
|
858
|
+
transform: translateY(0);
|
|
859
|
+
opacity: 1;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
@keyframes slideInRight {
|
|
864
|
+
from {
|
|
865
|
+
transform: translateX(100%);
|
|
866
|
+
opacity: 0;
|
|
867
|
+
}
|
|
868
|
+
to {
|
|
869
|
+
transform: translateX(0);
|
|
870
|
+
opacity: 1;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
@keyframes fadeIn {
|
|
875
|
+
from {
|
|
876
|
+
opacity: 0;
|
|
877
|
+
}
|
|
878
|
+
to {
|
|
879
|
+
opacity: 1;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.node-controls-panel.touch-optimized button {
|
|
884
|
+
min-height: 56px;
|
|
885
|
+
font-size: 1.125rem;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
.node-controls-panel.touch-optimized input {
|
|
889
|
+
min-height: 56px;
|
|
890
|
+
font-size: 1.125rem;
|
|
891
|
+
}
|
|
892
|
+
` })
|
|
893
|
+
] });
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
// src/components/DeviceControlPanel/DeviceControlPanel.tsx
|
|
897
|
+
import { useState as useState5, useEffect as useEffect2 } from "react";
|
|
898
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
899
|
+
function DeviceControlPanel({
|
|
900
|
+
binding,
|
|
901
|
+
onClose,
|
|
902
|
+
position = "bottom",
|
|
903
|
+
touchOptimized = true,
|
|
904
|
+
onModeChange,
|
|
905
|
+
onParameterChange,
|
|
906
|
+
onStart,
|
|
907
|
+
onStop,
|
|
908
|
+
onCustomAction
|
|
909
|
+
}) {
|
|
910
|
+
const [localParameterValues, setLocalParameterValues] = useState5({});
|
|
911
|
+
useEffect2(() => {
|
|
912
|
+
if (binding) {
|
|
913
|
+
const currentParams2 = binding.parameters[binding.state.currentMode] || [];
|
|
914
|
+
const values = {};
|
|
915
|
+
currentParams2.forEach((param) => {
|
|
916
|
+
values[param.id] = param.value;
|
|
917
|
+
});
|
|
918
|
+
setLocalParameterValues(values);
|
|
919
|
+
}
|
|
920
|
+
}, [binding, binding?.state.currentMode]);
|
|
921
|
+
if (!binding) return null;
|
|
922
|
+
const currentMode = binding.state.currentMode;
|
|
923
|
+
const currentParams = binding.parameters[currentMode] || [];
|
|
924
|
+
const touchSize = touchOptimized ? 56 : 40;
|
|
925
|
+
const backgroundColor = binding.theme?.backgroundColor || "#edeeef";
|
|
926
|
+
const surfaceColor = "#f5f6f7";
|
|
927
|
+
const borderColor = "#d2d2d2";
|
|
928
|
+
const textColor = binding.theme?.textColor || "#000000";
|
|
929
|
+
const mutedTextColor = "#666666";
|
|
930
|
+
const selectedColor = "#b4d0fe";
|
|
931
|
+
const statusColors = {
|
|
932
|
+
normal: binding.theme?.statusColors?.normal || "#888888",
|
|
933
|
+
// Gray (no alarm)
|
|
934
|
+
warning: binding.theme?.statusColors?.warning || "#FFD700",
|
|
935
|
+
// Yellow
|
|
936
|
+
alarm: binding.theme?.statusColors?.alarm || "#FF0000",
|
|
937
|
+
// Red
|
|
938
|
+
fault: binding.theme?.statusColors?.fault || "#FF0000",
|
|
939
|
+
// Red
|
|
940
|
+
off: binding.theme?.statusColors?.off || "#666666",
|
|
941
|
+
// Dark gray
|
|
942
|
+
starting: binding.theme?.statusColors?.starting || "#90EE90",
|
|
943
|
+
// Light green
|
|
944
|
+
stopping: binding.theme?.statusColors?.stopping || "#FFD700"
|
|
945
|
+
// Yellow
|
|
946
|
+
};
|
|
947
|
+
const statusColor = statusColors[binding.state.status || "normal"];
|
|
948
|
+
const handleModeChange = (mode) => {
|
|
949
|
+
onModeChange?.(mode);
|
|
950
|
+
};
|
|
951
|
+
const handleParameterCommit = (parameterId, value) => {
|
|
952
|
+
onParameterChange?.(parameterId, value);
|
|
953
|
+
};
|
|
954
|
+
const handleParameterInput = (parameterId, value) => {
|
|
955
|
+
setLocalParameterValues((prev) => ({ ...prev, [parameterId]: value }));
|
|
956
|
+
};
|
|
957
|
+
const panelStyle = {
|
|
958
|
+
position: "fixed",
|
|
959
|
+
...position === "bottom" ? {
|
|
960
|
+
bottom: 0,
|
|
961
|
+
left: 0,
|
|
962
|
+
right: 0,
|
|
963
|
+
animation: "slideUp 0.3s ease-out"
|
|
964
|
+
} : {
|
|
965
|
+
right: 0,
|
|
966
|
+
top: 0,
|
|
967
|
+
bottom: 0,
|
|
968
|
+
width: "400px",
|
|
969
|
+
animation: "slideIn 0.3s ease-out"
|
|
970
|
+
},
|
|
971
|
+
backgroundColor,
|
|
972
|
+
color: textColor,
|
|
973
|
+
borderRadius: position === "bottom" ? "8px 8px 0 0" : "8px 0 0 8px",
|
|
974
|
+
boxShadow: "none",
|
|
975
|
+
border: `2px solid ${borderColor}`,
|
|
976
|
+
padding: "20px",
|
|
977
|
+
zIndex: 9999,
|
|
978
|
+
maxHeight: position === "bottom" ? "70vh" : "100vh",
|
|
979
|
+
overflowY: "auto",
|
|
980
|
+
...binding.display?.style
|
|
981
|
+
};
|
|
982
|
+
const titleText = binding.display?.title || binding.deviceName || binding.tag || binding.nodeId;
|
|
983
|
+
return /* @__PURE__ */ jsx8(Fragment2, { children: /* @__PURE__ */ jsxs7("div", { style: panelStyle, className: binding.display?.className, children: [
|
|
984
|
+
/* @__PURE__ */ jsxs7(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
style: {
|
|
988
|
+
display: "flex",
|
|
989
|
+
justifyContent: "space-between",
|
|
990
|
+
alignItems: "center",
|
|
991
|
+
marginBottom: "16px",
|
|
992
|
+
paddingBottom: "12px",
|
|
993
|
+
borderBottom: `2px solid ${borderColor}`
|
|
994
|
+
},
|
|
995
|
+
children: [
|
|
996
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
997
|
+
/* @__PURE__ */ jsx8(
|
|
998
|
+
"h3",
|
|
999
|
+
{
|
|
1000
|
+
style: {
|
|
1001
|
+
margin: 0,
|
|
1002
|
+
fontSize: "14px",
|
|
1003
|
+
fontWeight: 600,
|
|
1004
|
+
fontFamily: "Arial, sans-serif",
|
|
1005
|
+
letterSpacing: "0.5px",
|
|
1006
|
+
textTransform: "uppercase",
|
|
1007
|
+
color: textColor
|
|
1008
|
+
},
|
|
1009
|
+
children: titleText
|
|
1010
|
+
}
|
|
1011
|
+
),
|
|
1012
|
+
binding.deviceType && /* @__PURE__ */ jsx8(
|
|
1013
|
+
"div",
|
|
1014
|
+
{
|
|
1015
|
+
style: {
|
|
1016
|
+
fontSize: "11px",
|
|
1017
|
+
color: mutedTextColor,
|
|
1018
|
+
marginTop: "4px",
|
|
1019
|
+
fontFamily: "Arial, sans-serif"
|
|
1020
|
+
},
|
|
1021
|
+
children: binding.deviceType
|
|
1022
|
+
}
|
|
1023
|
+
)
|
|
1024
|
+
] }),
|
|
1025
|
+
/* @__PURE__ */ jsx8(
|
|
1026
|
+
"button",
|
|
1027
|
+
{
|
|
1028
|
+
onClick: onClose,
|
|
1029
|
+
style: {
|
|
1030
|
+
width: touchSize * 0.7,
|
|
1031
|
+
height: touchSize * 0.7,
|
|
1032
|
+
backgroundColor: surfaceColor,
|
|
1033
|
+
color: textColor,
|
|
1034
|
+
border: `2px solid ${borderColor}`,
|
|
1035
|
+
borderRadius: "2px",
|
|
1036
|
+
fontSize: "18px",
|
|
1037
|
+
cursor: "pointer",
|
|
1038
|
+
fontWeight: "bold",
|
|
1039
|
+
fontFamily: "Arial, sans-serif"
|
|
1040
|
+
},
|
|
1041
|
+
children: "\xD7"
|
|
1042
|
+
}
|
|
1043
|
+
)
|
|
1044
|
+
]
|
|
1045
|
+
}
|
|
1046
|
+
),
|
|
1047
|
+
binding.state.status && /* @__PURE__ */ jsxs7(
|
|
1048
|
+
"div",
|
|
1049
|
+
{
|
|
1050
|
+
style: {
|
|
1051
|
+
display: "flex",
|
|
1052
|
+
alignItems: "center",
|
|
1053
|
+
gap: "12px",
|
|
1054
|
+
padding: "10px 12px",
|
|
1055
|
+
backgroundColor: surfaceColor,
|
|
1056
|
+
border: `1px solid ${borderColor}`,
|
|
1057
|
+
borderRadius: "6px",
|
|
1058
|
+
marginBottom: "16px"
|
|
1059
|
+
},
|
|
1060
|
+
children: [
|
|
1061
|
+
/* @__PURE__ */ jsx8(
|
|
1062
|
+
"div",
|
|
1063
|
+
{
|
|
1064
|
+
style: {
|
|
1065
|
+
width: "10px",
|
|
1066
|
+
height: "10px",
|
|
1067
|
+
borderRadius: "50%",
|
|
1068
|
+
backgroundColor: statusColor,
|
|
1069
|
+
border: "1px solid #333"
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
),
|
|
1073
|
+
/* @__PURE__ */ jsxs7("div", { style: { flex: 1 }, children: [
|
|
1074
|
+
/* @__PURE__ */ jsx8(
|
|
1075
|
+
"div",
|
|
1076
|
+
{
|
|
1077
|
+
style: {
|
|
1078
|
+
fontWeight: 600,
|
|
1079
|
+
textTransform: "uppercase",
|
|
1080
|
+
fontSize: "11px",
|
|
1081
|
+
fontFamily: "Arial, sans-serif",
|
|
1082
|
+
letterSpacing: "0.5px",
|
|
1083
|
+
color: textColor
|
|
1084
|
+
},
|
|
1085
|
+
children: binding.state.status
|
|
1086
|
+
}
|
|
1087
|
+
),
|
|
1088
|
+
binding.state.statusMessage && /* @__PURE__ */ jsx8(
|
|
1089
|
+
"div",
|
|
1090
|
+
{
|
|
1091
|
+
style: {
|
|
1092
|
+
fontSize: "10px",
|
|
1093
|
+
color: mutedTextColor,
|
|
1094
|
+
marginTop: "2px",
|
|
1095
|
+
fontFamily: "Arial, sans-serif"
|
|
1096
|
+
},
|
|
1097
|
+
children: binding.state.statusMessage
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
] }),
|
|
1101
|
+
binding.state.isRunning !== void 0 && /* @__PURE__ */ jsx8(
|
|
1102
|
+
"div",
|
|
1103
|
+
{
|
|
1104
|
+
style: {
|
|
1105
|
+
padding: "4px 10px",
|
|
1106
|
+
backgroundColor: binding.state.isRunning ? selectedColor : surfaceColor,
|
|
1107
|
+
border: `1px solid ${borderColor}`,
|
|
1108
|
+
borderRadius: "2px",
|
|
1109
|
+
fontSize: "10px",
|
|
1110
|
+
fontWeight: 600,
|
|
1111
|
+
fontFamily: "Arial, sans-serif",
|
|
1112
|
+
letterSpacing: "0.5px",
|
|
1113
|
+
color: textColor
|
|
1114
|
+
},
|
|
1115
|
+
children: binding.state.isRunning ? "RUNNING" : "STOPPED"
|
|
1116
|
+
}
|
|
1117
|
+
)
|
|
1118
|
+
]
|
|
1119
|
+
}
|
|
1120
|
+
),
|
|
1121
|
+
binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ jsxs7("div", { style: { marginBottom: "16px" }, children: [
|
|
1122
|
+
/* @__PURE__ */ jsx8(
|
|
1123
|
+
"label",
|
|
1124
|
+
{
|
|
1125
|
+
style: {
|
|
1126
|
+
display: "block",
|
|
1127
|
+
marginBottom: "8px",
|
|
1128
|
+
fontSize: "11px",
|
|
1129
|
+
fontWeight: 600,
|
|
1130
|
+
textTransform: "uppercase",
|
|
1131
|
+
letterSpacing: "0.5px",
|
|
1132
|
+
fontFamily: "Arial, sans-serif",
|
|
1133
|
+
color: mutedTextColor
|
|
1134
|
+
},
|
|
1135
|
+
children: "Mode"
|
|
1136
|
+
}
|
|
1137
|
+
),
|
|
1138
|
+
/* @__PURE__ */ jsx8("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: binding.modes.map((mode) => {
|
|
1139
|
+
const isSelected = mode.value === currentMode;
|
|
1140
|
+
const isEnabled = mode.enabled !== false;
|
|
1141
|
+
return /* @__PURE__ */ jsx8(
|
|
1142
|
+
"button",
|
|
1143
|
+
{
|
|
1144
|
+
onClick: () => isEnabled && handleModeChange(mode.value),
|
|
1145
|
+
disabled: !isEnabled,
|
|
1146
|
+
style: {
|
|
1147
|
+
flex: 1,
|
|
1148
|
+
minWidth: "80px",
|
|
1149
|
+
height: touchSize,
|
|
1150
|
+
backgroundColor: isSelected ? selectedColor : surfaceColor,
|
|
1151
|
+
color: isSelected ? "#000000" : textColor,
|
|
1152
|
+
border: `1px solid ${isSelected ? "#b4d0fe" : borderColor}`,
|
|
1153
|
+
borderRadius: "6px",
|
|
1154
|
+
fontSize: "11px",
|
|
1155
|
+
fontWeight: 600,
|
|
1156
|
+
fontFamily: "Arial, sans-serif",
|
|
1157
|
+
letterSpacing: "0.5px",
|
|
1158
|
+
textTransform: "uppercase",
|
|
1159
|
+
cursor: isEnabled ? "pointer" : "not-allowed",
|
|
1160
|
+
opacity: isEnabled ? 1 : 0.4
|
|
1161
|
+
},
|
|
1162
|
+
children: mode.label
|
|
1163
|
+
},
|
|
1164
|
+
mode.value
|
|
1165
|
+
);
|
|
1166
|
+
}) })
|
|
1167
|
+
] }),
|
|
1168
|
+
currentParams.length > 0 && /* @__PURE__ */ jsxs7("div", { style: { marginBottom: "16px" }, children: [
|
|
1169
|
+
/* @__PURE__ */ jsx8(
|
|
1170
|
+
"label",
|
|
1171
|
+
{
|
|
1172
|
+
style: {
|
|
1173
|
+
display: "block",
|
|
1174
|
+
marginBottom: "8px",
|
|
1175
|
+
fontSize: "11px",
|
|
1176
|
+
fontWeight: 600,
|
|
1177
|
+
textTransform: "uppercase",
|
|
1178
|
+
letterSpacing: "0.5px",
|
|
1179
|
+
fontFamily: "Arial, sans-serif",
|
|
1180
|
+
color: mutedTextColor
|
|
1181
|
+
},
|
|
1182
|
+
children: "Parameters"
|
|
1183
|
+
}
|
|
1184
|
+
),
|
|
1185
|
+
currentParams.map((param) => /* @__PURE__ */ jsxs7(
|
|
1186
|
+
"div",
|
|
1187
|
+
{
|
|
1188
|
+
style: {
|
|
1189
|
+
marginBottom: "10px",
|
|
1190
|
+
padding: "10px",
|
|
1191
|
+
backgroundColor: surfaceColor,
|
|
1192
|
+
border: `1px solid ${borderColor}`,
|
|
1193
|
+
borderRadius: "6px"
|
|
1194
|
+
},
|
|
1195
|
+
children: [
|
|
1196
|
+
/* @__PURE__ */ jsxs7(
|
|
1197
|
+
"div",
|
|
1198
|
+
{
|
|
1199
|
+
style: { display: "flex", justifyContent: "space-between", marginBottom: "8px" },
|
|
1200
|
+
children: [
|
|
1201
|
+
/* @__PURE__ */ jsx8(
|
|
1202
|
+
"span",
|
|
1203
|
+
{
|
|
1204
|
+
style: {
|
|
1205
|
+
fontSize: "11px",
|
|
1206
|
+
fontWeight: 600,
|
|
1207
|
+
textTransform: "uppercase",
|
|
1208
|
+
letterSpacing: "0.5px",
|
|
1209
|
+
fontFamily: "Arial, sans-serif",
|
|
1210
|
+
color: mutedTextColor
|
|
1211
|
+
},
|
|
1212
|
+
children: param.label
|
|
1213
|
+
}
|
|
1214
|
+
),
|
|
1215
|
+
/* @__PURE__ */ jsxs7(
|
|
1216
|
+
"span",
|
|
1217
|
+
{
|
|
1218
|
+
style: {
|
|
1219
|
+
fontSize: "13px",
|
|
1220
|
+
fontWeight: 700,
|
|
1221
|
+
fontFamily: "Arial, sans-serif",
|
|
1222
|
+
color: textColor
|
|
1223
|
+
},
|
|
1224
|
+
children: [
|
|
1225
|
+
localParameterValues[param.id] ?? param.value,
|
|
1226
|
+
" ",
|
|
1227
|
+
param.unit && /* @__PURE__ */ jsx8("span", { style: { color: mutedTextColor, fontSize: "10px", fontWeight: 600 }, children: param.unit })
|
|
1228
|
+
]
|
|
1229
|
+
}
|
|
1230
|
+
)
|
|
1231
|
+
]
|
|
1232
|
+
}
|
|
1233
|
+
),
|
|
1234
|
+
param.type === "boolean" ? /* @__PURE__ */ jsx8(
|
|
1235
|
+
"button",
|
|
1236
|
+
{
|
|
1237
|
+
onClick: () => {
|
|
1238
|
+
const newValue = !localParameterValues[param.id];
|
|
1239
|
+
handleParameterInput(param.id, newValue);
|
|
1240
|
+
handleParameterCommit(param.id, newValue);
|
|
1241
|
+
},
|
|
1242
|
+
disabled: param.readOnly,
|
|
1243
|
+
style: {
|
|
1244
|
+
width: "100%",
|
|
1245
|
+
height: touchSize,
|
|
1246
|
+
backgroundColor: localParameterValues[param.id] ? "#3f3f46" : surfaceColor,
|
|
1247
|
+
color: localParameterValues[param.id] ? textColor : mutedTextColor,
|
|
1248
|
+
border: `1px solid ${localParameterValues[param.id] ? "#52525b" : borderColor}`,
|
|
1249
|
+
borderRadius: "4px",
|
|
1250
|
+
fontSize: "12px",
|
|
1251
|
+
fontWeight: 600,
|
|
1252
|
+
fontFamily: "monospace",
|
|
1253
|
+
letterSpacing: "0.5px",
|
|
1254
|
+
cursor: param.readOnly ? "not-allowed" : "pointer",
|
|
1255
|
+
transition: "all 0.15s"
|
|
1256
|
+
},
|
|
1257
|
+
children: localParameterValues[param.id] ? "ON" : "OFF"
|
|
1258
|
+
}
|
|
1259
|
+
) : param.type === "select" ? /* @__PURE__ */ jsx8(
|
|
1260
|
+
"select",
|
|
1261
|
+
{
|
|
1262
|
+
value: localParameterValues[param.id] || param.value,
|
|
1263
|
+
onChange: (e) => {
|
|
1264
|
+
handleParameterInput(param.id, e.target.value);
|
|
1265
|
+
handleParameterCommit(param.id, e.target.value);
|
|
1266
|
+
},
|
|
1267
|
+
disabled: param.readOnly,
|
|
1268
|
+
style: {
|
|
1269
|
+
width: "100%",
|
|
1270
|
+
height: touchSize,
|
|
1271
|
+
backgroundColor: surfaceColor,
|
|
1272
|
+
color: textColor,
|
|
1273
|
+
border: `1px solid ${borderColor}`,
|
|
1274
|
+
borderRadius: "4px",
|
|
1275
|
+
padding: "0 12px",
|
|
1276
|
+
fontSize: "12px",
|
|
1277
|
+
fontFamily: "monospace",
|
|
1278
|
+
cursor: "pointer"
|
|
1279
|
+
},
|
|
1280
|
+
children: param.options?.map((opt) => /* @__PURE__ */ jsx8("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1281
|
+
}
|
|
1282
|
+
) : /* @__PURE__ */ jsx8(
|
|
1283
|
+
"input",
|
|
1284
|
+
{
|
|
1285
|
+
type: param.type === "number" ? "number" : "text",
|
|
1286
|
+
value: localParameterValues[param.id] ?? param.value,
|
|
1287
|
+
onChange: (e) => handleParameterInput(
|
|
1288
|
+
param.id,
|
|
1289
|
+
param.type === "number" ? +e.target.value : e.target.value
|
|
1290
|
+
),
|
|
1291
|
+
onBlur: () => handleParameterCommit(param.id, localParameterValues[param.id]),
|
|
1292
|
+
disabled: param.readOnly,
|
|
1293
|
+
min: param.min,
|
|
1294
|
+
max: param.max,
|
|
1295
|
+
step: param.step,
|
|
1296
|
+
style: {
|
|
1297
|
+
width: "100%",
|
|
1298
|
+
height: touchSize,
|
|
1299
|
+
backgroundColor: "#ffffff",
|
|
1300
|
+
color: textColor,
|
|
1301
|
+
border: `1px solid ${borderColor}`,
|
|
1302
|
+
borderRadius: "6px",
|
|
1303
|
+
padding: "0 12px",
|
|
1304
|
+
fontSize: "14px",
|
|
1305
|
+
fontFamily: "Arial, sans-serif",
|
|
1306
|
+
fontWeight: 600
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
)
|
|
1310
|
+
]
|
|
1311
|
+
},
|
|
1312
|
+
param.id
|
|
1313
|
+
))
|
|
1314
|
+
] }),
|
|
1315
|
+
binding.display?.showStartStop !== false && (binding.capabilities?.canStart || binding.capabilities?.canStop) && /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: "8px", marginBottom: "16px" }, children: [
|
|
1316
|
+
binding.capabilities?.canStart && /* @__PURE__ */ jsx8(
|
|
1317
|
+
"button",
|
|
1318
|
+
{
|
|
1319
|
+
onClick: onStart,
|
|
1320
|
+
disabled: binding.state.isRunning,
|
|
1321
|
+
style: {
|
|
1322
|
+
flex: 1,
|
|
1323
|
+
height: touchSize,
|
|
1324
|
+
backgroundColor: binding.state.isRunning ? "#a3a3a3" : "#10b981",
|
|
1325
|
+
color: "#ffffff",
|
|
1326
|
+
border: "none",
|
|
1327
|
+
borderRadius: "6px",
|
|
1328
|
+
fontSize: "12px",
|
|
1329
|
+
fontWeight: 700,
|
|
1330
|
+
fontFamily: "Arial, sans-serif",
|
|
1331
|
+
letterSpacing: "0.5px",
|
|
1332
|
+
cursor: binding.state.isRunning ? "not-allowed" : "pointer",
|
|
1333
|
+
opacity: binding.state.isRunning ? 0.5 : 1
|
|
1334
|
+
},
|
|
1335
|
+
children: "START"
|
|
1336
|
+
}
|
|
1337
|
+
),
|
|
1338
|
+
binding.capabilities?.canStop && /* @__PURE__ */ jsx8(
|
|
1339
|
+
"button",
|
|
1340
|
+
{
|
|
1341
|
+
onClick: onStop,
|
|
1342
|
+
disabled: !binding.state.isRunning,
|
|
1343
|
+
style: {
|
|
1344
|
+
flex: 1,
|
|
1345
|
+
height: touchSize,
|
|
1346
|
+
backgroundColor: !binding.state.isRunning ? "#a3a3a3" : "#ef4444",
|
|
1347
|
+
color: "#ffffff",
|
|
1348
|
+
border: "none",
|
|
1349
|
+
borderRadius: "6px",
|
|
1350
|
+
fontSize: "12px",
|
|
1351
|
+
fontWeight: 700,
|
|
1352
|
+
fontFamily: "Arial, sans-serif",
|
|
1353
|
+
letterSpacing: "0.5px",
|
|
1354
|
+
cursor: !binding.state.isRunning ? "not-allowed" : "pointer",
|
|
1355
|
+
opacity: !binding.state.isRunning ? 0.5 : 1
|
|
1356
|
+
},
|
|
1357
|
+
children: "STOP"
|
|
1358
|
+
}
|
|
1359
|
+
)
|
|
1360
|
+
] }),
|
|
1361
|
+
binding.capabilities?.customActions && binding.capabilities.customActions.length > 0 && /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: binding.capabilities.customActions.map((action) => /* @__PURE__ */ jsxs7(
|
|
1362
|
+
"button",
|
|
1363
|
+
{
|
|
1364
|
+
onClick: () => onCustomAction?.(action.id),
|
|
1365
|
+
style: {
|
|
1366
|
+
flex: 1,
|
|
1367
|
+
minWidth: "120px",
|
|
1368
|
+
height: touchSize,
|
|
1369
|
+
backgroundColor: surfaceColor,
|
|
1370
|
+
color: textColor,
|
|
1371
|
+
border: `1px solid ${borderColor}`,
|
|
1372
|
+
borderRadius: "6px",
|
|
1373
|
+
fontSize: "11px",
|
|
1374
|
+
fontWeight: 600,
|
|
1375
|
+
fontFamily: "monospace",
|
|
1376
|
+
letterSpacing: "0.5px",
|
|
1377
|
+
textTransform: "uppercase",
|
|
1378
|
+
cursor: "pointer",
|
|
1379
|
+
transition: "all 0.15s"
|
|
1380
|
+
},
|
|
1381
|
+
children: [
|
|
1382
|
+
action.icon && /* @__PURE__ */ jsx8("span", { style: { marginRight: "6px" }, children: action.icon }),
|
|
1383
|
+
action.label
|
|
1384
|
+
]
|
|
1385
|
+
},
|
|
1386
|
+
action.id
|
|
1387
|
+
)) }),
|
|
1388
|
+
binding.state.lastCommandResult && /* @__PURE__ */ jsx8(
|
|
1389
|
+
"div",
|
|
1390
|
+
{
|
|
1391
|
+
style: {
|
|
1392
|
+
marginTop: "16px",
|
|
1393
|
+
padding: "10px 12px",
|
|
1394
|
+
backgroundColor: surfaceColor,
|
|
1395
|
+
border: `1px solid ${binding.state.lastCommandResult.success ? "#52525b" : borderColor}`,
|
|
1396
|
+
borderRadius: "4px",
|
|
1397
|
+
fontSize: "11px",
|
|
1398
|
+
fontFamily: "monospace",
|
|
1399
|
+
color: binding.state.lastCommandResult.success ? textColor : mutedTextColor
|
|
1400
|
+
},
|
|
1401
|
+
children: binding.state.lastCommandResult.message
|
|
1402
|
+
}
|
|
1403
|
+
),
|
|
1404
|
+
/* @__PURE__ */ jsx8("style", { children: `
|
|
1405
|
+
@keyframes slideUp {
|
|
1406
|
+
from { transform: translateY(100%); }
|
|
1407
|
+
to { transform: translateY(0); }
|
|
1408
|
+
}
|
|
1409
|
+
@keyframes slideIn {
|
|
1410
|
+
from { transform: translateX(100%); }
|
|
1411
|
+
to { transform: translateX(0); }
|
|
1412
|
+
}
|
|
1413
|
+
` })
|
|
1414
|
+
] }) });
|
|
1415
|
+
}
|
|
1416
|
+
|
|
710
1417
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
711
|
-
import
|
|
1418
|
+
import React6 from "react";
|
|
712
1419
|
import { Tab } from "@mui/material";
|
|
713
1420
|
|
|
714
1421
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
|
|
715
1422
|
import { Box, IconButton, Tabs } from "@mui/material";
|
|
716
1423
|
import styled from "@emotion/styled";
|
|
717
|
-
import { jsx as
|
|
1424
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
718
1425
|
var FullscreenContainer = styled(Box)(
|
|
719
1426
|
({ leftCollapsed, rightCollapsed }) => {
|
|
720
1427
|
const getGridTemplateAreas = () => {
|
|
@@ -839,7 +1546,7 @@ var DisplayModeToggle = styled(IconButton)(({ mode }) => ({
|
|
|
839
1546
|
transform: "translateX(-50%) scale(1.05)"
|
|
840
1547
|
}
|
|
841
1548
|
}));
|
|
842
|
-
var ChevronLeft = () => /* @__PURE__ */
|
|
1549
|
+
var ChevronLeft = () => /* @__PURE__ */ jsx9(
|
|
843
1550
|
"div",
|
|
844
1551
|
{
|
|
845
1552
|
style: {
|
|
@@ -851,7 +1558,7 @@ var ChevronLeft = () => /* @__PURE__ */ jsx7(
|
|
|
851
1558
|
}
|
|
852
1559
|
}
|
|
853
1560
|
);
|
|
854
|
-
var ChevronRight = () => /* @__PURE__ */
|
|
1561
|
+
var ChevronRight = () => /* @__PURE__ */ jsx9(
|
|
855
1562
|
"div",
|
|
856
1563
|
{
|
|
857
1564
|
style: {
|
|
@@ -962,10 +1669,10 @@ var ScrollableSVGWrapper = styled("div")({
|
|
|
962
1669
|
});
|
|
963
1670
|
|
|
964
1671
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
|
|
965
|
-
import { useEffect as
|
|
1672
|
+
import { useEffect as useEffect3, useState as useState6 } from "react";
|
|
966
1673
|
import { Box as Box2 } from "@mui/material";
|
|
967
1674
|
import styled2 from "@emotion/styled";
|
|
968
|
-
import { jsx as
|
|
1675
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
969
1676
|
var baseOverlayStyles = {
|
|
970
1677
|
tank: {
|
|
971
1678
|
background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
|
|
@@ -1027,8 +1734,8 @@ var SVGLockedOverlay = ({
|
|
|
1027
1734
|
onClick,
|
|
1028
1735
|
containerSelector = ".tff-svg-container"
|
|
1029
1736
|
}) => {
|
|
1030
|
-
const [svgOffset, setSvgOffset] =
|
|
1031
|
-
|
|
1737
|
+
const [svgOffset, setSvgOffset] = useState6({ x: 0, y: 0 });
|
|
1738
|
+
useEffect3(() => {
|
|
1032
1739
|
const updateSvgOffset = () => {
|
|
1033
1740
|
const containerElement = document.querySelector(containerSelector);
|
|
1034
1741
|
const svgElement = containerElement?.querySelector("svg");
|
|
@@ -1048,7 +1755,7 @@ var SVGLockedOverlay = ({
|
|
|
1048
1755
|
const pixelX = svgX + svgOffset.x;
|
|
1049
1756
|
const pixelY = svgY + svgOffset.y;
|
|
1050
1757
|
const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
|
|
1051
|
-
return /* @__PURE__ */
|
|
1758
|
+
return /* @__PURE__ */ jsx10(
|
|
1052
1759
|
Box2,
|
|
1053
1760
|
{
|
|
1054
1761
|
className: `svg-locked-overlay ${className}`.trim(),
|
|
@@ -1112,7 +1819,7 @@ var CardUnit = styled2("div")({
|
|
|
1112
1819
|
});
|
|
1113
1820
|
|
|
1114
1821
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
|
|
1115
|
-
import { Fragment, jsx as
|
|
1822
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1116
1823
|
var TrendLine = ({
|
|
1117
1824
|
values,
|
|
1118
1825
|
width = 60,
|
|
@@ -1122,7 +1829,7 @@ var TrendLine = ({
|
|
|
1122
1829
|
backgroundColor = "rgba(255, 255, 255, 0.1)"
|
|
1123
1830
|
}) => {
|
|
1124
1831
|
if (!values || values.length < 2) {
|
|
1125
|
-
return /* @__PURE__ */
|
|
1832
|
+
return /* @__PURE__ */ jsx11(
|
|
1126
1833
|
"div",
|
|
1127
1834
|
{
|
|
1128
1835
|
style: {
|
|
@@ -1134,7 +1841,7 @@ var TrendLine = ({
|
|
|
1134
1841
|
alignItems: "center",
|
|
1135
1842
|
justifyContent: "center"
|
|
1136
1843
|
},
|
|
1137
|
-
children: /* @__PURE__ */
|
|
1844
|
+
children: /* @__PURE__ */ jsx11("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
|
|
1138
1845
|
}
|
|
1139
1846
|
);
|
|
1140
1847
|
}
|
|
@@ -1146,7 +1853,7 @@ var TrendLine = ({
|
|
|
1146
1853
|
const x = 4 + i / (values.length - 1) * (width - 8);
|
|
1147
1854
|
return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
|
|
1148
1855
|
}).join(" ");
|
|
1149
|
-
return /* @__PURE__ */
|
|
1856
|
+
return /* @__PURE__ */ jsx11(
|
|
1150
1857
|
"div",
|
|
1151
1858
|
{
|
|
1152
1859
|
style: {
|
|
@@ -1157,8 +1864,8 @@ var TrendLine = ({
|
|
|
1157
1864
|
position: "relative",
|
|
1158
1865
|
overflow: "hidden"
|
|
1159
1866
|
},
|
|
1160
|
-
children: /* @__PURE__ */
|
|
1161
|
-
/* @__PURE__ */
|
|
1867
|
+
children: /* @__PURE__ */ jsxs8("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
|
|
1868
|
+
/* @__PURE__ */ jsx11(
|
|
1162
1869
|
"path",
|
|
1163
1870
|
{
|
|
1164
1871
|
d: pathData,
|
|
@@ -1169,7 +1876,7 @@ var TrendLine = ({
|
|
|
1169
1876
|
strokeLinejoin: "round"
|
|
1170
1877
|
}
|
|
1171
1878
|
),
|
|
1172
|
-
/* @__PURE__ */
|
|
1879
|
+
/* @__PURE__ */ jsx11(
|
|
1173
1880
|
"circle",
|
|
1174
1881
|
{
|
|
1175
1882
|
cx: 4 + (width - 8),
|
|
@@ -1207,7 +1914,7 @@ var CircularGauge = ({
|
|
|
1207
1914
|
const borderColor = isHex ? hexToRgba(color, 0.9) : color;
|
|
1208
1915
|
const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
|
|
1209
1916
|
const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
|
|
1210
|
-
return /* @__PURE__ */
|
|
1917
|
+
return /* @__PURE__ */ jsxs8(
|
|
1211
1918
|
"div",
|
|
1212
1919
|
{
|
|
1213
1920
|
style: {
|
|
@@ -1216,7 +1923,7 @@ var CircularGauge = ({
|
|
|
1216
1923
|
alignItems: "center"
|
|
1217
1924
|
},
|
|
1218
1925
|
children: [
|
|
1219
|
-
/* @__PURE__ */
|
|
1926
|
+
/* @__PURE__ */ jsxs8(
|
|
1220
1927
|
"div",
|
|
1221
1928
|
{
|
|
1222
1929
|
style: {
|
|
@@ -1228,8 +1935,8 @@ var CircularGauge = ({
|
|
|
1228
1935
|
border: `1px solid ${borderStrokeColor}`
|
|
1229
1936
|
},
|
|
1230
1937
|
children: [
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1938
|
+
/* @__PURE__ */ jsxs8("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
|
|
1939
|
+
/* @__PURE__ */ jsx11(
|
|
1233
1940
|
"circle",
|
|
1234
1941
|
{
|
|
1235
1942
|
cx: size / 2,
|
|
@@ -1240,7 +1947,7 @@ var CircularGauge = ({
|
|
|
1240
1947
|
strokeWidth: 1
|
|
1241
1948
|
}
|
|
1242
1949
|
),
|
|
1243
|
-
/* @__PURE__ */
|
|
1950
|
+
/* @__PURE__ */ jsx11(
|
|
1244
1951
|
"circle",
|
|
1245
1952
|
{
|
|
1246
1953
|
cx: size / 2,
|
|
@@ -1251,7 +1958,7 @@ var CircularGauge = ({
|
|
|
1251
1958
|
fill: "transparent"
|
|
1252
1959
|
}
|
|
1253
1960
|
),
|
|
1254
|
-
/* @__PURE__ */
|
|
1961
|
+
/* @__PURE__ */ jsx11(
|
|
1255
1962
|
"circle",
|
|
1256
1963
|
{
|
|
1257
1964
|
cx: size / 2,
|
|
@@ -1267,7 +1974,7 @@ var CircularGauge = ({
|
|
|
1267
1974
|
}
|
|
1268
1975
|
)
|
|
1269
1976
|
] }),
|
|
1270
|
-
/* @__PURE__ */
|
|
1977
|
+
/* @__PURE__ */ jsxs8(
|
|
1271
1978
|
"div",
|
|
1272
1979
|
{
|
|
1273
1980
|
style: {
|
|
@@ -1283,14 +1990,14 @@ var CircularGauge = ({
|
|
|
1283
1990
|
},
|
|
1284
1991
|
children: [
|
|
1285
1992
|
value.toFixed(1),
|
|
1286
|
-
/* @__PURE__ */
|
|
1993
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
|
|
1287
1994
|
]
|
|
1288
1995
|
}
|
|
1289
1996
|
)
|
|
1290
1997
|
]
|
|
1291
1998
|
}
|
|
1292
1999
|
),
|
|
1293
|
-
/* @__PURE__ */
|
|
2000
|
+
/* @__PURE__ */ jsx11(
|
|
1294
2001
|
"div",
|
|
1295
2002
|
{
|
|
1296
2003
|
style: {
|
|
@@ -1321,7 +2028,7 @@ var Sparkline = ({ data, width, height, color }) => {
|
|
|
1321
2028
|
const y = height - 8 - (value - min) / range * (height - 8);
|
|
1322
2029
|
return `${x + 4},${y + 4}`;
|
|
1323
2030
|
}).join(" ");
|
|
1324
|
-
return /* @__PURE__ */
|
|
2031
|
+
return /* @__PURE__ */ jsx11(
|
|
1325
2032
|
"div",
|
|
1326
2033
|
{
|
|
1327
2034
|
style: {
|
|
@@ -1335,7 +2042,7 @@ var Sparkline = ({ data, width, height, color }) => {
|
|
|
1335
2042
|
justifyContent: "center",
|
|
1336
2043
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
1337
2044
|
},
|
|
1338
|
-
children: /* @__PURE__ */
|
|
2045
|
+
children: /* @__PURE__ */ jsx11("svg", { width, height, children: /* @__PURE__ */ jsx11("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
|
|
1339
2046
|
}
|
|
1340
2047
|
);
|
|
1341
2048
|
};
|
|
@@ -1349,8 +2056,8 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
1349
2056
|
sparklineOffset = { x: 40, y: 0 }
|
|
1350
2057
|
}) => {
|
|
1351
2058
|
const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
|
|
1352
|
-
return /* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
2059
|
+
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
2060
|
+
/* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ jsx11(
|
|
1354
2061
|
"div",
|
|
1355
2062
|
{
|
|
1356
2063
|
style: {
|
|
@@ -1371,7 +2078,7 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
1371
2078
|
children: label
|
|
1372
2079
|
}
|
|
1373
2080
|
) }),
|
|
1374
|
-
hasSparkline && /* @__PURE__ */
|
|
2081
|
+
hasSparkline && /* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ jsx11(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
|
|
1375
2082
|
] });
|
|
1376
2083
|
};
|
|
1377
2084
|
var EquipmentIndicator = ({
|
|
@@ -1384,7 +2091,7 @@ var EquipmentIndicator = ({
|
|
|
1384
2091
|
className
|
|
1385
2092
|
}) => {
|
|
1386
2093
|
const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
|
|
1387
|
-
return /* @__PURE__ */
|
|
2094
|
+
return /* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ jsx11(
|
|
1388
2095
|
"div",
|
|
1389
2096
|
{
|
|
1390
2097
|
style: {
|
|
@@ -1408,7 +2115,7 @@ var EquipmentIndicator = ({
|
|
|
1408
2115
|
};
|
|
1409
2116
|
|
|
1410
2117
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
1411
|
-
import { Fragment as
|
|
2118
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1412
2119
|
function FullscreenWorkspace({
|
|
1413
2120
|
svgContent,
|
|
1414
2121
|
overlays,
|
|
@@ -1436,10 +2143,10 @@ function FullscreenWorkspace({
|
|
|
1436
2143
|
className = "",
|
|
1437
2144
|
...rest
|
|
1438
2145
|
}) {
|
|
1439
|
-
const [leftCollapsedState, setLeftCollapsedState] =
|
|
1440
|
-
const [rightCollapsedState, setRightCollapsedState] =
|
|
1441
|
-
const [internalDisplayMode, setInternalDisplayMode] =
|
|
1442
|
-
const [internalTab, setInternalTab] =
|
|
2146
|
+
const [leftCollapsedState, setLeftCollapsedState] = React6.useState(defaultLeftCollapsed);
|
|
2147
|
+
const [rightCollapsedState, setRightCollapsedState] = React6.useState(defaultRightCollapsed);
|
|
2148
|
+
const [internalDisplayMode, setInternalDisplayMode] = React6.useState(displayMode ?? defaultDisplayMode);
|
|
2149
|
+
const [internalTab, setInternalTab] = React6.useState(
|
|
1443
2150
|
tabs && tabs.length > 0 ? tabs[0].value : ""
|
|
1444
2151
|
);
|
|
1445
2152
|
const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
|
|
@@ -1447,10 +2154,10 @@ function FullscreenWorkspace({
|
|
|
1447
2154
|
const isDisplayModeControlled = displayMode !== void 0;
|
|
1448
2155
|
const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
|
|
1449
2156
|
const isTabControlled = activeTab !== void 0 && activeTab !== null;
|
|
1450
|
-
const resolvedTabs =
|
|
2157
|
+
const resolvedTabs = React6.useMemo(() => tabs ?? [], [tabs]);
|
|
1451
2158
|
const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
|
|
1452
2159
|
const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
|
|
1453
|
-
|
|
2160
|
+
React6.useEffect(() => {
|
|
1454
2161
|
if (resolvedTabs.length > 0) {
|
|
1455
2162
|
const values = resolvedTabs.map((tab) => tab.value);
|
|
1456
2163
|
if (!values.includes(currentTab)) {
|
|
@@ -1459,7 +2166,7 @@ function FullscreenWorkspace({
|
|
|
1459
2166
|
}
|
|
1460
2167
|
}
|
|
1461
2168
|
}, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
|
|
1462
|
-
|
|
2169
|
+
React6.useEffect(() => {
|
|
1463
2170
|
if (displayMode !== void 0) {
|
|
1464
2171
|
setInternalDisplayMode(displayMode);
|
|
1465
2172
|
}
|
|
@@ -1494,7 +2201,7 @@ function FullscreenWorkspace({
|
|
|
1494
2201
|
const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
|
|
1495
2202
|
const showLeftToggle = Boolean(leftPanel);
|
|
1496
2203
|
const showRightToggle = Boolean(rightPanel);
|
|
1497
|
-
return /* @__PURE__ */
|
|
2204
|
+
return /* @__PURE__ */ jsxs9(
|
|
1498
2205
|
FullscreenContainer,
|
|
1499
2206
|
{
|
|
1500
2207
|
leftCollapsed,
|
|
@@ -1502,25 +2209,25 @@ function FullscreenWorkspace({
|
|
|
1502
2209
|
className: `tff-svg-container ${className}`.trim(),
|
|
1503
2210
|
...rest,
|
|
1504
2211
|
children: [
|
|
1505
|
-
showLeftToggle && /* @__PURE__ */
|
|
2212
|
+
showLeftToggle && /* @__PURE__ */ jsx12(
|
|
1506
2213
|
LeftToggleButton,
|
|
1507
2214
|
{
|
|
1508
2215
|
collapsed: leftCollapsed,
|
|
1509
2216
|
onClick: handleLeftToggle,
|
|
1510
2217
|
"aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
|
|
1511
|
-
children: leftCollapsed ? /* @__PURE__ */
|
|
2218
|
+
children: leftCollapsed ? /* @__PURE__ */ jsx12(ChevronRight, {}) : /* @__PURE__ */ jsx12(ChevronLeft, {})
|
|
1512
2219
|
}
|
|
1513
2220
|
),
|
|
1514
|
-
showRightToggle && /* @__PURE__ */
|
|
2221
|
+
showRightToggle && /* @__PURE__ */ jsx12(
|
|
1515
2222
|
RightToggleButton,
|
|
1516
2223
|
{
|
|
1517
2224
|
collapsed: rightCollapsed,
|
|
1518
2225
|
onClick: handleRightToggle,
|
|
1519
2226
|
"aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
|
|
1520
|
-
children: rightCollapsed ? /* @__PURE__ */
|
|
2227
|
+
children: rightCollapsed ? /* @__PURE__ */ jsx12(ChevronLeft, {}) : /* @__PURE__ */ jsx12(ChevronRight, {})
|
|
1521
2228
|
}
|
|
1522
2229
|
),
|
|
1523
|
-
showDisplayModeToggle && /* @__PURE__ */
|
|
2230
|
+
showDisplayModeToggle && /* @__PURE__ */ jsx12(
|
|
1524
2231
|
DisplayModeToggle,
|
|
1525
2232
|
{
|
|
1526
2233
|
mode: currentDisplayMode,
|
|
@@ -1529,9 +2236,9 @@ function FullscreenWorkspace({
|
|
|
1529
2236
|
children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
|
|
1530
2237
|
}
|
|
1531
2238
|
),
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
showZoomControls && /* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
2239
|
+
/* @__PURE__ */ jsxs9(SVGArea, { children: [
|
|
2240
|
+
showZoomControls && /* @__PURE__ */ jsxs9(ZoomControls, { children: [
|
|
2241
|
+
/* @__PURE__ */ jsx12(
|
|
1535
2242
|
ZoomButton,
|
|
1536
2243
|
{
|
|
1537
2244
|
onClick: onZoomIn,
|
|
@@ -1541,7 +2248,7 @@ function FullscreenWorkspace({
|
|
|
1541
2248
|
children: "+"
|
|
1542
2249
|
}
|
|
1543
2250
|
),
|
|
1544
|
-
/* @__PURE__ */
|
|
2251
|
+
/* @__PURE__ */ jsx12(
|
|
1545
2252
|
ZoomButton,
|
|
1546
2253
|
{
|
|
1547
2254
|
onClick: onZoomOut,
|
|
@@ -1551,7 +2258,7 @@ function FullscreenWorkspace({
|
|
|
1551
2258
|
children: "-"
|
|
1552
2259
|
}
|
|
1553
2260
|
),
|
|
1554
|
-
onResetZoom && /* @__PURE__ */
|
|
2261
|
+
onResetZoom && /* @__PURE__ */ jsx12(
|
|
1555
2262
|
ZoomButton,
|
|
1556
2263
|
{
|
|
1557
2264
|
onClick: onResetZoom,
|
|
@@ -1562,33 +2269,33 @@ function FullscreenWorkspace({
|
|
|
1562
2269
|
}
|
|
1563
2270
|
)
|
|
1564
2271
|
] }),
|
|
1565
|
-
/* @__PURE__ */
|
|
2272
|
+
/* @__PURE__ */ jsx12(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ jsxs9(FixedSVGContainer, { className: "svg-container", children: [
|
|
1566
2273
|
svgContent,
|
|
1567
2274
|
overlays
|
|
1568
2275
|
] }) })
|
|
1569
2276
|
] }),
|
|
1570
|
-
/* @__PURE__ */
|
|
1571
|
-
/* @__PURE__ */
|
|
2277
|
+
/* @__PURE__ */ jsx12(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
2278
|
+
/* @__PURE__ */ jsx12(
|
|
1572
2279
|
PanelTabs,
|
|
1573
2280
|
{
|
|
1574
2281
|
value: currentTab,
|
|
1575
2282
|
onChange: handleTabChangeInternal,
|
|
1576
2283
|
"aria-label": "Left panel tabs",
|
|
1577
|
-
children: resolvedTabs.map((tab) => /* @__PURE__ */
|
|
2284
|
+
children: resolvedTabs.map((tab) => /* @__PURE__ */ jsx12(Tab, { label: tab.label, value: tab.value }, tab.value))
|
|
1578
2285
|
}
|
|
1579
2286
|
),
|
|
1580
|
-
/* @__PURE__ */
|
|
2287
|
+
/* @__PURE__ */ jsx12(PanelContent, { children: currentTabContent })
|
|
1581
2288
|
] }) : leftPanel }),
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
2289
|
+
/* @__PURE__ */ jsx12(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
|
|
2290
|
+
/* @__PURE__ */ jsx12(FooterPanel, { children: footer })
|
|
1584
2291
|
]
|
|
1585
2292
|
}
|
|
1586
2293
|
);
|
|
1587
2294
|
}
|
|
1588
2295
|
|
|
1589
2296
|
// src/theme/ThemeContext.tsx
|
|
1590
|
-
import { createContext, useContext, useState as
|
|
1591
|
-
import { jsx as
|
|
2297
|
+
import { createContext, useContext, useState as useState7, useEffect as useEffect4 } from "react";
|
|
2298
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1592
2299
|
var ThemeContext = createContext(void 0);
|
|
1593
2300
|
var useTheme = () => {
|
|
1594
2301
|
const context = useContext(ThemeContext);
|
|
@@ -1598,8 +2305,8 @@ var useTheme = () => {
|
|
|
1598
2305
|
return context;
|
|
1599
2306
|
};
|
|
1600
2307
|
var ThemeProvider = ({ children }) => {
|
|
1601
|
-
const [theme, setThemeState] =
|
|
1602
|
-
|
|
2308
|
+
const [theme, setThemeState] = useState7("modern");
|
|
2309
|
+
useEffect4(() => {
|
|
1603
2310
|
document.body.className = "";
|
|
1604
2311
|
document.body.classList.add(`theme-${theme}`);
|
|
1605
2312
|
document.documentElement.className = "";
|
|
@@ -1611,11 +2318,11 @@ var ThemeProvider = ({ children }) => {
|
|
|
1611
2318
|
const setTheme = (newTheme) => {
|
|
1612
2319
|
setThemeState(newTheme);
|
|
1613
2320
|
};
|
|
1614
|
-
return /* @__PURE__ */
|
|
2321
|
+
return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
|
|
1615
2322
|
};
|
|
1616
2323
|
|
|
1617
2324
|
// src/theme/ThemeToggle.tsx
|
|
1618
|
-
import { jsx as
|
|
2325
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1619
2326
|
var ThemeToggle = ({
|
|
1620
2327
|
size = "medium",
|
|
1621
2328
|
position = "top-right",
|
|
@@ -1686,15 +2393,15 @@ var ThemeToggle = ({
|
|
|
1686
2393
|
transition: "all 0.2s ease",
|
|
1687
2394
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
|
|
1688
2395
|
};
|
|
1689
|
-
return /* @__PURE__ */
|
|
1690
|
-
/* @__PURE__ */
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
2396
|
+
return /* @__PURE__ */ jsxs10("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
|
|
2397
|
+
/* @__PURE__ */ jsx14("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
|
|
2398
|
+
/* @__PURE__ */ jsx14("div", { style: toggleStyle, children: /* @__PURE__ */ jsx14("div", { style: thumbStyle }) }),
|
|
2399
|
+
/* @__PURE__ */ jsx14("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
|
|
1693
2400
|
] });
|
|
1694
2401
|
};
|
|
1695
2402
|
|
|
1696
2403
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
1697
|
-
import { useCallback as useCallback7, useState as
|
|
2404
|
+
import { useCallback as useCallback7, useState as useState13, useEffect as useEffect11, useRef as useRef5 } from "react";
|
|
1698
2405
|
|
|
1699
2406
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
1700
2407
|
var mockSymbolLibrary = {
|
|
@@ -2915,7 +3622,7 @@ function getAvailableSymbols() {
|
|
|
2915
3622
|
}
|
|
2916
3623
|
|
|
2917
3624
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
2918
|
-
import { jsx as
|
|
3625
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2919
3626
|
function NodeRenderer({
|
|
2920
3627
|
nodes: nodes2,
|
|
2921
3628
|
selectedNodeIds,
|
|
@@ -2926,13 +3633,13 @@ function NodeRenderer({
|
|
|
2926
3633
|
dragOffset = { x: 0, y: 0 },
|
|
2927
3634
|
enableDrag = false
|
|
2928
3635
|
}) {
|
|
2929
|
-
return /* @__PURE__ */
|
|
3636
|
+
return /* @__PURE__ */ jsx15("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
|
|
2930
3637
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
2931
3638
|
const isSelected = selectedNodeIds?.has(node.id) ?? false;
|
|
2932
3639
|
const isDragging = draggingNodeId === node.id;
|
|
2933
3640
|
if (!symbol) {
|
|
2934
|
-
return /* @__PURE__ */
|
|
2935
|
-
/* @__PURE__ */
|
|
3641
|
+
return /* @__PURE__ */ jsxs11("g", { children: [
|
|
3642
|
+
/* @__PURE__ */ jsx15(
|
|
2936
3643
|
"circle",
|
|
2937
3644
|
{
|
|
2938
3645
|
cx: node.transform.x,
|
|
@@ -2944,7 +3651,7 @@ function NodeRenderer({
|
|
|
2944
3651
|
strokeWidth: "2"
|
|
2945
3652
|
}
|
|
2946
3653
|
),
|
|
2947
|
-
/* @__PURE__ */
|
|
3654
|
+
/* @__PURE__ */ jsx15(
|
|
2948
3655
|
"text",
|
|
2949
3656
|
{
|
|
2950
3657
|
x: node.transform.x,
|
|
@@ -3001,7 +3708,7 @@ function NodeRenderer({
|
|
|
3001
3708
|
};
|
|
3002
3709
|
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
3003
3710
|
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
3004
|
-
return /* @__PURE__ */
|
|
3711
|
+
return /* @__PURE__ */ jsxs11(
|
|
3005
3712
|
"g",
|
|
3006
3713
|
{
|
|
3007
3714
|
"data-node-id": node.id,
|
|
@@ -3034,7 +3741,7 @@ function NodeRenderer({
|
|
|
3034
3741
|
}
|
|
3035
3742
|
},
|
|
3036
3743
|
children: [
|
|
3037
|
-
isSelected && /* @__PURE__ */
|
|
3744
|
+
isSelected && /* @__PURE__ */ jsx15(
|
|
3038
3745
|
"rect",
|
|
3039
3746
|
{
|
|
3040
3747
|
x: "-5",
|
|
@@ -3049,7 +3756,7 @@ function NodeRenderer({
|
|
|
3049
3756
|
pointerEvents: "none"
|
|
3050
3757
|
}
|
|
3051
3758
|
),
|
|
3052
|
-
/* @__PURE__ */
|
|
3759
|
+
/* @__PURE__ */ jsx15(
|
|
3053
3760
|
"g",
|
|
3054
3761
|
{
|
|
3055
3762
|
dangerouslySetInnerHTML: { __html: symbol.svgContent },
|
|
@@ -3057,7 +3764,7 @@ function NodeRenderer({
|
|
|
3057
3764
|
style: { pointerEvents: "auto" }
|
|
3058
3765
|
}
|
|
3059
3766
|
),
|
|
3060
|
-
/* @__PURE__ */
|
|
3767
|
+
/* @__PURE__ */ jsx15(
|
|
3061
3768
|
"text",
|
|
3062
3769
|
{
|
|
3063
3770
|
x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
|
|
@@ -3078,7 +3785,7 @@ function NodeRenderer({
|
|
|
3078
3785
|
}
|
|
3079
3786
|
|
|
3080
3787
|
// src/components/PIDCanvas/PipeRenderer.tsx
|
|
3081
|
-
import { Fragment as
|
|
3788
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3082
3789
|
function PipeRenderer({
|
|
3083
3790
|
pipes,
|
|
3084
3791
|
selectedPipeIds,
|
|
@@ -3093,7 +3800,7 @@ function PipeRenderer({
|
|
|
3093
3800
|
waypointDragOffset,
|
|
3094
3801
|
onPipeSegmentClick
|
|
3095
3802
|
}) {
|
|
3096
|
-
return /* @__PURE__ */
|
|
3803
|
+
return /* @__PURE__ */ jsx16("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
|
|
3097
3804
|
const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
|
|
3098
3805
|
const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
|
|
3099
3806
|
const showEditingControls = enableWaypointEditing && isSelected;
|
|
@@ -3112,7 +3819,7 @@ function PipeRenderer({
|
|
|
3112
3819
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
3113
3820
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
3114
3821
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
3115
|
-
return /* @__PURE__ */
|
|
3822
|
+
return /* @__PURE__ */ jsxs12(
|
|
3116
3823
|
"g",
|
|
3117
3824
|
{
|
|
3118
3825
|
"data-pipe-id": pipe.id,
|
|
@@ -3125,8 +3832,8 @@ function PipeRenderer({
|
|
|
3125
3832
|
cursor: onPipeClick ? "pointer" : "default"
|
|
3126
3833
|
},
|
|
3127
3834
|
children: [
|
|
3128
|
-
!enableWaypointEditing && /* @__PURE__ */
|
|
3129
|
-
onPipeClick && /* @__PURE__ */
|
|
3835
|
+
!enableWaypointEditing && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3836
|
+
onPipeClick && /* @__PURE__ */ jsx16(
|
|
3130
3837
|
"polyline",
|
|
3131
3838
|
{
|
|
3132
3839
|
points: pointsString,
|
|
@@ -3138,7 +3845,7 @@ function PipeRenderer({
|
|
|
3138
3845
|
pointerEvents: "stroke"
|
|
3139
3846
|
}
|
|
3140
3847
|
),
|
|
3141
|
-
/* @__PURE__ */
|
|
3848
|
+
/* @__PURE__ */ jsx16(
|
|
3142
3849
|
"polyline",
|
|
3143
3850
|
{
|
|
3144
3851
|
points: pointsString,
|
|
@@ -3162,7 +3869,7 @@ function PipeRenderer({
|
|
|
3162
3869
|
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3163
3870
|
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3164
3871
|
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
3165
|
-
return /* @__PURE__ */
|
|
3872
|
+
return /* @__PURE__ */ jsx16(
|
|
3166
3873
|
"circle",
|
|
3167
3874
|
{
|
|
3168
3875
|
cx: point.x,
|
|
@@ -3199,12 +3906,12 @@ function PipeRenderer({
|
|
|
3199
3906
|
`${pipe.id}-point-${idx}`
|
|
3200
3907
|
);
|
|
3201
3908
|
}),
|
|
3202
|
-
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */
|
|
3909
|
+
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ jsx16(Fragment5, { children: displayPoints.slice(0, -1).map((point, idx) => {
|
|
3203
3910
|
const nextPoint = displayPoints[idx + 1];
|
|
3204
3911
|
const midX = (point.x + nextPoint.x) / 2;
|
|
3205
3912
|
const midY = (point.y + nextPoint.y) / 2;
|
|
3206
|
-
return /* @__PURE__ */
|
|
3207
|
-
/* @__PURE__ */
|
|
3913
|
+
return /* @__PURE__ */ jsxs12("g", { children: [
|
|
3914
|
+
/* @__PURE__ */ jsx16(
|
|
3208
3915
|
"circle",
|
|
3209
3916
|
{
|
|
3210
3917
|
cx: midX,
|
|
@@ -3220,7 +3927,7 @@ function PipeRenderer({
|
|
|
3220
3927
|
}
|
|
3221
3928
|
}
|
|
3222
3929
|
),
|
|
3223
|
-
/* @__PURE__ */
|
|
3930
|
+
/* @__PURE__ */ jsx16(
|
|
3224
3931
|
"circle",
|
|
3225
3932
|
{
|
|
3226
3933
|
cx: midX,
|
|
@@ -3236,7 +3943,7 @@ function PipeRenderer({
|
|
|
3236
3943
|
)
|
|
3237
3944
|
] }, `${pipe.id}-segment-${idx}`);
|
|
3238
3945
|
}) }),
|
|
3239
|
-
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */
|
|
3946
|
+
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ jsx16(
|
|
3240
3947
|
"text",
|
|
3241
3948
|
{
|
|
3242
3949
|
x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
|
|
@@ -3258,7 +3965,7 @@ function PipeRenderer({
|
|
|
3258
3965
|
}
|
|
3259
3966
|
|
|
3260
3967
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
3261
|
-
import { Fragment as
|
|
3968
|
+
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3262
3969
|
function DataOverlay({
|
|
3263
3970
|
nodeId,
|
|
3264
3971
|
x,
|
|
@@ -3278,7 +3985,7 @@ function DataOverlay({
|
|
|
3278
3985
|
const offsetX = display?.offsetX ?? 0;
|
|
3279
3986
|
const offsetY = display?.offsetY ?? 0;
|
|
3280
3987
|
if (!showValue) {
|
|
3281
|
-
return /* @__PURE__ */
|
|
3988
|
+
return /* @__PURE__ */ jsx17(Fragment6, {});
|
|
3282
3989
|
}
|
|
3283
3990
|
const formatValue = (val) => {
|
|
3284
3991
|
if (typeof val === "number") {
|
|
@@ -3296,9 +4003,14 @@ function DataOverlay({
|
|
|
3296
4003
|
fault: { bg: "#dc2626", text: "#ffffff", border: "#b91c1c" },
|
|
3297
4004
|
off: { bg: "#6b7280", text: "#ffffff", border: "#4b5563" }
|
|
3298
4005
|
};
|
|
3299
|
-
const
|
|
3300
|
-
|
|
3301
|
-
|
|
4006
|
+
const getStatusColors = () => {
|
|
4007
|
+
const customColor = telemetry.statusColors?.[value.status];
|
|
4008
|
+
if (customColor) {
|
|
4009
|
+
return { bg: customColor, text: "#ffffff", border: customColor };
|
|
4010
|
+
}
|
|
4011
|
+
return defaultStatusColors[value.status] || defaultStatusColors.normal;
|
|
4012
|
+
};
|
|
4013
|
+
const statusColors = getStatusColors();
|
|
3302
4014
|
const colors = backgroundColor && backgroundColor !== "status" ? { bg: backgroundColor, text: textColor || "#ffffff", border: backgroundColor } : statusColors;
|
|
3303
4015
|
const finalTextColor = textColor || colors.text;
|
|
3304
4016
|
const formattedValue = formatValue(value.value);
|
|
@@ -3325,8 +4037,8 @@ function DataOverlay({
|
|
|
3325
4037
|
const overlayWidth = 80 * scale;
|
|
3326
4038
|
const displayX = x + offsetX;
|
|
3327
4039
|
const displayY = y + offsetY;
|
|
3328
|
-
return /* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
4040
|
+
return /* @__PURE__ */ jsxs13("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
4041
|
+
/* @__PURE__ */ jsx17(
|
|
3330
4042
|
"rect",
|
|
3331
4043
|
{
|
|
3332
4044
|
x: displayX - overlayWidth / 2,
|
|
@@ -3341,7 +4053,7 @@ function DataOverlay({
|
|
|
3341
4053
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
3342
4054
|
}
|
|
3343
4055
|
),
|
|
3344
|
-
label && /* @__PURE__ */
|
|
4056
|
+
label && /* @__PURE__ */ jsx17(
|
|
3345
4057
|
"text",
|
|
3346
4058
|
{
|
|
3347
4059
|
x: displayX,
|
|
@@ -3354,7 +4066,7 @@ function DataOverlay({
|
|
|
3354
4066
|
children: label
|
|
3355
4067
|
}
|
|
3356
4068
|
),
|
|
3357
|
-
/* @__PURE__ */
|
|
4069
|
+
/* @__PURE__ */ jsx17(
|
|
3358
4070
|
"text",
|
|
3359
4071
|
{
|
|
3360
4072
|
x: displayX,
|
|
@@ -3367,7 +4079,7 @@ function DataOverlay({
|
|
|
3367
4079
|
children: displayText
|
|
3368
4080
|
}
|
|
3369
4081
|
),
|
|
3370
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */
|
|
4082
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ jsx17(
|
|
3371
4083
|
"circle",
|
|
3372
4084
|
{
|
|
3373
4085
|
cx: displayX + 35 * scale,
|
|
@@ -3375,7 +4087,7 @@ function DataOverlay({
|
|
|
3375
4087
|
r: 3 * scale,
|
|
3376
4088
|
fill: finalTextColor,
|
|
3377
4089
|
opacity: "0.9",
|
|
3378
|
-
children: /* @__PURE__ */
|
|
4090
|
+
children: /* @__PURE__ */ jsx17(
|
|
3379
4091
|
"animate",
|
|
3380
4092
|
{
|
|
3381
4093
|
attributeName: "opacity",
|
|
@@ -3386,7 +4098,7 @@ function DataOverlay({
|
|
|
3386
4098
|
)
|
|
3387
4099
|
}
|
|
3388
4100
|
),
|
|
3389
|
-
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */
|
|
4101
|
+
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs13(
|
|
3390
4102
|
"text",
|
|
3391
4103
|
{
|
|
3392
4104
|
x: displayX,
|
|
@@ -3403,7 +4115,7 @@ function DataOverlay({
|
|
|
3403
4115
|
]
|
|
3404
4116
|
}
|
|
3405
4117
|
),
|
|
3406
|
-
hasSparkline && /* @__PURE__ */
|
|
4118
|
+
hasSparkline && /* @__PURE__ */ jsx17("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ jsx17(
|
|
3407
4119
|
"path",
|
|
3408
4120
|
{
|
|
3409
4121
|
d: sparklinePath,
|
|
@@ -3419,8 +4131,8 @@ function DataOverlay({
|
|
|
3419
4131
|
}
|
|
3420
4132
|
|
|
3421
4133
|
// src/components/PIDCanvas/PositionPanel.tsx
|
|
3422
|
-
import { useState as
|
|
3423
|
-
import { jsx as
|
|
4134
|
+
import { useState as useState8, useEffect as useEffect5 } from "react";
|
|
4135
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3424
4136
|
function PositionPanel({
|
|
3425
4137
|
selectedNode,
|
|
3426
4138
|
selectedWaypoint,
|
|
@@ -3428,9 +4140,9 @@ function PositionPanel({
|
|
|
3428
4140
|
onWaypointPositionChange,
|
|
3429
4141
|
position = "top-right"
|
|
3430
4142
|
}) {
|
|
3431
|
-
const [x, setX] =
|
|
3432
|
-
const [y, setY] =
|
|
3433
|
-
|
|
4143
|
+
const [x, setX] = useState8("");
|
|
4144
|
+
const [y, setY] = useState8("");
|
|
4145
|
+
useEffect5(() => {
|
|
3434
4146
|
if (selectedNode) {
|
|
3435
4147
|
setX(selectedNode.transform.x.toFixed(2));
|
|
3436
4148
|
setY(selectedNode.transform.y.toFixed(2));
|
|
@@ -3489,7 +4201,7 @@ function PositionPanel({
|
|
|
3489
4201
|
"bottom-left": { bottom: 10, left: 10 },
|
|
3490
4202
|
"bottom-right": { bottom: 10, right: 10 }
|
|
3491
4203
|
};
|
|
3492
|
-
return /* @__PURE__ */
|
|
4204
|
+
return /* @__PURE__ */ jsxs14(
|
|
3493
4205
|
"div",
|
|
3494
4206
|
{
|
|
3495
4207
|
style: {
|
|
@@ -3506,11 +4218,11 @@ function PositionPanel({
|
|
|
3506
4218
|
fontSize: "13px"
|
|
3507
4219
|
},
|
|
3508
4220
|
children: [
|
|
3509
|
-
/* @__PURE__ */
|
|
3510
|
-
/* @__PURE__ */
|
|
3511
|
-
/* @__PURE__ */
|
|
3512
|
-
/* @__PURE__ */
|
|
3513
|
-
/* @__PURE__ */
|
|
4221
|
+
/* @__PURE__ */ jsx18("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
4222
|
+
/* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
4223
|
+
/* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
4224
|
+
/* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
4225
|
+
/* @__PURE__ */ jsx18(
|
|
3514
4226
|
"input",
|
|
3515
4227
|
{
|
|
3516
4228
|
type: "number",
|
|
@@ -3528,9 +4240,9 @@ function PositionPanel({
|
|
|
3528
4240
|
}
|
|
3529
4241
|
)
|
|
3530
4242
|
] }),
|
|
3531
|
-
/* @__PURE__ */
|
|
3532
|
-
/* @__PURE__ */
|
|
3533
|
-
/* @__PURE__ */
|
|
4243
|
+
/* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
4244
|
+
/* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
4245
|
+
/* @__PURE__ */ jsx18(
|
|
3534
4246
|
"input",
|
|
3535
4247
|
{
|
|
3536
4248
|
type: "number",
|
|
@@ -3549,14 +4261,14 @@ function PositionPanel({
|
|
|
3549
4261
|
)
|
|
3550
4262
|
] })
|
|
3551
4263
|
] }),
|
|
3552
|
-
/* @__PURE__ */
|
|
4264
|
+
/* @__PURE__ */ jsx18("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3553
4265
|
]
|
|
3554
4266
|
}
|
|
3555
4267
|
);
|
|
3556
4268
|
}
|
|
3557
4269
|
|
|
3558
4270
|
// src/diagram/hooks/useViewBox.ts
|
|
3559
|
-
import { useState as
|
|
4271
|
+
import { useState as useState9, useCallback as useCallback3, useRef as useRef2, useEffect as useEffect6 } from "react";
|
|
3560
4272
|
function useViewBox(options) {
|
|
3561
4273
|
const {
|
|
3562
4274
|
initialViewBox,
|
|
@@ -3567,7 +4279,7 @@ function useViewBox(options) {
|
|
|
3567
4279
|
zoomSensitivity = 1e-3,
|
|
3568
4280
|
allowLeftClickPan = true
|
|
3569
4281
|
} = options;
|
|
3570
|
-
const [viewBox, setViewBox] =
|
|
4282
|
+
const [viewBox, setViewBox] = useState9(initialViewBox);
|
|
3571
4283
|
const svgRef = useRef2(null);
|
|
3572
4284
|
const isPanningRef = useRef2(false);
|
|
3573
4285
|
const lastMousePosRef = useRef2({ x: 0, y: 0 });
|
|
@@ -3638,7 +4350,7 @@ function useViewBox(options) {
|
|
|
3638
4350
|
height: newHeight
|
|
3639
4351
|
});
|
|
3640
4352
|
}, [initialViewBox]);
|
|
3641
|
-
|
|
4353
|
+
useEffect6(() => {
|
|
3642
4354
|
if (!enableZoom || !svgRef.current) return;
|
|
3643
4355
|
const svg = svgRef.current;
|
|
3644
4356
|
const handleWheel = (e) => {
|
|
@@ -3671,7 +4383,7 @@ function useViewBox(options) {
|
|
|
3671
4383
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
3672
4384
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
3673
4385
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
3674
|
-
|
|
4386
|
+
useEffect6(() => {
|
|
3675
4387
|
if (!enablePan || !svgRef.current) return;
|
|
3676
4388
|
const svg = svgRef.current;
|
|
3677
4389
|
const handleMouseDown = (e) => {
|
|
@@ -3747,7 +4459,7 @@ function useViewBox(options) {
|
|
|
3747
4459
|
window.removeEventListener("keyup", handleKeyUp);
|
|
3748
4460
|
};
|
|
3749
4461
|
}, [enablePan, allowLeftClickPan]);
|
|
3750
|
-
|
|
4462
|
+
useEffect6(() => {
|
|
3751
4463
|
if (!svgRef.current) return;
|
|
3752
4464
|
if (!enablePan && !enableZoom) return;
|
|
3753
4465
|
const svg = svgRef.current;
|
|
@@ -3877,14 +4589,14 @@ function useViewBox(options) {
|
|
|
3877
4589
|
}
|
|
3878
4590
|
|
|
3879
4591
|
// src/diagram/hooks/useSelection.ts
|
|
3880
|
-
import { useState as
|
|
4592
|
+
import { useState as useState10, useCallback as useCallback4 } from "react";
|
|
3881
4593
|
function useSelection(options = {}) {
|
|
3882
4594
|
const {
|
|
3883
4595
|
multiSelect = true,
|
|
3884
4596
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
3885
4597
|
onSelectionChange
|
|
3886
4598
|
} = options;
|
|
3887
|
-
const [selection, setSelection] =
|
|
4599
|
+
const [selection, setSelection] = useState10(initialSelection);
|
|
3888
4600
|
const notifyChange = useCallback4(
|
|
3889
4601
|
(newSelection) => {
|
|
3890
4602
|
if (onSelectionChange) {
|
|
@@ -3982,14 +4694,14 @@ function useSelection(options = {}) {
|
|
|
3982
4694
|
}
|
|
3983
4695
|
|
|
3984
4696
|
// src/diagram/hooks/useTelemetry.ts
|
|
3985
|
-
import { useState as
|
|
4697
|
+
import { useState as useState11, useCallback as useCallback5, useEffect as useEffect7, useRef as useRef3 } from "react";
|
|
3986
4698
|
function useTelemetry(options = {}) {
|
|
3987
4699
|
const {
|
|
3988
4700
|
initialBindings = [],
|
|
3989
4701
|
onTelemetryChange,
|
|
3990
4702
|
refreshInterval = 0
|
|
3991
4703
|
} = options;
|
|
3992
|
-
const [telemetry, setTelemetry] =
|
|
4704
|
+
const [telemetry, setTelemetry] = useState11(() => {
|
|
3993
4705
|
const map = /* @__PURE__ */ new Map();
|
|
3994
4706
|
initialBindings.forEach((binding) => {
|
|
3995
4707
|
map.set(binding.nodeId, binding);
|
|
@@ -4110,7 +4822,7 @@ function useTelemetry(options = {}) {
|
|
|
4110
4822
|
},
|
|
4111
4823
|
[notifyChange]
|
|
4112
4824
|
);
|
|
4113
|
-
|
|
4825
|
+
useEffect7(() => {
|
|
4114
4826
|
if (refreshInterval <= 0) return;
|
|
4115
4827
|
const intervalId = setInterval(() => {
|
|
4116
4828
|
notifyChange(telemetryRef.current);
|
|
@@ -4128,10 +4840,10 @@ function useTelemetry(options = {}) {
|
|
|
4128
4840
|
}
|
|
4129
4841
|
|
|
4130
4842
|
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4131
|
-
import { useEffect as
|
|
4843
|
+
import { useEffect as useEffect8 } from "react";
|
|
4132
4844
|
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4133
4845
|
const { enabled = true, mapStatus } = options;
|
|
4134
|
-
|
|
4846
|
+
useEffect8(() => {
|
|
4135
4847
|
if (!enabled) return;
|
|
4136
4848
|
const defaultMapStatus = (telemetryStatus) => {
|
|
4137
4849
|
switch (telemetryStatus) {
|
|
@@ -4170,7 +4882,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
4170
4882
|
}
|
|
4171
4883
|
|
|
4172
4884
|
// src/diagram/hooks/useDrag.ts
|
|
4173
|
-
import { useState as
|
|
4885
|
+
import { useState as useState12, useCallback as useCallback6, useRef as useRef4, useEffect as useEffect9 } from "react";
|
|
4174
4886
|
function useDrag(options = {}) {
|
|
4175
4887
|
const {
|
|
4176
4888
|
onDragStart,
|
|
@@ -4180,13 +4892,13 @@ function useDrag(options = {}) {
|
|
|
4180
4892
|
dragThreshold = 3,
|
|
4181
4893
|
screenToWorld = (x, y) => ({ x, y })
|
|
4182
4894
|
} = options;
|
|
4183
|
-
const [dragState, setDragState] =
|
|
4895
|
+
const [dragState, setDragState] = useState12({
|
|
4184
4896
|
isDragging: false,
|
|
4185
4897
|
startPosition: null,
|
|
4186
4898
|
offset: { x: 0, y: 0 },
|
|
4187
4899
|
draggedId: null
|
|
4188
4900
|
});
|
|
4189
|
-
const [isListening, setIsListening] =
|
|
4901
|
+
const [isListening, setIsListening] = useState12(false);
|
|
4190
4902
|
const dragStartRef = useRef4(null);
|
|
4191
4903
|
const hasMovedRef = useRef4(false);
|
|
4192
4904
|
const applySnap = useCallback6(
|
|
@@ -4355,7 +5067,7 @@ function useDrag(options = {}) {
|
|
|
4355
5067
|
},
|
|
4356
5068
|
[screenToWorld, applySnap, onDragEnd]
|
|
4357
5069
|
);
|
|
4358
|
-
|
|
5070
|
+
useEffect9(() => {
|
|
4359
5071
|
if (!isListening) return;
|
|
4360
5072
|
document.addEventListener("mousemove", handleMouseMove);
|
|
4361
5073
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -4424,7 +5136,7 @@ function useDrag(options = {}) {
|
|
|
4424
5136
|
}
|
|
4425
5137
|
|
|
4426
5138
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
4427
|
-
import { useEffect as
|
|
5139
|
+
import { useEffect as useEffect10 } from "react";
|
|
4428
5140
|
function useKeyboardShortcuts(options) {
|
|
4429
5141
|
const {
|
|
4430
5142
|
onDelete,
|
|
@@ -4435,7 +5147,7 @@ function useKeyboardShortcuts(options) {
|
|
|
4435
5147
|
onSelectAll,
|
|
4436
5148
|
enabled = true
|
|
4437
5149
|
} = options;
|
|
4438
|
-
|
|
5150
|
+
useEffect10(() => {
|
|
4439
5151
|
if (!enabled) return;
|
|
4440
5152
|
const handleKeyDown = (event) => {
|
|
4441
5153
|
const target = event.target;
|
|
@@ -4544,7 +5256,7 @@ function nodeHasPort(node, portId) {
|
|
|
4544
5256
|
}
|
|
4545
5257
|
|
|
4546
5258
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
4547
|
-
import { Fragment as
|
|
5259
|
+
import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4548
5260
|
function PIDCanvas({
|
|
4549
5261
|
diagram,
|
|
4550
5262
|
className = "",
|
|
@@ -4571,21 +5283,21 @@ function PIDCanvas({
|
|
|
4571
5283
|
telemetry,
|
|
4572
5284
|
...props
|
|
4573
5285
|
}) {
|
|
4574
|
-
const [localDiagram, setLocalDiagram] =
|
|
4575
|
-
const [dragOverPosition, setDragOverPosition] =
|
|
4576
|
-
const [isConnecting, setIsConnecting] =
|
|
4577
|
-
const [connectionSource, setConnectionSource] =
|
|
4578
|
-
const [connectionSourcePort, setConnectionSourcePort] =
|
|
4579
|
-
const [connectionCursor, setConnectionCursor] =
|
|
4580
|
-
const [hoveredNode, setHoveredNode] =
|
|
4581
|
-
const [hoveredPort, setHoveredPort] =
|
|
4582
|
-
const [selectedWaypoint, setSelectedWaypoint] =
|
|
5286
|
+
const [localDiagram, setLocalDiagram] = useState13(diagram);
|
|
5287
|
+
const [dragOverPosition, setDragOverPosition] = useState13(null);
|
|
5288
|
+
const [isConnecting, setIsConnecting] = useState13(false);
|
|
5289
|
+
const [connectionSource, setConnectionSource] = useState13(null);
|
|
5290
|
+
const [connectionSourcePort, setConnectionSourcePort] = useState13(null);
|
|
5291
|
+
const [connectionCursor, setConnectionCursor] = useState13(null);
|
|
5292
|
+
const [hoveredNode, setHoveredNode] = useState13(null);
|
|
5293
|
+
const [hoveredPort, setHoveredPort] = useState13(null);
|
|
5294
|
+
const [selectedWaypoint, setSelectedWaypoint] = useState13(null);
|
|
4583
5295
|
const historyStack = useRef5([]);
|
|
4584
5296
|
const redoStack = useRef5([]);
|
|
4585
5297
|
const isUndoRedoAction = useRef5(false);
|
|
4586
5298
|
const isInternalChange = useRef5(false);
|
|
4587
5299
|
const lastInternalDiagram = useRef5(null);
|
|
4588
|
-
|
|
5300
|
+
useEffect11(() => {
|
|
4589
5301
|
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4590
5302
|
if (isExternal) {
|
|
4591
5303
|
setLocalDiagram(diagram);
|
|
@@ -4630,7 +5342,7 @@ function PIDCanvas({
|
|
|
4630
5342
|
});
|
|
4631
5343
|
return { minX, minY, maxX, maxY };
|
|
4632
5344
|
}, [localDiagram.nodes]);
|
|
4633
|
-
|
|
5345
|
+
useEffect11(() => {
|
|
4634
5346
|
if (onMounted) {
|
|
4635
5347
|
const controls = {
|
|
4636
5348
|
fitToContent: (padding = 50) => {
|
|
@@ -4709,7 +5421,7 @@ function PIDCanvas({
|
|
|
4709
5421
|
isUndoRedoAction.current = false;
|
|
4710
5422
|
}, 0);
|
|
4711
5423
|
}, [localDiagram, onDiagramChange]);
|
|
4712
|
-
|
|
5424
|
+
useEffect11(() => {
|
|
4713
5425
|
const handleKeyDown = (e) => {
|
|
4714
5426
|
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4715
5427
|
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
@@ -4726,7 +5438,7 @@ function PIDCanvas({
|
|
|
4726
5438
|
window.addEventListener("keydown", handleKeyDown);
|
|
4727
5439
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4728
5440
|
}, [undo, redo]);
|
|
4729
|
-
|
|
5441
|
+
useEffect11(() => {
|
|
4730
5442
|
if (!features.dragNodes) return;
|
|
4731
5443
|
const handleKeyDown = (e) => {
|
|
4732
5444
|
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
@@ -5136,7 +5848,7 @@ function PIDCanvas({
|
|
|
5136
5848
|
const viewBox = controlledViewBox;
|
|
5137
5849
|
const displayDiagram = localDiagram;
|
|
5138
5850
|
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5139
|
-
return /* @__PURE__ */
|
|
5851
|
+
return /* @__PURE__ */ jsxs15(
|
|
5140
5852
|
"div",
|
|
5141
5853
|
{
|
|
5142
5854
|
ref: containerRef,
|
|
@@ -5151,7 +5863,7 @@ function PIDCanvas({
|
|
|
5151
5863
|
},
|
|
5152
5864
|
...props,
|
|
5153
5865
|
children: [
|
|
5154
|
-
/* @__PURE__ */
|
|
5866
|
+
/* @__PURE__ */ jsxs15(
|
|
5155
5867
|
"svg",
|
|
5156
5868
|
{
|
|
5157
5869
|
ref: svgRef,
|
|
@@ -5170,15 +5882,15 @@ function PIDCanvas({
|
|
|
5170
5882
|
onDrop: handleDrop,
|
|
5171
5883
|
onDragLeave: handleDragLeave,
|
|
5172
5884
|
children: [
|
|
5173
|
-
features.showGrid !== false ? /* @__PURE__ */
|
|
5174
|
-
/* @__PURE__ */
|
|
5175
|
-
/* @__PURE__ */
|
|
5176
|
-
/* @__PURE__ */
|
|
5177
|
-
/* @__PURE__ */
|
|
5178
|
-
/* @__PURE__ */
|
|
5885
|
+
features.showGrid !== false ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
5886
|
+
/* @__PURE__ */ jsxs15("defs", { children: [
|
|
5887
|
+
/* @__PURE__ */ jsx19("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx19("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
5888
|
+
/* @__PURE__ */ jsxs15("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5889
|
+
/* @__PURE__ */ jsx19("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5890
|
+
/* @__PURE__ */ jsx19("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5179
5891
|
] })
|
|
5180
5892
|
] }),
|
|
5181
|
-
/* @__PURE__ */
|
|
5893
|
+
/* @__PURE__ */ jsx19(
|
|
5182
5894
|
"rect",
|
|
5183
5895
|
{
|
|
5184
5896
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -5188,7 +5900,7 @@ function PIDCanvas({
|
|
|
5188
5900
|
fill: "url(#grid-major)"
|
|
5189
5901
|
}
|
|
5190
5902
|
)
|
|
5191
|
-
] }) : /* @__PURE__ */
|
|
5903
|
+
] }) : /* @__PURE__ */ jsx19(
|
|
5192
5904
|
"rect",
|
|
5193
5905
|
{
|
|
5194
5906
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -5198,7 +5910,7 @@ function PIDCanvas({
|
|
|
5198
5910
|
fill: features.backgroundColor ?? "#ffffff"
|
|
5199
5911
|
}
|
|
5200
5912
|
),
|
|
5201
|
-
/* @__PURE__ */
|
|
5913
|
+
/* @__PURE__ */ jsx19(
|
|
5202
5914
|
PipeRenderer,
|
|
5203
5915
|
{
|
|
5204
5916
|
pipes: displayDiagram.pipes,
|
|
@@ -5212,12 +5924,12 @@ function PIDCanvas({
|
|
|
5212
5924
|
onPipeSegmentClick: void 0
|
|
5213
5925
|
}
|
|
5214
5926
|
),
|
|
5215
|
-
/* @__PURE__ */
|
|
5927
|
+
/* @__PURE__ */ jsx19(
|
|
5216
5928
|
NodeRenderer,
|
|
5217
5929
|
{
|
|
5218
5930
|
nodes: displayDiagram.nodes,
|
|
5219
5931
|
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5220
|
-
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5932
|
+
onNodeClick: onNodeClick ? handleNodeClick : selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5221
5933
|
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5222
5934
|
enableDrag: dragEnabled && !isConnecting,
|
|
5223
5935
|
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
@@ -5225,7 +5937,7 @@ function PIDCanvas({
|
|
|
5225
5937
|
dragOffset: dragState.offset
|
|
5226
5938
|
}
|
|
5227
5939
|
),
|
|
5228
|
-
(features.editPipeRoutes ?? false) && /* @__PURE__ */
|
|
5940
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx19(
|
|
5229
5941
|
PipeRenderer,
|
|
5230
5942
|
{
|
|
5231
5943
|
pipes: displayDiagram.pipes,
|
|
@@ -5242,14 +5954,14 @@ function PIDCanvas({
|
|
|
5242
5954
|
onPipeSegmentClick: handlePipeSegmentClick
|
|
5243
5955
|
}
|
|
5244
5956
|
),
|
|
5245
|
-
telemetryEnabled && telemetry && /* @__PURE__ */
|
|
5957
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ jsx19("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5246
5958
|
const binding = telemetry.get(node.id);
|
|
5247
5959
|
if (!binding) return null;
|
|
5248
5960
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
5249
5961
|
if (!symbol) return null;
|
|
5250
5962
|
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5251
5963
|
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5252
|
-
return /* @__PURE__ */
|
|
5964
|
+
return /* @__PURE__ */ jsx19(
|
|
5253
5965
|
DataOverlay,
|
|
5254
5966
|
{
|
|
5255
5967
|
nodeId: node.id,
|
|
@@ -5261,7 +5973,7 @@ function PIDCanvas({
|
|
|
5261
5973
|
`telemetry-${node.id}`
|
|
5262
5974
|
);
|
|
5263
5975
|
}) }),
|
|
5264
|
-
dragOverPosition && /* @__PURE__ */
|
|
5976
|
+
dragOverPosition && /* @__PURE__ */ jsx19(
|
|
5265
5977
|
"circle",
|
|
5266
5978
|
{
|
|
5267
5979
|
cx: dragOverPosition.x,
|
|
@@ -5274,7 +5986,7 @@ function PIDCanvas({
|
|
|
5274
5986
|
pointerEvents: "none"
|
|
5275
5987
|
}
|
|
5276
5988
|
),
|
|
5277
|
-
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */
|
|
5989
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx19("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5278
5990
|
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5279
5991
|
if (!sourceNode) return null;
|
|
5280
5992
|
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
@@ -5290,8 +6002,8 @@ function PIDCanvas({
|
|
|
5290
6002
|
}
|
|
5291
6003
|
}
|
|
5292
6004
|
}
|
|
5293
|
-
return /* @__PURE__ */
|
|
5294
|
-
/* @__PURE__ */
|
|
6005
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
6006
|
+
/* @__PURE__ */ jsx19(
|
|
5295
6007
|
"circle",
|
|
5296
6008
|
{
|
|
5297
6009
|
cx: lineStartX,
|
|
@@ -5303,7 +6015,7 @@ function PIDCanvas({
|
|
|
5303
6015
|
opacity: 0.6
|
|
5304
6016
|
}
|
|
5305
6017
|
),
|
|
5306
|
-
/* @__PURE__ */
|
|
6018
|
+
/* @__PURE__ */ jsx19(
|
|
5307
6019
|
"line",
|
|
5308
6020
|
{
|
|
5309
6021
|
x1: lineStartX,
|
|
@@ -5316,7 +6028,7 @@ function PIDCanvas({
|
|
|
5316
6028
|
opacity: 0.8
|
|
5317
6029
|
}
|
|
5318
6030
|
),
|
|
5319
|
-
/* @__PURE__ */
|
|
6031
|
+
/* @__PURE__ */ jsx19(
|
|
5320
6032
|
"circle",
|
|
5321
6033
|
{
|
|
5322
6034
|
cx: connectionCursor.x,
|
|
@@ -5328,7 +6040,7 @@ function PIDCanvas({
|
|
|
5328
6040
|
)
|
|
5329
6041
|
] });
|
|
5330
6042
|
})() }),
|
|
5331
|
-
features.connectionMode && /* @__PURE__ */
|
|
6043
|
+
features.connectionMode && /* @__PURE__ */ jsx19("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5332
6044
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
5333
6045
|
if (!symbol?.ports) return null;
|
|
5334
6046
|
return symbol.ports.map((port) => {
|
|
@@ -5336,8 +6048,8 @@ function PIDCanvas({
|
|
|
5336
6048
|
if (!portPos) return null;
|
|
5337
6049
|
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5338
6050
|
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5339
|
-
return /* @__PURE__ */
|
|
5340
|
-
/* @__PURE__ */
|
|
6051
|
+
return /* @__PURE__ */ jsxs15("g", { children: [
|
|
6052
|
+
/* @__PURE__ */ jsx19(
|
|
5341
6053
|
"circle",
|
|
5342
6054
|
{
|
|
5343
6055
|
cx: portPos.x,
|
|
@@ -5370,7 +6082,7 @@ function PIDCanvas({
|
|
|
5370
6082
|
}
|
|
5371
6083
|
}
|
|
5372
6084
|
),
|
|
5373
|
-
/* @__PURE__ */
|
|
6085
|
+
/* @__PURE__ */ jsx19(
|
|
5374
6086
|
"circle",
|
|
5375
6087
|
{
|
|
5376
6088
|
cx: portPos.x,
|
|
@@ -5389,7 +6101,7 @@ function PIDCanvas({
|
|
|
5389
6101
|
]
|
|
5390
6102
|
}
|
|
5391
6103
|
),
|
|
5392
|
-
features.dragNodes && /* @__PURE__ */
|
|
6104
|
+
features.dragNodes && /* @__PURE__ */ jsx19(
|
|
5393
6105
|
PositionPanel,
|
|
5394
6106
|
{
|
|
5395
6107
|
selectedNode,
|
|
@@ -5409,16 +6121,16 @@ function PIDCanvas({
|
|
|
5409
6121
|
}
|
|
5410
6122
|
|
|
5411
6123
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
5412
|
-
import { useState as
|
|
5413
|
-
import { jsx as
|
|
6124
|
+
import { useState as useState14 } from "react";
|
|
6125
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
5414
6126
|
function SymbolLibrary({
|
|
5415
6127
|
className = "",
|
|
5416
6128
|
onSymbolDragStart,
|
|
5417
6129
|
showCategories = true,
|
|
5418
6130
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
5419
6131
|
}) {
|
|
5420
|
-
const [selectedCategory, setSelectedCategory] =
|
|
5421
|
-
const [searchQuery, setSearchQuery] =
|
|
6132
|
+
const [selectedCategory, setSelectedCategory] = useState14("all");
|
|
6133
|
+
const [searchQuery, setSearchQuery] = useState14("");
|
|
5422
6134
|
const symbolIds = getAvailableSymbols();
|
|
5423
6135
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5424
6136
|
const categoryMap = {
|
|
@@ -5439,9 +6151,9 @@ function SymbolLibrary({
|
|
|
5439
6151
|
event.dataTransfer.effectAllowed = "copy";
|
|
5440
6152
|
onSymbolDragStart?.(symbol.id, event);
|
|
5441
6153
|
};
|
|
5442
|
-
return /* @__PURE__ */
|
|
5443
|
-
/* @__PURE__ */
|
|
5444
|
-
/* @__PURE__ */
|
|
6154
|
+
return /* @__PURE__ */ jsxs16("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
6155
|
+
/* @__PURE__ */ jsx20("div", { style: styles.header, children: /* @__PURE__ */ jsx20("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
6156
|
+
/* @__PURE__ */ jsx20("div", { style: styles.searchContainer, children: /* @__PURE__ */ jsx20(
|
|
5445
6157
|
"input",
|
|
5446
6158
|
{
|
|
5447
6159
|
type: "text",
|
|
@@ -5451,8 +6163,8 @@ function SymbolLibrary({
|
|
|
5451
6163
|
style: styles.searchInput
|
|
5452
6164
|
}
|
|
5453
6165
|
) }),
|
|
5454
|
-
showCategories && /* @__PURE__ */
|
|
5455
|
-
/* @__PURE__ */
|
|
6166
|
+
showCategories && /* @__PURE__ */ jsxs16("div", { style: styles.categories, children: [
|
|
6167
|
+
/* @__PURE__ */ jsx20(
|
|
5456
6168
|
"button",
|
|
5457
6169
|
{
|
|
5458
6170
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -5463,7 +6175,7 @@ function SymbolLibrary({
|
|
|
5463
6175
|
children: "All"
|
|
5464
6176
|
}
|
|
5465
6177
|
),
|
|
5466
|
-
categories.map((category) => /* @__PURE__ */
|
|
6178
|
+
categories.map((category) => /* @__PURE__ */ jsx20(
|
|
5467
6179
|
"button",
|
|
5468
6180
|
{
|
|
5469
6181
|
onClick: () => setSelectedCategory(category),
|
|
@@ -5476,7 +6188,7 @@ function SymbolLibrary({
|
|
|
5476
6188
|
category
|
|
5477
6189
|
))
|
|
5478
6190
|
] }),
|
|
5479
|
-
/* @__PURE__ */
|
|
6191
|
+
/* @__PURE__ */ jsx20("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ jsx20("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ jsxs16(
|
|
5480
6192
|
"div",
|
|
5481
6193
|
{
|
|
5482
6194
|
draggable: true,
|
|
@@ -5484,15 +6196,15 @@ function SymbolLibrary({
|
|
|
5484
6196
|
style: styles.symbolCard,
|
|
5485
6197
|
title: symbol.metadata?.description || symbol.name,
|
|
5486
6198
|
children: [
|
|
5487
|
-
/* @__PURE__ */
|
|
6199
|
+
/* @__PURE__ */ jsx20("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx20(
|
|
5488
6200
|
"svg",
|
|
5489
6201
|
{
|
|
5490
6202
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
5491
6203
|
style: styles.symbolSvg,
|
|
5492
|
-
children: /* @__PURE__ */
|
|
6204
|
+
children: /* @__PURE__ */ jsx20("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
5493
6205
|
}
|
|
5494
6206
|
) }),
|
|
5495
|
-
/* @__PURE__ */
|
|
6207
|
+
/* @__PURE__ */ jsx20("div", { style: styles.symbolName, children: symbol.name })
|
|
5496
6208
|
]
|
|
5497
6209
|
},
|
|
5498
6210
|
symbol.id
|
|
@@ -5601,7 +6313,7 @@ var styles = {
|
|
|
5601
6313
|
};
|
|
5602
6314
|
|
|
5603
6315
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
5604
|
-
import { Fragment as
|
|
6316
|
+
import { Fragment as Fragment8, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
5605
6317
|
function NodeConfigPanel({
|
|
5606
6318
|
node,
|
|
5607
6319
|
binding,
|
|
@@ -5620,15 +6332,15 @@ function NodeConfigPanel({
|
|
|
5620
6332
|
padding: "20px",
|
|
5621
6333
|
...style
|
|
5622
6334
|
};
|
|
5623
|
-
return /* @__PURE__ */
|
|
5624
|
-
/* @__PURE__ */
|
|
6335
|
+
return /* @__PURE__ */ jsxs17("div", { className, style: defaultStyle, children: [
|
|
6336
|
+
/* @__PURE__ */ jsxs17("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
5625
6337
|
"Configure: ",
|
|
5626
6338
|
node.id
|
|
5627
6339
|
] }),
|
|
5628
|
-
/* @__PURE__ */
|
|
5629
|
-
/* @__PURE__ */
|
|
5630
|
-
/* @__PURE__ */
|
|
5631
|
-
/* @__PURE__ */
|
|
6340
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
|
|
6341
|
+
/* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
6342
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
6343
|
+
/* @__PURE__ */ jsx21(
|
|
5632
6344
|
"input",
|
|
5633
6345
|
{
|
|
5634
6346
|
type: "text",
|
|
@@ -5644,10 +6356,10 @@ function NodeConfigPanel({
|
|
|
5644
6356
|
}
|
|
5645
6357
|
}
|
|
5646
6358
|
),
|
|
5647
|
-
/* @__PURE__ */
|
|
5648
|
-
/* @__PURE__ */
|
|
5649
|
-
/* @__PURE__ */
|
|
5650
|
-
/* @__PURE__ */
|
|
6359
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
6360
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6361
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
6362
|
+
/* @__PURE__ */ jsx21(
|
|
5651
6363
|
"input",
|
|
5652
6364
|
{
|
|
5653
6365
|
type: "number",
|
|
@@ -5668,9 +6380,9 @@ function NodeConfigPanel({
|
|
|
5668
6380
|
}
|
|
5669
6381
|
)
|
|
5670
6382
|
] }),
|
|
5671
|
-
/* @__PURE__ */
|
|
5672
|
-
/* @__PURE__ */
|
|
5673
|
-
/* @__PURE__ */
|
|
6383
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6384
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
6385
|
+
/* @__PURE__ */ jsx21(
|
|
5674
6386
|
"input",
|
|
5675
6387
|
{
|
|
5676
6388
|
type: "number",
|
|
@@ -5692,9 +6404,9 @@ function NodeConfigPanel({
|
|
|
5692
6404
|
)
|
|
5693
6405
|
] })
|
|
5694
6406
|
] }),
|
|
5695
|
-
/* @__PURE__ */
|
|
5696
|
-
/* @__PURE__ */
|
|
5697
|
-
/* @__PURE__ */
|
|
6407
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6408
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
6409
|
+
/* @__PURE__ */ jsx21(
|
|
5698
6410
|
"input",
|
|
5699
6411
|
{
|
|
5700
6412
|
type: "number",
|
|
@@ -5714,9 +6426,9 @@ function NodeConfigPanel({
|
|
|
5714
6426
|
}
|
|
5715
6427
|
)
|
|
5716
6428
|
] }),
|
|
5717
|
-
/* @__PURE__ */
|
|
5718
|
-
/* @__PURE__ */
|
|
5719
|
-
/* @__PURE__ */
|
|
6429
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6430
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
6431
|
+
/* @__PURE__ */ jsx21(
|
|
5720
6432
|
"input",
|
|
5721
6433
|
{
|
|
5722
6434
|
type: "number",
|
|
@@ -5741,9 +6453,9 @@ function NodeConfigPanel({
|
|
|
5741
6453
|
)
|
|
5742
6454
|
] })
|
|
5743
6455
|
] }),
|
|
5744
|
-
/* @__PURE__ */
|
|
5745
|
-
/* @__PURE__ */
|
|
5746
|
-
!binding ? /* @__PURE__ */
|
|
6456
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
|
|
6457
|
+
/* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
6458
|
+
!binding ? /* @__PURE__ */ jsx21(
|
|
5747
6459
|
"button",
|
|
5748
6460
|
{
|
|
5749
6461
|
onClick: () => {
|
|
@@ -5786,9 +6498,9 @@ function NodeConfigPanel({
|
|
|
5786
6498
|
},
|
|
5787
6499
|
children: "+ Add Telemetry"
|
|
5788
6500
|
}
|
|
5789
|
-
) : /* @__PURE__ */
|
|
5790
|
-
/* @__PURE__ */
|
|
5791
|
-
/* @__PURE__ */
|
|
6501
|
+
) : /* @__PURE__ */ jsxs17(Fragment8, { children: [
|
|
6502
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
6503
|
+
/* @__PURE__ */ jsx21(
|
|
5792
6504
|
"input",
|
|
5793
6505
|
{
|
|
5794
6506
|
type: "number",
|
|
@@ -5810,8 +6522,8 @@ function NodeConfigPanel({
|
|
|
5810
6522
|
}
|
|
5811
6523
|
}
|
|
5812
6524
|
),
|
|
5813
|
-
/* @__PURE__ */
|
|
5814
|
-
/* @__PURE__ */
|
|
6525
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
6526
|
+
/* @__PURE__ */ jsx21(
|
|
5815
6527
|
"input",
|
|
5816
6528
|
{
|
|
5817
6529
|
type: "text",
|
|
@@ -5833,8 +6545,8 @@ function NodeConfigPanel({
|
|
|
5833
6545
|
}
|
|
5834
6546
|
}
|
|
5835
6547
|
),
|
|
5836
|
-
/* @__PURE__ */
|
|
5837
|
-
/* @__PURE__ */
|
|
6548
|
+
/* @__PURE__ */ jsxs17("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
6549
|
+
/* @__PURE__ */ jsx21(
|
|
5838
6550
|
"input",
|
|
5839
6551
|
{
|
|
5840
6552
|
type: "checkbox",
|
|
@@ -5856,8 +6568,8 @@ function NodeConfigPanel({
|
|
|
5856
6568
|
),
|
|
5857
6569
|
"Show Sparkline"
|
|
5858
6570
|
] }),
|
|
5859
|
-
/* @__PURE__ */
|
|
5860
|
-
/* @__PURE__ */
|
|
6571
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginTop: "12px" }, children: [
|
|
6572
|
+
/* @__PURE__ */ jsx21(
|
|
5861
6573
|
"label",
|
|
5862
6574
|
{
|
|
5863
6575
|
style: {
|
|
@@ -5869,10 +6581,10 @@ function NodeConfigPanel({
|
|
|
5869
6581
|
children: "Telemetry Position Offset:"
|
|
5870
6582
|
}
|
|
5871
6583
|
),
|
|
5872
|
-
/* @__PURE__ */
|
|
5873
|
-
/* @__PURE__ */
|
|
5874
|
-
/* @__PURE__ */
|
|
5875
|
-
/* @__PURE__ */
|
|
6584
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
6585
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6586
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
6587
|
+
/* @__PURE__ */ jsx21(
|
|
5876
6588
|
"input",
|
|
5877
6589
|
{
|
|
5878
6590
|
type: "number",
|
|
@@ -5899,9 +6611,9 @@ function NodeConfigPanel({
|
|
|
5899
6611
|
}
|
|
5900
6612
|
)
|
|
5901
6613
|
] }),
|
|
5902
|
-
/* @__PURE__ */
|
|
5903
|
-
/* @__PURE__ */
|
|
5904
|
-
/* @__PURE__ */
|
|
6614
|
+
/* @__PURE__ */ jsxs17("div", { children: [
|
|
6615
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
6616
|
+
/* @__PURE__ */ jsx21(
|
|
5905
6617
|
"input",
|
|
5906
6618
|
{
|
|
5907
6619
|
type: "number",
|
|
@@ -5929,8 +6641,8 @@ function NodeConfigPanel({
|
|
|
5929
6641
|
)
|
|
5930
6642
|
] })
|
|
5931
6643
|
] }),
|
|
5932
|
-
/* @__PURE__ */
|
|
5933
|
-
/* @__PURE__ */
|
|
6644
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginTop: "16px" }, children: [
|
|
6645
|
+
/* @__PURE__ */ jsx21(
|
|
5934
6646
|
"label",
|
|
5935
6647
|
{
|
|
5936
6648
|
style: {
|
|
@@ -5942,10 +6654,10 @@ function NodeConfigPanel({
|
|
|
5942
6654
|
children: "Display Colors:"
|
|
5943
6655
|
}
|
|
5944
6656
|
),
|
|
5945
|
-
/* @__PURE__ */
|
|
5946
|
-
/* @__PURE__ */
|
|
5947
|
-
/* @__PURE__ */
|
|
5948
|
-
/* @__PURE__ */
|
|
6657
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
|
|
6658
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
6659
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6660
|
+
/* @__PURE__ */ jsx21(
|
|
5949
6661
|
"input",
|
|
5950
6662
|
{
|
|
5951
6663
|
type: "color",
|
|
@@ -5971,7 +6683,7 @@ function NodeConfigPanel({
|
|
|
5971
6683
|
}
|
|
5972
6684
|
}
|
|
5973
6685
|
),
|
|
5974
|
-
/* @__PURE__ */
|
|
6686
|
+
/* @__PURE__ */ jsx21(
|
|
5975
6687
|
"input",
|
|
5976
6688
|
{
|
|
5977
6689
|
type: "text",
|
|
@@ -6001,10 +6713,10 @@ function NodeConfigPanel({
|
|
|
6001
6713
|
)
|
|
6002
6714
|
] })
|
|
6003
6715
|
] }),
|
|
6004
|
-
binding.display?.showSparkline && /* @__PURE__ */
|
|
6005
|
-
/* @__PURE__ */
|
|
6006
|
-
/* @__PURE__ */
|
|
6007
|
-
/* @__PURE__ */
|
|
6716
|
+
binding.display?.showSparkline && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
|
|
6717
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
6718
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6719
|
+
/* @__PURE__ */ jsx21(
|
|
6008
6720
|
"input",
|
|
6009
6721
|
{
|
|
6010
6722
|
type: "color",
|
|
@@ -6030,7 +6742,7 @@ function NodeConfigPanel({
|
|
|
6030
6742
|
}
|
|
6031
6743
|
}
|
|
6032
6744
|
),
|
|
6033
|
-
/* @__PURE__ */
|
|
6745
|
+
/* @__PURE__ */ jsx21(
|
|
6034
6746
|
"input",
|
|
6035
6747
|
{
|
|
6036
6748
|
type: "text",
|
|
@@ -6060,9 +6772,9 @@ function NodeConfigPanel({
|
|
|
6060
6772
|
)
|
|
6061
6773
|
] })
|
|
6062
6774
|
] }),
|
|
6063
|
-
/* @__PURE__ */
|
|
6064
|
-
/* @__PURE__ */
|
|
6065
|
-
/* @__PURE__ */
|
|
6775
|
+
/* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
|
|
6776
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6777
|
+
/* @__PURE__ */ jsx21(
|
|
6066
6778
|
"input",
|
|
6067
6779
|
{
|
|
6068
6780
|
type: "text",
|
|
@@ -6090,20 +6802,20 @@ function NodeConfigPanel({
|
|
|
6090
6802
|
}
|
|
6091
6803
|
}
|
|
6092
6804
|
),
|
|
6093
|
-
/* @__PURE__ */
|
|
6805
|
+
/* @__PURE__ */ jsx21("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
6094
6806
|
] })
|
|
6095
6807
|
] }),
|
|
6096
6808
|
" "
|
|
6097
6809
|
] })
|
|
6098
6810
|
] })
|
|
6099
6811
|
] }),
|
|
6100
|
-
binding && /* @__PURE__ */
|
|
6101
|
-
/* @__PURE__ */
|
|
6812
|
+
binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
|
|
6813
|
+
/* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
6102
6814
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
6103
6815
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
6104
|
-
return /* @__PURE__ */
|
|
6105
|
-
/* @__PURE__ */
|
|
6106
|
-
/* @__PURE__ */
|
|
6816
|
+
return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
|
|
6817
|
+
/* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6818
|
+
/* @__PURE__ */ jsx21(
|
|
6107
6819
|
"input",
|
|
6108
6820
|
{
|
|
6109
6821
|
type: "number",
|
|
@@ -6127,8 +6839,8 @@ function NodeConfigPanel({
|
|
|
6127
6839
|
] }, key);
|
|
6128
6840
|
})
|
|
6129
6841
|
] }),
|
|
6130
|
-
binding && /* @__PURE__ */
|
|
6131
|
-
/* @__PURE__ */
|
|
6842
|
+
binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
|
|
6843
|
+
/* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
6132
6844
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
6133
6845
|
const defaultColors = {
|
|
6134
6846
|
normal: "#10b981",
|
|
@@ -6138,13 +6850,13 @@ function NodeConfigPanel({
|
|
|
6138
6850
|
off: "#6b7280"
|
|
6139
6851
|
};
|
|
6140
6852
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
6141
|
-
return /* @__PURE__ */
|
|
6142
|
-
/* @__PURE__ */
|
|
6853
|
+
return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
|
|
6854
|
+
/* @__PURE__ */ jsxs17("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
6143
6855
|
label,
|
|
6144
6856
|
":"
|
|
6145
6857
|
] }),
|
|
6146
|
-
/* @__PURE__ */
|
|
6147
|
-
/* @__PURE__ */
|
|
6858
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6859
|
+
/* @__PURE__ */ jsx21(
|
|
6148
6860
|
"input",
|
|
6149
6861
|
{
|
|
6150
6862
|
type: "color",
|
|
@@ -6165,7 +6877,7 @@ function NodeConfigPanel({
|
|
|
6165
6877
|
}
|
|
6166
6878
|
}
|
|
6167
6879
|
),
|
|
6168
|
-
/* @__PURE__ */
|
|
6880
|
+
/* @__PURE__ */ jsx21(
|
|
6169
6881
|
"input",
|
|
6170
6882
|
{
|
|
6171
6883
|
type: "text",
|
|
@@ -6192,7 +6904,7 @@ function NodeConfigPanel({
|
|
|
6192
6904
|
] }, status);
|
|
6193
6905
|
})
|
|
6194
6906
|
] }),
|
|
6195
|
-
/* @__PURE__ */
|
|
6907
|
+
/* @__PURE__ */ jsx21("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ jsx21(
|
|
6196
6908
|
"button",
|
|
6197
6909
|
{
|
|
6198
6910
|
onClick: onRemove,
|
|
@@ -6431,8 +7143,280 @@ var DEFAULT_THRESHOLDS = {
|
|
|
6431
7143
|
lowLow: 15
|
|
6432
7144
|
};
|
|
6433
7145
|
|
|
7146
|
+
// src/diagram/schema/DeviceControlBinding.ts
|
|
7147
|
+
function createControlBinding(nodeId, deviceConfig, actions) {
|
|
7148
|
+
const parametersByMode = {};
|
|
7149
|
+
deviceConfig.parameters.forEach((param) => {
|
|
7150
|
+
const modes = param.modes || deviceConfig.modes.map((m) => m.value);
|
|
7151
|
+
modes.forEach((mode) => {
|
|
7152
|
+
if (!parametersByMode[mode]) {
|
|
7153
|
+
parametersByMode[mode] = [];
|
|
7154
|
+
}
|
|
7155
|
+
parametersByMode[mode].push({
|
|
7156
|
+
id: param.id,
|
|
7157
|
+
label: param.label,
|
|
7158
|
+
unit: param.unit,
|
|
7159
|
+
min: param.min,
|
|
7160
|
+
max: param.max,
|
|
7161
|
+
value: param.value,
|
|
7162
|
+
type: typeof param.value === "number" ? "number" : "string"
|
|
7163
|
+
});
|
|
7164
|
+
});
|
|
7165
|
+
});
|
|
7166
|
+
return {
|
|
7167
|
+
nodeId,
|
|
7168
|
+
tag: deviceConfig.tag,
|
|
7169
|
+
deviceName: deviceConfig.name,
|
|
7170
|
+
deviceType: deviceConfig.type,
|
|
7171
|
+
modes: deviceConfig.modes,
|
|
7172
|
+
state: {
|
|
7173
|
+
currentMode: deviceConfig.currentMode,
|
|
7174
|
+
isRunning: deviceConfig.isRunning,
|
|
7175
|
+
status: deviceConfig.status
|
|
7176
|
+
},
|
|
7177
|
+
parameters: parametersByMode,
|
|
7178
|
+
capabilities: deviceConfig.capabilities,
|
|
7179
|
+
actions
|
|
7180
|
+
};
|
|
7181
|
+
}
|
|
7182
|
+
|
|
7183
|
+
// src/hooks/useDeviceControls.ts
|
|
7184
|
+
import { useState as useState15, useCallback as useCallback8 } from "react";
|
|
7185
|
+
function useDeviceControls(initialBindings) {
|
|
7186
|
+
const [controls, setControls] = useState15(() => {
|
|
7187
|
+
const map = /* @__PURE__ */ new Map();
|
|
7188
|
+
if (initialBindings) {
|
|
7189
|
+
initialBindings.forEach((binding) => {
|
|
7190
|
+
map.set(binding.nodeId, binding);
|
|
7191
|
+
});
|
|
7192
|
+
}
|
|
7193
|
+
return map;
|
|
7194
|
+
});
|
|
7195
|
+
const updateControl = useCallback8((nodeId, updates) => {
|
|
7196
|
+
setControls((prev) => {
|
|
7197
|
+
const newMap = new Map(prev);
|
|
7198
|
+
const existing = newMap.get(nodeId);
|
|
7199
|
+
if (existing) {
|
|
7200
|
+
newMap.set(nodeId, { ...existing, ...updates });
|
|
7201
|
+
} else {
|
|
7202
|
+
if ("tag" in updates && "modes" in updates && "state" in updates && "parameters" in updates && "actions" in updates) {
|
|
7203
|
+
newMap.set(nodeId, { nodeId, ...updates });
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
return newMap;
|
|
7207
|
+
});
|
|
7208
|
+
}, []);
|
|
7209
|
+
const updateControlBatch = useCallback8((updates) => {
|
|
7210
|
+
setControls((prev) => {
|
|
7211
|
+
const newMap = new Map(prev);
|
|
7212
|
+
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
7213
|
+
const existing = newMap.get(nodeId);
|
|
7214
|
+
if (existing) {
|
|
7215
|
+
newMap.set(nodeId, { ...existing, ...update });
|
|
7216
|
+
}
|
|
7217
|
+
});
|
|
7218
|
+
return newMap;
|
|
7219
|
+
});
|
|
7220
|
+
}, []);
|
|
7221
|
+
const updateDeviceState = useCallback8(
|
|
7222
|
+
(nodeId, stateUpdates) => {
|
|
7223
|
+
setControls((prev) => {
|
|
7224
|
+
const newMap = new Map(prev);
|
|
7225
|
+
const existing = newMap.get(nodeId);
|
|
7226
|
+
if (existing) {
|
|
7227
|
+
newMap.set(nodeId, {
|
|
7228
|
+
...existing,
|
|
7229
|
+
state: { ...existing.state, ...stateUpdates }
|
|
7230
|
+
});
|
|
7231
|
+
}
|
|
7232
|
+
return newMap;
|
|
7233
|
+
});
|
|
7234
|
+
},
|
|
7235
|
+
[]
|
|
7236
|
+
);
|
|
7237
|
+
const updateParameter = useCallback8(
|
|
7238
|
+
(nodeId, parameterId, value) => {
|
|
7239
|
+
setControls((prev) => {
|
|
7240
|
+
const newMap = new Map(prev);
|
|
7241
|
+
const existing = newMap.get(nodeId);
|
|
7242
|
+
if (existing) {
|
|
7243
|
+
const updatedParameters = { ...existing.parameters };
|
|
7244
|
+
Object.keys(updatedParameters).forEach((mode) => {
|
|
7245
|
+
const paramIndex = updatedParameters[mode].findIndex((p) => p.id === parameterId);
|
|
7246
|
+
if (paramIndex !== -1) {
|
|
7247
|
+
updatedParameters[mode] = [...updatedParameters[mode]];
|
|
7248
|
+
updatedParameters[mode][paramIndex] = {
|
|
7249
|
+
...updatedParameters[mode][paramIndex],
|
|
7250
|
+
value
|
|
7251
|
+
};
|
|
7252
|
+
}
|
|
7253
|
+
});
|
|
7254
|
+
newMap.set(nodeId, {
|
|
7255
|
+
...existing,
|
|
7256
|
+
parameters: updatedParameters
|
|
7257
|
+
});
|
|
7258
|
+
}
|
|
7259
|
+
return newMap;
|
|
7260
|
+
});
|
|
7261
|
+
},
|
|
7262
|
+
[]
|
|
7263
|
+
);
|
|
7264
|
+
const setControlBinding = useCallback8((binding) => {
|
|
7265
|
+
setControls((prev) => {
|
|
7266
|
+
const newMap = new Map(prev);
|
|
7267
|
+
newMap.set(binding.nodeId, binding);
|
|
7268
|
+
return newMap;
|
|
7269
|
+
});
|
|
7270
|
+
}, []);
|
|
7271
|
+
const removeControlBinding = useCallback8((nodeId) => {
|
|
7272
|
+
setControls((prev) => {
|
|
7273
|
+
const newMap = new Map(prev);
|
|
7274
|
+
newMap.delete(nodeId);
|
|
7275
|
+
return newMap;
|
|
7276
|
+
});
|
|
7277
|
+
}, []);
|
|
7278
|
+
const getControlBinding = useCallback8(
|
|
7279
|
+
(nodeId) => {
|
|
7280
|
+
return controls.get(nodeId);
|
|
7281
|
+
},
|
|
7282
|
+
[controls]
|
|
7283
|
+
);
|
|
7284
|
+
const sendModeChange = useCallback8(
|
|
7285
|
+
async (nodeId, mode) => {
|
|
7286
|
+
const binding = controls.get(nodeId);
|
|
7287
|
+
if (!binding) return;
|
|
7288
|
+
updateDeviceState(nodeId, { currentMode: mode });
|
|
7289
|
+
try {
|
|
7290
|
+
await binding.actions.onModeChange?.(mode);
|
|
7291
|
+
updateDeviceState(nodeId, {
|
|
7292
|
+
lastCommandTime: Date.now(),
|
|
7293
|
+
lastCommandResult: { success: true, message: `Mode changed to ${mode}` }
|
|
7294
|
+
});
|
|
7295
|
+
} catch (error) {
|
|
7296
|
+
updateDeviceState(nodeId, {
|
|
7297
|
+
currentMode: binding.state.currentMode,
|
|
7298
|
+
lastCommandResult: {
|
|
7299
|
+
success: false,
|
|
7300
|
+
message: error instanceof Error ? error.message : "Mode change failed"
|
|
7301
|
+
}
|
|
7302
|
+
});
|
|
7303
|
+
}
|
|
7304
|
+
},
|
|
7305
|
+
[controls, updateDeviceState]
|
|
7306
|
+
);
|
|
7307
|
+
const sendParameterChange = useCallback8(
|
|
7308
|
+
async (nodeId, parameterId, value) => {
|
|
7309
|
+
const binding = controls.get(nodeId);
|
|
7310
|
+
if (!binding) return;
|
|
7311
|
+
updateParameter(nodeId, parameterId, value);
|
|
7312
|
+
try {
|
|
7313
|
+
await binding.actions.onParameterChange?.(parameterId, value);
|
|
7314
|
+
updateDeviceState(nodeId, {
|
|
7315
|
+
lastCommandTime: Date.now(),
|
|
7316
|
+
lastCommandResult: { success: true, message: `Parameter ${parameterId} updated` }
|
|
7317
|
+
});
|
|
7318
|
+
} catch (error) {
|
|
7319
|
+
updateDeviceState(nodeId, {
|
|
7320
|
+
lastCommandResult: {
|
|
7321
|
+
success: false,
|
|
7322
|
+
message: error instanceof Error ? error.message : "Parameter change failed"
|
|
7323
|
+
}
|
|
7324
|
+
});
|
|
7325
|
+
}
|
|
7326
|
+
},
|
|
7327
|
+
[controls, updateParameter, updateDeviceState]
|
|
7328
|
+
);
|
|
7329
|
+
const sendStartCommand = useCallback8(
|
|
7330
|
+
async (nodeId) => {
|
|
7331
|
+
const binding = controls.get(nodeId);
|
|
7332
|
+
if (!binding) return;
|
|
7333
|
+
updateDeviceState(nodeId, { isRunning: true, status: "starting" });
|
|
7334
|
+
try {
|
|
7335
|
+
await binding.actions.onStart?.();
|
|
7336
|
+
updateDeviceState(nodeId, {
|
|
7337
|
+
status: "normal",
|
|
7338
|
+
lastCommandTime: Date.now(),
|
|
7339
|
+
lastCommandResult: { success: true, message: "Device started" }
|
|
7340
|
+
});
|
|
7341
|
+
} catch (error) {
|
|
7342
|
+
updateDeviceState(nodeId, {
|
|
7343
|
+
isRunning: false,
|
|
7344
|
+
status: "fault",
|
|
7345
|
+
lastCommandResult: {
|
|
7346
|
+
success: false,
|
|
7347
|
+
message: error instanceof Error ? error.message : "Start failed"
|
|
7348
|
+
}
|
|
7349
|
+
});
|
|
7350
|
+
}
|
|
7351
|
+
},
|
|
7352
|
+
[controls, updateDeviceState]
|
|
7353
|
+
);
|
|
7354
|
+
const sendStopCommand = useCallback8(
|
|
7355
|
+
async (nodeId) => {
|
|
7356
|
+
const binding = controls.get(nodeId);
|
|
7357
|
+
if (!binding) return;
|
|
7358
|
+
updateDeviceState(nodeId, { isRunning: false, status: "stopping" });
|
|
7359
|
+
try {
|
|
7360
|
+
await binding.actions.onStop?.();
|
|
7361
|
+
updateDeviceState(nodeId, {
|
|
7362
|
+
status: "off",
|
|
7363
|
+
lastCommandTime: Date.now(),
|
|
7364
|
+
lastCommandResult: { success: true, message: "Device stopped" }
|
|
7365
|
+
});
|
|
7366
|
+
} catch (error) {
|
|
7367
|
+
updateDeviceState(nodeId, {
|
|
7368
|
+
isRunning: true,
|
|
7369
|
+
status: "fault",
|
|
7370
|
+
lastCommandResult: {
|
|
7371
|
+
success: false,
|
|
7372
|
+
message: error instanceof Error ? error.message : "Stop failed"
|
|
7373
|
+
}
|
|
7374
|
+
});
|
|
7375
|
+
}
|
|
7376
|
+
},
|
|
7377
|
+
[controls, updateDeviceState]
|
|
7378
|
+
);
|
|
7379
|
+
const sendCustomAction = useCallback8(
|
|
7380
|
+
async (nodeId, actionId) => {
|
|
7381
|
+
const binding = controls.get(nodeId);
|
|
7382
|
+
if (!binding) return;
|
|
7383
|
+
try {
|
|
7384
|
+
await binding.actions.onCustomAction?.(actionId);
|
|
7385
|
+
updateDeviceState(nodeId, {
|
|
7386
|
+
lastCommandTime: Date.now(),
|
|
7387
|
+
lastCommandResult: { success: true, message: `Action ${actionId} executed` }
|
|
7388
|
+
});
|
|
7389
|
+
} catch (error) {
|
|
7390
|
+
updateDeviceState(nodeId, {
|
|
7391
|
+
lastCommandResult: {
|
|
7392
|
+
success: false,
|
|
7393
|
+
message: error instanceof Error ? error.message : "Action failed"
|
|
7394
|
+
}
|
|
7395
|
+
});
|
|
7396
|
+
}
|
|
7397
|
+
},
|
|
7398
|
+
[controls, updateDeviceState]
|
|
7399
|
+
);
|
|
7400
|
+
return {
|
|
7401
|
+
controls,
|
|
7402
|
+
updateControl,
|
|
7403
|
+
updateControlBatch,
|
|
7404
|
+
updateDeviceState,
|
|
7405
|
+
updateParameter,
|
|
7406
|
+
setControlBinding,
|
|
7407
|
+
removeControlBinding,
|
|
7408
|
+
getControlBinding,
|
|
7409
|
+
// Command helpers
|
|
7410
|
+
sendModeChange,
|
|
7411
|
+
sendParameterChange,
|
|
7412
|
+
sendStartCommand,
|
|
7413
|
+
sendStopCommand,
|
|
7414
|
+
sendCustomAction
|
|
7415
|
+
};
|
|
7416
|
+
}
|
|
7417
|
+
|
|
6434
7418
|
// src/diagram/hooks/useSimulation.ts
|
|
6435
|
-
import { useEffect as
|
|
7419
|
+
import { useEffect as useEffect12 } from "react";
|
|
6436
7420
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
6437
7421
|
const {
|
|
6438
7422
|
interval = 2e3,
|
|
@@ -6443,7 +7427,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
6443
7427
|
historyLength = 10,
|
|
6444
7428
|
generateValue
|
|
6445
7429
|
} = options;
|
|
6446
|
-
|
|
7430
|
+
useEffect12(() => {
|
|
6447
7431
|
if (!enabled) return;
|
|
6448
7432
|
const intervalId = setInterval(() => {
|
|
6449
7433
|
const updates = [];
|
|
@@ -6500,6 +7484,7 @@ export {
|
|
|
6500
7484
|
ControlPanel,
|
|
6501
7485
|
DEFAULT_THRESHOLDS,
|
|
6502
7486
|
DashboardCard,
|
|
7487
|
+
DeviceControlPanel,
|
|
6503
7488
|
DisplayModeToggle,
|
|
6504
7489
|
EquipmentIndicator,
|
|
6505
7490
|
EquipmentIndicatorWithSparkline,
|
|
@@ -6511,6 +7496,7 @@ export {
|
|
|
6511
7496
|
LeftToggleButton,
|
|
6512
7497
|
LegacyValueEntry,
|
|
6513
7498
|
NodeConfigPanel,
|
|
7499
|
+
NodeControlsPanel,
|
|
6514
7500
|
PIDCanvas,
|
|
6515
7501
|
PanelContent,
|
|
6516
7502
|
PanelTabs,
|
|
@@ -6530,6 +7516,7 @@ export {
|
|
|
6530
7516
|
ZoomButton,
|
|
6531
7517
|
ZoomControls,
|
|
6532
7518
|
calculateThresholdStatus,
|
|
7519
|
+
createControlBinding,
|
|
6533
7520
|
exampleDiagram,
|
|
6534
7521
|
exportDiagram,
|
|
6535
7522
|
generateRoutePoints,
|
|
@@ -6542,6 +7529,7 @@ export {
|
|
|
6542
7529
|
overlayStyles,
|
|
6543
7530
|
registerSymbol,
|
|
6544
7531
|
registerSymbols,
|
|
7532
|
+
useDeviceControls,
|
|
6545
7533
|
useDrag,
|
|
6546
7534
|
useKeyboardShortcuts,
|
|
6547
7535
|
useSelection,
|