@procaaso/alphinity-ui-components 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2076 -473
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +2026 -426
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1694,145 +1694,1224 @@ 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-
|
|
1702
|
-
id: "valve-
|
|
1703
|
-
name: "
|
|
1701
|
+
"valve-gate": {
|
|
1702
|
+
id: "valve-gate",
|
|
1703
|
+
name: "Gate Valve (Powered)",
|
|
1704
1704
|
category: "valve",
|
|
1705
|
-
viewBox: { x: 0, y: 0, width:
|
|
1705
|
+
viewBox: { x: 0, y: 0, width: 26, height: 26 },
|
|
1706
1706
|
ports: [
|
|
1707
|
-
{ id: "inlet", x: 0, y:
|
|
1708
|
-
{ id: "outlet", x:
|
|
1707
|
+
{ id: "inlet", x: 0, y: 18, type: "inlet", direction: "in" },
|
|
1708
|
+
{ id: "outlet", x: 26, y: 18, type: "outlet", direction: "out" }
|
|
1709
1709
|
],
|
|
1710
1710
|
svgContent: `
|
|
1711
|
-
<g>
|
|
1712
|
-
<!--
|
|
1713
|
-
<rect x="
|
|
1714
|
-
<!--
|
|
1715
|
-
<
|
|
1716
|
-
<!--
|
|
1717
|
-
<
|
|
1718
|
-
<line x1="35" y1="25" x2="50" y2="25" stroke="#263238" stroke-width="3" stroke-linecap="round"/>
|
|
1711
|
+
<g transform="scale(0.5)">
|
|
1712
|
+
<!-- Actuator box -->
|
|
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"/>
|
|
1714
|
+
<!-- Actuator stem -->
|
|
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"/>
|
|
1716
|
+
<!-- Valve body (two triangles forming diamond) -->
|
|
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"/>
|
|
1719
1718
|
</g>
|
|
1720
1719
|
`,
|
|
1721
1720
|
metadata: {
|
|
1722
|
-
description: "
|
|
1723
|
-
tags: ["valve", "
|
|
1721
|
+
description: "Gate valve with powered actuator",
|
|
1722
|
+
tags: ["valve", "gate", "powered", "actuator"]
|
|
1724
1723
|
}
|
|
1725
1724
|
},
|
|
1726
|
-
"
|
|
1727
|
-
id: "
|
|
1728
|
-
name: "
|
|
1725
|
+
"pump-positive-displacement": {
|
|
1726
|
+
id: "pump-positive-displacement",
|
|
1727
|
+
name: "Positive Displacement Pump",
|
|
1728
|
+
category: "pump",
|
|
1729
|
+
viewBox: { x: 0, y: 0, width: 28.125, height: 28.125 },
|
|
1730
|
+
ports: [
|
|
1731
|
+
{ id: "inlet", x: 0, y: 14.0625, type: "inlet", direction: "in" },
|
|
1732
|
+
{ id: "outlet", x: 28.125, y: 14.0625, type: "outlet", direction: "out" }
|
|
1733
|
+
],
|
|
1734
|
+
svgContent: `
|
|
1735
|
+
<g transform="scale(0.28125)">
|
|
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)",
|
|
1729
1776
|
category: "valve",
|
|
1730
|
-
viewBox: { x: 0, y: 0, width:
|
|
1777
|
+
viewBox: { x: -0.25, y: -0.25, width: 44, height: 33.892578 },
|
|
1731
1778
|
ports: [
|
|
1732
|
-
{ id: "inlet", x: 0, y:
|
|
1733
|
-
{ id: "outlet", x:
|
|
1779
|
+
{ id: "bottom-inlet", x: 0, y: 12.5, type: "control", direction: "in" },
|
|
1780
|
+
{ id: "top-outlet", x: 24, y: 32.5, type: "control", direction: "out" }
|
|
1734
1781
|
],
|
|
1735
1782
|
svgContent: `
|
|
1736
|
-
<g>
|
|
1737
|
-
<!--
|
|
1738
|
-
<
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1783
|
+
<g transform="scale(0.5)">
|
|
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
|
+
|
|
1743
1830
|
</g>
|
|
1744
1831
|
`,
|
|
1745
1832
|
metadata: {
|
|
1746
|
-
description: "
|
|
1747
|
-
tags: ["
|
|
1833
|
+
description: "Vannefold heat exchanger block with bottom inlet configuration",
|
|
1834
|
+
tags: ["heat-exchanger", "vannefold", "fold", "bottom"]
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
"vannefold-middle": {
|
|
1838
|
+
id: "vannefold-middle",
|
|
1839
|
+
name: "Vannefold Block (Middle)",
|
|
1840
|
+
category: "valve",
|
|
1841
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 26.548828 },
|
|
1842
|
+
ports: [
|
|
1843
|
+
{ id: "left-inlet", x: 0, y: 13.65625, type: "control", direction: "in" },
|
|
1844
|
+
{ id: "right-outlet", x: 47.5, y: 13.65625, type: "control", direction: "out" }
|
|
1845
|
+
],
|
|
1846
|
+
svgContent: `
|
|
1847
|
+
<g transform="scale(0.5)">
|
|
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)" />
|
|
1885
|
+
</g>
|
|
1886
|
+
`,
|
|
1887
|
+
metadata: {
|
|
1888
|
+
description: "Vannefold heat exchanger block with side inlet configuration",
|
|
1889
|
+
tags: ["heat-exchanger", "vannefold", "fold", "middle"]
|
|
1890
|
+
}
|
|
1891
|
+
},
|
|
1892
|
+
"vannefold-top": {
|
|
1893
|
+
id: "vannefold-top",
|
|
1894
|
+
name: "Vannefold Block (Top)",
|
|
1895
|
+
category: "valve",
|
|
1896
|
+
viewBox: { x: -0.25, y: -0.25, width: 47.5, height: 30.392578 },
|
|
1897
|
+
ports: [
|
|
1898
|
+
{ id: "bottom-inlet", x: 0, y: 17.5, type: "control", direction: "in" },
|
|
1899
|
+
{ id: "top-outlet", x: 24, y: 0, type: "control", direction: "out" }
|
|
1900
|
+
],
|
|
1901
|
+
svgContent: `
|
|
1902
|
+
<g transform="scale(0.5)">
|
|
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"]
|
|
1748
1946
|
}
|
|
1749
1947
|
},
|
|
1750
|
-
"
|
|
1751
|
-
id: "
|
|
1752
|
-
name: "
|
|
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: 44, height: 33.788002 },
|
|
1953
|
+
ports: [
|
|
1954
|
+
{ id: "top-inlet", x: 23.5, y: 0, type: "control", direction: "in" },
|
|
1955
|
+
{ id: "bottom-outlet", x: 0, y: 21, type: "control", direction: "out" }
|
|
1956
|
+
],
|
|
1957
|
+
svgContent: `
|
|
1958
|
+
<g transform="scale(0.5)">
|
|
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: 33.892578, height: 44.25 },
|
|
2017
|
+
ports: [
|
|
2018
|
+
{ id: "left-inlet", x: 0, y: 20.75, type: "control", direction: "in" },
|
|
2019
|
+
{ id: "right-outlet", x: 21, y: 43.5, type: "control", direction: "out" }
|
|
2020
|
+
],
|
|
2021
|
+
svgContent: `
|
|
2022
|
+
<g transform="scale(0.5)">
|
|
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: 33.892578, height: 44.25 },
|
|
2080
|
+
ports: [
|
|
2081
|
+
{ id: "right-inlet", x: 33.892578, y: 20.75, type: "control", direction: "in" },
|
|
2082
|
+
{ id: "left-outlet", x: 12.392578, y: 43.75, type: "control", direction: "out" }
|
|
2083
|
+
],
|
|
2084
|
+
svgContent: `
|
|
2085
|
+
<g transform="scale(0.5)">
|
|
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",
|
|
1753
2141
|
category: "pump",
|
|
1754
|
-
viewBox: { x: 0, y: 0, width:
|
|
2142
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
1755
2143
|
ports: [
|
|
1756
|
-
{ id: "
|
|
1757
|
-
{ id: "outlet", x:
|
|
2144
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
2145
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
2146
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
2147
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
2148
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
1758
2149
|
],
|
|
1759
2150
|
svgContent: `
|
|
1760
|
-
<g>
|
|
1761
|
-
<!--
|
|
1762
|
-
<
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
2151
|
+
<g transform="scale(0.0984375) 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
|
+
/>
|
|
1772
2405
|
</g>
|
|
1773
2406
|
`,
|
|
1774
2407
|
metadata: {
|
|
1775
|
-
description: "
|
|
1776
|
-
tags: ["
|
|
2408
|
+
description: "Pixer mixer/agitator vessel with top-mounted drive",
|
|
2409
|
+
tags: ["vessel", "mixer", "agitator", "pixer", "tank"]
|
|
1777
2410
|
}
|
|
1778
2411
|
},
|
|
1779
|
-
"
|
|
1780
|
-
id: "
|
|
1781
|
-
name: "
|
|
2412
|
+
"pixer-barb": {
|
|
2413
|
+
id: "pixer-barb",
|
|
2414
|
+
name: "Pixer (Hose Barb)",
|
|
2415
|
+
category: "pump",
|
|
2416
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 23.34375 },
|
|
2417
|
+
ports: [
|
|
2418
|
+
{ id: "right-outlet", x: 25.3125, y: 15.46875, type: "control", direction: "out" },
|
|
2419
|
+
{ id: "left-outlet", x: 0, y: 15.46875, type: "control", direction: "out" },
|
|
2420
|
+
{ id: "left-inlet", x: 25.3125, y: 9.84375, type: "control", direction: "in" },
|
|
2421
|
+
{ id: "right-inlet", x: 0, y: 9.84375, type: "control", direction: "in" },
|
|
2422
|
+
{ id: "top-inlet", x: 12.65625, y: 0, type: "control", direction: "in" }
|
|
2423
|
+
],
|
|
2424
|
+
svgContent: `
|
|
2425
|
+
<g transform="scale(0.0984375) 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",
|
|
1782
2706
|
category: "vessel",
|
|
1783
|
-
viewBox: { x: 0, y: 0, width:
|
|
2707
|
+
viewBox: { x: 0, y: 0, width: 25.3125, height: 45.5 },
|
|
2708
|
+
ports: [
|
|
2709
|
+
{ id: "top", type: "inlet", x: 12.65625, y: 0 },
|
|
2710
|
+
{ id: "left", type: "inlet", x: 2.5, y: 19.5 },
|
|
2711
|
+
{ id: "right", type: "outlet", x: 22.8125, y: 19.5 },
|
|
2712
|
+
{ id: "bottom", type: "outlet", x: 12.65625, y: 45.5 }
|
|
2713
|
+
],
|
|
2714
|
+
svgContent: `
|
|
2715
|
+
<g transform="scale(0.0984375) 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
|
+
"hollow-fiber": {
|
|
2781
|
+
id: "hollow-fiber",
|
|
2782
|
+
name: "Hollow Fiber",
|
|
2783
|
+
category: "other",
|
|
2784
|
+
viewBox: { x: 0, y: 0, width: 30, height: 109 },
|
|
2785
|
+
ports: [
|
|
2786
|
+
{ id: "top-left", type: "outlet", x: 10, y: 2.75 },
|
|
2787
|
+
{ id: "top-right", type: "outlet", x: 24.5, y: 22.25 },
|
|
2788
|
+
{ id: "bottom-left", type: "inlet", x: 10, y: 106.25 },
|
|
2789
|
+
{ id: "bottom-right", type: "inlet", x: 24.5, y: 87.25 }
|
|
2790
|
+
],
|
|
2791
|
+
svgContent: `
|
|
2792
|
+
<g transform="scale(0.5)">
|
|
2793
|
+
<!-- Top left flange -->
|
|
2794
|
+
<rect x="10.5" y="0.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2795
|
+
|
|
2796
|
+
<!-- Top right flange -->
|
|
2797
|
+
<rect x="39.5" y="39.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2798
|
+
|
|
2799
|
+
<!-- Bottom left flange -->
|
|
2800
|
+
<rect x="10.5" y="207.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2801
|
+
|
|
2802
|
+
<!-- Bottom right flange -->
|
|
2803
|
+
<rect x="39.5" y="169.5" width="20" height="10" rx="1.5" ry="1.5" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2804
|
+
|
|
2805
|
+
<!-- Main vessel body -->
|
|
2806
|
+
<rect x="0.5" y="9.5" width="40" height="199.5" rx="6" ry="6" fill="var(--symbol-fill, #eaeaea)" stroke="var(--symbol-stroke, #000000)" />
|
|
2807
|
+
</g>
|
|
2808
|
+
`,
|
|
2809
|
+
metadata: {
|
|
2810
|
+
description: "Hollow fiber filter module with multiple inlet/outlet connections",
|
|
2811
|
+
tags: ["filter", "hollow-fiber", "filtration", "separation", "membrane"]
|
|
2812
|
+
}
|
|
2813
|
+
},
|
|
2814
|
+
"psr-f": {
|
|
2815
|
+
id: "psr-f",
|
|
2816
|
+
name: "PSR F",
|
|
2817
|
+
category: "instrument",
|
|
2818
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
1784
2819
|
ports: [
|
|
1785
|
-
{ id: "
|
|
1786
|
-
{ id: "
|
|
2820
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
2821
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
2822
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
2823
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
1787
2824
|
],
|
|
1788
2825
|
svgContent: `
|
|
1789
|
-
<g>
|
|
1790
|
-
<!--
|
|
1791
|
-
<
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2826
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2827
|
+
<!-- Circle background -->
|
|
2828
|
+
<ellipse
|
|
2829
|
+
cx="28.5"
|
|
2830
|
+
cy="28.5"
|
|
2831
|
+
rx="28.5"
|
|
2832
|
+
ry="28.5"
|
|
2833
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2834
|
+
stroke-width="1"
|
|
2835
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2836
|
+
/>
|
|
2837
|
+
|
|
2838
|
+
<!-- Letter F -->
|
|
2839
|
+
<text
|
|
2840
|
+
x="28.5"
|
|
2841
|
+
y="38"
|
|
2842
|
+
text-anchor="middle"
|
|
2843
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2844
|
+
font-size="34"
|
|
2845
|
+
font-weight="normal"
|
|
2846
|
+
font-style="italic"
|
|
2847
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2848
|
+
>F</text>
|
|
1800
2849
|
</g>
|
|
1801
2850
|
`,
|
|
1802
2851
|
metadata: {
|
|
1803
|
-
description: "
|
|
1804
|
-
tags: ["
|
|
2852
|
+
description: "PSR F instrument symbol - Flow indicator",
|
|
2853
|
+
tags: ["instrument", "psr", "flow", "indicator"]
|
|
1805
2854
|
}
|
|
1806
2855
|
},
|
|
1807
|
-
"
|
|
1808
|
-
id: "
|
|
1809
|
-
name: "
|
|
2856
|
+
"psr-p": {
|
|
2857
|
+
id: "psr-p",
|
|
2858
|
+
name: "PSR P",
|
|
1810
2859
|
category: "instrument",
|
|
1811
|
-
viewBox: { x: 0, y: 0, width:
|
|
2860
|
+
viewBox: { x: 0, y: 0, width: 28.5, height: 28.5 },
|
|
1812
2861
|
ports: [
|
|
1813
|
-
{ id: "
|
|
2862
|
+
{ id: "top", type: "signal", x: 14.25, y: 7.125 },
|
|
2863
|
+
{ id: "right", type: "signal", x: 21.375, y: 14.25 },
|
|
2864
|
+
{ id: "bottom", type: "signal", x: 14.25, y: 21.375 },
|
|
2865
|
+
{ id: "left", type: "signal", x: 7.125, y: 14.25 }
|
|
1814
2866
|
],
|
|
1815
2867
|
svgContent: `
|
|
1816
|
-
<g>
|
|
1817
|
-
<!--
|
|
1818
|
-
<
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
2868
|
+
<g transform="scale(0.25) translate(28.5, 28.5)">
|
|
2869
|
+
<!-- Circle background -->
|
|
2870
|
+
<ellipse
|
|
2871
|
+
cx="28.5"
|
|
2872
|
+
cy="28.5"
|
|
2873
|
+
rx="28.5"
|
|
2874
|
+
ry="28.5"
|
|
2875
|
+
stroke="var(--symbol-stroke, #000000)"
|
|
2876
|
+
stroke-width="1"
|
|
2877
|
+
fill="var(--symbol-fill, #ffffff)"
|
|
2878
|
+
/>
|
|
2879
|
+
|
|
2880
|
+
<!-- Letter P -->
|
|
2881
|
+
<text
|
|
2882
|
+
x="28.5"
|
|
2883
|
+
y="38"
|
|
2884
|
+
text-anchor="middle"
|
|
2885
|
+
font-family="'Times New Roman', Georgia, serif"
|
|
2886
|
+
font-size="34"
|
|
2887
|
+
font-weight="normal"
|
|
2888
|
+
font-style="italic"
|
|
2889
|
+
fill="var(--symbol-stroke, #000000)"
|
|
2890
|
+
>P</text>
|
|
1823
2891
|
</g>
|
|
1824
2892
|
`,
|
|
1825
2893
|
metadata: {
|
|
1826
|
-
description: "
|
|
1827
|
-
tags: ["instrument", "
|
|
2894
|
+
description: "PSR P instrument symbol - Pressure indicator",
|
|
2895
|
+
tags: ["instrument", "psr", "pressure", "indicator"]
|
|
1828
2896
|
}
|
|
1829
2897
|
}
|
|
1830
2898
|
};
|
|
2899
|
+
var customSymbols = {};
|
|
2900
|
+
function registerSymbol(symbol) {
|
|
2901
|
+
customSymbols[symbol.id] = symbol;
|
|
2902
|
+
}
|
|
2903
|
+
function registerSymbols(symbols) {
|
|
2904
|
+
if (Array.isArray(symbols)) {
|
|
2905
|
+
symbols.forEach((symbol) => registerSymbol(symbol));
|
|
2906
|
+
} else {
|
|
2907
|
+
Object.values(symbols).forEach((symbol) => registerSymbol(symbol));
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
1831
2910
|
function getSymbolDefinition(symbolId) {
|
|
1832
|
-
return mockSymbolLibrary[symbolId];
|
|
2911
|
+
return customSymbols[symbolId] ?? mockSymbolLibrary[symbolId];
|
|
1833
2912
|
}
|
|
1834
2913
|
function getAvailableSymbols() {
|
|
1835
|
-
return Object.keys(mockSymbolLibrary);
|
|
2914
|
+
return [...Object.keys(customSymbols), ...Object.keys(mockSymbolLibrary)];
|
|
1836
2915
|
}
|
|
1837
2916
|
|
|
1838
2917
|
// src/components/PIDCanvas/NodeRenderer.tsx
|
|
@@ -1904,6 +2983,24 @@ function NodeRenderer({
|
|
|
1904
2983
|
`translate(${centerX}, ${centerY}) scale(${scaleX}, ${scaleY}) translate(${-centerX}, ${-centerY})`
|
|
1905
2984
|
);
|
|
1906
2985
|
}
|
|
2986
|
+
const getStatusColor = (status) => {
|
|
2987
|
+
switch (status) {
|
|
2988
|
+
case "running":
|
|
2989
|
+
return "#22c55e";
|
|
2990
|
+
// Green
|
|
2991
|
+
case "alarm":
|
|
2992
|
+
return "#ef4444";
|
|
2993
|
+
// Red
|
|
2994
|
+
case "warning":
|
|
2995
|
+
return "#f59e0b";
|
|
2996
|
+
// Orange
|
|
2997
|
+
case "stopped":
|
|
2998
|
+
default:
|
|
2999
|
+
return "#edeeef";
|
|
3000
|
+
}
|
|
3001
|
+
};
|
|
3002
|
+
const fillColor = node.customColors?.fill ?? getStatusColor(node.status);
|
|
3003
|
+
const strokeColor = node.customColors?.stroke ?? "rgb(0, 0, 0)";
|
|
1907
3004
|
return /* @__PURE__ */ jsxs9(
|
|
1908
3005
|
"g",
|
|
1909
3006
|
{
|
|
@@ -1912,6 +3009,11 @@ function NodeRenderer({
|
|
|
1912
3009
|
"data-selected": isSelected,
|
|
1913
3010
|
"data-dragging": isDragging,
|
|
1914
3011
|
transform: transforms.join(" "),
|
|
3012
|
+
style: {
|
|
3013
|
+
"--symbol-fill": fillColor,
|
|
3014
|
+
"--symbol-stroke": strokeColor,
|
|
3015
|
+
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
3016
|
+
},
|
|
1915
3017
|
onClick: (e) => {
|
|
1916
3018
|
e.stopPropagation();
|
|
1917
3019
|
onNodeClick?.(node.id, e);
|
|
@@ -1931,9 +3033,6 @@ function NodeRenderer({
|
|
|
1931
3033
|
onNodeDragStart?.(node.id, e);
|
|
1932
3034
|
}
|
|
1933
3035
|
},
|
|
1934
|
-
style: {
|
|
1935
|
-
cursor: enableDrag ? isDragging ? "grabbing" : "grab" : onNodeClick ? "pointer" : "default"
|
|
1936
|
-
},
|
|
1937
3036
|
children: [
|
|
1938
3037
|
isSelected && /* @__PURE__ */ jsx13(
|
|
1939
3038
|
"rect",
|
|
@@ -1986,6 +3085,9 @@ function PipeRenderer({
|
|
|
1986
3085
|
onPipeClick,
|
|
1987
3086
|
enableWaypointEditing = false,
|
|
1988
3087
|
onWaypointDragStart,
|
|
3088
|
+
onWaypointClick,
|
|
3089
|
+
selectedWaypointPipeId,
|
|
3090
|
+
selectedWaypointIndex,
|
|
1989
3091
|
editingPipeId,
|
|
1990
3092
|
draggingWaypointIndex,
|
|
1991
3093
|
waypointDragOffset,
|
|
@@ -2006,7 +3108,7 @@ function PipeRenderer({
|
|
|
2006
3108
|
});
|
|
2007
3109
|
const pointsString = displayPoints.map((point) => `${point.x},${point.y}`).join(" ");
|
|
2008
3110
|
const pipeStyle = pipe.style || {};
|
|
2009
|
-
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#
|
|
3111
|
+
const stroke = isSelected ? "#3b82f6" : pipeStyle.stroke || "#94a1b8";
|
|
2010
3112
|
const strokeWidth = isSelected ? (pipeStyle.strokeWidth || 3) + 2 : pipeStyle.strokeWidth || 3;
|
|
2011
3113
|
const strokeDasharray = pipeStyle.strokeDasharray;
|
|
2012
3114
|
const opacity = pipeStyle.opacity !== void 0 ? pipeStyle.opacity : 1;
|
|
@@ -2055,10 +3157,11 @@ function PipeRenderer({
|
|
|
2055
3157
|
] }),
|
|
2056
3158
|
displayPoints.map((point, idx) => {
|
|
2057
3159
|
const isEndpoint = idx === 0 || idx === displayPoints.length - 1;
|
|
3160
|
+
const isSelectedWaypoint = selectedWaypointPipeId === pipe.id && selectedWaypointIndex === idx;
|
|
2058
3161
|
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;
|
|
3162
|
+
const waypointSize = isSelectedWaypoint ? 8 : isDragging ? 8 : showEditingControls ? 6 : isSelected ? 3 : 2;
|
|
3163
|
+
const waypointOpacity = isSelectedWaypoint ? 1 : isDragging ? 1 : showEditingControls ? 0.9 : isSelected ? 0.8 : 0.5;
|
|
3164
|
+
const waypointColor = isSelectedWaypoint ? "#3b82f6" : isEndpoint && showEditingControls ? "#f59e0b" : isDragging ? "#10b981" : stroke;
|
|
2062
3165
|
return /* @__PURE__ */ jsx14(
|
|
2063
3166
|
"circle",
|
|
2064
3167
|
{
|
|
@@ -2074,6 +3177,12 @@ function PipeRenderer({
|
|
|
2074
3177
|
cursor: showEditingControls ? isDragging ? "grabbing" : "grab" : "default"
|
|
2075
3178
|
},
|
|
2076
3179
|
pointerEvents: showEditingControls ? "all" : "none",
|
|
3180
|
+
onClick: (e) => {
|
|
3181
|
+
if (showEditingControls) {
|
|
3182
|
+
e.stopPropagation();
|
|
3183
|
+
onWaypointClick?.(pipe.id, idx);
|
|
3184
|
+
}
|
|
3185
|
+
},
|
|
2077
3186
|
onMouseDown: (e) => {
|
|
2078
3187
|
if (showEditingControls) {
|
|
2079
3188
|
e.stopPropagation();
|
|
@@ -2150,7 +3259,13 @@ function PipeRenderer({
|
|
|
2150
3259
|
|
|
2151
3260
|
// src/components/PIDCanvas/DataOverlay.tsx
|
|
2152
3261
|
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2153
|
-
function DataOverlay({
|
|
3262
|
+
function DataOverlay({
|
|
3263
|
+
nodeId,
|
|
3264
|
+
x,
|
|
3265
|
+
y,
|
|
3266
|
+
telemetry,
|
|
3267
|
+
scale = 1
|
|
3268
|
+
}) {
|
|
2154
3269
|
const { value, display, history } = telemetry;
|
|
2155
3270
|
const showValue = display?.showValue ?? true;
|
|
2156
3271
|
const showStatus = display?.showStatus ?? true;
|
|
@@ -2190,9 +3305,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2190
3305
|
const displayText = value.unit ? `${formattedValue} ${value.unit}` : formattedValue;
|
|
2191
3306
|
const sparklinePath = (() => {
|
|
2192
3307
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
2193
|
-
const width = 70;
|
|
2194
|
-
const height = 20;
|
|
2195
|
-
const padding = 5;
|
|
3308
|
+
const width = 70 * scale;
|
|
3309
|
+
const height = 20 * scale;
|
|
3310
|
+
const padding = 5 * scale;
|
|
2196
3311
|
const effectiveWidth = width - padding * 2;
|
|
2197
3312
|
const effectiveHeight = height - padding * 2;
|
|
2198
3313
|
const min = Math.min(...history);
|
|
@@ -2206,21 +3321,22 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2206
3321
|
return `M ${points.join(" L ")}`;
|
|
2207
3322
|
})();
|
|
2208
3323
|
const hasSparkline = showSparkline && sparklinePath;
|
|
2209
|
-
const overlayHeight = label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22;
|
|
3324
|
+
const overlayHeight = (label ? hasSparkline ? 55 : 30 : hasSparkline ? 47 : 22) * scale;
|
|
3325
|
+
const overlayWidth = 80 * scale;
|
|
2210
3326
|
const displayX = x + offsetX;
|
|
2211
3327
|
const displayY = y + offsetY;
|
|
2212
3328
|
return /* @__PURE__ */ jsxs11("g", { "data-overlay-node": nodeId, "data-status": value.status, children: [
|
|
2213
3329
|
/* @__PURE__ */ jsx15(
|
|
2214
3330
|
"rect",
|
|
2215
3331
|
{
|
|
2216
|
-
x: displayX -
|
|
2217
|
-
y: displayY - 25,
|
|
2218
|
-
width:
|
|
3332
|
+
x: displayX - overlayWidth / 2,
|
|
3333
|
+
y: displayY - 25 * scale,
|
|
3334
|
+
width: overlayWidth,
|
|
2219
3335
|
height: overlayHeight,
|
|
2220
|
-
rx:
|
|
3336
|
+
rx: 4 * scale,
|
|
2221
3337
|
fill: colors.bg,
|
|
2222
3338
|
stroke: colors.border,
|
|
2223
|
-
strokeWidth:
|
|
3339
|
+
strokeWidth: 1 * scale,
|
|
2224
3340
|
opacity: "0.95",
|
|
2225
3341
|
filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))"
|
|
2226
3342
|
}
|
|
@@ -2229,9 +3345,9 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2229
3345
|
"text",
|
|
2230
3346
|
{
|
|
2231
3347
|
x: displayX,
|
|
2232
|
-
y: displayY - 15,
|
|
3348
|
+
y: displayY - 15 * scale,
|
|
2233
3349
|
textAnchor: "middle",
|
|
2234
|
-
fontSize:
|
|
3350
|
+
fontSize: 8 * scale,
|
|
2235
3351
|
fontWeight: "600",
|
|
2236
3352
|
fill: finalTextColor,
|
|
2237
3353
|
opacity: "0.9",
|
|
@@ -2242,31 +3358,41 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2242
3358
|
"text",
|
|
2243
3359
|
{
|
|
2244
3360
|
x: displayX,
|
|
2245
|
-
y: label ? displayY - 3 : displayY - 9,
|
|
3361
|
+
y: label ? displayY - 3 * scale : displayY - 9 * scale,
|
|
2246
3362
|
textAnchor: "middle",
|
|
2247
|
-
fontSize:
|
|
3363
|
+
fontSize: 11 * scale,
|
|
2248
3364
|
fontWeight: "700",
|
|
2249
3365
|
fill: finalTextColor,
|
|
2250
3366
|
letterSpacing: "0.02em",
|
|
2251
3367
|
children: displayText
|
|
2252
3368
|
}
|
|
2253
3369
|
),
|
|
2254
|
-
showStatus && value.status !== "normal" && /* @__PURE__ */ jsx15(
|
|
2255
|
-
"
|
|
3370
|
+
showStatus && value.status !== "normal" && /* @__PURE__ */ jsx15(
|
|
3371
|
+
"circle",
|
|
2256
3372
|
{
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
3373
|
+
cx: displayX + 35 * scale,
|
|
3374
|
+
cy: displayY - 18 * scale,
|
|
3375
|
+
r: 3 * scale,
|
|
3376
|
+
fill: finalTextColor,
|
|
3377
|
+
opacity: "0.9",
|
|
3378
|
+
children: /* @__PURE__ */ jsx15(
|
|
3379
|
+
"animate",
|
|
3380
|
+
{
|
|
3381
|
+
attributeName: "opacity",
|
|
3382
|
+
values: "0.9;0.3;0.9",
|
|
3383
|
+
dur: "1.5s",
|
|
3384
|
+
repeatCount: "indefinite"
|
|
3385
|
+
}
|
|
3386
|
+
)
|
|
2261
3387
|
}
|
|
2262
|
-
)
|
|
3388
|
+
),
|
|
2263
3389
|
value.quality !== void 0 && value.quality < 100 && /* @__PURE__ */ jsxs11(
|
|
2264
3390
|
"text",
|
|
2265
3391
|
{
|
|
2266
3392
|
x: displayX,
|
|
2267
|
-
y: displayY + 5,
|
|
3393
|
+
y: displayY + 5 * scale,
|
|
2268
3394
|
textAnchor: "middle",
|
|
2269
|
-
fontSize:
|
|
3395
|
+
fontSize: 7 * scale,
|
|
2270
3396
|
fontWeight: "500",
|
|
2271
3397
|
fill: finalTextColor,
|
|
2272
3398
|
opacity: "0.7",
|
|
@@ -2277,13 +3403,13 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2277
3403
|
]
|
|
2278
3404
|
}
|
|
2279
3405
|
),
|
|
2280
|
-
hasSparkline && /* @__PURE__ */ jsx15("g", { transform: `translate(${displayX - 35}, ${displayY + (label ? 5 : 0)})`, children: /* @__PURE__ */ jsx15(
|
|
3406
|
+
hasSparkline && /* @__PURE__ */ jsx15("g", { transform: `translate(${displayX - 35 * scale}, ${displayY + (label ? 5 : 0) * scale})`, children: /* @__PURE__ */ jsx15(
|
|
2281
3407
|
"path",
|
|
2282
3408
|
{
|
|
2283
3409
|
d: sparklinePath,
|
|
2284
3410
|
fill: "none",
|
|
2285
3411
|
stroke: sparklineColor || finalTextColor,
|
|
2286
|
-
strokeWidth:
|
|
3412
|
+
strokeWidth: 1.5 * scale,
|
|
2287
3413
|
strokeLinecap: "round",
|
|
2288
3414
|
strokeLinejoin: "round",
|
|
2289
3415
|
opacity: "0.9"
|
|
@@ -2292,8 +3418,145 @@ function DataOverlay({ nodeId, x, y, telemetry }) {
|
|
|
2292
3418
|
] });
|
|
2293
3419
|
}
|
|
2294
3420
|
|
|
3421
|
+
// src/components/PIDCanvas/PositionPanel.tsx
|
|
3422
|
+
import { useState as useState7, useEffect as useEffect4 } from "react";
|
|
3423
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3424
|
+
function PositionPanel({
|
|
3425
|
+
selectedNode,
|
|
3426
|
+
selectedWaypoint,
|
|
3427
|
+
onPositionChange,
|
|
3428
|
+
onWaypointPositionChange,
|
|
3429
|
+
position = "top-right"
|
|
3430
|
+
}) {
|
|
3431
|
+
const [x, setX] = useState7("");
|
|
3432
|
+
const [y, setY] = useState7("");
|
|
3433
|
+
useEffect4(() => {
|
|
3434
|
+
if (selectedNode) {
|
|
3435
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3436
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3437
|
+
} else if (selectedWaypoint) {
|
|
3438
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3439
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3440
|
+
}
|
|
3441
|
+
}, [selectedNode, selectedWaypoint]);
|
|
3442
|
+
if (!selectedNode && !selectedWaypoint) {
|
|
3443
|
+
return null;
|
|
3444
|
+
}
|
|
3445
|
+
const handleXChange = (value) => {
|
|
3446
|
+
setX(value);
|
|
3447
|
+
const numValue = parseFloat(value);
|
|
3448
|
+
if (!isNaN(numValue)) {
|
|
3449
|
+
if (selectedNode && onPositionChange) {
|
|
3450
|
+
onPositionChange(selectedNode.id, numValue, selectedNode.transform.y);
|
|
3451
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3452
|
+
onWaypointPositionChange(
|
|
3453
|
+
selectedWaypoint.pipeId,
|
|
3454
|
+
selectedWaypoint.pointIndex,
|
|
3455
|
+
numValue,
|
|
3456
|
+
selectedWaypoint.position.y
|
|
3457
|
+
);
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
};
|
|
3461
|
+
const handleYChange = (value) => {
|
|
3462
|
+
setY(value);
|
|
3463
|
+
const numValue = parseFloat(value);
|
|
3464
|
+
if (!isNaN(numValue)) {
|
|
3465
|
+
if (selectedNode && onPositionChange) {
|
|
3466
|
+
onPositionChange(selectedNode.id, selectedNode.transform.x, numValue);
|
|
3467
|
+
} else if (selectedWaypoint && onWaypointPositionChange) {
|
|
3468
|
+
onWaypointPositionChange(
|
|
3469
|
+
selectedWaypoint.pipeId,
|
|
3470
|
+
selectedWaypoint.pointIndex,
|
|
3471
|
+
selectedWaypoint.position.x,
|
|
3472
|
+
numValue
|
|
3473
|
+
);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3477
|
+
const handleBlur = () => {
|
|
3478
|
+
if (selectedNode) {
|
|
3479
|
+
setX(selectedNode.transform.x.toFixed(2));
|
|
3480
|
+
setY(selectedNode.transform.y.toFixed(2));
|
|
3481
|
+
} else if (selectedWaypoint) {
|
|
3482
|
+
setX(selectedWaypoint.position.x.toFixed(2));
|
|
3483
|
+
setY(selectedWaypoint.position.y.toFixed(2));
|
|
3484
|
+
}
|
|
3485
|
+
};
|
|
3486
|
+
const positionStyles = {
|
|
3487
|
+
"top-left": { top: 10, left: 10 },
|
|
3488
|
+
"top-right": { top: 10, right: 10 },
|
|
3489
|
+
"bottom-left": { bottom: 10, left: 10 },
|
|
3490
|
+
"bottom-right": { bottom: 10, right: 10 }
|
|
3491
|
+
};
|
|
3492
|
+
return /* @__PURE__ */ jsxs12(
|
|
3493
|
+
"div",
|
|
3494
|
+
{
|
|
3495
|
+
style: {
|
|
3496
|
+
position: "absolute",
|
|
3497
|
+
...positionStyles[position],
|
|
3498
|
+
backgroundColor: "white",
|
|
3499
|
+
border: "1px solid #ccc",
|
|
3500
|
+
borderRadius: "4px",
|
|
3501
|
+
padding: "12px",
|
|
3502
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
3503
|
+
zIndex: 1e3,
|
|
3504
|
+
minWidth: "180px",
|
|
3505
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
3506
|
+
fontSize: "13px"
|
|
3507
|
+
},
|
|
3508
|
+
children: [
|
|
3509
|
+
/* @__PURE__ */ jsx16("div", { style: { marginBottom: "8px", fontWeight: 600, color: "#333" }, children: "Position" }),
|
|
3510
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
3511
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3512
|
+
/* @__PURE__ */ jsx16("label", { style: { width: "16px", color: "#666" }, children: "X:" }),
|
|
3513
|
+
/* @__PURE__ */ jsx16(
|
|
3514
|
+
"input",
|
|
3515
|
+
{
|
|
3516
|
+
type: "number",
|
|
3517
|
+
value: x,
|
|
3518
|
+
onChange: (e) => handleXChange(e.target.value),
|
|
3519
|
+
onBlur: handleBlur,
|
|
3520
|
+
style: {
|
|
3521
|
+
flex: 1,
|
|
3522
|
+
padding: "4px 8px",
|
|
3523
|
+
border: "1px solid #ddd",
|
|
3524
|
+
borderRadius: "3px",
|
|
3525
|
+
fontSize: "13px"
|
|
3526
|
+
},
|
|
3527
|
+
step: "1"
|
|
3528
|
+
}
|
|
3529
|
+
)
|
|
3530
|
+
] }),
|
|
3531
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3532
|
+
/* @__PURE__ */ jsx16("label", { style: { width: "16px", color: "#666" }, children: "Y:" }),
|
|
3533
|
+
/* @__PURE__ */ jsx16(
|
|
3534
|
+
"input",
|
|
3535
|
+
{
|
|
3536
|
+
type: "number",
|
|
3537
|
+
value: y,
|
|
3538
|
+
onChange: (e) => handleYChange(e.target.value),
|
|
3539
|
+
onBlur: handleBlur,
|
|
3540
|
+
style: {
|
|
3541
|
+
flex: 1,
|
|
3542
|
+
padding: "4px 8px",
|
|
3543
|
+
border: "1px solid #ddd",
|
|
3544
|
+
borderRadius: "3px",
|
|
3545
|
+
fontSize: "13px"
|
|
3546
|
+
},
|
|
3547
|
+
step: "1"
|
|
3548
|
+
}
|
|
3549
|
+
)
|
|
3550
|
+
] })
|
|
3551
|
+
] }),
|
|
3552
|
+
/* @__PURE__ */ jsx16("div", { style: { marginTop: "8px", fontSize: "11px", color: "#888" }, children: "Use arrow keys to nudge (\xB11px)" })
|
|
3553
|
+
]
|
|
3554
|
+
}
|
|
3555
|
+
);
|
|
3556
|
+
}
|
|
3557
|
+
|
|
2295
3558
|
// src/diagram/hooks/useViewBox.ts
|
|
2296
|
-
import { useState as
|
|
3559
|
+
import { useState as useState8, useCallback as useCallback3, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
2297
3560
|
function useViewBox(options) {
|
|
2298
3561
|
const {
|
|
2299
3562
|
initialViewBox,
|
|
@@ -2304,7 +3567,7 @@ function useViewBox(options) {
|
|
|
2304
3567
|
zoomSensitivity = 1e-3,
|
|
2305
3568
|
allowLeftClickPan = true
|
|
2306
3569
|
} = options;
|
|
2307
|
-
const [viewBox, setViewBox] =
|
|
3570
|
+
const [viewBox, setViewBox] = useState8(initialViewBox);
|
|
2308
3571
|
const svgRef = useRef2(null);
|
|
2309
3572
|
const isPanningRef = useRef2(false);
|
|
2310
3573
|
const lastMousePosRef = useRef2({ x: 0, y: 0 });
|
|
@@ -2375,7 +3638,7 @@ function useViewBox(options) {
|
|
|
2375
3638
|
height: newHeight
|
|
2376
3639
|
});
|
|
2377
3640
|
}, [initialViewBox]);
|
|
2378
|
-
|
|
3641
|
+
useEffect5(() => {
|
|
2379
3642
|
if (!enableZoom || !svgRef.current) return;
|
|
2380
3643
|
const svg = svgRef.current;
|
|
2381
3644
|
const handleWheel = (e) => {
|
|
@@ -2408,7 +3671,7 @@ function useViewBox(options) {
|
|
|
2408
3671
|
svg.addEventListener("wheel", handleWheel, { passive: false });
|
|
2409
3672
|
return () => svg.removeEventListener("wheel", handleWheel);
|
|
2410
3673
|
}, [enableZoom, zoomSensitivity, minZoom, initialViewBox]);
|
|
2411
|
-
|
|
3674
|
+
useEffect5(() => {
|
|
2412
3675
|
if (!enablePan || !svgRef.current) return;
|
|
2413
3676
|
const svg = svgRef.current;
|
|
2414
3677
|
const handleMouseDown = (e) => {
|
|
@@ -2484,7 +3747,7 @@ function useViewBox(options) {
|
|
|
2484
3747
|
window.removeEventListener("keyup", handleKeyUp);
|
|
2485
3748
|
};
|
|
2486
3749
|
}, [enablePan, allowLeftClickPan]);
|
|
2487
|
-
|
|
3750
|
+
useEffect5(() => {
|
|
2488
3751
|
if (!svgRef.current) return;
|
|
2489
3752
|
if (!enablePan && !enableZoom) return;
|
|
2490
3753
|
const svg = svgRef.current;
|
|
@@ -2614,14 +3877,14 @@ function useViewBox(options) {
|
|
|
2614
3877
|
}
|
|
2615
3878
|
|
|
2616
3879
|
// src/diagram/hooks/useSelection.ts
|
|
2617
|
-
import { useState as
|
|
3880
|
+
import { useState as useState9, useCallback as useCallback4 } from "react";
|
|
2618
3881
|
function useSelection(options = {}) {
|
|
2619
3882
|
const {
|
|
2620
3883
|
multiSelect = true,
|
|
2621
3884
|
initialSelection = { selectedNodeIds: /* @__PURE__ */ new Set(), selectedPipeIds: /* @__PURE__ */ new Set() },
|
|
2622
3885
|
onSelectionChange
|
|
2623
3886
|
} = options;
|
|
2624
|
-
const [selection, setSelection] =
|
|
3887
|
+
const [selection, setSelection] = useState9(initialSelection);
|
|
2625
3888
|
const notifyChange = useCallback4(
|
|
2626
3889
|
(newSelection) => {
|
|
2627
3890
|
if (onSelectionChange) {
|
|
@@ -2719,14 +3982,14 @@ function useSelection(options = {}) {
|
|
|
2719
3982
|
}
|
|
2720
3983
|
|
|
2721
3984
|
// src/diagram/hooks/useTelemetry.ts
|
|
2722
|
-
import { useState as
|
|
3985
|
+
import { useState as useState10, useCallback as useCallback5, useEffect as useEffect6, useRef as useRef3 } from "react";
|
|
2723
3986
|
function useTelemetry(options = {}) {
|
|
2724
3987
|
const {
|
|
2725
3988
|
initialBindings = [],
|
|
2726
3989
|
onTelemetryChange,
|
|
2727
3990
|
refreshInterval = 0
|
|
2728
3991
|
} = options;
|
|
2729
|
-
const [telemetry, setTelemetry] =
|
|
3992
|
+
const [telemetry, setTelemetry] = useState10(() => {
|
|
2730
3993
|
const map = /* @__PURE__ */ new Map();
|
|
2731
3994
|
initialBindings.forEach((binding) => {
|
|
2732
3995
|
map.set(binding.nodeId, binding);
|
|
@@ -2847,7 +4110,7 @@ function useTelemetry(options = {}) {
|
|
|
2847
4110
|
},
|
|
2848
4111
|
[notifyChange]
|
|
2849
4112
|
);
|
|
2850
|
-
|
|
4113
|
+
useEffect6(() => {
|
|
2851
4114
|
if (refreshInterval <= 0) return;
|
|
2852
4115
|
const intervalId = setInterval(() => {
|
|
2853
4116
|
notifyChange(telemetryRef.current);
|
|
@@ -2864,8 +4127,50 @@ function useTelemetry(options = {}) {
|
|
|
2864
4127
|
};
|
|
2865
4128
|
}
|
|
2866
4129
|
|
|
4130
|
+
// src/diagram/hooks/useTelemetryStatus.ts
|
|
4131
|
+
import { useEffect as useEffect7 } from "react";
|
|
4132
|
+
function useTelemetryStatus(telemetry, diagram, setDiagram, options = {}) {
|
|
4133
|
+
const { enabled = true, mapStatus } = options;
|
|
4134
|
+
useEffect7(() => {
|
|
4135
|
+
if (!enabled) return;
|
|
4136
|
+
const defaultMapStatus = (telemetryStatus) => {
|
|
4137
|
+
switch (telemetryStatus) {
|
|
4138
|
+
case "normal":
|
|
4139
|
+
return "running";
|
|
4140
|
+
case "warning":
|
|
4141
|
+
return "warning";
|
|
4142
|
+
case "alarm":
|
|
4143
|
+
case "fault":
|
|
4144
|
+
return "alarm";
|
|
4145
|
+
case "off":
|
|
4146
|
+
return "stopped";
|
|
4147
|
+
default:
|
|
4148
|
+
return "stopped";
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
const statusMapper = mapStatus || defaultMapStatus;
|
|
4152
|
+
let needsUpdate = false;
|
|
4153
|
+
const updatedNodes = diagram.nodes.map((node) => {
|
|
4154
|
+
const binding = telemetry.get(node.id);
|
|
4155
|
+
if (!binding) return node;
|
|
4156
|
+
const newStatus = statusMapper(binding.value.status);
|
|
4157
|
+
if (node.status !== newStatus) {
|
|
4158
|
+
needsUpdate = true;
|
|
4159
|
+
return { ...node, status: newStatus };
|
|
4160
|
+
}
|
|
4161
|
+
return node;
|
|
4162
|
+
});
|
|
4163
|
+
if (needsUpdate) {
|
|
4164
|
+
setDiagram({
|
|
4165
|
+
...diagram,
|
|
4166
|
+
nodes: updatedNodes
|
|
4167
|
+
});
|
|
4168
|
+
}
|
|
4169
|
+
}, [telemetry, diagram, setDiagram, enabled, mapStatus]);
|
|
4170
|
+
}
|
|
4171
|
+
|
|
2867
4172
|
// src/diagram/hooks/useDrag.ts
|
|
2868
|
-
import { useState as
|
|
4173
|
+
import { useState as useState11, useCallback as useCallback6, useRef as useRef4, useEffect as useEffect8 } from "react";
|
|
2869
4174
|
function useDrag(options = {}) {
|
|
2870
4175
|
const {
|
|
2871
4176
|
onDragStart,
|
|
@@ -2875,13 +4180,13 @@ function useDrag(options = {}) {
|
|
|
2875
4180
|
dragThreshold = 3,
|
|
2876
4181
|
screenToWorld = (x, y) => ({ x, y })
|
|
2877
4182
|
} = options;
|
|
2878
|
-
const [dragState, setDragState] =
|
|
4183
|
+
const [dragState, setDragState] = useState11({
|
|
2879
4184
|
isDragging: false,
|
|
2880
4185
|
startPosition: null,
|
|
2881
4186
|
offset: { x: 0, y: 0 },
|
|
2882
4187
|
draggedId: null
|
|
2883
4188
|
});
|
|
2884
|
-
const [isListening, setIsListening] =
|
|
4189
|
+
const [isListening, setIsListening] = useState11(false);
|
|
2885
4190
|
const dragStartRef = useRef4(null);
|
|
2886
4191
|
const hasMovedRef = useRef4(false);
|
|
2887
4192
|
const applySnap = useCallback6(
|
|
@@ -3050,7 +4355,7 @@ function useDrag(options = {}) {
|
|
|
3050
4355
|
},
|
|
3051
4356
|
[screenToWorld, applySnap, onDragEnd]
|
|
3052
4357
|
);
|
|
3053
|
-
|
|
4358
|
+
useEffect8(() => {
|
|
3054
4359
|
if (!isListening) return;
|
|
3055
4360
|
document.addEventListener("mousemove", handleMouseMove);
|
|
3056
4361
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -3119,7 +4424,7 @@ function useDrag(options = {}) {
|
|
|
3119
4424
|
}
|
|
3120
4425
|
|
|
3121
4426
|
// src/diagram/hooks/useKeyboardShortcuts.ts
|
|
3122
|
-
import { useEffect as
|
|
4427
|
+
import { useEffect as useEffect9 } from "react";
|
|
3123
4428
|
function useKeyboardShortcuts(options) {
|
|
3124
4429
|
const {
|
|
3125
4430
|
onDelete,
|
|
@@ -3130,7 +4435,7 @@ function useKeyboardShortcuts(options) {
|
|
|
3130
4435
|
onSelectAll,
|
|
3131
4436
|
enabled = true
|
|
3132
4437
|
} = options;
|
|
3133
|
-
|
|
4438
|
+
useEffect9(() => {
|
|
3134
4439
|
if (!enabled) return;
|
|
3135
4440
|
const handleKeyDown = (event) => {
|
|
3136
4441
|
const target = event.target;
|
|
@@ -3239,7 +4544,7 @@ function nodeHasPort(node, portId) {
|
|
|
3239
4544
|
}
|
|
3240
4545
|
|
|
3241
4546
|
// src/components/PIDCanvas/PIDCanvas.tsx
|
|
3242
|
-
import { Fragment as Fragment5, jsx as
|
|
4547
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3243
4548
|
function PIDCanvas({
|
|
3244
4549
|
diagram,
|
|
3245
4550
|
className = "",
|
|
@@ -3266,16 +4571,30 @@ function PIDCanvas({
|
|
|
3266
4571
|
telemetry,
|
|
3267
4572
|
...props
|
|
3268
4573
|
}) {
|
|
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
|
-
|
|
4574
|
+
const [localDiagram, setLocalDiagram] = useState12(diagram);
|
|
4575
|
+
const [dragOverPosition, setDragOverPosition] = useState12(null);
|
|
4576
|
+
const [isConnecting, setIsConnecting] = useState12(false);
|
|
4577
|
+
const [connectionSource, setConnectionSource] = useState12(null);
|
|
4578
|
+
const [connectionSourcePort, setConnectionSourcePort] = useState12(null);
|
|
4579
|
+
const [connectionCursor, setConnectionCursor] = useState12(null);
|
|
4580
|
+
const [hoveredNode, setHoveredNode] = useState12(null);
|
|
4581
|
+
const [hoveredPort, setHoveredPort] = useState12(null);
|
|
4582
|
+
const [selectedWaypoint, setSelectedWaypoint] = useState12(null);
|
|
4583
|
+
const historyStack = useRef5([]);
|
|
4584
|
+
const redoStack = useRef5([]);
|
|
4585
|
+
const isUndoRedoAction = useRef5(false);
|
|
4586
|
+
const isInternalChange = useRef5(false);
|
|
4587
|
+
const lastInternalDiagram = useRef5(null);
|
|
4588
|
+
useEffect10(() => {
|
|
4589
|
+
const isExternal = !isInternalChange.current && diagram !== lastInternalDiagram.current;
|
|
4590
|
+
if (isExternal) {
|
|
4591
|
+
setLocalDiagram(diagram);
|
|
4592
|
+
if (!isUndoRedoAction.current) {
|
|
4593
|
+
historyStack.current = [];
|
|
4594
|
+
redoStack.current = [];
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
isInternalChange.current = false;
|
|
3279
4598
|
}, [diagram]);
|
|
3280
4599
|
const {
|
|
3281
4600
|
viewBox: controlledViewBox,
|
|
@@ -3311,7 +4630,7 @@ function PIDCanvas({
|
|
|
3311
4630
|
});
|
|
3312
4631
|
return { minX, minY, maxX, maxY };
|
|
3313
4632
|
}, [localDiagram.nodes]);
|
|
3314
|
-
|
|
4633
|
+
useEffect10(() => {
|
|
3315
4634
|
if (onMounted) {
|
|
3316
4635
|
const controls = {
|
|
3317
4636
|
fitToContent: (padding = 50) => {
|
|
@@ -3352,6 +4671,186 @@ function PIDCanvas({
|
|
|
3352
4671
|
});
|
|
3353
4672
|
const dragEnabled = features.dragNodes ?? false;
|
|
3354
4673
|
const selectionEnabled = features.selection ?? false;
|
|
4674
|
+
const containerRef = useRef5(null);
|
|
4675
|
+
const pushToHistory = useCallback7((currentDiagram) => {
|
|
4676
|
+
if (isUndoRedoAction.current) return;
|
|
4677
|
+
const snapshot = JSON.parse(JSON.stringify(currentDiagram));
|
|
4678
|
+
historyStack.current.push(snapshot);
|
|
4679
|
+
if (historyStack.current.length > 15) {
|
|
4680
|
+
historyStack.current.shift();
|
|
4681
|
+
}
|
|
4682
|
+
redoStack.current = [];
|
|
4683
|
+
}, []);
|
|
4684
|
+
const undo = useCallback7(() => {
|
|
4685
|
+
if (historyStack.current.length === 0) return;
|
|
4686
|
+
isUndoRedoAction.current = true;
|
|
4687
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4688
|
+
redoStack.current.push(currentSnapshot);
|
|
4689
|
+
const previousState = historyStack.current.pop();
|
|
4690
|
+
isInternalChange.current = true;
|
|
4691
|
+
lastInternalDiagram.current = previousState;
|
|
4692
|
+
setLocalDiagram(previousState);
|
|
4693
|
+
onDiagramChange?.(previousState);
|
|
4694
|
+
setTimeout(() => {
|
|
4695
|
+
isUndoRedoAction.current = false;
|
|
4696
|
+
}, 0);
|
|
4697
|
+
}, [localDiagram, onDiagramChange]);
|
|
4698
|
+
const redo = useCallback7(() => {
|
|
4699
|
+
if (redoStack.current.length === 0) return;
|
|
4700
|
+
isUndoRedoAction.current = true;
|
|
4701
|
+
const currentSnapshot = JSON.parse(JSON.stringify(localDiagram));
|
|
4702
|
+
historyStack.current.push(currentSnapshot);
|
|
4703
|
+
const nextState = redoStack.current.pop();
|
|
4704
|
+
isInternalChange.current = true;
|
|
4705
|
+
lastInternalDiagram.current = nextState;
|
|
4706
|
+
setLocalDiagram(nextState);
|
|
4707
|
+
onDiagramChange?.(nextState);
|
|
4708
|
+
setTimeout(() => {
|
|
4709
|
+
isUndoRedoAction.current = false;
|
|
4710
|
+
}, 0);
|
|
4711
|
+
}, [localDiagram, onDiagramChange]);
|
|
4712
|
+
useEffect10(() => {
|
|
4713
|
+
const handleKeyDown = (e) => {
|
|
4714
|
+
const isCtrlOrCmd = e.ctrlKey || e.metaKey;
|
|
4715
|
+
if (isCtrlOrCmd && e.key === "z" && !e.shiftKey) {
|
|
4716
|
+
e.preventDefault();
|
|
4717
|
+
undo();
|
|
4718
|
+
} else if (isCtrlOrCmd && e.key === "z" && e.shiftKey) {
|
|
4719
|
+
e.preventDefault();
|
|
4720
|
+
redo();
|
|
4721
|
+
} else if (isCtrlOrCmd && e.key === "y") {
|
|
4722
|
+
e.preventDefault();
|
|
4723
|
+
redo();
|
|
4724
|
+
}
|
|
4725
|
+
};
|
|
4726
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4727
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4728
|
+
}, [undo, redo]);
|
|
4729
|
+
useEffect10(() => {
|
|
4730
|
+
if (!features.dragNodes) return;
|
|
4731
|
+
const handleKeyDown = (e) => {
|
|
4732
|
+
if (selection.selectedNodeIds.size === 0 && !selectedWaypoint) return;
|
|
4733
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
4734
|
+
return;
|
|
4735
|
+
}
|
|
4736
|
+
const nudgeAmount = e.shiftKey ? 10 : 1;
|
|
4737
|
+
let dx = 0;
|
|
4738
|
+
let dy = 0;
|
|
4739
|
+
switch (e.key) {
|
|
4740
|
+
case "ArrowLeft":
|
|
4741
|
+
dx = -nudgeAmount;
|
|
4742
|
+
e.preventDefault();
|
|
4743
|
+
break;
|
|
4744
|
+
case "ArrowRight":
|
|
4745
|
+
dx = nudgeAmount;
|
|
4746
|
+
e.preventDefault();
|
|
4747
|
+
break;
|
|
4748
|
+
case "ArrowUp":
|
|
4749
|
+
dy = -nudgeAmount;
|
|
4750
|
+
e.preventDefault();
|
|
4751
|
+
break;
|
|
4752
|
+
case "ArrowDown":
|
|
4753
|
+
dy = nudgeAmount;
|
|
4754
|
+
e.preventDefault();
|
|
4755
|
+
break;
|
|
4756
|
+
default:
|
|
4757
|
+
return;
|
|
4758
|
+
}
|
|
4759
|
+
if (selectedWaypoint) {
|
|
4760
|
+
pushToHistory(localDiagram);
|
|
4761
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4762
|
+
if (pipe.id === selectedWaypoint.pipeId) {
|
|
4763
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4764
|
+
(point, idx) => idx === selectedWaypoint.pointIndex ? { x: point.x + dx, y: point.y + dy } : point
|
|
4765
|
+
);
|
|
4766
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4767
|
+
}
|
|
4768
|
+
return pipe;
|
|
4769
|
+
});
|
|
4770
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4771
|
+
isInternalChange.current = true;
|
|
4772
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4773
|
+
setLocalDiagram(updatedDiagram);
|
|
4774
|
+
onDiagramChange?.(updatedDiagram);
|
|
4775
|
+
return;
|
|
4776
|
+
}
|
|
4777
|
+
if (selectionEnabled && selection.selectedNodeIds.size > 0) {
|
|
4778
|
+
pushToHistory(localDiagram);
|
|
4779
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4780
|
+
(node) => selection.selectedNodeIds.has(node.id) ? {
|
|
4781
|
+
...node,
|
|
4782
|
+
transform: {
|
|
4783
|
+
...node.transform,
|
|
4784
|
+
x: node.transform.x + dx,
|
|
4785
|
+
y: node.transform.y + dy
|
|
4786
|
+
}
|
|
4787
|
+
} : node
|
|
4788
|
+
);
|
|
4789
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4790
|
+
isInternalChange.current = true;
|
|
4791
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4792
|
+
setLocalDiagram(updatedDiagram);
|
|
4793
|
+
onDiagramChange?.(updatedDiagram);
|
|
4794
|
+
selection.selectedNodeIds.forEach((nodeId) => {
|
|
4795
|
+
const node = updatedNodes.find((n) => n.id === nodeId);
|
|
4796
|
+
if (node) {
|
|
4797
|
+
onNodeMove?.(nodeId, node.transform.x, node.transform.y);
|
|
4798
|
+
}
|
|
4799
|
+
});
|
|
4800
|
+
}
|
|
4801
|
+
};
|
|
4802
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4803
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4804
|
+
}, [
|
|
4805
|
+
selectionEnabled,
|
|
4806
|
+
features.dragNodes,
|
|
4807
|
+
selection.selectedNodeIds,
|
|
4808
|
+
selectedWaypoint,
|
|
4809
|
+
localDiagram,
|
|
4810
|
+
onDiagramChange,
|
|
4811
|
+
onNodeMove,
|
|
4812
|
+
pushToHistory
|
|
4813
|
+
]);
|
|
4814
|
+
const handlePositionChange = useCallback7(
|
|
4815
|
+
(nodeId, x, y) => {
|
|
4816
|
+
pushToHistory(localDiagram);
|
|
4817
|
+
const updatedNodes = localDiagram.nodes.map(
|
|
4818
|
+
(node) => node.id === nodeId ? {
|
|
4819
|
+
...node,
|
|
4820
|
+
transform: {
|
|
4821
|
+
...node.transform,
|
|
4822
|
+
x,
|
|
4823
|
+
y
|
|
4824
|
+
}
|
|
4825
|
+
} : node
|
|
4826
|
+
);
|
|
4827
|
+
const updatedDiagram = { ...localDiagram, nodes: updatedNodes };
|
|
4828
|
+
isInternalChange.current = true;
|
|
4829
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
4830
|
+
setLocalDiagram(updatedDiagram);
|
|
4831
|
+
onDiagramChange?.(updatedDiagram);
|
|
4832
|
+
onNodeMove?.(nodeId, x, y);
|
|
4833
|
+
},
|
|
4834
|
+
[localDiagram, onDiagramChange, onNodeMove, pushToHistory]
|
|
4835
|
+
);
|
|
4836
|
+
const handleWaypointPositionChange = useCallback7(
|
|
4837
|
+
(pipeId, pointIndex, x, y) => {
|
|
4838
|
+
pushToHistory(localDiagram);
|
|
4839
|
+
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
4840
|
+
if (pipe.id === pipeId) {
|
|
4841
|
+
const updatedRoutePoints = pipe.routePoints.map(
|
|
4842
|
+
(point, idx) => idx === pointIndex ? { x, y } : point
|
|
4843
|
+
);
|
|
4844
|
+
return { ...pipe, routePoints: updatedRoutePoints };
|
|
4845
|
+
}
|
|
4846
|
+
return pipe;
|
|
4847
|
+
});
|
|
4848
|
+
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4849
|
+
setLocalDiagram(updatedDiagram);
|
|
4850
|
+
onDiagramChange?.(updatedDiagram);
|
|
4851
|
+
},
|
|
4852
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
4853
|
+
);
|
|
3355
4854
|
const handleDragEnd = useCallback7(
|
|
3356
4855
|
(nodeId, offset, finalPosition) => {
|
|
3357
4856
|
const dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2);
|
|
@@ -3361,6 +4860,7 @@ function PIDCanvas({
|
|
|
3361
4860
|
}
|
|
3362
4861
|
return;
|
|
3363
4862
|
}
|
|
4863
|
+
pushToHistory(localDiagram);
|
|
3364
4864
|
const updatedNodes = localDiagram.nodes.map(
|
|
3365
4865
|
(node) => node.id === nodeId ? {
|
|
3366
4866
|
...node,
|
|
@@ -3398,11 +4898,13 @@ function PIDCanvas({
|
|
|
3398
4898
|
nodes: updatedNodes,
|
|
3399
4899
|
pipes: updatedPipes
|
|
3400
4900
|
};
|
|
4901
|
+
isInternalChange.current = true;
|
|
4902
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3401
4903
|
setLocalDiagram(updatedDiagram);
|
|
3402
4904
|
onDiagramChange?.(updatedDiagram);
|
|
3403
4905
|
onNodeMove?.(nodeId, finalPosition.x, finalPosition.y);
|
|
3404
4906
|
},
|
|
3405
|
-
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode]
|
|
4907
|
+
[localDiagram, onDiagramChange, onNodeMove, selectionEnabled, selectNode, pushToHistory]
|
|
3406
4908
|
);
|
|
3407
4909
|
const { dragState, startDrag } = useDrag({
|
|
3408
4910
|
snapToGrid: features.snapToGrid ?? 0,
|
|
@@ -3413,6 +4915,7 @@ function PIDCanvas({
|
|
|
3413
4915
|
snapToGrid: features.snapToGrid ?? 0,
|
|
3414
4916
|
screenToWorld,
|
|
3415
4917
|
onDragEnd: (pipeId, _offset, finalPosition) => {
|
|
4918
|
+
pushToHistory(localDiagram);
|
|
3416
4919
|
const [actualPipeId, pointIndex] = pipeId.split(":");
|
|
3417
4920
|
const idx = parseInt(pointIndex, 10);
|
|
3418
4921
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
@@ -3423,6 +4926,8 @@ function PIDCanvas({
|
|
|
3423
4926
|
return { ...pipe, routePoints: updatedRoutePoints };
|
|
3424
4927
|
});
|
|
3425
4928
|
const updatedDiagram = { ...localDiagram, pipes: updatedPipes };
|
|
4929
|
+
isInternalChange.current = true;
|
|
4930
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3426
4931
|
setLocalDiagram(updatedDiagram);
|
|
3427
4932
|
onDiagramChange?.(updatedDiagram);
|
|
3428
4933
|
}
|
|
@@ -3435,6 +4940,15 @@ function PIDCanvas({
|
|
|
3435
4940
|
},
|
|
3436
4941
|
[localDiagram.nodes, startDrag]
|
|
3437
4942
|
);
|
|
4943
|
+
const handleWaypointClick = useCallback7(
|
|
4944
|
+
(pipeId, pointIndex) => {
|
|
4945
|
+
setSelectedWaypoint({ pipeId, pointIndex });
|
|
4946
|
+
if (selectionEnabled) {
|
|
4947
|
+
clearSelection();
|
|
4948
|
+
}
|
|
4949
|
+
},
|
|
4950
|
+
[selectionEnabled, clearSelection]
|
|
4951
|
+
);
|
|
3438
4952
|
const handleWaypointDragStart = useCallback7(
|
|
3439
4953
|
(pipeId, pointIndex, event) => {
|
|
3440
4954
|
const pipe = localDiagram.pipes.find((p) => p.id === pipeId);
|
|
@@ -3446,6 +4960,7 @@ function PIDCanvas({
|
|
|
3446
4960
|
);
|
|
3447
4961
|
const handlePipeSegmentClick = useCallback7(
|
|
3448
4962
|
(pipeId, position, segmentIndex) => {
|
|
4963
|
+
pushToHistory(localDiagram);
|
|
3449
4964
|
const updatedPipes = localDiagram.pipes.map((pipe) => {
|
|
3450
4965
|
if (pipe.id !== pipeId) return pipe;
|
|
3451
4966
|
const updatedRoutePoints = [
|
|
@@ -3459,13 +4974,14 @@ function PIDCanvas({
|
|
|
3459
4974
|
setLocalDiagram(updatedDiagram);
|
|
3460
4975
|
onDiagramChange?.(updatedDiagram);
|
|
3461
4976
|
},
|
|
3462
|
-
[localDiagram, onDiagramChange]
|
|
4977
|
+
[localDiagram, onDiagramChange, pushToHistory]
|
|
3463
4978
|
);
|
|
3464
4979
|
const telemetryEnabled = features.telemetry ?? false;
|
|
3465
4980
|
const handleDelete = useCallback7(() => {
|
|
3466
4981
|
if (!selectionEnabled) return;
|
|
3467
4982
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
3468
4983
|
if (selectedNodeIds.size === 0 && selectedPipeIds.size === 0) return;
|
|
4984
|
+
pushToHistory(localDiagram);
|
|
3469
4985
|
const updatedNodes = localDiagram.nodes.filter((node) => !selectedNodeIds.has(node.id));
|
|
3470
4986
|
const updatedPipes = localDiagram.pipes.filter(
|
|
3471
4987
|
(pipe) => !selectedPipeIds.has(pipe.id) && !selectedNodeIds.has(pipe.fromNodeId) && !selectedNodeIds.has(pipe.toNodeId)
|
|
@@ -3475,11 +4991,21 @@ function PIDCanvas({
|
|
|
3475
4991
|
nodes: updatedNodes,
|
|
3476
4992
|
pipes: updatedPipes
|
|
3477
4993
|
};
|
|
4994
|
+
isInternalChange.current = true;
|
|
4995
|
+
lastInternalDiagram.current = updatedDiagram;
|
|
3478
4996
|
setLocalDiagram(updatedDiagram);
|
|
3479
4997
|
clearSelection();
|
|
3480
4998
|
onDiagramChange?.(updatedDiagram);
|
|
3481
4999
|
onDelete?.(Array.from(selectedNodeIds), Array.from(selectedPipeIds));
|
|
3482
|
-
}, [
|
|
5000
|
+
}, [
|
|
5001
|
+
selection,
|
|
5002
|
+
localDiagram,
|
|
5003
|
+
selectionEnabled,
|
|
5004
|
+
clearSelection,
|
|
5005
|
+
onDiagramChange,
|
|
5006
|
+
onDelete,
|
|
5007
|
+
pushToHistory
|
|
5008
|
+
]);
|
|
3483
5009
|
const handleCopy = useCallback7(() => {
|
|
3484
5010
|
if (!selectionEnabled) return;
|
|
3485
5011
|
const { selectedNodeIds, selectedPipeIds } = selection;
|
|
@@ -3536,10 +5062,15 @@ function PIDCanvas({
|
|
|
3536
5062
|
}
|
|
3537
5063
|
onPipeClick?.(pipeId);
|
|
3538
5064
|
};
|
|
3539
|
-
const handleCanvasClick = () => {
|
|
5065
|
+
const handleCanvasClick = (e) => {
|
|
5066
|
+
const target = e.target;
|
|
5067
|
+
if (target.closest(".pipe-route-point")) {
|
|
5068
|
+
return;
|
|
5069
|
+
}
|
|
3540
5070
|
if (selectionEnabled) {
|
|
3541
5071
|
clearSelection();
|
|
3542
5072
|
}
|
|
5073
|
+
setSelectedWaypoint(null);
|
|
3543
5074
|
};
|
|
3544
5075
|
const handleDragOver = useCallback7(
|
|
3545
5076
|
(event) => {
|
|
@@ -3550,7 +5081,7 @@ function PIDCanvas({
|
|
|
3550
5081
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3551
5082
|
setDragOverPosition(worldPos);
|
|
3552
5083
|
},
|
|
3553
|
-
[features.allowSymbolDrop, screenToWorld]
|
|
5084
|
+
[features.allowSymbolDrop, screenToWorld, svgRef]
|
|
3554
5085
|
);
|
|
3555
5086
|
const handleDrop = useCallback7(
|
|
3556
5087
|
(event) => {
|
|
@@ -3563,7 +5094,7 @@ function PIDCanvas({
|
|
|
3563
5094
|
const worldPos = screenToWorld(event.clientX, event.clientY);
|
|
3564
5095
|
onSymbolDrop?.(symbolId, worldPos);
|
|
3565
5096
|
},
|
|
3566
|
-
[features.allowSymbolDrop, screenToWorld, onSymbolDrop]
|
|
5097
|
+
[features.allowSymbolDrop, screenToWorld, onSymbolDrop, svgRef]
|
|
3567
5098
|
);
|
|
3568
5099
|
const handleDragLeave = useCallback7(() => {
|
|
3569
5100
|
setDragOverPosition(null);
|
|
@@ -3587,7 +5118,7 @@ function PIDCanvas({
|
|
|
3587
5118
|
const distance = Math.sqrt(
|
|
3588
5119
|
(worldPos.x - portPos.x) ** 2 + (worldPos.y - portPos.y) ** 2
|
|
3589
5120
|
);
|
|
3590
|
-
if (distance <
|
|
5121
|
+
if (distance < 15) {
|
|
3591
5122
|
foundPort = port.id;
|
|
3592
5123
|
foundNode = node.id;
|
|
3593
5124
|
break;
|
|
@@ -3604,9 +5135,11 @@ function PIDCanvas({
|
|
|
3604
5135
|
const { name } = diagram;
|
|
3605
5136
|
const viewBox = controlledViewBox;
|
|
3606
5137
|
const displayDiagram = localDiagram;
|
|
3607
|
-
|
|
5138
|
+
const selectedNode = selectionEnabled && selection.selectedNodeIds.size === 1 ? localDiagram.nodes.find((n) => selection.selectedNodeIds.has(n.id)) || null : null;
|
|
5139
|
+
return /* @__PURE__ */ jsxs13(
|
|
3608
5140
|
"div",
|
|
3609
5141
|
{
|
|
5142
|
+
ref: containerRef,
|
|
3610
5143
|
className: `pid-canvas ${className}`.trim(),
|
|
3611
5144
|
style: {
|
|
3612
5145
|
width: "100%",
|
|
@@ -3617,223 +5150,287 @@ function PIDCanvas({
|
|
|
3617
5150
|
...style
|
|
3618
5151
|
},
|
|
3619
5152
|
...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
|
-
|
|
5153
|
+
children: [
|
|
5154
|
+
/* @__PURE__ */ jsxs13(
|
|
5155
|
+
"svg",
|
|
5156
|
+
{
|
|
5157
|
+
ref: svgRef,
|
|
5158
|
+
width: "100%",
|
|
5159
|
+
height: "100%",
|
|
5160
|
+
viewBox: `${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`,
|
|
5161
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
5162
|
+
style: {
|
|
5163
|
+
display: "block"
|
|
5164
|
+
},
|
|
5165
|
+
"aria-label": `P&ID diagram: ${name}`,
|
|
5166
|
+
role: "img",
|
|
5167
|
+
onClick: handleCanvasClick,
|
|
5168
|
+
onMouseMove: handleMouseMove,
|
|
5169
|
+
onDragOver: handleDragOver,
|
|
5170
|
+
onDrop: handleDrop,
|
|
5171
|
+
onDragLeave: handleDragLeave,
|
|
5172
|
+
children: [
|
|
5173
|
+
features.showGrid !== false ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
5174
|
+
/* @__PURE__ */ jsxs13("defs", { children: [
|
|
5175
|
+
/* @__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" }) }),
|
|
5176
|
+
/* @__PURE__ */ jsxs13("pattern", { id: "grid-major", width: "25", height: "25", patternUnits: "userSpaceOnUse", children: [
|
|
5177
|
+
/* @__PURE__ */ jsx17("rect", { width: "25", height: "25", fill: "url(#grid-minor)" }),
|
|
5178
|
+
/* @__PURE__ */ jsx17("path", { d: "M 25 0 L 0 0 0 25", fill: "none", stroke: "#d1d5db", strokeWidth: "1" })
|
|
5179
|
+
] })
|
|
5180
|
+
] }),
|
|
5181
|
+
/* @__PURE__ */ jsx17(
|
|
5182
|
+
"rect",
|
|
5183
|
+
{
|
|
5184
|
+
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
5185
|
+
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
5186
|
+
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
5187
|
+
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
5188
|
+
fill: "url(#grid-major)"
|
|
5189
|
+
}
|
|
5190
|
+
)
|
|
5191
|
+
] }) : /* @__PURE__ */ jsx17(
|
|
3648
5192
|
"rect",
|
|
3649
5193
|
{
|
|
3650
5194
|
x: Math.floor(viewBox.x / 25) * 25 - viewBox.width,
|
|
3651
5195
|
y: Math.floor(viewBox.y / 25) * 25 - viewBox.height,
|
|
3652
5196
|
width: Math.ceil(viewBox.width * 3 / 25) * 25,
|
|
3653
5197
|
height: Math.ceil(viewBox.height * 3 / 25) * 25,
|
|
3654
|
-
fill: "
|
|
5198
|
+
fill: features.backgroundColor ?? "#ffffff"
|
|
3655
5199
|
}
|
|
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,
|
|
5200
|
+
),
|
|
5201
|
+
/* @__PURE__ */ jsx17(
|
|
5202
|
+
PipeRenderer,
|
|
3716
5203
|
{
|
|
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
|
-
}
|
|
5204
|
+
pipes: displayDiagram.pipes,
|
|
5205
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5206
|
+
onPipeClick: selectionEnabled ? handlePipeClick : void 0,
|
|
5207
|
+
enableWaypointEditing: false,
|
|
5208
|
+
onWaypointDragStart: void 0,
|
|
5209
|
+
editingPipeId: null,
|
|
5210
|
+
draggingWaypointIndex: null,
|
|
5211
|
+
waypointDragOffset: void 0,
|
|
5212
|
+
onPipeSegmentClick: void 0
|
|
3752
5213
|
}
|
|
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",
|
|
5214
|
+
),
|
|
5215
|
+
/* @__PURE__ */ jsx17(
|
|
5216
|
+
NodeRenderer,
|
|
5217
|
+
{
|
|
5218
|
+
nodes: displayDiagram.nodes,
|
|
5219
|
+
selectedNodeIds: selectionEnabled ? selection.selectedNodeIds : void 0,
|
|
5220
|
+
onNodeClick: selectionEnabled || features.connectionMode ? handleNodeClick : void 0,
|
|
5221
|
+
onNodeDoubleClick: selectionEnabled ? handleNodeDoubleClick : void 0,
|
|
5222
|
+
enableDrag: dragEnabled && !isConnecting,
|
|
5223
|
+
onNodeDragStart: dragEnabled && !isConnecting ? handleNodeDragStart : void 0,
|
|
5224
|
+
draggingNodeId: dragState.draggedId,
|
|
5225
|
+
dragOffset: dragState.offset
|
|
5226
|
+
}
|
|
5227
|
+
),
|
|
5228
|
+
(features.editPipeRoutes ?? false) && /* @__PURE__ */ jsx17(
|
|
5229
|
+
PipeRenderer,
|
|
5230
|
+
{
|
|
5231
|
+
pipes: displayDiagram.pipes,
|
|
5232
|
+
selectedPipeIds: selectionEnabled ? selection.selectedPipeIds : void 0,
|
|
5233
|
+
onPipeClick: void 0,
|
|
5234
|
+
enableWaypointEditing: true,
|
|
5235
|
+
onWaypointClick: handleWaypointClick,
|
|
5236
|
+
onWaypointDragStart: handleWaypointDragStart,
|
|
5237
|
+
selectedWaypointPipeId: selectedWaypoint?.pipeId || null,
|
|
5238
|
+
selectedWaypointIndex: selectedWaypoint?.pointIndex ?? null,
|
|
5239
|
+
editingPipeId: waypointDragState.draggedId?.split(":")[0] || null,
|
|
5240
|
+
draggingWaypointIndex: waypointDragState.draggedId ? parseInt(waypointDragState.draggedId.split(":")[1], 10) : null,
|
|
5241
|
+
waypointDragOffset: waypointDragState.offset,
|
|
5242
|
+
onPipeSegmentClick: handlePipeSegmentClick
|
|
5243
|
+
}
|
|
5244
|
+
),
|
|
5245
|
+
telemetryEnabled && telemetry && /* @__PURE__ */ jsx17("g", { id: "layer-telemetry", children: displayDiagram.nodes.map((node) => {
|
|
5246
|
+
const binding = telemetry.get(node.id);
|
|
5247
|
+
if (!binding) return null;
|
|
5248
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5249
|
+
if (!symbol) return null;
|
|
5250
|
+
const overlayX = node.transform.x + symbol.viewBox.width / 2;
|
|
5251
|
+
const overlayY = node.transform.y + symbol.viewBox.height + 50;
|
|
5252
|
+
return /* @__PURE__ */ jsx17(
|
|
5253
|
+
DataOverlay,
|
|
3802
5254
|
{
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
3809
|
-
opacity: isHovered || isSourcePort ? 1 : 0.6
|
|
5255
|
+
nodeId: node.id,
|
|
5256
|
+
x: overlayX,
|
|
5257
|
+
y: overlayY,
|
|
5258
|
+
telemetry: binding,
|
|
5259
|
+
scale: features.telemetryScale ?? 1
|
|
3810
5260
|
},
|
|
3811
|
-
|
|
5261
|
+
`telemetry-${node.id}`
|
|
3812
5262
|
);
|
|
3813
|
-
})
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
5263
|
+
}) }),
|
|
5264
|
+
dragOverPosition && /* @__PURE__ */ jsx17(
|
|
5265
|
+
"circle",
|
|
5266
|
+
{
|
|
5267
|
+
cx: dragOverPosition.x,
|
|
5268
|
+
cy: dragOverPosition.y,
|
|
5269
|
+
r: 20,
|
|
5270
|
+
fill: "#3b82f6",
|
|
5271
|
+
opacity: 0.3,
|
|
5272
|
+
stroke: "#3b82f6",
|
|
5273
|
+
strokeWidth: 2,
|
|
5274
|
+
pointerEvents: "none"
|
|
5275
|
+
}
|
|
5276
|
+
),
|
|
5277
|
+
isConnecting && connectionSource && connectionCursor && /* @__PURE__ */ jsx17("g", { id: "connection-preview", pointerEvents: "none", children: (() => {
|
|
5278
|
+
const sourceNode = displayDiagram.nodes.find((n) => n.id === connectionSource);
|
|
5279
|
+
if (!sourceNode) return null;
|
|
5280
|
+
const symbol = getSymbolDefinition(sourceNode.symbolId);
|
|
5281
|
+
let lineStartX = sourceNode.transform.x;
|
|
5282
|
+
let lineStartY = sourceNode.transform.y;
|
|
5283
|
+
if (connectionSourcePort && symbol?.ports) {
|
|
5284
|
+
const port = symbol.ports.find((p) => p.id === connectionSourcePort);
|
|
5285
|
+
if (port) {
|
|
5286
|
+
const portPos = getPortWorldPosition(sourceNode, connectionSourcePort);
|
|
5287
|
+
if (portPos) {
|
|
5288
|
+
lineStartX = portPos.x;
|
|
5289
|
+
lineStartY = portPos.y;
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
return /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
5294
|
+
/* @__PURE__ */ jsx17(
|
|
5295
|
+
"circle",
|
|
5296
|
+
{
|
|
5297
|
+
cx: lineStartX,
|
|
5298
|
+
cy: lineStartY,
|
|
5299
|
+
r: 30,
|
|
5300
|
+
fill: "none",
|
|
5301
|
+
stroke: "#10b981",
|
|
5302
|
+
strokeWidth: 3,
|
|
5303
|
+
opacity: 0.6
|
|
5304
|
+
}
|
|
5305
|
+
),
|
|
5306
|
+
/* @__PURE__ */ jsx17(
|
|
5307
|
+
"line",
|
|
5308
|
+
{
|
|
5309
|
+
x1: lineStartX,
|
|
5310
|
+
y1: lineStartY,
|
|
5311
|
+
x2: connectionCursor.x,
|
|
5312
|
+
y2: connectionCursor.y,
|
|
5313
|
+
stroke: "#10b981",
|
|
5314
|
+
strokeWidth: 2,
|
|
5315
|
+
strokeDasharray: "5,5",
|
|
5316
|
+
opacity: 0.8
|
|
5317
|
+
}
|
|
5318
|
+
),
|
|
5319
|
+
/* @__PURE__ */ jsx17(
|
|
5320
|
+
"circle",
|
|
5321
|
+
{
|
|
5322
|
+
cx: connectionCursor.x,
|
|
5323
|
+
cy: connectionCursor.y,
|
|
5324
|
+
r: 8,
|
|
5325
|
+
fill: "#10b981",
|
|
5326
|
+
opacity: 0.6
|
|
5327
|
+
}
|
|
5328
|
+
)
|
|
5329
|
+
] });
|
|
5330
|
+
})() }),
|
|
5331
|
+
features.connectionMode && /* @__PURE__ */ jsx17("g", { id: "port-indicators", children: displayDiagram.nodes.map((node) => {
|
|
5332
|
+
const symbol = getSymbolDefinition(node.symbolId);
|
|
5333
|
+
if (!symbol?.ports) return null;
|
|
5334
|
+
return symbol.ports.map((port) => {
|
|
5335
|
+
const portPos = getPortWorldPosition(node, port.id);
|
|
5336
|
+
if (!portPos) return null;
|
|
5337
|
+
const isHovered = hoveredPort === port.id && hoveredNode === node.id;
|
|
5338
|
+
const isSourcePort = node.id === connectionSource && port.id === connectionSourcePort;
|
|
5339
|
+
return /* @__PURE__ */ jsxs13("g", { children: [
|
|
5340
|
+
/* @__PURE__ */ jsx17(
|
|
5341
|
+
"circle",
|
|
5342
|
+
{
|
|
5343
|
+
cx: portPos.x,
|
|
5344
|
+
cy: portPos.y,
|
|
5345
|
+
r: 15,
|
|
5346
|
+
fill: "transparent",
|
|
5347
|
+
style: { cursor: "pointer" },
|
|
5348
|
+
pointerEvents: "auto",
|
|
5349
|
+
onClick: (e) => {
|
|
5350
|
+
e.stopPropagation();
|
|
5351
|
+
if (isConnecting && connectionSource) {
|
|
5352
|
+
if (connectionSource !== node.id) {
|
|
5353
|
+
onPipeCreated?.(
|
|
5354
|
+
connectionSource,
|
|
5355
|
+
node.id,
|
|
5356
|
+
connectionSourcePort || void 0,
|
|
5357
|
+
port.id
|
|
5358
|
+
);
|
|
5359
|
+
setIsConnecting(false);
|
|
5360
|
+
setConnectionSource(null);
|
|
5361
|
+
setConnectionSourcePort(null);
|
|
5362
|
+
setConnectionCursor(null);
|
|
5363
|
+
setHoveredPort(null);
|
|
5364
|
+
}
|
|
5365
|
+
} else {
|
|
5366
|
+
setIsConnecting(true);
|
|
5367
|
+
setConnectionSource(node.id);
|
|
5368
|
+
setConnectionSourcePort(port.id);
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
),
|
|
5373
|
+
/* @__PURE__ */ jsx17(
|
|
5374
|
+
"circle",
|
|
5375
|
+
{
|
|
5376
|
+
cx: portPos.x,
|
|
5377
|
+
cy: portPos.y,
|
|
5378
|
+
r: isHovered ? 8 : 5,
|
|
5379
|
+
fill: isSourcePort ? "#10b981" : isHovered ? "#3b82f6" : "#94a3b8",
|
|
5380
|
+
stroke: isSourcePort ? "#059669" : isHovered ? "#2563eb" : "#64748b",
|
|
5381
|
+
strokeWidth: isHovered || isSourcePort ? 2 : 1,
|
|
5382
|
+
opacity: isHovered || isSourcePort ? 1 : 0.6,
|
|
5383
|
+
pointerEvents: "none"
|
|
5384
|
+
}
|
|
5385
|
+
)
|
|
5386
|
+
] }, `${node.id}-${port.id}`);
|
|
5387
|
+
});
|
|
5388
|
+
}) })
|
|
5389
|
+
]
|
|
5390
|
+
}
|
|
5391
|
+
),
|
|
5392
|
+
features.dragNodes && /* @__PURE__ */ jsx17(
|
|
5393
|
+
PositionPanel,
|
|
5394
|
+
{
|
|
5395
|
+
selectedNode,
|
|
5396
|
+
selectedWaypoint: selectedWaypoint ? {
|
|
5397
|
+
pipeId: selectedWaypoint.pipeId,
|
|
5398
|
+
pointIndex: selectedWaypoint.pointIndex,
|
|
5399
|
+
position: localDiagram.pipes.find((p) => p.id === selectedWaypoint.pipeId)?.routePoints[selectedWaypoint.pointIndex] || { x: 0, y: 0 }
|
|
5400
|
+
} : null,
|
|
5401
|
+
onPositionChange: handlePositionChange,
|
|
5402
|
+
onWaypointPositionChange: handleWaypointPositionChange,
|
|
5403
|
+
position: "top-right"
|
|
5404
|
+
}
|
|
5405
|
+
)
|
|
5406
|
+
]
|
|
3818
5407
|
}
|
|
3819
5408
|
);
|
|
3820
5409
|
}
|
|
3821
5410
|
|
|
3822
5411
|
// src/components/SymbolLibrary/SymbolLibrary.tsx
|
|
3823
|
-
import { useState as
|
|
3824
|
-
import { jsx as
|
|
5412
|
+
import { useState as useState13 } from "react";
|
|
5413
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3825
5414
|
function SymbolLibrary({
|
|
3826
5415
|
className = "",
|
|
3827
5416
|
onSymbolDragStart,
|
|
3828
5417
|
showCategories = true,
|
|
3829
5418
|
categories = ["Valves", "Pumps", "Tanks", "Instruments", "Displays"]
|
|
3830
5419
|
}) {
|
|
3831
|
-
const [selectedCategory, setSelectedCategory] =
|
|
3832
|
-
const [searchQuery, setSearchQuery] =
|
|
5420
|
+
const [selectedCategory, setSelectedCategory] = useState13("all");
|
|
5421
|
+
const [searchQuery, setSearchQuery] = useState13("");
|
|
3833
5422
|
const symbolIds = getAvailableSymbols();
|
|
3834
5423
|
const allSymbols = symbolIds.map((id) => getSymbolDefinition(id)).filter((symbol) => symbol !== void 0);
|
|
5424
|
+
const categoryMap = {
|
|
5425
|
+
Valves: "valve",
|
|
5426
|
+
Pumps: "pump",
|
|
5427
|
+
Tanks: "vessel",
|
|
5428
|
+
Instruments: "instrument",
|
|
5429
|
+
Displays: "display"
|
|
5430
|
+
};
|
|
3835
5431
|
const filteredSymbols = allSymbols.filter((symbol) => {
|
|
3836
|
-
const
|
|
5432
|
+
const actualCategory = categoryMap[selectedCategory] || selectedCategory;
|
|
5433
|
+
const matchesCategory = selectedCategory === "all" || symbol.category === actualCategory;
|
|
3837
5434
|
const matchesSearch = searchQuery === "" || symbol.name.toLowerCase().includes(searchQuery.toLowerCase()) || symbol.id.toLowerCase().includes(searchQuery.toLowerCase());
|
|
3838
5435
|
return matchesCategory && matchesSearch;
|
|
3839
5436
|
});
|
|
@@ -3842,9 +5439,9 @@ function SymbolLibrary({
|
|
|
3842
5439
|
event.dataTransfer.effectAllowed = "copy";
|
|
3843
5440
|
onSymbolDragStart?.(symbol.id, event);
|
|
3844
5441
|
};
|
|
3845
|
-
return /* @__PURE__ */
|
|
3846
|
-
/* @__PURE__ */
|
|
3847
|
-
/* @__PURE__ */
|
|
5442
|
+
return /* @__PURE__ */ jsxs14("div", { className: `symbol-library ${className}`.trim(), style: styles.container, children: [
|
|
5443
|
+
/* @__PURE__ */ jsx18("div", { style: styles.header, children: /* @__PURE__ */ jsx18("h3", { style: styles.title, children: "Symbol Library" }) }),
|
|
5444
|
+
/* @__PURE__ */ jsx18("div", { style: styles.searchContainer, children: /* @__PURE__ */ jsx18(
|
|
3848
5445
|
"input",
|
|
3849
5446
|
{
|
|
3850
5447
|
type: "text",
|
|
@@ -3854,8 +5451,8 @@ function SymbolLibrary({
|
|
|
3854
5451
|
style: styles.searchInput
|
|
3855
5452
|
}
|
|
3856
5453
|
) }),
|
|
3857
|
-
showCategories && /* @__PURE__ */
|
|
3858
|
-
/* @__PURE__ */
|
|
5454
|
+
showCategories && /* @__PURE__ */ jsxs14("div", { style: styles.categories, children: [
|
|
5455
|
+
/* @__PURE__ */ jsx18(
|
|
3859
5456
|
"button",
|
|
3860
5457
|
{
|
|
3861
5458
|
onClick: () => setSelectedCategory("all"),
|
|
@@ -3866,7 +5463,7 @@ function SymbolLibrary({
|
|
|
3866
5463
|
children: "All"
|
|
3867
5464
|
}
|
|
3868
5465
|
),
|
|
3869
|
-
categories.map((category) => /* @__PURE__ */
|
|
5466
|
+
categories.map((category) => /* @__PURE__ */ jsx18(
|
|
3870
5467
|
"button",
|
|
3871
5468
|
{
|
|
3872
5469
|
onClick: () => setSelectedCategory(category),
|
|
@@ -3879,7 +5476,7 @@ function SymbolLibrary({
|
|
|
3879
5476
|
category
|
|
3880
5477
|
))
|
|
3881
5478
|
] }),
|
|
3882
|
-
/* @__PURE__ */
|
|
5479
|
+
/* @__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
5480
|
"div",
|
|
3884
5481
|
{
|
|
3885
5482
|
draggable: true,
|
|
@@ -3887,15 +5484,15 @@ function SymbolLibrary({
|
|
|
3887
5484
|
style: styles.symbolCard,
|
|
3888
5485
|
title: symbol.metadata?.description || symbol.name,
|
|
3889
5486
|
children: [
|
|
3890
|
-
/* @__PURE__ */
|
|
5487
|
+
/* @__PURE__ */ jsx18("div", { style: styles.symbolPreview, children: /* @__PURE__ */ jsx18(
|
|
3891
5488
|
"svg",
|
|
3892
5489
|
{
|
|
3893
5490
|
viewBox: `${symbol.viewBox.x} ${symbol.viewBox.y} ${symbol.viewBox.width} ${symbol.viewBox.height}`,
|
|
3894
5491
|
style: styles.symbolSvg,
|
|
3895
|
-
children: /* @__PURE__ */
|
|
5492
|
+
children: /* @__PURE__ */ jsx18("g", { dangerouslySetInnerHTML: { __html: symbol.svgContent } })
|
|
3896
5493
|
}
|
|
3897
5494
|
) }),
|
|
3898
|
-
/* @__PURE__ */
|
|
5495
|
+
/* @__PURE__ */ jsx18("div", { style: styles.symbolName, children: symbol.name })
|
|
3899
5496
|
]
|
|
3900
5497
|
},
|
|
3901
5498
|
symbol.id
|
|
@@ -4004,7 +5601,7 @@ var styles = {
|
|
|
4004
5601
|
};
|
|
4005
5602
|
|
|
4006
5603
|
// src/components/NodeConfigPanel/NodeConfigPanel.tsx
|
|
4007
|
-
import { Fragment as Fragment6, jsx as
|
|
5604
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4008
5605
|
function NodeConfigPanel({
|
|
4009
5606
|
node,
|
|
4010
5607
|
binding,
|
|
@@ -4023,15 +5620,15 @@ function NodeConfigPanel({
|
|
|
4023
5620
|
padding: "20px",
|
|
4024
5621
|
...style
|
|
4025
5622
|
};
|
|
4026
|
-
return /* @__PURE__ */
|
|
4027
|
-
/* @__PURE__ */
|
|
5623
|
+
return /* @__PURE__ */ jsxs15("div", { className, style: defaultStyle, children: [
|
|
5624
|
+
/* @__PURE__ */ jsxs15("h2", { style: { margin: "0 0 16px 0", fontSize: "1rem", fontWeight: 600 }, children: [
|
|
4028
5625
|
"Configure: ",
|
|
4029
5626
|
node.id
|
|
4030
5627
|
] }),
|
|
4031
|
-
/* @__PURE__ */
|
|
4032
|
-
/* @__PURE__ */
|
|
4033
|
-
/* @__PURE__ */
|
|
4034
|
-
/* @__PURE__ */
|
|
5628
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
5629
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Node Settings" }),
|
|
5630
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label:" }),
|
|
5631
|
+
/* @__PURE__ */ jsx19(
|
|
4035
5632
|
"input",
|
|
4036
5633
|
{
|
|
4037
5634
|
type: "text",
|
|
@@ -4047,10 +5644,10 @@ function NodeConfigPanel({
|
|
|
4047
5644
|
}
|
|
4048
5645
|
}
|
|
4049
5646
|
),
|
|
4050
|
-
/* @__PURE__ */
|
|
4051
|
-
/* @__PURE__ */
|
|
4052
|
-
/* @__PURE__ */
|
|
4053
|
-
/* @__PURE__ */
|
|
5647
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5648
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5649
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset X:" }),
|
|
5650
|
+
/* @__PURE__ */ jsx19(
|
|
4054
5651
|
"input",
|
|
4055
5652
|
{
|
|
4056
5653
|
type: "number",
|
|
@@ -4071,9 +5668,9 @@ function NodeConfigPanel({
|
|
|
4071
5668
|
}
|
|
4072
5669
|
)
|
|
4073
5670
|
] }),
|
|
4074
|
-
/* @__PURE__ */
|
|
4075
|
-
/* @__PURE__ */
|
|
4076
|
-
/* @__PURE__ */
|
|
5671
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5672
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Offset Y:" }),
|
|
5673
|
+
/* @__PURE__ */ jsx19(
|
|
4077
5674
|
"input",
|
|
4078
5675
|
{
|
|
4079
5676
|
type: "number",
|
|
@@ -4095,9 +5692,9 @@ function NodeConfigPanel({
|
|
|
4095
5692
|
)
|
|
4096
5693
|
] })
|
|
4097
5694
|
] }),
|
|
4098
|
-
/* @__PURE__ */
|
|
4099
|
-
/* @__PURE__ */
|
|
4100
|
-
/* @__PURE__ */
|
|
5695
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5696
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Label Font Size:" }),
|
|
5697
|
+
/* @__PURE__ */ jsx19(
|
|
4101
5698
|
"input",
|
|
4102
5699
|
{
|
|
4103
5700
|
type: "number",
|
|
@@ -4117,9 +5714,9 @@ function NodeConfigPanel({
|
|
|
4117
5714
|
}
|
|
4118
5715
|
)
|
|
4119
5716
|
] }),
|
|
4120
|
-
/* @__PURE__ */
|
|
4121
|
-
/* @__PURE__ */
|
|
4122
|
-
/* @__PURE__ */
|
|
5717
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5718
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Rotation (degrees):" }),
|
|
5719
|
+
/* @__PURE__ */ jsx19(
|
|
4123
5720
|
"input",
|
|
4124
5721
|
{
|
|
4125
5722
|
type: "number",
|
|
@@ -4144,9 +5741,9 @@ function NodeConfigPanel({
|
|
|
4144
5741
|
)
|
|
4145
5742
|
] })
|
|
4146
5743
|
] }),
|
|
4147
|
-
/* @__PURE__ */
|
|
4148
|
-
/* @__PURE__ */
|
|
4149
|
-
!binding ? /* @__PURE__ */
|
|
5744
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
5745
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Telemetry Data" }),
|
|
5746
|
+
!binding ? /* @__PURE__ */ jsx19(
|
|
4150
5747
|
"button",
|
|
4151
5748
|
{
|
|
4152
5749
|
onClick: () => {
|
|
@@ -4189,9 +5786,9 @@ function NodeConfigPanel({
|
|
|
4189
5786
|
},
|
|
4190
5787
|
children: "+ Add Telemetry"
|
|
4191
5788
|
}
|
|
4192
|
-
) : /* @__PURE__ */
|
|
4193
|
-
/* @__PURE__ */
|
|
4194
|
-
/* @__PURE__ */
|
|
5789
|
+
) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
5790
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Initial Value:" }),
|
|
5791
|
+
/* @__PURE__ */ jsx19(
|
|
4195
5792
|
"input",
|
|
4196
5793
|
{
|
|
4197
5794
|
type: "number",
|
|
@@ -4213,8 +5810,8 @@ function NodeConfigPanel({
|
|
|
4213
5810
|
}
|
|
4214
5811
|
}
|
|
4215
5812
|
),
|
|
4216
|
-
/* @__PURE__ */
|
|
4217
|
-
/* @__PURE__ */
|
|
5813
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: "Unit:" }),
|
|
5814
|
+
/* @__PURE__ */ jsx19(
|
|
4218
5815
|
"input",
|
|
4219
5816
|
{
|
|
4220
5817
|
type: "text",
|
|
@@ -4236,8 +5833,8 @@ function NodeConfigPanel({
|
|
|
4236
5833
|
}
|
|
4237
5834
|
}
|
|
4238
5835
|
),
|
|
4239
|
-
/* @__PURE__ */
|
|
4240
|
-
/* @__PURE__ */
|
|
5836
|
+
/* @__PURE__ */ jsxs15("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
5837
|
+
/* @__PURE__ */ jsx19(
|
|
4241
5838
|
"input",
|
|
4242
5839
|
{
|
|
4243
5840
|
type: "checkbox",
|
|
@@ -4259,8 +5856,8 @@ function NodeConfigPanel({
|
|
|
4259
5856
|
),
|
|
4260
5857
|
"Show Sparkline"
|
|
4261
5858
|
] }),
|
|
4262
|
-
/* @__PURE__ */
|
|
4263
|
-
/* @__PURE__ */
|
|
5859
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginTop: "12px" }, children: [
|
|
5860
|
+
/* @__PURE__ */ jsx19(
|
|
4264
5861
|
"label",
|
|
4265
5862
|
{
|
|
4266
5863
|
style: {
|
|
@@ -4272,10 +5869,10 @@ function NodeConfigPanel({
|
|
|
4272
5869
|
children: "Telemetry Position Offset:"
|
|
4273
5870
|
}
|
|
4274
5871
|
),
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
/* @__PURE__ */
|
|
4277
|
-
/* @__PURE__ */
|
|
4278
|
-
/* @__PURE__ */
|
|
5872
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: [
|
|
5873
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5874
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "X Offset:" }),
|
|
5875
|
+
/* @__PURE__ */ jsx19(
|
|
4279
5876
|
"input",
|
|
4280
5877
|
{
|
|
4281
5878
|
type: "number",
|
|
@@ -4302,9 +5899,9 @@ function NodeConfigPanel({
|
|
|
4302
5899
|
}
|
|
4303
5900
|
)
|
|
4304
5901
|
] }),
|
|
4305
|
-
/* @__PURE__ */
|
|
4306
|
-
/* @__PURE__ */
|
|
4307
|
-
/* @__PURE__ */
|
|
5902
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
5903
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Y Offset:" }),
|
|
5904
|
+
/* @__PURE__ */ jsx19(
|
|
4308
5905
|
"input",
|
|
4309
5906
|
{
|
|
4310
5907
|
type: "number",
|
|
@@ -4332,8 +5929,8 @@ function NodeConfigPanel({
|
|
|
4332
5929
|
)
|
|
4333
5930
|
] })
|
|
4334
5931
|
] }),
|
|
4335
|
-
/* @__PURE__ */
|
|
4336
|
-
/* @__PURE__ */
|
|
5932
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginTop: "16px" }, children: [
|
|
5933
|
+
/* @__PURE__ */ jsx19(
|
|
4337
5934
|
"label",
|
|
4338
5935
|
{
|
|
4339
5936
|
style: {
|
|
@@ -4345,10 +5942,10 @@ function NodeConfigPanel({
|
|
|
4345
5942
|
children: "Display Colors:"
|
|
4346
5943
|
}
|
|
4347
5944
|
),
|
|
4348
|
-
/* @__PURE__ */
|
|
4349
|
-
/* @__PURE__ */
|
|
4350
|
-
/* @__PURE__ */
|
|
4351
|
-
/* @__PURE__ */
|
|
5945
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
5946
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Text Color:" }),
|
|
5947
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
5948
|
+
/* @__PURE__ */ jsx19(
|
|
4352
5949
|
"input",
|
|
4353
5950
|
{
|
|
4354
5951
|
type: "color",
|
|
@@ -4374,7 +5971,7 @@ function NodeConfigPanel({
|
|
|
4374
5971
|
}
|
|
4375
5972
|
}
|
|
4376
5973
|
),
|
|
4377
|
-
/* @__PURE__ */
|
|
5974
|
+
/* @__PURE__ */ jsx19(
|
|
4378
5975
|
"input",
|
|
4379
5976
|
{
|
|
4380
5977
|
type: "text",
|
|
@@ -4404,10 +6001,10 @@ function NodeConfigPanel({
|
|
|
4404
6001
|
)
|
|
4405
6002
|
] })
|
|
4406
6003
|
] }),
|
|
4407
|
-
binding.display?.showSparkline && /* @__PURE__ */
|
|
4408
|
-
/* @__PURE__ */
|
|
4409
|
-
/* @__PURE__ */
|
|
4410
|
-
/* @__PURE__ */
|
|
6004
|
+
binding.display?.showSparkline && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6005
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Sparkline Color:" }),
|
|
6006
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6007
|
+
/* @__PURE__ */ jsx19(
|
|
4411
6008
|
"input",
|
|
4412
6009
|
{
|
|
4413
6010
|
type: "color",
|
|
@@ -4433,7 +6030,7 @@ function NodeConfigPanel({
|
|
|
4433
6030
|
}
|
|
4434
6031
|
}
|
|
4435
6032
|
),
|
|
4436
|
-
/* @__PURE__ */
|
|
6033
|
+
/* @__PURE__ */ jsx19(
|
|
4437
6034
|
"input",
|
|
4438
6035
|
{
|
|
4439
6036
|
type: "text",
|
|
@@ -4463,9 +6060,9 @@ function NodeConfigPanel({
|
|
|
4463
6060
|
)
|
|
4464
6061
|
] })
|
|
4465
6062
|
] }),
|
|
4466
|
-
/* @__PURE__ */
|
|
4467
|
-
/* @__PURE__ */
|
|
4468
|
-
/* @__PURE__ */
|
|
6063
|
+
/* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6064
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.7rem", display: "block", marginBottom: "4px" }, children: "Background:" }),
|
|
6065
|
+
/* @__PURE__ */ jsx19(
|
|
4469
6066
|
"input",
|
|
4470
6067
|
{
|
|
4471
6068
|
type: "text",
|
|
@@ -4493,20 +6090,20 @@ function NodeConfigPanel({
|
|
|
4493
6090
|
}
|
|
4494
6091
|
}
|
|
4495
6092
|
),
|
|
4496
|
-
/* @__PURE__ */
|
|
6093
|
+
/* @__PURE__ */ jsx19("div", { style: { fontSize: "0.65rem", color: "#6b7280", marginTop: "2px" }, children: "Use 'status' for status-based color or hex code" })
|
|
4497
6094
|
] })
|
|
4498
6095
|
] }),
|
|
4499
6096
|
" "
|
|
4500
6097
|
] })
|
|
4501
6098
|
] })
|
|
4502
6099
|
] }),
|
|
4503
|
-
binding && /* @__PURE__ */
|
|
4504
|
-
/* @__PURE__ */
|
|
6100
|
+
binding && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
6101
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Thresholds" }),
|
|
4505
6102
|
["highHigh", "high", "low", "lowLow"].map((key) => {
|
|
4506
6103
|
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__ */
|
|
6104
|
+
return /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6105
|
+
/* @__PURE__ */ jsx19("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: label }),
|
|
6106
|
+
/* @__PURE__ */ jsx19(
|
|
4510
6107
|
"input",
|
|
4511
6108
|
{
|
|
4512
6109
|
type: "number",
|
|
@@ -4530,8 +6127,8 @@ function NodeConfigPanel({
|
|
|
4530
6127
|
] }, key);
|
|
4531
6128
|
})
|
|
4532
6129
|
] }),
|
|
4533
|
-
binding && /* @__PURE__ */
|
|
4534
|
-
/* @__PURE__ */
|
|
6130
|
+
binding && /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "20px" }, children: [
|
|
6131
|
+
/* @__PURE__ */ jsx19("h3", { style: { fontSize: "0.875rem", fontWeight: 600, marginBottom: "8px" }, children: "Status Colors" }),
|
|
4535
6132
|
["normal", "warning", "alarm", "fault", "off"].map((status) => {
|
|
4536
6133
|
const defaultColors = {
|
|
4537
6134
|
normal: "#10b981",
|
|
@@ -4541,13 +6138,13 @@ function NodeConfigPanel({
|
|
|
4541
6138
|
off: "#6b7280"
|
|
4542
6139
|
};
|
|
4543
6140
|
const label = status === "normal" ? "Normal" : status === "warning" ? "Warning" : status === "alarm" ? "Alarm" : status === "fault" ? "Fault" : "Off";
|
|
4544
|
-
return /* @__PURE__ */
|
|
4545
|
-
/* @__PURE__ */
|
|
6141
|
+
return /* @__PURE__ */ jsxs15("div", { style: { marginBottom: "8px" }, children: [
|
|
6142
|
+
/* @__PURE__ */ jsxs15("label", { style: { fontSize: "0.75rem", display: "block", marginBottom: "4px" }, children: [
|
|
4546
6143
|
label,
|
|
4547
6144
|
":"
|
|
4548
6145
|
] }),
|
|
4549
|
-
/* @__PURE__ */
|
|
4550
|
-
/* @__PURE__ */
|
|
6146
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
|
|
6147
|
+
/* @__PURE__ */ jsx19(
|
|
4551
6148
|
"input",
|
|
4552
6149
|
{
|
|
4553
6150
|
type: "color",
|
|
@@ -4568,7 +6165,7 @@ function NodeConfigPanel({
|
|
|
4568
6165
|
}
|
|
4569
6166
|
}
|
|
4570
6167
|
),
|
|
4571
|
-
/* @__PURE__ */
|
|
6168
|
+
/* @__PURE__ */ jsx19(
|
|
4572
6169
|
"input",
|
|
4573
6170
|
{
|
|
4574
6171
|
type: "text",
|
|
@@ -4595,7 +6192,7 @@ function NodeConfigPanel({
|
|
|
4595
6192
|
] }, status);
|
|
4596
6193
|
})
|
|
4597
6194
|
] }),
|
|
4598
|
-
/* @__PURE__ */
|
|
6195
|
+
/* @__PURE__ */ jsx19("div", { style: { marginTop: "20px", paddingTop: "20px", borderTop: "1px solid #cbd5e1" }, children: /* @__PURE__ */ jsx19(
|
|
4599
6196
|
"button",
|
|
4600
6197
|
{
|
|
4601
6198
|
onClick: onRemove,
|
|
@@ -4835,7 +6432,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
4835
6432
|
};
|
|
4836
6433
|
|
|
4837
6434
|
// src/diagram/hooks/useSimulation.ts
|
|
4838
|
-
import { useEffect as
|
|
6435
|
+
import { useEffect as useEffect11 } from "react";
|
|
4839
6436
|
function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
4840
6437
|
const {
|
|
4841
6438
|
interval = 2e3,
|
|
@@ -4846,7 +6443,7 @@ function useSimulation(telemetry, updateTelemetryBatch, options = {}) {
|
|
|
4846
6443
|
historyLength = 10,
|
|
4847
6444
|
generateValue
|
|
4848
6445
|
} = options;
|
|
4849
|
-
|
|
6446
|
+
useEffect11(() => {
|
|
4850
6447
|
if (!enabled) return;
|
|
4851
6448
|
const intervalId = setInterval(() => {
|
|
4852
6449
|
const updates = [];
|
|
@@ -4943,11 +6540,14 @@ export {
|
|
|
4943
6540
|
mockSymbolLibrary,
|
|
4944
6541
|
nodeHasPort,
|
|
4945
6542
|
overlayStyles,
|
|
6543
|
+
registerSymbol,
|
|
6544
|
+
registerSymbols,
|
|
4946
6545
|
useDrag,
|
|
4947
6546
|
useKeyboardShortcuts,
|
|
4948
6547
|
useSelection,
|
|
4949
6548
|
useSimulation,
|
|
4950
6549
|
useTelemetry,
|
|
6550
|
+
useTelemetryStatus,
|
|
4951
6551
|
useTheme,
|
|
4952
6552
|
useViewBox,
|
|
4953
6553
|
validateDiagram
|