@procaaso/alphinity-ui-components 1.3.0 → 1.5.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/dist/index.js CHANGED
@@ -935,6 +935,7 @@ function DeviceControlPanel({
935
935
  toastDuration = 3e3,
936
936
  onModeChange,
937
937
  onParameterChange,
938
+ onParameterActivate,
938
939
  onStart,
939
940
  onStop,
940
941
  startPending = false,
@@ -1647,6 +1648,36 @@ function DeviceControlPanel({
1647
1648
  },
1648
1649
  children: param.options?.map((opt) => /* @__PURE__ */ jsx8("option", { value: opt.value, children: opt.label }, opt.value))
1649
1650
  }
1651
+ ) : onParameterActivate && !param.readOnly ? (
1652
+ // Tappable value: defer editing to the consumer's editor (e.g. a
1653
+ // numpad dialog). Commit happens via onParameterChange.
1654
+ /* @__PURE__ */ jsxs7(
1655
+ "button",
1656
+ {
1657
+ type: "button",
1658
+ onClick: () => onParameterActivate(param.id, localParameterValues[param.id] ?? param.value),
1659
+ style: {
1660
+ width: "100%",
1661
+ height: touchSize,
1662
+ display: "flex",
1663
+ alignItems: "center",
1664
+ backgroundColor: "#ffffff",
1665
+ color: textColor,
1666
+ border: `1px solid ${borderColor}`,
1667
+ borderRadius: "6px",
1668
+ padding: "0 12px",
1669
+ fontSize: `${fontSize.input}px`,
1670
+ fontFamily: "Arial, sans-serif",
1671
+ fontWeight: 600,
1672
+ textAlign: "left",
1673
+ cursor: "pointer"
1674
+ },
1675
+ children: [
1676
+ localParameterValues[param.id] ?? param.value,
1677
+ param.unit ? ` ${param.unit}` : ""
1678
+ ]
1679
+ }
1680
+ )
1650
1681
  ) : /* @__PURE__ */ jsx8(
1651
1682
  "input",
1652
1683
  {
@@ -1809,14 +1840,457 @@ function DeviceControlPanel({
1809
1840
  ] });
1810
1841
  }
1811
1842
 
1843
+ // src/components/NumpadDialog/NumpadDialog.tsx
1844
+ import { useState as useState6, useEffect as useEffect3, useCallback as useCallback3, useRef as useRef2, useId } from "react";
1845
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1846
+ var NumpadDialog = ({
1847
+ isOpen,
1848
+ onClose,
1849
+ onApply,
1850
+ deviceName = "",
1851
+ parameterLabel = "Setpoint",
1852
+ unit = "",
1853
+ min = 0,
1854
+ max = 100,
1855
+ precision,
1856
+ currentValue = 0,
1857
+ touchOptimized = true
1858
+ }) => {
1859
+ const [inputValue, setInputValue] = useState6("");
1860
+ const [pristine, setPristine] = useState6(true);
1861
+ const dialogRef = useRef2(null);
1862
+ const titleId = useId();
1863
+ const decimals = precision ?? 1;
1864
+ useEffect3(() => {
1865
+ if (isOpen) {
1866
+ setInputValue(Number(currentValue).toFixed(decimals));
1867
+ setPristine(true);
1868
+ }
1869
+ }, [isOpen, currentValue, decimals]);
1870
+ useEffect3(() => {
1871
+ if (!isOpen) return;
1872
+ const previouslyFocused = document.activeElement;
1873
+ dialogRef.current?.focus();
1874
+ return () => previouslyFocused?.focus?.();
1875
+ }, [isOpen]);
1876
+ useEffect3(() => {
1877
+ if (!isOpen) return;
1878
+ const prevOverflow = document.body.style.overflow;
1879
+ document.body.style.overflow = "hidden";
1880
+ return () => {
1881
+ document.body.style.overflow = prevOverflow;
1882
+ };
1883
+ }, [isOpen]);
1884
+ const handleApply = useCallback3(() => {
1885
+ const n = Number(inputValue);
1886
+ if (inputValue === "" || inputValue === "-" || inputValue === "." || inputValue === "-.") return;
1887
+ if (isNaN(n) || n < min || n > max) return;
1888
+ onApply(Number(n.toFixed(decimals)));
1889
+ }, [inputValue, min, max, onApply, decimals]);
1890
+ const appendDigit = useCallback3(
1891
+ (digit) => {
1892
+ setInputValue((prev) => {
1893
+ const base = pristine ? "" : prev;
1894
+ if (digit === ".") {
1895
+ if (decimals === 0) return base;
1896
+ if (base.includes(".")) return base;
1897
+ if (base === "" || base === "-") return base + "0.";
1898
+ return base + ".";
1899
+ }
1900
+ const dot = base.indexOf(".");
1901
+ if (dot !== -1 && base.length - dot - 1 >= decimals) return base;
1902
+ if (base === "0") return digit;
1903
+ if (base === "-0") return "-" + digit;
1904
+ return base + digit;
1905
+ });
1906
+ if (pristine) setPristine(false);
1907
+ },
1908
+ [pristine, decimals]
1909
+ );
1910
+ const handleBackspace = useCallback3(() => {
1911
+ setPristine(false);
1912
+ setInputValue((prev) => prev.slice(0, -1));
1913
+ }, []);
1914
+ const handleClear = useCallback3(() => {
1915
+ setPristine(false);
1916
+ setInputValue("");
1917
+ }, []);
1918
+ const handleToggleSign = useCallback3(() => {
1919
+ if (min >= 0) return;
1920
+ setPristine(false);
1921
+ setInputValue((prev) => {
1922
+ if (prev.startsWith("-")) return prev.slice(1);
1923
+ if (prev === "" || prev === "0") return "-";
1924
+ return "-" + prev;
1925
+ });
1926
+ }, [min]);
1927
+ const bsTimer = useRef2(null);
1928
+ const bsLongFired = useRef2(false);
1929
+ const clearBsTimer = () => {
1930
+ if (bsTimer.current !== null) {
1931
+ clearTimeout(bsTimer.current);
1932
+ bsTimer.current = null;
1933
+ }
1934
+ };
1935
+ const handleBackspacePointerDown = () => {
1936
+ bsLongFired.current = false;
1937
+ bsTimer.current = window.setTimeout(() => {
1938
+ bsLongFired.current = true;
1939
+ handleClear();
1940
+ }, 500);
1941
+ };
1942
+ const handleBackspaceClick = () => {
1943
+ clearBsTimer();
1944
+ if (bsLongFired.current) {
1945
+ bsLongFired.current = false;
1946
+ return;
1947
+ }
1948
+ handleBackspace();
1949
+ };
1950
+ useEffect3(() => () => clearBsTimer(), []);
1951
+ useEffect3(() => {
1952
+ if (!isOpen) return;
1953
+ const handler = (e) => {
1954
+ if (e.key === "Tab") {
1955
+ const root = dialogRef.current;
1956
+ if (!root) return;
1957
+ const focusable = Array.from(
1958
+ root.querySelectorAll("button:not([disabled])")
1959
+ ).filter((el) => el.tabIndex !== -1);
1960
+ if (focusable.length === 0) {
1961
+ e.preventDefault();
1962
+ root.focus();
1963
+ return;
1964
+ }
1965
+ const first = focusable[0];
1966
+ const last = focusable[focusable.length - 1];
1967
+ const active = document.activeElement;
1968
+ if (e.shiftKey) {
1969
+ if (active === first || !root.contains(active)) {
1970
+ e.preventDefault();
1971
+ last.focus();
1972
+ }
1973
+ } else if (active === last || !root.contains(active)) {
1974
+ e.preventDefault();
1975
+ first.focus();
1976
+ }
1977
+ return;
1978
+ }
1979
+ if (e.key === "Enter") {
1980
+ const active = document.activeElement;
1981
+ if (active && active.tagName === "BUTTON" && dialogRef.current?.contains(active)) return;
1982
+ e.preventDefault();
1983
+ handleApply();
1984
+ } else if (e.key === "Escape") {
1985
+ e.preventDefault();
1986
+ onClose();
1987
+ } else if (e.key === "Backspace") {
1988
+ e.preventDefault();
1989
+ handleBackspace();
1990
+ } else if (/^[0-9]$/.test(e.key)) {
1991
+ e.preventDefault();
1992
+ appendDigit(e.key);
1993
+ } else if (e.key === ".") {
1994
+ e.preventDefault();
1995
+ appendDigit(".");
1996
+ } else if (e.key === "-") {
1997
+ e.preventDefault();
1998
+ handleToggleSign();
1999
+ }
2000
+ };
2001
+ window.addEventListener("keydown", handler);
2002
+ return () => window.removeEventListener("keydown", handler);
2003
+ }, [isOpen, handleApply, onClose, handleBackspace, appendDigit, handleToggleSign]);
2004
+ if (!isOpen) return null;
2005
+ const parsed = Number(inputValue);
2006
+ const hasNumber = inputValue !== "" && inputValue !== "-" && inputValue !== "." && inputValue !== "-." && !isNaN(parsed);
2007
+ const belowMin = hasNumber && parsed < min;
2008
+ const aboveMax = hasNumber && parsed > max;
2009
+ const outOfRange = belowMin || aboveMax;
2010
+ const isValid = hasNumber && !outOfRange;
2011
+ const alarmColor = "#dc2626";
2012
+ const limitStyle = (violated) => violated ? { color: alarmColor, fontWeight: 700, background: "#fee2e2", borderRadius: 3, padding: "0 3px" } : {};
2013
+ const keySize = touchOptimized ? 60 : 46;
2014
+ const keyFont = touchOptimized ? 22 : 18;
2015
+ const actionSize = touchOptimized ? 52 : 42;
2016
+ const keyStyle = {
2017
+ minWidth: 52,
2018
+ minHeight: keySize,
2019
+ fontSize: keyFont,
2020
+ fontWeight: 600,
2021
+ borderRadius: 8,
2022
+ border: "1px solid #e2e8f0",
2023
+ background: "#ffffff",
2024
+ color: "#0f172a",
2025
+ cursor: "pointer",
2026
+ display: "flex",
2027
+ alignItems: "center",
2028
+ justifyContent: "center",
2029
+ userSelect: "none",
2030
+ boxShadow: "0 1px 2px rgba(15, 23, 42, 0.06)"
2031
+ };
2032
+ const utilKeyStyle = {
2033
+ flex: 1,
2034
+ minHeight: touchOptimized ? 44 : 38,
2035
+ fontSize: 13,
2036
+ fontWeight: 600,
2037
+ borderRadius: 8,
2038
+ border: "1px solid #e2e8f0",
2039
+ background: "#f8fafc",
2040
+ color: "#64748b",
2041
+ cursor: "pointer",
2042
+ display: "flex",
2043
+ alignItems: "center",
2044
+ justifyContent: "center",
2045
+ userSelect: "none"
2046
+ };
2047
+ const reason = belowMin ? `Below minimum of ${min} ${unit}` : aboveMax ? `Above maximum of ${max} ${unit}` : "Type or tap to change the value";
2048
+ const backspaceInGrid = min >= 0;
2049
+ const BackspaceButton = ({ style, label }) => /* @__PURE__ */ jsx9(
2050
+ "button",
2051
+ {
2052
+ type: "button",
2053
+ className: "np-key",
2054
+ tabIndex: -1,
2055
+ "aria-label": "Backspace",
2056
+ style,
2057
+ onPointerDown: handleBackspacePointerDown,
2058
+ onPointerUp: clearBsTimer,
2059
+ onPointerLeave: clearBsTimer,
2060
+ onClick: handleBackspaceClick,
2061
+ children: label
2062
+ }
2063
+ );
2064
+ return (
2065
+ // Backdrop
2066
+ /* @__PURE__ */ jsxs8(
2067
+ "div",
2068
+ {
2069
+ style: {
2070
+ position: "fixed",
2071
+ top: 0,
2072
+ left: 0,
2073
+ right: 0,
2074
+ bottom: 0,
2075
+ backgroundColor: "rgba(15, 23, 42, 0.4)",
2076
+ zIndex: 1e4,
2077
+ display: "flex",
2078
+ alignItems: "center",
2079
+ justifyContent: "center"
2080
+ },
2081
+ onClick: onClose,
2082
+ children: [
2083
+ /* @__PURE__ */ jsx9("style", { children: `
2084
+ .np-key { transition: background .1s, transform .05s; touch-action: manipulation; }
2085
+ .np-key:active:not(:disabled) { background:#e2e8f0; transform: translateY(1px); }
2086
+ .np-key:focus-visible, .np-action:focus-visible { outline: 3px solid #2563eb; outline-offset: 2px; }
2087
+ @keyframes np-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
2088
+ .np-caret { display:inline-block; width:2px; height:1.1em; background:#2563eb; animation: np-blink 1s step-end infinite; }
2089
+ ` }),
2090
+ /* @__PURE__ */ jsxs8(
2091
+ "div",
2092
+ {
2093
+ ref: dialogRef,
2094
+ role: "dialog",
2095
+ "aria-modal": "true",
2096
+ "aria-labelledby": titleId,
2097
+ tabIndex: -1,
2098
+ style: {
2099
+ width: touchOptimized ? "340px" : "300px",
2100
+ maxHeight: "90vh",
2101
+ overflow: "auto",
2102
+ background: "#ffffff",
2103
+ borderRadius: 12,
2104
+ border: "1px solid #e2e8f0",
2105
+ boxShadow: "0 10px 40px rgba(15, 23, 42, 0.2)",
2106
+ fontFamily: "'Inter', system-ui, sans-serif",
2107
+ outline: "none"
2108
+ },
2109
+ onClick: (e) => e.stopPropagation(),
2110
+ children: [
2111
+ /* @__PURE__ */ jsx9("div", { style: { padding: "14px 16px 0 16px" }, children: /* @__PURE__ */ jsx9("h3", { id: titleId, style: { margin: 0, fontSize: 15, fontWeight: 700, color: "#0f172a" }, children: deviceName ? `${deviceName} - ${parameterLabel}` : parameterLabel }) }),
2112
+ /* @__PURE__ */ jsxs8("div", { style: { padding: 16, display: "flex", flexDirection: "column", gap: 10 }, children: [
2113
+ /* @__PURE__ */ jsxs8(
2114
+ "div",
2115
+ {
2116
+ style: {
2117
+ display: "flex",
2118
+ justifyContent: "space-between",
2119
+ fontSize: 12,
2120
+ color: "#64748b"
2121
+ },
2122
+ children: [
2123
+ /* @__PURE__ */ jsxs8("span", { children: [
2124
+ "Current: ",
2125
+ currentValue,
2126
+ " ",
2127
+ unit
2128
+ ] }),
2129
+ /* @__PURE__ */ jsxs8("span", { children: [
2130
+ "Range: ",
2131
+ /* @__PURE__ */ jsx9("span", { style: limitStyle(belowMin), children: min }),
2132
+ "-",
2133
+ /* @__PURE__ */ jsx9("span", { style: limitStyle(aboveMax), children: max }),
2134
+ " ",
2135
+ unit
2136
+ ] })
2137
+ ]
2138
+ }
2139
+ ),
2140
+ /* @__PURE__ */ jsxs8(
2141
+ "div",
2142
+ {
2143
+ "aria-live": "polite",
2144
+ "aria-atomic": "true",
2145
+ "aria-label": `Entered value ${inputValue || "0"} ${unit}`,
2146
+ style: {
2147
+ background: outOfRange ? "#fef2f2" : "#f8fafc",
2148
+ borderRadius: 8,
2149
+ padding: "10px 14px",
2150
+ fontSize: 28,
2151
+ fontWeight: 700,
2152
+ textAlign: "right",
2153
+ color: outOfRange ? alarmColor : "#0f172a",
2154
+ minHeight: 48,
2155
+ display: "flex",
2156
+ alignItems: "center",
2157
+ justifyContent: "flex-end",
2158
+ gap: 6,
2159
+ border: outOfRange ? "1.5px solid #fca5a5" : "1.5px solid #e2e8f0"
2160
+ },
2161
+ children: [
2162
+ /* @__PURE__ */ jsx9("span", { children: inputValue || "0" }),
2163
+ /* @__PURE__ */ jsx9("span", { className: "np-caret", "aria-hidden": "true" }),
2164
+ /* @__PURE__ */ jsx9("span", { style: { fontSize: 14, color: "#94a3b8", fontWeight: 500 }, children: unit })
2165
+ ]
2166
+ }
2167
+ ),
2168
+ /* @__PURE__ */ jsx9(
2169
+ "div",
2170
+ {
2171
+ role: "status",
2172
+ "aria-live": "polite",
2173
+ style: {
2174
+ fontSize: 12,
2175
+ color: outOfRange ? alarmColor : "#94a3b8",
2176
+ fontWeight: outOfRange ? 600 : 400,
2177
+ textAlign: "right",
2178
+ minHeight: 16
2179
+ },
2180
+ children: reason
2181
+ }
2182
+ ),
2183
+ /* @__PURE__ */ jsxs8("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 5 }, children: [
2184
+ ["7", "8", "9", "4", "5", "6", "1", "2", "3"].map((digit) => /* @__PURE__ */ jsx9(
2185
+ "button",
2186
+ {
2187
+ type: "button",
2188
+ className: "np-key",
2189
+ tabIndex: -1,
2190
+ style: keyStyle,
2191
+ onClick: () => appendDigit(digit),
2192
+ children: digit
2193
+ },
2194
+ digit
2195
+ )),
2196
+ min < 0 ? /* @__PURE__ */ jsx9(
2197
+ "button",
2198
+ {
2199
+ type: "button",
2200
+ className: "np-key",
2201
+ tabIndex: -1,
2202
+ "aria-label": "Toggle sign",
2203
+ style: { ...keyStyle, fontSize: 16, background: "#f8fafc", color: "#64748b" },
2204
+ onClick: handleToggleSign,
2205
+ children: "+/\u2212"
2206
+ }
2207
+ ) : /* @__PURE__ */ jsx9(BackspaceButton, { style: { ...keyStyle, fontSize: 20, background: "#f8fafc", color: "#64748b" }, label: "\u232B" }),
2208
+ /* @__PURE__ */ jsx9("button", { type: "button", className: "np-key", tabIndex: -1, style: keyStyle, onClick: () => appendDigit("0"), children: "0" }),
2209
+ /* @__PURE__ */ jsx9(
2210
+ "button",
2211
+ {
2212
+ type: "button",
2213
+ className: "np-key",
2214
+ tabIndex: -1,
2215
+ "aria-label": "Decimal point",
2216
+ style: {
2217
+ ...keyStyle,
2218
+ cursor: decimals === 0 ? "not-allowed" : "pointer",
2219
+ opacity: decimals === 0 ? 0.4 : 1
2220
+ },
2221
+ disabled: decimals === 0,
2222
+ onClick: () => appendDigit("."),
2223
+ children: "."
2224
+ }
2225
+ )
2226
+ ] }),
2227
+ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: 5 }, children: [
2228
+ /* @__PURE__ */ jsx9("button", { type: "button", className: "np-key", tabIndex: -1, style: utilKeyStyle, onClick: handleClear, children: "Clear" }),
2229
+ !backspaceInGrid && /* @__PURE__ */ jsx9(BackspaceButton, { style: utilKeyStyle, label: "Backspace" })
2230
+ ] }),
2231
+ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: 8, marginTop: 2 }, children: [
2232
+ /* @__PURE__ */ jsx9(
2233
+ "button",
2234
+ {
2235
+ type: "button",
2236
+ className: "np-action",
2237
+ onClick: onClose,
2238
+ style: {
2239
+ flex: 1,
2240
+ minHeight: actionSize,
2241
+ borderRadius: 8,
2242
+ border: "1px solid #e2e8f0",
2243
+ background: "#ffffff",
2244
+ color: "#0f172a",
2245
+ fontSize: 14,
2246
+ fontWeight: 600,
2247
+ cursor: "pointer"
2248
+ },
2249
+ children: "Cancel"
2250
+ }
2251
+ ),
2252
+ /* @__PURE__ */ jsx9(
2253
+ "button",
2254
+ {
2255
+ type: "button",
2256
+ className: "np-action",
2257
+ onClick: handleApply,
2258
+ disabled: !isValid,
2259
+ "aria-label": isValid ? `Apply ${inputValue} ${unit}` : "Apply (enter a valid value)",
2260
+ style: {
2261
+ flex: 1,
2262
+ minHeight: actionSize,
2263
+ borderRadius: 8,
2264
+ border: "none",
2265
+ background: "#2563eb",
2266
+ color: "#ffffff",
2267
+ fontSize: 14,
2268
+ fontWeight: 600,
2269
+ cursor: isValid ? "pointer" : "not-allowed",
2270
+ opacity: isValid ? 1 : 0.4
2271
+ },
2272
+ children: "Apply"
2273
+ }
2274
+ )
2275
+ ] })
2276
+ ] })
2277
+ ]
2278
+ }
2279
+ )
2280
+ ]
2281
+ }
2282
+ )
2283
+ );
2284
+ };
2285
+
1812
2286
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
1813
- import React6 from "react";
2287
+ import React7 from "react";
1814
2288
  import { Tab } from "@mui/material";
