@procaaso/alphinity-ui-components 1.0.4 → 1.0.5
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 +2021 -467
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +1973 -420
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -83,6 +83,7 @@ __export(index_exports, {
|
|
|
83
83
|
useSelection: () => useSelection,
|
|
84
84
|
useSimulation: () => useSimulation,
|
|
85
85
|
useTelemetry: () => useTelemetry,
|
|
86
|
+
useTelemetryStatus: () => useTelemetryStatus,
|
|
86
87
|
useTheme: () => useTheme,
|
|
87
88
|
useViewBox: () => useViewBox,
|
|
88
89
|
validateDiagram: () => validateDiagram
|
|
@@ -1785,35 +1786,10 @@ var ThemeToggle = ({
|
|
|
1785
1786
|
};
|
|
1786
1787
|
|
|
1787
1788
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
1788
|
-
var
|
|
1789
|
+
var import_react15 = require("react");
|
|
1789
1790
|
|
|
1790
1791
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
1791
1792
|
var mockSymbolLibrary = {
|
|
1792
|
-
"valve-ball": {
|
|
1793
|
-
id: "valve-ball",
|
|
1794
|
-
name: "Ball Valve",
|
|
1795
|
-
category: "valve",
|
|
1796
|
-
viewBox: { x: 0, y: 0, width: 50, height: 50 },
|
|
1797
|
-
ports: [
|
|
1798
|
-
{ id: "inlet", x: 0, y: 25, type: "inlet", direction: "in" },
|
|
1799
|
-
{ id: "outlet", x: 50, y: 25, type: "outlet", direction: "out" }
|
|
1800
|
-
],
|
|
1801
|
-
svgContent: `
|
|
1802
|
-
<g>
|
|
1803
|
-
<!-- Valve body -->
|
|
1804
|
-
<rect x="15" y="10" width="20" height="30" fill="#546e7a" stroke="#263238" stroke-width="2" rx="2"/>
|
|
1805
|
-
<!-- Ball indicator -->
|
|
1806
|
-
<circle cx="25" cy="25" r="6" fill="#ffa726" stroke="#e65100" stroke-width="1.5"/>
|
|
1807
|
-
<!-- Inlet/outlet lines -->
|
|
1808
|
-
<line x1="0" y1="25" x2="15" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1809
|
-
<line x1="35" y1="25" x2="50" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1810
|
-
</g>
|
|
1811
|
-
`,
|
|
1812
|
-
metadata: {
|
|
1813
|
-
description: "Ball valve for flow control",
|
|
1814
|
-
tags: ["valve", "control", "shutoff"]
|
|
1815
|
-
}
|
|
1816
|
-
},
|
|
1817
1793
|
"valve-gate": {
|
|
1818
1794
|
id: "valve-gate",
|
|
1819
1795
|
name: "Gate Valve (Powered)",
|
|
@@ -1826,11 +1802,11 @@ var mockSymbolLibrary = {
|
|
|
1826
1802
|
svgContent: `
|
|
1827
1803
|
<g>
|
|
1828
1804
|
<!-- Actuator box -->
|
|
1829
|
-
<rect x="16.74" y="0" width="18.02" height="18.02" fill="#edeeef" stroke="#666666" pointer-events="all"/>
|
|
1805
|
+
<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"/>
|
|
1830
1806
|
<!-- Actuator stem -->
|
|
1831
|
-
<path d="M 25.75 18.02 L 25.75 36.05" fill="none" stroke="#666666" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/>
|
|
1807
|
+
<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"/>
|
|
1832
1808
|
<!-- Valve body (two triangles forming diamond) -->
|
|
1833
|
-
<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="#edeeef" stroke="#666666" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/>
|
|
1809
|
+
<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"/>
|
|
1834
1810
|
</g>
|
|
1835
1811
|
`,
|
|
1836
1812
|
metadata: {
|
|
@@ -1838,84 +1814,1143 @@ var mockSymbolLibrary = {
|
|
|
1838
1814
|
tags: ["valve", "gate", "powered", "actuator"]
|
|
1839
1815
|
}
|
|
1840
1816
|
},
|
|
1841
|
-
"pump-
|
|
1842
|
-
id: "pump-
|
|
1843
|
-
name: "
|
|
1817
|
+
"pump-positive-displacement": {
|
|
1818
|
+
id: "pump-positive-displacement",
|
|
1819
|
+
name: "Positive Displacement Pump",
|
|
1844
1820
|
category: "pump",
|
|
1845
|
-
viewBox: { x: 0, y: 0, width:
|
|
1821
|
+
viewBox: { x: 0, y: 0, width: 56.25, height: 56.25 },
|
|
1846
1822
|
ports: [
|
|
1847
|
-
{ id: "inlet", x:
|
|
1848
|
-
{ id: "outlet", x:
|
|
1823
|
+
{ id: "inlet", x: 0, y: 28.125, type: "inlet", direction: "in" },
|
|
1824
|
+
{ id: "outlet", x: 56.25, y: 28.125, type: "outlet", direction: "out" }
|
|
1825
|
+
],
|
|
1826
|
+
svgContent: `
|
|
1827
|
+
<g transform="scale(0.5625)">
|
|
1828
|
+
<!-- Outer circle -->
|
|
1829
|
+
<ellipse
|
|
1830
|
+
cx="50"
|
|
1831
|
+
cy="50"
|
|
1832
|
+
rx="50"
|
|
1833
|
+
ry="50"
|
|
1834
|
+
fill="var(--symbol-fill, #edeeef)"
|
|
1835
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1836
|
+
stroke-width="1"
|
|
1837
|
+
/>
|
|
1838
|
+
|
|
1839
|
+
<!-- Diagonal line from top to bottom-right -->
|
|
1840
|
+
<path
|
|
1841
|
+
d="M 50 0 L 100 50 L 50 100"
|
|
1842
|
+
fill="none"
|
|
1843
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1844
|
+
stroke-width="1"
|
|
1845
|
+
stroke-miterlimit="10"
|
|
1846
|
+
/>
|
|
1847
|
+
|
|
1848
|
+
<!-- Center square -->
|
|
1849
|
+
<rect
|
|
1850
|
+
x="35"
|
|
1851
|
+
y="35"
|
|
1852
|
+
width="30"
|
|
1853
|
+
height="30"
|
|
1854
|
+
fill="none"
|
|
1855
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1856
|
+
stroke-width="1"
|
|
1857
|
+
/>
|
|
1858
|
+
</g>
|
|
1859
|
+
`,
|
|
1860
|
+
metadata: {
|
|
1861
|
+
description: "Positive displacement pump (ISO standard)",
|
|
1862
|
+
tags: ["pump", "positive-displacement", "iso"]
|
|
1863
|
+
}
|
|
1864
|
+
},
|
|
1865
|
+
"vannefold-bottom": {
|
|
1866
|
+
id: "vannefold-bottom",
|
|
1867
|
+
name: "Vannefold Block (Bottom)",
|
|
1868
|
+
category: "valve",
|
|
1869
|
+
viewBox: { x: -0.5, y: -0.5, width: 88, height: 67.785156 },
|
|
1870
|
+
ports: [
|
|
1871
|
+
{ id: "bottom-inlet", x: 0, y: 25, type: "control", direction: "in" },
|
|
1872
|
+
{ id: "top-outlet", x: 48, y: 65, type: "control", direction: "out" }
|
|
1849
1873
|
],
|
|
1850
1874
|
svgContent: `
|
|
1851
1875
|
<g>
|
|
1852
|
-
<!--
|
|
1853
|
-
<
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1876
|
+
<!-- Bottom inlet pipe -->
|
|
1877
|
+
<path
|
|
1878
|
+
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"
|
|
1879
|
+
fill="none"
|
|
1880
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1881
|
+
stroke-miterlimit="10"
|
|
1882
|
+
/>
|
|
1883
|
+
|
|
1884
|
+
<!-- Top outlet pipe -->
|
|
1885
|
+
<path
|
|
1886
|
+
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"
|
|
1887
|
+
fill="none"
|
|
1888
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1889
|
+
stroke-miterlimit="10"
|
|
1890
|
+
/>
|
|
1891
|
+
|
|
1892
|
+
<!-- Main block outer -->
|
|
1893
|
+
<rect
|
|
1894
|
+
x="7"
|
|
1895
|
+
y="0"
|
|
1896
|
+
width="80"
|
|
1897
|
+
height="59.785156"
|
|
1898
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1899
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1900
|
+
/>
|
|
1901
|
+
|
|
1902
|
+
<!-- Main block inner -->
|
|
1903
|
+
<rect
|
|
1904
|
+
x="9"
|
|
1905
|
+
y="2"
|
|
1906
|
+
width="76"
|
|
1907
|
+
height="55.785156"
|
|
1908
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1909
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1910
|
+
/>
|
|
1911
|
+
|
|
1912
|
+
<!-- Bolt holes -->
|
|
1913
|
+
<ellipse cx="15" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1914
|
+
<ellipse cx="15" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1915
|
+
<ellipse cx="79" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1916
|
+
<ellipse cx="79" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1917
|
+
<ellipse cx="15" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1918
|
+
<ellipse cx="15" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1919
|
+
<ellipse cx="79" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1920
|
+
<ellipse cx="79" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1921
|
+
|
|
1863
1922
|
</g>
|
|
1864
1923
|
`,
|
|
1865
1924
|
metadata: {
|
|
1866
|
-
description: "
|
|
1867
|
-
tags: ["
|
|
1925
|
+
description: "Vannefold heat exchanger block with bottom inlet configuration",
|
|
1926
|
+
tags: ["heat-exchanger", "vannefold", "fold", "bottom"]
|
|
1868
1927
|
}
|
|
1869
1928
|
},
|
|
1870
|
-
"
|
|
1871
|
-
id: "
|
|
1872
|
-
name: "
|
|
1873
|
-
category: "
|
|
1874
|
-
viewBox: { x: 0, y: 0, width:
|
|
1929
|
+
"vannefold-middle": {
|
|
1930
|
+
id: "vannefold-middle",
|
|
1931
|
+
name: "Vannefold Block (Middle)",
|
|
1932
|
+
category: "valve",
|
|
1933
|
+
viewBox: { x: -0.5, y: -0.5, width: 95, height: 53.097656 },
|
|
1875
1934
|
ports: [
|
|
1876
|
-
{ id: "inlet", x:
|
|
1877
|
-
{ id: "outlet", x:
|
|
1935
|
+
{ id: "left-inlet", x: 0, y: 27.3125, type: "control", direction: "in" },
|
|
1936
|
+
{ id: "right-outlet", x: 95, y: 27.3125, type: "control", direction: "out" }
|
|
1878
1937
|
],
|
|
1879
1938
|
svgContent: `
|
|
1880
1939
|
<g>
|
|
1881
|
-
<!--
|
|
1882
|
-
<
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
<!--
|
|
1890
|
-
<
|
|
1940
|
+
<!-- Left inlet pipe -->
|
|
1941
|
+
<path
|
|
1942
|
+
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"
|
|
1943
|
+
fill="none"
|
|
1944
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1945
|
+
stroke-miterlimit="10"
|
|
1946
|
+
/>
|
|
1947
|
+
|
|
1948
|
+
<!-- Main block outer -->
|
|
1949
|
+
<rect
|
|
1950
|
+
x="7"
|
|
1951
|
+
y="0"
|
|
1952
|
+
width="80"
|
|
1953
|
+
height="52.097656"
|
|
1954
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1955
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1956
|
+
/>
|
|
1957
|
+
|
|
1958
|
+
<!-- Main block inner -->
|
|
1959
|
+
<rect
|
|
1960
|
+
x="9"
|
|
1961
|
+
y="0"
|
|
1962
|
+
width="76"
|
|
1963
|
+
height="52.097656"
|
|
1964
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1965
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1966
|
+
/>
|
|
1967
|
+
|
|
1968
|
+
<!-- Bolt holes -->
|
|
1969
|
+
<ellipse cx="15" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1970
|
+
<ellipse cx="15" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1971
|
+
<ellipse cx="79" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1972
|
+
<ellipse cx="79" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1973
|
+
<ellipse cx="15" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1974
|
+
<ellipse cx="15" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1975
|
+
<ellipse cx="79" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1976
|
+
<ellipse cx="79" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1891
1977
|
</g>
|
|
1892
1978
|
`,
|
|
1893
1979
|
metadata: {
|
|
1894
|
-
description: "
|
|
1895
|
-
tags: ["
|
|
1980
|
+
description: "Vannefold heat exchanger block with side inlet configuration",
|
|
1981
|
+
tags: ["heat-exchanger", "vannefold", "fold", "middle"]
|
|
1896
1982
|
}
|
|
1897
1983
|
},
|
|
1898
|
-
"
|
|
1899
|
-
id: "
|
|
1900
|
-
name: "
|
|
1901
|
-
category: "
|
|
1902
|
-
viewBox: { x: 0, y: 0, width:
|
|
1984
|
+
"vannefold-top": {
|
|
1985
|
+
id: "vannefold-top",
|
|
1986
|
+
name: "Vannefold Block (Top)",
|
|
1987
|
+
category: "valve",
|
|
1988
|
+
viewBox: { x: -0.5, y: -0.5, width: 95, height: 60.785156 },
|
|
1989
|
+
ports: [
|
|
1990
|
+
{ id: "bottom-inlet", x: 0, y: 35, type: "control", direction: "in" },
|
|
1991
|
+
{ id: "top-outlet", x: 48, y: 0, type: "control", direction: "out" }
|
|
1992
|
+
],
|
|
1993
|
+
svgContent: `
|
|
1994
|
+
<g>
|
|
1995
|
+
<!-- Bottom inlet pipe -->
|
|
1996
|
+
<path
|
|
1997
|
+
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"
|
|
1998
|
+
fill="none"
|
|
1999
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2000
|
+
stroke-miterlimit="10"
|
|
2001
|
+
/>
|
|
2002
|
+
|
|
2003
|
+
<!-- Main block outer -->
|
|
2004
|
+
<rect
|
|
2005
|
+
x="7"
|
|
2006
|
+
y="0"
|
|
2007
|
+
width="80"
|
|
2008
|
+
height="59.785156"
|
|
2009
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2010
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2011
|
+
/>
|
|
2012
|
+
|
|
2013
|
+
<!-- Main block inner -->
|
|
2014
|
+
<rect
|
|
2015
|
+
x="9"
|
|
2016
|
+
y="2"
|
|
2017
|
+
width="76"
|
|
2018
|
+
height="57.785156"
|
|
2019
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2020
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2021
|
+
/>
|
|
2022
|
+
|
|
2023
|
+
<!-- Bolt holes -->
|
|
2024
|
+
<ellipse cx="15" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2025
|
+
<ellipse cx="15" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2026
|
+
<ellipse cx="79" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2027
|
+
<ellipse cx="79" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2028
|
+
<ellipse cx="15" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2029
|
+
<ellipse cx="15" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2030
|
+
<ellipse cx="79" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2031
|
+
<ellipse cx="79" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2032
|
+
|
|
2033
|
+
</g>
|
|
2034
|
+
`,
|
|
2035
|
+
metadata: {
|
|
2036
|
+
description: "Vannefold heat exchanger block with bottom inlet and top outlet configuration",
|
|
2037
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top"]
|
|
2038
|
+
}
|
|
2039
|
+
},
|
|
2040
|
+
"vannefold-top-top-inlet": {
|
|
2041
|
+
id: "vannefold-top-top-inlet",
|
|
2042
|
+
name: "Vannefold Block (Top, Top Inlet)",
|
|
2043
|
+
category: "valve",
|
|
2044
|
+
viewBox: { x: 0, y: 0, width: 88, height: 67.576004 },
|
|
1903
2045
|
ports: [
|
|
1904
|
-
{ id: "
|
|
2046
|
+
{ id: "top-inlet", x: 47, y: 0, type: "control", direction: "in" },
|
|
2047
|
+
{ id: "bottom-outlet", x: 0, y: 42, type: "control", direction: "out" }
|
|
1905
2048
|
],
|
|
1906
2049
|
svgContent: `
|
|
1907
2050
|
<g>
|
|
1908
|
-
<!--
|
|
1909
|
-
<
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
2051
|
+
<!-- Top inlet pipe flange -->
|
|
2052
|
+
<path
|
|
2053
|
+
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"
|
|
2054
|
+
fill="none"
|
|
2055
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2056
|
+
stroke-miterlimit="10"
|
|
2057
|
+
/>
|
|
2058
|
+
|
|
2059
|
+
<!-- Bottom outlet pipe flange -->
|
|
2060
|
+
<path
|
|
2061
|
+
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"
|
|
2062
|
+
fill="none"
|
|
2063
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2064
|
+
stroke-miterlimit="10"
|
|
2065
|
+
/>
|
|
2066
|
+
|
|
2067
|
+
<!-- Main block outer -->
|
|
2068
|
+
<rect
|
|
2069
|
+
x="7"
|
|
2070
|
+
y="6.7908498"
|
|
2071
|
+
width="80"
|
|
2072
|
+
height="59.785156"
|
|
2073
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2074
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2075
|
+
/>
|
|
2076
|
+
|
|
2077
|
+
<!-- Main block inner -->
|
|
2078
|
+
<rect
|
|
2079
|
+
x="9"
|
|
2080
|
+
y="8.7908498"
|
|
2081
|
+
width="76"
|
|
2082
|
+
height="57.785156"
|
|
2083
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2084
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2085
|
+
/>
|
|
2086
|
+
|
|
2087
|
+
<!-- Bolt holes -->
|
|
2088
|
+
<ellipse cx="15" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2089
|
+
<ellipse cx="15" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2090
|
+
<ellipse cx="15" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2091
|
+
<ellipse cx="15" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2092
|
+
<ellipse cx="79" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2093
|
+
<ellipse cx="79" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2094
|
+
<ellipse cx="79" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2095
|
+
<ellipse cx="79" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2096
|
+
|
|
2097
|
+
</g>
|
|
2098
|
+
`,
|
|
2099
|
+
metadata: {
|
|
2100
|
+
description: "Vannefold heat exchanger block with top inlet and bottom outlet configuration",
|
|
2101
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top", "top-inlet"]
|
|
2102
|
+
}
|
|
2103
|
+
},
|
|
2104
|
+
"vannefold-left": {
|
|
2105
|
+
id: "vannefold-left",
|
|
2106
|
+
name: "Vannefold Block (Left)",
|
|
2107
|
+
category: "valve",
|
|
2108
|
+
viewBox: { x: 0, y: 0, width: 67.785156, height: 88.5 },
|
|
2109
|
+
ports: [
|
|
2110
|
+
{ id: "left-inlet", x: 0, y: 41.5, type: "control", direction: "in" },
|
|
2111
|
+
{ id: "right-outlet", x: 42, y: 87, type: "control", direction: "out" }
|
|
2112
|
+
],
|
|
2113
|
+
svgContent: `
|
|
2114
|
+
<g>
|
|
2115
|
+
<!-- Left inlet pipe flange -->
|
|
2116
|
+
<path
|
|
2117
|
+
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"
|
|
2118
|
+
fill="none"
|
|
2119
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2120
|
+
stroke-miterlimit="10"
|
|
2121
|
+
/>
|
|
2122
|
+
|
|
2123
|
+
<!-- Right outlet pipe flange -->
|
|
2124
|
+
<path
|
|
2125
|
+
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"
|
|
2126
|
+
fill="none"
|
|
2127
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2128
|
+
stroke-miterlimit="10"
|
|
2129
|
+
/>
|
|
2130
|
+
|
|
2131
|
+
<!-- Main block outer -->
|
|
2132
|
+
<rect
|
|
2133
|
+
x="7"
|
|
2134
|
+
y="0.5"
|
|
2135
|
+
width="59.785156"
|
|
2136
|
+
height="80"
|
|
2137
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2138
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2139
|
+
/>
|
|
2140
|
+
|
|
2141
|
+
<!-- Main block inner -->
|
|
2142
|
+
<rect
|
|
2143
|
+
x="9"
|
|
2144
|
+
y="2.5"
|
|
2145
|
+
width="57.785156"
|
|
2146
|
+
height="76"
|
|
2147
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2148
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2149
|
+
/>
|
|
2150
|
+
|
|
2151
|
+
<!-- Bolt holes -->
|
|
2152
|
+
<ellipse cx="15" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2153
|
+
<ellipse cx="15" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2154
|
+
<ellipse cx="62" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2155
|
+
<ellipse cx="62" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2156
|
+
<ellipse cx="15" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2157
|
+
<ellipse cx="15" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2158
|
+
<ellipse cx="62" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2159
|
+
<ellipse cx="62" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2160
|
+
|
|
2161
|
+
`,
|
|
2162
|
+
metadata: {
|
|
2163
|
+
description: "Vannefold heat exchanger block with left inlet and right outlet, vertical orientation",
|
|
2164
|
+
tags: ["heat-exchanger", "vannefold", "fold", "left", "vertical"]
|
|
2165
|
+
}
|
|
2166
|
+
},
|
|
2167
|
+
"vannefold-right": {
|
|
2168
|
+
id: "vannefold-right",
|
|
2169
|
+
name: "Vannefold Block (Right)",
|
|
2170
|
+
category: "valve",
|
|
2171
|
+
viewBox: { x: 0, y: 0, width: 67.785156, height: 88.5 },
|
|
2172
|
+
ports: [
|
|
2173
|
+
{ id: "right-inlet", x: 67.785156, y: 41.5, type: "control", direction: "in" },
|
|
2174
|
+
{ id: "left-outlet", x: 24.785156, y: 87.5, type: "control", direction: "out" }
|
|
2175
|
+
],
|
|
2176
|
+
svgContent: `
|
|
2177
|
+
<g>
|
|
2178
|
+
<!-- Right inlet pipe flange -->
|
|
2179
|
+
<path
|
|
2180
|
+
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"
|
|
2181
|
+
fill="none"
|
|
2182
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2183
|
+
stroke-miterlimit="10"
|
|
2184
|
+
/>
|
|
2185
|
+
|
|
2186
|
+
<!-- Left outlet pipe flange -->
|
|
2187
|
+
<path
|
|
2188
|
+
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"
|
|
2189
|
+
fill="none"
|
|
2190
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2191
|
+
stroke-miterlimit="10"
|
|
2192
|
+
/>
|
|
2193
|
+
|
|
2194
|
+
<!-- Main block outer -->
|
|
2195
|
+
<rect
|
|
2196
|
+
x="0"
|
|
2197
|
+
y="0.5"
|
|
2198
|
+
width="59.785156"
|
|
2199
|
+
height="80"
|
|
2200
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2201
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2202
|
+
/>
|
|
2203
|
+
|
|
2204
|
+
<!-- Main block inner -->
|
|
2205
|
+
<rect
|
|
2206
|
+
x="0"
|
|
2207
|
+
y="2.5"
|
|
2208
|
+
width="57.785156"
|
|
2209
|
+
height="76"
|
|
2210
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2211
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2212
|
+
/>
|
|
2213
|
+
|
|
2214
|
+
<!-- Bolt holes -->
|
|
2215
|
+
<ellipse cx="51.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2216
|
+
<ellipse cx="51.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2217
|
+
<ellipse cx="4.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2218
|
+
<ellipse cx="4.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2219
|
+
<ellipse cx="51.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2220
|
+
<ellipse cx="51.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2221
|
+
<ellipse cx="4.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2222
|
+
<ellipse cx="4.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2223
|
+
|
|
2224
|
+
`,
|
|
2225
|
+
metadata: {
|
|
2226
|
+
description: "Vannefold heat exchanger block with right inlet and left outlet, vertical orientation",
|
|
2227
|
+
tags: ["heat-exchanger", "vannefold", "fold", "right", "vertical"]
|
|
2228
|
+
}
|
|
2229
|
+
},
|
|
2230
|
+
"pixer": {
|
|
2231
|
+
id: "pixer",
|
|
2232
|
+
name: "Pixer",
|
|
2233
|
+
category: "pump",
|
|
2234
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 46.6875 },
|
|
2235
|
+
ports: [
|
|
2236
|
+
{ id: "right-outlet", x: 50.625, y: 30.9375, type: "control", direction: "out" },
|
|
2237
|
+
{ id: "left-outlet", x: 0, y: 30.9375, type: "control", direction: "out" },
|
|
2238
|
+
{ id: "left-inlet", x: 50.625, y: 19.6875, type: "control", direction: "in" },
|
|
2239
|
+
{ id: "right-inlet", x: 0, y: 19.6875, type: "control", direction: "in" },
|
|
2240
|
+
{ id: "top-inlet", x: 25.3125, y: 0, type: "control", direction: "in" }
|
|
2241
|
+
],
|
|
2242
|
+
svgContent: `
|
|
2243
|
+
<g transform="scale(0.196875) translate(-195, -186)">
|
|
2244
|
+
<!-- Top mounting flange -->
|
|
2245
|
+
<rect
|
|
2246
|
+
width="141.313"
|
|
2247
|
+
height="9.872"
|
|
2248
|
+
transform="translate(252.392 185.89)"
|
|
2249
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2250
|
+
stroke-miterlimit="10"
|
|
2251
|
+
stroke-width="1"
|
|
2252
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2253
|
+
/>
|
|
2254
|
+
|
|
2255
|
+
<!-- Motor housing top -->
|
|
2256
|
+
<rect
|
|
2257
|
+
width="106.614"
|
|
2258
|
+
height="2.468"
|
|
2259
|
+
transform="translate(269.742 199.918)"
|
|
2260
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2261
|
+
stroke-miterlimit="10"
|
|
2262
|
+
stroke-width="1"
|
|
2263
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2264
|
+
/>
|
|
2265
|
+
<rect
|
|
2266
|
+
width="106.614"
|
|
2267
|
+
height="5.835"
|
|
2268
|
+
transform="translate(269.742 202.384)"
|
|
2269
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2270
|
+
stroke-miterlimit="10"
|
|
2271
|
+
stroke-width="1"
|
|
2272
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2273
|
+
/>
|
|
2274
|
+
<rect
|
|
2275
|
+
width="106.614"
|
|
2276
|
+
height="2.468"
|
|
2277
|
+
transform="translate(269.742 208.222)"
|
|
2278
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2279
|
+
stroke-miterlimit="10"
|
|
2280
|
+
stroke-width="1"
|
|
2281
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2282
|
+
/>
|
|
2283
|
+
|
|
2284
|
+
<!-- Bottom mounting flange -->
|
|
2285
|
+
<rect
|
|
2286
|
+
width="221.702"
|
|
2287
|
+
height="2.401"
|
|
2288
|
+
transform="translate(212.199 395.587)"
|
|
2289
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2290
|
+
stroke-miterlimit="10"
|
|
2291
|
+
stroke-width="1"
|
|
2292
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2293
|
+
/>
|
|
2294
|
+
<rect
|
|
2295
|
+
width="221.702"
|
|
2296
|
+
height="6.269"
|
|
2297
|
+
transform="translate(212.199 397.988)"
|
|
2298
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2299
|
+
stroke-miterlimit="10"
|
|
2300
|
+
stroke-width="1"
|
|
2301
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2302
|
+
/>
|
|
2303
|
+
<rect
|
|
2304
|
+
width="221.702"
|
|
2305
|
+
height="2.65"
|
|
2306
|
+
transform="translate(212.199 404.257)"
|
|
2307
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2308
|
+
stroke-miterlimit="10"
|
|
2309
|
+
stroke-width="1"
|
|
2310
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2311
|
+
/>
|
|
2312
|
+
|
|
2313
|
+
<!-- Motor housing transition -->
|
|
2314
|
+
<path
|
|
2315
|
+
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"
|
|
2316
|
+
transform="translate(-192.059 -32.959)"
|
|
2317
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2318
|
+
stroke-miterlimit="10"
|
|
2319
|
+
stroke-width="1"
|
|
2320
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2321
|
+
/>
|
|
2322
|
+
|
|
2323
|
+
<!-- Bottom flange -->
|
|
2324
|
+
<rect
|
|
2325
|
+
width="256"
|
|
2326
|
+
height="9.872"
|
|
2327
|
+
transform="translate(195.05 411.066)"
|
|
2328
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2329
|
+
stroke-miterlimit="10"
|
|
2330
|
+
stroke-width="1"
|
|
2331
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2332
|
+
/>
|
|
2333
|
+
<path
|
|
2334
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2335
|
+
transform="translate(0 -737.221)"
|
|
2336
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2337
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2338
|
+
stroke-miterlimit="10"
|
|
2339
|
+
stroke-width="1"
|
|
2340
|
+
/>
|
|
2341
|
+
|
|
2342
|
+
<!-- Vessel top cone -->
|
|
2343
|
+
<path
|
|
2344
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2345
|
+
transform="translate(0 -82.72)"
|
|
2346
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2347
|
+
stroke-miterlimit="10"
|
|
2348
|
+
stroke-width="1"
|
|
2349
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2350
|
+
/>
|
|
2351
|
+
|
|
2352
|
+
<!-- Main vessel body -->
|
|
2353
|
+
<rect
|
|
2354
|
+
width="256"
|
|
2355
|
+
height="59.803"
|
|
2356
|
+
transform="translate(195.05 245.636)"
|
|
2357
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2358
|
+
stroke-miterlimit="10"
|
|
2359
|
+
stroke-width="1"
|
|
2360
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2361
|
+
/>
|
|
2362
|
+
<rect
|
|
2363
|
+
width="256"
|
|
2364
|
+
height="76.892"
|
|
2365
|
+
transform="translate(195.05 308.417)"
|
|
2366
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2367
|
+
stroke-miterlimit="10"
|
|
2368
|
+
stroke-width="1"
|
|
2369
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2370
|
+
/>
|
|
2371
|
+
|
|
2372
|
+
<!-- Vessel bottom transitions -->
|
|
2373
|
+
<path
|
|
2374
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2375
|
+
transform="translate(-0.049 -398.769)"
|
|
2376
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2377
|
+
stroke-miterlimit="10"
|
|
2378
|
+
stroke-width="1"
|
|
2379
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2380
|
+
/>
|
|
2381
|
+
<path
|
|
2382
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2383
|
+
transform="translate(-0.062 -403.731)"
|
|
2384
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2385
|
+
stroke-miterlimit="10"
|
|
2386
|
+
stroke-width="1"
|
|
2387
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2388
|
+
/>
|
|
2389
|
+
<path
|
|
2390
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2391
|
+
transform="translate(0 -665.171)"
|
|
2392
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2393
|
+
stroke-miterlimit="10"
|
|
2394
|
+
stroke-width="1"
|
|
2395
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2396
|
+
/>
|
|
2397
|
+
|
|
2398
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2399
|
+
<ellipse
|
|
2400
|
+
cx="15.454"
|
|
2401
|
+
cy="6.096"
|
|
2402
|
+
rx="15.454"
|
|
2403
|
+
ry="6.096"
|
|
2404
|
+
transform="translate(307.486 228.161)"
|
|
2405
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2406
|
+
stroke-miterlimit="10"
|
|
2407
|
+
stroke-width="1"
|
|
2408
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2409
|
+
/>
|
|
2410
|
+
<ellipse
|
|
2411
|
+
cx="15.454"
|
|
2412
|
+
cy="5.3"
|
|
2413
|
+
rx="15.454"
|
|
2414
|
+
ry="5.3"
|
|
2415
|
+
transform="translate(307.486 229.753)"
|
|
2416
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2417
|
+
stroke-miterlimit="10"
|
|
2418
|
+
stroke-width="1"
|
|
2419
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2420
|
+
/>
|
|
2421
|
+
<ellipse
|
|
2422
|
+
cx="5.174"
|
|
2423
|
+
cy="15.117"
|
|
2424
|
+
rx="5.174"
|
|
2425
|
+
ry="15.117"
|
|
2426
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2427
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2428
|
+
stroke-miterlimit="10"
|
|
2429
|
+
stroke-width="1"
|
|
2430
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2431
|
+
/>
|
|
2432
|
+
<path
|
|
2433
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2434
|
+
transform="translate(-578.512 -147.764)"
|
|
2435
|
+
fill="none"
|
|
2436
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2437
|
+
stroke-miterlimit="10"
|
|
2438
|
+
stroke-width="1"
|
|
2439
|
+
/>
|
|
2440
|
+
<ellipse
|
|
2441
|
+
cx="15.117"
|
|
2442
|
+
cy="5.174"
|
|
2443
|
+
rx="15.117"
|
|
2444
|
+
ry="5.174"
|
|
2445
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2446
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2447
|
+
stroke-miterlimit="10"
|
|
2448
|
+
stroke-width="1"
|
|
2449
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2450
|
+
/>
|
|
2451
|
+
<path
|
|
2452
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2453
|
+
transform="translate(-179.058 -147.764)"
|
|
2454
|
+
fill="none"
|
|
2455
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2456
|
+
stroke-miterlimit="10"
|
|
2457
|
+
stroke-width="1"
|
|
2458
|
+
/>
|
|
2459
|
+
<ellipse
|
|
2460
|
+
cx="1.651"
|
|
2461
|
+
cy="15.082"
|
|
2462
|
+
rx="1.651"
|
|
2463
|
+
ry="15.082"
|
|
2464
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2465
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2466
|
+
stroke-miterlimit="10"
|
|
2467
|
+
stroke-width="1"
|
|
2468
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2469
|
+
/>
|
|
2470
|
+
<path
|
|
2471
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2472
|
+
transform="translate(-710.84 -145.969)"
|
|
2473
|
+
fill="none"
|
|
2474
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2475
|
+
stroke-miterlimit="10"
|
|
2476
|
+
stroke-width="1"
|
|
2477
|
+
/>
|
|
2478
|
+
<ellipse
|
|
2479
|
+
cx="15.082"
|
|
2480
|
+
cy="1.651"
|
|
2481
|
+
rx="15.082"
|
|
2482
|
+
ry="1.651"
|
|
2483
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2484
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2485
|
+
stroke-miterlimit="10"
|
|
2486
|
+
stroke-width="1"
|
|
2487
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2488
|
+
/>
|
|
2489
|
+
<path
|
|
2490
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2491
|
+
transform="translate(-55.932 -145.969)"
|
|
2492
|
+
fill="none"
|
|
2493
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2494
|
+
stroke-miterlimit="10"
|
|
2495
|
+
stroke-width="1"
|
|
2496
|
+
/>
|
|
2497
|
+
</g>
|
|
2498
|
+
`,
|
|
2499
|
+
metadata: {
|
|
2500
|
+
description: "Pixer mixer/agitator vessel with top-mounted drive",
|
|
2501
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank"]
|
|
2502
|
+
}
|
|
2503
|
+
},
|
|
2504
|
+
"pixer-barb": {
|
|
2505
|
+
id: "pixer-barb",
|
|
2506
|
+
name: "Pixer (Hose Barb)",
|
|
2507
|
+
category: "pump",
|
|
2508
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 46.6875 },
|
|
2509
|
+
ports: [
|
|
2510
|
+
{ id: "right-outlet", x: 50.625, y: 30.9375, type: "control", direction: "out" },
|
|
2511
|
+
{ id: "left-outlet", x: 0, y: 30.9375, type: "control", direction: "out" },
|
|
2512
|
+
{ id: "left-inlet", x: 50.625, y: 19.6875, type: "control", direction: "in" },
|
|
2513
|
+
{ id: "right-inlet", x: 0, y: 19.6875, type: "control", direction: "in" },
|
|
2514
|
+
{ id: "top-inlet", x: 25.3125, y: 0, type: "control", direction: "in" }
|
|
2515
|
+
],
|
|
2516
|
+
svgContent: `
|
|
2517
|
+
<g transform="scale(0.196875) translate(-195, -186)">
|
|
2518
|
+
<!-- Hose barb ridges at top -->
|
|
2519
|
+
<rect
|
|
2520
|
+
width="20"
|
|
2521
|
+
height="2"
|
|
2522
|
+
transform="translate(313 173)"
|
|
2523
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2524
|
+
stroke-miterlimit="10"
|
|
2525
|
+
stroke-width="0.5"
|
|
2526
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2527
|
+
/>
|
|
2528
|
+
<rect
|
|
2529
|
+
width="20"
|
|
2530
|
+
height="2"
|
|
2531
|
+
transform="translate(313 177)"
|
|
2532
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2533
|
+
stroke-miterlimit="10"
|
|
2534
|
+
stroke-width="0.5"
|
|
2535
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2536
|
+
/>
|
|
2537
|
+
<rect
|
|
2538
|
+
width="20"
|
|
2539
|
+
height="2"
|
|
2540
|
+
transform="translate(313 181)"
|
|
2541
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2542
|
+
stroke-miterlimit="10"
|
|
2543
|
+
stroke-width="0.5"
|
|
2544
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2545
|
+
/>
|
|
2546
|
+
|
|
2547
|
+
<!-- Taper from barb to motor housing -->
|
|
2548
|
+
<path
|
|
2549
|
+
d="M 313,183 L 269.742,199.918 L 376.356,199.918 L 333,183 Z"
|
|
2550
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2551
|
+
stroke-miterlimit="10"
|
|
2552
|
+
stroke-width="1"
|
|
2553
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2554
|
+
/>
|
|
2555
|
+
|
|
2556
|
+
<!-- Motor housing top -->
|
|
2557
|
+
<rect
|
|
2558
|
+
width="106.614"
|
|
2559
|
+
height="2.468"
|
|
2560
|
+
transform="translate(269.742 199.918)"
|
|
2561
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2562
|
+
stroke-miterlimit="10"
|
|
2563
|
+
stroke-width="1"
|
|
2564
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2565
|
+
/>
|
|
2566
|
+
<rect
|
|
2567
|
+
width="106.614"
|
|
2568
|
+
height="5.835"
|
|
2569
|
+
transform="translate(269.742 202.384)"
|
|
2570
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2571
|
+
stroke-miterlimit="10"
|
|
2572
|
+
stroke-width="1"
|
|
2573
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2574
|
+
/>
|
|
2575
|
+
<rect
|
|
2576
|
+
width="106.614"
|
|
2577
|
+
height="2.468"
|
|
2578
|
+
transform="translate(269.742 208.222)"
|
|
2579
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2580
|
+
stroke-miterlimit="10"
|
|
2581
|
+
stroke-width="1"
|
|
2582
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2583
|
+
/>
|
|
2584
|
+
|
|
2585
|
+
<!-- Bottom mounting flange -->
|
|
2586
|
+
<rect
|
|
2587
|
+
width="221.702"
|
|
2588
|
+
height="2.401"
|
|
2589
|
+
transform="translate(212.199 395.587)"
|
|
2590
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2591
|
+
stroke-miterlimit="10"
|
|
2592
|
+
stroke-width="1"
|
|
2593
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2594
|
+
/>
|
|
2595
|
+
<rect
|
|
2596
|
+
width="221.702"
|
|
2597
|
+
height="6.269"
|
|
2598
|
+
transform="translate(212.199 397.988)"
|
|
2599
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2600
|
+
stroke-miterlimit="10"
|
|
2601
|
+
stroke-width="1"
|
|
2602
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2603
|
+
/>
|
|
2604
|
+
<rect
|
|
2605
|
+
width="221.702"
|
|
2606
|
+
height="2.65"
|
|
2607
|
+
transform="translate(212.199 404.257)"
|
|
2608
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2609
|
+
stroke-miterlimit="10"
|
|
2610
|
+
stroke-width="1"
|
|
2611
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2612
|
+
/>
|
|
2613
|
+
|
|
2614
|
+
<!-- Bottom flange -->
|
|
2615
|
+
<rect
|
|
2616
|
+
width="256"
|
|
2617
|
+
height="9.872"
|
|
2618
|
+
transform="translate(195.05 411.066)"
|
|
2619
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2620
|
+
stroke-miterlimit="10"
|
|
2621
|
+
stroke-width="1"
|
|
2622
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2623
|
+
/>
|
|
2624
|
+
<path
|
|
2625
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2626
|
+
transform="translate(0 -737.221)"
|
|
2627
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2628
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2629
|
+
stroke-miterlimit="10"
|
|
2630
|
+
stroke-width="1"
|
|
2631
|
+
/>
|
|
2632
|
+
|
|
2633
|
+
<!-- Vessel top cone -->
|
|
2634
|
+
<path
|
|
2635
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2636
|
+
transform="translate(0 -82.72)"
|
|
2637
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2638
|
+
stroke-miterlimit="10"
|
|
2639
|
+
stroke-width="1"
|
|
2640
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2641
|
+
/>
|
|
2642
|
+
|
|
2643
|
+
<!-- Main vessel body -->
|
|
2644
|
+
<rect
|
|
2645
|
+
width="256"
|
|
2646
|
+
height="59.803"
|
|
2647
|
+
transform="translate(195.05 245.636)"
|
|
2648
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2649
|
+
stroke-miterlimit="10"
|
|
2650
|
+
stroke-width="1"
|
|
2651
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2652
|
+
/>
|
|
2653
|
+
<rect
|
|
2654
|
+
width="256"
|
|
2655
|
+
height="76.892"
|
|
2656
|
+
transform="translate(195.05 308.417)"
|
|
2657
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2658
|
+
stroke-miterlimit="10"
|
|
2659
|
+
stroke-width="1"
|
|
2660
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2661
|
+
/>
|
|
2662
|
+
|
|
2663
|
+
<!-- Vessel bottom transitions -->
|
|
2664
|
+
<path
|
|
2665
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2666
|
+
transform="translate(-0.049 -398.769)"
|
|
2667
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2668
|
+
stroke-miterlimit="10"
|
|
2669
|
+
stroke-width="1"
|
|
2670
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2671
|
+
/>
|
|
2672
|
+
<path
|
|
2673
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2674
|
+
transform="translate(-0.062 -403.731)"
|
|
2675
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2676
|
+
stroke-miterlimit="10"
|
|
2677
|
+
stroke-width="1"
|
|
2678
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2679
|
+
/>
|
|
2680
|
+
<path
|
|
2681
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2682
|
+
transform="translate(0 -665.171)"
|
|
2683
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2684
|
+
stroke-miterlimit="10"
|
|
2685
|
+
stroke-width="1"
|
|
2686
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2687
|
+
/>
|
|
2688
|
+
|
|
2689
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2690
|
+
<ellipse
|
|
2691
|
+
cx="15.454"
|
|
2692
|
+
cy="6.096"
|
|
2693
|
+
rx="15.454"
|
|
2694
|
+
ry="6.096"
|
|
2695
|
+
transform="translate(307.486 228.161)"
|
|
2696
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2697
|
+
stroke-miterlimit="10"
|
|
2698
|
+
stroke-width="1"
|
|
2699
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2700
|
+
/>
|
|
2701
|
+
<ellipse
|
|
2702
|
+
cx="15.454"
|
|
2703
|
+
cy="5.3"
|
|
2704
|
+
rx="15.454"
|
|
2705
|
+
ry="5.3"
|
|
2706
|
+
transform="translate(307.486 229.753)"
|
|
2707
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2708
|
+
stroke-miterlimit="10"
|
|
2709
|
+
stroke-width="1"
|
|
2710
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2711
|
+
/>
|
|
2712
|
+
<ellipse
|
|
2713
|
+
cx="5.174"
|
|
2714
|
+
cy="15.117"
|
|
2715
|
+
rx="5.174"
|
|
2716
|
+
ry="15.117"
|
|
2717
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2718
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2719
|
+
stroke-miterlimit="10"
|
|
2720
|
+
stroke-width="1"
|
|
2721
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2722
|
+
/>
|
|
2723
|
+
<path
|
|
2724
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2725
|
+
transform="translate(-578.512 -147.764)"
|
|
2726
|
+
fill="none"
|
|
2727
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2728
|
+
stroke-miterlimit="10"
|
|
2729
|
+
stroke-width="1"
|
|
2730
|
+
/>
|
|
2731
|
+
<ellipse
|
|
2732
|
+
cx="15.117"
|
|
2733
|
+
cy="5.174"
|
|
2734
|
+
rx="15.117"
|
|
2735
|
+
ry="5.174"
|
|
2736
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2737
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2738
|
+
stroke-miterlimit="10"
|
|
2739
|
+
stroke-width="1"
|
|
2740
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2741
|
+
/>
|
|
2742
|
+
<path
|
|
2743
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2744
|
+
transform="translate(-179.058 -147.764)"
|
|
2745
|
+
fill="none"
|
|
2746
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2747
|
+
stroke-miterlimit="10"
|
|
2748
|
+
stroke-width="1"
|
|
2749
|
+
/>
|
|
2750
|
+
<ellipse
|
|
2751
|
+
cx="1.651"
|
|
2752
|
+
cy="15.082"
|
|
2753
|
+
rx="1.651"
|
|
2754
|
+
ry="15.082"
|
|
2755
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2756
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2757
|
+
stroke-miterlimit="10"
|
|
2758
|
+
stroke-width="1"
|
|
2759
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2760
|
+
/>
|
|
2761
|
+
<path
|
|
2762
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2763
|
+
transform="translate(-710.84 -145.969)"
|
|
2764
|
+
fill="none"
|
|
2765
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2766
|
+
stroke-miterlimit="10"
|
|
2767
|
+
stroke-width="1"
|
|
2768
|
+
/>
|
|
2769
|
+
<ellipse
|
|
2770
|
+
cx="15.082"
|
|
2771
|
+
cy="1.651"
|
|
2772
|
+
rx="15.082"
|
|
2773
|
+
ry="1.651"
|
|
2774
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2775
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2776
|
+
stroke-miterlimit="10"
|
|
2777
|
+
stroke-width="1"
|
|
2778
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2779
|
+
/>
|
|
2780
|
+
<path
|
|
2781
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2782
|
+
transform="translate(-55.932 -145.969)"
|
|
2783
|
+
fill="none"
|
|
2784
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2785
|
+
stroke-miterlimit="10"
|
|
2786
|
+
stroke-width="1"
|
|
2787
|
+
/>
|
|
2788
|
+
</g>
|
|
2789
|
+
`,
|
|
2790
|
+
metadata: {
|
|
2791
|
+
description: "Pixer mixer/agitator vessel with tapered hose barb connection at top",
|
|
2792
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank", "hose-barb"]
|
|
2793
|
+
}
|
|
2794
|
+
},
|
|
2795
|
+
"vessel-balloon": {
|
|
2796
|
+
id: "vessel-balloon",
|
|
2797
|
+
name: "Vessel",
|
|
2798
|
+
category: "vessel",
|
|
2799
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 91 },
|
|
2800
|
+
ports: [
|
|
2801
|
+
{ id: "top", type: "inlet", x: 25.3125, y: 0 },
|
|
2802
|
+
{ id: "left", type: "inlet", x: 5, y: 39 },
|
|
2803
|
+
{ id: "right", type: "outlet", x: 45.625, y: 39 },
|
|
2804
|
+
{ id: "bottom", type: "outlet", x: 25.3125, y: 91 }
|
|
2805
|
+
],
|
|
2806
|
+
svgContent: `
|
|
2807
|
+
<g transform="scale(0.196875) translate(-195, -100)">
|
|
2808
|
+
<!-- Top opening nozzle -->
|
|
2809
|
+
<rect
|
|
2810
|
+
width="65"
|
|
2811
|
+
height="19.5"
|
|
2812
|
+
transform="translate(290.5, 100)"
|
|
2813
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2814
|
+
stroke-miterlimit="10"
|
|
2815
|
+
stroke-width="1"
|
|
2816
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2817
|
+
/>
|
|
2818
|
+
|
|
2819
|
+
<!-- Transition from nozzle to dome -->
|
|
2820
|
+
<path
|
|
2821
|
+
d="M 290.5,119.5 L 238,152 L 408,152 L 355.5,119.5 Z"
|
|
2822
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2823
|
+
stroke-miterlimit="10"
|
|
2824
|
+
stroke-width="1"
|
|
2825
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2826
|
+
/>
|
|
2827
|
+
|
|
2828
|
+
<!-- Upper balloon dome - rounded bulge -->
|
|
2829
|
+
<path
|
|
2830
|
+
d="M 238,152 C 185,210 150,320 180,395 L 466,395 C 496,320 461,210 408,152 Z"
|
|
2831
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2832
|
+
stroke-miterlimit="10"
|
|
2833
|
+
stroke-width="1"
|
|
2834
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2835
|
+
/>
|
|
2836
|
+
|
|
2837
|
+
<!-- Tapered vessel body -->
|
|
2838
|
+
<path
|
|
2839
|
+
d="M 180,395 L 269.742,530 L 376.356,530 L 466,395 Z"
|
|
2840
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2841
|
+
stroke-miterlimit="10"
|
|
2842
|
+
stroke-width="1"
|
|
2843
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2844
|
+
/>
|
|
2845
|
+
|
|
2846
|
+
<!-- Bottom cone -->
|
|
2847
|
+
<path
|
|
2848
|
+
d="M 269.742,530 L 280,555 L 366,555 L 376.356,530 Z"
|
|
2849
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2850
|
+
stroke-miterlimit="10"
|
|
2851
|
+
stroke-width="1"
|
|
2852
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2853
|
+
/>
|
|
2854
|
+
|
|
2855
|
+
<!-- Bottom flange matching pixer top dimensions -->
|
|
2856
|
+
<rect
|
|
2857
|
+
width="141.313"
|
|
2858
|
+
height="9.872"
|
|
2859
|
+
transform="translate(252.392, 555)"
|
|
2860
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2861
|
+
stroke-miterlimit="10"
|
|
2862
|
+
stroke-width="1"
|
|
2863
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2864
|
+
/>
|
|
2865
|
+
</g>
|
|
2866
|
+
`,
|
|
2867
|
+
metadata: {
|
|
2868
|
+
description: "Balloon-shaped vessel with rounded top and tapered bottom, designed to fit on standard pixer",
|
|
2869
|
+
tags: ["vessel", "storage", "tank", "balloon"]
|
|
2870
|
+
}
|
|
2871
|
+
},
|
|
2872
|
+
"psr-f": {
|
|
2873
|
+
id: "psr-f",
|
|
2874
|
+
name: "PSR F",
|
|
2875
|
+
category: "instrument",
|
|
2876
|
+
viewBox: { x: 0, y: 0, width: 57, height: 57 },
|
|
2877
|
+
ports: [
|
|
2878
|
+
{ id: "top", type: "signal", x: 28.5, y: 14.25 },
|
|
2879
|
+
{ id: "right", type: "signal", x: 42.75, y: 28.5 },
|
|
2880
|
+
{ id: "bottom", type: "signal", x: 28.5, y: 42.75 },
|
|
2881
|
+
{ id: "left", type: "signal", x: 14.25, y: 28.5 }
|
|
2882
|
+
],
|
|
2883
|
+
svgContent: `
|
|
2884
|
+
<g transform="scale(0.5) translate(28.5, 28.5)">
|
|
2885
|
+
<!-- Circle background -->
|
|
2886
|
+
<ellipse
|
|
2887
|
+
cx="28.5"
|
|
2888
|
+
cy="28.5"
|
|
2889
|
+
rx="28.5"
|
|
2890
|
+
ry="28.5"
|
|
2891
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2892
|
+
stroke-width="1"
|
|
2893
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2894
|
+
/>
|
|
2895
|
+
|
|
2896
|
+
<!-- Letter F -->
|
|
2897
|
+
<text
|
|
2898
|
+
x="28.5"
|
|
2899
|
+
y="38"
|
|
2900
|
+
text-anchor="middle"
|
|
2901
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2902
|
+
font-size="34"
|
|
2903
|
+
font-weight="normal"
|
|
2904
|
+
font-style="italic"
|
|
2905
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2906
|
+
>F</text>
|
|
2907
|
+
</g>
|
|
2908
|
+
`,
|
|
2909
|
+
metadata: {
|
|
2910
|
+
description: "PSR F instrument symbol - Flow indicator",
|
|
2911
|
+
tags: ["instrument", "psr", "flow", "indicator"]
|
|
2912
|
+
}
|
|
2913
|
+
},
|
|
2914
|
+
"psr-p": {
|
|
2915
|
+
id: "psr-p",
|
|
2916
|
+
name: "PSR P",
|
|
2917
|
+
category: "instrument",
|
|
2918
|
+
viewBox: { x: 0, y: 0, width: 57, height: 57 },
|
|
2919
|
+
ports: [
|
|
2920
|
+
{ id: "top", type: "signal", x: 28.5, y: 14.25 },
|
|
2921
|
+
{ id: "right", type: "signal", x: 42.75, y: 28.5 },
|
|
2922
|
+
{ id: "bottom", type: "signal", x: 28.5, y: 42.75 },
|
|
2923
|
+
{ id: "left", type: "signal", x: 14.25, y: 28.5 }
|
|
2924
|
+
],
|
|
2925
|
+
svgContent: `
|
|
2926
|
+
<g transform="scale(0.5) translate(28.5, 28.5)">
|
|
2927
|
+
<!-- Circle background -->
|
|
2928
|
+
<ellipse
|
|
2929
|
+
cx="28.5"
|
|
2930
|
+
cy="28.5"
|
|
2931
|
+
rx="28.5"
|
|
2932
|
+
ry="28.5"
|
|
2933
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2934
|
+
stroke-width="1"
|
|
2935
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2936
|
+
/>
|
|
2937
|
+
|
|
2938
|
+
<!-- Letter P -->
|
|
2939
|
+
<text
|
|
2940
|
+
x="28.5"
|
|
2941
|
+
y="38"
|
|
2942
|
+
text-anchor="middle"
|
|
2943
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2944
|
+
font-size="34"
|
|
2945
|
+
font-weight="normal"
|
|
2946
|
+
font-style="italic"
|
|
2947
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2948
|
+
>P</text>
|
|
1914
2949
|
</g>
|
|
1915
2950
|
`,
|
|
1916
2951
|
metadata: {
|
|
1917
|
-
description: "
|
|
1918
|
-
tags: ["instrument", "
|
|
2952
|
+
description: "PSR P instrument symbol - Pressure indicator",
|
|
2953
|
+
tags: ["instrument", "psr", "pressure", "indicator"]
|
|
1919
2954
|
}
|
|
1920
2955
|
}
|
|
1921
2956
|
};
|
|
@@ -1995,6 +3030,24 @@ function NodeRenderer({
|
|
|
1995
3030
|
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
1996
3031
|
);
|
|
1997
3032
|
}
|
|
3033
|
+
const getStatusColor = (status) => {
|
|
3034
|
+
switch (status) {
|
|
3035
|
+
case "running":
|
|
3036
|
+
return "#22c55e";
|
|
3037
|
+
// Green
|
|
3038
|
+
case "alarm":
|
|
3039
|
+
return "#ef4444";
|
|
3040
|
+
// Red
|
|
3041
|
+
case "warning":
|
|
3042
|
+
return "#f59e0b";
|
|
3043
|
+
// Orange
|
|
3044
|
+
case "stopped":
|
|
3045
|
+
default:
|
|
3046
|
+
return "#edeeef";
|
|
3047
|
+
}
|
|
3048
|
+
};
|
|
3049
|
+
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
3050
|
+
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
1998
3051
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1999
3052
|
"g",
|
|
2000
3053
|
{
|
|
@@ -2003,6 +3056,11 @@ function NodeRenderer({
|
|
|
2003
3056
|
"data-selected": isSelected,
|
|
2004
3057
|
"data-dragging": isDragging,
|
|
2005
3058
|
transform: transforms.join(" "),
|
|
3059
|
+
style: {
|
|
3060
|
+
"--symbol-fill": fillColor,
|
|
3061
|
+
"--symbol-stroke": strokeColor,
|
|
3062
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
3063
|
+
},
|
|
2006
3064
|
onClick: (e) => {
|
|
2007
3065
|
e.stopPropagation();
|
|
2008
3066
|
onNodeClick?.(node.id, e);
|
|
@@ -2022,9 +3080,6 @@ function NodeRenderer({
|
|
|
2022
3080
|
onNodeDragStart?.(node.id, e);
|
|
2023
3081
|
}
|
|
2024
3082
|
},
|
|
2025
|
-
style: {
|
|
2026
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
2027
|
-
},
|
|
2028
3083
|
children: [
|
|
2029
3084
|
isSelected && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2030
3085
|
"rect",
|
|
@@ -2077,6 +3132,9 @@ function PipeRenderer({
|
|
|
2077
3132
|
onPipeClick,
|
|
2078
3133
|
enableWaypointEditing = false,
|
|
2079
3134
|
onWaypointDragStart,
|
|
3135
|
+
onWaypointClick,
|
|
3136
|
+
selectedWaypointPipeId,
|
|
3137
|
+
selectedWaypointIndex,
|
|
2080
3138
|
editingPipeId,
|
|
2081
3139
|
draggingWaypointIndex,
|
|
2082
3140
|
waypointDragOffset,
|
|
@@ -2097,7 +3155,7 @@ function PipeRenderer({
|
|
|
2097
3155
|
});
|
|
2098
3156
|
const pointsString = displayPoints.map((point) => `${point.x},${point.y}`).join(" ");
|
|
2099
3157
|
const pipeStyle = pipe.style || {};
|
|
2100
|
-
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#
|
|
3158
|
+
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#94a1b8";
|
|
2101
3159
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
2102
3160
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
2103
3161
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
@@ -2146,10 +3204,11 @@ function PipeRenderer({
|
|
|
2146
3204
|
] }),
|
|
2147
3205
|
displayPoints.map((point, idx) => {
|
|
2148
3206
|
const isEndpoint = idx === 0 || idx === displayPoints.length - 1;
|
|
3207
|
+
const isSelectedWaypoint = selectedWaypointPipeId === pipe.id && selectedWaypointIndex === idx;
|
|
2149
3208
|
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;
|
|
3209
|
+
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3210
|
+
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3211
|
+
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
2153
3212
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2154
3213
|
"circle",
|
|
2155
3214
|
{
|
|
@@ -2165,6 +3224,12 @@ function PipeRenderer({
|
|
|
2165
3224
|
cursor: showEditingControls ? isDragging ? "grabbing" : "grab" : "default"
|
|
2166
3225
|
},
|
|
2167
3226
|
pointerEvents: showEditingControls ? "all" : "none",
|
|
3227
|
+
onClick: (e) => {
|
|
3228
|
+
if (showEditingControls) {
|
|
3229
|
+
e.stopPropagation();
|
|
3230
|
+
onWaypointClick?.(pipe.id, idx);
|
|
3231
|
+
}
|
|
3232
|
+
},
|
|
2168
3233
|
onMouseDown: (e) => {
|
|
2169
3234
|
if (showEditingControls) {
|
|
2170
3235
|
e.stopPropagation();
|
|
@@ -2241,7 +3306,13 @@ function PipeRenderer({
|
|
|
2241
3306
|
|
|
2242
3307
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
2243
3308
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2244
|
-
function DataOverlay({
|
|
3309
|
+
function DataOverlay({
|
|
3310
|
+
nodeId,
|
|
3311
|
+
x,
|
|
3312
|
+
y,
|
|
3313
|
+
telemetry,
|
|
3314
|
+
scale = 1
|
|
3315
|
+
}) {
|
|
2245
3316
|
const { value, display, history } = telemetry;
|
|
2246
3317
|
const showValue = display?.showValue ?? true;
|
|
2247
3318
|
const showStatus = display?.showStatus ?? true;
|
|
@@ -2281,9 +3352,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2281
3352
|
const displayText = value.unit ? `${formattedValue} ${value.unit}` : formattedValue;
|
|
2282
3353
|
const sparklinePath = (() => {
|
|
2283
3354
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
2284
|
-
const width = 70;
|
|
2285
|
-
const height = 20;
|
|
2286
|
-
const padding = 5;
|
|
3355
|
+
const width = 70 * scale;
|
|
3356
|
+
const height = 20 * scale;
|
|
3357
|
+
const padding = 5 * scale;
|
|
2287
3358
|
const effectiveWidth = width - padding * 2;
|
|
2288
3359
|
const effectiveHeight = height - padding * 2;
|
|
2289
3360
|
const min = Math.min(...history);
|
|
@@ -2297,21 +3368,22 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2297
3368
|
return `M ${points.join(" L ")}`;
|
|
2298
3369
|
})();
|
|
2299
3370
|
const hasSparkline = showSparkline && sparklinePath;
|
|
2300
|
-
const overlayHeight = label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22;
|
|
3371
|
+
const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
|
|
3372
|
+
const overlayWidth = 80 * scale;
|
|
2301
3373
|
const displayX = x + offsetX;
|
|
2302
3374
|
const displayY = y + offsetY;
|
|
2303
3375
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
2304
3376
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2305
3377
|
"rect",
|
|
2306
3378
|
{
|
|
2307
|
-
x: displayX -
|
|
2308
|
-
y: displayY - 25,
|
|
2309
|
-
width:
|
|
3379
|
+
x: displayX - overlayWidth / 2,
|
|
3380
|
+
y: displayY - 25 * scale,
|
|
3381
|
+
width: overlayWidth,
|
|
2310
3382
|
height: overlayHeight,
|
|
2311
|
-
rx:
|
|
3383
|
+
rx: 4 * scale,
|
|
2312
3384
|
fill: colors.bg,
|
|
2313
3385
|
stroke: colors.border,
|
|
2314
|
-
strokeWidth:
|
|
3386
|
+
strokeWidth: 1 * scale,
|
|
2315
3387
|
opacity: "0.95",
|
|
2316
3388
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
2317
3389
|
}
|
|
@@ -2320,9 +3392,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2320
3392
|
"text",
|
|
2321
3393
|
{
|
|
2322
3394
|
x: displayX,
|
|
2323
|
-
y: displayY - 15,
|
|
3395
|
+
y: displayY - 15 * scale,
|
|
2324
3396
|
textAnchor: "middle",
|
|
2325
|
-
fontSize:
|
|
3397
|
+
fontSize: 8 * scale,
|
|
2326
3398
|
fontWeight: "600",
|
|
2327
3399
|
fill: finalTextColor,
|
|
2328
3400
|
opacity: "0.9",
|
|
@@ -2333,31 +3405,41 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2333
3405
|
"text",
|
|
2334
3406
|
{
|
|
2335
3407
|
x: displayX,
|
|
2336
|
-
y: label ? displayY - 3 : displayY - 9,
|
|
3408
|
+
y: label ? displayY - 3 * scale : displayY - 9 * scale,
|
|
2337
3409
|
textAnchor: "middle",
|
|
2338
|
-
fontSize:
|
|
3410
|
+
fontSize: 11 * scale,
|
|
2339
3411
|
fontWeight: "700",
|
|
2340
3412
|
fill: finalTextColor,
|
|
2341
3413
|
letterSpacing: "0.02em",
|
|
2342
3414
|
children: displayText
|
|
2343
3415
|
}
|
|
2344
3416
|
),
|
|
2345
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2346
|
-
"
|
|
3417
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3418
|
+
"circle",
|
|
2347
3419
|
{
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
3420
|
+
cx: displayX + 35 * scale,
|
|
3421
|
+
cy: displayY - 18 * scale,
|
|
3422
|
+
r: 3 * scale,
|
|
3423
|
+
fill: finalTextColor,
|
|
3424
|
+
opacity: "0.9",
|
|
3425
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3426
|
+
"animate",
|
|
3427
|
+
{
|
|
3428
|
+
attributeName: "opacity",
|
|
3429
|
+
values: "0.9;0.3;0.9",
|
|
3430
|
+
dur: "1.5s",
|
|
3431
|
+
repeatCount: "indefinite"
|
|
3432
|
+
}
|
|
3433
|
+
)
|
|
2352
3434
|
}
|
|
2353
|
-
)
|
|
3435
|
+
),
|
|
2354
3436
|
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2355
3437
|
"text",
|
|
2356
3438
|
{
|
|
2357
3439
|
x: displayX,
|
|
2358
|
-
y: displayY + 5,
|
|
3440
|
+
y: displayY + 5 * scale,
|
|
2359
3441
|
textAnchor: "middle",
|
|
2360
|
-
fontSize:
|
|
3442
|
+
fontSize: 7 * scale,
|
|
2361
3443
|
fontWeight: "500",
|
|
2362
3444
|
fill: finalTextColor,
|
|
2363
3445
|
opacity: "0.7",
|
|
@@ -2368,13 +3450,13 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2368
3450
|
]
|
|
2369
3451
|
}
|
|
2370
3452
|
),
|
|
2371
|
-
hasSparkline && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { transform: `translate(${displayX - 35}, ${displayY + (label ? 5 : 0)})`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3453
|
+
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
3454
|
"path",
|
|
2373
3455
|
{
|
|
2374
3456
|
d: sparklinePath,
|
|
2375
3457
|
fill: "none",
|
|
2376
3458
|
stroke: sparklineColor || finalTextColor,
|
|
2377
|
-
strokeWidth:
|
|
3459
|
+
strokeWidth: 1.5 * scale,
|
|
2378
3460
|
strokeLinecap: "round",
|
|
2379
3461
|
strokeLinejoin: "round",
|
|
2380
3462
|
opacity: "0.9"
|
|
@@ -2383,8 +3465,145 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2383
3465
|
] });
|
|
2384
3466
|
}
|
|
2385
3467
|
|
|
2386
|
-
// src/
|
|
3468
|
+
// src/components/PIDCanvas/PositionPanel.tsx
|
|
2387
3469
|
var import_react8 = require("react");
|
|
3470
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3471
|
+
function PositionPanel({
|
|
3472
|
+
selectedNode,
|
|
3473
|
+
selectedWaypoint,
|
|
3474
|
+
onPositionChange,
|
|
3475
|
+
onWaypointPositionChange,
|
|
3476
|
+
position = "top-right"
|
|
3477
|
+
}) {
|
|
3478
|
+
const [x, setX] = (0, import_react8.useState)("");
|
|
3479
|
+
const [y, setY] = (0, import_react8.useState)("");
|
|
3480
|
+
(0, import_react8.useEffect)(() => {
|
|
3481
|
+
if (selectedNode) {
|
|
3482
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3483
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3484
|
+
} else if (selectedWaypoint) {
|
|
3485
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3486
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3487
|
+
}
|
|
3488
|
+
}, [selectedNode, selectedWaypoint]);
|
|
3489
|
+
if (!selectedNode && !selectedWaypoint) {
|
|
3490
|
+
return null;
|
|
3491
|
+
}
|
|
3492
|
+
const handleXChange = (value) => {
|
|
3493
|
+
setX(value);
|
|
3494
|
+
const numValue = parseFloat(value);
|
|
3495
|
+
if (!isNaN(numValue)) {
|
|
3496
|
+
if (selectedNode && onPositionChange) {
|
|
3497
|
+
onPositionChange(selectedNode.id, numValue, selectedNode.transform.y);
|
|
3498
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3499
|
+
onWaypointPositionChange(
|
|
3500
|
+
selectedWaypoint.pipeId,
|
|
3501
|
+
selectedWaypoint.pointIndex,
|
|
3502
|
+
numValue,
|
|
3503
|
+
selectedWaypoint.position.y
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
};
|
|
3508
|
+
const handleYChange = (value) => {
|
|
3509
|
+
setY(value);
|
|
3510
|
+
const numValue = parseFloat(value);
|
|
3511
|
+
if (!isNaN(numValue)) {
|
|
3512
|
+
if (selectedNode && onPositionChange) {
|
|
3513
|
+
onPositionChange(selectedNode.id, selectedNode.transform.x, numValue);
|
|
3514
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3515
|
+
onWaypointPositionChange(
|
|
3516
|
+
selectedWaypoint.pipeId,
|
|
3517
|
+
selectedWaypoint.pointIndex,
|
|
3518
|
+
selectedWaypoint.position.x,
|
|
3519
|
+
numValue
|
|
3520
|
+
);
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
};
|
|
3524
|
+
const handleBlur = () => {
|
|
3525
|
+
if (selectedNode) {
|
|
3526
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3527
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3528
|
+
} else if (selectedWaypoint) {
|
|
3529
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3530
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
const positionStyles = {
|
|
3534
|
+
"top-left": { top: 10, left: 10 },
|
|
3535
|
+
"top-right": { top: 10, right: 10 },
|
|
3536
|
+
"bottom-left": { bottom: 10, left: 10 },
|
|
3537
|
+
"bottom-right": { bottom: 10, right: 10 }
|
|
3538
|
+
};
|
|
3539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
3540
|
+
"div",
|
|
3541
|
+
{
|
|
3542
|
+
style: {
|
|
3543
|
+
position: "absolute",
|
|
3544
|
+
...positionStyles[position],
|
|
3545
|
+
backgroundColor: "white",
|
|
3546
|
+
border: "1px solid #ccc",
|
|
3547
|
+
borderRadius: "4px",
|
|
3548
|
+
padding: "12px",
|
|
3549
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
3550
|
+
zIndex: 1e3,
|
|
3551
|
+
minWidth: "180px",
|
|
3552
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
3553
|
+
fontSize: "13px"
|
|
3554
|
+
},
|
|
3555
|
+
children: [
|
|
3556
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
3558
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3559
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3561
|
+
"input",
|
|
3562
|
+
{
|
|
3563
|
+
type: "number",
|
|
3564
|
+
value: x,
|
|
3565
|
+
onChange: (e) => handleXChange(e.target.value),
|
|
3566
|
+
onBlur: handleBlur,
|
|
3567
|
+
style: {
|
|
3568
|
+
flex: 1,
|
|
3569
|
+
padding: "4px 8px",
|
|
3570
|
+
border: "1px solid #ddd",
|
|
3571
|
+
borderRadius: "3px",
|
|
3572
|
+
fontSize: "13px"
|
|
3573
|
+
},
|
|
3574
|
+
step: "1"
|
|
3575
|
+
}
|
|
3576
|
+
)
|
|
3577
|
+
] }),
|
|
3578
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3579
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
3580
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3581
|
+
"input",
|
|
3582
|
+
{
|
|
3583
|
+
type: "number",
|
|
3584
|
+
value: y,
|
|
3585
|
+
onChange: (e) => handleYChange(e.target.value),
|
|
3586
|
+
onBlur: handleBlur,
|
|
3587
|
+
style: {
|
|
3588
|
+
flex: 1,
|
|
3589
|
+
padding: "4px 8px",
|
|
3590
|
+
border: "1px solid #ddd",
|
|
3591
|
+
borderRadius: "3px",
|
|
3592
|
+
fontSize: "13px"
|
|
3593
|
+
},
|
|
3594
|
+
step: "1"
|
|
3595
|
+
}
|
|
3596
|
+
)
|
|
3597
|
+
] })
|
|
3598
|
+
] }),
|
|
3599
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3600
|
+
]
|
|
3601
|
+
}
|
|
3602
|
+
);
|
|
3603
|
+
}
|
|
3604
|
+
|
|
3605
|
+
// src/diagram/hooks/useViewBox.ts
|
|
3606
|
+
var import_react9 = require("react");
|
|
2388
3607
|
function useViewBox(options) {
|
|
2389
3608
|
const {
|
|
2390
3609
|
initialViewBox,
|
|
@@ -2395,16 +3614,16 @@ function useViewBox(options) {
|
|
|
2395
3614
|
zoomSensitivity = 1e-3,
|
|
2396
3615
|
allowLeftClickPan = true
|
|
2397
3616
|
} = 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,
|
|
3617
|
+
const [viewBox, setViewBox] = (0, import_react9.useState)(initialViewBox);
|
|
3618
|
+
const svgRef = (0, import_react9.useRef)(null);
|
|
3619
|
+
const isPanningRef = (0, import_react9.useRef)(false);
|
|
3620
|
+
const lastMousePosRef = (0, import_react9.useRef)({ x: 0, y: 0 });
|
|
3621
|
+
const spaceKeyDownRef = (0, import_react9.useRef)(false);
|
|
3622
|
+
const lastTouchDistanceRef = (0, import_react9.useRef)(null);
|
|
3623
|
+
const resetViewBox = (0, import_react9.useCallback)(() => {
|
|
2405
3624
|
setViewBox(initialViewBox);
|
|
2406
3625
|
}, [initialViewBox]);
|
|
2407
|
-
const zoomIn = (0,
|
|
3626
|
+
const zoomIn = (0, import_react9.useCallback)(() => {
|
|
2408
3627
|
setViewBox((prev) => {
|
|
2409
3628
|
const currentZoom = initialViewBox.width / prev.width;
|
|
2410
3629
|
const newZoom = Math.min(1 / minZoom, currentZoom * 1.25);
|
|
@@ -2421,7 +3640,7 @@ function useViewBox(options) {
|
|
|
2421
3640
|
};
|
|
2422
3641
|
});
|
|
2423
3642
|
}, [initialViewBox, minZoom]);
|
|
2424
|
-
const zoomOut = (0,
|
|
3643
|
+
const zoomOut = (0, import_react9.useCallback)(() => {
|
|
2425
3644
|
setViewBox((prev) => {
|
|
2426
3645
|
const currentZoom = initialViewBox.width / prev.width;
|
|
2427
3646
|
const newZoom = Math.max(1 / maxZoom, currentZoom * 0.8);
|
|
@@ -2438,7 +3657,7 @@ function useViewBox(options) {
|
|
|
2438
3657
|
};
|
|
2439
3658
|
});
|
|
2440
3659
|
}, [initialViewBox, maxZoom]);
|
|
2441
|
-
const fitToContent = (0,
|
|
3660
|
+
const fitToContent = (0, import_react9.useCallback)((bounds, padding = 50) => {
|
|
2442
3661
|
const contentWidth = bounds.maxX - bounds.minX;
|
|
2443
3662
|
const contentHeight = bounds.maxY - bounds.minY;
|
|
2444
3663
|
if (contentWidth === 0 || contentHeight === 0) {
|
|
@@ -2466,7 +3685,7 @@ function useViewBox(options) {
|
|
|
2466
3685
|
height: newHeight
|
|
2467
3686
|
});
|
|
2468
3687
|
}, [initialViewBox]);
|
|
2469
|
-
(0,
|
|
3688
|
+
(0, import_react9.useEffect)(() => {
|
|
2470
3689
|
if (!enableZoom || !svgRef.current) return;
|
|
2471
3690
|
const svg = svgRef.current;
|
|
2472
3691
|
const handleWheel = (e) => {
|
|
@@ -2499,7 +3718,7 @@ function useViewBox(options) {
|
|
|
2499
3718
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
2500
3719
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
2501
3720
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
2502
|
-
(0,
|
|
3721
|
+
(0, import_react9.useEffect)(() => {
|
|
2503
3722
|
if (!enablePan || !svgRef.current) return;
|
|
2504
3723
|
const svg = svgRef.current;
|
|
2505
3724
|
const handleMouseDown = (e) => {
|
|
@@ -2575,7 +3794,7 @@ function useViewBox(options) {
|
|
|
2575
3794
|
window.removeEventListener("keyup", handleKeyUp);
|
|
2576
3795
|
};
|
|
2577
3796
|
}, [enablePan, allowLeftClickPan]);
|
|
2578
|
-
(0,
|
|
3797
|
+
(0, import_react9.useEffect)(() => {
|
|
2579
3798
|
if (!svgRef.current) return;
|
|
2580
3799
|
if (!enablePan && !enableZoom) return;
|
|
2581
3800
|
const svg = svgRef.current;
|
|
@@ -2666,7 +3885,7 @@ function useViewBox(options) {
|
|
|
2666
3885
|
svg.removeEventListener("touchend", handleTouchEnd);
|
|
2667
3886
|
};
|
|
2668
3887
|
}, [enablePan, enableZoom, minZoom, initialViewBox]);
|
|
2669
|
-
const screenToWorld = (0,
|
|
3888
|
+
const screenToWorld = (0, import_react9.useCallback)(
|
|
2670
3889
|
(screenX, screenY) => {
|
|
2671
3890
|
const svg = svgRef.current;
|
|
2672
3891
|
if (!svg) return { x: screenX, y: screenY };
|
|
@@ -2705,15 +3924,15 @@ function useViewBox(options) {
|
|
|
2705
3924
|
}
|
|
2706
3925
|
|
|
2707
3926
|
// src/diagram/hooks/useSelection.ts
|
|
2708
|
-
var
|
|
3927
|
+
var import_react10 = require("react");
|
|
2709
3928
|
function useSelection(options = {}) {
|
|
2710
3929
|
const {
|
|
2711
3930
|
multiSelect = true,
|
|
2712
3931
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
2713
3932
|
onSelectionChange
|
|
2714
3933
|
} = options;
|
|
2715
|
-
const [selection, setSelection] = (0,
|
|
2716
|
-
const notifyChange = (0,
|
|
3934
|
+
const [selection, setSelection] = (0, import_react10.useState)(initialSelection);
|
|
3935
|
+
const notifyChange = (0, import_react10.useCallback)(
|
|
2717
3936
|
(newSelection) => {
|
|
2718
3937
|
if (onSelectionChange) {
|
|
2719
3938
|
onSelectionChange(newSelection);
|
|
@@ -2721,15 +3940,15 @@ function useSelection(options = {}) {
|
|
|
2721
3940
|
},
|
|
2722
3941
|
[onSelectionChange]
|
|
2723
3942
|
);
|
|
2724
|
-
const isNodeSelected = (0,
|
|
3943
|
+
const isNodeSelected = (0, import_react10.useCallback)(
|
|
2725
3944
|
(nodeId) => selection.selectedNodeIds.has(nodeId),
|
|
2726
3945
|
[selection.selectedNodeIds]
|
|
2727
3946
|
);
|
|
2728
|
-
const isPipeSelected = (0,
|
|
3947
|
+
const isPipeSelected = (0, import_react10.useCallback)(
|
|
2729
3948
|
(pipeId) => selection.selectedPipeIds.has(pipeId),
|
|
2730
3949
|
[selection.selectedPipeIds]
|
|
2731
3950
|
);
|
|
2732
|
-
const selectNode = (0,
|
|
3951
|
+
const selectNode = (0, import_react10.useCallback)(
|
|
2733
3952
|
(nodeId, isMultiSelect = false) => {
|
|
2734
3953
|
setSelection((prev) => {
|
|
2735
3954
|
const newNodeIds = new Set(isMultiSelect && multiSelect ? prev.selectedNodeIds : []);
|
|
@@ -2748,7 +3967,7 @@ function useSelection(options = {}) {
|
|
|
2748
3967
|
},
|
|
2749
3968
|
[multiSelect, notifyChange]
|
|
2750
3969
|
);
|
|
2751
|
-
const selectPipe = (0,
|
|
3970
|
+
const selectPipe = (0, import_react10.useCallback)(
|
|
2752
3971
|
(pipeId, isMultiSelect = false) => {
|
|
2753
3972
|
setSelection((prev) => {
|
|
2754
3973
|
const newPipeIds = new Set(isMultiSelect && multiSelect ? prev.selectedPipeIds : []);
|
|
@@ -2767,7 +3986,7 @@ function useSelection(options = {}) {
|
|
|
2767
3986
|
},
|
|
2768
3987
|
[multiSelect, notifyChange]
|
|
2769
3988
|
);
|
|
2770
|
-
const clearSelection = (0,
|
|
3989
|
+
const clearSelection = (0, import_react10.useCallback)(() => {
|
|
2771
3990
|
const newSelection = {
|
|
2772
3991
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
2773
3992
|
selectedPipeIds: /* @__PURE__ */ new Set()
|
|
@@ -2775,7 +3994,7 @@ function useSelection(options = {}) {
|
|
|
2775
3994
|
setSelection(newSelection);
|
|
2776
3995
|
notifyChange(newSelection);
|
|
2777
3996
|
}, [notifyChange]);
|
|
2778
|
-
const selectNodes = (0,
|
|
3997
|
+
const selectNodes = (0, import_react10.useCallback)(
|
|
2779
3998
|
(nodeIds) => {
|
|
2780
3999
|
const newSelection = {
|
|
2781
4000
|
selectedNodeIds: new Set(nodeIds),
|
|
@@ -2786,7 +4005,7 @@ function useSelection(options = {}) {
|
|
|
2786
4005
|
},
|
|
2787
4006
|
[notifyChange]
|
|
2788
4007
|
);
|
|
2789
|
-
const selectPipes = (0,
|
|
4008
|
+
const selectPipes = (0, import_react10.useCallback)(
|
|
2790
4009
|
(pipeIds) => {
|
|
2791
4010
|
const newSelection = {
|
|
2792
4011
|
selectedNodeIds: /* @__PURE__ */ new Set(),
|
|
@@ -2810,23 +4029,23 @@ function useSelection(options = {}) {
|
|
|
2810
4029
|
}
|
|
2811
4030
|
|
|
2812
4031
|
// src/diagram/hooks/useTelemetry.ts
|
|
2813
|
-
var
|
|
4032
|
+
var import_react11 = require("react");
|
|
2814
4033
|
function useTelemetry(options = {}) {
|
|
2815
4034
|
const {
|
|
2816
4035
|
initialBindings = [],
|
|
2817
4036
|
onTelemetryChange,
|
|
2818
4037
|
refreshInterval = 0
|
|
2819
4038
|
} = options;
|
|
2820
|
-
const [telemetry, setTelemetry] = (0,
|
|
4039
|
+
const [telemetry, setTelemetry] = (0, import_react11.useState)(() => {
|
|
2821
4040
|
const map = /* @__PURE__ */ new Map();
|
|
2822
4041
|
initialBindings.forEach((binding) => {
|
|
2823
4042
|
map.set(binding.nodeId, binding);
|
|
2824
4043
|
});
|
|
2825
4044
|
return map;
|
|
2826
4045
|
});
|
|
2827
|
-
const telemetryRef = (0,
|
|
4046
|
+
const telemetryRef = (0, import_react11.useRef)(telemetry);
|
|
2828
4047
|
telemetryRef.current = telemetry;
|
|
2829
|
-
const notifyChange = (0,
|
|
4048
|
+
const notifyChange = (0, import_react11.useCallback)(
|
|
2830
4049
|
(newTelemetry) => {
|
|
2831
4050
|
if (onTelemetryChange) {
|
|
2832
4051
|
onTelemetryChange(newTelemetry);
|
|
@@ -2834,7 +4053,7 @@ function useTelemetry(options = {}) {
|
|
|
2834
4053
|
},
|
|
2835
4054
|
[onTelemetryChange]
|
|
2836
4055
|
);
|
|
2837
|
-
const updateTelemetry = (0,
|
|
4056
|
+
const updateTelemetry = (0, import_react11.useCallback)(
|
|
2838
4057
|
(nodeId, value) => {
|
|
2839
4058
|
setTelemetry((prev) => {
|
|
2840
4059
|
const newMap = new Map(prev);
|
|
@@ -2864,7 +4083,7 @@ function useTelemetry(options = {}) {
|
|
|
2864
4083
|
},
|
|
2865
4084
|
[notifyChange]
|
|
2866
4085
|
);
|
|
2867
|
-
const updateTelemetryBatch = (0,
|
|
4086
|
+
const updateTelemetryBatch = (0, import_react11.useCallback)(
|
|
2868
4087
|
(updates) => {
|
|
2869
4088
|
setTelemetry((prev) => {
|
|
2870
4089
|
const newMap = new Map(prev);
|
|
@@ -2918,16 +4137,16 @@ function useTelemetry(options = {}) {
|
|
|
2918
4137
|
},
|
|
2919
4138
|
[notifyChange]
|
|
2920
4139
|
);
|
|
2921
|
-
const getTelemetry = (0,
|
|
4140
|
+
const getTelemetry = (0, import_react11.useCallback)(
|
|
2922
4141
|
(nodeId) => telemetryRef.current.get(nodeId),
|
|
2923
4142
|
[]
|
|
2924
4143
|
);
|
|
2925
|
-
const clearTelemetry = (0,
|
|
4144
|
+
const clearTelemetry = (0, import_react11.useCallback)(() => {
|
|
2926
4145
|
const newMap = /* @__PURE__ */ new Map();
|
|
2927
4146
|
setTelemetry(newMap);
|
|
2928
4147
|
notifyChange(newMap);
|
|
2929
4148
|
}, [notifyChange]);
|
|
2930
|
-
const setBindings = (0,
|
|
4149
|
+
const setBindings = (0, import_react11.useCallback)(
|
|
2931
4150
|
(bindings) => {
|
|
2932
4151
|
const newMap = /* @__PURE__ */ new Map();
|
|
2933
4152
|
bindings.forEach((binding) => {
|
|
@@ -2938,7 +4157,7 @@ function useTelemetry(options = {}) {
|
|
|
2938
4157
|
},
|
|
2939
4158
|
[notifyChange]
|
|
2940
4159
|
);
|
|
2941
|
-
(0,
|
|
4160
|
+
(0, import_react11.useEffect)(() => {
|
|
2942
4161
|
if (refreshInterval <= 0) return;
|
|
2943
4162
|
const intervalId = setInterval(() => {
|
|
2944
4163
|
notifyChange(telemetryRef.current);
|
|
@@ -2955,8 +4174,50 @@ function useTelemetry(options = {}) {
|
|
|
2955
4174
|
};
|
|
2956
4175
|
}
|
|
2957
4176
|
|
|
4177
|
+
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4178
|
+
var import_react12 = require("react");
|
|
4179
|
+
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4180
|
+
const { enabled = true, mapStatus } = options;
|
|
4181
|
+
(0, import_react12.useEffect)(() => {
|
|
4182
|
+
if (!enabled) return;
|
|
4183
|
+
const defaultMapStatus = (telemetryStatus) => {
|
|
4184
|
+
switch (telemetryStatus) {
|
|
4185
|
+
case "normal":
|
|
4186
|
+
return "running";
|
|
4187
|
+
case "warning":
|
|
4188
|
+
return "warning";
|
|
4189
|
+
case "alarm":
|
|
4190
|
+
case "fault":
|
|
4191
|
+
return "alarm";
|
|
4192
|
+
case "off":
|
|
4193
|
+
return "stopped";
|
|
4194
|
+
default:
|
|
4195
|
+
return "stopped";
|
|
4196
|
+
}
|
|
4197
|
+
};
|
|
4198
|
+
const statusMapper = mapStatus || defaultMapStatus;
|
|
4199
|
+
let needsUpdate = false;
|
|
4200
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
4201
|
+
const binding = telemetry.get(node.id);
|
|
4202
|
+
if (!binding) return node;
|
|
4203
|
+
const newStatus = statusMapper(binding.value.status);
|
|
4204
|
+
if (node.status !== newStatus) {
|
|
4205
|
+
needsUpdate = true;
|
|
4206
|
+
return { ...node, status: newStatus };
|
|
4207
|
+
}
|
|
4208
|
+
return node;
|
|
4209
|
+
});
|
|
4210
|
+
if (needsUpdate) {
|
|
4211
|
+
setDiagram({
|
|
4212
|
+
...diagram,
|
|
4213
|
+
nodes: updatedNodes
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4216
|
+
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
4217
|
+
}
|
|
4218
|
+
|
|
2958
4219
|
// src/diagram/hooks/useDrag.ts
|
|
2959
|
-
var
|
|
4220
|
+
var import_react13 = require("react");
|
|
2960
4221
|
function useDrag(options = {}) {
|
|
2961
4222
|
const {
|
|
2962
4223
|
onDragStart,
|
|
@@ -2966,23 +4227,23 @@ function useDrag(options = {}) {
|
|
|
2966
4227
|
dragThreshold = 3,
|
|
2967
4228
|
screenToWorld = (x, y) => ({ x, y })
|
|
2968
4229
|
} = options;
|
|
2969
|
-
const [dragState, setDragState] = (0,
|
|
4230
|
+
const [dragState, setDragState] = (0, import_react13.useState)({
|
|
2970
4231
|
isDragging: false,
|
|
2971
4232
|
startPosition: null,
|
|
2972
4233
|
offset: { x: 0, y: 0 },
|
|
2973
4234
|
draggedId: null
|
|
2974
4235
|
});
|
|
2975
|
-
const [isListening, setIsListening] = (0,
|
|
2976
|
-
const dragStartRef = (0,
|
|
2977
|
-
const hasMovedRef = (0,
|
|
2978
|
-
const applySnap = (0,
|
|
4236
|
+
const [isListening, setIsListening] = (0, import_react13.useState)(false);
|
|
4237
|
+
const dragStartRef = (0, import_react13.useRef)(null);
|
|
4238
|
+
const hasMovedRef = (0, import_react13.useRef)(false);
|
|
4239
|
+
const applySnap = (0, import_react13.useCallback)(
|
|
2979
4240
|
(value) => {
|
|
2980
4241
|
if (snapToGrid <= 0) return value;
|
|
2981
4242
|
return Math.round(value / snapToGrid) * snapToGrid;
|
|
2982
4243
|
},
|
|
2983
4244
|
[snapToGrid]
|
|
2984
4245
|
);
|
|
2985
|
-
const handleMouseMove = (0,
|
|
4246
|
+
const handleMouseMove = (0, import_react13.useCallback)(
|
|
2986
4247
|
(event) => {
|
|
2987
4248
|
if (!dragStartRef.current) return;
|
|
2988
4249
|
const { id, screenStart: _screenStart, itemPosition, clickOffset } = dragStartRef.current;
|
|
@@ -3023,7 +4284,7 @@ function useDrag(options = {}) {
|
|
|
3023
4284
|
},
|
|
3024
4285
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
3025
4286
|
);
|
|
3026
|
-
const handleMouseUp = (0,
|
|
4287
|
+
const handleMouseUp = (0, import_react13.useCallback)(
|
|
3027
4288
|
(event) => {
|
|
3028
4289
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
3029
4290
|
dragStartRef.current = null;
|
|
@@ -3060,7 +4321,7 @@ function useDrag(options = {}) {
|
|
|
3060
4321
|
},
|
|
3061
4322
|
[screenToWorld, applySnap, onDragEnd]
|
|
3062
4323
|
);
|
|
3063
|
-
const handleTouchMove = (0,
|
|
4324
|
+
const handleTouchMove = (0, import_react13.useCallback)(
|
|
3064
4325
|
(event) => {
|
|
3065
4326
|
if (!dragStartRef.current || event.touches.length !== 1) return;
|
|
3066
4327
|
const touch = event.touches[0];
|
|
@@ -3103,7 +4364,7 @@ function useDrag(options = {}) {
|
|
|
3103
4364
|
},
|
|
3104
4365
|
[screenToWorld, dragThreshold, applySnap, onDragStart, onDragMove]
|
|
3105
4366
|
);
|
|
3106
|
-
const handleTouchEnd = (0,
|
|
4367
|
+
const handleTouchEnd = (0, import_react13.useCallback)(
|
|
3107
4368
|
(event) => {
|
|
3108
4369
|
if (!dragStartRef.current || !hasMovedRef.current) {
|
|
3109
4370
|
dragStartRef.current = null;
|
|
@@ -3141,7 +4402,7 @@ function useDrag(options = {}) {
|
|
|
3141
4402
|
},
|
|
3142
4403
|
[screenToWorld, applySnap, onDragEnd]
|
|
3143
4404
|
);
|
|
3144
|
-
(0,
|
|
4405
|
+
(0, import_react13.useEffect)(() => {
|
|
3145
4406
|
if (!isListening) return;
|
|
3146
4407
|
document.addEventListener("mousemove", handleMouseMove);
|
|
3147
4408
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -3156,7 +4417,7 @@ function useDrag(options = {}) {
|
|
|
3156
4417
|
document.removeEventListener("touchcancel", handleTouchEnd);
|
|
3157
4418
|
};
|
|
3158
4419
|
}, [isListening, handleMouseMove, handleMouseUp, handleTouchMove, handleTouchEnd]);
|
|
3159
|
-
const startDrag = (0,
|
|
4420
|
+
const startDrag = (0, import_react13.useCallback)(
|
|
3160
4421
|
(id, event, itemPosition) => {
|
|
3161
4422
|
event.stopPropagation();
|
|
3162
4423
|
let clientX;
|
|
@@ -3186,7 +4447,7 @@ function useDrag(options = {}) {
|
|
|
3186
4447
|
},
|
|
3187
4448
|
[screenToWorld]
|
|
3188
4449
|
);
|
|
3189
|
-
const cancelDrag = (0,
|
|
4450
|
+
const cancelDrag = (0, import_react13.useCallback)(() => {
|
|
3190
4451
|
dragStartRef.current = null;
|
|
3191
4452
|
hasMovedRef.current = false;
|
|
3192
4453
|
setIsListening(false);
|
|
@@ -3197,7 +4458,7 @@ function useDrag(options = {}) {
|
|
|
3197
4458
|
draggedId: null
|
|
3198
4459
|
});
|
|
3199
4460
|
}, []);
|
|
3200
|
-
const isDraggingItem = (0,
|
|
4461
|
+
const isDraggingItem = (0, import_react13.useCallback)(
|
|
3201
4462
|
(id) => dragState.isDragging && dragState.draggedId === id,
|
|
3202
4463
|
[dragState.isDragging, dragState.draggedId]
|
|
3203
4464
|
);
|
|
@@ -3210,7 +4471,7 @@ function useDrag(options = {}) {
|
|
|
3210
4471
|
}
|
|
3211
4472
|
|
|
3212
4473
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
3213
|
-
var
|
|
4474
|
+
var import_react14 = require("react");
|
|
3214
4475
|
function useKeyboardShortcuts(options) {
|
|
3215
4476
|
const {
|
|
3216
4477
|
onDelete,
|
|
@@ -3221,7 +4482,7 @@ function useKeyboardShortcuts(options) {
|
|
|
3221
4482
|
onSelectAll,
|
|
3222
4483
|
enabled = true
|
|
3223
4484
|
} = options;
|
|
3224
|
-
(0,
|
|
4485
|
+
(0, import_react14.useEffect)(() => {
|
|
3225
4486
|
if (!enabled) return;
|
|
3226
4487
|
const handleKeyDown = (event) => {
|
|
3227
4488
|
const target = event.target;
|
|
@@ -3330,7 +4591,7 @@ function nodeHasPort(node, portId) {
|
|
|
3330
4591
|
}
|
|
3331
4592
|
|
|
3332
4593
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3333
|
-
var
|
|
4594
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3334
4595
|
function PIDCanvas({
|
|
3335
4596
|
diagram,
|
|
3336
4597
|
className = "",
|
|
@@ -3357,16 +4618,30 @@ function PIDCanvas({
|
|
|
3357
4618
|
telemetry,
|
|
3358
4619
|
...props
|
|
3359
4620
|
}) {
|
|
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
|
-
|
|
4621
|
+
const [localDiagram, setLocalDiagram] = (0, import_react15.useState)(diagram);
|
|
4622
|
+
const [dragOverPosition, setDragOverPosition] = (0, import_react15.useState)(null);
|
|
4623
|
+
const [isConnecting, setIsConnecting] = (0, import_react15.useState)(false);
|
|
4624
|
+
const [connectionSource, setConnectionSource] = (0, import_react15.useState)(null);
|
|
4625
|
+
const [connectionSourcePort, setConnectionSourcePort] = (0, import_react15.useState)(null);
|
|
4626
|
+
const [connectionCursor, setConnectionCursor] = (0, import_react15.useState)(null);
|
|
4627
|
+
const [hoveredNode, setHoveredNode] = (0, import_react15.useState)(null);
|
|
4628
|
+
const [hoveredPort, setHoveredPort] = (0, import_react15.useState)(null);
|
|
4629
|
+
const [selectedWaypoint, setSelectedWaypoint] = (0, import_react15.useState)(null);
|
|
4630
|
+
const historyStack = (0, import_react15.useRef)([]);
|
|
4631
|
+
const redoStack = (0, import_react15.useRef)([]);
|
|
4632
|
+
const isUndoRedoAction = (0, import_react15.useRef)(false);
|
|
4633
|
+
const isInternalChange = (0, import_react15.useRef)(false);
|
|
4634
|
+
const lastInternalDiagram = (0, import_react15.useRef)(null);
|
|
4635
|
+
(0, import_react15.useEffect)(() => {
|
|
4636
|
+
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4637
|
+
if (isExternal) {
|
|
4638
|
+
setLocalDiagram(diagram);
|
|
4639
|
+
if (!isUndoRedoAction.current) {
|
|
4640
|
+
historyStack.current = [];
|
|
4641
|
+
redoStack.current = [];
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
isInternalChange.current = false;
|
|
3370
4645
|
}, [diagram]);
|
|
3371
4646
|
const {
|
|
3372
4647
|
viewBox: controlledViewBox,
|
|
@@ -3379,7 +4654,7 @@ function PIDCanvas({
|
|
|
3379
4654
|
enablePan: features.pan ?? true,
|
|
3380
4655
|
enableZoom: features.zoom ?? true
|
|
3381
4656
|
});
|
|
3382
|
-
const calculateContentBounds = (0,
|
|
4657
|
+
const calculateContentBounds = (0, import_react15.useCallback)(() => {
|
|
3383
4658
|
const nodes2 = localDiagram.nodes.filter((n) => n.visible !== false);
|
|
3384
4659
|
if (nodes2.length === 0) {
|
|
3385
4660
|
return null;
|
|
@@ -3402,7 +4677,7 @@ function PIDCanvas({
|
|
|
3402
4677
|
});
|
|
3403
4678
|
return { minX, minY, maxX, maxY };
|
|
3404
4679
|
}, [localDiagram.nodes]);
|
|
3405
|
-
(0,
|
|
4680
|
+
(0, import_react15.useEffect)(() => {
|
|
3406
4681
|
if (onMounted) {
|
|
3407
4682
|
const controls = {
|
|
3408
4683
|
fitToContent: (padding = 50) => {
|
|
@@ -3443,7 +4718,187 @@ function PIDCanvas({
|
|
|
3443
4718
|
});
|
|
3444
4719
|
const dragEnabled = features.dragNodes ?? false;
|
|
3445
4720
|
const selectionEnabled = features.selection ?? false;
|
|
3446
|
-
const
|
|
4721
|
+
const containerRef = (0, import_react15.useRef)(null);
|
|
4722
|
+
const pushToHistory = (0, import_react15.useCallback)((currentDiagram) => {
|
|
4723
|
+
if (isUndoRedoAction.current) return;
|
|
4724
|
+
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
4725
|
+
historyStack.current.push(snapshot);
|
|
4726
|
+
if (historyStack.current.length > 15) {
|
|
4727
|
+
historyStack.current.shift();
|
|
4728
|
+
}
|
|
4729
|
+
redoStack.current = [];
|
|
4730
|
+
}, []);
|
|
4731
|
+
const undo = (0, import_react15.useCallback)(() => {
|
|
4732
|
+
if (historyStack.current.length === 0) return;
|
|
4733
|
+
isUndoRedoAction.current = true;
|
|
4734
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4735
|
+
redoStack.current.push(currentSnapshot);
|
|
4736
|
+
const previousState = historyStack.current.pop();
|
|
4737
|
+
isInternalChange.current = true;
|
|
4738
|
+
lastInternalDiagram.current = previousState;
|
|
4739
|
+
setLocalDiagram(previousState);
|
|
4740
|
+
onDiagramChange?.(previousState);
|
|
4741
|
+
setTimeout(() => {
|
|
4742
|
+
isUndoRedoAction.current = false;
|
|
4743
|
+
}, 0);
|
|
4744
|
+
}, [localDiagram, onDiagramChange]);
|
|
4745
|
+
const redo = (0, import_react15.useCallback)(() => {
|
|
4746
|
+
if (redoStack.current.length === 0) return;
|
|
4747
|
+
isUndoRedoAction.current = true;
|
|
4748
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4749
|
+
historyStack.current.push(currentSnapshot);
|
|
4750
|
+
const nextState = redoStack.current.pop();
|
|
4751
|
+
isInternalChange.current = true;
|
|
4752
|
+
lastInternalDiagram.current = nextState;
|
|
4753
|
+
setLocalDiagram(nextState);
|
|
4754
|
+
onDiagramChange?.(nextState);
|
|
4755
|
+
setTimeout(() => {
|
|
4756
|
+
isUndoRedoAction.current = false;
|
|
4757
|
+
}, 0);
|
|
4758
|
+
}, [localDiagram, onDiagramChange]);
|
|
4759
|
+
(0, import_react15.useEffect)(() => {
|
|
4760
|
+
const handleKeyDown = (e) => {
|
|
4761
|
+
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4762
|
+
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
4763
|
+
e.preventDefault();
|
|
4764
|
+
undo();
|
|
4765
|
+
} else if (isCtrlOrCmd && e.key === "z" && e.shiftKey) {
|
|
4766
|
+
e.preventDefault();
|
|
4767
|
+
redo();
|
|
4768
|
+
} else if (isCtrlOrCmd && e.key === "y") {
|
|
4769
|
+
e.preventDefault();
|
|
4770
|
+
redo();
|
|
4771
|
+
}
|
|
4772
|
+
};
|
|
4773
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4774
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4775
|
+
}, [undo, redo]);
|
|
4776
|
+
(0, import_react15.useEffect)(() => {
|
|
4777
|
+
if (!features.dragNodes) return;
|
|
4778
|
+
const handleKeyDown = (e) => {
|
|
4779
|
+
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
4780
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
4781
|
+
return;
|
|
4782
|
+
}
|
|
4783
|
+
const nudgeAmount = e.shiftKey ? 10 : 1;
|
|
4784
|
+
let dx = 0;
|
|
4785
|
+
let dy = 0;
|
|
4786
|
+
switch (e.key) {
|
|
4787
|
+
case "ArrowLeft":
|
|
4788
|
+
dx = -nudgeAmount;
|
|
4789
|
+
e.preventDefault();
|
|
4790
|
+
break;
|
|
4791
|
+
case "ArrowRight":
|
|
4792
|
+
dx = nudgeAmount;
|
|
4793
|
+
e.preventDefault();
|
|
4794
|
+
break;
|
|
4795
|
+
case "ArrowUp":
|
|
4796
|
+
dy = -nudgeAmount;
|
|
4797
|
+
e.preventDefault();
|
|
4798
|
+
break;
|
|
4799
|
+
case "ArrowDown":
|
|
4800
|
+
dy = nudgeAmount;
|
|
4801
|
+
e.preventDefault();
|
|
4802
|
+
break;
|
|
4803
|
+
default:
|
|
4804
|
+
return;
|
|
4805
|
+
}
|
|
4806
|
+
if (selectedWaypoint) {
|
|
4807
|
+
pushToHistory(localDiagram);
|
|
4808
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4809
|
+
if (pipe.id === selectedWaypoint.pipeId) {
|
|
4810
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4811
|
+
(point, idx) => idx === selectedWaypoint.pointIndex ? { x: point.x + dx, y: point.y + dy } : point
|
|
4812
|
+
);
|
|
4813
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4814
|
+
}
|
|
4815
|
+
return pipe;
|
|
4816
|
+
});
|
|
4817
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4818
|
+
isInternalChange.current = true;
|
|
4819
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4820
|
+
setLocalDiagram(updatedDiagram);
|
|
4821
|
+
onDiagramChange?.(updatedDiagram);
|
|
4822
|
+
return;
|
|
4823
|
+
}
|
|
4824
|
+
if (selectionEnabled && selection.selectedNodeIds.size > 0) {
|
|
4825
|
+
pushToHistory(localDiagram);
|
|
4826
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4827
|
+
(node) => selection.selectedNodeIds.has(node.id) ? {
|
|
4828
|
+
...node,
|
|
4829
|
+
transform: {
|
|
4830
|
+
...node.transform,
|
|
4831
|
+
x: node.transform.x + dx,
|
|
4832
|
+
y: node.transform.y + dy
|
|
4833
|
+
}
|
|
4834
|
+
} : node
|
|
4835
|
+
);
|
|
4836
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4837
|
+
isInternalChange.current = true;
|
|
4838
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4839
|
+
setLocalDiagram(updatedDiagram);
|
|
4840
|
+
onDiagramChange?.(updatedDiagram);
|
|
4841
|
+
selection.selectedNodeIds.forEach((nodeId) => {
|
|
4842
|
+
const node = updatedNodes.find((n) => n.id === nodeId);
|
|
4843
|
+
if (node) {
|
|
4844
|
+
onNodeMove?.(nodeId, node.transform.x, node.transform.y);
|
|
4845
|
+
}
|
|
4846
|
+
});
|
|
4847
|
+
}
|
|
4848
|
+
};
|
|
4849
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4850
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4851
|
+
}, [
|
|
4852
|
+
selectionEnabled,
|
|
4853
|
+
features.dragNodes,
|
|
4854
|
+
selection.selectedNodeIds,
|
|
4855
|
+
selectedWaypoint,
|
|
4856
|
+
localDiagram,
|
|
4857
|
+
onDiagramChange,
|
|
4858
|
+
onNodeMove,
|
|
4859
|
+
pushToHistory
|
|
4860
|
+
]);
|
|
4861
|
+
const handlePositionChange = (0, import_react15.useCallback)(
|
|
4862
|
+
(nodeId, x, y) => {
|
|
4863
|
+
pushToHistory(localDiagram);
|
|
4864
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4865
|
+
(node) => node.id === nodeId ? {
|
|
4866
|
+
...node,
|
|
4867
|
+
transform: {
|
|
4868
|
+
...node.transform,
|
|
4869
|
+
x,
|
|
4870
|
+
y
|
|
4871
|
+
}
|
|
4872
|
+
} : node
|
|
4873
|
+
);
|
|
4874
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4875
|
+
isInternalChange.current = true;
|
|
4876
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4877
|
+
setLocalDiagram(updatedDiagram);
|
|
4878
|
+
onDiagramChange?.(updatedDiagram);
|
|
4879
|
+
onNodeMove?.(nodeId, x, y);
|
|
4880
|
+
},
|
|
4881
|
+
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
4882
|
+
);
|
|
4883
|
+
const handleWaypointPositionChange = (0, import_react15.useCallback)(
|
|
4884
|
+
(pipeId, pointIndex, x, y) => {
|
|
4885
|
+
pushToHistory(localDiagram);
|
|
4886
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4887
|
+
if (pipe.id === pipeId) {
|
|
4888
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4889
|
+
(point, idx) => idx === pointIndex ? { x, y } : point
|
|
4890
|
+
);
|
|
4891
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4892
|
+
}
|
|
4893
|
+
return pipe;
|
|
4894
|
+
});
|
|
4895
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4896
|
+
setLocalDiagram(updatedDiagram);
|
|
4897
|
+
onDiagramChange?.(updatedDiagram);
|
|
4898
|
+
},
|
|
4899
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
4900
|
+
);
|
|
4901
|
+
const handleDragEnd = (0, import_react15.useCallback)(
|
|
3447
4902
|
(nodeId, offset, finalPosition) => {
|
|
3448
4903
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
3449
4904
|
if (dragDistance < 2) {
|
|
@@ -3452,6 +4907,7 @@ function PIDCanvas({
|
|
|
3452
4907
|
}
|
|
3453
4908
|
return;
|
|
3454
4909
|
}
|
|
4910
|
+
pushToHistory(localDiagram);
|
|
3455
4911
|
const updatedNodes = localDiagram.nodes.map(
|
|
3456
4912
|
(node) => node.id === nodeId ? {
|
|
3457
4913
|
...node,
|
|
@@ -3489,11 +4945,13 @@ function PIDCanvas({
|
|
|
3489
4945
|
nodes: updatedNodes,
|
|
3490
4946
|
pipes: updatedPipes
|
|
3491
4947
|
};
|
|
4948
|
+
isInternalChange.current = true;
|
|
4949
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3492
4950
|
setLocalDiagram(updatedDiagram);
|
|
3493
4951
|
onDiagramChange?.(updatedDiagram);
|
|
3494
4952
|
onNodeMove?.(nodeId, finalPosition.x, finalPosition.y);
|
|
3495
4953
|
},
|
|
3496
|
-
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode]
|
|
4954
|
+
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode, pushToHistory]
|
|
3497
4955
|
);
|
|
3498
4956
|
const { dragState, startDrag } = useDrag({
|
|
3499
4957
|
snapToGrid: features.snapToGrid ?? 0,
|
|
@@ -3504,6 +4962,7 @@ function PIDCanvas({
|
|
|
3504
4962
|
snapToGrid: features.snapToGrid ?? 0,
|
|
3505
4963
|
screenToWorld,
|
|
3506
4964
|
onDragEnd: (pipeId, _offset, finalPosition) => {
|
|
4965
|
+
pushToHistory(localDiagram);
|
|
3507
4966
|
const [actualPipeId, pointIndex] = pipeId.split(":");
|
|
3508
4967
|
const idx = parseInt(pointIndex, 10);
|
|
3509
4968
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -3514,11 +4973,13 @@ function PIDCanvas({
|
|
|
3514
4973
|
return { ...pipe, routePoints: updatedRoutePoints };
|
|
3515
4974
|
});
|
|
3516
4975
|
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4976
|
+
isInternalChange.current = true;
|
|
4977
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3517
4978
|
setLocalDiagram(updatedDiagram);
|
|
3518
4979
|
onDiagramChange?.(updatedDiagram);
|
|
3519
4980
|
}
|
|
3520
4981
|
});
|
|
3521
|
-
const handleNodeDragStart = (0,
|
|
4982
|
+
const handleNodeDragStart = (0, import_react15.useCallback)(
|
|
3522
4983
|
(nodeId, event) => {
|
|
3523
4984
|
const node = localDiagram.nodes.find((n) => n.id === nodeId);
|
|
3524
4985
|
if (!node) return;
|
|
@@ -3526,7 +4987,16 @@ function PIDCanvas({
|
|
|
3526
4987
|
},
|
|
3527
4988
|
[localDiagram.nodes, startDrag]
|
|
3528
4989
|
);
|
|
3529
|
-
const
|
|
4990
|
+
const handleWaypointClick = (0, import_react15.useCallback)(
|
|
4991
|
+
(pipeId, pointIndex) => {
|
|
4992
|
+
setSelectedWaypoint({ pipeId, pointIndex });
|
|
4993
|
+
if (selectionEnabled) {
|
|
4994
|
+
clearSelection();
|
|
4995
|
+
}
|
|
4996
|
+
},
|
|
4997
|
+
[selectionEnabled, clearSelection]
|
|
4998
|
+
);
|
|
4999
|
+
const handleWaypointDragStart = (0, import_react15.useCallback)(
|
|
3530
5000
|
(pipeId, pointIndex, event) => {
|
|
3531
5001
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
3532
5002
|
if (!pipe || pointIndex >= pipe.routePoints.length) return;
|
|
@@ -3535,8 +5005,9 @@ function PIDCanvas({
|
|
|
3535
5005
|
},
|
|
3536
5006
|
[localDiagram.pipes, startWaypointDrag]
|
|
3537
5007
|
);
|
|
3538
|
-
const handlePipeSegmentClick = (0,
|
|
5008
|
+
const handlePipeSegmentClick = (0, import_react15.useCallback)(
|
|
3539
5009
|
(pipeId, position, segmentIndex) => {
|
|
5010
|
+
pushToHistory(localDiagram);
|
|
3540
5011
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
3541
5012
|
if (pipe.id !== pipeId) return pipe;
|
|
3542
5013
|
const updatedRoutePoints = [
|
|
@@ -3550,13 +5021,14 @@ function PIDCanvas({
|
|
|
3550
5021
|
setLocalDiagram(updatedDiagram);
|
|
3551
5022
|
onDiagramChange?.(updatedDiagram);
|
|
3552
5023
|
},
|
|
3553
|
-
[localDiagram, onDiagramChange]
|
|
5024
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
3554
5025
|
);
|
|
3555
5026
|
const telemetryEnabled = features.telemetry ?? false;
|
|
3556
|
-
const handleDelete = (0,
|
|
5027
|
+
const handleDelete = (0, import_react15.useCallback)(() => {
|
|
3557
5028
|
if (!selectionEnabled) return;
|
|
3558
5029
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3559
5030
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
5031
|
+
pushToHistory(localDiagram);
|
|
3560
5032
|
const updatedNodes = localDiagram.nodes.filter((node) => !selectedNodeIds.has(node.id));
|
|
3561
5033
|
const updatedPipes = localDiagram.pipes.filter(
|
|
3562
5034
|
(pipe) => !selectedPipeIds.has(pipe.id) && !selectedNodeIds.has(pipe.fromNodeId) && !selectedNodeIds.has(pipe.toNodeId)
|
|
@@ -3566,18 +5038,28 @@ function PIDCanvas({
|
|
|
3566
5038
|
nodes: updatedNodes,
|
|
3567
5039
|
pipes: updatedPipes
|
|
3568
5040
|
};
|
|
5041
|
+
isInternalChange.current = true;
|
|
5042
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3569
5043
|
setLocalDiagram(updatedDiagram);
|
|
3570
5044
|
clearSelection();
|
|
3571
5045
|
onDiagramChange?.(updatedDiagram);
|
|
3572
5046
|
onDelete?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3573
|
-
}, [
|
|
3574
|
-
|
|
5047
|
+
}, [
|
|
5048
|
+
selection,
|
|
5049
|
+
localDiagram,
|
|
5050
|
+
selectionEnabled,
|
|
5051
|
+
clearSelection,
|
|
5052
|
+
onDiagramChange,
|
|
5053
|
+
onDelete,
|
|
5054
|
+
pushToHistory
|
|
5055
|
+
]);
|
|
5056
|
+
const handleCopy = (0, import_react15.useCallback)(() => {
|
|
3575
5057
|
if (!selectionEnabled) return;
|
|
3576
5058
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3577
5059
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
3578
5060
|
onItemsCopied?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3579
5061
|
}, [selection, selectionEnabled, onItemsCopied]);
|
|
3580
|
-
const handlePaste = (0,
|
|
5062
|
+
const handlePaste = (0, import_react15.useCallback)(() => {
|
|
3581
5063
|
if (!selectionEnabled) return;
|
|
3582
5064
|
onPaste?.();
|
|
3583
5065
|
}, [selectionEnabled, onPaste]);
|
|
@@ -3627,12 +5109,17 @@ function PIDCanvas({
|
|
|
3627
5109
|
}
|
|
3628
5110
|
onPipeClick?.(pipeId);
|
|
3629
5111
|
};
|
|
3630
|
-
const handleCanvasClick = () => {
|
|
5112
|
+
const handleCanvasClick = (e) => {
|
|
5113
|
+
const target = e.target;
|
|
5114
|
+
if (target.closest(".pipe-route-point")) {
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
3631
5117
|
if (selectionEnabled) {
|
|
3632
5118
|
clearSelection();
|
|
3633
5119
|
}
|
|
5120
|
+
setSelectedWaypoint(null);
|
|
3634
5121
|
};
|
|
3635
|
-
const handleDragOver = (0,
|
|
5122
|
+
const handleDragOver = (0, import_react15.useCallback)(
|
|
3636
5123
|
(event) => {
|
|
3637
5124
|
if (!features.allowSymbolDrop) return;
|
|
3638
5125
|
event.preventDefault();
|
|
@@ -3641,9 +5128,9 @@ function PIDCanvas({
|
|
|
3641
5128
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3642
5129
|
setDragOverPosition(worldPos);
|
|
3643
5130
|
},
|
|
3644
|
-
[features.allowSymbolDrop, screenToWorld]
|
|
5131
|
+
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
3645
5132
|
);
|
|
3646
|
-
const handleDrop = (0,
|
|
5133
|
+
const handleDrop = (0, import_react15.useCallback)(
|
|
3647
5134
|
(event) => {
|
|
3648
5135
|
if (!features.allowSymbolDrop) return;
|
|
3649
5136
|
event.preventDefault();
|
|
@@ -3654,12 +5141,12 @@ function PIDCanvas({
|
|
|
3654
5141
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3655
5142
|
onSymbolDrop?.(symbolId, worldPos);
|
|
3656
5143
|
},
|
|
3657
|
-
[features.allowSymbolDrop, screenToWorld, onSymbolDrop]
|
|
5144
|
+
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
3658
5145
|
);
|
|
3659
|
-
const handleDragLeave = (0,
|
|
5146
|
+
const handleDragLeave = (0, import_react15.useCallback)(() => {
|
|
3660
5147
|
setDragOverPosition(null);
|
|
3661
5148
|
}, []);
|
|
3662
|
-
const handleMouseMove = (0,
|
|
5149
|
+
const handleMouseMove = (0, import_react15.useCallback)(
|
|
3663
5150
|
(event) => {
|
|
3664
5151
|
const connectionModeEnabled = features.connectionMode ?? false;
|
|
3665
5152
|
if (connectionModeEnabled) {
|
|
@@ -3678,7 +5165,7 @@ function PIDCanvas({
|
|
|
3678
5165
|
const distance = Math.sqrt(
|
|
3679
5166
|
(worldPos.x - portPos.x) ** 2 + (worldPos.y - portPos.y) ** 2
|
|
3680
5167
|
);
|
|
3681
|
-
if (distance <
|
|
5168
|
+
if (distance < 15) {
|
|
3682
5169
|
foundPort = port.id;
|
|
3683
5170
|
foundNode = node.id;
|
|
3684
5171
|
break;
|
|
@@ -3695,9 +5182,11 @@ function PIDCanvas({
|
|
|
3695
5182
|
const { name } = diagram;
|
|
3696
5183
|
const viewBox = controlledViewBox;
|
|
3697
5184
|
const displayDiagram = localDiagram;
|
|
3698
|
-
|
|
5185
|
+
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3699
5187
|
"div",
|
|
3700
5188
|
{
|
|
5189
|
+
ref: containerRef,
|
|
3701
5190
|
className: `pid-canvas ${className}`.trim(),
|
|
3702
5191
|
style: {
|
|
3703
5192
|
width: "100%",
|
|
@@ -3708,223 +5197,287 @@ function PIDCanvas({
|
|
|
3708
5197
|
...style
|
|
3709
5198
|
},
|
|
3710
5199
|
...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
|
-
|
|
5200
|
+
children: [
|
|
5201
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
5202
|
+
"svg",
|
|
5203
|
+
{
|
|
5204
|
+
ref: svgRef,
|
|
5205
|
+
width: "100%",
|
|
5206
|
+
height: "100%",
|
|
5207
|
+
viewBox: `${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`,
|
|
5208
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
5209
|
+
style: {
|
|
5210
|
+
display: "block"
|
|
5211
|
+
},
|
|
5212
|
+
"aria-label": `P&ID diagram: ${name}`,
|
|
5213
|
+
role: "img",
|
|
5214
|
+
onClick: handleCanvasClick,
|
|
5215
|
+
onMouseMove: handleMouseMove,
|
|
5216
|
+
onDragOver: handleDragOver,
|
|
5217
|
+
onDrop: handleDrop,
|
|
5218
|
+
onDragLeave: handleDragLeave,
|
|
5219
|
+
children: [
|
|
5220
|
+
features.showGrid !== false ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
5221
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("defs", { children: [
|
|
5222
|
+
/* @__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" }) }),
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5224
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5225
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5226
|
+
] })
|
|
5227
|
+
] }),
|
|
5228
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5229
|
+
"rect",
|
|
5230
|
+
{
|
|
5231
|
+
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
5232
|
+
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
5233
|
+
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
5234
|
+
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
5235
|
+
fill: "url(#grid-major)"
|
|
5236
|
+
}
|
|
5237
|
+
)
|
|
5238
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3739
5239
|
"rect",
|
|
3740
5240
|
{
|
|
3741
5241
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3742
5242
|
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3743
5243
|
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3744
5244
|
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3745
|
-
fill: "
|
|
5245
|
+
fill: features.backgroundColor ?? "#ffffff"
|
|
3746
5246
|
}
|
|
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,
|
|
5247
|
+
),
|
|
5248
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5249
|
+
PipeRenderer,
|
|
3807
5250
|
{
|
|
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
|
-
}
|
|
5251
|
+
pipes: displayDiagram.pipes,
|
|
5252
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5253
|
+
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
5254
|
+
enableWaypointEditing: false,
|
|
5255
|
+
onWaypointDragStart: void 0,
|
|
5256
|
+
editingPipeId: null,
|
|
5257
|
+
draggingWaypointIndex: null,
|
|
5258
|
+
waypointDragOffset: void 0,
|
|
5259
|
+
onPipeSegmentClick: void 0
|
|
3843
5260
|
}
|
|
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",
|
|
5261
|
+
),
|
|
5262
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5263
|
+
NodeRenderer,
|
|
5264
|
+
{
|
|
5265
|
+
nodes: displayDiagram.nodes,
|
|
5266
|
+
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5267
|
+
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5268
|
+
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5269
|
+
enableDrag: dragEnabled && !isConnecting,
|
|
5270
|
+
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
5271
|
+
draggingNodeId: dragState.draggedId,
|
|
5272
|
+
dragOffset: dragState.offset
|
|
5273
|
+
}
|
|
5274
|
+
),
|
|
5275
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5276
|
+
PipeRenderer,
|
|
5277
|
+
{
|
|
5278
|
+
pipes: displayDiagram.pipes,
|
|
5279
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5280
|
+
onPipeClick: void 0,
|
|
5281
|
+
enableWaypointEditing: true,
|
|
5282
|
+
onWaypointClick: handleWaypointClick,
|
|
5283
|
+
onWaypointDragStart: handleWaypointDragStart,
|
|
5284
|
+
selectedWaypointPipeId: selectedWaypoint?.pipeId || null,
|
|
5285
|
+
selectedWaypointIndex: selectedWaypoint?.pointIndex ?? null,
|
|
5286
|
+
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
5287
|
+
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
5288
|
+
waypointDragOffset: waypointDragState.offset,
|
|
5289
|
+
onPipeSegmentClick: handlePipeSegmentClick
|
|
5290
|
+
}
|
|
5291
|
+
),
|
|
5292
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5293
|
+
const binding = telemetry.get(node.id);
|
|
5294
|
+
if (!binding) return null;
|
|
5295
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5296
|
+
if (!symbol) return null;
|
|
5297
|
+
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5298
|
+
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5300
|
+
DataOverlay,
|
|
3893
5301
|
{
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
3900
|
-
opacity: isHovered || isSourcePort ? 1 : 0.6
|
|
5302
|
+
nodeId: node.id,
|
|
5303
|
+
x: overlayX,
|
|
5304
|
+
y: overlayY,
|
|
5305
|
+
telemetry: binding,
|
|
5306
|
+
scale: features.telemetryScale ?? 1
|
|
3901
5307
|
},
|
|
3902
|
-
|
|
5308
|
+
`telemetry-${node.id}`
|
|
3903
5309
|
);
|
|
3904
|
-
})
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
5310
|
+
}) }),
|
|
5311
|
+
dragOverPosition && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5312
|
+
"circle",
|
|
5313
|
+
{
|
|
5314
|
+
cx: dragOverPosition.x,
|
|
5315
|
+
cy: dragOverPosition.y,
|
|
5316
|
+
r: 20,
|
|
5317
|
+
fill: "#3b82f6",
|
|
5318
|
+
opacity: 0.3,
|
|
5319
|
+
stroke: "#3b82f6",
|
|
5320
|
+
strokeWidth: 2,
|
|
5321
|
+
pointerEvents: "none"
|
|
5322
|
+
}
|
|
5323
|
+
),
|
|
5324
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5325
|
+
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5326
|
+
if (!sourceNode) return null;
|
|
5327
|
+
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
5328
|
+
let lineStartX = sourceNode.transform.x;
|
|
5329
|
+
let lineStartY = sourceNode.transform.y;
|
|
5330
|
+
if (connectionSourcePort && symbol?.ports) {
|
|
5331
|
+
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
5332
|
+
if (port) {
|
|
5333
|
+
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
5334
|
+
if (portPos) {
|
|
5335
|
+
lineStartX = portPos.x;
|
|
5336
|
+
lineStartY = portPos.y;
|
|
5337
|
+
}
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
5341
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5342
|
+
"circle",
|
|
5343
|
+
{
|
|
5344
|
+
cx: lineStartX,
|
|
5345
|
+
cy: lineStartY,
|
|
5346
|
+
r: 30,
|
|
5347
|
+
fill: "none",
|
|
5348
|
+
stroke: "#10b981",
|
|
5349
|
+
strokeWidth: 3,
|
|
5350
|
+
opacity: 0.6
|
|
5351
|
+
}
|
|
5352
|
+
),
|
|
5353
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5354
|
+
"line",
|
|
5355
|
+
{
|
|
5356
|
+
x1: lineStartX,
|
|
5357
|
+
y1: lineStartY,
|
|
5358
|
+
x2: connectionCursor.x,
|
|
5359
|
+
y2: connectionCursor.y,
|
|
5360
|
+
stroke: "#10b981",
|
|
5361
|
+
strokeWidth: 2,
|
|
5362
|
+
strokeDasharray: "5,5",
|
|
5363
|
+
opacity: 0.8
|
|
5364
|
+
}
|
|
5365
|
+
),
|
|
5366
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5367
|
+
"circle",
|
|
5368
|
+
{
|
|
5369
|
+
cx: connectionCursor.x,
|
|
5370
|
+
cy: connectionCursor.y,
|
|
5371
|
+
r: 8,
|
|
5372
|
+
fill: "#10b981",
|
|
5373
|
+
opacity: 0.6
|
|
5374
|
+
}
|
|
5375
|
+
)
|
|
5376
|
+
] });
|
|
5377
|
+
})() }),
|
|
5378
|
+
features.connectionMode && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5379
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5380
|
+
if (!symbol?.ports) return null;
|
|
5381
|
+
return symbol.ports.map((port) => {
|
|
5382
|
+
const portPos = getPortWorldPosition(node, port.id);
|
|
5383
|
+
if (!portPos) return null;
|
|
5384
|
+
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5385
|
+
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("g", { children: [
|
|
5387
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5388
|
+
"circle",
|
|
5389
|
+
{
|
|
5390
|
+
cx: portPos.x,
|
|
5391
|
+
cy: portPos.y,
|
|
5392
|
+
r: 15,
|
|
5393
|
+
fill: "transparent",
|
|
5394
|
+
style: { cursor: "pointer" },
|
|
5395
|
+
pointerEvents: "auto",
|
|
5396
|
+
onClick: (e) => {
|
|
5397
|
+
e.stopPropagation();
|
|
5398
|
+
if (isConnecting && connectionSource) {
|
|
5399
|
+
if (connectionSource !== node.id) {
|
|
5400
|
+
onPipeCreated?.(
|
|
5401
|
+
connectionSource,
|
|
5402
|
+
node.id,
|
|
5403
|
+
connectionSourcePort || void 0,
|
|
5404
|
+
port.id
|
|
5405
|
+
);
|
|
5406
|
+
setIsConnecting(false);
|
|
5407
|
+
setConnectionSource(null);
|
|
5408
|
+
setConnectionSourcePort(null);
|
|
5409
|
+
setConnectionCursor(null);
|
|
5410
|
+
setHoveredPort(null);
|
|
5411
|
+
}
|
|
5412
|
+
} else {
|
|
5413
|
+
setIsConnecting(true);
|
|
5414
|
+
setConnectionSource(node.id);
|
|
5415
|
+
setConnectionSourcePort(port.id);
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
),
|
|
5420
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5421
|
+
"circle",
|
|
5422
|
+
{
|
|
5423
|
+
cx: portPos.x,
|
|
5424
|
+
cy: portPos.y,
|
|
5425
|
+
r: isHovered ? 8 : 5,
|
|
5426
|
+
fill: isSourcePort ? "#10b981" : isHovered ? "#3b82f6" : "#94a3b8",
|
|
5427
|
+
stroke: isSourcePort ? "#059669" : isHovered ? "#2563eb" : "#64748b",
|
|
5428
|
+
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
5429
|
+
opacity: isHovered || isSourcePort ? 1 : 0.6,
|
|
5430
|
+
pointerEvents: "none"
|
|
5431
|
+
}
|
|
5432
|
+
)
|
|
5433
|
+
] }, `${node.id}-${port.id}`);
|
|
5434
|
+
});
|
|
5435
|
+
}) })
|
|
5436
|
+
]
|
|
5437
|
+
}
|
|
5438
|
+
),
|
|
5439
|
+
features.dragNodes && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5440
|
+
PositionPanel,
|
|
5441
|
+
{
|
|
5442
|
+
selectedNode,
|
|
5443
|
+
selectedWaypoint: selectedWaypoint ? {
|
|
5444
|
+
pipeId: selectedWaypoint.pipeId,
|
|
5445
|
+
pointIndex: selectedWaypoint.pointIndex,
|
|
5446
|
+
position: localDiagram.pipes.find((p) => p.id === selectedWaypoint.pipeId)?.routePoints[selectedWaypoint.pointIndex] || { x: 0, y: 0 }
|
|
5447
|
+
} : null,
|
|
5448
|
+
onPositionChange: handlePositionChange,
|
|
5449
|
+
onWaypointPositionChange: handleWaypointPositionChange,
|
|
5450
|
+
position: "top-right"
|
|
5451
|
+
}
|
|
5452
|
+
)
|
|
5453
|
+
]
|
|
3909
5454
|
}
|
|
3910
5455
|
);
|
|
3911
5456
|
}
|
|
3912
5457
|
|
|
3913
5458
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
3914
|
-
var
|
|
3915
|
-
var
|
|
5459
|
+
var import_react16 = require("react");
|
|
5460
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3916
5461
|
function SymbolLibrary({
|
|
3917
5462
|
className = "",
|
|
3918
5463
|
onSymbolDragStart,
|
|
3919
5464
|
showCategories = true,
|
|
3920
5465
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
3921
5466
|
}) {
|
|
3922
|
-
const [selectedCategory, setSelectedCategory] = (0,
|
|
3923
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
5467
|
+
const [selectedCategory, setSelectedCategory] = (0, import_react16.useState)("all");
|
|
5468
|
+
const [searchQuery, setSearchQuery] = (0, import_react16.useState)("");
|
|
3924
5469
|
const symbolIds = getAvailableSymbols();
|
|
3925
5470
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5471
|
+
const categoryMap = {
|
|
5472
|
+
Valves: "valve",
|
|
5473
|
+
Pumps: "pump",
|
|
5474
|
+
Tanks: "vessel",
|
|
5475
|
+
Instruments: "instrument",
|
|
5476
|
+
Displays: "display"
|
|
5477
|
+
};
|
|
3926
5478
|
const filteredSymbols = allSymbols.filter((symbol) => {
|
|
3927
|
-
const
|
|
5479
|
+
const actualCategory = categoryMap[selectedCategory] || selectedCategory;
|
|
5480
|
+
const matchesCategory = selectedCategory === "all" || symbol.category === actualCategory;
|
|
3928
5481
|
const matchesSearch = searchQuery === "" || symbol.name.toLowerCase().includes(searchQuery.toLowerCase()) || symbol.id.toLowerCase().includes(searchQuery.toLowerCase());
|
|
3929
5482
|
return matchesCategory && matchesSearch;
|
|
3930
5483
|
});
|
|
@@ -3933,9 +5486,9 @@ function SymbolLibrary({
|
|
|
3933
5486
|
event.dataTransfer.effectAllowed = "copy";
|
|
3934
5487
|
onSymbolDragStart?.(symbol.id, event);
|
|
3935
5488
|
};
|
|
3936
|
-
return /* @__PURE__ */ (0,
|
|
3937
|
-
/* @__PURE__ */ (0,
|
|
3938
|
-
/* @__PURE__ */ (0,
|
|
5489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
5490
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
5491
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3939
5492
|
"input",
|
|
3940
5493
|
{
|
|
3941
5494
|
type: "text",
|
|
@@ -3945,8 +5498,8 @@ function SymbolLibrary({
|
|
|
3945
5498
|
style: styles.searchInput
|
|
3946
5499
|
}
|
|
3947
5500
|
) }),
|
|
3948
|
-
showCategories && /* @__PURE__ */ (0,
|
|
3949
|
-
/* @__PURE__ */ (0,
|
|
5501
|
+
showCategories && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: styles.categories, children: [
|
|
5502
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3950
5503
|
"button",
|
|
3951
5504
|
{
|
|
3952
5505
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -3957,7 +5510,7 @@ function SymbolLibrary({
|
|
|
3957
5510
|
children: "All"
|
|
3958
5511
|
}
|
|
3959
5512
|
),
|
|
3960
|
-
categories.map((category) => /* @__PURE__ */ (0,
|
|
5513
|
+
categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3961
5514
|
"button",
|
|
3962
5515
|
{
|
|
3963
5516
|
onClick: () => setSelectedCategory(category),
|
|
@@ -3970,7 +5523,7 @@ function SymbolLibrary({
|
|
|
3970
5523
|
category
|
|
3971
5524
|
))
|
|
3972
5525
|
] }),
|
|
3973
|
-
/* @__PURE__ */ (0,
|
|
5526
|
+
/* @__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
5527
|
"div",
|
|
3975
5528
|
{
|
|
3976
5529
|
draggable: true,
|
|
@@ -3978,15 +5531,15 @@ function SymbolLibrary({
|
|
|
3978
5531
|
style: styles.symbolCard,
|
|
3979
5532
|
title: symbol.metadata?.description || symbol.name,
|
|
3980
5533
|
children: [
|
|
3981
|
-
/* @__PURE__ */ (0,
|
|
5534
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.symbolPreview, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3982
5535
|
"svg",
|
|
3983
5536
|
{
|
|
3984
5537
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
3985
5538
|
style: styles.symbolSvg,
|
|
3986
|
-
children: /* @__PURE__ */ (0,
|
|
5539
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
3987
5540
|
}
|
|
3988
5541
|
) }),
|
|
3989
|
-
/* @__PURE__ */ (0,
|
|
5542
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: styles.symbolName, children: symbol.name })
|
|
3990
5543
|
]
|
|
3991
5544
|
},
|
|
3992
5545
|
symbol.id
|
|
@@ -4095,7 +5648,7 @@ var styles = {
|
|
|
4095
5648
|
};
|
|
4096
5649
|
|
|
4097
5650
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
4098
|
-
var
|
|
5651
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4099
5652
|
function NodeConfigPanel({
|
|
4100
5653
|
node,
|
|
4101
5654
|
binding,
|
|
@@ -4114,15 +5667,15 @@ function NodeConfigPanel({
|
|
|
4114
5667
|
padding: "20px",
|
|
4115
5668
|
...style
|
|
4116
5669
|
};
|
|
4117
|
-
return /* @__PURE__ */ (0,
|
|
4118
|
-
/* @__PURE__ */ (0,
|
|
5670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className, style: defaultStyle, children: [
|
|
5671
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
4119
5672
|
"Configure: ",
|
|
4120
5673
|
node.id
|
|
4121
5674
|
] }),
|
|
4122
|
-
/* @__PURE__ */ (0,
|
|
4123
|
-
/* @__PURE__ */ (0,
|
|
4124
|
-
/* @__PURE__ */ (0,
|
|
4125
|
-
/* @__PURE__ */ (0,
|
|
5675
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
5676
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
5677
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
5678
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4126
5679
|
"input",
|
|
4127
5680
|
{
|
|
4128
5681
|
type: "text",
|
|
@@ -4138,10 +5691,10 @@ function NodeConfigPanel({
|
|
|
4138
5691
|
}
|
|
4139
5692
|
}
|
|
4140
5693
|
),
|
|
4141
|
-
/* @__PURE__ */ (0,
|
|
4142
|
-
/* @__PURE__ */ (0,
|
|
4143
|
-
/* @__PURE__ */ (0,
|
|
4144
|
-
/* @__PURE__ */ (0,
|
|
5694
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5695
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5696
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
5697
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4145
5698
|
"input",
|
|
4146
5699
|
{
|
|
4147
5700
|
type: "number",
|
|
@@ -4162,9 +5715,9 @@ function NodeConfigPanel({
|
|
|
4162
5715
|
}
|
|
4163
5716
|
)
|
|
4164
5717
|
] }),
|
|
4165
|
-
/* @__PURE__ */ (0,
|
|
4166
|
-
/* @__PURE__ */ (0,
|
|
4167
|
-
/* @__PURE__ */ (0,
|
|
5718
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5719
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
5720
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4168
5721
|
"input",
|
|
4169
5722
|
{
|
|
4170
5723
|
type: "number",
|
|
@@ -4186,9 +5739,9 @@ function NodeConfigPanel({
|
|
|
4186
5739
|
)
|
|
4187
5740
|
] })
|
|
4188
5741
|
] }),
|
|
4189
|
-
/* @__PURE__ */ (0,
|
|
4190
|
-
/* @__PURE__ */ (0,
|
|
4191
|
-
/* @__PURE__ */ (0,
|
|
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 Font Size:" }),
|
|
5744
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4192
5745
|
"input",
|
|
4193
5746
|
{
|
|
4194
5747
|
type: "number",
|
|
@@ -4208,9 +5761,9 @@ function NodeConfigPanel({
|
|
|
4208
5761
|
}
|
|
4209
5762
|
)
|
|
4210
5763
|
] }),
|
|
4211
|
-
/* @__PURE__ */ (0,
|
|
4212
|
-
/* @__PURE__ */ (0,
|
|
4213
|
-
/* @__PURE__ */ (0,
|
|
5764
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5765
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
5766
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4214
5767
|
"input",
|
|
4215
5768
|
{
|
|
4216
5769
|
type: "number",
|
|
@@ -4235,9 +5788,9 @@ function NodeConfigPanel({
|
|
|
4235
5788
|
)
|
|
4236
5789
|
] })
|
|
4237
5790
|
] }),
|
|
4238
|
-
/* @__PURE__ */ (0,
|
|
4239
|
-
/* @__PURE__ */ (0,
|
|
4240
|
-
!binding ? /* @__PURE__ */ (0,
|
|
5791
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
5792
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
5793
|
+
!binding ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4241
5794
|
"button",
|
|
4242
5795
|
{
|
|
4243
5796
|
onClick: () => {
|
|
@@ -4280,9 +5833,9 @@ function NodeConfigPanel({
|
|
|
4280
5833
|
},
|
|
4281
5834
|
children: "+ Add Telemetry"
|
|
4282
5835
|
}
|
|
4283
|
-
) : /* @__PURE__ */ (0,
|
|
4284
|
-
/* @__PURE__ */ (0,
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
5836
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5837
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
5838
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4286
5839
|
"input",
|
|
4287
5840
|
{
|
|
4288
5841
|
type: "number",
|
|
@@ -4304,8 +5857,8 @@ function NodeConfigPanel({
|
|
|
4304
5857
|
}
|
|
4305
5858
|
}
|
|
4306
5859
|
),
|
|
4307
|
-
/* @__PURE__ */ (0,
|
|
4308
|
-
/* @__PURE__ */ (0,
|
|
5860
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
5861
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4309
5862
|
"input",
|
|
4310
5863
|
{
|
|
4311
5864
|
type: "text",
|
|
@@ -4327,8 +5880,8 @@ function NodeConfigPanel({
|
|
|
4327
5880
|
}
|
|
4328
5881
|
}
|
|
4329
5882
|
),
|
|
4330
|
-
/* @__PURE__ */ (0,
|
|
4331
|
-
/* @__PURE__ */ (0,
|
|
5883
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
5884
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4332
5885
|
"input",
|
|
4333
5886
|
{
|
|
4334
5887
|
type: "checkbox",
|
|
@@ -4350,8 +5903,8 @@ function NodeConfigPanel({
|
|
|
4350
5903
|
),
|
|
4351
5904
|
"Show Sparkline"
|
|
4352
5905
|
] }),
|
|
4353
|
-
/* @__PURE__ */ (0,
|
|
4354
|
-
/* @__PURE__ */ (0,
|
|
5906
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginTop: "12px" }, children: [
|
|
5907
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4355
5908
|
"label",
|
|
4356
5909
|
{
|
|
4357
5910
|
style: {
|
|
@@ -4363,10 +5916,10 @@ function NodeConfigPanel({
|
|
|
4363
5916
|
children: "Telemetry Position Offset:"
|
|
4364
5917
|
}
|
|
4365
5918
|
),
|
|
4366
|
-
/* @__PURE__ */ (0,
|
|
4367
|
-
/* @__PURE__ */ (0,
|
|
4368
|
-
/* @__PURE__ */ (0,
|
|
4369
|
-
/* @__PURE__ */ (0,
|
|
5919
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5920
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5921
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
5922
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4370
5923
|
"input",
|
|
4371
5924
|
{
|
|
4372
5925
|
type: "number",
|
|
@@ -4393,9 +5946,9 @@ function NodeConfigPanel({
|
|
|
4393
5946
|
}
|
|
4394
5947
|
)
|
|
4395
5948
|
] }),
|
|
4396
|
-
/* @__PURE__ */ (0,
|
|
4397
|
-
/* @__PURE__ */ (0,
|
|
4398
|
-
/* @__PURE__ */ (0,
|
|
5949
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5950
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
5951
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4399
5952
|
"input",
|
|
4400
5953
|
{
|
|
4401
5954
|
type: "number",
|
|
@@ -4423,8 +5976,8 @@ function NodeConfigPanel({
|
|
|
4423
5976
|
)
|
|
4424
5977
|
] })
|
|
4425
5978
|
] }),
|
|
4426
|
-
/* @__PURE__ */ (0,
|
|
4427
|
-
/* @__PURE__ */ (0,
|
|
5979
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginTop: "16px" }, children: [
|
|
5980
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4428
5981
|
"label",
|
|
4429
5982
|
{
|
|
4430
5983
|
style: {
|
|
@@ -4436,10 +5989,10 @@ function NodeConfigPanel({
|
|
|
4436
5989
|
children: "Display Colors:"
|
|
4437
5990
|
}
|
|
4438
5991
|
),
|
|
4439
|
-
/* @__PURE__ */ (0,
|
|
4440
|
-
/* @__PURE__ */ (0,
|
|
4441
|
-
/* @__PURE__ */ (0,
|
|
4442
|
-
/* @__PURE__ */ (0,
|
|
5992
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
5993
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
5994
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
5995
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4443
5996
|
"input",
|
|
4444
5997
|
{
|
|
4445
5998
|
type: "color",
|
|
@@ -4465,7 +6018,7 @@ function NodeConfigPanel({
|
|
|
4465
6018
|
}
|
|
4466
6019
|
}
|
|
4467
6020
|
),
|
|
4468
|
-
/* @__PURE__ */ (0,
|
|
6021
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4469
6022
|
"input",
|
|
4470
6023
|
{
|
|
4471
6024
|
type: "text",
|
|
@@ -4495,10 +6048,10 @@ function NodeConfigPanel({
|
|
|
4495
6048
|
)
|
|
4496
6049
|
] })
|
|
4497
6050
|
] }),
|
|
4498
|
-
binding.display?.showSparkline && /* @__PURE__ */ (0,
|
|
4499
|
-
/* @__PURE__ */ (0,
|
|
4500
|
-
/* @__PURE__ */ (0,
|
|
4501
|
-
/* @__PURE__ */ (0,
|
|
6051
|
+
binding.display?.showSparkline && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6052
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
6053
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6054
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4502
6055
|
"input",
|
|
4503
6056
|
{
|
|
4504
6057
|
type: "color",
|
|
@@ -4524,7 +6077,7 @@ function NodeConfigPanel({
|
|
|
4524
6077
|
}
|
|
4525
6078
|
}
|
|
4526
6079
|
),
|
|
4527
|
-
/* @__PURE__ */ (0,
|
|
6080
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4528
6081
|
"input",
|
|
4529
6082
|
{
|
|
4530
6083
|
type: "text",
|
|
@@ -4554,9 +6107,9 @@ function NodeConfigPanel({
|
|
|
4554
6107
|
)
|
|
4555
6108
|
] })
|
|
4556
6109
|
] }),
|
|
4557
|
-
/* @__PURE__ */ (0,
|
|
4558
|
-
/* @__PURE__ */ (0,
|
|
4559
|
-
/* @__PURE__ */ (0,
|
|
6110
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6111
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6112
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4560
6113
|
"input",
|
|
4561
6114
|
{
|
|
4562
6115
|
type: "text",
|
|
@@ -4584,20 +6137,20 @@ function NodeConfigPanel({
|
|
|
4584
6137
|
}
|
|
4585
6138
|
}
|
|
4586
6139
|
),
|
|
4587
|
-
/* @__PURE__ */ (0,
|
|
6140
|
+
/* @__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
6141
|
] })
|
|
4589
6142
|
] }),
|
|
4590
6143
|
" "
|
|
4591
6144
|
] })
|
|
4592
6145
|
] })
|
|
4593
6146
|
] }),
|
|
4594
|
-
binding && /* @__PURE__ */ (0,
|
|
4595
|
-
/* @__PURE__ */ (0,
|
|
6147
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6148
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
4596
6149
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
4597
6150
|
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,
|
|
6151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6152
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6153
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4601
6154
|
"input",
|
|
4602
6155
|
{
|
|
4603
6156
|
type: "number",
|
|
@@ -4621,8 +6174,8 @@ function NodeConfigPanel({
|
|
|
4621
6174
|
] }, key);
|
|
4622
6175
|
})
|
|
4623
6176
|
] }),
|
|
4624
|
-
binding && /* @__PURE__ */ (0,
|
|
4625
|
-
/* @__PURE__ */ (0,
|
|
6177
|
+
binding && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "20px" }, children: [
|
|
6178
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
4626
6179
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
4627
6180
|
const defaultColors = {
|
|
4628
6181
|
normal: "#10b981",
|
|
@@ -4632,13 +6185,13 @@ function NodeConfigPanel({
|
|
|
4632
6185
|
off: "#6b7280"
|
|
4633
6186
|
};
|
|
4634
6187
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
4635
|
-
return /* @__PURE__ */ (0,
|
|
4636
|
-
/* @__PURE__ */ (0,
|
|
6188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
6189
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
4637
6190
|
label,
|
|
4638
6191
|
":"
|
|
4639
6192
|
] }),
|
|
4640
|
-
/* @__PURE__ */ (0,
|
|
4641
|
-
/* @__PURE__ */ (0,
|
|
6193
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6194
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4642
6195
|
"input",
|
|
4643
6196
|
{
|
|
4644
6197
|
type: "color",
|
|
@@ -4659,7 +6212,7 @@ function NodeConfigPanel({
|
|
|
4659
6212
|
}
|
|
4660
6213
|
}
|
|
4661
6214
|
),
|
|
4662
|
-
/* @__PURE__ */ (0,
|
|
6215
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4663
6216
|
"input",
|
|
4664
6217
|
{
|
|
4665
6218
|
type: "text",
|
|
@@ -4686,7 +6239,7 @@ function NodeConfigPanel({
|
|
|
4686
6239
|
] }, status);
|
|
4687
6240
|
})
|
|
4688
6241
|
] }),
|
|
4689
|
-
/* @__PURE__ */ (0,
|
|
6242
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4690
6243
|
"button",
|
|
4691
6244
|
{
|
|
4692
6245
|
onClick: onRemove,
|
|
@@ -4926,7 +6479,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
4926
6479
|
};
|
|
4927
6480
|
|
|
4928
6481
|
// src/diagram/hooks/useSimulation.ts
|
|
4929
|
-
var
|
|
6482
|
+
var import_react17 = require("react");
|
|
4930
6483
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
4931
6484
|
const {
|
|
4932
6485
|
interval = 2e3,
|
|
@@ -4937,7 +6490,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
4937
6490
|
historyLength = 10,
|
|
4938
6491
|
generateValue
|
|
4939
6492
|
} = options;
|
|
4940
|
-
(0,
|
|
6493
|
+
(0, import_react17.useEffect)(() => {
|
|
4941
6494
|
if (!enabled) return;
|
|
4942
6495
|
const intervalId = setInterval(() => {
|
|
4943
6496
|
const updates = [];
|
|
@@ -5040,6 +6593,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
5040
6593
|
useSelection,
|
|
5041
6594
|
useSimulation,
|
|
5042
6595
|
useTelemetry,
|
|
6596
|
+
useTelemetryStatus,
|
|
5043
6597
|
useTheme,
|
|
5044
6598
|
useViewBox,
|
|
5045
6599
|
validateDiagram
|