@procaaso/alphinity-ui-components 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -53,6 +53,7 @@ __export(index_exports, {
53
53
  LegacyValueEntry: () => LegacyValueEntry,
54
54
  NodeConfigPanel: () => NodeConfigPanel,
55
55
  NodeControlsPanel: () => NodeControlsPanel,
56
+ NumpadDialog: () => NumpadDialog,
56
57
  PIDCanvas: () => PIDCanvas,
57
58
  PanelContent: () => PanelContent,
58
59
  PanelTabs: () => PanelTabs,
@@ -1038,6 +1039,7 @@ function DeviceControlPanel({
1038
1039
  toastDuration = 3e3,
1039
1040
  onModeChange,
1040
1041
  onParameterChange,
1042
+ onParameterActivate,
1041
1043
  onStart,
1042
1044
  onStop,
1043
1045
  startPending = false,
@@ -1750,6 +1752,36 @@ function DeviceControlPanel({
1750
1752
  },
1751
1753
  children: param.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1752
1754
  }
1755
+ ) : onParameterActivate && !param.readOnly ? (
1756
+ // Tappable value: defer editing to the consumer's editor (e.g. a
1757
+ // numpad dialog). Commit happens via onParameterChange.
1758
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1759
+ "button",
1760
+ {
1761
+ type: "button",
1762
+ onClick: () => onParameterActivate(param.id, localParameterValues[param.id] ?? param.value),
1763
+ style: {
1764
+ width: "100%",
1765
+ height: touchSize,
1766
+ display: "flex",
1767
+ alignItems: "center",
1768
+ backgroundColor: "#ffffff",
1769
+ color: textColor,
1770
+ border: `1px solid ${borderColor}`,
1771
+ borderRadius: "6px",
1772
+ padding: "0 12px",
1773
+ fontSize: `${fontSize.input}px`,
1774
+ fontFamily: "Arial, sans-serif",
1775
+ fontWeight: 600,
1776
+ textAlign: "left",
1777
+ cursor: "pointer"
1778
+ },
1779
+ children: [
1780
+ localParameterValues[param.id] ?? param.value,
1781
+ param.unit ? ` ${param.unit}` : ""
1782
+ ]
1783
+ }
1784
+ )
1753
1785
  ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1754
1786
  "input",
1755
1787
  {
@@ -1912,14 +1944,457 @@ function DeviceControlPanel({
1912
1944
  ] });
1913
1945
  }
1914
1946
 
1947
+ // src/components/NumpadDialog/NumpadDialog.tsx
1948
+ var import_react6 = require("react");
1949
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1950
+ var NumpadDialog = ({
1951
+ isOpen,
1952
+ onClose,
1953
+ onApply,
1954
+ deviceName = "",
1955
+ parameterLabel = "Setpoint",
1956
+ unit = "",
1957
+ min = 0,
1958
+ max = 100,
1959
+ precision,
1960
+ currentValue = 0,
1961
+ touchOptimized = true
1962
+ }) => {
1963
+ const [inputValue, setInputValue] = (0, import_react6.useState)("");
1964
+ const [pristine, setPristine] = (0, import_react6.useState)(true);
1965
+ const dialogRef = (0, import_react6.useRef)(null);
1966
+ const titleId = (0, import_react6.useId)();
1967
+ const decimals = precision ?? 1;
1968
+ (0, import_react6.useEffect)(() => {
1969
+ if (isOpen) {
1970
+ setInputValue(Number(currentValue).toFixed(decimals));
1971
+ setPristine(true);
1972
+ }
1973
+ }, [isOpen, currentValue, decimals]);
1974
+ (0, import_react6.useEffect)(() => {
1975
+ if (!isOpen) return;
1976
+ const previouslyFocused = document.activeElement;
1977
+ dialogRef.current?.focus();
1978
+ return () => previouslyFocused?.focus?.();
1979
+ }, [isOpen]);
1980
+ (0, import_react6.useEffect)(() => {
1981
+ if (!isOpen) return;
1982
+ const prevOverflow = document.body.style.overflow;
1983
+ document.body.style.overflow = "hidden";
1984
+ return () => {
1985
+ document.body.style.overflow = prevOverflow;
1986
+ };
1987
+ }, [isOpen]);
1988
+ const handleApply = (0, import_react6.useCallback)(() => {
1989
+ const n = Number(inputValue);
1990
+ if (inputValue === "" || inputValue === "-" || inputValue === "." || inputValue === "-.") return;
1991
+ if (isNaN(n) || n < min || n > max) return;
1992
+ onApply(Number(n.toFixed(decimals)));
1993
+ }, [inputValue, min, max, onApply, decimals]);
1994
+ const appendDigit = (0, import_react6.useCallback)(
1995
+ (digit) => {
1996
+ setInputValue((prev) => {
1997
+ const base = pristine ? "" : prev;
1998
+ if (digit === ".") {
1999
+ if (decimals === 0) return base;
2000
+ if (base.includes(".")) return base;
2001
+ if (base === "" || base === "-") return base + "0.";
2002
+ return base + ".";
2003
+ }
2004
+ const dot = base.indexOf(".");
2005
+ if (dot !== -1 && base.length - dot - 1 >= decimals) return base;
2006
+ if (base === "0") return digit;
2007
+ if (base === "-0") return "-" + digit;
2008
+ return base + digit;
2009
+ });
2010
+ if (pristine) setPristine(false);
2011
+ },
2012
+ [pristine, decimals]
2013
+ );
2014
+ const handleBackspace = (0, import_react6.useCallback)(() => {
2015
+ setPristine(false);
2016
+ setInputValue((prev) => prev.slice(0, -1));
2017
+ }, []);
2018
+ const handleClear = (0, import_react6.useCallback)(() => {
2019
+ setPristine(false);
2020
+ setInputValue("");
2021
+ }, []);
2022
+ const handleToggleSign = (0, import_react6.useCallback)(() => {
2023
+ if (min >= 0) return;
2024
+ setPristine(false);
2025
+ setInputValue((prev) => {
2026
+ if (prev.startsWith("-")) return prev.slice(1);
2027
+ if (prev === "" || prev === "0") return "-";
2028
+ return "-" + prev;
2029
+ });
2030
+ }, [min]);
2031
+ const bsTimer = (0, import_react6.useRef)(null);
2032
+ const bsLongFired = (0, import_react6.useRef)(false);
2033
+ const clearBsTimer = () => {
2034
+ if (bsTimer.current !== null) {
2035
+ clearTimeout(bsTimer.current);
2036
+ bsTimer.current = null;
2037
+ }
2038
+ };
2039
+ const handleBackspacePointerDown = () => {
2040
+ bsLongFired.current = false;
2041
+ bsTimer.current = window.setTimeout(() => {
2042
+ bsLongFired.current = true;
2043
+ handleClear();
2044
+ }, 500);
2045
+ };
2046
+ const handleBackspaceClick = () => {
2047
+ clearBsTimer();
2048
+ if (bsLongFired.current) {
2049
+ bsLongFired.current = false;
2050
+ return;
2051
+ }
2052
+ handleBackspace();
2053
+ };
2054
+ (0, import_react6.useEffect)(() => () => clearBsTimer(), []);
2055
+ (0, import_react6.useEffect)(() => {
2056
+ if (!isOpen) return;
2057
+ const handler = (e) => {
2058
+ if (e.key === "Tab") {
2059
+ const root = dialogRef.current;
2060
+ if (!root) return;
2061
+ const focusable = Array.from(
2062
+ root.querySelectorAll("button:not([disabled])")
2063
+ ).filter((el) => el.tabIndex !== -1);
2064
+ if (focusable.length === 0) {
2065
+ e.preventDefault();
2066
+ root.focus();
2067
+ return;
2068
+ }
2069
+ const first = focusable[0];
2070
+ const last = focusable[focusable.length - 1];
2071
+ const active = document.activeElement;
2072
+ if (e.shiftKey) {
2073
+ if (active === first || !root.contains(active)) {
2074
+ e.preventDefault();
2075
+ last.focus();
2076
+ }
2077
+ } else if (active === last || !root.contains(active)) {
2078
+ e.preventDefault();
2079
+ first.focus();
2080
+ }
2081
+ return;
2082
+ }
2083
+ if (e.key === "Enter") {
2084
+ const active = document.activeElement;
2085
+ if (active && active.tagName === "BUTTON" && dialogRef.current?.contains(active)) return;
2086
+ e.preventDefault();
2087
+ handleApply();
2088
+ } else if (e.key === "Escape") {
2089
+ e.preventDefault();
2090
+ onClose();
2091
+ } else if (e.key === "Backspace") {
2092
+ e.preventDefault();
2093
+ handleBackspace();
2094
+ } else if (/^[0-9]$/.test(e.key)) {
2095
+ e.preventDefault();
2096
+ appendDigit(e.key);
2097
+ } else if (e.key === ".") {
2098
+ e.preventDefault();
2099
+ appendDigit(".");
2100
+ } else if (e.key === "-") {
2101
+ e.preventDefault();
2102
+ handleToggleSign();
2103
+ }
2104
+ };
2105
+ window.addEventListener("keydown", handler);
2106
+ return () => window.removeEventListener("keydown", handler);
2107
+ }, [isOpen, handleApply, onClose, handleBackspace, appendDigit, handleToggleSign]);
2108
+ if (!isOpen) return null;
2109
+ const parsed = Number(inputValue);
2110
+ const hasNumber = inputValue !== "" && inputValue !== "-" && inputValue !== "." && inputValue !== "-." && !isNaN(parsed);
2111
+ const belowMin = hasNumber && parsed < min;
2112
+ const aboveMax = hasNumber && parsed > max;
2113
+ const outOfRange = belowMin || aboveMax;
2114
+ const isValid = hasNumber && !outOfRange;
2115
+ const alarmColor = "#dc2626";
2116
+ const limitStyle = (violated) => violated ? { color: alarmColor, fontWeight: 700, background: "#fee2e2", borderRadius: 3, padding: "0 3px" } : {};
2117
+ const keySize = touchOptimized ? 60 : 46;
2118
+ const keyFont = touchOptimized ? 22 : 18;
2119
+ const actionSize = touchOptimized ? 52 : 42;
2120
+ const keyStyle = {
2121
+ minWidth: 52,
2122
+ minHeight: keySize,
2123
+ fontSize: keyFont,
2124
+ fontWeight: 600,
2125
+ borderRadius: 8,
2126
+ border: "1px solid #e2e8f0",
2127
+ background: "#ffffff",
2128
+ color: "#0f172a",
2129
+ cursor: "pointer",
2130
+ display: "flex",
2131
+ alignItems: "center",
2132
+ justifyContent: "center",
2133
+ userSelect: "none",
2134
+ boxShadow: "0 1px 2px rgba(15, 23, 42, 0.06)"
2135
+ };
2136
+ const utilKeyStyle = {
2137
+ flex: 1,
2138
+ minHeight: touchOptimized ? 44 : 38,
2139
+ fontSize: 13,
2140
+ fontWeight: 600,
2141
+ borderRadius: 8,
2142
+ border: "1px solid #e2e8f0",
2143
+ background: "#f8fafc",
2144
+ color: "#64748b",
2145
+ cursor: "pointer",
2146
+ display: "flex",
2147
+ alignItems: "center",
2148
+ justifyContent: "center",
2149
+ userSelect: "none"
2150
+ };
2151
+ const reason = belowMin ? `Below minimum of ${min} ${unit}` : aboveMax ? `Above maximum of ${max} ${unit}` : "Type or tap to change the value";
2152
+ const backspaceInGrid = min >= 0;
2153
+ const BackspaceButton = ({ style, label }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2154
+ "button",
2155
+ {
2156
+ type: "button",
2157
+ className: "np-key",
2158
+ tabIndex: -1,
2159
+ "aria-label": "Backspace",
2160
+ style,
2161
+ onPointerDown: handleBackspacePointerDown,
2162
+ onPointerUp: clearBsTimer,
2163
+ onPointerLeave: clearBsTimer,
2164
+ onClick: handleBackspaceClick,
2165
+ children: label
2166
+ }
2167
+ );
2168
+ return (
2169
+ // Backdrop
2170
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2171
+ "div",
2172
+ {
2173
+ style: {
2174
+ position: "fixed",
2175
+ top: 0,
2176
+ left: 0,
2177
+ right: 0,
2178
+ bottom: 0,
2179
+ backgroundColor: "rgba(15, 23, 42, 0.4)",
2180
+ zIndex: 1e4,
2181
+ display: "flex",
2182
+ alignItems: "center",
2183
+ justifyContent: "center"
2184
+ },
2185
+ onClick: onClose,
2186
+ children: [
2187
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("style", { children: `
2188
+ .np-key { transition: background .1s, transform .05s; touch-action: manipulation; }
2189
+ .np-key:active:not(:disabled) { background:#e2e8f0; transform: translateY(1px); }
2190
+ .np-key:focus-visible, .np-action:focus-visible { outline: 3px solid #2563eb; outline-offset: 2px; }
2191
+ @keyframes np-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }
2192
+ .np-caret { display:inline-block; width:2px; height:1.1em; background:#2563eb; animation: np-blink 1s step-end infinite; }
2193
+ ` }),
2194
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2195
+ "div",
2196
+ {
2197
+ ref: dialogRef,
2198
+ role: "dialog",
2199
+ "aria-modal": "true",
2200
+ "aria-labelledby": titleId,
2201
+ tabIndex: -1,
2202
+ style: {
2203
+ width: touchOptimized ? "340px" : "300px",
2204
+ maxHeight: "90vh",
2205
+ overflow: "auto",
2206
+ background: "#ffffff",
2207
+ borderRadius: 12,
2208
+ border: "1px solid #e2e8f0",
2209
+ boxShadow: "0 10px 40px rgba(15, 23, 42, 0.2)",
2210
+ fontFamily: "'Inter', system-ui, sans-serif",
2211
+ outline: "none"
2212
+ },
2213
+ onClick: (e) => e.stopPropagation(),
2214
+ children: [
2215
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { padding: "14px 16px 0 16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { id: titleId, style: { margin: 0, fontSize: 15, fontWeight: 700, color: "#0f172a" }, children: deviceName ? `${deviceName} - ${parameterLabel}` : parameterLabel }) }),
2216
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { padding: 16, display: "flex", flexDirection: "column", gap: 10 }, children: [
2217
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2218
+ "div",
2219
+ {
2220
+ style: {
2221
+ display: "flex",
2222
+ justifyContent: "space-between",
2223
+ fontSize: 12,
2224
+ color: "#64748b"
2225
+ },
2226
+ children: [
2227
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
2228
+ "Current: ",
2229
+ currentValue,
2230
+ " ",
2231
+ unit
2232
+ ] }),
2233
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
2234
+ "Range: ",
2235
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: limitStyle(belowMin), children: min }),
2236
+ "-",
2237
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: limitStyle(aboveMax), children: max }),
2238
+ " ",
2239
+ unit
2240
+ ] })
2241
+ ]
2242
+ }
2243
+ ),
2244
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2245
+ "div",
2246
+ {
2247
+ "aria-live": "polite",
2248
+ "aria-atomic": "true",
2249
+ "aria-label": `Entered value ${inputValue || "0"} ${unit}`,
2250
+ style: {
2251
+ background: outOfRange ? "#fef2f2" : "#f8fafc",
2252
+ borderRadius: 8,
2253
+ padding: "10px 14px",
2254
+ fontSize: 28,
2255
+ fontWeight: 700,
2256
+ textAlign: "right",
2257
+ color: outOfRange ? alarmColor : "#0f172a",
2258
+ minHeight: 48,
2259
+ display: "flex",
2260
+ alignItems: "center",
2261
+ justifyContent: "flex-end",
2262
+ gap: 6,
2263
+ border: outOfRange ? "1.5px solid #fca5a5" : "1.5px solid #e2e8f0"
2264
+ },
2265
+ children: [
2266
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: inputValue || "0" }),
2267
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "np-caret", "aria-hidden": "true" }),
2268
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: 14, color: "#94a3b8", fontWeight: 500 }, children: unit })
2269
+ ]
2270
+ }
2271
+ ),
2272
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2273
+ "div",
2274
+ {
2275
+ role: "status",
2276
+ "aria-live": "polite",
2277
+ style: {
2278
+ fontSize: 12,
2279
+ color: outOfRange ? alarmColor : "#94a3b8",
2280
+ fontWeight: outOfRange ? 600 : 400,
2281
+ textAlign: "right",
2282
+ minHeight: 16
2283
+ },
2284
+ children: reason
2285
+ }
2286
+ ),
2287
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 5 }, children: [
2288
+ ["7", "8", "9", "4", "5", "6", "1", "2", "3"].map((digit) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2289
+ "button",
2290
+ {
2291
+ type: "button",
2292
+ className: "np-key",
2293
+ tabIndex: -1,
2294
+ style: keyStyle,
2295
+ onClick: () => appendDigit(digit),
2296
+ children: digit
2297
+ },
2298
+ digit
2299
+ )),
2300
+ min < 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2301
+ "button",
2302
+ {
2303
+ type: "button",
2304
+ className: "np-key",
2305
+ tabIndex: -1,
2306
+ "aria-label": "Toggle sign",
2307
+ style: { ...keyStyle, fontSize: 16, background: "#f8fafc", color: "#64748b" },
2308
+ onClick: handleToggleSign,
2309
+ children: "+/\u2212"
2310
+ }
2311
+ ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BackspaceButton, { style: { ...keyStyle, fontSize: 20, background: "#f8fafc", color: "#64748b" }, label: "\u232B" }),
2312
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "np-key", tabIndex: -1, style: keyStyle, onClick: () => appendDigit("0"), children: "0" }),
2313
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2314
+ "button",
2315
+ {
2316
+ type: "button",
2317
+ className: "np-key",
2318
+ tabIndex: -1,
2319
+ "aria-label": "Decimal point",
2320
+ style: {
2321
+ ...keyStyle,
2322
+ cursor: decimals === 0 ? "not-allowed" : "pointer",
2323
+ opacity: decimals === 0 ? 0.4 : 1
2324
+ },
2325
+ disabled: decimals === 0,
2326
+ onClick: () => appendDigit("."),
2327
+ children: "."
2328
+ }
2329
+ )
2330
+ ] }),
2331
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: 5 }, children: [
2332
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "np-key", tabIndex: -1, style: utilKeyStyle, onClick: handleClear, children: "Clear" }),
2333
+ !backspaceInGrid && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(BackspaceButton, { style: utilKeyStyle, label: "Backspace" })
2334
+ ] }),
2335
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 2 }, children: [
2336
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2337
+ "button",
2338
+ {
2339
+ type: "button",
2340
+ className: "np-action",
2341
+ onClick: onClose,
2342
+ style: {
2343
+ flex: 1,
2344
+ minHeight: actionSize,
2345
+ borderRadius: 8,
2346
+ border: "1px solid #e2e8f0",
2347
+ background: "#ffffff",
2348
+ color: "#0f172a",
2349
+ fontSize: 14,
2350
+ fontWeight: 600,
2351
+ cursor: "pointer"
2352
+ },
2353
+ children: "Cancel"
2354
+ }
2355
+ ),
2356
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2357
+ "button",
2358
+ {
2359
+ type: "button",
2360
+ className: "np-action",
2361
+ onClick: handleApply,
2362
+ disabled: !isValid,
2363
+ "aria-label": isValid ? `Apply ${inputValue} ${unit}` : "Apply (enter a valid value)",
2364
+ style: {
2365
+ flex: 1,
2366
+ minHeight: actionSize,
2367
+ borderRadius: 8,
2368
+ border: "none",
2369
+ background: "#2563eb",
2370
+ color: "#ffffff",
2371
+ fontSize: 14,
2372
+ fontWeight: 600,
2373
+ cursor: isValid ? "pointer" : "not-allowed",
2374
+ opacity: isValid ? 1 : 0.4
2375
+ },
2376
+ children: "Apply"
2377
+ }
2378
+ )
2379
+ ] })
2380
+ ] })
2381
+ ]
2382
+ }
2383
+ )
2384
+ ]
2385
+ }
2386
+ )
2387
+ );
2388
+ };
2389
+
1915
2390
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
1916
- var import_react7 = __toESM(require("react"), 1);
2391
+ var import_react8 = __toESM(require("react"), 1);
1917
2392
  var import_material3 = require("@mui/material");
