@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.js
CHANGED
|
@@ -283,6 +283,20 @@ var FORCED_MARK_COLOR = {
|
|
|
283
283
|
text: "#5b21b6",
|
|
284
284
|
border: "#7c3aed"
|
|
285
285
|
};
|
|
286
|
+
var UNKNOWN_MARK_COLOR = {
|
|
287
|
+
fill: "#ebebf5",
|
|
288
|
+
stroke: "#8f8fc2",
|
|
289
|
+
bg: "#ebebf5",
|
|
290
|
+
text: "#4f4f8a",
|
|
291
|
+
border: "#8f8fc2"
|
|
292
|
+
};
|
|
293
|
+
var UNKNOWN_MARK_COLOR_DARK = {
|
|
294
|
+
fill: "#23263a",
|
|
295
|
+
stroke: "#6f74a3",
|
|
296
|
+
bg: "#23263a",
|
|
297
|
+
text: "#b9bbdb",
|
|
298
|
+
border: "#6f74a3"
|
|
299
|
+
};
|
|
286
300
|
var STATUS_ALIASES = {
|
|
287
301
|
running: "normal",
|
|
288
302
|
stopped: "off"
|
|
@@ -756,11 +770,15 @@ var StatusIndicator = ({
|
|
|
756
770
|
labelPosition = "right",
|
|
757
771
|
shape = "circle",
|
|
758
772
|
led = true,
|
|
773
|
+
visible = true,
|
|
759
774
|
forced = false,
|
|
760
775
|
realValue,
|
|
761
776
|
className = "",
|
|
762
777
|
...props
|
|
763
778
|
}) => {
|
|
779
|
+
if (!visible) {
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
764
782
|
const baseClass = "ui-status-indicator";
|
|
765
783
|
const statusClass = status ? `ui-status-indicator--${status}` : "";
|
|
766
784
|
const sizeClass = size ? `ui-status-indicator--${size}` : "";
|
|
@@ -3515,7 +3533,7 @@ var ThemeToggle = ({
|
|
|
3515
3533
|
};
|
|
3516
3534
|
|
|
3517
3535
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3518
|
-
import React13, { useCallback as useCallback8, useState as useState14, useEffect as
|
|
3536
|
+
import React13, { useCallback as useCallback8, useState as useState14, useEffect as useEffect13, useRef as useRef6 } from "react";
|
|
3519
3537
|
|
|
3520
3538
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
3521
3539
|
import React9 from "react";
|
|
@@ -3546,6 +3564,25 @@ var mockSymbolLibrary = {
|
|
|
3546
3564
|
tags: ["valve", "gate", "powered", "actuator"]
|
|
3547
3565
|
}
|
|
3548
3566
|
},
|
|
3567
|
+
"status-indicator": {
|
|
3568
|
+
id: "status-indicator",
|
|
3569
|
+
name: "Status LED",
|
|
3570
|
+
category: "instrument",
|
|
3571
|
+
viewBox: { x: 0, y: 0, width: 24, height: 24 },
|
|
3572
|
+
ports: [],
|
|
3573
|
+
svgContent: `
|
|
3574
|
+
<rect x="2" y="2" width="20" height="20"
|
|
3575
|
+
rx="var(--led-rx, 50%)"
|
|
3576
|
+
fill="var(--symbol-fill, #64748b)"
|
|
3577
|
+
stroke="rgba(255,255,255,0.4)"
|
|
3578
|
+
stroke-width="var(--led-bezel, 0)"
|
|
3579
|
+
style="transform-box: fill-box; transform: rotate(var(--led-rotate, 0deg)); transform-origin: center; pointer-events: all;"/>
|
|
3580
|
+
`,
|
|
3581
|
+
metadata: {
|
|
3582
|
+
description: "Status LED indicator driven by telemetry status color",
|
|
3583
|
+
tags: ["status", "led", "indicator", "instrument"]
|
|
3584
|
+
}
|
|
3585
|
+
},
|
|
3549
3586
|
"pump-positive-displacement": {
|
|
3550
3587
|
id: "pump-positive-displacement",
|
|
3551
3588
|
name: "Positive Displacement Pump",
|
|
@@ -4738,8 +4775,144 @@ function getAvailableSymbols() {
|
|
|
4738
4775
|
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
4739
4776
|
}
|
|
4740
4777
|
|
|
4778
|
+
// src/diagram/symbols/appearanceSchema.ts
|
|
4779
|
+
var COLOR_PRESETS = {
|
|
4780
|
+
green: "#22c55e",
|
|
4781
|
+
red: "#ef4444",
|
|
4782
|
+
amber: "#f59e0b",
|
|
4783
|
+
blue: "#3b82f6",
|
|
4784
|
+
grey: "#64748b"
|
|
4785
|
+
};
|
|
4786
|
+
function resolvePresetColor(name) {
|
|
4787
|
+
return name && COLOR_PRESETS[name] || COLOR_PRESETS.grey;
|
|
4788
|
+
}
|
|
4789
|
+
var COLOR_OPTIONS = Object.keys(COLOR_PRESETS);
|
|
4790
|
+
var STATUS_LED_APPEARANCE = [
|
|
4791
|
+
{
|
|
4792
|
+
key: "shape",
|
|
4793
|
+
kind: "select",
|
|
4794
|
+
label: "Shape",
|
|
4795
|
+
options: ["circle", "square", "diamond"],
|
|
4796
|
+
default: "circle"
|
|
4797
|
+
},
|
|
4798
|
+
{
|
|
4799
|
+
key: "size",
|
|
4800
|
+
kind: "select",
|
|
4801
|
+
label: "Size",
|
|
4802
|
+
target: "scale",
|
|
4803
|
+
options: ["small", "medium", "large"],
|
|
4804
|
+
default: "medium",
|
|
4805
|
+
valueMap: { small: 0.75, medium: 1, large: 1.5 }
|
|
4806
|
+
},
|
|
4807
|
+
{ key: "led", kind: "boolean", label: "Bezel ring", default: true },
|
|
4808
|
+
{ key: "glow", kind: "boolean", label: "Diffusion (glow)", default: false },
|
|
4809
|
+
{
|
|
4810
|
+
key: "animation",
|
|
4811
|
+
kind: "select",
|
|
4812
|
+
label: "Animation",
|
|
4813
|
+
options: ["none", "pulse", "blink"],
|
|
4814
|
+
default: "none"
|
|
4815
|
+
},
|
|
4816
|
+
{
|
|
4817
|
+
key: "labelPosition",
|
|
4818
|
+
kind: "select",
|
|
4819
|
+
label: "Label position",
|
|
4820
|
+
options: ["bottom", "top", "left", "right"],
|
|
4821
|
+
default: "bottom"
|
|
4822
|
+
},
|
|
4823
|
+
// Color binding: a named signal drives the on/off color.
|
|
4824
|
+
{
|
|
4825
|
+
key: "colorSource",
|
|
4826
|
+
kind: "tag",
|
|
4827
|
+
label: "Color source (tag)",
|
|
4828
|
+
default: "",
|
|
4829
|
+
help: "Signal/tag that drives color. True (non-zero) shows On color; false shows Off color. Blank = unbound (grey)."
|
|
4830
|
+
},
|
|
4831
|
+
{
|
|
4832
|
+
key: "onColor",
|
|
4833
|
+
kind: "select",
|
|
4834
|
+
label: "On color (true)",
|
|
4835
|
+
options: COLOR_OPTIONS,
|
|
4836
|
+
default: "green",
|
|
4837
|
+
help: "Color when the Color source is true."
|
|
4838
|
+
},
|
|
4839
|
+
{
|
|
4840
|
+
key: "offColor",
|
|
4841
|
+
kind: "select",
|
|
4842
|
+
label: "Off color (false)",
|
|
4843
|
+
options: COLOR_OPTIONS,
|
|
4844
|
+
default: "red",
|
|
4845
|
+
help: "Color when the Color source is false."
|
|
4846
|
+
},
|
|
4847
|
+
// Visibility binding: an independent named signal drives show/hide.
|
|
4848
|
+
{
|
|
4849
|
+
key: "visibleSource",
|
|
4850
|
+
kind: "tag",
|
|
4851
|
+
label: "Visibility source (tag)",
|
|
4852
|
+
default: "",
|
|
4853
|
+
help: "Signal/tag that drives visibility. True shows the LED, false hides it. Blank = always visible (use the Visible checkbox)."
|
|
4854
|
+
},
|
|
4855
|
+
{
|
|
4856
|
+
key: "visible",
|
|
4857
|
+
kind: "boolean",
|
|
4858
|
+
label: "Visible",
|
|
4859
|
+
target: "visible",
|
|
4860
|
+
default: true,
|
|
4861
|
+
help: "Static show/hide, used only when no Visibility source is set."
|
|
4862
|
+
}
|
|
4863
|
+
];
|
|
4864
|
+
var APPEARANCE_REGISTRY = {
|
|
4865
|
+
"status-indicator": STATUS_LED_APPEARANCE
|
|
4866
|
+
};
|
|
4867
|
+
function getAppearanceSchema(symbolId) {
|
|
4868
|
+
return APPEARANCE_REGISTRY[symbolId] ?? [];
|
|
4869
|
+
}
|
|
4870
|
+
function getAppearanceDefaults(symbolId) {
|
|
4871
|
+
const out = {};
|
|
4872
|
+
for (const field of getAppearanceSchema(symbolId)) {
|
|
4873
|
+
if ((field.target ?? "metadata") === "metadata" && field.default !== void 0) {
|
|
4874
|
+
out[field.key] = field.default;
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
return out;
|
|
4878
|
+
}
|
|
4879
|
+
function readAppearanceValue(node, field) {
|
|
4880
|
+
if (field.target === "visible") {
|
|
4881
|
+
return node.visible ?? field.default ?? true;
|
|
4882
|
+
}
|
|
4883
|
+
if (field.target === "scale") {
|
|
4884
|
+
const scale = node.transform.scale ?? 1;
|
|
4885
|
+
if (field.valueMap) {
|
|
4886
|
+
let bestOption = field.options?.[0] ?? String(scale);
|
|
4887
|
+
let bestDiff = Infinity;
|
|
4888
|
+
for (const [option, value2] of Object.entries(field.valueMap)) {
|
|
4889
|
+
const diff = Math.abs(value2 - scale);
|
|
4890
|
+
if (diff < bestDiff) {
|
|
4891
|
+
bestDiff = diff;
|
|
4892
|
+
bestOption = option;
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
return bestOption;
|
|
4896
|
+
}
|
|
4897
|
+
return scale;
|
|
4898
|
+
}
|
|
4899
|
+
const value = node.metadata?.[field.key];
|
|
4900
|
+
return value ?? field.default;
|
|
4901
|
+
}
|
|
4902
|
+
function writeAppearanceValue(node, field, value) {
|
|
4903
|
+
if (field.target === "visible") {
|
|
4904
|
+
return { visible: Boolean(value) };
|
|
4905
|
+
}
|
|
4906
|
+
if (field.target === "scale") {
|
|
4907
|
+
const scale = field.valueMap ? field.valueMap[String(value)] ?? 1 : Number(value);
|
|
4908
|
+
return { transform: { ...node.transform, scale } };
|
|
4909
|
+
}
|
|
4910
|
+
return { metadata: { ...node.metadata, [field.key]: value } };
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4741
4913
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
4742
4914
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4915
|
+
var HATCH_SIZE = 6;
|
|
4743
4916
|
function NodeRendererImpl({
|
|
4744
4917
|
nodes: nodes2,
|
|
4745
4918
|
selectedNodeIds,
|
|
@@ -4751,140 +4924,206 @@ function NodeRendererImpl({
|
|
|
4751
4924
|
enableDrag = false,
|
|
4752
4925
|
statusColorMap
|
|
4753
4926
|
}) {
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
return /* @__PURE__ */ jsxs12("g", { children: [
|
|
4760
|
-
/* @__PURE__ */ jsx16(
|
|
4761
|
-
"circle",
|
|
4762
|
-
{
|
|
4763
|
-
cx: node.transform.x,
|
|
4764
|
-
cy: node.transform.y,
|
|
4765
|
-
r: "15",
|
|
4766
|
-
fill: "#ff0000",
|
|
4767
|
-
opacity: "0.3",
|
|
4768
|
-
stroke: "#ff0000",
|
|
4769
|
-
strokeWidth: "2"
|
|
4770
|
-
}
|
|
4771
|
-
),
|
|
4772
|
-
/* @__PURE__ */ jsx16(
|
|
4773
|
-
"text",
|
|
4774
|
-
{
|
|
4775
|
-
x: node.transform.x,
|
|
4776
|
-
y: node.transform.y,
|
|
4777
|
-
textAnchor: "middle",
|
|
4778
|
-
dominantBaseline: "middle",
|
|
4779
|
-
fontSize: "10",
|
|
4780
|
-
fill: "#ff0000",
|
|
4781
|
-
children: "?"
|
|
4782
|
-
}
|
|
4783
|
-
)
|
|
4784
|
-
] }, node.id);
|
|
4785
|
-
}
|
|
4786
|
-
const transforms = [];
|
|
4787
|
-
const effectiveX = isDragging ? node.transform.x + dragOffset.x : node.transform.x;
|
|
4788
|
-
const effectiveY = isDragging ? node.transform.y + dragOffset.y : node.transform.y;
|
|
4789
|
-
transforms.push(`translate(${effectiveX}, ${effectiveY})`);
|
|
4790
|
-
if (node.transform.rotation) {
|
|
4791
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4792
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4793
|
-
transforms.push(`rotate(${node.transform.rotation}, ${centerX}, ${centerY})`);
|
|
4794
|
-
}
|
|
4795
|
-
if (node.transform.scale && node.transform.scale !== 1) {
|
|
4796
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4797
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4798
|
-
transforms.push(
|
|
4799
|
-
`translate(${centerX}, ${centerY}) scale(${node.transform.scale}) translate(${-centerX}, ${-centerY})`
|
|
4800
|
-
);
|
|
4801
|
-
}
|
|
4802
|
-
if (node.transform.flipX || node.transform.flipY) {
|
|
4803
|
-
const scaleX = node.transform.flipX ? -1 : 1;
|
|
4804
|
-
const scaleY = node.transform.flipY ? -1 : 1;
|
|
4805
|
-
const centerX = symbol.viewBox.width / 2;
|
|
4806
|
-
const centerY = symbol.viewBox.height / 2;
|
|
4807
|
-
transforms.push(
|
|
4808
|
-
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
4809
|
-
);
|
|
4810
|
-
}
|
|
4811
|
-
const statusEntry = resolveStatusColor(node.status, statusColorMap);
|
|
4812
|
-
const fillColor = node.customColors?.fill ?? statusEntry.fill;
|
|
4813
|
-
const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
|
|
4814
|
-
return /* @__PURE__ */ jsxs12(
|
|
4815
|
-
"g",
|
|
4927
|
+
const hatchId = `pid-unknown-hatch-${React9.useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
4928
|
+
const hasUnknown = nodes2.some((n) => n.positionUnknown === true && n.visible !== false);
|
|
4929
|
+
return /* @__PURE__ */ jsxs12("g", { id: "layer-nodes", children: [
|
|
4930
|
+
hasUnknown && /* @__PURE__ */ jsx16("defs", { children: /* @__PURE__ */ jsxs12(
|
|
4931
|
+
"pattern",
|
|
4816
4932
|
{
|
|
4817
|
-
|
|
4818
|
-
"data-
|
|
4819
|
-
"
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
"--symbol-fill": fillColor,
|
|
4824
|
-
"--symbol-stroke": strokeColor,
|
|
4825
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
4826
|
-
},
|
|
4827
|
-
onClick: (e) => {
|
|
4828
|
-
e.stopPropagation();
|
|
4829
|
-
onNodeClick?.(node.id, e);
|
|
4830
|
-
},
|
|
4831
|
-
onDoubleClick: (e) => {
|
|
4832
|
-
e.stopPropagation();
|
|
4833
|
-
onNodeDoubleClick?.(node.id, e);
|
|
4834
|
-
},
|
|
4835
|
-
onMouseDown: (e) => {
|
|
4836
|
-
if (enableDrag) {
|
|
4837
|
-
onNodeDragStart?.(node.id, e);
|
|
4838
|
-
}
|
|
4839
|
-
},
|
|
4840
|
-
onTouchStart: (e) => {
|
|
4841
|
-
if (enableDrag) {
|
|
4842
|
-
e.stopPropagation();
|
|
4843
|
-
onNodeDragStart?.(node.id, e);
|
|
4844
|
-
}
|
|
4845
|
-
},
|
|
4933
|
+
id: hatchId,
|
|
4934
|
+
"data-testid": "position-unknown-pattern",
|
|
4935
|
+
patternUnits: "userSpaceOnUse",
|
|
4936
|
+
width: HATCH_SIZE,
|
|
4937
|
+
height: HATCH_SIZE,
|
|
4938
|
+
patternTransform: "rotate(45)",
|
|
4846
4939
|
children: [
|
|
4847
|
-
|
|
4848
|
-
|
|
4940
|
+
/* @__PURE__ */ jsx16("rect", { width: HATCH_SIZE, height: HATCH_SIZE, fill: UNKNOWN_MARK_COLOR.fill }),
|
|
4941
|
+
/* @__PURE__ */ jsx16(
|
|
4942
|
+
"line",
|
|
4849
4943
|
{
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
strokeWidth: isDragging ? "3" : "2",
|
|
4857
|
-
strokeDasharray: "4 2",
|
|
4858
|
-
rx: "2",
|
|
4859
|
-
pointerEvents: "none"
|
|
4944
|
+
x1: "0",
|
|
4945
|
+
y1: "0",
|
|
4946
|
+
x2: "0",
|
|
4947
|
+
y2: HATCH_SIZE,
|
|
4948
|
+
stroke: UNKNOWN_MARK_COLOR.text,
|
|
4949
|
+
strokeWidth: "2"
|
|
4860
4950
|
}
|
|
4861
|
-
)
|
|
4951
|
+
)
|
|
4952
|
+
]
|
|
4953
|
+
}
|
|
4954
|
+
) }),
|
|
4955
|
+
nodes2.filter((node) => node.visible !== false).map((node) => {
|
|
4956
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
4957
|
+
const isSelected = selectedNodeIds?.has(node.id) ?? false;
|
|
4958
|
+
const isDragging = draggingNodeId === node.id;
|
|
4959
|
+
if (!symbol) {
|
|
4960
|
+
return /* @__PURE__ */ jsxs12("g", { children: [
|
|
4862
4961
|
/* @__PURE__ */ jsx16(
|
|
4863
|
-
"
|
|
4962
|
+
"circle",
|
|
4864
4963
|
{
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4964
|
+
cx: node.transform.x,
|
|
4965
|
+
cy: node.transform.y,
|
|
4966
|
+
r: "15",
|
|
4967
|
+
fill: "#ff0000",
|
|
4968
|
+
opacity: "0.3",
|
|
4969
|
+
stroke: "#ff0000",
|
|
4970
|
+
strokeWidth: "2"
|
|
4868
4971
|
}
|
|
4869
4972
|
),
|
|
4870
4973
|
/* @__PURE__ */ jsx16(
|
|
4871
4974
|
"text",
|
|
4872
4975
|
{
|
|
4873
|
-
x:
|
|
4874
|
-
y:
|
|
4976
|
+
x: node.transform.x,
|
|
4977
|
+
y: node.transform.y,
|
|
4875
4978
|
textAnchor: "middle",
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
fill:
|
|
4879
|
-
|
|
4880
|
-
children: node.label || node.id
|
|
4979
|
+
dominantBaseline: "middle",
|
|
4980
|
+
fontSize: "10",
|
|
4981
|
+
fill: "#ff0000",
|
|
4982
|
+
children: "?"
|
|
4881
4983
|
}
|
|
4882
4984
|
)
|
|
4883
|
-
]
|
|
4884
|
-
}
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4985
|
+
] }, node.id);
|
|
4986
|
+
}
|
|
4987
|
+
const transforms = [];
|
|
4988
|
+
const effectiveX = isDragging ? node.transform.x + dragOffset.x : node.transform.x;
|
|
4989
|
+
const effectiveY = isDragging ? node.transform.y + dragOffset.y : node.transform.y;
|
|
4990
|
+
transforms.push(`translate(${effectiveX}, ${effectiveY})`);
|
|
4991
|
+
if (node.transform.rotation) {
|
|
4992
|
+
const centerX = symbol.viewBox.width / 2;
|
|
4993
|
+
const centerY = symbol.viewBox.height / 2;
|
|
4994
|
+
transforms.push(`rotate(${node.transform.rotation}, ${centerX}, ${centerY})`);
|
|
4995
|
+
}
|
|
4996
|
+
if (node.transform.scale && node.transform.scale !== 1) {
|
|
4997
|
+
const centerX = symbol.viewBox.width / 2;
|
|
4998
|
+
const centerY = symbol.viewBox.height / 2;
|
|
4999
|
+
transforms.push(
|
|
5000
|
+
`translate(${centerX}, ${centerY}) scale(${node.transform.scale}) translate(${-centerX}, ${-centerY})`
|
|
5001
|
+
);
|
|
5002
|
+
}
|
|
5003
|
+
if (node.transform.flipX || node.transform.flipY) {
|
|
5004
|
+
const scaleX = node.transform.flipX ? -1 : 1;
|
|
5005
|
+
const scaleY = node.transform.flipY ? -1 : 1;
|
|
5006
|
+
const centerX = symbol.viewBox.width / 2;
|
|
5007
|
+
const centerY = symbol.viewBox.height / 2;
|
|
5008
|
+
transforms.push(
|
|
5009
|
+
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
5010
|
+
);
|
|
5011
|
+
}
|
|
5012
|
+
const statusEntry = resolveStatusColor(node.status, statusColorMap);
|
|
5013
|
+
const isUnknown = node.positionUnknown === true;
|
|
5014
|
+
const fillColor = isUnknown ? `url(#${hatchId})` : node.customColors?.fill ?? statusEntry.fill;
|
|
5015
|
+
const strokeColor = isUnknown ? UNKNOWN_MARK_COLOR.stroke : node.customColors?.stroke ?? statusEntry.stroke;
|
|
5016
|
+
const appearance = { ...getAppearanceDefaults(node.symbolId), ...node.metadata ?? {} };
|
|
5017
|
+
const ledStyle = {};
|
|
5018
|
+
if (appearance.shape !== void 0) {
|
|
5019
|
+
ledStyle["--led-rx"] = appearance.shape === "circle" ? "50%" : "2";
|
|
5020
|
+
ledStyle["--led-rotate"] = appearance.shape === "diamond" ? "45deg" : "0deg";
|
|
5021
|
+
}
|
|
5022
|
+
if (appearance.led !== void 0) {
|
|
5023
|
+
ledStyle["--led-bezel"] = appearance.led ? "2" : "0";
|
|
5024
|
+
}
|
|
5025
|
+
if (appearance.glow) {
|
|
5026
|
+
ledStyle.filter = `drop-shadow(0 0 4px ${fillColor})`;
|
|
5027
|
+
}
|
|
5028
|
+
const ledAnimation = typeof appearance.animation === "string" && appearance.animation !== "none" ? appearance.animation : void 0;
|
|
5029
|
+
const vb = symbol.viewBox;
|
|
5030
|
+
const ox = node.labelOffset?.x ?? 0;
|
|
5031
|
+
const oy = node.labelOffset?.y ?? 0;
|
|
5032
|
+
const labelPos = typeof appearance.labelPosition === "string" ? appearance.labelPosition : "bottom";
|
|
5033
|
+
let labelX = vb.width / 2 + ox;
|
|
5034
|
+
let labelY = vb.height + 12 + oy;
|
|
5035
|
+
let labelAnchor = "middle";
|
|
5036
|
+
if (labelPos === "top") {
|
|
5037
|
+
labelX = vb.width / 2 + ox;
|
|
5038
|
+
labelY = -6 + oy;
|
|
5039
|
+
labelAnchor = "middle";
|
|
5040
|
+
} else if (labelPos === "left") {
|
|
5041
|
+
labelX = -6 + ox;
|
|
5042
|
+
labelY = vb.height / 2 + oy;
|
|
5043
|
+
labelAnchor = "end";
|
|
5044
|
+
} else if (labelPos === "right") {
|
|
5045
|
+
labelX = vb.width + 6 + ox;
|
|
5046
|
+
labelY = vb.height / 2 + oy;
|
|
5047
|
+
labelAnchor = "start";
|
|
5048
|
+
}
|
|
5049
|
+
return /* @__PURE__ */ jsxs12(
|
|
5050
|
+
"g",
|
|
5051
|
+
{
|
|
5052
|
+
"data-node-id": node.id,
|
|
5053
|
+
"data-symbol-id": node.symbolId,
|
|
5054
|
+
"data-selected": isSelected,
|
|
5055
|
+
"data-dragging": isDragging,
|
|
5056
|
+
"data-led-animation": ledAnimation,
|
|
5057
|
+
"data-position-unknown": isUnknown ? "true" : void 0,
|
|
5058
|
+
transform: transforms.join(" "),
|
|
5059
|
+
style: {
|
|
5060
|
+
"--symbol-fill": fillColor,
|
|
5061
|
+
"--symbol-stroke": strokeColor,
|
|
5062
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default",
|
|
5063
|
+
...ledStyle
|
|
5064
|
+
},
|
|
5065
|
+
onClick: (e) => {
|
|
5066
|
+
e.stopPropagation();
|
|
5067
|
+
onNodeClick?.(node.id, e);
|
|
5068
|
+
},
|
|
5069
|
+
onDoubleClick: (e) => {
|
|
5070
|
+
e.stopPropagation();
|
|
5071
|
+
onNodeDoubleClick?.(node.id, e);
|
|
5072
|
+
},
|
|
5073
|
+
onMouseDown: (e) => {
|
|
5074
|
+
if (enableDrag) {
|
|
5075
|
+
onNodeDragStart?.(node.id, e);
|
|
5076
|
+
}
|
|
5077
|
+
},
|
|
5078
|
+
onTouchStart: (e) => {
|
|
5079
|
+
if (enableDrag) {
|
|
5080
|
+
e.stopPropagation();
|
|
5081
|
+
onNodeDragStart?.(node.id, e);
|
|
5082
|
+
}
|
|
5083
|
+
},
|
|
5084
|
+
children: [
|
|
5085
|
+
isSelected && /* @__PURE__ */ jsx16(
|
|
5086
|
+
"rect",
|
|
5087
|
+
{
|
|
5088
|
+
x: "-5",
|
|
5089
|
+
y: "-5",
|
|
5090
|
+
width: symbol.viewBox.width + 10,
|
|
5091
|
+
height: symbol.viewBox.height + 10,
|
|
5092
|
+
fill: "none",
|
|
5093
|
+
stroke: isDragging ? "#10b981" : "#3b82f6",
|
|
5094
|
+
strokeWidth: isDragging ? "3" : "2",
|
|
5095
|
+
strokeDasharray: "4 2",
|
|
5096
|
+
rx: "2",
|
|
5097
|
+
pointerEvents: "none"
|
|
5098
|
+
}
|
|
5099
|
+
),
|
|
5100
|
+
/* @__PURE__ */ jsx16(
|
|
5101
|
+
"g",
|
|
5102
|
+
{
|
|
5103
|
+
dangerouslySetInnerHTML: { __html: symbol.svgContent },
|
|
5104
|
+
"data-symbol-content": symbol.id,
|
|
5105
|
+
style: { pointerEvents: "auto" }
|
|
5106
|
+
}
|
|
5107
|
+
),
|
|
5108
|
+
/* @__PURE__ */ jsx16(
|
|
5109
|
+
"text",
|
|
5110
|
+
{
|
|
5111
|
+
x: labelX,
|
|
5112
|
+
y: labelY,
|
|
5113
|
+
textAnchor: labelAnchor,
|
|
5114
|
+
fontSize: node.labelFontSize ?? 10,
|
|
5115
|
+
fontWeight: "600",
|
|
5116
|
+
fill: isSelected ? "#3b82f6" : "#1f2937",
|
|
5117
|
+
transform: node.transform.rotation ? `rotate(${-node.transform.rotation}, ${labelX}, ${labelY})` : void 0,
|
|
5118
|
+
children: node.label || node.id
|
|
5119
|
+
}
|
|
5120
|
+
)
|
|
5121
|
+
]
|
|
5122
|
+
},
|
|
5123
|
+
node.id
|
|
5124
|
+
);
|
|
5125
|
+
})
|
|
5126
|
+
] });
|
|
4888
5127
|
}
|
|
4889
5128
|
var NodeRenderer = React9.memo(NodeRendererImpl);
|
|
4890
5129
|
|
|
@@ -6034,8 +6273,49 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
|
6034
6273
|
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
6035
6274
|
}
|
|
6036
6275
|
|
|
6276
|
+
// src/diagram/hooks/useBooleanIndicators.ts
|
|
6277
|
+
import { useEffect as useEffect10 } from "react";
|
|
6278
|
+
function useBooleanIndicators(telemetry, diagram, setDiagram, options = {}) {
|
|
6279
|
+
const { enabled = true, symbolId = "status-indicator" } = options;
|
|
6280
|
+
useEffect10(() => {
|
|
6281
|
+
if (!enabled) return;
|
|
6282
|
+
const tagIndex = /* @__PURE__ */ new Map();
|
|
6283
|
+
telemetry.forEach((binding) => {
|
|
6284
|
+
if (binding.tag) tagIndex.set(binding.tag, binding.value.value);
|
|
6285
|
+
});
|
|
6286
|
+
let needsUpdate = false;
|
|
6287
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
6288
|
+
if (node.symbolId !== symbolId) return node;
|
|
6289
|
+
const meta = node.metadata ?? {};
|
|
6290
|
+
const colorSource = typeof meta.colorSource === "string" ? meta.colorSource : "";
|
|
6291
|
+
const visibleSource = typeof meta.visibleSource === "string" ? meta.visibleSource : "";
|
|
6292
|
+
let next = node;
|
|
6293
|
+
if (colorSource) {
|
|
6294
|
+
const isTrue = Boolean(tagIndex.get(colorSource));
|
|
6295
|
+
const fill = resolvePresetColor(
|
|
6296
|
+
String(isTrue ? meta.onColor ?? "green" : meta.offColor ?? "red")
|
|
6297
|
+
);
|
|
6298
|
+
if (node.customColors?.fill !== fill) {
|
|
6299
|
+
next = { ...next, customColors: { ...next.customColors, fill } };
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
if (visibleSource) {
|
|
6303
|
+
const vis = Boolean(tagIndex.get(visibleSource));
|
|
6304
|
+
if ((next.visible ?? true) !== vis) {
|
|
6305
|
+
next = { ...next, visible: vis };
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
if (next !== node) needsUpdate = true;
|
|
6309
|
+
return next;
|
|
6310
|
+
});
|
|
6311
|
+
if (needsUpdate) {
|
|
6312
|
+
setDiagram({ ...diagram, nodes: updatedNodes });
|
|
6313
|
+
}
|
|
6314
|
+
}, [telemetry, diagram, setDiagram, enabled, symbolId]);
|
|
6315
|
+
}
|
|
6316
|
+
|
|
6037
6317
|
// src/diagram/hooks/useDrag.ts
|
|
6038
|
-
import { useState as useState13, useCallback as useCallback7, useRef as useRef5, useEffect as
|
|
6318
|
+
import { useState as useState13, useCallback as useCallback7, useRef as useRef5, useEffect as useEffect11 } from "react";
|
|
6039
6319
|
function useDrag(options = {}) {
|
|
6040
6320
|
const {
|
|
6041
6321
|
onDragStart,
|
|
@@ -6220,7 +6500,7 @@ function useDrag(options = {}) {
|
|
|
6220
6500
|
},
|
|
6221
6501
|
[screenToWorld, applySnap, onDragEnd]
|
|
6222
6502
|
);
|
|
6223
|
-
|
|
6503
|
+
useEffect11(() => {
|
|
6224
6504
|
if (!isListening) return;
|
|
6225
6505
|
document.addEventListener("mousemove", handleMouseMove);
|
|
6226
6506
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -6289,7 +6569,7 @@ function useDrag(options = {}) {
|
|
|
6289
6569
|
}
|
|
6290
6570
|
|
|
6291
6571
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
6292
|
-
import { useEffect as
|
|
6572
|
+
import { useEffect as useEffect12 } from "react";
|
|
6293
6573
|
function useKeyboardShortcuts(options) {
|
|
6294
6574
|
const {
|
|
6295
6575
|
onDelete,
|
|
@@ -6300,7 +6580,7 @@ function useKeyboardShortcuts(options) {
|
|
|
6300
6580
|
onSelectAll,
|
|
6301
6581
|
enabled = true
|
|
6302
6582
|
} = options;
|
|
6303
|
-
|
|
6583
|
+
useEffect12(() => {
|
|
6304
6584
|
if (!enabled) return;
|
|
6305
6585
|
const handleKeyDown = (event) => {
|
|
6306
6586
|
const target = event.target;
|
|
@@ -6452,7 +6732,7 @@ function PIDCanvasImpl({
|
|
|
6452
6732
|
const isUndoRedoAction = useRef6(false);
|
|
6453
6733
|
const isInternalChange = useRef6(false);
|
|
6454
6734
|
const lastInternalDiagram = useRef6(null);
|
|
6455
|
-
|
|
6735
|
+
useEffect13(() => {
|
|
6456
6736
|
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
6457
6737
|
if (isExternal) {
|
|
6458
6738
|
setLocalDiagram(diagram);
|
|
@@ -6497,7 +6777,7 @@ function PIDCanvasImpl({
|
|
|
6497
6777
|
});
|
|
6498
6778
|
return { minX, minY, maxX, maxY };
|
|
6499
6779
|
}, [localDiagram.nodes]);
|
|
6500
|
-
|
|
6780
|
+
useEffect13(() => {
|
|
6501
6781
|
if (onMounted) {
|
|
6502
6782
|
const controls = {
|
|
6503
6783
|
fitToContent: (padding = 50) => {
|
|
@@ -6576,7 +6856,7 @@ function PIDCanvasImpl({
|
|
|
6576
6856
|
isUndoRedoAction.current = false;
|
|
6577
6857
|
}, 0);
|
|
6578
6858
|
}, [localDiagram, onDiagramChange]);
|
|
6579
|
-
|
|
6859
|
+
useEffect13(() => {
|
|
6580
6860
|
const handleKeyDown = (e) => {
|
|
6581
6861
|
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
6582
6862
|
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
@@ -6593,7 +6873,7 @@ function PIDCanvasImpl({
|
|
|
6593
6873
|
window.addEventListener("keydown", handleKeyDown);
|
|
6594
6874
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
6595
6875
|
}, [undo, redo]);
|
|
6596
|
-
|
|
6876
|
+
useEffect13(() => {
|
|
6597
6877
|
if (!features.dragNodes) return;
|
|
6598
6878
|
const handleKeyDown = (e) => {
|
|
6599
6879
|
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
@@ -7130,6 +7410,7 @@ function PIDCanvasImpl({
|
|
|
7130
7410
|
}
|
|
7131
7411
|
),
|
|
7132
7412
|
telemetryEnabled && telemetry && /* @__PURE__ */ jsx20("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
7413
|
+
if (node.symbolId === "status-indicator") return null;
|
|
7133
7414
|
const binding = telemetry.get(node.id);
|
|
7134
7415
|
if (!binding) return null;
|
|
7135
7416
|
const symbol = getSymbolDefinition(node.symbolId);
|
|
@@ -7497,6 +7778,8 @@ function NodeConfigPanel({
|
|
|
7497
7778
|
onUpdateNode,
|
|
7498
7779
|
onUpdateTelemetry,
|
|
7499
7780
|
onAddTelemetry,
|
|
7781
|
+
onRemoveTelemetry,
|
|
7782
|
+
availableTags = [],
|
|
7500
7783
|
onRemove,
|
|
7501
7784
|
className = "",
|
|
7502
7785
|
style = {}
|
|
@@ -7509,6 +7792,8 @@ function NodeConfigPanel({
|
|
|
7509
7792
|
padding: "20px",
|
|
7510
7793
|
...style
|
|
7511
7794
|
};
|
|
7795
|
+
const appearanceFields = getAppearanceSchema(node.symbolId);
|
|
7796
|
+
const showGenericTelemetry = appearanceFields.length === 0;
|
|
7512
7797
|
return /* @__PURE__ */ jsxs18("div", { className, style: defaultStyle, children: [
|
|
7513
7798
|
/* @__PURE__ */ jsxs18("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
7514
7799
|
"Configure: ",
|
|
@@ -7630,7 +7915,136 @@ function NodeConfigPanel({
|
|
|
7630
7915
|
)
|
|
7631
7916
|
] })
|
|
7632
7917
|
] }),
|
|
7633
|
-
/* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
7918
|
+
appearanceFields.length > 0 && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
7919
|
+
/* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Appearance" }),
|
|
7920
|
+
appearanceFields.map((field) => {
|
|
7921
|
+
const value = readAppearanceValue(node, field);
|
|
7922
|
+
const fieldLabel = field.label ?? field.key;
|
|
7923
|
+
const inputStyle = {
|
|
7924
|
+
width: "100%",
|
|
7925
|
+
padding: "6px 8px",
|
|
7926
|
+
borderRadius: "4px",
|
|
7927
|
+
border: "1px solid #cbd5e1",
|
|
7928
|
+
fontSize: "0.875rem"
|
|
7929
|
+
};
|
|
7930
|
+
let control;
|
|
7931
|
+
if (field.kind === "boolean") {
|
|
7932
|
+
control = /* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block" }, children: [
|
|
7933
|
+
/* @__PURE__ */ jsx22(
|
|
7934
|
+
"input",
|
|
7935
|
+
{
|
|
7936
|
+
type: "checkbox",
|
|
7937
|
+
checked: Boolean(value),
|
|
7938
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.checked)),
|
|
7939
|
+
style: { marginRight: "6px" }
|
|
7940
|
+
}
|
|
7941
|
+
),
|
|
7942
|
+
fieldLabel
|
|
7943
|
+
] });
|
|
7944
|
+
} else if (field.kind === "select") {
|
|
7945
|
+
control = /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
7946
|
+
/* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
7947
|
+
fieldLabel,
|
|
7948
|
+
":"
|
|
7949
|
+
] }),
|
|
7950
|
+
/* @__PURE__ */ jsx22(
|
|
7951
|
+
"select",
|
|
7952
|
+
{
|
|
7953
|
+
value: String(value),
|
|
7954
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
7955
|
+
style: inputStyle,
|
|
7956
|
+
children: field.options?.map((opt) => /* @__PURE__ */ jsx22("option", { value: opt, children: opt }, opt))
|
|
7957
|
+
}
|
|
7958
|
+
)
|
|
7959
|
+
] });
|
|
7960
|
+
} else if (field.kind === "number") {
|
|
7961
|
+
control = /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
7962
|
+
/* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
7963
|
+
fieldLabel,
|
|
7964
|
+
":"
|
|
7965
|
+
] }),
|
|
7966
|
+
/* @__PURE__ */ jsx22(
|
|
7967
|
+
"input",
|
|
7968
|
+
{
|
|
7969
|
+
type: "number",
|
|
7970
|
+
value: Number(value),
|
|
7971
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, parseFloat(e.target.value) || 0)),
|
|
7972
|
+
style: inputStyle
|
|
7973
|
+
}
|
|
7974
|
+
)
|
|
7975
|
+
] });
|
|
7976
|
+
} else if (field.kind === "tag") {
|
|
7977
|
+
const tagValue = String(value);
|
|
7978
|
+
const listId = `tags-${node.id}-${field.key}`;
|
|
7979
|
+
const known = tagValue.length > 0 && availableTags.includes(tagValue);
|
|
7980
|
+
const unknown = tagValue.length > 0 && !known;
|
|
7981
|
+
control = /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
7982
|
+
/* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
7983
|
+
fieldLabel,
|
|
7984
|
+
":"
|
|
7985
|
+
] }),
|
|
7986
|
+
/* @__PURE__ */ jsx22(
|
|
7987
|
+
"input",
|
|
7988
|
+
{
|
|
7989
|
+
type: "text",
|
|
7990
|
+
value: tagValue,
|
|
7991
|
+
list: listId,
|
|
7992
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
7993
|
+
placeholder: "type or pick a signal\u2026",
|
|
7994
|
+
style: {
|
|
7995
|
+
...inputStyle,
|
|
7996
|
+
border: `1px solid ${unknown ? "#f59e0b" : known ? "#22c55e" : "#cbd5e1"}`
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7999
|
+
),
|
|
8000
|
+
/* @__PURE__ */ jsx22("datalist", { id: listId, children: availableTags.map((t) => /* @__PURE__ */ jsx22("option", { value: t }, t)) }),
|
|
8001
|
+
tagValue.length > 0 && /* @__PURE__ */ jsx22(
|
|
8002
|
+
"div",
|
|
8003
|
+
{
|
|
8004
|
+
style: {
|
|
8005
|
+
fontSize: "0.7rem",
|
|
8006
|
+
marginTop: "3px",
|
|
8007
|
+
color: known ? "#16a34a" : "#b45309"
|
|
8008
|
+
},
|
|
8009
|
+
children: known ? "\u2713 matched signal" : "\u26A0 no matching signal (reads as false until published)"
|
|
8010
|
+
}
|
|
8011
|
+
)
|
|
8012
|
+
] });
|
|
8013
|
+
} else {
|
|
8014
|
+
control = /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
8015
|
+
/* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
8016
|
+
fieldLabel,
|
|
8017
|
+
":"
|
|
8018
|
+
] }),
|
|
8019
|
+
/* @__PURE__ */ jsx22(
|
|
8020
|
+
"input",
|
|
8021
|
+
{
|
|
8022
|
+
type: "text",
|
|
8023
|
+
value: String(value),
|
|
8024
|
+
onChange: (e) => onUpdateNode(writeAppearanceValue(node, field, e.target.value)),
|
|
8025
|
+
style: inputStyle
|
|
8026
|
+
}
|
|
8027
|
+
)
|
|
8028
|
+
] });
|
|
8029
|
+
}
|
|
8030
|
+
return /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "10px" }, children: [
|
|
8031
|
+
control,
|
|
8032
|
+
field.help && /* @__PURE__ */ jsx22(
|
|
8033
|
+
"div",
|
|
8034
|
+
{
|
|
8035
|
+
style: {
|
|
8036
|
+
fontSize: "0.7rem",
|
|
8037
|
+
color: "#64748b",
|
|
8038
|
+
marginTop: "3px",
|
|
8039
|
+
lineHeight: 1.35
|
|
8040
|
+
},
|
|
8041
|
+
children: field.help
|
|
8042
|
+
}
|
|
8043
|
+
)
|
|
8044
|
+
] }, field.key);
|
|
8045
|
+
})
|
|
8046
|
+
] }),
|
|
8047
|
+
showGenericTelemetry && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
7634
8048
|
/* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
7635
8049
|
!binding ? /* @__PURE__ */ jsx22(
|
|
7636
8050
|
"button",
|
|
@@ -7676,6 +8090,27 @@ function NodeConfigPanel({
|
|
|
7676
8090
|
children: "+ Add Telemetry"
|
|
7677
8091
|
}
|
|
7678
8092
|
) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
8093
|
+
/* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Tag (attribute):" }),
|
|
8094
|
+
/* @__PURE__ */ jsx22(
|
|
8095
|
+
"input",
|
|
8096
|
+
{
|
|
8097
|
+
type: "text",
|
|
8098
|
+
value: binding.tag || "",
|
|
8099
|
+
onChange: (e) => onUpdateTelemetry({
|
|
8100
|
+
nodeId: node.id,
|
|
8101
|
+
tag: e.target.value
|
|
8102
|
+
}),
|
|
8103
|
+
placeholder: "e.g. pump.running",
|
|
8104
|
+
style: {
|
|
8105
|
+
width: "100%",
|
|
8106
|
+
padding: "6px 8px",
|
|
8107
|
+
borderRadius: "4px",
|
|
8108
|
+
border: "1px solid #cbd5e1",
|
|
8109
|
+
fontSize: "0.875rem",
|
|
8110
|
+
marginBottom: "8px"
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
),
|
|
7679
8114
|
/* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
7680
8115
|
/* @__PURE__ */ jsx22(
|
|
7681
8116
|
"input",
|
|
@@ -7983,10 +8418,28 @@ function NodeConfigPanel({
|
|
|
7983
8418
|
] })
|
|
7984
8419
|
] }),
|
|
7985
8420
|
" "
|
|
7986
|
-
] })
|
|
8421
|
+
] }),
|
|
8422
|
+
onRemoveTelemetry && /* @__PURE__ */ jsx22(
|
|
8423
|
+
"button",
|
|
8424
|
+
{
|
|
8425
|
+
onClick: onRemoveTelemetry,
|
|
8426
|
+
style: {
|
|
8427
|
+
width: "100%",
|
|
8428
|
+
padding: "6px 8px",
|
|
8429
|
+
marginTop: "8px",
|
|
8430
|
+
borderRadius: "4px",
|
|
8431
|
+
border: "1px solid #ef4444",
|
|
8432
|
+
background: "transparent",
|
|
8433
|
+
color: "#ef4444",
|
|
8434
|
+
fontSize: "0.8125rem",
|
|
8435
|
+
cursor: "pointer"
|
|
8436
|
+
},
|
|
8437
|
+
children: "Remove Telemetry"
|
|
8438
|
+
}
|
|
8439
|
+
)
|
|
7987
8440
|
] })
|
|
7988
8441
|
] }),
|
|
7989
|
-
binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
8442
|
+
showGenericTelemetry && binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
7990
8443
|
/* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
7991
8444
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
7992
8445
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
@@ -8016,7 +8469,7 @@ function NodeConfigPanel({
|
|
|
8016
8469
|
] }, key);
|
|
8017
8470
|
})
|
|
8018
8471
|
] }),
|
|
8019
|
-
binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
8472
|
+
showGenericTelemetry && binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
|
|
8020
8473
|
/* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
8021
8474
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
8022
8475
|
const defaultColors = {
|
|
@@ -8875,7 +9328,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8875
9328
|
}
|
|
8876
9329
|
|
|
8877
9330
|
// src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
|
|
8878
|
-
import React15, { useState as useState18, useEffect as
|
|
9331
|
+
import React15, { useState as useState18, useEffect as useEffect14, useMemo, useRef as useRef8 } from "react";
|
|
8879
9332
|
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8880
9333
|
function DeviceConfigPanelImpl({
|
|
8881
9334
|
binding,
|
|
@@ -8934,7 +9387,7 @@ function DeviceConfigPanelImpl({
|
|
|
8934
9387
|
setCollapsedSections(collapsed);
|
|
8935
9388
|
setBindingId(binding.nodeId);
|
|
8936
9389
|
}
|
|
8937
|
-
|
|
9390
|
+
useEffect14(() => {
|
|
8938
9391
|
const currentTimestamp = binding?.state.lastSaved || 0;
|
|
8939
9392
|
if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
|
|
8940
9393
|
lastResultTimestampRef.current = currentTimestamp;
|
|
@@ -9625,7 +10078,7 @@ function DeviceConfigPanelImpl({
|
|
|
9625
10078
|
var DeviceConfigPanel = React15.memo(DeviceConfigPanelImpl);
|
|
9626
10079
|
|
|
9627
10080
|
// src/diagram/hooks/useSimulation.ts
|
|
9628
|
-
import { useEffect as
|
|
10081
|
+
import { useEffect as useEffect15 } from "react";
|
|
9629
10082
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
9630
10083
|
const {
|
|
9631
10084
|
interval = 2e3,
|
|
@@ -9636,7 +10089,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9636
10089
|
historyLength = 10,
|
|
9637
10090
|
generateValue
|
|
9638
10091
|
} = options;
|
|
9639
|
-
|
|
10092
|
+
useEffect15(() => {
|
|
9640
10093
|
if (!enabled) return;
|
|
9641
10094
|
const intervalId = setInterval(() => {
|
|
9642
10095
|
const updates = [];
|
|
@@ -9686,6 +10139,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
9686
10139
|
}
|
|
9687
10140
|
export {
|
|
9688
10141
|
Button,
|
|
10142
|
+
COLOR_PRESETS,
|
|
9689
10143
|
CardHeader,
|
|
9690
10144
|
CardUnit,
|
|
9691
10145
|
CardValue,
|
|
@@ -9715,6 +10169,7 @@ export {
|
|
|
9715
10169
|
PanelTabs,
|
|
9716
10170
|
RightPanel,
|
|
9717
10171
|
RightToggleButton,
|
|
10172
|
+
STATUS_LED_APPEARANCE,
|
|
9718
10173
|
SVGArea,
|
|
9719
10174
|
SVGLockedOverlay,
|
|
9720
10175
|
ScrollableSVGWrapper,
|
|
@@ -9725,6 +10180,8 @@ export {
|
|
|
9725
10180
|
ThemeProvider,
|
|
9726
10181
|
ThemeToggle,
|
|
9727
10182
|
TrendLine,
|
|
10183
|
+
UNKNOWN_MARK_COLOR,
|
|
10184
|
+
UNKNOWN_MARK_COLOR_DARK,
|
|
9728
10185
|
ValueEntry,
|
|
9729
10186
|
ZoomButton,
|
|
9730
10187
|
ZoomControls,
|
|
@@ -9734,6 +10191,8 @@ export {
|
|
|
9734
10191
|
exampleDiagram,
|
|
9735
10192
|
exportDiagram,
|
|
9736
10193
|
generateRoutePoints,
|
|
10194
|
+
getAppearanceDefaults,
|
|
10195
|
+
getAppearanceSchema,
|
|
9737
10196
|
getAvailableSymbols,
|
|
9738
10197
|
getPortWorldPosition,
|
|
9739
10198
|
getSymbolDefinition,
|
|
@@ -9741,9 +10200,12 @@ export {
|
|
|
9741
10200
|
mockSymbolLibrary,
|
|
9742
10201
|
nodeHasPort,
|
|
9743
10202
|
overlayStyles,
|
|
10203
|
+
readAppearanceValue,
|
|
9744
10204
|
registerSymbol,
|
|
9745
10205
|
registerSymbols,
|
|
10206
|
+
resolvePresetColor,
|
|
9746
10207
|
resolveStatusColor,
|
|
10208
|
+
useBooleanIndicators,
|
|
9747
10209
|
useDeviceConfigs,
|
|
9748
10210
|
useDeviceControls,
|
|
9749
10211
|
useDrag,
|
|
@@ -9754,6 +10216,7 @@ export {
|
|
|
9754
10216
|
useTelemetryStatus,
|
|
9755
10217
|
useTheme,
|
|
9756
10218
|
useViewBox,
|
|
9757
|
-
validateDiagram
|
|
10219
|
+
validateDiagram,
|
|
10220
|
+
writeAppearanceValue
|
|
9758
10221
|
};
|
|
9759
10222
|
//# sourceMappingURL=index.js.map
|