@procaaso/alphinity-ui-components 1.10.0 → 1.11.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 +95 -95
- package/dist/index.cjs +707 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -2
- package/dist/index.d.ts +109 -2
- package/dist/index.js +601 -138
- 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,
|
|
@@ -60,6 +61,7 @@ __export(index_exports, {
|
|
|
60
61
|
PanelTabs: () => PanelTabs,
|
|
61
62
|
RightPanel: () => RightPanel,
|
|
62
63
|
RightToggleButton: () => RightToggleButton,
|
|
64
|
+
STATUS_LED_APPEARANCE: () => STATUS_LED_APPEARANCE,
|
|
63
65
|
SVGArea: () => SVGArea,
|
|
64
66
|
SVGLockedOverlay: () => SVGLockedOverlay,
|
|
65
67
|
ScrollableSVGWrapper: () => ScrollableSVGWrapper,
|
|
@@ -70,6 +72,8 @@ __export(index_exports, {
|
|
|
70
72
|
ThemeProvider: () => ThemeProvider,
|
|
71
73
|
ThemeToggle: () => ThemeToggle,
|
|
72
74
|
TrendLine: () => TrendLine,
|
|
75
|
+
UNKNOWN_MARK_COLOR: () => UNKNOWN_MARK_COLOR,
|
|
76
|
+
UNKNOWN_MARK_COLOR_DARK: () => UNKNOWN_MARK_COLOR_DARK,
|
|
73
77
|
ValueEntry: () => ValueEntry,
|
|
74
78
|
ZoomButton: () => ZoomButton,
|
|
75
79
|
ZoomControls: () => ZoomControls,
|
|
@@ -79,6 +83,8 @@ __export(index_exports, {
|
|
|
79
83
|
exampleDiagram: () => exampleDiagram,
|
|
80
84
|
exportDiagram: () => exportDiagram,
|
|
81
85
|
generateRoutePoints: () => generateRoutePoints,
|
|
86
|
+
getAppearanceDefaults: () => getAppearanceDefaults,
|
|
87
|
+
getAppearanceSchema: () => getAppearanceSchema,
|
|
82
88
|
getAvailableSymbols: () => getAvailableSymbols,
|
|
83
89
|
getPortWorldPosition: () => getPortWorldPosition,
|
|
84
90
|
getSymbolDefinition: () => getSymbolDefinition,
|
|
@@ -86,9 +92,12 @@ __export(index_exports, {
|
|
|
86
92
|
mockSymbolLibrary: () => mockSymbolLibrary,
|
|
87
93
|
nodeHasPort: () => nodeHasPort,
|
|
88
94
|
overlayStyles: () => overlayStyles,
|
|
95
|
+
readAppearanceValue: () => readAppearanceValue,
|
|
89
96
|
registerSymbol: () => registerSymbol,
|
|
90
97
|
registerSymbols: () => registerSymbols,
|
|
98
|
+
resolvePresetColor: () => resolvePresetColor,
|
|
91
99
|
resolveStatusColor: () => resolveStatusColor,
|
|
100
|
+
useBooleanIndicators: () => useBooleanIndicators,
|
|
92
101
|
useDeviceConfigs: () => useDeviceConfigs,
|
|
93
102
|
useDeviceControls: () => useDeviceControls,
|
|
94
103
|
useDrag: () => useDrag,
|
|
@@ -99,7 +108,8 @@ __export(index_exports, {
|
|
|
99
108
|
useTelemetryStatus: () => useTelemetryStatus,
|
|
100
109
|
useTheme: () => useTheme,
|
|
101
110
|
useViewBox: () => useViewBox,
|
|
102
|
-
validateDiagram: () => validateDiagram
|
|
111
|
+
validateDiagram: () => validateDiagram,
|
|
112
|
+
writeAppearanceValue: () => writeAppearanceValue
|
|
103
113
|
});
|
|
104
114
|
module.exports = __toCommonJS(index_exports);
|
|
105
115
|
|
|
@@ -388,6 +398,20 @@ var FORCED_MARK_COLOR = {
|
|
|
388
398
|
text: "#5b21b6",
|
|
389
399
|
border: "#7c3aed"
|
|
390
400
|
};
|
|
401
|
+
var UNKNOWN_MARK_COLOR = {
|
|
402
|
+
fill: "#ebebf5",
|
|
403
|
+
stroke: "#8f8fc2",
|
|
404
|
+
bg: "#ebebf5",
|
|
405
|
+
text: "#4f4f8a",
|
|
406
|
+
border: "#8f8fc2"
|
|
407
|
+
};
|
|
408
|
+
var UNKNOWN_MARK_COLOR_DARK = {
|
|
409
|
+
fill: "#23263a",
|
|
410
|
+
stroke: "#6f74a3",
|
|
411
|
+
bg: "#23263a",
|
|
412
|
+
text: "#b9bbdb",
|
|
413
|
+
border: "#6f74a3"
|
|
414
|
+
};
|
|
391
415
|
var STATUS_ALIASES = {
|
|
392
416
|
running: "normal",
|
|
393
417
|
stopped: "off"
|
|
@@ -861,11 +885,15 @@ var StatusIndicator = ({
|
|
|
861
885
|
labelPosition = "right",
|
|
862
886
|
shape = "circle",
|
|
863
887
|
led = true,
|
|
888
|
+
visible = true,
|
|
864
889
|
forced = false,
|
|
865
890
|
realValue,
|
|
866
891
|
className = "",
|
|
867
892
|
...props
|
|
868
893
|
}) => {
|
|
894
|
+
if (!visible) {
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
869
897
|
const baseClass = "ui-status-indicator";
|
|
870
898
|
const statusClass = status ? `ui-status-indicator--${status}` : "";
|
|
871
899
|
const sizeClass = size ? `ui-status-indicator--${size}` : "";
|
|
@@ -3620,7 +3648,7 @@ var ThemeToggle = ({
|
|
|
3620
3648
|
};
|
|
3621
3649
|
|
|
3622
3650
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3623
|
-
var
|
|
3651
|
+
var import_react21 = __toESM(require("react"), 1);
|
|
3624
3652
|
|
|
3625
3653
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
3626
3654
|
var import_react10 = __toESM(require("react"), 1);
|
|
@@ -3651,6 +3679,25 @@ var mockSymbolLibrary = {
|
|
|
3651
3679
|
tags: ["valve", "gate", "powered", "actuator"]
|
|
3652
3680
|
}
|
|
3653
3681
|
},
|
|
3682
|
+
"status-indicator": {
|
|
3683
|
+
id: "status-indicator",
|
|
3684
|
+
name: "Status LED",
|
|
3685
|
+
category: "instrument",
|
|
3686
|
+
viewBox: { x: 0, y: 0, width: 24, height: 24 },
|
|
3687
|
+
ports: [],
|
|
3688
|
+
svgContent: `
|
|
3689
|
+
<rect x="2" y="2" width="20" height="20"
|
|
3690
|
+
rx="var(--led-rx, 50%)"
|
|
3691
|
+
fill="var(--symbol-fill, #64748b)"
|
|
3692
|
+
stroke="rgba(255,255,255,0.4)"
|
|
3693
|
+
stroke-width="var(--led-bezel, 0)"
|
|
3694
|
+
style="transform-box: fill-box; transform: rotate(var(--led-rotate, 0deg)); transform-origin: center; pointer-events: all;"/>
|
|
3695
|
+
`,
|
|
3696
|
+
metadata: {
|
|
3697
|
+
description: "Status LED indicator driven by telemetry status color",
|
|
3698
|
+
tags: ["status", "led", "indicator", "instrument"]
|
|
3699
|
+
}
|
|
3700
|
+
},
|
|
3654
3701
|
"pump-positive-displacement": {
|
|
3655
3702
|
id: "pump-positive-displacement",
|
|
3656
3703
|
name: "Positive Displacement Pump",
|
|
@@ -4843,8 +4890,144 @@ function getAvailableSymbols() {
|
|
|
4843
4890
|
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
4844
4891
|
}
|
|
4845
4892
|
|
|
4893
|
+
// src/diagram/symbols/appearanceSchema.ts
|
|
4894
|
+
var COLOR_PRESETS = {
|
|
4895
|
+
green: "#22c55e",
|
|
4896
|
+
red: "#ef4444",
|
|
4897
|
+
amber: "#f59e0b",
|
|
4898
|
+
blue: "#3b82f6",
|
|
4899
|
+
grey: "#64748b"
|
|
4900
|
+
};
|
|
4901
|
+
function resolvePresetColor(name) {
|
|
4902
|
+
return name && COLOR_PRESETS[name] || COLOR_PRESETS.grey;
|
|
4903
|
+
}
|
|
4904
|
+
var COLOR_OPTIONS = Object.keys(COLOR_PRESETS);
|
|
4905
|
+
var STATUS_LED_APPEARANCE = [
|
|
4906
|
+
{
|
|
4907
|
+
key: "shape",
|
|
4908
|
+
kind: "select",
|
|
4909
|
+
label: "Shape",
|
|
4910
|
+
options: ["circle", "square", "diamond"],
|
|
4911
|
+
default: "circle"
|
|
4912
|
+
},
|
|
4913
|
+
{
|
|
4914
|
+
key: "size",
|
|
4915
|
+
kind: "select",
|
|
4916
|
+
label: "Size",
|
|
4917
|
+
target: "scale",
|
|
4918
|
+
options: ["small", "medium", "large"],
|
|
4919
|
+
default: "medium",
|
|
4920
|
+
valueMap: { small: 0.75, medium: 1, large: 1.5 }
|
|
4921
|
+
},
|
|
4922
|
+
{ key: "led", kind: "boolean", label: "Bezel ring", default: true },
|
|
4923
|
+
{ key: "glow", kind: "boolean", label: "Diffusion (glow)", default: false },
|
|
4924
|
+
{
|
|
4925
|
+
key: "animation",
|
|
4926
|
+
kind: "select",
|
|
4927
|
+
label: "Animation",
|
|
4928
|
+
options: ["none", "pulse", "blink"],
|
|
4929
|
+
default: "none"
|
|
4930
|
+
},
|
|
4931
|
+
{
|
|
4932
|
+
key: "labelPosition",
|
|
4933
|
+
kind: "select",
|
|
4934
|
+
label: "Label position",
|
|
4935
|
+
options: ["bottom", "top", "left", "right"],
|
|
4936
|
+
default: "bottom"
|
|
4937
|
+
},
|
|
4938
|
+
// Color binding: a named signal drives the on/off color.
|
|
4939
|
+
{
|
|
4940
|
+
key: "colorSource",
|
|
4941
|
+
kind: "tag",
|
|
4942
|
+
label: "Color source (tag)",
|
|
4943
|
+
default: "",
|
|
4944
|
+
help: "Signal/tag that drives color. True (non-zero) shows On color; false shows Off color. Blank = unbound (grey)."
|
|
4945
|
+
},
|
|
4946
|
+
{
|
|
4947
|
+
key: "onColor",
|
|
4948
|
+
kind: "select",
|
|
4949
|
+
label: "On color (true)",
|
|
4950
|
+
options: COLOR_OPTIONS,
|
|
4951
|
+
default: "green",
|
|
4952
|
+
help: "Color when the Color source is true."
|
|
4953
|
+
},
|
|
4954
|
+
{
|
|
4955
|
+
key: "offColor",
|
|
4956
|
+
kind: "select",
|
|
4957
|
+
label: "Off color (false)",
|
|
4958
|
+
options: COLOR_OPTIONS,
|
|
4959
|
+
default: "red",
|
|
4960
|
+
help: "Color when the Color source is false."
|
|
4961
|
+
},
|
|
4962
|
+
// Visibility binding: an independent named signal drives show/hide.
|
|
4963
|
+
{
|
|
4964
|
+
key: "visibleSource",
|
|
4965
|
+
kind: "tag",
|
|
4966
|
+
label: "Visibility source (tag)",
|
|
4967
|
+
default: "",
|
|
4968
|
+
help: "Signal/tag that drives visibility. True shows the LED, false hides it. Blank = always visible (use the Visible checkbox)."
|
|
4969
|
+
},
|
|
4970
|
+
{
|
|
4971
|
+
key: "visible",
|
|
4972
|
+
kind: "boolean",
|
|
4973
|
+
label: "Visible",
|
|
4974
|
+
target: "visible",
|
|
4975
|
+
default: true,
|
|
4976
|
+
help: "Static show/hide, used only when no Visibility source is set."
|
|
4977
|
+
}
|
|
4978
|
+
];
|
|
4979
|
+
var APPEARANCE_REGISTRY = {
|
|
4980
|
+
"status-indicator": STATUS_LED_APPEARANCE
|
|
4981
|
+
};
|
|
4982
|
+
function getAppearanceSchema(symbolId) {
|
|
4983
|
+
return APPEARANCE_REGISTRY[symbolId] ?? [];
|
|
4984
|
+
}
|
|
4985
|
+
function getAppearanceDefaults(symbolId) {
|
|
4986
|
+
const out = {};
|
|
4987
|
+
for (const field of getAppearanceSchema(symbolId)) {
|
|
4988
|
+
if ((field.target ?? "metadata") === "metadata" && field.default !== void 0) {
|
|
4989
|
+
out[field.key] = field.default;
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
return out;
|
|
4993
|
+
}
|
|
4994
|
+
function readAppearanceValue(node, field) {
|
|
4995
|
+
if (field.target === "visible") {
|
|
4996
|
+
return node.visible ?? field.default ?? true;
|
|
4997
|
+
}
|
|
4998
|
+
if (field.target === "scale") {
|
|
4999
|
+
const scale = node.transform.scale ?? 1;
|
|
5000
|
+
if (field.valueMap) {
|
|
5001
|
+
let bestOption = field.options?.[0] ?? String(scale);
|
|
5002
|
+
let bestDiff = Infinity;
|
|
5003
|
+
for (const [option, value2] of Object.entries(field.valueMap)) {
|
|
5004
|
+
const diff = Math.abs(value2 - scale);
|
|
5005
|
+
if (diff < bestDiff) {
|
|
5006
|
+
bestDiff = diff;
|
|
5007
|
+
bestOption = option;
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
return bestOption;
|
|
5011
|
+
}
|
|
5012
|
+
return scale;
|
|
5013
|
+
}
|
|
5014
|
+
const value = node.metadata?.[field.key];
|
|
5015
|
+
return value ?? field.default;
|
|
5016
|
+
}
|
|
5017
|
+
function writeAppearanceValue(node, field, value) {
|
|
5018
|
+
if (field.target === "visible") {
|
|
5019
|
+
return { visible: Boolean(value) };
|
|
5020
|
+
}
|
|
5021
|
+
if (field.target === "scale") {
|
|
5022
|
+
const scale = field.valueMap ? field.valueMap[String(value)] ?? 1 : Number(value);
|
|
5023
|
+
return { transform: { ...node.transform, scale } };
|
|
5024
|
+
}
|
|
5025
|
+
return { metadata: { ...node.metadata, [field.key]: value } };
|
|
5026
|
+
}
|
|
5027
|
+
|
|
4846
5028
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
4847
5029
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
5030
|
+
var HATCH_SIZE = 6;
|
|
4848
5031
|
function NodeRendererImpl({
|
|
4849
5032
|
nodes: nodes2,
|
|
4850
5033
|
selectedNodeIds,
|
|
@@ -4856,140 +5039,206 @@ function NodeRendererImpl({
|
|
|
4856
5039
|
enableDrag = false,
|
|
4857
5040
|
statusColorMap
|
|
4858
5041
|
}) {
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
|
|
4865
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
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",
|
|
5042
|
+
const hatchId = `pid-unknown-hatch-${import_react10.default.useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
5043
|
+
const hasUnknown = nodes2.some((n) => n.positionUnknown === true && n.visible !== false);
|
|
5044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { id: "layer-nodes", children: [
|
|
5045
|
+
hasUnknown && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
5046
|
+
"pattern",
|
|
4921
5047
|
{
|
|
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
|
-
},
|
|
5048
|
+
id: hatchId,
|
|
5049
|
+
"data-testid": "position-unknown-pattern",
|
|
5050
|
+
patternUnits: "userSpaceOnUse",
|
|
5051
|
+
width: HATCH_SIZE,
|
|
5052
|
+
height: HATCH_SIZE,
|
|
5053
|
+
patternTransform: "rotate(45)",
|
|
4951
5054
|
children: [
|
|
4952
|
-
|
|
4953
|
-
|
|
5055
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("rect", { width: HATCH_SIZE, height: HATCH_SIZE, fill: UNKNOWN_MARK_COLOR.fill }),
|
|
5056
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5057
|
+
"line",
|
|
4954
5058
|
{
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
strokeWidth: isDragging ? "3" : "2",
|
|
4962
|
-
strokeDasharray: "4 2",
|
|
4963
|
-
rx: "2",
|
|
4964
|
-
pointerEvents: "none"
|
|
5059
|
+
x1: "0",
|
|
5060
|
+
y1: "0",
|
|
5061
|
+
x2: "0",
|
|
5062
|
+
y2: HATCH_SIZE,
|
|
5063
|
+
stroke: UNKNOWN_MARK_COLOR.text,
|
|
5064
|
+
strokeWidth: "2"
|
|
4965
5065
|
}
|
|
4966
|
-
)
|
|
5066
|
+
)
|
|
5067
|
+
]
|
|
5068
|
+
}
|
|
5069
|
+
) }),
|
|
5070
|
+
nodes2.filter((node) => node.visible !== false).map((node) => {
|
|
5071
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5072
|
+
const isSelected = selectedNodeIds?.has(node.id) ?? false;
|
|
5073
|
+
const isDragging = draggingNodeId === node.id;
|
|
5074
|
+
if (!symbol) {
|
|
5075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
|
|
4967
5076
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
4968
|
-
"
|
|
5077
|
+
"circle",
|
|
4969
5078
|
{
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
5079
|
+
cx: node.transform.x,
|
|
5080
|
+
cy: node.transform.y,
|
|
5081
|
+
r: "15",
|
|
5082
|
+
fill: "#ff0000",
|
|
5083
|
+
opacity: "0.3",
|
|
5084
|
+
stroke: "#ff0000",
|
|
5085
|
+
strokeWidth: "2"
|
|
4973
5086
|
}
|
|
4974
5087
|
),
|
|
4975
5088
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
4976
5089
|
"text",
|
|
4977
5090
|
{
|
|
4978
|
-
x:
|
|
4979
|
-
y:
|
|
5091
|
+
x: node.transform.x,
|
|
5092
|
+
y: node.transform.y,
|
|
4980
5093
|
textAnchor: "middle",
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
fill:
|
|
4984
|
-
|
|
4985
|
-
children: node.label || node.id
|
|
5094
|
+
dominantBaseline: "middle",
|
|
5095
|
+
fontSize: "10",
|
|
5096
|
+
fill: "#ff0000",
|
|
5097
|
+
children: "?"
|
|
4986
5098
|
}
|
|
4987
5099
|
)
|
|
4988
|
-
]
|
|
4989
|
-
}
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
5100
|
+
] }, node.id);
|
|
5101
|
+
}
|
|
5102
|
+
const transforms = [];
|
|
5103
|
+
const effectiveX = isDragging ? node.transform.x + dragOffset.x : node.transform.x;
|
|
5104
|
+
const effectiveY = isDragging ? node.transform.y + dragOffset.y : node.transform.y;
|
|
5105
|
+
transforms.push(`translate(${effectiveX}, ${effectiveY})`);
|
|
5106
|
+
if (node.transform.rotation) {
|
|
5107
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5108
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5109
|
+
transforms.push(`rotate(${node.transform.rotation}, ${centerX}, ${centerY})`);
|
|
5110
|
+
}
|
|
5111
|
+
if (node.transform.scale && node.transform.scale !== 1) {
|
|
5112
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5113
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5114
|
+
transforms.push(
|
|
5115
|
+
`translate(${centerX}, ${centerY}) scale(${node.transform.scale}) translate(${-centerX}, ${-centerY})`
|
|
5116
|
+
);
|
|
5117
|
+
}
|
|
5118
|
+
if (node.transform.flipX || node.transform.flipY) {
|
|
5119
|
+
const scaleX = node.transform.flipX ? -1 : 1;
|
|
5120
|
+
const scaleY = node.transform.flipY ? -1 : 1;
|
|
5121
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5122
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5123
|
+
transforms.push(
|
|
5124
|
+
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
5125
|
+
);
|
|
5126
|
+
}
|
|
5127
|
+
const statusEntry = resolveStatusColor(node.status, statusColorMap);
|
|
5128
|
+
const isUnknown = node.positionUnknown === true;
|
|
5129
|
+
const fillColor = isUnknown ? `url(#${hatchId})` : node.customColors?.fill ?? statusEntry.fill;
|
|
5130
|
+
const strokeColor = isUnknown ? UNKNOWN_MARK_COLOR.stroke : node.customColors?.stroke ?? statusEntry.stroke;
|
|
5131
|
+
const appearance = { ...getAppearanceDefaults(node.symbolId), ...node.metadata ?? {} };
|
|
5132
|
+
const ledStyle = {};
|
|
5133
|
+
if (appearance.shape !== void 0) {
|
|
5134
|
+
ledStyle["--led-rx"] = appearance.shape === "circle" ? "50%" : "2";
|
|
5135
|
+
ledStyle["--led-rotate"] = appearance.shape === "diamond" ? "45deg" : "0deg";
|
|
5136
|
+
}
|
|
5137
|
+
if (appearance.led !== void 0) {
|
|
5138
|
+
ledStyle["--led-bezel"] = appearance.led ? "2" : "0";
|
|
5139
|
+
}
|
|
5140
|
+
if (appearance.glow) {
|
|
5141
|
+
ledStyle.filter = `drop-shadow(0 0 4px ${fillColor})`;
|
|
5142
|
+
}
|
|
5143
|
+
const ledAnimation = typeof appearance.animation === "string" && appearance.animation !== "none" ? appearance.animation : void 0;
|
|
5144
|
+
const vb = symbol.viewBox;
|
|
5145
|
+
const ox = node.labelOffset?.x ?? 0;
|
|
5146
|
+
const oy = node.labelOffset?.y ?? 0;
|
|
5147
|
+
const labelPos = typeof appearance.labelPosition === "string" ? appearance.labelPosition : "bottom";
|
|
5148
|
+
let labelX = vb.width / 2 + ox;
|
|
5149
|
+
let labelY = vb.height + 12 + oy;
|
|
5150
|
+
let labelAnchor = "middle";
|
|
5151
|
+
if (labelPos === "top") {
|
|
5152
|
+
labelX = vb.width / 2 + ox;
|
|
5153
|
+
labelY = -6 + oy;
|
|
5154
|
+
labelAnchor = "middle";
|
|
5155
|
+
} else if (labelPos === "left") {
|
|
5156
|
+
labelX = -6 + ox;
|
|
5157
|
+
labelY = vb.height / 2 + oy;
|
|
5158
|
+
labelAnchor = "end";
|
|
5159
|
+
} else if (labelPos === "right") {
|
|
5160
|
+
labelX = vb.width + 6 + ox;
|
|
5161
|
+
labelY = vb.height / 2 + oy;
|
|
5162
|
+
labelAnchor = "start";
|
|
5163
|
+
}
|
|
5164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
5165
|
+
"g",
|
|
5166
|
+
{
|
|
5167
|
+
"data-node-id": node.id,
|
|
5168
|
+
"data-symbol-id": node.symbolId,
|
|
5169
|
+
"data-selected": isSelected,
|
|
5170
|
+
"data-dragging": isDragging,
|
|
5171
|
+
"data-led-animation": ledAnimation,
|
|
5172
|
+
"data-position-unknown": isUnknown ? "true" : void 0,
|
|
5173
|
+
transform: transforms.join(" "),
|
|
5174
|
+
style: {
|
|
5175
|
+
"--symbol-fill": fillColor,
|
|
5176
|
+
"--symbol-stroke": strokeColor,
|
|
5177
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default",
|
|
5178
|
+
...ledStyle
|
|
5179
|
+
},
|
|
5180
|
+
onClick: (e) => {
|
|
5181
|
+
e.stopPropagation();
|
|
5182
|
+
onNodeClick?.(node.id, e);
|
|
5183
|
+
},
|
|
5184
|
+
onDoubleClick: (e) => {
|
|
5185
|
+
e.stopPropagation();
|
|
5186
|
+
onNodeDoubleClick?.(node.id, e);
|
|
5187
|
+
},
|
|
5188
|
+
onMouseDown: (e) => {
|
|
5189
|
+
if (enableDrag) {
|
|
5190
|
+
onNodeDragStart?.(node.id, e);
|
|
5191
|
+
}
|
|
5192
|
+
},
|
|
5193
|
+
onTouchStart: (e) => {
|
|
5194
|
+
if (enableDrag) {
|
|
5195
|
+
e.stopPropagation();
|
|
5196
|
+
onNodeDragStart?.(node.id, e);
|
|
5197
|
+
}
|
|
5198
|
+
},
|
|
5199
|
+
children: [
|
|
5200
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5201
|
+
"rect",
|
|
5202
|
+
{
|
|
5203
|
+
x: "-5",
|
|
5204
|
+
y: "-5",
|
|
5205
|
+
width: symbol.viewBox.width + 10,
|
|
5206
|
+
height: symbol.viewBox.height + 10,
|
|
5207
|
+
fill: "none",
|
|
5208
|
+
stroke: isDragging ? "#10b981" : "#3b82f6",
|
|
5209
|
+
strokeWidth: isDragging ? "3" : "2",
|
|
5210
|
+
strokeDasharray: "4 2",
|
|
5211
|
+
rx: "2",
|
|
5212
|
+
pointerEvents: "none"
|
|
5213
|
+
}
|
|
5214
|
+
),
|
|
5215
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5216
|
+
"g",
|
|
5217
|
+
{
|
|
5218
|
+
dangerouslySetInnerHTML: { __html: symbol.svgContent },
|
|
5219
|
+
"data-symbol-content": symbol.id,
|
|
5220
|
+
style: { pointerEvents: "auto" }
|
|
5221
|
+
}
|
|
5222
|
+
),
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5224
|
+
"text",
|
|
5225
|
+
{
|
|
5226
|
+
x: labelX,
|
|
5227
|
+
y: labelY,
|
|
5228
|
+
textAnchor: labelAnchor,
|
|
5229
|
+
fontSize: node.labelFontSize ?? 10,
|
|
5230
|
+
fontWeight: "600",
|
|
5231
|
+
fill: isSelected ? "#3b82f6" : "#1f2937",
|
|
5232
|
+
transform: node.transform.rotation ? `rotate(${-node.transform.rotation}, ${labelX}, ${labelY})` : void 0,
|
|
5233
|
+
children: node.label || node.id
|
|
5234
|
+
}
|
|
5235
|
+
)
|
|
5236
|
+
]
|
|
5237
|
+
},
|
|
5238
|
+
node.id
|
|
5239
|
+
);
|
|
5240
|
+
})
|
|
5241
|
+
] });
|
|
4993
5242
|
}
|
|
4994
5243
|
var NodeRenderer = import_react10.default.memo(NodeRendererImpl);
|
|
4995
5244
|
|
|
@@ -6139,8 +6388,49 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
6139
6388
|
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
6140
6389
|
}
|
|
6141
6390
|
|
|
6142
|
-
// src/diagram/hooks/
|
|
6391
|
+
// src/diagram/hooks/useBooleanIndicators.ts
|
|
6143
6392
|
var import_react18 = require("react");
|
|
6393
|
+
function useBooleanIndicators(telemetry, diagram, setDiagram, options = {}) {
|
|
6394
|
+
const { enabled = true, symbolId = "status-indicator" } = options;
|
|
6395
|
+
(0, import_react18.useEffect)(() => {
|
|
6396
|
+
if (!enabled) return;
|
|
6397
|
+
const tagIndex = /* @__PURE__ */ new Map();
|
|
6398
|
+
telemetry.forEach((binding) => {
|
|
6399
|
+
if (binding.tag) tagIndex.set(binding.tag, binding.value.value);
|
|
6400
|
+
});
|
|
6401
|
+
let needsUpdate = false;
|
|
6402
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
6403
|
+
if (node.symbolId !== symbolId) return node;
|
|
6404
|
+
const meta = node.metadata ?? {};
|
|
6405
|
+
const colorSource = typeof meta.colorSource === "string" ? meta.colorSource : "";
|
|
6406
|
+
const visibleSource = typeof meta.visibleSource === "string" ? meta.visibleSource : "";
|
|
6407
|
+
let next = node;
|
|
6408
|
+
if (colorSource) {
|
|
6409
|
+
const isTrue = Boolean(tagIndex.get(colorSource));
|
|
6410
|
+
const fill = resolvePresetColor(
|
|
6411
|
+
String(isTrue ? meta.onColor ?? "green" : meta.offColor ?? "red")
|
|
6412
|
+
);
|
|
6413
|
+
if (node.customColors?.fill !== fill) {
|
|
6414
|
+
next = { ...next, customColors: { ...next.customColors, fill } };
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
if (visibleSource) {
|
|
6418
|
+
const vis = Boolean(tagIndex.get(visibleSource));
|
|
6419
|
+
if ((next.visible ?? true) !== vis) {
|
|
6420
|
+
next = { ...next, visible: vis };
|
|
6421
|
+
}
|
|
6422
|
+
}
|
|
6423
|
+
if (next !== node) needsUpdate = true;
|
|
6424
|
+
return next;
|
|
6425
|
+
});
|
|
6426
|
+
if (needsUpdate) {
|
|
6427
|
+
setDiagram({ ...diagram, nodes: updatedNodes });
|
|
6428
|
+
}
|
|
6429
|
+
}, [telemetry, diagram, setDiagram, enabled, symbolId]);
|
|
6430
|
+
}
|
|
6431
|
+
|
|
6432
|
+
// src/diagram/hooks/useDrag.ts
|
|
6433
|
+
var import_react19 = require("react");
|
|
6144
6434
|
function useDrag(options = {}) {
|
|
6145
6435
|
const {
|
|
6146
6436
|
onDragStart,
|
|
@@ -6150,23 +6440,23 @@ function useDrag(options = {}) {
|
|
|
6150
6440
|
dragThreshold = 3,
|
|
6151
6441
|
screenToWorld = (x, y) => ({ x, y })
|
|
6152
6442
|
} = options;
|
|
6153
|
-
const [dragState, setDragState] = (0,
|
|
6443
|
+
const [dragState, setDragState] = (0, import_react19.useState)({
|
|
6154
6444
|
isDragging: false,
|
|
6155
6445
|
startPosition: null,
|
|
6156
6446
|
offset: { x: 0, y: 0 },
|
|
6157
6447
|
draggedId: null
|
|
6158
6448
|
});
|
|
6159
|
-
const [isListening, setIsListening] = (0,
|
|
6160
|
-
const dragStartRef = (0,
|
|
6161
|
-
const hasMovedRef = (0,
|
|
6162
|
-
const applySnap = (0,
|
|
6449
|
+
const [isListening, setIsListening] = (0, import_react19.useState)(false);
|
|
6450
|
+
const dragStartRef = (0, import_react19.useRef)(null);
|
|
6451
|
+
const hasMovedRef = (0, import_react19.useRef)(false);
|
|
6452
|
+
const applySnap = (0, import_react19.useCallback)(
|
|
6163
6453
|
(value) => {
|
|
6164
6454
|
if (snapToGrid <= 0) return value;
|
|
6165
6455
|
return Math.round(value / snapToGrid) * snapToGrid;
|
|
6166
6456
|
},
|
|
6167
6457
|
[snapToGrid]
|
|
6168
6458
|
);
|
|
6169
|
-
const handleMouseMove = (0,
|
|
6459
|
+
const handleMouseMove = (0, import_react19.useCallback)(
|
|
6170
6460
|
(event) => {
|
|
6171
6461
|
if (!dragStartRef.current) return;
|
|
6172
6462
|
const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
|
|
@@ -6207,7 +6497,7 @@ function useDrag(options = {}) {
|
|
|
6207
6497
|
},
|
|
6208
6498
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
6209
6499
|
);
|
|
6210
|
-
const handleMouseUp = (0,
|
|
6500
|
+
const handleMouseUp = (0, import_react19.useCallback)(
|
|
6211
6501
|
(event) => {
|
|
6212
6502
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
6213
6503
|
dragStartRef.current = null;
|
|
@@ -6244,7 +6534,7 @@ function useDrag(options = {}) {
|
|
|
6244
6534
|
},
|
|
6245
6535
|
[screenToWorld, applySnap, onDragEnd]
|
|
6246
6536
|
);
|
|
6247
|
-
const handleTouchMove = (0,
|
|
6537
|
+
const handleTouchMove = (0, import_react19.useCallback)(
|
|
6248
6538
|
(event) => {
|
|
6249
6539
|
if (!dragStartRef.current || event.touches.length !== 1) return;
|
|
6250
6540
|
const touch = event.touches[0];
|
|
@@ -6287,7 +6577,7 @@ function useDrag(options = {}) {
|
|
|
6287
6577
|
},
|
|
6288
6578
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
6289
6579
|
);
|
|
6290
|
-
const handleTouchEnd = (0,
|
|
6580
|
+
const handleTouchEnd = (0, import_react19.useCallback)(
|
|
6291
6581
|
(event) => {
|
|
6292
6582
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
6293
6583
|
dragStartRef.current = null;
|
|
@@ -6325,7 +6615,7 @@ function useDrag(options = {}) {
|
|
|
6325
6615
|
},
|
|
6326
6616
|
[screenToWorld, applySnap, onDragEnd]
|
|
6327
6617
|
);
|
|
6328
|
-
(0,
|
|
6618
|
+
(0, import_react19.useEffect)(() => {
|
|
6329
6619
|
if (!isListening) return;
|
|
6330
6620
|
document.addEventListener("mousemove", handleMouseMove);
|
|
6331
6621
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -6340,7 +6630,7 @@ function useDrag(options = {}) {
|
|
|
6340
6630
|
document.removeEventListener("touchcancel", handleTouchEnd);
|
|
6341
6631
|
};
|
|
6342
6632
|
}, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
|
|
6343
|
-
const startDrag = (0,
|
|
6633
|
+
const startDrag = (0, import_react19.useCallback)(
|
|
6344
6634
|
(id, event, itemPosition) => {
|
|
6345
6635
|
event.stopPropagation();
|
|
6346
6636
|
let clientX;
|
|
@@ -6370,7 +6660,7 @@ function useDrag(options = {}) {
|
|
|
6370
6660
|
},
|
|
6371
6661
|
[screenToWorld]
|
|
6372
6662
|
);
|
|
6373
|
-
const cancelDrag = (0,
|
|
6663
|
+
const cancelDrag = (0, import_react19.useCallback)(() => {
|
|
6374
6664
|
dragStartRef.current = null;
|
|
6375
6665
|
hasMovedRef.current = false;
|
|
6376
6666
|
setIsListening(false);
|
|
@@ -6381,7 +6671,7 @@ function useDrag(options = {}) {
|
|
|
6381
6671
|
draggedId: null
|
|
6382
6672
|
});
|
|
6383
6673
|
}, []);
|
|
6384
|
-
const isDraggingItem = (0,
|
|
6674
|
+
const isDraggingItem = (0, import_react19.useCallback)(
|
|
6385
6675
|
(id) => dragState.isDragging && dragState.draggedId === id,
|
|
6386
6676
|
[dragState.isDragging, dragState.draggedId]
|
|
6387
6677
|
);
|
|
@@ -6394,7 +6684,7 @@ function useDrag(options = {}) {
|
|
|
6394
6684
|
}
|
|
6395
6685
|
|
|
6396
6686
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
6397
|
-
var
|
|
6687
|
+
var import_react20 = require("react");
|
|
6398
6688
|
function useKeyboardShortcuts(options) {
|
|
6399
6689
|
const {
|
|
6400
6690
|
onDelete,
|
|
@@ -6405,7 +6695,7 @@ function useKeyboardShortcuts(options) {
|
|
|
6405
6695
|
onSelectAll,
|
|
6406
6696
|
enabled = true
|
|
6407
6697
|
} = options;
|
|
6408
|
-
(0,
|
|
6698
|
+
(0, import_react20.useEffect)(() => {
|
|
6409
6699
|
if (!enabled) return;
|
|
6410
6700
|
const handleKeyDown = (event) => {
|
|
6411
6701
|
const target = event.target;
|
|
@@ -6543,21 +6833,21 @@ function PIDCanvasImpl({
|
|
|
6543
6833
|
statusColorMap,
|
|
6544
6834
|
...props
|
|
6545
6835
|
}) {
|
|
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,
|
|
6836
|
+
const [localDiagram, setLocalDiagram] = (0, import_react21.useState)(diagram);
|
|
6837
|
+
const [dragOverPosition, setDragOverPosition] = (0, import_react21.useState)(null);
|
|
6838
|
+
const [isConnecting, setIsConnecting] = (0, import_react21.useState)(false);
|
|
6839
|
+
const [connectionSource, setConnectionSource] = (0, import_react21.useState)(null);
|
|
6840
|
+
const [connectionSourcePort, setConnectionSourcePort] = (0, import_react21.useState)(null);
|
|
6841
|
+
const [connectionCursor, setConnectionCursor] = (0, import_react21.useState)(null);
|
|
6842
|
+
const [hoveredNode, setHoveredNode] = (0, import_react21.useState)(null);
|
|
6843
|
+
const [hoveredPort, setHoveredPort] = (0, import_react21.useState)(null);
|
|
6844
|
+
const [selectedWaypoint, setSelectedWaypoint] = (0, import_react21.useState)(null);
|
|
6845
|
+
const historyStack = (0, import_react21.useRef)([]);
|
|
6846
|
+
const redoStack = (0, import_react21.useRef)([]);
|
|
6847
|
+
const isUndoRedoAction = (0, import_react21.useRef)(false);
|
|
6848
|
+
const isInternalChange = (0, import_react21.useRef)(false);
|
|
6849
|
+
const lastInternalDiagram = (0, import_react21.useRef)(null);
|
|
6850
|
+
(0, import_react21.useEffect)(() => {
|
|
6561
6851
|
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
6562
6852
|
if (isExternal) {
|
|
6563
6853
|
setLocalDiagram(diagram);
|
|
@@ -6579,7 +6869,7 @@ function PIDCanvasImpl({
|
|
|
6579
6869
|
enablePan: features.pan ?? true,
|
|
6580
6870
|
enableZoom: features.zoom ?? true
|
|
6581
6871
|
});
|
|
6582
|
-
const calculateContentBounds = (0,
|
|
6872
|
+
const calculateContentBounds = (0, import_react21.useCallback)(() => {
|
|
6583
6873
|
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
6584
6874
|
if (nodes2.length === 0) {
|
|
6585
6875
|
return null;
|
|
@@ -6602,7 +6892,7 @@ function PIDCanvasImpl({
|
|
|
6602
6892
|
});
|
|
6603
6893
|
return { minX, minY, maxX, maxY };
|
|
6604
6894
|
}, [localDiagram.nodes]);
|
|
6605
|
-
(0,
|
|
6895
|
+
(0, import_react21.useEffect)(() => {
|
|
6606
6896
|
if (onMounted) {
|
|
6607
6897
|
const controls = {
|
|
6608
6898
|
fitToContent: (padding = 50) => {
|
|
@@ -6643,8 +6933,8 @@ function PIDCanvasImpl({
|
|
|
6643
6933
|
});
|
|
6644
6934
|
const dragEnabled = features.dragNodes ?? false;
|
|
6645
6935
|
const selectionEnabled = features.selection ?? false;
|
|
6646
|
-
const containerRef = (0,
|
|
6647
|
-
const pushToHistory = (0,
|
|
6936
|
+
const containerRef = (0, import_react21.useRef)(null);
|
|
6937
|
+
const pushToHistory = (0, import_react21.useCallback)((currentDiagram) => {
|
|
6648
6938
|
if (isUndoRedoAction.current) return;
|
|
6649
6939
|
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
6650
6940
|
historyStack.current.push(snapshot);
|
|
@@ -6653,7 +6943,7 @@ function PIDCanvasImpl({
|
|
|
6653
6943
|
}
|
|
6654
6944
|
redoStack.current = [];
|
|
6655
6945
|
}, []);
|
|
6656
|
-
const undo = (0,
|
|
6946
|
+
const undo = (0, import_react21.useCallback)(() => {
|
|
6657
6947
|
if (historyStack.current.length === 0) return;
|
|
6658
6948
|
isUndoRedoAction.current = true;
|
|
6659
6949
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -6667,7 +6957,7 @@ function PIDCanvasImpl({
|
|
|
6667
6957
|
isUndoRedoAction.current = false;
|
|
6668
6958
|
}, 0);
|
|
6669
6959
|
}, [localDiagram, onDiagramChange]);
|
|
6670
|
-
const redo = (0,
|
|
6960
|
+
const redo = (0, import_react21.useCallback)(() => {
|
|
6671
6961
|
if (redoStack.current.length === 0) return;
|
|
6672
6962
|
isUndoRedoAction.current = true;
|
|
6673
6963
|
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
@@ -6681,7 +6971,7 @@ function PIDCanvasImpl({
|
|
|
6681
6971
|
isUndoRedoAction.current = false;
|
|
6682
6972
|
}, 0);
|
|
6683
6973
|
}, [localDiagram, onDiagramChange]);
|
|
6684
|
-
(0,
|
|
6974
|
+
(0, import_react21.useEffect)(() => {
|
|
6685
6975
|
const handleKeyDown = (e) => {
|
|
6686
6976
|
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
6687
6977
|
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
@@ -6698,7 +6988,7 @@ function PIDCanvasImpl({
|
|
|
6698
6988
|
window.addEventListener("keydown", handleKeyDown);
|
|
6699
6989
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
6700
6990
|
}, [undo, redo]);
|
|
6701
|
-
(0,
|
|
6991
|
+
(0, import_react21.useEffect)(() => {
|
|
6702
6992
|
if (!features.dragNodes) return;
|
|
6703
6993
|
const handleKeyDown = (e) => {
|
|
6704
6994
|
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
@@ -6783,7 +7073,7 @@ function PIDCanvasImpl({
|
|
|
6783
7073
|
onNodeMove,
|
|
6784
7074
|
pushToHistory
|
|
6785
7075
|
]);
|
|
6786
|
-
const handlePositionChange = (0,
|
|
7076
|
+
const handlePositionChange = (0, import_react21.useCallback)(
|
|
6787
7077
|
(nodeId, x, y) => {
|
|
6788
7078
|
pushToHistory(localDiagram);
|
|
6789
7079
|
const updatedNodes = localDiagram.nodes.map(
|
|
@@ -6805,7 +7095,7 @@ function PIDCanvasImpl({
|
|
|
6805
7095
|
},
|
|
6806
7096
|
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
6807
7097
|
);
|
|
6808
|
-
const handleWaypointPositionChange = (0,
|
|
7098
|
+
const handleWaypointPositionChange = (0, import_react21.useCallback)(
|
|
6809
7099
|
(pipeId, pointIndex, x, y) => {
|
|
6810
7100
|
pushToHistory(localDiagram);
|
|
6811
7101
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -6823,7 +7113,7 @@ function PIDCanvasImpl({
|
|
|
6823
7113
|
},
|
|
6824
7114
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
6825
7115
|
);
|
|
6826
|
-
const handleDragEnd = (0,
|
|
7116
|
+
const handleDragEnd = (0, import_react21.useCallback)(
|
|
6827
7117
|
(nodeId, offset, finalPosition) => {
|
|
6828
7118
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
6829
7119
|
if (dragDistance < 2) {
|
|
@@ -6904,7 +7194,7 @@ function PIDCanvasImpl({
|
|
|
6904
7194
|
onDiagramChange?.(updatedDiagram);
|
|
6905
7195
|
}
|
|
6906
7196
|
});
|
|
6907
|
-
const handleNodeDragStart = (0,
|
|
7197
|
+
const handleNodeDragStart = (0, import_react21.useCallback)(
|
|
6908
7198
|
(nodeId, event) => {
|
|
6909
7199
|
const node = localDiagram.nodes.find((n) => n.id === nodeId);
|
|
6910
7200
|
if (!node) return;
|
|
@@ -6912,7 +7202,7 @@ function PIDCanvasImpl({
|
|
|
6912
7202
|
},
|
|
6913
7203
|
[localDiagram.nodes, startDrag]
|
|
6914
7204
|
);
|
|
6915
|
-
const handleWaypointClick = (0,
|
|
7205
|
+
const handleWaypointClick = (0, import_react21.useCallback)(
|
|
6916
7206
|
(pipeId, pointIndex) => {
|
|
6917
7207
|
setSelectedWaypoint({ pipeId, pointIndex });
|
|
6918
7208
|
if (selectionEnabled) {
|
|
@@ -6921,7 +7211,7 @@ function PIDCanvasImpl({
|
|
|
6921
7211
|
},
|
|
6922
7212
|
[selectionEnabled, clearSelection]
|
|
6923
7213
|
);
|
|
6924
|
-
const handleWaypointDragStart = (0,
|
|
7214
|
+
const handleWaypointDragStart = (0, import_react21.useCallback)(
|
|
6925
7215
|
(pipeId, pointIndex, event) => {
|
|
6926
7216
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
6927
7217
|
if (!pipe || pointIndex >= pipe.routePoints.length) return;
|
|
@@ -6930,7 +7220,7 @@ function PIDCanvasImpl({
|
|
|
6930
7220
|
},
|
|
6931
7221
|
[localDiagram.pipes, startWaypointDrag]
|
|
6932
7222
|
);
|
|
6933
|
-
const handlePipeSegmentClick = (0,
|
|
7223
|
+
const handlePipeSegmentClick = (0, import_react21.useCallback)(
|
|
6934
7224
|
(pipeId, position, segmentIndex) => {
|
|
6935
7225
|
pushToHistory(localDiagram);
|
|
6936
7226
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -6949,7 +7239,7 @@ function PIDCanvasImpl({
|
|
|
6949
7239
|
[localDiagram, onDiagramChange, pushToHistory]
|
|
6950
7240
|
);
|
|
6951
7241
|
const telemetryEnabled = features.telemetry ?? false;
|
|
6952
|
-
const handleDelete = (0,
|
|
7242
|
+
const handleDelete = (0, import_react21.useCallback)(() => {
|
|
6953
7243
|
if (!selectionEnabled) return;
|
|
6954
7244
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
6955
7245
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
@@ -6978,17 +7268,17 @@ function PIDCanvasImpl({
|
|
|
6978
7268
|
onDelete,
|
|
6979
7269
|
pushToHistory
|
|
6980
7270
|
]);
|
|
6981
|
-
const handleCopy = (0,
|
|
7271
|
+
const handleCopy = (0, import_react21.useCallback)(() => {
|
|
6982
7272
|
if (!selectionEnabled) return;
|
|
6983
7273
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
6984
7274
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
6985
7275
|
onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
6986
7276
|
}, [selection, selectionEnabled, onItemsCopied]);
|
|
6987
|
-
const handlePaste = (0,
|
|
7277
|
+
const handlePaste = (0, import_react21.useCallback)(() => {
|
|
6988
7278
|
if (!selectionEnabled) return;
|
|
6989
7279
|
onPaste?.();
|
|
6990
7280
|
}, [selectionEnabled, onPaste]);
|
|
6991
|
-
const handleNodeDoubleClick = (0,
|
|
7281
|
+
const handleNodeDoubleClick = (0, import_react21.useCallback)(
|
|
6992
7282
|
(nodeId, event) => {
|
|
6993
7283
|
if (!selectionEnabled) return;
|
|
6994
7284
|
console.log("Node double-clicked:", nodeId);
|
|
@@ -7002,7 +7292,7 @@ function PIDCanvasImpl({
|
|
|
7002
7292
|
onCopy: handleCopy,
|
|
7003
7293
|
onPaste: handlePaste
|
|
7004
7294
|
});
|
|
7005
|
-
const handleNodeClick = (0,
|
|
7295
|
+
const handleNodeClick = (0, import_react21.useCallback)(
|
|
7006
7296
|
(nodeId, event) => {
|
|
7007
7297
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
7008
7298
|
if (connectionModeEnabled && isConnecting) {
|
|
@@ -7044,7 +7334,7 @@ function PIDCanvasImpl({
|
|
|
7044
7334
|
onNodeClick
|
|
7045
7335
|
]
|
|
7046
7336
|
);
|
|
7047
|
-
const handlePipeClick = (0,
|
|
7337
|
+
const handlePipeClick = (0, import_react21.useCallback)(
|
|
7048
7338
|
(pipeId, event) => {
|
|
7049
7339
|
if (selectionEnabled) {
|
|
7050
7340
|
selectPipe(pipeId, event.ctrlKey || event.metaKey);
|
|
@@ -7063,7 +7353,7 @@ function PIDCanvasImpl({
|
|
|
7063
7353
|
}
|
|
7064
7354
|
setSelectedWaypoint(null);
|
|
7065
7355
|
};
|
|
7066
|
-
const handleDragOver = (0,
|
|
7356
|
+
const handleDragOver = (0, import_react21.useCallback)(
|
|
7067
7357
|
(event) => {
|
|
7068
7358
|
if (!features.allowSymbolDrop) return;
|
|
7069
7359
|
event.preventDefault();
|
|
@@ -7074,7 +7364,7 @@ function PIDCanvasImpl({
|
|
|
7074
7364
|
},
|
|
7075
7365
|
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
7076
7366
|
);
|
|
7077
|
-
const handleDrop = (0,
|
|
7367
|
+
const handleDrop = (0, import_react21.useCallback)(
|
|
7078
7368
|
(event) => {
|
|
7079
7369
|
if (!features.allowSymbolDrop) return;
|
|
7080
7370
|
event.preventDefault();
|
|
@@ -7087,10 +7377,10 @@ function PIDCanvasImpl({
|
|
|
7087
7377
|
},
|
|
7088
7378
|
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
7089
7379
|
);
|
|
7090
|
-
const handleDragLeave = (0,
|
|
7380
|
+
const handleDragLeave = (0, import_react21.useCallback)(() => {
|
|
7091
7381
|
setDragOverPosition(null);
|
|
7092
7382
|
}, []);
|
|
7093
|
-
const handleMouseMove = (0,
|
|
7383
|
+
const handleMouseMove = (0, import_react21.useCallback)(
|
|
7094
7384
|
(event) => {
|
|
7095
7385
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
7096
7386
|
if (connectionModeEnabled) {
|
|
@@ -7235,6 +7525,7 @@ function PIDCanvasImpl({
|
|
|
7235
7525
|
}
|
|
7236
7526
|
),
|
|
7237
7527
|
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
7528
|
+
if (node.symbolId === "status-indicator") return null;
|
|
7238
7529
|
const binding = telemetry.get(node.id);
|
|
7239
7530
|
if (!binding) return null;
|
|
7240
7531
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
@@ -7400,10 +7691,10 @@ function PIDCanvasImpl({
|
|
|
7400
7691
|
}
|
|
7401
7692
|
);
|
|
7402
7693
|
}
|
|
7403
|
-
var PIDCanvas =
|
|
7694
|
+
var PIDCanvas = import_react21.default.memo(PIDCanvasImpl);
|
|
7404
7695
|
|
|
7405
7696
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
7406
|
-
var
|
|
7697
|
+
var import_react22 = require("react");
|
|
7407
7698
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
7408
7699
|
function SymbolLibrary({
|
|
7409
7700
|
className = "",
|
|
@@ -7411,8 +7702,8 @@ function SymbolLibrary({
|
|
|
7411
7702
|
showCategories = true,
|
|
7412
7703
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
7413
7704
|
}) {
|
|
7414
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
7415
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
7705
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react22.useState)("all");
|
|
7706
|
+
const [searchQuery, setSearchQuery] = (0, import_react22.useState)("");
|
|
7416
7707
|
const symbolIds = getAvailableSymbols();
|
|
7417
7708
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
7418
7709
|
const categoryMap = {
|
|
@@ -7602,6 +7893,8 @@ function NodeConfigPanel({
|
|
|
7602
7893
|
onUpdateNode,
|
|
7603
7894
|
onUpdateTelemetry,
|
|
7604
7895
|
onAddTelemetry,
|
|
7896
|
+
onRemoveTelemetry,
|
|
7897
|
+
availableTags = [],
|
|
7605
7898
|
onRemove,
|
|
7606
7899
|
className = "",
|
|
7607
7900
|
style = {}
|
|
@@ -7614,6 +7907,8 @@ function NodeConfigPanel({
|
|
|
7614
7907
|
padding: "20px",
|
|
7615
7908
|
...style
|
|
7616
7909
|
};
|
|
7910
|
+
const appearanceFields = getAppearanceSchema(node.symbolId);
|
|
7911
|
+
const showGenericTelemetry = appearanceFields.length === 0;
|
|
7617
7912
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, style: defaultStyle, children: [
|
|
7618
7913
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
7619
7914
|
"Configure: ",
|
|
@@ -7735,7 +8030,136 @@ function NodeConfigPanel({
|
|
|
7735
8030
|
)
|
|
7736
8031
|
] })
|
|
7737
8032
|
] }),
|
|
7738
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8033
|
+
appearanceFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8034
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Appearance" }),
|
|
8035
|
+
appearanceFields.map((field) => {
|
|
8036
|
+
const value = readAppearanceValue(node, field);
|
|
8037
|
+
const fieldLabel = field.label ?? field.key;
|
|
8038
|
+
const inputStyle = {
|
|
8039
|
+
width: "100%",
|
|
8040
|
+
padding: "6px 8px",
|
|
8041
|
+
borderRadius: "4px",
|
|
8042
|
+
border: "1px solid #cbd5e1",
|
|
8043
|
+
fontSize: "0.875rem"
|
|
8044
|
+
};
|
|
8045
|
+
let control;
|
|
8046
|
+
if (field.kind === "boolean") {
|
|
8047
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block" }, children: [
|
|
8048
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8049
|
+
"input",
|
|
8050
|
+
{
|
|
8051
|
+
type: "checkbox",
|
|
8052
|
+
checked: Boolean(value),
|
|
8053
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.checked)),
|
|
8054
|
+
style: { marginRight: "6px" }
|
|
8055
|
+
}
|
|
8056
|
+
),
|
|
8057
|
+
fieldLabel
|
|
8058
|
+
] });
|
|
8059
|
+
} else if (field.kind === "select") {
|
|
8060
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8061
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8062
|
+
fieldLabel,
|
|
8063
|
+
":"
|
|
8064
|
+
] }),
|
|
8065
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8066
|
+
"select",
|
|
8067
|
+
{
|
|
8068
|
+
value: String(value),
|
|
8069
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8070
|
+
style: inputStyle,
|
|
8071
|
+
children: field.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: opt, children: opt }, opt))
|
|
8072
|
+
}
|
|
8073
|
+
)
|
|
8074
|
+
] });
|
|
8075
|
+
} else if (field.kind === "number") {
|
|
8076
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8077
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8078
|
+
fieldLabel,
|
|
8079
|
+
":"
|
|
8080
|
+
] }),
|
|
8081
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8082
|
+
"input",
|
|
8083
|
+
{
|
|
8084
|
+
type: "number",
|
|
8085
|
+
value: Number(value),
|
|
8086
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, parseFloat(e.target.value) || 0)),
|
|
8087
|
+
style: inputStyle
|
|
8088
|
+
}
|
|
8089
|
+
)
|
|
8090
|
+
] });
|
|
8091
|
+
} else if (field.kind === "tag") {
|
|
8092
|
+
const tagValue = String(value);
|
|
8093
|
+
const listId = `tags-${node.id}-${field.key}`;
|
|
8094
|
+
const known = tagValue.length > 0 && availableTags.includes(tagValue);
|
|
8095
|
+
const unknown = tagValue.length > 0 && !known;
|
|
8096
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8097
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8098
|
+
fieldLabel,
|
|
8099
|
+
":"
|
|
8100
|
+
] }),
|
|
8101
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8102
|
+
"input",
|
|
8103
|
+
{
|
|
8104
|
+
type: "text",
|
|
8105
|
+
value: tagValue,
|
|
8106
|
+
list: listId,
|
|
8107
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8108
|
+
placeholder: "type or pick a signal\u2026",
|
|
8109
|
+
style: {
|
|
8110
|
+
...inputStyle,
|
|
8111
|
+
border: `1px solid ${unknown ? "#f59e0b" : known ? "#22c55e" : "#cbd5e1"}`
|
|
8112
|
+
}
|
|
8113
|
+
}
|
|
8114
|
+
),
|
|
8115
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("datalist", { id: listId, children: availableTags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: t }, t)) }),
|
|
8116
|
+
tagValue.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8117
|
+
"div",
|
|
8118
|
+
{
|
|
8119
|
+
style: {
|
|
8120
|
+
fontSize: "0.7rem",
|
|
8121
|
+
marginTop: "3px",
|
|
8122
|
+
color: known ? "#16a34a" : "#b45309"
|
|
8123
|
+
},
|
|
8124
|
+
children: known ? "\u2713 matched signal" : "\u26A0 no matching signal (reads as false until published)"
|
|
8125
|
+
}
|
|
8126
|
+
)
|
|
8127
|
+
] });
|
|
8128
|
+
} else {
|
|
8129
|
+
control = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8130
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8131
|
+
fieldLabel,
|
|
8132
|
+
":"
|
|
8133
|
+
] }),
|
|
8134
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8135
|
+
"input",
|
|
8136
|
+
{
|
|
8137
|
+
type: "text",
|
|
8138
|
+
value: String(value),
|
|
8139
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8140
|
+
style: inputStyle
|
|
8141
|
+
}
|
|
8142
|
+
)
|
|
8143
|
+
] });
|
|
8144
|
+
}
|
|
8145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "10px" }, children: [
|
|
8146
|
+
control,
|
|
8147
|
+
field.help && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8148
|
+
"div",
|
|
8149
|
+
{
|
|
8150
|
+
style: {
|
|
8151
|
+
fontSize: "0.7rem",
|
|
8152
|
+
color: "#64748b",
|
|
8153
|
+
marginTop: "3px",
|
|
8154
|
+
lineHeight: 1.35
|
|
8155
|
+
},
|
|
8156
|
+
children: field.help
|
|
8157
|
+
}
|
|
8158
|
+
)
|
|
8159
|
+
] }, field.key);
|
|
8160
|
+
})
|
|
8161
|
+
] }),
|
|
8162
|
+
showGenericTelemetry && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
7739
8163
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
7740
8164
|
!binding ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7741
8165
|
"button",
|
|
@@ -7781,6 +8205,27 @@ function NodeConfigPanel({
|
|
|
7781
8205
|
children: "+ Add Telemetry"
|
|
7782
8206
|
}
|
|
7783
8207
|
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8208
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Tag (attribute):" }),
|
|
8209
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8210
|
+
"input",
|
|
8211
|
+
{
|
|
8212
|
+
type: "text",
|
|
8213
|
+
value: binding.tag || "",
|
|
8214
|
+
onChange: (e) => onUpdateTelemetry({
|
|
8215
|
+
nodeId: node.id,
|
|
8216
|
+
tag: e.target.value
|
|
8217
|
+
}),
|
|
8218
|
+
placeholder: "e.g. pump.running",
|
|
8219
|
+
style: {
|
|
8220
|
+
width: "100%",
|
|
8221
|
+
padding: "6px 8px",
|
|
8222
|
+
borderRadius: "4px",
|
|
8223
|
+
border: "1px solid #cbd5e1",
|
|
8224
|
+
fontSize: "0.875rem",
|
|
8225
|
+
marginBottom: "8px"
|
|
8226
|
+
}
|
|
8227
|
+
}
|
|
8228
|
+
),
|
|
7784
8229
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
7785
8230
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7786
8231
|
"input",
|
|
@@ -8088,10 +8533,28 @@ function NodeConfigPanel({
|
|
|
8088
8533
|
] })
|
|
8089
8534
|
] }),
|
|
8090
8535
|
" "
|
|
8091
|
-
] })
|
|
8536
|
+
] }),
|
|
8537
|
+
onRemoveTelemetry && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8538
|
+
"button",
|
|
8539
|
+
{
|
|
8540
|
+
onClick: onRemoveTelemetry,
|
|
8541
|
+
style: {
|
|
8542
|
+
width: "100%",
|
|
8543
|
+
padding: "6px 8px",
|
|
8544
|
+
marginTop: "8px",
|
|
8545
|
+
borderRadius: "4px",
|
|
8546
|
+
border: "1px solid #ef4444",
|
|
8547
|
+
background: "transparent",
|
|
8548
|
+
color: "#ef4444",
|
|
8549
|
+
fontSize: "0.8125rem",
|
|
8550
|
+
cursor: "pointer"
|
|
8551
|
+
},
|
|
8552
|
+
children: "Remove Telemetry"
|
|
8553
|
+
}
|
|
8554
|
+
)
|
|
8092
8555
|
] })
|
|
8093
8556
|
] }),
|
|
8094
|
-
binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8557
|
+
showGenericTelemetry && binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8095
8558
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
8096
8559
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
8097
8560
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
@@ -8121,7 +8584,7 @@ function NodeConfigPanel({
|
|
|
8121
8584
|
] }, key);
|
|
8122
8585
|
})
|
|
8123
8586
|
] }),
|
|
8124
|
-
binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8587
|
+
showGenericTelemetry && binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
8125
8588
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
8126
8589
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
8127
8590
|
const defaultColors = {
|
|
@@ -8463,13 +8926,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
|
|
|
8463
8926
|
}
|
|
8464
8927
|
|
|
8465
8928
|
// src/hooks/useDeviceControls.ts
|
|
8466
|
-
var
|
|
8929
|
+
var import_react23 = require("react");
|
|
8467
8930
|
function commandKey(nodeId, kind, suffix) {
|
|
8468
8931
|
return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
|
|
8469
8932
|
}
|
|
8470
8933
|
function useDeviceControls(initialBindings, options) {
|
|
8471
8934
|
const { commandTimeoutMs } = options ?? {};
|
|
8472
|
-
const [controls, setControls] = (0,
|
|
8935
|
+
const [controls, setControls] = (0, import_react23.useState)(() => {
|
|
8473
8936
|
const map = /* @__PURE__ */ new Map();
|
|
8474
8937
|
if (initialBindings) {
|
|
8475
8938
|
initialBindings.forEach((binding) => {
|
|
@@ -8478,12 +8941,12 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8478
8941
|
}
|
|
8479
8942
|
return map;
|
|
8480
8943
|
});
|
|
8481
|
-
const pendingRef = (0,
|
|
8482
|
-
const [pendingCommands, setPendingCommands] = (0,
|
|
8483
|
-
const syncPending = (0,
|
|
8944
|
+
const pendingRef = (0, import_react23.useRef)(/* @__PURE__ */ new Map());
|
|
8945
|
+
const [pendingCommands, setPendingCommands] = (0, import_react23.useState)(() => /* @__PURE__ */ new Set());
|
|
8946
|
+
const syncPending = (0, import_react23.useCallback)(() => {
|
|
8484
8947
|
setPendingCommands(new Set(pendingRef.current.keys()));
|
|
8485
8948
|
}, []);
|
|
8486
|
-
const updateControl = (0,
|
|
8949
|
+
const updateControl = (0, import_react23.useCallback)((nodeId, updates) => {
|
|
8487
8950
|
setControls((prev) => {
|
|
8488
8951
|
const newMap = new Map(prev);
|
|
8489
8952
|
const existing = newMap.get(nodeId);
|
|
@@ -8497,7 +8960,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8497
8960
|
return newMap;
|
|
8498
8961
|
});
|
|
8499
8962
|
}, []);
|
|
8500
|
-
const updateControlBatch = (0,
|
|
8963
|
+
const updateControlBatch = (0, import_react23.useCallback)((updates) => {
|
|
8501
8964
|
setControls((prev) => {
|
|
8502
8965
|
const newMap = new Map(prev);
|
|
8503
8966
|
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
@@ -8509,7 +8972,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8509
8972
|
return newMap;
|
|
8510
8973
|
});
|
|
8511
8974
|
}, []);
|
|
8512
|
-
const updateDeviceState = (0,
|
|
8975
|
+
const updateDeviceState = (0, import_react23.useCallback)(
|
|
8513
8976
|
(nodeId, stateUpdates) => {
|
|
8514
8977
|
setControls((prev) => {
|
|
8515
8978
|
const newMap = new Map(prev);
|
|
@@ -8525,7 +8988,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8525
8988
|
},
|
|
8526
8989
|
[]
|
|
8527
8990
|
);
|
|
8528
|
-
const updateParameter = (0,
|
|
8991
|
+
const updateParameter = (0, import_react23.useCallback)(
|
|
8529
8992
|
(nodeId, parameterId, value) => {
|
|
8530
8993
|
setControls((prev) => {
|
|
8531
8994
|
const newMap = new Map(prev);
|
|
@@ -8552,27 +9015,27 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8552
9015
|
},
|
|
8553
9016
|
[]
|
|
8554
9017
|
);
|
|
8555
|
-
const setControlBinding = (0,
|
|
9018
|
+
const setControlBinding = (0, import_react23.useCallback)((binding) => {
|
|
8556
9019
|
setControls((prev) => {
|
|
8557
9020
|
const newMap = new Map(prev);
|
|
8558
9021
|
newMap.set(binding.nodeId, binding);
|
|
8559
9022
|
return newMap;
|
|
8560
9023
|
});
|
|
8561
9024
|
}, []);
|
|
8562
|
-
const removeControlBinding = (0,
|
|
9025
|
+
const removeControlBinding = (0, import_react23.useCallback)((nodeId) => {
|
|
8563
9026
|
setControls((prev) => {
|
|
8564
9027
|
const newMap = new Map(prev);
|
|
8565
9028
|
newMap.delete(nodeId);
|
|
8566
9029
|
return newMap;
|
|
8567
9030
|
});
|
|
8568
9031
|
}, []);
|
|
8569
|
-
const getControlBinding = (0,
|
|
9032
|
+
const getControlBinding = (0, import_react23.useCallback)(
|
|
8570
9033
|
(nodeId) => {
|
|
8571
9034
|
return controls.get(nodeId);
|
|
8572
9035
|
},
|
|
8573
9036
|
[controls]
|
|
8574
9037
|
);
|
|
8575
|
-
const isCommandPending = (0,
|
|
9038
|
+
const isCommandPending = (0, import_react23.useCallback)(
|
|
8576
9039
|
(nodeId, kind) => {
|
|
8577
9040
|
if (kind) {
|
|
8578
9041
|
const prefix2 = `${nodeId}:${kind}`;
|
|
@@ -8589,7 +9052,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8589
9052
|
},
|
|
8590
9053
|
[pendingCommands]
|
|
8591
9054
|
);
|
|
8592
|
-
const markPending = (0,
|
|
9055
|
+
const markPending = (0, import_react23.useCallback)(
|
|
8593
9056
|
(key, delta) => {
|
|
8594
9057
|
const next = (pendingRef.current.get(key) ?? 0) + delta;
|
|
8595
9058
|
if (next > 0) pendingRef.current.set(key, next);
|
|
@@ -8598,7 +9061,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8598
9061
|
},
|
|
8599
9062
|
[syncPending]
|
|
8600
9063
|
);
|
|
8601
|
-
const runCommand = (0,
|
|
9064
|
+
const runCommand = (0, import_react23.useCallback)(
|
|
8602
9065
|
async (nodeId, key, invoke, messages) => {
|
|
8603
9066
|
const binding = controls.get(nodeId);
|
|
8604
9067
|
if (!binding) return;
|
|
@@ -8638,7 +9101,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8638
9101
|
},
|
|
8639
9102
|
[controls, updateDeviceState, markPending, commandTimeoutMs]
|
|
8640
9103
|
);
|
|
8641
|
-
const sendModeChange = (0,
|
|
9104
|
+
const sendModeChange = (0, import_react23.useCallback)(
|
|
8642
9105
|
(nodeId, mode) => runCommand(
|
|
8643
9106
|
nodeId,
|
|
8644
9107
|
commandKey(nodeId, "mode"),
|
|
@@ -8647,7 +9110,7 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8647
9110
|
),
|
|
8648
9111
|
[runCommand]
|
|
8649
9112
|
);
|
|
8650
|
-
const sendParameterChange = (0,
|
|
9113
|
+
const sendParameterChange = (0, import_react23.useCallback)(
|
|
8651
9114
|
(nodeId, parameterId, value) => runCommand(
|
|
8652
9115
|
nodeId,
|
|
8653
9116
|
commandKey(nodeId, "parameter", parameterId),
|
|
@@ -8656,21 +9119,21 @@ function useDeviceControls(initialBindings, options) {
|
|
|
8656
9119
|
),
|
|
8657
9120
|
[runCommand]
|
|
8658
9121
|
);
|
|
8659
|
-
const sendStartCommand = (0,
|
|
9122
|
+
const sendStartCommand = (0, import_react23.useCallback)(
|
|
8660
9123
|
(nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
|
|
8661
9124
|
success: "Start command sent",
|
|
8662
9125
|
failure: "Start command failed"
|
|
8663
9126
|
}),
|
|
8664
9127
|
[runCommand]
|
|
8665
9128
|
);
|
|
8666
|
-
const sendStopCommand = (0,
|
|
9129
|
+
const sendStopCommand = (0, import_react23.useCallback)(
|
|
8667
9130
|
(nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
|
|
8668
9131
|
success: "Stop command sent",
|
|
8669
9132
|
failure: "Stop command failed"
|
|
8670
9133
|
}),
|
|
8671
9134
|
[runCommand]
|
|
8672
9135
|
);
|
|
8673
|
-
const sendCustomAction = (0,
|
|
9136
|
+
const sendCustomAction = (0, import_react23.useCallback)(
|
|
8674
9137
|
(nodeId, actionId) => runCommand(
|
|
8675
9138
|
nodeId,
|
|
8676
9139
|
commandKey(nodeId, "action", actionId),
|
|
@@ -8723,9 +9186,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
|
|
|
8723
9186
|
}
|
|
8724
9187
|
|
|
8725
9188
|
// src/hooks/useDeviceConfigs.ts
|
|
8726
|
-
var
|
|
9189
|
+
var import_react24 = require("react");
|
|
8727
9190
|
function useDeviceConfigs(initialConfigs) {
|
|
8728
|
-
const [configs, setConfigs] = (0,
|
|
9191
|
+
const [configs, setConfigs] = (0, import_react24.useState)(() => {
|
|
8729
9192
|
const map = /* @__PURE__ */ new Map();
|
|
8730
9193
|
if (initialConfigs) {
|
|
8731
9194
|
initialConfigs.forEach((config) => {
|
|
@@ -8734,13 +9197,13 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8734
9197
|
}
|
|
8735
9198
|
return map;
|
|
8736
9199
|
});
|
|
8737
|
-
const getConfig = (0,
|
|
9200
|
+
const getConfig = (0, import_react24.useCallback)(
|
|
8738
9201
|
(nodeId) => {
|
|
8739
9202
|
return configs.get(nodeId);
|
|
8740
9203
|
},
|
|
8741
9204
|
[configs]
|
|
8742
9205
|
);
|
|
8743
|
-
const updateConfig = (0,
|
|
9206
|
+
const updateConfig = (0, import_react24.useCallback)((nodeId, updates) => {
|
|
8744
9207
|
setConfigs((prev) => {
|
|
8745
9208
|
const newMap = new Map(prev);
|
|
8746
9209
|
const existing = newMap.get(nodeId);
|
|
@@ -8754,7 +9217,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8754
9217
|
return newMap;
|
|
8755
9218
|
});
|
|
8756
9219
|
}, []);
|
|
8757
|
-
const updateConfigState = (0,
|
|
9220
|
+
const updateConfigState = (0, import_react24.useCallback)((nodeId, stateUpdates) => {
|
|
8758
9221
|
setConfigs((prev) => {
|
|
8759
9222
|
const newMap = new Map(prev);
|
|
8760
9223
|
const existing = newMap.get(nodeId);
|
|
@@ -8767,7 +9230,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8767
9230
|
return newMap;
|
|
8768
9231
|
});
|
|
8769
9232
|
}, []);
|
|
8770
|
-
const updateConfigBatch = (0,
|
|
9233
|
+
const updateConfigBatch = (0, import_react24.useCallback)((updates) => {
|
|
8771
9234
|
setConfigs((prev) => {
|
|
8772
9235
|
const newMap = new Map(prev);
|
|
8773
9236
|
Object.entries(updates).forEach(([nodeId, update]) => {
|
|
@@ -8779,7 +9242,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8779
9242
|
return newMap;
|
|
8780
9243
|
});
|
|
8781
9244
|
}, []);
|
|
8782
|
-
const updateParameterValue = (0,
|
|
9245
|
+
const updateParameterValue = (0, import_react24.useCallback)((nodeId, parameterId, value) => {
|
|
8783
9246
|
setConfigs((prev) => {
|
|
8784
9247
|
const newMap = new Map(prev);
|
|
8785
9248
|
const existing = newMap.get(nodeId);
|
|
@@ -8796,7 +9259,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8796
9259
|
return newMap;
|
|
8797
9260
|
});
|
|
8798
9261
|
}, []);
|
|
8799
|
-
const applyConfig = (0,
|
|
9262
|
+
const applyConfig = (0, import_react24.useCallback)(
|
|
8800
9263
|
async (nodeId) => {
|
|
8801
9264
|
const config = configs.get(nodeId);
|
|
8802
9265
|
if (!config || !config.actions.onApply) {
|
|
@@ -8829,7 +9292,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8829
9292
|
},
|
|
8830
9293
|
[configs, updateConfigState]
|
|
8831
9294
|
);
|
|
8832
|
-
const saveConfig = (0,
|
|
9295
|
+
const saveConfig = (0, import_react24.useCallback)(
|
|
8833
9296
|
async (nodeId) => {
|
|
8834
9297
|
const config = configs.get(nodeId);
|
|
8835
9298
|
if (!config || !config.actions.onSave) {
|
|
@@ -8863,7 +9326,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8863
9326
|
},
|
|
8864
9327
|
[configs, updateConfigState]
|
|
8865
9328
|
);
|
|
8866
|
-
const resetConfig = (0,
|
|
9329
|
+
const resetConfig = (0, import_react24.useCallback)(
|
|
8867
9330
|
async (nodeId) => {
|
|
8868
9331
|
const config = configs.get(nodeId);
|
|
8869
9332
|
if (!config) {
|
|
@@ -8893,7 +9356,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8893
9356
|
},
|
|
8894
9357
|
[configs, updateConfig, updateConfigState]
|
|
8895
9358
|
);
|
|
8896
|
-
const cancelConfig = (0,
|
|
9359
|
+
const cancelConfig = (0, import_react24.useCallback)(
|
|
8897
9360
|
(nodeId) => {
|
|
8898
9361
|
const config = configs.get(nodeId);
|
|
8899
9362
|
if (config?.actions.onCancel) {
|
|
@@ -8902,7 +9365,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8902
9365
|
},
|
|
8903
9366
|
[configs]
|
|
8904
9367
|
);
|
|
8905
|
-
const validateConfig = (0,
|
|
9368
|
+
const validateConfig = (0, import_react24.useCallback)(
|
|
8906
9369
|
(nodeId) => {
|
|
8907
9370
|
const config = configs.get(nodeId);
|
|
8908
9371
|
if (!config) {
|
|
@@ -8944,21 +9407,21 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8944
9407
|
},
|
|
8945
9408
|
[configs, updateConfigState]
|
|
8946
9409
|
);
|
|
8947
|
-
const setConfig = (0,
|
|
9410
|
+
const setConfig = (0, import_react24.useCallback)((config) => {
|
|
8948
9411
|
setConfigs((prev) => {
|
|
8949
9412
|
const newMap = new Map(prev);
|
|
8950
9413
|
newMap.set(config.nodeId, config);
|
|
8951
9414
|
return newMap;
|
|
8952
9415
|
});
|
|
8953
9416
|
}, []);
|
|
8954
|
-
const removeConfig = (0,
|
|
9417
|
+
const removeConfig = (0, import_react24.useCallback)((nodeId) => {
|
|
8955
9418
|
setConfigs((prev) => {
|
|
8956
9419
|
const newMap = new Map(prev);
|
|
8957
9420
|
newMap.delete(nodeId);
|
|
8958
9421
|
return newMap;
|
|
8959
9422
|
});
|
|
8960
9423
|
}, []);
|
|
8961
|
-
const clearConfigs = (0,
|
|
9424
|
+
const clearConfigs = (0, import_react24.useCallback)(() => {
|
|
8962
9425
|
setConfigs(/* @__PURE__ */ new Map());
|
|
8963
9426
|
}, []);
|
|
8964
9427
|
return {
|
|
@@ -8980,7 +9443,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8980
9443
|
}
|
|
8981
9444
|
|
|
8982
9445
|
// src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
|
|
8983
|
-
var
|
|
9446
|
+
var import_react25 = __toESM(require("react"), 1);
|
|
8984
9447
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
8985
9448
|
function DeviceConfigPanelImpl({
|
|
8986
9449
|
binding,
|
|
@@ -9000,7 +9463,7 @@ function DeviceConfigPanelImpl({
|
|
|
9000
9463
|
showBuiltInToast = true,
|
|
9001
9464
|
embedded = false
|
|
9002
9465
|
}) {
|
|
9003
|
-
const [localValues, setLocalValues] = (0,
|
|
9466
|
+
const [localValues, setLocalValues] = (0, import_react25.useState)(() => {
|
|
9004
9467
|
if (binding) {
|
|
9005
9468
|
const values = {};
|
|
9006
9469
|
binding.parameters.forEach((param) => {
|
|
@@ -9010,7 +9473,7 @@ function DeviceConfigPanelImpl({
|
|
|
9010
9473
|
}
|
|
9011
9474
|
return {};
|
|
9012
9475
|
});
|
|
9013
|
-
const [collapsedSections, setCollapsedSections] = (0,
|
|
9476
|
+
const [collapsedSections, setCollapsedSections] = (0, import_react25.useState)(() => {
|
|
9014
9477
|
const collapsed = /* @__PURE__ */ new Set();
|
|
9015
9478
|
if (binding?.sections) {
|
|
9016
9479
|
binding.sections.forEach((section) => {
|
|
@@ -9021,9 +9484,9 @@ function DeviceConfigPanelImpl({
|
|
|
9021
9484
|
}
|
|
9022
9485
|
return collapsed;
|
|
9023
9486
|
});
|
|
9024
|
-
const [showToast, setShowToast] = (0,
|
|
9025
|
-
const [bindingId, setBindingId] = (0,
|
|
9026
|
-
const lastResultTimestampRef = (0,
|
|
9487
|
+
const [showToast, setShowToast] = (0, import_react25.useState)(true);
|
|
9488
|
+
const [bindingId, setBindingId] = (0, import_react25.useState)(binding?.nodeId || null);
|
|
9489
|
+
const lastResultTimestampRef = (0, import_react25.useRef)(0);
|
|
9027
9490
|
if (binding && binding.nodeId !== bindingId) {
|
|
9028
9491
|
const values = {};
|
|
9029
9492
|
binding.parameters.forEach((param) => {
|
|
@@ -9039,7 +9502,7 @@ function DeviceConfigPanelImpl({
|
|
|
9039
9502
|
setCollapsedSections(collapsed);
|
|
9040
9503
|
setBindingId(binding.nodeId);
|
|
9041
9504
|
}
|
|
9042
|
-
(0,
|
|
9505
|
+
(0, import_react25.useEffect)(() => {
|
|
9043
9506
|
const currentTimestamp = binding?.state.lastSaved || 0;
|
|
9044
9507
|
if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
|
|
9045
9508
|
lastResultTimestampRef.current = currentTimestamp;
|
|
@@ -9056,7 +9519,7 @@ function DeviceConfigPanelImpl({
|
|
|
9056
9519
|
};
|
|
9057
9520
|
}
|
|
9058
9521
|
}, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
|
|
9059
|
-
const parametersBySection = (0,
|
|
9522
|
+
const parametersBySection = (0, import_react25.useMemo)(() => {
|
|
9060
9523
|
if (!binding) return { _unsectioned: [] };
|
|
9061
9524
|
const groups = { _unsectioned: [] };
|
|
9062
9525
|
binding.parameters.forEach((param) => {
|
|
@@ -9071,7 +9534,7 @@ function DeviceConfigPanelImpl({
|
|
|
9071
9534
|
});
|
|
9072
9535
|
return groups;
|
|
9073
9536
|
}, [binding]);
|
|
9074
|
-
const sortedSections = (0,
|
|
9537
|
+
const sortedSections = (0, import_react25.useMemo)(() => {
|
|
9075
9538
|
if (!binding?.sections) return [];
|
|
9076
9539
|
return [...binding.sections].sort((a, b) => (a.order || 0) - (b.order || 0));
|
|
9077
9540
|
}, [binding]);
|
|
@@ -9727,10 +10190,10 @@ function DeviceConfigPanelImpl({
|
|
|
9727
10190
|
)
|
|
9728
10191
|
] });
|
|
9729
10192
|
}
|
|
9730
|
-
var DeviceConfigPanel =
|
|
10193
|
+
var DeviceConfigPanel = import_react25.default.memo(DeviceConfigPanelImpl);
|
|
9731
10194
|
|
|
9732
10195
|
// src/diagram/hooks/useSimulation.ts
|
|
9733
|
-
var
|
|
10196
|
+
var import_react26 = require("react");
|
|
9734
10197
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
9735
10198
|
const {
|
|
9736
10199
|
interval = 2e3,
|
|
@@ -9741,7 +10204,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9741
10204
|
historyLength = 10,
|
|
9742
10205
|
generateValue
|
|
9743
10206
|
} = options;
|
|
9744
|
-
(0,
|
|
10207
|
+
(0, import_react26.useEffect)(() => {
|
|
9745
10208
|
if (!enabled) return;
|
|
9746
10209
|
const intervalId = setInterval(() => {
|
|
9747
10210
|
const updates = [];
|
|
@@ -9792,6 +10255,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9792
10255
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9793
10256
|
0 && (module.exports = {
|
|
9794
10257
|
Button,
|
|
10258
|
+
COLOR_PRESETS,
|
|
9795
10259
|
CardHeader,
|
|
9796
10260
|
CardUnit,
|
|
9797
10261
|
CardValue,
|
|
@@ -9821,6 +10285,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9821
10285
|
PanelTabs,
|
|
9822
10286
|
RightPanel,
|
|
9823
10287
|
RightToggleButton,
|
|
10288
|
+
STATUS_LED_APPEARANCE,
|
|
9824
10289
|
SVGArea,
|
|
9825
10290
|
SVGLockedOverlay,
|
|
9826
10291
|
ScrollableSVGWrapper,
|
|
@@ -9831,6 +10296,8 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9831
10296
|
ThemeProvider,
|
|
9832
10297
|
ThemeToggle,
|
|
9833
10298
|
TrendLine,
|
|
10299
|
+
UNKNOWN_MARK_COLOR,
|
|
10300
|
+
UNKNOWN_MARK_COLOR_DARK,
|
|
9834
10301
|
ValueEntry,
|
|
9835
10302
|
ZoomButton,
|
|
9836
10303
|
ZoomControls,
|
|
@@ -9840,6 +10307,8 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9840
10307
|
exampleDiagram,
|
|
9841
10308
|
exportDiagram,
|
|
9842
10309
|
generateRoutePoints,
|
|
10310
|
+
getAppearanceDefaults,
|
|
10311
|
+
getAppearanceSchema,
|
|
9843
10312
|
getAvailableSymbols,
|
|
9844
10313
|
getPortWorldPosition,
|
|
9845
10314
|
getSymbolDefinition,
|
|
@@ -9847,9 +10316,12 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9847
10316
|
mockSymbolLibrary,
|
|
9848
10317
|
nodeHasPort,
|
|
9849
10318
|
overlayStyles,
|
|
10319
|
+
readAppearanceValue,
|
|
9850
10320
|
registerSymbol,
|
|
9851
10321
|
registerSymbols,
|
|
10322
|
+
resolvePresetColor,
|
|
9852
10323
|
resolveStatusColor,
|
|
10324
|
+
useBooleanIndicators,
|
|
9853
10325
|
useDeviceConfigs,
|
|
9854
10326
|
useDeviceControls,
|
|
9855
10327
|
useDrag,
|
|
@@ -9860,6 +10332,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9860
10332
|
useTelemetryStatus,
|
|
9861
10333
|
useTheme,
|
|
9862
10334
|
useViewBox,
|
|
9863
|
-
validateDiagram
|
|
10335
|
+
validateDiagram,
|
|
10336
|
+
writeAppearanceValue
|
|
9864
10337
|
});
|
|
9865
10338
|
//# sourceMappingURL=index.cjs.map
|