@procaaso/alphinity-ui-components 1.10.0 → 1.12.0
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/IMPLEMENTATION_GUIDE.md +1351 -1351
- package/README.md +98 -95
- package/dist/index.cjs +1317 -691
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +340 -83
- package/dist/index.d.ts +340 -83
- package/dist/index.js +1137 -525
- package/dist/index.js.map +1 -1
- package/package.json +85 -85
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
Button: () => Button,
|
|
34
|
+
COLOR_PRESETS: () => COLOR_PRESETS,
|
|
34
35
|
CardHeader: () => CardHeader,
|
|
35
36
|
CardUnit: () => CardUnit,
|
|
36
37
|
CardValue: () => CardValue,
|
|
@@ -49,6 +50,8 @@ __export(index_exports, {
|
|
|
49
50
|
FooterPanel: () => FooterPanel,
|
|
50
51
|
FullscreenContainer: () => FullscreenContainer,
|
|
51
52
|
FullscreenWorkspace: () => FullscreenWorkspace,
|
|
53
|
+
ISA_UNKNOWN: () => ISA_UNKNOWN,
|
|
54
|
+
ISA_UNKNOWN_DARK: () => ISA_UNKNOWN_DARK,
|
|
52
55
|
LeftPanel: () => LeftPanel,
|
|
53
56
|
LeftToggleButton: () => LeftToggleButton,
|
|
54
57
|
LegacyValueEntry: () => LegacyValueEntry,
|
|
@@ -60,6 +63,7 @@ __export(index_exports, {
|
|
|
60
63
|
PanelTabs: () => PanelTabs,
|
|
61
64
|
RightPanel: () => RightPanel,
|
|
62
65
|
RightToggleButton: () => RightToggleButton,
|
|
66
|
+
STATUS_LED_APPEARANCE: () => STATUS_LED_APPEARANCE,
|
|
63
67
|
SVGArea: () => SVGArea,
|
|
64
68
|
SVGLockedOverlay: () => SVGLockedOverlay,
|
|
65
69
|
ScrollableSVGWrapper: () => ScrollableSVGWrapper,
|
|
@@ -70,6 +74,9 @@ __export(index_exports, {
|
|
|
70
74
|
ThemeProvider: () => ThemeProvider,
|
|
71
75
|
ThemeToggle: () => ThemeToggle,
|
|
72
76
|
TrendLine: () => TrendLine,
|
|
77
|
+
UNKNOWN_GLYPH_RING_DASH: () => UNKNOWN_GLYPH_RING_DASH,
|
|
78
|
+
UNKNOWN_STATUS_GLYPH_COLOR_VAR: () => UNKNOWN_STATUS_GLYPH_COLOR_VAR,
|
|
79
|
+
UnknownStatusGlyph: () => UnknownStatusGlyph,
|
|
73
80
|
ValueEntry: () => ValueEntry,
|
|
74
81
|
ZoomButton: () => ZoomButton,
|
|
75
82
|
ZoomControls: () => ZoomControls,
|
|
@@ -79,16 +86,22 @@ __export(index_exports, {
|
|
|
79
86
|
exampleDiagram: () => exampleDiagram,
|
|
80
87
|
exportDiagram: () => exportDiagram,
|
|
81
88
|
generateRoutePoints: () => generateRoutePoints,
|
|
89
|
+
getAppearanceDefaults: () => getAppearanceDefaults,
|
|
90
|
+
getAppearanceSchema: () => getAppearanceSchema,
|
|
82
91
|
getAvailableSymbols: () => getAvailableSymbols,
|
|
83
92
|
getPortWorldPosition: () => getPortWorldPosition,
|
|
84
93
|
getSymbolDefinition: () => getSymbolDefinition,
|
|
85
94
|
importDiagram: () => importDiagram,
|
|
86
95
|
mockSymbolLibrary: () => mockSymbolLibrary,
|
|
87
96
|
nodeHasPort: () => nodeHasPort,
|
|
97
|
+
normalizeDeviceStatus: () => normalizeDeviceStatus,
|
|
88
98
|
overlayStyles: () => overlayStyles,
|
|
99
|
+
readAppearanceValue: () => readAppearanceValue,
|
|
89
100
|
registerSymbol: () => registerSymbol,
|
|
90
101
|
registerSymbols: () => registerSymbols,
|
|
102
|
+
resolvePresetColor: () => resolvePresetColor,
|
|
91
103
|
resolveStatusColor: () => resolveStatusColor,
|
|
104
|
+
useBooleanIndicators: () => useBooleanIndicators,
|
|
92
105
|
useDeviceConfigs: () => useDeviceConfigs,
|
|
93
106
|
useDeviceControls: () => useDeviceControls,
|
|
94
107
|
useDrag: () => useDrag,
|
|
@@ -99,7 +112,8 @@ __export(index_exports, {
|
|
|
99
112
|
useTelemetryStatus: () => useTelemetryStatus,
|
|
100
113
|
useTheme: () => useTheme,
|
|
101
114
|
useViewBox: () => useViewBox,
|
|
102
|
-
validateDiagram: () => validateDiagram
|
|
115
|
+
validateDiagram: () => validateDiagram,
|
|
116
|
+
writeAppearanceValue: () => writeAppearanceValue
|
|
103
117
|
});
|
|
104
118
|
module.exports = __toCommonJS(index_exports);
|
|
105
119
|
|
|
@@ -372,6 +386,16 @@ var ValueEntry = ({
|
|
|
372
386
|
var import_react3 = require("react");
|
|
373
387
|
|
|
374
388
|
// src/theme/statusColors.ts
|
|
389
|
+
var ISA_UNKNOWN = {
|
|
390
|
+
fg: "#4f4f8a",
|
|
391
|
+
bg: "#ebebf5",
|
|
392
|
+
border: "#8f8fc2"
|
|
393
|
+
};
|
|
394
|
+
var ISA_UNKNOWN_DARK = {
|
|
395
|
+
fg: "#b9bbdb",
|
|
396
|
+
bg: "#23263a",
|
|
397
|
+
border: "#6f74a3"
|
|
398
|
+
};
|
|
375
399
|
var DEFAULT_STATUS_COLORS = {
|
|
376
400
|
normal: { fill: "#888888", stroke: "#6b6b6b", bg: "#888888", text: "#ffffff", border: "#6b6b6b" },
|
|
377
401
|
warning: { fill: "#f59e0b", stroke: "#d97706", bg: "#FFD700", text: "#000000", border: "#d97706" },
|
|
@@ -379,7 +403,8 @@ var DEFAULT_STATUS_COLORS = {
|
|
|
379
403
|
fault: { fill: "#dc2626", stroke: "#b91c1c", bg: "#FF0000", text: "#ffffff", border: "#b91c1c" },
|
|
380
404
|
off: { fill: "#edeeef", stroke: "#000000", bg: "#666666", text: "#ffffff", border: "#4b5563" },
|
|
381
405
|
starting: { fill: "#90EE90", stroke: "#22c55e", bg: "#90EE90", text: "#000000", border: "#22c55e" },
|
|
382
|
-
stopping: { fill: "#FFD700", stroke: "#d97706", bg: "#FFD700", text: "#000000", border: "#d97706" }
|
|
406
|
+
stopping: { fill: "#FFD700", stroke: "#d97706", bg: "#FFD700", text: "#000000", border: "#d97706" },
|
|
407
|
+
unknown: { fill: ISA_UNKNOWN.bg, stroke: ISA_UNKNOWN.border, bg: ISA_UNKNOWN.bg, text: ISA_UNKNOWN.fg, border: ISA_UNKNOWN.border }
|
|
383
408
|
};
|
|
384
409
|
var FORCED_MARK_COLOR = {
|
|
385
410
|
fill: "#ede9fe",
|
|
@@ -392,9 +417,12 @@ var STATUS_ALIASES = {
|
|
|
392
417
|
running: "normal",
|
|
393
418
|
stopped: "off"
|
|
394
419
|
};
|
|
395
|
-
function
|
|
420
|
+
function normalizeDeviceStatus(status) {
|
|
396
421
|
const raw = (status || "off").toLowerCase();
|
|
397
|
-
|
|
422
|
+
return STATUS_ALIASES[raw] ?? raw;
|
|
423
|
+
}
|
|
424
|
+
function resolveStatusColor(status, customMap) {
|
|
425
|
+
const key = normalizeDeviceStatus(status);
|
|
398
426
|
const defaults = DEFAULT_STATUS_COLORS[key] ?? DEFAULT_STATUS_COLORS.off;
|
|
399
427
|
const overrides = customMap?.[key];
|
|
400
428
|
if (!overrides) return defaults;
|
|
@@ -834,7 +862,79 @@ var ControlPanel = ({
|
|
|
834
862
|
};
|
|
835
863
|
|
|
836
864
|
// src/components/StatusIndicator/StatusIndicator.tsx
|
|
865
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
866
|
+
|
|
867
|
+
// src/theme/unknownStatusGlyph.tsx
|
|
837
868
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
869
|
+
var UNKNOWN_STATUS_GLYPH_COLOR_VAR = "--ui-status-indicator-unknown-glyph-color";
|
|
870
|
+
var UNKNOWN_GLYPH_STROKE_WEIGHTS = {
|
|
871
|
+
small: { ring: 4.5, ringDash: "7 6", mark: 5, dot: 2.9 },
|
|
872
|
+
medium: { ring: 4, ringDash: "6.5 5.5", mark: 4.5, dot: 2.7 },
|
|
873
|
+
large: { ring: 3.5, ringDash: "6.5 5.5", mark: 4, dot: 2.5 }
|
|
874
|
+
};
|
|
875
|
+
var UNKNOWN_GLYPH_RING_DASH = UNKNOWN_GLYPH_STROKE_WEIGHTS.medium.ringDash;
|
|
876
|
+
var UNKNOWN_GLYPH_FILL_STYLE = {
|
|
877
|
+
position: "absolute",
|
|
878
|
+
inset: 0,
|
|
879
|
+
width: "100%",
|
|
880
|
+
height: "100%"
|
|
881
|
+
};
|
|
882
|
+
function unknownGlyphHostStyle(isUnknown, style) {
|
|
883
|
+
return isUnknown ? { position: "relative", ...style } : style;
|
|
884
|
+
}
|
|
885
|
+
function UnknownStatusGlyph({
|
|
886
|
+
size = "medium",
|
|
887
|
+
counterRotate = false,
|
|
888
|
+
style,
|
|
889
|
+
...rest
|
|
890
|
+
}) {
|
|
891
|
+
const weights = UNKNOWN_GLYPH_STROKE_WEIGHTS[size];
|
|
892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
893
|
+
"svg",
|
|
894
|
+
{
|
|
895
|
+
viewBox: "0 0 48 48",
|
|
896
|
+
"aria-hidden": "true",
|
|
897
|
+
focusable: "false",
|
|
898
|
+
style: {
|
|
899
|
+
display: "block",
|
|
900
|
+
color: `var(${UNKNOWN_STATUS_GLYPH_COLOR_VAR}, currentColor)`,
|
|
901
|
+
transform: counterRotate ? "rotate(-45deg)" : void 0,
|
|
902
|
+
...style
|
|
903
|
+
},
|
|
904
|
+
...rest,
|
|
905
|
+
children: [
|
|
906
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
907
|
+
"circle",
|
|
908
|
+
{
|
|
909
|
+
cx: 24,
|
|
910
|
+
cy: 24,
|
|
911
|
+
r: 20,
|
|
912
|
+
fill: "none",
|
|
913
|
+
stroke: "currentColor",
|
|
914
|
+
strokeDasharray: weights.ringDash,
|
|
915
|
+
strokeLinecap: "round",
|
|
916
|
+
strokeWidth: weights.ring
|
|
917
|
+
}
|
|
918
|
+
),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
920
|
+
"path",
|
|
921
|
+
{
|
|
922
|
+
d: "M18.4 18.6a5.8 5.8 0 1 1 6.4 8.1v3.1",
|
|
923
|
+
fill: "none",
|
|
924
|
+
stroke: "currentColor",
|
|
925
|
+
strokeLinecap: "round",
|
|
926
|
+
strokeLinejoin: "round",
|
|
927
|
+
strokeWidth: weights.mark
|
|
928
|
+
}
|
|
929
|
+
),
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: 24.6, cy: 35.4, r: weights.dot, fill: "currentColor" })
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// src/components/StatusIndicator/StatusIndicator.tsx
|
|
937
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
838
938
|
var getStatusDescription = (status) => {
|
|
839
939
|
switch (status) {
|
|
840
940
|
case "alarm":
|
|
@@ -849,10 +949,23 @@ var getStatusDescription = (status) => {
|
|
|
849
949
|
return "Operating normally";
|
|
850
950
|
case "off":
|
|
851
951
|
return "Equipment is off";
|
|
952
|
+
case "unknown":
|
|
953
|
+
return "Device state cannot be confirmed. Check the link or the wiring.";
|
|
852
954
|
default:
|
|
853
955
|
return "";
|
|
854
956
|
}
|
|
855
957
|
};
|
|
958
|
+
var visuallyHiddenStyle = {
|
|
959
|
+
position: "absolute",
|
|
960
|
+
width: "1px",
|
|
961
|
+
height: "1px",
|
|
962
|
+
padding: 0,
|
|
963
|
+
margin: "-1px",
|
|
964
|
+
overflow: "hidden",
|
|
965
|
+
clip: "rect(0, 0, 0, 0)",
|
|
966
|
+
whiteSpace: "nowrap",
|
|
967
|
+
border: 0
|
|
968
|
+
};
|
|
856
969
|
var StatusIndicator = ({
|
|
857
970
|
status,
|
|
858
971
|
size = "medium",
|
|
@@ -861,17 +974,29 @@ var StatusIndicator = ({
|
|
|
861
974
|
labelPosition = "right",
|
|
862
975
|
shape = "circle",
|
|
863
976
|
led = true,
|
|
977
|
+
visible = true,
|
|
864
978
|
forced = false,
|
|
865
979
|
realValue,
|
|
866
980
|
className = "",
|
|
981
|
+
style,
|
|
982
|
+
"aria-describedby": consumerDescribedBy,
|
|
983
|
+
children,
|
|
867
984
|
...props
|
|
868
985
|
}) => {
|
|
986
|
+
const generatedDescriptionId = `${import_react5.default.useId()}-status-description`;
|
|
987
|
+
if (!visible) {
|
|
988
|
+
return null;
|
|
989
|
+
}
|
|
990
|
+
const describedBy = consumerDescribedBy ? `${consumerDescribedBy} ${generatedDescriptionId}` : generatedDescriptionId;
|
|
991
|
+
const description = getStatusDescription(status);
|
|
869
992
|
const baseClass = "ui-status-indicator";
|
|
870
993
|
const statusClass = status ? `ui-status-indicator--${status}` : "";
|
|
871
994
|
const sizeClass = size ? `ui-status-indicator--${size}` : "";
|
|
872
995
|
const shapeClass = shape ? `ui-status-indicator--${shape}` : "";
|
|
873
996
|
const animationClass = animation ? `ui-status-indicator--${animation}` : "";
|
|
874
997
|
const ledClass = led ? "ui-status-indicator--led" : "";
|
|
998
|
+
const isUnknown = status === "unknown";
|
|
999
|
+
const indicatorStyle = unknownGlyphHostStyle(isUnknown, style);
|
|
875
1000
|
const getContainerLayout = () => {
|
|
876
1001
|
switch (labelPosition) {
|
|
877
1002
|
case "left":
|
|
@@ -888,19 +1013,20 @@ var StatusIndicator = ({
|
|
|
888
1013
|
};
|
|
889
1014
|
const forcedClass = forced ? "ui-status-indicator--forced" : "";
|
|
890
1015
|
const hasRealValue = forced && realValue !== void 0;
|
|
891
|
-
return /* @__PURE__ */ (0,
|
|
892
|
-
label && (labelPosition === "left" || labelPosition === "top") && /* @__PURE__ */ (0,
|
|
893
|
-
hasRealValue && (labelPosition === "left" || labelPosition === "top") && /* @__PURE__ */ (0,
|
|
1016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: getContainerLayout(), children: [
|
|
1017
|
+
label && (labelPosition === "left" || labelPosition === "top") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ui-status-indicator-label", children: label }),
|
|
1018
|
+
hasRealValue && (labelPosition === "left" || labelPosition === "top") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ui-status-indicator-real-value", children: [
|
|
894
1019
|
"REAL ",
|
|
895
1020
|
realValue
|
|
896
1021
|
] }),
|
|
897
|
-
/* @__PURE__ */ (0,
|
|
898
|
-
/* @__PURE__ */ (0,
|
|
1022
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
899
1024
|
"span",
|
|
900
1025
|
{
|
|
901
1026
|
role: "status",
|
|
902
1027
|
"aria-label": label || `Status: ${status}`,
|
|
903
|
-
"aria-description":
|
|
1028
|
+
"aria-description": description,
|
|
1029
|
+
"aria-describedby": describedBy,
|
|
904
1030
|
"data-status": status,
|
|
905
1031
|
"data-forced": forced,
|
|
906
1032
|
className: `
|
|
@@ -913,13 +1039,26 @@ var StatusIndicator = ({
|
|
|
913
1039
|
${forcedClass}
|
|
914
1040
|
${className}
|
|
915
1041
|
`.replace(/\s+/g, " ").trim(),
|
|
916
|
-
|
|
1042
|
+
style: indicatorStyle,
|
|
1043
|
+
...props,
|
|
1044
|
+
children: [
|
|
1045
|
+
isUnknown && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1046
|
+
UnknownStatusGlyph,
|
|
1047
|
+
{
|
|
1048
|
+
size,
|
|
1049
|
+
counterRotate: shape === "diamond",
|
|
1050
|
+
style: UNKNOWN_GLYPH_FILL_STYLE
|
|
1051
|
+
}
|
|
1052
|
+
),
|
|
1053
|
+
children,
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { id: generatedDescriptionId, style: visuallyHiddenStyle, children: description })
|
|
1055
|
+
]
|
|
917
1056
|
}
|
|
918
1057
|
),
|
|
919
|
-
forced && /* @__PURE__ */ (0,
|
|
1058
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ui-status-indicator-forced-badge", "aria-label": "Forced", children: "F" })
|
|
920
1059
|
] }),
|
|
921
|
-
label && (labelPosition === "right" || labelPosition === "bottom") && /* @__PURE__ */ (0,
|
|
922
|
-
hasRealValue && (labelPosition === "right" || labelPosition === "bottom") && /* @__PURE__ */ (0,
|
|
1060
|
+
label && (labelPosition === "right" || labelPosition === "bottom") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ui-status-indicator-label", children: label }),
|
|
1061
|
+
hasRealValue && (labelPosition === "right" || labelPosition === "bottom") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ui-status-indicator-real-value", children: [
|
|
923
1062
|
"REAL ",
|
|
924
1063
|
realValue
|
|
925
1064
|
] })
|
|
@@ -927,7 +1066,7 @@ var StatusIndicator = ({
|
|
|
927
1066
|
};
|
|
928
1067
|
|
|
929
1068
|
// src/components/NodeControlsPanel/NodeControlsPanel.tsx
|
|
930
|
-
var
|
|
1069
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
931
1070
|
var NodeControlsPanel = ({
|
|
932
1071
|
config,
|
|
933
1072
|
onClose,
|
|
@@ -1000,8 +1139,8 @@ var NodeControlsPanel = ({
|
|
|
1000
1139
|
overflowY: "auto",
|
|
1001
1140
|
flex: 1
|
|
1002
1141
|
};
|
|
1003
|
-
return /* @__PURE__ */ (0,
|
|
1004
|
-
/* @__PURE__ */ (0,
|
|
1142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1143
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1005
1144
|
"div",
|
|
1006
1145
|
{
|
|
1007
1146
|
style: {
|
|
@@ -1014,16 +1153,16 @@ var NodeControlsPanel = ({
|
|
|
1014
1153
|
onClick: onClose
|
|
1015
1154
|
}
|
|
1016
1155
|
),
|
|
1017
|
-
/* @__PURE__ */ (0,
|
|
1156
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1018
1157
|
"div",
|
|
1019
1158
|
{
|
|
1020
1159
|
className: `node-controls-panel ${touchClass} ${className}`.trim(),
|
|
1021
1160
|
style: containerStyle,
|
|
1022
1161
|
...props,
|
|
1023
1162
|
children: [
|
|
1024
|
-
/* @__PURE__ */ (0,
|
|
1025
|
-
/* @__PURE__ */ (0,
|
|
1026
|
-
/* @__PURE__ */ (0,
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: headerStyle, children: [
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: titleStyle, children: config.title }),
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1027
1166
|
"button",
|
|
1028
1167
|
{
|
|
1029
1168
|
style: closeButtonStyle,
|
|
@@ -1041,7 +1180,7 @@ var NodeControlsPanel = ({
|
|
|
1041
1180
|
}
|
|
1042
1181
|
)
|
|
1043
1182
|
] }),
|
|
1044
|
-
/* @__PURE__ */ (0,
|
|
1183
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: contentStyle, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1045
1184
|
ControlPanel,
|
|
1046
1185
|
{
|
|
1047
1186
|
title: config.nodeId,
|
|
@@ -1070,7 +1209,7 @@ var NodeControlsPanel = ({
|
|
|
1070
1209
|
]
|
|
1071
1210
|
}
|
|
1072
1211
|
),
|
|
1073
|
-
/* @__PURE__ */ (0,
|
|
1212
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
|
|
1074
1213
|
@keyframes slideUp {
|
|
1075
1214
|
from {
|
|
1076
1215
|
transform: translateY(100%);
|
|
@@ -1116,8 +1255,8 @@ var NodeControlsPanel = ({
|
|
|
1116
1255
|
};
|
|
1117
1256
|
|
|
1118
1257
|
// src/components/DeviceControlPanel/DeviceControlPanel.tsx
|
|
1119
|
-
var
|
|
1120
|
-
var
|
|
1258
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
1259
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1121
1260
|
function DeviceControlPanelImpl({
|
|
1122
1261
|
binding,
|
|
1123
1262
|
onClose,
|
|
@@ -1145,11 +1284,11 @@ function DeviceControlPanelImpl({
|
|
|
1145
1284
|
showBuiltInToast = true,
|
|
1146
1285
|
embedded = false
|
|
1147
1286
|
}) {
|
|
1148
|
-
const [localParameterValues, setLocalParameterValues] = (0,
|
|
1149
|
-
const [showModeModal, setShowModeModal] = (0,
|
|
1150
|
-
const [pendingMode, setPendingMode] = (0,
|
|
1151
|
-
const [showToast, setShowToast] = (0,
|
|
1152
|
-
(0,
|
|
1287
|
+
const [localParameterValues, setLocalParameterValues] = (0, import_react6.useState)({});
|
|
1288
|
+
const [showModeModal, setShowModeModal] = (0, import_react6.useState)(false);
|
|
1289
|
+
const [pendingMode, setPendingMode] = (0, import_react6.useState)(null);
|
|
1290
|
+
const [showToast, setShowToast] = (0, import_react6.useState)(true);
|
|
1291
|
+
(0, import_react6.useEffect)(() => {
|
|
1153
1292
|
if (binding) {
|
|
1154
1293
|
const currentParams2 = binding.parameters[binding.state.currentMode] || [];
|
|
1155
1294
|
const values = {};
|
|
@@ -1159,7 +1298,7 @@ function DeviceControlPanelImpl({
|
|
|
1159
1298
|
setLocalParameterValues(values);
|
|
1160
1299
|
}
|
|
1161
1300
|
}, [binding, binding?.state.currentMode]);
|
|
1162
|
-
(0,
|
|
1301
|
+
(0, import_react6.useEffect)(() => {
|
|
1163
1302
|
if (binding?.state.lastCommandResult) {
|
|
1164
1303
|
setShowToast(true);
|
|
1165
1304
|
const timer = setTimeout(() => {
|
|
@@ -1197,6 +1336,7 @@ function DeviceControlPanelImpl({
|
|
|
1197
1336
|
const selectedColor = "#b4d0fe";
|
|
1198
1337
|
const statusEntry = resolveStatusColor(binding.state.status, binding.theme?.statusColors);
|
|
1199
1338
|
const statusColor = statusEntry.bg;
|
|
1339
|
+
const isUnknownStatus = normalizeDeviceStatus(binding.state.status) === "unknown";
|
|
1200
1340
|
const handleModeChange = (mode) => {
|
|
1201
1341
|
onModeChange?.(mode);
|
|
1202
1342
|
};
|
|
@@ -1251,9 +1391,9 @@ function DeviceControlPanelImpl({
|
|
|
1251
1391
|
...binding.display?.style
|
|
1252
1392
|
};
|
|
1253
1393
|
const titleText = binding.display?.title || binding.deviceName || binding.tag || binding.nodeId;
|
|
1254
|
-
return /* @__PURE__ */ (0,
|
|
1255
|
-
/* @__PURE__ */ (0,
|
|
1256
|
-
/* @__PURE__ */ (0,
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
|
|
1396
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1257
1397
|
"div",
|
|
1258
1398
|
{
|
|
1259
1399
|
style: {
|
|
@@ -1265,8 +1405,8 @@ function DeviceControlPanelImpl({
|
|
|
1265
1405
|
borderBottom: `2px solid ${borderColor}`
|
|
1266
1406
|
},
|
|
1267
1407
|
children: [
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1270
1410
|
"h3",
|
|
1271
1411
|
{
|
|
1272
1412
|
style: {
|
|
@@ -1286,7 +1426,7 @@ function DeviceControlPanelImpl({
|
|
|
1286
1426
|
children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
|
|
1287
1427
|
}
|
|
1288
1428
|
),
|
|
1289
|
-
binding.deviceType && /* @__PURE__ */ (0,
|
|
1429
|
+
binding.deviceType && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1290
1430
|
"div",
|
|
1291
1431
|
{
|
|
1292
1432
|
style: {
|
|
@@ -1299,8 +1439,8 @@ function DeviceControlPanelImpl({
|
|
|
1299
1439
|
}
|
|
1300
1440
|
)
|
|
1301
1441
|
] }),
|
|
1302
|
-
/* @__PURE__ */ (0,
|
|
1303
|
-
showConfigButton && onOpenConfig && /* @__PURE__ */ (0,
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
1443
|
+
showConfigButton && onOpenConfig && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1304
1444
|
"button",
|
|
1305
1445
|
{
|
|
1306
1446
|
onClick: onOpenConfig,
|
|
@@ -1321,7 +1461,7 @@ function DeviceControlPanelImpl({
|
|
|
1321
1461
|
children: "\u2699"
|
|
1322
1462
|
}
|
|
1323
1463
|
),
|
|
1324
|
-
onUndock && /* @__PURE__ */ (0,
|
|
1464
|
+
onUndock && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1325
1465
|
"button",
|
|
1326
1466
|
{
|
|
1327
1467
|
onClick: onUndock,
|
|
@@ -1342,7 +1482,7 @@ function DeviceControlPanelImpl({
|
|
|
1342
1482
|
children: undockIcon
|
|
1343
1483
|
}
|
|
1344
1484
|
),
|
|
1345
|
-
/* @__PURE__ */ (0,
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1346
1486
|
"button",
|
|
1347
1487
|
{
|
|
1348
1488
|
onClick: onClose,
|
|
@@ -1365,7 +1505,7 @@ function DeviceControlPanelImpl({
|
|
|
1365
1505
|
]
|
|
1366
1506
|
}
|
|
1367
1507
|
),
|
|
1368
|
-
binding.state.status && /* @__PURE__ */ (0,
|
|
1508
|
+
binding.state.status && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1369
1509
|
"div",
|
|
1370
1510
|
{
|
|
1371
1511
|
style: {
|
|
@@ -1379,7 +1519,7 @@ function DeviceControlPanelImpl({
|
|
|
1379
1519
|
marginBottom: spacing.marginBottom
|
|
1380
1520
|
},
|
|
1381
1521
|
children: [
|
|
1382
|
-
/* @__PURE__ */ (0,
|
|
1522
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1383
1523
|
"div",
|
|
1384
1524
|
{
|
|
1385
1525
|
style: {
|
|
@@ -1387,12 +1527,17 @@ function DeviceControlPanelImpl({
|
|
|
1387
1527
|
height: "10px",
|
|
1388
1528
|
borderRadius: "50%",
|
|
1389
1529
|
backgroundColor: statusColor,
|
|
1390
|
-
border: "1px solid #333"
|
|
1391
|
-
|
|
1530
|
+
border: "1px solid #333",
|
|
1531
|
+
// The shared helper positions this dot only while it shows
|
|
1532
|
+
// the unknown marker. The glyph then fills the dot with an
|
|
1533
|
+
// absolute inset, the same pattern StatusIndicator uses.
|
|
1534
|
+
...unknownGlyphHostStyle(isUnknownStatus)
|
|
1535
|
+
},
|
|
1536
|
+
children: isUnknownStatus && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UnknownStatusGlyph, { size: "small", style: UNKNOWN_GLYPH_FILL_STYLE })
|
|
1392
1537
|
}
|
|
1393
1538
|
),
|
|
1394
|
-
/* @__PURE__ */ (0,
|
|
1395
|
-
/* @__PURE__ */ (0,
|
|
1539
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1 }, children: [
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1396
1541
|
"div",
|
|
1397
1542
|
{
|
|
1398
1543
|
style: {
|
|
@@ -1406,7 +1551,7 @@ function DeviceControlPanelImpl({
|
|
|
1406
1551
|
children: binding.state.status
|
|
1407
1552
|
}
|
|
1408
1553
|
),
|
|
1409
|
-
binding.state.statusMessage && /* @__PURE__ */ (0,
|
|
1554
|
+
binding.state.statusMessage && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1410
1555
|
"div",
|
|
1411
1556
|
{
|
|
1412
1557
|
style: {
|
|
@@ -1419,28 +1564,36 @@ function DeviceControlPanelImpl({
|
|
|
1419
1564
|
}
|
|
1420
1565
|
)
|
|
1421
1566
|
] }),
|
|
1422
|
-
binding.state.isRunning !== void 0 && /* @__PURE__ */ (0,
|
|
1567
|
+
binding.state.isRunning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1423
1568
|
"div",
|
|
1424
1569
|
{
|
|
1425
1570
|
style: {
|
|
1426
1571
|
padding: "4px 10px",
|
|
1427
|
-
|
|
1428
|
-
|
|
1572
|
+
// This badge shows the last published isRunning value. It
|
|
1573
|
+
// never re-derives that value here. When status is
|
|
1574
|
+
// unknown, the value may be stale. Muted colors carry that
|
|
1575
|
+
// warning alongside the word, so color is not the only
|
|
1576
|
+
// channel and the wording is not the only channel either.
|
|
1577
|
+
backgroundColor: isUnknownStatus ? statusEntry.bg : binding.state.isRunning ? selectedColor : surfaceColor,
|
|
1578
|
+
border: `1px solid ${isUnknownStatus ? statusEntry.border : borderColor}`,
|
|
1429
1579
|
borderRadius: "2px",
|
|
1430
1580
|
fontSize: "10px",
|
|
1431
1581
|
fontWeight: 600,
|
|
1432
1582
|
fontFamily: "Arial, sans-serif",
|
|
1433
1583
|
letterSpacing: "0.5px",
|
|
1434
|
-
color: textColor
|
|
1584
|
+
color: isUnknownStatus ? statusEntry.text : textColor
|
|
1435
1585
|
},
|
|
1436
|
-
children:
|
|
1586
|
+
children: [
|
|
1587
|
+
binding.state.isRunning ? "RUNNING" : "STOPPED",
|
|
1588
|
+
isUnknownStatus && " (unconfirmed)"
|
|
1589
|
+
]
|
|
1437
1590
|
}
|
|
1438
1591
|
)
|
|
1439
1592
|
]
|
|
1440
1593
|
}
|
|
1441
1594
|
),
|
|
1442
|
-
binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ (0,
|
|
1443
|
-
/* @__PURE__ */ (0,
|
|
1595
|
+
binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { marginBottom: "16px" }, children: [
|
|
1596
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1444
1597
|
"label",
|
|
1445
1598
|
{
|
|
1446
1599
|
style: {
|
|
@@ -1456,7 +1609,7 @@ function DeviceControlPanelImpl({
|
|
|
1456
1609
|
children: "Mode"
|
|
1457
1610
|
}
|
|
1458
1611
|
),
|
|
1459
|
-
modeSelectionStyle === "dropdown" ? /* @__PURE__ */ (0,
|
|
1612
|
+
modeSelectionStyle === "dropdown" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1460
1613
|
"select",
|
|
1461
1614
|
{
|
|
1462
1615
|
value: currentMode,
|
|
@@ -1477,10 +1630,10 @@ function DeviceControlPanelImpl({
|
|
|
1477
1630
|
paddingRight: "12px",
|
|
1478
1631
|
cursor: "pointer"
|
|
1479
1632
|
},
|
|
1480
|
-
children: binding.modes.map((mode) => /* @__PURE__ */ (0,
|
|
1633
|
+
children: binding.modes.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: mode.value, disabled: mode.enabled === false, children: mode.label }, mode.value))
|
|
1481
1634
|
}
|
|
1482
|
-
) : modeSelectionStyle === "modal" ? /* @__PURE__ */ (0,
|
|
1483
|
-
/* @__PURE__ */ (0,
|
|
1635
|
+
) : modeSelectionStyle === "modal" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1636
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1484
1637
|
"div",
|
|
1485
1638
|
{
|
|
1486
1639
|
onClick: () => {
|
|
@@ -1503,12 +1656,12 @@ function DeviceControlPanelImpl({
|
|
|
1503
1656
|
alignItems: "center"
|
|
1504
1657
|
},
|
|
1505
1658
|
children: [
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1507
|
-
/* @__PURE__ */ (0,
|
|
1659
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: binding.modes.find((m) => m.value === currentMode)?.label || currentMode }),
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "20px", marginLeft: "8px" }, children: "\u25BC" })
|
|
1508
1661
|
]
|
|
1509
1662
|
}
|
|
1510
1663
|
),
|
|
1511
|
-
showModeModal && /* @__PURE__ */ (0,
|
|
1664
|
+
showModeModal && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1512
1665
|
"div",
|
|
1513
1666
|
{
|
|
1514
1667
|
style: {
|
|
@@ -1527,7 +1680,7 @@ function DeviceControlPanelImpl({
|
|
|
1527
1680
|
setShowModeModal(false);
|
|
1528
1681
|
setPendingMode(null);
|
|
1529
1682
|
},
|
|
1530
|
-
children: /* @__PURE__ */ (0,
|
|
1683
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1531
1684
|
"div",
|
|
1532
1685
|
{
|
|
1533
1686
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -1540,7 +1693,7 @@ function DeviceControlPanelImpl({
|
|
|
1540
1693
|
border: `2px solid ${borderColor}`
|
|
1541
1694
|
},
|
|
1542
1695
|
children: [
|
|
1543
|
-
/* @__PURE__ */ (0,
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1544
1697
|
"h3",
|
|
1545
1698
|
{
|
|
1546
1699
|
style: {
|
|
@@ -1553,7 +1706,7 @@ function DeviceControlPanelImpl({
|
|
|
1553
1706
|
children: "Select Mode"
|
|
1554
1707
|
}
|
|
1555
1708
|
),
|
|
1556
|
-
/* @__PURE__ */ (0,
|
|
1709
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1557
1710
|
"div",
|
|
1558
1711
|
{
|
|
1559
1712
|
style: {
|
|
@@ -1567,7 +1720,7 @@ function DeviceControlPanelImpl({
|
|
|
1567
1720
|
children: binding.display?.title || binding.deviceName || binding.tag || binding.nodeId
|
|
1568
1721
|
}
|
|
1569
1722
|
),
|
|
1570
|
-
/* @__PURE__ */ (0,
|
|
1723
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1571
1724
|
"select",
|
|
1572
1725
|
{
|
|
1573
1726
|
value: pendingMode || currentMode,
|
|
@@ -1589,7 +1742,7 @@ function DeviceControlPanelImpl({
|
|
|
1589
1742
|
paddingRight: "12px",
|
|
1590
1743
|
cursor: "pointer"
|
|
1591
1744
|
},
|
|
1592
|
-
children: binding.modes.map((mode) => /* @__PURE__ */ (0,
|
|
1745
|
+
children: binding.modes.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1593
1746
|
"option",
|
|
1594
1747
|
{
|
|
1595
1748
|
value: mode.value,
|
|
@@ -1604,7 +1757,7 @@ function DeviceControlPanelImpl({
|
|
|
1604
1757
|
const selectedMode = binding.modes.find(
|
|
1605
1758
|
(m) => m.value === (pendingMode || currentMode)
|
|
1606
1759
|
);
|
|
1607
|
-
return selectedMode?.description ? /* @__PURE__ */ (0,
|
|
1760
|
+
return selectedMode?.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1608
1761
|
"div",
|
|
1609
1762
|
{
|
|
1610
1763
|
style: {
|
|
@@ -1622,8 +1775,8 @@ function DeviceControlPanelImpl({
|
|
|
1622
1775
|
}
|
|
1623
1776
|
) : null;
|
|
1624
1777
|
})(),
|
|
1625
|
-
/* @__PURE__ */ (0,
|
|
1626
|
-
/* @__PURE__ */ (0,
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "12px" }, children: [
|
|
1779
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1627
1780
|
"button",
|
|
1628
1781
|
{
|
|
1629
1782
|
onClick: () => {
|
|
@@ -1651,7 +1804,7 @@ function DeviceControlPanelImpl({
|
|
|
1651
1804
|
children: "Confirm"
|
|
1652
1805
|
}
|
|
1653
1806
|
),
|
|
1654
|
-
/* @__PURE__ */ (0,
|
|
1807
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1655
1808
|
"button",
|
|
1656
1809
|
{
|
|
1657
1810
|
onClick: () => {
|
|
@@ -1681,7 +1834,7 @@ function DeviceControlPanelImpl({
|
|
|
1681
1834
|
)
|
|
1682
1835
|
}
|
|
1683
1836
|
)
|
|
1684
|
-
] }) : /* @__PURE__ */ (0,
|
|
1837
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1685
1838
|
"div",
|
|
1686
1839
|
{
|
|
1687
1840
|
style: {
|
|
@@ -1697,7 +1850,7 @@ function DeviceControlPanelImpl({
|
|
|
1697
1850
|
children: binding.modes.map((mode) => {
|
|
1698
1851
|
const isSelected = mode.value === currentMode;
|
|
1699
1852
|
const isEnabled = mode.enabled !== false;
|
|
1700
|
-
return /* @__PURE__ */ (0,
|
|
1853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1701
1854
|
"button",
|
|
1702
1855
|
{
|
|
1703
1856
|
onClick: () => isEnabled && handleModeChange(mode.value),
|
|
@@ -1727,8 +1880,8 @@ function DeviceControlPanelImpl({
|
|
|
1727
1880
|
}
|
|
1728
1881
|
)
|
|
1729
1882
|
] }),
|
|
1730
|
-
currentParams.length > 0 && /* @__PURE__ */ (0,
|
|
1731
|
-
/* @__PURE__ */ (0,
|
|
1883
|
+
currentParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { marginBottom: spacing.marginBottom }, children: [
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1732
1885
|
"label",
|
|
1733
1886
|
{
|
|
1734
1887
|
style: {
|
|
@@ -1744,7 +1897,7 @@ function DeviceControlPanelImpl({
|
|
|
1744
1897
|
children: "Parameters"
|
|
1745
1898
|
}
|
|
1746
1899
|
),
|
|
1747
|
-
currentParams.map((param) => /* @__PURE__ */ (0,
|
|
1900
|
+
currentParams.map((param) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1748
1901
|
"div",
|
|
1749
1902
|
{
|
|
1750
1903
|
style: {
|
|
@@ -1755,7 +1908,7 @@ function DeviceControlPanelImpl({
|
|
|
1755
1908
|
borderRadius: "6px"
|
|
1756
1909
|
},
|
|
1757
1910
|
children: [
|
|
1758
|
-
/* @__PURE__ */ (0,
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1759
1912
|
"div",
|
|
1760
1913
|
{
|
|
1761
1914
|
style: {
|
|
@@ -1764,7 +1917,7 @@ function DeviceControlPanelImpl({
|
|
|
1764
1917
|
marginBottom: spacing.gap
|
|
1765
1918
|
},
|
|
1766
1919
|
children: [
|
|
1767
|
-
/* @__PURE__ */ (0,
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1768
1921
|
"span",
|
|
1769
1922
|
{
|
|
1770
1923
|
style: {
|
|
@@ -1780,7 +1933,7 @@ function DeviceControlPanelImpl({
|
|
|
1780
1933
|
},
|
|
1781
1934
|
children: [
|
|
1782
1935
|
param.label,
|
|
1783
|
-
param.forced?.active && /* @__PURE__ */ (0,
|
|
1936
|
+
param.forced?.active && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1784
1937
|
"span",
|
|
1785
1938
|
{
|
|
1786
1939
|
"aria-label": "Forced",
|
|
@@ -1803,7 +1956,7 @@ function DeviceControlPanelImpl({
|
|
|
1803
1956
|
]
|
|
1804
1957
|
}
|
|
1805
1958
|
),
|
|
1806
|
-
/* @__PURE__ */ (0,
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1807
1960
|
"span",
|
|
1808
1961
|
{
|
|
1809
1962
|
style: {
|
|
@@ -1815,14 +1968,14 @@ function DeviceControlPanelImpl({
|
|
|
1815
1968
|
children: [
|
|
1816
1969
|
localParameterValues[param.id] ?? param.value,
|
|
1817
1970
|
" ",
|
|
1818
|
-
param.unit && /* @__PURE__ */ (0,
|
|
1971
|
+
param.unit && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: mutedTextColor, fontSize: "10px", fontWeight: 600 }, children: param.unit })
|
|
1819
1972
|
]
|
|
1820
1973
|
}
|
|
1821
1974
|
)
|
|
1822
1975
|
]
|
|
1823
1976
|
}
|
|
1824
1977
|
),
|
|
1825
|
-
param.forced?.active && param.forced.realValue !== void 0 && /* @__PURE__ */ (0,
|
|
1978
|
+
param.forced?.active && param.forced.realValue !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1826
1979
|
"div",
|
|
1827
1980
|
{
|
|
1828
1981
|
style: {
|
|
@@ -1843,7 +1996,7 @@ function DeviceControlPanelImpl({
|
|
|
1843
1996
|
]
|
|
1844
1997
|
}
|
|
1845
1998
|
),
|
|
1846
|
-
param.type === "boolean" ? /* @__PURE__ */ (0,
|
|
1999
|
+
param.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1847
2000
|
"button",
|
|
1848
2001
|
{
|
|
1849
2002
|
onClick: () => {
|
|
@@ -1868,7 +2021,7 @@ function DeviceControlPanelImpl({
|
|
|
1868
2021
|
},
|
|
1869
2022
|
children: localParameterValues[param.id] ? "ON" : "OFF"
|
|
1870
2023
|
}
|
|
1871
|
-
) : param.type === "select" ? /* @__PURE__ */ (0,
|
|
2024
|
+
) : param.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1872
2025
|
"select",
|
|
1873
2026
|
{
|
|
1874
2027
|
value: localParameterValues[param.id] || param.value,
|
|
@@ -1889,12 +2042,12 @@ function DeviceControlPanelImpl({
|
|
|
1889
2042
|
fontFamily: "monospace",
|
|
1890
2043
|
cursor: "pointer"
|
|
1891
2044
|
},
|
|
1892
|
-
children: param.options?.map((opt) => /* @__PURE__ */ (0,
|
|
2045
|
+
children: param.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1893
2046
|
}
|
|
1894
2047
|
) : onParameterActivate && !param.readOnly ? (
|
|
1895
2048
|
// Tappable value: defer editing to the consumer's editor (e.g. a
|
|
1896
2049
|
// numpad dialog). Commit happens via onParameterChange.
|
|
1897
|
-
/* @__PURE__ */ (0,
|
|
2050
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1898
2051
|
"button",
|
|
1899
2052
|
{
|
|
1900
2053
|
type: "button",
|
|
@@ -1921,7 +2074,7 @@ function DeviceControlPanelImpl({
|
|
|
1921
2074
|
]
|
|
1922
2075
|
}
|
|
1923
2076
|
)
|
|
1924
|
-
) : /* @__PURE__ */ (0,
|
|
2077
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1925
2078
|
"input",
|
|
1926
2079
|
{
|
|
1927
2080
|
type: param.type === "number" ? "number" : "text",
|
|
@@ -1954,8 +2107,8 @@ function DeviceControlPanelImpl({
|
|
|
1954
2107
|
param.id
|
|
1955
2108
|
))
|
|
1956
2109
|
] }),
|
|
1957
|
-
binding.display?.showStartStop !== false && (activeCapabilities?.canStart || activeCapabilities?.canStop) && /* @__PURE__ */ (0,
|
|
1958
|
-
activeCapabilities?.canStart && /* @__PURE__ */ (0,
|
|
2110
|
+
binding.display?.showStartStop !== false && (activeCapabilities?.canStart || activeCapabilities?.canStop) && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: spacing.gap, marginBottom: spacing.marginBottom }, children: [
|
|
2111
|
+
activeCapabilities?.canStart && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1959
2112
|
"button",
|
|
1960
2113
|
{
|
|
1961
2114
|
onClick: onStart,
|
|
@@ -1976,7 +2129,7 @@ function DeviceControlPanelImpl({
|
|
|
1976
2129
|
children: startPending ? "STARTING\u2026" : "START"
|
|
1977
2130
|
}
|
|
1978
2131
|
),
|
|
1979
|
-
activeCapabilities?.canStop && /* @__PURE__ */ (0,
|
|
2132
|
+
activeCapabilities?.canStop && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1980
2133
|
"button",
|
|
1981
2134
|
{
|
|
1982
2135
|
onClick: onStop,
|
|
@@ -1998,9 +2151,9 @@ function DeviceControlPanelImpl({
|
|
|
1998
2151
|
}
|
|
1999
2152
|
)
|
|
2000
2153
|
] }),
|
|
2001
|
-
activeCapabilities?.customActions && activeCapabilities.customActions.length > 0 && /* @__PURE__ */ (0,
|
|
2154
|
+
activeCapabilities?.customActions && activeCapabilities.customActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: activeCapabilities.customActions.map((action) => {
|
|
2002
2155
|
const actionDisabled = action.disabled === true;
|
|
2003
|
-
return /* @__PURE__ */ (0,
|
|
2156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2004
2157
|
"button",
|
|
2005
2158
|
{
|
|
2006
2159
|
onClick: () => {
|
|
@@ -2026,7 +2179,7 @@ function DeviceControlPanelImpl({
|
|
|
2026
2179
|
transition: "all 0.15s"
|
|
2027
2180
|
},
|
|
2028
2181
|
children: [
|
|
2029
|
-
action.icon && /* @__PURE__ */ (0,
|
|
2182
|
+
action.icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { marginRight: "6px" }, children: action.icon }),
|
|
2030
2183
|
action.label
|
|
2031
2184
|
]
|
|
2032
2185
|
},
|
|
@@ -2034,7 +2187,7 @@ function DeviceControlPanelImpl({
|
|
|
2034
2187
|
);
|
|
2035
2188
|
}) })
|
|
2036
2189
|
] }),
|
|
2037
|
-
binding.state.lastCommandResult && showToast && showBuiltInToast && /* @__PURE__ */ (0,
|
|
2190
|
+
binding.state.lastCommandResult && showToast && showBuiltInToast && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2038
2191
|
"div",
|
|
2039
2192
|
{
|
|
2040
2193
|
style: {
|
|
@@ -2058,7 +2211,7 @@ function DeviceControlPanelImpl({
|
|
|
2058
2211
|
children: binding.state.lastCommandResult.message
|
|
2059
2212
|
}
|
|
2060
2213
|
),
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
|
|
2062
2215
|
@keyframes slideInToast {
|
|
2063
2216
|
from {
|
|
2064
2217
|
opacity: 0;
|
|
@@ -2090,11 +2243,11 @@ function DeviceControlPanelImpl({
|
|
|
2090
2243
|
` })
|
|
2091
2244
|
] });
|
|
2092
2245
|
}
|
|
2093
|
-
var DeviceControlPanel =
|
|
2246
|
+
var DeviceControlPanel = import_react6.default.memo(DeviceControlPanelImpl);
|
|
2094
2247
|
|
|
2095
2248
|
// src/components/NumpadDialog/NumpadDialog.tsx
|
|
2096
|
-
var
|
|
2097
|
-
var
|
|
2249
|
+
var import_react7 = require("react");
|
|
2250
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2098
2251
|
var NumpadDialog = ({
|
|
2099
2252
|
isOpen,
|
|
2100
2253
|
onClose,
|
|
@@ -2108,24 +2261,24 @@ var NumpadDialog = ({
|
|
|
2108
2261
|
currentValue = 0,
|
|
2109
2262
|
touchOptimized = true
|
|
2110
2263
|
}) => {
|
|
2111
|
-
const [inputValue, setInputValue] = (0,
|
|
2112
|
-
const [pristine, setPristine] = (0,
|
|
2113
|
-
const dialogRef = (0,
|
|
2114
|
-
const titleId = (0,
|
|
2264
|
+
const [inputValue, setInputValue] = (0, import_react7.useState)("");
|
|
2265
|
+
const [pristine, setPristine] = (0, import_react7.useState)(true);
|
|
2266
|
+
const dialogRef = (0, import_react7.useRef)(null);
|
|
2267
|
+
const titleId = (0, import_react7.useId)();
|
|
2115
2268
|
const decimals = precision ?? 1;
|
|
2116
|
-
(0,
|
|
2269
|
+
(0, import_react7.useEffect)(() => {
|
|
2117
2270
|
if (isOpen) {
|
|
2118
2271
|
setInputValue(Number(currentValue).toFixed(decimals));
|
|
2119
2272
|
setPristine(true);
|
|
2120
2273
|
}
|
|
2121
2274
|
}, [isOpen, currentValue, decimals]);
|
|
2122
|
-
(0,
|
|
2275
|
+
(0, import_react7.useEffect)(() => {
|
|
2123
2276
|
if (!isOpen) return;
|
|
2124
2277
|
const previouslyFocused = document.activeElement;
|
|
2125
2278
|
dialogRef.current?.focus();
|
|
2126
2279
|
return () => previouslyFocused?.focus?.();
|
|
2127
2280
|
}, [isOpen]);
|
|
2128
|
-
(0,
|
|
2281
|
+
(0, import_react7.useEffect)(() => {
|
|
2129
2282
|
if (!isOpen) return;
|
|
2130
2283
|
const prevOverflow = document.body.style.overflow;
|
|
2131
2284
|
document.body.style.overflow = "hidden";
|
|
@@ -2133,13 +2286,13 @@ var NumpadDialog = ({
|
|
|
2133
2286
|
document.body.style.overflow = prevOverflow;
|
|
2134
2287
|
};
|
|
2135
2288
|
}, [isOpen]);
|
|
2136
|
-
const handleApply = (0,
|
|
2289
|
+
const handleApply = (0, import_react7.useCallback)(() => {
|
|
2137
2290
|
const n = Number(inputValue);
|
|
2138
2291
|
if (inputValue === "" || inputValue === "-" || inputValue === "." || inputValue === "-.") return;
|
|
2139
2292
|
if (isNaN(n) || n < min || n > max) return;
|
|
2140
2293
|
onApply(Number(n.toFixed(decimals)));
|
|
2141
2294
|
}, [inputValue, min, max, onApply, decimals]);
|
|
2142
|
-
const appendDigit = (0,
|
|
2295
|
+
const appendDigit = (0, import_react7.useCallback)(
|
|
2143
2296
|
(digit) => {
|
|
2144
2297
|
setInputValue((prev) => {
|
|
2145
2298
|
const base = pristine ? "" : prev;
|
|
@@ -2159,15 +2312,15 @@ var NumpadDialog = ({
|
|
|
2159
2312
|
},
|
|
2160
2313
|
[pristine, decimals]
|
|
2161
2314
|
);
|
|
2162
|
-
const handleBackspace = (0,
|
|
2315
|
+
const handleBackspace = (0, import_react7.useCallback)(() => {
|
|
2163
2316
|
setPristine(false);
|
|
2164
2317
|
setInputValue((prev) => prev.slice(0, -1));
|
|
2165
2318
|
}, []);
|
|
2166
|
-
const handleClear = (0,
|
|
2319
|
+
const handleClear = (0, import_react7.useCallback)(() => {
|
|
2167
2320
|
setPristine(false);
|
|
2168
2321
|
setInputValue("");
|
|
2169
2322
|
}, []);
|
|
2170
|
-
const handleToggleSign = (0,
|
|
2323
|
+
const handleToggleSign = (0, import_react7.useCallback)(() => {
|
|
2171
2324
|
if (min >= 0) return;
|
|
2172
2325
|
setPristine(false);
|
|
2173
2326
|
setInputValue((prev) => {
|
|
@@ -2176,8 +2329,8 @@ var NumpadDialog = ({
|
|
|
2176
2329
|
return "-" + prev;
|
|
2177
2330
|
});
|
|
2178
2331
|
}, [min]);
|
|
2179
|
-
const bsTimer = (0,
|
|
2180
|
-
const bsLongFired = (0,
|
|
2332
|
+
const bsTimer = (0, import_react7.useRef)(null);
|
|
2333
|
+
const bsLongFired = (0, import_react7.useRef)(false);
|
|
2181
2334
|
const clearBsTimer = () => {
|
|
2182
2335
|
if (bsTimer.current !== null) {
|
|
2183
2336
|
clearTimeout(bsTimer.current);
|
|
@@ -2199,8 +2352,8 @@ var NumpadDialog = ({
|
|
|
2199
2352
|
}
|
|
2200
2353
|
handleBackspace();
|
|
2201
2354
|
};
|
|
2202
|
-
(0,
|
|
2203
|
-
(0,
|
|
2355
|
+
(0, import_react7.useEffect)(() => () => clearBsTimer(), []);
|
|
2356
|
+
(0, import_react7.useEffect)(() => {
|
|
2204
2357
|
if (!isOpen) return;
|
|
2205
2358
|
const handler = (e) => {
|
|
2206
2359
|
if (e.key === "Tab") {
|
|
@@ -2298,7 +2451,7 @@ var NumpadDialog = ({
|
|
|
2298
2451
|
};
|
|
2299
2452
|
const reason = belowMin ? `Below minimum of ${min} ${unit}` : aboveMax ? `Above maximum of ${max} ${unit}` : "Type or tap to change the value";
|
|
2300
2453
|
const backspaceInGrid = min >= 0;
|
|
2301
|
-
const BackspaceButton = ({ style, label }) => /* @__PURE__ */ (0,
|
|
2454
|
+
const BackspaceButton = ({ style, label }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2302
2455
|
"button",
|
|
2303
2456
|
{
|
|
2304
2457
|
type: "button",
|
|
@@ -2315,7 +2468,7 @@ var NumpadDialog = ({
|
|
|
2315
2468
|
);
|
|
2316
2469
|
return (
|
|
2317
2470
|
// Backdrop
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2319
2472
|
"div",
|
|
2320
2473
|
{
|
|
2321
2474
|
style: {
|
|
@@ -2332,14 +2485,14 @@ var NumpadDialog = ({
|
|
|
2332
2485
|
},
|
|
2333
2486
|
onClick: onClose,
|
|
2334
2487
|
children: [
|
|
2335
|
-
/* @__PURE__ */ (0,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("style", { children: `
|
|
2336
2489
|
.np-key { transition: background .1s, transform .05s; touch-action: manipulation; }
|
|
2337
2490
|
.np-key:active:not(:disabled) { background:#e2e8f0; transform: translateY(1px); }
|
|
2338
2491
|
.np-key:focus-visible, .np-action:focus-visible { outline: 3px solid #2563eb; outline-offset: 2px; }
|
|
2339
2492
|
@keyframes np-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
|
|
2340
2493
|
.np-caret { display:inline-block; width:2px; height:1.1em; background:#2563eb; animation: np-blink 1s step-end infinite; }
|
|
2341
2494
|
` }),
|
|
2342
|
-
/* @__PURE__ */ (0,
|
|
2495
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2343
2496
|
"div",
|
|
2344
2497
|
{
|
|
2345
2498
|
ref: dialogRef,
|
|
@@ -2360,9 +2513,9 @@ var NumpadDialog = ({
|
|
|
2360
2513
|
},
|
|
2361
2514
|
onClick: (e) => e.stopPropagation(),
|
|
2362
2515
|
children: [
|
|
2363
|
-
/* @__PURE__ */ (0,
|
|
2364
|
-
/* @__PURE__ */ (0,
|
|
2365
|
-
/* @__PURE__ */ (0,
|
|
2516
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { padding: "14px 16px 0 16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { id: titleId, style: { margin: 0, fontSize: 15, fontWeight: 700, color: "#0f172a" }, children: deviceName ? `${deviceName} - ${parameterLabel}` : parameterLabel }) }),
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { padding: 16, display: "flex", flexDirection: "column", gap: 10 }, children: [
|
|
2518
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2366
2519
|
"div",
|
|
2367
2520
|
{
|
|
2368
2521
|
style: {
|
|
@@ -2372,24 +2525,24 @@ var NumpadDialog = ({
|
|
|
2372
2525
|
color: "#64748b"
|
|
2373
2526
|
},
|
|
2374
2527
|
children: [
|
|
2375
|
-
/* @__PURE__ */ (0,
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
|
|
2376
2529
|
"Current: ",
|
|
2377
2530
|
currentValue,
|
|
2378
2531
|
" ",
|
|
2379
2532
|
unit
|
|
2380
2533
|
] }),
|
|
2381
|
-
/* @__PURE__ */ (0,
|
|
2534
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
|
|
2382
2535
|
"Range: ",
|
|
2383
|
-
/* @__PURE__ */ (0,
|
|
2536
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: limitStyle(belowMin), children: min }),
|
|
2384
2537
|
"-",
|
|
2385
|
-
/* @__PURE__ */ (0,
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: limitStyle(aboveMax), children: max }),
|
|
2386
2539
|
" ",
|
|
2387
2540
|
unit
|
|
2388
2541
|
] })
|
|
2389
2542
|
]
|
|
2390
2543
|
}
|
|
2391
2544
|
),
|
|
2392
|
-
/* @__PURE__ */ (0,
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2393
2546
|
"div",
|
|
2394
2547
|
{
|
|
2395
2548
|
"aria-live": "polite",
|
|
@@ -2411,13 +2564,13 @@ var NumpadDialog = ({
|
|
|
2411
2564
|
border: outOfRange ? "1.5px solid #fca5a5" : "1.5px solid #e2e8f0"
|
|
2412
2565
|
},
|
|
2413
2566
|
children: [
|
|
2414
|
-
/* @__PURE__ */ (0,
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2416
|
-
/* @__PURE__ */ (0,
|
|
2567
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: inputValue || "0" }),
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "np-caret", "aria-hidden": "true" }),
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: 14, color: "#94a3b8", fontWeight: 500 }, children: unit })
|
|
2417
2570
|
]
|
|
2418
2571
|
}
|
|
2419
2572
|
),
|
|
2420
|
-
/* @__PURE__ */ (0,
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2421
2574
|
"div",
|
|
2422
2575
|
{
|
|
2423
2576
|
role: "status",
|
|
@@ -2432,8 +2585,8 @@ var NumpadDialog = ({
|
|
|
2432
2585
|
children: reason
|
|
2433
2586
|
}
|
|
2434
2587
|
),
|
|
2435
|
-
/* @__PURE__ */ (0,
|
|
2436
|
-
["7", "8", "9", "4", "5", "6", "1", "2", "3"].map((digit) => /* @__PURE__ */ (0,
|
|
2588
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 5 }, children: [
|
|
2589
|
+
["7", "8", "9", "4", "5", "6", "1", "2", "3"].map((digit) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2437
2590
|
"button",
|
|
2438
2591
|
{
|
|
2439
2592
|
type: "button",
|
|
@@ -2445,7 +2598,7 @@ var NumpadDialog = ({
|
|
|
2445
2598
|
},
|
|
2446
2599
|
digit
|
|
2447
2600
|
)),
|
|
2448
|
-
min < 0 ? /* @__PURE__ */ (0,
|
|
2601
|
+
min < 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2449
2602
|
"button",
|
|
2450
2603
|
{
|
|
2451
2604
|
type: "button",
|
|
@@ -2456,9 +2609,9 @@ var NumpadDialog = ({
|
|
|
2456
2609
|
onClick: handleToggleSign,
|
|
2457
2610
|
children: "+/\u2212"
|
|
2458
2611
|
}
|
|
2459
|
-
) : /* @__PURE__ */ (0,
|
|
2460
|
-
/* @__PURE__ */ (0,
|
|
2461
|
-
/* @__PURE__ */ (0,
|
|
2612
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BackspaceButton, { style: { ...keyStyle, fontSize: 20, background: "#f8fafc", color: "#64748b" }, label: "\u232B" }),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "np-key", tabIndex: -1, style: keyStyle, onClick: () => appendDigit("0"), children: "0" }),
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2462
2615
|
"button",
|
|
2463
2616
|
{
|
|
2464
2617
|
type: "button",
|
|
@@ -2476,12 +2629,12 @@ var NumpadDialog = ({
|
|
|
2476
2629
|
}
|
|
2477
2630
|
)
|
|
2478
2631
|
] }),
|
|
2479
|
-
/* @__PURE__ */ (0,
|
|
2480
|
-
/* @__PURE__ */ (0,
|
|
2481
|
-
!backspaceInGrid && /* @__PURE__ */ (0,
|
|
2632
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: 5 }, children: [
|
|
2633
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "np-key", tabIndex: -1, style: utilKeyStyle, onClick: handleClear, children: "Clear" }),
|
|
2634
|
+
!backspaceInGrid && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BackspaceButton, { style: utilKeyStyle, label: "Backspace" })
|
|
2482
2635
|
] }),
|
|
2483
|
-
/* @__PURE__ */ (0,
|
|
2484
|
-
/* @__PURE__ */ (0,
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 2 }, children: [
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2485
2638
|
"button",
|
|
2486
2639
|
{
|
|
2487
2640
|
type: "button",
|
|
@@ -2501,7 +2654,7 @@ var NumpadDialog = ({
|
|
|
2501
2654
|
children: "Cancel"
|
|
2502
2655
|
}
|
|
2503
2656
|
),
|
|
2504
|
-
/* @__PURE__ */ (0,
|
|
2657
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2505
2658
|
"button",
|
|
2506
2659
|
{
|
|
2507
2660
|
type: "button",
|
|
@@ -2536,13 +2689,13 @@ var NumpadDialog = ({
|
|
|
2536
2689
|
};
|
|
2537
2690
|
|
|
2538
2691
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
2539
|
-
var
|
|
2692
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
2540
2693
|
var import_material3 = require("@mui/material");
|
|
2541
2694
|
|
|
2542
2695
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
|
|
2543
2696
|
var import_material = require("@mui/material");
|
|
2544
2697
|
var import_styled = __toESM(require("@emotion/styled"), 1);
|
|
2545
|
-
var
|
|
2698
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2546
2699
|
var FullscreenContainer = (0, import_styled.default)(import_material.Box)(
|
|
2547
2700
|
({ leftCollapsed, rightCollapsed }) => {
|
|
2548
2701
|
const getGridTemplateAreas = () => {
|
|
@@ -2667,7 +2820,7 @@ var DisplayModeToggle = (0, import_styled.default)(import_material.IconButton)((
|
|
|
2667
2820
|
transform: "translateX(-50%) scale(1.05)"
|
|
2668
2821
|
}
|
|
2669
2822
|
}));
|
|
2670
|
-
var ChevronLeft = () => /* @__PURE__ */ (0,
|
|
2823
|
+
var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2671
2824
|
"div",
|
|
2672
2825
|
{
|
|
2673
2826
|
style: {
|
|
@@ -2679,7 +2832,7 @@ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
|
2679
2832
|
}
|
|
2680
2833
|
}
|
|
2681
2834
|
);
|
|
2682
|
-
var ChevronRight = () => /* @__PURE__ */ (0,
|
|
2835
|
+
var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2683
2836
|
"div",
|
|
2684
2837
|
{
|
|
2685
2838
|
style: {
|
|
@@ -2790,10 +2943,10 @@ var ScrollableSVGWrapper = (0, import_styled.default)("div")({
|
|
|
2790
2943
|
});
|
|
2791
2944
|
|
|
2792
2945
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
|
|
2793
|
-
var
|
|
2946
|
+
var import_react8 = require("react");
|
|
2794
2947
|
var import_material2 = require("@mui/material");
|
|
2795
2948
|
var import_styled2 = __toESM(require("@emotion/styled"), 1);
|
|
2796
|
-
var
|
|
2949
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2797
2950
|
var baseOverlayStyles = {
|
|
2798
2951
|
tank: {
|
|
2799
2952
|
background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
|
|
@@ -2855,8 +3008,8 @@ var SVGLockedOverlay = ({
|
|
|
2855
3008
|
onClick,
|
|
2856
3009
|
containerSelector = ".tff-svg-container"
|
|
2857
3010
|
}) => {
|
|
2858
|
-
const [svgOffset, setSvgOffset] = (0,
|
|
2859
|
-
(0,
|
|
3011
|
+
const [svgOffset, setSvgOffset] = (0, import_react8.useState)({ x: 0, y: 0 });
|
|
3012
|
+
(0, import_react8.useEffect)(() => {
|
|
2860
3013
|
const updateSvgOffset = () => {
|
|
2861
3014
|
const containerElement = document.querySelector(containerSelector);
|
|
2862
3015
|
const svgElement = containerElement?.querySelector("svg");
|
|
@@ -2876,7 +3029,7 @@ var SVGLockedOverlay = ({
|
|
|
2876
3029
|
const pixelX = svgX + svgOffset.x;
|
|
2877
3030
|
const pixelY = svgY + svgOffset.y;
|
|
2878
3031
|
const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
|
|
2879
|
-
return /* @__PURE__ */ (0,
|
|
3032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2880
3033
|
import_material2.Box,
|
|
2881
3034
|
{
|
|
2882
3035
|
className: `svg-locked-overlay ${className}`.trim(),
|
|
@@ -2940,7 +3093,7 @@ var CardUnit = (0, import_styled2.default)("div")({
|
|
|
2940
3093
|
});
|
|
2941
3094
|
|
|
2942
3095
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
|
|
2943
|
-
var
|
|
3096
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2944
3097
|
var forcedTagStyle = {
|
|
2945
3098
|
position: "absolute",
|
|
2946
3099
|
top: "-6px",
|
|
@@ -2968,7 +3121,7 @@ var TrendLine = ({
|
|
|
2968
3121
|
forced = false
|
|
2969
3122
|
}) => {
|
|
2970
3123
|
if (!values || values.length < 2) {
|
|
2971
|
-
return /* @__PURE__ */ (0,
|
|
3124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2972
3125
|
"div",
|
|
2973
3126
|
{
|
|
2974
3127
|
style: {
|
|
@@ -2982,8 +3135,8 @@ var TrendLine = ({
|
|
|
2982
3135
|
justifyContent: "center"
|
|
2983
3136
|
},
|
|
2984
3137
|
children: [
|
|
2985
|
-
/* @__PURE__ */ (0,
|
|
2986
|
-
forced && /* @__PURE__ */ (0,
|
|
3138
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" }),
|
|
3139
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: forcedTagStyle, "aria-label": "Forced", children: "F" })
|
|
2987
3140
|
]
|
|
2988
3141
|
}
|
|
2989
3142
|
);
|
|
@@ -2996,7 +3149,7 @@ var TrendLine = ({
|
|
|
2996
3149
|
const x = 4 + i / (values.length - 1) * (width - 8);
|
|
2997
3150
|
return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
|
|
2998
3151
|
}).join(" ");
|
|
2999
|
-
return /* @__PURE__ */ (0,
|
|
3152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3000
3153
|
"div",
|
|
3001
3154
|
{
|
|
3002
3155
|
style: {
|
|
@@ -3008,14 +3161,14 @@ var TrendLine = ({
|
|
|
3008
3161
|
overflow: "visible"
|
|
3009
3162
|
},
|
|
3010
3163
|
children: [
|
|
3011
|
-
/* @__PURE__ */ (0,
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3012
3165
|
"svg",
|
|
3013
3166
|
{
|
|
3014
3167
|
width,
|
|
3015
3168
|
height,
|
|
3016
3169
|
style: { position: "absolute", top: 0, left: 0, overflow: "hidden", borderRadius: "2px" },
|
|
3017
3170
|
children: [
|
|
3018
|
-
/* @__PURE__ */ (0,
|
|
3171
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3019
3172
|
"path",
|
|
3020
3173
|
{
|
|
3021
3174
|
d: pathData,
|
|
@@ -3026,7 +3179,7 @@ var TrendLine = ({
|
|
|
3026
3179
|
strokeLinejoin: "round"
|
|
3027
3180
|
}
|
|
3028
3181
|
),
|
|
3029
|
-
/* @__PURE__ */ (0,
|
|
3182
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3030
3183
|
"circle",
|
|
3031
3184
|
{
|
|
3032
3185
|
cx: 4 + (width - 8),
|
|
@@ -3038,7 +3191,7 @@ var TrendLine = ({
|
|
|
3038
3191
|
]
|
|
3039
3192
|
}
|
|
3040
3193
|
),
|
|
3041
|
-
forced && /* @__PURE__ */ (0,
|
|
3194
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: forcedTagStyle, "aria-label": "Forced", children: "F" })
|
|
3042
3195
|
]
|
|
3043
3196
|
}
|
|
3044
3197
|
);
|
|
@@ -3070,7 +3223,7 @@ var CircularGauge = ({
|
|
|
3070
3223
|
const borderColor = isHex ? hexToRgba(color, 0.9) : color;
|
|
3071
3224
|
const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
|
|
3072
3225
|
const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
|
|
3073
|
-
return /* @__PURE__ */ (0,
|
|
3226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3074
3227
|
"div",
|
|
3075
3228
|
{
|
|
3076
3229
|
style: {
|
|
@@ -3079,7 +3232,7 @@ var CircularGauge = ({
|
|
|
3079
3232
|
alignItems: "center"
|
|
3080
3233
|
},
|
|
3081
3234
|
children: [
|
|
3082
|
-
/* @__PURE__ */ (0,
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3083
3236
|
"div",
|
|
3084
3237
|
{
|
|
3085
3238
|
style: {
|
|
@@ -3091,8 +3244,8 @@ var CircularGauge = ({
|
|
|
3091
3244
|
border: forced ? `2px solid ${FORCED_MARK_COLOR.border}` : `1px solid ${borderStrokeColor}`
|
|
3092
3245
|
},
|
|
3093
3246
|
children: [
|
|
3094
|
-
/* @__PURE__ */ (0,
|
|
3095
|
-
/* @__PURE__ */ (0,
|
|
3247
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
|
|
3248
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3096
3249
|
"circle",
|
|
3097
3250
|
{
|
|
3098
3251
|
cx: size / 2,
|
|
@@ -3103,7 +3256,7 @@ var CircularGauge = ({
|
|
|
3103
3256
|
strokeWidth: 1
|
|
3104
3257
|
}
|
|
3105
3258
|
),
|
|
3106
|
-
/* @__PURE__ */ (0,
|
|
3259
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3107
3260
|
"circle",
|
|
3108
3261
|
{
|
|
3109
3262
|
cx: size / 2,
|
|
@@ -3114,7 +3267,7 @@ var CircularGauge = ({
|
|
|
3114
3267
|
fill: "transparent"
|
|
3115
3268
|
}
|
|
3116
3269
|
),
|
|
3117
|
-
/* @__PURE__ */ (0,
|
|
3270
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3118
3271
|
"circle",
|
|
3119
3272
|
{
|
|
3120
3273
|
cx: size / 2,
|
|
@@ -3130,7 +3283,7 @@ var CircularGauge = ({
|
|
|
3130
3283
|
}
|
|
3131
3284
|
)
|
|
3132
3285
|
] }),
|
|
3133
|
-
/* @__PURE__ */ (0,
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3134
3287
|
"div",
|
|
3135
3288
|
{
|
|
3136
3289
|
style: {
|
|
@@ -3146,14 +3299,14 @@ var CircularGauge = ({
|
|
|
3146
3299
|
},
|
|
3147
3300
|
children: [
|
|
3148
3301
|
value.toFixed(1),
|
|
3149
|
-
/* @__PURE__ */ (0,
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
|
|
3150
3303
|
]
|
|
3151
3304
|
}
|
|
3152
3305
|
)
|
|
3153
3306
|
]
|
|
3154
3307
|
}
|
|
3155
3308
|
),
|
|
3156
|
-
/* @__PURE__ */ (0,
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3157
3310
|
"div",
|
|
3158
3311
|
{
|
|
3159
3312
|
style: {
|
|
@@ -3165,7 +3318,7 @@ var CircularGauge = ({
|
|
|
3165
3318
|
children: label
|
|
3166
3319
|
}
|
|
3167
3320
|
),
|
|
3168
|
-
forced && /* @__PURE__ */ (0,
|
|
3321
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3169
3322
|
"span",
|
|
3170
3323
|
{
|
|
3171
3324
|
"aria-label": "Forced",
|
|
@@ -3186,7 +3339,7 @@ var CircularGauge = ({
|
|
|
3186
3339
|
children: "F"
|
|
3187
3340
|
}
|
|
3188
3341
|
),
|
|
3189
|
-
forced && realValue !== void 0 && /* @__PURE__ */ (0,
|
|
3342
|
+
forced && realValue !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { fontSize: "8px", opacity: 0.8, color: "white", marginTop: "1px" }, children: [
|
|
3190
3343
|
"REAL ",
|
|
3191
3344
|
realValue.toFixed(1),
|
|
3192
3345
|
" ",
|
|
@@ -3211,7 +3364,7 @@ var Sparkline = ({ data, width, height, color, forced = false }) => {
|
|
|
3211
3364
|
const y = height - 8 - (value - min) / range * (height - 8);
|
|
3212
3365
|
return `${x + 4},${y + 4}`;
|
|
3213
3366
|
}).join(" ");
|
|
3214
|
-
return /* @__PURE__ */ (0,
|
|
3367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3215
3368
|
"div",
|
|
3216
3369
|
{
|
|
3217
3370
|
style: {
|
|
@@ -3227,13 +3380,13 @@ var Sparkline = ({ data, width, height, color, forced = false }) => {
|
|
|
3227
3380
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
3228
3381
|
},
|
|
3229
3382
|
children: [
|
|
3230
|
-
/* @__PURE__ */ (0,
|
|
3231
|
-
forced && /* @__PURE__ */ (0,
|
|
3383
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width, height, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) }),
|
|
3384
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: forcedTagStyle, "aria-label": "Forced", children: "F" })
|
|
3232
3385
|
]
|
|
3233
3386
|
}
|
|
3234
3387
|
);
|
|
3235
3388
|
};
|
|
3236
|
-
var EquipmentForcedBadge = () => /* @__PURE__ */ (0,
|
|
3389
|
+
var EquipmentForcedBadge = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3237
3390
|
"span",
|
|
3238
3391
|
{
|
|
3239
3392
|
"aria-label": "Forced",
|
|
@@ -3268,9 +3421,9 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
3268
3421
|
forced = false
|
|
3269
3422
|
}) => {
|
|
3270
3423
|
const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
|
|
3271
|
-
return /* @__PURE__ */ (0,
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3273
|
-
/* @__PURE__ */ (0,
|
|
3424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
3425
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { position: "relative", width: size, height: size }, children: [
|
|
3426
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3274
3427
|
"div",
|
|
3275
3428
|
{
|
|
3276
3429
|
style: {
|
|
@@ -3291,9 +3444,9 @@ var EquipmentIndicatorWithSparkline = ({
|
|
|
3291
3444
|
children: label
|
|
3292
3445
|
}
|
|
3293
3446
|
),
|
|
3294
|
-
forced && /* @__PURE__ */ (0,
|
|
3447
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EquipmentForcedBadge, {})
|
|
3295
3448
|
] }) }),
|
|
3296
|
-
hasSparkline && /* @__PURE__ */ (0,
|
|
3449
|
+
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Sparkline, { data: sparklineData, width: 60, height: 20, color, forced }) })
|
|
3297
3450
|
] });
|
|
3298
3451
|
};
|
|
3299
3452
|
var EquipmentIndicator = ({
|
|
@@ -3307,8 +3460,8 @@ var EquipmentIndicator = ({
|
|
|
3307
3460
|
forced = false
|
|
3308
3461
|
}) => {
|
|
3309
3462
|
const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
|
|
3310
|
-
return /* @__PURE__ */ (0,
|
|
3311
|
-
/* @__PURE__ */ (0,
|
|
3463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { position: "relative", width: size, height: size }, children: [
|
|
3464
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3312
3465
|
"div",
|
|
3313
3466
|
{
|
|
3314
3467
|
style: {
|
|
@@ -3329,12 +3482,12 @@ var EquipmentIndicator = ({
|
|
|
3329
3482
|
children: label
|
|
3330
3483
|
}
|
|
3331
3484
|
),
|
|
3332
|
-
forced && /* @__PURE__ */ (0,
|
|
3485
|
+
forced && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EquipmentForcedBadge, {})
|
|
3333
3486
|
] }) });
|
|
3334
3487
|
};
|
|
3335
3488
|
|
|
3336
3489
|
// src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
|
|
3337
|
-
var
|
|
3490
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3338
3491
|
function FullscreenWorkspace({
|
|
3339
3492
|
svgContent,
|
|
3340
3493
|
overlays,
|
|
@@ -3362,10 +3515,10 @@ function FullscreenWorkspace({
|
|
|
3362
3515
|
className = "",
|
|
3363
3516
|
...rest
|
|
3364
3517
|
}) {
|
|
3365
|
-
const [leftCollapsedState, setLeftCollapsedState] =
|
|
3366
|
-
const [rightCollapsedState, setRightCollapsedState] =
|
|
3367
|
-
const [internalDisplayMode, setInternalDisplayMode] =
|
|
3368
|
-
const [internalTab, setInternalTab] =
|
|
3518
|
+
const [leftCollapsedState, setLeftCollapsedState] = import_react9.default.useState(defaultLeftCollapsed);
|
|
3519
|
+
const [rightCollapsedState, setRightCollapsedState] = import_react9.default.useState(defaultRightCollapsed);
|
|
3520
|
+
const [internalDisplayMode, setInternalDisplayMode] = import_react9.default.useState(displayMode ?? defaultDisplayMode);
|
|
3521
|
+
const [internalTab, setInternalTab] = import_react9.default.useState(
|
|
3369
3522
|
tabs && tabs.length > 0 ? tabs[0].value : ""
|
|
3370
3523
|
);
|
|
3371
3524
|
const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
|
|
@@ -3373,10 +3526,10 @@ function FullscreenWorkspace({
|
|
|
3373
3526
|
const isDisplayModeControlled = displayMode !== void 0;
|
|
3374
3527
|
const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
|
|
3375
3528
|
const isTabControlled = activeTab !== void 0 && activeTab !== null;
|
|
3376
|
-
const resolvedTabs =
|
|
3529
|
+
const resolvedTabs = import_react9.default.useMemo(() => tabs ?? [], [tabs]);
|
|
3377
3530
|
const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
|
|
3378
3531
|
const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
|
|
3379
|
-
|
|
3532
|
+
import_react9.default.useEffect(() => {
|
|
3380
3533
|
if (resolvedTabs.length > 0) {
|
|
3381
3534
|
const values = resolvedTabs.map((tab) => tab.value);
|
|
3382
3535
|
if (!values.includes(currentTab)) {
|
|
@@ -3385,7 +3538,7 @@ function FullscreenWorkspace({
|
|
|
3385
3538
|
}
|
|
3386
3539
|
}
|
|
3387
3540
|
}, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
|
|
3388
|
-
|
|
3541
|
+
import_react9.default.useEffect(() => {
|
|
3389
3542
|
if (displayMode !== void 0) {
|
|
3390
3543
|
setInternalDisplayMode(displayMode);
|
|
3391
3544
|
}
|
|
@@ -3420,7 +3573,7 @@ function FullscreenWorkspace({
|
|
|
3420
3573
|
const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
|
|
3421
3574
|
const showLeftToggle = Boolean(leftPanel);
|
|
3422
3575
|
const showRightToggle = Boolean(rightPanel);
|
|
3423
|
-
return /* @__PURE__ */ (0,
|
|
3576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
3424
3577
|
FullscreenContainer,
|
|
3425
3578
|
{
|
|
3426
3579
|
leftCollapsed,
|
|
@@ -3428,25 +3581,25 @@ function FullscreenWorkspace({
|
|
|
3428
3581
|
className: `tff-svg-container ${className}`.trim(),
|
|
3429
3582
|
...rest,
|
|
3430
3583
|
children: [
|
|
3431
|
-
showLeftToggle && /* @__PURE__ */ (0,
|
|
3584
|
+
showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3432
3585
|
LeftToggleButton,
|
|
3433
3586
|
{
|
|
3434
3587
|
collapsed: leftCollapsed,
|
|
3435
3588
|
onClick: handleLeftToggle,
|
|
3436
3589
|
"aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
|
|
3437
|
-
children: leftCollapsed ? /* @__PURE__ */ (0,
|
|
3590
|
+
children: leftCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChevronRight, {}) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChevronLeft, {})
|
|
3438
3591
|
}
|
|
3439
3592
|
),
|
|
3440
|
-
showRightToggle && /* @__PURE__ */ (0,
|
|
3593
|
+
showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3441
3594
|
RightToggleButton,
|
|
3442
3595
|
{
|
|
3443
3596
|
collapsed: rightCollapsed,
|
|
3444
3597
|
onClick: handleRightToggle,
|
|
3445
3598
|
"aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
|
|
3446
|
-
children: rightCollapsed ? /* @__PURE__ */ (0,
|
|
3599
|
+
children: rightCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChevronLeft, {}) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChevronRight, {})
|
|
3447
3600
|
}
|
|
3448
3601
|
),
|
|
3449
|
-
showDisplayModeToggle && /* @__PURE__ */ (0,
|
|
3602
|
+
showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3450
3603
|
DisplayModeToggle,
|
|
3451
3604
|
{
|
|
3452
3605
|
mode: currentDisplayMode,
|
|
@@ -3455,9 +3608,9 @@ function FullscreenWorkspace({
|
|
|
3455
3608
|
children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
|
|
3456
3609
|
}
|
|
3457
3610
|
),
|
|
3458
|
-
/* @__PURE__ */ (0,
|
|
3459
|
-
showZoomControls && /* @__PURE__ */ (0,
|
|
3460
|
-
/* @__PURE__ */ (0,
|
|
3611
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(SVGArea, { children: [
|
|
3612
|
+
showZoomControls && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(ZoomControls, { children: [
|
|
3613
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3461
3614
|
ZoomButton,
|
|
3462
3615
|
{
|
|
3463
3616
|
onClick: onZoomIn,
|
|
@@ -3467,7 +3620,7 @@ function FullscreenWorkspace({
|
|
|
3467
3620
|
children: "+"
|
|
3468
3621
|
}
|
|
3469
3622
|
),
|
|
3470
|
-
/* @__PURE__ */ (0,
|
|
3623
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3471
3624
|
ZoomButton,
|
|
3472
3625
|
{
|
|
3473
3626
|
onClick: onZoomOut,
|
|
@@ -3477,7 +3630,7 @@ function FullscreenWorkspace({
|
|
|
3477
3630
|
children: "-"
|
|
3478
3631
|
}
|
|
3479
3632
|
),
|
|
3480
|
-
onResetZoom && /* @__PURE__ */ (0,
|
|
3633
|
+
onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3481
3634
|
ZoomButton,
|
|
3482
3635
|
{
|
|
3483
3636
|
onClick: onResetZoom,
|
|
@@ -3488,44 +3641,44 @@ function FullscreenWorkspace({
|
|
|
3488
3641
|
}
|
|
3489
3642
|
)
|
|
3490
3643
|
] }),
|
|
3491
|
-
/* @__PURE__ */ (0,
|
|
3644
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(FixedSVGContainer, { className: "svg-container", children: [
|
|
3492
3645
|
svgContent,
|
|
3493
3646
|
overlays
|
|
3494
3647
|
] }) })
|
|
3495
3648
|
] }),
|
|
3496
|
-
/* @__PURE__ */ (0,
|
|
3497
|
-
/* @__PURE__ */ (0,
|
|
3649
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
3650
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3498
3651
|
PanelTabs,
|
|
3499
3652
|
{
|
|
3500
3653
|
value: currentTab,
|
|
3501
3654
|
onChange: handleTabChangeInternal,
|
|
3502
3655
|
"aria-label": "Left panel tabs",
|
|
3503
|
-
children: resolvedTabs.map((tab) => /* @__PURE__ */ (0,
|
|
3656
|
+
children: resolvedTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material3.Tab, { label: tab.label, value: tab.value }, tab.value))
|
|
3504
3657
|
}
|
|
3505
3658
|
),
|
|
3506
|
-
/* @__PURE__ */ (0,
|
|
3659
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PanelContent, { children: currentTabContent })
|
|
3507
3660
|
] }) : leftPanel }),
|
|
3508
|
-
/* @__PURE__ */ (0,
|
|
3509
|
-
/* @__PURE__ */ (0,
|
|
3661
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
|
|
3662
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FooterPanel, { children: footer })
|
|
3510
3663
|
]
|
|
3511
3664
|
}
|
|
3512
3665
|
);
|
|
3513
3666
|
}
|
|
3514
3667
|
|
|
3515
3668
|
// src/theme/ThemeContext.tsx
|
|
3516
|
-
var
|
|
3517
|
-
var
|
|
3518
|
-
var ThemeContext = (0,
|
|
3669
|
+
var import_react10 = require("react");
|
|
3670
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3671
|
+
var ThemeContext = (0, import_react10.createContext)(void 0);
|
|
3519
3672
|
var useTheme = () => {
|
|
3520
|
-
const context = (0,
|
|
3673
|
+
const context = (0, import_react10.useContext)(ThemeContext);
|
|
3521
3674
|
if (!context) {
|
|
3522
3675
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
3523
3676
|
}
|
|
3524
3677
|
return context;
|
|
3525
3678
|
};
|
|
3526
3679
|
var ThemeProvider = ({ children }) => {
|
|
3527
|
-
const [theme, setThemeState] = (0,
|
|
3528
|
-
(0,
|
|
3680
|
+
const [theme, setThemeState] = (0, import_react10.useState)("modern");
|
|
3681
|
+
(0, import_react10.useEffect)(() => {
|
|
3529
3682
|
document.body.className = "";
|
|
3530
3683
|
document.body.classList.add(`theme-${theme}`);
|
|
3531
3684
|
document.documentElement.className = "";
|
|
@@ -3537,11 +3690,11 @@ var ThemeProvider = ({ children }) => {
|
|
|
3537
3690
|
const setTheme = (newTheme) => {
|
|
3538
3691
|
setThemeState(newTheme);
|
|
3539
3692
|
};
|
|
3540
|
-
return /* @__PURE__ */ (0,
|
|
3693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
|
|
3541
3694
|
};
|
|
3542
3695
|
|
|
3543
3696
|
// src/theme/ThemeToggle.tsx
|
|
3544
|
-
var
|
|
3697
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3545
3698
|
var ThemeToggle = ({
|
|
3546
3699
|
size = "medium",
|
|
3547
3700
|
position = "top-right",
|
|
@@ -3612,18 +3765,18 @@ var ThemeToggle = ({
|
|
|
3612
3765
|
transition: "all 0.2s ease",
|
|
3613
3766
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
|
|
3614
3767
|
};
|
|
3615
|
-
return /* @__PURE__ */ (0,
|
|
3616
|
-
/* @__PURE__ */ (0,
|
|
3617
|
-
/* @__PURE__ */ (0,
|
|
3618
|
-
/* @__PURE__ */ (0,
|
|
3768
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
|
|
3769
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
|
|
3770
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: toggleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: thumbStyle }) }),
|
|
3771
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
|
|
3619
3772
|
] });
|
|
3620
3773
|
};
|
|
3621
3774
|
|
|
3622
3775
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3623
|
-
var
|
|
3776
|
+
var import_react22 = __toESM(require("react"), 1);
|
|
3624
3777
|
|
|
3625
3778
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
3626
|
-
var
|
|
3779
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
3627
3780
|
|
|
3628
3781
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
3629
3782
|
var mockSymbolLibrary = {
|
|
@@ -3651,6 +3804,25 @@ var mockSymbolLibrary = {
|
|
|
3651
3804
|
tags: ["valve", "gate", "powered", "actuator"]
|
|
3652
3805
|
}
|
|
3653
3806
|
},
|
|
3807
|
+
"status-indicator": {
|
|
3808
|
+
id: "status-indicator",
|
|
3809
|
+
name: "Status LED",
|
|
3810
|
+
category: "instrument",
|
|
3811
|
+
viewBox: { x: 0, y: 0, width: 24, height: 24 },
|
|
3812
|
+
ports: [],
|
|
3813
|
+
svgContent: `
|
|
3814
|
+
<rect x="2" y="2" width="20" height="20"
|
|
3815
|
+
rx="var(--led-rx, 50%)"
|
|
3816
|
+
fill="var(--symbol-fill, #64748b)"
|
|
3817
|
+
stroke="rgba(255,255,255,0.4)"
|
|
3818
|
+
stroke-width="var(--led-bezel, 0)"
|
|
3819
|
+
style="transform-box: fill-box; transform: rotate(var(--led-rotate, 0deg)); transform-origin: center; pointer-events: all;"/>
|
|
3820
|
+
`,
|
|
3821
|
+
metadata: {
|
|
3822
|
+
description: "Status LED indicator driven by telemetry status color",
|
|
3823
|
+
tags: ["status", "led", "indicator", "instrument"]
|
|
3824
|
+
}
|
|
3825
|
+
},
|
|
3654
3826
|
"pump-positive-displacement": {
|
|
3655
3827
|
id: "pump-positive-displacement",
|
|
3656
3828
|
name: "Positive Displacement Pump",
|
|
@@ -4843,8 +5015,150 @@ function getAvailableSymbols() {
|
|
|
4843
5015
|
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
4844
5016
|
}
|
|
4845
5017
|
|
|
5018
|
+
// src/diagram/symbols/appearanceSchema.ts
|
|
5019
|
+
var COLOR_PRESETS = {
|
|
5020
|
+
green: "#22c55e",
|
|
5021
|
+
red: "#ef4444",
|
|
5022
|
+
amber: "#f59e0b",
|
|
5023
|
+
blue: "#3b82f6",
|
|
5024
|
+
grey: "#64748b"
|
|
5025
|
+
};
|
|
5026
|
+
function resolvePresetColor(name) {
|
|
5027
|
+
return name && COLOR_PRESETS[name] || COLOR_PRESETS.grey;
|
|
5028
|
+
}
|
|
5029
|
+
var COLOR_OPTIONS = Object.keys(COLOR_PRESETS);
|
|
5030
|
+
var STATUS_LED_APPEARANCE = [
|
|
5031
|
+
{
|
|
5032
|
+
key: "shape",
|
|
5033
|
+
kind: "select",
|
|
5034
|
+
label: "Shape",
|
|
5035
|
+
options: ["circle", "square", "diamond"],
|
|
5036
|
+
default: "circle"
|
|
5037
|
+
},
|
|
5038
|
+
{
|
|
5039
|
+
key: "size",
|
|
5040
|
+
kind: "select",
|
|
5041
|
+
label: "Size",
|
|
5042
|
+
target: "scale",
|
|
5043
|
+
options: ["small", "medium", "large"],
|
|
5044
|
+
default: "medium",
|
|
5045
|
+
valueMap: { small: 0.75, medium: 1, large: 1.5 }
|
|
5046
|
+
},
|
|
5047
|
+
{ key: "led", kind: "boolean", label: "Bezel ring", default: true },
|
|
5048
|
+
{ key: "glow", kind: "boolean", label: "Diffusion (glow)", default: false },
|
|
5049
|
+
{
|
|
5050
|
+
key: "animation",
|
|
5051
|
+
kind: "select",
|
|
5052
|
+
label: "Animation",
|
|
5053
|
+
options: ["none", "pulse", "blink"],
|
|
5054
|
+
default: "none"
|
|
5055
|
+
},
|
|
5056
|
+
{
|
|
5057
|
+
key: "labelPosition",
|
|
5058
|
+
kind: "select",
|
|
5059
|
+
label: "Label position",
|
|
5060
|
+
options: ["bottom", "top", "left", "right"],
|
|
5061
|
+
default: "bottom"
|
|
5062
|
+
},
|
|
5063
|
+
// Color binding: a named signal drives the on/off color.
|
|
5064
|
+
{
|
|
5065
|
+
key: "colorSource",
|
|
5066
|
+
kind: "tag",
|
|
5067
|
+
label: "Color source (tag)",
|
|
5068
|
+
default: "",
|
|
5069
|
+
help: "Signal/tag that drives color. True (non-zero) shows On color; false shows Off color. Blank = unbound (grey)."
|
|
5070
|
+
},
|
|
5071
|
+
{
|
|
5072
|
+
key: "onColor",
|
|
5073
|
+
kind: "select",
|
|
5074
|
+
label: "On color (true)",
|
|
5075
|
+
options: COLOR_OPTIONS,
|
|
5076
|
+
default: "green",
|
|
5077
|
+
help: "Color when the Color source is true."
|
|
5078
|
+
},
|
|
5079
|
+
{
|
|
5080
|
+
key: "offColor",
|
|
5081
|
+
kind: "select",
|
|
5082
|
+
label: "Off color (false)",
|
|
5083
|
+
options: COLOR_OPTIONS,
|
|
5084
|
+
default: "red",
|
|
5085
|
+
help: "Color when the Color source is false."
|
|
5086
|
+
},
|
|
5087
|
+
// Visibility binding: an independent named signal drives show/hide.
|
|
5088
|
+
{
|
|
5089
|
+
key: "visibleSource",
|
|
5090
|
+
kind: "tag",
|
|
5091
|
+
label: "Visibility source (tag)",
|
|
5092
|
+
default: "",
|
|
5093
|
+
help: "Signal/tag that drives visibility. True shows the LED, false hides it. Blank = always visible (use the Visible checkbox)."
|
|
5094
|
+
},
|
|
5095
|
+
{
|
|
5096
|
+
key: "visible",
|
|
5097
|
+
kind: "boolean",
|
|
5098
|
+
label: "Visible",
|
|
5099
|
+
target: "visible",
|
|
5100
|
+
default: true,
|
|
5101
|
+
help: "Static show/hide, used only when no Visibility source is set."
|
|
5102
|
+
}
|
|
5103
|
+
];
|
|
5104
|
+
var APPEARANCE_REGISTRY = {
|
|
5105
|
+
"status-indicator": STATUS_LED_APPEARANCE
|
|
5106
|
+
};
|
|
5107
|
+
function getAppearanceSchema(symbolId) {
|
|
5108
|
+
return APPEARANCE_REGISTRY[symbolId] ?? [];
|
|
5109
|
+
}
|
|
5110
|
+
function getAppearanceDefaults(symbolId) {
|
|
5111
|
+
const out = {};
|
|
5112
|
+
for (const field of getAppearanceSchema(symbolId)) {
|
|
5113
|
+
if ((field.target ?? "metadata") === "metadata" && field.default !== void 0) {
|
|
5114
|
+
out[field.key] = field.default;
|
|
5115
|
+
}
|
|
5116
|
+
}
|
|
5117
|
+
return out;
|
|
5118
|
+
}
|
|
5119
|
+
function readAppearanceValue(node, field) {
|
|
5120
|
+
if (field.target === "visible") {
|
|
5121
|
+
return node.visible ?? field.default ?? true;
|
|
5122
|
+
}
|
|
5123
|
+
if (field.target === "scale") {
|
|
5124
|
+
const scale = node.transform.scale ?? 1;
|
|
5125
|
+
if (field.valueMap) {
|
|
5126
|
+
let bestOption = field.options?.[0] ?? String(scale);
|
|
5127
|
+
let bestDiff = Infinity;
|
|
5128
|
+
for (const [option, value2] of Object.entries(field.valueMap)) {
|
|
5129
|
+
const diff = Math.abs(value2 - scale);
|
|
5130
|
+
if (diff < bestDiff) {
|
|
5131
|
+
bestDiff = diff;
|
|
5132
|
+
bestOption = option;
|
|
5133
|
+
}
|
|
5134
|
+
}
|
|
5135
|
+
return bestOption;
|
|
5136
|
+
}
|
|
5137
|
+
return scale;
|
|
5138
|
+
}
|
|
5139
|
+
const value = node.metadata?.[field.key];
|
|
5140
|
+
return value ?? field.default;
|
|
5141
|
+
}
|
|
5142
|
+
function writeAppearanceValue(node, field, value) {
|
|
5143
|
+
if (field.target === "visible") {
|
|
5144
|
+
return { visible: Boolean(value) };
|
|
5145
|
+
}
|
|
5146
|
+
if (field.target === "scale") {
|
|
5147
|
+
const scale = field.valueMap ? field.valueMap[String(value)] ?? 1 : Number(value);
|
|
5148
|
+
return { transform: { ...node.transform, scale } };
|
|
5149
|
+
}
|
|
5150
|
+
return { metadata: { ...node.metadata, [field.key]: value } };
|
|
5151
|
+
}
|
|
5152
|
+
|
|
4846
5153
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
4847
|
-
var
|
|
5154
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
5155
|
+
var HATCH_TILE_SIZE = 7;
|
|
5156
|
+
var HATCH_STRIPE_WIDTH = 2;
|
|
5157
|
+
var HATCH_STRIPE_ANGLE = 135;
|
|
5158
|
+
var HATCH_STRIPE_OPACITY = 85 / 255;
|
|
5159
|
+
function isUnknownNode(node) {
|
|
5160
|
+
return node.positionUnknown === true || normalizeDeviceStatus(node.status) === "unknown";
|
|
5161
|
+
}
|
|
4848
5162
|
function NodeRendererImpl({
|
|
4849
5163
|
nodes: nodes2,
|
|
4850
5164
|
selectedNodeIds,
|
|
@@ -4856,146 +5170,214 @@ function NodeRendererImpl({
|
|
|
4856
5170
|
enableDrag = false,
|
|
4857
5171
|
statusColorMap
|
|
4858
5172
|
}) {
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
"circle",
|
|
4867
|
-
{
|
|
4868
|
-
cx: node.transform.x,
|
|
4869
|
-
cy: node.transform.y,
|
|
4870
|
-
r: "15",
|
|
4871
|
-
fill: "#ff0000",
|
|
4872
|
-
opacity: "0.3",
|
|
4873
|
-
stroke: "#ff0000",
|
|
4874
|
-
strokeWidth: "2"
|
|
4875
|
-
}
|
|
4876
|
-
),
|
|
4877
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
4878
|
-
"text",
|
|
4879
|
-
{
|
|
4880
|
-
x: node.transform.x,
|
|
4881
|
-
y: node.transform.y,
|
|
4882
|
-
textAnchor: "middle",
|
|
4883
|
-
dominantBaseline: "middle",
|
|
4884
|
-
fontSize: "10",
|
|
4885
|
-
fill: "#ff0000",
|
|
4886
|
-
children: "?"
|
|
4887
|
-
}
|
|
4888
|
-
)
|
|
4889
|
-
] }, node.id);
|
|
4890
|
-
}
|
|
4891
|
-
const transforms = [];
|
|
4892
|
-
const effectiveX = isDragging ? node.transform.x + dragOffset.x : node.transform.x;
|
|
4893
|
-
const effectiveY = isDragging ? node.transform.y + dragOffset.y : node.transform.y;
|
|
4894
|
-
transforms.push(`translate(${effectiveX}, ${effectiveY})`);
|
|
4895
|
-
if (node.transform.rotation) {
|
|
4896
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4897
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4898
|
-
transforms.push(`rotate(${node.transform.rotation}, ${centerX}, ${centerY})`);
|
|
4899
|
-
}
|
|
4900
|
-
if (node.transform.scale && node.transform.scale !== 1) {
|
|
4901
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4902
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4903
|
-
transforms.push(
|
|
4904
|
-
`translate(${centerX}, ${centerY}) scale(${node.transform.scale}) translate(${-centerX}, ${-centerY})`
|
|
4905
|
-
);
|
|
4906
|
-
}
|
|
4907
|
-
if (node.transform.flipX || node.transform.flipY) {
|
|
4908
|
-
const scaleX = node.transform.flipX ? -1 : 1;
|
|
4909
|
-
const scaleY = node.transform.flipY ? -1 : 1;
|
|
4910
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4911
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4912
|
-
transforms.push(
|
|
4913
|
-
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
4914
|
-
);
|
|
4915
|
-
}
|
|
4916
|
-
const statusEntry = resolveStatusColor(node.status, statusColorMap);
|
|
4917
|
-
const fillColor = node.customColors?.fill ?? statusEntry.fill;
|
|
4918
|
-
const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
|
|
4919
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
4920
|
-
"g",
|
|
5173
|
+
const hatchPatternId = `node-unknown-hatch-${import_react11.default.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
5174
|
+
const visibleNodes = nodes2.filter((node) => node.visible !== false);
|
|
5175
|
+
const hasUnknownNode = visibleNodes.some(isUnknownNode);
|
|
5176
|
+
const unknownEntry = resolveStatusColor("unknown", statusColorMap);
|
|
5177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { id: "layer-nodes", children: [
|
|
5178
|
+
hasUnknownNode && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
5179
|
+
"pattern",
|
|
4921
5180
|
{
|
|
4922
|
-
|
|
4923
|
-
"data-
|
|
4924
|
-
"
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
"--symbol-fill": fillColor,
|
|
4929
|
-
"--symbol-stroke": strokeColor,
|
|
4930
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
4931
|
-
},
|
|
4932
|
-
onClick: (e) => {
|
|
4933
|
-
e.stopPropagation();
|
|
4934
|
-
onNodeClick?.(node.id, e);
|
|
4935
|
-
},
|
|
4936
|
-
onDoubleClick: (e) => {
|
|
4937
|
-
e.stopPropagation();
|
|
4938
|
-
onNodeDoubleClick?.(node.id, e);
|
|
4939
|
-
},
|
|
4940
|
-
onMouseDown: (e) => {
|
|
4941
|
-
if (enableDrag) {
|
|
4942
|
-
onNodeDragStart?.(node.id, e);
|
|
4943
|
-
}
|
|
4944
|
-
},
|
|
4945
|
-
onTouchStart: (e) => {
|
|
4946
|
-
if (enableDrag) {
|
|
4947
|
-
e.stopPropagation();
|
|
4948
|
-
onNodeDragStart?.(node.id, e);
|
|
4949
|
-
}
|
|
4950
|
-
},
|
|
5181
|
+
id: hatchPatternId,
|
|
5182
|
+
"data-testid": "unknown-hatch-pattern",
|
|
5183
|
+
patternUnits: "userSpaceOnUse",
|
|
5184
|
+
width: HATCH_TILE_SIZE,
|
|
5185
|
+
height: HATCH_TILE_SIZE,
|
|
5186
|
+
patternTransform: `rotate(${HATCH_STRIPE_ANGLE})`,
|
|
4951
5187
|
children: [
|
|
4952
|
-
|
|
5188
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("rect", { width: HATCH_TILE_SIZE, height: HATCH_TILE_SIZE, fill: unknownEntry.fill }),
|
|
5189
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
4953
5190
|
"rect",
|
|
4954
5191
|
{
|
|
4955
|
-
x:
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
stroke: isDragging ? "#10b981" : "#3b82f6",
|
|
4961
|
-
strokeWidth: isDragging ? "3" : "2",
|
|
4962
|
-
strokeDasharray: "4 2",
|
|
4963
|
-
rx: "2",
|
|
4964
|
-
pointerEvents: "none"
|
|
5192
|
+
x: HATCH_TILE_SIZE - HATCH_STRIPE_WIDTH,
|
|
5193
|
+
width: HATCH_STRIPE_WIDTH,
|
|
5194
|
+
height: HATCH_TILE_SIZE,
|
|
5195
|
+
fill: unknownEntry.stroke,
|
|
5196
|
+
fillOpacity: HATCH_STRIPE_OPACITY
|
|
4965
5197
|
}
|
|
4966
|
-
)
|
|
4967
|
-
|
|
4968
|
-
|
|
5198
|
+
)
|
|
5199
|
+
]
|
|
5200
|
+
}
|
|
5201
|
+
) }),
|
|
5202
|
+
visibleNodes.map((node) => {
|
|
5203
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5204
|
+
const isSelected = selectedNodeIds?.has(node.id) ?? false;
|
|
5205
|
+
const isDragging = draggingNodeId === node.id;
|
|
5206
|
+
if (!symbol) {
|
|
5207
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { children: [
|
|
5208
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5209
|
+
"circle",
|
|
4969
5210
|
{
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
5211
|
+
cx: node.transform.x,
|
|
5212
|
+
cy: node.transform.y,
|
|
5213
|
+
r: "15",
|
|
5214
|
+
fill: "#ff0000",
|
|
5215
|
+
opacity: "0.3",
|
|
5216
|
+
stroke: "#ff0000",
|
|
5217
|
+
strokeWidth: "2"
|
|
4973
5218
|
}
|
|
4974
5219
|
),
|
|
4975
|
-
/* @__PURE__ */ (0,
|
|
5220
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
4976
5221
|
"text",
|
|
4977
5222
|
{
|
|
4978
|
-
x:
|
|
4979
|
-
y:
|
|
5223
|
+
x: node.transform.x,
|
|
5224
|
+
y: node.transform.y,
|
|
4980
5225
|
textAnchor: "middle",
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
fill:
|
|
4984
|
-
|
|
4985
|
-
children: node.label || node.id
|
|
5226
|
+
dominantBaseline: "middle",
|
|
5227
|
+
fontSize: "10",
|
|
5228
|
+
fill: "#ff0000",
|
|
5229
|
+
children: "?"
|
|
4986
5230
|
}
|
|
4987
5231
|
)
|
|
4988
|
-
]
|
|
4989
|
-
}
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
5232
|
+
] }, node.id);
|
|
5233
|
+
}
|
|
5234
|
+
const transforms = [];
|
|
5235
|
+
const effectiveX = isDragging ? node.transform.x + dragOffset.x : node.transform.x;
|
|
5236
|
+
const effectiveY = isDragging ? node.transform.y + dragOffset.y : node.transform.y;
|
|
5237
|
+
transforms.push(`translate(${effectiveX}, ${effectiveY})`);
|
|
5238
|
+
if (node.transform.rotation) {
|
|
5239
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5240
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5241
|
+
transforms.push(`rotate(${node.transform.rotation}, ${centerX}, ${centerY})`);
|
|
5242
|
+
}
|
|
5243
|
+
if (node.transform.scale && node.transform.scale !== 1) {
|
|
5244
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5245
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5246
|
+
transforms.push(
|
|
5247
|
+
`translate(${centerX}, ${centerY}) scale(${node.transform.scale}) translate(${-centerX}, ${-centerY})`
|
|
5248
|
+
);
|
|
5249
|
+
}
|
|
5250
|
+
if (node.transform.flipX || node.transform.flipY) {
|
|
5251
|
+
const scaleX = node.transform.flipX ? -1 : 1;
|
|
5252
|
+
const scaleY = node.transform.flipY ? -1 : 1;
|
|
5253
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5254
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5255
|
+
transforms.push(
|
|
5256
|
+
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
5257
|
+
);
|
|
5258
|
+
}
|
|
5259
|
+
const statusEntry = resolveStatusColor(node.status, statusColorMap);
|
|
5260
|
+
const isUnknown = isUnknownNode(node);
|
|
5261
|
+
const fillColor = isUnknown ? `url(#${hatchPatternId})` : node.customColors?.fill ?? statusEntry.fill;
|
|
5262
|
+
const strokeColor = isUnknown ? unknownEntry.stroke : node.customColors?.stroke ?? statusEntry.stroke;
|
|
5263
|
+
const appearance = { ...getAppearanceDefaults(node.symbolId), ...node.metadata ?? {} };
|
|
5264
|
+
const ledStyle = {};
|
|
5265
|
+
if (appearance.shape !== void 0) {
|
|
5266
|
+
ledStyle["--led-rx"] = appearance.shape === "circle" ? "50%" : "2";
|
|
5267
|
+
ledStyle["--led-rotate"] = appearance.shape === "diamond" ? "45deg" : "0deg";
|
|
5268
|
+
}
|
|
5269
|
+
if (appearance.led !== void 0) {
|
|
5270
|
+
ledStyle["--led-bezel"] = appearance.led ? "2" : "0";
|
|
5271
|
+
}
|
|
5272
|
+
if (appearance.glow) {
|
|
5273
|
+
const glowColor = isUnknown ? unknownEntry.stroke : fillColor;
|
|
5274
|
+
ledStyle.filter = `drop-shadow(0 0 4px ${glowColor})`;
|
|
5275
|
+
}
|
|
5276
|
+
const ledAnimation = typeof appearance.animation === "string" && appearance.animation !== "none" ? appearance.animation : void 0;
|
|
5277
|
+
const vb = symbol.viewBox;
|
|
5278
|
+
const ox = node.labelOffset?.x ?? 0;
|
|
5279
|
+
const oy = node.labelOffset?.y ?? 0;
|
|
5280
|
+
const labelPos = typeof appearance.labelPosition === "string" ? appearance.labelPosition : "bottom";
|
|
5281
|
+
let labelX = vb.width / 2 + ox;
|
|
5282
|
+
let labelY = vb.height + 12 + oy;
|
|
5283
|
+
let labelAnchor = "middle";
|
|
5284
|
+
if (labelPos === "top") {
|
|
5285
|
+
labelX = vb.width / 2 + ox;
|
|
5286
|
+
labelY = -6 + oy;
|
|
5287
|
+
labelAnchor = "middle";
|
|
5288
|
+
} else if (labelPos === "left") {
|
|
5289
|
+
labelX = -6 + ox;
|
|
5290
|
+
labelY = vb.height / 2 + oy;
|
|
5291
|
+
labelAnchor = "end";
|
|
5292
|
+
} else if (labelPos === "right") {
|
|
5293
|
+
labelX = vb.width + 6 + ox;
|
|
5294
|
+
labelY = vb.height / 2 + oy;
|
|
5295
|
+
labelAnchor = "start";
|
|
5296
|
+
}
|
|
5297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
5298
|
+
"g",
|
|
5299
|
+
{
|
|
5300
|
+
"data-node-id": node.id,
|
|
5301
|
+
"data-symbol-id": node.symbolId,
|
|
5302
|
+
"data-selected": isSelected,
|
|
5303
|
+
"data-dragging": isDragging,
|
|
5304
|
+
"data-led-animation": ledAnimation,
|
|
5305
|
+
"data-position-unknown": node.positionUnknown === true ? "true" : void 0,
|
|
5306
|
+
transform: transforms.join(" "),
|
|
5307
|
+
style: {
|
|
5308
|
+
"--symbol-fill": fillColor,
|
|
5309
|
+
"--symbol-stroke": strokeColor,
|
|
5310
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default",
|
|
5311
|
+
...ledStyle
|
|
5312
|
+
},
|
|
5313
|
+
onClick: (e) => {
|
|
5314
|
+
e.stopPropagation();
|
|
5315
|
+
onNodeClick?.(node.id, e);
|
|
5316
|
+
},
|
|
5317
|
+
onDoubleClick: (e) => {
|
|
5318
|
+
e.stopPropagation();
|
|
5319
|
+
onNodeDoubleClick?.(node.id, e);
|
|
5320
|
+
},
|
|
5321
|
+
onMouseDown: (e) => {
|
|
5322
|
+
if (enableDrag) {
|
|
5323
|
+
onNodeDragStart?.(node.id, e);
|
|
5324
|
+
}
|
|
5325
|
+
},
|
|
5326
|
+
onTouchStart: (e) => {
|
|
5327
|
+
if (enableDrag) {
|
|
5328
|
+
e.stopPropagation();
|
|
5329
|
+
onNodeDragStart?.(node.id, e);
|
|
5330
|
+
}
|
|
5331
|
+
},
|
|
5332
|
+
children: [
|
|
5333
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5334
|
+
"rect",
|
|
5335
|
+
{
|
|
5336
|
+
x: "-5",
|
|
5337
|
+
y: "-5",
|
|
5338
|
+
width: symbol.viewBox.width + 10,
|
|
5339
|
+
height: symbol.viewBox.height + 10,
|
|
5340
|
+
fill: "none",
|
|
5341
|
+
stroke: isDragging ? "#10b981" : "#3b82f6",
|
|
5342
|
+
strokeWidth: isDragging ? "3" : "2",
|
|
5343
|
+
strokeDasharray: "4 2",
|
|
5344
|
+
rx: "2",
|
|
5345
|
+
pointerEvents: "none"
|
|
5346
|
+
}
|
|
5347
|
+
),
|
|
5348
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5349
|
+
"g",
|
|
5350
|
+
{
|
|
5351
|
+
dangerouslySetInnerHTML: { __html: symbol.svgContent },
|
|
5352
|
+
"data-symbol-content": symbol.id,
|
|
5353
|
+
style: { pointerEvents: "auto" }
|
|
5354
|
+
}
|
|
5355
|
+
),
|
|
5356
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5357
|
+
"text",
|
|
5358
|
+
{
|
|
5359
|
+
x: labelX,
|
|
5360
|
+
y: labelY,
|
|
5361
|
+
textAnchor: labelAnchor,
|
|
5362
|
+
fontSize: node.labelFontSize ?? 10,
|
|
5363
|
+
fontWeight: "600",
|
|
5364
|
+
fill: isSelected ? "#3b82f6" : "#1f2937",
|
|
5365
|
+
transform: node.transform.rotation ? `rotate(${-node.transform.rotation}, ${labelX}, ${labelY})` : void 0,
|
|
5366
|
+
children: node.label || node.id
|
|
5367
|
+
}
|
|
5368
|
+
)
|
|
5369
|
+
]
|
|
5370
|
+
},
|
|
5371
|
+
node.id
|
|
5372
|
+
);
|
|
5373
|
+
})
|
|
5374
|
+
] });
|
|
4993
5375
|
}
|
|
4994
|
-
var NodeRenderer =
|
|
5376
|
+
var NodeRenderer = import_react11.default.memo(NodeRendererImpl);
|
|
4995
5377
|
|
|
4996
5378
|
// src/components/PIDCanvas/PipeRenderer.tsx
|
|
4997
|
-
var
|
|
4998
|
-
var
|
|
5379
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
5380
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
4999
5381
|
function PipeRendererImpl({
|
|
5000
5382
|
pipes,
|
|
5001
5383
|
selectedPipeIds,
|
|
@@ -5010,7 +5392,7 @@ function PipeRendererImpl({
|
|
|
5010
5392
|
waypointDragOffset,
|
|
5011
5393
|
onPipeSegmentClick
|
|
5012
5394
|
}) {
|
|
5013
|
-
return /* @__PURE__ */ (0,
|
|
5395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
|
|
5014
5396
|
const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
|
|
5015
5397
|
const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
|
|
5016
5398
|
const showEditingControls = enableWaypointEditing && isSelected;
|
|
@@ -5029,7 +5411,7 @@ function PipeRendererImpl({
|
|
|
5029
5411
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
5030
5412
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
5031
5413
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
5032
|
-
return /* @__PURE__ */ (0,
|
|
5414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
5033
5415
|
"g",
|
|
5034
5416
|
{
|
|
5035
5417
|
"data-pipe-id": pipe.id,
|
|
@@ -5042,8 +5424,8 @@ function PipeRendererImpl({
|
|
|
5042
5424
|
cursor: onPipeClick ? "pointer" : "default"
|
|
5043
5425
|
},
|
|
5044
5426
|
children: [
|
|
5045
|
-
!enableWaypointEditing && /* @__PURE__ */ (0,
|
|
5046
|
-
onPipeClick && /* @__PURE__ */ (0,
|
|
5427
|
+
!enableWaypointEditing && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
5428
|
+
onPipeClick && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5047
5429
|
"polyline",
|
|
5048
5430
|
{
|
|
5049
5431
|
points: pointsString,
|
|
@@ -5055,7 +5437,7 @@ function PipeRendererImpl({
|
|
|
5055
5437
|
pointerEvents: "stroke"
|
|
5056
5438
|
}
|
|
5057
5439
|
),
|
|
5058
|
-
/* @__PURE__ */ (0,
|
|
5440
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5059
5441
|
"polyline",
|
|
5060
5442
|
{
|
|
5061
5443
|
points: pointsString,
|
|
@@ -5079,7 +5461,7 @@ function PipeRendererImpl({
|
|
|
5079
5461
|
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
5080
5462
|
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
5081
5463
|
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
5082
|
-
return /* @__PURE__ */ (0,
|
|
5464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5083
5465
|
"circle",
|
|
5084
5466
|
{
|
|
5085
5467
|
cx: point.x,
|
|
@@ -5116,12 +5498,12 @@ function PipeRendererImpl({
|
|
|
5116
5498
|
`${pipe.id}-point-${idx}`
|
|
5117
5499
|
);
|
|
5118
5500
|
}),
|
|
5119
|
-
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0,
|
|
5501
|
+
showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: displayPoints.slice(0, -1).map((point, idx) => {
|
|
5120
5502
|
const nextPoint = displayPoints[idx + 1];
|
|
5121
5503
|
const midX = (point.x + nextPoint.x) / 2;
|
|
5122
5504
|
const midY = (point.y + nextPoint.y) / 2;
|
|
5123
|
-
return /* @__PURE__ */ (0,
|
|
5124
|
-
/* @__PURE__ */ (0,
|
|
5505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("g", { children: [
|
|
5506
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5125
5507
|
"circle",
|
|
5126
5508
|
{
|
|
5127
5509
|
cx: midX,
|
|
@@ -5137,7 +5519,7 @@ function PipeRendererImpl({
|
|
|
5137
5519
|
}
|
|
5138
5520
|
}
|
|
5139
5521
|
),
|
|
5140
|
-
/* @__PURE__ */ (0,
|
|
5522
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5141
5523
|
"circle",
|
|
5142
5524
|
{
|
|
5143
5525
|
cx: midX,
|
|
@@ -5153,7 +5535,7 @@ function PipeRendererImpl({
|
|
|
5153
5535
|
)
|
|
5154
5536
|
] }, `${pipe.id}-segment-${idx}`);
|
|
5155
5537
|
}) }),
|
|
5156
|
-
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0,
|
|
5538
|
+
pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5157
5539
|
"text",
|
|
5158
5540
|
{
|
|
5159
5541
|
x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
|
|
@@ -5173,11 +5555,11 @@ function PipeRendererImpl({
|
|
|
5173
5555
|
);
|
|
5174
5556
|
}) });
|
|
5175
5557
|
}
|
|
5176
|
-
var PipeRenderer =
|
|
5558
|
+
var PipeRenderer = import_react12.default.memo(PipeRendererImpl);
|
|
5177
5559
|
|
|
5178
5560
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
5179
|
-
var
|
|
5180
|
-
var
|
|
5561
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
5562
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5181
5563
|
var PULSE_KEYFRAME_ID = "pid-data-overlay-pulse-keyframes";
|
|
5182
5564
|
var PULSE_ANIMATION = "pid-data-overlay-pulse 1.5s ease-in-out infinite";
|
|
5183
5565
|
function ensurePulseKeyframes() {
|
|
@@ -5188,9 +5570,10 @@ function ensurePulseKeyframes() {
|
|
|
5188
5570
|
style.textContent = "@keyframes pid-data-overlay-pulse{0%{opacity:.9}50%{opacity:.3}100%{opacity:.9}}";
|
|
5189
5571
|
document.head.appendChild(style);
|
|
5190
5572
|
}
|
|
5191
|
-
function renderStatusDot(cx, cy, scale, fill) {
|
|
5192
|
-
|
|
5193
|
-
|
|
5573
|
+
function renderStatusDot(cx, cy, scale, fill, status) {
|
|
5574
|
+
const isUnknown = normalizeDeviceStatus(status) === "unknown";
|
|
5575
|
+
if (!isUnknown) ensurePulseKeyframes();
|
|
5576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5194
5577
|
"circle",
|
|
5195
5578
|
{
|
|
5196
5579
|
className: "pid-data-overlay-status-dot",
|
|
@@ -5198,7 +5581,7 @@ function renderStatusDot(cx, cy, scale, fill) {
|
|
|
5198
5581
|
cy: cy - 18 * scale,
|
|
5199
5582
|
r: 3 * scale,
|
|
5200
5583
|
fill,
|
|
5201
|
-
style: { animation: PULSE_ANIMATION }
|
|
5584
|
+
style: isUnknown ? void 0 : { animation: PULSE_ANIMATION }
|
|
5202
5585
|
}
|
|
5203
5586
|
);
|
|
5204
5587
|
}
|
|
@@ -5224,7 +5607,7 @@ function DataOverlayImpl({
|
|
|
5224
5607
|
const backgroundColor = display?.backgroundColor;
|
|
5225
5608
|
const offsetX = display?.offsetX ?? 0;
|
|
5226
5609
|
const offsetY = display?.offsetY ?? 0;
|
|
5227
|
-
const sparklinePath =
|
|
5610
|
+
const sparklinePath = import_react13.default.useMemo(() => {
|
|
5228
5611
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
5229
5612
|
const width = 70 * scale;
|
|
5230
5613
|
const height = 20 * scale;
|
|
@@ -5243,7 +5626,7 @@ function DataOverlayImpl({
|
|
|
5243
5626
|
return `M ${points.join(" L ")}`;
|
|
5244
5627
|
}, [showSparkline, history, scaling, scale]);
|
|
5245
5628
|
if (!showValue) {
|
|
5246
|
-
return /* @__PURE__ */ (0,
|
|
5629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, {});
|
|
5247
5630
|
}
|
|
5248
5631
|
const formatValue = (val) => {
|
|
5249
5632
|
if (typeof val === "number") {
|
|
@@ -5268,10 +5651,11 @@ function DataOverlayImpl({
|
|
|
5268
5651
|
const extraMarkRows = realDisplayText ? 1 : 0;
|
|
5269
5652
|
const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale + extraMarkRows * 9 * scale;
|
|
5270
5653
|
const overlayWidth = 80 * scale;
|
|
5654
|
+
const isUnknownValue = normalizeDeviceStatus(value.status) === "unknown";
|
|
5271
5655
|
const displayX = x + offsetX;
|
|
5272
5656
|
const displayY = y + offsetY;
|
|
5273
|
-
return /* @__PURE__ */ (0,
|
|
5274
|
-
/* @__PURE__ */ (0,
|
|
5657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, "data-forced": isForced, children: [
|
|
5658
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5275
5659
|
"rect",
|
|
5276
5660
|
{
|
|
5277
5661
|
x: displayX - overlayWidth / 2,
|
|
@@ -5286,7 +5670,7 @@ function DataOverlayImpl({
|
|
|
5286
5670
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
5287
5671
|
}
|
|
5288
5672
|
),
|
|
5289
|
-
label && /* @__PURE__ */ (0,
|
|
5673
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5290
5674
|
"text",
|
|
5291
5675
|
{
|
|
5292
5676
|
x: displayX,
|
|
@@ -5299,7 +5683,7 @@ function DataOverlayImpl({
|
|
|
5299
5683
|
children: label
|
|
5300
5684
|
}
|
|
5301
5685
|
),
|
|
5302
|
-
/* @__PURE__ */ (0,
|
|
5686
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5303
5687
|
"text",
|
|
5304
5688
|
{
|
|
5305
5689
|
x: displayX,
|
|
@@ -5312,8 +5696,17 @@ function DataOverlayImpl({
|
|
|
5312
5696
|
children: displayText
|
|
5313
5697
|
}
|
|
5314
5698
|
),
|
|
5315
|
-
showStatus && value.status !== "normal" && renderStatusDot(displayX, displayY, scale, finalTextColor),
|
|
5316
|
-
|
|
5699
|
+
showStatus && value.status !== "normal" && renderStatusDot(displayX, displayY, scale, finalTextColor, value.status),
|
|
5700
|
+
showStatus && isUnknownValue && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5701
|
+
UnknownStatusGlyph,
|
|
5702
|
+
{
|
|
5703
|
+
x: displayX - overlayWidth / 2 + 2 * scale,
|
|
5704
|
+
y: displayY - 25 * scale - 6 * scale,
|
|
5705
|
+
width: 12 * scale,
|
|
5706
|
+
height: 12 * scale
|
|
5707
|
+
}
|
|
5708
|
+
),
|
|
5709
|
+
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5317
5710
|
"text",
|
|
5318
5711
|
{
|
|
5319
5712
|
x: displayX,
|
|
@@ -5330,13 +5723,13 @@ function DataOverlayImpl({
|
|
|
5330
5723
|
]
|
|
5331
5724
|
}
|
|
5332
5725
|
),
|
|
5333
|
-
isForced && /* @__PURE__ */ (0,
|
|
5726
|
+
isForced && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5334
5727
|
"g",
|
|
5335
5728
|
{
|
|
5336
5729
|
transform: `translate(${displayX + overlayWidth / 2}, ${displayY - 25 * scale})`,
|
|
5337
5730
|
"aria-label": "Forced",
|
|
5338
5731
|
children: [
|
|
5339
|
-
/* @__PURE__ */ (0,
|
|
5732
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5340
5733
|
"circle",
|
|
5341
5734
|
{
|
|
5342
5735
|
r: 7 * scale,
|
|
@@ -5345,7 +5738,7 @@ function DataOverlayImpl({
|
|
|
5345
5738
|
strokeWidth: 1.5 * scale
|
|
5346
5739
|
}
|
|
5347
5740
|
),
|
|
5348
|
-
/* @__PURE__ */ (0,
|
|
5741
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5349
5742
|
"text",
|
|
5350
5743
|
{
|
|
5351
5744
|
textAnchor: "middle",
|
|
@@ -5359,7 +5752,7 @@ function DataOverlayImpl({
|
|
|
5359
5752
|
]
|
|
5360
5753
|
}
|
|
5361
5754
|
),
|
|
5362
|
-
realDisplayText && /* @__PURE__ */ (0,
|
|
5755
|
+
realDisplayText && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5363
5756
|
"text",
|
|
5364
5757
|
{
|
|
5365
5758
|
x: displayX,
|
|
@@ -5372,7 +5765,7 @@ function DataOverlayImpl({
|
|
|
5372
5765
|
children: realDisplayText
|
|
5373
5766
|
}
|
|
5374
5767
|
),
|
|
5375
|
-
hasSparkline && /* @__PURE__ */ (0,
|
|
5768
|
+
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5376
5769
|
"path",
|
|
5377
5770
|
{
|
|
5378
5771
|
d: sparklinePath,
|
|
@@ -5386,11 +5779,11 @@ function DataOverlayImpl({
|
|
|
5386
5779
|
) })
|
|
5387
5780
|
] });
|
|
5388
5781
|
}
|
|
5389
|
-
var DataOverlay =
|
|
5782
|
+
var DataOverlay = import_react13.default.memo(DataOverlayImpl);
|
|
5390
5783
|
|
|
5391
5784
|
// src/components/PIDCanvas/PositionPanel.tsx
|
|
5392
|
-
var
|
|
5393
|
-
var
|
|
5785
|
+
var import_react14 = require("react");
|
|
5786
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5394
5787
|
function PositionPanel({
|
|
5395
5788
|
selectedNode,
|
|
5396
5789
|
selectedWaypoint,
|
|
@@ -5398,9 +5791,9 @@ function PositionPanel({
|
|
|
5398
5791
|
onWaypointPositionChange,
|
|
5399
5792
|
position = "top-right"
|
|
5400
5793
|
}) {
|
|
5401
|
-
const [x, setX] = (0,
|
|
5402
|
-
const [y, setY] = (0,
|
|
5403
|
-
(0,
|
|
5794
|
+
const [x, setX] = (0, import_react14.useState)("");
|
|
5795
|
+
const [y, setY] = (0, import_react14.useState)("");
|
|
5796
|
+
(0, import_react14.useEffect)(() => {
|
|
5404
5797
|
if (selectedNode) {
|
|
5405
5798
|
setX(selectedNode.transform.x.toFixed(2));
|
|
5406
5799
|
setY(selectedNode.transform.y.toFixed(2));
|
|
@@ -5459,7 +5852,7 @@ function PositionPanel({
|
|
|
5459
5852
|
"bottom-left": { bottom: 10, left: 10 },
|
|
5460
5853
|
"bottom-right": { bottom: 10, right: 10 }
|
|
5461
5854
|
};
|
|
5462
|
-
return /* @__PURE__ */ (0,
|
|
5855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5463
5856
|
"div",
|
|
5464
5857
|
{
|
|
5465
5858
|
style: {
|
|
@@ -5476,11 +5869,11 @@ function PositionPanel({
|
|
|
5476
5869
|
fontSize: "13px"
|
|
5477
5870
|
},
|
|
5478
5871
|
children: [
|
|
5479
|
-
/* @__PURE__ */ (0,
|
|
5480
|
-
/* @__PURE__ */ (0,
|
|
5481
|
-
/* @__PURE__ */ (0,
|
|
5482
|
-
/* @__PURE__ */ (0,
|
|
5483
|
-
/* @__PURE__ */ (0,
|
|
5872
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
5873
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
5874
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
5875
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
5876
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5484
5877
|
"input",
|
|
5485
5878
|
{
|
|
5486
5879
|
type: "number",
|
|
@@ -5498,9 +5891,9 @@ function PositionPanel({
|
|
|
5498
5891
|
}
|
|
5499
5892
|
)
|
|
5500
5893
|
] }),
|
|
5501
|
-
/* @__PURE__ */ (0,
|
|
5502
|
-
/* @__PURE__ */ (0,
|
|
5503
|
-
/* @__PURE__ */ (0,
|
|
5894
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
5895
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
5896
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5504
5897
|
"input",
|
|
5505
5898
|
{
|
|
5506
5899
|
type: "number",
|
|
@@ -5519,14 +5912,14 @@ function PositionPanel({
|
|
|
5519
5912
|
)
|
|
5520
5913
|
] })
|
|
5521
5914
|
] }),
|
|
5522
|
-
/* @__PURE__ */ (0,
|
|
5915
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
5523
5916
|
]
|
|
5524
5917
|
}
|
|
5525
5918
|
);
|
|
5526
5919
|
}
|
|
5527
5920
|
|
|
5528
5921
|
// src/diagram/hooks/useViewBox.ts
|
|
5529
|
-
var
|
|
5922
|
+
var import_react15 = require("react");
|
|
5530
5923
|
function useViewBox(options) {
|
|
5531
5924
|
const {
|
|
5532
5925
|
initialViewBox,
|
|
@@ -5537,16 +5930,16 @@ function useViewBox(options) {
|
|
|
5537
5930
|
zoomSensitivity = 1e-3,
|
|
5538
5931
|
allowLeftClickPan = true
|
|
5539
5932
|
} = options;
|
|
5540
|
-
const [viewBox, setViewBox] = (0,
|
|
5541
|
-
const svgRef = (0,
|
|
5542
|
-
const isPanningRef = (0,
|
|
5543
|
-
const lastMousePosRef = (0,
|
|
5544
|
-
const spaceKeyDownRef = (0,
|
|
5545
|
-
const lastTouchDistanceRef = (0,
|
|
5546
|
-
const resetViewBox = (0,
|
|
5933
|
+
const [viewBox, setViewBox] = (0, import_react15.useState)(initialViewBox);
|
|
5934
|
+
const svgRef = (0, import_react15.useRef)(null);
|
|
5935
|
+
const isPanningRef = (0, import_react15.useRef)(false);
|
|
5936
|
+
const lastMousePosRef = (0, import_react15.useRef)({ x: 0, y: 0 });
|
|
5937
|
+
const spaceKeyDownRef = (0, import_react15.useRef)(false);
|
|
5938
|
+
const lastTouchDistanceRef = (0, import_react15.useRef)(null);
|
|
5939
|
+
const resetViewBox = (0, import_react15.useCallback)(() => {
|
|
5547
5940
|
setViewBox(initialViewBox);
|
|
5548
5941
|
}, [initialViewBox]);
|
|
5549
|
-
const zoomIn = (0,
|
|
5942
|
+
const zoomIn = (0, import_react15.useCallback)(() => {
|
|
5550
5943
|
setViewBox((prev) => {
|
|
5551
5944
|
const currentZoom = initialViewBox.width / prev.width;
|
|
5552
5945
|
const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
|
|
@@ -5563,7 +5956,7 @@ function useViewBox(options) {
|
|
|
5563
5956
|
};
|
|
5564
5957
|
});
|
|
5565
5958
|
}, [initialViewBox, minZoom]);
|
|
5566
|
-
const zoomOut = (0,
|
|
5959
|
+
const zoomOut = (0, import_react15.useCallback)(() => {
|
|
5567
5960
|
setViewBox((prev) => {
|
|
5568
5961
|
const currentZoom = initialViewBox.width / prev.width;
|
|
5569
5962
|
const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
|
|
@@ -5580,7 +5973,7 @@ function useViewBox(options) {
|
|
|
5580
5973
|
};
|
|
5581
5974
|
});
|
|
5582
5975
|
}, [initialViewBox, maxZoom]);
|
|
5583
|
-
const fitToContent = (0,
|
|
5976
|
+
const fitToContent = (0, import_react15.useCallback)((bounds, padding = 50) => {
|
|
5584
5977
|
const contentWidth = bounds.maxX - bounds.minX;
|
|
5585
5978
|
const contentHeight = bounds.maxY - bounds.minY;
|
|
5586
5979
|
if (contentWidth === 0 || contentHeight === 0) {
|
|
@@ -5608,7 +6001,7 @@ function useViewBox(options) {
|
|
|
5608
6001
|
height: newHeight
|
|
5609
6002
|
});
|
|
5610
6003
|
}, [initialViewBox]);
|
|
5611
|
-
(0,
|
|
6004
|
+
(0, import_react15.useEffect)(() => {
|
|
5612
6005
|
if (!enableZoom || !svgRef.current) return;
|
|
5613
6006
|
const svg = svgRef.current;
|
|
5614
6007
|
const handleWheel = (e) => {
|
|
@@ -5641,7 +6034,7 @@ function useViewBox(options) {
|
|
|
5641
6034
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
5642
6035
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
5643
6036
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
5644
|
-
(0,
|
|
6037
|
+
(0, import_react15.useEffect)(() => {
|
|
5645
6038
|
if (!enablePan || !svgRef.current) return;
|
|
5646
6039
|
const svg = svgRef.current;
|
|
5647
6040
|
const handleMouseDown = (e) => {
|
|
@@ -5717,7 +6110,7 @@ function useViewBox(options) {
|
|
|
5717
6110
|
window.removeEventListener("keyup", handleKeyUp);
|
|
5718
6111
|
};
|
|
5719
6112
|
}, [enablePan, allowLeftClickPan]);
|
|
5720
|
-
(0,
|
|
6113
|
+
(0, import_react15.useEffect)(() => {
|
|
5721
6114
|
if (!svgRef.current) return;
|
|
5722
6115
|
if (!enablePan && !enableZoom) return;
|
|
5723
6116
|
const svg = svgRef.current;
|
|
@@ -5808,7 +6201,7 @@ function useViewBox(options) {
|
|
|
5808
6201
|
svg.removeEventListener("touchend", handleTouchEnd);
|
|
5809
6202
|
};
|
|
5810
6203
|
}, [enablePan, enableZoom, minZoom, initialViewBox]);
|
|
5811
|
-
const screenToWorld = (0,
|
|
6204
|
+
const screenToWorld = (0, import_react15.useCallback)(
|
|
5812
6205
|
(screenX, screenY) => {
|
|
5813
6206
|
const svg = svgRef.current;
|
|
5814
6207
|
if (!svg) return { x: screenX, y: screenY };
|
|
@@ -5847,15 +6240,15 @@ function useViewBox(options) {
|
|
|
5847
6240
|
}
|
|
5848
6241
|
|
|
5849
6242
|
// src/diagram/hooks/useSelection.ts
|
|
5850
|
-
var
|
|
6243
|
+
var import_react16 = require("react");
|
|
5851
6244
|
function useSelection(options = {}) {
|
|
5852
6245
|
const {
|
|
5853
6246
|
multiSelect = true,
|
|
5854
6247
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
5855
6248
|
onSelectionChange
|
|
5856
6249
|
} = options;
|
|
5857
|
-
const [selection, setSelection] = (0,
|
|
5858
|
-
const notifyChange = (0,
|
|
6250
|
+
const [selection, setSelection] = (0, import_react16.useState)(initialSelection);
|
|
6251
|
+
const notifyChange = (0, import_react16.useCallback)(
|
|
5859
6252
|
(newSelection) => {
|
|
5860
6253
|
if (onSelectionChange) {
|
|
5861
6254
|
onSelectionChange(newSelection);
|
|
@@ -5863,15 +6256,15 @@ function useSelection(options = {}) {
|
|
|
5863
6256
|
},
|
|
5864
6257
|
[onSelectionChange]
|
|
5865
6258
|
);
|
|
5866
|
-
const isNodeSelected = (0,
|
|
6259
|
+
const isNodeSelected = (0, import_react16.useCallback)(
|
|
5867
6260
|
(nodeId) => selection.selectedNodeIds.has(nodeId),
|
|
5868
6261
|
[selection.selectedNodeIds]
|
|
5869
6262
|
);
|
|
5870
|
-
const isPipeSelected = (0,
|
|
6263
|
+
const isPipeSelected = (0, import_react16.useCallback)(
|
|
5871
6264
|
(pipeId) => selection.selectedPipeIds.has(pipeId),
|
|
5872
6265
|
[selection.selectedPipeIds]
|
|
5873
6266
|
);
|
|
5874
|
-
const selectNode = (0,
|
|
6267
|
+
const selectNode = (0, import_react16.useCallback)(
|
|
5875
6268
|
(nodeId, isMultiSelect = false) => {
|
|
5876
6269
|
setSelection((prev) => {
|
|
5877
6270
|
const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
|
|
@@ -5890,7 +6283,7 @@ function useSelection(options = {}) {
|
|
|
5890
6283
|
},
|
|
5891
6284
|
[multiSelect, notifyChange]
|
|
5892
6285
|
);
|
|
5893
|
-
const selectPipe = (0,
|
|
6286
|
+
const selectPipe = (0, import_react16.useCallback)(
|
|
5894
6287
|
(pipeId, isMultiSelect = false) => {
|
|
5895
6288
|
setSelection((prev) => {
|
|
5896
6289
|
const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
|
|
@@ -5909,7 +6302,7 @@ function useSelection(options = {}) {
|
|
|
5909
6302
|
},
|
|
5910
6303
|
[multiSelect, notifyChange]
|
|
5911
6304
|
);
|
|
5912
|
-
const clearSelection = (0,
|
|
6305
|
+
const clearSelection = (0, import_react16.useCallback)(() => {
|
|
5913
6306
|
const newSelection = {
|
|
5914
6307
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
5915
6308
|
selectedPipeIds: /* @__PURE__ */ new Set()
|
|
@@ -5917,7 +6310,7 @@ function useSelection(options = {}) {
|
|
|
5917
6310
|
setSelection(newSelection);
|
|
5918
6311
|
notifyChange(newSelection);
|
|
5919
6312
|
}, [notifyChange]);
|
|
5920
|
-
const selectNodes = (0,
|
|
6313
|
+
const selectNodes = (0, import_react16.useCallback)(
|
|
5921
6314
|
(nodeIds) => {
|
|
5922
6315
|
const newSelection = {
|
|
5923
6316
|
selectedNodeIds: new Set(nodeIds),
|
|
@@ -5928,7 +6321,7 @@ function useSelection(options = {}) {
|
|
|
5928
6321
|
},
|
|
5929
6322
|
[notifyChange]
|
|
5930
6323
|
);
|
|
5931
|
-
const selectPipes = (0,
|
|
6324
|
+
const selectPipes = (0, import_react16.useCallback)(
|
|
5932
6325
|
(pipeIds) => {
|
|
5933
6326
|
const newSelection = {
|
|
5934
6327
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
@@ -5952,23 +6345,23 @@ function useSelection(options = {}) {
|
|
|
5952
6345
|
}
|
|
5953
6346
|
|
|
5954
6347
|
// src/diagram/hooks/useTelemetry.ts
|
|
5955
|
-
var
|
|
6348
|
+
var import_react17 = require("react");
|
|
5956
6349
|
function useTelemetry(options = {}) {
|
|
5957
6350
|
const {
|
|
5958
6351
|
initialBindings = [],
|
|
5959
6352
|
onTelemetryChange,
|
|
5960
6353
|
refreshInterval = 0
|
|
5961
6354
|
} = options;
|
|
5962
|
-
const [telemetry, setTelemetry] = (0,
|
|
6355
|
+
const [telemetry, setTelemetry] = (0, import_react17.useState)(() => {
|
|
5963
6356
|
const map = /* @__PURE__ */ new Map();
|
|
5964
6357
|
initialBindings.forEach((binding) => {
|
|
5965
6358
|
map.set(binding.nodeId, binding);
|
|
5966
6359
|
});
|
|
5967
6360
|
return map;
|
|
5968
6361
|
});
|
|
5969
|
-
const telemetryRef = (0,
|
|
6362
|
+
const telemetryRef = (0, import_react17.useRef)(telemetry);
|
|
5970
6363
|
telemetryRef.current = telemetry;
|
|
5971
|
-
const notifyChange = (0,
|
|
6364
|
+
const notifyChange = (0, import_react17.useCallback)(
|
|
5972
6365
|
(newTelemetry) => {
|
|
5973
6366
|
if (onTelemetryChange) {
|
|
5974
6367
|
onTelemetryChange(newTelemetry);
|
|
@@ -5976,7 +6369,7 @@ function useTelemetry(options = {}) {
|
|
|
5976
6369
|
},
|
|
5977
6370
|
[onTelemetryChange]
|
|
5978
6371
|
);
|
|
5979
|
-
const updateTelemetry = (0,
|
|
6372
|
+
const updateTelemetry = (0, import_react17.useCallback)(
|
|
5980
6373
|
(nodeId, value) => {
|
|
5981
6374
|
setTelemetry((prev) => {
|
|
5982
6375
|
const newMap = new Map(prev);
|
|
@@ -6006,7 +6399,7 @@ function useTelemetry(options = {}) {
|
|
|
6006
6399
|
},
|
|
6007
6400
|
[notifyChange]
|
|
6008
6401
|
);
|
|
6009
|
-
const updateTelemetryBatch = (0,
|
|
6402
|
+
const updateTelemetryBatch = (0, import_react17.useCallback)(
|
|
6010
6403
|
(updates) => {
|
|
6011
6404
|
setTelemetry((prev) => {
|
|
6012
6405
|
const newMap = new Map(prev);
|
|
@@ -6060,16 +6453,16 @@ function useTelemetry(options = {}) {
|
|
|
6060
6453
|
},
|
|
6061
6454
|
[notifyChange]
|
|
6062
6455
|
);
|
|
6063
|
-
const getTelemetry = (0,
|
|
6456
|
+
const getTelemetry = (0, import_react17.useCallback)(
|
|
6064
6457
|
(nodeId) => telemetryRef.current.get(nodeId),
|
|
6065
6458
|
[]
|
|
6066
6459
|
);
|
|
6067
|
-
const clearTelemetry = (0,
|
|
6460
|
+
const clearTelemetry = (0, import_react17.useCallback)(() => {
|
|
6068
6461
|
const newMap = /* @__PURE__ */ new Map();
|
|
6069
6462
|
setTelemetry(newMap);
|
|
6070
6463
|
notifyChange(newMap);
|
|
6071
6464
|
}, [notifyChange]);
|
|
6072
|
-
const setBindings = (0,
|
|
6465
|
+
const setBindings = (0, import_react17.useCallback)(
|
|
6073
6466
|
(bindings) => {
|
|
6074
6467
|
const newMap = /* @__PURE__ */ new Map();
|
|
6075
6468
|
bindings.forEach((binding) => {
|
|
@@ -6080,7 +6473,7 @@ function useTelemetry(options = {}) {
|
|
|
6080
6473
|
},
|
|
6081
6474
|
[notifyChange]
|
|
6082
6475
|
);
|
|
6083
|
-
(0,
|
|
6476
|
+
(0, import_react17.useEffect)(() => {
|
|
6084
6477
|
if (refreshInterval <= 0) return;
|
|
6085
6478
|
const intervalId = setInterval(() => {
|
|
6086
6479
|
notifyChange(telemetryRef.current);
|
|
@@ -6098,10 +6491,10 @@ function useTelemetry(options = {}) {
|
|
|
6098
6491
|
}
|
|
6099
6492
|
|
|
6100
6493
|
// src/diagram/hooks/useTelemetryStatus.ts
|
|
6101
|
-
var
|
|
6494
|
+
var import_react18 = require("react");
|
|
6102
6495
|
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
6103
6496
|
const { enabled = true, mapStatus } = options;
|
|
6104
|
-
(0,
|
|
6497
|
+
(0, import_react18.useEffect)(() => {
|
|
6105
6498
|
if (!enabled) return;
|
|
6106
6499
|
const defaultMapStatus = (telemetryStatus) => {
|
|
6107
6500
|
switch (telemetryStatus) {
|
|
@@ -6114,8 +6507,13 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
6114
6507
|
return "alarm";
|
|
6115
6508
|
case "off":
|
|
6116
6509
|
return "stopped";
|
|
6117
|
-
|
|
6510
|
+
case "unknown":
|
|
6511
|
+
return "unknown";
|
|
6512
|
+
default: {
|
|
6513
|
+
const exhaustive = telemetryStatus;
|
|
6514
|
+
void exhaustive;
|
|
6118
6515
|
return "stopped";
|
|
6516
|
+
}
|
|
6119
6517
|
}
|
|
6120
6518
|
};
|
|
6121
6519
|
const statusMapper = mapStatus || defaultMapStatus;
|
|
@@ -6139,8 +6537,49 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
6139
6537
|
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
6140
6538
|
}
|
|
6141
6539
|
|
|
6540
|
+
// src/diagram/hooks/useBooleanIndicators.ts
|
|
6541
|
+
var import_react19 = require("react");
|
|
6542
|
+
function useBooleanIndicators(telemetry, diagram, setDiagram, options = {}) {
|
|
6543
|
+
const { enabled = true, symbolId = "status-indicator" } = options;
|
|
6544
|
+
(0, import_react19.useEffect)(() => {
|
|
6545
|
+
if (!enabled) return;
|
|
6546
|
+
const tagIndex = /* @__PURE__ */ new Map();
|
|
6547
|
+
telemetry.forEach((binding) => {
|
|
6548
|
+
if (binding.tag) tagIndex.set(binding.tag, binding.value.value);
|
|
6549
|
+
});
|
|
6550
|
+
let needsUpdate = false;
|
|
6551
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
6552
|
+
if (node.symbolId !== symbolId) return node;
|
|
6553
|
+
const meta = node.metadata ?? {};
|
|
6554
|
+
const colorSource = typeof meta.colorSource === "string" ? meta.colorSource : "";
|
|
6555
|
+
const visibleSource = typeof meta.visibleSource === "string" ? meta.visibleSource : "";
|
|
6556
|
+
let next = node;
|
|
6557
|
+
if (colorSource) {
|
|
6558
|
+
const isTrue = Boolean(tagIndex.get(colorSource));
|
|
6559
|
+
const fill = resolvePresetColor(
|
|
6560
|
+
String(isTrue ? meta.onColor ?? "green" : meta.offColor ?? "red")
|
|
6561
|
+
);
|
|
6562
|
+
if (node.customColors?.fill !== fill) {
|
|
6563
|
+
next = { ...next, customColors: { ...next.customColors, fill } };
|
|
6564
|
+
}
|
|
6565
|
+
}
|
|
6566
|
+
if (visibleSource) {
|
|
6567
|
+
const vis = Boolean(tagIndex.get(visibleSource));
|
|
6568
|
+
if ((next.visible ?? true) !== vis) {
|
|
6569
|
+
next = { ...next, visible: vis };
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6572
|
+
if (next !== node) needsUpdate = true;
|
|
6573
|
+
return next;
|
|
6574
|
+
});
|
|
6575
|
+
if (needsUpdate) {
|
|
6576
|
+
setDiagram({ ...diagram, nodes: updatedNodes });
|
|
6577
|
+
}
|
|
6578
|
+
}, [telemetry, diagram, setDiagram, enabled, symbolId]);
|
|
6579
|
+
}
|
|
6580
|
+
|
|
6142
6581
|
// src/diagram/hooks/useDrag.ts
|
|
6143
|
-
var
|
|
6582
|
+
var import_react20 = require("react");
|
|
6144
6583
|
function useDrag(options = {}) {
|
|
6145
6584
|
const {
|
|
6146
6585
|
onDragStart,
|
|
@@ -6150,23 +6589,23 @@ function useDrag(options = {}) {
|
|
|
6150
6589
|
dragThreshold = 3,
|
|
6151
6590
|
screenToWorld = (x, y) => ({ x, y })
|
|
6152
6591
|
} = options;
|
|
6153
|
-
const [dragState, setDragState] = (0,
|
|
6592
|
+
const [dragState, setDragState] = (0, import_react20.useState)({
|
|
6154
6593
|
isDragging: false,
|
|
6155
6594
|
startPosition: null,
|
|
6156
6595
|
offset: { x: 0, y: 0 },
|
|
6157
6596
|
draggedId: null
|
|
6158
6597
|
});
|
|
6159
|
-
const [isListening, setIsListening] = (0,
|
|
6160
|
-
const dragStartRef = (0,
|
|
6161
|
-
const hasMovedRef = (0,
|
|
6162
|
-
const applySnap = (0,
|
|
6598
|
+
const [isListening, setIsListening] = (0, import_react20.useState)(false);
|
|
6599
|
+
const dragStartRef = (0, import_react20.useRef)(null);
|
|
6600
|
+
const hasMovedRef = (0, import_react20.useRef)(false);
|
|
6601
|
+
const applySnap = (0, import_react20.useCallback)(
|
|
6163
6602
|
(value) => {
|
|
6164
6603
|
if (snapToGrid <= 0) return value;
|
|
6165
6604
|
return Math.round(value / snapToGrid) * snapToGrid;
|
|
6166
6605
|
},
|
|
6167
6606
|
[snapToGrid]
|
|
6168
6607
|
);
|
|
6169
|
-
const handleMouseMove = (0,
|
|
6608
|
+
const handleMouseMove = (0, import_react20.useCallback)(
|
|
6170
6609
|
(event) => {
|
|
6171
6610
|
if (!dragStartRef.current) return;
|
|
6172
6611
|
const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
|
|
@@ -6207,7 +6646,7 @@ function useDrag(options = {}) {
|
|
|
6207
6646
|
},
|
|
6208
6647
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
6209
6648
|
);
|
|
6210
|
-
const handleMouseUp = (0,
|
|
6649
|
+
const handleMouseUp = (0, import_react20.useCallback)(
|
|
6211
6650
|
(event) => {
|
|
6212
6651
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
6213
6652
|
dragStartRef.current = null;
|
|
@@ -6244,7 +6683,7 @@ function useDrag(options = {}) {
|
|
|
6244
6683
|
},
|
|
6245
6684
|
[screenToWorld, applySnap, onDragEnd]
|
|
6246
6685
|
);
|
|
6247
|
-
const handleTouchMove = (0,
|
|
6686
|
+
const handleTouchMove = (0, import_react20.useCallback)(
|
|
6248
6687
|
(event) => {
|
|
6249
6688
|
if (!dragStartRef.current || event.touches.length !== 1) return;
|
|
6250
6689
|
const touch = event.touches[0];
|
|
@@ -6287,7 +6726,7 @@ function useDrag(options = {}) {
|
|
|
6287
6726
|
},
|
|
6288
6727
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
6289
6728
|
);
|
|
6290
|
-
const handleTouchEnd = (0,
|
|
6729
|
+
const handleTouchEnd = (0, import_react20.useCallback)(
|
|
6291
6730
|
(event) => {
|
|
6292
6731
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
6293
6732
|
dragStartRef.current = null;
|
|
@@ -6325,7 +6764,7 @@ function useDrag(options = {}) {
|
|
|
6325
6764
|
},
|
|
6326
6765
|
[screenToWorld, applySnap, onDragEnd]
|
|
6327
6766
|
);
|
|
6328
|
-
(0,
|
|
6767
|
+
(0, import_react20.useEffect)(() => {
|
|
6329
6768
|
if (!isListening) return;
|
|
6330
6769
|
document.addEventListener("mousemove", handleMouseMove);
|
|
6331
6770
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -6340,7 +6779,7 @@ function useDrag(options = {}) {
|
|
|
6340
6779
|
document.removeEventListener("touchcancel", handleTouchEnd);
|
|
6341
6780
|
};
|
|
6342
6781
|
}, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
|
|
6343
|
-
const startDrag = (0,
|
|
6782
|
+
const startDrag = (0, import_react20.useCallback)(
|
|
6344
6783
|
(id, event, itemPosition) => {
|
|
6345
6784
|
event.stopPropagation();
|
|
6346
6785
|
let clientX;
|
|
@@ -6370,7 +6809,7 @@ function useDrag(options = {}) {
|
|
|
6370
6809
|
},
|
|
6371
6810
|
[screenToWorld]
|
|
6372
6811
|
);
|
|
6373
|
-
const cancelDrag = (0,
|
|
6812
|
+
const cancelDrag = (0, import_react20.useCallback)(() => {
|
|
6374
6813
|
dragStartRef.current = null;
|
|
6375
6814
|
hasMovedRef.current = false;
|
|
6376
6815
|
setIsListening(false);
|
|
@@ -6381,7 +6820,7 @@ function useDrag(options = {}) {
|
|
|
6381
6820
|
draggedId: null
|
|
6382
6821
|
});
|
|
6383
6822
|
}, []);
|
|
6384
|
-
const isDraggingItem = (0,
|
|
6823
|
+
const isDraggingItem = (0, import_react20.useCallback)(
|
|
6385
6824
|
(id) => dragState.isDragging && dragState.draggedId === id,
|
|
6386
6825
|
[dragState.isDragging, dragState.draggedId]
|
|
6387
6826
|
);
|
|
@@ -6394,7 +6833,7 @@ function useDrag(options = {}) {
|
|
|
6394
6833
|
}
|
|
6395
6834
|
|
|
6396
6835
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
6397
|
-
var
|
|
6836
|
+
var import_react21 = require("react");
|
|
6398
6837
|
function useKeyboardShortcuts(options) {
|
|
6399
6838
|
const {
|
|
6400
6839
|
onDelete,
|
|
@@ -6405,7 +6844,7 @@ function useKeyboardShortcuts(options) {
|
|
|
6405
6844
|
onSelectAll,
|
|
6406
6845
|
enabled = true
|
|
6407
6846
|
} = options;
|
|
6408
|
-
(0,
|
|
6847
|
+
(0, import_react21.useEffect)(() => {
|
|
6409
6848
|
if (!enabled) return;
|
|
6410
6849
|
const handleKeyDown = (event) => {
|
|
6411
6850
|
const target = event.target;
|
|
@@ -6514,7 +6953,7 @@ function nodeHasPort(node, portId) {
|
|
|
6514
6953
|
}
|
|
6515
6954
|
|
|
6516
6955
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
6517
|
-
var
|
|
6956
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6518
6957
|
var DEFAULT_FEATURES = {
|
|
6519
6958
|
pan: true,
|
|
6520
6959
|
zoom: true,
|
|
@@ -6543,21 +6982,21 @@ function PIDCanvasImpl({
|
|
|
6543
6982
|
statusColorMap,
|
|
6544
6983
|
...props
|
|
6545
6984
|
}) {
|
|
6546
|
-
const [localDiagram, setLocalDiagram] = (0,
|
|
6547
|
-
const [dragOverPosition, setDragOverPosition] = (0,
|
|
6548
|
-
const [isConnecting, setIsConnecting] = (0,
|
|
6549
|
-
const [connectionSource, setConnectionSource] = (0,
|
|
6550
|
-
const [connectionSourcePort, setConnectionSourcePort] = (0,
|
|
6551
|
-
const [connectionCursor, setConnectionCursor] = (0,
|
|
6552
|
-
const [hoveredNode, setHoveredNode] = (0,
|
|
6553
|
-
const [hoveredPort, setHoveredPort] = (0,
|
|
6554
|
-
const [selectedWaypoint, setSelectedWaypoint] = (0,
|
|
6555
|
-
const historyStack = (0,
|
|
6556
|
-
const redoStack = (0,
|
|
6557
|
-
const isUndoRedoAction = (0,
|
|
6558
|
-
const isInternalChange = (0,
|
|
6559
|
-
const lastInternalDiagram = (0,
|
|
6560
|
-
(0,
|
|
6985
|
+
const [localDiagram, setLocalDiagram] = (0, import_react22.useState)(diagram);
|
|
6986
|
+
const [dragOverPosition, setDragOverPosition] = (0, import_react22.useState)(null);
|
|
6987
|
+
const [isConnecting, setIsConnecting] = (0, import_react22.useState)(false);
|
|
6988
|
+
const [connectionSource, setConnectionSource] = (0, import_react22.useState)(null);
|
|
6989
|
+
const [connectionSourcePort, setConnectionSourcePort] = (0, import_react22.useState)(null);
|
|
6990
|
+
const [connectionCursor, setConnectionCursor] = (0, import_react22.useState)(null);
|
|
6991
|
+
const [hoveredNode, setHoveredNode] = (0, import_react22.useState)(null);
|
|
6992
|
+
const [hoveredPort, setHoveredPort] = (0, import_react22.useState)(null);
|
|
6993
|
+
const [selectedWaypoint, setSelectedWaypoint] = (0, import_react22.useState)(null);
|
|
6994
|
+
const historyStack = (0, import_react22.useRef)([]);
|
|
6995
|
+
const redoStack = (0, import_react22.useRef)([]);
|
|
6996
|
+
const isUndoRedoAction = (0, import_react22.useRef)(false);
|
|
6997
|
+
const isInternalChange = (0, import_react22.useRef)(false);
|
|
6998
|
+
const lastInternalDiagram = (0, import_react22.useRef)(null);
|
|
6999
|
+
(0, import_react22.useEffect)(() => {
|
|
6561
7000
|
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
6562
7001
|
if (isExternal) {
|
|
6563
7002
|
setLocalDiagram(diagram);
|
|
@@ -6579,7 +7018,7 @@ function PIDCanvasImpl({
|
|
|
6579
7018
|
enablePan: features.pan ?? true,
|
|
6580
7019
|
enableZoom: features.zoom ?? true
|
|
6581
7020
|
});
|
|
6582
|
-
const calculateContentBounds = (0,
|
|
7021
|
+
const calculateContentBounds = (0, import_react22.useCallback)(() => {
|
|
6583
7022
|
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
6584
7023
|
if (nodes2.length === 0) {
|
|
6585
7024
|
return null;
|
|
@@ -6602,7 +7041,7 @@ function PIDCanvasImpl({
|
|
|
6602
7041
|
});
|
|
6603
7042
|
return { minX, minY, maxX, maxY };
|
|
6604
7043
|
}, [localDiagram.nodes]);
|
|
6605
|
-
(0,
|
|
7044
|
+
(0, import_react22.useEffect)(() => {
|
|
6606
7045
|
if (onMounted) {
|
|
6607
7046
|
const controls = {
|
|
6608
7047
|
fitToContent: (padding = 50) => {
|
|
@@ -6643,8 +7082,8 @@ function PIDCanvasImpl({
|
|
|
6643
7082
|
});
|
|
6644
7083
|
const dragEnabled = features.dragNodes ?? false;
|
|
6645
7084
|
const selectionEnabled = features.selection ?? false;
|
|
6646
|
-
const containerRef = (0,
|
|
6647
|
-
const pushToHistory = (0,
|
|
7085
|
+
const containerRef = (0, import_react22.useRef)(null);
|
|
7086
|
+
const pushToHistory = (0, import_react22.useCallback)((currentDiagram) => {
|
|
6648
7087
|
if (isUndoRedoAction.current) return;
|
|
6649
7088
|
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
6650
7089
|
historyStack.current.push(snapshot);
|
|
@@ -6653,7 +7092,7 @@ function PIDCanvasImpl({
|
|
|
6653
7092
|
}
|
|
6654
7093
|
redoStack.current = [];
|
|
6655
7094
|
}, []);
|
|
6656
|
-
const undo = (0,
|
|
7095
|
+
const undo = (0, import_react22.useCallback)(() => {
|
|
6657
7096
|
if (historyStack.current.length === 0) return;
|
|
6658
7097
|
isUndoRedoAction.current = true;
|
|
6659
7098
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -6667,7 +7106,7 @@ function PIDCanvasImpl({
|
|
|
6667
7106
|
isUndoRedoAction.current = false;
|
|
6668
7107
|
}, 0);
|
|
6669
7108
|
}, [localDiagram, onDiagramChange]);
|
|
6670
|
-
const redo = (0,
|
|
7109
|
+
const redo = (0, import_react22.useCallback)(() => {
|
|
6671
7110
|
if (redoStack.current.length === 0) return;
|
|
6672
7111
|
isUndoRedoAction.current = true;
|
|
6673
7112
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -6681,7 +7120,7 @@ function PIDCanvasImpl({
|
|
|
6681
7120
|
isUndoRedoAction.current = false;
|
|
6682
7121
|
}, 0);
|
|
6683
7122
|
}, [localDiagram, onDiagramChange]);
|
|
6684
|
-
(0,
|
|
7123
|
+
(0, import_react22.useEffect)(() => {
|
|
6685
7124
|
const handleKeyDown = (e) => {
|
|
6686
7125
|
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
6687
7126
|
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
@@ -6698,7 +7137,7 @@ function PIDCanvasImpl({
|
|
|
6698
7137
|
window.addEventListener("keydown", handleKeyDown);
|
|
6699
7138
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
6700
7139
|
}, [undo, redo]);
|
|
6701
|
-
(0,
|
|
7140
|
+
(0, import_react22.useEffect)(() => {
|
|
6702
7141
|
if (!features.dragNodes) return;
|
|
6703
7142
|
const handleKeyDown = (e) => {
|
|
6704
7143
|
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
@@ -6783,7 +7222,7 @@ function PIDCanvasImpl({
|
|
|
6783
7222
|
onNodeMove,
|
|
6784
7223
|
pushToHistory
|
|
6785
7224
|
]);
|
|
6786
|
-
const handlePositionChange = (0,
|
|
7225
|
+
const handlePositionChange = (0, import_react22.useCallback)(
|
|
6787
7226
|
(nodeId, x, y) => {
|
|
6788
7227
|
pushToHistory(localDiagram);
|
|
6789
7228
|
const updatedNodes = localDiagram.nodes.map(
|
|
@@ -6805,7 +7244,7 @@ function PIDCanvasImpl({
|
|
|
6805
7244
|
},
|
|
6806
7245
|
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
6807
7246
|
);
|
|
6808
|
-
const handleWaypointPositionChange = (0,
|
|
7247
|
+
const handleWaypointPositionChange = (0, import_react22.useCallback)(
|
|
6809
7248
|
(pipeId, pointIndex, x, y) => {
|
|
6810
7249
|
pushToHistory(localDiagram);
|
|
6811
7250
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -6823,7 +7262,7 @@ function PIDCanvasImpl({
|
|
|
6823
7262
|
},
|
|
6824
7263
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
6825
7264
|
);
|
|
6826
|
-
const handleDragEnd = (0,
|
|
7265
|
+
const handleDragEnd = (0, import_react22.useCallback)(
|
|
6827
7266
|
(nodeId, offset, finalPosition) => {
|
|
6828
7267
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
6829
7268
|
if (dragDistance < 2) {
|
|
@@ -6904,7 +7343,7 @@ function PIDCanvasImpl({
|
|
|
6904
7343
|
onDiagramChange?.(updatedDiagram);
|
|
6905
7344
|
}
|
|
6906
7345
|
});
|
|
6907
|
-
const handleNodeDragStart = (0,
|
|
7346
|
+
const handleNodeDragStart = (0, import_react22.useCallback)(
|
|
6908
7347
|
(nodeId, event) => {
|
|
6909
7348
|
const node = localDiagram.nodes.find((n) => n.id === nodeId);
|
|
6910
7349
|
if (!node) return;
|
|
@@ -6912,7 +7351,7 @@ function PIDCanvasImpl({
|
|
|
6912
7351
|
},
|
|
6913
7352
|
[localDiagram.nodes, startDrag]
|
|
6914
7353
|
);
|
|
6915
|
-
const handleWaypointClick = (0,
|
|
7354
|
+
const handleWaypointClick = (0, import_react22.useCallback)(
|
|
6916
7355
|
(pipeId, pointIndex) => {
|
|
6917
7356
|
setSelectedWaypoint({ pipeId, pointIndex });
|
|
6918
7357
|
if (selectionEnabled) {
|
|
@@ -6921,7 +7360,7 @@ function PIDCanvasImpl({
|
|
|
6921
7360
|
},
|
|
6922
7361
|
[selectionEnabled, clearSelection]
|
|
6923
7362
|
);
|
|
6924
|
-
const handleWaypointDragStart = (0,
|
|
7363
|
+
const handleWaypointDragStart = (0, import_react22.useCallback)(
|
|
6925
7364
|
(pipeId, pointIndex, event) => {
|
|
6926
7365
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
6927
7366
|
if (!pipe || pointIndex >= pipe.routePoints.length) return;
|
|
@@ -6930,7 +7369,7 @@ function PIDCanvasImpl({
|
|
|
6930
7369
|
},
|
|
6931
7370
|
[localDiagram.pipes, startWaypointDrag]
|
|
6932
7371
|
);
|
|
6933
|
-
const handlePipeSegmentClick = (0,
|
|
7372
|
+
const handlePipeSegmentClick = (0, import_react22.useCallback)(
|
|
6934
7373
|
(pipeId, position, segmentIndex) => {
|
|
6935
7374
|
pushToHistory(localDiagram);
|
|
6936
7375
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -6949,7 +7388,7 @@ function PIDCanvasImpl({
|
|
|
6949
7388
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
6950
7389
|
);
|
|
6951
7390
|
const telemetryEnabled = features.telemetry ?? false;
|
|
6952
|
-
const handleDelete = (0,
|
|
7391
|
+
const handleDelete = (0, import_react22.useCallback)(() => {
|
|
6953
7392
|
if (!selectionEnabled) return;
|
|
6954
7393
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
6955
7394
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
@@ -6978,17 +7417,17 @@ function PIDCanvasImpl({
|
|
|
6978
7417
|
onDelete,
|
|
6979
7418
|
pushToHistory
|
|
6980
7419
|
]);
|
|
6981
|
-
const handleCopy = (0,
|
|
7420
|
+
const handleCopy = (0, import_react22.useCallback)(() => {
|
|
6982
7421
|
if (!selectionEnabled) return;
|
|
6983
7422
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
6984
7423
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
6985
7424
|
onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
6986
7425
|
}, [selection, selectionEnabled, onItemsCopied]);
|
|
6987
|
-
const handlePaste = (0,
|
|
7426
|
+
const handlePaste = (0, import_react22.useCallback)(() => {
|
|
6988
7427
|
if (!selectionEnabled) return;
|
|
6989
7428
|
onPaste?.();
|
|
6990
7429
|
}, [selectionEnabled, onPaste]);
|
|
6991
|
-
const handleNodeDoubleClick = (0,
|
|
7430
|
+
const handleNodeDoubleClick = (0, import_react22.useCallback)(
|
|
6992
7431
|
(nodeId, event) => {
|
|
6993
7432
|
if (!selectionEnabled) return;
|
|
6994
7433
|
console.log("Node double-clicked:", nodeId);
|
|
@@ -7002,7 +7441,7 @@ function PIDCanvasImpl({
|
|
|
7002
7441
|
onCopy: handleCopy,
|
|
7003
7442
|
onPaste: handlePaste
|
|
7004
7443
|
});
|
|
7005
|
-
const handleNodeClick = (0,
|
|
7444
|
+
const handleNodeClick = (0, import_react22.useCallback)(
|
|
7006
7445
|
(nodeId, event) => {
|
|
7007
7446
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
7008
7447
|
if (connectionModeEnabled && isConnecting) {
|
|
@@ -7044,7 +7483,7 @@ function PIDCanvasImpl({
|
|
|
7044
7483
|
onNodeClick
|
|
7045
7484
|
]
|
|
7046
7485
|
);
|
|
7047
|
-
const handlePipeClick = (0,
|
|
7486
|
+
const handlePipeClick = (0, import_react22.useCallback)(
|
|
7048
7487
|
(pipeId, event) => {
|
|
7049
7488
|
if (selectionEnabled) {
|
|
7050
7489
|
selectPipe(pipeId, event.ctrlKey || event.metaKey);
|
|
@@ -7063,7 +7502,7 @@ function PIDCanvasImpl({
|
|
|
7063
7502
|
}
|
|
7064
7503
|
setSelectedWaypoint(null);
|
|
7065
7504
|
};
|
|
7066
|
-
const handleDragOver = (0,
|
|
7505
|
+
const handleDragOver = (0, import_react22.useCallback)(
|
|
7067
7506
|
(event) => {
|
|
7068
7507
|
if (!features.allowSymbolDrop) return;
|
|
7069
7508
|
event.preventDefault();
|
|
@@ -7074,7 +7513,7 @@ function PIDCanvasImpl({
|
|
|
7074
7513
|
},
|
|
7075
7514
|
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
7076
7515
|
);
|
|
7077
|
-
const handleDrop = (0,
|
|
7516
|
+
const handleDrop = (0, import_react22.useCallback)(
|
|
7078
7517
|
(event) => {
|
|
7079
7518
|
if (!features.allowSymbolDrop) return;
|
|
7080
7519
|
event.preventDefault();
|
|
@@ -7087,10 +7526,10 @@ function PIDCanvasImpl({
|
|
|
7087
7526
|
},
|
|
7088
7527
|
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
7089
7528
|
);
|
|
7090
|
-
const handleDragLeave = (0,
|
|
7529
|
+
const handleDragLeave = (0, import_react22.useCallback)(() => {
|
|
7091
7530
|
setDragOverPosition(null);
|
|
7092
7531
|
}, []);
|
|
7093
|
-
const handleMouseMove = (0,
|
|
7532
|
+
const handleMouseMove = (0, import_react22.useCallback)(
|
|
7094
7533
|
(event) => {
|
|
7095
7534
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
7096
7535
|
if (connectionModeEnabled) {
|
|
@@ -7127,7 +7566,7 @@ function PIDCanvasImpl({
|
|
|
7127
7566
|
const viewBox = controlledViewBox;
|
|
7128
7567
|
const displayDiagram = localDiagram;
|
|
7129
7568
|
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
7130
|
-
return /* @__PURE__ */ (0,
|
|
7569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
7131
7570
|
"div",
|
|
7132
7571
|
{
|
|
7133
7572
|
ref: containerRef,
|
|
@@ -7142,7 +7581,7 @@ function PIDCanvasImpl({
|
|
|
7142
7581
|
},
|
|
7143
7582
|
...props,
|
|
7144
7583
|
children: [
|
|
7145
|
-
/* @__PURE__ */ (0,
|
|
7584
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
7146
7585
|
"svg",
|
|
7147
7586
|
{
|
|
7148
7587
|
ref: svgRef,
|
|
@@ -7161,15 +7600,15 @@ function PIDCanvasImpl({
|
|
|
7161
7600
|
onDrop: handleDrop,
|
|
7162
7601
|
onDragLeave: handleDragLeave,
|
|
7163
7602
|
children: [
|
|
7164
|
-
features.showGrid !== false ? /* @__PURE__ */ (0,
|
|
7165
|
-
/* @__PURE__ */ (0,
|
|
7166
|
-
/* @__PURE__ */ (0,
|
|
7167
|
-
/* @__PURE__ */ (0,
|
|
7168
|
-
/* @__PURE__ */ (0,
|
|
7169
|
-
/* @__PURE__ */ (0,
|
|
7603
|
+
features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
7604
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("defs", { children: [
|
|
7605
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
7606
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
7607
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
7608
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
7170
7609
|
] })
|
|
7171
7610
|
] }),
|
|
7172
|
-
/* @__PURE__ */ (0,
|
|
7611
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7173
7612
|
"rect",
|
|
7174
7613
|
{
|
|
7175
7614
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -7179,7 +7618,7 @@ function PIDCanvasImpl({
|
|
|
7179
7618
|
fill: "url(#grid-major)"
|
|
7180
7619
|
}
|
|
7181
7620
|
)
|
|
7182
|
-
] }) : /* @__PURE__ */ (0,
|
|
7621
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7183
7622
|
"rect",
|
|
7184
7623
|
{
|
|
7185
7624
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
@@ -7189,7 +7628,7 @@ function PIDCanvasImpl({
|
|
|
7189
7628
|
fill: features.backgroundColor ?? "#ffffff"
|
|
7190
7629
|
}
|
|
7191
7630
|
),
|
|
7192
|
-
/* @__PURE__ */ (0,
|
|
7631
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7193
7632
|
PipeRenderer,
|
|
7194
7633
|
{
|
|
7195
7634
|
pipes: displayDiagram.pipes,
|
|
@@ -7203,7 +7642,7 @@ function PIDCanvasImpl({
|
|
|
7203
7642
|
onPipeSegmentClick: void 0
|
|
7204
7643
|
}
|
|
7205
7644
|
),
|
|
7206
|
-
/* @__PURE__ */ (0,
|
|
7645
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7207
7646
|
NodeRenderer,
|
|
7208
7647
|
{
|
|
7209
7648
|
nodes: displayDiagram.nodes,
|
|
@@ -7217,7 +7656,7 @@ function PIDCanvasImpl({
|
|
|
7217
7656
|
statusColorMap
|
|
7218
7657
|
}
|
|
7219
7658
|
),
|
|
7220
|
-
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0,
|
|
7659
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7221
7660
|
PipeRenderer,
|
|
7222
7661
|
{
|
|
7223
7662
|
pipes: displayDiagram.pipes,
|
|
@@ -7234,14 +7673,15 @@ function PIDCanvasImpl({
|
|
|
7234
7673
|
onPipeSegmentClick: handlePipeSegmentClick
|
|
7235
7674
|
}
|
|
7236
7675
|
),
|
|
7237
|
-
telemetryEnabled && telemetry && /* @__PURE__ */ (0,
|
|
7676
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
7677
|
+
if (node.symbolId === "status-indicator") return null;
|
|
7238
7678
|
const binding = telemetry.get(node.id);
|
|
7239
7679
|
if (!binding) return null;
|
|
7240
7680
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
7241
7681
|
if (!symbol) return null;
|
|
7242
7682
|
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
7243
7683
|
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
7244
|
-
return /* @__PURE__ */ (0,
|
|
7684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7245
7685
|
DataOverlay,
|
|
7246
7686
|
{
|
|
7247
7687
|
nodeId: node.id,
|
|
@@ -7254,7 +7694,7 @@ function PIDCanvasImpl({
|
|
|
7254
7694
|
`telemetry-${node.id}`
|
|
7255
7695
|
);
|
|
7256
7696
|
}) }),
|
|
7257
|
-
dragOverPosition && /* @__PURE__ */ (0,
|
|
7697
|
+
dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7258
7698
|
"circle",
|
|
7259
7699
|
{
|
|
7260
7700
|
cx: dragOverPosition.x,
|
|
@@ -7267,7 +7707,7 @@ function PIDCanvasImpl({
|
|
|
7267
7707
|
pointerEvents: "none"
|
|
7268
7708
|
}
|
|
7269
7709
|
),
|
|
7270
|
-
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0,
|
|
7710
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
7271
7711
|
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
7272
7712
|
if (!sourceNode) return null;
|
|
7273
7713
|
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
@@ -7283,8 +7723,8 @@ function PIDCanvasImpl({
|
|
|
7283
7723
|
}
|
|
7284
7724
|
}
|
|
7285
7725
|
}
|
|
7286
|
-
return /* @__PURE__ */ (0,
|
|
7287
|
-
/* @__PURE__ */ (0,
|
|
7726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
7727
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7288
7728
|
"circle",
|
|
7289
7729
|
{
|
|
7290
7730
|
cx: lineStartX,
|
|
@@ -7296,7 +7736,7 @@ function PIDCanvasImpl({
|
|
|
7296
7736
|
opacity: 0.6
|
|
7297
7737
|
}
|
|
7298
7738
|
),
|
|
7299
|
-
/* @__PURE__ */ (0,
|
|
7739
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7300
7740
|
"line",
|
|
7301
7741
|
{
|
|
7302
7742
|
x1: lineStartX,
|
|
@@ -7309,7 +7749,7 @@ function PIDCanvasImpl({
|
|
|
7309
7749
|
opacity: 0.8
|
|
7310
7750
|
}
|
|
7311
7751
|
),
|
|
7312
|
-
/* @__PURE__ */ (0,
|
|
7752
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7313
7753
|
"circle",
|
|
7314
7754
|
{
|
|
7315
7755
|
cx: connectionCursor.x,
|
|
@@ -7321,7 +7761,7 @@ function PIDCanvasImpl({
|
|
|
7321
7761
|
)
|
|
7322
7762
|
] });
|
|
7323
7763
|
})() }),
|
|
7324
|
-
features.connectionMode && /* @__PURE__ */ (0,
|
|
7764
|
+
features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
7325
7765
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
7326
7766
|
if (!symbol?.ports) return null;
|
|
7327
7767
|
return symbol.ports.map((port) => {
|
|
@@ -7329,8 +7769,8 @@ function PIDCanvasImpl({
|
|
|
7329
7769
|
if (!portPos) return null;
|
|
7330
7770
|
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
7331
7771
|
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
7332
|
-
return /* @__PURE__ */ (0,
|
|
7333
|
-
/* @__PURE__ */ (0,
|
|
7772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("g", { children: [
|
|
7773
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7334
7774
|
"circle",
|
|
7335
7775
|
{
|
|
7336
7776
|
cx: portPos.x,
|
|
@@ -7363,7 +7803,7 @@ function PIDCanvasImpl({
|
|
|
7363
7803
|
}
|
|
7364
7804
|
}
|
|
7365
7805
|
),
|
|
7366
|
-
/* @__PURE__ */ (0,
|
|
7806
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7367
7807
|
"circle",
|
|
7368
7808
|
{
|
|
7369
7809
|
cx: portPos.x,
|
|
@@ -7382,7 +7822,7 @@ function PIDCanvasImpl({
|
|
|
7382
7822
|
]
|
|
7383
7823
|
}
|
|
7384
7824
|
),
|
|
7385
|
-
features.dragNodes && /* @__PURE__ */ (0,
|
|
7825
|
+
features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7386
7826
|
PositionPanel,
|
|
7387
7827
|
{
|
|
7388
7828
|
selectedNode,
|
|
@@ -7400,19 +7840,19 @@ function PIDCanvasImpl({
|
|
|
7400
7840
|
}
|
|
7401
7841
|
);
|
|
7402
7842
|
}
|
|
7403
|
-
var PIDCanvas =
|
|
7843
|
+
var PIDCanvas = import_react22.default.memo(PIDCanvasImpl);
|
|
7404
7844
|
|
|
7405
7845
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
7406
|
-
var
|
|
7407
|
-
var
|
|
7846
|
+
var import_react23 = require("react");
|
|
7847
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7408
7848
|
function SymbolLibrary({
|
|
7409
7849
|
className = "",
|
|
7410
7850
|
onSymbolDragStart,
|
|
7411
7851
|
showCategories = true,
|
|
7412
7852
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
7413
7853
|
}) {
|
|
7414
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
7415
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
7854
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react23.useState)("all");
|
|
7855
|
+
const [searchQuery, setSearchQuery] = (0, import_react23.useState)("");
|
|
7416
7856
|
const symbolIds = getAvailableSymbols();
|
|
7417
7857
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
7418
7858
|
const categoryMap = {
|
|
@@ -7433,9 +7873,9 @@ function SymbolLibrary({
|
|
|
7433
7873
|
event.dataTransfer.effectAllowed = "copy";
|
|
7434
7874
|
onSymbolDragStart?.(symbol.id, event);
|
|
7435
7875
|
};
|
|
7436
|
-
return /* @__PURE__ */ (0,
|
|
7437
|
-
/* @__PURE__ */ (0,
|
|
7438
|
-
/* @__PURE__ */ (0,
|
|
7876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
7877
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
7878
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7439
7879
|
"input",
|
|
7440
7880
|
{
|
|
7441
7881
|
type: "text",
|
|
@@ -7445,8 +7885,8 @@ function SymbolLibrary({
|
|
|
7445
7885
|
style: styles.searchInput
|
|
7446
7886
|
}
|
|
7447
7887
|
) }),
|
|
7448
|
-
showCategories && /* @__PURE__ */ (0,
|
|
7449
|
-
/* @__PURE__ */ (0,
|
|
7888
|
+
showCategories && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: styles.categories, children: [
|
|
7889
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7450
7890
|
"button",
|
|
7451
7891
|
{
|
|
7452
7892
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -7457,7 +7897,7 @@ function SymbolLibrary({
|
|
|
7457
7897
|
children: "All"
|
|
7458
7898
|
}
|
|
7459
7899
|
),
|
|
7460
|
-
categories.map((category) => /* @__PURE__ */ (0,
|
|
7900
|
+
categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7461
7901
|
"button",
|
|
7462
7902
|
{
|
|
7463
7903
|
onClick: () => setSelectedCategory(category),
|
|
@@ -7470,7 +7910,7 @@ function SymbolLibrary({
|
|
|
7470
7910
|
category
|
|
7471
7911
|
))
|
|
7472
7912
|
] }),
|
|
7473
|
-
/* @__PURE__ */ (0,
|
|
7913
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7474
7914
|
"div",
|
|
7475
7915
|
{
|
|
7476
7916
|
draggable: true,
|
|
@@ -7478,15 +7918,15 @@ function SymbolLibrary({
|
|
|
7478
7918
|
style: styles.symbolCard,
|
|
7479
7919
|
title: symbol.metadata?.description || symbol.name,
|
|
7480
7920
|
children: [
|
|
7481
|
-
/* @__PURE__ */ (0,
|
|
7921
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7482
7922
|
"svg",
|
|
7483
7923
|
{
|
|
7484
7924
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
7485
7925
|
style: styles.symbolSvg,
|
|
7486
|
-
children: /* @__PURE__ */ (0,
|
|
7926
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
7487
7927
|
}
|
|
7488
7928
|
) }),
|
|
7489
|
-
/* @__PURE__ */ (0,
|
|
7929
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: styles.symbolName, children: symbol.name })
|
|
7490
7930
|
]
|
|
7491
7931
|
},
|
|
7492
7932
|
symbol.id
|
|
@@ -7595,13 +8035,15 @@ var styles = {
|
|
|
7595
8035
|
};
|
|
7596
8036
|
|
|
7597
8037
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
7598
|
-
var
|
|
8038
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
7599
8039
|
function NodeConfigPanel({
|
|
7600
8040
|
node,
|
|
7601
8041
|
binding,
|
|
7602
8042
|
onUpdateNode,
|
|
7603
8043
|
onUpdateTelemetry,
|
|
7604
8044
|
onAddTelemetry,
|
|
8045
|
+
onRemoveTelemetry,
|
|
8046
|
+
availableTags = [],
|
|
7605
8047
|
onRemove,
|
|
7606
8048
|
className = "",
|
|
7607
8049
|
style = {}
|
|
@@ -7614,15 +8056,17 @@ function NodeConfigPanel({
|
|
|
7614
8056
|
padding: "20px",
|
|
7615
8057
|
...style
|
|
7616
8058
|
};
|
|
7617
|
-
|
|
7618
|
-
|
|
8059
|
+
const appearanceFields = getAppearanceSchema(node.symbolId);
|
|
8060
|
+
const showGenericTelemetry = appearanceFields.length === 0;
|
|
8061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className, style: defaultStyle, children: [
|
|
8062
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
7619
8063
|
"Configure: ",
|
|
7620
8064
|
node.id
|
|
7621
8065
|
] }),
|
|
7622
|
-
/* @__PURE__ */ (0,
|
|
7623
|
-
/* @__PURE__ */ (0,
|
|
7624
|
-
/* @__PURE__ */ (0,
|
|
7625
|
-
/* @__PURE__ */ (0,
|
|
8066
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8067
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
8068
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
8069
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7626
8070
|
"input",
|
|
7627
8071
|
{
|
|
7628
8072
|
type: "text",
|
|
@@ -7638,10 +8082,10 @@ function NodeConfigPanel({
|
|
|
7638
8082
|
}
|
|
7639
8083
|
}
|
|
7640
8084
|
),
|
|
7641
|
-
/* @__PURE__ */ (0,
|
|
7642
|
-
/* @__PURE__ */ (0,
|
|
7643
|
-
/* @__PURE__ */ (0,
|
|
7644
|
-
/* @__PURE__ */ (0,
|
|
8085
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
8086
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8087
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
8088
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7645
8089
|
"input",
|
|
7646
8090
|
{
|
|
7647
8091
|
type: "number",
|
|
@@ -7662,9 +8106,9 @@ function NodeConfigPanel({
|
|
|
7662
8106
|
}
|
|
7663
8107
|
)
|
|
7664
8108
|
] }),
|
|
7665
|
-
/* @__PURE__ */ (0,
|
|
7666
|
-
/* @__PURE__ */ (0,
|
|
7667
|
-
/* @__PURE__ */ (0,
|
|
8109
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8110
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
8111
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7668
8112
|
"input",
|
|
7669
8113
|
{
|
|
7670
8114
|
type: "number",
|
|
@@ -7686,9 +8130,9 @@ function NodeConfigPanel({
|
|
|
7686
8130
|
)
|
|
7687
8131
|
] })
|
|
7688
8132
|
] }),
|
|
7689
|
-
/* @__PURE__ */ (0,
|
|
7690
|
-
/* @__PURE__ */ (0,
|
|
7691
|
-
/* @__PURE__ */ (0,
|
|
8133
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8134
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
8135
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7692
8136
|
"input",
|
|
7693
8137
|
{
|
|
7694
8138
|
type: "number",
|
|
@@ -7708,9 +8152,9 @@ function NodeConfigPanel({
|
|
|
7708
8152
|
}
|
|
7709
8153
|
)
|
|
7710
8154
|
] }),
|
|
7711
|
-
/* @__PURE__ */ (0,
|
|
7712
|
-
/* @__PURE__ */ (0,
|
|
7713
|
-
/* @__PURE__ */ (0,
|
|
8155
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8156
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
8157
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7714
8158
|
"input",
|
|
7715
8159
|
{
|
|
7716
8160
|
type: "number",
|
|
@@ -7735,9 +8179,138 @@ function NodeConfigPanel({
|
|
|
7735
8179
|
)
|
|
7736
8180
|
] })
|
|
7737
8181
|
] }),
|
|
7738
|
-
/* @__PURE__ */ (0,
|
|
7739
|
-
/* @__PURE__ */ (0,
|
|
7740
|
-
|
|
8182
|
+
appearanceFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8183
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Appearance" }),
|
|
8184
|
+
appearanceFields.map((field) => {
|
|
8185
|
+
const value = readAppearanceValue(node, field);
|
|
8186
|
+
const fieldLabel = field.label ?? field.key;
|
|
8187
|
+
const inputStyle = {
|
|
8188
|
+
width: "100%",
|
|
8189
|
+
padding: "6px 8px",
|
|
8190
|
+
borderRadius: "4px",
|
|
8191
|
+
border: "1px solid #cbd5e1",
|
|
8192
|
+
fontSize: "0.875rem"
|
|
8193
|
+
};
|
|
8194
|
+
let control;
|
|
8195
|
+
if (field.kind === "boolean") {
|
|
8196
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block" }, children: [
|
|
8197
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8198
|
+
"input",
|
|
8199
|
+
{
|
|
8200
|
+
type: "checkbox",
|
|
8201
|
+
checked: Boolean(value),
|
|
8202
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.checked)),
|
|
8203
|
+
style: { marginRight: "6px" }
|
|
8204
|
+
}
|
|
8205
|
+
),
|
|
8206
|
+
fieldLabel
|
|
8207
|
+
] });
|
|
8208
|
+
} else if (field.kind === "select") {
|
|
8209
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
8210
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8211
|
+
fieldLabel,
|
|
8212
|
+
":"
|
|
8213
|
+
] }),
|
|
8214
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8215
|
+
"select",
|
|
8216
|
+
{
|
|
8217
|
+
value: String(value),
|
|
8218
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8219
|
+
style: inputStyle,
|
|
8220
|
+
children: field.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: opt, children: opt }, opt))
|
|
8221
|
+
}
|
|
8222
|
+
)
|
|
8223
|
+
] });
|
|
8224
|
+
} else if (field.kind === "number") {
|
|
8225
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
8226
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8227
|
+
fieldLabel,
|
|
8228
|
+
":"
|
|
8229
|
+
] }),
|
|
8230
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8231
|
+
"input",
|
|
8232
|
+
{
|
|
8233
|
+
type: "number",
|
|
8234
|
+
value: Number(value),
|
|
8235
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, parseFloat(e.target.value) || 0)),
|
|
8236
|
+
style: inputStyle
|
|
8237
|
+
}
|
|
8238
|
+
)
|
|
8239
|
+
] });
|
|
8240
|
+
} else if (field.kind === "tag") {
|
|
8241
|
+
const tagValue = String(value);
|
|
8242
|
+
const listId = `tags-${node.id}-${field.key}`;
|
|
8243
|
+
const known = tagValue.length > 0 && availableTags.includes(tagValue);
|
|
8244
|
+
const unknown = tagValue.length > 0 && !known;
|
|
8245
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
8246
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8247
|
+
fieldLabel,
|
|
8248
|
+
":"
|
|
8249
|
+
] }),
|
|
8250
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8251
|
+
"input",
|
|
8252
|
+
{
|
|
8253
|
+
type: "text",
|
|
8254
|
+
value: tagValue,
|
|
8255
|
+
list: listId,
|
|
8256
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8257
|
+
placeholder: "type or pick a signal\u2026",
|
|
8258
|
+
style: {
|
|
8259
|
+
...inputStyle,
|
|
8260
|
+
border: `1px solid ${unknown ? "#f59e0b" : known ? "#22c55e" : "#cbd5e1"}`
|
|
8261
|
+
}
|
|
8262
|
+
}
|
|
8263
|
+
),
|
|
8264
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("datalist", { id: listId, children: availableTags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: t }, t)) }),
|
|
8265
|
+
tagValue.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8266
|
+
"div",
|
|
8267
|
+
{
|
|
8268
|
+
style: {
|
|
8269
|
+
fontSize: "0.7rem",
|
|
8270
|
+
marginTop: "3px",
|
|
8271
|
+
color: known ? "#16a34a" : "#b45309"
|
|
8272
|
+
},
|
|
8273
|
+
children: known ? "\u2713 matched signal" : "\u26A0 no matching signal (reads as false until published)"
|
|
8274
|
+
}
|
|
8275
|
+
)
|
|
8276
|
+
] });
|
|
8277
|
+
} else {
|
|
8278
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
8279
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8280
|
+
fieldLabel,
|
|
8281
|
+
":"
|
|
8282
|
+
] }),
|
|
8283
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8284
|
+
"input",
|
|
8285
|
+
{
|
|
8286
|
+
type: "text",
|
|
8287
|
+
value: String(value),
|
|
8288
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8289
|
+
style: inputStyle
|
|
8290
|
+
}
|
|
8291
|
+
)
|
|
8292
|
+
] });
|
|
8293
|
+
}
|
|
8294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "10px" }, children: [
|
|
8295
|
+
control,
|
|
8296
|
+
field.help && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8297
|
+
"div",
|
|
8298
|
+
{
|
|
8299
|
+
style: {
|
|
8300
|
+
fontSize: "0.7rem",
|
|
8301
|
+
color: "#64748b",
|
|
8302
|
+
marginTop: "3px",
|
|
8303
|
+
lineHeight: 1.35
|
|
8304
|
+
},
|
|
8305
|
+
children: field.help
|
|
8306
|
+
}
|
|
8307
|
+
)
|
|
8308
|
+
] }, field.key);
|
|
8309
|
+
})
|
|
8310
|
+
] }),
|
|
8311
|
+
showGenericTelemetry && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8312
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
8313
|
+
!binding ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7741
8314
|
"button",
|
|
7742
8315
|
{
|
|
7743
8316
|
onClick: () => {
|
|
@@ -7780,9 +8353,30 @@ function NodeConfigPanel({
|
|
|
7780
8353
|
},
|
|
7781
8354
|
children: "+ Add Telemetry"
|
|
7782
8355
|
}
|
|
7783
|
-
) : /* @__PURE__ */ (0,
|
|
7784
|
-
/* @__PURE__ */ (0,
|
|
7785
|
-
/* @__PURE__ */ (0,
|
|
8356
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
8357
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Tag (attribute):" }),
|
|
8358
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8359
|
+
"input",
|
|
8360
|
+
{
|
|
8361
|
+
type: "text",
|
|
8362
|
+
value: binding.tag || "",
|
|
8363
|
+
onChange: (e) => onUpdateTelemetry({
|
|
8364
|
+
nodeId: node.id,
|
|
8365
|
+
tag: e.target.value
|
|
8366
|
+
}),
|
|
8367
|
+
placeholder: "e.g. pump.running",
|
|
8368
|
+
style: {
|
|
8369
|
+
width: "100%",
|
|
8370
|
+
padding: "6px 8px",
|
|
8371
|
+
borderRadius: "4px",
|
|
8372
|
+
border: "1px solid #cbd5e1",
|
|
8373
|
+
fontSize: "0.875rem",
|
|
8374
|
+
marginBottom: "8px"
|
|
8375
|
+
}
|
|
8376
|
+
}
|
|
8377
|
+
),
|
|
8378
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
8379
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7786
8380
|
"input",
|
|
7787
8381
|
{
|
|
7788
8382
|
type: "number",
|
|
@@ -7804,8 +8398,8 @@ function NodeConfigPanel({
|
|
|
7804
8398
|
}
|
|
7805
8399
|
}
|
|
7806
8400
|
),
|
|
7807
|
-
/* @__PURE__ */ (0,
|
|
7808
|
-
/* @__PURE__ */ (0,
|
|
8401
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
8402
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7809
8403
|
"input",
|
|
7810
8404
|
{
|
|
7811
8405
|
type: "text",
|
|
@@ -7827,8 +8421,8 @@ function NodeConfigPanel({
|
|
|
7827
8421
|
}
|
|
7828
8422
|
}
|
|
7829
8423
|
),
|
|
7830
|
-
/* @__PURE__ */ (0,
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
8424
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8425
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7832
8426
|
"input",
|
|
7833
8427
|
{
|
|
7834
8428
|
type: "checkbox",
|
|
@@ -7850,8 +8444,8 @@ function NodeConfigPanel({
|
|
|
7850
8444
|
),
|
|
7851
8445
|
"Show Sparkline"
|
|
7852
8446
|
] }),
|
|
7853
|
-
/* @__PURE__ */ (0,
|
|
7854
|
-
/* @__PURE__ */ (0,
|
|
8447
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginTop: "12px" }, children: [
|
|
8448
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7855
8449
|
"label",
|
|
7856
8450
|
{
|
|
7857
8451
|
style: {
|
|
@@ -7863,10 +8457,10 @@ function NodeConfigPanel({
|
|
|
7863
8457
|
children: "Telemetry Position Offset:"
|
|
7864
8458
|
}
|
|
7865
8459
|
),
|
|
7866
|
-
/* @__PURE__ */ (0,
|
|
7867
|
-
/* @__PURE__ */ (0,
|
|
7868
|
-
/* @__PURE__ */ (0,
|
|
7869
|
-
/* @__PURE__ */ (0,
|
|
8460
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
8461
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8462
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
8463
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7870
8464
|
"input",
|
|
7871
8465
|
{
|
|
7872
8466
|
type: "number",
|
|
@@ -7893,9 +8487,9 @@ function NodeConfigPanel({
|
|
|
7893
8487
|
}
|
|
7894
8488
|
)
|
|
7895
8489
|
] }),
|
|
7896
|
-
/* @__PURE__ */ (0,
|
|
7897
|
-
/* @__PURE__ */ (0,
|
|
7898
|
-
/* @__PURE__ */ (0,
|
|
8490
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
|
|
8491
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
8492
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7899
8493
|
"input",
|
|
7900
8494
|
{
|
|
7901
8495
|
type: "number",
|
|
@@ -7923,8 +8517,8 @@ function NodeConfigPanel({
|
|
|
7923
8517
|
)
|
|
7924
8518
|
] })
|
|
7925
8519
|
] }),
|
|
7926
|
-
/* @__PURE__ */ (0,
|
|
7927
|
-
/* @__PURE__ */ (0,
|
|
8520
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginTop: "16px" }, children: [
|
|
8521
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7928
8522
|
"label",
|
|
7929
8523
|
{
|
|
7930
8524
|
style: {
|
|
@@ -7936,10 +8530,10 @@ function NodeConfigPanel({
|
|
|
7936
8530
|
children: "Display Colors:"
|
|
7937
8531
|
}
|
|
7938
8532
|
),
|
|
7939
|
-
/* @__PURE__ */ (0,
|
|
7940
|
-
/* @__PURE__ */ (0,
|
|
7941
|
-
/* @__PURE__ */ (0,
|
|
7942
|
-
/* @__PURE__ */ (0,
|
|
8533
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
8534
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
8535
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
8536
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7943
8537
|
"input",
|
|
7944
8538
|
{
|
|
7945
8539
|
type: "color",
|
|
@@ -7965,7 +8559,7 @@ function NodeConfigPanel({
|
|
|
7965
8559
|
}
|
|
7966
8560
|
}
|
|
7967
8561
|
),
|
|
7968
|
-
/* @__PURE__ */ (0,
|
|
8562
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7969
8563
|
"input",
|
|
7970
8564
|
{
|
|
7971
8565
|
type: "text",
|
|
@@ -7995,10 +8589,10 @@ function NodeConfigPanel({
|
|
|
7995
8589
|
)
|
|
7996
8590
|
] })
|
|
7997
8591
|
] }),
|
|
7998
|
-
binding.display?.showSparkline && /* @__PURE__ */ (0,
|
|
7999
|
-
/* @__PURE__ */ (0,
|
|
8000
|
-
/* @__PURE__ */ (0,
|
|
8001
|
-
/* @__PURE__ */ (0,
|
|
8592
|
+
binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
8593
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
8594
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
8595
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8002
8596
|
"input",
|
|
8003
8597
|
{
|
|
8004
8598
|
type: "color",
|
|
@@ -8024,7 +8618,7 @@ function NodeConfigPanel({
|
|
|
8024
8618
|
}
|
|
8025
8619
|
}
|
|
8026
8620
|
),
|
|
8027
|
-
/* @__PURE__ */ (0,
|
|
8621
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8028
8622
|
"input",
|
|
8029
8623
|
{
|
|
8030
8624
|
type: "text",
|
|
@@ -8054,9 +8648,9 @@ function NodeConfigPanel({
|
|
|
8054
8648
|
)
|
|
8055
8649
|
] })
|
|
8056
8650
|
] }),
|
|
8057
|
-
/* @__PURE__ */ (0,
|
|
8058
|
-
/* @__PURE__ */ (0,
|
|
8059
|
-
/* @__PURE__ */ (0,
|
|
8651
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
8652
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
8653
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8060
8654
|
"input",
|
|
8061
8655
|
{
|
|
8062
8656
|
type: "text",
|
|
@@ -8084,20 +8678,38 @@ function NodeConfigPanel({
|
|
|
8084
8678
|
}
|
|
8085
8679
|
}
|
|
8086
8680
|
),
|
|
8087
|
-
/* @__PURE__ */ (0,
|
|
8681
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
8088
8682
|
] })
|
|
8089
8683
|
] }),
|
|
8090
8684
|
" "
|
|
8091
|
-
] })
|
|
8685
|
+
] }),
|
|
8686
|
+
onRemoveTelemetry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8687
|
+
"button",
|
|
8688
|
+
{
|
|
8689
|
+
onClick: onRemoveTelemetry,
|
|
8690
|
+
style: {
|
|
8691
|
+
width: "100%",
|
|
8692
|
+
padding: "6px 8px",
|
|
8693
|
+
marginTop: "8px",
|
|
8694
|
+
borderRadius: "4px",
|
|
8695
|
+
border: "1px solid #ef4444",
|
|
8696
|
+
background: "transparent",
|
|
8697
|
+
color: "#ef4444",
|
|
8698
|
+
fontSize: "0.8125rem",
|
|
8699
|
+
cursor: "pointer"
|
|
8700
|
+
},
|
|
8701
|
+
children: "Remove Telemetry"
|
|
8702
|
+
}
|
|
8703
|
+
)
|
|
8092
8704
|
] })
|
|
8093
8705
|
] }),
|
|
8094
|
-
binding && /* @__PURE__ */ (0,
|
|
8095
|
-
/* @__PURE__ */ (0,
|
|
8706
|
+
showGenericTelemetry && binding && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8707
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
8096
8708
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
8097
8709
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
8098
|
-
return /* @__PURE__ */ (0,
|
|
8099
|
-
/* @__PURE__ */ (0,
|
|
8100
|
-
/* @__PURE__ */ (0,
|
|
8710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
8711
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
8712
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8101
8713
|
"input",
|
|
8102
8714
|
{
|
|
8103
8715
|
type: "number",
|
|
@@ -8121,8 +8733,8 @@ function NodeConfigPanel({
|
|
|
8121
8733
|
] }, key);
|
|
8122
8734
|
})
|
|
8123
8735
|
] }),
|
|
8124
|
-
binding && /* @__PURE__ */ (0,
|
|
8125
|
-
/* @__PURE__ */ (0,
|
|
8736
|
+
showGenericTelemetry && binding && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8737
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
8126
8738
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
8127
8739
|
const defaultColors = {
|
|
8128
8740
|
normal: "#10b981",
|
|
@@ -8132,13 +8744,13 @@ function NodeConfigPanel({
|
|
|
8132
8744
|
off: "#6b7280"
|
|
8133
8745
|
};
|
|
8134
8746
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
8135
|
-
return /* @__PURE__ */ (0,
|
|
8136
|
-
/* @__PURE__ */ (0,
|
|
8747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
8748
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8137
8749
|
label,
|
|
8138
8750
|
":"
|
|
8139
8751
|
] }),
|
|
8140
|
-
/* @__PURE__ */ (0,
|
|
8141
|
-
/* @__PURE__ */ (0,
|
|
8752
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
8753
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8142
8754
|
"input",
|
|
8143
8755
|
{
|
|
8144
8756
|
type: "color",
|
|
@@ -8159,7 +8771,7 @@ function NodeConfigPanel({
|
|
|
8159
8771
|
}
|
|
8160
8772
|
}
|
|
8161
8773
|
),
|
|
8162
|
-
/* @__PURE__ */ (0,
|
|
8774
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8163
8775
|
"input",
|
|
8164
8776
|
{
|
|
8165
8777
|
type: "text",
|
|
@@ -8186,7 +8798,7 @@ function NodeConfigPanel({
|
|
|
8186
8798
|
] }, status);
|
|
8187
8799
|
})
|
|
8188
8800
|
] }),
|
|
8189
|
-
/* @__PURE__ */ (0,
|
|
8801
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8190
8802
|
"button",
|
|
8191
8803
|
{
|
|
8192
8804
|
onClick: onRemove,
|
|
@@ -8463,13 +9075,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
|
|
|
8463
9075
|
}
|
|
8464
9076
|
|
|
8465
9077
|
// src/hooks/useDeviceControls.ts
|
|
8466
|
-
var
|
|
9078
|
+
var import_react24 = require("react");
|
|
8467
9079
|
function commandKey(nodeId, kind, suffix) {
|
|
8468
9080
|
return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
|
|
8469
9081
|
}
|
|
8470
9082
|
function useDeviceControls(initialBindings, options) {
|
|
8471
9083
|
const { commandTimeoutMs } = options ?? {};
|
|
8472
|
-
const [controls, setControls] = (0,
|
|
9084
|
+
const [controls, setControls] = (0, import_react24.useState)(() => {
|
|
8473
9085
|
const map = /* @__PURE__ */ new Map();
|
|
8474
9086
|
if (initialBindings) {
|
|
8475
9087
|
initialBindings.forEach((binding) => {
|
|
@@ -8478,12 +9090,12 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8478
9090
|
}
|
|
8479
9091
|
return map;
|
|
8480
9092
|
});
|
|
8481
|
-
const pendingRef = (0,
|
|
8482
|
-
const [pendingCommands, setPendingCommands] = (0,
|
|
8483
|
-
const syncPending = (0,
|
|
9093
|
+
const pendingRef = (0, import_react24.useRef)(/* @__PURE__ */ new Map());
|
|
9094
|
+
const [pendingCommands, setPendingCommands] = (0, import_react24.useState)(() => /* @__PURE__ */ new Set());
|
|
9095
|
+
const syncPending = (0, import_react24.useCallback)(() => {
|
|
8484
9096
|
setPendingCommands(new Set(pendingRef.current.keys()));
|
|
8485
9097
|
}, []);
|
|
8486
|
-
const updateControl = (0,
|
|
9098
|
+
const updateControl = (0, import_react24.useCallback)((nodeId, updates) => {
|
|
8487
9099
|
setControls((prev) => {
|
|
8488
9100
|
const newMap = new Map(prev);
|
|
8489
9101
|
const existing = newMap.get(nodeId);
|
|
@@ -8497,7 +9109,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8497
9109
|
return newMap;
|
|
8498
9110
|
});
|
|
8499
9111
|
}, []);
|
|
8500
|
-
const updateControlBatch = (0,
|
|
9112
|
+
const updateControlBatch = (0, import_react24.useCallback)((updates) => {
|
|
8501
9113
|
setControls((prev) => {
|
|
8502
9114
|
const newMap = new Map(prev);
|
|
8503
9115
|
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
@@ -8509,7 +9121,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8509
9121
|
return newMap;
|
|
8510
9122
|
});
|
|
8511
9123
|
}, []);
|
|
8512
|
-
const updateDeviceState = (0,
|
|
9124
|
+
const updateDeviceState = (0, import_react24.useCallback)(
|
|
8513
9125
|
(nodeId, stateUpdates) => {
|
|
8514
9126
|
setControls((prev) => {
|
|
8515
9127
|
const newMap = new Map(prev);
|
|
@@ -8525,7 +9137,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8525
9137
|
},
|
|
8526
9138
|
[]
|
|
8527
9139
|
);
|
|
8528
|
-
const updateParameter = (0,
|
|
9140
|
+
const updateParameter = (0, import_react24.useCallback)(
|
|
8529
9141
|
(nodeId, parameterId, value) => {
|
|
8530
9142
|
setControls((prev) => {
|
|
8531
9143
|
const newMap = new Map(prev);
|
|
@@ -8552,27 +9164,27 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8552
9164
|
},
|
|
8553
9165
|
[]
|
|
8554
9166
|
);
|
|
8555
|
-
const setControlBinding = (0,
|
|
9167
|
+
const setControlBinding = (0, import_react24.useCallback)((binding) => {
|
|
8556
9168
|
setControls((prev) => {
|
|
8557
9169
|
const newMap = new Map(prev);
|
|
8558
9170
|
newMap.set(binding.nodeId, binding);
|
|
8559
9171
|
return newMap;
|
|
8560
9172
|
});
|
|
8561
9173
|
}, []);
|
|
8562
|
-
const removeControlBinding = (0,
|
|
9174
|
+
const removeControlBinding = (0, import_react24.useCallback)((nodeId) => {
|
|
8563
9175
|
setControls((prev) => {
|
|
8564
9176
|
const newMap = new Map(prev);
|
|
8565
9177
|
newMap.delete(nodeId);
|
|
8566
9178
|
return newMap;
|
|
8567
9179
|
});
|
|
8568
9180
|
}, []);
|
|
8569
|
-
const getControlBinding = (0,
|
|
9181
|
+
const getControlBinding = (0, import_react24.useCallback)(
|
|
8570
9182
|
(nodeId) => {
|
|
8571
9183
|
return controls.get(nodeId);
|
|
8572
9184
|
},
|
|
8573
9185
|
[controls]
|
|
8574
9186
|
);
|
|
8575
|
-
const isCommandPending = (0,
|
|
9187
|
+
const isCommandPending = (0, import_react24.useCallback)(
|
|
8576
9188
|
(nodeId, kind) => {
|
|
8577
9189
|
if (kind) {
|
|
8578
9190
|
const prefix2 = `${nodeId}:${kind}`;
|
|
@@ -8589,7 +9201,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8589
9201
|
},
|
|
8590
9202
|
[pendingCommands]
|
|
8591
9203
|
);
|
|
8592
|
-
const markPending = (0,
|
|
9204
|
+
const markPending = (0, import_react24.useCallback)(
|
|
8593
9205
|
(key, delta) => {
|
|
8594
9206
|
const next = (pendingRef.current.get(key) ?? 0) + delta;
|
|
8595
9207
|
if (next > 0) pendingRef.current.set(key, next);
|
|
@@ -8598,7 +9210,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8598
9210
|
},
|
|
8599
9211
|
[syncPending]
|
|
8600
9212
|
);
|
|
8601
|
-
const runCommand = (0,
|
|
9213
|
+
const runCommand = (0, import_react24.useCallback)(
|
|
8602
9214
|
async (nodeId, key, invoke, messages) => {
|
|
8603
9215
|
const binding = controls.get(nodeId);
|
|
8604
9216
|
if (!binding) return;
|
|
@@ -8638,7 +9250,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8638
9250
|
},
|
|
8639
9251
|
[controls, updateDeviceState, markPending, commandTimeoutMs]
|
|
8640
9252
|
);
|
|
8641
|
-
const sendModeChange = (0,
|
|
9253
|
+
const sendModeChange = (0, import_react24.useCallback)(
|
|
8642
9254
|
(nodeId, mode) => runCommand(
|
|
8643
9255
|
nodeId,
|
|
8644
9256
|
commandKey(nodeId, "mode"),
|
|
@@ -8647,7 +9259,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8647
9259
|
),
|
|
8648
9260
|
[runCommand]
|
|
8649
9261
|
);
|
|
8650
|
-
const sendParameterChange = (0,
|
|
9262
|
+
const sendParameterChange = (0, import_react24.useCallback)(
|
|
8651
9263
|
(nodeId, parameterId, value) => runCommand(
|
|
8652
9264
|
nodeId,
|
|
8653
9265
|
commandKey(nodeId, "parameter", parameterId),
|
|
@@ -8656,21 +9268,21 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8656
9268
|
),
|
|
8657
9269
|
[runCommand]
|
|
8658
9270
|
);
|
|
8659
|
-
const sendStartCommand = (0,
|
|
9271
|
+
const sendStartCommand = (0, import_react24.useCallback)(
|
|
8660
9272
|
(nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
|
|
8661
9273
|
success: "Start command sent",
|
|
8662
9274
|
failure: "Start command failed"
|
|
8663
9275
|
}),
|
|
8664
9276
|
[runCommand]
|
|
8665
9277
|
);
|
|
8666
|
-
const sendStopCommand = (0,
|
|
9278
|
+
const sendStopCommand = (0, import_react24.useCallback)(
|
|
8667
9279
|
(nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
|
|
8668
9280
|
success: "Stop command sent",
|
|
8669
9281
|
failure: "Stop command failed"
|
|
8670
9282
|
}),
|
|
8671
9283
|
[runCommand]
|
|
8672
9284
|
);
|
|
8673
|
-
const sendCustomAction = (0,
|
|
9285
|
+
const sendCustomAction = (0, import_react24.useCallback)(
|
|
8674
9286
|
(nodeId, actionId) => runCommand(
|
|
8675
9287
|
nodeId,
|
|
8676
9288
|
commandKey(nodeId, "action", actionId),
|
|
@@ -8723,9 +9335,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
|
|
|
8723
9335
|
}
|
|
8724
9336
|
|
|
8725
9337
|
// src/hooks/useDeviceConfigs.ts
|
|
8726
|
-
var
|
|
9338
|
+
var import_react25 = require("react");
|
|
8727
9339
|
function useDeviceConfigs(initialConfigs) {
|
|
8728
|
-
const [configs, setConfigs] = (0,
|
|
9340
|
+
const [configs, setConfigs] = (0, import_react25.useState)(() => {
|
|
8729
9341
|
const map = /* @__PURE__ */ new Map();
|
|
8730
9342
|
if (initialConfigs) {
|
|
8731
9343
|
initialConfigs.forEach((config) => {
|
|
@@ -8734,13 +9346,13 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8734
9346
|
}
|
|
8735
9347
|
return map;
|
|
8736
9348
|
});
|
|
8737
|
-
const getConfig = (0,
|
|
9349
|
+
const getConfig = (0, import_react25.useCallback)(
|
|
8738
9350
|
(nodeId) => {
|
|
8739
9351
|
return configs.get(nodeId);
|
|
8740
9352
|
},
|
|
8741
9353
|
[configs]
|
|
8742
9354
|
);
|
|
8743
|
-
const updateConfig = (0,
|
|
9355
|
+
const updateConfig = (0, import_react25.useCallback)((nodeId, updates) => {
|
|
8744
9356
|
setConfigs((prev) => {
|
|
8745
9357
|
const newMap = new Map(prev);
|
|
8746
9358
|
const existing = newMap.get(nodeId);
|
|
@@ -8754,7 +9366,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8754
9366
|
return newMap;
|
|
8755
9367
|
});
|
|
8756
9368
|
}, []);
|
|
8757
|
-
const updateConfigState = (0,
|
|
9369
|
+
const updateConfigState = (0, import_react25.useCallback)((nodeId, stateUpdates) => {
|
|
8758
9370
|
setConfigs((prev) => {
|
|
8759
9371
|
const newMap = new Map(prev);
|
|
8760
9372
|
const existing = newMap.get(nodeId);
|
|
@@ -8767,7 +9379,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8767
9379
|
return newMap;
|
|
8768
9380
|
});
|
|
8769
9381
|
}, []);
|
|
8770
|
-
const updateConfigBatch = (0,
|
|
9382
|
+
const updateConfigBatch = (0, import_react25.useCallback)((updates) => {
|
|
8771
9383
|
setConfigs((prev) => {
|
|
8772
9384
|
const newMap = new Map(prev);
|
|
8773
9385
|
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
@@ -8779,7 +9391,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8779
9391
|
return newMap;
|
|
8780
9392
|
});
|
|
8781
9393
|
}, []);
|
|
8782
|
-
const updateParameterValue = (0,
|
|
9394
|
+
const updateParameterValue = (0, import_react25.useCallback)((nodeId, parameterId, value) => {
|
|
8783
9395
|
setConfigs((prev) => {
|
|
8784
9396
|
const newMap = new Map(prev);
|
|
8785
9397
|
const existing = newMap.get(nodeId);
|
|
@@ -8796,7 +9408,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8796
9408
|
return newMap;
|
|
8797
9409
|
});
|
|
8798
9410
|
}, []);
|
|
8799
|
-
const applyConfig = (0,
|
|
9411
|
+
const applyConfig = (0, import_react25.useCallback)(
|
|
8800
9412
|
async (nodeId) => {
|
|
8801
9413
|
const config = configs.get(nodeId);
|
|
8802
9414
|
if (!config || !config.actions.onApply) {
|
|
@@ -8829,7 +9441,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8829
9441
|
},
|
|
8830
9442
|
[configs, updateConfigState]
|
|
8831
9443
|
);
|
|
8832
|
-
const saveConfig = (0,
|
|
9444
|
+
const saveConfig = (0, import_react25.useCallback)(
|
|
8833
9445
|
async (nodeId) => {
|
|
8834
9446
|
const config = configs.get(nodeId);
|
|
8835
9447
|
if (!config || !config.actions.onSave) {
|
|
@@ -8863,7 +9475,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8863
9475
|
},
|
|
8864
9476
|
[configs, updateConfigState]
|
|
8865
9477
|
);
|
|
8866
|
-
const resetConfig = (0,
|
|
9478
|
+
const resetConfig = (0, import_react25.useCallback)(
|
|
8867
9479
|
async (nodeId) => {
|
|
8868
9480
|
const config = configs.get(nodeId);
|
|
8869
9481
|
if (!config) {
|
|
@@ -8893,7 +9505,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8893
9505
|
},
|
|
8894
9506
|
[configs, updateConfig, updateConfigState]
|
|
8895
9507
|
);
|
|
8896
|
-
const cancelConfig = (0,
|
|
9508
|
+
const cancelConfig = (0, import_react25.useCallback)(
|
|
8897
9509
|
(nodeId) => {
|
|
8898
9510
|
const config = configs.get(nodeId);
|
|
8899
9511
|
if (config?.actions.onCancel) {
|
|
@@ -8902,7 +9514,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8902
9514
|
},
|
|
8903
9515
|
[configs]
|
|
8904
9516
|
);
|
|
8905
|
-
const validateConfig = (0,
|
|
9517
|
+
const validateConfig = (0, import_react25.useCallback)(
|
|
8906
9518
|
(nodeId) => {
|
|
8907
9519
|
const config = configs.get(nodeId);
|
|
8908
9520
|
if (!config) {
|
|
@@ -8944,21 +9556,21 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8944
9556
|
},
|
|
8945
9557
|
[configs, updateConfigState]
|
|
8946
9558
|
);
|
|
8947
|
-
const setConfig = (0,
|
|
9559
|
+
const setConfig = (0, import_react25.useCallback)((config) => {
|
|
8948
9560
|
setConfigs((prev) => {
|
|
8949
9561
|
const newMap = new Map(prev);
|
|
8950
9562
|
newMap.set(config.nodeId, config);
|
|
8951
9563
|
return newMap;
|
|
8952
9564
|
});
|
|
8953
9565
|
}, []);
|
|
8954
|
-
const removeConfig = (0,
|
|
9566
|
+
const removeConfig = (0, import_react25.useCallback)((nodeId) => {
|
|
8955
9567
|
setConfigs((prev) => {
|
|
8956
9568
|
const newMap = new Map(prev);
|
|
8957
9569
|
newMap.delete(nodeId);
|
|
8958
9570
|
return newMap;
|
|
8959
9571
|
});
|
|
8960
9572
|
}, []);
|
|
8961
|
-
const clearConfigs = (0,
|
|
9573
|
+
const clearConfigs = (0, import_react25.useCallback)(() => {
|
|
8962
9574
|
setConfigs(/* @__PURE__ */ new Map());
|
|
8963
9575
|
}, []);
|
|
8964
9576
|
return {
|
|
@@ -8980,8 +9592,8 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8980
9592
|
}
|
|
8981
9593
|
|
|
8982
9594
|
// src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
|
|
8983
|
-
var
|
|
8984
|
-
var
|
|
9595
|
+
var import_react26 = __toESM(require("react"), 1);
|
|
9596
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
8985
9597
|
function DeviceConfigPanelImpl({
|
|
8986
9598
|
binding,
|
|
8987
9599
|
onClose,
|
|
@@ -9000,7 +9612,7 @@ function DeviceConfigPanelImpl({
|
|
|
9000
9612
|
showBuiltInToast = true,
|
|
9001
9613
|
embedded = false
|
|
9002
9614
|
}) {
|
|
9003
|
-
const [localValues, setLocalValues] = (0,
|
|
9615
|
+
const [localValues, setLocalValues] = (0, import_react26.useState)(() => {
|
|
9004
9616
|
if (binding) {
|
|
9005
9617
|
const values = {};
|
|
9006
9618
|
binding.parameters.forEach((param) => {
|
|
@@ -9010,7 +9622,7 @@ function DeviceConfigPanelImpl({
|
|
|
9010
9622
|
}
|
|
9011
9623
|
return {};
|
|
9012
9624
|
});
|
|
9013
|
-
const [collapsedSections, setCollapsedSections] = (0,
|
|
9625
|
+
const [collapsedSections, setCollapsedSections] = (0, import_react26.useState)(() => {
|
|
9014
9626
|
const collapsed = /* @__PURE__ */ new Set();
|
|
9015
9627
|
if (binding?.sections) {
|
|
9016
9628
|
binding.sections.forEach((section) => {
|
|
@@ -9021,9 +9633,9 @@ function DeviceConfigPanelImpl({
|
|
|
9021
9633
|
}
|
|
9022
9634
|
return collapsed;
|
|
9023
9635
|
});
|
|
9024
|
-
const [showToast, setShowToast] = (0,
|
|
9025
|
-
const [bindingId, setBindingId] = (0,
|
|
9026
|
-
const lastResultTimestampRef = (0,
|
|
9636
|
+
const [showToast, setShowToast] = (0, import_react26.useState)(true);
|
|
9637
|
+
const [bindingId, setBindingId] = (0, import_react26.useState)(binding?.nodeId || null);
|
|
9638
|
+
const lastResultTimestampRef = (0, import_react26.useRef)(0);
|
|
9027
9639
|
if (binding && binding.nodeId !== bindingId) {
|
|
9028
9640
|
const values = {};
|
|
9029
9641
|
binding.parameters.forEach((param) => {
|
|
@@ -9039,7 +9651,7 @@ function DeviceConfigPanelImpl({
|
|
|
9039
9651
|
setCollapsedSections(collapsed);
|
|
9040
9652
|
setBindingId(binding.nodeId);
|
|
9041
9653
|
}
|
|
9042
|
-
(0,
|
|
9654
|
+
(0, import_react26.useEffect)(() => {
|
|
9043
9655
|
const currentTimestamp = binding?.state.lastSaved || 0;
|
|
9044
9656
|
if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
|
|
9045
9657
|
lastResultTimestampRef.current = currentTimestamp;
|
|
@@ -9056,7 +9668,7 @@ function DeviceConfigPanelImpl({
|
|
|
9056
9668
|
};
|
|
9057
9669
|
}
|
|
9058
9670
|
}, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
|
|
9059
|
-
const parametersBySection = (0,
|
|
9671
|
+
const parametersBySection = (0, import_react26.useMemo)(() => {
|
|
9060
9672
|
if (!binding) return { _unsectioned: [] };
|
|
9061
9673
|
const groups = { _unsectioned: [] };
|
|
9062
9674
|
binding.parameters.forEach((param) => {
|
|
@@ -9071,7 +9683,7 @@ function DeviceConfigPanelImpl({
|
|
|
9071
9683
|
});
|
|
9072
9684
|
return groups;
|
|
9073
9685
|
}, [binding]);
|
|
9074
|
-
const sortedSections = (0,
|
|
9686
|
+
const sortedSections = (0, import_react26.useMemo)(() => {
|
|
9075
9687
|
if (!binding?.sections) return [];
|
|
9076
9688
|
return [...binding.sections].sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
9077
9689
|
}, [binding]);
|
|
@@ -9147,14 +9759,14 @@ function DeviceConfigPanelImpl({
|
|
|
9147
9759
|
const value = localValues[param.id];
|
|
9148
9760
|
const error = binding.state.errors?.[param.id];
|
|
9149
9761
|
const isDisabled = param.readOnly || param.enabled === false;
|
|
9150
|
-
return /* @__PURE__ */ (0,
|
|
9762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9151
9763
|
"div",
|
|
9152
9764
|
{
|
|
9153
9765
|
style: {
|
|
9154
9766
|
marginBottom: spacing.marginBottom
|
|
9155
9767
|
},
|
|
9156
9768
|
children: [
|
|
9157
|
-
/* @__PURE__ */ (0,
|
|
9769
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9158
9770
|
"label",
|
|
9159
9771
|
{
|
|
9160
9772
|
style: {
|
|
@@ -9169,13 +9781,13 @@ function DeviceConfigPanelImpl({
|
|
|
9169
9781
|
},
|
|
9170
9782
|
children: [
|
|
9171
9783
|
param.label,
|
|
9172
|
-
param.required && /* @__PURE__ */ (0,
|
|
9173
|
-
param.unit && /* @__PURE__ */ (0,
|
|
9784
|
+
param.required && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { color: errorColor }, children: " *" }),
|
|
9785
|
+
param.unit && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { color: mutedTextColor, fontWeight: "normal" }, children: [
|
|
9174
9786
|
" (",
|
|
9175
9787
|
param.unit,
|
|
9176
9788
|
")"
|
|
9177
9789
|
] }),
|
|
9178
|
-
param.forced?.active && /* @__PURE__ */ (0,
|
|
9790
|
+
param.forced?.active && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9179
9791
|
"span",
|
|
9180
9792
|
{
|
|
9181
9793
|
"aria-label": "Forced",
|
|
@@ -9202,7 +9814,7 @@ function DeviceConfigPanelImpl({
|
|
|
9202
9814
|
]
|
|
9203
9815
|
}
|
|
9204
9816
|
),
|
|
9205
|
-
param.forced?.active && param.forced.realValue !== void 0 && /* @__PURE__ */ (0,
|
|
9817
|
+
param.forced?.active && param.forced.realValue !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9206
9818
|
"div",
|
|
9207
9819
|
{
|
|
9208
9820
|
style: {
|
|
@@ -9220,7 +9832,7 @@ function DeviceConfigPanelImpl({
|
|
|
9220
9832
|
]
|
|
9221
9833
|
}
|
|
9222
9834
|
),
|
|
9223
|
-
param.description && /* @__PURE__ */ (0,
|
|
9835
|
+
param.description && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9224
9836
|
"div",
|
|
9225
9837
|
{
|
|
9226
9838
|
style: {
|
|
@@ -9232,7 +9844,7 @@ function DeviceConfigPanelImpl({
|
|
|
9232
9844
|
children: param.description
|
|
9233
9845
|
}
|
|
9234
9846
|
),
|
|
9235
|
-
param.type === "number" && /* @__PURE__ */ (0,
|
|
9847
|
+
param.type === "number" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9236
9848
|
"input",
|
|
9237
9849
|
{
|
|
9238
9850
|
type: "number",
|
|
@@ -9256,7 +9868,7 @@ function DeviceConfigPanelImpl({
|
|
|
9256
9868
|
}
|
|
9257
9869
|
}
|
|
9258
9870
|
),
|
|
9259
|
-
param.type === "string" && /* @__PURE__ */ (0,
|
|
9871
|
+
param.type === "string" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9260
9872
|
"input",
|
|
9261
9873
|
{
|
|
9262
9874
|
type: "text",
|
|
@@ -9277,7 +9889,7 @@ function DeviceConfigPanelImpl({
|
|
|
9277
9889
|
}
|
|
9278
9890
|
}
|
|
9279
9891
|
),
|
|
9280
|
-
param.type === "boolean" && /* @__PURE__ */ (0,
|
|
9892
|
+
param.type === "boolean" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9281
9893
|
"label",
|
|
9282
9894
|
{
|
|
9283
9895
|
style: {
|
|
@@ -9287,7 +9899,7 @@ function DeviceConfigPanelImpl({
|
|
|
9287
9899
|
cursor: isDisabled ? "not-allowed" : "pointer"
|
|
9288
9900
|
},
|
|
9289
9901
|
children: [
|
|
9290
|
-
/* @__PURE__ */ (0,
|
|
9902
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9291
9903
|
"input",
|
|
9292
9904
|
{
|
|
9293
9905
|
type: "checkbox",
|
|
@@ -9301,11 +9913,11 @@ function DeviceConfigPanelImpl({
|
|
|
9301
9913
|
}
|
|
9302
9914
|
}
|
|
9303
9915
|
),
|
|
9304
|
-
/* @__PURE__ */ (0,
|
|
9916
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: `${fontSize.value}px`, color: textColor }, children: value ? "Enabled" : "Disabled" })
|
|
9305
9917
|
]
|
|
9306
9918
|
}
|
|
9307
9919
|
),
|
|
9308
|
-
param.type === "select" && /* @__PURE__ */ (0,
|
|
9920
|
+
param.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9309
9921
|
"select",
|
|
9310
9922
|
{
|
|
9311
9923
|
value: value ?? "",
|
|
@@ -9323,10 +9935,10 @@ function DeviceConfigPanelImpl({
|
|
|
9323
9935
|
borderRadius: "2px",
|
|
9324
9936
|
outline: "none"
|
|
9325
9937
|
},
|
|
9326
|
-
children: param.options?.map((option) => /* @__PURE__ */ (0,
|
|
9938
|
+
children: param.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
9327
9939
|
}
|
|
9328
9940
|
),
|
|
9329
|
-
error && /* @__PURE__ */ (0,
|
|
9941
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9330
9942
|
"div",
|
|
9331
9943
|
{
|
|
9332
9944
|
style: {
|
|
@@ -9346,7 +9958,7 @@ function DeviceConfigPanelImpl({
|
|
|
9346
9958
|
const renderSection = (section) => {
|
|
9347
9959
|
const params = parametersBySection[section.id] || [];
|
|
9348
9960
|
const isCollapsed = collapsedSections.has(section.id);
|
|
9349
|
-
return /* @__PURE__ */ (0,
|
|
9961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9350
9962
|
"div",
|
|
9351
9963
|
{
|
|
9352
9964
|
style: {
|
|
@@ -9356,7 +9968,7 @@ function DeviceConfigPanelImpl({
|
|
|
9356
9968
|
backgroundColor: surfaceColor
|
|
9357
9969
|
},
|
|
9358
9970
|
children: [
|
|
9359
|
-
/* @__PURE__ */ (0,
|
|
9971
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9360
9972
|
"div",
|
|
9361
9973
|
{
|
|
9362
9974
|
onClick: () => section.collapsible && toggleSection(section.id),
|
|
@@ -9369,8 +9981,8 @@ function DeviceConfigPanelImpl({
|
|
|
9369
9981
|
alignItems: "center"
|
|
9370
9982
|
},
|
|
9371
9983
|
children: [
|
|
9372
|
-
/* @__PURE__ */ (0,
|
|
9373
|
-
/* @__PURE__ */ (0,
|
|
9984
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
9985
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9374
9986
|
"div",
|
|
9375
9987
|
{
|
|
9376
9988
|
style: {
|
|
@@ -9382,12 +9994,12 @@ function DeviceConfigPanelImpl({
|
|
|
9382
9994
|
letterSpacing: "0.5px"
|
|
9383
9995
|
},
|
|
9384
9996
|
children: [
|
|
9385
|
-
section.icon && /* @__PURE__ */ (0,
|
|
9997
|
+
section.icon && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { marginRight: "8px" }, children: section.icon }),
|
|
9386
9998
|
section.title
|
|
9387
9999
|
]
|
|
9388
10000
|
}
|
|
9389
10001
|
),
|
|
9390
|
-
section.description && /* @__PURE__ */ (0,
|
|
10002
|
+
section.description && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9391
10003
|
"div",
|
|
9392
10004
|
{
|
|
9393
10005
|
style: {
|
|
@@ -9400,11 +10012,11 @@ function DeviceConfigPanelImpl({
|
|
|
9400
10012
|
}
|
|
9401
10013
|
)
|
|
9402
10014
|
] }),
|
|
9403
|
-
section.collapsible && /* @__PURE__ */ (0,
|
|
10015
|
+
section.collapsible && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: "16px", color: mutedTextColor }, children: isCollapsed ? "\u25BC" : "\u25B2" })
|
|
9404
10016
|
]
|
|
9405
10017
|
}
|
|
9406
10018
|
),
|
|
9407
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
10019
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: spacing.padding }, children: params.map(renderParameter) })
|
|
9408
10020
|
]
|
|
9409
10021
|
},
|
|
9410
10022
|
section.id
|
|
@@ -9463,9 +10075,9 @@ function DeviceConfigPanelImpl({
|
|
|
9463
10075
|
const showSave = binding.display?.showSave !== false && binding.actions.onSave;
|
|
9464
10076
|
const showReset = binding.display?.showReset !== false && binding.actions.onReset;
|
|
9465
10077
|
const showCancel = binding.display?.showCancel !== false;
|
|
9466
|
-
return /* @__PURE__ */ (0,
|
|
9467
|
-
/* @__PURE__ */ (0,
|
|
9468
|
-
/* @__PURE__ */ (0,
|
|
10078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
10079
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
|
|
10080
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9469
10081
|
"div",
|
|
9470
10082
|
{
|
|
9471
10083
|
style: {
|
|
@@ -9477,8 +10089,8 @@ function DeviceConfigPanelImpl({
|
|
|
9477
10089
|
borderBottom: `2px solid ${borderColor}`
|
|
9478
10090
|
},
|
|
9479
10091
|
children: [
|
|
9480
|
-
/* @__PURE__ */ (0,
|
|
9481
|
-
/* @__PURE__ */ (0,
|
|
10092
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
10093
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9482
10094
|
"h3",
|
|
9483
10095
|
{
|
|
9484
10096
|
style: {
|
|
@@ -9498,7 +10110,7 @@ function DeviceConfigPanelImpl({
|
|
|
9498
10110
|
children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
|
|
9499
10111
|
}
|
|
9500
10112
|
),
|
|
9501
|
-
binding.display?.subtitle && /* @__PURE__ */ (0,
|
|
10113
|
+
binding.display?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9502
10114
|
"div",
|
|
9503
10115
|
{
|
|
9504
10116
|
style: {
|
|
@@ -9511,8 +10123,8 @@ function DeviceConfigPanelImpl({
|
|
|
9511
10123
|
}
|
|
9512
10124
|
)
|
|
9513
10125
|
] }),
|
|
9514
|
-
/* @__PURE__ */ (0,
|
|
9515
|
-
showControlsButton && onOpenControls && /* @__PURE__ */ (0,
|
|
10126
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
10127
|
+
showControlsButton && onOpenControls && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9516
10128
|
"button",
|
|
9517
10129
|
{
|
|
9518
10130
|
onClick: onOpenControls,
|
|
@@ -9535,7 +10147,7 @@ function DeviceConfigPanelImpl({
|
|
|
9535
10147
|
children: "CTRL"
|
|
9536
10148
|
}
|
|
9537
10149
|
),
|
|
9538
|
-
onUndock && /* @__PURE__ */ (0,
|
|
10150
|
+
onUndock && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9539
10151
|
"button",
|
|
9540
10152
|
{
|
|
9541
10153
|
onClick: onUndock,
|
|
@@ -9556,7 +10168,7 @@ function DeviceConfigPanelImpl({
|
|
|
9556
10168
|
children: undockIcon
|
|
9557
10169
|
}
|
|
9558
10170
|
),
|
|
9559
|
-
/* @__PURE__ */ (0,
|
|
10171
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9560
10172
|
"button",
|
|
9561
10173
|
{
|
|
9562
10174
|
onClick: onClose,
|
|
@@ -9579,7 +10191,7 @@ function DeviceConfigPanelImpl({
|
|
|
9579
10191
|
]
|
|
9580
10192
|
}
|
|
9581
10193
|
),
|
|
9582
|
-
binding.state.isDirty && /* @__PURE__ */ (0,
|
|
10194
|
+
binding.state.isDirty && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9583
10195
|
"div",
|
|
9584
10196
|
{
|
|
9585
10197
|
style: {
|
|
@@ -9594,11 +10206,11 @@ function DeviceConfigPanelImpl({
|
|
|
9594
10206
|
children: "Unsaved changes"
|
|
9595
10207
|
}
|
|
9596
10208
|
),
|
|
9597
|
-
/* @__PURE__ */ (0,
|
|
10209
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflowY: "auto", marginBottom: spacing.marginBottom }, children: sortedSections.length > 0 ? sortedSections.map(renderSection) : (
|
|
9598
10210
|
/* Render unsectioned parameters */
|
|
9599
|
-
/* @__PURE__ */ (0,
|
|
10211
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
|
|
9600
10212
|
) }),
|
|
9601
|
-
/* @__PURE__ */ (0,
|
|
10213
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
9602
10214
|
"div",
|
|
9603
10215
|
{
|
|
9604
10216
|
style: {
|
|
@@ -9609,7 +10221,7 @@ function DeviceConfigPanelImpl({
|
|
|
9609
10221
|
flexWrap: "wrap"
|
|
9610
10222
|
},
|
|
9611
10223
|
children: [
|
|
9612
|
-
showApply && /* @__PURE__ */ (0,
|
|
10224
|
+
showApply && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9613
10225
|
"button",
|
|
9614
10226
|
{
|
|
9615
10227
|
onClick: handleApply,
|
|
@@ -9632,7 +10244,7 @@ function DeviceConfigPanelImpl({
|
|
|
9632
10244
|
children: binding.state.isSaving ? "Applying..." : "Apply"
|
|
9633
10245
|
}
|
|
9634
10246
|
),
|
|
9635
|
-
showSave && /* @__PURE__ */ (0,
|
|
10247
|
+
showSave && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9636
10248
|
"button",
|
|
9637
10249
|
{
|
|
9638
10250
|
onClick: handleSave,
|
|
@@ -9655,7 +10267,7 @@ function DeviceConfigPanelImpl({
|
|
|
9655
10267
|
children: binding.state.isSaving ? "Saving..." : "Save"
|
|
9656
10268
|
}
|
|
9657
10269
|
),
|
|
9658
|
-
showReset && /* @__PURE__ */ (0,
|
|
10270
|
+
showReset && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9659
10271
|
"button",
|
|
9660
10272
|
{
|
|
9661
10273
|
onClick: handleReset,
|
|
@@ -9678,7 +10290,7 @@ function DeviceConfigPanelImpl({
|
|
|
9678
10290
|
children: "Reset"
|
|
9679
10291
|
}
|
|
9680
10292
|
),
|
|
9681
|
-
showCancel && /* @__PURE__ */ (0,
|
|
10293
|
+
showCancel && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9682
10294
|
"button",
|
|
9683
10295
|
{
|
|
9684
10296
|
onClick: handleCancel,
|
|
@@ -9705,7 +10317,7 @@ function DeviceConfigPanelImpl({
|
|
|
9705
10317
|
}
|
|
9706
10318
|
)
|
|
9707
10319
|
] }),
|
|
9708
|
-
binding.state.lastSaveResult && showToast && showBuiltInToast && /* @__PURE__ */ (0,
|
|
10320
|
+
binding.state.lastSaveResult && showToast && showBuiltInToast && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9709
10321
|
"div",
|
|
9710
10322
|
{
|
|
9711
10323
|
style: {
|
|
@@ -9727,10 +10339,10 @@ function DeviceConfigPanelImpl({
|
|
|
9727
10339
|
)
|
|
9728
10340
|
] });
|
|
9729
10341
|
}
|
|
9730
|
-
var DeviceConfigPanel =
|
|
10342
|
+
var DeviceConfigPanel = import_react26.default.memo(DeviceConfigPanelImpl);
|
|
9731
10343
|
|
|
9732
10344
|
// src/diagram/hooks/useSimulation.ts
|
|
9733
|
-
var
|
|
10345
|
+
var import_react27 = require("react");
|
|
9734
10346
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
9735
10347
|
const {
|
|
9736
10348
|
interval = 2e3,
|
|
@@ -9741,7 +10353,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9741
10353
|
historyLength = 10,
|
|
9742
10354
|
generateValue
|
|
9743
10355
|
} = options;
|
|
9744
|
-
(0,
|
|
10356
|
+
(0, import_react27.useEffect)(() => {
|
|
9745
10357
|
if (!enabled) return;
|
|
9746
10358
|
const intervalId = setInterval(() => {
|
|
9747
10359
|
const updates = [];
|
|
@@ -9792,6 +10404,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9792
10404
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9793
10405
|
0 && (module.exports = {
|
|
9794
10406
|
Button,
|
|
10407
|
+
COLOR_PRESETS,
|
|
9795
10408
|
CardHeader,
|
|
9796
10409
|
CardUnit,
|
|
9797
10410
|
CardValue,
|
|
@@ -9810,6 +10423,8 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9810
10423
|
FooterPanel,
|
|
9811
10424
|
FullscreenContainer,
|
|
9812
10425
|
FullscreenWorkspace,
|
|
10426
|
+
ISA_UNKNOWN,
|
|
10427
|
+
ISA_UNKNOWN_DARK,
|
|
9813
10428
|
LeftPanel,
|
|
9814
10429
|
LeftToggleButton,
|
|
9815
10430
|
LegacyValueEntry,
|
|
@@ -9821,6 +10436,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9821
10436
|
PanelTabs,
|
|
9822
10437
|
RightPanel,
|
|
9823
10438
|
RightToggleButton,
|
|
10439
|
+
STATUS_LED_APPEARANCE,
|
|
9824
10440
|
SVGArea,
|
|
9825
10441
|
SVGLockedOverlay,
|
|
9826
10442
|
ScrollableSVGWrapper,
|
|
@@ -9831,6 +10447,9 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9831
10447
|
ThemeProvider,
|
|
9832
10448
|
ThemeToggle,
|
|
9833
10449
|
TrendLine,
|
|
10450
|
+
UNKNOWN_GLYPH_RING_DASH,
|
|
10451
|
+
UNKNOWN_STATUS_GLYPH_COLOR_VAR,
|
|
10452
|
+
UnknownStatusGlyph,
|
|
9834
10453
|
ValueEntry,
|
|
9835
10454
|
ZoomButton,
|
|
9836
10455
|
ZoomControls,
|
|
@@ -9840,16 +10459,22 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9840
10459
|
exampleDiagram,
|
|
9841
10460
|
exportDiagram,
|
|
9842
10461
|
generateRoutePoints,
|
|
10462
|
+
getAppearanceDefaults,
|
|
10463
|
+
getAppearanceSchema,
|
|
9843
10464
|
getAvailableSymbols,
|
|
9844
10465
|
getPortWorldPosition,
|
|
9845
10466
|
getSymbolDefinition,
|
|
9846
10467
|
importDiagram,
|
|
9847
10468
|
mockSymbolLibrary,
|
|
9848
10469
|
nodeHasPort,
|
|
10470
|
+
normalizeDeviceStatus,
|
|
9849
10471
|
overlayStyles,
|
|
10472
|
+
readAppearanceValue,
|
|
9850
10473
|
registerSymbol,
|
|
9851
10474
|
registerSymbols,
|
|
10475
|
+
resolvePresetColor,
|
|
9852
10476
|
resolveStatusColor,
|
|
10477
|
+
useBooleanIndicators,
|
|
9853
10478
|
useDeviceConfigs,
|
|
9854
10479
|
useDeviceControls,
|
|
9855
10480
|
useDrag,
|
|
@@ -9860,6 +10485,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9860
10485
|
useTelemetryStatus,
|
|
9861
10486
|
useTheme,
|
|
9862
10487
|
useViewBox,
|
|
9863
|
-
validateDiagram
|
|
10488
|
+
validateDiagram,
|
|
10489
|
+
writeAppearanceValue
|
|
9864
10490
|
});
|
|
9865
10491
|
//# sourceMappingURL=index.cjs.map
|