@procaaso/alphinity-ui-components 1.4.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,
@@ -1943,14 +1944,457 @@ function DeviceControlPanel({
1943
1944
  ] });
1944
1945
  }
1945
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
+
1946
2390
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
1947
- var import_react7 = __toESM(require("react"), 1);
2391
+ var import_react8 = __toESM(require("react"), 1);
1948
2392
  var import_material3 = require("@mui/material");
1949
2393
 
1950
2394
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.styles.tsx
1951
2395
  var import_material = require("@mui/material");
1952
2396
  var import_styled = __toESM(require("@emotion/styled"), 1);
1953
- var import_jsx_runtime9 = require("react/jsx-runtime");
2397
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1954
2398
  var FullscreenContainer = (0, import_styled.default)(import_material.Box)(
1955
2399
  ({ leftCollapsed, rightCollapsed }) => {
1956
2400
  const getGridTemplateAreas = () => {
@@ -2075,7 +2519,7 @@ var DisplayModeToggle = (0, import_styled.default)(import_material.IconButton)((
2075
2519
  transform: "translateX(-50%) scale(1.05)"
2076
2520
  }
2077
2521
  }));
2078
- var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2522
+ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2079
2523
  "div",
2080
2524
  {
2081
2525
  style: {
@@ -2087,7 +2531,7 @@ var ChevronLeft = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2087
2531
  }
2088
2532
  }
2089
2533
  );
2090
- var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2534
+ var ChevronRight = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2091
2535
  "div",
