@procaaso/alphinity-ui-components 1.4.0 → 1.7.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
@@ -1840,14 +1840,457 @@ function DeviceControlPanel({
1840
1840
  ] });
1841
1841
  }
1842
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
+
1843
2286
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
1844
- import React6 from "react";
2287
+ import React7 from "react";
1845
2288
  import { Tab } from "@mui/material";
1846
2289
 
1847
2290
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
1848
2291
  import { Box, IconButton, Tabs } from "@mui/material";
1849
2292
  import styled from "@emotion/styled";
1850
- import { jsx as jsx9 } from "react/jsx-runtime";
2293
+ import { jsx as jsx10 } from "react/jsx-runtime";
1851
2294
  var FullscreenContainer = styled(Box)(
1852
2295
  ({ leftCollapsed, rightCollapsed }) => {
1853
2296
  const getGridTemplateAreas = () => {
@@ -1972,7 +2415,7 @@ var DisplayModeToggle = styled(IconButton)(({ mode }) => ({
1972
2415
  transform: "translateX(-50%) scale(1.05)"
1973
2416
  }
1974
2417
  }));
1975
- var ChevronLeft = () => /* @__PURE__ */ jsx9(
2418
+ var ChevronLeft = () => /* @__PURE__ */ jsx10(
1976
2419
  "div",
1977
2420
  {
1978
2421
  style: {
@@ -1984,7 +2427,7 @@ var ChevronLeft = () => /* @__PURE__ */ jsx9(
1984
2427
  }
1985
2428
  }
1986
2429
  );
1987
- var ChevronRight = () => /* @__PURE__ */ jsx9(
2430
+ var ChevronRight = () => /* @__PURE__ */ jsx10(
1988
2431
  "div",
1989
2432
  {
1990
2433
  style: {
@@ -2095,10 +2538,10 @@ var ScrollableSVGWrapper = styled("div")({
2095
2538
  });
2096
2539
 
2097
2540
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
2098
- import { useEffect as useEffect3, useState as useState6 } from "react";
2541
+ import { useEffect as useEffect4, useState as useState7 } from "react";
2099
2542
  import { Box as Box2 } from "@mui/material";
2100
2543
  import styled2 from "@emotion/styled";
2101
- import { jsx as jsx10 } from "react/jsx-runtime";
2544
+ import { jsx as jsx11 } from "react/jsx-runtime";
2102
2545
  var baseOverlayStyles = {
2103
2546
  tank: {
2104
2547
  background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
@@ -2160,8 +2603,8 @@ var SVGLockedOverlay = ({
2160
2603
  onClick,
2161
2604
  containerSelector = ".tff-svg-container"
2162
2605
  }) => {
2163
- const [svgOffset, setSvgOffset] = useState6({ x: 0, y: 0 });
2164
- useEffect3(() => {
2606
+ const [svgOffset, setSvgOffset] = useState7({ x: 0, y: 0 });
2607
+ useEffect4(() => {
2165
2608
  const updateSvgOffset = () => {
2166
2609
  const containerElement = document.querySelector(containerSelector);
2167
2610
  const svgElement = containerElement?.querySelector("svg");
@@ -2181,7 +2624,7 @@ var SVGLockedOverlay = ({
2181
2624
  const pixelX = svgX + svgOffset.x;
2182
2625
  const pixelY = svgY + svgOffset.y;
2183
2626
  const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
2184
- return /* @__PURE__ */ jsx10(
2627
+ return /* @__PURE__ */ jsx11(
2185
2628
  Box2,
2186
2629
  {
2187
2630
  className: `svg-locked-overlay ${className}`.trim(),
@@ -2245,7 +2688,7 @@ var CardUnit = styled2("div")({
2245
2688
  });
2246
2689
 
2247
2690
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
2248
- 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";
2249
2692
  var TrendLine = ({
2250
2693
  values,
2251
2694
  width = 60,
@@ -2255,7 +2698,7 @@ var TrendLine = ({
2255
2698
  backgroundColor = "rgba(255, 255, 255, 0.1)"
2256
2699
  }) => {
2257
2700
  if (!values || values.length < 2) {
2258
- return /* @__PURE__ */ jsx11(
2701
+ return /* @__PURE__ */ jsx12(
2259
2702
  "div",
2260
2703
  {
2261
2704
  style: {
@@ -2267,7 +2710,7 @@ var TrendLine = ({
2267
2710
  alignItems: "center",
2268
2711
  justifyContent: "center"
2269
2712
  },
2270
- 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" })
2271
2714
  }
2272
2715
  );
2273
2716
  }
@@ -2279,7 +2722,7 @@ var TrendLine = ({
2279
2722
  const x = 4 + i / (values.length - 1) * (width - 8);
2280
2723
  return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
2281
2724
  }).join(" ");
2282
- return /* @__PURE__ */ jsx11(
2725
+ return /* @__PURE__ */ jsx12(
2283
2726
  "div",
2284
2727
  {
2285
2728
  style: {
@@ -2290,8 +2733,8 @@ var TrendLine = ({
2290
2733
  position: "relative",
2291
2734
  overflow: "hidden"
2292
2735
  },
2293
- children: /* @__PURE__ */ jsxs8("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2294
- /* @__PURE__ */ jsx11(
2736
+ children: /* @__PURE__ */ jsxs9("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2737
+ /* @__PURE__ */ jsx12(
2295
2738
  "path",
2296
2739
  {
2297
2740
  d: pathData,
@@ -2302,7 +2745,7 @@ var TrendLine = ({
2302
2745
  strokeLinejoin: "round"
2303
2746
  }
2304
2747
  ),
2305
- /* @__PURE__ */ jsx11(
2748
+ /* @__PURE__ */ jsx12(
2306
2749
  "circle",
2307
2750
  {
2308
2751
  cx: 4 + (width - 8),
@@ -2340,7 +2783,7 @@ var CircularGauge = ({
2340
2783
  const borderColor = isHex ? hexToRgba(color, 0.9) : color;
2341
2784
  const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
2342
2785
  const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
2343
- return /* @__PURE__ */ jsxs8(
2786
+ return /* @__PURE__ */ jsxs9(
2344
2787
  "div",
2345
2788
  {
2346
2789
  style: {
@@ -2349,7 +2792,7 @@ var CircularGauge = ({
2349
2792
  alignItems: "center"
2350
2793
  },
2351
2794
  children: [
2352
- /* @__PURE__ */ jsxs8(
2795
+ /* @__PURE__ */ jsxs9(
2353
2796
  "div",
2354
2797
  {
2355
2798
  style: {
@@ -2361,8 +2804,8 @@ var CircularGauge = ({
2361
2804
  border: `1px solid ${borderStrokeColor}`
2362
2805
  },
2363
2806
  children: [
2364
- /* @__PURE__ */ jsxs8("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2365
- /* @__PURE__ */ jsx11(
2807
+ /* @__PURE__ */ jsxs9("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2808
+ /* @__PURE__ */ jsx12(
2366
2809
  "circle",
2367
2810
  {
2368
2811
  cx: size / 2,
@@ -2373,7 +2816,7 @@ var CircularGauge = ({
2373
2816
  strokeWidth: 1
2374
2817
  }
2375
2818
  ),
2376
- /* @__PURE__ */ jsx11(
2819
+ /* @__PURE__ */ jsx12(
2377
2820
  "circle",
2378
2821
  {
2379
2822
  cx: size / 2,
@@ -2384,7 +2827,7 @@ var CircularGauge = ({
2384
2827
  fill: "transparent"
2385
2828
  }
2386
2829
  ),
2387
- /* @__PURE__ */ jsx11(
2830
+ /* @__PURE__ */ jsx12(
2388
2831
  "circle",
2389
2832
  {
2390
2833
  cx: size / 2,
@@ -2400,7 +2843,7 @@ var CircularGauge = ({
2400
2843
  }
2401
2844
  )
2402
2845
  ] }),
2403
- /* @__PURE__ */ jsxs8(
2846
+ /* @__PURE__ */ jsxs9(
2404
2847
  "div",
2405
2848
  {
2406
2849
  style: {
@@ -2416,14 +2859,14 @@ var CircularGauge = ({
2416
2859
  },
2417
2860
  children: [
2418
2861
  value.toFixed(1),
2419
- /* @__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 })
2420
2863
  ]
2421
2864
  }
2422
2865
  )
2423
2866
  ]
2424
2867
  }
2425
2868
  ),
2426
- /* @__PURE__ */ jsx11(
2869
+ /* @__PURE__ */ jsx12(
2427
2870
  "div",
2428
2871
  {
2429
2872
  style: {
@@ -2454,7 +2897,7 @@ var Sparkline = ({ data, width, height, color }) => {
2454
2897
  const y = height - 8 - (value - min) / range * (height - 8);
2455
2898
  return `${x + 4},${y + 4}`;
2456
2899
  }).join(" ");
2457
- return /* @__PURE__ */ jsx11(
2900
+ return /* @__PURE__ */ jsx12(
2458
2901
  "div",
2459
2902
  {
2460
2903
  style: {
@@ -2468,7 +2911,7 @@ var Sparkline = ({ data, width, height, color }) => {
2468
2911
  justifyContent: "center",
2469
2912
  boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
2470
2913
  },
2471
- 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" }) })
2472
2915
  }
2473
2916
  );
2474
2917
  };
@@ -2482,8 +2925,8 @@ var EquipmentIndicatorWithSparkline = ({
2482
2925
  sparklineOffset = { x: 40, y: 0 }
2483
2926
  }) => {
2484
2927
  const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
2485
- return /* @__PURE__ */ jsxs8(Fragment3, { children: [
2486
- /* @__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(
2487
2930
  "div",
2488
2931
  {
2489
2932
  style: {
@@ -2504,7 +2947,7 @@ var EquipmentIndicatorWithSparkline = ({
2504
2947
  children: label
2505
2948
  }
2506
2949
  ) }),
2507
- 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 }) })
2508
2951
  ] });
2509
2952
  };
2510
2953
  var EquipmentIndicator = ({
@@ -2517,7 +2960,7 @@ var EquipmentIndicator = ({
2517
2960
  className
2518
2961
  }) => {
2519
2962
  const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
2520
- 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(
2521
2964
  "div",
2522
2965
  {
2523
2966
  style: {
@@ -2541,7 +2984,7 @@ var EquipmentIndicator = ({
2541
2984
  };
2542
2985
 
2543
2986
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
2544
- 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";
2545
2988
  function FullscreenWorkspace({
2546
2989
  svgContent,
2547
2990
  overlays,
@@ -2569,10 +3012,10 @@ function FullscreenWorkspace({
2569
3012
  className = "",
2570
3013
  ...rest
2571
3014
  }) {
2572
- const [leftCollapsedState, setLeftCollapsedState] = React6.useState(defaultLeftCollapsed);
2573
- const [rightCollapsedState, setRightCollapsedState] = React6.useState(defaultRightCollapsed);
2574
- const [internalDisplayMode, setInternalDisplayMode] = React6.useState(displayMode ?? defaultDisplayMode);
2575
- 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(
2576
3019
  tabs && tabs.length > 0 ? tabs[0].value : ""
2577
3020
  );
2578
3021
  const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
@@ -2580,10 +3023,10 @@ function FullscreenWorkspace({
2580
3023
  const isDisplayModeControlled = displayMode !== void 0;
2581
3024
  const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
2582
3025
  const isTabControlled = activeTab !== void 0 && activeTab !== null;
2583
- const resolvedTabs = React6.useMemo(() => tabs ?? [], [tabs]);
3026
+ const resolvedTabs = React7.useMemo(() => tabs ?? [], [tabs]);
2584
3027
  const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
2585
3028
  const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
2586
- React6.useEffect(() => {
3029
+ React7.useEffect(() => {
2587
3030
  if (resolvedTabs.length > 0) {
2588
3031
  const values = resolvedTabs.map((tab) => tab.value);
2589
3032
  if (!values.includes(currentTab)) {
@@ -2592,7 +3035,7 @@ function FullscreenWorkspace({
2592
3035
  }
2593
3036
  }
2594
3037
  }, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
2595
- React6.useEffect(() => {
3038
+ React7.useEffect(() => {
2596
3039
  if (displayMode !== void 0) {
2597
3040
  setInternalDisplayMode(displayMode);
2598
3041
  }
@@ -2627,7 +3070,7 @@ function FullscreenWorkspace({
2627
3070
  const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
2628
3071
  const showLeftToggle = Boolean(leftPanel);
2629
3072
  const showRightToggle = Boolean(rightPanel);
2630
- return /* @__PURE__ */ jsxs9(
3073
+ return /* @__PURE__ */ jsxs10(
2631
3074
  FullscreenContainer,
2632
3075
  {
2633
3076
  leftCollapsed,
@@ -2635,25 +3078,25 @@ function FullscreenWorkspace({
2635
3078
  className: `tff-svg-container ${className}`.trim(),
2636
3079
  ...rest,
2637
3080
  children: [
2638
- showLeftToggle && /* @__PURE__ */ jsx12(
3081
+ showLeftToggle && /* @__PURE__ */ jsx13(
2639
3082
  LeftToggleButton,
2640
3083
  {
2641
3084
  collapsed: leftCollapsed,
2642
3085
  onClick: handleLeftToggle,
2643
3086
  "aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
2644
- children: leftCollapsed ? /* @__PURE__ */ jsx12(ChevronRight, {}) : /* @__PURE__ */ jsx12(ChevronLeft, {})
3087
+ children: leftCollapsed ? /* @__PURE__ */ jsx13(ChevronRight, {}) : /* @__PURE__ */ jsx13(ChevronLeft, {})
2645
3088
  }
2646
3089
  ),
2647
- showRightToggle && /* @__PURE__ */ jsx12(
3090
+ showRightToggle && /* @__PURE__ */ jsx13(
2648
3091
  RightToggleButton,
2649
3092
  {
2650
3093
  collapsed: rightCollapsed,
2651
3094
  onClick: handleRightToggle,
2652
3095
  "aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
2653
- children: rightCollapsed ? /* @__PURE__ */ jsx12(ChevronLeft, {}) : /* @__PURE__ */ jsx12(ChevronRight, {})
3096
+ children: rightCollapsed ? /* @__PURE__ */ jsx13(ChevronLeft, {}) : /* @__PURE__ */ jsx13(ChevronRight, {})
2654
3097
  }
2655
3098
  ),
2656
- showDisplayModeToggle && /* @__PURE__ */ jsx12(
3099
+ showDisplayModeToggle && /* @__PURE__ */ jsx13(
2657
3100
  DisplayModeToggle,
2658
3101
  {
2659
3102
  mode: currentDisplayMode,
@@ -2662,9 +3105,9 @@ function FullscreenWorkspace({
2662
3105
  children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
2663
3106
  }
2664
3107
  ),
2665
- /* @__PURE__ */ jsxs9(SVGArea, { children: [
2666
- showZoomControls && /* @__PURE__ */ jsxs9(ZoomControls, { children: [
2667
- /* @__PURE__ */ jsx12(
3108
+ /* @__PURE__ */ jsxs10(SVGArea, { children: [
3109
+ showZoomControls && /* @__PURE__ */ jsxs10(ZoomControls, { children: [
3110
+ /* @__PURE__ */ jsx13(
2668
3111
  ZoomButton,
2669
3112
  {
2670
3113
  onClick: onZoomIn,
@@ -2674,7 +3117,7 @@ function FullscreenWorkspace({
2674
3117
  children: "+"
2675
3118
  }
2676
3119
  ),
2677
- /* @__PURE__ */ jsx12(
3120
+ /* @__PURE__ */ jsx13(
2678
3121
  ZoomButton,
2679
3122
  {
2680
3123
  onClick: onZoomOut,
@@ -2684,7 +3127,7 @@ function FullscreenWorkspace({
2684
3127
  children: "-"
2685
3128
  }
2686
3129
  ),
2687
- onResetZoom && /* @__PURE__ */ jsx12(
3130
+ onResetZoom && /* @__PURE__ */ jsx13(
2688
3131
  ZoomButton,
2689
3132
  {
2690
3133
  onClick: onResetZoom,
@@ -2695,33 +3138,33 @@ function FullscreenWorkspace({
2695
3138
  }
2696
3139
  )
2697
3140
  ] }),
2698
- /* @__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: [
2699
3142
  svgContent,
2700
3143
  overlays
2701
3144
  ] }) })
2702
3145
  ] }),
2703
- /* @__PURE__ */ jsx12(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
2704
- /* @__PURE__ */ jsx12(
3146
+ /* @__PURE__ */ jsx13(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
3147
+ /* @__PURE__ */ jsx13(
2705
3148
  PanelTabs,
2706
3149
  {
2707
3150
  value: currentTab,
2708
3151
  onChange: handleTabChangeInternal,
2709
3152
  "aria-label": "Left panel tabs",
2710
- 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))
2711
3154
  }
2712
3155
  ),
2713
- /* @__PURE__ */ jsx12(PanelContent, { children: currentTabContent })
3156
+ /* @__PURE__ */ jsx13(PanelContent, { children: currentTabContent })
2714
3157
  ] }) : leftPanel }),
2715
- /* @__PURE__ */ jsx12(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
2716
- /* @__PURE__ */ jsx12(FooterPanel, { children: footer })
3158
+ /* @__PURE__ */ jsx13(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
3159
+ /* @__PURE__ */ jsx13(FooterPanel, { children: footer })
2717
3160
  ]
2718
3161
  }
2719
3162
  );
2720
3163
  }
2721
3164
 
2722
3165
  // src/theme/ThemeContext.tsx
2723
- import { createContext, useContext, useState as useState7, useEffect as useEffect4 } from "react";
2724
- 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";
2725
3168
  var ThemeContext = createContext(void 0);
2726
3169
  var useTheme = () => {
2727
3170
  const context = useContext(ThemeContext);
@@ -2731,8 +3174,8 @@ var useTheme = () => {
2731
3174
  return context;
2732
3175
  };
2733
3176
  var ThemeProvider = ({ children }) => {
2734
- const [theme, setThemeState] = useState7("modern");
2735
- useEffect4(() => {
3177
+ const [theme, setThemeState] = useState8("modern");
3178
+ useEffect5(() => {
2736
3179
  document.body.className = "";
2737
3180
  document.body.classList.add(`theme-${theme}`);
2738
3181
  document.documentElement.className = "";
@@ -2744,11 +3187,11 @@ var ThemeProvider = ({ children }) => {
2744
3187
  const setTheme = (newTheme) => {
2745
3188
  setThemeState(newTheme);
2746
3189
  };
2747
- return /* @__PURE__ */ jsx13(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
3190
+ return /* @__PURE__ */ jsx14(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
2748
3191
  };
2749
3192
 
2750
3193
  // src/theme/ThemeToggle.tsx
2751
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3194
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
2752
3195
  var ThemeToggle = ({
2753
3196
  size = "medium",
2754
3197
  position = "top-right",
@@ -2819,15 +3262,15 @@ var ThemeToggle = ({
2819
3262
  transition: "all 0.2s ease",
2820
3263
  boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
2821
3264
  };
2822
- return /* @__PURE__ */ jsxs10("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
2823
- /* @__PURE__ */ jsx14("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
2824
- /* @__PURE__ */ jsx14("div", { style: toggleStyle, children: /* @__PURE__ */ jsx14("div", { style: thumbStyle }) }),
2825
- /* @__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" })
2826
3269
  ] });
2827
3270
  };
2828
3271
 
2829
3272
  // src/components/PIDCanvas/PIDCanvas.tsx
2830
- 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";
2831
3274
 
2832
3275
  // src/diagram/symbols/mockSymbolLibrary.ts
2833
3276
  var mockSymbolLibrary = {
@@ -4048,7 +4491,7 @@ function getAvailableSymbols() {
4048
4491
  }
4049
4492
 
4050
4493
  // src/components/PIDCanvas/NodeRenderer.tsx
4051
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
4494
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4052
4495
  function NodeRenderer({
4053
4496
  nodes: nodes2,
4054
4497
  selectedNodeIds,
@@ -4060,13 +4503,13 @@ function NodeRenderer({
4060
4503
  enableDrag = false,
4061
4504
  statusColorMap
4062
4505
  }) {
4063
- 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) => {
4064
4507
  const symbol = getSymbolDefinition(node.symbolId);
4065
4508
  const isSelected = selectedNodeIds?.has(node.id) ?? false;
4066
4509
  const isDragging = draggingNodeId === node.id;
4067
4510
  if (!symbol) {
4068
- return /* @__PURE__ */ jsxs11("g", { children: [
4069
- /* @__PURE__ */ jsx15(
4511
+ return /* @__PURE__ */ jsxs12("g", { children: [
4512
+ /* @__PURE__ */ jsx16(
4070
4513
  "circle",
4071
4514
  {
4072
4515
  cx: node.transform.x,
@@ -4078,7 +4521,7 @@ function NodeRenderer({
4078
4521
  strokeWidth: "2"
4079
4522
  }
4080
4523
  ),
4081
- /* @__PURE__ */ jsx15(
4524
+ /* @__PURE__ */ jsx16(
4082
4525
  "text",
4083
4526
  {
4084
4527
  x: node.transform.x,
@@ -4120,7 +4563,7 @@ function NodeRenderer({
4120
4563
  const statusEntry = resolveStatusColor(node.status, statusColorMap);
4121
4564
  const fillColor = node.customColors?.fill ?? statusEntry.fill;
4122
4565
  const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
4123
- return /* @__PURE__ */ jsxs11(
4566
+ return /* @__PURE__ */ jsxs12(
4124
4567
  "g",
4125
4568
  {
4126
4569
  "data-node-id": node.id,
@@ -4153,7 +4596,7 @@ function NodeRenderer({
4153
4596
  }
4154
4597
  },
4155
4598
  children: [
4156
- isSelected && /* @__PURE__ */ jsx15(
4599
+ isSelected && /* @__PURE__ */ jsx16(
4157
4600
  "rect",
4158
4601
  {
4159
4602
  x: "-5",
@@ -4168,7 +4611,7 @@ function NodeRenderer({
4168
4611
  pointerEvents: "none"
4169
4612
  }
4170
4613
  ),
4171
- /* @__PURE__ */ jsx15(
4614
+ /* @__PURE__ */ jsx16(
4172
4615
  "g",
4173
4616
  {
4174
4617
  dangerouslySetInnerHTML: { __html: symbol.svgContent },
@@ -4176,7 +4619,7 @@ function NodeRenderer({
4176
4619
  style: { pointerEvents: "auto" }
4177
4620
  }
4178
4621
  ),
4179
- /* @__PURE__ */ jsx15(
4622
+ /* @__PURE__ */ jsx16(
4180
4623
  "text",
4181
4624
  {
4182
4625
  x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
@@ -4197,7 +4640,7 @@ function NodeRenderer({
4197
4640
  }
4198
4641
 
4199
4642
  // src/components/PIDCanvas/PipeRenderer.tsx
4200
- 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";
4201
4644
  function PipeRenderer({
4202
4645
  pipes,
4203
4646
  selectedPipeIds,
@@ -4212,7 +4655,7 @@ function PipeRenderer({
4212
4655
  waypointDragOffset,
4213
4656
  onPipeSegmentClick
4214
4657
  }) {
4215
- 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) => {
4216
4659
  const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
4217
4660
  const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
4218
4661
  const showEditingControls = enableWaypointEditing && isSelected;
@@ -4231,7 +4674,7 @@ function PipeRenderer({
4231
4674
  const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
4232
4675
  const strokeDasharray = pipeStyle.strokeDasharray;
4233
4676
  const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
4234
- return /* @__PURE__ */ jsxs12(
4677
+ return /* @__PURE__ */ jsxs13(
4235
4678
  "g",
4236
4679
  {
4237
4680
  "data-pipe-id": pipe.id,
@@ -4244,8 +4687,8 @@ function PipeRenderer({
4244
4687
  cursor: onPipeClick ? "pointer" : "default"
4245
4688
  },
4246
4689
  children: [
4247
- !enableWaypointEditing && /* @__PURE__ */ jsxs12(Fragment5, { children: [
4248
- onPipeClick && /* @__PURE__ */ jsx16(
4690
+ !enableWaypointEditing && /* @__PURE__ */ jsxs13(Fragment5, { children: [
4691
+ onPipeClick && /* @__PURE__ */ jsx17(
4249
4692
  "polyline",
4250
4693
  {
4251
4694
  points: pointsString,
@@ -4257,7 +4700,7 @@ function PipeRenderer({
4257
4700
  pointerEvents: "stroke"
4258
4701
  }
4259
4702
  ),
4260
- /* @__PURE__ */ jsx16(
4703
+ /* @__PURE__ */ jsx17(
4261
4704
  "polyline",
4262
4705
  {
4263
4706
  points: pointsString,
@@ -4281,7 +4724,7 @@ function PipeRenderer({
4281
4724
  const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
4282
4725
  const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
4283
4726
  const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
4284
- return /* @__PURE__ */ jsx16(
4727
+ return /* @__PURE__ */ jsx17(
4285
4728
  "circle",
4286
4729
  {
4287
4730
  cx: point.x,
@@ -4318,12 +4761,12 @@ function PipeRenderer({
4318
4761
  `${pipe.id}-point-${idx}`
4319
4762
  );
4320
4763
  }),
4321
- 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) => {
4322
4765
  const nextPoint = displayPoints[idx + 1];
4323
4766
  const midX = (point.x + nextPoint.x) / 2;
4324
4767
  const midY = (point.y + nextPoint.y) / 2;
4325
- return /* @__PURE__ */ jsxs12("g", { children: [
4326
- /* @__PURE__ */ jsx16(
4768
+ return /* @__PURE__ */ jsxs13("g", { children: [
4769
+ /* @__PURE__ */ jsx17(
4327
4770
  "circle",
4328
4771
  {
4329
4772
  cx: midX,
@@ -4339,7 +4782,7 @@ function PipeRenderer({
4339
4782
  }
4340
4783
  }
4341
4784
  ),
4342
- /* @__PURE__ */ jsx16(
4785
+ /* @__PURE__ */ jsx17(
4343
4786
  "circle",
4344
4787
  {
4345
4788
  cx: midX,
@@ -4355,7 +4798,7 @@ function PipeRenderer({
4355
4798
  )
4356
4799
  ] }, `${pipe.id}-segment-${idx}`);
4357
4800
  }) }),
4358
- pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ jsx16(
4801
+ pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ jsx17(
4359
4802
  "text",
4360
4803
  {
4361
4804
  x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
@@ -4377,7 +4820,7 @@ function PipeRenderer({
4377
4820
  }
4378
4821
 
4379
4822
  // src/components/PIDCanvas/DataOverlay.tsx
4380
- 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";
4381
4824
  function DataOverlay({
4382
4825
  nodeId,
4383
4826
  x,
@@ -4399,7 +4842,7 @@ function DataOverlay({
4399
4842
  const offsetX = display?.offsetX ?? 0;
4400
4843
  const offsetY = display?.offsetY ?? 0;
4401
4844
  if (!showValue) {
4402
- return /* @__PURE__ */ jsx17(Fragment6, {});
4845
+ return /* @__PURE__ */ jsx18(Fragment6, {});
4403
4846
  }
4404
4847
  const formatValue = (val) => {
4405
4848
  if (typeof val === "number") {
@@ -4440,8 +4883,8 @@ function DataOverlay({
4440
4883
  const overlayWidth = 80 * scale;
4441
4884
  const displayX = x + offsetX;
4442
4885
  const displayY = y + offsetY;
4443
- return /* @__PURE__ */ jsxs13("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4444
- /* @__PURE__ */ jsx17(
4886
+ return /* @__PURE__ */ jsxs14("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4887
+ /* @__PURE__ */ jsx18(
4445
4888
  "rect",
4446
4889
  {
4447
4890
  x: displayX - overlayWidth / 2,
@@ -4456,7 +4899,7 @@ function DataOverlay({
4456
4899
  filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
4457
4900
  }
4458
4901
  ),
4459
- label && /* @__PURE__ */ jsx17(
4902
+ label && /* @__PURE__ */ jsx18(
4460
4903
  "text",
4461
4904
  {
4462
4905
  x: displayX,
@@ -4469,7 +4912,7 @@ function DataOverlay({
4469
4912
  children: label
4470
4913
  }
4471
4914
  ),
4472
- /* @__PURE__ */ jsx17(
4915
+ /* @__PURE__ */ jsx18(
4473
4916
  "text",
4474
4917
  {
4475
4918
  x: displayX,
@@ -4482,7 +4925,7 @@ function DataOverlay({
4482
4925
  children: displayText
4483
4926
  }
4484
4927
  ),
4485
- showStatus && value.status !== "normal" && /* @__PURE__ */ jsx17(
4928
+ showStatus && value.status !== "normal" && /* @__PURE__ */ jsx18(
4486
4929
  "circle",
4487
4930
  {
4488
4931
  cx: displayX + 35 * scale,
@@ -4490,7 +4933,7 @@ function DataOverlay({
4490
4933
  r: 3 * scale,
4491
4934
  fill: finalTextColor,
4492
4935
  opacity: "0.9",
4493
- children: /* @__PURE__ */ jsx17(
4936
+ children: /* @__PURE__ */ jsx18(
4494
4937
  "animate",
4495
4938
  {
4496
4939
  attributeName: "opacity",
@@ -4501,7 +4944,7 @@ function DataOverlay({
4501
4944
  )
4502
4945
  }
4503
4946
  ),
4504
- value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs13(
4947
+ value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs14(
4505
4948
  "text",
4506
4949
  {
4507
4950
  x: displayX,
@@ -4518,7 +4961,7 @@ function DataOverlay({
4518
4961
  ]
4519
4962
  }
4520
4963
  ),
4521
- 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(
4522
4965
  "path",
4523
4966
  {
4524
4967
  d: sparklinePath,
@@ -4534,8 +4977,8 @@ function DataOverlay({
4534
4977
  }
4535
4978
 
4536
4979
  // src/components/PIDCanvas/PositionPanel.tsx
4537
- import { useState as useState8, useEffect as useEffect5 } from "react";
4538
- 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";
4539
4982
  function PositionPanel({
4540
4983
  selectedNode,
4541
4984
  selectedWaypoint,
@@ -4543,9 +4986,9 @@ function PositionPanel({
4543
4986
  onWaypointPositionChange,
4544
4987
  position = "top-right"
4545
4988
  }) {
4546
- const [x, setX] = useState8("");
4547
- const [y, setY] = useState8("");
4548
- useEffect5(() => {
4989
+ const [x, setX] = useState9("");
4990
+ const [y, setY] = useState9("");
4991
+ useEffect6(() => {
4549
4992
  if (selectedNode) {
4550
4993
  setX(selectedNode.transform.x.toFixed(2));
4551
4994
  setY(selectedNode.transform.y.toFixed(2));
@@ -4604,7 +5047,7 @@ function PositionPanel({
4604
5047
  "bottom-left": { bottom: 10, left: 10 },
4605
5048
  "bottom-right": { bottom: 10, right: 10 }
4606
5049
  };
4607
- return /* @__PURE__ */ jsxs14(
5050
+ return /* @__PURE__ */ jsxs15(
4608
5051
  "div",
4609
5052
  {
4610
5053
  style: {
@@ -4621,11 +5064,11 @@ function PositionPanel({
4621
5064
  fontSize: "13px"
4622
5065
  },
4623
5066
  children: [
4624
- /* @__PURE__ */ jsx18("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
4625
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
4626
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4627
- /* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
4628
- /* @__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(
4629
5072
  "input",
4630
5073
  {
4631
5074
  type: "number",
@@ -4643,9 +5086,9 @@ function PositionPanel({
4643
5086
  }
4644
5087
  )
4645
5088
  ] }),
4646
- /* @__PURE__ */ jsxs14("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4647
- /* @__PURE__ */ jsx18("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
4648
- /* @__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(
4649
5092
  "input",
4650
5093
  {
4651
5094
  type: "number",
@@ -4664,14 +5107,14 @@ function PositionPanel({
4664
5107
  )
4665
5108
  ] })
4666
5109
  ] }),
4667
- /* @__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)" })
4668
5111
  ]
4669
5112
  }
4670
5113
  );
4671
5114
  }
4672
5115
 
4673
5116
  // src/diagram/hooks/useViewBox.ts
4674
- 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";
4675
5118
  function useViewBox(options) {
4676
5119
  const {
4677
5120
  initialViewBox,
@@ -4682,16 +5125,16 @@ function useViewBox(options) {
4682
5125
  zoomSensitivity = 1e-3,
4683
5126
  allowLeftClickPan = true
4684
5127
  } = options;
4685
- const [viewBox, setViewBox] = useState9(initialViewBox);
4686
- const svgRef = useRef2(null);
4687
- const isPanningRef = useRef2(false);
4688
- const lastMousePosRef = useRef2({ x: 0, y: 0 });
4689
- const spaceKeyDownRef = useRef2(false);
4690
- const lastTouchDistanceRef = useRef2(null);
4691
- 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(() => {
4692
5135
  setViewBox(initialViewBox);
4693
5136
  }, [initialViewBox]);
4694
- const zoomIn = useCallback3(() => {
5137
+ const zoomIn = useCallback4(() => {
4695
5138
  setViewBox((prev) => {
4696
5139
  const currentZoom = initialViewBox.width / prev.width;
4697
5140
  const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
@@ -4708,7 +5151,7 @@ function useViewBox(options) {
4708
5151
  };
4709
5152
  });
4710
5153
  }, [initialViewBox, minZoom]);
4711
- const zoomOut = useCallback3(() => {
5154
+ const zoomOut = useCallback4(() => {
4712
5155
  setViewBox((prev) => {
4713
5156
  const currentZoom = initialViewBox.width / prev.width;
4714
5157
  const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
@@ -4725,7 +5168,7 @@ function useViewBox(options) {
4725
5168
  };
4726
5169
  });
4727
5170
  }, [initialViewBox, maxZoom]);
4728
- const fitToContent = useCallback3((bounds, padding = 50) => {
5171
+ const fitToContent = useCallback4((bounds, padding = 50) => {
4729
5172
  const contentWidth = bounds.maxX - bounds.minX;
4730
5173
  const contentHeight = bounds.maxY - bounds.minY;
4731
5174
  if (contentWidth === 0 || contentHeight === 0) {
@@ -4753,7 +5196,7 @@ function useViewBox(options) {
4753
5196
  height: newHeight
4754
5197
  });
4755
5198
  }, [initialViewBox]);
4756
- useEffect6(() => {
5199
+ useEffect7(() => {
4757
5200
  if (!enableZoom || !svgRef.current) return;
4758
5201
  const svg = svgRef.current;
4759
5202
  const handleWheel = (e) => {
@@ -4786,7 +5229,7 @@ function useViewBox(options) {
4786
5229
  svg.addEventListener("wheel", handleWheel, { passive: false });
4787
5230
  return () => svg.removeEventListener("wheel", handleWheel);
4788
5231
  }, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
4789
- useEffect6(() => {
5232
+ useEffect7(() => {
4790
5233
  if (!enablePan || !svgRef.current) return;
4791
5234
  const svg = svgRef.current;
4792
5235
  const handleMouseDown = (e) => {
@@ -4862,7 +5305,7 @@ function useViewBox(options) {
4862
5305
  window.removeEventListener("keyup", handleKeyUp);
4863
5306
  };
4864
5307
  }, [enablePan, allowLeftClickPan]);
4865
- useEffect6(() => {
5308
+ useEffect7(() => {
4866
5309
  if (!svgRef.current) return;
4867
5310
  if (!enablePan && !enableZoom) return;
4868
5311
  const svg = svgRef.current;
@@ -4953,7 +5396,7 @@ function useViewBox(options) {
4953
5396
  svg.removeEventListener("touchend", handleTouchEnd);
4954
5397
  };
4955
5398
  }, [enablePan, enableZoom, minZoom, initialViewBox]);
4956
- const screenToWorld = useCallback3(
5399
+ const screenToWorld = useCallback4(
4957
5400
  (screenX, screenY) => {
4958
5401
  const svg = svgRef.current;
4959
5402
  if (!svg) return { x: screenX, y: screenY };
@@ -4992,15 +5435,15 @@ function useViewBox(options) {
4992
5435
  }
4993
5436
 
4994
5437
  // src/diagram/hooks/useSelection.ts
4995
- import { useState as useState10, useCallback as useCallback4 } from "react";
5438
+ import { useState as useState11, useCallback as useCallback5 } from "react";
4996
5439
  function useSelection(options = {}) {
4997
5440
  const {
4998
5441
  multiSelect = true,
4999
5442
  initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
5000
5443
  onSelectionChange
5001
5444
  } = options;
5002
- const [selection, setSelection] = useState10(initialSelection);
5003
- const notifyChange = useCallback4(
5445
+ const [selection, setSelection] = useState11(initialSelection);
5446
+ const notifyChange = useCallback5(
5004
5447
  (newSelection) => {
5005
5448
  if (onSelectionChange) {
5006
5449
  onSelectionChange(newSelection);
@@ -5008,15 +5451,15 @@ function useSelection(options = {}) {
5008
5451
  },
5009
5452
  [onSelectionChange]
5010
5453
  );
5011
- const isNodeSelected = useCallback4(
5454
+ const isNodeSelected = useCallback5(
5012
5455
  (nodeId) => selection.selectedNodeIds.has(nodeId),
5013
5456
  [selection.selectedNodeIds]
5014
5457
  );
5015
- const isPipeSelected = useCallback4(
5458
+ const isPipeSelected = useCallback5(
5016
5459
  (pipeId) => selection.selectedPipeIds.has(pipeId),
5017
5460
  [selection.selectedPipeIds]
5018
5461
  );
5019
- const selectNode = useCallback4(
5462
+ const selectNode = useCallback5(
5020
5463
  (nodeId, isMultiSelect = false) => {
5021
5464
  setSelection((prev) => {
5022
5465
  const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
@@ -5035,7 +5478,7 @@ function useSelection(options = {}) {
5035
5478
  },
5036
5479
  [multiSelect, notifyChange]
5037
5480
  );
5038
- const selectPipe = useCallback4(
5481
+ const selectPipe = useCallback5(
5039
5482
  (pipeId, isMultiSelect = false) => {
5040
5483
  setSelection((prev) => {
5041
5484
  const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
@@ -5054,7 +5497,7 @@ function useSelection(options = {}) {
5054
5497
  },
5055
5498
  [multiSelect, notifyChange]
5056
5499
  );
5057
- const clearSelection = useCallback4(() => {
5500
+ const clearSelection = useCallback5(() => {
5058
5501
  const newSelection = {
5059
5502
  selectedNodeIds: /* @__PURE__ */ new Set(),
5060
5503
  selectedPipeIds: /* @__PURE__ */ new Set()
@@ -5062,7 +5505,7 @@ function useSelection(options = {}) {
5062
5505
  setSelection(newSelection);
5063
5506
  notifyChange(newSelection);
5064
5507
  }, [notifyChange]);
5065
- const selectNodes = useCallback4(
5508
+ const selectNodes = useCallback5(
5066
5509
  (nodeIds) => {
5067
5510
  const newSelection = {
5068
5511
  selectedNodeIds: new Set(nodeIds),
@@ -5073,7 +5516,7 @@ function useSelection(options = {}) {
5073
5516
  },
5074
5517
  [notifyChange]
5075
5518
  );
5076
- const selectPipes = useCallback4(
5519
+ const selectPipes = useCallback5(
5077
5520
  (pipeIds) => {
5078
5521
  const newSelection = {
5079
5522
  selectedNodeIds: /* @__PURE__ */ new Set(),
@@ -5097,23 +5540,23 @@ function useSelection(options = {}) {
5097
5540
  }
5098
5541
 
5099
5542
  // src/diagram/hooks/useTelemetry.ts
5100
- 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";
5101
5544
  function useTelemetry(options = {}) {
5102
5545
  const {
5103
5546
  initialBindings = [],
5104
5547
  onTelemetryChange,
5105
5548
  refreshInterval = 0
5106
5549
  } = options;
5107
- const [telemetry, setTelemetry] = useState11(() => {
5550
+ const [telemetry, setTelemetry] = useState12(() => {
5108
5551
  const map = /* @__PURE__ */ new Map();
5109
5552
  initialBindings.forEach((binding) => {
5110
5553
  map.set(binding.nodeId, binding);
5111
5554
  });
5112
5555
  return map;
5113
5556
  });
5114
- const telemetryRef = useRef3(telemetry);
5557
+ const telemetryRef = useRef4(telemetry);
5115
5558
  telemetryRef.current = telemetry;
5116
- const notifyChange = useCallback5(
5559
+ const notifyChange = useCallback6(
5117
5560
  (newTelemetry) => {
5118
5561
  if (onTelemetryChange) {
5119
5562
  onTelemetryChange(newTelemetry);
@@ -5121,7 +5564,7 @@ function useTelemetry(options = {}) {
5121
5564
  },
5122
5565
  [onTelemetryChange]
5123
5566
  );
5124
- const updateTelemetry = useCallback5(
5567
+ const updateTelemetry = useCallback6(
5125
5568
  (nodeId, value) => {
5126
5569
  setTelemetry((prev) => {
5127
5570
  const newMap = new Map(prev);
@@ -5151,7 +5594,7 @@ function useTelemetry(options = {}) {
5151
5594
  },
5152
5595
  [notifyChange]
5153
5596
  );
5154
- const updateTelemetryBatch = useCallback5(
5597
+ const updateTelemetryBatch = useCallback6(
5155
5598
  (updates) => {
5156
5599
  setTelemetry((prev) => {
5157
5600
  const newMap = new Map(prev);
@@ -5205,16 +5648,16 @@ function useTelemetry(options = {}) {
5205
5648
  },
5206
5649
  [notifyChange]
5207
5650
  );
5208
- const getTelemetry = useCallback5(
5651
+ const getTelemetry = useCallback6(
5209
5652
  (nodeId) => telemetryRef.current.get(nodeId),
5210
5653
  []
5211
5654
  );
5212
- const clearTelemetry = useCallback5(() => {
5655
+ const clearTelemetry = useCallback6(() => {
5213
5656
  const newMap = /* @__PURE__ */ new Map();
5214
5657
  setTelemetry(newMap);
5215
5658
  notifyChange(newMap);
5216
5659
  }, [notifyChange]);
5217
- const setBindings = useCallback5(
5660
+ const setBindings = useCallback6(
5218
5661
  (bindings) => {
5219
5662
  const newMap = /* @__PURE__ */ new Map();
5220
5663
  bindings.forEach((binding) => {
@@ -5225,7 +5668,7 @@ function useTelemetry(options = {}) {
5225
5668
  },
5226
5669
  [notifyChange]
5227
5670
  );
5228
- useEffect7(() => {
5671
+ useEffect8(() => {
5229
5672
  if (refreshInterval <= 0) return;
5230
5673
  const intervalId = setInterval(() => {
5231
5674
  notifyChange(telemetryRef.current);
@@ -5243,10 +5686,10 @@ function useTelemetry(options = {}) {
5243
5686
  }
5244
5687
 
5245
5688
  // src/diagram/hooks/useTelemetryStatus.ts
5246
- import { useEffect as useEffect8 } from "react";
5689
+ import { useEffect as useEffect9 } from "react";
5247
5690
  function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5248
5691
  const { enabled = true, mapStatus } = options;
5249
- useEffect8(() => {
5692
+ useEffect9(() => {
5250
5693
  if (!enabled) return;
5251
5694
  const defaultMapStatus = (telemetryStatus) => {
5252
5695
  switch (telemetryStatus) {
@@ -5285,7 +5728,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5285
5728
  }
5286
5729
 
5287
5730
  // src/diagram/hooks/useDrag.ts
5288
- 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";
5289
5732
  function useDrag(options = {}) {
5290
5733
  const {
5291
5734
  onDragStart,
@@ -5295,23 +5738,23 @@ function useDrag(options = {}) {
5295
5738
  dragThreshold = 3,
5296
5739
  screenToWorld = (x, y) => ({ x, y })
5297
5740
  } = options;
5298
- const [dragState, setDragState] = useState12({
5741
+ const [dragState, setDragState] = useState13({
5299
5742
  isDragging: false,
5300
5743
  startPosition: null,
5301
5744
  offset: { x: 0, y: 0 },
5302
5745
  draggedId: null
5303
5746
  });
5304
- const [isListening, setIsListening] = useState12(false);
5305
- const dragStartRef = useRef4(null);
5306
- const hasMovedRef = useRef4(false);
5307
- const applySnap = useCallback6(
5747
+ const [isListening, setIsListening] = useState13(false);
5748
+ const dragStartRef = useRef5(null);
5749
+ const hasMovedRef = useRef5(false);
5750
+ const applySnap = useCallback7(
5308
5751
  (value) => {
5309
5752
  if (snapToGrid <= 0) return value;
5310
5753
  return Math.round(value / snapToGrid) * snapToGrid;
5311
5754
  },
5312
5755
  [snapToGrid]
5313
5756
  );
5314
- const handleMouseMove = useCallback6(
5757
+ const handleMouseMove = useCallback7(
5315
5758
  (event) => {
5316
5759
  if (!dragStartRef.current) return;
5317
5760
  const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
@@ -5352,7 +5795,7 @@ function useDrag(options = {}) {
5352
5795
  },
5353
5796
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5354
5797
  );
5355
- const handleMouseUp = useCallback6(
5798
+ const handleMouseUp = useCallback7(
5356
5799
  (event) => {
5357
5800
  if (!dragStartRef.current || !hasMovedRef.current) {
5358
5801
  dragStartRef.current = null;
@@ -5389,7 +5832,7 @@ function useDrag(options = {}) {
5389
5832
  },
5390
5833
  [screenToWorld, applySnap, onDragEnd]
5391
5834
  );
5392
- const handleTouchMove = useCallback6(
5835
+ const handleTouchMove = useCallback7(
5393
5836
  (event) => {
5394
5837
  if (!dragStartRef.current || event.touches.length !== 1) return;
5395
5838
  const touch = event.touches[0];
@@ -5432,7 +5875,7 @@ function useDrag(options = {}) {
5432
5875
  },
5433
5876
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5434
5877
  );
5435
- const handleTouchEnd = useCallback6(
5878
+ const handleTouchEnd = useCallback7(
5436
5879
  (event) => {
5437
5880
  if (!dragStartRef.current || !hasMovedRef.current) {
5438
5881
  dragStartRef.current = null;
@@ -5470,7 +5913,7 @@ function useDrag(options = {}) {
5470
5913
  },
5471
5914
  [screenToWorld, applySnap, onDragEnd]
5472
5915
  );
5473
- useEffect9(() => {
5916
+ useEffect10(() => {
5474
5917
  if (!isListening) return;
5475
5918
  document.addEventListener("mousemove", handleMouseMove);
5476
5919
  document.addEventListener("mouseup", handleMouseUp);
@@ -5485,7 +5928,7 @@ function useDrag(options = {}) {
5485
5928
  document.removeEventListener("touchcancel", handleTouchEnd);
5486
5929
  };
5487
5930
  }, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
5488
- const startDrag = useCallback6(
5931
+ const startDrag = useCallback7(
5489
5932
  (id, event, itemPosition) => {
5490
5933
  event.stopPropagation();
5491
5934
  let clientX;
@@ -5515,7 +5958,7 @@ function useDrag(options = {}) {
5515
5958
  },
5516
5959
  [screenToWorld]
5517
5960
  );
5518
- const cancelDrag = useCallback6(() => {
5961
+ const cancelDrag = useCallback7(() => {
5519
5962
  dragStartRef.current = null;
5520
5963
  hasMovedRef.current = false;
5521
5964
  setIsListening(false);
@@ -5526,7 +5969,7 @@ function useDrag(options = {}) {
5526
5969
  draggedId: null
5527
5970
  });
5528
5971
  }, []);
5529
- const isDraggingItem = useCallback6(
5972
+ const isDraggingItem = useCallback7(
5530
5973
  (id) => dragState.isDragging && dragState.draggedId === id,
5531
5974
  [dragState.isDragging, dragState.draggedId]
5532
5975
  );
@@ -5539,7 +5982,7 @@ function useDrag(options = {}) {
5539
5982
  }
5540
5983
 
5541
5984
  // src/diagram/hooks/useKeyboardShortcuts.ts
5542
- import { useEffect as useEffect10 } from "react";
5985
+ import { useEffect as useEffect11 } from "react";
5543
5986
  function useKeyboardShortcuts(options) {
5544
5987
  const {
5545
5988
  onDelete,
@@ -5550,7 +5993,7 @@ function useKeyboardShortcuts(options) {
5550
5993
  onSelectAll,
5551
5994
  enabled = true
5552
5995
  } = options;
5553
- useEffect10(() => {
5996
+ useEffect11(() => {
5554
5997
  if (!enabled) return;
5555
5998
  const handleKeyDown = (event) => {
5556
5999
  const target = event.target;
@@ -5659,7 +6102,7 @@ function nodeHasPort(node, portId) {
5659
6102
  }
5660
6103
 
5661
6104
  // src/components/PIDCanvas/PIDCanvas.tsx
5662
- 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";
5663
6106
  function PIDCanvas({
5664
6107
  diagram,
5665
6108
  className = "",
@@ -5687,21 +6130,21 @@ function PIDCanvas({
5687
6130
  statusColorMap,
5688
6131
  ...props
5689
6132
  }) {
5690
- const [localDiagram, setLocalDiagram] = useState13(diagram);
5691
- const [dragOverPosition, setDragOverPosition] = useState13(null);
5692
- const [isConnecting, setIsConnecting] = useState13(false);
5693
- const [connectionSource, setConnectionSource] = useState13(null);
5694
- const [connectionSourcePort, setConnectionSourcePort] = useState13(null);
5695
- const [connectionCursor, setConnectionCursor] = useState13(null);
5696
- const [hoveredNode, setHoveredNode] = useState13(null);
5697
- const [hoveredPort, setHoveredPort] = useState13(null);
5698
- const [selectedWaypoint, setSelectedWaypoint] = useState13(null);
5699
- const historyStack = useRef5([]);
5700
- const redoStack = useRef5([]);
5701
- const isUndoRedoAction = useRef5(false);
5702
- const isInternalChange = useRef5(false);
5703
- const lastInternalDiagram = useRef5(null);
5704
- 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(() => {
5705
6148
  const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
5706
6149
  if (isExternal) {
5707
6150
  setLocalDiagram(diagram);
@@ -5723,7 +6166,7 @@ function PIDCanvas({
5723
6166
  enablePan: features.pan ?? true,
5724
6167
  enableZoom: features.zoom ?? true
5725
6168
  });
5726
- const calculateContentBounds = useCallback7(() => {
6169
+ const calculateContentBounds = useCallback8(() => {
5727
6170
  const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
5728
6171
  if (nodes2.length === 0) {
5729
6172
  return null;
@@ -5746,7 +6189,7 @@ function PIDCanvas({
5746
6189
  });
5747
6190
  return { minX, minY, maxX, maxY };
5748
6191
  }, [localDiagram.nodes]);
5749
- useEffect11(() => {
6192
+ useEffect12(() => {
5750
6193
  if (onMounted) {
5751
6194
  const controls = {
5752
6195
  fitToContent: (padding = 50) => {
@@ -5787,8 +6230,8 @@ function PIDCanvas({
5787
6230
  });
5788
6231
  const dragEnabled = features.dragNodes ?? false;
5789
6232
  const selectionEnabled = features.selection ?? false;
5790
- const containerRef = useRef5(null);
5791
- const pushToHistory = useCallback7((currentDiagram) => {
6233
+ const containerRef = useRef6(null);
6234
+ const pushToHistory = useCallback8((currentDiagram) => {
5792
6235
  if (isUndoRedoAction.current) return;
5793
6236
  const snapshot = JSON.parse(JSON.stringify(currentDiagram));
5794
6237
  historyStack.current.push(snapshot);
@@ -5797,7 +6240,7 @@ function PIDCanvas({
5797
6240
  }
5798
6241
  redoStack.current = [];
5799
6242
  }, []);
5800
- const undo = useCallback7(() => {
6243
+ const undo = useCallback8(() => {
5801
6244
  if (historyStack.current.length === 0) return;
5802
6245
  isUndoRedoAction.current = true;
5803
6246
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5811,7 +6254,7 @@ function PIDCanvas({
5811
6254
  isUndoRedoAction.current = false;
5812
6255
  }, 0);
5813
6256
  }, [localDiagram, onDiagramChange]);
5814
- const redo = useCallback7(() => {
6257
+ const redo = useCallback8(() => {
5815
6258
  if (redoStack.current.length === 0) return;
5816
6259
  isUndoRedoAction.current = true;
5817
6260
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5825,7 +6268,7 @@ function PIDCanvas({
5825
6268
  isUndoRedoAction.current = false;
5826
6269
  }, 0);
5827
6270
  }, [localDiagram, onDiagramChange]);
5828
- useEffect11(() => {
6271
+ useEffect12(() => {
5829
6272
  const handleKeyDown = (e) => {
5830
6273
  const isCtrlOrCmd = e.ctrlKey || e.metaKey;
5831
6274
  if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
@@ -5842,7 +6285,7 @@ function PIDCanvas({
5842
6285
  window.addEventListener("keydown", handleKeyDown);
5843
6286
  return () => window.removeEventListener("keydown", handleKeyDown);
5844
6287
  }, [undo, redo]);
5845
- useEffect11(() => {
6288
+ useEffect12(() => {
5846
6289
  if (!features.dragNodes) return;
5847
6290
  const handleKeyDown = (e) => {
5848
6291
  if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
@@ -5927,7 +6370,7 @@ function PIDCanvas({
5927
6370
  onNodeMove,
5928
6371
  pushToHistory
5929
6372
  ]);
5930
- const handlePositionChange = useCallback7(
6373
+ const handlePositionChange = useCallback8(
5931
6374
  (nodeId, x, y) => {
5932
6375
  pushToHistory(localDiagram);
5933
6376
  const updatedNodes = localDiagram.nodes.map(
@@ -5949,7 +6392,7 @@ function PIDCanvas({
5949
6392
  },
5950
6393
  [localDiagram, onDiagramChange, onNodeMove, pushToHistory]
5951
6394
  );
5952
- const handleWaypointPositionChange = useCallback7(
6395
+ const handleWaypointPositionChange = useCallback8(
5953
6396
  (pipeId, pointIndex, x, y) => {
5954
6397
  pushToHistory(localDiagram);
5955
6398
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -5967,7 +6410,7 @@ function PIDCanvas({
5967
6410
  },
5968
6411
  [localDiagram, onDiagramChange, pushToHistory]
5969
6412
  );
5970
- const handleDragEnd = useCallback7(
6413
+ const handleDragEnd = useCallback8(
5971
6414
  (nodeId, offset, finalPosition) => {
5972
6415
  const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
5973
6416
  if (dragDistance < 2) {
@@ -6048,7 +6491,7 @@ function PIDCanvas({
6048
6491
  onDiagramChange?.(updatedDiagram);
6049
6492
  }
6050
6493
  });
6051
- const handleNodeDragStart = useCallback7(
6494
+ const handleNodeDragStart = useCallback8(
6052
6495
  (nodeId, event) => {
6053
6496
  const node = localDiagram.nodes.find((n) => n.id === nodeId);
6054
6497
  if (!node) return;
@@ -6056,7 +6499,7 @@ function PIDCanvas({
6056
6499
  },
6057
6500
  [localDiagram.nodes, startDrag]
6058
6501
  );
6059
- const handleWaypointClick = useCallback7(
6502
+ const handleWaypointClick = useCallback8(
6060
6503
  (pipeId, pointIndex) => {
6061
6504
  setSelectedWaypoint({ pipeId, pointIndex });
6062
6505
  if (selectionEnabled) {
@@ -6065,7 +6508,7 @@ function PIDCanvas({
6065
6508
  },
6066
6509
  [selectionEnabled, clearSelection]
6067
6510
  );
6068
- const handleWaypointDragStart = useCallback7(
6511
+ const handleWaypointDragStart = useCallback8(
6069
6512
  (pipeId, pointIndex, event) => {
6070
6513
  const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
6071
6514
  if (!pipe || pointIndex >= pipe.routePoints.length) return;
@@ -6074,7 +6517,7 @@ function PIDCanvas({
6074
6517
  },
6075
6518
  [localDiagram.pipes, startWaypointDrag]
6076
6519
  );
6077
- const handlePipeSegmentClick = useCallback7(
6520
+ const handlePipeSegmentClick = useCallback8(
6078
6521
  (pipeId, position, segmentIndex) => {
6079
6522
  pushToHistory(localDiagram);
6080
6523
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6093,7 +6536,7 @@ function PIDCanvas({
6093
6536
  [localDiagram, onDiagramChange, pushToHistory]
6094
6537
  );
6095
6538
  const telemetryEnabled = features.telemetry ?? false;
6096
- const handleDelete = useCallback7(() => {
6539
+ const handleDelete = useCallback8(() => {
6097
6540
  if (!selectionEnabled) return;
6098
6541
  const { selectedNodeIds, selectedPipeIds } = selection;
6099
6542
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
@@ -6122,13 +6565,13 @@ function PIDCanvas({
6122
6565
  onDelete,
6123
6566
  pushToHistory
6124
6567
  ]);
6125
- const handleCopy = useCallback7(() => {
6568
+ const handleCopy = useCallback8(() => {
6126
6569
  if (!selectionEnabled) return;
6127
6570
  const { selectedNodeIds, selectedPipeIds } = selection;
6128
6571
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
6129
6572
  onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
6130
6573
  }, [selection, selectionEnabled, onItemsCopied]);
6131
- const handlePaste = useCallback7(() => {
6574
+ const handlePaste = useCallback8(() => {
6132
6575
  if (!selectionEnabled) return;
6133
6576
  onPaste?.();
6134
6577
  }, [selectionEnabled, onPaste]);
@@ -6188,7 +6631,7 @@ function PIDCanvas({
6188
6631
  }
6189
6632
  setSelectedWaypoint(null);
6190
6633
  };
6191
- const handleDragOver = useCallback7(
6634
+ const handleDragOver = useCallback8(
6192
6635
  (event) => {
6193
6636
  if (!features.allowSymbolDrop) return;
6194
6637
  event.preventDefault();
@@ -6199,7 +6642,7 @@ function PIDCanvas({
6199
6642
  },
6200
6643
  [features.allowSymbolDrop, screenToWorld, svgRef]
6201
6644
  );
6202
- const handleDrop = useCallback7(
6645
+ const handleDrop = useCallback8(
6203
6646
  (event) => {
6204
6647
  if (!features.allowSymbolDrop) return;
6205
6648
  event.preventDefault();
@@ -6212,10 +6655,10 @@ function PIDCanvas({
6212
6655
  },
6213
6656
  [features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
6214
6657
  );
6215
- const handleDragLeave = useCallback7(() => {
6658
+ const handleDragLeave = useCallback8(() => {
6216
6659
  setDragOverPosition(null);
6217
6660
  }, []);
6218
- const handleMouseMove = useCallback7(
6661
+ const handleMouseMove = useCallback8(
6219
6662
  (event) => {
6220
6663
  const connectionModeEnabled = features.connectionMode ?? false;
6221
6664
  if (connectionModeEnabled) {
@@ -6252,7 +6695,7 @@ function PIDCanvas({
6252
6695
  const viewBox = controlledViewBox;
6253
6696
  const displayDiagram = localDiagram;
6254
6697
  const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
6255
- return /* @__PURE__ */ jsxs15(
6698
+ return /* @__PURE__ */ jsxs16(
6256
6699
  "div",
6257
6700
  {
6258
6701
  ref: containerRef,
@@ -6267,7 +6710,7 @@ function PIDCanvas({
6267
6710
  },
6268
6711
  ...props,
6269
6712
  children: [
6270
- /* @__PURE__ */ jsxs15(
6713
+ /* @__PURE__ */ jsxs16(
6271
6714
  "svg",
6272
6715
  {
6273
6716
  ref: svgRef,
@@ -6286,15 +6729,15 @@ function PIDCanvas({
6286
6729
  onDrop: handleDrop,
6287
6730
  onDragLeave: handleDragLeave,
6288
6731
  children: [
6289
- features.showGrid !== false ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
6290
- /* @__PURE__ */ jsxs15("defs", { children: [
6291
- /* @__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" }) }),
6292
- /* @__PURE__ */ jsxs15("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6293
- /* @__PURE__ */ jsx19("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6294
- /* @__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" })
6295
6738
  ] })
6296
6739
  ] }),
6297
- /* @__PURE__ */ jsx19(
6740
+ /* @__PURE__ */ jsx20(
6298
6741
  "rect",
6299
6742
  {
6300
6743
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6304,7 +6747,7 @@ function PIDCanvas({
6304
6747
  fill: "url(#grid-major)"
6305
6748
  }
6306
6749
  )
6307
- ] }) : /* @__PURE__ */ jsx19(
6750
+ ] }) : /* @__PURE__ */ jsx20(
6308
6751
  "rect",
6309
6752
  {
6310
6753
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6314,7 +6757,7 @@ function PIDCanvas({
6314
6757
  fill: features.backgroundColor ?? "#ffffff"
6315
6758
  }
6316
6759
  ),
6317
- /* @__PURE__ */ jsx19(
6760
+ /* @__PURE__ */ jsx20(
6318
6761
  PipeRenderer,
6319
6762
  {
6320
6763
  pipes: displayDiagram.pipes,
@@ -6328,7 +6771,7 @@ function PIDCanvas({
6328
6771
  onPipeSegmentClick: void 0
6329
6772
  }
6330
6773
  ),
6331
- /* @__PURE__ */ jsx19(
6774
+ /* @__PURE__ */ jsx20(
6332
6775
  NodeRenderer,
6333
6776
  {
6334
6777
  nodes: displayDiagram.nodes,
@@ -6342,7 +6785,7 @@ function PIDCanvas({
6342
6785
  statusColorMap
6343
6786
  }
6344
6787
  ),
6345
- (features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx19(
6788
+ (features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx20(
6346
6789
  PipeRenderer,
6347
6790
  {
6348
6791
  pipes: displayDiagram.pipes,
@@ -6359,14 +6802,14 @@ function PIDCanvas({
6359
6802
  onPipeSegmentClick: handlePipeSegmentClick
6360
6803
  }
6361
6804
  ),
6362
- 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) => {
6363
6806
  const binding = telemetry.get(node.id);
6364
6807
  if (!binding) return null;
6365
6808
  const symbol = getSymbolDefinition(node.symbolId);
6366
6809
  if (!symbol) return null;
6367
6810
  const overlayX = node.transform.x + symbol.viewBox.width / 2;
6368
6811
  const overlayY = node.transform.y + symbol.viewBox.height + 50;
6369
- return /* @__PURE__ */ jsx19(
6812
+ return /* @__PURE__ */ jsx20(
6370
6813
  DataOverlay,
6371
6814
  {
6372
6815
  nodeId: node.id,
@@ -6379,7 +6822,7 @@ function PIDCanvas({
6379
6822
  `telemetry-${node.id}`
6380
6823
  );
6381
6824
  }) }),
6382
- dragOverPosition && /* @__PURE__ */ jsx19(
6825
+ dragOverPosition && /* @__PURE__ */ jsx20(
6383
6826
  "circle",
6384
6827
  {
6385
6828
  cx: dragOverPosition.x,
@@ -6392,7 +6835,7 @@ function PIDCanvas({
6392
6835
  pointerEvents: "none"
6393
6836
  }
6394
6837
  ),
6395
- 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: (() => {
6396
6839
  const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
6397
6840
  if (!sourceNode) return null;
6398
6841
  const symbol = getSymbolDefinition(sourceNode.symbolId);
@@ -6408,8 +6851,8 @@ function PIDCanvas({
6408
6851
  }
6409
6852
  }
6410
6853
  }
6411
- return /* @__PURE__ */ jsxs15(Fragment7, { children: [
6412
- /* @__PURE__ */ jsx19(
6854
+ return /* @__PURE__ */ jsxs16(Fragment7, { children: [
6855
+ /* @__PURE__ */ jsx20(
6413
6856
  "circle",
6414
6857
  {
6415
6858
  cx: lineStartX,
@@ -6421,7 +6864,7 @@ function PIDCanvas({
6421
6864
  opacity: 0.6
6422
6865
  }
6423
6866
  ),
6424
- /* @__PURE__ */ jsx19(
6867
+ /* @__PURE__ */ jsx20(
6425
6868
  "line",
6426
6869
  {
6427
6870
  x1: lineStartX,
@@ -6434,7 +6877,7 @@ function PIDCanvas({
6434
6877
  opacity: 0.8
6435
6878
  }
6436
6879
  ),
6437
- /* @__PURE__ */ jsx19(
6880
+ /* @__PURE__ */ jsx20(
6438
6881
  "circle",
6439
6882
  {
6440
6883
  cx: connectionCursor.x,
@@ -6446,7 +6889,7 @@ function PIDCanvas({
6446
6889
  )
6447
6890
  ] });
6448
6891
  })() }),
6449
- 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) => {
6450
6893
  const symbol = getSymbolDefinition(node.symbolId);
6451
6894
  if (!symbol?.ports) return null;
6452
6895
  return symbol.ports.map((port) => {
@@ -6454,8 +6897,8 @@ function PIDCanvas({
6454
6897
  if (!portPos) return null;
6455
6898
  const isHovered = hoveredPort === port.id && hoveredNode === node.id;
6456
6899
  const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
6457
- return /* @__PURE__ */ jsxs15("g", { children: [
6458
- /* @__PURE__ */ jsx19(
6900
+ return /* @__PURE__ */ jsxs16("g", { children: [
6901
+ /* @__PURE__ */ jsx20(
6459
6902
  "circle",
6460
6903
  {
6461
6904
  cx: portPos.x,
@@ -6488,7 +6931,7 @@ function PIDCanvas({
6488
6931
  }
6489
6932
  }
6490
6933
  ),
6491
- /* @__PURE__ */ jsx19(
6934
+ /* @__PURE__ */ jsx20(
6492
6935
  "circle",
6493
6936
  {
6494
6937
  cx: portPos.x,
@@ -6507,7 +6950,7 @@ function PIDCanvas({
6507
6950
  ]
6508
6951
  }
6509
6952
  ),
6510
- features.dragNodes && /* @__PURE__ */ jsx19(
6953
+ features.dragNodes && /* @__PURE__ */ jsx20(
6511
6954
  PositionPanel,
6512
6955
  {
6513
6956
  selectedNode,
@@ -6527,16 +6970,16 @@ function PIDCanvas({
6527
6970
  }
6528
6971
 
6529
6972
  // src/components/SymbolLibrary/SymbolLibrary.tsx
6530
- import { useState as useState14 } from "react";
6531
- 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";
6532
6975
  function SymbolLibrary({
6533
6976
  className = "",
6534
6977
  onSymbolDragStart,
6535
6978
  showCategories = true,
6536
6979
  categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
6537
6980
  }) {
6538
- const [selectedCategory, setSelectedCategory] = useState14("all");
6539
- const [searchQuery, setSearchQuery] = useState14("");
6981
+ const [selectedCategory, setSelectedCategory] = useState15("all");
6982
+ const [searchQuery, setSearchQuery] = useState15("");
6540
6983
  const symbolIds = getAvailableSymbols();
6541
6984
  const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
6542
6985
  const categoryMap = {
@@ -6557,9 +7000,9 @@ function SymbolLibrary({
6557
7000
  event.dataTransfer.effectAllowed = "copy";
6558
7001
  onSymbolDragStart?.(symbol.id, event);
6559
7002
  };
6560
- return /* @__PURE__ */ jsxs16("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
6561
- /* @__PURE__ */ jsx20("div", { style: styles.header, children: /* @__PURE__ */ jsx20("h3", { style: styles.title, children: "Symbol Library" }) }),
6562
- /* @__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(
6563
7006
  "input",
6564
7007
  {
6565
7008
  type: "text",
@@ -6569,8 +7012,8 @@ function SymbolLibrary({
6569
7012
  style: styles.searchInput
6570
7013
  }
6571
7014
  ) }),
6572
- showCategories && /* @__PURE__ */ jsxs16("div", { style: styles.categories, children: [
6573
- /* @__PURE__ */ jsx20(
7015
+ showCategories && /* @__PURE__ */ jsxs17("div", { style: styles.categories, children: [
7016
+ /* @__PURE__ */ jsx21(
6574
7017
  "button",
6575
7018
  {
6576
7019
  onClick: () => setSelectedCategory("all"),
@@ -6581,7 +7024,7 @@ function SymbolLibrary({
6581
7024
  children: "All"
6582
7025
  }
6583
7026
  ),
6584
- categories.map((category) => /* @__PURE__ */ jsx20(
7027
+ categories.map((category) => /* @__PURE__ */ jsx21(
6585
7028
  "button",
6586
7029
  {
6587
7030
  onClick: () => setSelectedCategory(category),
@@ -6594,7 +7037,7 @@ function SymbolLibrary({
6594
7037
  category
6595
7038
  ))
6596
7039
  ] }),
6597
- /* @__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(
6598
7041
  "div",
6599
7042
  {
6600
7043
  draggable: true,
@@ -6602,15 +7045,15 @@ function SymbolLibrary({
6602
7045
  style: styles.symbolCard,
6603
7046
  title: symbol.metadata?.description || symbol.name,
6604
7047
  children: [
6605
- /* @__PURE__ */ jsx20("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx20(
7048
+ /* @__PURE__ */ jsx21("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx21(
6606
7049
  "svg",
6607
7050
  {
6608
7051
  viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
6609
7052
  style: styles.symbolSvg,
6610
- children: /* @__PURE__ */ jsx20("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
7053
+ children: /* @__PURE__ */ jsx21("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
6611
7054
  }
6612
7055
  ) }),
6613
- /* @__PURE__ */ jsx20("div", { style: styles.symbolName, children: symbol.name })
7056
+ /* @__PURE__ */ jsx21("div", { style: styles.symbolName, children: symbol.name })
6614
7057
  ]
6615
7058
  },
6616
7059
  symbol.id
@@ -6719,7 +7162,7 @@ var styles = {
6719
7162
  };
6720
7163
 
6721
7164
  // src/components/NodeConfigPanel/NodeConfigPanel.tsx
6722
- 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";
6723
7166
  function NodeConfigPanel({
6724
7167
  node,
6725
7168
  binding,
@@ -6738,15 +7181,15 @@ function NodeConfigPanel({
6738
7181
  padding: "20px",
6739
7182
  ...style
6740
7183
  };
6741
- return /* @__PURE__ */ jsxs17("div", { className, style: defaultStyle, children: [
6742
- /* @__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: [
6743
7186
  "Configure: ",
6744
7187
  node.id
6745
7188
  ] }),
6746
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
6747
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
6748
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
6749
- /* @__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(
6750
7193
  "input",
6751
7194
  {
6752
7195
  type: "text",
@@ -6762,10 +7205,10 @@ function NodeConfigPanel({
6762
7205
  }
6763
7206
  }
6764
7207
  ),
6765
- /* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6766
- /* @__PURE__ */ jsxs17("div", { children: [
6767
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
6768
- /* @__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(
6769
7212
  "input",
6770
7213
  {
6771
7214
  type: "number",
@@ -6786,9 +7229,9 @@ function NodeConfigPanel({
6786
7229
  }
6787
7230
  )
6788
7231
  ] }),
6789
- /* @__PURE__ */ jsxs17("div", { children: [
6790
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
6791
- /* @__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(
6792
7235
  "input",
6793
7236
  {
6794
7237
  type: "number",
@@ -6810,9 +7253,9 @@ function NodeConfigPanel({
6810
7253
  )
6811
7254
  ] })
6812
7255
  ] }),
6813
- /* @__PURE__ */ jsxs17("div", { children: [
6814
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
6815
- /* @__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(
6816
7259
  "input",
6817
7260
  {
6818
7261
  type: "number",
@@ -6832,9 +7275,9 @@ function NodeConfigPanel({
6832
7275
  }
6833
7276
  )
6834
7277
  ] }),
6835
- /* @__PURE__ */ jsxs17("div", { children: [
6836
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
6837
- /* @__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(
6838
7281
  "input",
6839
7282
  {
6840
7283
  type: "number",
@@ -6859,9 +7302,9 @@ function NodeConfigPanel({
6859
7302
  )
6860
7303
  ] })
6861
7304
  ] }),
6862
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
6863
- /* @__PURE__ */ jsx21("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
6864
- !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(
6865
7308
  "button",
6866
7309
  {
6867
7310
  onClick: () => {
@@ -6904,9 +7347,9 @@ function NodeConfigPanel({
6904
7347
  },
6905
7348
  children: "+ Add Telemetry"
6906
7349
  }
6907
- ) : /* @__PURE__ */ jsxs17(Fragment8, { children: [
6908
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
6909
- /* @__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(
6910
7353
  "input",
6911
7354
  {
6912
7355
  type: "number",
@@ -6928,8 +7371,8 @@ function NodeConfigPanel({
6928
7371
  }
6929
7372
  }
6930
7373
  ),
6931
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
6932
- /* @__PURE__ */ jsx21(
7374
+ /* @__PURE__ */ jsx22("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
7375
+ /* @__PURE__ */ jsx22(
6933
7376
  "input",
6934
7377
  {
6935
7378
  type: "text",
@@ -6951,8 +7394,8 @@ function NodeConfigPanel({
6951
7394
  }
6952
7395
  }
6953
7396
  ),
6954
- /* @__PURE__ */ jsxs17("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
6955
- /* @__PURE__ */ jsx21(
7397
+ /* @__PURE__ */ jsxs18("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7398
+ /* @__PURE__ */ jsx22(
6956
7399
  "input",
6957
7400
  {
6958
7401
  type: "checkbox",
@@ -6974,8 +7417,8 @@ function NodeConfigPanel({
6974
7417
  ),
6975
7418
  "Show Sparkline"
6976
7419
  ] }),
6977
- /* @__PURE__ */ jsxs17("div", { style: { marginTop: "12px" }, children: [
6978
- /* @__PURE__ */ jsx21(
7420
+ /* @__PURE__ */ jsxs18("div", { style: { marginTop: "12px" }, children: [
7421
+ /* @__PURE__ */ jsx22(
6979
7422
  "label",
6980
7423
  {
6981
7424
  style: {
@@ -6987,10 +7430,10 @@ function NodeConfigPanel({
6987
7430
  children: "Telemetry Position Offset:"
6988
7431
  }
6989
7432
  ),
6990
- /* @__PURE__ */ jsxs17("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6991
- /* @__PURE__ */ jsxs17("div", { children: [
6992
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
6993
- /* @__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(
6994
7437
  "input",
6995
7438
  {
6996
7439
  type: "number",
@@ -7017,9 +7460,9 @@ function NodeConfigPanel({
7017
7460
  }
7018
7461
  )
7019
7462
  ] }),
7020
- /* @__PURE__ */ jsxs17("div", { children: [
7021
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
7022
- /* @__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(
7023
7466
  "input",
7024
7467
  {
7025
7468
  type: "number",
@@ -7047,8 +7490,8 @@ function NodeConfigPanel({
7047
7490
  )
7048
7491
  ] })
7049
7492
  ] }),
7050
- /* @__PURE__ */ jsxs17("div", { style: { marginTop: "16px" }, children: [
7051
- /* @__PURE__ */ jsx21(
7493
+ /* @__PURE__ */ jsxs18("div", { style: { marginTop: "16px" }, children: [
7494
+ /* @__PURE__ */ jsx22(
7052
7495
  "label",
7053
7496
  {
7054
7497
  style: {
@@ -7060,10 +7503,10 @@ function NodeConfigPanel({
7060
7503
  children: "Display Colors:"
7061
7504
  }
7062
7505
  ),
7063
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7064
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7065
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7066
- /* @__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(
7067
7510
  "input",
7068
7511
  {
7069
7512
  type: "color",
@@ -7089,7 +7532,7 @@ function NodeConfigPanel({
7089
7532
  }
7090
7533
  }
7091
7534
  ),
7092
- /* @__PURE__ */ jsx21(
7535
+ /* @__PURE__ */ jsx22(
7093
7536
  "input",
7094
7537
  {
7095
7538
  type: "text",
@@ -7119,10 +7562,10 @@ function NodeConfigPanel({
7119
7562
  )
7120
7563
  ] })
7121
7564
  ] }),
7122
- binding.display?.showSparkline && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7123
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7124
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7125
- /* @__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(
7126
7569
  "input",
7127
7570
  {
7128
7571
  type: "color",
@@ -7148,7 +7591,7 @@ function NodeConfigPanel({
7148
7591
  }
7149
7592
  }
7150
7593
  ),
7151
- /* @__PURE__ */ jsx21(
7594
+ /* @__PURE__ */ jsx22(
7152
7595
  "input",
7153
7596
  {
7154
7597
  type: "text",
@@ -7178,9 +7621,9 @@ function NodeConfigPanel({
7178
7621
  )
7179
7622
  ] })
7180
7623
  ] }),
7181
- /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7182
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7183
- /* @__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(
7184
7627
  "input",
7185
7628
  {
7186
7629
  type: "text",
@@ -7208,20 +7651,20 @@ function NodeConfigPanel({
7208
7651
  }
7209
7652
  }
7210
7653
  ),
7211
- /* @__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" })
7212
7655
  ] })
7213
7656
  ] }),
7214
7657
  " "
7215
7658
  ] })
7216
7659
  ] })
7217
7660
  ] }),
7218
- binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
7219
- /* @__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" }),
7220
7663
  ["highHigh", "high", "low", "lowLow"].map((key) => {
7221
7664
  const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
7222
- return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7223
- /* @__PURE__ */ jsx21("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7224
- /* @__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(
7225
7668
  "input",
7226
7669
  {
7227
7670
  type: "number",
@@ -7245,8 +7688,8 @@ function NodeConfigPanel({
7245
7688
  ] }, key);
7246
7689
  })
7247
7690
  ] }),
7248
- binding && /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "20px" }, children: [
7249
- /* @__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" }),
7250
7693
  ["normal", "warning", "alarm", "fault", "off"].map((status) => {
7251
7694
  const defaultColors = {
7252
7695
  normal: "#10b981",
@@ -7256,13 +7699,13 @@ function NodeConfigPanel({
7256
7699
  off: "#6b7280"
7257
7700
  };
7258
7701
  const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
7259
- return /* @__PURE__ */ jsxs17("div", { style: { marginBottom: "8px" }, children: [
7260
- /* @__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: [
7261
7704
  label,
7262
7705
  ":"
7263
7706
  ] }),
7264
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7265
- /* @__PURE__ */ jsx21(
7707
+ /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7708
+ /* @__PURE__ */ jsx22(
7266
7709
  "input",
7267
7710
  {
7268
7711
  type: "color",
@@ -7283,7 +7726,7 @@ function NodeConfigPanel({
7283
7726
  }
7284
7727
  }
7285
7728
  ),
7286
- /* @__PURE__ */ jsx21(
7729
+ /* @__PURE__ */ jsx22(
7287
7730
  "input",
7288
7731
  {
7289
7732
  type: "text",
@@ -7310,7 +7753,7 @@ function NodeConfigPanel({
7310
7753
  ] }, status);
7311
7754
  })
7312
7755
  ] }),
7313
- /* @__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(
7314
7757
  "button",
7315
7758
  {
7316
7759
  onClick: onRemove,
@@ -7587,13 +8030,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
7587
8030
  }
7588
8031
 
7589
8032
  // src/hooks/useDeviceControls.ts
7590
- 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";
7591
8034
  function commandKey(nodeId, kind, suffix) {
7592
8035
  return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
7593
8036
  }
7594
8037
  function useDeviceControls(initialBindings, options) {
7595
8038
  const { commandTimeoutMs } = options ?? {};
7596
- const [controls, setControls] = useState15(() => {
8039
+ const [controls, setControls] = useState16(() => {
7597
8040
  const map = /* @__PURE__ */ new Map();
7598
8041
  if (initialBindings) {
7599
8042
  initialBindings.forEach((binding) => {
@@ -7602,12 +8045,12 @@ function useDeviceControls(initialBindings, options) {
7602
8045
  }
7603
8046
  return map;
7604
8047
  });
7605
- const pendingRef = useRef6(/* @__PURE__ */ new Map());
7606
- const [pendingCommands, setPendingCommands] = useState15(() => /* @__PURE__ */ new Set());
7607
- const syncPending = useCallback8(() => {
8048
+ const pendingRef = useRef7(/* @__PURE__ */ new Map());
8049
+ const [pendingCommands, setPendingCommands] = useState16(() => /* @__PURE__ */ new Set());
8050
+ const syncPending = useCallback9(() => {
7608
8051
  setPendingCommands(new Set(pendingRef.current.keys()));
7609
8052
  }, []);
7610
- const updateControl = useCallback8((nodeId, updates) => {
8053
+ const updateControl = useCallback9((nodeId, updates) => {
7611
8054
  setControls((prev) => {
7612
8055
  const newMap = new Map(prev);
7613
8056
  const existing = newMap.get(nodeId);
@@ -7621,7 +8064,7 @@ function useDeviceControls(initialBindings, options) {
7621
8064
  return newMap;
7622
8065
  });
7623
8066
  }, []);
7624
- const updateControlBatch = useCallback8((updates) => {
8067
+ const updateControlBatch = useCallback9((updates) => {
7625
8068
  setControls((prev) => {
7626
8069
  const newMap = new Map(prev);
7627
8070
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7633,7 +8076,7 @@ function useDeviceControls(initialBindings, options) {
7633
8076
  return newMap;
7634
8077
  });
7635
8078
  }, []);
7636
- const updateDeviceState = useCallback8(
8079
+ const updateDeviceState = useCallback9(
7637
8080
  (nodeId, stateUpdates) => {
7638
8081
  setControls((prev) => {
7639
8082
  const newMap = new Map(prev);
@@ -7649,7 +8092,7 @@ function useDeviceControls(initialBindings, options) {
7649
8092
  },
7650
8093
  []
7651
8094
  );
7652
- const updateParameter = useCallback8(
8095
+ const updateParameter = useCallback9(
7653
8096
  (nodeId, parameterId, value) => {
7654
8097
  setControls((prev) => {
7655
8098
  const newMap = new Map(prev);
@@ -7676,27 +8119,27 @@ function useDeviceControls(initialBindings, options) {
7676
8119
  },
7677
8120
  []
7678
8121
  );
7679
- const setControlBinding = useCallback8((binding) => {
8122
+ const setControlBinding = useCallback9((binding) => {
7680
8123
  setControls((prev) => {
7681
8124
  const newMap = new Map(prev);
7682
8125
  newMap.set(binding.nodeId, binding);
7683
8126
  return newMap;
7684
8127
  });
7685
8128
  }, []);
7686
- const removeControlBinding = useCallback8((nodeId) => {
8129
+ const removeControlBinding = useCallback9((nodeId) => {
7687
8130
  setControls((prev) => {
7688
8131
  const newMap = new Map(prev);
7689
8132
  newMap.delete(nodeId);
7690
8133
  return newMap;
7691
8134
  });
7692
8135
  }, []);
7693
- const getControlBinding = useCallback8(
8136
+ const getControlBinding = useCallback9(
7694
8137
  (nodeId) => {
7695
8138
  return controls.get(nodeId);
7696
8139
  },
7697
8140
  [controls]
7698
8141
  );
7699
- const isCommandPending = useCallback8(
8142
+ const isCommandPending = useCallback9(
7700
8143
  (nodeId, kind) => {
7701
8144
  if (kind) {
7702
8145
  const prefix2 = `${nodeId}:${kind}`;
@@ -7713,7 +8156,7 @@ function useDeviceControls(initialBindings, options) {
7713
8156
  },
7714
8157
  [pendingCommands]
7715
8158
  );
7716
- const markPending = useCallback8(
8159
+ const markPending = useCallback9(
7717
8160
  (key, delta) => {
7718
8161
  const next = (pendingRef.current.get(key) ?? 0) + delta;
7719
8162
  if (next > 0) pendingRef.current.set(key, next);
@@ -7722,7 +8165,7 @@ function useDeviceControls(initialBindings, options) {
7722
8165
  },
7723
8166
  [syncPending]
7724
8167
  );
7725
- const runCommand = useCallback8(
8168
+ const runCommand = useCallback9(
7726
8169
  async (nodeId, key, invoke, messages) => {
7727
8170
  const binding = controls.get(nodeId);
7728
8171
  if (!binding) return;
@@ -7762,7 +8205,7 @@ function useDeviceControls(initialBindings, options) {
7762
8205
  },
7763
8206
  [controls, updateDeviceState, markPending, commandTimeoutMs]
7764
8207
  );
7765
- const sendModeChange = useCallback8(
8208
+ const sendModeChange = useCallback9(
7766
8209
  (nodeId, mode) => runCommand(
7767
8210
  nodeId,
7768
8211
  commandKey(nodeId, "mode"),
@@ -7771,7 +8214,7 @@ function useDeviceControls(initialBindings, options) {
7771
8214
  ),
7772
8215
  [runCommand]
7773
8216
  );
7774
- const sendParameterChange = useCallback8(
8217
+ const sendParameterChange = useCallback9(
7775
8218
  (nodeId, parameterId, value) => runCommand(
7776
8219
  nodeId,
7777
8220
  commandKey(nodeId, "parameter", parameterId),
@@ -7780,21 +8223,21 @@ function useDeviceControls(initialBindings, options) {
7780
8223
  ),
7781
8224
  [runCommand]
7782
8225
  );
7783
- const sendStartCommand = useCallback8(
8226
+ const sendStartCommand = useCallback9(
7784
8227
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
7785
8228
  success: "Start command sent",
7786
8229
  failure: "Start command failed"
7787
8230
  }),
7788
8231
  [runCommand]
7789
8232
  );
7790
- const sendStopCommand = useCallback8(
8233
+ const sendStopCommand = useCallback9(
7791
8234
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
7792
8235
  success: "Stop command sent",
7793
8236
  failure: "Stop command failed"
7794
8237
  }),
7795
8238
  [runCommand]
7796
8239
  );
7797
- const sendCustomAction = useCallback8(
8240
+ const sendCustomAction = useCallback9(
7798
8241
  (nodeId, actionId) => runCommand(
7799
8242
  nodeId,
7800
8243
  commandKey(nodeId, "action", actionId),
@@ -7847,9 +8290,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
7847
8290
  }
7848
8291
 
7849
8292
  // src/hooks/useDeviceConfigs.ts
7850
- import { useState as useState16, useCallback as useCallback9 } from "react";
8293
+ import { useState as useState17, useCallback as useCallback10 } from "react";
7851
8294
  function useDeviceConfigs(initialConfigs) {
7852
- const [configs, setConfigs] = useState16(() => {
8295
+ const [configs, setConfigs] = useState17(() => {
7853
8296
  const map = /* @__PURE__ */ new Map();
7854
8297
  if (initialConfigs) {
7855
8298
  initialConfigs.forEach((config) => {
@@ -7858,13 +8301,13 @@ function useDeviceConfigs(initialConfigs) {
7858
8301
  }
7859
8302
  return map;
7860
8303
  });
7861
- const getConfig = useCallback9(
8304
+ const getConfig = useCallback10(
7862
8305
  (nodeId) => {
7863
8306
  return configs.get(nodeId);
7864
8307
  },
7865
8308
  [configs]
7866
8309
  );
7867
- const updateConfig = useCallback9((nodeId, updates) => {
8310
+ const updateConfig = useCallback10((nodeId, updates) => {
7868
8311
  setConfigs((prev) => {
7869
8312
  const newMap = new Map(prev);
7870
8313
  const existing = newMap.get(nodeId);
@@ -7878,7 +8321,7 @@ function useDeviceConfigs(initialConfigs) {
7878
8321
  return newMap;
7879
8322
  });
7880
8323
  }, []);
7881
- const updateConfigState = useCallback9((nodeId, stateUpdates) => {
8324
+ const updateConfigState = useCallback10((nodeId, stateUpdates) => {
7882
8325
  setConfigs((prev) => {
7883
8326
  const newMap = new Map(prev);
7884
8327
  const existing = newMap.get(nodeId);
@@ -7891,7 +8334,7 @@ function useDeviceConfigs(initialConfigs) {
7891
8334
  return newMap;
7892
8335
  });
7893
8336
  }, []);
7894
- const updateConfigBatch = useCallback9((updates) => {
8337
+ const updateConfigBatch = useCallback10((updates) => {
7895
8338
  setConfigs((prev) => {
7896
8339
  const newMap = new Map(prev);
7897
8340
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7903,7 +8346,7 @@ function useDeviceConfigs(initialConfigs) {
7903
8346
  return newMap;
7904
8347
  });
7905
8348
  }, []);
7906
- const updateParameterValue = useCallback9((nodeId, parameterId, value) => {
8349
+ const updateParameterValue = useCallback10((nodeId, parameterId, value) => {
7907
8350
  setConfigs((prev) => {
7908
8351
  const newMap = new Map(prev);
7909
8352
  const existing = newMap.get(nodeId);
@@ -7920,7 +8363,7 @@ function useDeviceConfigs(initialConfigs) {
7920
8363
  return newMap;
7921
8364
  });
7922
8365
  }, []);
7923
- const applyConfig = useCallback9(
8366
+ const applyConfig = useCallback10(
7924
8367
  async (nodeId) => {
7925
8368
  const config = configs.get(nodeId);
7926
8369
  if (!config || !config.actions.onApply) {
@@ -7953,7 +8396,7 @@ function useDeviceConfigs(initialConfigs) {
7953
8396
  },
7954
8397
  [configs, updateConfigState]
7955
8398
  );
7956
- const saveConfig = useCallback9(
8399
+ const saveConfig = useCallback10(
7957
8400
  async (nodeId) => {
7958
8401
  const config = configs.get(nodeId);
7959
8402
  if (!config || !config.actions.onSave) {
@@ -7987,7 +8430,7 @@ function useDeviceConfigs(initialConfigs) {
7987
8430
  },
7988
8431
  [configs, updateConfigState]
7989
8432
  );
7990
- const resetConfig = useCallback9(
8433
+ const resetConfig = useCallback10(
7991
8434
  async (nodeId) => {
7992
8435
  const config = configs.get(nodeId);
7993
8436
  if (!config) {
@@ -8017,7 +8460,7 @@ function useDeviceConfigs(initialConfigs) {
8017
8460
  },
8018
8461
  [configs, updateConfig, updateConfigState]
8019
8462
  );
8020
- const cancelConfig = useCallback9(
8463
+ const cancelConfig = useCallback10(
8021
8464
  (nodeId) => {
8022
8465
  const config = configs.get(nodeId);
8023
8466
  if (config?.actions.onCancel) {
@@ -8026,7 +8469,7 @@ function useDeviceConfigs(initialConfigs) {
8026
8469
  },
8027
8470
  [configs]
8028
8471
  );
8029
- const validateConfig = useCallback9(
8472
+ const validateConfig = useCallback10(
8030
8473
  (nodeId) => {
8031
8474
  const config = configs.get(nodeId);
8032
8475
  if (!config) {
@@ -8068,21 +8511,21 @@ function useDeviceConfigs(initialConfigs) {
8068
8511
  },
8069
8512
  [configs, updateConfigState]
8070
8513
  );
8071
- const setConfig = useCallback9((config) => {
8514
+ const setConfig = useCallback10((config) => {
8072
8515
  setConfigs((prev) => {
8073
8516
  const newMap = new Map(prev);
8074
8517
  newMap.set(config.nodeId, config);
8075
8518
  return newMap;
8076
8519
  });
8077
8520
  }, []);
8078
- const removeConfig = useCallback9((nodeId) => {
8521
+ const removeConfig = useCallback10((nodeId) => {
8079
8522
  setConfigs((prev) => {
8080
8523
  const newMap = new Map(prev);
8081
8524
  newMap.delete(nodeId);
8082
8525
  return newMap;
8083
8526
  });
8084
8527
  }, []);
8085
- const clearConfigs = useCallback9(() => {
8528
+ const clearConfigs = useCallback10(() => {
8086
8529
  setConfigs(/* @__PURE__ */ new Map());
8087
8530
  }, []);
8088
8531
  return {
@@ -8104,8 +8547,8 @@ function useDeviceConfigs(initialConfigs) {
8104
8547
  }
8105
8548
 
8106
8549
  // src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
8107
- import { useState as useState17, useEffect as useEffect12, useMemo, useRef as useRef7 } from "react";
8108
- 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";
8109
8552
  function DeviceConfigPanel({
8110
8553
  binding,
8111
8554
  onClose,
@@ -8123,7 +8566,7 @@ function DeviceConfigPanel({
8123
8566
  showControlsButton = true,
8124
8567
  embedded = false
8125
8568
  }) {
8126
- const [localValues, setLocalValues] = useState17(() => {
8569
+ const [localValues, setLocalValues] = useState18(() => {
8127
8570
  if (binding) {
8128
8571
  const values = {};
8129
8572
  binding.parameters.forEach((param) => {
@@ -8133,7 +8576,7 @@ function DeviceConfigPanel({
8133
8576
  }
8134
8577
  return {};
8135
8578
  });
8136
- const [collapsedSections, setCollapsedSections] = useState17(() => {
8579
+ const [collapsedSections, setCollapsedSections] = useState18(() => {
8137
8580
  const collapsed = /* @__PURE__ */ new Set();
8138
8581
  if (binding?.sections) {
8139
8582
  binding.sections.forEach((section) => {
@@ -8144,9 +8587,9 @@ function DeviceConfigPanel({
8144
8587
  }
8145
8588
  return collapsed;
8146
8589
  });
8147
- const [showToast, setShowToast] = useState17(true);
8148
- const [bindingId, setBindingId] = useState17(binding?.nodeId || null);
8149
- const lastResultTimestampRef = useRef7(0);
8590
+ const [showToast, setShowToast] = useState18(true);
8591
+ const [bindingId, setBindingId] = useState18(binding?.nodeId || null);
8592
+ const lastResultTimestampRef = useRef8(0);
8150
8593
  if (binding && binding.nodeId !== bindingId) {
8151
8594
  const values = {};
8152
8595
  binding.parameters.forEach((param) => {
@@ -8162,7 +8605,7 @@ function DeviceConfigPanel({
8162
8605
  setCollapsedSections(collapsed);
8163
8606
  setBindingId(binding.nodeId);
8164
8607
  }
8165
- useEffect12(() => {
8608
+ useEffect13(() => {
8166
8609
  const currentTimestamp = binding?.state.lastSaved || 0;
8167
8610
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8168
8611
  lastResultTimestampRef.current = currentTimestamp;
@@ -8267,14 +8710,14 @@ function DeviceConfigPanel({
8267
8710
  const value = localValues[param.id];
8268
8711
  const error = binding.state.errors?.[param.id];
8269
8712
  const isDisabled = param.readOnly || param.enabled === false;
8270
- return /* @__PURE__ */ jsxs18(
8713
+ return /* @__PURE__ */ jsxs19(
8271
8714
  "div",
8272
8715
  {
8273
8716
  style: {
8274
8717
  marginBottom: spacing.marginBottom
8275
8718
  },
8276
8719
  children: [
8277
- /* @__PURE__ */ jsxs18(
8720
+ /* @__PURE__ */ jsxs19(
8278
8721
  "label",
8279
8722
  {
8280
8723
  style: {
@@ -8289,8 +8732,8 @@ function DeviceConfigPanel({
8289
8732
  },
8290
8733
  children: [
8291
8734
  param.label,
8292
- param.required && /* @__PURE__ */ jsx22("span", { style: { color: errorColor }, children: " *" }),
8293
- 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: [
8294
8737
  " (",
8295
8738
  param.unit,
8296
8739
  ")"
@@ -8298,7 +8741,7 @@ function DeviceConfigPanel({
8298
8741
  ]
8299
8742
  }
8300
8743
  ),
8301
- param.description && /* @__PURE__ */ jsx22(
8744
+ param.description && /* @__PURE__ */ jsx23(
8302
8745
  "div",
8303
8746
  {
8304
8747
  style: {
@@ -8310,7 +8753,7 @@ function DeviceConfigPanel({
8310
8753
  children: param.description
8311
8754
  }
8312
8755
  ),
8313
- param.type === "number" && /* @__PURE__ */ jsx22(
8756
+ param.type === "number" && /* @__PURE__ */ jsx23(
8314
8757
  "input",
8315
8758
  {
8316
8759
  type: "number",
@@ -8334,7 +8777,7 @@ function DeviceConfigPanel({
8334
8777
  }
8335
8778
  }
8336
8779
  ),
8337
- param.type === "string" && /* @__PURE__ */ jsx22(
8780
+ param.type === "string" && /* @__PURE__ */ jsx23(
8338
8781
  "input",
8339
8782
  {
8340
8783
  type: "text",
@@ -8355,7 +8798,7 @@ function DeviceConfigPanel({
8355
8798
  }
8356
8799
  }
8357
8800
  ),
8358
- param.type === "boolean" && /* @__PURE__ */ jsxs18(
8801
+ param.type === "boolean" && /* @__PURE__ */ jsxs19(
8359
8802
  "label",
8360
8803
  {
8361
8804
  style: {
@@ -8365,7 +8808,7 @@ function DeviceConfigPanel({
8365
8808
  cursor: isDisabled ? "not-allowed" : "pointer"
8366
8809
  },
8367
8810
  children: [
8368
- /* @__PURE__ */ jsx22(
8811
+ /* @__PURE__ */ jsx23(
8369
8812
  "input",
8370
8813
  {
8371
8814
  type: "checkbox",
@@ -8379,11 +8822,11 @@ function DeviceConfigPanel({
8379
8822
  }
8380
8823
  }
8381
8824
  ),
8382
- /* @__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" })
8383
8826
  ]
8384
8827
  }
8385
8828
  ),
8386
- param.type === "select" && /* @__PURE__ */ jsx22(
8829
+ param.type === "select" && /* @__PURE__ */ jsx23(
8387
8830
  "select",
8388
8831
  {
8389
8832
  value: value ?? "",
@@ -8401,10 +8844,10 @@ function DeviceConfigPanel({
8401
8844
  borderRadius: "2px",
8402
8845
  outline: "none"
8403
8846
  },
8404
- 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))
8405
8848
  }
8406
8849
  ),
8407
- error && /* @__PURE__ */ jsx22(
8850
+ error && /* @__PURE__ */ jsx23(
8408
8851
  "div",
8409
8852
  {
8410
8853
  style: {
@@ -8424,7 +8867,7 @@ function DeviceConfigPanel({
8424
8867
  const renderSection = (section) => {
8425
8868
  const params = parametersBySection[section.id] || [];
8426
8869
  const isCollapsed = collapsedSections.has(section.id);
8427
- return /* @__PURE__ */ jsxs18(
8870
+ return /* @__PURE__ */ jsxs19(
8428
8871
  "div",
8429
8872
  {
8430
8873
  style: {
@@ -8434,7 +8877,7 @@ function DeviceConfigPanel({
8434
8877
  backgroundColor: surfaceColor
8435
8878
  },
8436
8879
  children: [
8437
- /* @__PURE__ */ jsxs18(
8880
+ /* @__PURE__ */ jsxs19(
8438
8881
  "div",
8439
8882
  {
8440
8883
  onClick: () => section.collapsible && toggleSection(section.id),
@@ -8447,8 +8890,8 @@ function DeviceConfigPanel({
8447
8890
  alignItems: "center"
8448
8891
  },
8449
8892
  children: [
8450
- /* @__PURE__ */ jsxs18("div", { children: [
8451
- /* @__PURE__ */ jsxs18(
8893
+ /* @__PURE__ */ jsxs19("div", { children: [
8894
+ /* @__PURE__ */ jsxs19(
8452
8895
  "div",
8453
8896
  {
8454
8897
  style: {
@@ -8460,12 +8903,12 @@ function DeviceConfigPanel({
8460
8903
  letterSpacing: "0.5px"
8461
8904
  },
8462
8905
  children: [
8463
- section.icon && /* @__PURE__ */ jsx22("span", { style: { marginRight: "8px" }, children: section.icon }),
8906
+ section.icon && /* @__PURE__ */ jsx23("span", { style: { marginRight: "8px" }, children: section.icon }),
8464
8907
  section.title
8465
8908
  ]
8466
8909
  }
8467
8910
  ),
8468
- section.description && /* @__PURE__ */ jsx22(
8911
+ section.description && /* @__PURE__ */ jsx23(
8469
8912
  "div",
8470
8913
  {
8471
8914
  style: {
@@ -8478,11 +8921,11 @@ function DeviceConfigPanel({
8478
8921
  }
8479
8922
  )
8480
8923
  ] }),
8481
- 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" })
8482
8925
  ]
8483
8926
  }
8484
8927
  ),
8485
- !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) })
8486
8929
  ]
8487
8930
  },
8488
8931
  section.id
@@ -8541,9 +8984,9 @@ function DeviceConfigPanel({
8541
8984
  const showSave = binding.display?.showSave !== false && binding.actions.onSave;
8542
8985
  const showReset = binding.display?.showReset !== false && binding.actions.onReset;
8543
8986
  const showCancel = binding.display?.showCancel !== false;
8544
- return /* @__PURE__ */ jsxs18(Fragment9, { children: [
8545
- /* @__PURE__ */ jsxs18("div", { style: panelStyle, className: binding.display?.className, children: [
8546
- /* @__PURE__ */ jsxs18(
8987
+ return /* @__PURE__ */ jsxs19(Fragment9, { children: [
8988
+ /* @__PURE__ */ jsxs19("div", { style: panelStyle, className: binding.display?.className, children: [
8989
+ /* @__PURE__ */ jsxs19(
8547
8990
  "div",
8548
8991
  {
8549
8992
  style: {
@@ -8555,8 +8998,8 @@ function DeviceConfigPanel({
8555
8998
  borderBottom: `2px solid ${borderColor}`
8556
8999
  },
8557
9000
  children: [
8558
- /* @__PURE__ */ jsxs18("div", { children: [
8559
- /* @__PURE__ */ jsx22(
9001
+ /* @__PURE__ */ jsxs19("div", { children: [
9002
+ /* @__PURE__ */ jsx23(
8560
9003
  "h3",
8561
9004
  {
8562
9005
  style: {
@@ -8576,7 +9019,7 @@ function DeviceConfigPanel({
8576
9019
  children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
8577
9020
  }
8578
9021
  ),
8579
- binding.display?.subtitle && /* @__PURE__ */ jsx22(
9022
+ binding.display?.subtitle && /* @__PURE__ */ jsx23(
8580
9023
  "div",
8581
9024
  {
8582
9025
  style: {
@@ -8589,8 +9032,8 @@ function DeviceConfigPanel({
8589
9032
  }
8590
9033
  )
8591
9034
  ] }),
8592
- /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: "8px" }, children: [
8593
- showControlsButton && onOpenControls && /* @__PURE__ */ jsx22(
9035
+ /* @__PURE__ */ jsxs19("div", { style: { display: "flex", gap: "8px" }, children: [
9036
+ showControlsButton && onOpenControls && /* @__PURE__ */ jsx23(
8594
9037
  "button",
8595
9038
  {
8596
9039
  onClick: onOpenControls,
@@ -8613,7 +9056,7 @@ function DeviceConfigPanel({
8613
9056
  children: "CTRL"
8614
9057
  }
8615
9058
  ),
8616
- onUndock && /* @__PURE__ */ jsx22(
9059
+ onUndock && /* @__PURE__ */ jsx23(
8617
9060
  "button",
8618
9061
  {
8619
9062
  onClick: onUndock,
@@ -8634,7 +9077,7 @@ function DeviceConfigPanel({
8634
9077
  children: undockIcon
8635
9078
  }
8636
9079
  ),
8637
- /* @__PURE__ */ jsx22(
9080
+ /* @__PURE__ */ jsx23(
8638
9081
  "button",
8639
9082
  {
8640
9083
  onClick: onClose,
@@ -8657,7 +9100,7 @@ function DeviceConfigPanel({
8657
9100
  ]
8658
9101
  }
8659
9102
  ),
8660
- binding.state.isDirty && /* @__PURE__ */ jsx22(
9103
+ binding.state.isDirty && /* @__PURE__ */ jsx23(
8661
9104
  "div",
8662
9105
  {
8663
9106
  style: {
@@ -8672,11 +9115,11 @@ function DeviceConfigPanel({
8672
9115
  children: "Unsaved changes"
8673
9116
  }
8674
9117
  ),
8675
- /* @__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) : (
8676
9119
  /* Render unsectioned parameters */
8677
- /* @__PURE__ */ jsx22("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
9120
+ /* @__PURE__ */ jsx23("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
8678
9121
  ) }),
8679
- /* @__PURE__ */ jsxs18(
9122
+ /* @__PURE__ */ jsxs19(
8680
9123
  "div",
8681
9124
  {
8682
9125
  style: {
@@ -8687,7 +9130,7 @@ function DeviceConfigPanel({
8687
9130
  flexWrap: "wrap"
8688
9131
  },
8689
9132
  children: [
8690
- showApply && /* @__PURE__ */ jsx22(
9133
+ showApply && /* @__PURE__ */ jsx23(
8691
9134
  "button",
8692
9135
  {
8693
9136
  onClick: handleApply,
@@ -8710,7 +9153,7 @@ function DeviceConfigPanel({
8710
9153
  children: binding.state.isSaving ? "Applying..." : "Apply"
8711
9154
  }
8712
9155
  ),
8713
- showSave && /* @__PURE__ */ jsx22(
9156
+ showSave && /* @__PURE__ */ jsx23(
8714
9157
  "button",
8715
9158
  {
8716
9159
  onClick: handleSave,
@@ -8733,7 +9176,7 @@ function DeviceConfigPanel({
8733
9176
  children: binding.state.isSaving ? "Saving..." : "Save"
8734
9177
  }
8735
9178
  ),
8736
- showReset && /* @__PURE__ */ jsx22(
9179
+ showReset && /* @__PURE__ */ jsx23(
8737
9180
  "button",
8738
9181
  {
8739
9182
  onClick: handleReset,
@@ -8756,7 +9199,7 @@ function DeviceConfigPanel({
8756
9199
  children: "Reset"
8757
9200
  }
8758
9201
  ),
8759
- showCancel && /* @__PURE__ */ jsx22(
9202
+ showCancel && /* @__PURE__ */ jsx23(
8760
9203
  "button",
8761
9204
  {
8762
9205
  onClick: handleCancel,
@@ -8783,7 +9226,7 @@ function DeviceConfigPanel({
8783
9226
  }
8784
9227
  )
8785
9228
  ] }),
8786
- binding.state.lastSaveResult && showToast && /* @__PURE__ */ jsx22(
9229
+ binding.state.lastSaveResult && showToast && /* @__PURE__ */ jsx23(
8787
9230
  "div",
8788
9231
  {
8789
9232
  style: {
@@ -8807,7 +9250,7 @@ function DeviceConfigPanel({
8807
9250
  }
8808
9251
 
8809
9252
  // src/diagram/hooks/useSimulation.ts
8810
- import { useEffect as useEffect13 } from "react";
9253
+ import { useEffect as useEffect14 } from "react";
8811
9254
  function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8812
9255
  const {
8813
9256
  interval = 2e3,
@@ -8818,7 +9261,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8818
9261
  historyLength = 10,
8819
9262
  generateValue
8820
9263
  } = options;
8821
- useEffect13(() => {
9264
+ useEffect14(() => {
8822
9265
  if (!enabled) return;
8823
9266
  const intervalId = setInterval(() => {
8824
9267
  const updates = [];
@@ -8890,6 +9333,7 @@ export {
8890
9333
  LegacyValueEntry,
8891
9334
  NodeConfigPanel,
8892
9335
  NodeControlsPanel,
9336
+ NumpadDialog,
8893
9337
  PIDCanvas,
8894
9338
  PanelContent,
8895
9339
  PanelTabs,