1918
2393
 
1919
2394
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
1920
2395
  var import_material = require("@mui/material");
1921
2396
  var import_styled = __toESM(require("@emotion/styled"), 1);
1922
- var import_jsx_runtime9 = require("react/jsx-runtime");
2397
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1923
2398
  var FullscreenContainer = (0, import_styled.default)(import_material.Box)(
1924
2399
  ({ leftCollapsed, rightCollapsed }) => {
1925
2400
  const getGridTemplateAreas = () => {
@@ -2044,7 +2519,7 @@ var DisplayModeToggle = (0, import_styled.default)(import_material.IconButton)((
2044
2519
  transform: "translateX(-50%) scale(1.05)"
2045
2520
  }
2046
2521
  }));
2047
- var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2522
+ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2048
2523
  "div",
2049
2524
  {
2050
2525
  style: {
@@ -2056,7 +2531,7 @@ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2056
2531
  }
2057
2532
  }
2058
2533
  );
2059
- var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2534
+ var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2060
2535
  "div",
2061
2536
  {
2062
2537
  style: {
@@ -2167,10 +2642,10 @@ var ScrollableSVGWrapper = (0, import_styled.default)("div")({
2167
2642
  });
2168
2643
 
2169
2644
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
2170
- var import_react6 = require("react");
2645
+ var import_react7 = require("react");
2171
2646
  var import_material2 = require("@mui/material");
2172
2647
  var import_styled2 = __toESM(require("@emotion/styled"), 1);
2173
- var import_jsx_runtime10 = require("react/jsx-runtime");
2648
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2174
2649
  var baseOverlayStyles = {
2175
2650
  tank: {
2176
2651
  background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
@@ -2232,8 +2707,8 @@ var SVGLockedOverlay = ({
2232
2707
  onClick,
2233
2708
  containerSelector = ".tff-svg-container"
2234
2709
  }) => {
2235
- const [svgOffset, setSvgOffset] = (0, import_react6.useState)({ x: 0, y: 0 });
2236
- (0, import_react6.useEffect)(() => {
2710
+ const [svgOffset, setSvgOffset] = (0, import_react7.useState)({ x: 0, y: 0 });
2711
+ (0, import_react7.useEffect)(() => {
2237
2712
  const updateSvgOffset = () => {
2238
2713
  const containerElement = document.querySelector(containerSelector);
2239
2714
  const svgElement = containerElement?.querySelector("svg");
@@ -2253,7 +2728,7 @@ var SVGLockedOverlay = ({
2253
2728
  const pixelX = svgX + svgOffset.x;
2254
2729
  const pixelY = svgY + svgOffset.y;
2255
2730
  const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
2256
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2731
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2257
2732
  import_material2.Box,
2258
2733
  {
2259
2734
  className: `svg-locked-overlay ${className}`.trim(),
@@ -2317,7 +2792,7 @@ var CardUnit = (0, import_styled2.default)("div")({
2317
2792
  });
2318
2793
 
2319
2794
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
2320
- var import_jsx_runtime11 = require("react/jsx-runtime");
2795
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2321
2796
  var TrendLine = ({
2322
2797
  values,
2323
2798
  width = 60,
@@ -2327,7 +2802,7 @@ var TrendLine = ({
2327
2802
  backgroundColor = "rgba(255, 255, 255, 0.1)"
2328
2803
  }) => {
2329
2804
  if (!values || values.length < 2) {
2330
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2805
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2331
2806
  "div",
2332
2807
  {
2333
2808
  style: {
@@ -2339,7 +2814,7 @@ var TrendLine = ({
2339
2814
  alignItems: "center",
2340
2815
  justifyContent: "center"
2341
2816
  },
2342
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
2817
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: "8px", color: "#ccc" }, children: "No data" })
2343
2818
  }
2344
2819
  );
2345
2820
  }
@@ -2351,7 +2826,7 @@ var TrendLine = ({
2351
2826
  const x = 4 + i / (values.length - 1) * (width - 8);
2352
2827
  return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
2353
2828
  }).join(" ");
2354
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2829
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2355
2830
  "div",
2356
2831
  {
2357
2832
  style: {
@@ -2362,8 +2837,8 @@ var TrendLine = ({
2362
2837
  position: "relative",
2363
2838
  overflow: "hidden"
2364
2839
  },
2365
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2366
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2840
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2841
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2367
2842
  "path",
2368
2843
  {
2369
2844
  d: pathData,
@@ -2374,7 +2849,7 @@ var TrendLine = ({
2374
2849
  strokeLinejoin: "round"
2375
2850
  }
2376
2851
  ),
2377
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2852
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2378
2853
  "circle",
2379
2854
  {
2380
2855
  cx: 4 + (width - 8),
@@ -2412,7 +2887,7 @@ var CircularGauge = ({
2412
2887
  const borderColor = isHex ? hexToRgba(color, 0.9) : color;
2413
2888
  const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
2414
2889
  const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
2415
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2416
2891
  "div",
2417
2892
  {
2418
2893
  style: {
@@ -2421,7 +2896,7 @@ var CircularGauge = ({
2421
2896
  alignItems: "center"
2422
2897
  },
2423
2898
  children: [
2424
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2899
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2425
2900
  "div",
2426
2901
  {
2427
2902
  style: {
@@ -2433,8 +2908,8 @@ var CircularGauge = ({
2433
2908
  border: `1px solid ${borderStrokeColor}`
2434
2909
  },
2435
2910
  children: [
2436
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2437
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2911
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2912
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2438
2913
  "circle",
2439
2914
  {
2440
2915
  cx: size / 2,
@@ -2445,7 +2920,7 @@ var CircularGauge = ({
2445
2920
  strokeWidth: 1
2446
2921
  }
2447
2922
  ),
2448
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2923
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2449
2924
  "circle",
2450
2925
  {
2451
2926
  cx: size / 2,
@@ -2456,7 +2931,7 @@ var CircularGauge = ({
2456
2931
  fill: "transparent"
2457
2932
  }
2458
2933
  ),
2459
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2934
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2460
2935
  "circle",
2461
2936
  {
2462
2937
  cx: size / 2,
@@ -2472,7 +2947,7 @@ var CircularGauge = ({
2472
2947
  }
2473
2948
  )
2474
2949
  ] }),
2475
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2950
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2476
2951
  "div",
2477
2952
  {
2478
2953
  style: {
@@ -2488,14 +2963,14 @@ var CircularGauge = ({
2488
2963
  },
2489
2964
  children: [
2490
2965
  value.toFixed(1),
2491
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
2966
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontSize: "8px", opacity: 0.9, color: "white" }, children: unit })
2492
2967
  ]
2493
2968
  }
2494
2969
  )
2495
2970
  ]
2496
2971
  }
2497
2972
  ),
2498
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2973
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2499
2974
  "div",
2500
2975
  {
2501
2976
  style: {
@@ -2526,7 +3001,7 @@ var Sparkline = ({ data, width, height, color }) => {
2526
3001
  const y = height - 8 - (value - min) / range * (height - 8);
2527
3002
  return `${x + 4},${y + 4}`;
2528
3003
  }).join(" ");
2529
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3004
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2530
3005
  "div",
2531
3006
  {
2532
3007
  style: {
@@ -2540,7 +3015,7 @@ var Sparkline = ({ data, width, height, color }) => {
2540
3015
  justifyContent: "center",
2541
3016
  boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
2542
3017
  },
2543
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { width, height, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
3018
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { width, height, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("polyline", { points, fill: "none", stroke: color, strokeWidth: "1.5", opacity: "0.9" }) })
2544
3019
  }
2545
3020
  );
2546
3021
  };
@@ -2554,8 +3029,8 @@ var EquipmentIndicatorWithSparkline = ({
2554
3029
  sparklineOffset = { x: 40, y: 0 }
2555
3030
  }) => {
2556
3031
  const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
2557
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2558
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3032
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3033
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SVGLockedOverlay, { svgX, svgY, style: { transform: "translate(-50%, -50%)" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2559
3034
  "div",
2560
3035
  {
2561
3036
  style: {
@@ -2576,7 +3051,7 @@ var EquipmentIndicatorWithSparkline = ({
2576
3051
  children: label
2577
3052
  }
2578
3053
  ) }),
2579
- hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
3054
+ hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SVGLockedOverlay, { svgX: svgX + sparklineOffset.x, svgY: svgY + sparklineOffset.y, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Sparkline, { data: sparklineData, width: 60, height: 20, color }) })
2580
3055
  ] });
2581
3056
  };
2582
3057
  var EquipmentIndicator = ({
@@ -2589,7 +3064,7 @@ var EquipmentIndicator = ({
2589
3064
  className
2590
3065
  }) => {
2591
3066
  const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
2592
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3067
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SVGLockedOverlay, { svgX, svgY, style: overlayStyle, className, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2593
3068
  "div",
2594
3069
  {
2595
3070
  style: {
@@ -2613,7 +3088,7 @@ var EquipmentIndicator = ({
2613
3088
  };
2614
3089
 
2615
3090
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
2616
- var import_jsx_runtime12 = require("react/jsx-runtime");
3091
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2617
3092
  function FullscreenWorkspace({
2618
3093
  svgContent,
2619
3094
  overlays,
@@ -2641,10 +3116,10 @@ function FullscreenWorkspace({
2641
3116
  className = "",
2642
3117
  ...rest
2643
3118
  }) {
2644
- const [leftCollapsedState, setLeftCollapsedState] = import_react7.default.useState(defaultLeftCollapsed);
2645
- const [rightCollapsedState, setRightCollapsedState] = import_react7.default.useState(defaultRightCollapsed);
2646
- const [internalDisplayMode, setInternalDisplayMode] = import_react7.default.useState(displayMode ?? defaultDisplayMode);
2647
- const [internalTab, setInternalTab] = import_react7.default.useState(
3119
+ const [leftCollapsedState, setLeftCollapsedState] = import_react8.default.useState(defaultLeftCollapsed);
3120
+ const [rightCollapsedState, setRightCollapsedState] = import_react8.default.useState(defaultRightCollapsed);
3121
+ const [internalDisplayMode, setInternalDisplayMode] = import_react8.default.useState(displayMode ?? defaultDisplayMode);
3122
+ const [internalTab, setInternalTab] = import_react8.default.useState(
2648
3123
  tabs && tabs.length > 0 ? tabs[0].value : ""
2649
3124
  );
2650
3125
  const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
@@ -2652,10 +3127,10 @@ function FullscreenWorkspace({
2652
3127
  const isDisplayModeControlled = displayMode !== void 0;
2653
3128
  const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
2654
3129
  const isTabControlled = activeTab !== void 0 && activeTab !== null;
2655
- const resolvedTabs = import_react7.default.useMemo(() => tabs ?? [], [tabs]);
3130
+ const resolvedTabs = import_react8.default.useMemo(() => tabs ?? [], [tabs]);
2656
3131
  const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
2657
3132
  const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
2658
- import_react7.default.useEffect(() => {
3133
+ import_react8.default.useEffect(() => {
2659
3134
  if (resolvedTabs.length > 0) {
2660
3135
  const values = resolvedTabs.map((tab) => tab.value);
2661
3136
  if (!values.includes(currentTab)) {
@@ -2664,7 +3139,7 @@ function FullscreenWorkspace({
2664
3139
  }
2665
3140
  }
2666
3141
  }, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
2667
- import_react7.default.useEffect(() => {
3142
+ import_react8.default.useEffect(() => {
2668
3143
  if (displayMode !== void 0) {
2669
3144
  setInternalDisplayMode(displayMode);
2670
3145
  }
@@ -2699,7 +3174,7 @@ function FullscreenWorkspace({
2699
3174
  const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
2700
3175
  const showLeftToggle = Boolean(leftPanel);
2701
3176
  const showRightToggle = Boolean(rightPanel);
2702
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3177
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2703
3178
  FullscreenContainer,
2704
3179
  {
2705
3180
  leftCollapsed,
@@ -2707,25 +3182,25 @@ function FullscreenWorkspace({
2707
3182
  className: `tff-svg-container ${className}`.trim(),
2708
3183
  ...rest,
2709
3184
  children: [
2710
- showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3185
+ showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2711
3186
  LeftToggleButton,
2712
3187
  {
2713
3188
  collapsed: leftCollapsed,
2714
3189
  onClick: handleLeftToggle,
2715
3190
  "aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
2716
- children: leftCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRight, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronLeft, {})
3191
+ children: leftCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronRight, {}) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronLeft, {})
2717
3192
  }
2718
3193
  ),
2719
- showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3194
+ showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2720
3195
  RightToggleButton,
2721
3196
  {
2722
3197
  collapsed: rightCollapsed,
2723
3198
  onClick: handleRightToggle,
2724
3199
  "aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
2725
- children: rightCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronLeft, {}) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronRight, {})
3200
+ children: rightCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronLeft, {}) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronRight, {})
2726
3201
  }
2727
3202
  ),
2728
- showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3203
+ showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2729
3204
  DisplayModeToggle,
2730
3205
  {
2731
3206
  mode: currentDisplayMode,
@@ -2734,9 +3209,9 @@ function FullscreenWorkspace({
2734
3209
  children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
2735
3210
  }
2736
3211
  ),
2737
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SVGArea, { children: [
2738
- showZoomControls && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(ZoomControls, { children: [
2739
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3212
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(SVGArea, { children: [
3213
+ showZoomControls && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ZoomControls, { children: [
3214
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2740
3215
  ZoomButton,
2741
3216
  {
2742
3217
  onClick: onZoomIn,
@@ -2746,7 +3221,7 @@ function FullscreenWorkspace({
2746
3221
  children: "+"
2747
3222
  }
2748
3223
  ),
2749
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3224
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2750
3225
  ZoomButton,
2751
3226
  {
2752
3227
  onClick: onZoomOut,
@@ -2756,7 +3231,7 @@ function FullscreenWorkspace({
2756
3231
  children: "-"
2757
3232
  }
2758
3233
  ),
2759
- onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3234
+ onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2760
3235
  ZoomButton,
2761
3236
  {
2762
3237
  onClick: onResetZoom,
@@ -2767,44 +3242,44 @@ function FullscreenWorkspace({
2767
3242
  }
2768
3243
  )
2769
3244
  ] }),
2770
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(FixedSVGContainer, { className: "svg-container", children: [
3245
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollableSVGWrapper, { className: "svg-scroll-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(FixedSVGContainer, { className: "svg-container", children: [
2771
3246
  svgContent,
2772
3247
  overlays
2773
3248
  ] }) })
2774
3249
  ] }),
2775
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2776
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3250
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3251
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2777
3252
  PanelTabs,
2778
3253
  {
2779
3254
  value: currentTab,
2780
3255
  onChange: handleTabChangeInternal,
2781
3256
  "aria-label": "Left panel tabs",
2782
- children: resolvedTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material3.Tab, { label: tab.label, value: tab.value }, tab.value))
3257
+ children: resolvedTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material3.Tab, { label: tab.label, value: tab.value }, tab.value))
2783
3258
  }
2784
3259
  ),
2785
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PanelContent, { children: currentTabContent })
3260
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PanelContent, { children: currentTabContent })
2786
3261
  ] }) : leftPanel }),
2787
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
2788
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FooterPanel, { children: footer })
3262
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
3263
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FooterPanel, { children: footer })
2789
3264
  ]
2790
3265
  }
2791
3266
  );
2792
3267
  }
2793
3268
 
2794
3269
  // src/theme/ThemeContext.tsx
2795
- var import_react8 = require("react");
2796
- var import_jsx_runtime13 = require("react/jsx-runtime");
2797
- var ThemeContext = (0, import_react8.createContext)(void 0);
3270
+ var import_react9 = require("react");
3271
+ var import_jsx_runtime14 = require("react/jsx-runtime");
3272
+ var ThemeContext = (0, import_react9.createContext)(void 0);
2798
3273
  var useTheme = () => {
2799
- const context = (0, import_react8.useContext)(ThemeContext);
3274
+ const context = (0, import_react9.useContext)(ThemeContext);
2800
3275
  if (!context) {
2801
3276
  throw new Error("useTheme must be used within a ThemeProvider");
2802
3277
  }
2803
3278
  return context;
2804
3279
  };
2805
3280
  var ThemeProvider = ({ children }) => {
2806
- const [theme, setThemeState] = (0, import_react8.useState)("modern");
2807
- (0, import_react8.useEffect)(() => {
3281
+ const [theme, setThemeState] = (0, import_react9.useState)("modern");
3282
+ (0, import_react9.useEffect)(() => {
2808
3283
  document.body.className = "";
2809
3284
  document.body.classList.add(`theme-${theme}`);
2810
3285
  document.documentElement.className = "";
@@ -2816,11 +3291,11 @@ var ThemeProvider = ({ children }) => {
2816
3291
  const setTheme = (newTheme) => {
2817
3292
  setThemeState(newTheme);
2818
3293
  };
2819
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
3294
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ThemeContext.Provider, { value: { theme, toggleTheme, setTheme }, children });
2820
3295
  };
2821
3296
 
2822
3297
  // src/theme/ThemeToggle.tsx
2823
- var import_jsx_runtime14 = require("react/jsx-runtime");
3298
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2824
3299
  var ThemeToggle = ({
2825
3300
  size = "medium",
2826
3301
  position = "top-right",
@@ -2891,15 +3366,15 @@ var ThemeToggle = ({
2891
3366
  transition: "all 0.2s ease",
2892
3367
  boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
2893
3368
  };
2894
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
2895
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
2896
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: toggleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: thumbStyle }) }),
2897
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
3369
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
3370
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
3371
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: toggleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: thumbStyle }) }),
3372
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontSize: "0.75rem", opacity: 0.8 }, children: theme === "modern" ? "Industrial Design" : "High Performance" })
2898
3373
  ] });
2899
3374
  };
2900
3375
 
2901
3376
  // src/components/PIDCanvas/PIDCanvas.tsx
2902
- var import_react16 = require("react");
3377
+ var import_react17 = require("react");
2903
3378
 
2904
3379
  // src/diagram/symbols/mockSymbolLibrary.ts
2905
3380
  var mockSymbolLibrary = {
@@ -4120,7 +4595,7 @@ function getAvailableSymbols() {
4120
4595
  }
4121
4596
 
4122
4597
  // src/components/PIDCanvas/NodeRenderer.tsx
4123
- var import_jsx_runtime15 = require("react/jsx-runtime");
4598
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4124
4599
  function NodeRenderer({
4125
4600
  nodes: nodes2,
4126
4601
  selectedNodeIds,
@@ -4132,13 +4607,13 @@ function NodeRenderer({
4132
4607
  enableDrag = false,
4133
4608
  statusColorMap
4134
4609
  }) {
4135
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
4610
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("g", { id: "layer-nodes", children: nodes2.filter((node) => node.visible !== false).map((node) => {
4136
4611
  const symbol = getSymbolDefinition(node.symbolId);
4137
4612
  const isSelected = selectedNodeIds?.has(node.id) ?? false;
4138
4613
  const isDragging = draggingNodeId === node.id;
4139
4614
  if (!symbol) {
4140
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { children: [
4141
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4615
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
4616
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4142
4617
  "circle",
4143
4618
  {
4144
4619
  cx: node.transform.x,
@@ -4150,7 +4625,7 @@ function NodeRenderer({
4150
4625
  strokeWidth: "2"
4151
4626
  }
4152
4627
  ),
4153
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4628
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4154
4629
  "text",
4155
4630
  {
4156
4631
  x: node.transform.x,
@@ -4192,7 +4667,7 @@ function NodeRenderer({
4192
4667
  const statusEntry = resolveStatusColor(node.status, statusColorMap);
4193
4668
  const fillColor = node.customColors?.fill ?? statusEntry.fill;
4194
4669
  const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
4195
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4670
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4196
4671
  "g",
4197
4672
  {
4198
4673
  "data-node-id": node.id,
@@ -4225,7 +4700,7 @@ function NodeRenderer({
4225
4700
  }
4226
4701
  },
4227
4702
  children: [
4228
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4703
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4229
4704
  "rect",
4230
4705
  {
4231
4706
  x: "-5",
@@ -4240,7 +4715,7 @@ function NodeRenderer({
4240
4715
  pointerEvents: "none"
4241
4716
  }
4242
4717
  ),
4243
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4718
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4244
4719
  "g",
4245
4720
  {
4246
4721
  dangerouslySetInnerHTML: { __html: symbol.svgContent },
@@ -4248,7 +4723,7 @@ function NodeRenderer({
4248
4723
  style: { pointerEvents: "auto" }
4249
4724
  }
4250
4725
  ),
4251
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4726
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4252
4727
  "text",
4253
4728
  {
4254
4729
  x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
@@ -4269,7 +4744,7 @@ function NodeRenderer({
4269
4744
  }
4270
4745
 
4271
4746
  // src/components/PIDCanvas/PipeRenderer.tsx
4272
- var import_jsx_runtime16 = require("react/jsx-runtime");
4747
+ var import_jsx_runtime17 = require("react/jsx-runtime");
4273
4748
  function PipeRenderer({
4274
4749
  pipes,
4275
4750
  selectedPipeIds,
@@ -4284,7 +4759,7 @@ function PipeRenderer({
4284
4759
  waypointDragOffset,
4285
4760
  onPipeSegmentClick
4286
4761
  }) {
4287
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
4762
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "layer-pipes", children: pipes.filter((pipe) => pipe.visible !== false).map((pipe) => {
4288
4763
  const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
4289
4764
  const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
4290
4765
  const showEditingControls = enableWaypointEditing && isSelected;
@@ -4303,7 +4778,7 @@ function PipeRenderer({
4303
4778
  const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
4304
4779
  const strokeDasharray = pipeStyle.strokeDasharray;
4305
4780
  const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
4306
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4781
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4307
4782
  "g",
4308
4783
  {
4309
4784
  "data-pipe-id": pipe.id,
@@ -4316,8 +4791,8 @@ function PipeRenderer({
4316
4791
  cursor: onPipeClick ? "pointer" : "default"
4317
4792
  },
4318
4793
  children: [
4319
- !enableWaypointEditing && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
4320
- onPipeClick && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4794
+ !enableWaypointEditing && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4795
+ onPipeClick && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4321
4796
  "polyline",
4322
4797
  {
4323
4798
  points: pointsString,
@@ -4329,7 +4804,7 @@ function PipeRenderer({
4329
4804
  pointerEvents: "stroke"
4330
4805
  }
4331
4806
  ),
4332
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4807
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4333
4808
  "polyline",
4334
4809
  {
4335
4810
  points: pointsString,
@@ -4353,7 +4828,7 @@ function PipeRenderer({
4353
4828
  const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
4354
4829
  const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
4355
4830
  const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
4356
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4831
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4357
4832
  "circle",
4358
4833
  {
4359
4834
  cx: point.x,
@@ -4390,12 +4865,12 @@ function PipeRenderer({
4390
4865
  `${pipe.id}-point-${idx}`
4391
4866
  );
4392
4867
  }),
4393
- showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: displayPoints.slice(0, -1).map((point, idx) => {
4868
+ showEditingControls && onPipeSegmentClick && displayPoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: displayPoints.slice(0, -1).map((point, idx) => {
4394
4869
  const nextPoint = displayPoints[idx + 1];
4395
4870
  const midX = (point.x + nextPoint.x) / 2;
4396
4871
  const midY = (point.y + nextPoint.y) / 2;
4397
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
4398
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4872
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { children: [
4873
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4399
4874
  "circle",
4400
4875
  {
4401
4876
  cx: midX,
@@ -4411,7 +4886,7 @@ function PipeRenderer({
4411
4886
  }
4412
4887
  }
4413
4888
  ),
4414
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4889
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4415
4890
  "circle",
4416
4891
  {
4417
4892
  cx: midX,
@@ -4427,7 +4902,7 @@ function PipeRenderer({
4427
4902
  )
4428
4903
  ] }, `${pipe.id}-segment-${idx}`);
4429
4904
  }) }),
4430
- pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4905
+ pipe.showLabel !== false && pipe.label && pipe.routePoints.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4431
4906
  "text",
4432
4907
  {
4433
4908
  x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
@@ -4449,7 +4924,7 @@ function PipeRenderer({
4449
4924
  }
4450
4925
 
4451
4926
  // src/components/PIDCanvas/DataOverlay.tsx
4452
- var import_jsx_runtime17 = require("react/jsx-runtime");
4927
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4453
4928
  function DataOverlay({
4454
4929
  nodeId,
4455
4930
  x,
@@ -4471,7 +4946,7 @@ function DataOverlay({
4471
4946
  const offsetX = display?.offsetX ?? 0;
4472
4947
  const offsetY = display?.offsetY ?? 0;
4473
4948
  if (!showValue) {
4474
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, {});
4949
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, {});
4475
4950
  }
4476
4951
  const formatValue = (val) => {
4477
4952
  if (typeof val === "number") {
@@ -4512,8 +4987,8 @@ function DataOverlay({
4512
4987
  const overlayWidth = 80 * scale;
4513
4988
  const displayX = x + offsetX;
4514
4989
  const displayY = y + offsetY;
4515
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4516
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4990
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4991
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4517
4992
  "rect",
4518
4993
  {
4519
4994
  x: displayX - overlayWidth / 2,
@@ -4528,7 +5003,7 @@ function DataOverlay({
4528
5003
  filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
4529
5004
  }
4530
5005
  ),
4531
- label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5006
+ label && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4532
5007
  "text",
4533
5008
  {
4534
5009
  x: displayX,
@@ -4541,7 +5016,7 @@ function DataOverlay({
4541
5016
  children: label
4542
5017
  }
4543
5018
  ),
4544
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5019
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4545
5020
  "text",
4546
5021
  {
4547
5022
  x: displayX,
@@ -4554,7 +5029,7 @@ function DataOverlay({
4554
5029
  children: displayText
4555
5030
  }
4556
5031
  ),
4557
- showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5032
+ showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4558
5033
  "circle",
4559
5034
  {
4560
5035
  cx: displayX + 35 * scale,
@@ -4562,7 +5037,7 @@ function DataOverlay({
4562
5037
  r: 3 * scale,
4563
5038
  fill: finalTextColor,
4564
5039
  opacity: "0.9",
4565
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5040
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4566
5041
  "animate",
4567
5042
  {
4568
5043
  attributeName: "opacity",
@@ -4573,7 +5048,7 @@ function DataOverlay({
4573
5048
  )
4574
5049
  }
4575
5050
  ),
4576
- value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5051
+ value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4577
5052
  "text",
4578
5053
  {
4579
5054
  x: displayX,
@@ -4590,7 +5065,7 @@ function DataOverlay({
4590
5065
  ]
4591
5066
  }
4592
5067
  ),
4593
- hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5068
+ hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4594
5069
  "path",
4595
5070
  {
4596
5071
  d: sparklinePath,
@@ -4606,8 +5081,8 @@ function DataOverlay({
4606
5081
  }
4607
5082
 
4608
5083
  // src/components/PIDCanvas/PositionPanel.tsx
4609
- var import_react9 = require("react");
4610
- var import_jsx_runtime18 = require("react/jsx-runtime");
5084
+ var import_react10 = require("react");
5085
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4611
5086
  function PositionPanel({
4612
5087
  selectedNode,
4613
5088
  selectedWaypoint,
@@ -4615,9 +5090,9 @@ function PositionPanel({
4615
5090
  onWaypointPositionChange,
4616
5091
  position = "top-right"
4617
5092
  }) {
4618
- const [x, setX] = (0, import_react9.useState)("");
4619
- const [y, setY] = (0, import_react9.useState)("");
4620
- (0, import_react9.useEffect)(() => {
5093
+ const [x, setX] = (0, import_react10.useState)("");
5094
+ const [y, setY] = (0, import_react10.useState)("");
5095
+ (0, import_react10.useEffect)(() => {
4621
5096
  if (selectedNode) {
4622
5097
  setX(selectedNode.transform.x.toFixed(2));
4623
5098
  setY(selectedNode.transform.y.toFixed(2));
@@ -4676,7 +5151,7 @@ function PositionPanel({
4676
5151
  "bottom-left": { bottom: 10, left: 10 },
4677
5152
  "bottom-right": { bottom: 10, right: 10 }
4678
5153
  };
4679
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5154
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4680
5155
  "div",
4681
5156
  {
4682
5157
  style: {
@@ -4693,11 +5168,11 @@ function PositionPanel({
4693
5168
  fontSize: "13px"
4694
5169
  },
4695
5170
  children: [
4696
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
4697
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
4698
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4699
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
4700
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5171
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
5172
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
5173
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
5174
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
5175
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4701
5176
  "input",
4702
5177
  {
4703
5178
  type: "number",
@@ -4715,9 +5190,9 @@ function PositionPanel({
4715
5190
  }
4716
5191
  )
4717
5192
  ] }),
4718
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4719
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
4720
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5193
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
5194
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
5195
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4721
5196
  "input",
4722
5197
  {
4723
5198
  type: "number",
@@ -4736,14 +5211,14 @@ function PositionPanel({
4736
5211
  )
4737
5212
  ] })
4738
5213
  ] }),
4739
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
5214
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
4740
5215
  ]
4741
5216
  }
4742
5217
  );
4743
5218
  }
4744
5219
 
4745
5220
  // src/diagram/hooks/useViewBox.ts
4746
- var import_react10 = require("react");
5221
+ var import_react11 = require("react");
4747
5222
  function useViewBox(options) {
4748
5223
  const {
4749
5224
  initialViewBox,
@@ -4754,16 +5229,16 @@ function useViewBox(options) {
4754
5229
  zoomSensitivity = 1e-3,
4755
5230
  allowLeftClickPan = true
4756
5231
  } = options;
4757
- const [viewBox, setViewBox] = (0, import_react10.useState)(initialViewBox);
4758
- const svgRef = (0, import_react10.useRef)(null);
4759
- const isPanningRef = (0, import_react10.useRef)(false);
4760
- const lastMousePosRef = (0, import_react10.useRef)({ x: 0, y: 0 });
4761
- const spaceKeyDownRef = (0, import_react10.useRef)(false);
4762
- const lastTouchDistanceRef = (0, import_react10.useRef)(null);
4763
- const resetViewBox = (0, import_react10.useCallback)(() => {
5232
+ const [viewBox, setViewBox] = (0, import_react11.useState)(initialViewBox);
5233
+ const svgRef = (0, import_react11.useRef)(null);
5234
+ const isPanningRef = (0, import_react11.useRef)(false);
5235
+ const lastMousePosRef = (0, import_react11.useRef)({ x: 0, y: 0 });
5236
+ const spaceKeyDownRef = (0, import_react11.useRef)(false);
5237
+ const lastTouchDistanceRef = (0, import_react11.useRef)(null);
5238
+ const resetViewBox = (0, import_react11.useCallback)(() => {
4764
5239
  setViewBox(initialViewBox);
4765
5240
  }, [initialViewBox]);
4766
- const zoomIn = (0, import_react10.useCallback)(() => {
5241
+ const zoomIn = (0, import_react11.useCallback)(() => {
4767
5242
  setViewBox((prev) => {
4768
5243
  const currentZoom = initialViewBox.width / prev.width;
4769
5244
  const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
@@ -4780,7 +5255,7 @@ function useViewBox(options) {
4780
5255
  };
4781
5256
  });
4782
5257
  }, [initialViewBox, minZoom]);
4783
- const zoomOut = (0, import_react10.useCallback)(() => {
5258
+ const zoomOut = (0, import_react11.useCallback)(() => {
4784
5259
  setViewBox((prev) => {
4785
5260
  const currentZoom = initialViewBox.width / prev.width;
4786
5261
  const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
@@ -4797,7 +5272,7 @@ function useViewBox(options) {
4797
5272
  };
4798
5273
  });
4799
5274
  }, [initialViewBox, maxZoom]);
4800
- const fitToContent = (0, import_react10.useCallback)((bounds, padding = 50) => {
5275
+ const fitToContent = (0, import_react11.useCallback)((bounds, padding = 50) => {
4801
5276
  const contentWidth = bounds.maxX - bounds.minX;
4802
5277
  const contentHeight = bounds.maxY - bounds.minY;
4803
5278
  if (contentWidth === 0 || contentHeight === 0) {
@@ -4825,7 +5300,7 @@ function useViewBox(options) {
4825
5300
  height: newHeight
4826
5301
  });
4827
5302
  }, [initialViewBox]);
4828
- (0, import_react10.useEffect)(() => {
5303
+ (0, import_react11.useEffect)(() => {
4829
5304
  if (!enableZoom || !svgRef.current) return;
4830
5305
  const svg = svgRef.current;
4831
5306
  const handleWheel = (e) => {
@@ -4858,7 +5333,7 @@ function useViewBox(options) {
4858
5333
  svg.addEventListener("wheel", handleWheel, { passive: false });
4859
5334
  return () => svg.removeEventListener("wheel", handleWheel);
4860
5335
  }, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
4861
- (0, import_react10.useEffect)(() => {
5336
+ (0, import_react11.useEffect)(() => {
4862
5337
  if (!enablePan || !svgRef.current) return;
4863
5338
  const svg = svgRef.current;
4864
5339
  const handleMouseDown = (e) => {
@@ -4934,7 +5409,7 @@ function useViewBox(options) {
4934
5409
  window.removeEventListener("keyup", handleKeyUp);
4935
5410
  };
4936
5411
  }, [enablePan, allowLeftClickPan]);
4937
- (0, import_react10.useEffect)(() => {
5412
+ (0, import_react11.useEffect)(() => {
4938
5413
  if (!svgRef.current) return;
4939
5414
  if (!enablePan && !enableZoom) return;
4940
5415
  const svg = svgRef.current;
@@ -5025,7 +5500,7 @@ function useViewBox(options) {
5025
5500
  svg.removeEventListener("touchend", handleTouchEnd);
5026
5501
  };
5027
5502
  }, [enablePan, enableZoom, minZoom, initialViewBox]);
5028
- const screenToWorld = (0, import_react10.useCallback)(
5503
+ const screenToWorld = (0, import_react11.useCallback)(
5029
5504
  (screenX, screenY) => {
5030
5505
  const svg = svgRef.current;
5031
5506
  if (!svg) return { x: screenX, y: screenY };
@@ -5064,15 +5539,15 @@ function useViewBox(options) {
5064
5539
  }
5065
5540
 
5066
5541
  // src/diagram/hooks/useSelection.ts
5067
- var import_react11 = require("react");
5542
+ var import_react12 = require("react");
5068
5543
  function useSelection(options = {}) {
5069
5544
  const {
5070
5545
  multiSelect = true,
5071
5546
  initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
5072
5547
  onSelectionChange
5073
5548
  } = options;
5074
- const [selection, setSelection] = (0, import_react11.useState)(initialSelection);
5075
- const notifyChange = (0, import_react11.useCallback)(
5549
+ const [selection, setSelection] = (0, import_react12.useState)(initialSelection);
5550
+ const notifyChange = (0, import_react12.useCallback)(
5076
5551
  (newSelection) => {
5077
5552
  if (onSelectionChange) {
5078
5553
  onSelectionChange(newSelection);
@@ -5080,15 +5555,15 @@ function useSelection(options = {}) {
5080
5555
  },
5081
5556
  [onSelectionChange]
5082
5557
  );
5083
- const isNodeSelected = (0, import_react11.useCallback)(
5558
+ const isNodeSelected = (0, import_react12.useCallback)(
5084
5559
  (nodeId) => selection.selectedNodeIds.has(nodeId),
5085
5560
  [selection.selectedNodeIds]
5086
5561
  );
5087
- const isPipeSelected = (0, import_react11.useCallback)(
5562
+ const isPipeSelected = (0, import_react12.useCallback)(
5088
5563
  (pipeId) => selection.selectedPipeIds.has(pipeId),
5089
5564
  [selection.selectedPipeIds]
5090
5565
  );
5091
- const selectNode = (0, import_react11.useCallback)(
5566
+ const selectNode = (0, import_react12.useCallback)(
5092
5567
  (nodeId, isMultiSelect = false) => {
5093
5568
  setSelection((prev) => {
5094
5569
  const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
@@ -5107,7 +5582,7 @@ function useSelection(options = {}) {
5107
5582
  },
5108
5583
  [multiSelect, notifyChange]
5109
5584
  );
5110
- const selectPipe = (0, import_react11.useCallback)(
5585
+ const selectPipe = (0, import_react12.useCallback)(
5111
5586
  (pipeId, isMultiSelect = false) => {
5112
5587
  setSelection((prev) => {
5113
5588
  const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
@@ -5126,7 +5601,7 @@ function useSelection(options = {}) {
5126
5601
  },
5127
5602
  [multiSelect, notifyChange]
5128
5603
  );
5129
- const clearSelection = (0, import_react11.useCallback)(() => {
5604
+ const clearSelection = (0, import_react12.useCallback)(() => {
5130
5605
  const newSelection = {
5131
5606
  selectedNodeIds: /* @__PURE__ */ new Set(),
5132
5607
  selectedPipeIds: /* @__PURE__ */ new Set()
@@ -5134,7 +5609,7 @@ function useSelection(options = {}) {
5134
5609
  setSelection(newSelection);
5135
5610
  notifyChange(newSelection);
5136
5611
  }, [notifyChange]);
5137
- const selectNodes = (0, import_react11.useCallback)(
5612
+ const selectNodes = (0, import_react12.useCallback)(
5138
5613
  (nodeIds) => {
5139
5614
  const newSelection = {
5140
5615
  selectedNodeIds: new Set(nodeIds),
@@ -5145,7 +5620,7 @@ function useSelection(options = {}) {
5145
5620
  },
5146
5621
  [notifyChange]
5147
5622
  );
5148
- const selectPipes = (0, import_react11.useCallback)(
5623
+ const selectPipes = (0, import_react12.useCallback)(
5149
5624
  (pipeIds) => {
5150
5625
  const newSelection = {
5151
5626
  selectedNodeIds: /* @__PURE__ */ new Set(),
@@ -5169,23 +5644,23 @@ function useSelection(options = {}) {
5169
5644
  }
5170
5645
 
5171
5646
  // src/diagram/hooks/useTelemetry.ts
5172
- var import_react12 = require("react");
5647
+ var import_react13 = require("react");
5173
5648
  function useTelemetry(options = {}) {
5174
5649
  const {
5175
5650
  initialBindings = [],
5176
5651
  onTelemetryChange,
5177
5652
  refreshInterval = 0
5178
5653
  } = options;
5179
- const [telemetry, setTelemetry] = (0, import_react12.useState)(() => {
5654
+ const [telemetry, setTelemetry] = (0, import_react13.useState)(() => {
5180
5655
  const map = /* @__PURE__ */ new Map();
5181
5656
  initialBindings.forEach((binding) => {
5182
5657
  map.set(binding.nodeId, binding);
5183
5658
  });
5184
5659
  return map;
5185
5660
  });
5186
- const telemetryRef = (0, import_react12.useRef)(telemetry);
5661
+ const telemetryRef = (0, import_react13.useRef)(telemetry);
5187
5662
  telemetryRef.current = telemetry;
5188
- const notifyChange = (0, import_react12.useCallback)(
5663
+ const notifyChange = (0, import_react13.useCallback)(
5189
5664
  (newTelemetry) => {
5190
5665
  if (onTelemetryChange) {
5191
5666
  onTelemetryChange(newTelemetry);
@@ -5193,7 +5668,7 @@ function useTelemetry(options = {}) {
5193
5668
  },
5194
5669
  [onTelemetryChange]
5195
5670
  );
5196
- const updateTelemetry = (0, import_react12.useCallback)(
5671
+ const updateTelemetry = (0, import_react13.useCallback)(
5197
5672
  (nodeId, value) => {
5198
5673
  setTelemetry((prev) => {
5199
5674
  const newMap = new Map(prev);
@@ -5223,7 +5698,7 @@ function useTelemetry(options = {}) {
5223
5698
  },
5224
5699
  [notifyChange]
5225
5700
  );
5226
- const updateTelemetryBatch = (0, import_react12.useCallback)(
5701
+ const updateTelemetryBatch = (0, import_react13.useCallback)(
5227
5702
  (updates) => {
5228
5703
  setTelemetry((prev) => {
5229
5704
  const newMap = new Map(prev);
@@ -5277,16 +5752,16 @@ function useTelemetry(options = {}) {
5277
5752
  },
5278
5753
  [notifyChange]
5279
5754
  );
5280
- const getTelemetry = (0, import_react12.useCallback)(
5755
+ const getTelemetry = (0, import_react13.useCallback)(
5281
5756
  (nodeId) => telemetryRef.current.get(nodeId),
5282
5757
  []
5283
5758
  );
5284
- const clearTelemetry = (0, import_react12.useCallback)(() => {
5759
+ const clearTelemetry = (0, import_react13.useCallback)(() => {
5285
5760
  const newMap = /* @__PURE__ */ new Map();
5286
5761
  setTelemetry(newMap);
5287
5762
  notifyChange(newMap);
5288
5763
  }, [notifyChange]);
5289
- const setBindings = (0, import_react12.useCallback)(
5764
+ const setBindings = (0, import_react13.useCallback)(
5290
5765
  (bindings) => {
5291
5766
  const newMap = /* @__PURE__ */ new Map();
5292
5767
  bindings.forEach((binding) => {
@@ -5297,7 +5772,7 @@ function useTelemetry(options = {}) {
5297
5772
  },
5298
5773
  [notifyChange]
5299
5774
  );
5300
- (0, import_react12.useEffect)(() => {
5775
+ (0, import_react13.useEffect)(() => {
5301
5776
  if (refreshInterval <= 0) return;
5302
5777
  const intervalId = setInterval(() => {
5303
5778
  notifyChange(telemetryRef.current);
@@ -5315,10 +5790,10 @@ function useTelemetry(options = {}) {
5315
5790
  }
5316
5791
 
5317
5792
  // src/diagram/hooks/useTelemetryStatus.ts
5318
- var import_react13 = require("react");
5793
+ var import_react14 = require("react");
5319
5794
  function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5320
5795
  const { enabled = true, mapStatus } = options;
5321
- (0, import_react13.useEffect)(() => {
5796
+ (0, import_react14.useEffect)(() => {
5322
5797
  if (!enabled) return;
5323
5798
  const defaultMapStatus = (telemetryStatus) => {
5324
5799
  switch (telemetryStatus) {
@@ -5357,7 +5832,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5357
5832
  }
5358
5833
 
5359
5834
  // src/diagram/hooks/useDrag.ts
5360
- var import_react14 = require("react");
5835
+ var import_react15 = require("react");
5361
5836
  function useDrag(options = {}) {
5362
5837
  const {
5363
5838
  onDragStart,
@@ -5367,23 +5842,23 @@ function useDrag(options = {}) {
5367
5842
  dragThreshold = 3,
5368
5843
  screenToWorld = (x, y) => ({ x, y })
5369
5844
  } = options;
5370
- const [dragState, setDragState] = (0, import_react14.useState)({
5845
+ const [dragState, setDragState] = (0, import_react15.useState)({
5371
5846
  isDragging: false,
5372
5847
  startPosition: null,
5373
5848
  offset: { x: 0, y: 0 },
5374
5849
  draggedId: null
5375
5850
  });
5376
- const [isListening, setIsListening] = (0, import_react14.useState)(false);
5377
- const dragStartRef = (0, import_react14.useRef)(null);
5378
- const hasMovedRef = (0, import_react14.useRef)(false);
5379
- const applySnap = (0, import_react14.useCallback)(
5851
+ const [isListening, setIsListening] = (0, import_react15.useState)(false);
5852
+ const dragStartRef = (0, import_react15.useRef)(null);
5853
+ const hasMovedRef = (0, import_react15.useRef)(false);
5854
+ const applySnap = (0, import_react15.useCallback)(
5380
5855
  (value) => {
5381
5856
  if (snapToGrid <= 0) return value;
5382
5857
  return Math.round(value / snapToGrid) * snapToGrid;
5383
5858
  },
5384
5859
  [snapToGrid]
5385
5860
  );
5386
- const handleMouseMove = (0, import_react14.useCallback)(
5861
+ const handleMouseMove = (0, import_react15.useCallback)(
5387
5862
  (event) => {
5388
5863
  if (!dragStartRef.current) return;
5389
5864
  const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
@@ -5424,7 +5899,7 @@ function useDrag(options = {}) {
5424
5899
  },
5425
5900
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5426
5901
  );
5427
- const handleMouseUp = (0, import_react14.useCallback)(
5902
+ const handleMouseUp = (0, import_react15.useCallback)(
5428
5903
  (event) => {
5429
5904
  if (!dragStartRef.current || !hasMovedRef.current) {
5430
5905
  dragStartRef.current = null;
@@ -5461,7 +5936,7 @@ function useDrag(options = {}) {
5461
5936
  },
5462
5937
  [screenToWorld, applySnap, onDragEnd]
5463
5938
  );
5464
- const handleTouchMove = (0, import_react14.useCallback)(
5939
+ const handleTouchMove = (0, import_react15.useCallback)(
5465
5940
  (event) => {
5466
5941
  if (!dragStartRef.current || event.touches.length !== 1) return;
5467
5942
  const touch = event.touches[0];
@@ -5504,7 +5979,7 @@ function useDrag(options = {}) {
5504
5979
  },
5505
5980
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5506
5981
  );
5507
- const handleTouchEnd = (0, import_react14.useCallback)(
5982
+ const handleTouchEnd = (0, import_react15.useCallback)(
5508
5983
  (event) => {
5509
5984
  if (!dragStartRef.current || !hasMovedRef.current) {
5510
5985
  dragStartRef.current = null;
@@ -5542,7 +6017,7 @@ function useDrag(options = {}) {
5542
6017
  },
5543
6018
  [screenToWorld, applySnap, onDragEnd]
5544
6019
  );
5545
- (0, import_react14.useEffect)(() => {
6020
+ (0, import_react15.useEffect)(() => {
5546
6021
  if (!isListening) return;
5547
6022
  document.addEventListener("mousemove", handleMouseMove);
5548
6023
  document.addEventListener("mouseup", handleMouseUp);
@@ -5557,7 +6032,7 @@ function useDrag(options = {}) {
5557
6032
  document.removeEventListener("touchcancel", handleTouchEnd);
5558
6033
  };
5559
6034
  }, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
5560
- const startDrag = (0, import_react14.useCallback)(
6035
+ const startDrag = (0, import_react15.useCallback)(
5561
6036
  (id, event, itemPosition) => {
5562
6037
  event.stopPropagation();
5563
6038
  let clientX;
@@ -5587,7 +6062,7 @@ function useDrag(options = {}) {
5587
6062
  },
5588
6063
  [screenToWorld]
5589
6064
  );
5590
- const cancelDrag = (0, import_react14.useCallback)(() => {
6065
+ const cancelDrag = (0, import_react15.useCallback)(() => {
5591
6066
  dragStartRef.current = null;
5592
6067
  hasMovedRef.current = false;
5593
6068
  setIsListening(false);
@@ -5598,7 +6073,7 @@ function useDrag(options = {}) {
5598
6073
  draggedId: null
5599
6074
  });
5600
6075
  }, []);
5601
- const isDraggingItem = (0, import_react14.useCallback)(
6076
+ const isDraggingItem = (0, import_react15.useCallback)(
5602
6077
  (id) => dragState.isDragging && dragState.draggedId === id,
5603
6078
  [dragState.isDragging, dragState.draggedId]
5604
6079
  );
@@ -5611,7 +6086,7 @@ function useDrag(options = {}) {
5611
6086
  }
5612
6087
 
5613
6088
  // src/diagram/hooks/useKeyboardShortcuts.ts
5614
- var import_react15 = require("react");
6089
+ var import_react16 = require("react");
5615
6090
  function useKeyboardShortcuts(options) {
5616
6091
  const {
5617
6092
  onDelete,
@@ -5622,7 +6097,7 @@ function useKeyboardShortcuts(options) {
5622
6097
  onSelectAll,
5623
6098
  enabled = true
5624
6099
  } = options;
5625
- (0, import_react15.useEffect)(() => {
6100
+ (0, import_react16.useEffect)(() => {
5626
6101
  if (!enabled) return;
5627
6102
  const handleKeyDown = (event) => {
5628
6103
  const target = event.target;
@@ -5731,7 +6206,7 @@ function nodeHasPort(node, portId) {
5731
6206
  }
5732
6207
 
5733
6208
  // src/components/PIDCanvas/PIDCanvas.tsx
5734
- var import_jsx_runtime19 = require("react/jsx-runtime");
6209
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5735
6210
  function PIDCanvas({
5736
6211
  diagram,
5737
6212
  className = "",
@@ -5759,21 +6234,21 @@ function PIDCanvas({
5759
6234
  statusColorMap,
5760
6235
  ...props
5761
6236
  }) {
5762
- const [localDiagram, setLocalDiagram] = (0, import_react16.useState)(diagram);
5763
- const [dragOverPosition, setDragOverPosition] = (0, import_react16.useState)(null);
5764
- const [isConnecting, setIsConnecting] = (0, import_react16.useState)(false);
5765
- const [connectionSource, setConnectionSource] = (0, import_react16.useState)(null);
5766
- const [connectionSourcePort, setConnectionSourcePort] = (0, import_react16.useState)(null);
5767
- const [connectionCursor, setConnectionCursor] = (0, import_react16.useState)(null);
5768
- const [hoveredNode, setHoveredNode] = (0, import_react16.useState)(null);
5769
- const [hoveredPort, setHoveredPort] = (0, import_react16.useState)(null);
5770
- const [selectedWaypoint, setSelectedWaypoint] = (0, import_react16.useState)(null);
5771
- const historyStack = (0, import_react16.useRef)([]);
5772
- const redoStack = (0, import_react16.useRef)([]);
5773
- const isUndoRedoAction = (0, import_react16.useRef)(false);
5774
- const isInternalChange = (0, import_react16.useRef)(false);
5775
- const lastInternalDiagram = (0, import_react16.useRef)(null);
5776
- (0, import_react16.useEffect)(() => {
6237
+ const [localDiagram, setLocalDiagram] = (0, import_react17.useState)(diagram);
6238
+ const [dragOverPosition, setDragOverPosition] = (0, import_react17.useState)(null);
6239
+ const [isConnecting, setIsConnecting] = (0, import_react17.useState)(false);
6240
+ const [connectionSource, setConnectionSource] = (0, import_react17.useState)(null);
6241
+ const [connectionSourcePort, setConnectionSourcePort] = (0, import_react17.useState)(null);
6242
+ const [connectionCursor, setConnectionCursor] = (0, import_react17.useState)(null);
6243
+ const [hoveredNode, setHoveredNode] = (0, import_react17.useState)(null);
6244
+ const [hoveredPort, setHoveredPort] = (0, import_react17.useState)(null);
6245
+ const [selectedWaypoint, setSelectedWaypoint] = (0, import_react17.useState)(null);
6246
+ const historyStack = (0, import_react17.useRef)([]);
6247
+ const redoStack = (0, import_react17.useRef)([]);
6248
+ const isUndoRedoAction = (0, import_react17.useRef)(false);
6249
+ const isInternalChange = (0, import_react17.useRef)(false);
6250
+ const lastInternalDiagram = (0, import_react17.useRef)(null);
6251
+ (0, import_react17.useEffect)(() => {
5777
6252
  const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
5778
6253
  if (isExternal) {
5779
6254
  setLocalDiagram(diagram);
@@ -5795,7 +6270,7 @@ function PIDCanvas({
5795
6270
  enablePan: features.pan ?? true,
5796
6271
  enableZoom: features.zoom ?? true
5797
6272
  });
5798
- const calculateContentBounds = (0, import_react16.useCallback)(() => {
6273
+ const calculateContentBounds = (0, import_react17.useCallback)(() => {
5799
6274
  const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
5800
6275
  if (nodes2.length === 0) {
5801
6276
  return null;
@@ -5818,7 +6293,7 @@ function PIDCanvas({
5818
6293
  });
5819
6294
  return { minX, minY, maxX, maxY };
5820
6295
  }, [localDiagram.nodes]);
5821
- (0, import_react16.useEffect)(() => {
6296
+ (0, import_react17.useEffect)(() => {
5822
6297
  if (onMounted) {
5823
6298
  const controls = {
5824
6299
  fitToContent: (padding = 50) => {
@@ -5859,8 +6334,8 @@ function PIDCanvas({
5859
6334
  });
5860
6335
  const dragEnabled = features.dragNodes ?? false;
5861
6336
  const selectionEnabled = features.selection ?? false;
5862
- const containerRef = (0, import_react16.useRef)(null);
5863
- const pushToHistory = (0, import_react16.useCallback)((currentDiagram) => {
6337
+ const containerRef = (0, import_react17.useRef)(null);
6338
+ const pushToHistory = (0, import_react17.useCallback)((currentDiagram) => {
5864
6339
  if (isUndoRedoAction.current) return;
5865
6340
  const snapshot = JSON.parse(JSON.stringify(currentDiagram));
5866
6341
  historyStack.current.push(snapshot);
@@ -5869,7 +6344,7 @@ function PIDCanvas({
5869
6344
  }
5870
6345
  redoStack.current = [];
5871
6346
  }, []);
5872
- const undo = (0, import_react16.useCallback)(() => {
6347
+ const undo = (0, import_react17.useCallback)(() => {
5873
6348
  if (historyStack.current.length === 0) return;
5874
6349
  isUndoRedoAction.current = true;
5875
6350
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5883,7 +6358,7 @@ function PIDCanvas({
5883
6358
  isUndoRedoAction.current = false;
5884
6359
  }, 0);
5885
6360
  }, [localDiagram, onDiagramChange]);
5886
- const redo = (0, import_react16.useCallback)(() => {
6361
+ const redo = (0, import_react17.useCallback)(() => {
5887
6362
  if (redoStack.current.length === 0) return;
5888
6363
  isUndoRedoAction.current = true;
5889
6364
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5897,7 +6372,7 @@ function PIDCanvas({
5897
6372
  isUndoRedoAction.current = false;
5898
6373
  }, 0);
5899
6374
  }, [localDiagram, onDiagramChange]);
5900
- (0, import_react16.useEffect)(() => {
6375
+ (0, import_react17.useEffect)(() => {
5901
6376
  const handleKeyDown = (e) => {
5902
6377
  const isCtrlOrCmd = e.ctrlKey || e.metaKey;
5903
6378
  if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
@@ -5914,7 +6389,7 @@ function PIDCanvas({
5914
6389
  window.addEventListener("keydown", handleKeyDown);
5915
6390
  return () => window.removeEventListener("keydown", handleKeyDown);
5916
6391
  }, [undo, redo]);
5917
- (0, import_react16.useEffect)(() => {
6392
+ (0, import_react17.useEffect)(() => {
5918
6393
  if (!features.dragNodes) return;
5919
6394
  const handleKeyDown = (e) => {
5920
6395
  if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
@@ -5999,7 +6474,7 @@ function PIDCanvas({
5999
6474
  onNodeMove,
6000
6475
  pushToHistory
6001
6476
  ]);
6002
- const handlePositionChange = (0, import_react16.useCallback)(
6477
+ const handlePositionChange = (0, import_react17.useCallback)(
6003
6478
  (nodeId, x, y) => {
6004
6479
  pushToHistory(localDiagram);
6005
6480
  const updatedNodes = localDiagram.nodes.map(
@@ -6021,7 +6496,7 @@ function PIDCanvas({
6021
6496
  },
6022
6497
  [localDiagram, onDiagramChange, onNodeMove, pushToHistory]
6023
6498
  );
6024
- const handleWaypointPositionChange = (0, import_react16.useCallback)(
6499
+ const handleWaypointPositionChange = (0, import_react17.useCallback)(
6025
6500
  (pipeId, pointIndex, x, y) => {
6026
6501
  pushToHistory(localDiagram);
6027
6502
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6039,7 +6514,7 @@ function PIDCanvas({
6039
6514
  },
6040
6515
  [localDiagram, onDiagramChange, pushToHistory]
6041
6516
  );
6042
- const handleDragEnd = (0, import_react16.useCallback)(
6517
+ const handleDragEnd = (0, import_react17.useCallback)(
6043
6518
  (nodeId, offset, finalPosition) => {
6044
6519
  const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
6045
6520
  if (dragDistance < 2) {
@@ -6120,7 +6595,7 @@ function PIDCanvas({
6120
6595
  onDiagramChange?.(updatedDiagram);
6121
6596
  }
6122
6597
  });
6123
- const handleNodeDragStart = (0, import_react16.useCallback)(
6598
+ const handleNodeDragStart = (0, import_react17.useCallback)(
6124
6599
  (nodeId, event) => {
6125
6600
  const node = localDiagram.nodes.find((n) => n.id === nodeId);
6126
6601
  if (!node) return;
@@ -6128,7 +6603,7 @@ function PIDCanvas({
6128
6603
  },
6129
6604
  [localDiagram.nodes, startDrag]
6130
6605
  );
6131
- const handleWaypointClick = (0, import_react16.useCallback)(
6606
+ const handleWaypointClick = (0, import_react17.useCallback)(
6132
6607
  (pipeId, pointIndex) => {
6133
6608
  setSelectedWaypoint({ pipeId, pointIndex });
6134
6609
  if (selectionEnabled) {
@@ -6137,7 +6612,7 @@ function PIDCanvas({
6137
6612
  },
6138
6613
  [selectionEnabled, clearSelection]
6139
6614
  );
6140
- const handleWaypointDragStart = (0, import_react16.useCallback)(
6615
+ const handleWaypointDragStart = (0, import_react17.useCallback)(
6141
6616
  (pipeId, pointIndex, event) => {
6142
6617
  const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
6143
6618
  if (!pipe || pointIndex >= pipe.routePoints.length) return;
@@ -6146,7 +6621,7 @@ function PIDCanvas({
6146
6621
  },
6147
6622
  [localDiagram.pipes, startWaypointDrag]
6148
6623
  );
6149
- const handlePipeSegmentClick = (0, import_react16.useCallback)(
6624
+ const handlePipeSegmentClick = (0, import_react17.useCallback)(
6150
6625
  (pipeId, position, segmentIndex) => {
6151
6626
  pushToHistory(localDiagram);
6152
6627
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6165,7 +6640,7 @@ function PIDCanvas({
6165
6640
  [localDiagram, onDiagramChange, pushToHistory]
6166
6641
  );
6167
6642
  const telemetryEnabled = features.telemetry ?? false;
6168
- const handleDelete = (0, import_react16.useCallback)(() => {
6643
+ const handleDelete = (0, import_react17.useCallback)(() => {
6169
6644
  if (!selectionEnabled) return;
6170
6645
  const { selectedNodeIds, selectedPipeIds } = selection;
6171
6646
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
@@ -6194,13 +6669,13 @@ function PIDCanvas({
6194
6669
  onDelete,
6195
6670
  pushToHistory
6196
6671
  ]);
6197
- const handleCopy = (0, import_react16.useCallback)(() => {
6672
+ const handleCopy = (0, import_react17.useCallback)(() => {
6198
6673
  if (!selectionEnabled) return;
6199
6674
  const { selectedNodeIds, selectedPipeIds } = selection;
6200
6675
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
6201
6676
  onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
6202
6677
  }, [selection, selectionEnabled, onItemsCopied]);
6203
- const handlePaste = (0, import_react16.useCallback)(() => {
6678
+ const handlePaste = (0, import_react17.useCallback)(() => {
6204
6679
  if (!selectionEnabled) return;
6205
6680
  onPaste?.();
6206
6681
  }, [selectionEnabled, onPaste]);
@@ -6260,7 +6735,7 @@ function PIDCanvas({
6260
6735
  }
6261
6736
  setSelectedWaypoint(null);
6262
6737
  };
6263
- const handleDragOver = (0, import_react16.useCallback)(
6738
+ const handleDragOver = (0, import_react17.useCallback)(
6264
6739
  (event) => {
6265
6740
  if (!features.allowSymbolDrop) return;
6266
6741
  event.preventDefault();
@@ -6271,7 +6746,7 @@ function PIDCanvas({
6271
6746
  },
6272
6747
  [features.allowSymbolDrop, screenToWorld, svgRef]
6273
6748
  );
6274
- const handleDrop = (0, import_react16.useCallback)(
6749
+ const handleDrop = (0, import_react17.useCallback)(
6275
6750
  (event) => {
6276
6751
  if (!features.allowSymbolDrop) return;
6277
6752
  event.preventDefault();
@@ -6284,10 +6759,10 @@ function PIDCanvas({
6284
6759
  },
6285
6760
  [features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
6286
6761
  );
6287
- const handleDragLeave = (0, import_react16.useCallback)(() => {
6762
+ const handleDragLeave = (0, import_react17.useCallback)(() => {
6288
6763
  setDragOverPosition(null);
6289
6764
  }, []);
6290
- const handleMouseMove = (0, import_react16.useCallback)(
6765
+ const handleMouseMove = (0, import_react17.useCallback)(
6291
6766
  (event) => {
6292
6767
  const connectionModeEnabled = features.connectionMode ?? false;
6293
6768
  if (connectionModeEnabled) {
@@ -6324,7 +6799,7 @@ function PIDCanvas({
6324
6799
  const viewBox = controlledViewBox;
6325
6800
  const displayDiagram = localDiagram;
6326
6801
  const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
6327
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6802
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6328
6803
  "div",
6329
6804
  {
6330
6805
  ref: containerRef,
@@ -6339,7 +6814,7 @@ function PIDCanvas({
6339
6814
  },
6340
6815
  ...props,
6341
6816
  children: [
6342
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6817
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6343
6818
  "svg",
6344
6819
  {
6345
6820
  ref: svgRef,
@@ -6358,15 +6833,15 @@ function PIDCanvas({
6358
6833
  onDrop: handleDrop,
6359
6834
  onDragLeave: handleDragLeave,
6360
6835
  children: [
6361
- features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
6362
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("defs", { children: [
6363
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
6364
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6365
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6366
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
6836
+ features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6837
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("defs", { children: [
6838
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
6839
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6840
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6841
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
6367
6842
  ] })
6368
6843
  ] }),
6369
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6844
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6370
6845
  "rect",
6371
6846
  {
6372
6847
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6376,7 +6851,7 @@ function PIDCanvas({
6376
6851
  fill: "url(#grid-major)"
6377
6852
  }
6378
6853
  )
6379
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6854
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6380
6855
  "rect",
6381
6856
  {
6382
6857
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6386,7 +6861,7 @@ function PIDCanvas({
6386
6861
  fill: features.backgroundColor ?? "#ffffff"
6387
6862
  }
6388
6863
  ),
6389
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6864
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6390
6865
  PipeRenderer,
6391
6866
  {
6392
6867
  pipes: displayDiagram.pipes,
@@ -6400,7 +6875,7 @@ function PIDCanvas({
6400
6875
  onPipeSegmentClick: void 0
6401
6876
  }
6402
6877
  ),
6403
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6878
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6404
6879
  NodeRenderer,
6405
6880
  {
6406
6881
  nodes: displayDiagram.nodes,
@@ -6414,7 +6889,7 @@ function PIDCanvas({
6414
6889
  statusColorMap
6415
6890
  }
6416
6891
  ),
6417
- (features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6892
+ (features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6418
6893
  PipeRenderer,
6419
6894
  {
6420
6895
  pipes: displayDiagram.pipes,
@@ -6431,14 +6906,14 @@ function PIDCanvas({
6431
6906
  onPipeSegmentClick: handlePipeSegmentClick
6432
6907
  }
6433
6908
  ),
6434
- telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
6909
+ telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
6435
6910
  const binding = telemetry.get(node.id);
6436
6911
  if (!binding) return null;
6437
6912
  const symbol = getSymbolDefinition(node.symbolId);
6438
6913
  if (!symbol) return null;
6439
6914
  const overlayX = node.transform.x + symbol.viewBox.width / 2;
6440
6915
  const overlayY = node.transform.y + symbol.viewBox.height + 50;
6441
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6916
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6442
6917
  DataOverlay,
6443
6918
  {
6444
6919
  nodeId: node.id,
@@ -6451,7 +6926,7 @@ function PIDCanvas({
6451
6926
  `telemetry-${node.id}`
6452
6927
  );
6453
6928
  }) }),
6454
- dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6929
+ dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6455
6930
  "circle",
6456
6931
  {
6457
6932
  cx: dragOverPosition.x,
@@ -6464,7 +6939,7 @@ function PIDCanvas({
6464
6939
  pointerEvents: "none"
6465
6940
  }
6466
6941
  ),
6467
- isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
6942
+ isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
6468
6943
  const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
6469
6944
  if (!sourceNode) return null;
6470
6945
  const symbol = getSymbolDefinition(sourceNode.symbolId);
@@ -6480,8 +6955,8 @@ function PIDCanvas({
6480
6955
  }
6481
6956
  }
6482
6957
  }
6483
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
6484
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6958
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6959
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6485
6960
  "circle",
6486
6961
  {
6487
6962
  cx: lineStartX,
@@ -6493,7 +6968,7 @@ function PIDCanvas({
6493
6968
  opacity: 0.6
6494
6969
  }
6495
6970
  ),
6496
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6971
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6497
6972
  "line",
6498
6973
  {
6499
6974
  x1: lineStartX,
@@ -6506,7 +6981,7 @@ function PIDCanvas({
6506
6981
  opacity: 0.8
6507
6982
  }
6508
6983
  ),
6509
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6984
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6510
6985
  "circle",
6511
6986
  {
6512
6987
  cx: connectionCursor.x,
@@ -6518,7 +6993,7 @@ function PIDCanvas({
6518
6993
  )
6519
6994
  ] });
6520
6995
  })() }),
6521
- features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
6996
+ features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
6522
6997
  const symbol = getSymbolDefinition(node.symbolId);
6523
6998
  if (!symbol?.ports) return null;
6524
6999
  return symbol.ports.map((port) => {
@@ -6526,8 +7001,8 @@ function PIDCanvas({
6526
7001
  if (!portPos) return null;
6527
7002
  const isHovered = hoveredPort === port.id && hoveredNode === node.id;
6528
7003
  const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
6529
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("g", { children: [
6530
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7004
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("g", { children: [
7005
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6531
7006
  "circle",
6532
7007
  {
6533
7008
  cx: portPos.x,
@@ -6560,7 +7035,7 @@ function PIDCanvas({
6560
7035
  }
6561
7036
  }
6562
7037
  ),
6563
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7038
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6564
7039
  "circle",
6565
7040
  {
6566
7041
  cx: portPos.x,
@@ -6579,7 +7054,7 @@ function PIDCanvas({
6579
7054
  ]
6580
7055
  }
6581
7056
  ),
6582
- features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7057
+ features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6583
7058
  PositionPanel,
6584
7059
  {
6585
7060
  selectedNode,
@@ -6599,16 +7074,16 @@ function PIDCanvas({
6599
7074
  }
6600
7075
 
6601
7076
  // src/components/SymbolLibrary/SymbolLibrary.tsx
6602
- var import_react17 = require("react");
6603
- var import_jsx_runtime20 = require("react/jsx-runtime");
7077
+ var import_react18 = require("react");
7078
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6604
7079
  function SymbolLibrary({
6605
7080
  className = "",
6606
7081
  onSymbolDragStart,
6607
7082
  showCategories = true,
6608
7083
  categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
6609
7084
  }) {
6610
- const [selectedCategory, setSelectedCategory] = (0, import_react17.useState)("all");
6611
- const [searchQuery, setSearchQuery] = (0, import_react17.useState)("");
7085
+ const [selectedCategory, setSelectedCategory] = (0, import_react18.useState)("all");
7086
+ const [searchQuery, setSearchQuery] = (0, import_react18.useState)("");
6612
7087
  const symbolIds = getAvailableSymbols();
6613
7088
  const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
6614
7089
  const categoryMap = {
@@ -6629,9 +7104,9 @@ function SymbolLibrary({
6629
7104
  event.dataTransfer.effectAllowed = "copy";
6630
7105
  onSymbolDragStart?.(symbol.id, event);
6631
7106
  };
6632
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
6633
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
6634
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
7107
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
7108
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
7109
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6635
7110
  "input",
6636
7111
  {
6637
7112
  type: "text",
@@ -6641,8 +7116,8 @@ function SymbolLibrary({
6641
7116
  style: styles.searchInput
6642
7117
  }
6643
7118
  ) }),
6644
- showCategories && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: styles.categories, children: [
6645
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
7119
+ showCategories && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: styles.categories, children: [
7120
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6646
7121
  "button",
6647
7122
  {
6648
7123
  onClick: () => setSelectedCategory("all"),
@@ -6653,7 +7128,7 @@ function SymbolLibrary({
6653
7128
  children: "All"
6654
7129
  }
6655
7130
  ),
6656
- categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
7131
+ categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6657
7132
  "button",
6658
7133
  {
6659
7134
  onClick: () => setSelectedCategory(category),
@@ -6666,7 +7141,7 @@ function SymbolLibrary({
6666
7141
  category
6667
7142
  ))
6668
7143
  ] }),
6669
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
7144
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6670
7145
  "div",
6671
7146
  {
6672
7147
  draggable: true,
@@ -6674,15 +7149,15 @@ function SymbolLibrary({
6674
7149
  style: styles.symbolCard,
6675
7150
  title: symbol.metadata?.description || symbol.name,
6676
7151
  children: [
6677
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
7152
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6678
7153
  "svg",
6679
7154
  {
6680
7155
  viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
6681
7156
  style: styles.symbolSvg,
6682
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
7157
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
6683
7158
  }
6684
7159
  ) }),
6685
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.symbolName, children: symbol.name })
7160
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: styles.symbolName, children: symbol.name })
6686
7161
  ]
6687
7162
  },
6688
7163
  symbol.id
@@ -6791,7 +7266,7 @@ var styles = {
6791
7266
  };
6792
7267
 
6793
7268
  // src/components/NodeConfigPanel/NodeConfigPanel.tsx
6794
- var import_jsx_runtime21 = require("react/jsx-runtime");
7269
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6795
7270
  function NodeConfigPanel({
6796
7271
  node,
6797
7272
  binding,
@@ -6810,15 +7285,15 @@ function NodeConfigPanel({
6810
7285
  padding: "20px",
6811
7286
  ...style
6812
7287
  };
6813
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, style: defaultStyle, children: [
6814
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
7288
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, style: defaultStyle, children: [
7289
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
6815
7290
  "Configure: ",
6816
7291
  node.id
6817
7292
  ] }),
6818
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
6819
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
6820
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
6821
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7293
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7294
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
7295
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
7296
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6822
7297
  "input",
6823
7298
  {
6824
7299
  type: "text",
@@ -6834,10 +7309,10 @@ function NodeConfigPanel({
6834
7309
  }
6835
7310
  }
6836
7311
  ),
6837
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6838
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6839
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
6840
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7312
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7313
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7314
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
7315
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6841
7316
  "input",
6842
7317
  {
6843
7318
  type: "number",
@@ -6858,9 +7333,9 @@ function NodeConfigPanel({
6858
7333
  }
6859
7334
  )
6860
7335
  ] }),
6861
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6862
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
6863
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7336
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7337
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
7338
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6864
7339
  "input",
6865
7340
  {
6866
7341
  type: "number",
@@ -6882,9 +7357,9 @@ function NodeConfigPanel({
6882
7357
  )
6883
7358
  ] })
6884
7359
  ] }),
6885
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6886
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
6887
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7360
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7361
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
7362
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6888
7363
  "input",
6889
7364
  {
6890
7365
  type: "number",
@@ -6904,9 +7379,9 @@ function NodeConfigPanel({
6904
7379
  }
6905
7380
  )
6906
7381
  ] }),
6907
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6908
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
6909
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7382
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7383
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
7384
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6910
7385
  "input",
6911
7386
  {
6912
7387
  type: "number",
@@ -6931,9 +7406,9 @@ function NodeConfigPanel({
6931
7406
  )
6932
7407
  ] })
6933
7408
  ] }),
6934
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
6935
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
6936
- !binding ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7409
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7410
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
7411
+ !binding ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6937
7412
  "button",
6938
7413
  {
6939
7414
  onClick: () => {
@@ -6976,9 +7451,9 @@ function NodeConfigPanel({
6976
7451
  },
6977
7452
  children: "+ Add Telemetry"
6978
7453
  }
6979
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6980
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
6981
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7454
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
7455
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
7456
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6982
7457
  "input",
6983
7458
  {
6984
7459
  type: "number",
@@ -7000,8 +7475,8 @@ function NodeConfigPanel({
7000
7475
  }
7001
7476
  }
7002
7477
  ),
7003
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
7004
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7478
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
7479
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7005
7480
  "input",
7006
7481
  {
7007
7482
  type: "text",
@@ -7023,8 +7498,8 @@ function NodeConfigPanel({
7023
7498
  }
7024
7499
  }
7025
7500
  ),
7026
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7027
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7501
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7502
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7028
7503
  "input",
7029
7504
  {
7030
7505
  type: "checkbox",
@@ -7046,8 +7521,8 @@ function NodeConfigPanel({
7046
7521
  ),
7047
7522
  "Show Sparkline"
7048
7523
  ] }),
7049
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "12px" }, children: [
7050
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7524
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginTop: "12px" }, children: [
7525
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7051
7526
  "label",
7052
7527
  {
7053
7528
  style: {
@@ -7059,10 +7534,10 @@ function NodeConfigPanel({
7059
7534
  children: "Telemetry Position Offset:"
7060
7535
  }
7061
7536
  ),
7062
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7063
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
7064
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
7065
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7537
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7538
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7539
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
7540
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7066
7541
  "input",
7067
7542
  {
7068
7543
  type: "number",
@@ -7089,9 +7564,9 @@ function NodeConfigPanel({
7089
7564
  }
7090
7565
  )
7091
7566
  ] }),
7092
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
7093
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
7094
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7567
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
7568
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
7569
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7095
7570
  "input",
7096
7571
  {
7097
7572
  type: "number",
@@ -7119,8 +7594,8 @@ function NodeConfigPanel({
7119
7594
  )
7120
7595
  ] })
7121
7596
  ] }),
7122
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "16px" }, children: [
7123
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7597
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginTop: "16px" }, children: [
7598
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7124
7599
  "label",
7125
7600
  {
7126
7601
  style: {
@@ -7132,10 +7607,10 @@ function NodeConfigPanel({
7132
7607
  children: "Display Colors:"
7133
7608
  }
7134
7609
  ),
7135
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7136
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7137
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7138
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7610
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7611
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7612
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7613
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7139
7614
  "input",
7140
7615
  {
7141
7616
  type: "color",
@@ -7161,7 +7636,7 @@ function NodeConfigPanel({
7161
7636
  }
7162
7637
  }
7163
7638
  ),
7164
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7639
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7165
7640
  "input",
7166
7641
  {
7167
7642
  type: "text",
@@ -7191,10 +7666,10 @@ function NodeConfigPanel({
7191
7666
  )
7192
7667
  ] })
7193
7668
  ] }),
7194
- binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7195
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7196
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7197
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7669
+ binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7670
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7671
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7672
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7198
7673
  "input",
7199
7674
  {
7200
7675
  type: "color",
@@ -7220,7 +7695,7 @@ function NodeConfigPanel({
7220
7695
  }
7221
7696
  }
7222
7697
  ),
7223
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7698
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7224
7699
  "input",
7225
7700
  {
7226
7701
  type: "text",
@@ -7250,9 +7725,9 @@ function NodeConfigPanel({
7250
7725
  )
7251
7726
  ] })
7252
7727
  ] }),
7253
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7254
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7255
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7728
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7729
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7730
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7256
7731
  "input",
7257
7732
  {
7258
7733
  type: "text",
@@ -7280,20 +7755,20 @@ function NodeConfigPanel({
7280
7755
  }
7281
7756
  }
7282
7757
  ),
7283
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
7758
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
7284
7759
  ] })
7285
7760
  ] }),
7286
7761
  " "
7287
7762
  ] })
7288
7763
  ] })
7289
7764
  ] }),
7290
- binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7291
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
7765
+ binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7766
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
7292
7767
  ["highHigh", "high", "low", "lowLow"].map((key) => {
7293
7768
  const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
7294
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7295
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7296
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7769
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7770
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7771
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7297
7772
  "input",
7298
7773
  {
7299
7774
  type: "number",
@@ -7317,8 +7792,8 @@ function NodeConfigPanel({
7317
7792
  ] }, key);
7318
7793
  })
7319
7794
  ] }),
7320
- binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7321
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
7795
+ binding && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7796
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
7322
7797
  ["normal", "warning", "alarm", "fault", "off"].map((status) => {
7323
7798
  const defaultColors = {
7324
7799
  normal: "#10b981",
@@ -7328,13 +7803,13 @@ function NodeConfigPanel({
7328
7803
  off: "#6b7280"
7329
7804
  };
7330
7805
  const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
7331
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7332
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7806
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7807
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7333
7808
  label,
7334
7809
  ":"
7335
7810
  ] }),
7336
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7337
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7811
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7812
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7338
7813
  "input",
7339
7814
  {
7340
7815
  type: "color",
@@ -7355,7 +7830,7 @@ function NodeConfigPanel({
7355
7830
  }
7356
7831
  }
7357
7832
  ),
7358
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7833
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7359
7834
  "input",
7360
7835
  {
7361
7836
  type: "text",
@@ -7382,7 +7857,7 @@ function NodeConfigPanel({
7382
7857
  ] }, status);
7383
7858
  })
7384
7859
  ] }),
7385
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7860
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7386
7861
  "button",
7387
7862
  {
7388
7863
  onClick: onRemove,
@@ -7659,13 +8134,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
7659
8134
  }
7660
8135
 
7661
8136
  // src/hooks/useDeviceControls.ts
7662
- var import_react18 = require("react");
8137
+ var import_react19 = require("react");
7663
8138
  function commandKey(nodeId, kind, suffix) {
7664
8139
  return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
7665
8140
  }
7666
8141
  function useDeviceControls(initialBindings, options) {
7667
8142
  const { commandTimeoutMs } = options ?? {};
7668
- const [controls, setControls] = (0, import_react18.useState)(() => {
8143
+ const [controls, setControls] = (0, import_react19.useState)(() => {
7669
8144
  const map = /* @__PURE__ */ new Map();
7670
8145
  if (initialBindings) {
7671
8146
  initialBindings.forEach((binding) => {
@@ -7674,12 +8149,12 @@ function useDeviceControls(initialBindings, options) {
7674
8149
  }
7675
8150
  return map;
7676
8151
  });
7677
- const pendingRef = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
7678
- const [pendingCommands, setPendingCommands] = (0, import_react18.useState)(() => /* @__PURE__ */ new Set());
7679
- const syncPending = (0, import_react18.useCallback)(() => {
8152
+ const pendingRef = (0, import_react19.useRef)(/* @__PURE__ */ new Map());
8153
+ const [pendingCommands, setPendingCommands] = (0, import_react19.useState)(() => /* @__PURE__ */ new Set());
8154
+ const syncPending = (0, import_react19.useCallback)(() => {
7680
8155
  setPendingCommands(new Set(pendingRef.current.keys()));
7681
8156
  }, []);
7682
- const updateControl = (0, import_react18.useCallback)((nodeId, updates) => {
8157
+ const updateControl = (0, import_react19.useCallback)((nodeId, updates) => {
7683
8158
  setControls((prev) => {
7684
8159
  const newMap = new Map(prev);
7685
8160
  const existing = newMap.get(nodeId);
@@ -7693,7 +8168,7 @@ function useDeviceControls(initialBindings, options) {
7693
8168
  return newMap;
7694
8169
  });
7695
8170
  }, []);
7696
- const updateControlBatch = (0, import_react18.useCallback)((updates) => {
8171
+ const updateControlBatch = (0, import_react19.useCallback)((updates) => {
7697
8172
  setControls((prev) => {
7698
8173
  const newMap = new Map(prev);
7699
8174
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7705,7 +8180,7 @@ function useDeviceControls(initialBindings, options) {
7705
8180
  return newMap;
7706
8181
  });
7707
8182
  }, []);
7708
- const updateDeviceState = (0, import_react18.useCallback)(
8183
+ const updateDeviceState = (0, import_react19.useCallback)(
7709
8184
  (nodeId, stateUpdates) => {
7710
8185
  setControls((prev) => {
7711
8186
  const newMap = new Map(prev);
@@ -7721,7 +8196,7 @@ function useDeviceControls(initialBindings, options) {
7721
8196
  },
7722
8197
  []
7723
8198
  );
7724
- const updateParameter = (0, import_react18.useCallback)(
8199
+ const updateParameter = (0, import_react19.useCallback)(
7725
8200
  (nodeId, parameterId, value) => {
7726
8201
  setControls((prev) => {
7727
8202
  const newMap = new Map(prev);
@@ -7748,27 +8223,27 @@ function useDeviceControls(initialBindings, options) {
7748
8223
  },
7749
8224
  []
7750
8225
  );
7751
- const setControlBinding = (0, import_react18.useCallback)((binding) => {
8226
+ const setControlBinding = (0, import_react19.useCallback)((binding) => {
7752
8227
  setControls((prev) => {
7753
8228
  const newMap = new Map(prev);
7754
8229
  newMap.set(binding.nodeId, binding);
7755
8230
  return newMap;
7756
8231
  });
7757
8232
  }, []);
7758
- const removeControlBinding = (0, import_react18.useCallback)((nodeId) => {
8233
+ const removeControlBinding = (0, import_react19.useCallback)((nodeId) => {
7759
8234
  setControls((prev) => {
7760
8235
  const newMap = new Map(prev);
7761
8236
  newMap.delete(nodeId);
7762
8237
  return newMap;
7763
8238
  });
7764
8239
  }, []);
7765
- const getControlBinding = (0, import_react18.useCallback)(
8240
+ const getControlBinding = (0, import_react19.useCallback)(
7766
8241
  (nodeId) => {
7767
8242
  return controls.get(nodeId);
7768
8243
  },
7769
8244
  [controls]
7770
8245
  );
7771
- const isCommandPending = (0, import_react18.useCallback)(
8246
+ const isCommandPending = (0, import_react19.useCallback)(
7772
8247
  (nodeId, kind) => {
7773
8248
  if (kind) {
7774
8249
  const prefix2 = `${nodeId}:${kind}`;
@@ -7785,7 +8260,7 @@ function useDeviceControls(initialBindings, options) {
7785
8260
  },
7786
8261
  [pendingCommands]
7787
8262
  );
7788
- const markPending = (0, import_react18.useCallback)(
8263
+ const markPending = (0, import_react19.useCallback)(
7789
8264
  (key, delta) => {
7790
8265
  const next = (pendingRef.current.get(key) ?? 0) + delta;
7791
8266
  if (next > 0) pendingRef.current.set(key, next);
@@ -7794,7 +8269,7 @@ function useDeviceControls(initialBindings, options) {
7794
8269
  },
7795
8270
  [syncPending]
7796
8271
  );
7797
- const runCommand = (0, import_react18.useCallback)(
8272
+ const runCommand = (0, import_react19.useCallback)(
7798
8273
  async (nodeId, key, invoke, messages) => {
7799
8274
  const binding = controls.get(nodeId);
7800
8275
  if (!binding) return;
@@ -7834,7 +8309,7 @@ function useDeviceControls(initialBindings, options) {
7834
8309
  },
7835
8310
  [controls, updateDeviceState, markPending, commandTimeoutMs]
7836
8311
  );
7837
- const sendModeChange = (0, import_react18.useCallback)(
8312
+ const sendModeChange = (0, import_react19.useCallback)(
7838
8313
  (nodeId, mode) => runCommand(
7839
8314
  nodeId,
7840
8315
  commandKey(nodeId, "mode"),
@@ -7843,7 +8318,7 @@ function useDeviceControls(initialBindings, options) {
7843
8318
  ),
7844
8319
  [runCommand]
7845
8320
  );
7846
- const sendParameterChange = (0, import_react18.useCallback)(
8321
+ const sendParameterChange = (0, import_react19.useCallback)(
7847
8322
  (nodeId, parameterId, value) => runCommand(
7848
8323
  nodeId,
7849
8324
  commandKey(nodeId, "parameter", parameterId),
@@ -7852,21 +8327,21 @@ function useDeviceControls(initialBindings, options) {
7852
8327
  ),
7853
8328
  [runCommand]
7854
8329
  );
7855
- const sendStartCommand = (0, import_react18.useCallback)(
8330
+ const sendStartCommand = (0, import_react19.useCallback)(
7856
8331
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
7857
8332
  success: "Start command sent",
7858
8333
  failure: "Start command failed"
7859
8334
  }),
7860
8335
  [runCommand]
7861
8336
  );
7862
- const sendStopCommand = (0, import_react18.useCallback)(
8337
+ const sendStopCommand = (0, import_react19.useCallback)(
7863
8338
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
7864
8339
  success: "Stop command sent",
7865
8340
  failure: "Stop command failed"
7866
8341
  }),
7867
8342
  [runCommand]
7868
8343
  );
7869
- const sendCustomAction = (0, import_react18.useCallback)(
8344
+ const sendCustomAction = (0, import_react19.useCallback)(
7870
8345
  (nodeId, actionId) => runCommand(
7871
8346
  nodeId,
7872
8347
  commandKey(nodeId, "action", actionId),
@@ -7919,9 +8394,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
7919
8394
  }
7920
8395
 
7921
8396
  // src/hooks/useDeviceConfigs.ts
7922
- var import_react19 = require("react");
8397
+ var import_react20 = require("react");
7923
8398
  function useDeviceConfigs(initialConfigs) {
7924
- const [configs, setConfigs] = (0, import_react19.useState)(() => {
8399
+ const [configs, setConfigs] = (0, import_react20.useState)(() => {
7925
8400
  const map = /* @__PURE__ */ new Map();
7926
8401
  if (initialConfigs) {
7927
8402
  initialConfigs.forEach((config) => {
@@ -7930,13 +8405,13 @@ function useDeviceConfigs(initialConfigs) {
7930
8405
  }
7931
8406
  return map;
7932
8407
  });
7933
- const getConfig = (0, import_react19.useCallback)(
8408
+ const getConfig = (0, import_react20.useCallback)(
7934
8409
  (nodeId) => {
7935
8410
  return configs.get(nodeId);
7936
8411
  },
7937
8412
  [configs]
7938
8413
  );
7939
- const updateConfig = (0, import_react19.useCallback)((nodeId, updates) => {
8414
+ const updateConfig = (0, import_react20.useCallback)((nodeId, updates) => {
7940
8415
  setConfigs((prev) => {
7941
8416
  const newMap = new Map(prev);
7942
8417
  const existing = newMap.get(nodeId);
@@ -7950,7 +8425,7 @@ function useDeviceConfigs(initialConfigs) {
7950
8425
  return newMap;
7951
8426
  });
7952
8427
  }, []);
7953
- const updateConfigState = (0, import_react19.useCallback)((nodeId, stateUpdates) => {
8428
+ const updateConfigState = (0, import_react20.useCallback)((nodeId, stateUpdates) => {
7954
8429
  setConfigs((prev) => {
7955
8430
  const newMap = new Map(prev);
7956
8431
  const existing = newMap.get(nodeId);
@@ -7963,7 +8438,7 @@ function useDeviceConfigs(initialConfigs) {
7963
8438
  return newMap;
7964
8439
  });
7965
8440
  }, []);
7966
- const updateConfigBatch = (0, import_react19.useCallback)((updates) => {
8441
+ const updateConfigBatch = (0, import_react20.useCallback)((updates) => {
7967
8442
  setConfigs((prev) => {
7968
8443
  const newMap = new Map(prev);
7969
8444
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7975,7 +8450,7 @@ function useDeviceConfigs(initialConfigs) {
7975
8450
  return newMap;
7976
8451
  });
7977
8452
  }, []);
7978
- const updateParameterValue = (0, import_react19.useCallback)((nodeId, parameterId, value) => {
8453
+ const updateParameterValue = (0, import_react20.useCallback)((nodeId, parameterId, value) => {
7979
8454
  setConfigs((prev) => {
7980
8455
  const newMap = new Map(prev);
7981
8456
  const existing = newMap.get(nodeId);
@@ -7992,7 +8467,7 @@ function useDeviceConfigs(initialConfigs) {
7992
8467
  return newMap;
7993
8468
  });
7994
8469
  }, []);
7995
- const applyConfig = (0, import_react19.useCallback)(
8470
+ const applyConfig = (0, import_react20.useCallback)(
7996
8471
  async (nodeId) => {
7997
8472
  const config = configs.get(nodeId);
7998
8473
  if (!config || !config.actions.onApply) {
@@ -8025,7 +8500,7 @@ function useDeviceConfigs(initialConfigs) {
8025
8500
  },
8026
8501
  [configs, updateConfigState]
8027
8502
  );
8028
- const saveConfig = (0, import_react19.useCallback)(
8503
+ const saveConfig = (0, import_react20.useCallback)(
8029
8504
  async (nodeId) => {
8030
8505
  const config = configs.get(nodeId);
8031
8506
  if (!config || !config.actions.onSave) {
@@ -8059,7 +8534,7 @@ function useDeviceConfigs(initialConfigs) {
8059
8534
  },
8060
8535
  [configs, updateConfigState]
8061
8536
  );
8062
- const resetConfig = (0, import_react19.useCallback)(
8537
+ const resetConfig = (0, import_react20.useCallback)(
8063
8538
  async (nodeId) => {
8064
8539
  const config = configs.get(nodeId);
8065
8540
  if (!config) {
@@ -8089,7 +8564,7 @@ function useDeviceConfigs(initialConfigs) {
8089
8564
  },
8090
8565
  [configs, updateConfig, updateConfigState]
8091
8566
  );
8092
- const cancelConfig = (0, import_react19.useCallback)(
8567
+ const cancelConfig = (0, import_react20.useCallback)(
8093
8568
  (nodeId) => {
8094
8569
  const config = configs.get(nodeId);
8095
8570
  if (config?.actions.onCancel) {
@@ -8098,7 +8573,7 @@ function useDeviceConfigs(initialConfigs) {
8098
8573
  },
8099
8574
  [configs]
8100
8575
  );
8101
- const validateConfig = (0, import_react19.useCallback)(
8576
+ const validateConfig = (0, import_react20.useCallback)(
8102
8577
  (nodeId) => {
8103
8578
  const config = configs.get(nodeId);
8104
8579
  if (!config) {
@@ -8140,21 +8615,21 @@ function useDeviceConfigs(initialConfigs) {
8140
8615
  },
8141
8616
  [configs, updateConfigState]
8142
8617
  );
8143
- const setConfig = (0, import_react19.useCallback)((config) => {
8618
+ const setConfig = (0, import_react20.useCallback)((config) => {
8144
8619
  setConfigs((prev) => {
8145
8620
  const newMap = new Map(prev);
8146
8621
  newMap.set(config.nodeId, config);
8147
8622
  return newMap;
8148
8623
  });
8149
8624
  }, []);
8150
- const removeConfig = (0, import_react19.useCallback)((nodeId) => {
8625
+ const removeConfig = (0, import_react20.useCallback)((nodeId) => {
8151
8626
  setConfigs((prev) => {
8152
8627
  const newMap = new Map(prev);
8153
8628
  newMap.delete(nodeId);
8154
8629
  return newMap;
8155
8630
  });
8156
8631
  }, []);
8157
- const clearConfigs = (0, import_react19.useCallback)(() => {
8632
+ const clearConfigs = (0, import_react20.useCallback)(() => {
8158
8633
  setConfigs(/* @__PURE__ */ new Map());
8159
8634
  }, []);
8160
8635
  return {
@@ -8176,8 +8651,8 @@ function useDeviceConfigs(initialConfigs) {
8176
8651
  }
8177
8652
 
8178
8653
  // src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
8179
- var import_react20 = require("react");
8180
- var import_jsx_runtime22 = require("react/jsx-runtime");
8654
+ var import_react21 = require("react");
8655
+ var import_jsx_runtime23 = require("react/jsx-runtime");
8181
8656
  function DeviceConfigPanel({
8182
8657
  binding,
8183
8658
  onClose,
@@ -8195,7 +8670,7 @@ function DeviceConfigPanel({
8195
8670
  showControlsButton = true,
8196
8671
  embedded = false
8197
8672
  }) {
8198
- const [localValues, setLocalValues] = (0, import_react20.useState)(() => {
8673
+ const [localValues, setLocalValues] = (0, import_react21.useState)(() => {
8199
8674
  if (binding) {
8200
8675
  const values = {};
8201
8676
  binding.parameters.forEach((param) => {
@@ -8205,7 +8680,7 @@ function DeviceConfigPanel({
8205
8680
  }
8206
8681
  return {};
8207
8682
  });
8208
- const [collapsedSections, setCollapsedSections] = (0, import_react20.useState)(() => {
8683
+ const [collapsedSections, setCollapsedSections] = (0, import_react21.useState)(() => {
8209
8684
  const collapsed = /* @__PURE__ */ new Set();
8210
8685
  if (binding?.sections) {
8211
8686
  binding.sections.forEach((section) => {
@@ -8216,9 +8691,9 @@ function DeviceConfigPanel({
8216
8691
  }
8217
8692
  return collapsed;
8218
8693
  });
8219
- const [showToast, setShowToast] = (0, import_react20.useState)(true);
8220
- const [bindingId, setBindingId] = (0, import_react20.useState)(binding?.nodeId || null);
8221
- const lastResultTimestampRef = (0, import_react20.useRef)(0);
8694
+ const [showToast, setShowToast] = (0, import_react21.useState)(true);
8695
+ const [bindingId, setBindingId] = (0, import_react21.useState)(binding?.nodeId || null);
8696
+ const lastResultTimestampRef = (0, import_react21.useRef)(0);
8222
8697
  if (binding && binding.nodeId !== bindingId) {
8223
8698
  const values = {};
8224
8699
  binding.parameters.forEach((param) => {
@@ -8234,7 +8709,7 @@ function DeviceConfigPanel({
8234
8709
  setCollapsedSections(collapsed);
8235
8710
  setBindingId(binding.nodeId);
8236
8711
  }
8237
- (0, import_react20.useEffect)(() => {
8712
+ (0, import_react21.useEffect)(() => {
8238
8713
  const currentTimestamp = binding?.state.lastSaved || 0;
8239
8714
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8240
8715
  lastResultTimestampRef.current = currentTimestamp;
@@ -8248,7 +8723,7 @@ function DeviceConfigPanel({
8248
8723
  return () => clearTimeout(showTimer);
8249
8724
  }
8250
8725
  }, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
8251
- const parametersBySection = (0, import_react20.useMemo)(() => {
8726
+ const parametersBySection = (0, import_react21.useMemo)(() => {
8252
8727
  if (!binding) return { _unsectioned: [] };
8253
8728
  const groups = { _unsectioned: [] };
8254
8729
  binding.parameters.forEach((param) => {
@@ -8263,7 +8738,7 @@ function DeviceConfigPanel({
8263
8738
  });
8264
8739
  return groups;
8265
8740
  }, [binding]);
8266
- const sortedSections = (0, import_react20.useMemo)(() => {
8741
+ const sortedSections = (0, import_react21.useMemo)(() => {
8267
8742
  if (!binding?.sections) return [];
8268
8743
  return [...binding.sections].sort((a, b) => (a.order || 0) - (b.order || 0));
8269
8744
  }, [binding]);
@@ -8339,14 +8814,14 @@ function DeviceConfigPanel({
8339
8814
  const value = localValues[param.id];
8340
8815
  const error = binding.state.errors?.[param.id];
8341
8816
  const isDisabled = param.readOnly || param.enabled === false;
8342
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8817
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8343
8818
  "div",
8344
8819
  {
8345
8820
  style: {
8346
8821
  marginBottom: spacing.marginBottom
8347
8822
  },
8348
8823
  children: [
8349
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8824
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8350
8825
  "label",
8351
8826
  {
8352
8827
  style: {
@@ -8361,8 +8836,8 @@ function DeviceConfigPanel({
8361
8836
  },
8362
8837
  children: [
8363
8838
  param.label,
8364
- param.required && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: errorColor }, children: " *" }),
8365
- param.unit && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { color: mutedTextColor, fontWeight: "normal" }, children: [
8839
+ param.required && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { color: errorColor }, children: " *" }),
8840
+ param.unit && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { style: { color: mutedTextColor, fontWeight: "normal" }, children: [
8366
8841
  " (",
8367
8842
  param.unit,
8368
8843
  ")"
@@ -8370,7 +8845,7 @@ function DeviceConfigPanel({
8370
8845
  ]
8371
8846
  }
8372
8847
  ),
8373
- param.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8848
+ param.description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8374
8849
  "div",
8375
8850
  {
8376
8851
  style: {
@@ -8382,7 +8857,7 @@ function DeviceConfigPanel({
8382
8857
  children: param.description
8383
8858
  }
8384
8859
  ),
8385
- param.type === "number" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8860
+ param.type === "number" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8386
8861
  "input",
8387
8862
  {
8388
8863
  type: "number",
@@ -8406,7 +8881,7 @@ function DeviceConfigPanel({
8406
8881
  }
8407
8882
  }
8408
8883
  ),
8409
- param.type === "string" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8884
+ param.type === "string" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8410
8885
  "input",
8411
8886
  {
8412
8887
  type: "text",
@@ -8427,7 +8902,7 @@ function DeviceConfigPanel({
8427
8902
  }
8428
8903
  }
8429
8904
  ),
8430
- param.type === "boolean" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8905
+ param.type === "boolean" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8431
8906
  "label",
8432
8907
  {
8433
8908
  style: {
@@ -8437,7 +8912,7 @@ function DeviceConfigPanel({
8437
8912
  cursor: isDisabled ? "not-allowed" : "pointer"
8438
8913
  },
8439
8914
  children: [
8440
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8915
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8441
8916
  "input",
8442
8917
  {
8443
8918
  type: "checkbox",
@@ -8451,11 +8926,11 @@ function DeviceConfigPanel({
8451
8926
  }
8452
8927
  }
8453
8928
  ),
8454
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: `${fontSize.value}px`, color: textColor }, children: value ? "Enabled" : "Disabled" })
8929
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: `${fontSize.value}px`, color: textColor }, children: value ? "Enabled" : "Disabled" })
8455
8930
  ]
8456
8931
  }
8457
8932
  ),
8458
- param.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8933
+ param.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8459
8934
  "select",
8460
8935
  {
8461
8936
  value: value ?? "",
@@ -8473,10 +8948,10 @@ function DeviceConfigPanel({
8473
8948
  borderRadius: "2px",
8474
8949
  outline: "none"
8475
8950
  },
8476
- children: param.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: option.value, children: option.label }, option.value))
8951
+ children: param.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: option.value, children: option.label }, option.value))
8477
8952
  }
8478
8953
  ),
8479
- error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8954
+ error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8480
8955
  "div",
8481
8956
  {
8482
8957
  style: {
@@ -8496,7 +8971,7 @@ function DeviceConfigPanel({
8496
8971
  const renderSection = (section) => {
8497
8972
  const params = parametersBySection[section.id] || [];
8498
8973
  const isCollapsed = collapsedSections.has(section.id);
8499
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8974
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8500
8975
  "div",
8501
8976
  {
8502
8977
  style: {
@@ -8506,7 +8981,7 @@ function DeviceConfigPanel({
8506
8981
  backgroundColor: surfaceColor
8507
8982
  },
8508
8983
  children: [
8509
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8984
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8510
8985
  "div",
8511
8986
  {
8512
8987
  onClick: () => section.collapsible && toggleSection(section.id),
@@ -8519,8 +8994,8 @@ function DeviceConfigPanel({
8519
8994
  alignItems: "center"
8520
8995
  },
8521
8996
  children: [
8522
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
8523
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8997
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
8998
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8524
8999
  "div",
8525
9000
  {
8526
9001
  style: {
@@ -8532,12 +9007,12 @@ function DeviceConfigPanel({
8532
9007
  letterSpacing: "0.5px"
8533
9008
  },
8534
9009
  children: [
8535
- section.icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { marginRight: "8px" }, children: section.icon }),
9010
+ section.icon && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { marginRight: "8px" }, children: section.icon }),
8536
9011
  section.title
8537
9012
  ]
8538
9013
  }
8539
9014
  ),
8540
- section.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9015
+ section.description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8541
9016
  "div",
8542
9017
  {
8543
9018
  style: {
@@ -8550,11 +9025,11 @@ function DeviceConfigPanel({
8550
9025
  }
8551
9026
  )
8552
9027
  ] }),
8553
- section.collapsible && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: "16px", color: mutedTextColor }, children: isCollapsed ? "\u25BC" : "\u25B2" })
9028
+ section.collapsible && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: "16px", color: mutedTextColor }, children: isCollapsed ? "\u25BC" : "\u25B2" })
8554
9029
  ]
8555
9030
  }
8556
9031
  ),
8557
- !isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { padding: spacing.padding }, children: params.map(renderParameter) })
9032
+ !isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: spacing.padding }, children: params.map(renderParameter) })
8558
9033
  ]
8559
9034
  },
8560
9035
  section.id
@@ -8613,9 +9088,9 @@ function DeviceConfigPanel({
8613
9088
  const showSave = binding.display?.showSave !== false && binding.actions.onSave;
8614
9089
  const showReset = binding.display?.showReset !== false && binding.actions.onReset;
8615
9090
  const showCancel = binding.display?.showCancel !== false;
8616
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
8617
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
8618
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
9091
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
9092
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
9093
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8619
9094
  "div",
8620
9095
  {
8621
9096
  style: {
@@ -8627,8 +9102,8 @@ function DeviceConfigPanel({
8627
9102
  borderBottom: `2px solid ${borderColor}`
8628
9103
  },
8629
9104
  children: [
8630
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
8631
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9105
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
9106
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8632
9107
  "h3",
8633
9108
  {
8634
9109
  style: {
@@ -8648,7 +9123,7 @@ function DeviceConfigPanel({
8648
9123
  children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
8649
9124
  }
8650
9125
  ),
8651
- binding.display?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9126
+ binding.display?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8652
9127
  "div",
8653
9128
  {
8654
9129
  style: {
@@ -8661,8 +9136,8 @@ function DeviceConfigPanel({
8661
9136
  }
8662
9137
  )
8663
9138
  ] }),
8664
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
8665
- showControlsButton && onOpenControls && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9139
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
9140
+ showControlsButton && onOpenControls && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8666
9141
  "button",
8667
9142
  {
8668
9143
  onClick: onOpenControls,
@@ -8685,7 +9160,7 @@ function DeviceConfigPanel({
8685
9160
  children: "CTRL"
8686
9161
  }
8687
9162
  ),
8688
- onUndock && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9163
+ onUndock && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8689
9164
  "button",
8690
9165
  {
8691
9166
  onClick: onUndock,
@@ -8706,7 +9181,7 @@ function DeviceConfigPanel({
8706
9181
  children: undockIcon
8707
9182
  }
8708
9183
  ),
8709
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9184
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8710
9185
  "button",
8711
9186
  {
8712
9187
  onClick: onClose,
@@ -8729,7 +9204,7 @@ function DeviceConfigPanel({
8729
9204
  ]
8730
9205
  }
8731
9206
  ),
8732
- binding.state.isDirty && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9207
+ binding.state.isDirty && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8733
9208
  "div",
8734
9209
  {
8735
9210
  style: {
@@ -8744,11 +9219,11 @@ function DeviceConfigPanel({
8744
9219
  children: "Unsaved changes"
8745
9220
  }
8746
9221
  ),
8747
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflowY: "auto", marginBottom: spacing.marginBottom }, children: sortedSections.length > 0 ? sortedSections.map(renderSection) : (
9222
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1, overflowY: "auto", marginBottom: spacing.marginBottom }, children: sortedSections.length > 0 ? sortedSections.map(renderSection) : (
8748
9223
  /* Render unsectioned parameters */
8749
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
9224
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { children: parametersBySection._unsectioned?.map(renderParameter) })
8750
9225
  ) }),
8751
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
9226
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8752
9227
  "div",
8753
9228
  {
8754
9229
  style: {
@@ -8759,7 +9234,7 @@ function DeviceConfigPanel({
8759
9234
  flexWrap: "wrap"
8760
9235
  },
8761
9236
  children: [
8762
- showApply && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9237
+ showApply && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8763
9238
  "button",
8764
9239
  {
8765
9240
  onClick: handleApply,
@@ -8782,7 +9257,7 @@ function DeviceConfigPanel({
8782
9257
  children: binding.state.isSaving ? "Applying..." : "Apply"
8783
9258
  }
8784
9259
  ),
8785
- showSave && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9260
+ showSave && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8786
9261
  "button",
8787
9262
  {
8788
9263
  onClick: handleSave,
@@ -8805,7 +9280,7 @@ function DeviceConfigPanel({
8805
9280
  children: binding.state.isSaving ? "Saving..." : "Save"
8806
9281
  }
8807
9282
  ),
8808
- showReset && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9283
+ showReset && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8809
9284
  "button",
8810
9285
  {
8811
9286
  onClick: handleReset,
@@ -8828,7 +9303,7 @@ function DeviceConfigPanel({
8828
9303
  children: "Reset"
8829
9304
  }
8830
9305
  ),
8831
- showCancel && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9306
+ showCancel && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8832
9307
  "button",
8833
9308
  {
8834
9309
  onClick: handleCancel,
@@ -8855,7 +9330,7 @@ function DeviceConfigPanel({
8855
9330
  }
8856
9331
  )
8857
9332
  ] }),
8858
- binding.state.lastSaveResult && showToast && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9333
+ binding.state.lastSaveResult && showToast && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8859
9334
  "div",
8860
9335
  {
8861
9336
  style: {
@@ -8879,7 +9354,7 @@ function DeviceConfigPanel({
8879
9354
  }
8880
9355
 
8881
9356
  // src/diagram/hooks/useSimulation.ts
8882
- var import_react21 = require("react");
9357
+ var import_react22 = require("react");
8883
9358
  function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8884
9359
  const {
8885
9360
  interval = 2e3,
@@ -8890,7 +9365,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8890
9365
  historyLength = 10,
8891
9366
  generateValue
8892
9367
  } = options;
8893
- (0, import_react21.useEffect)(() => {
9368
+ (0, import_react22.useEffect)(() => {
8894
9369
  if (!enabled) return;
8895
9370
  const intervalId = setInterval(() => {
8896
9371
  const updates = [];
@@ -8963,6 +9438,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8963
9438
  LegacyValueEntry,
8964
9439
  NodeConfigPanel,
8965
9440
  NodeControlsPanel,
9441
+ NumpadDialog,
8966
9442
  PIDCanvas,
8967
9443
  PanelContent,
8968
9444
  PanelTabs,