1815
2289
 
1816
2290
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
1817
2291
  import { Box, IconButton, Tabs } from "@mui/material";
1818
2292
  import styled from "@emotion/styled";
1819
- import { jsx as jsx9 } from "react/jsx-runtime";
2293
+ import { jsx as jsx10 } from "react/jsx-runtime";
1820
2294
  var FullscreenContainer = styled(Box)(
1821
2295
  ({ leftCollapsed, rightCollapsed }) => {
1822
2296
  const getGridTemplateAreas = () => {
@@ -1941,7 +2415,7 @@ var DisplayModeToggle = styled(IconButton)(({ mode }) => ({
1941
2415
  transform: "translateX(-50%) scale(1.05)"
1942
2416
  }
1943
2417
  }));
1944
- var ChevronLeft = () => /* @__PURE__ */ jsx9(
2418
+ var ChevronLeft = () => /* @__PURE__ */ jsx10(
1945
2419
  "div",
1946
2420
  {
1947
2421
  style: {
@@ -1953,7 +2427,7 @@ var ChevronLeft = () => /* @__PURE__ */ jsx9(
1953
2427
  }
1954
2428
  }
1955
2429
  );
1956
- var ChevronRight = () => /* @__PURE__ */ jsx9(
2430
+ var ChevronRight = () => /* @__PURE__ */ jsx10(
1957
2431
  "div",
1958
2432
  {
1959
2433
  style: {
@@ -2064,10 +2538,10 @@ var ScrollableSVGWrapper = styled("div")({
2064
2538
  });
2065
2539
 
2066
2540
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
2067
- import { useEffect as useEffect3, useState as useState6 } from "react";
2541
+ import { useEffect as useEffect4, useState as useState7 } from "react";
2068
2542
  import { Box as Box2 } from "@mui/material";
2069
2543
  import styled2 from "@emotion/styled";
2070
- import { jsx as jsx10 } from "react/jsx-runtime";
2544
+ import { jsx as jsx11 } from "react/jsx-runtime";
2071
2545
  var baseOverlayStyles = {
2072
2546
  tank: {
2073
2547
  background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
@@ -2129,8 +2603,8 @@ var SVGLockedOverlay = ({
2129
2603
  onClick,
2130
2604
  containerSelector = ".tff-svg-container"
2131
2605
  }) => {
2132
- const [svgOffset, setSvgOffset] = useState6({ x: 0, y: 0 });
2133
- useEffect3(() => {
2606
+ const [svgOffset, setSvgOffset] = useState7({ x: 0, y: 0 });
2607
+ useEffect4(() => {
2134
2608
  const updateSvgOffset = () => {
2135
2609
  const containerElement = document.querySelector(containerSelector);
2136
2610
  const svgElement = containerElement?.querySelector("svg");
@@ -2150,7 +2624,7 @@ var SVGLockedOverlay = ({
2150
2624
  const pixelX = svgX + svgOffset.x;
2151
2625
  const pixelY = svgY + svgOffset.y;
2152
2626
  const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
2153
- return /* @__PURE__ */ jsx10(
2627
+ return /* @__PURE__ */ jsx11(
2154
2628
  Box2,
2155
2629
  {
2156
2630
  className: `svg-locked-overlay ${className}`.trim(),
@@ -2214,7 +2688,7 @@ var CardUnit = styled2("div")({
2214
2688
  });
2215
2689
 
2216
2690
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
2217
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2691
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2218
2692
  var TrendLine = ({
2219
2693
  values,
2220
2694
  width = 60,
@@ -2224,7 +2698,7 @@ var TrendLine = ({
2224
2698
  backgroundColor = "rgba(255, 255, 255, 0.1)"
2225
2699
  }) => {
2226
2700
  if (!values || values.length < 2) {
2227
- return /* @__PURE__ */ jsx11(
2701
+ return /* @__PURE__ */ jsx12(
2228
2702
  "div",
2229
2703
  {
2230
2704
  style: {
@@ -2236,7 +2710,7 @@ var TrendLine = ({
2236
2710
  alignItems: "center",
2237
2711
  justifyContent: "center"
2238
2712
  },
2239
- children: /* @__PURE__ */ jsx11("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
2713
+ children: /* @__PURE__ */ jsx12("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
2240
2714
  }
2241
2715
  );
2242
2716
  }
@@ -2248,7 +2722,7 @@ var TrendLine = ({
2248
2722
  const x = 4 + i / (values.length - 1) * (width - 8);
2249
2723
  return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
2250
2724
  }).join(" ");
2251
- return /* @__PURE__ */ jsx11(
2725
+ return /* @__PURE__ */ jsx12(
2252
2726
  "div",
2253
2727
  {
2254
2728
  style: {
@@ -2259,8 +2733,8 @@ var TrendLine = ({
2259
2733
  position: "relative",
2260
2734
  overflow: "hidden"
2261
2735
  },
2262
- children: /* @__PURE__ */ jsxs8("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2263
- /* @__PURE__ */ jsx11(
2736
+ children: /* @__PURE__ */ jsxs9("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2737
+ /* @__PURE__ */ jsx12(
2264
2738
  "path",
2265
2739
  {
2266
2740
  d: pathData,
@@ -2271,7 +2745,7 @@ var TrendLine = ({
2271
2745
  strokeLinejoin: "round"
2272
2746
  }
2273
2747
  ),
2274
- /* @__PURE__ */ jsx11(
2748
+ /* @__PURE__ */ jsx12(
2275
2749
  "circle",
2276
2750
  {
2277
2751
  cx: 4 + (width - 8),
@@ -2309,7 +2783,7 @@ var CircularGauge = ({
2309
2783
  const borderColor = isHex ? hexToRgba(color, 0.9) : color;
2310
2784
  const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
2311
2785
  const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
2312
- return /* @__PURE__ */ jsxs8(
2786
+ return /* @__PURE__ */ jsxs9(
2313
2787
  "div",
2314
2788
  {
2315
2789
  style: {
@@ -2318,7 +2792,7 @@ var CircularGauge = ({
2318
2792
  alignItems: "center"
2319
2793
  },
2320
2794
  children: [
2321
- /* @__PURE__ */ jsxs8(
2795
+ /* @__PURE__ */ jsxs9(
2322
2796
  "div",
2323
2797
  {
2324
2798
  style: {
@@ -2330,8 +2804,8 @@ var CircularGauge = ({
2330
2804
  border: `1px solid ${borderStrokeColor}`
2331
2805
  },
2332
2806
  children: [
2333
- /* @__PURE__ */ jsxs8("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2334
- /* @__PURE__ */ jsx11(
2807
+ /* @__PURE__ */ jsxs9("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2808
+ /* @__PURE__ */ jsx12(
2335
2809
  "circle",
2336
2810
  {
2337
2811
  cx: size / 2,
@@ -2342,7 +2816,7 @@ var CircularGauge = ({
2342
2816
  strokeWidth: 1
2343
2817
  }
2344
2818
  ),
2345
- /* @__PURE__ */ jsx11(
2819
+ /* @__PURE__ */ jsx12(
2346
2820
  "circle",
2347
2821
  {
2348
2822
  cx: size / 2,
@@ -2353,7 +2827,7 @@ var CircularGauge = ({
2353
2827
  fill: "transparent"
2354
2828
  }
2355
2829
  ),
2356
- /* @__PURE__ */ jsx11(
2830
+ /* @__PURE__ */ jsx12(
2357
2831
  "circle",
2358
2832
  {
2359
2833
  cx: size / 2,
@@ -2369,7 +2843,7 @@ var CircularGauge = ({
2369
2843
  }
2370
2844
  )
2371
2845
  ] }),
2372
- /* @__PURE__ */ jsxs8(
2846
+ /* @__PURE__ */ jsxs9(
2373
2847
  "div",
2374
2848
  {
2375
2849
  style: {
@@ -2385,14 +2859,14 @@ var CircularGauge = ({
2385
2859
  },
2386
2860
  children: [
2387
2861
  value.toFixed(1),
2388
- /* @__PURE__ */ jsx11("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
2862
+ /* @__PURE__ */ jsx12("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
2389
2863
  ]
2390
2864
  }
2391
2865
  )
2392
2866
  ]
2393
2867
  }
2394
2868
  ),
2395
- /* @__PURE__ */ jsx11(
2869
+ /* @__PURE__ */ jsx12(
2396
2870
  "div",
2397
2871
  {
2398
2872
  style: {
@@ -2423,7 +2897,7 @@ var Sparkline = ({ data, width, height, color }) => {
2423
2897
  const y = height - 8 - (value - min) / range * (height - 8);
2424
2898
  return `${x + 4},${y + 4}`;
2425
2899
  }).join(" ");
2426
- return /* @__PURE__ */ jsx11(
2900
+ return /* @__PURE__ */ jsx12(
2427
2901
  "div",
2428
2902
  {
2429
2903
  style: {
@@ -2437,7 +2911,7 @@ var Sparkline = ({ data, width, height, color }) => {
2437
2911
  justifyContent: "center",
2438
2912
  boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
2439
2913
  },
2440
- children: /* @__PURE__ */ jsx11("svg", { width, height, children: /* @__PURE__ */ jsx11("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
2914
+ children: /* @__PURE__ */ jsx12("svg", { width, height, children: /* @__PURE__ */ jsx12("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
2441
2915
  }
2442
2916
  );
2443
2917
  };
@@ -2451,8 +2925,8 @@ var EquipmentIndicatorWithSparkline = ({
2451
2925
  sparklineOffset = { x: 40, y: 0 }
2452
2926
  }) => {
2453
2927
  const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
2454
- return /* @__PURE__ */ jsxs8(Fragment3, { children: [
2455
- /* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ jsx11(
2928
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
2929
+ /* @__PURE__ */ jsx12(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ jsx12(
2456
2930
  "div",
2457
2931
  {
2458
2932
  style: {
@@ -2473,7 +2947,7 @@ var EquipmentIndicatorWithSparkline = ({
2473
2947
  children: label
2474
2948
  }
2475
2949
  ) }),
2476
- hasSparkline && /* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ jsx11(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
2950
+ hasSparkline && /* @__PURE__ */ jsx12(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ jsx12(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
2477
2951
  ] });
2478
2952
  };
2479
2953
  var EquipmentIndicator = ({
@@ -2486,7 +2960,7 @@ var EquipmentIndicator = ({
2486
2960
  className
2487
2961
  }) => {
2488
2962
  const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
2489
- return /* @__PURE__ */ jsx11(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ jsx11(
2963
+ return /* @__PURE__ */ jsx12(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ jsx12(
2490
2964
  "div",
2491
2965
  {
2492
2966
  style: {
@@ -2510,7 +2984,7 @@ var EquipmentIndicator = ({
2510
2984
  };
2511
2985
 
2512
2986
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
2513
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2987
+ import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
2514
2988
  function FullscreenWorkspace({
2515
2989
  svgContent,
2516
2990
  overlays,
@@ -2538,10 +3012,10 @@ function FullscreenWorkspace({
2538
3012
  className = "",
2539
3013
  ...rest
2540
3014
  }) {
2541
- const [leftCollapsedState, setLeftCollapsedState] = React6.useState(defaultLeftCollapsed);
2542
- const [rightCollapsedState, setRightCollapsedState] = React6.useState(defaultRightCollapsed);
2543
- const [internalDisplayMode, setInternalDisplayMode] = React6.useState(displayMode ?? defaultDisplayMode);
2544
- const [internalTab, setInternalTab] = React6.useState(
3015
+ const [leftCollapsedState, setLeftCollapsedState] = React7.useState(defaultLeftCollapsed);
3016
+ const [rightCollapsedState, setRightCollapsedState] = React7.useState(defaultRightCollapsed);
3017
+ const [internalDisplayMode, setInternalDisplayMode] = React7.useState(displayMode ?? defaultDisplayMode);
3018
+ const [internalTab, setInternalTab] = React7.useState(
2545
3019
  tabs && tabs.length > 0 ? tabs[0].value : ""
2546
3020
  );
2547
3021
  const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
@@ -2549,10 +3023,10 @@ function FullscreenWorkspace({
2549
3023
  const isDisplayModeControlled = displayMode !== void 0;
2550
3024
  const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
2551
3025
  const isTabControlled = activeTab !== void 0 && activeTab !== null;
2552
- const resolvedTabs = React6.useMemo(() => tabs ?? [], [tabs]);
3026
+ const resolvedTabs = React7.useMemo(() => tabs ?? [], [tabs]);
2553
3027
  const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
2554
3028
  const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
2555
- React6.useEffect(() => {
3029
+ React7.useEffect(() => {
2556
3030
  if (resolvedTabs.length > 0) {
2557
3031
  const values = resolvedTabs.map((tab) => tab.value);
2558
3032
  if (!values.includes(currentTab)) {
@@ -2561,7 +3035,7 @@ function FullscreenWorkspace({
2561
3035
  }
2562
3036
  }
2563
3037
  }, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
2564
- React6.useEffect(() => {
3038
+ React7.useEffect(() => {
2565
3039
  if (displayMode !== void 0) {
2566
3040
  setInternalDisplayMode(displayMode);
2567
3041
  }
@@ -2596,7 +3070,7 @@ function FullscreenWorkspace({
2596
3070
  const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
2597
3071
  const showLeftToggle = Boolean(leftPanel);
2598
3072
  const showRightToggle = Boolean(rightPanel);
2599
- return /* @__PURE__ */ jsxs9(
3073
+ return /* @__PURE__ */ jsxs10(
2600
3074
  FullscreenContainer,
2601
3075
  {
2602
3076
  leftCollapsed,
@@ -2604,25 +3078,25 @@ function FullscreenWorkspace({
2604
3078
  className: `tff-svg-container ${className}`.trim(),
2605
3079
  ...rest,
2606
3080
  children: [
2607
- showLeftToggle && /* @__PURE__ */ jsx12(
3081
+ showLeftToggle && /* @__PURE__ */ jsx13(
2608
3082
  LeftToggleButton,
2609
3083
  {
2610
3084
  collapsed: leftCollapsed,
2611
3085
  onClick: handleLeftToggle,
2612
3086
  "aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
2613
- children: leftCollapsed ? /* @__PURE__ */ jsx12(ChevronRight, {}) : /* @__PURE__ */ jsx12(ChevronLeft, {})
3087
+ children: leftCollapsed ? /* @__PURE__ */ jsx13(ChevronRight, {}) : /* @__PURE__ */ jsx13(ChevronLeft, {})
2614
3088
  }
2615
3089
  ),
2616
- showRightToggle && /* @__PURE__ */ jsx12(
3090
+ showRightToggle && /* @__PURE__ */ jsx13(
2617
3091
  RightToggleButton,
2618
3092
  {
2619
3093
  collapsed: rightCollapsed,
2620
3094
  onClick: handleRightToggle,
2621
3095
  "aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
2622
- children: rightCollapsed ? /* @__PURE__ */ jsx12(ChevronLeft, {}) : /* @__PURE__ */ jsx12(ChevronRight, {})
3096
+ children: rightCollapsed ? /* @__PURE__ */ jsx13(ChevronLeft, {}) : /* @__PURE__ */ jsx13(ChevronRight, {})
2623
3097
  }
2624
3098
  ),
2625
- showDisplayModeToggle && /* @__PURE__ */ jsx12(
3099
+ showDisplayModeToggle && /* @__PURE__ */ jsx13(
2626
3100
  DisplayModeToggle,
2627
3101
  {
2628
3102
  mode: currentDisplayMode,
@@ -2631,9 +3105,9 @@ function FullscreenWorkspace({
2631
3105
  children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
2632
3106
  }
2633
3107
  ),
2634
- /* @__PURE__ */ jsxs9(SVGArea, { children: [
2635
- showZoomControls && /* @__PURE__ */ jsxs9(ZoomControls, { children: [
2636
- /* @__PURE__ */ jsx12(
3108
+ /* @__PURE__ */ jsxs10(SVGArea, { children: [
3109
+ showZoomControls && /* @__PURE__ */ jsxs10(ZoomControls, { children: [
3110
+ /* @__PURE__ */ jsx13(
2637
3111
  ZoomButton,
2638
3112
  {
2639
3113
  onClick: onZoomIn,
@@ -2643,7 +3117,7 @@ function FullscreenWorkspace({
2643
3117
  children: "+"
2644
3118
  }
2645
3119
  ),
2646
- /* @__PURE__ */ jsx12(
3120
+ /* @__PURE__ */ jsx13(
2647
3121
  ZoomButton,
2648
3122
  {
2649
3123
  onClick: onZoomOut,
@@ -2653,7 +3127,7 @@ function FullscreenWorkspace({
2653
3127
  children: "-"
2654
3128
  }
2655
3129
  ),
2656
- onResetZoom && /* @__PURE__ */ jsx12(
3130
+ onResetZoom && /* @__PURE__ */ jsx13(
2657
3131
  ZoomButton,
2658
3132
  {
2659
3133
  onClick: onResetZoom,
@@ -2664,33 +3138,33 @@ function FullscreenWorkspace({
2664
3138
  }
2665
3139
  )
2666
3140
  ] }),
2667
- /* @__PURE__ */ jsx12(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ jsxs9(FixedSVGContainer, { className: "svg-container", children: [
3141
+ /* @__PURE__ */ jsx13(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ jsxs10(FixedSVGContainer, { className: "svg-container", children: [
2668
3142
  svgContent,
2669
3143
  overlays
2670
3144
  ] }) })
2671
3145
  ] }),
2672
- /* @__PURE__ */ jsx12(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
2673
- /* @__PURE__ */ jsx12(
3146
+ /* @__PURE__ */ jsx13(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
3147
+ /* @__PURE__ */ jsx13(
2674
3148
  PanelTabs,
2675
3149
  {
2676
3150
  value: currentTab,
2677
3151
  onChange: handleTabChangeInternal,
2678
3152
  "aria-label": "Left panel tabs",
2679
- children: resolvedTabs.map((tab) => /* @__PURE__ */ jsx12(Tab, { label: tab.label, value: tab.value }, tab.value))
3153
+ children: resolvedTabs.map((tab) => /* @__PURE__ */ jsx13(Tab, { label: tab.label, value: tab.value }, tab.value))
2680
3154
  }
2681
3155
  ),
2682
- /* @__PURE__ */ jsx12(PanelContent, { children: currentTabContent })
3156
+ /* @__PURE__ */ jsx13(PanelContent, { children: currentTabContent })
2683
3157
  ] }) : leftPanel }),
2684
- /* @__PURE__ */ jsx12(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
2685
- /* @__PURE__ */ jsx12(FooterPanel, { children: footer })
3158
+ /* @__PURE__ */ jsx13(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
3159
+ /* @__PURE__ */ jsx13(FooterPanel, { children: footer })
2686
3160
  ]
2687
3161
  }
2688
3162
  );
2689
3163
  }
2690
3164
 
2691
3165
  // src/theme/ThemeContext.tsx
2692
- import { createContext, useContext, useState as useState7, useEffect as useEffect4 } from "react";
2693
- import { jsx as jsx13 } from "react/jsx-runtime";
3166
+ import { createContext, useContext, useState as useState8, useEffect as useEffect5 } from "react";
3167
+ import { jsx as jsx14 } from "react/jsx-runtime";
2694
3168
  var ThemeContext = createContext(void 0);
2695
3169
  var useTheme = () => {
2696
3170
  const context = useContext(ThemeContext);
@@ -2700,8 +3174,8 @@ var useTheme = () => {
2700
3174
  return context;
2701
3175
  };
2702
3176
  var ThemeProvider = ({ children }) => {
2703
- const [theme, setThemeState] = useState7("modern");
2704
- useEffect4(() => {
3177
+ const [theme, setThemeState] = useState8("modern");
3178
+ useEffect5(() => {
2705
3179
  document.body.className = "";
2706
3180
  document.body.classList.add(`theme-${theme}`);
2707
3181
  document.documentElement.className = "";
@@ -2713,11 +3187,11 @@ var ThemeProvider = ({ children }) => {
2713
3187
  const setTheme = (newTheme) => {
2714
3188
  setThemeState(newTheme);
2715
3189
  };
2716
- return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
3190
+ return /* @__PURE__ */ jsx14(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
2717
3191
  };
2718
3192
 
2719
3193
  // src/theme/ThemeToggle.tsx
2720
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3194
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
2721
3195
  var ThemeToggle = ({
2722
3196
  size = "medium",
2723
3197
  position = "top-right",
@@ -2788,15 +3262,15 @@ var ThemeToggle = ({
2788
3262
  transition: "all 0.2s ease",
2789
3263
  boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
2790
3264
  };
2791
- return /* @__PURE__ */ jsxs10("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
2792
- /* @__PURE__ */ jsx14("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
2793
- /* @__PURE__ */ jsx14("div", { style: toggleStyle, children: /* @__PURE__ */ jsx14("div", { style: thumbStyle }) }),
2794
- /* @__PURE__ */ jsx14("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
3265
+ return /* @__PURE__ */ jsxs11("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
3266
+ /* @__PURE__ */ jsx15("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
3267
+ /* @__PURE__ */ jsx15("div", { style: toggleStyle, children: /* @__PURE__ */ jsx15("div", { style: thumbStyle }) }),
3268
+ /* @__PURE__ */ jsx15("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
2795
3269
  ] });
2796
3270
  };
2797
3271
 
2798
3272
  // src/components/PIDCanvas/PIDCanvas.tsx
2799
- import { useCallback as useCallback7, useState as useState13, useEffect as useEffect11, useRef as useRef5 } from "react";
3273
+ import { useCallback as useCallback8, useState as useState14, useEffect as useEffect12, useRef as useRef6 } from "react";
2800
3274
 
2801
3275
  // src/diagram/symbols/mockSymbolLibrary.ts
2802
3276
  var mockSymbolLibrary = {
@@ -4017,7 +4491,7 @@ function getAvailableSymbols() {
4017
4491
  }
4018
4492
 
4019
4493
  // src/components/PIDCanvas/NodeRenderer.tsx
4020
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4494
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4021
4495
  function NodeRenderer({
4022
4496
  nodes: nodes2,
4023
4497
  selectedNodeIds,
@@ -4029,13 +4503,13 @@ function NodeRenderer({
4029
4503
  enableDrag = false,
4030
4504
  statusColorMap
4031
4505
  }) {
4032
- return /* @__PURE__ */ jsx15("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
4506
+ return /* @__PURE__ */ jsx16("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
4033
4507
  const symbol = getSymbolDefinition(node.symbolId);
4034
4508
  const isSelected = selectedNodeIds?.has(node.id) ?? false;
4035
4509
  const isDragging = draggingNodeId === node.id;
4036
4510
  if (!symbol) {
4037
- return /* @__PURE__ */ jsxs11("g", { children: [
4038
- /* @__PURE__ */ jsx15(
4511
+ return /* @__PURE__ */ jsxs12("g", { children: [
4512
+ /* @__PURE__ */ jsx16(
4039
4513
  "circle",
4040
4514
  {
4041
4515
  cx: node.transform.x,
@@ -4047,7 +4521,7 @@ function NodeRenderer({
4047
4521
  strokeWidth: "2"
4048
4522
  }
4049
4523
  ),
4050
- /* @__PURE__ */ jsx15(
4524
+ /* @__PURE__ */ jsx16(
4051
4525
  "text",
4052
4526
  {
4053
4527
  x: node.transform.x,
@@ -4089,7 +4563,7 @@ function NodeRenderer({
4089
4563
  const statusEntry = resolveStatusColor(node.status, statusColorMap);
4090
4564
  const fillColor = node.customColors?.fill ?? statusEntry.fill;
4091
4565
  const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
4092
- return /* @__PURE__ */ jsxs11(
4566
+ return /* @__PURE__ */ jsxs12(
4093
4567
  "g",
4094
4568
  {
4095
4569
  "data-node-id": node.id,
@@ -4122,7 +4596,7 @@ function NodeRenderer({
4122
4596
  }
4123
4597
  },
4124
4598
  children: [
4125
- isSelected && /* @__PURE__ */ jsx15(
4599
+ isSelected && /* @__PURE__ */ jsx16(
4126
4600
  "rect",
4127
4601
  {
4128
4602
  x: "-5",
@@ -4137,7 +4611,7 @@ function NodeRenderer({
4137
4611
  pointerEvents: "none"
4138
4612
  }
4139
4613
  ),
4140
- /* @__PURE__ */ jsx15(
4614
+ /* @__PURE__ */ jsx16(
4141
4615
  "g",
4142
4616
  {
4143
4617
  dangerouslySetInnerHTML: { __html: symbol.svgContent },
@@ -4145,7 +4619,7 @@ function NodeRenderer({
4145
4619
  style: { pointerEvents: "auto" }
4146
4620
  }
4147
4621
  ),
4148
- /* @__PURE__ */ jsx15(
4622
+ /* @__PURE__ */ jsx16(
4149
4623
  "text",
4150
4624
  {
4151
4625
  x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
@@ -4166,7 +4640,7 @@ function NodeRenderer({
4166
4640
  }
4167
4641
 
4168
4642
  // src/components/PIDCanvas/PipeRenderer.tsx
4169
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4643
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4170
4644
  function PipeRenderer({
4171
4645
  pipes,
4172
4646
  selectedPipeIds,
@@ -4181,7 +4655,7 @@ function PipeRenderer({
4181
4655
  waypointDragOffset,
4182
4656
  onPipeSegmentClick
4183
4657
  }) {
4184
- return /* @__PURE__ */ jsx16("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
4658
+ return /* @__PURE__ */ jsx17("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
4185
4659
  const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
4186
4660
  const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
4187
4661
  const showEditingControls = enableWaypointEditing && isSelected;
@@ -4200,7 +4674,7 @@ function PipeRenderer({
4200
4674
  const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
4201
4675
  const strokeDasharray = pipeStyle.strokeDasharray;
4202
4676
  const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
4203
- return /* @__PURE__ */ jsxs12(
4677
+ return /* @__PURE__ */ jsxs13(
4204
4678
  "g",
4205
4679
  {
4206
4680
  "data-pipe-id": pipe.id,
@@ -4213,8 +4687,8 @@ function PipeRenderer({
4213
4687
  cursor: onPipeClick ? "pointer" : "default"
4214
4688
  },
4215
4689
  children: [
4216
- !enableWaypointEditing && /* @__PURE__ */ jsxs12(Fragment5, { children: [
4217
- onPipeClick && /* @__PURE__ */ jsx16(
4690
+ !enableWaypointEditing && /* @__PURE__ */ jsxs13(Fragment5, { children: [
4691
+ onPipeClick && /* @__PURE__ */ jsx17(
4218
4692
  "polyline",
4219
4693
  {
4220
4694
  points: pointsString,
@@ -4226,7 +4700,7 @@ function PipeRenderer({
4226
4700
  pointerEvents: "stroke"
4227
4701
  }
4228
4702
  ),
4229
- /* @__PURE__ */ jsx16(
4703
+ /* @__PURE__ */ jsx17(
4230
4704
  "polyline",
4231
4705
  {
4232
4706
  points: pointsString,
@@ -4250,7 +4724,7 @@ function PipeRenderer({
4250
4724
  const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
4251
4725
  const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
4252
4726
  const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
4253
- return /* @__PURE__ */ jsx16(
4727
+ return /* @__PURE__ */ jsx17(
4254
4728
  "circle",
4255
4729
  {
4256
4730
  cx: point.x,
@@ -4287,12 +4761,12 @@ function PipeRenderer({
4287
4761
  `${pipe.id}-point-${idx}`
4288
4762
  );
4289
4763
  }),
4290
- showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ jsx16(Fragment5, { children: displayPoints.slice(0, -1).map((point, idx) => {
4764
+ showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ jsx17(Fragment5, { children: displayPoints.slice(0, -1).map((point, idx) => {
4291
4765
  const nextPoint = displayPoints[idx + 1];
4292
4766
  const midX = (point.x + nextPoint.x) / 2;
4293
4767
  const midY = (point.y + nextPoint.y) / 2;
4294
- return /* @__PURE__ */ jsxs12("g", { children: [
4295
- /* @__PURE__ */ jsx16(
4768
+ return /* @__PURE__ */ jsxs13("g", { children: [
4769
+ /* @__PURE__ */ jsx17(
4296
4770
  "circle",
4297
4771
  {
4298
4772
  cx: midX,
@@ -4308,7 +4782,7 @@ function PipeRenderer({
4308
4782
  }
4309
4783
  }
4310
4784
  ),
4311
- /* @__PURE__ */ jsx16(
4785
+ /* @__PURE__ */ jsx17(
4312
4786
  "circle",
4313
4787
  {
4314
4788
  cx: midX,
@@ -4324,7 +4798,7 @@ function PipeRenderer({
4324
4798
  )
4325
4799
  ] }, `${pipe.id}-segment-${idx}`);
4326
4800
  }) }),
4327
- pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ jsx16(
4801
+ pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ jsx17(
4328
4802
  "text",
4329
4803
  {
4330
4804
  x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
@@ -4346,7 +4820,7 @@ function PipeRenderer({
4346
4820
  }
4347
4821
 
4348
4822
  // src/components/PIDCanvas/DataOverlay.tsx
4349
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4823
+ import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4350
4824
  function DataOverlay({
4351
4825
  nodeId,
4352
4826
  x,
@@ -4368,7 +4842,7 @@ function DataOverlay({
4368
4842
  const offsetX = display?.offsetX ?? 0;
4369
4843
  const offsetY = display?.offsetY ?? 0;
4370
4844
  if (!showValue) {
4371
- return /* @__PURE__ */ jsx17(Fragment6, {});
4845
+ return /* @__PURE__ */ jsx18(Fragment6, {});
4372
4846
  }
4373
4847
  const formatValue = (val) => {
4374
4848
  if (typeof val === "number") {
@@ -4409,8 +4883,8 @@ function DataOverlay({
4409
4883
  const overlayWidth = 80 * scale;
4410
4884
  const displayX = x + offsetX;
4411
4885
  const displayY = y + offsetY;
4412
- return /* @__PURE__ */ jsxs13("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4413
- /* @__PURE__ */ jsx17(
4886
+ return /* @__PURE__ */ jsxs14("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4887
+ /* @__PURE__ */ jsx18(
4414
4888
  "rect",
4415
4889
  {
4416
4890
  x: displayX - overlayWidth / 2,
@@ -4425,7 +4899,7 @@ function DataOverlay({
4425
4899
  filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
4426
4900
  }
4427
4901
  ),
4428
- label && /* @__PURE__ */ jsx17(
4902
+ label && /* @__PURE__ */ jsx18(
4429
4903
  "text",
4430
4904
  {
4431
4905
  x: displayX,
@@ -4438,7 +4912,7 @@ function DataOverlay({
4438
4912
  children: label
4439
4913
  }
4440
4914
  ),
4441
- /* @__PURE__ */ jsx17(
4915
+ /* @__PURE__ */ jsx18(
4442
4916
  "text",
4443
4917
  {
4444
4918
  x: displayX,
@@ -4451,7 +4925,7 @@ function DataOverlay({
4451
4925
  children: displayText
4452
4926
  }
4453
4927
  ),
4454
- showStatus && value.status !== "normal" && /* @__PURE__ */ jsx17(
4928
+ showStatus && value.status !== "normal" && /* @__PURE__ */ jsx18(
4455
4929
  "circle",
4456
4930
  {
4457
4931
  cx: displayX + 35 * scale,
@@ -4459,7 +4933,7 @@ function DataOverlay({
4459
4933
  r: 3 * scale,
4460
4934
  fill: finalTextColor,
4461
4935
  opacity: "0.9",
4462
- children: /* @__PURE__ */ jsx17(
4936
+ children: /* @__PURE__ */ jsx18(
4463
4937
  "animate",
4464
4938
  {
4465
4939
  attributeName: "opacity",
@@ -4470,7 +4944,7 @@ function DataOverlay({
4470
4944
  )
4471
4945
  }
4472
4946
  ),
4473
- value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs13(
4947
+ value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs14(
4474
4948
  "text",
4475
4949
  {
4476
4950
  x: displayX,
@@ -4487,7 +4961,7 @@ function DataOverlay({
4487
4961
  ]
4488
4962
  }
4489
4963
  ),
4490
- hasSparkline && /* @__PURE__ */ jsx17("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ jsx17(
4964
+ hasSparkline && /* @__PURE__ */ jsx18("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ jsx18(
4491
4965
  "path",
4492
4966
  {
4493
4967
  d: sparklinePath,
@@ -4503,8 +4977,8 @@ function DataOverlay({
4503
4977
  }
4504
4978
 
4505
4979
  // src/components/PIDCanvas/PositionPanel.tsx
4506
- import { useState as useState8, useEffect as useEffect5 } from "react";
4507
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4980
+ import { useState as useState9, useEffect as useEffect6 } from "react";
4981
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
4508
4982
  function PositionPanel({
4509
4983
  selectedNode,
4510
4984
  selectedWaypoint,
@@ -4512,9 +4986,9 @@ function PositionPanel({
4512
4986
  onWaypointPositionChange,
4513
4987
  position = "top-right"
4514
4988
  }) {
4515
- const [x, setX] = useState8("");
4516
- const [y, setY] = useState8("");
4517
- useEffect5(() => {
4989
+ const [x, setX] = useState9("");
4990
+ const [y, setY] = useState9("");
4991
+ useEffect6(() => {
4518
4992
  if (selectedNode) {
4519
4993
  setX(selectedNode.transform.x.toFixed(2));
4520
4994
  setY(selectedNode.transform.y.toFixed(2));
@@ -4573,7 +5047,7 @@ function PositionPanel({
4573
5047
  "bottom-left": { bottom: 10, left: 10 },
4574
5048
  "bottom-right": { bottom: 10, right: 10 }
4575
5049
  };
4576
- return /* @__PURE__ */ jsxs14(
5050
+ return /* @__PURE__ */ jsxs15(
4577
5051
  "div",
4578
5052
  {
4579
5053
  style: {
@@ -4590,11 +5064,11 @@ function PositionPanel({
4590
5064
  fontSize: "13px"
4591
5065
  },
4592
5066
  children: [
4593
- /* @__PURE__ */ jsx18("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
4594
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
4595
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4596
- /* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
4597
- /* @__PURE__ */ jsx18(
5067
+ /* @__PURE__ */ jsx19("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
5068
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
5069
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
5070
+ /* @__PURE__ */ jsx19("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
5071
+ /* @__PURE__ */ jsx19(
4598
5072
  "input",
4599
5073
  {
4600
5074
  type: "number",
@@ -4612,9 +5086,9 @@ function PositionPanel({
4612
5086
  }
4613
5087
  )
4614
5088
  ] }),
4615
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4616
- /* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
4617
- /* @__PURE__ */ jsx18(
5089
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
5090
+ /* @__PURE__ */ jsx19("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
5091
+ /* @__PURE__ */ jsx19(
4618
5092
  "input",
4619
5093
  {
4620
5094
  type: "number",
@@ -4633,14 +5107,14 @@ function PositionPanel({
4633
5107
  )
4634
5108
  ] })
4635
5109
  ] }),
4636
- /* @__PURE__ */ jsx18("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
5110
+ /* @__PURE__ */ jsx19("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
4637
5111
  ]
4638
5112
  }
4639
5113
  );
4640
5114
  }
4641
5115
 
4642
5116
  // src/diagram/hooks/useViewBox.ts
4643
- import { useState as useState9, useCallback as useCallback3, useRef as useRef2, useEffect as useEffect6 } from "react";
5117
+ import { useState as useState10, useCallback as useCallback4, useRef as useRef3, useEffect as useEffect7 } from "react";
4644
5118
  function useViewBox(options) {
4645
5119
  const {
4646
5120
  initialViewBox,
@@ -4651,16 +5125,16 @@ function useViewBox(options) {
4651
5125
  zoomSensitivity = 1e-3,
4652
5126
  allowLeftClickPan = true
4653
5127
  } = options;
4654
- const [viewBox, setViewBox] = useState9(initialViewBox);
4655
- const svgRef = useRef2(null);
4656
- const isPanningRef = useRef2(false);
4657
- const lastMousePosRef = useRef2({ x: 0, y: 0 });
4658
- const spaceKeyDownRef = useRef2(false);
4659
- const lastTouchDistanceRef = useRef2(null);
4660
- const resetViewBox = useCallback3(() => {
5128
+ const [viewBox, setViewBox] = useState10(initialViewBox);
5129
+ const svgRef = useRef3(null);
5130
+ const isPanningRef = useRef3(false);
5131
+ const lastMousePosRef = useRef3({ x: 0, y: 0 });
5132
+ const spaceKeyDownRef = useRef3(false);
5133
+ const lastTouchDistanceRef = useRef3(null);
5134
+ const resetViewBox = useCallback4(() => {
4661
5135
  setViewBox(initialViewBox);
4662
5136
  }, [initialViewBox]);
4663
- const zoomIn = useCallback3(() => {
5137
+ const zoomIn = useCallback4(() => {
4664
5138
  setViewBox((prev) => {
4665
5139
  const currentZoom = initialViewBox.width / prev.width;
4666
5140
  const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
@@ -4677,7 +5151,7 @@ function useViewBox(options) {
4677
5151
  };
4678
5152
  });
4679
5153
  }, [initialViewBox, minZoom]);
4680
- const zoomOut = useCallback3(() => {
5154
+ const zoomOut = useCallback4(() => {
4681
5155
  setViewBox((prev) => {
4682
5156
  const currentZoom = initialViewBox.width / prev.width;
4683
5157
  const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
@@ -4694,7 +5168,7 @@ function useViewBox(options) {
4694
5168
  };
4695
5169
  });
4696
5170
  }, [initialViewBox, maxZoom]);
4697
- const fitToContent = useCallback3((bounds, padding = 50) => {
5171
+ const fitToContent = useCallback4((bounds, padding = 50) => {
4698
5172
  const contentWidth = bounds.maxX - bounds.minX;
4699
5173
  const contentHeight = bounds.maxY - bounds.minY;
4700
5174
  if (contentWidth === 0 || contentHeight === 0) {
@@ -4722,7 +5196,7 @@ function useViewBox(options) {
4722
5196
  height: newHeight
4723
5197
  });
4724
5198
  }, [initialViewBox]);
4725
- useEffect6(() => {
5199
+ useEffect7(() => {
4726
5200
  if (!enableZoom || !svgRef.current) return;
4727
5201
  const svg = svgRef.current;
4728
5202
  const handleWheel = (e) => {
@@ -4755,7 +5229,7 @@ function useViewBox(options) {
4755
5229
  svg.addEventListener("wheel", handleWheel, { passive: false });
4756
5230
  return () => svg.removeEventListener("wheel", handleWheel);
4757
5231
  }, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
4758
- useEffect6(() => {
5232
+ useEffect7(() => {
4759
5233
  if (!enablePan || !svgRef.current) return;
4760
5234
  const svg = svgRef.current;
4761
5235
  const handleMouseDown = (e) => {
@@ -4831,7 +5305,7 @@ function useViewBox(options) {
4831
5305
  window.removeEventListener("keyup", handleKeyUp);
4832
5306
  };
4833
5307
  }, [enablePan, allowLeftClickPan]);
4834
- useEffect6(() => {
5308
+ useEffect7(() => {
4835
5309
  if (!svgRef.current) return;
4836
5310
  if (!enablePan && !enableZoom) return;
4837
5311
  const svg = svgRef.current;
@@ -4922,7 +5396,7 @@ function useViewBox(options) {
4922
5396
  svg.removeEventListener("touchend", handleTouchEnd);
4923
5397
  };
4924
5398
  }, [enablePan, enableZoom, minZoom, initialViewBox]);
4925
- const screenToWorld = useCallback3(
5399
+ const screenToWorld = useCallback4(
4926
5400
  (screenX, screenY) => {
4927
5401
  const svg = svgRef.current;
4928
5402
  if (!svg) return { x: screenX, y: screenY };
@@ -4961,15 +5435,15 @@ function useViewBox(options) {
4961
5435
  }
4962
5436
 
4963
5437
  // src/diagram/hooks/useSelection.ts
4964
- import { useState as useState10, useCallback as useCallback4 } from "react";
5438
+ import { useState as useState11, useCallback as useCallback5 } from "react";
4965
5439
  function useSelection(options = {}) {
4966
5440
  const {
4967
5441
  multiSelect = true,
4968
5442
  initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
4969
5443
  onSelectionChange
4970
5444
  } = options;
4971
- const [selection, setSelection] = useState10(initialSelection);
4972
- const notifyChange = useCallback4(
5445
+ const [selection, setSelection] = useState11(initialSelection);
5446
+ const notifyChange = useCallback5(
4973
5447
  (newSelection) => {
4974
5448
  if (onSelectionChange) {
4975
5449
  onSelectionChange(newSelection);
@@ -4977,15 +5451,15 @@ function useSelection(options = {}) {
4977
5451
  },
4978
5452
  [onSelectionChange]
4979
5453
  );
4980
- const isNodeSelected = useCallback4(
5454
+ const isNodeSelected = useCallback5(
4981
5455
  (nodeId) => selection.selectedNodeIds.has(nodeId),
4982
5456
  [selection.selectedNodeIds]
4983
5457
  );
4984
- const isPipeSelected = useCallback4(
5458
+ const isPipeSelected = useCallback5(
4985
5459
  (pipeId) => selection.selectedPipeIds.has(pipeId),
4986
5460
  [selection.selectedPipeIds]
4987
5461
  );
4988
- const selectNode = useCallback4(
5462
+ const selectNode = useCallback5(
4989
5463
  (nodeId, isMultiSelect = false) => {
4990
5464
  setSelection((prev) => {
4991
5465
  const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
@@ -5004,7 +5478,7 @@ function useSelection(options = {}) {
5004
5478
  },
5005
5479
  [multiSelect, notifyChange]
5006
5480
  );
5007
- const selectPipe = useCallback4(
5481
+ const selectPipe = useCallback5(
5008
5482
  (pipeId, isMultiSelect = false) => {
5009
5483
  setSelection((prev) => {
5010
5484
  const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
@@ -5023,7 +5497,7 @@ function useSelection(options = {}) {
5023
5497
  },
5024
5498
  [multiSelect, notifyChange]
5025
5499
  );
5026
- const clearSelection = useCallback4(() => {
5500
+ const clearSelection = useCallback5(() => {
5027
5501
  const newSelection = {
5028
5502
  selectedNodeIds: /* @__PURE__ */ new Set(),
5029
5503
  selectedPipeIds: /* @__PURE__ */ new Set()
@@ -5031,7 +5505,7 @@ function useSelection(options = {}) {
5031
5505
  setSelection(newSelection);
5032
5506
  notifyChange(newSelection);
5033
5507
  }, [notifyChange]);
5034
- const selectNodes = useCallback4(
5508
+ const selectNodes = useCallback5(
5035
5509
  (nodeIds) => {
5036
5510
  const newSelection = {
5037
5511
  selectedNodeIds: new Set(nodeIds),
@@ -5042,7 +5516,7 @@ function useSelection(options = {}) {
5042
5516
  },
5043
5517
  [notifyChange]
5044
5518
  );
5045
- const selectPipes = useCallback4(
5519
+ const selectPipes = useCallback5(
5046
5520
  (pipeIds) => {
5047
5521
  const newSelection = {
5048
5522
  selectedNodeIds: /* @__PURE__ */ new Set(),
@@ -5066,23 +5540,23 @@ function useSelection(options = {}) {
5066
5540
  }
5067
5541
 
5068
5542
  // src/diagram/hooks/useTelemetry.ts
5069
- import { useState as useState11, useCallback as useCallback5, useEffect as useEffect7, useRef as useRef3 } from "react";
5543
+ import { useState as useState12, useCallback as useCallback6, useEffect as useEffect8, useRef as useRef4 } from "react";
5070
5544
  function useTelemetry(options = {}) {
5071
5545
  const {
5072
5546
  initialBindings = [],
5073
5547
  onTelemetryChange,
5074
5548
  refreshInterval = 0
5075
5549
  } = options;
5076
- const [telemetry, setTelemetry] = useState11(() => {
5550
+ const [telemetry, setTelemetry] = useState12(() => {
5077
5551
  const map = /* @__PURE__ */ new Map();
5078
5552
  initialBindings.forEach((binding) => {
5079
5553
  map.set(binding.nodeId, binding);
5080
5554
  });
5081
5555
  return map;
5082
5556
  });
5083
- const telemetryRef = useRef3(telemetry);
5557
+ const telemetryRef = useRef4(telemetry);
5084
5558
  telemetryRef.current = telemetry;
5085
- const notifyChange = useCallback5(
5559
+ const notifyChange = useCallback6(
5086
5560
  (newTelemetry) => {
5087
5561
  if (onTelemetryChange) {
5088
5562
  onTelemetryChange(newTelemetry);
@@ -5090,7 +5564,7 @@ function useTelemetry(options = {}) {
5090
5564
  },
5091
5565
  [onTelemetryChange]
5092
5566
  );
5093
- const updateTelemetry = useCallback5(
5567
+ const updateTelemetry = useCallback6(
5094
5568
  (nodeId, value) => {
5095
5569
  setTelemetry((prev) => {
5096
5570
  const newMap = new Map(prev);
@@ -5120,7 +5594,7 @@ function useTelemetry(options = {}) {
5120
5594
  },
5121
5595
  [notifyChange]
5122
5596
  );
5123
- const updateTelemetryBatch = useCallback5(
5597
+ const updateTelemetryBatch = useCallback6(
5124
5598
  (updates) => {
5125
5599
  setTelemetry((prev) => {
5126
5600
  const newMap = new Map(prev);
@@ -5174,16 +5648,16 @@ function useTelemetry(options = {}) {
5174
5648
  },
5175
5649
  [notifyChange]
5176
5650
  );
5177
- const getTelemetry = useCallback5(
5651
+ const getTelemetry = useCallback6(
5178
5652
  (nodeId) => telemetryRef.current.get(nodeId),
5179
5653
  []
5180
5654
  );
5181
- const clearTelemetry = useCallback5(() => {
5655
+ const clearTelemetry = useCallback6(() => {
5182
5656
  const newMap = /* @__PURE__ */ new Map();
5183
5657
  setTelemetry(newMap);
5184
5658
  notifyChange(newMap);
5185
5659
  }, [notifyChange]);
5186
- const setBindings = useCallback5(
5660
+ const setBindings = useCallback6(
5187
5661
  (bindings) => {
5188
5662
  const newMap = /* @__PURE__ */ new Map();
5189
5663
  bindings.forEach((binding) => {
@@ -5194,7 +5668,7 @@ function useTelemetry(options = {}) {
5194
5668
  },
5195
5669
  [notifyChange]
5196
5670
  );
5197
- useEffect7(() => {
5671
+ useEffect8(() => {
5198
5672
  if (refreshInterval <= 0) return;
5199
5673
  const intervalId = setInterval(() => {
5200
5674
  notifyChange(telemetryRef.current);
@@ -5212,10 +5686,10 @@ function useTelemetry(options = {}) {
5212
5686
  }
5213
5687
 
5214
5688
  // src/diagram/hooks/useTelemetryStatus.ts
5215
- import { useEffect as useEffect8 } from "react";
5689
+ import { useEffect as useEffect9 } from "react";
5216
5690
  function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5217
5691
  const { enabled = true, mapStatus } = options;
5218
- useEffect8(() => {
5692
+ useEffect9(() => {
5219
5693
  if (!enabled) return;
5220
5694
  const defaultMapStatus = (telemetryStatus) => {
5221
5695
  switch (telemetryStatus) {
@@ -5254,7 +5728,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5254
5728
  }
5255
5729
 
5256
5730
  // src/diagram/hooks/useDrag.ts
5257
- import { useState as useState12, useCallback as useCallback6, useRef as useRef4, useEffect as useEffect9 } from "react";
5731
+ import { useState as useState13, useCallback as useCallback7, useRef as useRef5, useEffect as useEffect10 } from "react";
5258
5732
  function useDrag(options = {}) {
5259
5733
  const {
5260
5734
  onDragStart,
@@ -5264,23 +5738,23 @@ function useDrag(options = {}) {
5264
5738
  dragThreshold = 3,
5265
5739
  screenToWorld = (x, y) => ({ x, y })
5266
5740
  } = options;
5267
- const [dragState, setDragState] = useState12({
5741
+ const [dragState, setDragState] = useState13({
5268
5742
  isDragging: false,
5269
5743
  startPosition: null,
5270
5744
  offset: { x: 0, y: 0 },
5271
5745
  draggedId: null
5272
5746
  });
5273
- const [isListening, setIsListening] = useState12(false);
5274
- const dragStartRef = useRef4(null);
5275
- const hasMovedRef = useRef4(false);
5276
- const applySnap = useCallback6(
5747
+ const [isListening, setIsListening] = useState13(false);
5748
+ const dragStartRef = useRef5(null);
5749
+ const hasMovedRef = useRef5(false);
5750
+ const applySnap = useCallback7(
5277
5751
  (value) => {
5278
5752
  if (snapToGrid <= 0) return value;
5279
5753
  return Math.round(value / snapToGrid) * snapToGrid;
5280
5754
  },
5281
5755
  [snapToGrid]
5282
5756
  );
5283
- const handleMouseMove = useCallback6(
5757
+ const handleMouseMove = useCallback7(
5284
5758
  (event) => {
5285
5759
  if (!dragStartRef.current) return;
5286
5760
  const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
@@ -5321,7 +5795,7 @@ function useDrag(options = {}) {
5321
5795
  },
5322
5796
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5323
5797
  );
5324
- const handleMouseUp = useCallback6(
5798
+ const handleMouseUp = useCallback7(
5325
5799
  (event) => {
5326
5800
  if (!dragStartRef.current || !hasMovedRef.current) {
5327
5801
  dragStartRef.current = null;
@@ -5358,7 +5832,7 @@ function useDrag(options = {}) {
5358
5832
  },
5359
5833
  [screenToWorld, applySnap, onDragEnd]
5360
5834
  );
5361
- const handleTouchMove = useCallback6(
5835
+ const handleTouchMove = useCallback7(
5362
5836
  (event) => {
5363
5837
  if (!dragStartRef.current || event.touches.length !== 1) return;
5364
5838
  const touch = event.touches[0];
@@ -5401,7 +5875,7 @@ function useDrag(options = {}) {
5401
5875
  },
5402
5876
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5403
5877
  );
5404
- const handleTouchEnd = useCallback6(
5878
+ const handleTouchEnd = useCallback7(
5405
5879
  (event) => {
5406
5880
  if (!dragStartRef.current || !hasMovedRef.current) {
5407
5881
  dragStartRef.current = null;
@@ -5439,7 +5913,7 @@ function useDrag(options = {}) {
5439
5913
  },
5440
5914
  [screenToWorld, applySnap, onDragEnd]
5441
5915
  );
5442
- useEffect9(() => {
5916
+ useEffect10(() => {
5443
5917
  if (!isListening) return;
5444
5918
  document.addEventListener("mousemove", handleMouseMove);
5445
5919
  document.addEventListener("mouseup", handleMouseUp);
@@ -5454,7 +5928,7 @@ function useDrag(options = {}) {
5454
5928
  document.removeEventListener("touchcancel", handleTouchEnd);
5455
5929
  };
5456
5930
  }, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
5457
- const startDrag = useCallback6(
5931
+ const startDrag = useCallback7(
5458
5932
  (id, event, itemPosition) => {
5459
5933
  event.stopPropagation();
5460
5934
  let clientX;
@@ -5484,7 +5958,7 @@ function useDrag(options = {}) {
5484
5958
  },
5485
5959
  [screenToWorld]
5486
5960
  );
5487
- const cancelDrag = useCallback6(() => {
5961
+ const cancelDrag = useCallback7(() => {
5488
5962
  dragStartRef.current = null;
5489
5963
  hasMovedRef.current = false;
5490
5964
  setIsListening(false);
@@ -5495,7 +5969,7 @@ function useDrag(options = {}) {
5495
5969
  draggedId: null
5496
5970
  });
5497
5971
  }, []);
5498
- const isDraggingItem = useCallback6(
5972
+ const isDraggingItem = useCallback7(
5499
5973
  (id) => dragState.isDragging && dragState.draggedId === id,
5500
5974
  [dragState.isDragging, dragState.draggedId]
5501
5975
  );
@@ -5508,7 +5982,7 @@ function useDrag(options = {}) {
5508
5982
  }
5509
5983
 
5510
5984
  // src/diagram/hooks/useKeyboardShortcuts.ts
5511
- import { useEffect as useEffect10 } from "react";
5985
+ import { useEffect as useEffect11 } from "react";
5512
5986
  function useKeyboardShortcuts(options) {
5513
5987
  const {
5514
5988
  onDelete,
@@ -5519,7 +5993,7 @@ function useKeyboardShortcuts(options) {
5519
5993
  onSelectAll,
5520
5994
  enabled = true
5521
5995
  } = options;
5522
- useEffect10(() => {
5996
+ useEffect11(() => {
5523
5997
  if (!enabled) return;
5524
5998
  const handleKeyDown = (event) => {
5525
5999
  const target = event.target;
@@ -5628,7 +6102,7 @@ function nodeHasPort(node, portId) {
5628
6102
  }
5629
6103
 
5630
6104
  // src/components/PIDCanvas/PIDCanvas.tsx
5631
- import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
6105
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5632
6106
  function PIDCanvas({
5633
6107
  diagram,
5634
6108
  className = "",
@@ -5656,21 +6130,21 @@ function PIDCanvas({
5656
6130
  statusColorMap,
5657
6131
  ...props
5658
6132
  }) {
5659
- const [localDiagram, setLocalDiagram] = useState13(diagram);
5660
- const [dragOverPosition, setDragOverPosition] = useState13(null);
5661
- const [isConnecting, setIsConnecting] = useState13(false);
5662
- const [connectionSource, setConnectionSource] = useState13(null);
5663
- const [connectionSourcePort, setConnectionSourcePort] = useState13(null);
5664
- const [connectionCursor, setConnectionCursor] = useState13(null);
5665
- const [hoveredNode, setHoveredNode] = useState13(null);
5666
- const [hoveredPort, setHoveredPort] = useState13(null);
5667
- const [selectedWaypoint, setSelectedWaypoint] = useState13(null);
5668
- const historyStack = useRef5([]);
5669
- const redoStack = useRef5([]);
5670
- const isUndoRedoAction = useRef5(false);
5671
- const isInternalChange = useRef5(false);
5672
- const lastInternalDiagram = useRef5(null);
5673
- useEffect11(() => {
6133
+ const [localDiagram, setLocalDiagram] = useState14(diagram);
6134
+ const [dragOverPosition, setDragOverPosition] = useState14(null);
6135
+ const [isConnecting, setIsConnecting] = useState14(false);
6136
+ const [connectionSource, setConnectionSource] = useState14(null);
6137
+ const [connectionSourcePort, setConnectionSourcePort] = useState14(null);
6138
+ const [connectionCursor, setConnectionCursor] = useState14(null);
6139
+ const [hoveredNode, setHoveredNode] = useState14(null);
6140
+ const [hoveredPort, setHoveredPort] = useState14(null);
6141
+ const [selectedWaypoint, setSelectedWaypoint] = useState14(null);
6142
+ const historyStack = useRef6([]);
6143
+ const redoStack = useRef6([]);
6144
+ const isUndoRedoAction = useRef6(false);
6145
+ const isInternalChange = useRef6(false);
6146
+ const lastInternalDiagram = useRef6(null);
6147
+ useEffect12(() => {
5674
6148
  const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
5675
6149
  if (isExternal) {
5676
6150
  setLocalDiagram(diagram);
@@ -5692,7 +6166,7 @@ function PIDCanvas({
5692
6166
  enablePan: features.pan ?? true,
5693
6167
  enableZoom: features.zoom ?? true
5694
6168
  });
5695
- const calculateContentBounds = useCallback7(() => {
6169
+ const calculateContentBounds = useCallback8(() => {
5696
6170
  const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
5697
6171
  if (nodes2.length === 0) {
5698
6172
  return null;
@@ -5715,7 +6189,7 @@ function PIDCanvas({
5715
6189
  });
5716
6190
  return { minX, minY, maxX, maxY };
5717
6191
  }, [localDiagram.nodes]);
5718
- useEffect11(() => {
6192
+ useEffect12(() => {
5719
6193
  if (onMounted) {
5720
6194
  const controls = {
5721
6195
  fitToContent: (padding = 50) => {
@@ -5756,8 +6230,8 @@ function PIDCanvas({
5756
6230
  });
5757
6231
  const dragEnabled = features.dragNodes ?? false;
5758
6232
  const selectionEnabled = features.selection ?? false;
5759
- const containerRef = useRef5(null);
5760
- const pushToHistory = useCallback7((currentDiagram) => {
6233
+ const containerRef = useRef6(null);
6234
+ const pushToHistory = useCallback8((currentDiagram) => {
5761
6235
  if (isUndoRedoAction.current) return;
5762
6236
  const snapshot = JSON.parse(JSON.stringify(currentDiagram));
5763
6237
  historyStack.current.push(snapshot);
@@ -5766,7 +6240,7 @@ function PIDCanvas({
5766
6240
  }
5767
6241
  redoStack.current = [];
5768
6242
  }, []);
5769
- const undo = useCallback7(() => {
6243
+ const undo = useCallback8(() => {
5770
6244
  if (historyStack.current.length === 0) return;
5771
6245
  isUndoRedoAction.current = true;
5772
6246
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5780,7 +6254,7 @@ function PIDCanvas({
5780
6254
  isUndoRedoAction.current = false;
5781
6255
  }, 0);
5782
6256
  }, [localDiagram, onDiagramChange]);
5783
- const redo = useCallback7(() => {
6257
+ const redo = useCallback8(() => {
5784
6258
  if (redoStack.current.length === 0) return;
5785
6259
  isUndoRedoAction.current = true;
5786
6260
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5794,7 +6268,7 @@ function PIDCanvas({
5794
6268
  isUndoRedoAction.current = false;
5795
6269
  }, 0);
5796
6270
  }, [localDiagram, onDiagramChange]);
5797
- useEffect11(() => {
6271
+ useEffect12(() => {
5798
6272
  const handleKeyDown = (e) => {
5799
6273
  const isCtrlOrCmd = e.ctrlKey || e.metaKey;
5800
6274
  if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
@@ -5811,7 +6285,7 @@ function PIDCanvas({
5811
6285
  window.addEventListener("keydown", handleKeyDown);
5812
6286
  return () => window.removeEventListener("keydown", handleKeyDown);
5813
6287
  }, [undo, redo]);
5814
- useEffect11(() => {
6288
+ useEffect12(() => {
5815
6289
  if (!features.dragNodes) return;
5816
6290
  const handleKeyDown = (e) => {
5817
6291
  if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
@@ -5896,7 +6370,7 @@ function PIDCanvas({
5896
6370
  onNodeMove,
5897
6371
  pushToHistory
5898
6372
  ]);
5899
- const handlePositionChange = useCallback7(
6373
+ const handlePositionChange = useCallback8(
5900
6374
  (nodeId, x, y) => {
5901
6375
  pushToHistory(localDiagram);
5902
6376
  const updatedNodes = localDiagram.nodes.map(
@@ -5918,7 +6392,7 @@ function PIDCanvas({
5918
6392
  },
5919
6393
  [localDiagram, onDiagramChange, onNodeMove, pushToHistory]
5920
6394
  );
5921
- const handleWaypointPositionChange = useCallback7(
6395
+ const handleWaypointPositionChange = useCallback8(
5922
6396
  (pipeId, pointIndex, x, y) => {
5923
6397
  pushToHistory(localDiagram);
5924
6398
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -5936,7 +6410,7 @@ function PIDCanvas({
5936
6410
  },
5937
6411
  [localDiagram, onDiagramChange, pushToHistory]
5938
6412
  );
5939
- const handleDragEnd = useCallback7(
6413
+ const handleDragEnd = useCallback8(
5940
6414
  (nodeId, offset, finalPosition) => {
5941
6415
  const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
5942
6416
  if (dragDistance < 2) {
@@ -6017,7 +6491,7 @@ function PIDCanvas({
6017
6491
  onDiagramChange?.(updatedDiagram);
6018
6492
  }
6019
6493
  });
6020
- const handleNodeDragStart = useCallback7(
6494
+ const handleNodeDragStart = useCallback8(
6021
6495
  (nodeId, event) => {
6022
6496
  const node = localDiagram.nodes.find((n) => n.id === nodeId);
6023
6497
  if (!node) return;
@@ -6025,7 +6499,7 @@ function PIDCanvas({
6025
6499
  },
6026
6500
  [localDiagram.nodes, startDrag]
6027
6501
  );
6028
- const handleWaypointClick = useCallback7(
6502
+ const handleWaypointClick = useCallback8(
6029
6503
  (pipeId, pointIndex) => {
6030
6504
  setSelectedWaypoint({ pipeId, pointIndex });
6031
6505
  if (selectionEnabled) {
@@ -6034,7 +6508,7 @@ function PIDCanvas({
6034
6508
  },
6035
6509
  [selectionEnabled, clearSelection]
6036
6510
  );
6037
- const handleWaypointDragStart = useCallback7(
6511
+ const handleWaypointDragStart = useCallback8(
6038
6512
  (pipeId, pointIndex, event) => {
6039
6513
  const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
6040
6514
  if (!pipe || pointIndex >= pipe.routePoints.length) return;
@@ -6043,7 +6517,7 @@ function PIDCanvas({
6043
6517
  },
6044
6518
  [localDiagram.pipes, startWaypointDrag]
6045
6519
  );
6046
- const handlePipeSegmentClick = useCallback7(
6520
+ const handlePipeSegmentClick = useCallback8(
6047
6521
  (pipeId, position, segmentIndex) => {
6048
6522
  pushToHistory(localDiagram);
6049
6523
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6062,7 +6536,7 @@ function PIDCanvas({
6062
6536
  [localDiagram, onDiagramChange, pushToHistory]
6063
6537
  );
6064
6538
  const telemetryEnabled = features.telemetry ?? false;
6065
- const handleDelete = useCallback7(() => {
6539
+ const handleDelete = useCallback8(() => {
6066
6540
  if (!selectionEnabled) return;
6067
6541
  const { selectedNodeIds, selectedPipeIds } = selection;
6068
6542
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
@@ -6091,13 +6565,13 @@ function PIDCanvas({
6091
6565
  onDelete,
6092
6566
  pushToHistory
6093
6567
  ]);
6094
- const handleCopy = useCallback7(() => {
6568
+ const handleCopy = useCallback8(() => {
6095
6569
  if (!selectionEnabled) return;
6096
6570
  const { selectedNodeIds, selectedPipeIds } = selection;
6097
6571
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
6098
6572
  onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
6099
6573
  }, [selection, selectionEnabled, onItemsCopied]);
6100
- const handlePaste = useCallback7(() => {
6574
+ const handlePaste = useCallback8(() => {
6101
6575
  if (!selectionEnabled) return;
6102
6576
  onPaste?.();
6103
6577
  }, [selectionEnabled, onPaste]);
@@ -6157,7 +6631,7 @@ function PIDCanvas({
6157
6631
  }
6158
6632
  setSelectedWaypoint(null);
6159
6633
  };
6160
- const handleDragOver = useCallback7(
6634
+ const handleDragOver = useCallback8(
6161
6635
  (event) => {
6162
6636
  if (!features.allowSymbolDrop) return;
6163
6637
  event.preventDefault();
@@ -6168,7 +6642,7 @@ function PIDCanvas({
6168
6642
  },
6169
6643
  [features.allowSymbolDrop, screenToWorld, svgRef]
6170
6644
  );
6171
- const handleDrop = useCallback7(
6645
+ const handleDrop = useCallback8(
6172
6646
  (event) => {
6173
6647
  if (!features.allowSymbolDrop) return;
6174
6648
  event.preventDefault();
@@ -6181,10 +6655,10 @@ function PIDCanvas({
6181
6655
  },
6182
6656
  [features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
6183
6657
  );
6184
- const handleDragLeave = useCallback7(() => {
6658
+ const handleDragLeave = useCallback8(() => {
6185
6659
  setDragOverPosition(null);
6186
6660
  }, []);
6187
- const handleMouseMove = useCallback7(
6661
+ const handleMouseMove = useCallback8(
6188
6662
  (event) => {
6189
6663
  const connectionModeEnabled = features.connectionMode ?? false;
6190
6664
  if (connectionModeEnabled) {
@@ -6221,7 +6695,7 @@ function PIDCanvas({
6221
6695
  const viewBox = controlledViewBox;
6222
6696
  const displayDiagram = localDiagram;
6223
6697
  const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
6224
- return /* @__PURE__ */ jsxs15(
6698
+ return /* @__PURE__ */ jsxs16(
6225
6699
  "div",
6226
6700
  {
6227
6701
  ref: containerRef,
@@ -6236,7 +6710,7 @@ function PIDCanvas({
6236
6710
  },
6237
6711
  ...props,
6238
6712
  children: [
6239
- /* @__PURE__ */ jsxs15(
6713
+ /* @__PURE__ */ jsxs16(
6240
6714
  "svg",
6241
6715
  {
6242
6716
  ref: svgRef,
@@ -6255,15 +6729,15 @@ function PIDCanvas({
6255
6729
  onDrop: handleDrop,
6256
6730
  onDragLeave: handleDragLeave,
6257
6731
  children: [
6258
- features.showGrid !== false ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
6259
- /* @__PURE__ */ jsxs15("defs", { children: [
6260
- /* @__PURE__ */ jsx19("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx19("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
6261
- /* @__PURE__ */ jsxs15("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6262
- /* @__PURE__ */ jsx19("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6263
- /* @__PURE__ */ jsx19("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
6732
+ features.showGrid !== false ? /* @__PURE__ */ jsxs16(Fragment7, { children: [
6733
+ /* @__PURE__ */ jsxs16("defs", { children: [
6734
+ /* @__PURE__ */ jsx20("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx20("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
6735
+ /* @__PURE__ */ jsxs16("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6736
+ /* @__PURE__ */ jsx20("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6737
+ /* @__PURE__ */ jsx20("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
6264
6738
  ] })
6265
6739
  ] }),
6266
- /* @__PURE__ */ jsx19(
6740
+ /* @__PURE__ */ jsx20(
6267
6741
  "rect",
6268
6742
  {
6269
6743
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6273,7 +6747,7 @@ function PIDCanvas({
6273
6747
  fill: "url(#grid-major)"
6274
6748
  }
6275
6749
  )
6276
- ] }) : /* @__PURE__ */ jsx19(
6750
+ ] }) : /* @__PURE__ */ jsx20(
6277
6751
  "rect",
6278
6752
  {
6279
6753
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6283,7 +6757,7 @@ function PIDCanvas({
6283
6757
  fill: features.backgroundColor ?? "#ffffff"
6284
6758
  }
6285
6759
  ),
6286
- /* @__PURE__ */ jsx19(
6760
+ /* @__PURE__ */ jsx20(
6287
6761
  PipeRenderer,
6288
6762
  {
6289
6763
  pipes: displayDiagram.pipes,
@@ -6297,7 +6771,7 @@ function PIDCanvas({
6297
6771
  onPipeSegmentClick: void 0
6298
6772
  }
6299
6773
  ),
6300
- /* @__PURE__ */ jsx19(
6774
+ /* @__PURE__ */ jsx20(
6301
6775
  NodeRenderer,
6302
6776
  {
6303
6777
  nodes: displayDiagram.nodes,
@@ -6311,7 +6785,7 @@ function PIDCanvas({
6311
6785
  statusColorMap
6312
6786
  }
6313
6787
  ),
6314
- (features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx19(
6788
+ (features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx20(
6315
6789
  PipeRenderer,
6316
6790
  {
6317
6791
  pipes: displayDiagram.pipes,
@@ -6328,14 +6802,14 @@ function PIDCanvas({
6328
6802
  onPipeSegmentClick: handlePipeSegmentClick
6329
6803
  }
6330
6804
  ),
6331
- telemetryEnabled && telemetry && /* @__PURE__ */ jsx19("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
6805
+ telemetryEnabled && telemetry && /* @__PURE__ */ jsx20("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
6332
6806
  const binding = telemetry.get(node.id);
6333
6807
  if (!binding) return null;
6334
6808
  const symbol = getSymbolDefinition(node.symbolId);
6335
6809
  if (!symbol) return null;
6336
6810
  const overlayX = node.transform.x + symbol.viewBox.width / 2;
6337
6811
  const overlayY = node.transform.y + symbol.viewBox.height + 50;
6338
- return /* @__PURE__ */ jsx19(
6812
+ return /* @__PURE__ */ jsx20(
6339
6813
  DataOverlay,
6340
6814
  {
6341
6815
  nodeId: node.id,
@@ -6348,7 +6822,7 @@ function PIDCanvas({
6348
6822
  `telemetry-${node.id}`
6349
6823
  );
6350
6824
  }) }),
6351
- dragOverPosition && /* @__PURE__ */ jsx19(
6825
+ dragOverPosition && /* @__PURE__ */ jsx20(
6352
6826
  "circle",
6353
6827
  {
6354
6828
  cx: dragOverPosition.x,
@@ -6361,7 +6835,7 @@ function PIDCanvas({
6361
6835
  pointerEvents: "none"
6362
6836
  }
6363
6837
  ),
6364
- isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx19("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
6838
+ isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx20("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
6365
6839
  const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
6366
6840
  if (!sourceNode) return null;
6367
6841
  const symbol = getSymbolDefinition(sourceNode.symbolId);
@@ -6377,8 +6851,8 @@ function PIDCanvas({
6377
6851
  }
6378
6852
  }
6379
6853
  }
6380
- return /* @__PURE__ */ jsxs15(Fragment7, { children: [
6381
- /* @__PURE__ */ jsx19(
6854
+ return /* @__PURE__ */ jsxs16(Fragment7, { children: [
6855
+ /* @__PURE__ */ jsx20(
6382
6856
  "circle",
6383
6857
  {
6384
6858
  cx: lineStartX,
@@ -6390,7 +6864,7 @@ function PIDCanvas({
6390
6864
  opacity: 0.6
6391
6865
  }
6392
6866
  ),
6393
- /* @__PURE__ */ jsx19(
6867
+ /* @__PURE__ */ jsx20(
6394
6868
  "line",
6395
6869
  {
6396
6870
  x1: lineStartX,
@@ -6403,7 +6877,7 @@ function PIDCanvas({
6403
6877
  opacity: 0.8
6404
6878
  }
6405
6879
  ),
6406
- /* @__PURE__ */ jsx19(
6880
+ /* @__PURE__ */ jsx20(
6407
6881
  "circle",
6408
6882
  {
6409
6883
  cx: connectionCursor.x,
@@ -6415,7 +6889,7 @@ function PIDCanvas({
6415
6889
  )
6416
6890
  ] });
6417
6891
  })() }),
6418
- features.connectionMode && /* @__PURE__ */ jsx19("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
6892
+ features.connectionMode && /* @__PURE__ */ jsx20("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
6419
6893
  const symbol = getSymbolDefinition(node.symbolId);
6420
6894
  if (!symbol?.ports) return null;
6421
6895
  return symbol.ports.map((port) => {
@@ -6423,8 +6897,8 @@ function PIDCanvas({
6423
6897
  if (!portPos) return null;
6424
6898
  const isHovered = hoveredPort === port.id && hoveredNode === node.id;
6425
6899
  const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
6426
- return /* @__PURE__ */ jsxs15("g", { children: [
6427
- /* @__PURE__ */ jsx19(
6900
+ return /* @__PURE__ */ jsxs16("g", { children: [
6901
+ /* @__PURE__ */ jsx20(
6428
6902
  "circle",
6429
6903
  {
6430
6904
  cx: portPos.x,
@@ -6457,7 +6931,7 @@ function PIDCanvas({
6457
6931
  }
6458
6932
  }
6459
6933
  ),
6460
- /* @__PURE__ */ jsx19(
6934
+ /* @__PURE__ */ jsx20(
6461
6935
  "circle",
6462
6936
  {
6463
6937
  cx: portPos.x,
@@ -6476,7 +6950,7 @@ function PIDCanvas({
6476
6950
  ]
6477
6951
  }
6478
6952
  ),
6479
- features.dragNodes && /* @__PURE__ */ jsx19(
6953
+ features.dragNodes && /* @__PURE__ */ jsx20(
6480
6954
  PositionPanel,
6481
6955
  {
6482
6956
  selectedNode,
@@ -6496,16 +6970,16 @@ function PIDCanvas({
6496
6970
  }
6497
6971
 
6498
6972
  // src/components/SymbolLibrary/SymbolLibrary.tsx
6499
- import { useState as useState14 } from "react";
6500
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
6973
+ import { useState as useState15 } from "react";
6974
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
6501
6975
  function SymbolLibrary({
6502
6976
  className = "",
6503
6977
  onSymbolDragStart,
6504
6978
  showCategories = true,
6505
6979
  categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
6506
6980
  }) {
6507
- const [selectedCategory, setSelectedCategory] = useState14("all");
6508
- const [searchQuery, setSearchQuery] = useState14("");
6981
+ const [selectedCategory, setSelectedCategory] = useState15("all");
6982
+ const [searchQuery, setSearchQuery] = useState15("");
6509
6983
  const symbolIds = getAvailableSymbols();
6510
6984
  const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
6511
6985
  const categoryMap = {
@@ -6526,9 +7000,9 @@ function SymbolLibrary({
6526
7000
  event.dataTransfer.effectAllowed = "copy";
6527
7001
  onSymbolDragStart?.(symbol.id, event);
6528
7002
  };
6529
- return /* @__PURE__ */ jsxs16("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
6530
- /* @__PURE__ */ jsx20("div", { style: styles.header, children: /* @__PURE__ */ jsx20("h3", { style: styles.title, children: "Symbol Library" }) }),
6531
- /* @__PURE__ */ jsx20("div", { style: styles.searchContainer, children: /* @__PURE__ */ jsx20(
7003
+ return /* @__PURE__ */ jsxs17("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
7004
+ /* @__PURE__ */ jsx21("div", { style: styles.header, children: /* @__PURE__ */ jsx21("h3", { style: styles.title, children: "Symbol Library" }) }),
7005
+ /* @__PURE__ */ jsx21("div", { style: styles.searchContainer, children: /* @__PURE__ */ jsx21(
6532
7006
  "input",
6533
7007
  {
6534
7008
  type: "text",
@@ -6538,8 +7012,8 @@ function SymbolLibrary({
6538
7012
  style: styles.searchInput
6539
7013
  }
6540
7014
  ) }),
6541
- showCategories && /* @__PURE__ */ jsxs16("div", { style: styles.categories, children: [
6542
- /* @__PURE__ */ jsx20(
7015
+ showCategories && /* @__PURE__ */ jsxs17("div", { style: styles.categories, children: [
7016
+ /* @__PURE__ */ jsx21(
6543
7017
  "button",
6544
7018
  {
6545
7019
  onClick: () => setSelectedCategory("all"),
@@ -6550,7 +7024,7 @@ function SymbolLibrary({
6550
7024
  children: "All"
6551
7025
  }
6552
7026
  ),
6553
- categories.map((category) => /* @__PURE__ */ jsx20(
7027
+ categories.map((category) => /* @__PURE__ */ jsx21(
6554
7028
  "button",
6555
7029
  {
6556
7030
  onClick: () => setSelectedCategory(category),
@@ -6563,7 +7037,7 @@ function SymbolLibrary({
6563
7037
  category
6564
7038
  ))
6565
7039
  ] }),
6566
- /* @__PURE__ */ jsx20("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ jsx20("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ jsxs16(
7040
+ /* @__PURE__ */ jsx21("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ jsx21("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ jsxs17(
6567
7041
  "div",
6568
7042
  {
6569
7043
  draggable: true,
@@ -6571,15 +7045,15 @@ function SymbolLibrary({
6571
7045
  style: styles.symbolCard,
6572
7046
  title: symbol.metadata?.description || symbol.name,
6573
7047
  children: [
6574
- /* @__PURE__ */ jsx20("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx20(
7048
+ /* @__PURE__ */ jsx21("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx21(
6575
7049
  "svg",
6576
7050
  {
6577
7051
  viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
6578
7052
  style: styles.symbolSvg,
6579
- children: /* @__PURE__ */ jsx20("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
7053
+ children: /* @__PURE__ */ jsx21("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
6580
7054
  }
6581
7055
  ) }),
6582
- /* @__PURE__ */ jsx20("div", { style: styles.symbolName, children: symbol.name })
7056
+ /* @__PURE__ */ jsx21("div", { style: styles.symbolName, children: symbol.name })
6583
7057
  ]
6584
7058
  },
6585
7059
  symbol.id
@@ -6688,7 +7162,7 @@ var styles = {
6688
7162
  };
6689
7163
 
6690
7164
  // src/components/NodeConfigPanel/NodeConfigPanel.tsx
6691
- import { Fragment as Fragment8, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
7165
+ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6692
7166
  function NodeConfigPanel({
6693
7167
  node,
6694
7168
  binding,
@@ -6707,15 +7181,15 @@ function NodeConfigPanel({
6707
7181
  padding: "20px",
6708
7182
  ...style
6709
7183
  };
6710
- return /* @__PURE__ */ jsxs17("div", { className, style: defaultStyle, children: [
6711
- /* @__PURE__ */ jsxs17("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
7184
+ return /* @__PURE__ */ jsxs18("div", { className, style: defaultStyle, children: [
7185
+ /* @__PURE__ */ jsxs18("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
6712
7186
  "Configure: ",
6713
7187
  node.id
6714
7188
  ] }),
6715
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
6716
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
6717
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
6718
- /* @__PURE__ */ jsx21(
7189
+ /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
7190
+ /* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
7191
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
7192
+ /* @__PURE__ */ jsx22(
6719
7193
  "input",
6720
7194
  {
6721
7195
  type: "text",
@@ -6731,10 +7205,10 @@ function NodeConfigPanel({
6731
7205
  }
6732
7206
  }
6733
7207
  ),
6734
- /* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6735
- /* @__PURE__ */ jsxs17("div", { children: [
6736
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
6737
- /* @__PURE__ */ jsx21(
7208
+ /* @__PURE__ */ jsxs18("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7209
+ /* @__PURE__ */ jsxs18("div", { children: [
7210
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
7211
+ /* @__PURE__ */ jsx22(
6738
7212
  "input",
6739
7213
  {
6740
7214
  type: "number",
@@ -6755,9 +7229,9 @@ function NodeConfigPanel({
6755
7229
  }
6756
7230
  )
6757
7231
  ] }),
6758
- /* @__PURE__ */ jsxs17("div", { children: [
6759
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
6760
- /* @__PURE__ */ jsx21(
7232
+ /* @__PURE__ */ jsxs18("div", { children: [
7233
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
7234
+ /* @__PURE__ */ jsx22(
6761
7235
  "input",
6762
7236
  {
6763
7237
  type: "number",
@@ -6779,9 +7253,9 @@ function NodeConfigPanel({
6779
7253
  )
6780
7254
  ] })
6781
7255
  ] }),
6782
- /* @__PURE__ */ jsxs17("div", { children: [
6783
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
6784
- /* @__PURE__ */ jsx21(
7256
+ /* @__PURE__ */ jsxs18("div", { children: [
7257
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
7258
+ /* @__PURE__ */ jsx22(
6785
7259
  "input",
6786
7260
  {
6787
7261
  type: "number",
@@ -6801,9 +7275,9 @@ function NodeConfigPanel({
6801
7275
  }
6802
7276
  )
6803
7277
  ] }),
6804
- /* @__PURE__ */ jsxs17("div", { children: [
6805
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
6806
- /* @__PURE__ */ jsx21(
7278
+ /* @__PURE__ */ jsxs18("div", { children: [
7279
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
7280
+ /* @__PURE__ */ jsx22(
6807
7281
  "input",
6808
7282
  {
6809
7283
  type: "number",
@@ -6828,9 +7302,9 @@ function NodeConfigPanel({
6828
7302
  )
6829
7303
  ] })
6830
7304
  ] }),
6831
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
6832
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
6833
- !binding ? /* @__PURE__ */ jsx21(
7305
+ /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
7306
+ /* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
7307
+ !binding ? /* @__PURE__ */ jsx22(
6834
7308
  "button",
6835
7309
  {
6836
7310
  onClick: () => {
@@ -6873,9 +7347,9 @@ function NodeConfigPanel({
6873
7347
  },
6874
7348
  children: "+ Add Telemetry"
6875
7349
  }
6876
- ) : /* @__PURE__ */ jsxs17(Fragment8, { children: [
6877
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
6878
- /* @__PURE__ */ jsx21(
7350
+ ) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
7351
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
7352
+ /* @__PURE__ */ jsx22(
6879
7353
  "input",
6880
7354
  {
6881
7355
  type: "number",
@@ -6897,8 +7371,8 @@ function NodeConfigPanel({
6897
7371
  }
6898
7372
  }
6899
7373
  ),
6900
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
6901
- /* @__PURE__ */ jsx21(
7374
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
7375
+ /* @__PURE__ */ jsx22(
6902
7376
  "input",
6903
7377
  {
6904
7378
  type: "text",
@@ -6920,8 +7394,8 @@ function NodeConfigPanel({
6920
7394
  }
6921
7395
  }
6922
7396
  ),
6923
- /* @__PURE__ */ jsxs17("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
6924
- /* @__PURE__ */ jsx21(
7397
+ /* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7398
+ /* @__PURE__ */ jsx22(
6925
7399
  "input",
6926
7400
  {
6927
7401
  type: "checkbox",
@@ -6943,8 +7417,8 @@ function NodeConfigPanel({
6943
7417
  ),
6944
7418
  "Show Sparkline"
6945
7419
  ] }),
6946
- /* @__PURE__ */ jsxs17("div", { style: { marginTop: "12px" }, children: [
6947
- /* @__PURE__ */ jsx21(
7420
+ /* @__PURE__ */ jsxs18("div", { style: { marginTop: "12px" }, children: [
7421
+ /* @__PURE__ */ jsx22(
6948
7422
  "label",
6949
7423
  {
6950
7424
  style: {
@@ -6956,10 +7430,10 @@ function NodeConfigPanel({
6956
7430
  children: "Telemetry Position Offset:"
6957
7431
  }
6958
7432
  ),
6959
- /* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6960
- /* @__PURE__ */ jsxs17("div", { children: [
6961
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
6962
- /* @__PURE__ */ jsx21(
7433
+ /* @__PURE__ */ jsxs18("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7434
+ /* @__PURE__ */ jsxs18("div", { children: [
7435
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
7436
+ /* @__PURE__ */ jsx22(
6963
7437
  "input",
6964
7438
  {
6965
7439
  type: "number",
@@ -6986,9 +7460,9 @@ function NodeConfigPanel({
6986
7460
  }
6987
7461
  )
6988
7462
  ] }),
6989
- /* @__PURE__ */ jsxs17("div", { children: [
6990
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
6991
- /* @__PURE__ */ jsx21(
7463
+ /* @__PURE__ */ jsxs18("div", { children: [
7464
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
7465
+ /* @__PURE__ */ jsx22(
6992
7466
  "input",
6993
7467
  {
6994
7468
  type: "number",
@@ -7016,8 +7490,8 @@ function NodeConfigPanel({
7016
7490
  )
7017
7491
  ] })
7018
7492
  ] }),
7019
- /* @__PURE__ */ jsxs17("div", { style: { marginTop: "16px" }, children: [
7020
- /* @__PURE__ */ jsx21(
7493
+ /* @__PURE__ */ jsxs18("div", { style: { marginTop: "16px" }, children: [
7494
+ /* @__PURE__ */ jsx22(
7021
7495
  "label",
7022
7496
  {
7023
7497
  style: {
@@ -7029,10 +7503,10 @@ function NodeConfigPanel({
7029
7503
  children: "Display Colors:"
7030
7504
  }
7031
7505
  ),
7032
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7033
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7034
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7035
- /* @__PURE__ */ jsx21(
7506
+ /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "8px" }, children: [
7507
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7508
+ /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7509
+ /* @__PURE__ */ jsx22(
7036
7510
  "input",
7037
7511
  {
7038
7512
  type: "color",
@@ -7058,7 +7532,7 @@ function NodeConfigPanel({
7058
7532
  }
7059
7533
  }
7060
7534
  ),
7061
- /* @__PURE__ */ jsx21(
7535
+ /* @__PURE__ */ jsx22(
7062
7536
  "input",
7063
7537
  {
7064
7538
  type: "text",
@@ -7088,10 +7562,10 @@ function NodeConfigPanel({
7088
7562
  )
7089
7563
  ] })
7090
7564
  ] }),
7091
- binding.display?.showSparkline && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7092
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7093
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7094
- /* @__PURE__ */ jsx21(
7565
+ binding.display?.showSparkline && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "8px" }, children: [
7566
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7567
+ /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7568
+ /* @__PURE__ */ jsx22(
7095
7569
  "input",
7096
7570
  {
7097
7571
  type: "color",
@@ -7117,7 +7591,7 @@ function NodeConfigPanel({
7117
7591
  }
7118
7592
  }
7119
7593
  ),
7120
- /* @__PURE__ */ jsx21(
7594
+ /* @__PURE__ */ jsx22(
7121
7595
  "input",
7122
7596
  {
7123
7597
  type: "text",
@@ -7147,9 +7621,9 @@ function NodeConfigPanel({
7147
7621
  )
7148
7622
  ] })
7149
7623
  ] }),
7150
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7151
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7152
- /* @__PURE__ */ jsx21(
7624
+ /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "8px" }, children: [
7625
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7626
+ /* @__PURE__ */ jsx22(
7153
7627
  "input",
7154
7628
  {
7155
7629
  type: "text",
@@ -7177,20 +7651,20 @@ function NodeConfigPanel({
7177
7651
  }
7178
7652
  }
7179
7653
  ),
7180
- /* @__PURE__ */ jsx21("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
7654
+ /* @__PURE__ */ jsx22("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
7181
7655
  ] })
7182
7656
  ] }),
7183
7657
  " "
7184
7658
  ] })
7185
7659
  ] })
7186
7660
  ] }),
7187
- binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
7188
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
7661
+ binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
7662
+ /* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
7189
7663
  ["highHigh", "high", "low", "lowLow"].map((key) => {
7190
7664
  const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
7191
- return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7192
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7193
- /* @__PURE__ */ jsx21(
7665
+ return /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "8px" }, children: [
7666
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7667
+ /* @__PURE__ */ jsx22(
7194
7668
  "input",
7195
7669
  {
7196
7670
  type: "number",
@@ -7214,8 +7688,8 @@ function NodeConfigPanel({
7214
7688
  ] }, key);
7215
7689
  })
7216
7690
  ] }),
7217
- binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
7218
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
7691
+ binding && /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "20px" }, children: [
7692
+ /* @__PURE__ */ jsx22("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
7219
7693
  ["normal", "warning", "alarm", "fault", "off"].map((status) => {
7220
7694
  const defaultColors = {
7221
7695
  normal: "#10b981",
@@ -7225,13 +7699,13 @@ function NodeConfigPanel({
7225
7699
  off: "#6b7280"
7226
7700
  };
7227
7701
  const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
7228
- return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7229
- /* @__PURE__ */ jsxs17("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7702
+ return /* @__PURE__ */ jsxs18("div", { style: { marginBottom: "8px" }, children: [
7703
+ /* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7230
7704
  label,
7231
7705
  ":"
7232
7706
  ] }),
7233
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7234
- /* @__PURE__ */ jsx21(
7707
+ /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7708
+ /* @__PURE__ */ jsx22(
7235
7709
  "input",
7236
7710
  {
7237
7711
  type: "color",
@@ -7252,7 +7726,7 @@ function NodeConfigPanel({
7252
7726
  }
7253
7727
  }
7254
7728
  ),
7255
- /* @__PURE__ */ jsx21(
7729
+ /* @__PURE__ */ jsx22(
7256
7730
  "input",
7257
7731
  {
7258
7732
  type: "text",
@@ -7279,7 +7753,7 @@ function NodeConfigPanel({
7279
7753
  ] }, status);
7280
7754
  })
7281
7755
  ] }),
7282
- /* @__PURE__ */ jsx21("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ jsx21(
7756
+ /* @__PURE__ */ jsx22("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ jsx22(
7283
7757
  "button",
7284
7758
  {
7285
7759
  onClick: onRemove,
@@ -7556,13 +8030,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
7556
8030
  }
7557
8031
 
7558
8032
  // src/hooks/useDeviceControls.ts
7559
- import { useState as useState15, useCallback as useCallback8, useRef as useRef6 } from "react";
8033
+ import { useState as useState16, useCallback as useCallback9, useRef as useRef7 } from "react";
7560
8034
  function commandKey(nodeId, kind, suffix) {
7561
8035
  return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
7562
8036
  }
7563
8037
  function useDeviceControls(initialBindings, options) {
7564
8038
  const { commandTimeoutMs } = options ?? {};
7565
- const [controls, setControls] = useState15(() => {
8039
+ const [controls, setControls] = useState16(() => {
7566
8040
  const map = /* @__PURE__ */ new Map();
7567
8041
  if (initialBindings) {
7568
8042
  initialBindings.forEach((binding) => {
@@ -7571,12 +8045,12 @@ function useDeviceControls(initialBindings, options) {
7571
8045
  }
7572
8046
  return map;
7573
8047
  });
7574
- const pendingRef = useRef6(/* @__PURE__ */ new Map());
7575
- const [pendingCommands, setPendingCommands] = useState15(() => /* @__PURE__ */ new Set());
7576
- const syncPending = useCallback8(() => {
8048
+ const pendingRef = useRef7(/* @__PURE__ */ new Map());
8049
+ const [pendingCommands, setPendingCommands] = useState16(() => /* @__PURE__ */ new Set());
8050
+ const syncPending = useCallback9(() => {
7577
8051
  setPendingCommands(new Set(pendingRef.current.keys()));
7578
8052
  }, []);
7579
- const updateControl = useCallback8((nodeId, updates) => {
8053
+ const updateControl = useCallback9((nodeId, updates) => {
7580
8054
  setControls((prev) => {
7581
8055
  const newMap = new Map(prev);
7582
8056
  const existing = newMap.get(nodeId);
@@ -7590,7 +8064,7 @@ function useDeviceControls(initialBindings, options) {
7590
8064
  return newMap;
7591
8065
  });
7592
8066
  }, []);
7593
- const updateControlBatch = useCallback8((updates) => {
8067
+ const updateControlBatch = useCallback9((updates) => {
7594
8068
  setControls((prev) => {
7595
8069
  const newMap = new Map(prev);
7596
8070
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7602,7 +8076,7 @@ function useDeviceControls(initialBindings, options) {
7602
8076
  return newMap;
7603
8077
  });
7604
8078
  }, []);
7605
- const updateDeviceState = useCallback8(
8079
+ const updateDeviceState = useCallback9(
7606
8080
  (nodeId, stateUpdates) => {
7607
8081
  setControls((prev) => {
7608
8082
  const newMap = new Map(prev);
@@ -7618,7 +8092,7 @@ function useDeviceControls(initialBindings, options) {
7618
8092
  },
7619
8093
  []
7620
8094
  );
7621
- const updateParameter = useCallback8(
8095
+ const updateParameter = useCallback9(
7622
8096
  (nodeId, parameterId, value) => {
7623
8097
  setControls((prev) => {
7624
8098
  const newMap = new Map(prev);
@@ -7645,27 +8119,27 @@ function useDeviceControls(initialBindings, options) {
7645
8119
  },
7646
8120
  []
7647
8121
  );
7648
- const setControlBinding = useCallback8((binding) => {
8122
+ const setControlBinding = useCallback9((binding) => {
7649
8123
  setControls((prev) => {
7650
8124
  const newMap = new Map(prev);
7651
8125
  newMap.set(binding.nodeId, binding);
7652
8126
  return newMap;
7653
8127
  });
7654
8128
  }, []);
7655
- const removeControlBinding = useCallback8((nodeId) => {
8129
+ const removeControlBinding = useCallback9((nodeId) => {
7656
8130
  setControls((prev) => {
7657
8131
  const newMap = new Map(prev);
7658
8132
  newMap.delete(nodeId);
7659
8133
  return newMap;
7660
8134
  });
7661
8135
  }, []);
7662
- const getControlBinding = useCallback8(
8136
+ const getControlBinding = useCallback9(
7663
8137
  (nodeId) => {
7664
8138
  return controls.get(nodeId);
7665
8139
  },
7666
8140
  [controls]
7667
8141
  );
7668
- const isCommandPending = useCallback8(
8142
+ const isCommandPending = useCallback9(
7669
8143
  (nodeId, kind) => {
7670
8144
  if (kind) {
7671
8145
  const prefix2 = `${nodeId}:${kind}`;
@@ -7682,7 +8156,7 @@ function useDeviceControls(initialBindings, options) {
7682
8156
  },
7683
8157
  [pendingCommands]
7684
8158
  );
7685
- const markPending = useCallback8(
8159
+ const markPending = useCallback9(
7686
8160
  (key, delta) => {
7687
8161
  const next = (pendingRef.current.get(key) ?? 0) + delta;
7688
8162
  if (next > 0) pendingRef.current.set(key, next);
@@ -7691,7 +8165,7 @@ function useDeviceControls(initialBindings, options) {
7691
8165
  },
7692
8166
  [syncPending]
7693
8167
  );
7694
- const runCommand = useCallback8(
8168
+ const runCommand = useCallback9(
7695
8169
  async (nodeId, key, invoke, messages) => {
7696
8170
  const binding = controls.get(nodeId);
7697
8171
  if (!binding) return;
@@ -7731,7 +8205,7 @@ function useDeviceControls(initialBindings, options) {
7731
8205
  },
7732
8206
  [controls, updateDeviceState, markPending, commandTimeoutMs]
7733
8207
  );
7734
- const sendModeChange = useCallback8(
8208
+ const sendModeChange = useCallback9(
7735
8209
  (nodeId, mode) => runCommand(
7736
8210
  nodeId,
7737
8211
  commandKey(nodeId, "mode"),
@@ -7740,7 +8214,7 @@ function useDeviceControls(initialBindings, options) {
7740
8214
  ),
7741
8215
  [runCommand]
7742
8216
  );
7743
- const sendParameterChange = useCallback8(
8217
+ const sendParameterChange = useCallback9(
7744
8218
  (nodeId, parameterId, value) => runCommand(
7745
8219
  nodeId,
7746
8220
  commandKey(nodeId, "parameter", parameterId),
@@ -7749,21 +8223,21 @@ function useDeviceControls(initialBindings, options) {
7749
8223
  ),
7750
8224
  [runCommand]
7751
8225
  );
7752
- const sendStartCommand = useCallback8(
8226
+ const sendStartCommand = useCallback9(
7753
8227
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
7754
8228
  success: "Start command sent",
7755
8229
  failure: "Start command failed"
7756
8230
  }),
7757
8231
  [runCommand]
7758
8232
  );
7759
- const sendStopCommand = useCallback8(
8233
+ const sendStopCommand = useCallback9(
7760
8234
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
7761
8235
  success: "Stop command sent",
7762
8236
  failure: "Stop command failed"
7763
8237
  }),
7764
8238
  [runCommand]
7765
8239
  );
7766
- const sendCustomAction = useCallback8(
8240
+ const sendCustomAction = useCallback9(
7767
8241
  (nodeId, actionId) => runCommand(
7768
8242
  nodeId,
7769
8243
  commandKey(nodeId, "action", actionId),
@@ -7816,9 +8290,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
7816
8290
  }
7817
8291
 
7818
8292
  // src/hooks/useDeviceConfigs.ts
7819
- import { useState as useState16, useCallback as useCallback9 } from "react";
8293
+ import { useState as useState17, useCallback as useCallback10 } from "react";
7820
8294
  function useDeviceConfigs(initialConfigs) {
7821
- const [configs, setConfigs] = useState16(() => {
8295
+ const [configs, setConfigs] = useState17(() => {
7822
8296
  const map = /* @__PURE__ */ new Map();
7823
8297
  if (initialConfigs) {
7824
8298
  initialConfigs.forEach((config) => {
@@ -7827,13 +8301,13 @@ function useDeviceConfigs(initialConfigs) {
7827
8301
  }
7828
8302
  return map;
7829
8303
  });
7830
- const getConfig = useCallback9(
8304
+ const getConfig = useCallback10(
7831
8305
  (nodeId) => {
7832
8306
  return configs.get(nodeId);
7833
8307
  },
7834
8308
  [configs]
7835
8309
  );
7836
- const updateConfig = useCallback9((nodeId, updates) => {
8310
+ const updateConfig = useCallback10((nodeId, updates) => {
7837
8311
  setConfigs((prev) => {
7838
8312
  const newMap = new Map(prev);
7839
8313
  const existing = newMap.get(nodeId);
@@ -7847,7 +8321,7 @@ function useDeviceConfigs(initialConfigs) {
7847
8321
  return newMap;
7848
8322
  });
7849
8323
  }, []);
7850
- const updateConfigState = useCallback9((nodeId, stateUpdates) => {
8324
+ const updateConfigState = useCallback10((nodeId, stateUpdates) => {
7851
8325
  setConfigs((prev) => {
7852
8326
  const newMap = new Map(prev);
7853
8327
  const existing = newMap.get(nodeId);
@@ -7860,7 +8334,7 @@ function useDeviceConfigs(initialConfigs) {
7860
8334
  return newMap;
7861
8335
  });
7862
8336
  }, []);
7863
- const updateConfigBatch = useCallback9((updates) => {
8337
+ const updateConfigBatch = useCallback10((updates) => {
7864
8338
  setConfigs((prev) => {
7865
8339
  const newMap = new Map(prev);
7866
8340
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7872,7 +8346,7 @@ function useDeviceConfigs(initialConfigs) {
7872
8346
  return newMap;
7873
8347
  });
7874
8348
  }, []);
7875
- const updateParameterValue = useCallback9((nodeId, parameterId, value) => {
8349
+ const updateParameterValue = useCallback10((nodeId, parameterId, value) => {
7876
8350
  setConfigs((prev) => {
7877
8351
  const newMap = new Map(prev);
7878
8352
  const existing = newMap.get(nodeId);
@@ -7889,7 +8363,7 @@ function useDeviceConfigs(initialConfigs) {
7889
8363
  return newMap;
7890
8364
  });
7891
8365
  }, []);
7892
- const applyConfig = useCallback9(
8366
+ const applyConfig = useCallback10(
7893
8367
  async (nodeId) => {
7894
8368
  const config = configs.get(nodeId);
7895
8369
  if (!config || !config.actions.onApply) {
@@ -7922,7 +8396,7 @@ function useDeviceConfigs(initialConfigs) {
7922
8396
  },
7923
8397
  [configs, updateConfigState]
7924
8398
  );
7925
- const saveConfig = useCallback9(
8399
+ const saveConfig = useCallback10(
7926
8400
  async (nodeId) => {
7927
8401
  const config = configs.get(nodeId);
7928
8402
  if (!config || !config.actions.onSave) {
@@ -7956,7 +8430,7 @@ function useDeviceConfigs(initialConfigs) {
7956
8430
  },
7957
8431
  [configs, updateConfigState]
7958
8432
  );
7959
- const resetConfig = useCallback9(
8433
+ const resetConfig = useCallback10(
7960
8434
  async (nodeId) => {
7961
8435
  const config = configs.get(nodeId);
7962
8436
  if (!config) {
@@ -7986,7 +8460,7 @@ function useDeviceConfigs(initialConfigs) {
7986
8460
  },
7987
8461
  [configs, updateConfig, updateConfigState]
7988
8462
  );
7989
- const cancelConfig = useCallback9(
8463
+ const cancelConfig = useCallback10(
7990
8464
  (nodeId) => {
7991
8465
  const config = configs.get(nodeId);
7992
8466
  if (config?.actions.onCancel) {
@@ -7995,7 +8469,7 @@ function useDeviceConfigs(initialConfigs) {
7995
8469
  },
7996
8470
  [configs]
7997
8471
  );
7998
- const validateConfig = useCallback9(
8472
+ const validateConfig = useCallback10(
7999
8473
  (nodeId) => {
8000
8474
  const config = configs.get(nodeId);
8001
8475
  if (!config) {
@@ -8037,21 +8511,21 @@ function useDeviceConfigs(initialConfigs) {
8037
8511
  },
8038
8512
  [configs, updateConfigState]
8039
8513
  );
8040
- const setConfig = useCallback9((config) => {
8514
+ const setConfig = useCallback10((config) => {
8041
8515
  setConfigs((prev) => {
8042
8516
  const newMap = new Map(prev);
8043
8517
  newMap.set(config.nodeId, config);
8044
8518
  return newMap;
8045
8519
  });
8046
8520
  }, []);
8047
- const removeConfig = useCallback9((nodeId) => {
8521
+ const removeConfig = useCallback10((nodeId) => {
8048
8522
  setConfigs((prev) => {
8049
8523
  const newMap = new Map(prev);
8050
8524
  newMap.delete(nodeId);
8051
8525
  return newMap;
8052
8526
  });
8053
8527
  }, []);
8054
- const clearConfigs = useCallback9(() => {
8528
+ const clearConfigs = useCallback10(() => {
8055
8529
  setConfigs(/* @__PURE__ */ new Map());
8056
8530
  }, []);
8057
8531
  return {
@@ -8073,8 +8547,8 @@ function useDeviceConfigs(initialConfigs) {
8073
8547
  }
8074
8548
 
8075
8549
  // src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
8076
- import { useState as useState17, useEffect as useEffect12, useMemo, useRef as useRef7 } from "react";
8077
- import { Fragment as Fragment9, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
8550
+ import { useState as useState18, useEffect as useEffect13, useMemo, useRef as useRef8 } from "react";
8551
+ import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
8078
8552
  function DeviceConfigPanel({
8079
8553
  binding,
8080
8554
  onClose,
@@ -8092,7 +8566,7 @@ function DeviceConfigPanel({
8092
8566
  showControlsButton = true,
8093
8567
  embedded = false
8094
8568
  }) {
8095
- const [localValues, setLocalValues] = useState17(() => {
8569
+ const [localValues, setLocalValues] = useState18(() => {
8096
8570
  if (binding) {
8097
8571
  const values = {};
8098
8572
  binding.parameters.forEach((param) => {
@@ -8102,7 +8576,7 @@ function DeviceConfigPanel({
8102
8576
  }
8103
8577
  return {};
8104
8578
  });
8105
- const [collapsedSections, setCollapsedSections] = useState17(() => {
8579
+ const [collapsedSections, setCollapsedSections] = useState18(() => {
8106
8580
  const collapsed = /* @__PURE__ */ new Set();
8107
8581
  if (binding?.sections) {
8108
8582
  binding.sections.forEach((section) => {
@@ -8113,9 +8587,9 @@ function DeviceConfigPanel({
8113
8587
  }
8114
8588
  return collapsed;
8115
8589
  });
8116
- const [showToast, setShowToast] = useState17(true);
8117
- const [bindingId, setBindingId] = useState17(binding?.nodeId || null);
8118
- const lastResultTimestampRef = useRef7(0);
8590
+ const [showToast, setShowToast] = useState18(true);
8591
+ const [bindingId, setBindingId] = useState18(binding?.nodeId || null);
8592
+ const lastResultTimestampRef = useRef8(0);
8119
8593
  if (binding && binding.nodeId !== bindingId) {
8120
8594
  const values = {};
8121
8595
  binding.parameters.forEach((param) => {
@@ -8131,7 +8605,7 @@ function DeviceConfigPanel({
8131
8605
  setCollapsedSections(collapsed);
8132
8606
  setBindingId(binding.nodeId);
8133
8607
  }
8134
- useEffect12(() => {
8608
+ useEffect13(() => {
8135
8609
  const currentTimestamp = binding?.state.lastSaved || 0;
8136
8610
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8137
8611
  lastResultTimestampRef.current = currentTimestamp;
@@ -8236,14 +8710,14 @@ function DeviceConfigPanel({
8236
8710
  const value = localValues[param.id];
8237
8711
  const error = binding.state.errors?.[param.id];
8238
8712
  const isDisabled = param.readOnly || param.enabled === false;
8239
- return /* @__PURE__ */ jsxs18(
8713
+ return /* @__PURE__ */ jsxs19(
8240
8714
  "div",
8241
8715
  {
8242
8716
  style: {
8243
8717
  marginBottom: spacing.marginBottom
8244
8718
  },
8245
8719
  children: [
8246
- /* @__PURE__ */ jsxs18(
8720
+ /* @__PURE__ */ jsxs19(
8247
8721
  "label",
8248
8722
  {
8249
8723
  style: {
@@ -8258,8 +8732,8 @@ function DeviceConfigPanel({
8258
8732
  },
8259
8733
  children: [
8260
8734
  param.label,
8261
- param.required && /* @__PURE__ */ jsx22("span", { style: { color: errorColor }, children: " *" }),
8262
- param.unit && /* @__PURE__ */ jsxs18("span", { style: { color: mutedTextColor, fontWeight: "normal" }, children: [
8735
+ param.required && /* @__PURE__ */ jsx23("span", { style: { color: errorColor }, children: " *" }),
8736
+ param.unit && /* @__PURE__ */ jsxs19("span", { style: { color: mutedTextColor, fontWeight: "normal" }, children: [
8263
8737
  " (",
8264
8738
  param.unit,
8265
8739
  ")"
@@ -8267,7 +8741,7 @@ function DeviceConfigPanel({
8267
8741
  ]
8268
8742
  }
8269
8743
  ),
8270
- param.description && /* @__PURE__ */ jsx22(
8744
+ param.description && /* @__PURE__ */ jsx23(
8271
8745
  "div",
8272
8746
  {
8273
8747
  style: {
@@ -8279,7 +8753,7 @@ function DeviceConfigPanel({
8279
8753
  children: param.description
8280
8754
  }
8281
8755
  ),
8282
- param.type === "number" && /* @__PURE__ */ jsx22(
8756
+ param.type === "number" && /* @__PURE__ */ jsx23(
8283
8757
  "input",
8284
8758
  {
8285
8759
  type: "number",
@@ -8303,7 +8777,7 @@ function DeviceConfigPanel({
8303
8777
  }
8304
8778
  }
8305
8779
  ),
8306
- param.type === "string" && /* @__PURE__ */ jsx22(
8780
+ param.type === "string" && /* @__PURE__ */ jsx23(
8307
8781
  "input",
8308
8782
  {
8309
8783
  type: "text",
@@ -8324,7 +8798,7 @@ function DeviceConfigPanel({
8324
8798
  }
8325
8799
  }
8326
8800
  ),
8327
- param.type === "boolean" && /* @__PURE__ */ jsxs18(
8801
+ param.type === "boolean" && /* @__PURE__ */ jsxs19(
8328
8802
  "label",
8329
8803
  {
8330
8804
  style: {
@@ -8334,7 +8808,7 @@ function DeviceConfigPanel({
8334
8808
  cursor: isDisabled ? "not-allowed" : "pointer"
8335
8809
  },
8336
8810
  children: [
8337
- /* @__PURE__ */ jsx22(
8811
+ /* @__PURE__ */ jsx23(
8338
8812
  "input",
8339
8813
  {
8340
8814
  type: "checkbox",
@@ -8348,11 +8822,11 @@ function DeviceConfigPanel({
8348
8822
  }
8349
8823
  }
8350
8824
  ),
8351
- /* @__PURE__ */ jsx22("span", { style: { fontSize: `${fontSize.value}px`, color: textColor }, children: value ? "Enabled" : "Disabled" })
8825
+ /* @__PURE__ */ jsx23("span", { style: { fontSize: `${fontSize.value}px`, color: textColor }, children: value ? "Enabled" : "Disabled" })
8352
8826
  ]
8353
8827
  }
8354
8828
  ),
8355
- param.type === "select" && /* @__PURE__ */ jsx22(
8829
+ param.type === "select" && /* @__PURE__ */ jsx23(
8356
8830
  "select",
8357
8831
  {
8358
8832
  value: value ?? "",
@@ -8370,10 +8844,10 @@ function DeviceConfigPanel({
8370
8844
  borderRadius: "2px",
8371
8845
  outline: "none"
8372
8846
  },
8373
- children: param.options?.map((option) => /* @__PURE__ */ jsx22("option", { value: option.value, children: option.label }, option.value))
8847
+ children: param.options?.map((option) => /* @__PURE__ */ jsx23("option", { value: option.value, children: option.label }, option.value))
8374
8848
  }
8375
8849
  ),
8376
- error && /* @__PURE__ */ jsx22(
8850
+ error && /* @__PURE__ */ jsx23(
8377
8851
  "div",
8378
8852
  {
8379
8853
  style: {
@@ -8393,7 +8867,7 @@ function DeviceConfigPanel({
8393
8867
  const renderSection = (section) => {
8394
8868
  const params = parametersBySection[section.id] || [];
8395
8869
  const isCollapsed = collapsedSections.has(section.id);
8396
- return /* @__PURE__ */ jsxs18(
8870
+ return /* @__PURE__ */ jsxs19(
8397
8871
  "div",
8398
8872
  {
8399
8873
  style: {
@@ -8403,7 +8877,7 @@ function DeviceConfigPanel({
8403
8877
  backgroundColor: surfaceColor
8404
8878
  },
8405
8879
  children: [
8406
- /* @__PURE__ */ jsxs18(
8880
+ /* @__PURE__ */ jsxs19(
8407
8881
  "div",
8408
8882
  {
8409
8883
  onClick: () => section.collapsible && toggleSection(section.id),
@@ -8416,8 +8890,8 @@ function DeviceConfigPanel({
8416
8890
  alignItems: "center"
8417
8891
  },
8418
8892
  children: [
8419
- /* @__PURE__ */ jsxs18("div", { children: [
8420
- /* @__PURE__ */ jsxs18(
8893
+ /* @__PURE__ */ jsxs19("div", { children: [
8894
+ /* @__PURE__ */ jsxs19(
8421
8895
  "div",
8422
8896
  {
8423
8897
  style: {
@@ -8429,12 +8903,12 @@ function DeviceConfigPanel({
8429
8903
  letterSpacing: "0.5px"
8430
8904
  },
8431
8905
  children: [
8432
- section.icon && /* @__PURE__ */ jsx22("span", { style: { marginRight: "8px" }, children: section.icon }),
8906
+ section.icon && /* @__PURE__ */ jsx23("span", { style: { marginRight: "8px" }, children: section.icon }),
8433
8907
  section.title
8434
8908
  ]
8435
8909
  }
8436
8910
  ),
8437
- section.description && /* @__PURE__ */ jsx22(
8911
+ section.description && /* @__PURE__ */ jsx23(
8438
8912
  "div",
8439
8913
  {
8440
8914
  style: {
@@ -8447,11 +8921,11 @@ function DeviceConfigPanel({
8447
8921
  }
8448
8922
  )
8449
8923
  ] }),
8450
- section.collapsible && /* @__PURE__ */ jsx22("span", { style: { fontSize: "16px", color: mutedTextColor }, children: isCollapsed ? "\u25BC" : "\u25B2" })
8924
+ section.collapsible && /* @__PURE__ */ jsx23("span", { style: { fontSize: "16px", color: mutedTextColor }, children: isCollapsed ? "\u25BC" : "\u25B2" })
8451
8925
  ]
8452
8926
  }
8453
8927
  ),
8454
- !isCollapsed && /* @__PURE__ */ jsx22("div", { style: { padding: spacing.padding }, children: params.map(renderParameter) })
8928
+ !isCollapsed && /* @__PURE__ */ jsx23("div", { style: { padding: spacing.padding }, children: params.map(renderParameter) })
8455
8929
  ]
8456
8930
  },
8457
8931
  section.id
@@ -8510,9 +8984,9 @@ function DeviceConfigPanel({
8510
8984
  const showSave = binding.display?.showSave !== false && binding.actions.onSave;
8511
8985
  const showReset = binding.display?.showReset !== false && binding.actions.onReset;
8512
8986
  const showCancel = binding.display?.showCancel !== false;
8513
- return /* @__PURE__ */ jsxs18(Fragment9, { children: [
8514
- /* @__PURE__ */ jsxs18("div", { style: panelStyle, className: binding.display?.className, children: [
8515
- /* @__PURE__ */ jsxs18(
8987
+ return /* @__PURE__ */ jsxs19(Fragment9, { children: [
8988
+ /* @__PURE__ */ jsxs19("div", { style: panelStyle, className: binding.display?.className, children: [
8989
+ /* @__PURE__ */ jsxs19(
8516
8990
  "div",
8517
8991
  {
8518
8992
  style: {
@@ -8524,8 +8998,8 @@ function DeviceConfigPanel({
8524
8998
  borderBottom: `2px solid ${borderColor}`
8525
8999
  },
8526
9000
  children: [
8527
- /* @__PURE__ */ jsxs18("div", { children: [
8528
- /* @__PURE__ */ jsx22(
9001
+ /* @__PURE__ */ jsxs19("div", { children: [
9002
+ /* @__PURE__ */ jsx23(
8529
9003
  "h3",
8530
9004
  {
8531
9005
  style: {
@@ -8545,7 +9019,7 @@ function DeviceConfigPanel({
8545
9019
  children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
8546
9020
  }
8547
9021
  ),
8548
- binding.display?.subtitle && /* @__PURE__ */ jsx22(
9022
+ binding.display?.subtitle && /* @__PURE__ */ jsx23(
8549
9023
  "div",
8550
9024
  {
8551
9025
  style: {
@@ -8558,8 +9032,8 @@ function DeviceConfigPanel({
8558
9032
  }
8559
9033
  )
8560
9034
  ] }),
8561
- /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px" }, children: [
8562
- showControlsButton && onOpenControls && /* @__PURE__ */ jsx22(
9035
+ /* @__PURE__ */ jsxs19("div", { style: { display: "flex", gap: "8px" }, children: [
9036
+ showControlsButton && onOpenControls && /* @__PURE__ */ jsx23(
8563
9037
  "button",
8564
9038
  {
8565
9039
  onClick: onOpenControls,
@@ -8582,7 +9056,7 @@ function DeviceConfigPanel({
8582
9056
  children: "CTRL"
8583
9057
  }
8584
9058
  ),
8585
- onUndock && /* @__PURE__ */ jsx22(
9059
+ onUndock && /* @__PURE__ */ jsx23(
8586
9060
  "button",
8587
9061
  {
8588
9062
  onClick: onUndock,
@@ -8603,7 +9077,7 @@ function DeviceConfigPanel({
8603
9077
  children: undockIcon
8604
9078
  }
8605
9079
  ),
8606
- /* @__PURE__ */ jsx22(
9080
+ /* @__PURE__ */ jsx23(
8607
9081
  "button",
8608
9082
  {
8609
9083
  onClick: onClose,
@@ -8626,7 +9100,7 @@ function DeviceConfigPanel({
8626
9100
  ]
8627
9101
  }
8628
9102
  ),
8629
- binding.state.isDirty && /* @__PURE__ */ jsx22(
9103
+ binding.state.isDirty && /* @__PURE__ */ jsx23(
8630
9104
  "div",
8631
9105
  {
8632
9106
  style: {
@@ -8641,11 +9115,11 @@ function DeviceConfigPanel({
8641
9115
  children: "Unsaved changes"
8642
9116
  }
8643
9117
  ),
8644
- /* @__PURE__ */ jsx22("div", { style: { flex: 1, overflowY: "auto", marginBottom: spacing.marginBottom }, children: sortedSections.length > 0 ? sortedSections.map(renderSection) : (
9118
+ /* @__PURE__ */ jsx23("div", { style: { flex: 1, overflowY: "auto", marginBottom: spacing.marginBottom }, children: sortedSections.length > 0 ? sortedSections.map(renderSection) : (
8645
9119
  /* Render unsectioned parameters */
8646
- /* @__PURE__ */ jsx22("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
9120
+ /* @__PURE__ */ jsx23("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
8647
9121
  ) }),
8648
- /* @__PURE__ */ jsxs18(
9122
+ /* @__PURE__ */ jsxs19(
8649
9123
  "div",
8650
9124
  {
8651
9125
  style: {
@@ -8656,7 +9130,7 @@ function DeviceConfigPanel({
8656
9130
  flexWrap: "wrap"
8657
9131
  },
8658
9132
  children: [
8659
- showApply && /* @__PURE__ */ jsx22(
9133
+ showApply && /* @__PURE__ */ jsx23(
8660
9134
  "button",
8661
9135
  {
8662
9136
  onClick: handleApply,
@@ -8679,7 +9153,7 @@ function DeviceConfigPanel({
8679
9153
  children: binding.state.isSaving ? "Applying..." : "Apply"
8680
9154
  }
8681
9155
  ),
8682
- showSave && /* @__PURE__ */ jsx22(
9156
+ showSave && /* @__PURE__ */ jsx23(
8683
9157
  "button",
8684
9158
  {
8685
9159
  onClick: handleSave,
@@ -8702,7 +9176,7 @@ function DeviceConfigPanel({
8702
9176
  children: binding.state.isSaving ? "Saving..." : "Save"
8703
9177
  }
8704
9178
  ),
8705
- showReset && /* @__PURE__ */ jsx22(
9179
+ showReset && /* @__PURE__ */ jsx23(
8706
9180
  "button",
8707
9181
  {
8708
9182
  onClick: handleReset,
@@ -8725,7 +9199,7 @@ function DeviceConfigPanel({
8725
9199
  children: "Reset"
8726
9200
  }
8727
9201
  ),
8728
- showCancel && /* @__PURE__ */ jsx22(
9202
+ showCancel && /* @__PURE__ */ jsx23(
8729
9203
  "button",
8730
9204
  {
8731
9205
  onClick: handleCancel,
@@ -8752,7 +9226,7 @@ function DeviceConfigPanel({
8752
9226
  }
8753
9227
  )
8754
9228
  ] }),
8755
- binding.state.lastSaveResult && showToast && /* @__PURE__ */ jsx22(
9229
+ binding.state.lastSaveResult && showToast && /* @__PURE__ */ jsx23(
8756
9230
  "div",
8757
9231
  {
8758
9232
  style: {
@@ -8776,7 +9250,7 @@ function DeviceConfigPanel({
8776
9250
  }
8777
9251
 
8778
9252
  // src/diagram/hooks/useSimulation.ts
8779
- import { useEffect as useEffect13 } from "react";
9253
+ import { useEffect as useEffect14 } from "react";
8780
9254
  function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8781
9255
  const {
8782
9256
  interval = 2e3,
@@ -8787,7 +9261,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8787
9261
  historyLength = 10,
8788
9262
  generateValue
8789
9263
  } = options;
8790
- useEffect13(() => {
9264
+ useEffect14(() => {
8791
9265
  if (!enabled) return;
8792
9266
  const intervalId = setInterval(() => {
8793
9267
  const updates = [];
@@ -8859,6 +9333,7 @@ export {
8859
9333
  LegacyValueEntry,
8860
9334
  NodeConfigPanel,
8861
9335
  NodeControlsPanel,
9336
+ NumpadDialog,
8862
9337
  PIDCanvas,
8863
9338
  PanelContent,
8864
9339
  PanelTabs,