@procaaso/alphinity-ui-components 1.0.4 → 1.0.6
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 +2076 -473
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +2026 -426
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -78,11 +78,14 @@ __export(index_exports, {
|
|
|
78
78
|
mockSymbolLibrary: () => mockSymbolLibrary,
|
|
79
79
|
nodeHasPort: () => nodeHasPort,
|
|
80
80
|
overlayStyles: () => overlayStyles,
|
|
81
|
+
registerSymbol: () => registerSymbol,
|
|
82
|
+
registerSymbols: () => registerSymbols,
|
|
81
83
|
useDrag: () => useDrag,
|
|
82
84
|
useKeyboardShortcuts: () => useKeyboardShortcuts,
|
|
83
85
|
useSelection: () => useSelection,
|
|
84
86
|
useSimulation: () => useSimulation,
|
|
85
87
|
useTelemetry: () => useTelemetry,
|
|
88
|
+
useTelemetryStatus: () => useTelemetryStatus,
|
|
86
89
|
useTheme: () => useTheme,
|
|
87
90
|
useViewBox: () => useViewBox,
|
|
88
91
|
validateDiagram: () => validateDiagram
|
|
@@ -1785,145 +1788,1224 @@ var ThemeToggle = ({
|
|
|
1785
1788
|
};
|
|
1786
1789
|
|
|
1787
1790
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
1788
|
-
var
|
|
1791
|
+
var import_react15 = require("react");
|
|
1789
1792
|
|
|
1790
1793
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
1791
1794
|
var mockSymbolLibrary = {
|
|
1792
|
-
"valve-
|
|
1793
|
-
id: "valve-
|
|
1794
|
-
name: "
|
|
1795
|
+
"valve-gate": {
|
|
1796
|
+
id: "valve-gate",
|
|
1797
|
+
name: "Gate Valve (Powered)",
|
|
1795
1798
|
category: "valve",
|
|
1796
|
-
viewBox: { x: 0, y: 0, width:
|
|
1799
|
+
viewBox: { x: 0, y: 0, width: 26, height: 26 },
|
|
1797
1800
|
ports: [
|
|
1798
|
-
{ id: "inlet", x: 0, y:
|
|
1799
|
-
{ id: "outlet", x:
|
|
1801
|
+
{ id: "inlet", x: 0, y: 18, type: "inlet", direction: "in" },
|
|
1802
|
+
{ id: "outlet", x: 26, y: 18, type: "outlet", direction: "out" }
|
|
1800
1803
|
],
|
|
1801
1804
|
svgContent: `
|
|
1802
|
-
<g>
|
|
1803
|
-
<!--
|
|
1804
|
-
<rect x="
|
|
1805
|
-
<!--
|
|
1806
|
-
<
|
|
1807
|
-
<!--
|
|
1808
|
-
<
|
|
1809
|
-
<line x1="35" y1="25" x2="50" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1805
|
+
<g transform="scale(0.5)">
|
|
1806
|
+
<!-- Actuator box -->
|
|
1807
|
+
<rect x="16.74" y="0" width="18.02" height="18.02" fill="var(--symbol-fill, #edeeef)" stroke="var(--symbol-stroke, #666666)" pointer-events="all"/>
|
|
1808
|
+
<!-- Actuator stem -->
|
|
1809
|
+
<path d="M 25.75 18.02 L 25.75 36.05" fill="none" stroke="var(--symbol-stroke, #666666)" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/>
|
|
1810
|
+
<!-- Valve body (two triangles forming diamond) -->
|
|
1811
|
+
<path d="M 0 20.6 L 25.75 36.05 L 0 51.5 Z M 51.5 20.6 L 25.75 36.05 L 51.5 51.5 Z" fill="var(--symbol-fill, #edeeef)" stroke="var(--symbol-stroke, #666666)" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/>
|
|
1810
1812
|
</g>
|
|
1811
1813
|
`,
|
|
1812
1814
|
metadata: {
|
|
1813
|
-
description: "
|
|
1814
|
-
tags: ["valve", "
|
|
1815
|
+
description: "Gate valve with powered actuator",
|
|
1816
|
+
tags: ["valve", "gate", "powered", "actuator"]
|
|
1815
1817
|
}
|
|
1816
1818
|
},
|
|
1817
|
-
"
|
|
1818
|
-
id: "
|
|
1819
|
-
name: "
|
|
1819
|
+
"pump-positive-displacement": {
|
|
1820
|
+
id: "pump-positive-displacement",
|
|
1821
|
+
name: "Positive Displacement Pump",
|
|
1822
|
+
category: "pump",
|
|
1823
|
+
viewBox: { x: 0, y: 0, width: 28.125, height: 28.125 },
|
|
1824
|
+
ports: [
|
|
1825
|
+
{ id: "inlet", x: 0, y: 14.0625, type: "inlet", direction: "in" },
|
|
1826
|
+
{ id: "outlet", x: 28.125, y: 14.0625, type: "outlet", direction: "out" }
|
|
1827
|
+
],
|
|
1828
|
+
svgContent: `
|
|
1829
|
+
<g transform="scale(0.28125)">
|
|
1830
|
+
<!-- Outer circle -->
|
|
1831
|
+
<ellipse
|
|
1832
|
+
cx="50"
|
|
1833
|
+
cy="50"
|
|
1834
|
+
rx="50"
|
|
1835
|
+
ry="50"
|
|
1836
|
+
fill="var(--symbol-fill, #edeeef)"
|
|
1837
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1838
|
+
stroke-width="1"
|
|
1839
|
+
/>
|
|
1840
|
+
|
|
1841
|
+
<!-- Diagonal line from top to bottom-right -->
|
|
1842
|
+
<path
|
|
1843
|
+
d="M 50 0 L 100 50 L 50 100"
|
|
1844
|
+
fill="none"
|
|
1845
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1846
|
+
stroke-width="1"
|
|
1847
|
+
stroke-miterlimit="10"
|
|
1848
|
+
/>
|
|
1849
|
+
|
|
1850
|
+
<!-- Center square -->
|
|
1851
|
+
<rect
|
|
1852
|
+
x="35"
|
|
1853
|
+
y="35"
|
|
1854
|
+
width="30"
|
|
1855
|
+
height="30"
|
|
1856
|
+
fill="none"
|
|
1857
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1858
|
+
stroke-width="1"
|
|
1859
|
+
/>
|
|
1860
|
+
</g>
|
|
1861
|
+
`,
|
|
1862
|
+
metadata: {
|
|
1863
|
+
description: "Positive displacement pump (ISO standard)",
|
|
1864
|
+
tags: ["pump", "positive-displacement", "iso"]
|
|
1865
|
+
}
|
|
1866
|
+
},
|
|
1867
|
+
"vannefold-bottom": {
|
|
1868
|
+
id: "vannefold-bottom",
|
|
1869
|
+
name: "Vannefold Block (Bottom)",
|
|
1820
1870
|
category: "valve",
|
|
1821
|
-
viewBox: { x: 0, y: 0, width:
|
|
1871
|
+
viewBox: { x: -0.25, y: -0.25, width: 44, height: 33.892578 },
|
|
1822
1872
|
ports: [
|
|
1823
|
-
{ id: "inlet", x: 0, y:
|
|
1824
|
-
{ id: "outlet", x:
|
|
1873
|
+
{ id: "bottom-inlet", x: 0, y: 12.5, type: "control", direction: "in" },
|
|
1874
|
+
{ id: "top-outlet", x: 24, y: 32.5, type: "control", direction: "out" }
|
|
1825
1875
|
],
|
|
1826
1876
|
svgContent: `
|
|
1827
|
-
<g>
|
|
1828
|
-
<!--
|
|
1829
|
-
<
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1877
|
+
<g transform="scale(0.5)">
|
|
1878
|
+
<!-- Bottom inlet pipe -->
|
|
1879
|
+
<path
|
|
1880
|
+
d="M 3,29.785156 H 0 v -10 h 3 m 14,10 h 3 v -10 h -3 m -15,8 h 16 m -16,-6 h 16"
|
|
1881
|
+
fill="none"
|
|
1882
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1883
|
+
stroke-miterlimit="10"
|
|
1884
|
+
/>
|
|
1885
|
+
|
|
1886
|
+
<!-- Top outlet pipe -->
|
|
1887
|
+
<path
|
|
1888
|
+
d="m 43,49.785156 v -3 h 10 v 3 m -10,14 v 3 h 10 v -3 m -8,-15 v 16 m 6,-16 v 16"
|
|
1889
|
+
fill="none"
|
|
1890
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1891
|
+
stroke-miterlimit="10"
|
|
1892
|
+
/>
|
|
1893
|
+
|
|
1894
|
+
<!-- Main block outer -->
|
|
1895
|
+
<rect
|
|
1896
|
+
x="7"
|
|
1897
|
+
y="0"
|
|
1898
|
+
width="80"
|
|
1899
|
+
height="59.785156"
|
|
1900
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1901
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1902
|
+
/>
|
|
1903
|
+
|
|
1904
|
+
<!-- Main block inner -->
|
|
1905
|
+
<rect
|
|
1906
|
+
x="9"
|
|
1907
|
+
y="2"
|
|
1908
|
+
width="76"
|
|
1909
|
+
height="55.785156"
|
|
1910
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1911
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1912
|
+
/>
|
|
1913
|
+
|
|
1914
|
+
<!-- Bolt holes -->
|
|
1915
|
+
<ellipse cx="15" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1916
|
+
<ellipse cx="15" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1917
|
+
<ellipse cx="79" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1918
|
+
<ellipse cx="79" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1919
|
+
<ellipse cx="15" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1920
|
+
<ellipse cx="15" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1921
|
+
<ellipse cx="79" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1922
|
+
<ellipse cx="79" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1923
|
+
|
|
1834
1924
|
</g>
|
|
1835
1925
|
`,
|
|
1836
1926
|
metadata: {
|
|
1837
|
-
description: "
|
|
1838
|
-
tags: ["
|
|
1927
|
+
description: "Vannefold heat exchanger block with bottom inlet configuration",
|
|
1928
|
+
tags: ["heat-exchanger", "vannefold", "fold", "bottom"]
|
|
1929
|
+
}
|
|
1930
|
+
},
|
|
1931
|
+
"vannefold-middle": {
|
|
1932
|
+
id: "vannefold-middle",
|
|
1933
|
+
name: "Vannefold Block (Middle)",
|
|
1934
|
+
category: "valve",
|
|
1935
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 26.548828 },
|
|
1936
|
+
ports: [
|
|
1937
|
+
{ id: "left-inlet", x: 0, y: 13.65625, type: "control", direction: "in" },
|
|
1938
|
+
{ id: "right-outlet", x: 47.5, y: 13.65625, type: "control", direction: "out" }
|
|
1939
|
+
],
|
|
1940
|
+
svgContent: `
|
|
1941
|
+
<g transform="scale(0.5)">
|
|
1942
|
+
<!-- Left inlet pipe -->
|
|
1943
|
+
<path
|
|
1944
|
+
d="M 3,22.3125 H 0 v 10 H 3 m 14,-10 h 3 v 10 h -3 m -15,-8 h 16 m -16,6 h 16"
|
|
1945
|
+
fill="none"
|
|
1946
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1947
|
+
stroke-miterlimit="10"
|
|
1948
|
+
/>
|
|
1949
|
+
|
|
1950
|
+
<!-- Main block outer -->
|
|
1951
|
+
<rect
|
|
1952
|
+
x="7"
|
|
1953
|
+
y="0"
|
|
1954
|
+
width="80"
|
|
1955
|
+
height="52.097656"
|
|
1956
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1957
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1958
|
+
/>
|
|
1959
|
+
|
|
1960
|
+
<!-- Main block inner -->
|
|
1961
|
+
<rect
|
|
1962
|
+
x="9"
|
|
1963
|
+
y="0"
|
|
1964
|
+
width="76"
|
|
1965
|
+
height="52.097656"
|
|
1966
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1967
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1968
|
+
/>
|
|
1969
|
+
|
|
1970
|
+
<!-- Bolt holes -->
|
|
1971
|
+
<ellipse cx="15" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1972
|
+
<ellipse cx="15" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1973
|
+
<ellipse cx="79" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1974
|
+
<ellipse cx="79" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1975
|
+
<ellipse cx="15" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1976
|
+
<ellipse cx="15" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1977
|
+
<ellipse cx="79" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1978
|
+
<ellipse cx="79" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1979
|
+
</g>
|
|
1980
|
+
`,
|
|
1981
|
+
metadata: {
|
|
1982
|
+
description: "Vannefold heat exchanger block with side inlet configuration",
|
|
1983
|
+
tags: ["heat-exchanger", "vannefold", "fold", "middle"]
|
|
1984
|
+
}
|
|
1985
|
+
},
|
|
1986
|
+
"vannefold-top": {
|
|
1987
|
+
id: "vannefold-top",
|
|
1988
|
+
name: "Vannefold Block (Top)",
|
|
1989
|
+
category: "valve",
|
|
1990
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 30.392578 },
|
|
1991
|
+
ports: [
|
|
1992
|
+
{ id: "bottom-inlet", x: 0, y: 17.5, type: "control", direction: "in" },
|
|
1993
|
+
{ id: "top-outlet", x: 24, y: 0, type: "control", direction: "out" }
|
|
1994
|
+
],
|
|
1995
|
+
svgContent: `
|
|
1996
|
+
<g transform="scale(0.5)">
|
|
1997
|
+
<!-- Bottom inlet pipe -->
|
|
1998
|
+
<path
|
|
1999
|
+
d="M 3,30 H 0 V 40 H 3 M 17,30 h 3 V 40 H 17 M 2,32 H 18 M 2,38 H 18"
|
|
2000
|
+
fill="none"
|
|
2001
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2002
|
+
stroke-miterlimit="10"
|
|
2003
|
+
/>
|
|
2004
|
+
|
|
2005
|
+
<!-- Main block outer -->
|
|
2006
|
+
<rect
|
|
2007
|
+
x="7"
|
|
2008
|
+
y="0"
|
|
2009
|
+
width="80"
|
|
2010
|
+
height="59.785156"
|
|
2011
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2012
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2013
|
+
/>
|
|
2014
|
+
|
|
2015
|
+
<!-- Main block inner -->
|
|
2016
|
+
<rect
|
|
2017
|
+
x="9"
|
|
2018
|
+
y="2"
|
|
2019
|
+
width="76"
|
|
2020
|
+
height="57.785156"
|
|
2021
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2022
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2023
|
+
/>
|
|
2024
|
+
|
|
2025
|
+
<!-- Bolt holes -->
|
|
2026
|
+
<ellipse cx="15" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2027
|
+
<ellipse cx="15" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2028
|
+
<ellipse cx="79" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2029
|
+
<ellipse cx="79" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2030
|
+
<ellipse cx="15" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2031
|
+
<ellipse cx="15" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2032
|
+
<ellipse cx="79" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2033
|
+
<ellipse cx="79" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2034
|
+
|
|
2035
|
+
</g>
|
|
2036
|
+
`,
|
|
2037
|
+
metadata: {
|
|
2038
|
+
description: "Vannefold heat exchanger block with bottom inlet and top outlet configuration",
|
|
2039
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top"]
|
|
2040
|
+
}
|
|
2041
|
+
},
|
|
2042
|
+
"vannefold-top-top-inlet": {
|
|
2043
|
+
id: "vannefold-top-top-inlet",
|
|
2044
|
+
name: "Vannefold Block (Top, Top Inlet)",
|
|
2045
|
+
category: "valve",
|
|
2046
|
+
viewBox: { x: 0, y: 0, width: 44, height: 33.788002 },
|
|
2047
|
+
ports: [
|
|
2048
|
+
{ id: "top-inlet", x: 23.5, y: 0, type: "control", direction: "in" },
|
|
2049
|
+
{ id: "bottom-outlet", x: 0, y: 21, type: "control", direction: "out" }
|
|
2050
|
+
],
|
|
2051
|
+
svgContent: `
|
|
2052
|
+
<g transform="scale(0.5)">
|
|
2053
|
+
<!-- Top inlet pipe flange -->
|
|
2054
|
+
<path
|
|
2055
|
+
d="M 52,3 V 1.3598666e-8 H 42 V 3 m 10,14 v 3 H 42 V 17 M 50,2 V 18 M 44,2 v 16"
|
|
2056
|
+
fill="none"
|
|
2057
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2058
|
+
stroke-miterlimit="10"
|
|
2059
|
+
/>
|
|
2060
|
+
|
|
2061
|
+
<!-- Bottom outlet pipe flange -->
|
|
2062
|
+
<path
|
|
2063
|
+
d="M 3,36.79085 H 0 v 10 h 3 m 14,-10 h 3 v 10 h -3 m -15,-8 h 16 m -16,6 h 16"
|
|
2064
|
+
fill="none"
|
|
2065
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2066
|
+
stroke-miterlimit="10"
|
|
2067
|
+
/>
|
|
2068
|
+
|
|
2069
|
+
<!-- Main block outer -->
|
|
2070
|
+
<rect
|
|
2071
|
+
x="7"
|
|
2072
|
+
y="6.7908498"
|
|
2073
|
+
width="80"
|
|
2074
|
+
height="59.785156"
|
|
2075
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2076
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2077
|
+
/>
|
|
2078
|
+
|
|
2079
|
+
<!-- Main block inner -->
|
|
2080
|
+
<rect
|
|
2081
|
+
x="9"
|
|
2082
|
+
y="8.7908498"
|
|
2083
|
+
width="76"
|
|
2084
|
+
height="57.785156"
|
|
2085
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2086
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2087
|
+
/>
|
|
2088
|
+
|
|
2089
|
+
<!-- Bolt holes -->
|
|
2090
|
+
<ellipse cx="15" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2091
|
+
<ellipse cx="15" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2092
|
+
<ellipse cx="15" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2093
|
+
<ellipse cx="15" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2094
|
+
<ellipse cx="79" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2095
|
+
<ellipse cx="79" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2096
|
+
<ellipse cx="79" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2097
|
+
<ellipse cx="79" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2098
|
+
|
|
2099
|
+
</g>
|
|
2100
|
+
`,
|
|
2101
|
+
metadata: {
|
|
2102
|
+
description: "Vannefold heat exchanger block with top inlet and bottom outlet configuration",
|
|
2103
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top", "top-inlet"]
|
|
2104
|
+
}
|
|
2105
|
+
},
|
|
2106
|
+
"vannefold-left": {
|
|
2107
|
+
id: "vannefold-left",
|
|
2108
|
+
name: "Vannefold Block (Left)",
|
|
2109
|
+
category: "valve",
|
|
2110
|
+
viewBox: { x: 0, y: 0, width: 33.892578, height: 44.25 },
|
|
2111
|
+
ports: [
|
|
2112
|
+
{ id: "left-inlet", x: 0, y: 20.75, type: "control", direction: "in" },
|
|
2113
|
+
{ id: "right-outlet", x: 21, y: 43.5, type: "control", direction: "out" }
|
|
2114
|
+
],
|
|
2115
|
+
svgContent: `
|
|
2116
|
+
<g transform="scale(0.5)">
|
|
2117
|
+
<!-- Left inlet pipe flange -->
|
|
2118
|
+
<path
|
|
2119
|
+
d="M 3,46.5 H 2.8789924e-8 v -10 H 3 m 14,10 h 3 v -10 h -3 m -15,8 h 16 m -16,-6 h 16"
|
|
2120
|
+
fill="none"
|
|
2121
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2122
|
+
stroke-miterlimit="10"
|
|
2123
|
+
/>
|
|
2124
|
+
|
|
2125
|
+
<!-- Right outlet pipe flange -->
|
|
2126
|
+
<path
|
|
2127
|
+
d="m 37,70.5 v -3 h 10 v 3 m -10,14 v 3 h 10 v -3 m -8,-15 v 16 m 6,-16 v 16"
|
|
2128
|
+
fill="none"
|
|
2129
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2130
|
+
stroke-miterlimit="10"
|
|
2131
|
+
/>
|
|
2132
|
+
|
|
2133
|
+
<!-- Main block outer -->
|
|
2134
|
+
<rect
|
|
2135
|
+
x="7"
|
|
2136
|
+
y="0.5"
|
|
2137
|
+
width="59.785156"
|
|
2138
|
+
height="80"
|
|
2139
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2140
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2141
|
+
/>
|
|
2142
|
+
|
|
2143
|
+
<!-- Main block inner -->
|
|
2144
|
+
<rect
|
|
2145
|
+
x="9"
|
|
2146
|
+
y="2.5"
|
|
2147
|
+
width="57.785156"
|
|
2148
|
+
height="76"
|
|
2149
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2150
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2151
|
+
/>
|
|
2152
|
+
|
|
2153
|
+
<!-- Bolt holes -->
|
|
2154
|
+
<ellipse cx="15" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2155
|
+
<ellipse cx="15" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2156
|
+
<ellipse cx="62" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2157
|
+
<ellipse cx="62" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2158
|
+
<ellipse cx="15" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2159
|
+
<ellipse cx="15" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2160
|
+
<ellipse cx="62" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2161
|
+
<ellipse cx="62" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2162
|
+
|
|
2163
|
+
`,
|
|
2164
|
+
metadata: {
|
|
2165
|
+
description: "Vannefold heat exchanger block with left inlet and right outlet, vertical orientation",
|
|
2166
|
+
tags: ["heat-exchanger", "vannefold", "fold", "left", "vertical"]
|
|
2167
|
+
}
|
|
2168
|
+
},
|
|
2169
|
+
"vannefold-right": {
|
|
2170
|
+
id: "vannefold-right",
|
|
2171
|
+
name: "Vannefold Block (Right)",
|
|
2172
|
+
category: "valve",
|
|
2173
|
+
viewBox: { x: 0, y: 0, width: 33.892578, height: 44.25 },
|
|
2174
|
+
ports: [
|
|
2175
|
+
{ id: "right-inlet", x: 33.892578, y: 20.75, type: "control", direction: "in" },
|
|
2176
|
+
{ id: "left-outlet", x: 12.392578, y: 43.75, type: "control", direction: "out" }
|
|
2177
|
+
],
|
|
2178
|
+
svgContent: `
|
|
2179
|
+
<g transform="scale(0.5)">
|
|
2180
|
+
<!-- Right inlet pipe flange -->
|
|
2181
|
+
<path
|
|
2182
|
+
d="m 63.785156,46.5 h 3 v -10 h -3 m -14,10 h -3 v -10 h 3 m 15,8 h -16 m 16,-6 h -16"
|
|
2183
|
+
fill="none"
|
|
2184
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2185
|
+
stroke-miterlimit="10"
|
|
2186
|
+
/>
|
|
2187
|
+
|
|
2188
|
+
<!-- Left outlet pipe flange -->
|
|
2189
|
+
<path
|
|
2190
|
+
d="m 29.785156,70.5 v -3 h -10 v 3 m 10,14 v 3 h -10 v -3 m 8,-15 v 16 m -6,-16 v 16"
|
|
2191
|
+
fill="none"
|
|
2192
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2193
|
+
stroke-miterlimit="10"
|
|
2194
|
+
/>
|
|
2195
|
+
|
|
2196
|
+
<!-- Main block outer -->
|
|
2197
|
+
<rect
|
|
2198
|
+
x="0"
|
|
2199
|
+
y="0.5"
|
|
2200
|
+
width="59.785156"
|
|
2201
|
+
height="80"
|
|
2202
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2203
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2204
|
+
/>
|
|
2205
|
+
|
|
2206
|
+
<!-- Main block inner -->
|
|
2207
|
+
<rect
|
|
2208
|
+
x="0"
|
|
2209
|
+
y="2.5"
|
|
2210
|
+
width="57.785156"
|
|
2211
|
+
height="76"
|
|
2212
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2213
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2214
|
+
/>
|
|
2215
|
+
|
|
2216
|
+
<!-- Bolt holes -->
|
|
2217
|
+
<ellipse cx="51.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2218
|
+
<ellipse cx="51.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2219
|
+
<ellipse cx="4.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2220
|
+
<ellipse cx="4.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2221
|
+
<ellipse cx="51.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2222
|
+
<ellipse cx="51.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2223
|
+
<ellipse cx="4.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2224
|
+
<ellipse cx="4.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2225
|
+
|
|
2226
|
+
`,
|
|
2227
|
+
metadata: {
|
|
2228
|
+
description: "Vannefold heat exchanger block with right inlet and left outlet, vertical orientation",
|
|
2229
|
+
tags: ["heat-exchanger", "vannefold", "fold", "right", "vertical"]
|
|
2230
|
+
}
|
|
2231
|
+
},
|
|
2232
|
+
"pixer": {
|
|
2233
|
+
id: "pixer",
|
|
2234
|
+
name: "Pixer",
|
|
2235
|
+
category: "pump",
|
|
2236
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
2237
|
+
ports: [
|
|
2238
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
2239
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
2240
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
2241
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
2242
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
2243
|
+
],
|
|
2244
|
+
svgContent: `
|
|
2245
|
+
<g transform="scale(0.0984375) translate(-195, -186)">
|
|
2246
|
+
<!-- Top mounting flange -->
|
|
2247
|
+
<rect
|
|
2248
|
+
width="141.313"
|
|
2249
|
+
height="9.872"
|
|
2250
|
+
transform="translate(252.392 185.89)"
|
|
2251
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2252
|
+
stroke-miterlimit="10"
|
|
2253
|
+
stroke-width="1"
|
|
2254
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2255
|
+
/>
|
|
2256
|
+
|
|
2257
|
+
<!-- Motor housing top -->
|
|
2258
|
+
<rect
|
|
2259
|
+
width="106.614"
|
|
2260
|
+
height="2.468"
|
|
2261
|
+
transform="translate(269.742 199.918)"
|
|
2262
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2263
|
+
stroke-miterlimit="10"
|
|
2264
|
+
stroke-width="1"
|
|
2265
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2266
|
+
/>
|
|
2267
|
+
<rect
|
|
2268
|
+
width="106.614"
|
|
2269
|
+
height="5.835"
|
|
2270
|
+
transform="translate(269.742 202.384)"
|
|
2271
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2272
|
+
stroke-miterlimit="10"
|
|
2273
|
+
stroke-width="1"
|
|
2274
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2275
|
+
/>
|
|
2276
|
+
<rect
|
|
2277
|
+
width="106.614"
|
|
2278
|
+
height="2.468"
|
|
2279
|
+
transform="translate(269.742 208.222)"
|
|
2280
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2281
|
+
stroke-miterlimit="10"
|
|
2282
|
+
stroke-width="1"
|
|
2283
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2284
|
+
/>
|
|
2285
|
+
|
|
2286
|
+
<!-- Bottom mounting flange -->
|
|
2287
|
+
<rect
|
|
2288
|
+
width="221.702"
|
|
2289
|
+
height="2.401"
|
|
2290
|
+
transform="translate(212.199 395.587)"
|
|
2291
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2292
|
+
stroke-miterlimit="10"
|
|
2293
|
+
stroke-width="1"
|
|
2294
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2295
|
+
/>
|
|
2296
|
+
<rect
|
|
2297
|
+
width="221.702"
|
|
2298
|
+
height="6.269"
|
|
2299
|
+
transform="translate(212.199 397.988)"
|
|
2300
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2301
|
+
stroke-miterlimit="10"
|
|
2302
|
+
stroke-width="1"
|
|
2303
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2304
|
+
/>
|
|
2305
|
+
<rect
|
|
2306
|
+
width="221.702"
|
|
2307
|
+
height="2.65"
|
|
2308
|
+
transform="translate(212.199 404.257)"
|
|
2309
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2310
|
+
stroke-miterlimit="10"
|
|
2311
|
+
stroke-width="1"
|
|
2312
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2313
|
+
/>
|
|
2314
|
+
|
|
2315
|
+
<!-- Motor housing transition -->
|
|
2316
|
+
<path
|
|
2317
|
+
d="M444.7,228.776l17.117,4.1H568.429l17.089-4.085a.032.032,0,0,0,0-.062H444.705a.028.028,0,0,0-.007.046Z"
|
|
2318
|
+
transform="translate(-192.059 -32.959)"
|
|
2319
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2320
|
+
stroke-miterlimit="10"
|
|
2321
|
+
stroke-width="1"
|
|
2322
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2323
|
+
/>
|
|
2324
|
+
|
|
2325
|
+
<!-- Bottom flange -->
|
|
2326
|
+
<rect
|
|
2327
|
+
width="256"
|
|
2328
|
+
height="9.872"
|
|
2329
|
+
transform="translate(195.05 411.066)"
|
|
2330
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2331
|
+
stroke-miterlimit="10"
|
|
2332
|
+
stroke-width="1"
|
|
2333
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2334
|
+
/>
|
|
2335
|
+
<path
|
|
2336
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2337
|
+
transform="translate(0 -737.221)"
|
|
2338
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2339
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2340
|
+
stroke-miterlimit="10"
|
|
2341
|
+
stroke-width="1"
|
|
2342
|
+
/>
|
|
2343
|
+
|
|
2344
|
+
<!-- Vessel top cone -->
|
|
2345
|
+
<path
|
|
2346
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2347
|
+
transform="translate(0 -82.72)"
|
|
2348
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2349
|
+
stroke-miterlimit="10"
|
|
2350
|
+
stroke-width="1"
|
|
2351
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2352
|
+
/>
|
|
2353
|
+
|
|
2354
|
+
<!-- Main vessel body -->
|
|
2355
|
+
<rect
|
|
2356
|
+
width="256"
|
|
2357
|
+
height="59.803"
|
|
2358
|
+
transform="translate(195.05 245.636)"
|
|
2359
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2360
|
+
stroke-miterlimit="10"
|
|
2361
|
+
stroke-width="1"
|
|
2362
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2363
|
+
/>
|
|
2364
|
+
<rect
|
|
2365
|
+
width="256"
|
|
2366
|
+
height="76.892"
|
|
2367
|
+
transform="translate(195.05 308.417)"
|
|
2368
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2369
|
+
stroke-miterlimit="10"
|
|
2370
|
+
stroke-width="1"
|
|
2371
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2372
|
+
/>
|
|
2373
|
+
|
|
2374
|
+
<!-- Vessel bottom transitions -->
|
|
2375
|
+
<path
|
|
2376
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2377
|
+
transform="translate(-0.049 -398.769)"
|
|
2378
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2379
|
+
stroke-miterlimit="10"
|
|
2380
|
+
stroke-width="1"
|
|
2381
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2382
|
+
/>
|
|
2383
|
+
<path
|
|
2384
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2385
|
+
transform="translate(-0.062 -403.731)"
|
|
2386
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2387
|
+
stroke-miterlimit="10"
|
|
2388
|
+
stroke-width="1"
|
|
2389
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2390
|
+
/>
|
|
2391
|
+
<path
|
|
2392
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2393
|
+
transform="translate(0 -665.171)"
|
|
2394
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2395
|
+
stroke-miterlimit="10"
|
|
2396
|
+
stroke-width="1"
|
|
2397
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2398
|
+
/>
|
|
2399
|
+
|
|
2400
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2401
|
+
<ellipse
|
|
2402
|
+
cx="15.454"
|
|
2403
|
+
cy="6.096"
|
|
2404
|
+
rx="15.454"
|
|
2405
|
+
ry="6.096"
|
|
2406
|
+
transform="translate(307.486 228.161)"
|
|
2407
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2408
|
+
stroke-miterlimit="10"
|
|
2409
|
+
stroke-width="1"
|
|
2410
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2411
|
+
/>
|
|
2412
|
+
<ellipse
|
|
2413
|
+
cx="15.454"
|
|
2414
|
+
cy="5.3"
|
|
2415
|
+
rx="15.454"
|
|
2416
|
+
ry="5.3"
|
|
2417
|
+
transform="translate(307.486 229.753)"
|
|
2418
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2419
|
+
stroke-miterlimit="10"
|
|
2420
|
+
stroke-width="1"
|
|
2421
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2422
|
+
/>
|
|
2423
|
+
<ellipse
|
|
2424
|
+
cx="5.174"
|
|
2425
|
+
cy="15.117"
|
|
2426
|
+
rx="5.174"
|
|
2427
|
+
ry="15.117"
|
|
2428
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2429
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2430
|
+
stroke-miterlimit="10"
|
|
2431
|
+
stroke-width="1"
|
|
2432
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2433
|
+
/>
|
|
2434
|
+
<path
|
|
2435
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2436
|
+
transform="translate(-578.512 -147.764)"
|
|
2437
|
+
fill="none"
|
|
2438
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2439
|
+
stroke-miterlimit="10"
|
|
2440
|
+
stroke-width="1"
|
|
2441
|
+
/>
|
|
2442
|
+
<ellipse
|
|
2443
|
+
cx="15.117"
|
|
2444
|
+
cy="5.174"
|
|
2445
|
+
rx="15.117"
|
|
2446
|
+
ry="5.174"
|
|
2447
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2448
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2449
|
+
stroke-miterlimit="10"
|
|
2450
|
+
stroke-width="1"
|
|
2451
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2452
|
+
/>
|
|
2453
|
+
<path
|
|
2454
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2455
|
+
transform="translate(-179.058 -147.764)"
|
|
2456
|
+
fill="none"
|
|
2457
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2458
|
+
stroke-miterlimit="10"
|
|
2459
|
+
stroke-width="1"
|
|
2460
|
+
/>
|
|
2461
|
+
<ellipse
|
|
2462
|
+
cx="1.651"
|
|
2463
|
+
cy="15.082"
|
|
2464
|
+
rx="1.651"
|
|
2465
|
+
ry="15.082"
|
|
2466
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2467
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2468
|
+
stroke-miterlimit="10"
|
|
2469
|
+
stroke-width="1"
|
|
2470
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2471
|
+
/>
|
|
2472
|
+
<path
|
|
2473
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2474
|
+
transform="translate(-710.84 -145.969)"
|
|
2475
|
+
fill="none"
|
|
2476
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2477
|
+
stroke-miterlimit="10"
|
|
2478
|
+
stroke-width="1"
|
|
2479
|
+
/>
|
|
2480
|
+
<ellipse
|
|
2481
|
+
cx="15.082"
|
|
2482
|
+
cy="1.651"
|
|
2483
|
+
rx="15.082"
|
|
2484
|
+
ry="1.651"
|
|
2485
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2486
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2487
|
+
stroke-miterlimit="10"
|
|
2488
|
+
stroke-width="1"
|
|
2489
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2490
|
+
/>
|
|
2491
|
+
<path
|
|
2492
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2493
|
+
transform="translate(-55.932 -145.969)"
|
|
2494
|
+
fill="none"
|
|
2495
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2496
|
+
stroke-miterlimit="10"
|
|
2497
|
+
stroke-width="1"
|
|
2498
|
+
/>
|
|
2499
|
+
</g>
|
|
2500
|
+
`,
|
|
2501
|
+
metadata: {
|
|
2502
|
+
description: "Pixer mixer/agitator vessel with top-mounted drive",
|
|
2503
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank"]
|
|
1839
2504
|
}
|
|
1840
2505
|
},
|
|
1841
|
-
"
|
|
1842
|
-
id: "
|
|
1843
|
-
name: "
|
|
2506
|
+
"pixer-barb": {
|
|
2507
|
+
id: "pixer-barb",
|
|
2508
|
+
name: "Pixer (Hose Barb)",
|
|
1844
2509
|
category: "pump",
|
|
1845
|
-
viewBox: { x: 0, y: 0, width:
|
|
2510
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
1846
2511
|
ports: [
|
|
1847
|
-
{ id: "
|
|
1848
|
-
{ id: "outlet", x:
|
|
2512
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
2513
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
2514
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
2515
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
2516
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
1849
2517
|
],
|
|
1850
2518
|
svgContent: `
|
|
1851
|
-
<g>
|
|
1852
|
-
<!--
|
|
1853
|
-
<
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
<
|
|
2519
|
+
<g transform="scale(0.0984375) translate(-195, -186)">
|
|
2520
|
+
<!-- Hose barb ridges at top -->
|
|
2521
|
+
<rect
|
|
2522
|
+
width="20"
|
|
2523
|
+
height="2"
|
|
2524
|
+
transform="translate(313 173)"
|
|
2525
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2526
|
+
stroke-miterlimit="10"
|
|
2527
|
+
stroke-width="0.5"
|
|
2528
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2529
|
+
/>
|
|
2530
|
+
<rect
|
|
2531
|
+
width="20"
|
|
2532
|
+
height="2"
|
|
2533
|
+
transform="translate(313 177)"
|
|
2534
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2535
|
+
stroke-miterlimit="10"
|
|
2536
|
+
stroke-width="0.5"
|
|
2537
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2538
|
+
/>
|
|
2539
|
+
<rect
|
|
2540
|
+
width="20"
|
|
2541
|
+
height="2"
|
|
2542
|
+
transform="translate(313 181)"
|
|
2543
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2544
|
+
stroke-miterlimit="10"
|
|
2545
|
+
stroke-width="0.5"
|
|
2546
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2547
|
+
/>
|
|
2548
|
+
|
|
2549
|
+
<!-- Taper from barb to motor housing -->
|
|
2550
|
+
<path
|
|
2551
|
+
d="M 313,183 L 269.742,199.918 L 376.356,199.918 L 333,183 Z"
|
|
2552
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2553
|
+
stroke-miterlimit="10"
|
|
2554
|
+
stroke-width="1"
|
|
2555
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2556
|
+
/>
|
|
2557
|
+
|
|
2558
|
+
<!-- Motor housing top -->
|
|
2559
|
+
<rect
|
|
2560
|
+
width="106.614"
|
|
2561
|
+
height="2.468"
|
|
2562
|
+
transform="translate(269.742 199.918)"
|
|
2563
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2564
|
+
stroke-miterlimit="10"
|
|
2565
|
+
stroke-width="1"
|
|
2566
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2567
|
+
/>
|
|
2568
|
+
<rect
|
|
2569
|
+
width="106.614"
|
|
2570
|
+
height="5.835"
|
|
2571
|
+
transform="translate(269.742 202.384)"
|
|
2572
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2573
|
+
stroke-miterlimit="10"
|
|
2574
|
+
stroke-width="1"
|
|
2575
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2576
|
+
/>
|
|
2577
|
+
<rect
|
|
2578
|
+
width="106.614"
|
|
2579
|
+
height="2.468"
|
|
2580
|
+
transform="translate(269.742 208.222)"
|
|
2581
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2582
|
+
stroke-miterlimit="10"
|
|
2583
|
+
stroke-width="1"
|
|
2584
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2585
|
+
/>
|
|
2586
|
+
|
|
2587
|
+
<!-- Bottom mounting flange -->
|
|
2588
|
+
<rect
|
|
2589
|
+
width="221.702"
|
|
2590
|
+
height="2.401"
|
|
2591
|
+
transform="translate(212.199 395.587)"
|
|
2592
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2593
|
+
stroke-miterlimit="10"
|
|
2594
|
+
stroke-width="1"
|
|
2595
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2596
|
+
/>
|
|
2597
|
+
<rect
|
|
2598
|
+
width="221.702"
|
|
2599
|
+
height="6.269"
|
|
2600
|
+
transform="translate(212.199 397.988)"
|
|
2601
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2602
|
+
stroke-miterlimit="10"
|
|
2603
|
+
stroke-width="1"
|
|
2604
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2605
|
+
/>
|
|
2606
|
+
<rect
|
|
2607
|
+
width="221.702"
|
|
2608
|
+
height="2.65"
|
|
2609
|
+
transform="translate(212.199 404.257)"
|
|
2610
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2611
|
+
stroke-miterlimit="10"
|
|
2612
|
+
stroke-width="1"
|
|
2613
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2614
|
+
/>
|
|
2615
|
+
|
|
2616
|
+
<!-- Bottom flange -->
|
|
2617
|
+
<rect
|
|
2618
|
+
width="256"
|
|
2619
|
+
height="9.872"
|
|
2620
|
+
transform="translate(195.05 411.066)"
|
|
2621
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2622
|
+
stroke-miterlimit="10"
|
|
2623
|
+
stroke-width="1"
|
|
2624
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2625
|
+
/>
|
|
2626
|
+
<path
|
|
2627
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2628
|
+
transform="translate(0 -737.221)"
|
|
2629
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2630
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2631
|
+
stroke-miterlimit="10"
|
|
2632
|
+
stroke-width="1"
|
|
2633
|
+
/>
|
|
2634
|
+
|
|
2635
|
+
<!-- Vessel top cone -->
|
|
2636
|
+
<path
|
|
2637
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2638
|
+
transform="translate(0 -82.72)"
|
|
2639
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2640
|
+
stroke-miterlimit="10"
|
|
2641
|
+
stroke-width="1"
|
|
2642
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2643
|
+
/>
|
|
2644
|
+
|
|
2645
|
+
<!-- Main vessel body -->
|
|
2646
|
+
<rect
|
|
2647
|
+
width="256"
|
|
2648
|
+
height="59.803"
|
|
2649
|
+
transform="translate(195.05 245.636)"
|
|
2650
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2651
|
+
stroke-miterlimit="10"
|
|
2652
|
+
stroke-width="1"
|
|
2653
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2654
|
+
/>
|
|
2655
|
+
<rect
|
|
2656
|
+
width="256"
|
|
2657
|
+
height="76.892"
|
|
2658
|
+
transform="translate(195.05 308.417)"
|
|
2659
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2660
|
+
stroke-miterlimit="10"
|
|
2661
|
+
stroke-width="1"
|
|
2662
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2663
|
+
/>
|
|
2664
|
+
|
|
2665
|
+
<!-- Vessel bottom transitions -->
|
|
2666
|
+
<path
|
|
2667
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2668
|
+
transform="translate(-0.049 -398.769)"
|
|
2669
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2670
|
+
stroke-miterlimit="10"
|
|
2671
|
+
stroke-width="1"
|
|
2672
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2673
|
+
/>
|
|
2674
|
+
<path
|
|
2675
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2676
|
+
transform="translate(-0.062 -403.731)"
|
|
2677
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2678
|
+
stroke-miterlimit="10"
|
|
2679
|
+
stroke-width="1"
|
|
2680
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2681
|
+
/>
|
|
2682
|
+
<path
|
|
2683
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2684
|
+
transform="translate(0 -665.171)"
|
|
2685
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2686
|
+
stroke-miterlimit="10"
|
|
2687
|
+
stroke-width="1"
|
|
2688
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2689
|
+
/>
|
|
2690
|
+
|
|
2691
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2692
|
+
<ellipse
|
|
2693
|
+
cx="15.454"
|
|
2694
|
+
cy="6.096"
|
|
2695
|
+
rx="15.454"
|
|
2696
|
+
ry="6.096"
|
|
2697
|
+
transform="translate(307.486 228.161)"
|
|
2698
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2699
|
+
stroke-miterlimit="10"
|
|
2700
|
+
stroke-width="1"
|
|
2701
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2702
|
+
/>
|
|
2703
|
+
<ellipse
|
|
2704
|
+
cx="15.454"
|
|
2705
|
+
cy="5.3"
|
|
2706
|
+
rx="15.454"
|
|
2707
|
+
ry="5.3"
|
|
2708
|
+
transform="translate(307.486 229.753)"
|
|
2709
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2710
|
+
stroke-miterlimit="10"
|
|
2711
|
+
stroke-width="1"
|
|
2712
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2713
|
+
/>
|
|
2714
|
+
<ellipse
|
|
2715
|
+
cx="5.174"
|
|
2716
|
+
cy="15.117"
|
|
2717
|
+
rx="5.174"
|
|
2718
|
+
ry="15.117"
|
|
2719
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2720
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2721
|
+
stroke-miterlimit="10"
|
|
2722
|
+
stroke-width="1"
|
|
2723
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2724
|
+
/>
|
|
2725
|
+
<path
|
|
2726
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2727
|
+
transform="translate(-578.512 -147.764)"
|
|
2728
|
+
fill="none"
|
|
2729
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2730
|
+
stroke-miterlimit="10"
|
|
2731
|
+
stroke-width="1"
|
|
2732
|
+
/>
|
|
2733
|
+
<ellipse
|
|
2734
|
+
cx="15.117"
|
|
2735
|
+
cy="5.174"
|
|
2736
|
+
rx="15.117"
|
|
2737
|
+
ry="5.174"
|
|
2738
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2739
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2740
|
+
stroke-miterlimit="10"
|
|
2741
|
+
stroke-width="1"
|
|
2742
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2743
|
+
/>
|
|
2744
|
+
<path
|
|
2745
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2746
|
+
transform="translate(-179.058 -147.764)"
|
|
2747
|
+
fill="none"
|
|
2748
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2749
|
+
stroke-miterlimit="10"
|
|
2750
|
+
stroke-width="1"
|
|
2751
|
+
/>
|
|
2752
|
+
<ellipse
|
|
2753
|
+
cx="1.651"
|
|
2754
|
+
cy="15.082"
|
|
2755
|
+
rx="1.651"
|
|
2756
|
+
ry="15.082"
|
|
2757
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2758
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2759
|
+
stroke-miterlimit="10"
|
|
2760
|
+
stroke-width="1"
|
|
2761
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2762
|
+
/>
|
|
2763
|
+
<path
|
|
2764
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2765
|
+
transform="translate(-710.84 -145.969)"
|
|
2766
|
+
fill="none"
|
|
2767
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2768
|
+
stroke-miterlimit="10"
|
|
2769
|
+
stroke-width="1"
|
|
2770
|
+
/>
|
|
2771
|
+
<ellipse
|
|
2772
|
+
cx="15.082"
|
|
2773
|
+
cy="1.651"
|
|
2774
|
+
rx="15.082"
|
|
2775
|
+
ry="1.651"
|
|
2776
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2777
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2778
|
+
stroke-miterlimit="10"
|
|
2779
|
+
stroke-width="1"
|
|
2780
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2781
|
+
/>
|
|
2782
|
+
<path
|
|
2783
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2784
|
+
transform="translate(-55.932 -145.969)"
|
|
2785
|
+
fill="none"
|
|
2786
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2787
|
+
stroke-miterlimit="10"
|
|
2788
|
+
stroke-width="1"
|
|
2789
|
+
/>
|
|
1863
2790
|
</g>
|
|
1864
2791
|
`,
|
|
1865
2792
|
metadata: {
|
|
1866
|
-
description: "
|
|
1867
|
-
tags: ["
|
|
2793
|
+
description: "Pixer mixer/agitator vessel with tapered hose barb connection at top",
|
|
2794
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank", "hose-barb"]
|
|
1868
2795
|
}
|
|
1869
2796
|
},
|
|
1870
|
-
"vessel-
|
|
1871
|
-
id: "vessel-
|
|
1872
|
-
name: "
|
|
2797
|
+
"vessel-balloon": {
|
|
2798
|
+
id: "vessel-balloon",
|
|
2799
|
+
name: "Vessel",
|
|
1873
2800
|
category: "vessel",
|
|
1874
|
-
viewBox: { x: 0, y: 0, width:
|
|
2801
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 45.5 },
|
|
1875
2802
|
ports: [
|
|
1876
|
-
{ id: "
|
|
1877
|
-
{ id: "
|
|
2803
|
+
{ id: "top", type: "inlet", x: 12.65625, y: 0 },
|
|
2804
|
+
{ id: "left", type: "inlet", x: 2.5, y: 19.5 },
|
|
2805
|
+
{ id: "right", type: "outlet", x: 22.8125, y: 19.5 },
|
|
2806
|
+
{ id: "bottom", type: "outlet", x: 12.65625, y: 45.5 }
|
|
1878
2807
|
],
|
|
1879
2808
|
svgContent: `
|
|
1880
|
-
<g>
|
|
1881
|
-
<!--
|
|
1882
|
-
<rect
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
2809
|
+
<g transform="scale(0.0984375) translate(-195, -100)">
|
|
2810
|
+
<!-- Top opening nozzle -->
|
|
2811
|
+
<rect
|
|
2812
|
+
width="65"
|
|
2813
|
+
height="19.5"
|
|
2814
|
+
transform="translate(290.5, 100)"
|
|
2815
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2816
|
+
stroke-miterlimit="10"
|
|
2817
|
+
stroke-width="1"
|
|
2818
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2819
|
+
/>
|
|
2820
|
+
|
|
2821
|
+
<!-- Transition from nozzle to dome -->
|
|
2822
|
+
<path
|
|
2823
|
+
d="M 290.5,119.5 L 238,152 L 408,152 L 355.5,119.5 Z"
|
|
2824
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2825
|
+
stroke-miterlimit="10"
|
|
2826
|
+
stroke-width="1"
|
|
2827
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2828
|
+
/>
|
|
2829
|
+
|
|
2830
|
+
<!-- Upper balloon dome - rounded bulge -->
|
|
2831
|
+
<path
|
|
2832
|
+
d="M 238,152 C 185,210 150,320 180,395 L 466,395 C 496,320 461,210 408,152 Z"
|
|
2833
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2834
|
+
stroke-miterlimit="10"
|
|
2835
|
+
stroke-width="1"
|
|
2836
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2837
|
+
/>
|
|
2838
|
+
|
|
2839
|
+
<!-- Tapered vessel body -->
|
|
2840
|
+
<path
|
|
2841
|
+
d="M 180,395 L 269.742,530 L 376.356,530 L 466,395 Z"
|
|
2842
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2843
|
+
stroke-miterlimit="10"
|
|
2844
|
+
stroke-width="1"
|
|
2845
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2846
|
+
/>
|
|
2847
|
+
|
|
2848
|
+
<!-- Bottom cone -->
|
|
2849
|
+
<path
|
|
2850
|
+
d="M 269.742,530 L 280,555 L 366,555 L 376.356,530 Z"
|
|
2851
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2852
|
+
stroke-miterlimit="10"
|
|
2853
|
+
stroke-width="1"
|
|
2854
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2855
|
+
/>
|
|
2856
|
+
|
|
2857
|
+
<!-- Bottom flange matching pixer top dimensions -->
|
|
2858
|
+
<rect
|
|
2859
|
+
width="141.313"
|
|
2860
|
+
height="9.872"
|
|
2861
|
+
transform="translate(252.392, 555)"
|
|
2862
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2863
|
+
stroke-miterlimit="10"
|
|
2864
|
+
stroke-width="1"
|
|
2865
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2866
|
+
/>
|
|
1891
2867
|
</g>
|
|
1892
2868
|
`,
|
|
1893
2869
|
metadata: {
|
|
1894
|
-
description: "
|
|
1895
|
-
tags: ["vessel", "tank", "
|
|
2870
|
+
description: "Balloon-shaped vessel with rounded top and tapered bottom, designed to fit on standard pixer",
|
|
2871
|
+
tags: ["vessel", "storage", "tank", "balloon"]
|
|
1896
2872
|
}
|
|
1897
2873
|
},
|
|
1898
|
-
"
|
|
1899
|
-
id: "
|
|
1900
|
-
name: "
|
|
2874
|
+
"hollow-fiber": {
|
|
2875
|
+
id: "hollow-fiber",
|
|
2876
|
+
name: "Hollow Fiber",
|
|
2877
|
+
category: "other",
|
|
2878
|
+
viewBox: { x: 0, y: 0, width: 30, height: 109 },
|
|
2879
|
+
ports: [
|
|
2880
|
+
{ id: "top-left", type: "outlet", x: 10, y: 2.75 },
|
|
2881
|
+
{ id: "top-right", type: "outlet", x: 24.5, y: 22.25 },
|
|
2882
|
+
{ id: "bottom-left", type: "inlet", x: 10, y: 106.25 },
|
|
2883
|
+
{ id: "bottom-right", type: "inlet", x: 24.5, y: 87.25 }
|
|
2884
|
+
],
|
|
2885
|
+
svgContent: `
|
|
2886
|
+
<g transform="scale(0.5)">
|
|
2887
|
+
<!-- Top left flange -->
|
|
2888
|
+
<rect x="10.5" y="0.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2889
|
+
|
|
2890
|
+
<!-- Top right flange -->
|
|
2891
|
+
<rect x="39.5" y="39.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2892
|
+
|
|
2893
|
+
<!-- Bottom left flange -->
|
|
2894
|
+
<rect x="10.5" y="207.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2895
|
+
|
|
2896
|
+
<!-- Bottom right flange -->
|
|
2897
|
+
<rect x="39.5" y="169.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2898
|
+
|
|
2899
|
+
<!-- Main vessel body -->
|
|
2900
|
+
<rect x="0.5" y="9.5" width="40" height="199.5" rx="6" ry="6" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2901
|
+
</g>
|
|
2902
|
+
`,
|
|
2903
|
+
metadata: {
|
|
2904
|
+
description: "Hollow fiber filter module with multiple inlet/outlet connections",
|
|
2905
|
+
tags: ["filter", "hollow-fiber", "filtration", "separation", "membrane"]
|
|
2906
|
+
}
|
|
2907
|
+
},
|
|
2908
|
+
"psr-f": {
|
|
2909
|
+
id: "psr-f",
|
|
2910
|
+
name: "PSR F",
|
|
1901
2911
|
category: "instrument",
|
|
1902
|
-
viewBox: { x: 0, y: 0, width:
|
|
2912
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
1903
2913
|
ports: [
|
|
1904
|
-
{ id: "
|
|
2914
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
2915
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
2916
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
2917
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
1905
2918
|
],
|
|
1906
2919
|
svgContent: `
|
|
1907
|
-
<g>
|
|
1908
|
-
<!--
|
|
1909
|
-
<
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
2920
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2921
|
+
<!-- Circle background -->
|
|
2922
|
+
<ellipse
|
|
2923
|
+
cx="28.5"
|
|
2924
|
+
cy="28.5"
|
|
2925
|
+
rx="28.5"
|
|
2926
|
+
ry="28.5"
|
|
2927
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2928
|
+
stroke-width="1"
|
|
2929
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2930
|
+
/>
|
|
2931
|
+
|
|
2932
|
+
<!-- Letter F -->
|
|
2933
|
+
<text
|
|
2934
|
+
x="28.5"
|
|
2935
|
+
y="38"
|
|
2936
|
+
text-anchor="middle"
|
|
2937
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2938
|
+
font-size="34"
|
|
2939
|
+
font-weight="normal"
|
|
2940
|
+
font-style="italic"
|
|
2941
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2942
|
+
>F</text>
|
|
1914
2943
|
</g>
|
|
1915
2944
|
`,
|
|
1916
2945
|
metadata: {
|
|
1917
|
-
description: "
|
|
1918
|
-
tags: ["instrument", "
|
|
2946
|
+
description: "PSR F instrument symbol - Flow indicator",
|
|
2947
|
+
tags: ["instrument", "psr", "flow", "indicator"]
|
|
2948
|
+
}
|
|
2949
|
+
},
|
|
2950
|
+
"psr-p": {
|
|
2951
|
+
id: "psr-p",
|
|
2952
|
+
name: "PSR P",
|
|
2953
|
+
category: "instrument",
|
|
2954
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
2955
|
+
ports: [
|
|
2956
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
2957
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
2958
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
2959
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
2960
|
+
],
|
|
2961
|
+
svgContent: `
|
|
2962
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2963
|
+
<!-- Circle background -->
|
|
2964
|
+
<ellipse
|
|
2965
|
+
cx="28.5"
|
|
2966
|
+
cy="28.5"
|
|
2967
|
+
rx="28.5"
|
|
2968
|
+
ry="28.5"
|
|
2969
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2970
|
+
stroke-width="1"
|
|
2971
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2972
|
+
/>
|
|
2973
|
+
|
|
2974
|
+
<!-- Letter P -->
|
|
2975
|
+
<text
|
|
2976
|
+
x="28.5"
|
|
2977
|
+
y="38"
|
|
2978
|
+
text-anchor="middle"
|
|
2979
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2980
|
+
font-size="34"
|
|
2981
|
+
font-weight="normal"
|
|
2982
|
+
font-style="italic"
|
|
2983
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2984
|
+
>P</text>
|
|
2985
|
+
</g>
|
|
2986
|
+
`,
|
|
2987
|
+
metadata: {
|
|
2988
|
+
description: "PSR P instrument symbol - Pressure indicator",
|
|
2989
|
+
tags: ["instrument", "psr", "pressure", "indicator"]
|
|
1919
2990
|
}
|
|
1920
2991
|
}
|
|
1921
2992
|
};
|
|
2993
|
+
var customSymbols = {};
|
|
2994
|
+
function registerSymbol(symbol) {
|
|
2995
|
+
customSymbols[symbol.id] = symbol;
|
|
2996
|
+
}
|
|
2997
|
+
function registerSymbols(symbols) {
|
|
2998
|
+
if (Array.isArray(symbols)) {
|
|
2999
|
+
symbols.forEach((symbol) => registerSymbol(symbol));
|
|
3000
|
+
} else {
|
|
3001
|
+
Object.values(symbols).forEach((symbol) => registerSymbol(symbol));
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
1922
3004
|
function getSymbolDefinition(symbolId) {
|
|
1923
|
-
return mockSymbolLibrary[symbolId];
|
|
3005
|
+
return customSymbols[symbolId] ?? mockSymbolLibrary[symbolId];
|
|
1924
3006
|
}
|
|
1925
3007
|
function getAvailableSymbols() {
|
|
1926
|
-
return Object.keys(mockSymbolLibrary);
|
|
3008
|
+
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
1927
3009
|
}
|
|
1928
3010
|
|
|
1929
3011
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
@@ -1995,6 +3077,24 @@ function NodeRenderer({
|
|
|
1995
3077
|
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
1996
3078
|
);
|
|
1997
3079
|
}
|
|
3080
|
+
const getStatusColor = (status) => {
|
|
3081
|
+
switch (status) {
|
|
3082
|
+
case "running":
|
|
3083
|
+
return "#22c55e";
|
|
3084
|
+
// Green
|
|
3085
|
+
case "alarm":
|
|
3086
|
+
return "#ef4444";
|
|
3087
|
+
// Red
|
|
3088
|
+
case "warning":
|
|
3089
|
+
return "#f59e0b";
|
|
3090
|
+
// Orange
|
|
3091
|
+
case "stopped":
|
|
3092
|
+
default:
|
|
3093
|
+
return "#edeeef";
|
|
3094
|
+
}
|
|
3095
|
+
};
|
|
3096
|
+
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
3097
|
+
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
1998
3098
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1999
3099
|
"g",
|
|
2000
3100
|
{
|
|
@@ -2003,6 +3103,11 @@ function NodeRenderer({
|
|
|
2003
3103
|
"data-selected": isSelected,
|
|
2004
3104
|
"data-dragging": isDragging,
|
|
2005
3105
|
transform: transforms.join(" "),
|
|
3106
|
+
style: {
|
|
3107
|
+
"--symbol-fill": fillColor,
|
|
3108
|
+
"--symbol-stroke": strokeColor,
|
|
3109
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
3110
|
+
},
|
|
2006
3111
|
onClick: (e) => {
|
|
2007
3112
|
e.stopPropagation();
|
|
2008
3113
|
onNodeClick?.(node.id, e);
|
|
@@ -2022,9 +3127,6 @@ function NodeRenderer({
|
|
|
2022
3127
|
onNodeDragStart?.(node.id, e);
|
|
2023
3128
|
}
|
|
2024
3129
|
},
|
|
2025
|
-
style: {
|
|
2026
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
2027
|
-
},
|
|
2028
3130
|
children: [
|
|
2029
3131
|
isSelected && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2030
3132
|
"rect",
|
|
@@ -2077,6 +3179,9 @@ function PipeRenderer({
|
|
|
2077
3179
|
onPipeClick,
|
|
2078
3180
|
enableWaypointEditing = false,
|
|
2079
3181
|
onWaypointDragStart,
|
|
3182
|
+
onWaypointClick,
|
|
3183
|
+
selectedWaypointPipeId,
|
|
3184
|
+
selectedWaypointIndex,
|
|
2080
3185
|
editingPipeId,
|
|
2081
3186
|
draggingWaypointIndex,
|
|
2082
3187
|
waypointDragOffset,
|
|
@@ -2097,7 +3202,7 @@ function PipeRenderer({
|
|
|
2097
3202
|
});
|
|
2098
3203
|
const pointsString = displayPoints.map((point) => `${point.x},${point.y}`).join(" ");
|
|
2099
3204
|
const pipeStyle = pipe.style || {};
|
|
2100
|
-
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#
|
|
3205
|
+
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#94a1b8";
|
|
2101
3206
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
2102
3207
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
2103
3208
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
@@ -2146,10 +3251,11 @@ function PipeRenderer({
|
|
|
2146
3251
|
] }),
|
|
2147
3252
|
displayPoints.map((point, idx) => {
|
|
2148
3253
|
const isEndpoint = idx === 0 || idx === displayPoints.length - 1;
|
|
3254
|
+
const isSelectedWaypoint = selectedWaypointPipeId === pipe.id && selectedWaypointIndex === idx;
|
|
2149
3255
|
const isDragging = isEditing && draggingWaypointIndex === idx;
|
|
2150
|
-
const waypointSize = isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
2151
|
-
const waypointOpacity = isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
2152
|
-
const waypointColor = isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
3256
|
+
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3257
|
+
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3258
|
+
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
2153
3259
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2154
3260
|
"circle",
|
|
2155
3261
|
{
|
|
@@ -2165,6 +3271,12 @@ function PipeRenderer({
|
|
|
2165
3271
|
cursor: showEditingControls ? isDragging ? "grabbing" : "grab" : "default"
|
|
2166
3272
|
},
|
|
2167
3273
|
pointerEvents: showEditingControls ? "all" : "none",
|
|
3274
|
+
onClick: (e) => {
|
|
3275
|
+
if (showEditingControls) {
|
|
3276
|
+
e.stopPropagation();
|
|
3277
|
+
onWaypointClick?.(pipe.id, idx);
|
|
3278
|
+
}
|
|
3279
|
+
},
|
|
2168
3280
|
onMouseDown: (e) => {
|
|
2169
3281
|
if (showEditingControls) {
|
|
2170
3282
|
e.stopPropagation();
|
|
@@ -2241,7 +3353,13 @@ function PipeRenderer({
|
|
|
2241
3353
|
|
|
2242
3354
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
2243
3355
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2244
|
-
function DataOverlay({
|
|
3356
|
+
function DataOverlay({
|
|
3357
|
+
nodeId,
|
|
3358
|
+
x,
|
|
3359
|
+
y,
|
|
3360
|
+
telemetry,
|
|
3361
|
+
scale = 1
|
|
3362
|
+
}) {
|
|
2245
3363
|
const { value, display, history } = telemetry;
|
|
2246
3364
|
const showValue = display?.showValue ?? true;
|
|
2247
3365
|
const showStatus = display?.showStatus ?? true;
|
|
@@ -2281,9 +3399,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2281
3399
|
const displayText = value.unit ? `${formattedValue} ${value.unit}` : formattedValue;
|
|
2282
3400
|
const sparklinePath = (() => {
|
|
2283
3401
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
2284
|
-
const width = 70;
|
|
2285
|
-
const height = 20;
|
|
2286
|
-
const padding = 5;
|
|
3402
|
+
const width = 70 * scale;
|
|
3403
|
+
const height = 20 * scale;
|
|
3404
|
+
const padding = 5 * scale;
|
|
2287
3405
|
const effectiveWidth = width - padding * 2;
|
|
2288
3406
|
const effectiveHeight = height - padding * 2;
|
|
2289
3407
|
const min = Math.min(...history);
|
|
@@ -2297,21 +3415,22 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2297
3415
|
return `M ${points.join(" L ")}`;
|
|
2298
3416
|
})();
|
|
2299
3417
|
const hasSparkline = showSparkline && sparklinePath;
|
|
2300
|
-
const overlayHeight = label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22;
|
|
3418
|
+
const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
|
|
3419
|
+
const overlayWidth = 80 * scale;
|
|
2301
3420
|
const displayX = x + offsetX;
|
|
2302
3421
|
const displayY = y + offsetY;
|
|
2303
3422
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
2304
3423
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2305
3424
|
"rect",
|
|
2306
3425
|
{
|
|
2307
|
-
x: displayX -
|
|
2308
|
-
y: displayY - 25,
|
|
2309
|
-
width:
|
|
3426
|
+
x: displayX - overlayWidth / 2,
|
|
3427
|
+
y: displayY - 25 * scale,
|
|
3428
|
+
width: overlayWidth,
|
|
2310
3429
|
height: overlayHeight,
|
|
2311
|
-
rx:
|
|
3430
|
+
rx: 4 * scale,
|
|
2312
3431
|
fill: colors.bg,
|
|
2313
3432
|
stroke: colors.border,
|
|
2314
|
-
strokeWidth:
|
|
3433
|
+
strokeWidth: 1 * scale,
|
|
2315
3434
|
opacity: "0.95",
|
|
2316
3435
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
2317
3436
|
}
|
|
@@ -2320,9 +3439,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2320
3439
|
"text",
|
|
2321
3440
|
{
|
|
2322
3441
|
x: displayX,
|
|
2323
|
-
y: displayY - 15,
|
|
3442
|
+
y: displayY - 15 * scale,
|
|
2324
3443
|
textAnchor: "middle",
|
|
2325
|
-
fontSize:
|
|
3444
|
+
fontSize: 8 * scale,
|
|
2326
3445
|
fontWeight: "600",
|
|
2327
3446
|
fill: finalTextColor,
|
|
2328
3447
|
opacity: "0.9",
|
|
@@ -2333,31 +3452,41 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2333
3452
|
"text",
|
|
2334
3453
|
{
|
|
2335
3454
|
x: displayX,
|
|
2336
|
-
y: label ? displayY - 3 : displayY - 9,
|
|
3455
|
+
y: label ? displayY - 3 * scale : displayY - 9 * scale,
|
|
2337
3456
|
textAnchor: "middle",
|
|
2338
|
-
fontSize:
|
|
3457
|
+
fontSize: 11 * scale,
|
|
2339
3458
|
fontWeight: "700",
|
|
2340
3459
|
fill: finalTextColor,
|
|
2341
3460
|
letterSpacing: "0.02em",
|
|
2342
3461
|
children: displayText
|
|
2343
3462
|
}
|
|
2344
3463
|
),
|
|
2345
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2346
|
-
"
|
|
3464
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3465
|
+
"circle",
|
|
2347
3466
|
{
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
3467
|
+
cx: displayX + 35 * scale,
|
|
3468
|
+
cy: displayY - 18 * scale,
|
|
3469
|
+
r: 3 * scale,
|
|
3470
|
+
fill: finalTextColor,
|
|
3471
|
+
opacity: "0.9",
|
|
3472
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3473
|
+
"animate",
|
|
3474
|
+
{
|
|
3475
|
+
attributeName: "opacity",
|
|
3476
|
+
values: "0.9;0.3;0.9",
|
|
3477
|
+
dur: "1.5s",
|
|
3478
|
+
repeatCount: "indefinite"
|
|
3479
|
+
}
|
|
3480
|
+
)
|
|
2352
3481
|
}
|
|
2353
|
-
)
|
|
3482
|
+
),
|
|
2354
3483
|
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2355
3484
|
"text",
|
|
2356
3485
|
{
|
|
2357
3486
|
x: displayX,
|
|
2358
|
-
y: displayY + 5,
|
|
3487
|
+
y: displayY + 5 * scale,
|
|
2359
3488
|
textAnchor: "middle",
|
|
2360
|
-
fontSize:
|
|
3489
|
+
fontSize: 7 * scale,
|
|
2361
3490
|
fontWeight: "500",
|
|
2362
3491
|
fill: finalTextColor,
|
|
2363
3492
|
opacity: "0.7",
|
|
@@ -2368,13 +3497,13 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2368
3497
|
]
|
|
2369
3498
|
}
|
|
2370
3499
|
),
|
|
2371
|
-
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { transform: `translate(${displayX - 35}, ${displayY + (label ? 5 : 0)})`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3500
|
+
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2372
3501
|
"path",
|
|
2373
3502
|
{
|
|
2374
3503
|
d: sparklinePath,
|
|
2375
3504
|
fill: "none",
|
|
2376
3505
|
stroke: sparklineColor || finalTextColor,
|
|
2377
|
-
strokeWidth:
|
|
3506
|
+
strokeWidth: 1.5 * scale,
|
|
2378
3507
|
strokeLinecap: "round",
|
|
2379
3508
|
strokeLinejoin: "round",
|
|
2380
3509
|
opacity: "0.9"
|
|
@@ -2383,8 +3512,145 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2383
3512
|
] });
|
|
2384
3513
|
}
|
|
2385
3514
|
|
|
2386
|
-
// src/
|
|
3515
|
+
// src/components/PIDCanvas/PositionPanel.tsx
|
|
2387
3516
|
var import_react8 = require("react");
|
|
3517
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3518
|
+
function PositionPanel({
|
|
3519
|
+
selectedNode,
|
|
3520
|
+
selectedWaypoint,
|
|
3521
|
+
onPositionChange,
|
|
3522
|
+
onWaypointPositionChange,
|
|
3523
|
+
position = "top-right"
|
|
3524
|
+
}) {
|
|
3525
|
+
const [x, setX] = (0, import_react8.useState)("");
|
|
3526
|
+
const [y, setY] = (0, import_react8.useState)("");
|
|
3527
|
+
(0, import_react8.useEffect)(() => {
|
|
3528
|
+
if (selectedNode) {
|
|
3529
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3530
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3531
|
+
} else if (selectedWaypoint) {
|
|
3532
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3533
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3534
|
+
}
|
|
3535
|
+
}, [selectedNode, selectedWaypoint]);
|
|
3536
|
+
if (!selectedNode && !selectedWaypoint) {
|
|
3537
|
+
return null;
|
|
3538
|
+
}
|
|
3539
|
+
const handleXChange = (value) => {
|
|
3540
|
+
setX(value);
|
|
3541
|
+
const numValue = parseFloat(value);
|
|
3542
|
+
if (!isNaN(numValue)) {
|
|
3543
|
+
if (selectedNode && onPositionChange) {
|
|
3544
|
+
onPositionChange(selectedNode.id, numValue, selectedNode.transform.y);
|
|
3545
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3546
|
+
onWaypointPositionChange(
|
|
3547
|
+
selectedWaypoint.pipeId,
|
|
3548
|
+
selectedWaypoint.pointIndex,
|
|
3549
|
+
numValue,
|
|
3550
|
+
selectedWaypoint.position.y
|
|
3551
|
+
);
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
};
|
|
3555
|
+
const handleYChange = (value) => {
|
|
3556
|
+
setY(value);
|
|
3557
|
+
const numValue = parseFloat(value);
|
|
3558
|
+
if (!isNaN(numValue)) {
|
|
3559
|
+
if (selectedNode && onPositionChange) {
|
|
3560
|
+
onPositionChange(selectedNode.id, selectedNode.transform.x, numValue);
|
|
3561
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3562
|
+
onWaypointPositionChange(
|
|
3563
|
+
selectedWaypoint.pipeId,
|
|
3564
|
+
selectedWaypoint.pointIndex,
|
|
3565
|
+
selectedWaypoint.position.x,
|
|
3566
|
+
numValue
|
|
3567
|
+
);
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
};
|
|
3571
|
+
const handleBlur = () => {
|
|
3572
|
+
if (selectedNode) {
|
|
3573
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3574
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3575
|
+
} else if (selectedWaypoint) {
|
|
3576
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3577
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3578
|
+
}
|
|
3579
|
+
};
|
|
3580
|
+
const positionStyles = {
|
|
3581
|
+
"top-left": { top: 10, left: 10 },
|
|
3582
|
+
"top-right": { top: 10, right: 10 },
|
|
3583
|
+
"bottom-left": { bottom: 10, left: 10 },
|
|
3584
|
+
"bottom-right": { bottom: 10, right: 10 }
|
|
3585
|
+
};
|
|
3586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
3587
|
+
"div",
|
|
3588
|
+
{
|
|
3589
|
+
style: {
|
|
3590
|
+
position: "absolute",
|
|
3591
|
+
...positionStyles[position],
|
|
3592
|
+
backgroundColor: "white",
|
|
3593
|
+
border: "1px solid #ccc",
|
|
3594
|
+
borderRadius: "4px",
|
|
3595
|
+
padding: "12px",
|
|
3596
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
3597
|
+
zIndex: 1e3,
|
|
3598
|
+
minWidth: "180px",
|
|
3599
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
3600
|
+
fontSize: "13px"
|
|
3601
|
+
},
|
|
3602
|
+
children: [
|
|
3603
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
3604
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
3605
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3606
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
3607
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3608
|
+
"input",
|
|
3609
|
+
{
|
|
3610
|
+
type: "number",
|
|
3611
|
+
value: x,
|
|
3612
|
+
onChange: (e) => handleXChange(e.target.value),
|
|
3613
|
+
onBlur: handleBlur,
|
|
3614
|
+
style: {
|
|
3615
|
+
flex: 1,
|
|
3616
|
+
padding: "4px 8px",
|
|
3617
|
+
border: "1px solid #ddd",
|
|
3618
|
+
borderRadius: "3px",
|
|
3619
|
+
fontSize: "13px"
|
|
3620
|
+
},
|
|
3621
|
+
step: "1"
|
|
3622
|
+
}
|
|
3623
|
+
)
|
|
3624
|
+
] }),
|
|
3625
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3626
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
3627
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3628
|
+
"input",
|
|
3629
|
+
{
|
|
3630
|
+
type: "number",
|
|
3631
|
+
value: y,
|
|
3632
|
+
onChange: (e) => handleYChange(e.target.value),
|
|
3633
|
+
onBlur: handleBlur,
|
|
3634
|
+
style: {
|
|
3635
|
+
flex: 1,
|
|
3636
|
+
padding: "4px 8px",
|
|
3637
|
+
border: "1px solid #ddd",
|
|
3638
|
+
borderRadius: "3px",
|
|
3639
|
+
fontSize: "13px"
|
|
3640
|
+
},
|
|
3641
|
+
step: "1"
|
|
3642
|
+
}
|
|
3643
|
+
)
|
|
3644
|
+
] })
|
|
3645
|
+
] }),
|
|
3646
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3647
|
+
]
|
|
3648
|
+
}
|
|
3649
|
+
);
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
// src/diagram/hooks/useViewBox.ts
|
|
3653
|
+
var import_react9 = require("react");
|
|
2388
3654
|
function useViewBox(options) {
|
|
2389
3655
|
const {
|
|
2390
3656
|
initialViewBox,
|
|
@@ -2395,16 +3661,16 @@ function useViewBox(options) {
|
|
|
2395
3661
|
zoomSensitivity = 1e-3,
|
|
2396
3662
|
allowLeftClickPan = true
|
|
2397
3663
|
} = options;
|
|
2398
|
-
const [viewBox, setViewBox] = (0,
|
|
2399
|
-
const svgRef = (0,
|
|
2400
|
-
const isPanningRef = (0,
|
|
2401
|
-
const lastMousePosRef = (0,
|
|
2402
|
-
const spaceKeyDownRef = (0,
|
|
2403
|
-
const lastTouchDistanceRef = (0,
|
|
2404
|
-
const resetViewBox = (0,
|
|
3664
|
+
const [viewBox, setViewBox] = (0, import_react9.useState)(initialViewBox);
|
|
3665
|
+
const svgRef = (0, import_react9.useRef)(null);
|
|
3666
|
+
const isPanningRef = (0, import_react9.useRef)(false);
|
|
3667
|
+
const lastMousePosRef = (0, import_react9.useRef)({ x: 0, y: 0 });
|
|
3668
|
+
const spaceKeyDownRef = (0, import_react9.useRef)(false);
|
|
3669
|
+
const lastTouchDistanceRef = (0, import_react9.useRef)(null);
|
|
3670
|
+
const resetViewBox = (0, import_react9.useCallback)(() => {
|
|
2405
3671
|
setViewBox(initialViewBox);
|
|
2406
3672
|
}, [initialViewBox]);
|
|
2407
|
-
const zoomIn = (0,
|
|
3673
|
+
const zoomIn = (0, import_react9.useCallback)(() => {
|
|
2408
3674
|
setViewBox((prev) => {
|
|
2409
3675
|
const currentZoom = initialViewBox.width / prev.width;
|
|
2410
3676
|
const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
|
|
@@ -2421,7 +3687,7 @@ function useViewBox(options) {
|
|
|
2421
3687
|
};
|
|
2422
3688
|
});
|
|
2423
3689
|
}, [initialViewBox, minZoom]);
|
|
2424
|
-
const zoomOut = (0,
|
|
3690
|
+
const zoomOut = (0, import_react9.useCallback)(() => {
|
|
2425
3691
|
setViewBox((prev) => {
|
|
2426
3692
|
const currentZoom = initialViewBox.width / prev.width;
|
|
2427
3693
|
const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
|
|
@@ -2438,7 +3704,7 @@ function useViewBox(options) {
|
|
|
2438
3704
|
};
|
|
2439
3705
|
});
|
|
2440
3706
|
}, [initialViewBox, maxZoom]);
|
|
2441
|
-
const fitToContent = (0,
|
|
3707
|
+
const fitToContent = (0, import_react9.useCallback)((bounds, padding = 50) => {
|
|
2442
3708
|
const contentWidth = bounds.maxX - bounds.minX;
|
|
2443
3709
|
const contentHeight = bounds.maxY - bounds.minY;
|
|
2444
3710
|
if (contentWidth === 0 || contentHeight === 0) {
|
|
@@ -2466,7 +3732,7 @@ function useViewBox(options) {
|
|
|
2466
3732
|
height: newHeight
|
|
2467
3733
|
});
|
|
2468
3734
|
}, [initialViewBox]);
|
|
2469
|
-
(0,
|
|
3735
|
+
(0, import_react9.useEffect)(() => {
|
|
2470
3736
|
if (!enableZoom || !svgRef.current) return;
|
|
2471
3737
|
const svg = svgRef.current;
|
|
2472
3738
|
const handleWheel = (e) => {
|
|
@@ -2499,7 +3765,7 @@ function useViewBox(options) {
|
|
|
2499
3765
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
2500
3766
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
2501
3767
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
2502
|
-
(0,
|
|
3768
|
+
(0, import_react9.useEffect)(() => {
|
|
2503
3769
|
if (!enablePan || !svgRef.current) return;
|
|
2504
3770
|
const svg = svgRef.current;
|
|
2505
3771
|
const handleMouseDown = (e) => {
|
|
@@ -2575,7 +3841,7 @@ function useViewBox(options) {
|
|
|
2575
3841
|
window.removeEventListener("keyup", handleKeyUp);
|
|
2576
3842
|
};
|
|
2577
3843
|
}, [enablePan, allowLeftClickPan]);
|
|
2578
|
-
(0,
|
|
3844
|
+
(0, import_react9.useEffect)(() => {
|
|
2579
3845
|
if (!svgRef.current) return;
|
|
2580
3846
|
if (!enablePan && !enableZoom) return;
|
|
2581
3847
|
const svg = svgRef.current;
|
|
@@ -2666,7 +3932,7 @@ function useViewBox(options) {
|
|
|
2666
3932
|
svg.removeEventListener("touchend", handleTouchEnd);
|
|
2667
3933
|
};
|
|
2668
3934
|
}, [enablePan, enableZoom, minZoom, initialViewBox]);
|
|
2669
|
-
const screenToWorld = (0,
|
|
3935
|
+
const screenToWorld = (0, import_react9.useCallback)(
|
|
2670
3936
|
(screenX, screenY) => {
|
|
2671
3937
|
const svg = svgRef.current;
|
|
2672
3938
|
if (!svg) return { x: screenX, y: screenY };
|
|
@@ -2705,15 +3971,15 @@ function useViewBox(options) {
|
|
|
2705
3971
|
}
|
|
2706
3972
|
|
|
2707
3973
|
// src/diagram/hooks/useSelection.ts
|
|
2708
|
-
var
|
|
3974
|
+
var import_react10 = require("react");
|
|
2709
3975
|
function useSelection(options = {}) {
|
|
2710
3976
|
const {
|
|
2711
3977
|
multiSelect = true,
|
|
2712
3978
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
2713
3979
|
onSelectionChange
|
|
2714
3980
|
} = options;
|
|
2715
|
-
const [selection, setSelection] = (0,
|
|
2716
|
-
const notifyChange = (0,
|
|
3981
|
+
const [selection, setSelection] = (0, import_react10.useState)(initialSelection);
|
|
3982
|
+
const notifyChange = (0, import_react10.useCallback)(
|
|
2717
3983
|
(newSelection) => {
|
|
2718
3984
|
if (onSelectionChange) {
|
|
2719
3985
|
onSelectionChange(newSelection);
|
|
@@ -2721,15 +3987,15 @@ function useSelection(options = {}) {
|
|
|
2721
3987
|
},
|
|
2722
3988
|
[onSelectionChange]
|
|
2723
3989
|
);
|
|
2724
|
-
const isNodeSelected = (0,
|
|
3990
|
+
const isNodeSelected = (0, import_react10.useCallback)(
|
|
2725
3991
|
(nodeId) => selection.selectedNodeIds.has(nodeId),
|
|
2726
3992
|
[selection.selectedNodeIds]
|
|
2727
3993
|
);
|
|
2728
|
-
const isPipeSelected = (0,
|
|
3994
|
+
const isPipeSelected = (0, import_react10.useCallback)(
|
|
2729
3995
|
(pipeId) => selection.selectedPipeIds.has(pipeId),
|
|
2730
3996
|
[selection.selectedPipeIds]
|
|
2731
3997
|
);
|
|
2732
|
-
const selectNode = (0,
|
|
3998
|
+
const selectNode = (0, import_react10.useCallback)(
|
|
2733
3999
|
(nodeId, isMultiSelect = false) => {
|
|
2734
4000
|
setSelection((prev) => {
|
|
2735
4001
|
const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
|
|
@@ -2748,7 +4014,7 @@ function useSelection(options = {}) {
|
|
|
2748
4014
|
},
|
|
2749
4015
|
[multiSelect, notifyChange]
|
|
2750
4016
|
);
|
|
2751
|
-
const selectPipe = (0,
|
|
4017
|
+
const selectPipe = (0, import_react10.useCallback)(
|
|
2752
4018
|
(pipeId, isMultiSelect = false) => {
|
|
2753
4019
|
setSelection((prev) => {
|
|
2754
4020
|
const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
|
|
@@ -2767,7 +4033,7 @@ function useSelection(options = {}) {
|
|
|
2767
4033
|
},
|
|
2768
4034
|
[multiSelect, notifyChange]
|
|
2769
4035
|
);
|
|
2770
|
-
const clearSelection = (0,
|
|
4036
|
+
const clearSelection = (0, import_react10.useCallback)(() => {
|
|
2771
4037
|
const newSelection = {
|
|
2772
4038
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
2773
4039
|
selectedPipeIds: /* @__PURE__ */ new Set()
|
|
@@ -2775,7 +4041,7 @@ function useSelection(options = {}) {
|
|
|
2775
4041
|
setSelection(newSelection);
|
|
2776
4042
|
notifyChange(newSelection);
|
|
2777
4043
|
}, [notifyChange]);
|
|
2778
|
-
const selectNodes = (0,
|
|
4044
|
+
const selectNodes = (0, import_react10.useCallback)(
|
|
2779
4045
|
(nodeIds) => {
|
|
2780
4046
|
const newSelection = {
|
|
2781
4047
|
selectedNodeIds: new Set(nodeIds),
|
|
@@ -2786,7 +4052,7 @@ function useSelection(options = {}) {
|
|
|
2786
4052
|
},
|
|
2787
4053
|
[notifyChange]
|
|
2788
4054
|
);
|
|
2789
|
-
const selectPipes = (0,
|
|
4055
|
+
const selectPipes = (0, import_react10.useCallback)(
|
|
2790
4056
|
(pipeIds) => {
|
|
2791
4057
|
const newSelection = {
|
|
2792
4058
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
@@ -2810,23 +4076,23 @@ function useSelection(options = {}) {
|
|
|
2810
4076
|
}
|
|
2811
4077
|
|
|
2812
4078
|
// src/diagram/hooks/useTelemetry.ts
|
|
2813
|
-
var
|
|
4079
|
+
var import_react11 = require("react");
|
|
2814
4080
|
function useTelemetry(options = {}) {
|
|
2815
4081
|
const {
|
|
2816
4082
|
initialBindings = [],
|
|
2817
4083
|
onTelemetryChange,
|
|
2818
4084
|
refreshInterval = 0
|
|
2819
4085
|
} = options;
|
|
2820
|
-
const [telemetry, setTelemetry] = (0,
|
|
4086
|
+
const [telemetry, setTelemetry] = (0, import_react11.useState)(() => {
|
|
2821
4087
|
const map = /* @__PURE__ */ new Map();
|
|
2822
4088
|
initialBindings.forEach((binding) => {
|
|
2823
4089
|
map.set(binding.nodeId, binding);
|
|
2824
4090
|
});
|
|
2825
4091
|
return map;
|
|
2826
4092
|
});
|
|
2827
|
-
const telemetryRef = (0,
|
|
4093
|
+
const telemetryRef = (0, import_react11.useRef)(telemetry);
|
|
2828
4094
|
telemetryRef.current = telemetry;
|
|
2829
|
-
const notifyChange = (0,
|
|
4095
|
+
const notifyChange = (0, import_react11.useCallback)(
|
|
2830
4096
|
(newTelemetry) => {
|
|
2831
4097
|
if (onTelemetryChange) {
|
|
2832
4098
|
onTelemetryChange(newTelemetry);
|
|
@@ -2834,7 +4100,7 @@ function useTelemetry(options = {}) {
|
|
|
2834
4100
|
},
|
|
2835
4101
|
[onTelemetryChange]
|
|
2836
4102
|
);
|
|
2837
|
-
const updateTelemetry = (0,
|
|
4103
|
+
const updateTelemetry = (0, import_react11.useCallback)(
|
|
2838
4104
|
(nodeId, value) => {
|
|
2839
4105
|
setTelemetry((prev) => {
|
|
2840
4106
|
const newMap = new Map(prev);
|
|
@@ -2864,7 +4130,7 @@ function useTelemetry(options = {}) {
|
|
|
2864
4130
|
},
|
|
2865
4131
|
[notifyChange]
|
|
2866
4132
|
);
|
|
2867
|
-
const updateTelemetryBatch = (0,
|
|
4133
|
+
const updateTelemetryBatch = (0, import_react11.useCallback)(
|
|
2868
4134
|
(updates) => {
|
|
2869
4135
|
setTelemetry((prev) => {
|
|
2870
4136
|
const newMap = new Map(prev);
|
|
@@ -2918,16 +4184,16 @@ function useTelemetry(options = {}) {
|
|
|
2918
4184
|
},
|
|
2919
4185
|
[notifyChange]
|
|
2920
4186
|
);
|
|
2921
|
-
const getTelemetry = (0,
|
|
4187
|
+
const getTelemetry = (0, import_react11.useCallback)(
|
|
2922
4188
|
(nodeId) => telemetryRef.current.get(nodeId),
|
|
2923
4189
|
[]
|
|
2924
4190
|
);
|
|
2925
|
-
const clearTelemetry = (0,
|
|
4191
|
+
const clearTelemetry = (0, import_react11.useCallback)(() => {
|
|
2926
4192
|
const newMap = /* @__PURE__ */ new Map();
|
|
2927
4193
|
setTelemetry(newMap);
|
|
2928
4194
|
notifyChange(newMap);
|
|
2929
4195
|
}, [notifyChange]);
|
|
2930
|
-
const setBindings = (0,
|
|
4196
|
+
const setBindings = (0, import_react11.useCallback)(
|
|
2931
4197
|
(bindings) => {
|
|
2932
4198
|
const newMap = /* @__PURE__ */ new Map();
|
|
2933
4199
|
bindings.forEach((binding) => {
|
|
@@ -2938,7 +4204,7 @@ function useTelemetry(options = {}) {
|
|
|
2938
4204
|
},
|
|
2939
4205
|
[notifyChange]
|
|
2940
4206
|
);
|
|
2941
|
-
(0,
|
|
4207
|
+
(0, import_react11.useEffect)(() => {
|
|
2942
4208
|
if (refreshInterval <= 0) return;
|
|
2943
4209
|
const intervalId = setInterval(() => {
|
|
2944
4210
|
notifyChange(telemetryRef.current);
|
|
@@ -2955,8 +4221,50 @@ function useTelemetry(options = {}) {
|
|
|
2955
4221
|
};
|
|
2956
4222
|
}
|
|
2957
4223
|
|
|
4224
|
+
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4225
|
+
var import_react12 = require("react");
|
|
4226
|
+
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4227
|
+
const { enabled = true, mapStatus } = options;
|
|
4228
|
+
(0, import_react12.useEffect)(() => {
|
|
4229
|
+
if (!enabled) return;
|
|
4230
|
+
const defaultMapStatus = (telemetryStatus) => {
|
|
4231
|
+
switch (telemetryStatus) {
|
|
4232
|
+
case "normal":
|
|
4233
|
+
return "running";
|
|
4234
|
+
case "warning":
|
|
4235
|
+
return "warning";
|
|
4236
|
+
case "alarm":
|
|
4237
|
+
case "fault":
|
|
4238
|
+
return "alarm";
|
|
4239
|
+
case "off":
|
|
4240
|
+
return "stopped";
|
|
4241
|
+
default:
|
|
4242
|
+
return "stopped";
|
|
4243
|
+
}
|
|
4244
|
+
};
|
|
4245
|
+
const statusMapper = mapStatus || defaultMapStatus;
|
|
4246
|
+
let needsUpdate = false;
|
|
4247
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
4248
|
+
const binding = telemetry.get(node.id);
|
|
4249
|
+
if (!binding) return node;
|
|
4250
|
+
const newStatus = statusMapper(binding.value.status);
|
|
4251
|
+
if (node.status !== newStatus) {
|
|
4252
|
+
needsUpdate = true;
|
|
4253
|
+
return { ...node, status: newStatus };
|
|
4254
|
+
}
|
|
4255
|
+
return node;
|
|
4256
|
+
});
|
|
4257
|
+
if (needsUpdate) {
|
|
4258
|
+
setDiagram({
|
|
4259
|
+
...diagram,
|
|
4260
|
+
nodes: updatedNodes
|
|
4261
|
+
});
|
|
4262
|
+
}
|
|
4263
|
+
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
4264
|
+
}
|
|
4265
|
+
|
|
2958
4266
|
// src/diagram/hooks/useDrag.ts
|
|
2959
|
-
var
|
|
4267
|
+
var import_react13 = require("react");
|
|
2960
4268
|
function useDrag(options = {}) {
|
|
2961
4269
|
const {
|
|
2962
4270
|
onDragStart,
|
|
@@ -2966,23 +4274,23 @@ function useDrag(options = {}) {
|
|
|
2966
4274
|
dragThreshold = 3,
|
|
2967
4275
|
screenToWorld = (x, y) => ({ x, y })
|
|
2968
4276
|
} = options;
|
|
2969
|
-
const [dragState, setDragState] = (0,
|
|
4277
|
+
const [dragState, setDragState] = (0, import_react13.useState)({
|
|
2970
4278
|
isDragging: false,
|
|
2971
4279
|
startPosition: null,
|
|
2972
4280
|
offset: { x: 0, y: 0 },
|
|
2973
4281
|
draggedId: null
|
|
2974
4282
|
});
|
|
2975
|
-
const [isListening, setIsListening] = (0,
|
|
2976
|
-
const dragStartRef = (0,
|
|
2977
|
-
const hasMovedRef = (0,
|
|
2978
|
-
const applySnap = (0,
|
|
4283
|
+
const [isListening, setIsListening] = (0, import_react13.useState)(false);
|
|
4284
|
+
const dragStartRef = (0, import_react13.useRef)(null);
|
|
4285
|
+
const hasMovedRef = (0, import_react13.useRef)(false);
|
|
4286
|
+
const applySnap = (0, import_react13.useCallback)(
|
|
2979
4287
|
(value) => {
|
|
2980
4288
|
if (snapToGrid <= 0) return value;
|
|
2981
4289
|
return Math.round(value / snapToGrid) * snapToGrid;
|
|
2982
4290
|
},
|
|
2983
4291
|
[snapToGrid]
|
|
2984
4292
|
);
|
|
2985
|
-
const handleMouseMove = (0,
|
|
4293
|
+
const handleMouseMove = (0, import_react13.useCallback)(
|
|
2986
4294
|
(event) => {
|
|
2987
4295
|
if (!dragStartRef.current) return;
|
|
2988
4296
|
const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
|
|
@@ -3023,7 +4331,7 @@ function useDrag(options = {}) {
|
|
|
3023
4331
|
},
|
|
3024
4332
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
3025
4333
|
);
|
|
3026
|
-
const handleMouseUp = (0,
|
|
4334
|
+
const handleMouseUp = (0, import_react13.useCallback)(
|
|
3027
4335
|
(event) => {
|
|
3028
4336
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
3029
4337
|
dragStartRef.current = null;
|
|
@@ -3060,7 +4368,7 @@ function useDrag(options = {}) {
|
|
|
3060
4368
|
},
|
|
3061
4369
|
[screenToWorld, applySnap, onDragEnd]
|
|
3062
4370
|
);
|
|
3063
|
-
const handleTouchMove = (0,
|
|
4371
|
+
const handleTouchMove = (0, import_react13.useCallback)(
|
|
3064
4372
|
(event) => {
|
|
3065
4373
|
if (!dragStartRef.current || event.touches.length !== 1) return;
|
|
3066
4374
|
const touch = event.touches[0];
|
|
@@ -3103,7 +4411,7 @@ function useDrag(options = {}) {
|
|
|
3103
4411
|
},
|
|
3104
4412
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
3105
4413
|
);
|
|
3106
|
-
const handleTouchEnd = (0,
|
|
4414
|
+
const handleTouchEnd = (0, import_react13.useCallback)(
|
|
3107
4415
|
(event) => {
|
|
3108
4416
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
3109
4417
|
dragStartRef.current = null;
|
|
@@ -3141,7 +4449,7 @@ function useDrag(options = {}) {
|
|
|
3141
4449
|
},
|
|
3142
4450
|
[screenToWorld, applySnap, onDragEnd]
|
|
3143
4451
|
);
|
|
3144
|
-
(0,
|
|
4452
|
+
(0, import_react13.useEffect)(() => {
|
|
3145
4453
|
if (!isListening) return;
|
|
3146
4454
|
document.addEventListener("mousemove", handleMouseMove);
|
|
3147
4455
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -3156,7 +4464,7 @@ function useDrag(options = {}) {
|
|
|
3156
4464
|
document.removeEventListener("touchcancel", handleTouchEnd);
|
|
3157
4465
|
};
|
|
3158
4466
|
}, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
|
|
3159
|
-
const startDrag = (0,
|
|
4467
|
+
const startDrag = (0, import_react13.useCallback)(
|
|
3160
4468
|
(id, event, itemPosition) => {
|
|
3161
4469
|
event.stopPropagation();
|
|
3162
4470
|
let clientX;
|
|
@@ -3186,7 +4494,7 @@ function useDrag(options = {}) {
|
|
|
3186
4494
|
},
|
|
3187
4495
|
[screenToWorld]
|
|
3188
4496
|
);
|
|
3189
|
-
const cancelDrag = (0,
|
|
4497
|
+
const cancelDrag = (0, import_react13.useCallback)(() => {
|
|
3190
4498
|
dragStartRef.current = null;
|
|
3191
4499
|
hasMovedRef.current = false;
|
|
3192
4500
|
setIsListening(false);
|
|
@@ -3197,7 +4505,7 @@ function useDrag(options = {}) {
|
|
|
3197
4505
|
draggedId: null
|
|
3198
4506
|
});
|
|
3199
4507
|
}, []);
|
|
3200
|
-
const isDraggingItem = (0,
|
|
4508
|
+
const isDraggingItem = (0, import_react13.useCallback)(
|
|
3201
4509
|
(id) => dragState.isDragging && dragState.draggedId === id,
|
|
3202
4510
|
[dragState.isDragging, dragState.draggedId]
|
|
3203
4511
|
);
|
|
@@ -3210,7 +4518,7 @@ function useDrag(options = {}) {
|
|
|
3210
4518
|
}
|
|
3211
4519
|
|
|
3212
4520
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
3213
|
-
var
|
|
4521
|
+
var import_react14 = require("react");
|
|
3214
4522
|
function useKeyboardShortcuts(options) {
|
|
3215
4523
|
const {
|
|
3216
4524
|
onDelete,
|
|
@@ -3221,7 +4529,7 @@ function useKeyboardShortcuts(options) {
|
|
|
3221
4529
|
onSelectAll,
|
|
3222
4530
|
enabled = true
|
|
3223
4531
|
} = options;
|
|
3224
|
-
(0,
|
|
4532
|
+
(0, import_react14.useEffect)(() => {
|
|
3225
4533
|
if (!enabled) return;
|
|
3226
4534
|
const handleKeyDown = (event) => {
|
|
3227
4535
|
const target = event.target;
|
|
@@ -3330,7 +4638,7 @@ function nodeHasPort(node, portId) {
|
|
|
3330
4638
|
}
|
|
3331
4639
|
|
|
3332
4640
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3333
|
-
var
|
|
4641
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3334
4642
|
function PIDCanvas({
|
|
3335
4643
|
diagram,
|
|
3336
4644
|
className = "",
|
|
@@ -3357,16 +4665,30 @@ function PIDCanvas({
|
|
|
3357
4665
|
telemetry,
|
|
3358
4666
|
...props
|
|
3359
4667
|
}) {
|
|
3360
|
-
const [localDiagram, setLocalDiagram] = (0,
|
|
3361
|
-
const [dragOverPosition, setDragOverPosition] = (0,
|
|
3362
|
-
const [isConnecting, setIsConnecting] = (0,
|
|
3363
|
-
const [connectionSource, setConnectionSource] = (0,
|
|
3364
|
-
const [connectionSourcePort, setConnectionSourcePort] = (0,
|
|
3365
|
-
const [connectionCursor, setConnectionCursor] = (0,
|
|
3366
|
-
const [hoveredNode, setHoveredNode] = (0,
|
|
3367
|
-
const [hoveredPort, setHoveredPort] = (0,
|
|
3368
|
-
(0,
|
|
3369
|
-
|
|
4668
|
+
const [localDiagram, setLocalDiagram] = (0, import_react15.useState)(diagram);
|
|
4669
|
+
const [dragOverPosition, setDragOverPosition] = (0, import_react15.useState)(null);
|
|
4670
|
+
const [isConnecting, setIsConnecting] = (0, import_react15.useState)(false);
|
|
4671
|
+
const [connectionSource, setConnectionSource] = (0, import_react15.useState)(null);
|
|
4672
|
+
const [connectionSourcePort, setConnectionSourcePort] = (0, import_react15.useState)(null);
|
|
4673
|
+
const [connectionCursor, setConnectionCursor] = (0, import_react15.useState)(null);
|
|
4674
|
+
const [hoveredNode, setHoveredNode] = (0, import_react15.useState)(null);
|
|
4675
|
+
const [hoveredPort, setHoveredPort] = (0, import_react15.useState)(null);
|
|
4676
|
+
const [selectedWaypoint, setSelectedWaypoint] = (0, import_react15.useState)(null);
|
|
4677
|
+
const historyStack = (0, import_react15.useRef)([]);
|
|
4678
|
+
const redoStack = (0, import_react15.useRef)([]);
|
|
4679
|
+
const isUndoRedoAction = (0, import_react15.useRef)(false);
|
|
4680
|
+
const isInternalChange = (0, import_react15.useRef)(false);
|
|
4681
|
+
const lastInternalDiagram = (0, import_react15.useRef)(null);
|
|
4682
|
+
(0, import_react15.useEffect)(() => {
|
|
4683
|
+
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4684
|
+
if (isExternal) {
|
|
4685
|
+
setLocalDiagram(diagram);
|
|
4686
|
+
if (!isUndoRedoAction.current) {
|
|
4687
|
+
historyStack.current = [];
|
|
4688
|
+
redoStack.current = [];
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
isInternalChange.current = false;
|
|
3370
4692
|
}, [diagram]);
|
|
3371
4693
|
const {
|
|
3372
4694
|
viewBox: controlledViewBox,
|
|
@@ -3379,7 +4701,7 @@ function PIDCanvas({
|
|
|
3379
4701
|
enablePan: features.pan ?? true,
|
|
3380
4702
|
enableZoom: features.zoom ?? true
|
|
3381
4703
|
});
|
|
3382
|
-
const calculateContentBounds = (0,
|
|
4704
|
+
const calculateContentBounds = (0, import_react15.useCallback)(() => {
|
|
3383
4705
|
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
3384
4706
|
if (nodes2.length === 0) {
|
|
3385
4707
|
return null;
|
|
@@ -3402,7 +4724,7 @@ function PIDCanvas({
|
|
|
3402
4724
|
});
|
|
3403
4725
|
return { minX, minY, maxX, maxY };
|
|
3404
4726
|
}, [localDiagram.nodes]);
|
|
3405
|
-
(0,
|
|
4727
|
+
(0, import_react15.useEffect)(() => {
|
|
3406
4728
|
if (onMounted) {
|
|
3407
4729
|
const controls = {
|
|
3408
4730
|
fitToContent: (padding = 50) => {
|
|
@@ -3443,7 +4765,187 @@ function PIDCanvas({
|
|
|
3443
4765
|
});
|
|
3444
4766
|
const dragEnabled = features.dragNodes ?? false;
|
|
3445
4767
|
const selectionEnabled = features.selection ?? false;
|
|
3446
|
-
const
|
|
4768
|
+
const containerRef = (0, import_react15.useRef)(null);
|
|
4769
|
+
const pushToHistory = (0, import_react15.useCallback)((currentDiagram) => {
|
|
4770
|
+
if (isUndoRedoAction.current) return;
|
|
4771
|
+
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
4772
|
+
historyStack.current.push(snapshot);
|
|
4773
|
+
if (historyStack.current.length > 15) {
|
|
4774
|
+
historyStack.current.shift();
|
|
4775
|
+
}
|
|
4776
|
+
redoStack.current = [];
|
|
4777
|
+
}, []);
|
|
4778
|
+
const undo = (0, import_react15.useCallback)(() => {
|
|
4779
|
+
if (historyStack.current.length === 0) return;
|
|
4780
|
+
isUndoRedoAction.current = true;
|
|
4781
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4782
|
+
redoStack.current.push(currentSnapshot);
|
|
4783
|
+
const previousState = historyStack.current.pop();
|
|
4784
|
+
isInternalChange.current = true;
|
|
4785
|
+
lastInternalDiagram.current = previousState;
|
|
4786
|
+
setLocalDiagram(previousState);
|
|
4787
|
+
onDiagramChange?.(previousState);
|
|
4788
|
+
setTimeout(() => {
|
|
4789
|
+
isUndoRedoAction.current = false;
|
|
4790
|
+
}, 0);
|
|
4791
|
+
}, [localDiagram, onDiagramChange]);
|
|
4792
|
+
const redo = (0, import_react15.useCallback)(() => {
|
|
4793
|
+
if (redoStack.current.length === 0) return;
|
|
4794
|
+
isUndoRedoAction.current = true;
|
|
4795
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4796
|
+
historyStack.current.push(currentSnapshot);
|
|
4797
|
+
const nextState = redoStack.current.pop();
|
|
4798
|
+
isInternalChange.current = true;
|
|
4799
|
+
lastInternalDiagram.current = nextState;
|
|
4800
|
+
setLocalDiagram(nextState);
|
|
4801
|
+
onDiagramChange?.(nextState);
|
|
4802
|
+
setTimeout(() => {
|
|
4803
|
+
isUndoRedoAction.current = false;
|
|
4804
|
+
}, 0);
|
|
4805
|
+
}, [localDiagram, onDiagramChange]);
|
|
4806
|
+
(0, import_react15.useEffect)(() => {
|
|
4807
|
+
const handleKeyDown = (e) => {
|
|
4808
|
+
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4809
|
+
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
4810
|
+
e.preventDefault();
|
|
4811
|
+
undo();
|
|
4812
|
+
} else if (isCtrlOrCmd && e.key === "z" && e.shiftKey) {
|
|
4813
|
+
e.preventDefault();
|
|
4814
|
+
redo();
|
|
4815
|
+
} else if (isCtrlOrCmd && e.key === "y") {
|
|
4816
|
+
e.preventDefault();
|
|
4817
|
+
redo();
|
|
4818
|
+
}
|
|
4819
|
+
};
|
|
4820
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4821
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4822
|
+
}, [undo, redo]);
|
|
4823
|
+
(0, import_react15.useEffect)(() => {
|
|
4824
|
+
if (!features.dragNodes) return;
|
|
4825
|
+
const handleKeyDown = (e) => {
|
|
4826
|
+
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
4827
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
4828
|
+
return;
|
|
4829
|
+
}
|
|
4830
|
+
const nudgeAmount = e.shiftKey ? 10 : 1;
|
|
4831
|
+
let dx = 0;
|
|
4832
|
+
let dy = 0;
|
|
4833
|
+
switch (e.key) {
|
|
4834
|
+
case "ArrowLeft":
|
|
4835
|
+
dx = -nudgeAmount;
|
|
4836
|
+
e.preventDefault();
|
|
4837
|
+
break;
|
|
4838
|
+
case "ArrowRight":
|
|
4839
|
+
dx = nudgeAmount;
|
|
4840
|
+
e.preventDefault();
|
|
4841
|
+
break;
|
|
4842
|
+
case "ArrowUp":
|
|
4843
|
+
dy = -nudgeAmount;
|
|
4844
|
+
e.preventDefault();
|
|
4845
|
+
break;
|
|
4846
|
+
case "ArrowDown":
|
|
4847
|
+
dy = nudgeAmount;
|
|
4848
|
+
e.preventDefault();
|
|
4849
|
+
break;
|
|
4850
|
+
default:
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4853
|
+
if (selectedWaypoint) {
|
|
4854
|
+
pushToHistory(localDiagram);
|
|
4855
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4856
|
+
if (pipe.id === selectedWaypoint.pipeId) {
|
|
4857
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4858
|
+
(point, idx) => idx === selectedWaypoint.pointIndex ? { x: point.x + dx, y: point.y + dy } : point
|
|
4859
|
+
);
|
|
4860
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4861
|
+
}
|
|
4862
|
+
return pipe;
|
|
4863
|
+
});
|
|
4864
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4865
|
+
isInternalChange.current = true;
|
|
4866
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4867
|
+
setLocalDiagram(updatedDiagram);
|
|
4868
|
+
onDiagramChange?.(updatedDiagram);
|
|
4869
|
+
return;
|
|
4870
|
+
}
|
|
4871
|
+
if (selectionEnabled && selection.selectedNodeIds.size > 0) {
|
|
4872
|
+
pushToHistory(localDiagram);
|
|
4873
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4874
|
+
(node) => selection.selectedNodeIds.has(node.id) ? {
|
|
4875
|
+
...node,
|
|
4876
|
+
transform: {
|
|
4877
|
+
...node.transform,
|
|
4878
|
+
x: node.transform.x + dx,
|
|
4879
|
+
y: node.transform.y + dy
|
|
4880
|
+
}
|
|
4881
|
+
} : node
|
|
4882
|
+
);
|
|
4883
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4884
|
+
isInternalChange.current = true;
|
|
4885
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4886
|
+
setLocalDiagram(updatedDiagram);
|
|
4887
|
+
onDiagramChange?.(updatedDiagram);
|
|
4888
|
+
selection.selectedNodeIds.forEach((nodeId) => {
|
|
4889
|
+
const node = updatedNodes.find((n) => n.id === nodeId);
|
|
4890
|
+
if (node) {
|
|
4891
|
+
onNodeMove?.(nodeId, node.transform.x, node.transform.y);
|
|
4892
|
+
}
|
|
4893
|
+
});
|
|
4894
|
+
}
|
|
4895
|
+
};
|
|
4896
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4897
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4898
|
+
}, [
|
|
4899
|
+
selectionEnabled,
|
|
4900
|
+
features.dragNodes,
|
|
4901
|
+
selection.selectedNodeIds,
|
|
4902
|
+
selectedWaypoint,
|
|
4903
|
+
localDiagram,
|
|
4904
|
+
onDiagramChange,
|
|
4905
|
+
onNodeMove,
|
|
4906
|
+
pushToHistory
|
|
4907
|
+
]);
|
|
4908
|
+
const handlePositionChange = (0, import_react15.useCallback)(
|
|
4909
|
+
(nodeId, x, y) => {
|
|
4910
|
+
pushToHistory(localDiagram);
|
|
4911
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4912
|
+
(node) => node.id === nodeId ? {
|
|
4913
|
+
...node,
|
|
4914
|
+
transform: {
|
|
4915
|
+
...node.transform,
|
|
4916
|
+
x,
|
|
4917
|
+
y
|
|
4918
|
+
}
|
|
4919
|
+
} : node
|
|
4920
|
+
);
|
|
4921
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4922
|
+
isInternalChange.current = true;
|
|
4923
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4924
|
+
setLocalDiagram(updatedDiagram);
|
|
4925
|
+
onDiagramChange?.(updatedDiagram);
|
|
4926
|
+
onNodeMove?.(nodeId, x, y);
|
|
4927
|
+
},
|
|
4928
|
+
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
4929
|
+
);
|
|
4930
|
+
const handleWaypointPositionChange = (0, import_react15.useCallback)(
|
|
4931
|
+
(pipeId, pointIndex, x, y) => {
|
|
4932
|
+
pushToHistory(localDiagram);
|
|
4933
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4934
|
+
if (pipe.id === pipeId) {
|
|
4935
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4936
|
+
(point, idx) => idx === pointIndex ? { x, y } : point
|
|
4937
|
+
);
|
|
4938
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4939
|
+
}
|
|
4940
|
+
return pipe;
|
|
4941
|
+
});
|
|
4942
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4943
|
+
setLocalDiagram(updatedDiagram);
|
|
4944
|
+
onDiagramChange?.(updatedDiagram);
|
|
4945
|
+
},
|
|
4946
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
4947
|
+
);
|
|
4948
|
+
const handleDragEnd = (0, import_react15.useCallback)(
|
|
3447
4949
|
(nodeId, offset, finalPosition) => {
|
|
3448
4950
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
3449
4951
|
if (dragDistance < 2) {
|
|
@@ -3452,6 +4954,7 @@ function PIDCanvas({
|
|
|
3452
4954
|
}
|
|
3453
4955
|
return;
|
|
3454
4956
|
}
|
|
4957
|
+
pushToHistory(localDiagram);
|
|
3455
4958
|
const updatedNodes = localDiagram.nodes.map(
|
|
3456
4959
|
(node) => node.id === nodeId ? {
|
|
3457
4960
|
...node,
|
|
@@ -3489,11 +4992,13 @@ function PIDCanvas({
|
|
|
3489
4992
|
nodes: updatedNodes,
|
|
3490
4993
|
pipes: updatedPipes
|
|
3491
4994
|
};
|
|
4995
|
+
isInternalChange.current = true;
|
|
4996
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3492
4997
|
setLocalDiagram(updatedDiagram);
|
|
3493
4998
|
onDiagramChange?.(updatedDiagram);
|
|
3494
4999
|
onNodeMove?.(nodeId, finalPosition.x, finalPosition.y);
|
|
3495
5000
|
},
|
|
3496
|
-
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode]
|
|
5001
|
+
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode, pushToHistory]
|
|
3497
5002
|
);
|
|
3498
5003
|
const { dragState, startDrag } = useDrag({
|
|
3499
5004
|
snapToGrid: features.snapToGrid ?? 0,
|
|
@@ -3504,6 +5009,7 @@ function PIDCanvas({
|
|
|
3504
5009
|
snapToGrid: features.snapToGrid ?? 0,
|
|
3505
5010
|
screenToWorld,
|
|
3506
5011
|
onDragEnd: (pipeId, _offset, finalPosition) => {
|
|
5012
|
+
pushToHistory(localDiagram);
|
|
3507
5013
|
const [actualPipeId, pointIndex] = pipeId.split(":");
|
|
3508
5014
|
const idx = parseInt(pointIndex, 10);
|
|
3509
5015
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -3514,11 +5020,13 @@ function PIDCanvas({
|
|
|
3514
5020
|
return { ...pipe, routePoints: updatedRoutePoints };
|
|
3515
5021
|
});
|
|
3516
5022
|
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
5023
|
+
isInternalChange.current = true;
|
|
5024
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3517
5025
|
setLocalDiagram(updatedDiagram);
|
|
3518
5026
|
onDiagramChange?.(updatedDiagram);
|
|
3519
5027
|
}
|
|
3520
5028
|
});
|
|
3521
|
-
const handleNodeDragStart = (0,
|
|
5029
|
+
const handleNodeDragStart = (0, import_react15.useCallback)(
|
|
3522
5030
|
(nodeId, event) => {
|
|
3523
5031
|
const node = localDiagram.nodes.find((n) => n.id === nodeId);
|
|
3524
5032
|
if (!node) return;
|
|
@@ -3526,7 +5034,16 @@ function PIDCanvas({
|
|
|
3526
5034
|
},
|
|
3527
5035
|
[localDiagram.nodes, startDrag]
|
|
3528
5036
|
);
|
|
3529
|
-
const
|
|
5037
|
+
const handleWaypointClick = (0, import_react15.useCallback)(
|
|
5038
|
+
(pipeId, pointIndex) => {
|
|
5039
|
+
setSelectedWaypoint({ pipeId, pointIndex });
|
|
5040
|
+
if (selectionEnabled) {
|
|
5041
|
+
clearSelection();
|
|
5042
|
+
}
|
|
5043
|
+
},
|
|
5044
|
+
[selectionEnabled, clearSelection]
|
|
5045
|
+
);
|
|
5046
|
+
const handleWaypointDragStart = (0, import_react15.useCallback)(
|
|
3530
5047
|
(pipeId, pointIndex, event) => {
|
|
3531
5048
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
3532
5049
|
if (!pipe || pointIndex >= pipe.routePoints.length) return;
|
|
@@ -3535,8 +5052,9 @@ function PIDCanvas({
|
|
|
3535
5052
|
},
|
|
3536
5053
|
[localDiagram.pipes, startWaypointDrag]
|
|
3537
5054
|
);
|
|
3538
|
-
const handlePipeSegmentClick = (0,
|
|
5055
|
+
const handlePipeSegmentClick = (0, import_react15.useCallback)(
|
|
3539
5056
|
(pipeId, position, segmentIndex) => {
|
|
5057
|
+
pushToHistory(localDiagram);
|
|
3540
5058
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
3541
5059
|
if (pipe.id !== pipeId) return pipe;
|
|
3542
5060
|
const updatedRoutePoints = [
|
|
@@ -3550,13 +5068,14 @@ function PIDCanvas({
|
|
|
3550
5068
|
setLocalDiagram(updatedDiagram);
|
|
3551
5069
|
onDiagramChange?.(updatedDiagram);
|
|
3552
5070
|
},
|
|
3553
|
-
[localDiagram, onDiagramChange]
|
|
5071
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
3554
5072
|
);
|
|
3555
5073
|
const telemetryEnabled = features.telemetry ?? false;
|
|
3556
|
-
const handleDelete = (0,
|
|
5074
|
+
const handleDelete = (0, import_react15.useCallback)(() => {
|
|
3557
5075
|
if (!selectionEnabled) return;
|
|
3558
5076
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3559
5077
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
5078
|
+
pushToHistory(localDiagram);
|
|
3560
5079
|
const updatedNodes = localDiagram.nodes.filter((node) => !selectedNodeIds.has(node.id));
|
|
3561
5080
|
const updatedPipes = localDiagram.pipes.filter(
|
|
3562
5081
|
(pipe) => !selectedPipeIds.has(pipe.id) && !selectedNodeIds.has(pipe.fromNodeId) && !selectedNodeIds.has(pipe.toNodeId)
|
|
@@ -3566,18 +5085,28 @@ function PIDCanvas({
|
|
|
3566
5085
|
nodes: updatedNodes,
|
|
3567
5086
|
pipes: updatedPipes
|
|
3568
5087
|
};
|
|
5088
|
+
isInternalChange.current = true;
|
|
5089
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3569
5090
|
setLocalDiagram(updatedDiagram);
|
|
3570
5091
|
clearSelection();
|
|
3571
5092
|
onDiagramChange?.(updatedDiagram);
|
|
3572
5093
|
onDelete?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3573
|
-
}, [
|
|
3574
|
-
|
|
5094
|
+
}, [
|
|
5095
|
+
selection,
|
|
5096
|
+
localDiagram,
|
|
5097
|
+
selectionEnabled,
|
|
5098
|
+
clearSelection,
|
|
5099
|
+
onDiagramChange,
|
|
5100
|
+
onDelete,
|
|
5101
|
+
pushToHistory
|
|
5102
|
+
]);
|
|
5103
|
+
const handleCopy = (0, import_react15.useCallback)(() => {
|
|
3575
5104
|
if (!selectionEnabled) return;
|
|
3576
5105
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3577
5106
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
3578
5107
|
onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3579
5108
|
}, [selection, selectionEnabled, onItemsCopied]);
|
|
3580
|
-
const handlePaste = (0,
|
|
5109
|
+
const handlePaste = (0, import_react15.useCallback)(() => {
|
|
3581
5110
|
if (!selectionEnabled) return;
|
|
3582
5111
|
onPaste?.();
|
|
3583
5112
|
}, [selectionEnabled, onPaste]);
|
|
@@ -3627,12 +5156,17 @@ function PIDCanvas({
|
|
|
3627
5156
|
}
|
|
3628
5157
|
onPipeClick?.(pipeId);
|
|
3629
5158
|
};
|
|
3630
|
-
const handleCanvasClick = () => {
|
|
5159
|
+
const handleCanvasClick = (e) => {
|
|
5160
|
+
const target = e.target;
|
|
5161
|
+
if (target.closest(".pipe-route-point")) {
|
|
5162
|
+
return;
|
|
5163
|
+
}
|
|
3631
5164
|
if (selectionEnabled) {
|
|
3632
5165
|
clearSelection();
|
|
3633
5166
|
}
|
|
5167
|
+
setSelectedWaypoint(null);
|
|
3634
5168
|
};
|
|
3635
|
-
const handleDragOver = (0,
|
|
5169
|
+
const handleDragOver = (0, import_react15.useCallback)(
|
|
3636
5170
|
(event) => {
|
|
3637
5171
|
if (!features.allowSymbolDrop) return;
|
|
3638
5172
|
event.preventDefault();
|
|
@@ -3641,9 +5175,9 @@ function PIDCanvas({
|
|
|
3641
5175
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3642
5176
|
setDragOverPosition(worldPos);
|
|
3643
5177
|
},
|
|
3644
|
-
[features.allowSymbolDrop, screenToWorld]
|
|
5178
|
+
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
3645
5179
|
);
|
|
3646
|
-
const handleDrop = (0,
|
|
5180
|
+
const handleDrop = (0, import_react15.useCallback)(
|
|
3647
5181
|
(event) => {
|
|
3648
5182
|
if (!features.allowSymbolDrop) return;
|
|
3649
5183
|
event.preventDefault();
|
|
@@ -3654,12 +5188,12 @@ function PIDCanvas({
|
|
|
3654
5188
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3655
5189
|
onSymbolDrop?.(symbolId, worldPos);
|
|
3656
5190
|
},
|
|
3657
|
-
[features.allowSymbolDrop, screenToWorld, onSymbolDrop]
|
|
5191
|
+
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
3658
5192
|
);
|
|
3659
|
-
const handleDragLeave = (0,
|
|
5193
|
+
const handleDragLeave = (0, import_react15.useCallback)(() => {
|
|
3660
5194
|
setDragOverPosition(null);
|
|
3661
5195
|
}, []);
|
|
3662
|
-
const handleMouseMove = (0,
|
|
5196
|
+
const handleMouseMove = (0, import_react15.useCallback)(
|
|
3663
5197
|
(event) => {
|
|
3664
5198
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
3665
5199
|
if (connectionModeEnabled) {
|
|
@@ -3678,7 +5212,7 @@ function PIDCanvas({
|
|
|
3678
5212
|
const distance = Math.sqrt(
|
|
3679
5213
|
(worldPos.x - portPos.x) ** 2 + (worldPos.y - portPos.y) ** 2
|
|
3680
5214
|
);
|
|
3681
|
-
if (distance <
|
|
5215
|
+
if (distance < 15) {
|
|
3682
5216
|
foundPort = port.id;
|
|
3683
5217
|
foundNode = node.id;
|
|
3684
5218
|
break;
|
|
@@ -3695,9 +5229,11 @@ function PIDCanvas({
|
|
|
3695
5229
|
const { name } = diagram;
|
|
3696
5230
|
const viewBox = controlledViewBox;
|
|
3697
5231
|
const displayDiagram = localDiagram;
|
|
3698
|
-
|
|
5232
|
+
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3699
5234
|
"div",
|
|
3700
5235
|
{
|
|
5236
|
+
ref: containerRef,
|
|
3701
5237
|
className: `pid-canvas ${className}`.trim(),
|
|
3702
5238
|
style: {
|
|
3703
5239
|
width: "100%",
|
|
@@ -3708,223 +5244,287 @@ function PIDCanvas({
|
|
|
3708
5244
|
...style
|
|
3709
5245
|
},
|
|
3710
5246
|
...props,
|
|
3711
|
-
children:
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
/* @__PURE__ */ (0,
|
|
3732
|
-
/* @__PURE__ */ (0,
|
|
3733
|
-
|
|
3734
|
-
/* @__PURE__ */ (0,
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
5247
|
+
children: [
|
|
5248
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
5249
|
+
"svg",
|
|
5250
|
+
{
|
|
5251
|
+
ref: svgRef,
|
|
5252
|
+
width: "100%",
|
|
5253
|
+
height: "100%",
|
|
5254
|
+
viewBox: `${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`,
|
|
5255
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
5256
|
+
style: {
|
|
5257
|
+
display: "block"
|
|
5258
|
+
},
|
|
5259
|
+
"aria-label": `P&ID diagram: ${name}`,
|
|
5260
|
+
role: "img",
|
|
5261
|
+
onClick: handleCanvasClick,
|
|
5262
|
+
onMouseMove: handleMouseMove,
|
|
5263
|
+
onDragOver: handleDragOver,
|
|
5264
|
+
onDrop: handleDrop,
|
|
5265
|
+
onDragLeave: handleDragLeave,
|
|
5266
|
+
children: [
|
|
5267
|
+
features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
5268
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("defs", { children: [
|
|
5269
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
5270
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5271
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5272
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5273
|
+
] })
|
|
5274
|
+
] }),
|
|
5275
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5276
|
+
"rect",
|
|
5277
|
+
{
|
|
5278
|
+
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
5279
|
+
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
5280
|
+
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
5281
|
+
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
5282
|
+
fill: "url(#grid-major)"
|
|
5283
|
+
}
|
|
5284
|
+
)
|
|
5285
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3739
5286
|
"rect",
|
|
3740
5287
|
{
|
|
3741
5288
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3742
5289
|
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3743
5290
|
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3744
5291
|
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3745
|
-
fill: "
|
|
5292
|
+
fill: features.backgroundColor ?? "#ffffff"
|
|
3746
5293
|
}
|
|
3747
|
-
)
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
{
|
|
3751
|
-
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3752
|
-
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3753
|
-
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3754
|
-
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3755
|
-
fill: features.backgroundColor ?? "#ffffff"
|
|
3756
|
-
}
|
|
3757
|
-
),
|
|
3758
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3759
|
-
PipeRenderer,
|
|
3760
|
-
{
|
|
3761
|
-
pipes: displayDiagram.pipes,
|
|
3762
|
-
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
3763
|
-
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
3764
|
-
enableWaypointEditing: false,
|
|
3765
|
-
onWaypointDragStart: void 0,
|
|
3766
|
-
editingPipeId: null,
|
|
3767
|
-
draggingWaypointIndex: null,
|
|
3768
|
-
waypointDragOffset: void 0,
|
|
3769
|
-
onPipeSegmentClick: void 0
|
|
3770
|
-
}
|
|
3771
|
-
),
|
|
3772
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3773
|
-
NodeRenderer,
|
|
3774
|
-
{
|
|
3775
|
-
nodes: displayDiagram.nodes,
|
|
3776
|
-
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
3777
|
-
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
3778
|
-
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
3779
|
-
enableDrag: dragEnabled && !isConnecting,
|
|
3780
|
-
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
3781
|
-
draggingNodeId: dragState.draggedId,
|
|
3782
|
-
dragOffset: dragState.offset
|
|
3783
|
-
}
|
|
3784
|
-
),
|
|
3785
|
-
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3786
|
-
PipeRenderer,
|
|
3787
|
-
{
|
|
3788
|
-
pipes: displayDiagram.pipes,
|
|
3789
|
-
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
3790
|
-
onPipeClick: void 0,
|
|
3791
|
-
enableWaypointEditing: true,
|
|
3792
|
-
onWaypointDragStart: handleWaypointDragStart,
|
|
3793
|
-
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
3794
|
-
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
3795
|
-
waypointDragOffset: waypointDragState.offset,
|
|
3796
|
-
onPipeSegmentClick: handlePipeSegmentClick
|
|
3797
|
-
}
|
|
3798
|
-
),
|
|
3799
|
-
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
3800
|
-
const binding = telemetry.get(node.id);
|
|
3801
|
-
if (!binding) return null;
|
|
3802
|
-
const symbol = getSymbolDefinition(node.symbolId);
|
|
3803
|
-
if (!symbol) return null;
|
|
3804
|
-
const overlayY = node.transform.y - symbol.viewBox.height / 2 - 10;
|
|
3805
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3806
|
-
DataOverlay,
|
|
5294
|
+
),
|
|
5295
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5296
|
+
PipeRenderer,
|
|
3807
5297
|
{
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
"circle",
|
|
3818
|
-
{
|
|
3819
|
-
cx: dragOverPosition.x,
|
|
3820
|
-
cy: dragOverPosition.y,
|
|
3821
|
-
r: 20,
|
|
3822
|
-
fill: "#3b82f6",
|
|
3823
|
-
opacity: 0.3,
|
|
3824
|
-
stroke: "#3b82f6",
|
|
3825
|
-
strokeWidth: 2,
|
|
3826
|
-
pointerEvents: "none"
|
|
3827
|
-
}
|
|
3828
|
-
),
|
|
3829
|
-
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
3830
|
-
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
3831
|
-
if (!sourceNode) return null;
|
|
3832
|
-
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
3833
|
-
let lineStartX = sourceNode.transform.x;
|
|
3834
|
-
let lineStartY = sourceNode.transform.y;
|
|
3835
|
-
if (connectionSourcePort && symbol?.ports) {
|
|
3836
|
-
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
3837
|
-
if (port) {
|
|
3838
|
-
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
3839
|
-
if (portPos) {
|
|
3840
|
-
lineStartX = portPos.x;
|
|
3841
|
-
lineStartY = portPos.y;
|
|
3842
|
-
}
|
|
5298
|
+
pipes: displayDiagram.pipes,
|
|
5299
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5300
|
+
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
5301
|
+
enableWaypointEditing: false,
|
|
5302
|
+
onWaypointDragStart: void 0,
|
|
5303
|
+
editingPipeId: null,
|
|
5304
|
+
draggingWaypointIndex: null,
|
|
5305
|
+
waypointDragOffset: void 0,
|
|
5306
|
+
onPipeSegmentClick: void 0
|
|
3843
5307
|
}
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
const symbol = getSymbolDefinition(node.symbolId);
|
|
3885
|
-
if (!symbol?.ports) return null;
|
|
3886
|
-
return symbol.ports.map((port) => {
|
|
3887
|
-
const portPos = getPortWorldPosition(node, port.id);
|
|
3888
|
-
if (!portPos) return null;
|
|
3889
|
-
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
3890
|
-
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
3891
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3892
|
-
"circle",
|
|
5308
|
+
),
|
|
5309
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5310
|
+
NodeRenderer,
|
|
5311
|
+
{
|
|
5312
|
+
nodes: displayDiagram.nodes,
|
|
5313
|
+
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5314
|
+
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5315
|
+
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5316
|
+
enableDrag: dragEnabled && !isConnecting,
|
|
5317
|
+
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
5318
|
+
draggingNodeId: dragState.draggedId,
|
|
5319
|
+
dragOffset: dragState.offset
|
|
5320
|
+
}
|
|
5321
|
+
),
|
|
5322
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5323
|
+
PipeRenderer,
|
|
5324
|
+
{
|
|
5325
|
+
pipes: displayDiagram.pipes,
|
|
5326
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5327
|
+
onPipeClick: void 0,
|
|
5328
|
+
enableWaypointEditing: true,
|
|
5329
|
+
onWaypointClick: handleWaypointClick,
|
|
5330
|
+
onWaypointDragStart: handleWaypointDragStart,
|
|
5331
|
+
selectedWaypointPipeId: selectedWaypoint?.pipeId || null,
|
|
5332
|
+
selectedWaypointIndex: selectedWaypoint?.pointIndex ?? null,
|
|
5333
|
+
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
5334
|
+
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
5335
|
+
waypointDragOffset: waypointDragState.offset,
|
|
5336
|
+
onPipeSegmentClick: handlePipeSegmentClick
|
|
5337
|
+
}
|
|
5338
|
+
),
|
|
5339
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5340
|
+
const binding = telemetry.get(node.id);
|
|
5341
|
+
if (!binding) return null;
|
|
5342
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5343
|
+
if (!symbol) return null;
|
|
5344
|
+
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5345
|
+
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5347
|
+
DataOverlay,
|
|
3893
5348
|
{
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
3900
|
-
opacity: isHovered || isSourcePort ? 1 : 0.6
|
|
5349
|
+
nodeId: node.id,
|
|
5350
|
+
x: overlayX,
|
|
5351
|
+
y: overlayY,
|
|
5352
|
+
telemetry: binding,
|
|
5353
|
+
scale: features.telemetryScale ?? 1
|
|
3901
5354
|
},
|
|
3902
|
-
|
|
5355
|
+
`telemetry-${node.id}`
|
|
3903
5356
|
);
|
|
3904
|
-
})
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
5357
|
+
}) }),
|
|
5358
|
+
dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5359
|
+
"circle",
|
|
5360
|
+
{
|
|
5361
|
+
cx: dragOverPosition.x,
|
|
5362
|
+
cy: dragOverPosition.y,
|
|
5363
|
+
r: 20,
|
|
5364
|
+
fill: "#3b82f6",
|
|
5365
|
+
opacity: 0.3,
|
|
5366
|
+
stroke: "#3b82f6",
|
|
5367
|
+
strokeWidth: 2,
|
|
5368
|
+
pointerEvents: "none"
|
|
5369
|
+
}
|
|
5370
|
+
),
|
|
5371
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5372
|
+
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5373
|
+
if (!sourceNode) return null;
|
|
5374
|
+
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
5375
|
+
let lineStartX = sourceNode.transform.x;
|
|
5376
|
+
let lineStartY = sourceNode.transform.y;
|
|
5377
|
+
if (connectionSourcePort && symbol?.ports) {
|
|
5378
|
+
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
5379
|
+
if (port) {
|
|
5380
|
+
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
5381
|
+
if (portPos) {
|
|
5382
|
+
lineStartX = portPos.x;
|
|
5383
|
+
lineStartY = portPos.y;
|
|
5384
|
+
}
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
5388
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5389
|
+
"circle",
|
|
5390
|
+
{
|
|
5391
|
+
cx: lineStartX,
|
|
5392
|
+
cy: lineStartY,
|
|
5393
|
+
r: 30,
|
|
5394
|
+
fill: "none",
|
|
5395
|
+
stroke: "#10b981",
|
|
5396
|
+
strokeWidth: 3,
|
|
5397
|
+
opacity: 0.6
|
|
5398
|
+
}
|
|
5399
|
+
),
|
|
5400
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5401
|
+
"line",
|
|
5402
|
+
{
|
|
5403
|
+
x1: lineStartX,
|
|
5404
|
+
y1: lineStartY,
|
|
5405
|
+
x2: connectionCursor.x,
|
|
5406
|
+
y2: connectionCursor.y,
|
|
5407
|
+
stroke: "#10b981",
|
|
5408
|
+
strokeWidth: 2,
|
|
5409
|
+
strokeDasharray: "5,5",
|
|
5410
|
+
opacity: 0.8
|
|
5411
|
+
}
|
|
5412
|
+
),
|
|
5413
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5414
|
+
"circle",
|
|
5415
|
+
{
|
|
5416
|
+
cx: connectionCursor.x,
|
|
5417
|
+
cy: connectionCursor.y,
|
|
5418
|
+
r: 8,
|
|
5419
|
+
fill: "#10b981",
|
|
5420
|
+
opacity: 0.6
|
|
5421
|
+
}
|
|
5422
|
+
)
|
|
5423
|
+
] });
|
|
5424
|
+
})() }),
|
|
5425
|
+
features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5426
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5427
|
+
if (!symbol?.ports) return null;
|
|
5428
|
+
return symbol.ports.map((port) => {
|
|
5429
|
+
const portPos = getPortWorldPosition(node, port.id);
|
|
5430
|
+
if (!portPos) return null;
|
|
5431
|
+
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5432
|
+
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { children: [
|
|
5434
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5435
|
+
"circle",
|
|
5436
|
+
{
|
|
5437
|
+
cx: portPos.x,
|
|
5438
|
+
cy: portPos.y,
|
|
5439
|
+
r: 15,
|
|
5440
|
+
fill: "transparent",
|
|
5441
|
+
style: { cursor: "pointer" },
|
|
5442
|
+
pointerEvents: "auto",
|
|
5443
|
+
onClick: (e) => {
|
|
5444
|
+
e.stopPropagation();
|
|
5445
|
+
if (isConnecting && connectionSource) {
|
|
5446
|
+
if (connectionSource !== node.id) {
|
|
5447
|
+
onPipeCreated?.(
|
|
5448
|
+
connectionSource,
|
|
5449
|
+
node.id,
|
|
5450
|
+
connectionSourcePort || void 0,
|
|
5451
|
+
port.id
|
|
5452
|
+
);
|
|
5453
|
+
setIsConnecting(false);
|
|
5454
|
+
setConnectionSource(null);
|
|
5455
|
+
setConnectionSourcePort(null);
|
|
5456
|
+
setConnectionCursor(null);
|
|
5457
|
+
setHoveredPort(null);
|
|
5458
|
+
}
|
|
5459
|
+
} else {
|
|
5460
|
+
setIsConnecting(true);
|
|
5461
|
+
setConnectionSource(node.id);
|
|
5462
|
+
setConnectionSourcePort(port.id);
|
|
5463
|
+
}
|
|
5464
|
+
}
|
|
5465
|
+
}
|
|
5466
|
+
),
|
|
5467
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5468
|
+
"circle",
|
|
5469
|
+
{
|
|
5470
|
+
cx: portPos.x,
|
|
5471
|
+
cy: portPos.y,
|
|
5472
|
+
r: isHovered ? 8 : 5,
|
|
5473
|
+
fill: isSourcePort ? "#10b981" : isHovered ? "#3b82f6" : "#94a3b8",
|
|
5474
|
+
stroke: isSourcePort ? "#059669" : isHovered ? "#2563eb" : "#64748b",
|
|
5475
|
+
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
5476
|
+
opacity: isHovered || isSourcePort ? 1 : 0.6,
|
|
5477
|
+
pointerEvents: "none"
|
|
5478
|
+
}
|
|
5479
|
+
)
|
|
5480
|
+
] }, `${node.id}-${port.id}`);
|
|
5481
|
+
});
|
|
5482
|
+
}) })
|
|
5483
|
+
]
|
|
5484
|
+
}
|
|
5485
|
+
),
|
|
5486
|
+
features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5487
|
+
PositionPanel,
|
|
5488
|
+
{
|
|
5489
|
+
selectedNode,
|
|
5490
|
+
selectedWaypoint: selectedWaypoint ? {
|
|
5491
|
+
pipeId: selectedWaypoint.pipeId,
|
|
5492
|
+
pointIndex: selectedWaypoint.pointIndex,
|
|
5493
|
+
position: localDiagram.pipes.find((p) => p.id === selectedWaypoint.pipeId)?.routePoints[selectedWaypoint.pointIndex] || { x: 0, y: 0 }
|
|
5494
|
+
} : null,
|
|
5495
|
+
onPositionChange: handlePositionChange,
|
|
5496
|
+
onWaypointPositionChange: handleWaypointPositionChange,
|
|
5497
|
+
position: "top-right"
|
|
5498
|
+
}
|
|
5499
|
+
)
|
|
5500
|
+
]
|
|
3909
5501
|
}
|
|
3910
5502
|
);
|
|
3911
5503
|
}
|
|
3912
5504
|
|
|
3913
5505
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
3914
|
-
var
|
|
3915
|
-
var
|
|
5506
|
+
var import_react16 = require("react");
|
|
5507
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3916
5508
|
function SymbolLibrary({
|
|
3917
5509
|
className = "",
|
|
3918
5510
|
onSymbolDragStart,
|
|
3919
5511
|
showCategories = true,
|
|
3920
5512
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
3921
5513
|
}) {
|
|
3922
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
3923
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
5514
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react16.useState)("all");
|
|
5515
|
+
const [searchQuery, setSearchQuery] = (0, import_react16.useState)("");
|
|
3924
5516
|
const symbolIds = getAvailableSymbols();
|
|
3925
5517
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5518
|
+
const categoryMap = {
|
|
5519
|
+
Valves: "valve",
|
|
5520
|
+
Pumps: "pump",
|
|
5521
|
+
Tanks: "vessel",
|
|
5522
|
+
Instruments: "instrument",
|
|
5523
|
+
Displays: "display"
|
|
5524
|
+
};
|
|
3926
5525
|
const filteredSymbols = allSymbols.filter((symbol) => {
|
|
3927
|
-
const
|
|
5526
|
+
const actualCategory = categoryMap[selectedCategory] || selectedCategory;
|
|
5527
|
+
const matchesCategory = selectedCategory === "all" || symbol.category === actualCategory;
|
|
3928
5528
|
const matchesSearch = searchQuery === "" || symbol.name.toLowerCase().includes(searchQuery.toLowerCase()) || symbol.id.toLowerCase().includes(searchQuery.toLowerCase());
|
|
3929
5529
|
return matchesCategory && matchesSearch;
|
|
3930
5530
|
});
|
|
@@ -3933,9 +5533,9 @@ function SymbolLibrary({
|
|
|
3933
5533
|
event.dataTransfer.effectAllowed = "copy";
|
|
3934
5534
|
onSymbolDragStart?.(symbol.id, event);
|
|
3935
5535
|
};
|
|
3936
|
-
return /* @__PURE__ */ (0,
|
|
3937
|
-
/* @__PURE__ */ (0,
|
|
3938
|
-
/* @__PURE__ */ (0,
|
|
5536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
5537
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
5538
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3939
5539
|
"input",
|
|
3940
5540
|
{
|
|
3941
5541
|
type: "text",
|
|
@@ -3945,8 +5545,8 @@ function SymbolLibrary({
|
|
|
3945
5545
|
style: styles.searchInput
|
|
3946
5546
|
}
|
|
3947
5547
|
) }),
|
|
3948
|
-
showCategories && /* @__PURE__ */ (0,
|
|
3949
|
-
/* @__PURE__ */ (0,
|
|
5548
|
+
showCategories && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: styles.categories, children: [
|
|
5549
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3950
5550
|
"button",
|
|
3951
5551
|
{
|
|
3952
5552
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -3957,7 +5557,7 @@ function SymbolLibrary({
|
|
|
3957
5557
|
children: "All"
|
|
3958
5558
|
}
|
|
3959
5559
|
),
|
|
3960
|
-
categories.map((category) => /* @__PURE__ */ (0,
|
|
5560
|
+
categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3961
5561
|
"button",
|
|
3962
5562
|
{
|
|
3963
5563
|
onClick: () => setSelectedCategory(category),
|
|
@@ -3970,7 +5570,7 @@ function SymbolLibrary({
|
|
|
3970
5570
|
category
|
|
3971
5571
|
))
|
|
3972
5572
|
] }),
|
|
3973
|
-
/* @__PURE__ */ (0,
|
|
5573
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3974
5574
|
"div",
|
|
3975
5575
|
{
|
|
3976
5576
|
draggable: true,
|
|
@@ -3978,15 +5578,15 @@ function SymbolLibrary({
|
|
|
3978
5578
|
style: styles.symbolCard,
|
|
3979
5579
|
title: symbol.metadata?.description || symbol.name,
|
|
3980
5580
|
children: [
|
|
3981
|
-
/* @__PURE__ */ (0,
|
|
5581
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3982
5582
|
"svg",
|
|
3983
5583
|
{
|
|
3984
5584
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
3985
5585
|
style: styles.symbolSvg,
|
|
3986
|
-
children: /* @__PURE__ */ (0,
|
|
5586
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
3987
5587
|
}
|
|
3988
5588
|
) }),
|
|
3989
|
-
/* @__PURE__ */ (0,
|
|
5589
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.symbolName, children: symbol.name })
|
|
3990
5590
|
]
|
|
3991
5591
|
},
|
|
3992
5592
|
symbol.id
|
|
@@ -4095,7 +5695,7 @@ var styles = {
|
|
|
4095
5695
|
};
|
|
4096
5696
|
|
|
4097
5697
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
4098
|
-
var
|
|
5698
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4099
5699
|
function NodeConfigPanel({
|
|
4100
5700
|
node,
|
|
4101
5701
|
binding,
|
|
@@ -4114,15 +5714,15 @@ function NodeConfigPanel({
|
|
|
4114
5714
|
padding: "20px",
|
|
4115
5715
|
...style
|
|
4116
5716
|
};
|
|
4117
|
-
return /* @__PURE__ */ (0,
|
|
4118
|
-
/* @__PURE__ */ (0,
|
|
5717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className, style: defaultStyle, children: [
|
|
5718
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
4119
5719
|
"Configure: ",
|
|
4120
5720
|
node.id
|
|
4121
5721
|
] }),
|
|
4122
|
-
/* @__PURE__ */ (0,
|
|
4123
|
-
/* @__PURE__ */ (0,
|
|
4124
|
-
/* @__PURE__ */ (0,
|
|
4125
|
-
/* @__PURE__ */ (0,
|
|
5722
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
5723
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
5724
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
5725
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4126
5726
|
"input",
|
|
4127
5727
|
{
|
|
4128
5728
|
type: "text",
|
|
@@ -4138,10 +5738,10 @@ function NodeConfigPanel({
|
|
|
4138
5738
|
}
|
|
4139
5739
|
}
|
|
4140
5740
|
),
|
|
4141
|
-
/* @__PURE__ */ (0,
|
|
4142
|
-
/* @__PURE__ */ (0,
|
|
4143
|
-
/* @__PURE__ */ (0,
|
|
4144
|
-
/* @__PURE__ */ (0,
|
|
5741
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5742
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5743
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
5744
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4145
5745
|
"input",
|
|
4146
5746
|
{
|
|
4147
5747
|
type: "number",
|
|
@@ -4162,9 +5762,9 @@ function NodeConfigPanel({
|
|
|
4162
5762
|
}
|
|
4163
5763
|
)
|
|
4164
5764
|
] }),
|
|
4165
|
-
/* @__PURE__ */ (0,
|
|
4166
|
-
/* @__PURE__ */ (0,
|
|
4167
|
-
/* @__PURE__ */ (0,
|
|
5765
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5766
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
5767
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4168
5768
|
"input",
|
|
4169
5769
|
{
|
|
4170
5770
|
type: "number",
|
|
@@ -4186,9 +5786,9 @@ function NodeConfigPanel({
|
|
|
4186
5786
|
)
|
|
4187
5787
|
] })
|
|
4188
5788
|
] }),
|
|
4189
|
-
/* @__PURE__ */ (0,
|
|
4190
|
-
/* @__PURE__ */ (0,
|
|
4191
|
-
/* @__PURE__ */ (0,
|
|
5789
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5790
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
5791
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4192
5792
|
"input",
|
|
4193
5793
|
{
|
|
4194
5794
|
type: "number",
|
|
@@ -4208,9 +5808,9 @@ function NodeConfigPanel({
|
|
|
4208
5808
|
}
|
|
4209
5809
|
)
|
|
4210
5810
|
] }),
|
|
4211
|
-
/* @__PURE__ */ (0,
|
|
4212
|
-
/* @__PURE__ */ (0,
|
|
4213
|
-
/* @__PURE__ */ (0,
|
|
5811
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5812
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
5813
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4214
5814
|
"input",
|
|
4215
5815
|
{
|
|
4216
5816
|
type: "number",
|
|
@@ -4235,9 +5835,9 @@ function NodeConfigPanel({
|
|
|
4235
5835
|
)
|
|
4236
5836
|
] })
|
|
4237
5837
|
] }),
|
|
4238
|
-
/* @__PURE__ */ (0,
|
|
4239
|
-
/* @__PURE__ */ (0,
|
|
4240
|
-
!binding ? /* @__PURE__ */ (0,
|
|
5838
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
5839
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
5840
|
+
!binding ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4241
5841
|
"button",
|
|
4242
5842
|
{
|
|
4243
5843
|
onClick: () => {
|
|
@@ -4280,9 +5880,9 @@ function NodeConfigPanel({
|
|
|
4280
5880
|
},
|
|
4281
5881
|
children: "+ Add Telemetry"
|
|
4282
5882
|
}
|
|
4283
|
-
) : /* @__PURE__ */ (0,
|
|
4284
|
-
/* @__PURE__ */ (0,
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
5883
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5884
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
5885
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4286
5886
|
"input",
|
|
4287
5887
|
{
|
|
4288
5888
|
type: "number",
|
|
@@ -4304,8 +5904,8 @@ function NodeConfigPanel({
|
|
|
4304
5904
|
}
|
|
4305
5905
|
}
|
|
4306
5906
|
),
|
|
4307
|
-
/* @__PURE__ */ (0,
|
|
4308
|
-
/* @__PURE__ */ (0,
|
|
5907
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
5908
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4309
5909
|
"input",
|
|
4310
5910
|
{
|
|
4311
5911
|
type: "text",
|
|
@@ -4327,8 +5927,8 @@ function NodeConfigPanel({
|
|
|
4327
5927
|
}
|
|
4328
5928
|
}
|
|
4329
5929
|
),
|
|
4330
|
-
/* @__PURE__ */ (0,
|
|
4331
|
-
/* @__PURE__ */ (0,
|
|
5930
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4332
5932
|
"input",
|
|
4333
5933
|
{
|
|
4334
5934
|
type: "checkbox",
|
|
@@ -4350,8 +5950,8 @@ function NodeConfigPanel({
|
|
|
4350
5950
|
),
|
|
4351
5951
|
"Show Sparkline"
|
|
4352
5952
|
] }),
|
|
4353
|
-
/* @__PURE__ */ (0,
|
|
4354
|
-
/* @__PURE__ */ (0,
|
|
5953
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginTop: "12px" }, children: [
|
|
5954
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4355
5955
|
"label",
|
|
4356
5956
|
{
|
|
4357
5957
|
style: {
|
|
@@ -4363,10 +5963,10 @@ function NodeConfigPanel({
|
|
|
4363
5963
|
children: "Telemetry Position Offset:"
|
|
4364
5964
|
}
|
|
4365
5965
|
),
|
|
4366
|
-
/* @__PURE__ */ (0,
|
|
4367
|
-
/* @__PURE__ */ (0,
|
|
4368
|
-
/* @__PURE__ */ (0,
|
|
4369
|
-
/* @__PURE__ */ (0,
|
|
5966
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5967
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5968
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
5969
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4370
5970
|
"input",
|
|
4371
5971
|
{
|
|
4372
5972
|
type: "number",
|
|
@@ -4393,9 +5993,9 @@ function NodeConfigPanel({
|
|
|
4393
5993
|
}
|
|
4394
5994
|
)
|
|
4395
5995
|
] }),
|
|
4396
|
-
/* @__PURE__ */ (0,
|
|
4397
|
-
/* @__PURE__ */ (0,
|
|
4398
|
-
/* @__PURE__ */ (0,
|
|
5996
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5997
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
5998
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4399
5999
|
"input",
|
|
4400
6000
|
{
|
|
4401
6001
|
type: "number",
|
|
@@ -4423,8 +6023,8 @@ function NodeConfigPanel({
|
|
|
4423
6023
|
)
|
|
4424
6024
|
] })
|
|
4425
6025
|
] }),
|
|
4426
|
-
/* @__PURE__ */ (0,
|
|
4427
|
-
/* @__PURE__ */ (0,
|
|
6026
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginTop: "16px" }, children: [
|
|
6027
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4428
6028
|
"label",
|
|
4429
6029
|
{
|
|
4430
6030
|
style: {
|
|
@@ -4436,10 +6036,10 @@ function NodeConfigPanel({
|
|
|
4436
6036
|
children: "Display Colors:"
|
|
4437
6037
|
}
|
|
4438
6038
|
),
|
|
4439
|
-
/* @__PURE__ */ (0,
|
|
4440
|
-
/* @__PURE__ */ (0,
|
|
4441
|
-
/* @__PURE__ */ (0,
|
|
4442
|
-
/* @__PURE__ */ (0,
|
|
6039
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6040
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
6041
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6042
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4443
6043
|
"input",
|
|
4444
6044
|
{
|
|
4445
6045
|
type: "color",
|
|
@@ -4465,7 +6065,7 @@ function NodeConfigPanel({
|
|
|
4465
6065
|
}
|
|
4466
6066
|
}
|
|
4467
6067
|
),
|
|
4468
|
-
/* @__PURE__ */ (0,
|
|
6068
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4469
6069
|
"input",
|
|
4470
6070
|
{
|
|
4471
6071
|
type: "text",
|
|
@@ -4495,10 +6095,10 @@ function NodeConfigPanel({
|
|
|
4495
6095
|
)
|
|
4496
6096
|
] })
|
|
4497
6097
|
] }),
|
|
4498
|
-
binding.display?.showSparkline && /* @__PURE__ */ (0,
|
|
4499
|
-
/* @__PURE__ */ (0,
|
|
4500
|
-
/* @__PURE__ */ (0,
|
|
4501
|
-
/* @__PURE__ */ (0,
|
|
6098
|
+
binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6099
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
6100
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6101
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4502
6102
|
"input",
|
|
4503
6103
|
{
|
|
4504
6104
|
type: "color",
|
|
@@ -4524,7 +6124,7 @@ function NodeConfigPanel({
|
|
|
4524
6124
|
}
|
|
4525
6125
|
}
|
|
4526
6126
|
),
|
|
4527
|
-
/* @__PURE__ */ (0,
|
|
6127
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4528
6128
|
"input",
|
|
4529
6129
|
{
|
|
4530
6130
|
type: "text",
|
|
@@ -4554,9 +6154,9 @@ function NodeConfigPanel({
|
|
|
4554
6154
|
)
|
|
4555
6155
|
] })
|
|
4556
6156
|
] }),
|
|
4557
|
-
/* @__PURE__ */ (0,
|
|
4558
|
-
/* @__PURE__ */ (0,
|
|
4559
|
-
/* @__PURE__ */ (0,
|
|
6157
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6158
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6159
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4560
6160
|
"input",
|
|
4561
6161
|
{
|
|
4562
6162
|
type: "text",
|
|
@@ -4584,20 +6184,20 @@ function NodeConfigPanel({
|
|
|
4584
6184
|
}
|
|
4585
6185
|
}
|
|
4586
6186
|
),
|
|
4587
|
-
/* @__PURE__ */ (0,
|
|
6187
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
4588
6188
|
] })
|
|
4589
6189
|
] }),
|
|
4590
6190
|
" "
|
|
4591
6191
|
] })
|
|
4592
6192
|
] })
|
|
4593
6193
|
] }),
|
|
4594
|
-
binding && /* @__PURE__ */ (0,
|
|
4595
|
-
/* @__PURE__ */ (0,
|
|
6194
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6195
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
4596
6196
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
4597
6197
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
4598
|
-
return /* @__PURE__ */ (0,
|
|
4599
|
-
/* @__PURE__ */ (0,
|
|
4600
|
-
/* @__PURE__ */ (0,
|
|
6198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6199
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6200
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4601
6201
|
"input",
|
|
4602
6202
|
{
|
|
4603
6203
|
type: "number",
|
|
@@ -4621,8 +6221,8 @@ function NodeConfigPanel({
|
|
|
4621
6221
|
] }, key);
|
|
4622
6222
|
})
|
|
4623
6223
|
] }),
|
|
4624
|
-
binding && /* @__PURE__ */ (0,
|
|
4625
|
-
/* @__PURE__ */ (0,
|
|
6224
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6225
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
4626
6226
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
4627
6227
|
const defaultColors = {
|
|
4628
6228
|
normal: "#10b981",
|
|
@@ -4632,13 +6232,13 @@ function NodeConfigPanel({
|
|
|
4632
6232
|
off: "#6b7280"
|
|
4633
6233
|
};
|
|
4634
6234
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
4635
|
-
return /* @__PURE__ */ (0,
|
|
4636
|
-
/* @__PURE__ */ (0,
|
|
6235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6236
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
4637
6237
|
label,
|
|
4638
6238
|
":"
|
|
4639
6239
|
] }),
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4641
|
-
/* @__PURE__ */ (0,
|
|
6240
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6241
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4642
6242
|
"input",
|
|
4643
6243
|
{
|
|
4644
6244
|
type: "color",
|
|
@@ -4659,7 +6259,7 @@ function NodeConfigPanel({
|
|
|
4659
6259
|
}
|
|
4660
6260
|
}
|
|
4661
6261
|
),
|
|
4662
|
-
/* @__PURE__ */ (0,
|
|
6262
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4663
6263
|
"input",
|
|
4664
6264
|
{
|
|
4665
6265
|
type: "text",
|
|
@@ -4686,7 +6286,7 @@ function NodeConfigPanel({
|
|
|
4686
6286
|
] }, status);
|
|
4687
6287
|
})
|
|
4688
6288
|
] }),
|
|
4689
|
-
/* @__PURE__ */ (0,
|
|
6289
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4690
6290
|
"button",
|
|
4691
6291
|
{
|
|
4692
6292
|
onClick: onRemove,
|
|
@@ -4926,7 +6526,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
4926
6526
|
};
|
|
4927
6527
|
|
|
4928
6528
|
// src/diagram/hooks/useSimulation.ts
|
|
4929
|
-
var
|
|
6529
|
+
var import_react17 = require("react");
|
|
4930
6530
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
4931
6531
|
const {
|
|
4932
6532
|
interval = 2e3,
|
|
@@ -4937,7 +6537,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
4937
6537
|
historyLength = 10,
|
|
4938
6538
|
generateValue
|
|
4939
6539
|
} = options;
|
|
4940
|
-
(0,
|
|
6540
|
+
(0, import_react17.useEffect)(() => {
|
|
4941
6541
|
if (!enabled) return;
|
|
4942
6542
|
const intervalId = setInterval(() => {
|
|
4943
6543
|
const updates = [];
|
|
@@ -5035,11 +6635,14 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
5035
6635
|
mockSymbolLibrary,
|
|
5036
6636
|
nodeHasPort,
|
|
5037
6637
|
overlayStyles,
|
|
6638
|
+
registerSymbol,
|
|
6639
|
+
registerSymbols,
|
|
5038
6640
|
useDrag,
|
|
5039
6641
|
useKeyboardShortcuts,
|
|
5040
6642
|
useSelection,
|
|
5041
6643
|
useSimulation,
|
|
5042
6644
|
useTelemetry,
|
|
6645
|
+
useTelemetryStatus,
|
|
5043
6646
|
useTheme,
|
|
5044
6647
|
useViewBox,
|
|
5045
6648
|
validateDiagram
|