@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.js
CHANGED
|
@@ -1694,35 +1694,10 @@ var ThemeToggle = ({
|
|
|
1694
1694
|
};
|
|
1695
1695
|
|
|
1696
1696
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
1697
|
-
import { useCallback as useCallback7, useState as
|
|
1697
|
+
import { useCallback as useCallback7, useState as useState12, useEffect as useEffect10, useRef as useRef5 } from "react";
|
|
1698
1698
|
|
|
1699
1699
|
// src/diagram/symbols/mockSymbolLibrary.ts
|
|
1700
1700
|
var mockSymbolLibrary = {
|
|
1701
|
-
"valve-ball": {
|
|
1702
|
-
id: "valve-ball",
|
|
1703
|
-
name: "Ball Valve",
|
|
1704
|
-
category: "valve",
|
|
1705
|
-
viewBox: { x: 0, y: 0, width: 50, height: 50 },
|
|
1706
|
-
ports: [
|
|
1707
|
-
{ id: "inlet", x: 0, y: 25, type: "inlet", direction: "in" },
|
|
1708
|
-
{ id: "outlet", x: 50, y: 25, type: "outlet", direction: "out" }
|
|
1709
|
-
],
|
|
1710
|
-
svgContent: `
|
|
1711
|
-
<g>
|
|
1712
|
-
<!-- Valve body -->
|
|
1713
|
-
<rect x="15" y="10" width="20" height="30" fill="#546e7a" stroke="#263238" stroke-width="2" rx="2"/>
|
|
1714
|
-
<!-- Ball indicator -->
|
|
1715
|
-
<circle cx="25" cy="25" r="6" fill="#ffa726" stroke="#e65100" stroke-width="1.5"/>
|
|
1716
|
-
<!-- Inlet/outlet lines -->
|
|
1717
|
-
<line x1="0" y1="25" x2="15" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1718
|
-
<line x1="35" y1="25" x2="50" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1719
|
-
</g>
|
|
1720
|
-
`,
|
|
1721
|
-
metadata: {
|
|
1722
|
-
description: "Ball valve for flow control",
|
|
1723
|
-
tags: ["valve", "control", "shutoff"]
|
|
1724
|
-
}
|
|
1725
|
-
},
|
|
1726
1701
|
"valve-gate": {
|
|
1727
1702
|
id: "valve-gate",
|
|
1728
1703
|
name: "Gate Valve (Powered)",
|
|
@@ -1735,11 +1710,11 @@ var mockSymbolLibrary = {
|
|
|
1735
1710
|
svgContent: `
|
|
1736
1711
|
<g>
|
|
1737
1712
|
<!-- Actuator box -->
|
|
1738
|
-
<rect x="16.74" y="0" width="18.02" height="18.02" fill="#edeeef" stroke="#666666" pointer-events="all"/>
|
|
1713
|
+
<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"/>
|
|
1739
1714
|
<!-- Actuator stem -->
|
|
1740
|
-
<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"/>
|
|
1715
|
+
<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"/>
|
|
1741
1716
|
<!-- Valve body (two triangles forming diamond) -->
|
|
1742
|
-
<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"/>
|
|
1717
|
+
<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"/>
|
|
1743
1718
|
</g>
|
|
1744
1719
|
`,
|
|
1745
1720
|
metadata: {
|
|
@@ -1747,84 +1722,1143 @@ var mockSymbolLibrary = {
|
|
|
1747
1722
|
tags: ["valve", "gate", "powered", "actuator"]
|
|
1748
1723
|
}
|
|
1749
1724
|
},
|
|
1750
|
-
"pump-
|
|
1751
|
-
id: "pump-
|
|
1752
|
-
name: "
|
|
1725
|
+
"pump-positive-displacement": {
|
|
1726
|
+
id: "pump-positive-displacement",
|
|
1727
|
+
name: "Positive Displacement Pump",
|
|
1753
1728
|
category: "pump",
|
|
1754
|
-
viewBox: { x: 0, y: 0, width:
|
|
1729
|
+
viewBox: { x: 0, y: 0, width: 56.25, height: 56.25 },
|
|
1730
|
+
ports: [
|
|
1731
|
+
{ id: "inlet", x: 0, y: 28.125, type: "inlet", direction: "in" },
|
|
1732
|
+
{ id: "outlet", x: 56.25, y: 28.125, type: "outlet", direction: "out" }
|
|
1733
|
+
],
|
|
1734
|
+
svgContent: `
|
|
1735
|
+
<g transform="scale(0.5625)">
|
|
1736
|
+
<!-- Outer circle -->
|
|
1737
|
+
<ellipse
|
|
1738
|
+
cx="50"
|
|
1739
|
+
cy="50"
|
|
1740
|
+
rx="50"
|
|
1741
|
+
ry="50"
|
|
1742
|
+
fill="var(--symbol-fill, #edeeef)"
|
|
1743
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1744
|
+
stroke-width="1"
|
|
1745
|
+
/>
|
|
1746
|
+
|
|
1747
|
+
<!-- Diagonal line from top to bottom-right -->
|
|
1748
|
+
<path
|
|
1749
|
+
d="M 50 0 L 100 50 L 50 100"
|
|
1750
|
+
fill="none"
|
|
1751
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1752
|
+
stroke-width="1"
|
|
1753
|
+
stroke-miterlimit="10"
|
|
1754
|
+
/>
|
|
1755
|
+
|
|
1756
|
+
<!-- Center square -->
|
|
1757
|
+
<rect
|
|
1758
|
+
x="35"
|
|
1759
|
+
y="35"
|
|
1760
|
+
width="30"
|
|
1761
|
+
height="30"
|
|
1762
|
+
fill="none"
|
|
1763
|
+
stroke="var(--symbol-stroke, rgb(0, 0, 0))"
|
|
1764
|
+
stroke-width="1"
|
|
1765
|
+
/>
|
|
1766
|
+
</g>
|
|
1767
|
+
`,
|
|
1768
|
+
metadata: {
|
|
1769
|
+
description: "Positive displacement pump (ISO standard)",
|
|
1770
|
+
tags: ["pump", "positive-displacement", "iso"]
|
|
1771
|
+
}
|
|
1772
|
+
},
|
|
1773
|
+
"vannefold-bottom": {
|
|
1774
|
+
id: "vannefold-bottom",
|
|
1775
|
+
name: "Vannefold Block (Bottom)",
|
|
1776
|
+
category: "valve",
|
|
1777
|
+
viewBox: { x: -0.5, y: -0.5, width: 88, height: 67.785156 },
|
|
1755
1778
|
ports: [
|
|
1756
|
-
{ id: "inlet", x:
|
|
1757
|
-
{ id: "outlet", x:
|
|
1779
|
+
{ id: "bottom-inlet", x: 0, y: 25, type: "control", direction: "in" },
|
|
1780
|
+
{ id: "top-outlet", x: 48, y: 65, type: "control", direction: "out" }
|
|
1758
1781
|
],
|
|
1759
1782
|
svgContent: `
|
|
1760
1783
|
<g>
|
|
1761
|
-
<!--
|
|
1762
|
-
<
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1784
|
+
<!-- Bottom inlet pipe -->
|
|
1785
|
+
<path
|
|
1786
|
+
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"
|
|
1787
|
+
fill="none"
|
|
1788
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1789
|
+
stroke-miterlimit="10"
|
|
1790
|
+
/>
|
|
1791
|
+
|
|
1792
|
+
<!-- Top outlet pipe -->
|
|
1793
|
+
<path
|
|
1794
|
+
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"
|
|
1795
|
+
fill="none"
|
|
1796
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1797
|
+
stroke-miterlimit="10"
|
|
1798
|
+
/>
|
|
1799
|
+
|
|
1800
|
+
<!-- Main block outer -->
|
|
1801
|
+
<rect
|
|
1802
|
+
x="7"
|
|
1803
|
+
y="0"
|
|
1804
|
+
width="80"
|
|
1805
|
+
height="59.785156"
|
|
1806
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1807
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1808
|
+
/>
|
|
1809
|
+
|
|
1810
|
+
<!-- Main block inner -->
|
|
1811
|
+
<rect
|
|
1812
|
+
x="9"
|
|
1813
|
+
y="2"
|
|
1814
|
+
width="76"
|
|
1815
|
+
height="55.785156"
|
|
1816
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1817
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1818
|
+
/>
|
|
1819
|
+
|
|
1820
|
+
<!-- Bolt holes -->
|
|
1821
|
+
<ellipse cx="15" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1822
|
+
<ellipse cx="15" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1823
|
+
<ellipse cx="79" cy="7" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1824
|
+
<ellipse cx="79" cy="7" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1825
|
+
<ellipse cx="15" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1826
|
+
<ellipse cx="15" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1827
|
+
<ellipse cx="79" cy="51.785156" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1828
|
+
<ellipse cx="79" cy="51.785156" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1829
|
+
|
|
1772
1830
|
</g>
|
|
1773
1831
|
`,
|
|
1774
1832
|
metadata: {
|
|
1775
|
-
description: "
|
|
1776
|
-
tags: ["
|
|
1833
|
+
description: "Vannefold heat exchanger block with bottom inlet configuration",
|
|
1834
|
+
tags: ["heat-exchanger", "vannefold", "fold", "bottom"]
|
|
1777
1835
|
}
|
|
1778
1836
|
},
|
|
1779
|
-
"
|
|
1780
|
-
id: "
|
|
1781
|
-
name: "
|
|
1782
|
-
category: "
|
|
1783
|
-
viewBox: { x: 0, y: 0, width:
|
|
1837
|
+
"vannefold-middle": {
|
|
1838
|
+
id: "vannefold-middle",
|
|
1839
|
+
name: "Vannefold Block (Middle)",
|
|
1840
|
+
category: "valve",
|
|
1841
|
+
viewBox: { x: -0.5, y: -0.5, width: 95, height: 53.097656 },
|
|
1784
1842
|
ports: [
|
|
1785
|
-
{ id: "inlet", x:
|
|
1786
|
-
{ id: "outlet", x:
|
|
1843
|
+
{ id: "left-inlet", x: 0, y: 27.3125, type: "control", direction: "in" },
|
|
1844
|
+
{ id: "right-outlet", x: 95, y: 27.3125, type: "control", direction: "out" }
|
|
1787
1845
|
],
|
|
1788
1846
|
svgContent: `
|
|
1789
1847
|
<g>
|
|
1790
|
-
<!--
|
|
1791
|
-
<
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
<!--
|
|
1799
|
-
<
|
|
1848
|
+
<!-- Left inlet pipe -->
|
|
1849
|
+
<path
|
|
1850
|
+
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"
|
|
1851
|
+
fill="none"
|
|
1852
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1853
|
+
stroke-miterlimit="10"
|
|
1854
|
+
/>
|
|
1855
|
+
|
|
1856
|
+
<!-- Main block outer -->
|
|
1857
|
+
<rect
|
|
1858
|
+
x="7"
|
|
1859
|
+
y="0"
|
|
1860
|
+
width="80"
|
|
1861
|
+
height="52.097656"
|
|
1862
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1863
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1864
|
+
/>
|
|
1865
|
+
|
|
1866
|
+
<!-- Main block inner -->
|
|
1867
|
+
<rect
|
|
1868
|
+
x="9"
|
|
1869
|
+
y="0"
|
|
1870
|
+
width="76"
|
|
1871
|
+
height="52.097656"
|
|
1872
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1873
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1874
|
+
/>
|
|
1875
|
+
|
|
1876
|
+
<!-- Bolt holes -->
|
|
1877
|
+
<ellipse cx="15" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1878
|
+
<ellipse cx="15" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1879
|
+
<ellipse cx="79" cy="5.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1880
|
+
<ellipse cx="79" cy="5.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1881
|
+
<ellipse cx="15" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1882
|
+
<ellipse cx="15" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1883
|
+
<ellipse cx="79" cy="47.3125" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1884
|
+
<ellipse cx="79" cy="47.3125" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1800
1885
|
</g>
|
|
1801
1886
|
`,
|
|
1802
1887
|
metadata: {
|
|
1803
|
-
description: "
|
|
1804
|
-
tags: ["
|
|
1888
|
+
description: "Vannefold heat exchanger block with side inlet configuration",
|
|
1889
|
+
tags: ["heat-exchanger", "vannefold", "fold", "middle"]
|
|
1805
1890
|
}
|
|
1806
1891
|
},
|
|
1807
|
-
"
|
|
1808
|
-
id: "
|
|
1809
|
-
name: "
|
|
1810
|
-
category: "
|
|
1811
|
-
viewBox: { x: 0, y: 0, width:
|
|
1892
|
+
"vannefold-top": {
|
|
1893
|
+
id: "vannefold-top",
|
|
1894
|
+
name: "Vannefold Block (Top)",
|
|
1895
|
+
category: "valve",
|
|
1896
|
+
viewBox: { x: -0.5, y: -0.5, width: 95, height: 60.785156 },
|
|
1897
|
+
ports: [
|
|
1898
|
+
{ id: "bottom-inlet", x: 0, y: 35, type: "control", direction: "in" },
|
|
1899
|
+
{ id: "top-outlet", x: 48, y: 0, type: "control", direction: "out" }
|
|
1900
|
+
],
|
|
1901
|
+
svgContent: `
|
|
1902
|
+
<g>
|
|
1903
|
+
<!-- Bottom inlet pipe -->
|
|
1904
|
+
<path
|
|
1905
|
+
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"
|
|
1906
|
+
fill="none"
|
|
1907
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1908
|
+
stroke-miterlimit="10"
|
|
1909
|
+
/>
|
|
1910
|
+
|
|
1911
|
+
<!-- Main block outer -->
|
|
1912
|
+
<rect
|
|
1913
|
+
x="7"
|
|
1914
|
+
y="0"
|
|
1915
|
+
width="80"
|
|
1916
|
+
height="59.785156"
|
|
1917
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1918
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1919
|
+
/>
|
|
1920
|
+
|
|
1921
|
+
<!-- Main block inner -->
|
|
1922
|
+
<rect
|
|
1923
|
+
x="9"
|
|
1924
|
+
y="2"
|
|
1925
|
+
width="76"
|
|
1926
|
+
height="57.785156"
|
|
1927
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1928
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1929
|
+
/>
|
|
1930
|
+
|
|
1931
|
+
<!-- Bolt holes -->
|
|
1932
|
+
<ellipse cx="15" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1933
|
+
<ellipse cx="15" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1934
|
+
<ellipse cx="79" cy="8" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1935
|
+
<ellipse cx="79" cy="8" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1936
|
+
<ellipse cx="15" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1937
|
+
<ellipse cx="15" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1938
|
+
<ellipse cx="79" cy="55" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1939
|
+
<ellipse cx="79" cy="55" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1940
|
+
|
|
1941
|
+
</g>
|
|
1942
|
+
`,
|
|
1943
|
+
metadata: {
|
|
1944
|
+
description: "Vannefold heat exchanger block with bottom inlet and top outlet configuration",
|
|
1945
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top"]
|
|
1946
|
+
}
|
|
1947
|
+
},
|
|
1948
|
+
"vannefold-top-top-inlet": {
|
|
1949
|
+
id: "vannefold-top-top-inlet",
|
|
1950
|
+
name: "Vannefold Block (Top, Top Inlet)",
|
|
1951
|
+
category: "valve",
|
|
1952
|
+
viewBox: { x: 0, y: 0, width: 88, height: 67.576004 },
|
|
1953
|
+
ports: [
|
|
1954
|
+
{ id: "top-inlet", x: 47, y: 0, type: "control", direction: "in" },
|
|
1955
|
+
{ id: "bottom-outlet", x: 0, y: 42, type: "control", direction: "out" }
|
|
1956
|
+
],
|
|
1957
|
+
svgContent: `
|
|
1958
|
+
<g>
|
|
1959
|
+
<!-- Top inlet pipe flange -->
|
|
1960
|
+
<path
|
|
1961
|
+
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"
|
|
1962
|
+
fill="none"
|
|
1963
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1964
|
+
stroke-miterlimit="10"
|
|
1965
|
+
/>
|
|
1966
|
+
|
|
1967
|
+
<!-- Bottom outlet pipe flange -->
|
|
1968
|
+
<path
|
|
1969
|
+
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"
|
|
1970
|
+
fill="none"
|
|
1971
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1972
|
+
stroke-miterlimit="10"
|
|
1973
|
+
/>
|
|
1974
|
+
|
|
1975
|
+
<!-- Main block outer -->
|
|
1976
|
+
<rect
|
|
1977
|
+
x="7"
|
|
1978
|
+
y="6.7908498"
|
|
1979
|
+
width="80"
|
|
1980
|
+
height="59.785156"
|
|
1981
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1982
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1983
|
+
/>
|
|
1984
|
+
|
|
1985
|
+
<!-- Main block inner -->
|
|
1986
|
+
<rect
|
|
1987
|
+
x="9"
|
|
1988
|
+
y="8.7908498"
|
|
1989
|
+
width="76"
|
|
1990
|
+
height="57.785156"
|
|
1991
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
1992
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
1993
|
+
/>
|
|
1994
|
+
|
|
1995
|
+
<!-- Bolt holes -->
|
|
1996
|
+
<ellipse cx="15" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1997
|
+
<ellipse cx="15" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
1998
|
+
<ellipse cx="15" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
1999
|
+
<ellipse cx="15" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2000
|
+
<ellipse cx="79" cy="14.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2001
|
+
<ellipse cx="79" cy="14.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2002
|
+
<ellipse cx="79" cy="61.79085" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2003
|
+
<ellipse cx="79" cy="61.79085" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2004
|
+
|
|
2005
|
+
</g>
|
|
2006
|
+
`,
|
|
2007
|
+
metadata: {
|
|
2008
|
+
description: "Vannefold heat exchanger block with top inlet and bottom outlet configuration",
|
|
2009
|
+
tags: ["heat-exchanger", "vannefold", "fold", "top", "top-inlet"]
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
"vannefold-left": {
|
|
2013
|
+
id: "vannefold-left",
|
|
2014
|
+
name: "Vannefold Block (Left)",
|
|
2015
|
+
category: "valve",
|
|
2016
|
+
viewBox: { x: 0, y: 0, width: 67.785156, height: 88.5 },
|
|
1812
2017
|
ports: [
|
|
1813
|
-
{ id: "
|
|
2018
|
+
{ id: "left-inlet", x: 0, y: 41.5, type: "control", direction: "in" },
|
|
2019
|
+
{ id: "right-outlet", x: 42, y: 87, type: "control", direction: "out" }
|
|
1814
2020
|
],
|
|
1815
2021
|
svgContent: `
|
|
1816
2022
|
<g>
|
|
1817
|
-
<!--
|
|
1818
|
-
<
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
2023
|
+
<!-- Left inlet pipe flange -->
|
|
2024
|
+
<path
|
|
2025
|
+
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"
|
|
2026
|
+
fill="none"
|
|
2027
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2028
|
+
stroke-miterlimit="10"
|
|
2029
|
+
/>
|
|
2030
|
+
|
|
2031
|
+
<!-- Right outlet pipe flange -->
|
|
2032
|
+
<path
|
|
2033
|
+
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"
|
|
2034
|
+
fill="none"
|
|
2035
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2036
|
+
stroke-miterlimit="10"
|
|
2037
|
+
/>
|
|
2038
|
+
|
|
2039
|
+
<!-- Main block outer -->
|
|
2040
|
+
<rect
|
|
2041
|
+
x="7"
|
|
2042
|
+
y="0.5"
|
|
2043
|
+
width="59.785156"
|
|
2044
|
+
height="80"
|
|
2045
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2046
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2047
|
+
/>
|
|
2048
|
+
|
|
2049
|
+
<!-- Main block inner -->
|
|
2050
|
+
<rect
|
|
2051
|
+
x="9"
|
|
2052
|
+
y="2.5"
|
|
2053
|
+
width="57.785156"
|
|
2054
|
+
height="76"
|
|
2055
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2056
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2057
|
+
/>
|
|
2058
|
+
|
|
2059
|
+
<!-- Bolt holes -->
|
|
2060
|
+
<ellipse cx="15" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2061
|
+
<ellipse cx="15" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2062
|
+
<ellipse cx="62" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2063
|
+
<ellipse cx="62" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2064
|
+
<ellipse cx="15" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2065
|
+
<ellipse cx="15" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2066
|
+
<ellipse cx="62" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2067
|
+
<ellipse cx="62" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2068
|
+
|
|
2069
|
+
`,
|
|
2070
|
+
metadata: {
|
|
2071
|
+
description: "Vannefold heat exchanger block with left inlet and right outlet, vertical orientation",
|
|
2072
|
+
tags: ["heat-exchanger", "vannefold", "fold", "left", "vertical"]
|
|
2073
|
+
}
|
|
2074
|
+
},
|
|
2075
|
+
"vannefold-right": {
|
|
2076
|
+
id: "vannefold-right",
|
|
2077
|
+
name: "Vannefold Block (Right)",
|
|
2078
|
+
category: "valve",
|
|
2079
|
+
viewBox: { x: 0, y: 0, width: 67.785156, height: 88.5 },
|
|
2080
|
+
ports: [
|
|
2081
|
+
{ id: "right-inlet", x: 67.785156, y: 41.5, type: "control", direction: "in" },
|
|
2082
|
+
{ id: "left-outlet", x: 24.785156, y: 87.5, type: "control", direction: "out" }
|
|
2083
|
+
],
|
|
2084
|
+
svgContent: `
|
|
2085
|
+
<g>
|
|
2086
|
+
<!-- Right inlet pipe flange -->
|
|
2087
|
+
<path
|
|
2088
|
+
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"
|
|
2089
|
+
fill="none"
|
|
2090
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2091
|
+
stroke-miterlimit="10"
|
|
2092
|
+
/>
|
|
2093
|
+
|
|
2094
|
+
<!-- Left outlet pipe flange -->
|
|
2095
|
+
<path
|
|
2096
|
+
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"
|
|
2097
|
+
fill="none"
|
|
2098
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2099
|
+
stroke-miterlimit="10"
|
|
2100
|
+
/>
|
|
2101
|
+
|
|
2102
|
+
<!-- Main block outer -->
|
|
2103
|
+
<rect
|
|
2104
|
+
x="0"
|
|
2105
|
+
y="0.5"
|
|
2106
|
+
width="59.785156"
|
|
2107
|
+
height="80"
|
|
2108
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2109
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2110
|
+
/>
|
|
2111
|
+
|
|
2112
|
+
<!-- Main block inner -->
|
|
2113
|
+
<rect
|
|
2114
|
+
x="0"
|
|
2115
|
+
y="2.5"
|
|
2116
|
+
width="57.785156"
|
|
2117
|
+
height="76"
|
|
2118
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2119
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2120
|
+
/>
|
|
2121
|
+
|
|
2122
|
+
<!-- Bolt holes -->
|
|
2123
|
+
<ellipse cx="51.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2124
|
+
<ellipse cx="51.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2125
|
+
<ellipse cx="4.785156" cy="8.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2126
|
+
<ellipse cx="4.785156" cy="8.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2127
|
+
<ellipse cx="51.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2128
|
+
<ellipse cx="51.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2129
|
+
<ellipse cx="4.785156" cy="72.5" rx="5" ry="5" fill="#ffffff" stroke="var(--symbol-stroke, #000000)" />
|
|
2130
|
+
<ellipse cx="4.785156" cy="72.5" rx="3" ry="3" fill="none" stroke="var(--symbol-stroke, #000000)" />
|
|
2131
|
+
|
|
2132
|
+
`,
|
|
2133
|
+
metadata: {
|
|
2134
|
+
description: "Vannefold heat exchanger block with right inlet and left outlet, vertical orientation",
|
|
2135
|
+
tags: ["heat-exchanger", "vannefold", "fold", "right", "vertical"]
|
|
2136
|
+
}
|
|
2137
|
+
},
|
|
2138
|
+
"pixer": {
|
|
2139
|
+
id: "pixer",
|
|
2140
|
+
name: "Pixer",
|
|
2141
|
+
category: "pump",
|
|
2142
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 46.6875 },
|
|
2143
|
+
ports: [
|
|
2144
|
+
{ id: "right-outlet", x: 50.625, y: 30.9375, type: "control", direction: "out" },
|
|
2145
|
+
{ id: "left-outlet", x: 0, y: 30.9375, type: "control", direction: "out" },
|
|
2146
|
+
{ id: "left-inlet", x: 50.625, y: 19.6875, type: "control", direction: "in" },
|
|
2147
|
+
{ id: "right-inlet", x: 0, y: 19.6875, type: "control", direction: "in" },
|
|
2148
|
+
{ id: "top-inlet", x: 25.3125, y: 0, type: "control", direction: "in" }
|
|
2149
|
+
],
|
|
2150
|
+
svgContent: `
|
|
2151
|
+
<g transform="scale(0.196875) translate(-195, -186)">
|
|
2152
|
+
<!-- Top mounting flange -->
|
|
2153
|
+
<rect
|
|
2154
|
+
width="141.313"
|
|
2155
|
+
height="9.872"
|
|
2156
|
+
transform="translate(252.392 185.89)"
|
|
2157
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2158
|
+
stroke-miterlimit="10"
|
|
2159
|
+
stroke-width="1"
|
|
2160
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2161
|
+
/>
|
|
2162
|
+
|
|
2163
|
+
<!-- Motor housing top -->
|
|
2164
|
+
<rect
|
|
2165
|
+
width="106.614"
|
|
2166
|
+
height="2.468"
|
|
2167
|
+
transform="translate(269.742 199.918)"
|
|
2168
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2169
|
+
stroke-miterlimit="10"
|
|
2170
|
+
stroke-width="1"
|
|
2171
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2172
|
+
/>
|
|
2173
|
+
<rect
|
|
2174
|
+
width="106.614"
|
|
2175
|
+
height="5.835"
|
|
2176
|
+
transform="translate(269.742 202.384)"
|
|
2177
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2178
|
+
stroke-miterlimit="10"
|
|
2179
|
+
stroke-width="1"
|
|
2180
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2181
|
+
/>
|
|
2182
|
+
<rect
|
|
2183
|
+
width="106.614"
|
|
2184
|
+
height="2.468"
|
|
2185
|
+
transform="translate(269.742 208.222)"
|
|
2186
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2187
|
+
stroke-miterlimit="10"
|
|
2188
|
+
stroke-width="1"
|
|
2189
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2190
|
+
/>
|
|
2191
|
+
|
|
2192
|
+
<!-- Bottom mounting flange -->
|
|
2193
|
+
<rect
|
|
2194
|
+
width="221.702"
|
|
2195
|
+
height="2.401"
|
|
2196
|
+
transform="translate(212.199 395.587)"
|
|
2197
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2198
|
+
stroke-miterlimit="10"
|
|
2199
|
+
stroke-width="1"
|
|
2200
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2201
|
+
/>
|
|
2202
|
+
<rect
|
|
2203
|
+
width="221.702"
|
|
2204
|
+
height="6.269"
|
|
2205
|
+
transform="translate(212.199 397.988)"
|
|
2206
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2207
|
+
stroke-miterlimit="10"
|
|
2208
|
+
stroke-width="1"
|
|
2209
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2210
|
+
/>
|
|
2211
|
+
<rect
|
|
2212
|
+
width="221.702"
|
|
2213
|
+
height="2.65"
|
|
2214
|
+
transform="translate(212.199 404.257)"
|
|
2215
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2216
|
+
stroke-miterlimit="10"
|
|
2217
|
+
stroke-width="1"
|
|
2218
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2219
|
+
/>
|
|
2220
|
+
|
|
2221
|
+
<!-- Motor housing transition -->
|
|
2222
|
+
<path
|
|
2223
|
+
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"
|
|
2224
|
+
transform="translate(-192.059 -32.959)"
|
|
2225
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2226
|
+
stroke-miterlimit="10"
|
|
2227
|
+
stroke-width="1"
|
|
2228
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2229
|
+
/>
|
|
2230
|
+
|
|
2231
|
+
<!-- Bottom flange -->
|
|
2232
|
+
<rect
|
|
2233
|
+
width="256"
|
|
2234
|
+
height="9.872"
|
|
2235
|
+
transform="translate(195.05 411.066)"
|
|
2236
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2237
|
+
stroke-miterlimit="10"
|
|
2238
|
+
stroke-width="1"
|
|
2239
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2240
|
+
/>
|
|
2241
|
+
<path
|
|
2242
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2243
|
+
transform="translate(0 -737.221)"
|
|
2244
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2245
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2246
|
+
stroke-miterlimit="10"
|
|
2247
|
+
stroke-width="1"
|
|
2248
|
+
/>
|
|
2249
|
+
|
|
2250
|
+
<!-- Vessel top cone -->
|
|
2251
|
+
<path
|
|
2252
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2253
|
+
transform="translate(0 -82.72)"
|
|
2254
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2255
|
+
stroke-miterlimit="10"
|
|
2256
|
+
stroke-width="1"
|
|
2257
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2258
|
+
/>
|
|
2259
|
+
|
|
2260
|
+
<!-- Main vessel body -->
|
|
2261
|
+
<rect
|
|
2262
|
+
width="256"
|
|
2263
|
+
height="59.803"
|
|
2264
|
+
transform="translate(195.05 245.636)"
|
|
2265
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2266
|
+
stroke-miterlimit="10"
|
|
2267
|
+
stroke-width="1"
|
|
2268
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2269
|
+
/>
|
|
2270
|
+
<rect
|
|
2271
|
+
width="256"
|
|
2272
|
+
height="76.892"
|
|
2273
|
+
transform="translate(195.05 308.417)"
|
|
2274
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2275
|
+
stroke-miterlimit="10"
|
|
2276
|
+
stroke-width="1"
|
|
2277
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2278
|
+
/>
|
|
2279
|
+
|
|
2280
|
+
<!-- Vessel bottom transitions -->
|
|
2281
|
+
<path
|
|
2282
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2283
|
+
transform="translate(-0.049 -398.769)"
|
|
2284
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2285
|
+
stroke-miterlimit="10"
|
|
2286
|
+
stroke-width="1"
|
|
2287
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2288
|
+
/>
|
|
2289
|
+
<path
|
|
2290
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2291
|
+
transform="translate(-0.062 -403.731)"
|
|
2292
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2293
|
+
stroke-miterlimit="10"
|
|
2294
|
+
stroke-width="1"
|
|
2295
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2296
|
+
/>
|
|
2297
|
+
<path
|
|
2298
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2299
|
+
transform="translate(0 -665.171)"
|
|
2300
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2301
|
+
stroke-miterlimit="10"
|
|
2302
|
+
stroke-width="1"
|
|
2303
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2304
|
+
/>
|
|
2305
|
+
|
|
2306
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2307
|
+
<ellipse
|
|
2308
|
+
cx="15.454"
|
|
2309
|
+
cy="6.096"
|
|
2310
|
+
rx="15.454"
|
|
2311
|
+
ry="6.096"
|
|
2312
|
+
transform="translate(307.486 228.161)"
|
|
2313
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2314
|
+
stroke-miterlimit="10"
|
|
2315
|
+
stroke-width="1"
|
|
2316
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2317
|
+
/>
|
|
2318
|
+
<ellipse
|
|
2319
|
+
cx="15.454"
|
|
2320
|
+
cy="5.3"
|
|
2321
|
+
rx="15.454"
|
|
2322
|
+
ry="5.3"
|
|
2323
|
+
transform="translate(307.486 229.753)"
|
|
2324
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2325
|
+
stroke-miterlimit="10"
|
|
2326
|
+
stroke-width="1"
|
|
2327
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2328
|
+
/>
|
|
2329
|
+
<ellipse
|
|
2330
|
+
cx="5.174"
|
|
2331
|
+
cy="15.117"
|
|
2332
|
+
rx="5.174"
|
|
2333
|
+
ry="15.117"
|
|
2334
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2335
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2336
|
+
stroke-miterlimit="10"
|
|
2337
|
+
stroke-width="1"
|
|
2338
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2339
|
+
/>
|
|
2340
|
+
<path
|
|
2341
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2342
|
+
transform="translate(-578.512 -147.764)"
|
|
2343
|
+
fill="none"
|
|
2344
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2345
|
+
stroke-miterlimit="10"
|
|
2346
|
+
stroke-width="1"
|
|
2347
|
+
/>
|
|
2348
|
+
<ellipse
|
|
2349
|
+
cx="15.117"
|
|
2350
|
+
cy="5.174"
|
|
2351
|
+
rx="15.117"
|
|
2352
|
+
ry="5.174"
|
|
2353
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2354
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2355
|
+
stroke-miterlimit="10"
|
|
2356
|
+
stroke-width="1"
|
|
2357
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2358
|
+
/>
|
|
2359
|
+
<path
|
|
2360
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2361
|
+
transform="translate(-179.058 -147.764)"
|
|
2362
|
+
fill="none"
|
|
2363
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2364
|
+
stroke-miterlimit="10"
|
|
2365
|
+
stroke-width="1"
|
|
2366
|
+
/>
|
|
2367
|
+
<ellipse
|
|
2368
|
+
cx="1.651"
|
|
2369
|
+
cy="15.082"
|
|
2370
|
+
rx="1.651"
|
|
2371
|
+
ry="15.082"
|
|
2372
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2373
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2374
|
+
stroke-miterlimit="10"
|
|
2375
|
+
stroke-width="1"
|
|
2376
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2377
|
+
/>
|
|
2378
|
+
<path
|
|
2379
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2380
|
+
transform="translate(-710.84 -145.969)"
|
|
2381
|
+
fill="none"
|
|
2382
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2383
|
+
stroke-miterlimit="10"
|
|
2384
|
+
stroke-width="1"
|
|
2385
|
+
/>
|
|
2386
|
+
<ellipse
|
|
2387
|
+
cx="15.082"
|
|
2388
|
+
cy="1.651"
|
|
2389
|
+
rx="15.082"
|
|
2390
|
+
ry="1.651"
|
|
2391
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2392
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2393
|
+
stroke-miterlimit="10"
|
|
2394
|
+
stroke-width="1"
|
|
2395
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2396
|
+
/>
|
|
2397
|
+
<path
|
|
2398
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2399
|
+
transform="translate(-55.932 -145.969)"
|
|
2400
|
+
fill="none"
|
|
2401
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2402
|
+
stroke-miterlimit="10"
|
|
2403
|
+
stroke-width="1"
|
|
2404
|
+
/>
|
|
2405
|
+
</g>
|
|
2406
|
+
`,
|
|
2407
|
+
metadata: {
|
|
2408
|
+
description: "Pixer mixer/agitator vessel with top-mounted drive",
|
|
2409
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank"]
|
|
2410
|
+
}
|
|
2411
|
+
},
|
|
2412
|
+
"pixer-barb": {
|
|
2413
|
+
id: "pixer-barb",
|
|
2414
|
+
name: "Pixer (Hose Barb)",
|
|
2415
|
+
category: "pump",
|
|
2416
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 46.6875 },
|
|
2417
|
+
ports: [
|
|
2418
|
+
{ id: "right-outlet", x: 50.625, y: 30.9375, type: "control", direction: "out" },
|
|
2419
|
+
{ id: "left-outlet", x: 0, y: 30.9375, type: "control", direction: "out" },
|
|
2420
|
+
{ id: "left-inlet", x: 50.625, y: 19.6875, type: "control", direction: "in" },
|
|
2421
|
+
{ id: "right-inlet", x: 0, y: 19.6875, type: "control", direction: "in" },
|
|
2422
|
+
{ id: "top-inlet", x: 25.3125, y: 0, type: "control", direction: "in" }
|
|
2423
|
+
],
|
|
2424
|
+
svgContent: `
|
|
2425
|
+
<g transform="scale(0.196875) translate(-195, -186)">
|
|
2426
|
+
<!-- Hose barb ridges at top -->
|
|
2427
|
+
<rect
|
|
2428
|
+
width="20"
|
|
2429
|
+
height="2"
|
|
2430
|
+
transform="translate(313 173)"
|
|
2431
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2432
|
+
stroke-miterlimit="10"
|
|
2433
|
+
stroke-width="0.5"
|
|
2434
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2435
|
+
/>
|
|
2436
|
+
<rect
|
|
2437
|
+
width="20"
|
|
2438
|
+
height="2"
|
|
2439
|
+
transform="translate(313 177)"
|
|
2440
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2441
|
+
stroke-miterlimit="10"
|
|
2442
|
+
stroke-width="0.5"
|
|
2443
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2444
|
+
/>
|
|
2445
|
+
<rect
|
|
2446
|
+
width="20"
|
|
2447
|
+
height="2"
|
|
2448
|
+
transform="translate(313 181)"
|
|
2449
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2450
|
+
stroke-miterlimit="10"
|
|
2451
|
+
stroke-width="0.5"
|
|
2452
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2453
|
+
/>
|
|
2454
|
+
|
|
2455
|
+
<!-- Taper from barb to motor housing -->
|
|
2456
|
+
<path
|
|
2457
|
+
d="M 313,183 L 269.742,199.918 L 376.356,199.918 L 333,183 Z"
|
|
2458
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2459
|
+
stroke-miterlimit="10"
|
|
2460
|
+
stroke-width="1"
|
|
2461
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2462
|
+
/>
|
|
2463
|
+
|
|
2464
|
+
<!-- Motor housing top -->
|
|
2465
|
+
<rect
|
|
2466
|
+
width="106.614"
|
|
2467
|
+
height="2.468"
|
|
2468
|
+
transform="translate(269.742 199.918)"
|
|
2469
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2470
|
+
stroke-miterlimit="10"
|
|
2471
|
+
stroke-width="1"
|
|
2472
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2473
|
+
/>
|
|
2474
|
+
<rect
|
|
2475
|
+
width="106.614"
|
|
2476
|
+
height="5.835"
|
|
2477
|
+
transform="translate(269.742 202.384)"
|
|
2478
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2479
|
+
stroke-miterlimit="10"
|
|
2480
|
+
stroke-width="1"
|
|
2481
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2482
|
+
/>
|
|
2483
|
+
<rect
|
|
2484
|
+
width="106.614"
|
|
2485
|
+
height="2.468"
|
|
2486
|
+
transform="translate(269.742 208.222)"
|
|
2487
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2488
|
+
stroke-miterlimit="10"
|
|
2489
|
+
stroke-width="1"
|
|
2490
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2491
|
+
/>
|
|
2492
|
+
|
|
2493
|
+
<!-- Bottom mounting flange -->
|
|
2494
|
+
<rect
|
|
2495
|
+
width="221.702"
|
|
2496
|
+
height="2.401"
|
|
2497
|
+
transform="translate(212.199 395.587)"
|
|
2498
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2499
|
+
stroke-miterlimit="10"
|
|
2500
|
+
stroke-width="1"
|
|
2501
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2502
|
+
/>
|
|
2503
|
+
<rect
|
|
2504
|
+
width="221.702"
|
|
2505
|
+
height="6.269"
|
|
2506
|
+
transform="translate(212.199 397.988)"
|
|
2507
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2508
|
+
stroke-miterlimit="10"
|
|
2509
|
+
stroke-width="1"
|
|
2510
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2511
|
+
/>
|
|
2512
|
+
<rect
|
|
2513
|
+
width="221.702"
|
|
2514
|
+
height="2.65"
|
|
2515
|
+
transform="translate(212.199 404.257)"
|
|
2516
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2517
|
+
stroke-miterlimit="10"
|
|
2518
|
+
stroke-width="1"
|
|
2519
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2520
|
+
/>
|
|
2521
|
+
|
|
2522
|
+
<!-- Bottom flange -->
|
|
2523
|
+
<rect
|
|
2524
|
+
width="256"
|
|
2525
|
+
height="9.872"
|
|
2526
|
+
transform="translate(195.05 411.066)"
|
|
2527
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2528
|
+
stroke-miterlimit="10"
|
|
2529
|
+
stroke-width="1"
|
|
2530
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2531
|
+
/>
|
|
2532
|
+
<path
|
|
2533
|
+
d="M195.05,1148.286l17.149-4.156H433.9l17.149,4.156Z"
|
|
2534
|
+
transform="translate(0 -737.221)"
|
|
2535
|
+
fill="var(--symbol-fill, #e2e2e2)"
|
|
2536
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2537
|
+
stroke-miterlimit="10"
|
|
2538
|
+
stroke-width="1"
|
|
2539
|
+
/>
|
|
2540
|
+
|
|
2541
|
+
<!-- Vessel top cone -->
|
|
2542
|
+
<path
|
|
2543
|
+
d="M451.05,328.356h-256l74.692-34.946H376.358Z"
|
|
2544
|
+
transform="translate(0 -82.72)"
|
|
2545
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2546
|
+
stroke-miterlimit="10"
|
|
2547
|
+
stroke-width="1"
|
|
2548
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2549
|
+
/>
|
|
2550
|
+
|
|
2551
|
+
<!-- Main vessel body -->
|
|
2552
|
+
<rect
|
|
2553
|
+
width="256"
|
|
2554
|
+
height="59.803"
|
|
2555
|
+
transform="translate(195.05 245.636)"
|
|
2556
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2557
|
+
stroke-miterlimit="10"
|
|
2558
|
+
stroke-width="1"
|
|
2559
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2560
|
+
/>
|
|
2561
|
+
<rect
|
|
2562
|
+
width="256"
|
|
2563
|
+
height="76.892"
|
|
2564
|
+
transform="translate(195.05 308.417)"
|
|
2565
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2566
|
+
stroke-miterlimit="10"
|
|
2567
|
+
stroke-width="1"
|
|
2568
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2569
|
+
/>
|
|
2570
|
+
|
|
2571
|
+
<!-- Vessel bottom transitions -->
|
|
2572
|
+
<path
|
|
2573
|
+
d="M449.265,705.7H196.773l-1.654-1.465a.014.014,0,0,1,0-.023H451.078Z"
|
|
2574
|
+
transform="translate(-0.049 -398.769)"
|
|
2575
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2576
|
+
stroke-miterlimit="10"
|
|
2577
|
+
stroke-width="1"
|
|
2578
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2579
|
+
/>
|
|
2580
|
+
<path
|
|
2581
|
+
d="M449.278,710.66H196.793l-1.663,1.462v.016H451.086s.012,0,0-.016Z"
|
|
2582
|
+
transform="translate(-0.062 -403.731)"
|
|
2583
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2584
|
+
stroke-miterlimit="10"
|
|
2585
|
+
stroke-width="1"
|
|
2586
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2587
|
+
/>
|
|
2588
|
+
<path
|
|
2589
|
+
d="M433.9,1060.758H212.2L195.05,1050.48h256Z"
|
|
2590
|
+
transform="translate(0 -665.171)"
|
|
2591
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2592
|
+
stroke-miterlimit="10"
|
|
2593
|
+
stroke-width="1"
|
|
2594
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2595
|
+
/>
|
|
2596
|
+
|
|
2597
|
+
<!-- Agitator blades/impellers (simplified without gradients) -->
|
|
2598
|
+
<ellipse
|
|
2599
|
+
cx="15.454"
|
|
2600
|
+
cy="6.096"
|
|
2601
|
+
rx="15.454"
|
|
2602
|
+
ry="6.096"
|
|
2603
|
+
transform="translate(307.486 228.161)"
|
|
2604
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2605
|
+
stroke-miterlimit="10"
|
|
2606
|
+
stroke-width="1"
|
|
2607
|
+
fill="var(--symbol-fill, #c0c0c0)"
|
|
2608
|
+
/>
|
|
2609
|
+
<ellipse
|
|
2610
|
+
cx="15.454"
|
|
2611
|
+
cy="5.3"
|
|
2612
|
+
rx="15.454"
|
|
2613
|
+
ry="5.3"
|
|
2614
|
+
transform="translate(307.486 229.753)"
|
|
2615
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2616
|
+
stroke-miterlimit="10"
|
|
2617
|
+
stroke-width="1"
|
|
2618
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2619
|
+
/>
|
|
2620
|
+
<ellipse
|
|
2621
|
+
cx="5.174"
|
|
2622
|
+
cy="15.117"
|
|
2623
|
+
rx="5.174"
|
|
2624
|
+
ry="15.117"
|
|
2625
|
+
transform="translate(367.144 236.079) rotate(-77.61)"
|
|
2626
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2627
|
+
stroke-miterlimit="10"
|
|
2628
|
+
stroke-width="1"
|
|
2629
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2630
|
+
/>
|
|
2631
|
+
<path
|
|
2632
|
+
d="M947,380.271s1.631-2.83,8.084-2.235c5.427.5,16.927,2.855,20.574,8.26"
|
|
2633
|
+
transform="translate(-578.512 -147.764)"
|
|
2634
|
+
fill="none"
|
|
2635
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2636
|
+
stroke-miterlimit="10"
|
|
2637
|
+
stroke-width="1"
|
|
2638
|
+
/>
|
|
2639
|
+
<ellipse
|
|
2640
|
+
cx="15.117"
|
|
2641
|
+
cy="5.174"
|
|
2642
|
+
rx="15.117"
|
|
2643
|
+
ry="5.174"
|
|
2644
|
+
transform="translate(247 232.438) rotate(-12.39)"
|
|
2645
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2646
|
+
stroke-miterlimit="10"
|
|
2647
|
+
stroke-width="1"
|
|
2648
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2649
|
+
/>
|
|
2650
|
+
<path
|
|
2651
|
+
d="M456.439,380.271s-1.631-2.83-8.073-2.235c-5.43.5-16.93,2.855-20.576,8.26"
|
|
2652
|
+
transform="translate(-179.058 -147.764)"
|
|
2653
|
+
fill="none"
|
|
2654
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2655
|
+
stroke-miterlimit="10"
|
|
2656
|
+
stroke-width="1"
|
|
2657
|
+
/>
|
|
2658
|
+
<ellipse
|
|
2659
|
+
cx="1.651"
|
|
2660
|
+
cy="15.082"
|
|
2661
|
+
rx="1.651"
|
|
2662
|
+
ry="15.082"
|
|
2663
|
+
transform="translate(406.71 230.174) rotate(-68.13)"
|
|
2664
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2665
|
+
stroke-miterlimit="10"
|
|
2666
|
+
stroke-width="1"
|
|
2667
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2668
|
+
/>
|
|
2669
|
+
<path
|
|
2670
|
+
d="M1119,375.62a119.876,119.876,0,0,1,26.193,10.419"
|
|
2671
|
+
transform="translate(-710.84 -145.969)"
|
|
2672
|
+
fill="none"
|
|
2673
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2674
|
+
stroke-miterlimit="10"
|
|
2675
|
+
stroke-width="1"
|
|
2676
|
+
/>
|
|
2677
|
+
<ellipse
|
|
2678
|
+
cx="15.082"
|
|
2679
|
+
cy="1.651"
|
|
2680
|
+
rx="15.082"
|
|
2681
|
+
ry="1.651"
|
|
2682
|
+
transform="translate(210.225 238.342) rotate(-21.87)"
|
|
2683
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2684
|
+
stroke-miterlimit="10"
|
|
2685
|
+
stroke-width="1"
|
|
2686
|
+
fill="var(--symbol-fill, #d0d0d0)"
|
|
2687
|
+
/>
|
|
2688
|
+
<path
|
|
2689
|
+
d="M293.943,375.62a119.829,119.829,0,0,0-26.193,10.419"
|
|
2690
|
+
transform="translate(-55.932 -145.969)"
|
|
2691
|
+
fill="none"
|
|
2692
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2693
|
+
stroke-miterlimit="10"
|
|
2694
|
+
stroke-width="1"
|
|
2695
|
+
/>
|
|
2696
|
+
</g>
|
|
2697
|
+
`,
|
|
2698
|
+
metadata: {
|
|
2699
|
+
description: "Pixer mixer/agitator vessel with tapered hose barb connection at top",
|
|
2700
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank", "hose-barb"]
|
|
2701
|
+
}
|
|
2702
|
+
},
|
|
2703
|
+
"vessel-balloon": {
|
|
2704
|
+
id: "vessel-balloon",
|
|
2705
|
+
name: "Vessel",
|
|
2706
|
+
category: "vessel",
|
|
2707
|
+
viewBox: { x: 0, y: 0, width: 50.625, height: 91 },
|
|
2708
|
+
ports: [
|
|
2709
|
+
{ id: "top", type: "inlet", x: 25.3125, y: 0 },
|
|
2710
|
+
{ id: "left", type: "inlet", x: 5, y: 39 },
|
|
2711
|
+
{ id: "right", type: "outlet", x: 45.625, y: 39 },
|
|
2712
|
+
{ id: "bottom", type: "outlet", x: 25.3125, y: 91 }
|
|
2713
|
+
],
|
|
2714
|
+
svgContent: `
|
|
2715
|
+
<g transform="scale(0.196875) translate(-195, -100)">
|
|
2716
|
+
<!-- Top opening nozzle -->
|
|
2717
|
+
<rect
|
|
2718
|
+
width="65"
|
|
2719
|
+
height="19.5"
|
|
2720
|
+
transform="translate(290.5, 100)"
|
|
2721
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2722
|
+
stroke-miterlimit="10"
|
|
2723
|
+
stroke-width="1"
|
|
2724
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2725
|
+
/>
|
|
2726
|
+
|
|
2727
|
+
<!-- Transition from nozzle to dome -->
|
|
2728
|
+
<path
|
|
2729
|
+
d="M 290.5,119.5 L 238,152 L 408,152 L 355.5,119.5 Z"
|
|
2730
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2731
|
+
stroke-miterlimit="10"
|
|
2732
|
+
stroke-width="1"
|
|
2733
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2734
|
+
/>
|
|
2735
|
+
|
|
2736
|
+
<!-- Upper balloon dome - rounded bulge -->
|
|
2737
|
+
<path
|
|
2738
|
+
d="M 238,152 C 185,210 150,320 180,395 L 466,395 C 496,320 461,210 408,152 Z"
|
|
2739
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2740
|
+
stroke-miterlimit="10"
|
|
2741
|
+
stroke-width="1"
|
|
2742
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2743
|
+
/>
|
|
2744
|
+
|
|
2745
|
+
<!-- Tapered vessel body -->
|
|
2746
|
+
<path
|
|
2747
|
+
d="M 180,395 L 269.742,530 L 376.356,530 L 466,395 Z"
|
|
2748
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2749
|
+
stroke-miterlimit="10"
|
|
2750
|
+
stroke-width="1"
|
|
2751
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2752
|
+
/>
|
|
2753
|
+
|
|
2754
|
+
<!-- Bottom cone -->
|
|
2755
|
+
<path
|
|
2756
|
+
d="M 269.742,530 L 280,555 L 366,555 L 376.356,530 Z"
|
|
2757
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2758
|
+
stroke-miterlimit="10"
|
|
2759
|
+
stroke-width="1"
|
|
2760
|
+
fill="var(--symbol-fill, #e0e0e0)"
|
|
2761
|
+
/>
|
|
2762
|
+
|
|
2763
|
+
<!-- Bottom flange matching pixer top dimensions -->
|
|
2764
|
+
<rect
|
|
2765
|
+
width="141.313"
|
|
2766
|
+
height="9.872"
|
|
2767
|
+
transform="translate(252.392, 555)"
|
|
2768
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2769
|
+
stroke-miterlimit="10"
|
|
2770
|
+
stroke-width="1"
|
|
2771
|
+
fill="var(--symbol-fill, #eaeaea)"
|
|
2772
|
+
/>
|
|
2773
|
+
</g>
|
|
2774
|
+
`,
|
|
2775
|
+
metadata: {
|
|
2776
|
+
description: "Balloon-shaped vessel with rounded top and tapered bottom, designed to fit on standard pixer",
|
|
2777
|
+
tags: ["vessel", "storage", "tank", "balloon"]
|
|
2778
|
+
}
|
|
2779
|
+
},
|
|
2780
|
+
"psr-f": {
|
|
2781
|
+
id: "psr-f",
|
|
2782
|
+
name: "PSR F",
|
|
2783
|
+
category: "instrument",
|
|
2784
|
+
viewBox: { x: 0, y: 0, width: 57, height: 57 },
|
|
2785
|
+
ports: [
|
|
2786
|
+
{ id: "top", type: "signal", x: 28.5, y: 14.25 },
|
|
2787
|
+
{ id: "right", type: "signal", x: 42.75, y: 28.5 },
|
|
2788
|
+
{ id: "bottom", type: "signal", x: 28.5, y: 42.75 },
|
|
2789
|
+
{ id: "left", type: "signal", x: 14.25, y: 28.5 }
|
|
2790
|
+
],
|
|
2791
|
+
svgContent: `
|
|
2792
|
+
<g transform="scale(0.5) translate(28.5, 28.5)">
|
|
2793
|
+
<!-- Circle background -->
|
|
2794
|
+
<ellipse
|
|
2795
|
+
cx="28.5"
|
|
2796
|
+
cy="28.5"
|
|
2797
|
+
rx="28.5"
|
|
2798
|
+
ry="28.5"
|
|
2799
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2800
|
+
stroke-width="1"
|
|
2801
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2802
|
+
/>
|
|
2803
|
+
|
|
2804
|
+
<!-- Letter F -->
|
|
2805
|
+
<text
|
|
2806
|
+
x="28.5"
|
|
2807
|
+
y="38"
|
|
2808
|
+
text-anchor="middle"
|
|
2809
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2810
|
+
font-size="34"
|
|
2811
|
+
font-weight="normal"
|
|
2812
|
+
font-style="italic"
|
|
2813
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2814
|
+
>F</text>
|
|
1823
2815
|
</g>
|
|
1824
2816
|
`,
|
|
1825
2817
|
metadata: {
|
|
1826
|
-
description: "
|
|
1827
|
-
tags: ["instrument", "
|
|
2818
|
+
description: "PSR F instrument symbol - Flow indicator",
|
|
2819
|
+
tags: ["instrument", "psr", "flow", "indicator"]
|
|
2820
|
+
}
|
|
2821
|
+
},
|
|
2822
|
+
"psr-p": {
|
|
2823
|
+
id: "psr-p",
|
|
2824
|
+
name: "PSR P",
|
|
2825
|
+
category: "instrument",
|
|
2826
|
+
viewBox: { x: 0, y: 0, width: 57, height: 57 },
|
|
2827
|
+
ports: [
|
|
2828
|
+
{ id: "top", type: "signal", x: 28.5, y: 14.25 },
|
|
2829
|
+
{ id: "right", type: "signal", x: 42.75, y: 28.5 },
|
|
2830
|
+
{ id: "bottom", type: "signal", x: 28.5, y: 42.75 },
|
|
2831
|
+
{ id: "left", type: "signal", x: 14.25, y: 28.5 }
|
|
2832
|
+
],
|
|
2833
|
+
svgContent: `
|
|
2834
|
+
<g transform="scale(0.5) translate(28.5, 28.5)">
|
|
2835
|
+
<!-- Circle background -->
|
|
2836
|
+
<ellipse
|
|
2837
|
+
cx="28.5"
|
|
2838
|
+
cy="28.5"
|
|
2839
|
+
rx="28.5"
|
|
2840
|
+
ry="28.5"
|
|
2841
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2842
|
+
stroke-width="1"
|
|
2843
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2844
|
+
/>
|
|
2845
|
+
|
|
2846
|
+
<!-- Letter P -->
|
|
2847
|
+
<text
|
|
2848
|
+
x="28.5"
|
|
2849
|
+
y="38"
|
|
2850
|
+
text-anchor="middle"
|
|
2851
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2852
|
+
font-size="34"
|
|
2853
|
+
font-weight="normal"
|
|
2854
|
+
font-style="italic"
|
|
2855
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2856
|
+
>P</text>
|
|
2857
|
+
</g>
|
|
2858
|
+
`,
|
|
2859
|
+
metadata: {
|
|
2860
|
+
description: "PSR P instrument symbol - Pressure indicator",
|
|
2861
|
+
tags: ["instrument", "psr", "pressure", "indicator"]
|
|
1828
2862
|
}
|
|
1829
2863
|
}
|
|
1830
2864
|
};
|
|
@@ -1904,6 +2938,24 @@ function NodeRenderer({
|
|
|
1904
2938
|
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
1905
2939
|
);
|
|
1906
2940
|
}
|
|
2941
|
+
const getStatusColor = (status) => {
|
|
2942
|
+
switch (status) {
|
|
2943
|
+
case "running":
|
|
2944
|
+
return "#22c55e";
|
|
2945
|
+
// Green
|
|
2946
|
+
case "alarm":
|
|
2947
|
+
return "#ef4444";
|
|
2948
|
+
// Red
|
|
2949
|
+
case "warning":
|
|
2950
|
+
return "#f59e0b";
|
|
2951
|
+
// Orange
|
|
2952
|
+
case "stopped":
|
|
2953
|
+
default:
|
|
2954
|
+
return "#edeeef";
|
|
2955
|
+
}
|
|
2956
|
+
};
|
|
2957
|
+
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
2958
|
+
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
1907
2959
|
return /* @__PURE__ */ jsxs9(
|
|
1908
2960
|
"g",
|
|
1909
2961
|
{
|
|
@@ -1912,6 +2964,11 @@ function NodeRenderer({
|
|
|
1912
2964
|
"data-selected": isSelected,
|
|
1913
2965
|
"data-dragging": isDragging,
|
|
1914
2966
|
transform: transforms.join(" "),
|
|
2967
|
+
style: {
|
|
2968
|
+
"--symbol-fill": fillColor,
|
|
2969
|
+
"--symbol-stroke": strokeColor,
|
|
2970
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
2971
|
+
},
|
|
1915
2972
|
onClick: (e) => {
|
|
1916
2973
|
e.stopPropagation();
|
|
1917
2974
|
onNodeClick?.(node.id, e);
|
|
@@ -1931,9 +2988,6 @@ function NodeRenderer({
|
|
|
1931
2988
|
onNodeDragStart?.(node.id, e);
|
|
1932
2989
|
}
|
|
1933
2990
|
},
|
|
1934
|
-
style: {
|
|
1935
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
1936
|
-
},
|
|
1937
2991
|
children: [
|
|
1938
2992
|
isSelected && /* @__PURE__ */ jsx13(
|
|
1939
2993
|
"rect",
|
|
@@ -1986,6 +3040,9 @@ function PipeRenderer({
|
|
|
1986
3040
|
onPipeClick,
|
|
1987
3041
|
enableWaypointEditing = false,
|
|
1988
3042
|
onWaypointDragStart,
|
|
3043
|
+
onWaypointClick,
|
|
3044
|
+
selectedWaypointPipeId,
|
|
3045
|
+
selectedWaypointIndex,
|
|
1989
3046
|
editingPipeId,
|
|
1990
3047
|
draggingWaypointIndex,
|
|
1991
3048
|
waypointDragOffset,
|
|
@@ -2006,7 +3063,7 @@ function PipeRenderer({
|
|
|
2006
3063
|
});
|
|
2007
3064
|
const pointsString = displayPoints.map((point) => `${point.x},${point.y}`).join(" ");
|
|
2008
3065
|
const pipeStyle = pipe.style || {};
|
|
2009
|
-
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#
|
|
3066
|
+
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#94a1b8";
|
|
2010
3067
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
2011
3068
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
2012
3069
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
@@ -2055,10 +3112,11 @@ function PipeRenderer({
|
|
|
2055
3112
|
] }),
|
|
2056
3113
|
displayPoints.map((point, idx) => {
|
|
2057
3114
|
const isEndpoint = idx === 0 || idx === displayPoints.length - 1;
|
|
3115
|
+
const isSelectedWaypoint = selectedWaypointPipeId === pipe.id && selectedWaypointIndex === idx;
|
|
2058
3116
|
const isDragging = isEditing && draggingWaypointIndex === idx;
|
|
2059
|
-
const waypointSize = isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
2060
|
-
const waypointOpacity = isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
2061
|
-
const waypointColor = isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
3117
|
+
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3118
|
+
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3119
|
+
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
2062
3120
|
return /* @__PURE__ */ jsx14(
|
|
2063
3121
|
"circle",
|
|
2064
3122
|
{
|
|
@@ -2074,6 +3132,12 @@ function PipeRenderer({
|
|
|
2074
3132
|
cursor: showEditingControls ? isDragging ? "grabbing" : "grab" : "default"
|
|
2075
3133
|
},
|
|
2076
3134
|
pointerEvents: showEditingControls ? "all" : "none",
|
|
3135
|
+
onClick: (e) => {
|
|
3136
|
+
if (showEditingControls) {
|
|
3137
|
+
e.stopPropagation();
|
|
3138
|
+
onWaypointClick?.(pipe.id, idx);
|
|
3139
|
+
}
|
|
3140
|
+
},
|
|
2077
3141
|
onMouseDown: (e) => {
|
|
2078
3142
|
if (showEditingControls) {
|
|
2079
3143
|
e.stopPropagation();
|
|
@@ -2150,7 +3214,13 @@ function PipeRenderer({
|
|
|
2150
3214
|
|
|
2151
3215
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
2152
3216
|
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2153
|
-
function DataOverlay({
|
|
3217
|
+
function DataOverlay({
|
|
3218
|
+
nodeId,
|
|
3219
|
+
x,
|
|
3220
|
+
y,
|
|
3221
|
+
telemetry,
|
|
3222
|
+
scale = 1
|
|
3223
|
+
}) {
|
|
2154
3224
|
const { value, display, history } = telemetry;
|
|
2155
3225
|
const showValue = display?.showValue ?? true;
|
|
2156
3226
|
const showStatus = display?.showStatus ?? true;
|
|
@@ -2190,9 +3260,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2190
3260
|
const displayText = value.unit ? `${formattedValue} ${value.unit}` : formattedValue;
|
|
2191
3261
|
const sparklinePath = (() => {
|
|
2192
3262
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
2193
|
-
const width = 70;
|
|
2194
|
-
const height = 20;
|
|
2195
|
-
const padding = 5;
|
|
3263
|
+
const width = 70 * scale;
|
|
3264
|
+
const height = 20 * scale;
|
|
3265
|
+
const padding = 5 * scale;
|
|
2196
3266
|
const effectiveWidth = width - padding * 2;
|
|
2197
3267
|
const effectiveHeight = height - padding * 2;
|
|
2198
3268
|
const min = Math.min(...history);
|
|
@@ -2206,21 +3276,22 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2206
3276
|
return `M ${points.join(" L ")}`;
|
|
2207
3277
|
})();
|
|
2208
3278
|
const hasSparkline = showSparkline && sparklinePath;
|
|
2209
|
-
const overlayHeight = label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22;
|
|
3279
|
+
const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
|
|
3280
|
+
const overlayWidth = 80 * scale;
|
|
2210
3281
|
const displayX = x + offsetX;
|
|
2211
3282
|
const displayY = y + offsetY;
|
|
2212
3283
|
return /* @__PURE__ */ jsxs11("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
2213
3284
|
/* @__PURE__ */ jsx15(
|
|
2214
3285
|
"rect",
|
|
2215
3286
|
{
|
|
2216
|
-
x: displayX -
|
|
2217
|
-
y: displayY - 25,
|
|
2218
|
-
width:
|
|
3287
|
+
x: displayX - overlayWidth / 2,
|
|
3288
|
+
y: displayY - 25 * scale,
|
|
3289
|
+
width: overlayWidth,
|
|
2219
3290
|
height: overlayHeight,
|
|
2220
|
-
rx:
|
|
3291
|
+
rx: 4 * scale,
|
|
2221
3292
|
fill: colors.bg,
|
|
2222
3293
|
stroke: colors.border,
|
|
2223
|
-
strokeWidth:
|
|
3294
|
+
strokeWidth: 1 * scale,
|
|
2224
3295
|
opacity: "0.95",
|
|
2225
3296
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
2226
3297
|
}
|
|
@@ -2229,9 +3300,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2229
3300
|
"text",
|
|
2230
3301
|
{
|
|
2231
3302
|
x: displayX,
|
|
2232
|
-
y: displayY - 15,
|
|
3303
|
+
y: displayY - 15 * scale,
|
|
2233
3304
|
textAnchor: "middle",
|
|
2234
|
-
fontSize:
|
|
3305
|
+
fontSize: 8 * scale,
|
|
2235
3306
|
fontWeight: "600",
|
|
2236
3307
|
fill: finalTextColor,
|
|
2237
3308
|
opacity: "0.9",
|
|
@@ -2242,31 +3313,41 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2242
3313
|
"text",
|
|
2243
3314
|
{
|
|
2244
3315
|
x: displayX,
|
|
2245
|
-
y: label ? displayY - 3 : displayY - 9,
|
|
3316
|
+
y: label ? displayY - 3 * scale : displayY - 9 * scale,
|
|
2246
3317
|
textAnchor: "middle",
|
|
2247
|
-
fontSize:
|
|
3318
|
+
fontSize: 11 * scale,
|
|
2248
3319
|
fontWeight: "700",
|
|
2249
3320
|
fill: finalTextColor,
|
|
2250
3321
|
letterSpacing: "0.02em",
|
|
2251
3322
|
children: displayText
|
|
2252
3323
|
}
|
|
2253
3324
|
),
|
|
2254
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */ jsx15(
|
|
2255
|
-
"
|
|
3325
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ jsx15(
|
|
3326
|
+
"circle",
|
|
2256
3327
|
{
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
3328
|
+
cx: displayX + 35 * scale,
|
|
3329
|
+
cy: displayY - 18 * scale,
|
|
3330
|
+
r: 3 * scale,
|
|
3331
|
+
fill: finalTextColor,
|
|
3332
|
+
opacity: "0.9",
|
|
3333
|
+
children: /* @__PURE__ */ jsx15(
|
|
3334
|
+
"animate",
|
|
3335
|
+
{
|
|
3336
|
+
attributeName: "opacity",
|
|
3337
|
+
values: "0.9;0.3;0.9",
|
|
3338
|
+
dur: "1.5s",
|
|
3339
|
+
repeatCount: "indefinite"
|
|
3340
|
+
}
|
|
3341
|
+
)
|
|
2261
3342
|
}
|
|
2262
|
-
)
|
|
3343
|
+
),
|
|
2263
3344
|
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs11(
|
|
2264
3345
|
"text",
|
|
2265
3346
|
{
|
|
2266
3347
|
x: displayX,
|
|
2267
|
-
y: displayY + 5,
|
|
3348
|
+
y: displayY + 5 * scale,
|
|
2268
3349
|
textAnchor: "middle",
|
|
2269
|
-
fontSize:
|
|
3350
|
+
fontSize: 7 * scale,
|
|
2270
3351
|
fontWeight: "500",
|
|
2271
3352
|
fill: finalTextColor,
|
|
2272
3353
|
opacity: "0.7",
|
|
@@ -2277,13 +3358,13 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2277
3358
|
]
|
|
2278
3359
|
}
|
|
2279
3360
|
),
|
|
2280
|
-
hasSparkline && /* @__PURE__ */ jsx15("g", { transform: `translate(${displayX - 35}, ${displayY + (label ? 5 : 0)})`, children: /* @__PURE__ */ jsx15(
|
|
3361
|
+
hasSparkline && /* @__PURE__ */ jsx15("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ jsx15(
|
|
2281
3362
|
"path",
|
|
2282
3363
|
{
|
|
2283
3364
|
d: sparklinePath,
|
|
2284
3365
|
fill: "none",
|
|
2285
3366
|
stroke: sparklineColor || finalTextColor,
|
|
2286
|
-
strokeWidth:
|
|
3367
|
+
strokeWidth: 1.5 * scale,
|
|
2287
3368
|
strokeLinecap: "round",
|
|
2288
3369
|
strokeLinejoin: "round",
|
|
2289
3370
|
opacity: "0.9"
|
|
@@ -2292,8 +3373,145 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2292
3373
|
] });
|
|
2293
3374
|
}
|
|
2294
3375
|
|
|
3376
|
+
// src/components/PIDCanvas/PositionPanel.tsx
|
|
3377
|
+
import { useState as useState7, useEffect as useEffect4 } from "react";
|
|
3378
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3379
|
+
function PositionPanel({
|
|
3380
|
+
selectedNode,
|
|
3381
|
+
selectedWaypoint,
|
|
3382
|
+
onPositionChange,
|
|
3383
|
+
onWaypointPositionChange,
|
|
3384
|
+
position = "top-right"
|
|
3385
|
+
}) {
|
|
3386
|
+
const [x, setX] = useState7("");
|
|
3387
|
+
const [y, setY] = useState7("");
|
|
3388
|
+
useEffect4(() => {
|
|
3389
|
+
if (selectedNode) {
|
|
3390
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3391
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3392
|
+
} else if (selectedWaypoint) {
|
|
3393
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3394
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3395
|
+
}
|
|
3396
|
+
}, [selectedNode, selectedWaypoint]);
|
|
3397
|
+
if (!selectedNode && !selectedWaypoint) {
|
|
3398
|
+
return null;
|
|
3399
|
+
}
|
|
3400
|
+
const handleXChange = (value) => {
|
|
3401
|
+
setX(value);
|
|
3402
|
+
const numValue = parseFloat(value);
|
|
3403
|
+
if (!isNaN(numValue)) {
|
|
3404
|
+
if (selectedNode && onPositionChange) {
|
|
3405
|
+
onPositionChange(selectedNode.id, numValue, selectedNode.transform.y);
|
|
3406
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3407
|
+
onWaypointPositionChange(
|
|
3408
|
+
selectedWaypoint.pipeId,
|
|
3409
|
+
selectedWaypoint.pointIndex,
|
|
3410
|
+
numValue,
|
|
3411
|
+
selectedWaypoint.position.y
|
|
3412
|
+
);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
};
|
|
3416
|
+
const handleYChange = (value) => {
|
|
3417
|
+
setY(value);
|
|
3418
|
+
const numValue = parseFloat(value);
|
|
3419
|
+
if (!isNaN(numValue)) {
|
|
3420
|
+
if (selectedNode && onPositionChange) {
|
|
3421
|
+
onPositionChange(selectedNode.id, selectedNode.transform.x, numValue);
|
|
3422
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3423
|
+
onWaypointPositionChange(
|
|
3424
|
+
selectedWaypoint.pipeId,
|
|
3425
|
+
selectedWaypoint.pointIndex,
|
|
3426
|
+
selectedWaypoint.position.x,
|
|
3427
|
+
numValue
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
};
|
|
3432
|
+
const handleBlur = () => {
|
|
3433
|
+
if (selectedNode) {
|
|
3434
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3435
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3436
|
+
} else if (selectedWaypoint) {
|
|
3437
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3438
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3439
|
+
}
|
|
3440
|
+
};
|
|
3441
|
+
const positionStyles = {
|
|
3442
|
+
"top-left": { top: 10, left: 10 },
|
|
3443
|
+
"top-right": { top: 10, right: 10 },
|
|
3444
|
+
"bottom-left": { bottom: 10, left: 10 },
|
|
3445
|
+
"bottom-right": { bottom: 10, right: 10 }
|
|
3446
|
+
};
|
|
3447
|
+
return /* @__PURE__ */ jsxs12(
|
|
3448
|
+
"div",
|
|
3449
|
+
{
|
|
3450
|
+
style: {
|
|
3451
|
+
position: "absolute",
|
|
3452
|
+
...positionStyles[position],
|
|
3453
|
+
backgroundColor: "white",
|
|
3454
|
+
border: "1px solid #ccc",
|
|
3455
|
+
borderRadius: "4px",
|
|
3456
|
+
padding: "12px",
|
|
3457
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
3458
|
+
zIndex: 1e3,
|
|
3459
|
+
minWidth: "180px",
|
|
3460
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
3461
|
+
fontSize: "13px"
|
|
3462
|
+
},
|
|
3463
|
+
children: [
|
|
3464
|
+
/* @__PURE__ */ jsx16("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
3465
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
3466
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3467
|
+
/* @__PURE__ */ jsx16("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
3468
|
+
/* @__PURE__ */ jsx16(
|
|
3469
|
+
"input",
|
|
3470
|
+
{
|
|
3471
|
+
type: "number",
|
|
3472
|
+
value: x,
|
|
3473
|
+
onChange: (e) => handleXChange(e.target.value),
|
|
3474
|
+
onBlur: handleBlur,
|
|
3475
|
+
style: {
|
|
3476
|
+
flex: 1,
|
|
3477
|
+
padding: "4px 8px",
|
|
3478
|
+
border: "1px solid #ddd",
|
|
3479
|
+
borderRadius: "3px",
|
|
3480
|
+
fontSize: "13px"
|
|
3481
|
+
},
|
|
3482
|
+
step: "1"
|
|
3483
|
+
}
|
|
3484
|
+
)
|
|
3485
|
+
] }),
|
|
3486
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3487
|
+
/* @__PURE__ */ jsx16("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
3488
|
+
/* @__PURE__ */ jsx16(
|
|
3489
|
+
"input",
|
|
3490
|
+
{
|
|
3491
|
+
type: "number",
|
|
3492
|
+
value: y,
|
|
3493
|
+
onChange: (e) => handleYChange(e.target.value),
|
|
3494
|
+
onBlur: handleBlur,
|
|
3495
|
+
style: {
|
|
3496
|
+
flex: 1,
|
|
3497
|
+
padding: "4px 8px",
|
|
3498
|
+
border: "1px solid #ddd",
|
|
3499
|
+
borderRadius: "3px",
|
|
3500
|
+
fontSize: "13px"
|
|
3501
|
+
},
|
|
3502
|
+
step: "1"
|
|
3503
|
+
}
|
|
3504
|
+
)
|
|
3505
|
+
] })
|
|
3506
|
+
] }),
|
|
3507
|
+
/* @__PURE__ */ jsx16("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3508
|
+
]
|
|
3509
|
+
}
|
|
3510
|
+
);
|
|
3511
|
+
}
|
|
3512
|
+
|
|
2295
3513
|
// src/diagram/hooks/useViewBox.ts
|
|
2296
|
-
import { useState as
|
|
3514
|
+
import { useState as useState8, useCallback as useCallback3, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
2297
3515
|
function useViewBox(options) {
|
|
2298
3516
|
const {
|
|
2299
3517
|
initialViewBox,
|
|
@@ -2304,7 +3522,7 @@ function useViewBox(options) {
|
|
|
2304
3522
|
zoomSensitivity = 1e-3,
|
|
2305
3523
|
allowLeftClickPan = true
|
|
2306
3524
|
} = options;
|
|
2307
|
-
const [viewBox, setViewBox] =
|
|
3525
|
+
const [viewBox, setViewBox] = useState8(initialViewBox);
|
|
2308
3526
|
const svgRef = useRef2(null);
|
|
2309
3527
|
const isPanningRef = useRef2(false);
|
|
2310
3528
|
const lastMousePosRef = useRef2({ x: 0, y: 0 });
|
|
@@ -2375,7 +3593,7 @@ function useViewBox(options) {
|
|
|
2375
3593
|
height: newHeight
|
|
2376
3594
|
});
|
|
2377
3595
|
}, [initialViewBox]);
|
|
2378
|
-
|
|
3596
|
+
useEffect5(() => {
|
|
2379
3597
|
if (!enableZoom || !svgRef.current) return;
|
|
2380
3598
|
const svg = svgRef.current;
|
|
2381
3599
|
const handleWheel = (e) => {
|
|
@@ -2408,7 +3626,7 @@ function useViewBox(options) {
|
|
|
2408
3626
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
2409
3627
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
2410
3628
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
2411
|
-
|
|
3629
|
+
useEffect5(() => {
|
|
2412
3630
|
if (!enablePan || !svgRef.current) return;
|
|
2413
3631
|
const svg = svgRef.current;
|
|
2414
3632
|
const handleMouseDown = (e) => {
|
|
@@ -2484,7 +3702,7 @@ function useViewBox(options) {
|
|
|
2484
3702
|
window.removeEventListener("keyup", handleKeyUp);
|
|
2485
3703
|
};
|
|
2486
3704
|
}, [enablePan, allowLeftClickPan]);
|
|
2487
|
-
|
|
3705
|
+
useEffect5(() => {
|
|
2488
3706
|
if (!svgRef.current) return;
|
|
2489
3707
|
if (!enablePan && !enableZoom) return;
|
|
2490
3708
|
const svg = svgRef.current;
|
|
@@ -2614,14 +3832,14 @@ function useViewBox(options) {
|
|
|
2614
3832
|
}
|
|
2615
3833
|
|
|
2616
3834
|
// src/diagram/hooks/useSelection.ts
|
|
2617
|
-
import { useState as
|
|
3835
|
+
import { useState as useState9, useCallback as useCallback4 } from "react";
|
|
2618
3836
|
function useSelection(options = {}) {
|
|
2619
3837
|
const {
|
|
2620
3838
|
multiSelect = true,
|
|
2621
3839
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
2622
3840
|
onSelectionChange
|
|
2623
3841
|
} = options;
|
|
2624
|
-
const [selection, setSelection] =
|
|
3842
|
+
const [selection, setSelection] = useState9(initialSelection);
|
|
2625
3843
|
const notifyChange = useCallback4(
|
|
2626
3844
|
(newSelection) => {
|
|
2627
3845
|
if (onSelectionChange) {
|
|
@@ -2719,14 +3937,14 @@ function useSelection(options = {}) {
|
|
|
2719
3937
|
}
|
|
2720
3938
|
|
|
2721
3939
|
// src/diagram/hooks/useTelemetry.ts
|
|
2722
|
-
import { useState as
|
|
3940
|
+
import { useState as useState10, useCallback as useCallback5, useEffect as useEffect6, useRef as useRef3 } from "react";
|
|
2723
3941
|
function useTelemetry(options = {}) {
|
|
2724
3942
|
const {
|
|
2725
3943
|
initialBindings = [],
|
|
2726
3944
|
onTelemetryChange,
|
|
2727
3945
|
refreshInterval = 0
|
|
2728
3946
|
} = options;
|
|
2729
|
-
const [telemetry, setTelemetry] =
|
|
3947
|
+
const [telemetry, setTelemetry] = useState10(() => {
|
|
2730
3948
|
const map = /* @__PURE__ */ new Map();
|
|
2731
3949
|
initialBindings.forEach((binding) => {
|
|
2732
3950
|
map.set(binding.nodeId, binding);
|
|
@@ -2847,7 +4065,7 @@ function useTelemetry(options = {}) {
|
|
|
2847
4065
|
},
|
|
2848
4066
|
[notifyChange]
|
|
2849
4067
|
);
|
|
2850
|
-
|
|
4068
|
+
useEffect6(() => {
|
|
2851
4069
|
if (refreshInterval <= 0) return;
|
|
2852
4070
|
const intervalId = setInterval(() => {
|
|
2853
4071
|
notifyChange(telemetryRef.current);
|
|
@@ -2864,8 +4082,50 @@ function useTelemetry(options = {}) {
|
|
|
2864
4082
|
};
|
|
2865
4083
|
}
|
|
2866
4084
|
|
|
4085
|
+
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4086
|
+
import { useEffect as useEffect7 } from "react";
|
|
4087
|
+
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4088
|
+
const { enabled = true, mapStatus } = options;
|
|
4089
|
+
useEffect7(() => {
|
|
4090
|
+
if (!enabled) return;
|
|
4091
|
+
const defaultMapStatus = (telemetryStatus) => {
|
|
4092
|
+
switch (telemetryStatus) {
|
|
4093
|
+
case "normal":
|
|
4094
|
+
return "running";
|
|
4095
|
+
case "warning":
|
|
4096
|
+
return "warning";
|
|
4097
|
+
case "alarm":
|
|
4098
|
+
case "fault":
|
|
4099
|
+
return "alarm";
|
|
4100
|
+
case "off":
|
|
4101
|
+
return "stopped";
|
|
4102
|
+
default:
|
|
4103
|
+
return "stopped";
|
|
4104
|
+
}
|
|
4105
|
+
};
|
|
4106
|
+
const statusMapper = mapStatus || defaultMapStatus;
|
|
4107
|
+
let needsUpdate = false;
|
|
4108
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
4109
|
+
const binding = telemetry.get(node.id);
|
|
4110
|
+
if (!binding) return node;
|
|
4111
|
+
const newStatus = statusMapper(binding.value.status);
|
|
4112
|
+
if (node.status !== newStatus) {
|
|
4113
|
+
needsUpdate = true;
|
|
4114
|
+
return { ...node, status: newStatus };
|
|
4115
|
+
}
|
|
4116
|
+
return node;
|
|
4117
|
+
});
|
|
4118
|
+
if (needsUpdate) {
|
|
4119
|
+
setDiagram({
|
|
4120
|
+
...diagram,
|
|
4121
|
+
nodes: updatedNodes
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4124
|
+
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
4125
|
+
}
|
|
4126
|
+
|
|
2867
4127
|
// src/diagram/hooks/useDrag.ts
|
|
2868
|
-
import { useState as
|
|
4128
|
+
import { useState as useState11, useCallback as useCallback6, useRef as useRef4, useEffect as useEffect8 } from "react";
|
|
2869
4129
|
function useDrag(options = {}) {
|
|
2870
4130
|
const {
|
|
2871
4131
|
onDragStart,
|
|
@@ -2875,13 +4135,13 @@ function useDrag(options = {}) {
|
|
|
2875
4135
|
dragThreshold = 3,
|
|
2876
4136
|
screenToWorld = (x, y) => ({ x, y })
|
|
2877
4137
|
} = options;
|
|
2878
|
-
const [dragState, setDragState] =
|
|
4138
|
+
const [dragState, setDragState] = useState11({
|
|
2879
4139
|
isDragging: false,
|
|
2880
4140
|
startPosition: null,
|
|
2881
4141
|
offset: { x: 0, y: 0 },
|
|
2882
4142
|
draggedId: null
|
|
2883
4143
|
});
|
|
2884
|
-
const [isListening, setIsListening] =
|
|
4144
|
+
const [isListening, setIsListening] = useState11(false);
|
|
2885
4145
|
const dragStartRef = useRef4(null);
|
|
2886
4146
|
const hasMovedRef = useRef4(false);
|
|
2887
4147
|
const applySnap = useCallback6(
|
|
@@ -3050,7 +4310,7 @@ function useDrag(options = {}) {
|
|
|
3050
4310
|
},
|
|
3051
4311
|
[screenToWorld, applySnap, onDragEnd]
|
|
3052
4312
|
);
|
|
3053
|
-
|
|
4313
|
+
useEffect8(() => {
|
|
3054
4314
|
if (!isListening) return;
|
|
3055
4315
|
document.addEventListener("mousemove", handleMouseMove);
|
|
3056
4316
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -3119,7 +4379,7 @@ function useDrag(options = {}) {
|
|
|
3119
4379
|
}
|
|
3120
4380
|
|
|
3121
4381
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
3122
|
-
import { useEffect as
|
|
4382
|
+
import { useEffect as useEffect9 } from "react";
|
|
3123
4383
|
function useKeyboardShortcuts(options) {
|
|
3124
4384
|
const {
|
|
3125
4385
|
onDelete,
|
|
@@ -3130,7 +4390,7 @@ function useKeyboardShortcuts(options) {
|
|
|
3130
4390
|
onSelectAll,
|
|
3131
4391
|
enabled = true
|
|
3132
4392
|
} = options;
|
|
3133
|
-
|
|
4393
|
+
useEffect9(() => {
|
|
3134
4394
|
if (!enabled) return;
|
|
3135
4395
|
const handleKeyDown = (event) => {
|
|
3136
4396
|
const target = event.target;
|
|
@@ -3239,7 +4499,7 @@ function nodeHasPort(node, portId) {
|
|
|
3239
4499
|
}
|
|
3240
4500
|
|
|
3241
4501
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3242
|
-
import { Fragment as Fragment5, jsx as
|
|
4502
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3243
4503
|
function PIDCanvas({
|
|
3244
4504
|
diagram,
|
|
3245
4505
|
className = "",
|
|
@@ -3266,16 +4526,30 @@ function PIDCanvas({
|
|
|
3266
4526
|
telemetry,
|
|
3267
4527
|
...props
|
|
3268
4528
|
}) {
|
|
3269
|
-
const [localDiagram, setLocalDiagram] =
|
|
3270
|
-
const [dragOverPosition, setDragOverPosition] =
|
|
3271
|
-
const [isConnecting, setIsConnecting] =
|
|
3272
|
-
const [connectionSource, setConnectionSource] =
|
|
3273
|
-
const [connectionSourcePort, setConnectionSourcePort] =
|
|
3274
|
-
const [connectionCursor, setConnectionCursor] =
|
|
3275
|
-
const [hoveredNode, setHoveredNode] =
|
|
3276
|
-
const [hoveredPort, setHoveredPort] =
|
|
3277
|
-
|
|
3278
|
-
|
|
4529
|
+
const [localDiagram, setLocalDiagram] = useState12(diagram);
|
|
4530
|
+
const [dragOverPosition, setDragOverPosition] = useState12(null);
|
|
4531
|
+
const [isConnecting, setIsConnecting] = useState12(false);
|
|
4532
|
+
const [connectionSource, setConnectionSource] = useState12(null);
|
|
4533
|
+
const [connectionSourcePort, setConnectionSourcePort] = useState12(null);
|
|
4534
|
+
const [connectionCursor, setConnectionCursor] = useState12(null);
|
|
4535
|
+
const [hoveredNode, setHoveredNode] = useState12(null);
|
|
4536
|
+
const [hoveredPort, setHoveredPort] = useState12(null);
|
|
4537
|
+
const [selectedWaypoint, setSelectedWaypoint] = useState12(null);
|
|
4538
|
+
const historyStack = useRef5([]);
|
|
4539
|
+
const redoStack = useRef5([]);
|
|
4540
|
+
const isUndoRedoAction = useRef5(false);
|
|
4541
|
+
const isInternalChange = useRef5(false);
|
|
4542
|
+
const lastInternalDiagram = useRef5(null);
|
|
4543
|
+
useEffect10(() => {
|
|
4544
|
+
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4545
|
+
if (isExternal) {
|
|
4546
|
+
setLocalDiagram(diagram);
|
|
4547
|
+
if (!isUndoRedoAction.current) {
|
|
4548
|
+
historyStack.current = [];
|
|
4549
|
+
redoStack.current = [];
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
isInternalChange.current = false;
|
|
3279
4553
|
}, [diagram]);
|
|
3280
4554
|
const {
|
|
3281
4555
|
viewBox: controlledViewBox,
|
|
@@ -3311,7 +4585,7 @@ function PIDCanvas({
|
|
|
3311
4585
|
});
|
|
3312
4586
|
return { minX, minY, maxX, maxY };
|
|
3313
4587
|
}, [localDiagram.nodes]);
|
|
3314
|
-
|
|
4588
|
+
useEffect10(() => {
|
|
3315
4589
|
if (onMounted) {
|
|
3316
4590
|
const controls = {
|
|
3317
4591
|
fitToContent: (padding = 50) => {
|
|
@@ -3352,6 +4626,186 @@ function PIDCanvas({
|
|
|
3352
4626
|
});
|
|
3353
4627
|
const dragEnabled = features.dragNodes ?? false;
|
|
3354
4628
|
const selectionEnabled = features.selection ?? false;
|
|
4629
|
+
const containerRef = useRef5(null);
|
|
4630
|
+
const pushToHistory = useCallback7((currentDiagram) => {
|
|
4631
|
+
if (isUndoRedoAction.current) return;
|
|
4632
|
+
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
4633
|
+
historyStack.current.push(snapshot);
|
|
4634
|
+
if (historyStack.current.length > 15) {
|
|
4635
|
+
historyStack.current.shift();
|
|
4636
|
+
}
|
|
4637
|
+
redoStack.current = [];
|
|
4638
|
+
}, []);
|
|
4639
|
+
const undo = useCallback7(() => {
|
|
4640
|
+
if (historyStack.current.length === 0) return;
|
|
4641
|
+
isUndoRedoAction.current = true;
|
|
4642
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4643
|
+
redoStack.current.push(currentSnapshot);
|
|
4644
|
+
const previousState = historyStack.current.pop();
|
|
4645
|
+
isInternalChange.current = true;
|
|
4646
|
+
lastInternalDiagram.current = previousState;
|
|
4647
|
+
setLocalDiagram(previousState);
|
|
4648
|
+
onDiagramChange?.(previousState);
|
|
4649
|
+
setTimeout(() => {
|
|
4650
|
+
isUndoRedoAction.current = false;
|
|
4651
|
+
}, 0);
|
|
4652
|
+
}, [localDiagram, onDiagramChange]);
|
|
4653
|
+
const redo = useCallback7(() => {
|
|
4654
|
+
if (redoStack.current.length === 0) return;
|
|
4655
|
+
isUndoRedoAction.current = true;
|
|
4656
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4657
|
+
historyStack.current.push(currentSnapshot);
|
|
4658
|
+
const nextState = redoStack.current.pop();
|
|
4659
|
+
isInternalChange.current = true;
|
|
4660
|
+
lastInternalDiagram.current = nextState;
|
|
4661
|
+
setLocalDiagram(nextState);
|
|
4662
|
+
onDiagramChange?.(nextState);
|
|
4663
|
+
setTimeout(() => {
|
|
4664
|
+
isUndoRedoAction.current = false;
|
|
4665
|
+
}, 0);
|
|
4666
|
+
}, [localDiagram, onDiagramChange]);
|
|
4667
|
+
useEffect10(() => {
|
|
4668
|
+
const handleKeyDown = (e) => {
|
|
4669
|
+
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4670
|
+
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
4671
|
+
e.preventDefault();
|
|
4672
|
+
undo();
|
|
4673
|
+
} else if (isCtrlOrCmd && e.key === "z" && e.shiftKey) {
|
|
4674
|
+
e.preventDefault();
|
|
4675
|
+
redo();
|
|
4676
|
+
} else if (isCtrlOrCmd && e.key === "y") {
|
|
4677
|
+
e.preventDefault();
|
|
4678
|
+
redo();
|
|
4679
|
+
}
|
|
4680
|
+
};
|
|
4681
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4682
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4683
|
+
}, [undo, redo]);
|
|
4684
|
+
useEffect10(() => {
|
|
4685
|
+
if (!features.dragNodes) return;
|
|
4686
|
+
const handleKeyDown = (e) => {
|
|
4687
|
+
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
4688
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
const nudgeAmount = e.shiftKey ? 10 : 1;
|
|
4692
|
+
let dx = 0;
|
|
4693
|
+
let dy = 0;
|
|
4694
|
+
switch (e.key) {
|
|
4695
|
+
case "ArrowLeft":
|
|
4696
|
+
dx = -nudgeAmount;
|
|
4697
|
+
e.preventDefault();
|
|
4698
|
+
break;
|
|
4699
|
+
case "ArrowRight":
|
|
4700
|
+
dx = nudgeAmount;
|
|
4701
|
+
e.preventDefault();
|
|
4702
|
+
break;
|
|
4703
|
+
case "ArrowUp":
|
|
4704
|
+
dy = -nudgeAmount;
|
|
4705
|
+
e.preventDefault();
|
|
4706
|
+
break;
|
|
4707
|
+
case "ArrowDown":
|
|
4708
|
+
dy = nudgeAmount;
|
|
4709
|
+
e.preventDefault();
|
|
4710
|
+
break;
|
|
4711
|
+
default:
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
if (selectedWaypoint) {
|
|
4715
|
+
pushToHistory(localDiagram);
|
|
4716
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4717
|
+
if (pipe.id === selectedWaypoint.pipeId) {
|
|
4718
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4719
|
+
(point, idx) => idx === selectedWaypoint.pointIndex ? { x: point.x + dx, y: point.y + dy } : point
|
|
4720
|
+
);
|
|
4721
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4722
|
+
}
|
|
4723
|
+
return pipe;
|
|
4724
|
+
});
|
|
4725
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4726
|
+
isInternalChange.current = true;
|
|
4727
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4728
|
+
setLocalDiagram(updatedDiagram);
|
|
4729
|
+
onDiagramChange?.(updatedDiagram);
|
|
4730
|
+
return;
|
|
4731
|
+
}
|
|
4732
|
+
if (selectionEnabled && selection.selectedNodeIds.size > 0) {
|
|
4733
|
+
pushToHistory(localDiagram);
|
|
4734
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4735
|
+
(node) => selection.selectedNodeIds.has(node.id) ? {
|
|
4736
|
+
...node,
|
|
4737
|
+
transform: {
|
|
4738
|
+
...node.transform,
|
|
4739
|
+
x: node.transform.x + dx,
|
|
4740
|
+
y: node.transform.y + dy
|
|
4741
|
+
}
|
|
4742
|
+
} : node
|
|
4743
|
+
);
|
|
4744
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4745
|
+
isInternalChange.current = true;
|
|
4746
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4747
|
+
setLocalDiagram(updatedDiagram);
|
|
4748
|
+
onDiagramChange?.(updatedDiagram);
|
|
4749
|
+
selection.selectedNodeIds.forEach((nodeId) => {
|
|
4750
|
+
const node = updatedNodes.find((n) => n.id === nodeId);
|
|
4751
|
+
if (node) {
|
|
4752
|
+
onNodeMove?.(nodeId, node.transform.x, node.transform.y);
|
|
4753
|
+
}
|
|
4754
|
+
});
|
|
4755
|
+
}
|
|
4756
|
+
};
|
|
4757
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4758
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4759
|
+
}, [
|
|
4760
|
+
selectionEnabled,
|
|
4761
|
+
features.dragNodes,
|
|
4762
|
+
selection.selectedNodeIds,
|
|
4763
|
+
selectedWaypoint,
|
|
4764
|
+
localDiagram,
|
|
4765
|
+
onDiagramChange,
|
|
4766
|
+
onNodeMove,
|
|
4767
|
+
pushToHistory
|
|
4768
|
+
]);
|
|
4769
|
+
const handlePositionChange = useCallback7(
|
|
4770
|
+
(nodeId, x, y) => {
|
|
4771
|
+
pushToHistory(localDiagram);
|
|
4772
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4773
|
+
(node) => node.id === nodeId ? {
|
|
4774
|
+
...node,
|
|
4775
|
+
transform: {
|
|
4776
|
+
...node.transform,
|
|
4777
|
+
x,
|
|
4778
|
+
y
|
|
4779
|
+
}
|
|
4780
|
+
} : node
|
|
4781
|
+
);
|
|
4782
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4783
|
+
isInternalChange.current = true;
|
|
4784
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4785
|
+
setLocalDiagram(updatedDiagram);
|
|
4786
|
+
onDiagramChange?.(updatedDiagram);
|
|
4787
|
+
onNodeMove?.(nodeId, x, y);
|
|
4788
|
+
},
|
|
4789
|
+
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
4790
|
+
);
|
|
4791
|
+
const handleWaypointPositionChange = useCallback7(
|
|
4792
|
+
(pipeId, pointIndex, x, y) => {
|
|
4793
|
+
pushToHistory(localDiagram);
|
|
4794
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4795
|
+
if (pipe.id === pipeId) {
|
|
4796
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4797
|
+
(point, idx) => idx === pointIndex ? { x, y } : point
|
|
4798
|
+
);
|
|
4799
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4800
|
+
}
|
|
4801
|
+
return pipe;
|
|
4802
|
+
});
|
|
4803
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4804
|
+
setLocalDiagram(updatedDiagram);
|
|
4805
|
+
onDiagramChange?.(updatedDiagram);
|
|
4806
|
+
},
|
|
4807
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
4808
|
+
);
|
|
3355
4809
|
const handleDragEnd = useCallback7(
|
|
3356
4810
|
(nodeId, offset, finalPosition) => {
|
|
3357
4811
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
@@ -3361,6 +4815,7 @@ function PIDCanvas({
|
|
|
3361
4815
|
}
|
|
3362
4816
|
return;
|
|
3363
4817
|
}
|
|
4818
|
+
pushToHistory(localDiagram);
|
|
3364
4819
|
const updatedNodes = localDiagram.nodes.map(
|
|
3365
4820
|
(node) => node.id === nodeId ? {
|
|
3366
4821
|
...node,
|
|
@@ -3398,11 +4853,13 @@ function PIDCanvas({
|
|
|
3398
4853
|
nodes: updatedNodes,
|
|
3399
4854
|
pipes: updatedPipes
|
|
3400
4855
|
};
|
|
4856
|
+
isInternalChange.current = true;
|
|
4857
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3401
4858
|
setLocalDiagram(updatedDiagram);
|
|
3402
4859
|
onDiagramChange?.(updatedDiagram);
|
|
3403
4860
|
onNodeMove?.(nodeId, finalPosition.x, finalPosition.y);
|
|
3404
4861
|
},
|
|
3405
|
-
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode]
|
|
4862
|
+
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode, pushToHistory]
|
|
3406
4863
|
);
|
|
3407
4864
|
const { dragState, startDrag } = useDrag({
|
|
3408
4865
|
snapToGrid: features.snapToGrid ?? 0,
|
|
@@ -3413,6 +4870,7 @@ function PIDCanvas({
|
|
|
3413
4870
|
snapToGrid: features.snapToGrid ?? 0,
|
|
3414
4871
|
screenToWorld,
|
|
3415
4872
|
onDragEnd: (pipeId, _offset, finalPosition) => {
|
|
4873
|
+
pushToHistory(localDiagram);
|
|
3416
4874
|
const [actualPipeId, pointIndex] = pipeId.split(":");
|
|
3417
4875
|
const idx = parseInt(pointIndex, 10);
|
|
3418
4876
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -3423,6 +4881,8 @@ function PIDCanvas({
|
|
|
3423
4881
|
return { ...pipe, routePoints: updatedRoutePoints };
|
|
3424
4882
|
});
|
|
3425
4883
|
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4884
|
+
isInternalChange.current = true;
|
|
4885
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3426
4886
|
setLocalDiagram(updatedDiagram);
|
|
3427
4887
|
onDiagramChange?.(updatedDiagram);
|
|
3428
4888
|
}
|
|
@@ -3435,6 +4895,15 @@ function PIDCanvas({
|
|
|
3435
4895
|
},
|
|
3436
4896
|
[localDiagram.nodes, startDrag]
|
|
3437
4897
|
);
|
|
4898
|
+
const handleWaypointClick = useCallback7(
|
|
4899
|
+
(pipeId, pointIndex) => {
|
|
4900
|
+
setSelectedWaypoint({ pipeId, pointIndex });
|
|
4901
|
+
if (selectionEnabled) {
|
|
4902
|
+
clearSelection();
|
|
4903
|
+
}
|
|
4904
|
+
},
|
|
4905
|
+
[selectionEnabled, clearSelection]
|
|
4906
|
+
);
|
|
3438
4907
|
const handleWaypointDragStart = useCallback7(
|
|
3439
4908
|
(pipeId, pointIndex, event) => {
|
|
3440
4909
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
@@ -3446,6 +4915,7 @@ function PIDCanvas({
|
|
|
3446
4915
|
);
|
|
3447
4916
|
const handlePipeSegmentClick = useCallback7(
|
|
3448
4917
|
(pipeId, position, segmentIndex) => {
|
|
4918
|
+
pushToHistory(localDiagram);
|
|
3449
4919
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
3450
4920
|
if (pipe.id !== pipeId) return pipe;
|
|
3451
4921
|
const updatedRoutePoints = [
|
|
@@ -3459,13 +4929,14 @@ function PIDCanvas({
|
|
|
3459
4929
|
setLocalDiagram(updatedDiagram);
|
|
3460
4930
|
onDiagramChange?.(updatedDiagram);
|
|
3461
4931
|
},
|
|
3462
|
-
[localDiagram, onDiagramChange]
|
|
4932
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
3463
4933
|
);
|
|
3464
4934
|
const telemetryEnabled = features.telemetry ?? false;
|
|
3465
4935
|
const handleDelete = useCallback7(() => {
|
|
3466
4936
|
if (!selectionEnabled) return;
|
|
3467
4937
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3468
4938
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
4939
|
+
pushToHistory(localDiagram);
|
|
3469
4940
|
const updatedNodes = localDiagram.nodes.filter((node) => !selectedNodeIds.has(node.id));
|
|
3470
4941
|
const updatedPipes = localDiagram.pipes.filter(
|
|
3471
4942
|
(pipe) => !selectedPipeIds.has(pipe.id) && !selectedNodeIds.has(pipe.fromNodeId) && !selectedNodeIds.has(pipe.toNodeId)
|
|
@@ -3475,11 +4946,21 @@ function PIDCanvas({
|
|
|
3475
4946
|
nodes: updatedNodes,
|
|
3476
4947
|
pipes: updatedPipes
|
|
3477
4948
|
};
|
|
4949
|
+
isInternalChange.current = true;
|
|
4950
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3478
4951
|
setLocalDiagram(updatedDiagram);
|
|
3479
4952
|
clearSelection();
|
|
3480
4953
|
onDiagramChange?.(updatedDiagram);
|
|
3481
4954
|
onDelete?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3482
|
-
}, [
|
|
4955
|
+
}, [
|
|
4956
|
+
selection,
|
|
4957
|
+
localDiagram,
|
|
4958
|
+
selectionEnabled,
|
|
4959
|
+
clearSelection,
|
|
4960
|
+
onDiagramChange,
|
|
4961
|
+
onDelete,
|
|
4962
|
+
pushToHistory
|
|
4963
|
+
]);
|
|
3483
4964
|
const handleCopy = useCallback7(() => {
|
|
3484
4965
|
if (!selectionEnabled) return;
|
|
3485
4966
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
@@ -3536,10 +5017,15 @@ function PIDCanvas({
|
|
|
3536
5017
|
}
|
|
3537
5018
|
onPipeClick?.(pipeId);
|
|
3538
5019
|
};
|
|
3539
|
-
const handleCanvasClick = () => {
|
|
5020
|
+
const handleCanvasClick = (e) => {
|
|
5021
|
+
const target = e.target;
|
|
5022
|
+
if (target.closest(".pipe-route-point")) {
|
|
5023
|
+
return;
|
|
5024
|
+
}
|
|
3540
5025
|
if (selectionEnabled) {
|
|
3541
5026
|
clearSelection();
|
|
3542
5027
|
}
|
|
5028
|
+
setSelectedWaypoint(null);
|
|
3543
5029
|
};
|
|
3544
5030
|
const handleDragOver = useCallback7(
|
|
3545
5031
|
(event) => {
|
|
@@ -3550,7 +5036,7 @@ function PIDCanvas({
|
|
|
3550
5036
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3551
5037
|
setDragOverPosition(worldPos);
|
|
3552
5038
|
},
|
|
3553
|
-
[features.allowSymbolDrop, screenToWorld]
|
|
5039
|
+
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
3554
5040
|
);
|
|
3555
5041
|
const handleDrop = useCallback7(
|
|
3556
5042
|
(event) => {
|
|
@@ -3563,7 +5049,7 @@ function PIDCanvas({
|
|
|
3563
5049
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3564
5050
|
onSymbolDrop?.(symbolId, worldPos);
|
|
3565
5051
|
},
|
|
3566
|
-
[features.allowSymbolDrop, screenToWorld, onSymbolDrop]
|
|
5052
|
+
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
3567
5053
|
);
|
|
3568
5054
|
const handleDragLeave = useCallback7(() => {
|
|
3569
5055
|
setDragOverPosition(null);
|
|
@@ -3587,7 +5073,7 @@ function PIDCanvas({
|
|
|
3587
5073
|
const distance = Math.sqrt(
|
|
3588
5074
|
(worldPos.x - portPos.x) ** 2 + (worldPos.y - portPos.y) ** 2
|
|
3589
5075
|
);
|
|
3590
|
-
if (distance <
|
|
5076
|
+
if (distance < 15) {
|
|
3591
5077
|
foundPort = port.id;
|
|
3592
5078
|
foundNode = node.id;
|
|
3593
5079
|
break;
|
|
@@ -3604,9 +5090,11 @@ function PIDCanvas({
|
|
|
3604
5090
|
const { name } = diagram;
|
|
3605
5091
|
const viewBox = controlledViewBox;
|
|
3606
5092
|
const displayDiagram = localDiagram;
|
|
3607
|
-
|
|
5093
|
+
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5094
|
+
return /* @__PURE__ */ jsxs13(
|
|
3608
5095
|
"div",
|
|
3609
5096
|
{
|
|
5097
|
+
ref: containerRef,
|
|
3610
5098
|
className: `pid-canvas ${className}`.trim(),
|
|
3611
5099
|
style: {
|
|
3612
5100
|
width: "100%",
|
|
@@ -3617,223 +5105,287 @@ function PIDCanvas({
|
|
|
3617
5105
|
...style
|
|
3618
5106
|
},
|
|
3619
5107
|
...props,
|
|
3620
|
-
children:
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
/* @__PURE__ */
|
|
3641
|
-
/* @__PURE__ */
|
|
3642
|
-
|
|
3643
|
-
/* @__PURE__ */
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
5108
|
+
children: [
|
|
5109
|
+
/* @__PURE__ */ jsxs13(
|
|
5110
|
+
"svg",
|
|
5111
|
+
{
|
|
5112
|
+
ref: svgRef,
|
|
5113
|
+
width: "100%",
|
|
5114
|
+
height: "100%",
|
|
5115
|
+
viewBox: `${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`,
|
|
5116
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
5117
|
+
style: {
|
|
5118
|
+
display: "block"
|
|
5119
|
+
},
|
|
5120
|
+
"aria-label": `P&ID diagram: ${name}`,
|
|
5121
|
+
role: "img",
|
|
5122
|
+
onClick: handleCanvasClick,
|
|
5123
|
+
onMouseMove: handleMouseMove,
|
|
5124
|
+
onDragOver: handleDragOver,
|
|
5125
|
+
onDrop: handleDrop,
|
|
5126
|
+
onDragLeave: handleDragLeave,
|
|
5127
|
+
children: [
|
|
5128
|
+
features.showGrid !== false ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
5129
|
+
/* @__PURE__ */ jsxs13("defs", { children: [
|
|
5130
|
+
/* @__PURE__ */ jsx17("pattern", { id: "grid-minor", width: "5", height: "5", patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx17("path", { d: "M 5 0 L 0 0 0 5", fill: "none", stroke: "#e5e7eb", strokeWidth: "0.5" }) }),
|
|
5131
|
+
/* @__PURE__ */ jsxs13("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5132
|
+
/* @__PURE__ */ jsx17("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5133
|
+
/* @__PURE__ */ jsx17("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5134
|
+
] })
|
|
5135
|
+
] }),
|
|
5136
|
+
/* @__PURE__ */ jsx17(
|
|
5137
|
+
"rect",
|
|
5138
|
+
{
|
|
5139
|
+
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
5140
|
+
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
5141
|
+
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
5142
|
+
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
5143
|
+
fill: "url(#grid-major)"
|
|
5144
|
+
}
|
|
5145
|
+
)
|
|
5146
|
+
] }) : /* @__PURE__ */ jsx17(
|
|
3648
5147
|
"rect",
|
|
3649
5148
|
{
|
|
3650
5149
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3651
5150
|
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3652
5151
|
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3653
5152
|
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3654
|
-
fill: "
|
|
5153
|
+
fill: features.backgroundColor ?? "#ffffff"
|
|
3655
5154
|
}
|
|
3656
|
-
)
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
{
|
|
3660
|
-
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3661
|
-
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3662
|
-
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3663
|
-
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3664
|
-
fill: features.backgroundColor ?? "#ffffff"
|
|
3665
|
-
}
|
|
3666
|
-
),
|
|
3667
|
-
/* @__PURE__ */ jsx16(
|
|
3668
|
-
PipeRenderer,
|
|
3669
|
-
{
|
|
3670
|
-
pipes: displayDiagram.pipes,
|
|
3671
|
-
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
3672
|
-
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
3673
|
-
enableWaypointEditing: false,
|
|
3674
|
-
onWaypointDragStart: void 0,
|
|
3675
|
-
editingPipeId: null,
|
|
3676
|
-
draggingWaypointIndex: null,
|
|
3677
|
-
waypointDragOffset: void 0,
|
|
3678
|
-
onPipeSegmentClick: void 0
|
|
3679
|
-
}
|
|
3680
|
-
),
|
|
3681
|
-
/* @__PURE__ */ jsx16(
|
|
3682
|
-
NodeRenderer,
|
|
3683
|
-
{
|
|
3684
|
-
nodes: displayDiagram.nodes,
|
|
3685
|
-
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
3686
|
-
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
3687
|
-
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
3688
|
-
enableDrag: dragEnabled && !isConnecting,
|
|
3689
|
-
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
3690
|
-
draggingNodeId: dragState.draggedId,
|
|
3691
|
-
dragOffset: dragState.offset
|
|
3692
|
-
}
|
|
3693
|
-
),
|
|
3694
|
-
(features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx16(
|
|
3695
|
-
PipeRenderer,
|
|
3696
|
-
{
|
|
3697
|
-
pipes: displayDiagram.pipes,
|
|
3698
|
-
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
3699
|
-
onPipeClick: void 0,
|
|
3700
|
-
enableWaypointEditing: true,
|
|
3701
|
-
onWaypointDragStart: handleWaypointDragStart,
|
|
3702
|
-
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
3703
|
-
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
3704
|
-
waypointDragOffset: waypointDragState.offset,
|
|
3705
|
-
onPipeSegmentClick: handlePipeSegmentClick
|
|
3706
|
-
}
|
|
3707
|
-
),
|
|
3708
|
-
telemetryEnabled && telemetry && /* @__PURE__ */ jsx16("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
3709
|
-
const binding = telemetry.get(node.id);
|
|
3710
|
-
if (!binding) return null;
|
|
3711
|
-
const symbol = getSymbolDefinition(node.symbolId);
|
|
3712
|
-
if (!symbol) return null;
|
|
3713
|
-
const overlayY = node.transform.y - symbol.viewBox.height / 2 - 10;
|
|
3714
|
-
return /* @__PURE__ */ jsx16(
|
|
3715
|
-
DataOverlay,
|
|
5155
|
+
),
|
|
5156
|
+
/* @__PURE__ */ jsx17(
|
|
5157
|
+
PipeRenderer,
|
|
3716
5158
|
{
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
"circle",
|
|
3727
|
-
{
|
|
3728
|
-
cx: dragOverPosition.x,
|
|
3729
|
-
cy: dragOverPosition.y,
|
|
3730
|
-
r: 20,
|
|
3731
|
-
fill: "#3b82f6",
|
|
3732
|
-
opacity: 0.3,
|
|
3733
|
-
stroke: "#3b82f6",
|
|
3734
|
-
strokeWidth: 2,
|
|
3735
|
-
pointerEvents: "none"
|
|
3736
|
-
}
|
|
3737
|
-
),
|
|
3738
|
-
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx16("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
3739
|
-
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
3740
|
-
if (!sourceNode) return null;
|
|
3741
|
-
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
3742
|
-
let lineStartX = sourceNode.transform.x;
|
|
3743
|
-
let lineStartY = sourceNode.transform.y;
|
|
3744
|
-
if (connectionSourcePort && symbol?.ports) {
|
|
3745
|
-
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
3746
|
-
if (port) {
|
|
3747
|
-
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
3748
|
-
if (portPos) {
|
|
3749
|
-
lineStartX = portPos.x;
|
|
3750
|
-
lineStartY = portPos.y;
|
|
3751
|
-
}
|
|
5159
|
+
pipes: displayDiagram.pipes,
|
|
5160
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5161
|
+
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
5162
|
+
enableWaypointEditing: false,
|
|
5163
|
+
onWaypointDragStart: void 0,
|
|
5164
|
+
editingPipeId: null,
|
|
5165
|
+
draggingWaypointIndex: null,
|
|
5166
|
+
waypointDragOffset: void 0,
|
|
5167
|
+
onPipeSegmentClick: void 0
|
|
3752
5168
|
}
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
const symbol = getSymbolDefinition(node.symbolId);
|
|
3794
|
-
if (!symbol?.ports) return null;
|
|
3795
|
-
return symbol.ports.map((port) => {
|
|
3796
|
-
const portPos = getPortWorldPosition(node, port.id);
|
|
3797
|
-
if (!portPos) return null;
|
|
3798
|
-
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
3799
|
-
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
3800
|
-
return /* @__PURE__ */ jsx16(
|
|
3801
|
-
"circle",
|
|
5169
|
+
),
|
|
5170
|
+
/* @__PURE__ */ jsx17(
|
|
5171
|
+
NodeRenderer,
|
|
5172
|
+
{
|
|
5173
|
+
nodes: displayDiagram.nodes,
|
|
5174
|
+
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5175
|
+
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5176
|
+
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5177
|
+
enableDrag: dragEnabled && !isConnecting,
|
|
5178
|
+
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
5179
|
+
draggingNodeId: dragState.draggedId,
|
|
5180
|
+
dragOffset: dragState.offset
|
|
5181
|
+
}
|
|
5182
|
+
),
|
|
5183
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx17(
|
|
5184
|
+
PipeRenderer,
|
|
5185
|
+
{
|
|
5186
|
+
pipes: displayDiagram.pipes,
|
|
5187
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5188
|
+
onPipeClick: void 0,
|
|
5189
|
+
enableWaypointEditing: true,
|
|
5190
|
+
onWaypointClick: handleWaypointClick,
|
|
5191
|
+
onWaypointDragStart: handleWaypointDragStart,
|
|
5192
|
+
selectedWaypointPipeId: selectedWaypoint?.pipeId || null,
|
|
5193
|
+
selectedWaypointIndex: selectedWaypoint?.pointIndex ?? null,
|
|
5194
|
+
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
5195
|
+
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
5196
|
+
waypointDragOffset: waypointDragState.offset,
|
|
5197
|
+
onPipeSegmentClick: handlePipeSegmentClick
|
|
5198
|
+
}
|
|
5199
|
+
),
|
|
5200
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ jsx17("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5201
|
+
const binding = telemetry.get(node.id);
|
|
5202
|
+
if (!binding) return null;
|
|
5203
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5204
|
+
if (!symbol) return null;
|
|
5205
|
+
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5206
|
+
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5207
|
+
return /* @__PURE__ */ jsx17(
|
|
5208
|
+
DataOverlay,
|
|
3802
5209
|
{
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
3809
|
-
opacity: isHovered || isSourcePort ? 1 : 0.6
|
|
5210
|
+
nodeId: node.id,
|
|
5211
|
+
x: overlayX,
|
|
5212
|
+
y: overlayY,
|
|
5213
|
+
telemetry: binding,
|
|
5214
|
+
scale: features.telemetryScale ?? 1
|
|
3810
5215
|
},
|
|
3811
|
-
|
|
5216
|
+
`telemetry-${node.id}`
|
|
3812
5217
|
);
|
|
3813
|
-
})
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
5218
|
+
}) }),
|
|
5219
|
+
dragOverPosition && /* @__PURE__ */ jsx17(
|
|
5220
|
+
"circle",
|
|
5221
|
+
{
|
|
5222
|
+
cx: dragOverPosition.x,
|
|
5223
|
+
cy: dragOverPosition.y,
|
|
5224
|
+
r: 20,
|
|
5225
|
+
fill: "#3b82f6",
|
|
5226
|
+
opacity: 0.3,
|
|
5227
|
+
stroke: "#3b82f6",
|
|
5228
|
+
strokeWidth: 2,
|
|
5229
|
+
pointerEvents: "none"
|
|
5230
|
+
}
|
|
5231
|
+
),
|
|
5232
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx17("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5233
|
+
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5234
|
+
if (!sourceNode) return null;
|
|
5235
|
+
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
5236
|
+
let lineStartX = sourceNode.transform.x;
|
|
5237
|
+
let lineStartY = sourceNode.transform.y;
|
|
5238
|
+
if (connectionSourcePort && symbol?.ports) {
|
|
5239
|
+
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
5240
|
+
if (port) {
|
|
5241
|
+
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
5242
|
+
if (portPos) {
|
|
5243
|
+
lineStartX = portPos.x;
|
|
5244
|
+
lineStartY = portPos.y;
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
}
|
|
5248
|
+
return /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
5249
|
+
/* @__PURE__ */ jsx17(
|
|
5250
|
+
"circle",
|
|
5251
|
+
{
|
|
5252
|
+
cx: lineStartX,
|
|
5253
|
+
cy: lineStartY,
|
|
5254
|
+
r: 30,
|
|
5255
|
+
fill: "none",
|
|
5256
|
+
stroke: "#10b981",
|
|
5257
|
+
strokeWidth: 3,
|
|
5258
|
+
opacity: 0.6
|
|
5259
|
+
}
|
|
5260
|
+
),
|
|
5261
|
+
/* @__PURE__ */ jsx17(
|
|
5262
|
+
"line",
|
|
5263
|
+
{
|
|
5264
|
+
x1: lineStartX,
|
|
5265
|
+
y1: lineStartY,
|
|
5266
|
+
x2: connectionCursor.x,
|
|
5267
|
+
y2: connectionCursor.y,
|
|
5268
|
+
stroke: "#10b981",
|
|
5269
|
+
strokeWidth: 2,
|
|
5270
|
+
strokeDasharray: "5,5",
|
|
5271
|
+
opacity: 0.8
|
|
5272
|
+
}
|
|
5273
|
+
),
|
|
5274
|
+
/* @__PURE__ */ jsx17(
|
|
5275
|
+
"circle",
|
|
5276
|
+
{
|
|
5277
|
+
cx: connectionCursor.x,
|
|
5278
|
+
cy: connectionCursor.y,
|
|
5279
|
+
r: 8,
|
|
5280
|
+
fill: "#10b981",
|
|
5281
|
+
opacity: 0.6
|
|
5282
|
+
}
|
|
5283
|
+
)
|
|
5284
|
+
] });
|
|
5285
|
+
})() }),
|
|
5286
|
+
features.connectionMode && /* @__PURE__ */ jsx17("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5287
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5288
|
+
if (!symbol?.ports) return null;
|
|
5289
|
+
return symbol.ports.map((port) => {
|
|
5290
|
+
const portPos = getPortWorldPosition(node, port.id);
|
|
5291
|
+
if (!portPos) return null;
|
|
5292
|
+
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5293
|
+
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5294
|
+
return /* @__PURE__ */ jsxs13("g", { children: [
|
|
5295
|
+
/* @__PURE__ */ jsx17(
|
|
5296
|
+
"circle",
|
|
5297
|
+
{
|
|
5298
|
+
cx: portPos.x,
|
|
5299
|
+
cy: portPos.y,
|
|
5300
|
+
r: 15,
|
|
5301
|
+
fill: "transparent",
|
|
5302
|
+
style: { cursor: "pointer" },
|
|
5303
|
+
pointerEvents: "auto",
|
|
5304
|
+
onClick: (e) => {
|
|
5305
|
+
e.stopPropagation();
|
|
5306
|
+
if (isConnecting && connectionSource) {
|
|
5307
|
+
if (connectionSource !== node.id) {
|
|
5308
|
+
onPipeCreated?.(
|
|
5309
|
+
connectionSource,
|
|
5310
|
+
node.id,
|
|
5311
|
+
connectionSourcePort || void 0,
|
|
5312
|
+
port.id
|
|
5313
|
+
);
|
|
5314
|
+
setIsConnecting(false);
|
|
5315
|
+
setConnectionSource(null);
|
|
5316
|
+
setConnectionSourcePort(null);
|
|
5317
|
+
setConnectionCursor(null);
|
|
5318
|
+
setHoveredPort(null);
|
|
5319
|
+
}
|
|
5320
|
+
} else {
|
|
5321
|
+
setIsConnecting(true);
|
|
5322
|
+
setConnectionSource(node.id);
|
|
5323
|
+
setConnectionSourcePort(port.id);
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
),
|
|
5328
|
+
/* @__PURE__ */ jsx17(
|
|
5329
|
+
"circle",
|
|
5330
|
+
{
|
|
5331
|
+
cx: portPos.x,
|
|
5332
|
+
cy: portPos.y,
|
|
5333
|
+
r: isHovered ? 8 : 5,
|
|
5334
|
+
fill: isSourcePort ? "#10b981" : isHovered ? "#3b82f6" : "#94a3b8",
|
|
5335
|
+
stroke: isSourcePort ? "#059669" : isHovered ? "#2563eb" : "#64748b",
|
|
5336
|
+
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
5337
|
+
opacity: isHovered || isSourcePort ? 1 : 0.6,
|
|
5338
|
+
pointerEvents: "none"
|
|
5339
|
+
}
|
|
5340
|
+
)
|
|
5341
|
+
] }, `${node.id}-${port.id}`);
|
|
5342
|
+
});
|
|
5343
|
+
}) })
|
|
5344
|
+
]
|
|
5345
|
+
}
|
|
5346
|
+
),
|
|
5347
|
+
features.dragNodes && /* @__PURE__ */ jsx17(
|
|
5348
|
+
PositionPanel,
|
|
5349
|
+
{
|
|
5350
|
+
selectedNode,
|
|
5351
|
+
selectedWaypoint: selectedWaypoint ? {
|
|
5352
|
+
pipeId: selectedWaypoint.pipeId,
|
|
5353
|
+
pointIndex: selectedWaypoint.pointIndex,
|
|
5354
|
+
position: localDiagram.pipes.find((p) => p.id === selectedWaypoint.pipeId)?.routePoints[selectedWaypoint.pointIndex] || { x: 0, y: 0 }
|
|
5355
|
+
} : null,
|
|
5356
|
+
onPositionChange: handlePositionChange,
|
|
5357
|
+
onWaypointPositionChange: handleWaypointPositionChange,
|
|
5358
|
+
position: "top-right"
|
|
5359
|
+
}
|
|
5360
|
+
)
|
|
5361
|
+
]
|
|
3818
5362
|
}
|
|
3819
5363
|
);
|
|
3820
5364
|
}
|
|
3821
5365
|
|
|
3822
5366
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
3823
|
-
import { useState as
|
|
3824
|
-
import { jsx as
|
|
5367
|
+
import { useState as useState13 } from "react";
|
|
5368
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3825
5369
|
function SymbolLibrary({
|
|
3826
5370
|
className = "",
|
|
3827
5371
|
onSymbolDragStart,
|
|
3828
5372
|
showCategories = true,
|
|
3829
5373
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
3830
5374
|
}) {
|
|
3831
|
-
const [selectedCategory, setSelectedCategory] =
|
|
3832
|
-
const [searchQuery, setSearchQuery] =
|
|
5375
|
+
const [selectedCategory, setSelectedCategory] = useState13("all");
|
|
5376
|
+
const [searchQuery, setSearchQuery] = useState13("");
|
|
3833
5377
|
const symbolIds = getAvailableSymbols();
|
|
3834
5378
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5379
|
+
const categoryMap = {
|
|
5380
|
+
Valves: "valve",
|
|
5381
|
+
Pumps: "pump",
|
|
5382
|
+
Tanks: "vessel",
|
|
5383
|
+
Instruments: "instrument",
|
|
5384
|
+
Displays: "display"
|
|
5385
|
+
};
|
|
3835
5386
|
const filteredSymbols = allSymbols.filter((symbol) => {
|
|
3836
|
-
const
|
|
5387
|
+
const actualCategory = categoryMap[selectedCategory] || selectedCategory;
|
|
5388
|
+
const matchesCategory = selectedCategory === "all" || symbol.category === actualCategory;
|
|
3837
5389
|
const matchesSearch = searchQuery === "" || symbol.name.toLowerCase().includes(searchQuery.toLowerCase()) || symbol.id.toLowerCase().includes(searchQuery.toLowerCase());
|
|
3838
5390
|
return matchesCategory && matchesSearch;
|
|
3839
5391
|
});
|
|
@@ -3842,9 +5394,9 @@ function SymbolLibrary({
|
|
|
3842
5394
|
event.dataTransfer.effectAllowed = "copy";
|
|
3843
5395
|
onSymbolDragStart?.(symbol.id, event);
|
|
3844
5396
|
};
|
|
3845
|
-
return /* @__PURE__ */
|
|
3846
|
-
/* @__PURE__ */
|
|
3847
|
-
/* @__PURE__ */
|
|
5397
|
+
return /* @__PURE__ */ jsxs14("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
5398
|
+
/* @__PURE__ */ jsx18("div", { style: styles.header, children: /* @__PURE__ */ jsx18("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
5399
|
+
/* @__PURE__ */ jsx18("div", { style: styles.searchContainer, children: /* @__PURE__ */ jsx18(
|
|
3848
5400
|
"input",
|
|
3849
5401
|
{
|
|
3850
5402
|
type: "text",
|
|
@@ -3854,8 +5406,8 @@ function SymbolLibrary({
|
|
|
3854
5406
|
style: styles.searchInput
|
|
3855
5407
|
}
|
|
3856
5408
|
) }),
|
|
3857
|
-
showCategories && /* @__PURE__ */
|
|
3858
|
-
/* @__PURE__ */
|
|
5409
|
+
showCategories && /* @__PURE__ */ jsxs14("div", { style: styles.categories, children: [
|
|
5410
|
+
/* @__PURE__ */ jsx18(
|
|
3859
5411
|
"button",
|
|
3860
5412
|
{
|
|
3861
5413
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -3866,7 +5418,7 @@ function SymbolLibrary({
|
|
|
3866
5418
|
children: "All"
|
|
3867
5419
|
}
|
|
3868
5420
|
),
|
|
3869
|
-
categories.map((category) => /* @__PURE__ */
|
|
5421
|
+
categories.map((category) => /* @__PURE__ */ jsx18(
|
|
3870
5422
|
"button",
|
|
3871
5423
|
{
|
|
3872
5424
|
onClick: () => setSelectedCategory(category),
|
|
@@ -3879,7 +5431,7 @@ function SymbolLibrary({
|
|
|
3879
5431
|
category
|
|
3880
5432
|
))
|
|
3881
5433
|
] }),
|
|
3882
|
-
/* @__PURE__ */
|
|
5434
|
+
/* @__PURE__ */ jsx18("div", { style: styles.symbolGrid, children: filteredSymbols.length === 0 ? /* @__PURE__ */ jsx18("div", { style: styles.emptyState, children: "No symbols found" }) : filteredSymbols.map((symbol) => /* @__PURE__ */ jsxs14(
|
|
3883
5435
|
"div",
|
|
3884
5436
|
{
|
|
3885
5437
|
draggable: true,
|
|
@@ -3887,15 +5439,15 @@ function SymbolLibrary({
|
|
|
3887
5439
|
style: styles.symbolCard,
|
|
3888
5440
|
title: symbol.metadata?.description || symbol.name,
|
|
3889
5441
|
children: [
|
|
3890
|
-
/* @__PURE__ */
|
|
5442
|
+
/* @__PURE__ */ jsx18("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx18(
|
|
3891
5443
|
"svg",
|
|
3892
5444
|
{
|
|
3893
5445
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
3894
5446
|
style: styles.symbolSvg,
|
|
3895
|
-
children: /* @__PURE__ */
|
|
5447
|
+
children: /* @__PURE__ */ jsx18("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
3896
5448
|
}
|
|
3897
5449
|
) }),
|
|
3898
|
-
/* @__PURE__ */
|
|
5450
|
+
/* @__PURE__ */ jsx18("div", { style: styles.symbolName, children: symbol.name })
|
|
3899
5451
|
]
|
|
3900
5452
|
},
|
|
3901
5453
|
symbol.id
|
|
@@ -4004,7 +5556,7 @@ var styles = {
|
|
|
4004
5556
|
};
|
|
4005
5557
|
|
|
4006
5558
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
4007
|
-
import { Fragment as Fragment6, jsx as
|
|
5559
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4008
5560
|
function NodeConfigPanel({
|
|
4009
5561
|
node,
|
|
4010
5562
|
binding,
|
|
@@ -4023,15 +5575,15 @@ function NodeConfigPanel({
|
|
|
4023
5575
|
padding: "20px",
|
|
4024
5576
|
...style
|
|
4025
5577
|
};
|
|
4026
|
-
return /* @__PURE__ */
|
|
4027
|
-
/* @__PURE__ */
|
|
5578
|
+
return /* @__PURE__ */ jsxs15("div", { className, style: defaultStyle, children: [
|
|
5579
|
+
/* @__PURE__ */ jsxs15("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
4028
5580
|
"Configure: ",
|
|
4029
5581
|
node.id
|
|
4030
5582
|
] }),
|
|
4031
|
-
/* @__PURE__ */
|
|
4032
|
-
/* @__PURE__ */
|
|
4033
|
-
/* @__PURE__ */
|
|
4034
|
-
/* @__PURE__ */
|
|
5583
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
5584
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
5585
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
5586
|
+
/* @__PURE__ */ jsx19(
|
|
4035
5587
|
"input",
|
|
4036
5588
|
{
|
|
4037
5589
|
type: "text",
|
|
@@ -4047,10 +5599,10 @@ function NodeConfigPanel({
|
|
|
4047
5599
|
}
|
|
4048
5600
|
}
|
|
4049
5601
|
),
|
|
4050
|
-
/* @__PURE__ */
|
|
4051
|
-
/* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4053
|
-
/* @__PURE__ */
|
|
5602
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5603
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5604
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
5605
|
+
/* @__PURE__ */ jsx19(
|
|
4054
5606
|
"input",
|
|
4055
5607
|
{
|
|
4056
5608
|
type: "number",
|
|
@@ -4071,9 +5623,9 @@ function NodeConfigPanel({
|
|
|
4071
5623
|
}
|
|
4072
5624
|
)
|
|
4073
5625
|
] }),
|
|
4074
|
-
/* @__PURE__ */
|
|
4075
|
-
/* @__PURE__ */
|
|
4076
|
-
/* @__PURE__ */
|
|
5626
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5627
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
5628
|
+
/* @__PURE__ */ jsx19(
|
|
4077
5629
|
"input",
|
|
4078
5630
|
{
|
|
4079
5631
|
type: "number",
|
|
@@ -4095,9 +5647,9 @@ function NodeConfigPanel({
|
|
|
4095
5647
|
)
|
|
4096
5648
|
] })
|
|
4097
5649
|
] }),
|
|
4098
|
-
/* @__PURE__ */
|
|
4099
|
-
/* @__PURE__ */
|
|
4100
|
-
/* @__PURE__ */
|
|
5650
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5651
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
5652
|
+
/* @__PURE__ */ jsx19(
|
|
4101
5653
|
"input",
|
|
4102
5654
|
{
|
|
4103
5655
|
type: "number",
|
|
@@ -4117,9 +5669,9 @@ function NodeConfigPanel({
|
|
|
4117
5669
|
}
|
|
4118
5670
|
)
|
|
4119
5671
|
] }),
|
|
4120
|
-
/* @__PURE__ */
|
|
4121
|
-
/* @__PURE__ */
|
|
4122
|
-
/* @__PURE__ */
|
|
5672
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5673
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
5674
|
+
/* @__PURE__ */ jsx19(
|
|
4123
5675
|
"input",
|
|
4124
5676
|
{
|
|
4125
5677
|
type: "number",
|
|
@@ -4144,9 +5696,9 @@ function NodeConfigPanel({
|
|
|
4144
5696
|
)
|
|
4145
5697
|
] })
|
|
4146
5698
|
] }),
|
|
4147
|
-
/* @__PURE__ */
|
|
4148
|
-
/* @__PURE__ */
|
|
4149
|
-
!binding ? /* @__PURE__ */
|
|
5699
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
5700
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
5701
|
+
!binding ? /* @__PURE__ */ jsx19(
|
|
4150
5702
|
"button",
|
|
4151
5703
|
{
|
|
4152
5704
|
onClick: () => {
|
|
@@ -4189,9 +5741,9 @@ function NodeConfigPanel({
|
|
|
4189
5741
|
},
|
|
4190
5742
|
children: "+ Add Telemetry"
|
|
4191
5743
|
}
|
|
4192
|
-
) : /* @__PURE__ */
|
|
4193
|
-
/* @__PURE__ */
|
|
4194
|
-
/* @__PURE__ */
|
|
5744
|
+
) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
5745
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
5746
|
+
/* @__PURE__ */ jsx19(
|
|
4195
5747
|
"input",
|
|
4196
5748
|
{
|
|
4197
5749
|
type: "number",
|
|
@@ -4213,8 +5765,8 @@ function NodeConfigPanel({
|
|
|
4213
5765
|
}
|
|
4214
5766
|
}
|
|
4215
5767
|
),
|
|
4216
|
-
/* @__PURE__ */
|
|
4217
|
-
/* @__PURE__ */
|
|
5768
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
5769
|
+
/* @__PURE__ */ jsx19(
|
|
4218
5770
|
"input",
|
|
4219
5771
|
{
|
|
4220
5772
|
type: "text",
|
|
@@ -4236,8 +5788,8 @@ function NodeConfigPanel({
|
|
|
4236
5788
|
}
|
|
4237
5789
|
}
|
|
4238
5790
|
),
|
|
4239
|
-
/* @__PURE__ */
|
|
4240
|
-
/* @__PURE__ */
|
|
5791
|
+
/* @__PURE__ */ jsxs15("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
5792
|
+
/* @__PURE__ */ jsx19(
|
|
4241
5793
|
"input",
|
|
4242
5794
|
{
|
|
4243
5795
|
type: "checkbox",
|
|
@@ -4259,8 +5811,8 @@ function NodeConfigPanel({
|
|
|
4259
5811
|
),
|
|
4260
5812
|
"Show Sparkline"
|
|
4261
5813
|
] }),
|
|
4262
|
-
/* @__PURE__ */
|
|
4263
|
-
/* @__PURE__ */
|
|
5814
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginTop: "12px" }, children: [
|
|
5815
|
+
/* @__PURE__ */ jsx19(
|
|
4264
5816
|
"label",
|
|
4265
5817
|
{
|
|
4266
5818
|
style: {
|
|
@@ -4272,10 +5824,10 @@ function NodeConfigPanel({
|
|
|
4272
5824
|
children: "Telemetry Position Offset:"
|
|
4273
5825
|
}
|
|
4274
5826
|
),
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
4277
|
-
/* @__PURE__ */
|
|
4278
|
-
/* @__PURE__ */
|
|
5827
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5828
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5829
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
5830
|
+
/* @__PURE__ */ jsx19(
|
|
4279
5831
|
"input",
|
|
4280
5832
|
{
|
|
4281
5833
|
type: "number",
|
|
@@ -4302,9 +5854,9 @@ function NodeConfigPanel({
|
|
|
4302
5854
|
}
|
|
4303
5855
|
)
|
|
4304
5856
|
] }),
|
|
4305
|
-
/* @__PURE__ */
|
|
4306
|
-
/* @__PURE__ */
|
|
4307
|
-
/* @__PURE__ */
|
|
5857
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5858
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
5859
|
+
/* @__PURE__ */ jsx19(
|
|
4308
5860
|
"input",
|
|
4309
5861
|
{
|
|
4310
5862
|
type: "number",
|
|
@@ -4332,8 +5884,8 @@ function NodeConfigPanel({
|
|
|
4332
5884
|
)
|
|
4333
5885
|
] })
|
|
4334
5886
|
] }),
|
|
4335
|
-
/* @__PURE__ */
|
|
4336
|
-
/* @__PURE__ */
|
|
5887
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginTop: "16px" }, children: [
|
|
5888
|
+
/* @__PURE__ */ jsx19(
|
|
4337
5889
|
"label",
|
|
4338
5890
|
{
|
|
4339
5891
|
style: {
|
|
@@ -4345,10 +5897,10 @@ function NodeConfigPanel({
|
|
|
4345
5897
|
children: "Display Colors:"
|
|
4346
5898
|
}
|
|
4347
5899
|
),
|
|
4348
|
-
/* @__PURE__ */
|
|
4349
|
-
/* @__PURE__ */
|
|
4350
|
-
/* @__PURE__ */
|
|
4351
|
-
/* @__PURE__ */
|
|
5900
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
5901
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
5902
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
5903
|
+
/* @__PURE__ */ jsx19(
|
|
4352
5904
|
"input",
|
|
4353
5905
|
{
|
|
4354
5906
|
type: "color",
|
|
@@ -4374,7 +5926,7 @@ function NodeConfigPanel({
|
|
|
4374
5926
|
}
|
|
4375
5927
|
}
|
|
4376
5928
|
),
|
|
4377
|
-
/* @__PURE__ */
|
|
5929
|
+
/* @__PURE__ */ jsx19(
|
|
4378
5930
|
"input",
|
|
4379
5931
|
{
|
|
4380
5932
|
type: "text",
|
|
@@ -4404,10 +5956,10 @@ function NodeConfigPanel({
|
|
|
4404
5956
|
)
|
|
4405
5957
|
] })
|
|
4406
5958
|
] }),
|
|
4407
|
-
binding.display?.showSparkline && /* @__PURE__ */
|
|
4408
|
-
/* @__PURE__ */
|
|
4409
|
-
/* @__PURE__ */
|
|
4410
|
-
/* @__PURE__ */
|
|
5959
|
+
binding.display?.showSparkline && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
5960
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
5961
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
5962
|
+
/* @__PURE__ */ jsx19(
|
|
4411
5963
|
"input",
|
|
4412
5964
|
{
|
|
4413
5965
|
type: "color",
|
|
@@ -4433,7 +5985,7 @@ function NodeConfigPanel({
|
|
|
4433
5985
|
}
|
|
4434
5986
|
}
|
|
4435
5987
|
),
|
|
4436
|
-
/* @__PURE__ */
|
|
5988
|
+
/* @__PURE__ */ jsx19(
|
|
4437
5989
|
"input",
|
|
4438
5990
|
{
|
|
4439
5991
|
type: "text",
|
|
@@ -4463,9 +6015,9 @@ function NodeConfigPanel({
|
|
|
4463
6015
|
)
|
|
4464
6016
|
] })
|
|
4465
6017
|
] }),
|
|
4466
|
-
/* @__PURE__ */
|
|
4467
|
-
/* @__PURE__ */
|
|
4468
|
-
/* @__PURE__ */
|
|
6018
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6019
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6020
|
+
/* @__PURE__ */ jsx19(
|
|
4469
6021
|
"input",
|
|
4470
6022
|
{
|
|
4471
6023
|
type: "text",
|
|
@@ -4493,20 +6045,20 @@ function NodeConfigPanel({
|
|
|
4493
6045
|
}
|
|
4494
6046
|
}
|
|
4495
6047
|
),
|
|
4496
|
-
/* @__PURE__ */
|
|
6048
|
+
/* @__PURE__ */ jsx19("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
4497
6049
|
] })
|
|
4498
6050
|
] }),
|
|
4499
6051
|
" "
|
|
4500
6052
|
] })
|
|
4501
6053
|
] })
|
|
4502
6054
|
] }),
|
|
4503
|
-
binding && /* @__PURE__ */
|
|
4504
|
-
/* @__PURE__ */
|
|
6055
|
+
binding && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
6056
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
4505
6057
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
4506
6058
|
const label = key === "highHigh" ? "High-High (\u2265)" : key === "high" ? "High (\u2265)" : key === "low" ? "Low (\u2264)" : "Low-Low (\u2264)";
|
|
4507
|
-
return /* @__PURE__ */
|
|
4508
|
-
/* @__PURE__ */
|
|
4509
|
-
/* @__PURE__ */
|
|
6059
|
+
return /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6060
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6061
|
+
/* @__PURE__ */ jsx19(
|
|
4510
6062
|
"input",
|
|
4511
6063
|
{
|
|
4512
6064
|
type: "number",
|
|
@@ -4530,8 +6082,8 @@ function NodeConfigPanel({
|
|
|
4530
6082
|
] }, key);
|
|
4531
6083
|
})
|
|
4532
6084
|
] }),
|
|
4533
|
-
binding && /* @__PURE__ */
|
|
4534
|
-
/* @__PURE__ */
|
|
6085
|
+
binding && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
6086
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
4535
6087
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
4536
6088
|
const defaultColors = {
|
|
4537
6089
|
normal: "#10b981",
|
|
@@ -4541,13 +6093,13 @@ function NodeConfigPanel({
|
|
|
4541
6093
|
off: "#6b7280"
|
|
4542
6094
|
};
|
|
4543
6095
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
4544
|
-
return /* @__PURE__ */
|
|
4545
|
-
/* @__PURE__ */
|
|
6096
|
+
return /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6097
|
+
/* @__PURE__ */ jsxs15("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
4546
6098
|
label,
|
|
4547
6099
|
":"
|
|
4548
6100
|
] }),
|
|
4549
|
-
/* @__PURE__ */
|
|
4550
|
-
/* @__PURE__ */
|
|
6101
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6102
|
+
/* @__PURE__ */ jsx19(
|
|
4551
6103
|
"input",
|
|
4552
6104
|
{
|
|
4553
6105
|
type: "color",
|
|
@@ -4568,7 +6120,7 @@ function NodeConfigPanel({
|
|
|
4568
6120
|
}
|
|
4569
6121
|
}
|
|
4570
6122
|
),
|
|
4571
|
-
/* @__PURE__ */
|
|
6123
|
+
/* @__PURE__ */ jsx19(
|
|
4572
6124
|
"input",
|
|
4573
6125
|
{
|
|
4574
6126
|
type: "text",
|
|
@@ -4595,7 +6147,7 @@ function NodeConfigPanel({
|
|
|
4595
6147
|
] }, status);
|
|
4596
6148
|
})
|
|
4597
6149
|
] }),
|
|
4598
|
-
/* @__PURE__ */
|
|
6150
|
+
/* @__PURE__ */ jsx19("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ jsx19(
|
|
4599
6151
|
"button",
|
|
4600
6152
|
{
|
|
4601
6153
|
onClick: onRemove,
|
|
@@ -4835,7 +6387,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
4835
6387
|
};
|
|
4836
6388
|
|
|
4837
6389
|
// src/diagram/hooks/useSimulation.ts
|
|
4838
|
-
import { useEffect as
|
|
6390
|
+
import { useEffect as useEffect11 } from "react";
|
|
4839
6391
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
4840
6392
|
const {
|
|
4841
6393
|
interval = 2e3,
|
|
@@ -4846,7 +6398,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
4846
6398
|
historyLength = 10,
|
|
4847
6399
|
generateValue
|
|
4848
6400
|
} = options;
|
|
4849
|
-
|
|
6401
|
+
useEffect11(() => {
|
|
4850
6402
|
if (!enabled) return;
|
|
4851
6403
|
const intervalId = setInterval(() => {
|
|
4852
6404
|
const updates = [];
|
|
@@ -4948,6 +6500,7 @@ export {
|
|
|
4948
6500
|
useSelection,
|
|
4949
6501
|
useSimulation,
|
|
4950
6502
|
useTelemetry,
|
|
6503
|
+
useTelemetryStatus,
|
|
4951
6504
|
useTheme,
|
|
4952
6505
|
useViewBox,
|
|
4953
6506
|
validateDiagram
|