@tscircuit/core 0.0.149 → 0.0.150
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.d.ts +17 -17
- package/dist/index.js +377 -368
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,23 @@ type ReactSubtree = {
|
|
|
60
60
|
component: NormalComponent;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
type SchematicBoxPortPositionWithMetadata = {
|
|
64
|
+
trueIndex: number;
|
|
65
|
+
pinNumber: number;
|
|
66
|
+
side: "left" | "right" | "top" | "bottom";
|
|
67
|
+
distanceFromOrthogonalEdge: number;
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
};
|
|
71
|
+
interface SchematicBoxDimensions {
|
|
72
|
+
pinCount: number;
|
|
73
|
+
getPortPositionByPinNumber(pinNumber: number): SchematicBoxPortPositionWithMetadata | null;
|
|
74
|
+
getSize(): {
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
63
80
|
type RootCircuitEventName = "asyncEffectComplete";
|
|
64
81
|
declare class Circuit {
|
|
65
82
|
firstChild: PrimitiveComponent | null;
|
|
@@ -111,23 +128,6 @@ interface ISubcircuit extends PrimitiveComponent {
|
|
|
111
128
|
_shouldUseTraceByTraceRouting(): boolean;
|
|
112
129
|
}
|
|
113
130
|
|
|
114
|
-
type SchematicBoxPortPositionWithMetadata = {
|
|
115
|
-
trueIndex: number;
|
|
116
|
-
pinNumber: number;
|
|
117
|
-
side: "left" | "right" | "top" | "bottom";
|
|
118
|
-
distanceFromOrthogonalEdge: number;
|
|
119
|
-
x: number;
|
|
120
|
-
y: number;
|
|
121
|
-
};
|
|
122
|
-
interface SchematicBoxDimensions {
|
|
123
|
-
pinCount: number;
|
|
124
|
-
getPortPositionByPinNumber(pinNumber: number): SchematicBoxPortPositionWithMetadata | null;
|
|
125
|
-
getSize(): {
|
|
126
|
-
width: number;
|
|
127
|
-
height: number;
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
131
|
interface BaseComponentConfig {
|
|
132
132
|
componentName: string;
|
|
133
133
|
schematicSymbolName?: BaseSymbolName | null;
|
package/dist/index.js
CHANGED
|
@@ -355,6 +355,53 @@ var createInstanceFromReactElement = (reactElm) => {
|
|
|
355
355
|
return rootContainer.children[0];
|
|
356
356
|
};
|
|
357
357
|
|
|
358
|
+
// lib/soup/underscorifyPinStyles.ts
|
|
359
|
+
import "circuit-json";
|
|
360
|
+
import "zod";
|
|
361
|
+
var underscorifyPinStyles = (pinStyles) => {
|
|
362
|
+
if (!pinStyles) return void 0;
|
|
363
|
+
const underscorePinStyles = {};
|
|
364
|
+
for (const [pinName, pinStyle] of Object.entries(pinStyles)) {
|
|
365
|
+
underscorePinStyles[pinName] = {
|
|
366
|
+
bottom_margin: pinStyle.bottomMargin,
|
|
367
|
+
left_margin: pinStyle.leftMargin,
|
|
368
|
+
right_margin: pinStyle.rightMargin,
|
|
369
|
+
top_margin: pinStyle.topMargin
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return underscorePinStyles;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// lib/soup/underscorifyPortArrangement.ts
|
|
376
|
+
var underscorifyPortArrangement = (portArrangement) => {
|
|
377
|
+
if (!portArrangement) return void 0;
|
|
378
|
+
if ("leftSide" in portArrangement || "rightSide" in portArrangement || "topSide" in portArrangement || "bottomSide" in portArrangement) {
|
|
379
|
+
return {
|
|
380
|
+
left_side: portArrangement.leftSide,
|
|
381
|
+
right_side: portArrangement.rightSide,
|
|
382
|
+
top_side: portArrangement.topSide,
|
|
383
|
+
bottom_side: portArrangement.bottomSide
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if ("leftPinCount" in portArrangement || "rightPinCount" in portArrangement || "topPinCount" in portArrangement || "bottomPinCount" in portArrangement) {
|
|
387
|
+
return {
|
|
388
|
+
left_size: portArrangement.leftPinCount,
|
|
389
|
+
right_size: portArrangement.rightPinCount,
|
|
390
|
+
top_size: portArrangement.topPinCount,
|
|
391
|
+
bottom_size: portArrangement.bottomPinCount
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
if ("leftSize" in portArrangement || "rightSize" in portArrangement || "topSize" in portArrangement || "bottomSize" in portArrangement) {
|
|
395
|
+
return {
|
|
396
|
+
left_size: portArrangement.leftSize,
|
|
397
|
+
right_size: portArrangement.rightSize,
|
|
398
|
+
top_size: portArrangement.topSize,
|
|
399
|
+
bottom_size: portArrangement.bottomSize
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
return void 0;
|
|
403
|
+
};
|
|
404
|
+
|
|
358
405
|
// lib/errors/InvalidProps.ts
|
|
359
406
|
var InvalidProps = class extends Error {
|
|
360
407
|
constructor(componentName, originalProps, formattedError) {
|
|
@@ -421,7 +468,7 @@ import {
|
|
|
421
468
|
rotate,
|
|
422
469
|
translate
|
|
423
470
|
} from "transformation-matrix";
|
|
424
|
-
import { z } from "zod";
|
|
471
|
+
import { z as z2 } from "zod";
|
|
425
472
|
var PrimitiveComponent = class extends Renderable {
|
|
426
473
|
parent = null;
|
|
427
474
|
children;
|
|
@@ -429,7 +476,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
429
476
|
get config() {
|
|
430
477
|
return {
|
|
431
478
|
componentName: "",
|
|
432
|
-
zodProps:
|
|
479
|
+
zodProps: z2.object({}).passthrough()
|
|
433
480
|
};
|
|
434
481
|
}
|
|
435
482
|
props;
|
|
@@ -841,7 +888,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
841
888
|
};
|
|
842
889
|
|
|
843
890
|
// lib/components/primitive-components/Net.ts
|
|
844
|
-
import { z as
|
|
891
|
+
import { z as z3 } from "zod";
|
|
845
892
|
|
|
846
893
|
// lib/utils/pairs.ts
|
|
847
894
|
function pairs(arr) {
|
|
@@ -854,8 +901,8 @@ function pairs(arr) {
|
|
|
854
901
|
|
|
855
902
|
// lib/components/primitive-components/Net.ts
|
|
856
903
|
import { autoroute } from "@tscircuit/infgrid-ijump-astar";
|
|
857
|
-
var netProps =
|
|
858
|
-
name:
|
|
904
|
+
var netProps = z3.object({
|
|
905
|
+
name: z3.string()
|
|
859
906
|
});
|
|
860
907
|
var Net = class extends PrimitiveComponent {
|
|
861
908
|
source_net_id;
|
|
@@ -1571,11 +1618,11 @@ function getRelativeDirection(pointA, pointB) {
|
|
|
1571
1618
|
// lib/components/primitive-components/Port.ts
|
|
1572
1619
|
import "schematic-symbols";
|
|
1573
1620
|
import { applyToPoint as applyToPoint4, compose as compose3, translate as translate3 } from "transformation-matrix";
|
|
1574
|
-
import { z as
|
|
1575
|
-
var portProps =
|
|
1576
|
-
name:
|
|
1577
|
-
pinNumber:
|
|
1578
|
-
aliases:
|
|
1621
|
+
import { z as z4 } from "zod";
|
|
1622
|
+
var portProps = z4.object({
|
|
1623
|
+
name: z4.string().optional(),
|
|
1624
|
+
pinNumber: z4.number().optional(),
|
|
1625
|
+
aliases: z4.array(z4.string()).optional()
|
|
1579
1626
|
});
|
|
1580
1627
|
var Port = class extends PrimitiveComponent {
|
|
1581
1628
|
source_port_id = null;
|
|
@@ -1821,322 +1868,105 @@ function getPortFromHints(hints) {
|
|
|
1821
1868
|
});
|
|
1822
1869
|
}
|
|
1823
1870
|
|
|
1824
|
-
// lib/
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1871
|
+
// lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts
|
|
1872
|
+
var hasExplicitPinMapping = (pa) => {
|
|
1873
|
+
for (const side of [
|
|
1874
|
+
"leftSide",
|
|
1875
|
+
"rightSide",
|
|
1876
|
+
"topSide",
|
|
1877
|
+
"bottomSide"
|
|
1878
|
+
]) {
|
|
1879
|
+
if (side in pa && typeof pa[side] === "number") {
|
|
1880
|
+
throw new Error(
|
|
1881
|
+
`A number was specified for "${side}", you probably meant to use "size" not "side"`
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
return "leftSide" in pa || "rightSide" in pa || "topSide" in pa || "bottomSide" in pa;
|
|
1886
|
+
};
|
|
1887
|
+
var getSizeOfSidesFromPortArrangement = (pa) => {
|
|
1888
|
+
if (hasExplicitPinMapping(pa)) {
|
|
1839
1889
|
return {
|
|
1840
|
-
|
|
1841
|
-
|
|
1890
|
+
leftSize: pa.leftSide?.pins.length ?? 0,
|
|
1891
|
+
rightSize: pa.rightSide?.pins.length ?? 0,
|
|
1892
|
+
topSize: pa.topSide?.pins.length ?? 0,
|
|
1893
|
+
bottomSize: pa.bottomSide?.pins.length ?? 0
|
|
1842
1894
|
};
|
|
1843
1895
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1896
|
+
const { leftSize = 0, rightSize = 0, topSize = 0, bottomSize = 0 } = pa;
|
|
1897
|
+
return { leftSize, rightSize, topSize, bottomSize };
|
|
1898
|
+
};
|
|
1899
|
+
|
|
1900
|
+
// lib/utils/schematic/getAllDimensionsForSchematicBox.ts
|
|
1901
|
+
function isExplicitPinMappingArrangement(arrangement) {
|
|
1902
|
+
return arrangement.leftSide !== void 0;
|
|
1903
|
+
}
|
|
1904
|
+
var getAllDimensionsForSchematicBox = (params) => {
|
|
1905
|
+
const portDistanceFromEdge = params.portDistanceFromEdge ?? 0.4;
|
|
1906
|
+
let sidePinCounts = params.schPortArrangement ? getSizeOfSidesFromPortArrangement(params.schPortArrangement) : null;
|
|
1907
|
+
const sideLengths = {
|
|
1908
|
+
left: 0,
|
|
1909
|
+
right: 0,
|
|
1910
|
+
top: 0,
|
|
1911
|
+
bottom: 0
|
|
1912
|
+
};
|
|
1913
|
+
let pinCount = params.pinCount ?? null;
|
|
1914
|
+
if (pinCount === null) {
|
|
1915
|
+
if (sidePinCounts) {
|
|
1916
|
+
pinCount = sidePinCounts.leftSize + sidePinCounts.rightSize + sidePinCounts.topSize;
|
|
1917
|
+
} else {
|
|
1918
|
+
throw new Error("Could not determine pin count for the schematic box");
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
if (pinCount && !sidePinCounts) {
|
|
1922
|
+
const rightSize = Math.floor(pinCount / 2);
|
|
1923
|
+
sidePinCounts = {
|
|
1924
|
+
leftSize: pinCount - rightSize,
|
|
1925
|
+
rightSize,
|
|
1926
|
+
topSize: 0,
|
|
1927
|
+
bottomSize: 0
|
|
1865
1928
|
};
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1929
|
+
}
|
|
1930
|
+
if (!sidePinCounts) {
|
|
1931
|
+
sidePinCounts = {
|
|
1932
|
+
leftSize: 0,
|
|
1933
|
+
rightSize: 0,
|
|
1934
|
+
topSize: 0,
|
|
1935
|
+
bottomSize: 0
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
const orderedTruePorts = [];
|
|
1939
|
+
let currentDistanceFromEdge = 0;
|
|
1940
|
+
let truePinIndex = 0;
|
|
1941
|
+
for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) {
|
|
1942
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement?.leftSide?.pins[sideIndex] : truePinIndex + 1;
|
|
1943
|
+
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
1944
|
+
if (pinStyle?.topMargin) {
|
|
1945
|
+
currentDistanceFromEdge += pinStyle.topMargin;
|
|
1879
1946
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1947
|
+
orderedTruePorts.push({
|
|
1948
|
+
trueIndex: truePinIndex,
|
|
1949
|
+
pinNumber,
|
|
1950
|
+
side: "left",
|
|
1951
|
+
distanceFromOrthogonalEdge: currentDistanceFromEdge
|
|
1952
|
+
});
|
|
1953
|
+
if (pinStyle?.bottomMargin) {
|
|
1954
|
+
currentDistanceFromEdge += pinStyle.bottomMargin;
|
|
1882
1955
|
}
|
|
1883
|
-
const
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
solver.addEditVariable(kVars[name], kiwi.Strength.weak);
|
|
1889
|
-
}
|
|
1890
|
-
return kVars[name];
|
|
1956
|
+
const isLastPinOnSide = sideIndex === sidePinCounts.leftSize - 1;
|
|
1957
|
+
if (!isLastPinOnSide) {
|
|
1958
|
+
currentDistanceFromEdge += params.schPinSpacing;
|
|
1959
|
+
} else {
|
|
1960
|
+
sideLengths.left = currentDistanceFromEdge;
|
|
1891
1961
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
if ("xDist" in props) {
|
|
1901
|
-
const { xDist, left, right, edgeToEdge, centerToCenter } = maybeFlipLeftRight(props);
|
|
1902
|
-
const leftVar = getKVar(`${left}_x`);
|
|
1903
|
-
const rightVar = getKVar(`${right}_x`);
|
|
1904
|
-
const leftBounds = getComponentDetails(left)?.bounds;
|
|
1905
|
-
const rightBounds = getComponentDetails(right)?.bounds;
|
|
1906
|
-
if (centerToCenter) {
|
|
1907
|
-
const expr = new kiwi.Expression(rightVar, [-1, leftVar]);
|
|
1908
|
-
solver.addConstraint(
|
|
1909
|
-
new kiwi.Constraint(
|
|
1910
|
-
expr,
|
|
1911
|
-
kiwi.Operator.Eq,
|
|
1912
|
-
props.xDist,
|
|
1913
|
-
kiwi.Strength.required
|
|
1914
|
-
)
|
|
1915
|
-
);
|
|
1916
|
-
} else if (edgeToEdge) {
|
|
1917
|
-
const expr = new kiwi.Expression(
|
|
1918
|
-
rightVar,
|
|
1919
|
-
-rightBounds.width / 2,
|
|
1920
|
-
[-1, leftVar],
|
|
1921
|
-
-leftBounds.width / 2
|
|
1922
|
-
);
|
|
1923
|
-
solver.addConstraint(
|
|
1924
|
-
new kiwi.Constraint(
|
|
1925
|
-
expr,
|
|
1926
|
-
kiwi.Operator.Eq,
|
|
1927
|
-
props.xDist,
|
|
1928
|
-
kiwi.Strength.required
|
|
1929
|
-
)
|
|
1930
|
-
);
|
|
1931
|
-
}
|
|
1932
|
-
} else if ("yDist" in props) {
|
|
1933
|
-
const { yDist, top, bottom, edgeToEdge, centerToCenter } = props;
|
|
1934
|
-
const topVar = getKVar(`${top}_y`);
|
|
1935
|
-
const bottomVar = getKVar(`${bottom}_y`);
|
|
1936
|
-
const topBounds = getComponentDetails(top)?.bounds;
|
|
1937
|
-
const bottomBounds = getComponentDetails(bottom)?.bounds;
|
|
1938
|
-
if (centerToCenter) {
|
|
1939
|
-
const expr = new kiwi.Expression(topVar, [-1, bottomVar]);
|
|
1940
|
-
solver.addConstraint(
|
|
1941
|
-
new kiwi.Constraint(
|
|
1942
|
-
expr,
|
|
1943
|
-
kiwi.Operator.Eq,
|
|
1944
|
-
props.yDist,
|
|
1945
|
-
kiwi.Strength.required
|
|
1946
|
-
)
|
|
1947
|
-
);
|
|
1948
|
-
} else if (edgeToEdge) {
|
|
1949
|
-
const expr = new kiwi.Expression(
|
|
1950
|
-
topVar,
|
|
1951
|
-
topBounds.height / 2,
|
|
1952
|
-
[-1, bottomVar],
|
|
1953
|
-
-bottomBounds.height / 2
|
|
1954
|
-
);
|
|
1955
|
-
solver.addConstraint(
|
|
1956
|
-
new kiwi.Constraint(
|
|
1957
|
-
expr,
|
|
1958
|
-
kiwi.Operator.Eq,
|
|
1959
|
-
props.yDist,
|
|
1960
|
-
kiwi.Strength.required
|
|
1961
|
-
)
|
|
1962
|
-
);
|
|
1963
|
-
}
|
|
1964
|
-
} else if ("sameY" in props) {
|
|
1965
|
-
const { for: selectors } = props;
|
|
1966
|
-
if (selectors.length < 2) continue;
|
|
1967
|
-
const vars = selectors.map((selector) => getKVar(`${selector}_y`));
|
|
1968
|
-
const expr = new kiwi.Expression(...vars.slice(1));
|
|
1969
|
-
solver.addConstraint(
|
|
1970
|
-
new kiwi.Constraint(
|
|
1971
|
-
expr,
|
|
1972
|
-
kiwi.Operator.Eq,
|
|
1973
|
-
vars[0],
|
|
1974
|
-
kiwi.Strength.required
|
|
1975
|
-
)
|
|
1976
|
-
);
|
|
1977
|
-
} else if ("sameX" in props) {
|
|
1978
|
-
const { for: selectors } = props;
|
|
1979
|
-
if (selectors.length < 2) continue;
|
|
1980
|
-
const vars = selectors.map((selector) => getKVar(`${selector}_x`));
|
|
1981
|
-
const expr = new kiwi.Expression(...vars.slice(1));
|
|
1982
|
-
solver.addConstraint(
|
|
1983
|
-
new kiwi.Constraint(
|
|
1984
|
-
expr,
|
|
1985
|
-
kiwi.Operator.Eq,
|
|
1986
|
-
vars[0],
|
|
1987
|
-
kiwi.Strength.required
|
|
1988
|
-
)
|
|
1989
|
-
);
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
solver.updateVariables();
|
|
1993
|
-
if (debug.enabled) {
|
|
1994
|
-
console.log("Solution to layout constraints:");
|
|
1995
|
-
console.table(
|
|
1996
|
-
Object.entries(kVars).map(([key, kvar]) => ({
|
|
1997
|
-
var: key,
|
|
1998
|
-
val: kvar.value()
|
|
1999
|
-
}))
|
|
2000
|
-
);
|
|
2001
|
-
}
|
|
2002
|
-
const bounds = {
|
|
2003
|
-
left: Infinity,
|
|
2004
|
-
right: -Infinity,
|
|
2005
|
-
top: -Infinity,
|
|
2006
|
-
bottom: Infinity
|
|
2007
|
-
};
|
|
2008
|
-
for (const {
|
|
2009
|
-
selector,
|
|
2010
|
-
bounds: { width, height }
|
|
2011
|
-
} of involvedComponents) {
|
|
2012
|
-
const kvx = getKVar(`${selector}_x`);
|
|
2013
|
-
const kvy = getKVar(`${selector}_y`);
|
|
2014
|
-
const newLeft = kvx.value() - width / 2;
|
|
2015
|
-
const newRight = kvx.value() + width / 2;
|
|
2016
|
-
const newTop = kvy.value() + height / 2;
|
|
2017
|
-
const newBottom = kvy.value() - height / 2;
|
|
2018
|
-
bounds.left = Math.min(bounds.left, newLeft);
|
|
2019
|
-
bounds.right = Math.max(bounds.right, newRight);
|
|
2020
|
-
bounds.top = Math.max(bounds.top, newTop);
|
|
2021
|
-
bounds.bottom = Math.min(bounds.bottom, newBottom);
|
|
2022
|
-
}
|
|
2023
|
-
const globalOffset = {
|
|
2024
|
-
x: -(bounds.right + bounds.left) / 2,
|
|
2025
|
-
y: -(bounds.top + bounds.bottom) / 2
|
|
2026
|
-
};
|
|
2027
|
-
const containerPos = this.getPrimitiveContainer()._getGlobalPcbPositionBeforeLayout();
|
|
2028
|
-
globalOffset.x += containerPos.x;
|
|
2029
|
-
globalOffset.y += containerPos.y;
|
|
2030
|
-
for (const { component, selector } of involvedComponents) {
|
|
2031
|
-
const kvx = getKVar(`${selector}_x`);
|
|
2032
|
-
const kvy = getKVar(`${selector}_y`);
|
|
2033
|
-
component._setPositionFromLayout({
|
|
2034
|
-
x: kvx.value() + globalOffset.x,
|
|
2035
|
-
y: kvy.value() + globalOffset.y
|
|
2036
|
-
});
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
};
|
|
2040
|
-
|
|
2041
|
-
// lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts
|
|
2042
|
-
var hasExplicitPinMapping = (pa) => {
|
|
2043
|
-
for (const side of [
|
|
2044
|
-
"leftSide",
|
|
2045
|
-
"rightSide",
|
|
2046
|
-
"topSide",
|
|
2047
|
-
"bottomSide"
|
|
2048
|
-
]) {
|
|
2049
|
-
if (side in pa && typeof pa[side] === "number") {
|
|
2050
|
-
throw new Error(
|
|
2051
|
-
`A number was specified for "${side}", you probably meant to use "size" not "side"`
|
|
2052
|
-
);
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
return "leftSide" in pa || "rightSide" in pa || "topSide" in pa || "bottomSide" in pa;
|
|
2056
|
-
};
|
|
2057
|
-
var getSizeOfSidesFromPortArrangement = (pa) => {
|
|
2058
|
-
if (hasExplicitPinMapping(pa)) {
|
|
2059
|
-
return {
|
|
2060
|
-
leftSize: pa.leftSide?.pins.length ?? 0,
|
|
2061
|
-
rightSize: pa.rightSide?.pins.length ?? 0,
|
|
2062
|
-
topSize: pa.topSide?.pins.length ?? 0,
|
|
2063
|
-
bottomSize: pa.bottomSide?.pins.length ?? 0
|
|
2064
|
-
};
|
|
2065
|
-
}
|
|
2066
|
-
const { leftSize = 0, rightSize = 0, topSize = 0, bottomSize = 0 } = pa;
|
|
2067
|
-
return { leftSize, rightSize, topSize, bottomSize };
|
|
2068
|
-
};
|
|
2069
|
-
|
|
2070
|
-
// lib/utils/schematic/getAllDimensionsForSchematicBox.ts
|
|
2071
|
-
function isExplicitPinMappingArrangement(arrangement) {
|
|
2072
|
-
return arrangement.leftSide !== void 0;
|
|
2073
|
-
}
|
|
2074
|
-
var getAllDimensionsForSchematicBox = (params) => {
|
|
2075
|
-
const portDistanceFromEdge = params.portDistanceFromEdge ?? 0.4;
|
|
2076
|
-
let sidePinCounts = params.schPortArrangement ? getSizeOfSidesFromPortArrangement(params.schPortArrangement) : null;
|
|
2077
|
-
const sideLengths = {
|
|
2078
|
-
left: 0,
|
|
2079
|
-
right: 0,
|
|
2080
|
-
top: 0,
|
|
2081
|
-
bottom: 0
|
|
2082
|
-
};
|
|
2083
|
-
let pinCount = params.pinCount ?? null;
|
|
2084
|
-
if (pinCount === null) {
|
|
2085
|
-
if (sidePinCounts) {
|
|
2086
|
-
pinCount = sidePinCounts.leftSize + sidePinCounts.rightSize + sidePinCounts.topSize;
|
|
2087
|
-
} else {
|
|
2088
|
-
throw new Error("Could not determine pin count for the schematic box");
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
if (pinCount && !sidePinCounts) {
|
|
2092
|
-
const rightSize = Math.floor(pinCount / 2);
|
|
2093
|
-
sidePinCounts = {
|
|
2094
|
-
leftSize: pinCount - rightSize,
|
|
2095
|
-
rightSize,
|
|
2096
|
-
topSize: 0,
|
|
2097
|
-
bottomSize: 0
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2100
|
-
if (!sidePinCounts) {
|
|
2101
|
-
sidePinCounts = {
|
|
2102
|
-
leftSize: 0,
|
|
2103
|
-
rightSize: 0,
|
|
2104
|
-
topSize: 0,
|
|
2105
|
-
bottomSize: 0
|
|
2106
|
-
};
|
|
2107
|
-
}
|
|
2108
|
-
const orderedTruePorts = [];
|
|
2109
|
-
let currentDistanceFromEdge = 0;
|
|
2110
|
-
let truePinIndex = 0;
|
|
2111
|
-
for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) {
|
|
2112
|
-
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement?.leftSide?.pins[sideIndex] : truePinIndex + 1;
|
|
2113
|
-
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
2114
|
-
if (pinStyle?.topMargin) {
|
|
2115
|
-
currentDistanceFromEdge += pinStyle.topMargin;
|
|
2116
|
-
}
|
|
2117
|
-
orderedTruePorts.push({
|
|
2118
|
-
trueIndex: truePinIndex,
|
|
2119
|
-
pinNumber,
|
|
2120
|
-
side: "left",
|
|
2121
|
-
distanceFromOrthogonalEdge: currentDistanceFromEdge
|
|
2122
|
-
});
|
|
2123
|
-
if (pinStyle?.bottomMargin) {
|
|
2124
|
-
currentDistanceFromEdge += pinStyle.bottomMargin;
|
|
2125
|
-
}
|
|
2126
|
-
const isLastPinOnSide = sideIndex === sidePinCounts.leftSize - 1;
|
|
2127
|
-
if (!isLastPinOnSide) {
|
|
2128
|
-
currentDistanceFromEdge += params.schPinSpacing;
|
|
2129
|
-
} else {
|
|
2130
|
-
sideLengths.left = currentDistanceFromEdge;
|
|
2131
|
-
}
|
|
2132
|
-
truePinIndex++;
|
|
2133
|
-
}
|
|
2134
|
-
currentDistanceFromEdge = 0;
|
|
2135
|
-
for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) {
|
|
2136
|
-
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.bottomSide?.pins[sideIndex] : truePinIndex + 1;
|
|
2137
|
-
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
2138
|
-
if (pinStyle?.leftMargin) {
|
|
2139
|
-
currentDistanceFromEdge += pinStyle.leftMargin;
|
|
1962
|
+
truePinIndex++;
|
|
1963
|
+
}
|
|
1964
|
+
currentDistanceFromEdge = 0;
|
|
1965
|
+
for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) {
|
|
1966
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.bottomSide?.pins[sideIndex] : truePinIndex + 1;
|
|
1967
|
+
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
1968
|
+
if (pinStyle?.leftMargin) {
|
|
1969
|
+
currentDistanceFromEdge += pinStyle.leftMargin;
|
|
2140
1970
|
}
|
|
2141
1971
|
orderedTruePorts.push({
|
|
2142
1972
|
trueIndex: truePinIndex,
|
|
@@ -2272,51 +2102,221 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
2272
2102
|
};
|
|
2273
2103
|
};
|
|
2274
2104
|
|
|
2275
|
-
// lib/
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2105
|
+
// lib/components/base-components/NormalComponent.ts
|
|
2106
|
+
import {
|
|
2107
|
+
isValidElement as isReactElement,
|
|
2108
|
+
isValidElement
|
|
2109
|
+
} from "react";
|
|
2110
|
+
import { symbols as symbols2 } from "schematic-symbols";
|
|
2111
|
+
import { z as z5 } from "zod";
|
|
2112
|
+
|
|
2113
|
+
// lib/components/primitive-components/Footprint.ts
|
|
2114
|
+
import { footprintProps } from "@tscircuit/props";
|
|
2115
|
+
import * as kiwi from "@lume/kiwi";
|
|
2116
|
+
import Debug from "debug";
|
|
2117
|
+
var debug = Debug("tscircuit:core:footprint");
|
|
2118
|
+
var Footprint = class extends PrimitiveComponent {
|
|
2119
|
+
get config() {
|
|
2279
2120
|
return {
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
top_side: portArrangement.topSide,
|
|
2283
|
-
bottom_side: portArrangement.bottomSide
|
|
2121
|
+
componentName: "Footprint",
|
|
2122
|
+
zodProps: footprintProps
|
|
2284
2123
|
};
|
|
2285
2124
|
}
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2125
|
+
/**
|
|
2126
|
+
* A footprint is a constrainedlayout, the db elements are adjusted according
|
|
2127
|
+
* to any constraints that are defined.
|
|
2128
|
+
*/
|
|
2129
|
+
doInitialPcbFootprintLayout() {
|
|
2130
|
+
const constraints = this.children.filter(
|
|
2131
|
+
(child) => child.componentName === "Constraint"
|
|
2132
|
+
);
|
|
2133
|
+
if (constraints.length === 0) return;
|
|
2134
|
+
const { isFlipped } = this._getPcbPrimitiveFlippedHelpers();
|
|
2135
|
+
const maybeFlipLeftRight = (props) => {
|
|
2136
|
+
if (isFlipped) {
|
|
2137
|
+
if ("left" in props && "right" in props) {
|
|
2138
|
+
return {
|
|
2139
|
+
...props,
|
|
2140
|
+
left: props.right,
|
|
2141
|
+
right: props.left
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
return props;
|
|
2292
2146
|
};
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2147
|
+
const involvedComponents = constraints.flatMap(
|
|
2148
|
+
(constraint) => constraint._getAllReferencedComponents().componentsWithSelectors
|
|
2149
|
+
).map(({ component, selector, componentSelector, edge }) => ({
|
|
2150
|
+
component,
|
|
2151
|
+
selector,
|
|
2152
|
+
componentSelector,
|
|
2153
|
+
edge,
|
|
2154
|
+
bounds: component._getPcbCircuitJsonBounds()
|
|
2155
|
+
}));
|
|
2156
|
+
if (involvedComponents.some((c) => c.edge)) {
|
|
2157
|
+
throw new Error(
|
|
2158
|
+
"edge constraints not implemented yet for footprint layout, contributions welcome!"
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
function getComponentDetails(selector) {
|
|
2162
|
+
return involvedComponents.find(({ selector: s }) => s === selector);
|
|
2163
|
+
}
|
|
2164
|
+
const solver = new kiwi.Solver();
|
|
2165
|
+
const kVars = {};
|
|
2166
|
+
function getKVar(name) {
|
|
2167
|
+
if (!(name in kVars)) {
|
|
2168
|
+
kVars[name] = new kiwi.Variable(name);
|
|
2169
|
+
solver.addEditVariable(kVars[name], kiwi.Strength.weak);
|
|
2170
|
+
}
|
|
2171
|
+
return kVars[name];
|
|
2172
|
+
}
|
|
2173
|
+
for (const { selector, bounds: bounds2 } of involvedComponents) {
|
|
2174
|
+
const kvx = getKVar(`${selector}_x`);
|
|
2175
|
+
const kvy = getKVar(`${selector}_y`);
|
|
2176
|
+
solver.suggestValue(kvx, bounds2.center.x);
|
|
2177
|
+
solver.suggestValue(kvy, bounds2.center.y);
|
|
2178
|
+
}
|
|
2179
|
+
for (const constraint of constraints) {
|
|
2180
|
+
const props = constraint._parsedProps;
|
|
2181
|
+
if ("xDist" in props) {
|
|
2182
|
+
const { xDist, left, right, edgeToEdge, centerToCenter } = maybeFlipLeftRight(props);
|
|
2183
|
+
const leftVar = getKVar(`${left}_x`);
|
|
2184
|
+
const rightVar = getKVar(`${right}_x`);
|
|
2185
|
+
const leftBounds = getComponentDetails(left)?.bounds;
|
|
2186
|
+
const rightBounds = getComponentDetails(right)?.bounds;
|
|
2187
|
+
if (centerToCenter) {
|
|
2188
|
+
const expr = new kiwi.Expression(rightVar, [-1, leftVar]);
|
|
2189
|
+
solver.addConstraint(
|
|
2190
|
+
new kiwi.Constraint(
|
|
2191
|
+
expr,
|
|
2192
|
+
kiwi.Operator.Eq,
|
|
2193
|
+
props.xDist,
|
|
2194
|
+
kiwi.Strength.required
|
|
2195
|
+
)
|
|
2196
|
+
);
|
|
2197
|
+
} else if (edgeToEdge) {
|
|
2198
|
+
const expr = new kiwi.Expression(
|
|
2199
|
+
rightVar,
|
|
2200
|
+
-rightBounds.width / 2,
|
|
2201
|
+
[-1, leftVar],
|
|
2202
|
+
-leftBounds.width / 2
|
|
2203
|
+
);
|
|
2204
|
+
solver.addConstraint(
|
|
2205
|
+
new kiwi.Constraint(
|
|
2206
|
+
expr,
|
|
2207
|
+
kiwi.Operator.Eq,
|
|
2208
|
+
props.xDist,
|
|
2209
|
+
kiwi.Strength.required
|
|
2210
|
+
)
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
} else if ("yDist" in props) {
|
|
2214
|
+
const { yDist, top, bottom, edgeToEdge, centerToCenter } = props;
|
|
2215
|
+
const topVar = getKVar(`${top}_y`);
|
|
2216
|
+
const bottomVar = getKVar(`${bottom}_y`);
|
|
2217
|
+
const topBounds = getComponentDetails(top)?.bounds;
|
|
2218
|
+
const bottomBounds = getComponentDetails(bottom)?.bounds;
|
|
2219
|
+
if (centerToCenter) {
|
|
2220
|
+
const expr = new kiwi.Expression(topVar, [-1, bottomVar]);
|
|
2221
|
+
solver.addConstraint(
|
|
2222
|
+
new kiwi.Constraint(
|
|
2223
|
+
expr,
|
|
2224
|
+
kiwi.Operator.Eq,
|
|
2225
|
+
props.yDist,
|
|
2226
|
+
kiwi.Strength.required
|
|
2227
|
+
)
|
|
2228
|
+
);
|
|
2229
|
+
} else if (edgeToEdge) {
|
|
2230
|
+
const expr = new kiwi.Expression(
|
|
2231
|
+
topVar,
|
|
2232
|
+
topBounds.height / 2,
|
|
2233
|
+
[-1, bottomVar],
|
|
2234
|
+
-bottomBounds.height / 2
|
|
2235
|
+
);
|
|
2236
|
+
solver.addConstraint(
|
|
2237
|
+
new kiwi.Constraint(
|
|
2238
|
+
expr,
|
|
2239
|
+
kiwi.Operator.Eq,
|
|
2240
|
+
props.yDist,
|
|
2241
|
+
kiwi.Strength.required
|
|
2242
|
+
)
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
} else if ("sameY" in props) {
|
|
2246
|
+
const { for: selectors } = props;
|
|
2247
|
+
if (selectors.length < 2) continue;
|
|
2248
|
+
const vars = selectors.map((selector) => getKVar(`${selector}_y`));
|
|
2249
|
+
const expr = new kiwi.Expression(...vars.slice(1));
|
|
2250
|
+
solver.addConstraint(
|
|
2251
|
+
new kiwi.Constraint(
|
|
2252
|
+
expr,
|
|
2253
|
+
kiwi.Operator.Eq,
|
|
2254
|
+
vars[0],
|
|
2255
|
+
kiwi.Strength.required
|
|
2256
|
+
)
|
|
2257
|
+
);
|
|
2258
|
+
} else if ("sameX" in props) {
|
|
2259
|
+
const { for: selectors } = props;
|
|
2260
|
+
if (selectors.length < 2) continue;
|
|
2261
|
+
const vars = selectors.map((selector) => getKVar(`${selector}_x`));
|
|
2262
|
+
const expr = new kiwi.Expression(...vars.slice(1));
|
|
2263
|
+
solver.addConstraint(
|
|
2264
|
+
new kiwi.Constraint(
|
|
2265
|
+
expr,
|
|
2266
|
+
kiwi.Operator.Eq,
|
|
2267
|
+
vars[0],
|
|
2268
|
+
kiwi.Strength.required
|
|
2269
|
+
)
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
solver.updateVariables();
|
|
2274
|
+
if (debug.enabled) {
|
|
2275
|
+
console.log("Solution to layout constraints:");
|
|
2276
|
+
console.table(
|
|
2277
|
+
Object.entries(kVars).map(([key, kvar]) => ({
|
|
2278
|
+
var: key,
|
|
2279
|
+
val: kvar.value()
|
|
2280
|
+
}))
|
|
2281
|
+
);
|
|
2282
|
+
}
|
|
2283
|
+
const bounds = {
|
|
2284
|
+
left: Infinity,
|
|
2285
|
+
right: -Infinity,
|
|
2286
|
+
top: -Infinity,
|
|
2287
|
+
bottom: Infinity
|
|
2300
2288
|
};
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2289
|
+
for (const {
|
|
2290
|
+
selector,
|
|
2291
|
+
bounds: { width, height }
|
|
2292
|
+
} of involvedComponents) {
|
|
2293
|
+
const kvx = getKVar(`${selector}_x`);
|
|
2294
|
+
const kvy = getKVar(`${selector}_y`);
|
|
2295
|
+
const newLeft = kvx.value() - width / 2;
|
|
2296
|
+
const newRight = kvx.value() + width / 2;
|
|
2297
|
+
const newTop = kvy.value() + height / 2;
|
|
2298
|
+
const newBottom = kvy.value() - height / 2;
|
|
2299
|
+
bounds.left = Math.min(bounds.left, newLeft);
|
|
2300
|
+
bounds.right = Math.max(bounds.right, newRight);
|
|
2301
|
+
bounds.top = Math.max(bounds.top, newTop);
|
|
2302
|
+
bounds.bottom = Math.min(bounds.bottom, newBottom);
|
|
2303
|
+
}
|
|
2304
|
+
const globalOffset = {
|
|
2305
|
+
x: -(bounds.right + bounds.left) / 2,
|
|
2306
|
+
y: -(bounds.top + bounds.bottom) / 2
|
|
2317
2307
|
};
|
|
2308
|
+
const containerPos = this.getPrimitiveContainer()._getGlobalPcbPositionBeforeLayout();
|
|
2309
|
+
globalOffset.x += containerPos.x;
|
|
2310
|
+
globalOffset.y += containerPos.y;
|
|
2311
|
+
for (const { component, selector } of involvedComponents) {
|
|
2312
|
+
const kvx = getKVar(`${selector}_x`);
|
|
2313
|
+
const kvy = getKVar(`${selector}_y`);
|
|
2314
|
+
component._setPositionFromLayout({
|
|
2315
|
+
x: kvx.value() + globalOffset.x,
|
|
2316
|
+
y: kvy.value() + globalOffset.y
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2318
2319
|
}
|
|
2319
|
-
return underscorePinStyles;
|
|
2320
2320
|
};
|
|
2321
2321
|
|
|
2322
2322
|
// lib/components/base-components/NormalComponent.ts
|
|
@@ -2430,10 +2430,14 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
2430
2430
|
this.addAll(portsToCreate);
|
|
2431
2431
|
return;
|
|
2432
2432
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
portsToCreate.
|
|
2433
|
+
if (!this._parsedProps.schPortArrangement) {
|
|
2434
|
+
const portsFromFootprint = this.getPortsFromFootprint();
|
|
2435
|
+
for (const port of portsFromFootprint) {
|
|
2436
|
+
if (!portsToCreate.some(
|
|
2437
|
+
(p) => p.isMatchingAnyOf(port.getNameAndAliases())
|
|
2438
|
+
)) {
|
|
2439
|
+
portsToCreate.push(port);
|
|
2440
|
+
}
|
|
2437
2441
|
}
|
|
2438
2442
|
}
|
|
2439
2443
|
if (portsToCreate.length > 0) {
|
|
@@ -2723,10 +2727,14 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
2723
2727
|
*
|
|
2724
2728
|
*/
|
|
2725
2729
|
doInitialPortDiscovery() {
|
|
2726
|
-
const
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
+
const { _parsedProps: props } = this;
|
|
2731
|
+
let newPorts = [];
|
|
2732
|
+
if (!props.schPortArrangement) {
|
|
2733
|
+
newPorts = [
|
|
2734
|
+
...this.getPortsFromFootprint(),
|
|
2735
|
+
...this.getPortsFromSchematicSymbol()
|
|
2736
|
+
];
|
|
2737
|
+
}
|
|
2730
2738
|
const existingPorts = this.children.filter(
|
|
2731
2739
|
(c) => c.componentName === "Port"
|
|
2732
2740
|
);
|
|
@@ -2762,9 +2770,10 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
2762
2770
|
}
|
|
2763
2771
|
_getPinCount() {
|
|
2764
2772
|
const schPortArrangement = this._getSchematicPortArrangement();
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2773
|
+
if (schPortArrangement) {
|
|
2774
|
+
return (schPortArrangement.leftSize ?? 0) + (schPortArrangement.rightSize ?? 0) + (schPortArrangement.topSize ?? 0) + (schPortArrangement.bottomSize ?? 0);
|
|
2775
|
+
}
|
|
2776
|
+
return this.getPortsFromFootprint().length;
|
|
2768
2777
|
}
|
|
2769
2778
|
/**
|
|
2770
2779
|
* Override the schematic port arrangement if you want to customize where pins
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.150",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@tscircuit/soup-util": "^0.0.33",
|
|
46
46
|
"circuit-json": "^0.0.93",
|
|
47
47
|
"circuit-json-to-connectivity-map": "^0.0.17",
|
|
48
|
-
"circuit-to-svg": "^0.0.
|
|
48
|
+
"circuit-to-svg": "^0.0.59",
|
|
49
49
|
"nanoid": "^5.0.7",
|
|
50
50
|
"performance-now": "^2.1.0",
|
|
51
51
|
"react": "^18.3.1",
|