2092
2536
  {
2093
2537
  style: {
@@ -2198,10 +2642,10 @@ var ScrollableSVGWrapper = (0, import_styled.default)("div")({
2198
2642
  });
2199
2643
 
2200
2644
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.overlays.tsx
2201
- var import_react6 = require("react");
2645
+ var import_react7 = require("react");
2202
2646
  var import_material2 = require("@mui/material");
2203
2647
  var import_styled2 = __toESM(require("@emotion/styled"), 1);
2204
- var import_jsx_runtime10 = require("react/jsx-runtime");
2648
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2205
2649
  var baseOverlayStyles = {
2206
2650
  tank: {
2207
2651
  background: "linear-gradient(135deg, rgba(69, 90, 120, 0.95) 0%, rgba(52, 73, 94, 0.95) 100%)",
@@ -2263,8 +2707,8 @@ var SVGLockedOverlay = ({
2263
2707
  onClick,
2264
2708
  containerSelector = ".tff-svg-container"
2265
2709
  }) => {
2266
- const [svgOffset, setSvgOffset] = (0, import_react6.useState)({ x: 0, y: 0 });
2267
- (0, import_react6.useEffect)(() => {
2710
+ const [svgOffset, setSvgOffset] = (0, import_react7.useState)({ x: 0, y: 0 });
2711
+ (0, import_react7.useEffect)(() => {
2268
2712
  const updateSvgOffset = () => {
2269
2713
  const containerElement = document.querySelector(containerSelector);
2270
2714
  const svgElement = containerElement?.querySelector("svg");
@@ -2284,7 +2728,7 @@ var SVGLockedOverlay = ({
2284
2728
  const pixelX = svgX + svgOffset.x;
2285
2729
  const pixelY = svgY + svgOffset.y;
2286
2730
  const appliedStyle = theme ? { ...overlayStyles[theme], ...style } : style;
2287
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2731
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2288
2732
  import_material2.Box,
2289
2733
  {
2290
2734
  className: `svg-locked-overlay ${className}`.trim(),
@@ -2348,7 +2792,7 @@ var CardUnit = (0, import_styled2.default)("div")({
2348
2792
  });
2349
2793
 
2350
2794
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.visuals.tsx
2351
- var import_jsx_runtime11 = require("react/jsx-runtime");
2795
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2352
2796
  var TrendLine = ({
2353
2797
  values,
2354
2798
  width = 60,
@@ -2358,7 +2802,7 @@ var TrendLine = ({
2358
2802
  backgroundColor = "rgba(255, 255, 255, 0.1)"
2359
2803
  }) => {
2360
2804
  if (!values || values.length < 2) {
2361
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2805
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2362
2806
  "div",
2363
2807
  {
2364
2808
  style: {
@@ -2370,7 +2814,7 @@ var TrendLine = ({
2370
2814
  alignItems: "center",
2371
2815
  justifyContent: "center"
2372
2816
  },
2373
- 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" })
2374
2818
  }
2375
2819
  );
2376
2820
  }
@@ -2382,7 +2826,7 @@ var TrendLine = ({
2382
2826
  const x = 4 + i / (values.length - 1) * (width - 8);
2383
2827
  return i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
2384
2828
  }).join(" ");
2385
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2829
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2386
2830
  "div",
2387
2831
  {
2388
2832
  style: {
@@ -2393,8 +2837,8 @@ var TrendLine = ({
2393
2837
  position: "relative",
2394
2838
  overflow: "hidden"
2395
2839
  },
2396
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width, height, style: { position: "absolute", top: 0, left: 0 }, children: [
2397
- /* @__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)(
2398
2842
  "path",
2399
2843
  {
2400
2844
  d: pathData,
@@ -2405,7 +2849,7 @@ var TrendLine = ({
2405
2849
  strokeLinejoin: "round"
2406
2850
  }
2407
2851
  ),
2408
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2852
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2409
2853
  "circle",
2410
2854
  {
2411
2855
  cx: 4 + (width - 8),
@@ -2443,7 +2887,7 @@ var CircularGauge = ({
2443
2887
  const borderColor = isHex ? hexToRgba(color, 0.9) : color;
2444
2888
  const backgroundColor = isHex ? hexToRgba(color, 0.15) : color;
2445
2889
  const borderStrokeColor = isHex ? hexToRgba(color, 0.4) : color;
2446
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2447
2891
  "div",
2448
2892
  {
2449
2893
  style: {
@@ -2452,7 +2896,7 @@ var CircularGauge = ({
2452
2896
  alignItems: "center"
2453
2897
  },
2454
2898
  children: [
2455
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2899
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2456
2900
  "div",
2457
2901
  {
2458
2902
  style: {
@@ -2464,8 +2908,8 @@ var CircularGauge = ({
2464
2908
  border: `1px solid ${borderStrokeColor}`
2465
2909
  },
2466
2910
  children: [
2467
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" }, children: [
2468
- /* @__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)(
2469
2913
  "circle",
2470
2914
  {
2471
2915
  cx: size / 2,
@@ -2476,7 +2920,7 @@ var CircularGauge = ({
2476
2920
  strokeWidth: 1
2477
2921
  }
2478
2922
  ),
2479
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2923
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2480
2924
  "circle",
2481
2925
  {
2482
2926
  cx: size / 2,
@@ -2487,7 +2931,7 @@ var CircularGauge = ({
2487
2931
  fill: "transparent"
2488
2932
  }
2489
2933
  ),
2490
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2934
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2491
2935
  "circle",
2492
2936
  {
2493
2937
  cx: size / 2,
@@ -2503,7 +2947,7 @@ var CircularGauge = ({
2503
2947
  }
2504
2948
  )
2505
2949
  ] }),
2506
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2950
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2507
2951
  "div",
2508
2952
  {
2509
2953
  style: {
@@ -2519,14 +2963,14 @@ var CircularGauge = ({
2519
2963
  },
2520
2964
  children: [
2521
2965
  value.toFixed(1),
2522
- /* @__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 })
2523
2967
  ]
2524
2968
  }
2525
2969
  )
2526
2970
  ]
2527
2971
  }
2528
2972
  ),
2529
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2973
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2530
2974
  "div",
2531
2975
  {
2532
2976
  style: {
@@ -2557,7 +3001,7 @@ var Sparkline = ({ data, width, height, color }) => {
2557
3001
  const y = height - 8 - (value - min) / range * (height - 8);
2558
3002
  return `${x + 4},${y + 4}`;
2559
3003
  }).join(" ");
2560
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3004
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2561
3005
  "div",
2562
3006
  {
2563
3007
  style: {
@@ -2571,7 +3015,7 @@ var Sparkline = ({ data, width, height, color }) => {
2571
3015
  justifyContent: "center",
2572
3016
  boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)"
2573
3017
  },
2574
- 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" }) })
2575
3019
  }
2576
3020
  );
2577
3021
  };
@@ -2585,8 +3029,8 @@ var EquipmentIndicatorWithSparkline = ({
2585
3029
  sparklineOffset = { x: 40, y: 0 }
2586
3030
  }) => {
2587
3031
  const hasSparkline = sparklineData && sparklineData.length > 1 && Math.max(...sparklineData) !== Math.min(...sparklineData);
2588
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2589
- /* @__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)(
2590
3034
  "div",
2591
3035
  {
2592
3036
  style: {
@@ -2607,7 +3051,7 @@ var EquipmentIndicatorWithSparkline = ({
2607
3051
  children: label
2608
3052
  }
2609
3053
  ) }),
2610
- 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 }) })
2611
3055
  ] });
2612
3056
  };
2613
3057
  var EquipmentIndicator = ({
@@ -2620,7 +3064,7 @@ var EquipmentIndicator = ({
2620
3064
  className
2621
3065
  }) => {
2622
3066
  const overlayStyle = style !== void 0 ? { transform: "translate(-50%, -50%)", ...style } : { transform: "translate(-50%, -50%)" };
2623
- 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)(
2624
3068
  "div",
2625
3069
  {
2626
3070
  style: {
@@ -2644,7 +3088,7 @@ var EquipmentIndicator = ({
2644
3088
  };
2645
3089
 
2646
3090
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx
2647
- var import_jsx_runtime12 = require("react/jsx-runtime");
3091
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2648
3092
  function FullscreenWorkspace({
2649
3093
  svgContent,
2650
3094
  overlays,
@@ -2672,10 +3116,10 @@ function FullscreenWorkspace({
2672
3116
  className = "",
2673
3117
  ...rest
2674
3118
  }) {
2675
- const [leftCollapsedState, setLeftCollapsedState] = import_react7.default.useState(defaultLeftCollapsed);
2676
- const [rightCollapsedState, setRightCollapsedState] = import_react7.default.useState(defaultRightCollapsed);
2677
- const [internalDisplayMode, setInternalDisplayMode] = import_react7.default.useState(displayMode ?? defaultDisplayMode);
2678
- 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(
2679
3123
  tabs && tabs.length > 0 ? tabs[0].value : ""
2680
3124
  );
2681
3125
  const leftCollapsed = leftCollapsedProp ?? leftCollapsedState;
@@ -2683,10 +3127,10 @@ function FullscreenWorkspace({
2683
3127
  const isDisplayModeControlled = displayMode !== void 0;
2684
3128
  const currentDisplayMode = isDisplayModeControlled ? displayMode : internalDisplayMode;
2685
3129
  const isTabControlled = activeTab !== void 0 && activeTab !== null;
2686
- const resolvedTabs = import_react7.default.useMemo(() => tabs ?? [], [tabs]);
3130
+ const resolvedTabs = import_react8.default.useMemo(() => tabs ?? [], [tabs]);
2687
3131
  const defaultTabValue = resolvedTabs.length > 0 ? resolvedTabs[0].value : "";
2688
3132
  const currentTab = isTabControlled ? activeTab : internalTab || defaultTabValue;
2689
- import_react7.default.useEffect(() => {
3133
+ import_react8.default.useEffect(() => {
2690
3134
  if (resolvedTabs.length > 0) {
2691
3135
  const values = resolvedTabs.map((tab) => tab.value);
2692
3136
  if (!values.includes(currentTab)) {
@@ -2695,7 +3139,7 @@ function FullscreenWorkspace({
2695
3139
  }
2696
3140
  }
2697
3141
  }, [resolvedTabs, activeTab, currentTab, defaultTabValue]);
2698
- import_react7.default.useEffect(() => {
3142
+ import_react8.default.useEffect(() => {
2699
3143
  if (displayMode !== void 0) {
2700
3144
  setInternalDisplayMode(displayMode);
2701
3145
  }
@@ -2730,7 +3174,7 @@ function FullscreenWorkspace({
2730
3174
  const currentTabContent = resolvedTabs.find((tab) => tab.value === currentTab)?.content ?? null;
2731
3175
  const showLeftToggle = Boolean(leftPanel);
2732
3176
  const showRightToggle = Boolean(rightPanel);
2733
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3177
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2734
3178
  FullscreenContainer,
2735
3179
  {
2736
3180
  leftCollapsed,
@@ -2738,25 +3182,25 @@ function FullscreenWorkspace({
2738
3182
  className: `tff-svg-container ${className}`.trim(),
2739
3183
  ...rest,
2740
3184
  children: [
2741
- showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3185
+ showLeftToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2742
3186
  LeftToggleButton,
2743
3187
  {
2744
3188
  collapsed: leftCollapsed,
2745
3189
  onClick: handleLeftToggle,
2746
3190
  "aria-label": leftCollapsed ? "Expand left panel" : "Collapse left panel",
2747
- 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, {})
2748
3192
  }
2749
3193
  ),
2750
- showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3194
+ showRightToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2751
3195
  RightToggleButton,
2752
3196
  {
2753
3197
  collapsed: rightCollapsed,
2754
3198
  onClick: handleRightToggle,
2755
3199
  "aria-label": rightCollapsed ? "Expand right panel" : "Collapse right panel",
2756
- 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, {})
2757
3201
  }
2758
3202
  ),
2759
- showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3203
+ showDisplayModeToggle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2760
3204
  DisplayModeToggle,
2761
3205
  {
2762
3206
  mode: currentDisplayMode,
@@ -2765,9 +3209,9 @@ function FullscreenWorkspace({
2765
3209
  children: currentDisplayMode === "dashboard" ? "Dashboard Mode" : "Standard Mode"
2766
3210
  }
2767
3211
  ),
2768
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SVGArea, { children: [
2769
- showZoomControls && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(ZoomControls, { children: [
2770
- /* @__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)(
2771
3215
  ZoomButton,
2772
3216
  {
2773
3217
  onClick: onZoomIn,
@@ -2777,7 +3221,7 @@ function FullscreenWorkspace({
2777
3221
  children: "+"
2778
3222
  }
2779
3223
  ),
2780
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3224
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2781
3225
  ZoomButton,
2782
3226
  {
2783
3227
  onClick: onZoomOut,
@@ -2787,7 +3231,7 @@ function FullscreenWorkspace({
2787
3231
  children: "-"
2788
3232
  }
2789
3233
  ),
2790
- onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3234
+ onResetZoom && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2791
3235
  ZoomButton,
2792
3236
  {
2793
3237
  onClick: onResetZoom,
@@ -2798,44 +3242,44 @@ function FullscreenWorkspace({
2798
3242
  }
2799
3243
  )
2800
3244
  ] }),
2801
- /* @__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: [
2802
3246
  svgContent,
2803
3247
  overlays
2804
3248
  ] }) })
2805
3249
  ] }),
2806
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LeftPanel, { collapsed: leftCollapsed, children: resolvedTabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2807
- /* @__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)(
2808
3252
  PanelTabs,
2809
3253
  {
2810
3254
  value: currentTab,
2811
3255
  onChange: handleTabChangeInternal,
2812
3256
  "aria-label": "Left panel tabs",
2813
- 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))
2814
3258
  }
2815
3259
  ),
2816
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PanelContent, { children: currentTabContent })
3260
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PanelContent, { children: currentTabContent })
2817
3261
  ] }) : leftPanel }),
2818
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RightPanel, { collapsed: rightCollapsed, children: rightPanel }),
2819
- /* @__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 })
2820
3264
  ]
2821
3265
  }
2822
3266
  );
2823
3267
  }
2824
3268
 
2825
3269
  // src/theme/ThemeContext.tsx
2826
- var import_react8 = require("react");
2827
- var import_jsx_runtime13 = require("react/jsx-runtime");
2828
- 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);
2829
3273
  var useTheme = () => {
2830
- const context = (0, import_react8.useContext)(ThemeContext);
3274
+ const context = (0, import_react9.useContext)(ThemeContext);
2831
3275
  if (!context) {
2832
3276
  throw new Error("useTheme must be used within a ThemeProvider");
2833
3277
  }
2834
3278
  return context;
2835
3279
  };
2836
3280
  var ThemeProvider = ({ children }) => {
2837
- const [theme, setThemeState] = (0, import_react8.useState)("modern");
2838
- (0, import_react8.useEffect)(() => {
3281
+ const [theme, setThemeState] = (0, import_react9.useState)("modern");
3282
+ (0, import_react9.useEffect)(() => {
2839
3283
  document.body.className = "";
2840
3284
  document.body.classList.add(`theme-${theme}`);
2841
3285
  document.documentElement.className = "";
@@ -2847,11 +3291,11 @@ var ThemeProvider = ({ children }) => {
2847
3291
  const setTheme = (newTheme) => {
2848
3292
  setThemeState(newTheme);
2849
3293
  };
2850
- 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 });
2851
3295
  };
2852
3296
 
2853
3297
  // src/theme/ThemeToggle.tsx
2854
- var import_jsx_runtime14 = require("react/jsx-runtime");
3298
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2855
3299
  var ThemeToggle = ({
2856
3300
  size = "medium",
2857
3301
  position = "top-right",
@@ -2922,15 +3366,15 @@ var ThemeToggle = ({
2922
3366
  transition: "all 0.2s ease",
2923
3367
  boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)"
2924
3368
  };
2925
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: currentStyle, onClick: toggleTheme, className, ...props, children: [
2926
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: theme === "modern" ? "\u{1F3A8} Modern" : "\u{1F3ED} HMI" }),
2927
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: toggleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: thumbStyle }) }),
2928
- /* @__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" })
2929
3373
  ] });
2930
3374
  };
2931
3375
 
2932
3376
  // src/components/PIDCanvas/PIDCanvas.tsx
2933
- var import_react16 = require("react");
3377
+ var import_react17 = require("react");
2934
3378
 
2935
3379
  // src/diagram/symbols/mockSymbolLibrary.ts
2936
3380
  var mockSymbolLibrary = {
@@ -4151,7 +4595,7 @@ function getAvailableSymbols() {
4151
4595
  }
4152
4596
 
4153
4597
  // src/components/PIDCanvas/NodeRenderer.tsx
4154
- var import_jsx_runtime15 = require("react/jsx-runtime");
4598
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4155
4599
  function NodeRenderer({
4156
4600
  nodes: nodes2,
4157
4601
  selectedNodeIds,
@@ -4163,13 +4607,13 @@ function NodeRenderer({
4163
4607
  enableDrag = false,
4164
4608
  statusColorMap
4165
4609
  }) {
4166
- 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) => {
4167
4611
  const symbol = getSymbolDefinition(node.symbolId);
4168
4612
  const isSelected = selectedNodeIds?.has(node.id) ?? false;
4169
4613
  const isDragging = draggingNodeId === node.id;
4170
4614
  if (!symbol) {
4171
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { children: [
4172
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4615
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
4616
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4173
4617
  "circle",
4174
4618
  {
4175
4619
  cx: node.transform.x,
@@ -4181,7 +4625,7 @@ function NodeRenderer({
4181
4625
  strokeWidth: "2"
4182
4626
  }
4183
4627
  ),
4184
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4628
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4185
4629
  "text",
4186
4630
  {
4187
4631
  x: node.transform.x,
@@ -4223,7 +4667,7 @@ function NodeRenderer({
4223
4667
  const statusEntry = resolveStatusColor(node.status, statusColorMap);
4224
4668
  const fillColor = node.customColors?.fill ?? statusEntry.fill;
4225
4669
  const strokeColor = node.customColors?.stroke ?? statusEntry.stroke;
4226
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4670
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4227
4671
  "g",
4228
4672
  {
4229
4673
  "data-node-id": node.id,
@@ -4256,7 +4700,7 @@ function NodeRenderer({
4256
4700
  }
4257
4701
  },
4258
4702
  children: [
4259
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4703
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4260
4704
  "rect",
4261
4705
  {
4262
4706
  x: "-5",
@@ -4271,7 +4715,7 @@ function NodeRenderer({
4271
4715
  pointerEvents: "none"
4272
4716
  }
4273
4717
  ),
4274
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4718
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4275
4719
  "g",
4276
4720
  {
4277
4721
  dangerouslySetInnerHTML: { __html: symbol.svgContent },
@@ -4279,7 +4723,7 @@ function NodeRenderer({
4279
4723
  style: { pointerEvents: "auto" }
4280
4724
  }
4281
4725
  ),
4282
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4726
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4283
4727
  "text",
4284
4728
  {
4285
4729
  x: symbol.viewBox.width / 2 + (node.labelOffset?.x ?? 0),
@@ -4300,7 +4744,7 @@ function NodeRenderer({
4300
4744
  }
4301
4745
 
4302
4746
  // src/components/PIDCanvas/PipeRenderer.tsx
4303
- var import_jsx_runtime16 = require("react/jsx-runtime");
4747
+ var import_jsx_runtime17 = require("react/jsx-runtime");
4304
4748
  function PipeRenderer({
4305
4749
  pipes,
4306
4750
  selectedPipeIds,
@@ -4315,7 +4759,7 @@ function PipeRenderer({
4315
4759
  waypointDragOffset,
4316
4760
  onPipeSegmentClick
4317
4761
  }) {
4318
- 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) => {
4319
4763
  const isSelected = selectedPipeIds?.has(pipe.id) ?? false;
4320
4764
  const isEditing = enableWaypointEditing && editingPipeId === pipe.id;
4321
4765
  const showEditingControls = enableWaypointEditing && isSelected;
@@ -4334,7 +4778,7 @@ function PipeRenderer({
4334
4778
  const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
4335
4779
  const strokeDasharray = pipeStyle.strokeDasharray;
4336
4780
  const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
4337
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4781
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4338
4782
  "g",
4339
4783
  {
4340
4784
  "data-pipe-id": pipe.id,
@@ -4347,8 +4791,8 @@ function PipeRenderer({
4347
4791
  cursor: onPipeClick ? "pointer" : "default"
4348
4792
  },
4349
4793
  children: [
4350
- !enableWaypointEditing && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
4351
- 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)(
4352
4796
  "polyline",
4353
4797
  {
4354
4798
  points: pointsString,
@@ -4360,7 +4804,7 @@ function PipeRenderer({
4360
4804
  pointerEvents: "stroke"
4361
4805
  }
4362
4806
  ),
4363
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4807
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4364
4808
  "polyline",
4365
4809
  {
4366
4810
  points: pointsString,
@@ -4384,7 +4828,7 @@ function PipeRenderer({
4384
4828
  const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
4385
4829
  const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
4386
4830
  const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
4387
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4831
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4388
4832
  "circle",
4389
4833
  {
4390
4834
  cx: point.x,
@@ -4421,12 +4865,12 @@ function PipeRenderer({
4421
4865
  `${pipe.id}-point-${idx}`
4422
4866
  );
4423
4867
  }),
4424
- 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) => {
4425
4869
  const nextPoint = displayPoints[idx + 1];
4426
4870
  const midX = (point.x + nextPoint.x) / 2;
4427
4871
  const midY = (point.y + nextPoint.y) / 2;
4428
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("g", { children: [
4429
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4872
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { children: [
4873
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4430
4874
  "circle",
4431
4875
  {
4432
4876
  cx: midX,
@@ -4442,7 +4886,7 @@ function PipeRenderer({
4442
4886
  }
4443
4887
  }
4444
4888
  ),
4445
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4889
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4446
4890
  "circle",
4447
4891
  {
4448
4892
  cx: midX,
@@ -4458,7 +4902,7 @@ function PipeRenderer({
4458
4902
  )
4459
4903
  ] }, `${pipe.id}-segment-${idx}`);
4460
4904
  }) }),
4461
- 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)(
4462
4906
  "text",
4463
4907
  {
4464
4908
  x: pipe.routePoints[Math.floor(pipe.routePoints.length / 2)].x + (pipe.labelOffset?.x ?? 0),
@@ -4480,7 +4924,7 @@ function PipeRenderer({
4480
4924
  }
4481
4925
 
4482
4926
  // src/components/PIDCanvas/DataOverlay.tsx
4483
- var import_jsx_runtime17 = require("react/jsx-runtime");
4927
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4484
4928
  function DataOverlay({
4485
4929
  nodeId,
4486
4930
  x,
@@ -4502,7 +4946,7 @@ function DataOverlay({
4502
4946
  const offsetX = display?.offsetX ?? 0;
4503
4947
  const offsetY = display?.offsetY ?? 0;
4504
4948
  if (!showValue) {
4505
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, {});
4949
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, {});
4506
4950
  }
4507
4951
  const formatValue = (val) => {
4508
4952
  if (typeof val === "number") {
@@ -4543,8 +4987,8 @@ function DataOverlay({
4543
4987
  const overlayWidth = 80 * scale;
4544
4988
  const displayX = x + offsetX;
4545
4989
  const displayY = y + offsetY;
4546
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
4547
- /* @__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)(
4548
4992
  "rect",
4549
4993
  {
4550
4994
  x: displayX - overlayWidth / 2,
@@ -4559,7 +5003,7 @@ function DataOverlay({
4559
5003
  filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
4560
5004
  }
4561
5005
  ),
4562
- label && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5006
+ label && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4563
5007
  "text",
4564
5008
  {
4565
5009
  x: displayX,
@@ -4572,7 +5016,7 @@ function DataOverlay({
4572
5016
  children: label
4573
5017
  }
4574
5018
  ),
4575
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5019
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4576
5020
  "text",
4577
5021
  {
4578
5022
  x: displayX,
@@ -4585,7 +5029,7 @@ function DataOverlay({
4585
5029
  children: displayText
4586
5030
  }
4587
5031
  ),
4588
- showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5032
+ showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4589
5033
  "circle",
4590
5034
  {
4591
5035
  cx: displayX + 35 * scale,
@@ -4593,7 +5037,7 @@ function DataOverlay({
4593
5037
  r: 3 * scale,
4594
5038
  fill: finalTextColor,
4595
5039
  opacity: "0.9",
4596
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5040
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4597
5041
  "animate",
4598
5042
  {
4599
5043
  attributeName: "opacity",
@@ -4604,7 +5048,7 @@ function DataOverlay({
4604
5048
  )
4605
5049
  }
4606
5050
  ),
4607
- 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)(
4608
5052
  "text",
4609
5053
  {
4610
5054
  x: displayX,
@@ -4621,7 +5065,7 @@ function DataOverlay({
4621
5065
  ]
4622
5066
  }
4623
5067
  ),
4624
- 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)(
4625
5069
  "path",
4626
5070
  {
4627
5071
  d: sparklinePath,
@@ -4637,8 +5081,8 @@ function DataOverlay({
4637
5081
  }
4638
5082
 
4639
5083
  // src/components/PIDCanvas/PositionPanel.tsx
4640
- var import_react9 = require("react");
4641
- var import_jsx_runtime18 = require("react/jsx-runtime");
5084
+ var import_react10 = require("react");
5085
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4642
5086
  function PositionPanel({
4643
5087
  selectedNode,
4644
5088
  selectedWaypoint,
@@ -4646,9 +5090,9 @@ function PositionPanel({
4646
5090
  onWaypointPositionChange,
4647
5091
  position = "top-right"
4648
5092
  }) {
4649
- const [x, setX] = (0, import_react9.useState)("");
4650
- const [y, setY] = (0, import_react9.useState)("");
4651
- (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)(() => {
4652
5096
  if (selectedNode) {
4653
5097
  setX(selectedNode.transform.x.toFixed(2));
4654
5098
  setY(selectedNode.transform.y.toFixed(2));
@@ -4707,7 +5151,7 @@ function PositionPanel({
4707
5151
  "bottom-left": { bottom: 10, left: 10 },
4708
5152
  "bottom-right": { bottom: 10, right: 10 }
4709
5153
  };
4710
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5154
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4711
5155
  "div",
4712
5156
  {
4713
5157
  style: {
@@ -4724,11 +5168,11 @@ function PositionPanel({
4724
5168
  fontSize: "13px"
4725
5169
  },
4726
5170
  children: [
4727
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
4728
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
4729
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4730
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
4731
- /* @__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)(
4732
5176
  "input",
4733
5177
  {
4734
5178
  type: "number",
@@ -4746,9 +5190,9 @@ function PositionPanel({
4746
5190
  }
4747
5191
  )
4748
5192
  ] }),
4749
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
4750
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
4751
- /* @__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)(
4752
5196
  "input",
4753
5197
  {
4754
5198
  type: "number",
@@ -4767,14 +5211,14 @@ function PositionPanel({
4767
5211
  )
4768
5212
  ] })
4769
5213
  ] }),
4770
- /* @__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)" })
4771
5215
  ]
4772
5216
  }
4773
5217
  );
4774
5218
  }
4775
5219
 
4776
5220
  // src/diagram/hooks/useViewBox.ts
4777
- var import_react10 = require("react");
5221
+ var import_react11 = require("react");
4778
5222
  function useViewBox(options) {
4779
5223
  const {
4780
5224
  initialViewBox,
@@ -4785,16 +5229,16 @@ function useViewBox(options) {
4785
5229
  zoomSensitivity = 1e-3,
4786
5230
  allowLeftClickPan = true
4787
5231
  } = options;
4788
- const [viewBox, setViewBox] = (0, import_react10.useState)(initialViewBox);
4789
- const svgRef = (0, import_react10.useRef)(null);
4790
- const isPanningRef = (0, import_react10.useRef)(false);
4791
- const lastMousePosRef = (0, import_react10.useRef)({ x: 0, y: 0 });
4792
- const spaceKeyDownRef = (0, import_react10.useRef)(false);
4793
- const lastTouchDistanceRef = (0, import_react10.useRef)(null);
4794
- 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)(() => {
4795
5239
  setViewBox(initialViewBox);
4796
5240
  }, [initialViewBox]);
4797
- const zoomIn = (0, import_react10.useCallback)(() => {
5241
+ const zoomIn = (0, import_react11.useCallback)(() => {
4798
5242
  setViewBox((prev) => {
4799
5243
  const currentZoom = initialViewBox.width / prev.width;
4800
5244
  const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
@@ -4811,7 +5255,7 @@ function useViewBox(options) {
4811
5255
  };
4812
5256
  });
4813
5257
  }, [initialViewBox, minZoom]);
4814
- const zoomOut = (0, import_react10.useCallback)(() => {
5258
+ const zoomOut = (0, import_react11.useCallback)(() => {
4815
5259
  setViewBox((prev) => {
4816
5260
  const currentZoom = initialViewBox.width / prev.width;
4817
5261
  const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
@@ -4828,7 +5272,7 @@ function useViewBox(options) {
4828
5272
  };
4829
5273
  });
4830
5274
  }, [initialViewBox, maxZoom]);
4831
- const fitToContent = (0, import_react10.useCallback)((bounds, padding = 50) => {
5275
+ const fitToContent = (0, import_react11.useCallback)((bounds, padding = 50) => {
4832
5276
  const contentWidth = bounds.maxX - bounds.minX;
4833
5277
  const contentHeight = bounds.maxY - bounds.minY;
4834
5278
  if (contentWidth === 0 || contentHeight === 0) {
@@ -4856,7 +5300,7 @@ function useViewBox(options) {
4856
5300
  height: newHeight
4857
5301
  });
4858
5302
  }, [initialViewBox]);
4859
- (0, import_react10.useEffect)(() => {
5303
+ (0, import_react11.useEffect)(() => {
4860
5304
  if (!enableZoom || !svgRef.current) return;
4861
5305
  const svg = svgRef.current;
4862
5306
  const handleWheel = (e) => {
@@ -4889,7 +5333,7 @@ function useViewBox(options) {
4889
5333
  svg.addEventListener("wheel", handleWheel, { passive: false });
4890
5334
  return () => svg.removeEventListener("wheel", handleWheel);
4891
5335
  }, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
4892
- (0, import_react10.useEffect)(() => {
5336
+ (0, import_react11.useEffect)(() => {
4893
5337
  if (!enablePan || !svgRef.current) return;
4894
5338
  const svg = svgRef.current;
4895
5339
  const handleMouseDown = (e) => {
@@ -4965,7 +5409,7 @@ function useViewBox(options) {
4965
5409
  window.removeEventListener("keyup", handleKeyUp);
4966
5410
  };
4967
5411
  }, [enablePan, allowLeftClickPan]);
4968
- (0, import_react10.useEffect)(() => {
5412
+ (0, import_react11.useEffect)(() => {
4969
5413
  if (!svgRef.current) return;
4970
5414
  if (!enablePan && !enableZoom) return;
4971
5415
  const svg = svgRef.current;
@@ -5056,7 +5500,7 @@ function useViewBox(options) {
5056
5500
  svg.removeEventListener("touchend", handleTouchEnd);
5057
5501
  };
5058
5502
  }, [enablePan, enableZoom, minZoom, initialViewBox]);
5059
- const screenToWorld = (0, import_react10.useCallback)(
5503
+ const screenToWorld = (0, import_react11.useCallback)(
5060
5504
  (screenX, screenY) => {
5061
5505
  const svg = svgRef.current;
5062
5506
  if (!svg) return { x: screenX, y: screenY };
@@ -5095,15 +5539,15 @@ function useViewBox(options) {
5095
5539
  }
5096
5540
 
5097
5541
  // src/diagram/hooks/useSelection.ts
5098
- var import_react11 = require("react");
5542
+ var import_react12 = require("react");
5099
5543
  function useSelection(options = {}) {
5100
5544
  const {
5101
5545
  multiSelect = true,
5102
5546
  initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
5103
5547
  onSelectionChange
5104
5548
  } = options;
5105
- const [selection, setSelection] = (0, import_react11.useState)(initialSelection);
5106
- const notifyChange = (0, import_react11.useCallback)(
5549
+ const [selection, setSelection] = (0, import_react12.useState)(initialSelection);
5550
+ const notifyChange = (0, import_react12.useCallback)(
5107
5551
  (newSelection) => {
5108
5552
  if (onSelectionChange) {
5109
5553
  onSelectionChange(newSelection);
@@ -5111,15 +5555,15 @@ function useSelection(options = {}) {
5111
5555
  },
5112
5556
  [onSelectionChange]
5113
5557
  );
5114
- const isNodeSelected = (0, import_react11.useCallback)(
5558
+ const isNodeSelected = (0, import_react12.useCallback)(
5115
5559
  (nodeId) => selection.selectedNodeIds.has(nodeId),
5116
5560
  [selection.selectedNodeIds]
5117
5561
  );
5118
- const isPipeSelected = (0, import_react11.useCallback)(
5562
+ const isPipeSelected = (0, import_react12.useCallback)(
5119
5563
  (pipeId) => selection.selectedPipeIds.has(pipeId),
5120
5564
  [selection.selectedPipeIds]
5121
5565
  );
5122
- const selectNode = (0, import_react11.useCallback)(
5566
+ const selectNode = (0, import_react12.useCallback)(
5123
5567
  (nodeId, isMultiSelect = false) => {
5124
5568
  setSelection((prev) => {
5125
5569
  const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
@@ -5138,7 +5582,7 @@ function useSelection(options = {}) {
5138
5582
  },
5139
5583
  [multiSelect, notifyChange]
5140
5584
  );
5141
- const selectPipe = (0, import_react11.useCallback)(
5585
+ const selectPipe = (0, import_react12.useCallback)(
5142
5586
  (pipeId, isMultiSelect = false) => {
5143
5587
  setSelection((prev) => {
5144
5588
  const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
@@ -5157,7 +5601,7 @@ function useSelection(options = {}) {
5157
5601
  },
5158
5602
  [multiSelect, notifyChange]
5159
5603
  );
5160
- const clearSelection = (0, import_react11.useCallback)(() => {
5604
+ const clearSelection = (0, import_react12.useCallback)(() => {
5161
5605
  const newSelection = {
5162
5606
  selectedNodeIds: /* @__PURE__ */ new Set(),
5163
5607
  selectedPipeIds: /* @__PURE__ */ new Set()
@@ -5165,7 +5609,7 @@ function useSelection(options = {}) {
5165
5609
  setSelection(newSelection);
5166
5610
  notifyChange(newSelection);
5167
5611
  }, [notifyChange]);
5168
- const selectNodes = (0, import_react11.useCallback)(
5612
+ const selectNodes = (0, import_react12.useCallback)(
5169
5613
  (nodeIds) => {
5170
5614
  const newSelection = {
5171
5615
  selectedNodeIds: new Set(nodeIds),
@@ -5176,7 +5620,7 @@ function useSelection(options = {}) {
5176
5620
  },
5177
5621
  [notifyChange]
5178
5622
  );
5179
- const selectPipes = (0, import_react11.useCallback)(
5623
+ const selectPipes = (0, import_react12.useCallback)(
5180
5624
  (pipeIds) => {
5181
5625
  const newSelection = {
5182
5626
  selectedNodeIds: /* @__PURE__ */ new Set(),
@@ -5200,23 +5644,23 @@ function useSelection(options = {}) {
5200
5644
  }
5201
5645
 
5202
5646
  // src/diagram/hooks/useTelemetry.ts
5203
- var import_react12 = require("react");
5647
+ var import_react13 = require("react");
5204
5648
  function useTelemetry(options = {}) {
5205
5649
  const {
5206
5650
  initialBindings = [],
5207
5651
  onTelemetryChange,
5208
5652
  refreshInterval = 0
5209
5653
  } = options;
5210
- const [telemetry, setTelemetry] = (0, import_react12.useState)(() => {
5654
+ const [telemetry, setTelemetry] = (0, import_react13.useState)(() => {
5211
5655
  const map = /* @__PURE__ */ new Map();
5212
5656
  initialBindings.forEach((binding) => {
5213
5657
  map.set(binding.nodeId, binding);
5214
5658
  });
5215
5659
  return map;
5216
5660
  });
5217
- const telemetryRef = (0, import_react12.useRef)(telemetry);
5661
+ const telemetryRef = (0, import_react13.useRef)(telemetry);
5218
5662
  telemetryRef.current = telemetry;
5219
- const notifyChange = (0, import_react12.useCallback)(
5663
+ const notifyChange = (0, import_react13.useCallback)(
5220
5664
  (newTelemetry) => {
5221
5665
  if (onTelemetryChange) {
5222
5666
  onTelemetryChange(newTelemetry);
@@ -5224,7 +5668,7 @@ function useTelemetry(options = {}) {
5224
5668
  },
5225
5669
  [onTelemetryChange]
5226
5670
  );
5227
- const updateTelemetry = (0, import_react12.useCallback)(
5671
+ const updateTelemetry = (0, import_react13.useCallback)(
5228
5672
  (nodeId, value) => {
5229
5673
  setTelemetry((prev) => {
5230
5674
  const newMap = new Map(prev);
@@ -5254,7 +5698,7 @@ function useTelemetry(options = {}) {
5254
5698
  },
5255
5699
  [notifyChange]
5256
5700
  );
5257
- const updateTelemetryBatch = (0, import_react12.useCallback)(
5701
+ const updateTelemetryBatch = (0, import_react13.useCallback)(
5258
5702
  (updates) => {
5259
5703
  setTelemetry((prev) => {
5260
5704
  const newMap = new Map(prev);
@@ -5308,16 +5752,16 @@ function useTelemetry(options = {}) {
5308
5752
  },
5309
5753
  [notifyChange]
5310
5754
  );
5311
- const getTelemetry = (0, import_react12.useCallback)(
5755
+ const getTelemetry = (0, import_react13.useCallback)(
5312
5756
  (nodeId) => telemetryRef.current.get(nodeId),
5313
5757
  []
5314
5758
  );
5315
- const clearTelemetry = (0, import_react12.useCallback)(() => {
5759
+ const clearTelemetry = (0, import_react13.useCallback)(() => {
5316
5760
  const newMap = /* @__PURE__ */ new Map();
5317
5761
  setTelemetry(newMap);
5318
5762
  notifyChange(newMap);
5319
5763
  }, [notifyChange]);
5320
- const setBindings = (0, import_react12.useCallback)(
5764
+ const setBindings = (0, import_react13.useCallback)(
5321
5765
  (bindings) => {
5322
5766
  const newMap = /* @__PURE__ */ new Map();
5323
5767
  bindings.forEach((binding) => {
@@ -5328,7 +5772,7 @@ function useTelemetry(options = {}) {
5328
5772
  },
5329
5773
  [notifyChange]
5330
5774
  );
5331
- (0, import_react12.useEffect)(() => {
5775
+ (0, import_react13.useEffect)(() => {
5332
5776
  if (refreshInterval <= 0) return;
5333
5777
  const intervalId = setInterval(() => {
5334
5778
  notifyChange(telemetryRef.current);
@@ -5346,10 +5790,10 @@ function useTelemetry(options = {}) {
5346
5790
  }
5347
5791
 
5348
5792
  // src/diagram/hooks/useTelemetryStatus.ts
5349
- var import_react13 = require("react");
5793
+ var import_react14 = require("react");
5350
5794
  function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5351
5795
  const { enabled = true, mapStatus } = options;
5352
- (0, import_react13.useEffect)(() => {
5796
+ (0, import_react14.useEffect)(() => {
5353
5797
  if (!enabled) return;
5354
5798
  const defaultMapStatus = (telemetryStatus) => {
5355
5799
  switch (telemetryStatus) {
@@ -5388,7 +5832,7 @@ function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
5388
5832
  }
5389
5833
 
5390
5834
  // src/diagram/hooks/useDrag.ts
5391
- var import_react14 = require("react");
5835
+ var import_react15 = require("react");
5392
5836
  function useDrag(options = {}) {
5393
5837
  const {
5394
5838
  onDragStart,
@@ -5398,23 +5842,23 @@ function useDrag(options = {}) {
5398
5842
  dragThreshold = 3,
5399
5843
  screenToWorld = (x, y) => ({ x, y })
5400
5844
  } = options;
5401
- const [dragState, setDragState] = (0, import_react14.useState)({
5845
+ const [dragState, setDragState] = (0, import_react15.useState)({
5402
5846
  isDragging: false,
5403
5847
  startPosition: null,
5404
5848
  offset: { x: 0, y: 0 },
5405
5849
  draggedId: null
5406
5850
  });
5407
- const [isListening, setIsListening] = (0, import_react14.useState)(false);
5408
- const dragStartRef = (0, import_react14.useRef)(null);
5409
- const hasMovedRef = (0, import_react14.useRef)(false);
5410
- 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)(
5411
5855
  (value) => {
5412
5856
  if (snapToGrid <= 0) return value;
5413
5857
  return Math.round(value / snapToGrid) * snapToGrid;
5414
5858
  },
5415
5859
  [snapToGrid]
5416
5860
  );
5417
- const handleMouseMove = (0, import_react14.useCallback)(
5861
+ const handleMouseMove = (0, import_react15.useCallback)(
5418
5862
  (event) => {
5419
5863
  if (!dragStartRef.current) return;
5420
5864
  const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
@@ -5455,7 +5899,7 @@ function useDrag(options = {}) {
5455
5899
  },
5456
5900
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5457
5901
  );
5458
- const handleMouseUp = (0, import_react14.useCallback)(
5902
+ const handleMouseUp = (0, import_react15.useCallback)(
5459
5903
  (event) => {
5460
5904
  if (!dragStartRef.current || !hasMovedRef.current) {
5461
5905
  dragStartRef.current = null;
@@ -5492,7 +5936,7 @@ function useDrag(options = {}) {
5492
5936
  },
5493
5937
  [screenToWorld, applySnap, onDragEnd]
5494
5938
  );
5495
- const handleTouchMove = (0, import_react14.useCallback)(
5939
+ const handleTouchMove = (0, import_react15.useCallback)(
5496
5940
  (event) => {
5497
5941
  if (!dragStartRef.current || event.touches.length !== 1) return;
5498
5942
  const touch = event.touches[0];
@@ -5535,7 +5979,7 @@ function useDrag(options = {}) {
5535
5979
  },
5536
5980
  [screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
5537
5981
  );
5538
- const handleTouchEnd = (0, import_react14.useCallback)(
5982
+ const handleTouchEnd = (0, import_react15.useCallback)(
5539
5983
  (event) => {
5540
5984
  if (!dragStartRef.current || !hasMovedRef.current) {
5541
5985
  dragStartRef.current = null;
@@ -5573,7 +6017,7 @@ function useDrag(options = {}) {
5573
6017
  },
5574
6018
  [screenToWorld, applySnap, onDragEnd]
5575
6019
  );
5576
- (0, import_react14.useEffect)(() => {
6020
+ (0, import_react15.useEffect)(() => {
5577
6021
  if (!isListening) return;
5578
6022
  document.addEventListener("mousemove", handleMouseMove);
5579
6023
  document.addEventListener("mouseup", handleMouseUp);
@@ -5588,7 +6032,7 @@ function useDrag(options = {}) {
5588
6032
  document.removeEventListener("touchcancel", handleTouchEnd);
5589
6033
  };
5590
6034
  }, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
5591
- const startDrag = (0, import_react14.useCallback)(
6035
+ const startDrag = (0, import_react15.useCallback)(
5592
6036
  (id, event, itemPosition) => {
5593
6037
  event.stopPropagation();
5594
6038
  let clientX;
@@ -5618,7 +6062,7 @@ function useDrag(options = {}) {
5618
6062
  },
5619
6063
  [screenToWorld]
5620
6064
  );
5621
- const cancelDrag = (0, import_react14.useCallback)(() => {
6065
+ const cancelDrag = (0, import_react15.useCallback)(() => {
5622
6066
  dragStartRef.current = null;
5623
6067
  hasMovedRef.current = false;
5624
6068
  setIsListening(false);
@@ -5629,7 +6073,7 @@ function useDrag(options = {}) {
5629
6073
  draggedId: null
5630
6074
  });
5631
6075
  }, []);
5632
- const isDraggingItem = (0, import_react14.useCallback)(
6076
+ const isDraggingItem = (0, import_react15.useCallback)(
5633
6077
  (id) => dragState.isDragging && dragState.draggedId === id,
5634
6078
  [dragState.isDragging, dragState.draggedId]
5635
6079
  );
@@ -5642,7 +6086,7 @@ function useDrag(options = {}) {
5642
6086
  }
5643
6087
 
5644
6088
  // src/diagram/hooks/useKeyboardShortcuts.ts
5645
- var import_react15 = require("react");
6089
+ var import_react16 = require("react");
5646
6090
  function useKeyboardShortcuts(options) {
5647
6091
  const {
5648
6092
  onDelete,
@@ -5653,7 +6097,7 @@ function useKeyboardShortcuts(options) {
5653
6097
  onSelectAll,
5654
6098
  enabled = true
5655
6099
  } = options;
5656
- (0, import_react15.useEffect)(() => {
6100
+ (0, import_react16.useEffect)(() => {
5657
6101
  if (!enabled) return;
5658
6102
  const handleKeyDown = (event) => {
5659
6103
  const target = event.target;
@@ -5762,7 +6206,7 @@ function nodeHasPort(node, portId) {
5762
6206
  }
5763
6207
 
5764
6208
  // src/components/PIDCanvas/PIDCanvas.tsx
5765
- var import_jsx_runtime19 = require("react/jsx-runtime");
6209
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5766
6210
  function PIDCanvas({
5767
6211
  diagram,
5768
6212
  className = "",
@@ -5790,21 +6234,21 @@ function PIDCanvas({
5790
6234
  statusColorMap,
5791
6235
  ...props
5792
6236
  }) {
5793
- const [localDiagram, setLocalDiagram] = (0, import_react16.useState)(diagram);
5794
- const [dragOverPosition, setDragOverPosition] = (0, import_react16.useState)(null);
5795
- const [isConnecting, setIsConnecting] = (0, import_react16.useState)(false);
5796
- const [connectionSource, setConnectionSource] = (0, import_react16.useState)(null);
5797
- const [connectionSourcePort, setConnectionSourcePort] = (0, import_react16.useState)(null);
5798
- const [connectionCursor, setConnectionCursor] = (0, import_react16.useState)(null);
5799
- const [hoveredNode, setHoveredNode] = (0, import_react16.useState)(null);
5800
- const [hoveredPort, setHoveredPort] = (0, import_react16.useState)(null);
5801
- const [selectedWaypoint, setSelectedWaypoint] = (0, import_react16.useState)(null);
5802
- const historyStack = (0, import_react16.useRef)([]);
5803
- const redoStack = (0, import_react16.useRef)([]);
5804
- const isUndoRedoAction = (0, import_react16.useRef)(false);
5805
- const isInternalChange = (0, import_react16.useRef)(false);
5806
- const lastInternalDiagram = (0, import_react16.useRef)(null);
5807
- (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)(() => {
5808
6252
  const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
5809
6253
  if (isExternal) {
5810
6254
  setLocalDiagram(diagram);
@@ -5826,7 +6270,7 @@ function PIDCanvas({
5826
6270
  enablePan: features.pan ?? true,
5827
6271
  enableZoom: features.zoom ?? true
5828
6272
  });
5829
- const calculateContentBounds = (0, import_react16.useCallback)(() => {
6273
+ const calculateContentBounds = (0, import_react17.useCallback)(() => {
5830
6274
  const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
5831
6275
  if (nodes2.length === 0) {
5832
6276
  return null;
@@ -5849,7 +6293,7 @@ function PIDCanvas({
5849
6293
  });
5850
6294
  return { minX, minY, maxX, maxY };
5851
6295
  }, [localDiagram.nodes]);
5852
- (0, import_react16.useEffect)(() => {
6296
+ (0, import_react17.useEffect)(() => {
5853
6297
  if (onMounted) {
5854
6298
  const controls = {
5855
6299
  fitToContent: (padding = 50) => {
@@ -5890,8 +6334,8 @@ function PIDCanvas({
5890
6334
  });
5891
6335
  const dragEnabled = features.dragNodes ?? false;
5892
6336
  const selectionEnabled = features.selection ?? false;
5893
- const containerRef = (0, import_react16.useRef)(null);
5894
- const pushToHistory = (0, import_react16.useCallback)((currentDiagram) => {
6337
+ const containerRef = (0, import_react17.useRef)(null);
6338
+ const pushToHistory = (0, import_react17.useCallback)((currentDiagram) => {
5895
6339
  if (isUndoRedoAction.current) return;
5896
6340
  const snapshot = JSON.parse(JSON.stringify(currentDiagram));
5897
6341
  historyStack.current.push(snapshot);
@@ -5900,7 +6344,7 @@ function PIDCanvas({
5900
6344
  }
5901
6345
  redoStack.current = [];
5902
6346
  }, []);
5903
- const undo = (0, import_react16.useCallback)(() => {
6347
+ const undo = (0, import_react17.useCallback)(() => {
5904
6348
  if (historyStack.current.length === 0) return;
5905
6349
  isUndoRedoAction.current = true;
5906
6350
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5914,7 +6358,7 @@ function PIDCanvas({
5914
6358
  isUndoRedoAction.current = false;
5915
6359
  }, 0);
5916
6360
  }, [localDiagram, onDiagramChange]);
5917
- const redo = (0, import_react16.useCallback)(() => {
6361
+ const redo = (0, import_react17.useCallback)(() => {
5918
6362
  if (redoStack.current.length === 0) return;
5919
6363
  isUndoRedoAction.current = true;
5920
6364
  const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
@@ -5928,7 +6372,7 @@ function PIDCanvas({
5928
6372
  isUndoRedoAction.current = false;
5929
6373
  }, 0);
5930
6374
  }, [localDiagram, onDiagramChange]);
5931
- (0, import_react16.useEffect)(() => {
6375
+ (0, import_react17.useEffect)(() => {
5932
6376
  const handleKeyDown = (e) => {
5933
6377
  const isCtrlOrCmd = e.ctrlKey || e.metaKey;
5934
6378
  if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
@@ -5945,7 +6389,7 @@ function PIDCanvas({
5945
6389
  window.addEventListener("keydown", handleKeyDown);
5946
6390
  return () => window.removeEventListener("keydown", handleKeyDown);
5947
6391
  }, [undo, redo]);
5948
- (0, import_react16.useEffect)(() => {
6392
+ (0, import_react17.useEffect)(() => {
5949
6393
  if (!features.dragNodes) return;
5950
6394
  const handleKeyDown = (e) => {
5951
6395
  if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
@@ -6030,7 +6474,7 @@ function PIDCanvas({
6030
6474
  onNodeMove,
6031
6475
  pushToHistory
6032
6476
  ]);
6033
- const handlePositionChange = (0, import_react16.useCallback)(
6477
+ const handlePositionChange = (0, import_react17.useCallback)(
6034
6478
  (nodeId, x, y) => {
6035
6479
  pushToHistory(localDiagram);
6036
6480
  const updatedNodes = localDiagram.nodes.map(
@@ -6052,7 +6496,7 @@ function PIDCanvas({
6052
6496
  },
6053
6497
  [localDiagram, onDiagramChange, onNodeMove, pushToHistory]
6054
6498
  );
6055
- const handleWaypointPositionChange = (0, import_react16.useCallback)(
6499
+ const handleWaypointPositionChange = (0, import_react17.useCallback)(
6056
6500
  (pipeId, pointIndex, x, y) => {
6057
6501
  pushToHistory(localDiagram);
6058
6502
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6070,7 +6514,7 @@ function PIDCanvas({
6070
6514
  },
6071
6515
  [localDiagram, onDiagramChange, pushToHistory]
6072
6516
  );
6073
- const handleDragEnd = (0, import_react16.useCallback)(
6517
+ const handleDragEnd = (0, import_react17.useCallback)(
6074
6518
  (nodeId, offset, finalPosition) => {
6075
6519
  const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
6076
6520
  if (dragDistance < 2) {
@@ -6151,7 +6595,7 @@ function PIDCanvas({
6151
6595
  onDiagramChange?.(updatedDiagram);
6152
6596
  }
6153
6597
  });
6154
- const handleNodeDragStart = (0, import_react16.useCallback)(
6598
+ const handleNodeDragStart = (0, import_react17.useCallback)(
6155
6599
  (nodeId, event) => {
6156
6600
  const node = localDiagram.nodes.find((n) => n.id === nodeId);
6157
6601
  if (!node) return;
@@ -6159,7 +6603,7 @@ function PIDCanvas({
6159
6603
  },
6160
6604
  [localDiagram.nodes, startDrag]
6161
6605
  );
6162
- const handleWaypointClick = (0, import_react16.useCallback)(
6606
+ const handleWaypointClick = (0, import_react17.useCallback)(
6163
6607
  (pipeId, pointIndex) => {
6164
6608
  setSelectedWaypoint({ pipeId, pointIndex });
6165
6609
  if (selectionEnabled) {
@@ -6168,7 +6612,7 @@ function PIDCanvas({
6168
6612
  },
6169
6613
  [selectionEnabled, clearSelection]
6170
6614
  );
6171
- const handleWaypointDragStart = (0, import_react16.useCallback)(
6615
+ const handleWaypointDragStart = (0, import_react17.useCallback)(
6172
6616
  (pipeId, pointIndex, event) => {
6173
6617
  const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
6174
6618
  if (!pipe || pointIndex >= pipe.routePoints.length) return;
@@ -6177,7 +6621,7 @@ function PIDCanvas({
6177
6621
  },
6178
6622
  [localDiagram.pipes, startWaypointDrag]
6179
6623
  );
6180
- const handlePipeSegmentClick = (0, import_react16.useCallback)(
6624
+ const handlePipeSegmentClick = (0, import_react17.useCallback)(
6181
6625
  (pipeId, position, segmentIndex) => {
6182
6626
  pushToHistory(localDiagram);
6183
6627
  const updatedPipes = localDiagram.pipes.map((pipe) => {
@@ -6196,7 +6640,7 @@ function PIDCanvas({
6196
6640
  [localDiagram, onDiagramChange, pushToHistory]
6197
6641
  );
6198
6642
  const telemetryEnabled = features.telemetry ?? false;
6199
- const handleDelete = (0, import_react16.useCallback)(() => {
6643
+ const handleDelete = (0, import_react17.useCallback)(() => {
6200
6644
  if (!selectionEnabled) return;
6201
6645
  const { selectedNodeIds, selectedPipeIds } = selection;
6202
6646
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
@@ -6225,13 +6669,13 @@ function PIDCanvas({
6225
6669
  onDelete,
6226
6670
  pushToHistory
6227
6671
  ]);
6228
- const handleCopy = (0, import_react16.useCallback)(() => {
6672
+ const handleCopy = (0, import_react17.useCallback)(() => {
6229
6673
  if (!selectionEnabled) return;
6230
6674
  const { selectedNodeIds, selectedPipeIds } = selection;
6231
6675
  if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
6232
6676
  onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
6233
6677
  }, [selection, selectionEnabled, onItemsCopied]);
6234
- const handlePaste = (0, import_react16.useCallback)(() => {
6678
+ const handlePaste = (0, import_react17.useCallback)(() => {
6235
6679
  if (!selectionEnabled) return;
6236
6680
  onPaste?.();
6237
6681
  }, [selectionEnabled, onPaste]);
@@ -6291,7 +6735,7 @@ function PIDCanvas({
6291
6735
  }
6292
6736
  setSelectedWaypoint(null);
6293
6737
  };
6294
- const handleDragOver = (0, import_react16.useCallback)(
6738
+ const handleDragOver = (0, import_react17.useCallback)(
6295
6739
  (event) => {
6296
6740
  if (!features.allowSymbolDrop) return;
6297
6741
  event.preventDefault();
@@ -6302,7 +6746,7 @@ function PIDCanvas({
6302
6746
  },
6303
6747
  [features.allowSymbolDrop, screenToWorld, svgRef]
6304
6748
  );
6305
- const handleDrop = (0, import_react16.useCallback)(
6749
+ const handleDrop = (0, import_react17.useCallback)(
6306
6750
  (event) => {
6307
6751
  if (!features.allowSymbolDrop) return;
6308
6752
  event.preventDefault();
@@ -6315,10 +6759,10 @@ function PIDCanvas({
6315
6759
  },
6316
6760
  [features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
6317
6761
  );
6318
- const handleDragLeave = (0, import_react16.useCallback)(() => {
6762
+ const handleDragLeave = (0, import_react17.useCallback)(() => {
6319
6763
  setDragOverPosition(null);
6320
6764
  }, []);
6321
- const handleMouseMove = (0, import_react16.useCallback)(
6765
+ const handleMouseMove = (0, import_react17.useCallback)(
6322
6766
  (event) => {
6323
6767
  const connectionModeEnabled = features.connectionMode ?? false;
6324
6768
  if (connectionModeEnabled) {
@@ -6355,7 +6799,7 @@ function PIDCanvas({
6355
6799
  const viewBox = controlledViewBox;
6356
6800
  const displayDiagram = localDiagram;
6357
6801
  const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
6358
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6802
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6359
6803
  "div",
6360
6804
  {
6361
6805
  ref: containerRef,
@@ -6370,7 +6814,7 @@ function PIDCanvas({
6370
6814
  },
6371
6815
  ...props,
6372
6816
  children: [
6373
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6817
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6374
6818
  "svg",
6375
6819
  {
6376
6820
  ref: svgRef,
@@ -6389,15 +6833,15 @@ function PIDCanvas({
6389
6833
  onDrop: handleDrop,
6390
6834
  onDragLeave: handleDragLeave,
6391
6835
  children: [
6392
- features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
6393
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("defs", { children: [
6394
- /* @__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" }) }),
6395
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
6396
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
6397
- /* @__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" })
6398
6842
  ] })
6399
6843
  ] }),
6400
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6844
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6401
6845
  "rect",
6402
6846
  {
6403
6847
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6407,7 +6851,7 @@ function PIDCanvas({
6407
6851
  fill: "url(#grid-major)"
6408
6852
  }
6409
6853
  )
6410
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6854
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6411
6855
  "rect",
6412
6856
  {
6413
6857
  x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
@@ -6417,7 +6861,7 @@ function PIDCanvas({
6417
6861
  fill: features.backgroundColor ?? "#ffffff"
6418
6862
  }
6419
6863
  ),
6420
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6864
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6421
6865
  PipeRenderer,
6422
6866
  {
6423
6867
  pipes: displayDiagram.pipes,
@@ -6431,7 +6875,7 @@ function PIDCanvas({
6431
6875
  onPipeSegmentClick: void 0
6432
6876
  }
6433
6877
  ),
6434
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6878
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6435
6879
  NodeRenderer,
6436
6880
  {
6437
6881
  nodes: displayDiagram.nodes,
@@ -6445,7 +6889,7 @@ function PIDCanvas({
6445
6889
  statusColorMap
6446
6890
  }
6447
6891
  ),
6448
- (features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6892
+ (features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6449
6893
  PipeRenderer,
6450
6894
  {
6451
6895
  pipes: displayDiagram.pipes,
@@ -6462,14 +6906,14 @@ function PIDCanvas({
6462
6906
  onPipeSegmentClick: handlePipeSegmentClick
6463
6907
  }
6464
6908
  ),
6465
- 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) => {
6466
6910
  const binding = telemetry.get(node.id);
6467
6911
  if (!binding) return null;
6468
6912
  const symbol = getSymbolDefinition(node.symbolId);
6469
6913
  if (!symbol) return null;
6470
6914
  const overlayX = node.transform.x + symbol.viewBox.width / 2;
6471
6915
  const overlayY = node.transform.y + symbol.viewBox.height + 50;
6472
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6916
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6473
6917
  DataOverlay,
6474
6918
  {
6475
6919
  nodeId: node.id,
@@ -6482,7 +6926,7 @@ function PIDCanvas({
6482
6926
  `telemetry-${node.id}`
6483
6927
  );
6484
6928
  }) }),
6485
- dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6929
+ dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6486
6930
  "circle",
6487
6931
  {
6488
6932
  cx: dragOverPosition.x,
@@ -6495,7 +6939,7 @@ function PIDCanvas({
6495
6939
  pointerEvents: "none"
6496
6940
  }
6497
6941
  ),
6498
- 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: (() => {
6499
6943
  const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
6500
6944
  if (!sourceNode) return null;
6501
6945
  const symbol = getSymbolDefinition(sourceNode.symbolId);
@@ -6511,8 +6955,8 @@ function PIDCanvas({
6511
6955
  }
6512
6956
  }
6513
6957
  }
6514
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
6515
- /* @__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)(
6516
6960
  "circle",
6517
6961
  {
6518
6962
  cx: lineStartX,
@@ -6524,7 +6968,7 @@ function PIDCanvas({
6524
6968
  opacity: 0.6
6525
6969
  }
6526
6970
  ),
6527
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6971
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6528
6972
  "line",
6529
6973
  {
6530
6974
  x1: lineStartX,
@@ -6537,7 +6981,7 @@ function PIDCanvas({
6537
6981
  opacity: 0.8
6538
6982
  }
6539
6983
  ),
6540
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6984
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6541
6985
  "circle",
6542
6986
  {
6543
6987
  cx: connectionCursor.x,
@@ -6549,7 +6993,7 @@ function PIDCanvas({
6549
6993
  )
6550
6994
  ] });
6551
6995
  })() }),
6552
- 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) => {
6553
6997
  const symbol = getSymbolDefinition(node.symbolId);
6554
6998
  if (!symbol?.ports) return null;
6555
6999
  return symbol.ports.map((port) => {
@@ -6557,8 +7001,8 @@ function PIDCanvas({
6557
7001
  if (!portPos) return null;
6558
7002
  const isHovered = hoveredPort === port.id && hoveredNode === node.id;
6559
7003
  const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
6560
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("g", { children: [
6561
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7004
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("g", { children: [
7005
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6562
7006
  "circle",
6563
7007
  {
6564
7008
  cx: portPos.x,
@@ -6591,7 +7035,7 @@ function PIDCanvas({
6591
7035
  }
6592
7036
  }
6593
7037
  ),
6594
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7038
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6595
7039
  "circle",
6596
7040
  {
6597
7041
  cx: portPos.x,
@@ -6610,7 +7054,7 @@ function PIDCanvas({
6610
7054
  ]
6611
7055
  }
6612
7056
  ),
6613
- features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
7057
+ features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6614
7058
  PositionPanel,
6615
7059
  {
6616
7060
  selectedNode,
@@ -6630,16 +7074,16 @@ function PIDCanvas({
6630
7074
  }
6631
7075
 
6632
7076
  // src/components/SymbolLibrary/SymbolLibrary.tsx
6633
- var import_react17 = require("react");
6634
- var import_jsx_runtime20 = require("react/jsx-runtime");
7077
+ var import_react18 = require("react");
7078
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6635
7079
  function SymbolLibrary({
6636
7080
  className = "",
6637
7081
  onSymbolDragStart,
6638
7082
  showCategories = true,
6639
7083
  categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
6640
7084
  }) {
6641
- const [selectedCategory, setSelectedCategory] = (0, import_react17.useState)("all");
6642
- const [searchQuery, setSearchQuery] = (0, import_react17.useState)("");
7085
+ const [selectedCategory, setSelectedCategory] = (0, import_react18.useState)("all");
7086
+ const [searchQuery, setSearchQuery] = (0, import_react18.useState)("");
6643
7087
  const symbolIds = getAvailableSymbols();
6644
7088
  const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
6645
7089
  const categoryMap = {
@@ -6660,9 +7104,9 @@ function SymbolLibrary({
6660
7104
  event.dataTransfer.effectAllowed = "copy";
6661
7105
  onSymbolDragStart?.(symbol.id, event);
6662
7106
  };
6663
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
6664
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
6665
- /* @__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)(
6666
7110
  "input",
6667
7111
  {
6668
7112
  type: "text",
@@ -6672,8 +7116,8 @@ function SymbolLibrary({
6672
7116
  style: styles.searchInput
6673
7117
  }
6674
7118
  ) }),
6675
- showCategories && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: styles.categories, children: [
6676
- /* @__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)(
6677
7121
  "button",
6678
7122
  {
6679
7123
  onClick: () => setSelectedCategory("all"),
@@ -6684,7 +7128,7 @@ function SymbolLibrary({
6684
7128
  children: "All"
6685
7129
  }
6686
7130
  ),
6687
- categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
7131
+ categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6688
7132
  "button",
6689
7133
  {
6690
7134
  onClick: () => setSelectedCategory(category),
@@ -6697,7 +7141,7 @@ function SymbolLibrary({
6697
7141
  category
6698
7142
  ))
6699
7143
  ] }),
6700
- /* @__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)(
6701
7145
  "div",
6702
7146
  {
6703
7147
  draggable: true,
@@ -6705,15 +7149,15 @@ function SymbolLibrary({
6705
7149
  style: styles.symbolCard,
6706
7150
  title: symbol.metadata?.description || symbol.name,
6707
7151
  children: [
6708
- /* @__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)(
6709
7153
  "svg",
6710
7154
  {
6711
7155
  viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
6712
7156
  style: styles.symbolSvg,
6713
- 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 } })
6714
7158
  }
6715
7159
  ) }),
6716
- /* @__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 })
6717
7161
  ]
6718
7162
  },
6719
7163
  symbol.id
@@ -6822,7 +7266,7 @@ var styles = {
6822
7266
  };
6823
7267
 
6824
7268
  // src/components/NodeConfigPanel/NodeConfigPanel.tsx
6825
- var import_jsx_runtime21 = require("react/jsx-runtime");
7269
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6826
7270
  function NodeConfigPanel({
6827
7271
  node,
6828
7272
  binding,
@@ -6841,15 +7285,15 @@ function NodeConfigPanel({
6841
7285
  padding: "20px",
6842
7286
  ...style
6843
7287
  };
6844
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, style: defaultStyle, children: [
6845
- /* @__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: [
6846
7290
  "Configure: ",
6847
7291
  node.id
6848
7292
  ] }),
6849
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
6850
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
6851
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
6852
- /* @__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)(
6853
7297
  "input",
6854
7298
  {
6855
7299
  type: "text",
@@ -6865,10 +7309,10 @@ function NodeConfigPanel({
6865
7309
  }
6866
7310
  }
6867
7311
  ),
6868
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
6869
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6870
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
6871
- /* @__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)(
6872
7316
  "input",
6873
7317
  {
6874
7318
  type: "number",
@@ -6889,9 +7333,9 @@ function NodeConfigPanel({
6889
7333
  }
6890
7334
  )
6891
7335
  ] }),
6892
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6893
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
6894
- /* @__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)(
6895
7339
  "input",
6896
7340
  {
6897
7341
  type: "number",
@@ -6913,9 +7357,9 @@ function NodeConfigPanel({
6913
7357
  )
6914
7358
  ] })
6915
7359
  ] }),
6916
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6917
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
6918
- /* @__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)(
6919
7363
  "input",
6920
7364
  {
6921
7365
  type: "number",
@@ -6935,9 +7379,9 @@ function NodeConfigPanel({
6935
7379
  }
6936
7380
  )
6937
7381
  ] }),
6938
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6939
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
6940
- /* @__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)(
6941
7385
  "input",
6942
7386
  {
6943
7387
  type: "number",
@@ -6962,9 +7406,9 @@ function NodeConfigPanel({
6962
7406
  )
6963
7407
  ] })
6964
7408
  ] }),
6965
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
6966
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
6967
- !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)(
6968
7412
  "button",
6969
7413
  {
6970
7414
  onClick: () => {
@@ -7007,9 +7451,9 @@ function NodeConfigPanel({
7007
7451
  },
7008
7452
  children: "+ Add Telemetry"
7009
7453
  }
7010
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
7011
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
7012
- /* @__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)(
7013
7457
  "input",
7014
7458
  {
7015
7459
  type: "number",
@@ -7031,8 +7475,8 @@ function NodeConfigPanel({
7031
7475
  }
7032
7476
  }
7033
7477
  ),
7034
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
7035
- /* @__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)(
7036
7480
  "input",
7037
7481
  {
7038
7482
  type: "text",
@@ -7054,8 +7498,8 @@ function NodeConfigPanel({
7054
7498
  }
7055
7499
  }
7056
7500
  ),
7057
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
7058
- /* @__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)(
7059
7503
  "input",
7060
7504
  {
7061
7505
  type: "checkbox",
@@ -7077,8 +7521,8 @@ function NodeConfigPanel({
7077
7521
  ),
7078
7522
  "Show Sparkline"
7079
7523
  ] }),
7080
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "12px" }, children: [
7081
- /* @__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)(
7082
7526
  "label",
7083
7527
  {
7084
7528
  style: {
@@ -7090,10 +7534,10 @@ function NodeConfigPanel({
7090
7534
  children: "Telemetry Position Offset:"
7091
7535
  }
7092
7536
  ),
7093
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
7094
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
7095
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
7096
- /* @__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)(
7097
7541
  "input",
7098
7542
  {
7099
7543
  type: "number",
@@ -7120,9 +7564,9 @@ function NodeConfigPanel({
7120
7564
  }
7121
7565
  )
7122
7566
  ] }),
7123
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
7124
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
7125
- /* @__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)(
7126
7570
  "input",
7127
7571
  {
7128
7572
  type: "number",
@@ -7150,8 +7594,8 @@ function NodeConfigPanel({
7150
7594
  )
7151
7595
  ] })
7152
7596
  ] }),
7153
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: "16px" }, children: [
7154
- /* @__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)(
7155
7599
  "label",
7156
7600
  {
7157
7601
  style: {
@@ -7163,10 +7607,10 @@ function NodeConfigPanel({
7163
7607
  children: "Display Colors:"
7164
7608
  }
7165
7609
  ),
7166
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7167
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
7168
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7169
- /* @__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)(
7170
7614
  "input",
7171
7615
  {
7172
7616
  type: "color",
@@ -7192,7 +7636,7 @@ function NodeConfigPanel({
7192
7636
  }
7193
7637
  }
7194
7638
  ),
7195
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7639
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7196
7640
  "input",
7197
7641
  {
7198
7642
  type: "text",
@@ -7222,10 +7666,10 @@ function NodeConfigPanel({
7222
7666
  )
7223
7667
  ] })
7224
7668
  ] }),
7225
- binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7226
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
7227
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7228
- /* @__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)(
7229
7673
  "input",
7230
7674
  {
7231
7675
  type: "color",
@@ -7251,7 +7695,7 @@ function NodeConfigPanel({
7251
7695
  }
7252
7696
  }
7253
7697
  ),
7254
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7698
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7255
7699
  "input",
7256
7700
  {
7257
7701
  type: "text",
@@ -7281,9 +7725,9 @@ function NodeConfigPanel({
7281
7725
  )
7282
7726
  ] })
7283
7727
  ] }),
7284
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7285
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
7286
- /* @__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)(
7287
7731
  "input",
7288
7732
  {
7289
7733
  type: "text",
@@ -7311,20 +7755,20 @@ function NodeConfigPanel({
7311
7755
  }
7312
7756
  }
7313
7757
  ),
7314
- /* @__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" })
7315
7759
  ] })
7316
7760
  ] }),
7317
7761
  " "
7318
7762
  ] })
7319
7763
  ] })
7320
7764
  ] }),
7321
- binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7322
- /* @__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" }),
7323
7767
  ["highHigh", "high", "low", "lowLow"].map((key) => {
7324
7768
  const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
7325
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7326
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
7327
- /* @__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)(
7328
7772
  "input",
7329
7773
  {
7330
7774
  type: "number",
@@ -7348,8 +7792,8 @@ function NodeConfigPanel({
7348
7792
  ] }, key);
7349
7793
  })
7350
7794
  ] }),
7351
- binding && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "20px" }, children: [
7352
- /* @__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" }),
7353
7797
  ["normal", "warning", "alarm", "fault", "off"].map((status) => {
7354
7798
  const defaultColors = {
7355
7799
  normal: "#10b981",
@@ -7359,13 +7803,13 @@ function NodeConfigPanel({
7359
7803
  off: "#6b7280"
7360
7804
  };
7361
7805
  const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
7362
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: "8px" }, children: [
7363
- /* @__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: [
7364
7808
  label,
7365
7809
  ":"
7366
7810
  ] }),
7367
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
7368
- /* @__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)(
7369
7813
  "input",
7370
7814
  {
7371
7815
  type: "color",
@@ -7386,7 +7830,7 @@ function NodeConfigPanel({
7386
7830
  }
7387
7831
  }
7388
7832
  ),
7389
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7833
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7390
7834
  "input",
7391
7835
  {
7392
7836
  type: "text",
@@ -7413,7 +7857,7 @@ function NodeConfigPanel({
7413
7857
  ] }, status);
7414
7858
  })
7415
7859
  ] }),
7416
- /* @__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)(
7417
7861
  "button",
7418
7862
  {
7419
7863
  onClick: onRemove,
@@ -7690,13 +8134,13 @@ function createControlBinding(nodeId, deviceConfig, actions) {
7690
8134
  }
7691
8135
 
7692
8136
  // src/hooks/useDeviceControls.ts
7693
- var import_react18 = require("react");
8137
+ var import_react19 = require("react");
7694
8138
  function commandKey(nodeId, kind, suffix) {
7695
8139
  return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
7696
8140
  }
7697
8141
  function useDeviceControls(initialBindings, options) {
7698
8142
  const { commandTimeoutMs } = options ?? {};
7699
- const [controls, setControls] = (0, import_react18.useState)(() => {
8143
+ const [controls, setControls] = (0, import_react19.useState)(() => {
7700
8144
  const map = /* @__PURE__ */ new Map();
7701
8145
  if (initialBindings) {
7702
8146
  initialBindings.forEach((binding) => {
@@ -7705,12 +8149,12 @@ function useDeviceControls(initialBindings, options) {
7705
8149
  }
7706
8150
  return map;
7707
8151
  });
7708
- const pendingRef = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
7709
- const [pendingCommands, setPendingCommands] = (0, import_react18.useState)(() => /* @__PURE__ */ new Set());
7710
- 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)(() => {
7711
8155
  setPendingCommands(new Set(pendingRef.current.keys()));
7712
8156
  }, []);
7713
- const updateControl = (0, import_react18.useCallback)((nodeId, updates) => {
8157
+ const updateControl = (0, import_react19.useCallback)((nodeId, updates) => {
7714
8158
  setControls((prev) => {
7715
8159
  const newMap = new Map(prev);
7716
8160
  const existing = newMap.get(nodeId);
@@ -7724,7 +8168,7 @@ function useDeviceControls(initialBindings, options) {
7724
8168
  return newMap;
7725
8169
  });
7726
8170
  }, []);
7727
- const updateControlBatch = (0, import_react18.useCallback)((updates) => {
8171
+ const updateControlBatch = (0, import_react19.useCallback)((updates) => {
7728
8172
  setControls((prev) => {
7729
8173
  const newMap = new Map(prev);
7730
8174
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -7736,7 +8180,7 @@ function useDeviceControls(initialBindings, options) {
7736
8180
  return newMap;
7737
8181
  });
7738
8182
  }, []);
7739
- const updateDeviceState = (0, import_react18.useCallback)(
8183
+ const updateDeviceState = (0, import_react19.useCallback)(
7740
8184
  (nodeId, stateUpdates) => {
7741
8185
  setControls((prev) => {
7742
8186
  const newMap = new Map(prev);
@@ -7752,7 +8196,7 @@ function useDeviceControls(initialBindings, options) {
7752
8196
  },
7753
8197
  []
7754
8198
  );
7755
- const updateParameter = (0, import_react18.useCallback)(
8199
+ const updateParameter = (0, import_react19.useCallback)(
7756
8200
  (nodeId, parameterId, value) => {
7757
8201
  setControls((prev) => {
7758
8202
  const newMap = new Map(prev);
@@ -7779,27 +8223,27 @@ function useDeviceControls(initialBindings, options) {
7779
8223
  },
7780
8224
  []
7781
8225
  );
7782
- const setControlBinding = (0, import_react18.useCallback)((binding) => {
8226
+ const setControlBinding = (0, import_react19.useCallback)((binding) => {
7783
8227
  setControls((prev) => {
7784
8228
  const newMap = new Map(prev);
7785
8229
  newMap.set(binding.nodeId, binding);
7786
8230
  return newMap;
7787
8231
  });
7788
8232
  }, []);
7789
- const removeControlBinding = (0, import_react18.useCallback)((nodeId) => {
8233
+ const removeControlBinding = (0, import_react19.useCallback)((nodeId) => {
7790
8234
  setControls((prev) => {
7791
8235
  const newMap = new Map(prev);
7792
8236
  newMap.delete(nodeId);
7793
8237
  return newMap;
7794
8238
  });
7795
8239
  }, []);
7796
- const getControlBinding = (0, import_react18.useCallback)(
8240
+ const getControlBinding = (0, import_react19.useCallback)(
7797
8241
  (nodeId) => {
7798
8242
  return controls.get(nodeId);
7799
8243
  },
7800
8244
  [controls]
7801
8245
  );
7802
- const isCommandPending = (0, import_react18.useCallback)(
8246
+ const isCommandPending = (0, import_react19.useCallback)(
7803
8247
  (nodeId, kind) => {
7804
8248
  if (kind) {
7805
8249
  const prefix2 = `${nodeId}:${kind}`;
@@ -7816,7 +8260,7 @@ function useDeviceControls(initialBindings, options) {
7816
8260
  },
7817
8261
  [pendingCommands]
7818
8262
  );
7819
- const markPending = (0, import_react18.useCallback)(
8263
+ const markPending = (0, import_react19.useCallback)(
7820
8264
  (key, delta) => {
7821
8265
  const next = (pendingRef.current.get(key) ?? 0) + delta;
7822
8266
  if (next > 0) pendingRef.current.set(key, next);
@@ -7825,7 +8269,7 @@ function useDeviceControls(initialBindings, options) {
7825
8269
  },
7826
8270
  [syncPending]
7827
8271
  );
7828
- const runCommand = (0, import_react18.useCallback)(
8272
+ const runCommand = (0, import_react19.useCallback)(
7829
8273
  async (nodeId, key, invoke, messages) => {
7830
8274
  const binding = controls.get(nodeId);
7831
8275
  if (!binding) return;
@@ -7865,7 +8309,7 @@ function useDeviceControls(initialBindings, options) {
7865
8309
  },
7866
8310
  [controls, updateDeviceState, markPending, commandTimeoutMs]
7867
8311
  );
7868
- const sendModeChange = (0, import_react18.useCallback)(
8312
+ const sendModeChange = (0, import_react19.useCallback)(
7869
8313
  (nodeId, mode) => runCommand(
7870
8314
  nodeId,
7871
8315
  commandKey(nodeId, "mode"),
@@ -7874,7 +8318,7 @@ function useDeviceControls(initialBindings, options) {
7874
8318
  ),
7875
8319
  [runCommand]
7876
8320
  );
7877
- const sendParameterChange = (0, import_react18.useCallback)(
8321
+ const sendParameterChange = (0, import_react19.useCallback)(
7878
8322
  (nodeId, parameterId, value) => runCommand(
7879
8323
  nodeId,
7880
8324
  commandKey(nodeId, "parameter", parameterId),
@@ -7883,21 +8327,21 @@ function useDeviceControls(initialBindings, options) {
7883
8327
  ),
7884
8328
  [runCommand]
7885
8329
  );
7886
- const sendStartCommand = (0, import_react18.useCallback)(
8330
+ const sendStartCommand = (0, import_react19.useCallback)(
7887
8331
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
7888
8332
  success: "Start command sent",
7889
8333
  failure: "Start command failed"
7890
8334
  }),
7891
8335
  [runCommand]
7892
8336
  );
7893
- const sendStopCommand = (0, import_react18.useCallback)(
8337
+ const sendStopCommand = (0, import_react19.useCallback)(
7894
8338
  (nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
7895
8339
  success: "Stop command sent",
7896
8340
  failure: "Stop command failed"
7897
8341
  }),
7898
8342
  [runCommand]
7899
8343
  );
7900
- const sendCustomAction = (0, import_react18.useCallback)(
8344
+ const sendCustomAction = (0, import_react19.useCallback)(
7901
8345
  (nodeId, actionId) => runCommand(
7902
8346
  nodeId,
7903
8347
  commandKey(nodeId, "action", actionId),
@@ -7950,9 +8394,9 @@ function createConfigBinding(nodeId, tag, parameters, actions, options) {
7950
8394
  }
7951
8395
 
7952
8396
  // src/hooks/useDeviceConfigs.ts
7953
- var import_react19 = require("react");
8397
+ var import_react20 = require("react");
7954
8398
  function useDeviceConfigs(initialConfigs) {
7955
- const [configs, setConfigs] = (0, import_react19.useState)(() => {
8399
+ const [configs, setConfigs] = (0, import_react20.useState)(() => {
7956
8400
  const map = /* @__PURE__ */ new Map();
7957
8401
  if (initialConfigs) {
7958
8402
  initialConfigs.forEach((config) => {
@@ -7961,13 +8405,13 @@ function useDeviceConfigs(initialConfigs) {
7961
8405
  }
7962
8406
  return map;
7963
8407
  });
7964
- const getConfig = (0, import_react19.useCallback)(
8408
+ const getConfig = (0, import_react20.useCallback)(
7965
8409
  (nodeId) => {
7966
8410
  return configs.get(nodeId);
7967
8411
  },
7968
8412
  [configs]
7969
8413
  );
7970
- const updateConfig = (0, import_react19.useCallback)((nodeId, updates) => {
8414
+ const updateConfig = (0, import_react20.useCallback)((nodeId, updates) => {
7971
8415
  setConfigs((prev) => {
7972
8416
  const newMap = new Map(prev);
7973
8417
  const existing = newMap.get(nodeId);
@@ -7981,7 +8425,7 @@ function useDeviceConfigs(initialConfigs) {
7981
8425
  return newMap;
7982
8426
  });
7983
8427
  }, []);
7984
- const updateConfigState = (0, import_react19.useCallback)((nodeId, stateUpdates) => {
8428
+ const updateConfigState = (0, import_react20.useCallback)((nodeId, stateUpdates) => {
7985
8429
  setConfigs((prev) => {
7986
8430
  const newMap = new Map(prev);
7987
8431
  const existing = newMap.get(nodeId);
@@ -7994,7 +8438,7 @@ function useDeviceConfigs(initialConfigs) {
7994
8438
  return newMap;
7995
8439
  });
7996
8440
  }, []);
7997
- const updateConfigBatch = (0, import_react19.useCallback)((updates) => {
8441
+ const updateConfigBatch = (0, import_react20.useCallback)((updates) => {
7998
8442
  setConfigs((prev) => {
7999
8443
  const newMap = new Map(prev);
8000
8444
  Object.entries(updates).forEach(([nodeId, update]) => {
@@ -8006,7 +8450,7 @@ function useDeviceConfigs(initialConfigs) {
8006
8450
  return newMap;
8007
8451
  });
8008
8452
  }, []);
8009
- const updateParameterValue = (0, import_react19.useCallback)((nodeId, parameterId, value) => {
8453
+ const updateParameterValue = (0, import_react20.useCallback)((nodeId, parameterId, value) => {
8010
8454
  setConfigs((prev) => {
8011
8455
  const newMap = new Map(prev);
8012
8456
  const existing = newMap.get(nodeId);
@@ -8023,7 +8467,7 @@ function useDeviceConfigs(initialConfigs) {
8023
8467
  return newMap;
8024
8468
  });
8025
8469
  }, []);
8026
- const applyConfig = (0, import_react19.useCallback)(
8470
+ const applyConfig = (0, import_react20.useCallback)(
8027
8471
  async (nodeId) => {
8028
8472
  const config = configs.get(nodeId);
8029
8473
  if (!config || !config.actions.onApply) {
@@ -8056,7 +8500,7 @@ function useDeviceConfigs(initialConfigs) {
8056
8500
  },
8057
8501
  [configs, updateConfigState]
8058
8502
  );
8059
- const saveConfig = (0, import_react19.useCallback)(
8503
+ const saveConfig = (0, import_react20.useCallback)(
8060
8504
  async (nodeId) => {
8061
8505
  const config = configs.get(nodeId);
8062
8506
  if (!config || !config.actions.onSave) {
@@ -8090,7 +8534,7 @@ function useDeviceConfigs(initialConfigs) {
8090
8534
  },
8091
8535
  [configs, updateConfigState]
8092
8536
  );
8093
- const resetConfig = (0, import_react19.useCallback)(
8537
+ const resetConfig = (0, import_react20.useCallback)(
8094
8538
  async (nodeId) => {
8095
8539
  const config = configs.get(nodeId);
8096
8540
  if (!config) {
@@ -8120,7 +8564,7 @@ function useDeviceConfigs(initialConfigs) {
8120
8564
  },
8121
8565
  [configs, updateConfig, updateConfigState]
8122
8566
  );
8123
- const cancelConfig = (0, import_react19.useCallback)(
8567
+ const cancelConfig = (0, import_react20.useCallback)(
8124
8568
  (nodeId) => {
8125
8569
  const config = configs.get(nodeId);
8126
8570
  if (config?.actions.onCancel) {
@@ -8129,7 +8573,7 @@ function useDeviceConfigs(initialConfigs) {
8129
8573
  },
8130
8574
  [configs]
8131
8575
  );
8132
- const validateConfig = (0, import_react19.useCallback)(
8576
+ const validateConfig = (0, import_react20.useCallback)(
8133
8577
  (nodeId) => {
8134
8578
  const config = configs.get(nodeId);
8135
8579
  if (!config) {
@@ -8171,21 +8615,21 @@ function useDeviceConfigs(initialConfigs) {
8171
8615
  },
8172
8616
  [configs, updateConfigState]
8173
8617
  );
8174
- const setConfig = (0, import_react19.useCallback)((config) => {
8618
+ const setConfig = (0, import_react20.useCallback)((config) => {
8175
8619
  setConfigs((prev) => {
8176
8620
  const newMap = new Map(prev);
8177
8621
  newMap.set(config.nodeId, config);
8178
8622
  return newMap;
8179
8623
  });
8180
8624
  }, []);
8181
- const removeConfig = (0, import_react19.useCallback)((nodeId) => {
8625
+ const removeConfig = (0, import_react20.useCallback)((nodeId) => {
8182
8626
  setConfigs((prev) => {
8183
8627
  const newMap = new Map(prev);
8184
8628
  newMap.delete(nodeId);
8185
8629
  return newMap;
8186
8630
  });
8187
8631
  }, []);
8188
- const clearConfigs = (0, import_react19.useCallback)(() => {
8632
+ const clearConfigs = (0, import_react20.useCallback)(() => {
8189
8633
  setConfigs(/* @__PURE__ */ new Map());
8190
8634
  }, []);
8191
8635
  return {
@@ -8207,8 +8651,8 @@ function useDeviceConfigs(initialConfigs) {
8207
8651
  }
8208
8652
 
8209
8653
  // src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
8210
- var import_react20 = require("react");
8211
- var import_jsx_runtime22 = require("react/jsx-runtime");
8654
+ var import_react21 = require("react");
8655
+ var import_jsx_runtime23 = require("react/jsx-runtime");
8212
8656
  function DeviceConfigPanel({
8213
8657
  binding,
8214
8658
  onClose,
@@ -8226,7 +8670,7 @@ function DeviceConfigPanel({
8226
8670
  showControlsButton = true,
8227
8671
  embedded = false
8228
8672
  }) {
8229
- const [localValues, setLocalValues] = (0, import_react20.useState)(() => {
8673
+ const [localValues, setLocalValues] = (0, import_react21.useState)(() => {
8230
8674
  if (binding) {
8231
8675
  const values = {};
8232
8676
  binding.parameters.forEach((param) => {
@@ -8236,7 +8680,7 @@ function DeviceConfigPanel({
8236
8680
  }
8237
8681
  return {};
8238
8682
  });
8239
- const [collapsedSections, setCollapsedSections] = (0, import_react20.useState)(() => {
8683
+ const [collapsedSections, setCollapsedSections] = (0, import_react21.useState)(() => {
8240
8684
  const collapsed = /* @__PURE__ */ new Set();
8241
8685
  if (binding?.sections) {
8242
8686
  binding.sections.forEach((section) => {
@@ -8247,9 +8691,9 @@ function DeviceConfigPanel({
8247
8691
  }
8248
8692
  return collapsed;
8249
8693
  });
8250
- const [showToast, setShowToast] = (0, import_react20.useState)(true);
8251
- const [bindingId, setBindingId] = (0, import_react20.useState)(binding?.nodeId || null);
8252
- 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);
8253
8697
  if (binding && binding.nodeId !== bindingId) {
8254
8698
  const values = {};
8255
8699
  binding.parameters.forEach((param) => {
@@ -8265,7 +8709,7 @@ function DeviceConfigPanel({
8265
8709
  setCollapsedSections(collapsed);
8266
8710
  setBindingId(binding.nodeId);
8267
8711
  }
8268
- (0, import_react20.useEffect)(() => {
8712
+ (0, import_react21.useEffect)(() => {
8269
8713
  const currentTimestamp = binding?.state.lastSaved || 0;
8270
8714
  if (binding?.state.lastSaveResult && currentTimestamp !== lastResultTimestampRef.current) {
8271
8715
  lastResultTimestampRef.current = currentTimestamp;
@@ -8279,7 +8723,7 @@ function DeviceConfigPanel({
8279
8723
  return () => clearTimeout(showTimer);
8280
8724
  }
8281
8725
  }, [binding?.state.lastSaveResult, binding?.state.lastSaved, toastDuration]);
8282
- const parametersBySection = (0, import_react20.useMemo)(() => {
8726
+ const parametersBySection = (0, import_react21.useMemo)(() => {
8283
8727
  if (!binding) return { _unsectioned: [] };
8284
8728
  const groups = { _unsectioned: [] };
8285
8729
  binding.parameters.forEach((param) => {
@@ -8294,7 +8738,7 @@ function DeviceConfigPanel({
8294
8738
  });
8295
8739
  return groups;
8296
8740
  }, [binding]);
8297
- const sortedSections = (0, import_react20.useMemo)(() => {
8741
+ const sortedSections = (0, import_react21.useMemo)(() => {
8298
8742
  if (!binding?.sections) return [];
8299
8743
  return [...binding.sections].sort((a, b) => (a.order || 0) - (b.order || 0));
8300
8744
  }, [binding]);
@@ -8370,14 +8814,14 @@ function DeviceConfigPanel({
8370
8814
  const value = localValues[param.id];
8371
8815
  const error = binding.state.errors?.[param.id];
8372
8816
  const isDisabled = param.readOnly || param.enabled === false;
8373
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8817
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8374
8818
  "div",
8375
8819
  {
8376
8820
  style: {
8377
8821
  marginBottom: spacing.marginBottom
8378
8822
  },
8379
8823
  children: [
8380
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8824
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8381
8825
  "label",
8382
8826
  {
8383
8827
  style: {
@@ -8392,8 +8836,8 @@ function DeviceConfigPanel({
8392
8836
  },
8393
8837
  children: [
8394
8838
  param.label,
8395
- param.required && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: errorColor }, children: " *" }),
8396
- 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: [
8397
8841
  " (",
8398
8842
  param.unit,
8399
8843
  ")"
@@ -8401,7 +8845,7 @@ function DeviceConfigPanel({
8401
8845
  ]
8402
8846
  }
8403
8847
  ),
8404
- param.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8848
+ param.description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8405
8849
  "div",
8406
8850
  {
8407
8851
  style: {
@@ -8413,7 +8857,7 @@ function DeviceConfigPanel({
8413
8857
  children: param.description
8414
8858
  }
8415
8859
  ),
8416
- param.type === "number" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8860
+ param.type === "number" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8417
8861
  "input",
8418
8862
  {
8419
8863
  type: "number",
@@ -8437,7 +8881,7 @@ function DeviceConfigPanel({
8437
8881
  }
8438
8882
  }
8439
8883
  ),
8440
- param.type === "string" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8884
+ param.type === "string" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8441
8885
  "input",
8442
8886
  {
8443
8887
  type: "text",
@@ -8458,7 +8902,7 @@ function DeviceConfigPanel({
8458
8902
  }
8459
8903
  }
8460
8904
  ),
8461
- param.type === "boolean" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8905
+ param.type === "boolean" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8462
8906
  "label",
8463
8907
  {
8464
8908
  style: {
@@ -8468,7 +8912,7 @@ function DeviceConfigPanel({
8468
8912
  cursor: isDisabled ? "not-allowed" : "pointer"
8469
8913
  },
8470
8914
  children: [
8471
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8915
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8472
8916
  "input",
8473
8917
  {
8474
8918
  type: "checkbox",
@@ -8482,11 +8926,11 @@ function DeviceConfigPanel({
8482
8926
  }
8483
8927
  }
8484
8928
  ),
8485
- /* @__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" })
8486
8930
  ]
8487
8931
  }
8488
8932
  ),
8489
- param.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8933
+ param.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8490
8934
  "select",
8491
8935
  {
8492
8936
  value: value ?? "",
@@ -8504,10 +8948,10 @@ function DeviceConfigPanel({
8504
8948
  borderRadius: "2px",
8505
8949
  outline: "none"
8506
8950
  },
8507
- 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))
8508
8952
  }
8509
8953
  ),
8510
- error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8954
+ error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8511
8955
  "div",
8512
8956
  {
8513
8957
  style: {
@@ -8527,7 +8971,7 @@ function DeviceConfigPanel({
8527
8971
  const renderSection = (section) => {
8528
8972
  const params = parametersBySection[section.id] || [];
8529
8973
  const isCollapsed = collapsedSections.has(section.id);
8530
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8974
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8531
8975
  "div",
8532
8976
  {
8533
8977
  style: {
@@ -8537,7 +8981,7 @@ function DeviceConfigPanel({
8537
8981
  backgroundColor: surfaceColor
8538
8982
  },
8539
8983
  children: [
8540
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8984
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8541
8985
  "div",
8542
8986
  {
8543
8987
  onClick: () => section.collapsible && toggleSection(section.id),
@@ -8550,8 +8994,8 @@ function DeviceConfigPanel({
8550
8994
  alignItems: "center"
8551
8995
  },
8552
8996
  children: [
8553
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
8554
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
8997
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
8998
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8555
8999
  "div",
8556
9000
  {
8557
9001
  style: {
@@ -8563,12 +9007,12 @@ function DeviceConfigPanel({
8563
9007
  letterSpacing: "0.5px"
8564
9008
  },
8565
9009
  children: [
8566
- 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 }),
8567
9011
  section.title
8568
9012
  ]
8569
9013
  }
8570
9014
  ),
8571
- section.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9015
+ section.description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8572
9016
  "div",
8573
9017
  {
8574
9018
  style: {
@@ -8581,11 +9025,11 @@ function DeviceConfigPanel({
8581
9025
  }
8582
9026
  )
8583
9027
  ] }),
8584
- 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" })
8585
9029
  ]
8586
9030
  }
8587
9031
  ),
8588
- !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) })
8589
9033
  ]
8590
9034
  },
8591
9035
  section.id
@@ -8644,9 +9088,9 @@ function DeviceConfigPanel({
8644
9088
  const showSave = binding.display?.showSave !== false && binding.actions.onSave;
8645
9089
  const showReset = binding.display?.showReset !== false && binding.actions.onReset;
8646
9090
  const showCancel = binding.display?.showCancel !== false;
8647
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
8648
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
8649
- /* @__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)(
8650
9094
  "div",
8651
9095
  {
8652
9096
  style: {
@@ -8658,8 +9102,8 @@ function DeviceConfigPanel({
8658
9102
  borderBottom: `2px solid ${borderColor}`
8659
9103
  },
8660
9104
  children: [
8661
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
8662
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9105
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
9106
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8663
9107
  "h3",
8664
9108
  {
8665
9109
  style: {
@@ -8679,7 +9123,7 @@ function DeviceConfigPanel({
8679
9123
  children: titleText.length > 25 ? titleText.slice(0, 25) + "..." : titleText
8680
9124
  }
8681
9125
  ),
8682
- binding.display?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9126
+ binding.display?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8683
9127
  "div",
8684
9128
  {
8685
9129
  style: {
@@ -8692,8 +9136,8 @@ function DeviceConfigPanel({
8692
9136
  }
8693
9137
  )
8694
9138
  ] }),
8695
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
8696
- 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)(
8697
9141
  "button",
8698
9142
  {
8699
9143
  onClick: onOpenControls,
@@ -8716,7 +9160,7 @@ function DeviceConfigPanel({
8716
9160
  children: "CTRL"
8717
9161
  }
8718
9162
  ),
8719
- onUndock && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9163
+ onUndock && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8720
9164
  "button",
8721
9165
  {
8722
9166
  onClick: onUndock,
@@ -8737,7 +9181,7 @@ function DeviceConfigPanel({
8737
9181
  children: undockIcon
8738
9182
  }
8739
9183
  ),
8740
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9184
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8741
9185
  "button",
8742
9186
  {
8743
9187
  onClick: onClose,
@@ -8760,7 +9204,7 @@ function DeviceConfigPanel({
8760
9204
  ]
8761
9205
  }
8762
9206
  ),
8763
- binding.state.isDirty && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9207
+ binding.state.isDirty && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8764
9208
  "div",
8765
9209
  {
8766
9210
  style: {
@@ -8775,11 +9219,11 @@ function DeviceConfigPanel({
8775
9219
  children: "Unsaved changes"
8776
9220
  }
8777
9221
  ),
8778
- /* @__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) : (
8779
9223
  /* Render unsectioned parameters */
8780
- /* @__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) })
8781
9225
  ) }),
8782
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
9226
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
8783
9227
  "div",
8784
9228
  {
8785
9229
  style: {
@@ -8790,7 +9234,7 @@ function DeviceConfigPanel({
8790
9234
  flexWrap: "wrap"
8791
9235
  },
8792
9236
  children: [
8793
- showApply && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9237
+ showApply && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8794
9238
  "button",
8795
9239
  {
8796
9240
  onClick: handleApply,
@@ -8813,7 +9257,7 @@ function DeviceConfigPanel({
8813
9257
  children: binding.state.isSaving ? "Applying..." : "Apply"
8814
9258
  }
8815
9259
  ),
8816
- showSave && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9260
+ showSave && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8817
9261
  "button",
8818
9262
  {
8819
9263
  onClick: handleSave,
@@ -8836,7 +9280,7 @@ function DeviceConfigPanel({
8836
9280
  children: binding.state.isSaving ? "Saving..." : "Save"
8837
9281
  }
8838
9282
  ),
8839
- showReset && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9283
+ showReset && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8840
9284
  "button",
8841
9285
  {
8842
9286
  onClick: handleReset,
@@ -8859,7 +9303,7 @@ function DeviceConfigPanel({
8859
9303
  children: "Reset"
8860
9304
  }
8861
9305
  ),
8862
- showCancel && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9306
+ showCancel && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8863
9307
  "button",
8864
9308
  {
8865
9309
  onClick: handleCancel,
@@ -8886,7 +9330,7 @@ function DeviceConfigPanel({
8886
9330
  }
8887
9331
  )
8888
9332
  ] }),
8889
- binding.state.lastSaveResult && showToast && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
9333
+ binding.state.lastSaveResult && showToast && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8890
9334
  "div",
8891
9335
  {
8892
9336
  style: {
@@ -8910,7 +9354,7 @@ function DeviceConfigPanel({
8910
9354
  }
8911
9355
 
8912
9356
  // src/diagram/hooks/useSimulation.ts
8913
- var import_react21 = require("react");
9357
+ var import_react22 = require("react");
8914
9358
  function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8915
9359
  const {
8916
9360
  interval = 2e3,
@@ -8921,7 +9365,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8921
9365
  historyLength = 10,
8922
9366
  generateValue
8923
9367
  } = options;
8924
- (0, import_react21.useEffect)(() => {
9368
+ (0, import_react22.useEffect)(() => {
8925
9369
  if (!enabled) return;
8926
9370
  const intervalId = setInterval(() => {
8927
9371
  const updates = [];
@@ -8994,6 +9438,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
8994
9438
  LegacyValueEntry,
8995
9439
  NodeConfigPanel,
8996
9440
  NodeControlsPanel,
9441
+ NumpadDialog,
8997
9442
  PIDCanvas,
8998
9443
  PanelContent,
8999
9444
  PanelTabs,