@tscircuit/core 0.0.148 → 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 +341 -276
- 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,223 +1868,6 @@ function getPortFromHints(hints) {
|
|
|
1821
1868
|
});
|
|
1822
1869
|
}
|
|
1823
1870
|
|
|
1824
|
-
// lib/components/base-components/NormalComponent.ts
|
|
1825
|
-
import {
|
|
1826
|
-
isValidElement as isReactElement,
|
|
1827
|
-
isValidElement
|
|
1828
|
-
} from "react";
|
|
1829
|
-
import { symbols as symbols2 } from "schematic-symbols";
|
|
1830
|
-
import { z as z5 } from "zod";
|
|
1831
|
-
|
|
1832
|
-
// lib/components/primitive-components/Footprint.ts
|
|
1833
|
-
import { footprintProps } from "@tscircuit/props";
|
|
1834
|
-
import * as kiwi from "@lume/kiwi";
|
|
1835
|
-
import Debug from "debug";
|
|
1836
|
-
var debug = Debug("tscircuit:core:footprint");
|
|
1837
|
-
var Footprint = class extends PrimitiveComponent {
|
|
1838
|
-
get config() {
|
|
1839
|
-
return {
|
|
1840
|
-
componentName: "Footprint",
|
|
1841
|
-
zodProps: footprintProps
|
|
1842
|
-
};
|
|
1843
|
-
}
|
|
1844
|
-
/**
|
|
1845
|
-
* A footprint is a constrainedlayout, the db elements are adjusted according
|
|
1846
|
-
* to any constraints that are defined.
|
|
1847
|
-
*/
|
|
1848
|
-
doInitialPcbFootprintLayout() {
|
|
1849
|
-
const constraints = this.children.filter(
|
|
1850
|
-
(child) => child.componentName === "Constraint"
|
|
1851
|
-
);
|
|
1852
|
-
if (constraints.length === 0) return;
|
|
1853
|
-
const { isFlipped } = this._getPcbPrimitiveFlippedHelpers();
|
|
1854
|
-
const maybeFlipLeftRight = (props) => {
|
|
1855
|
-
if (isFlipped) {
|
|
1856
|
-
if ("left" in props && "right" in props) {
|
|
1857
|
-
return {
|
|
1858
|
-
...props,
|
|
1859
|
-
left: props.right,
|
|
1860
|
-
right: props.left
|
|
1861
|
-
};
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
return props;
|
|
1865
|
-
};
|
|
1866
|
-
const involvedComponents = constraints.flatMap(
|
|
1867
|
-
(constraint) => constraint._getAllReferencedComponents().componentsWithSelectors
|
|
1868
|
-
).map(({ component, selector, componentSelector, edge }) => ({
|
|
1869
|
-
component,
|
|
1870
|
-
selector,
|
|
1871
|
-
componentSelector,
|
|
1872
|
-
edge,
|
|
1873
|
-
bounds: component._getPcbCircuitJsonBounds()
|
|
1874
|
-
}));
|
|
1875
|
-
if (involvedComponents.some((c) => c.edge)) {
|
|
1876
|
-
throw new Error(
|
|
1877
|
-
"edge constraints not implemented yet for footprint layout, contributions welcome!"
|
|
1878
|
-
);
|
|
1879
|
-
}
|
|
1880
|
-
function getComponentDetails(selector) {
|
|
1881
|
-
return involvedComponents.find(({ selector: s }) => s === selector);
|
|
1882
|
-
}
|
|
1883
|
-
const solver = new kiwi.Solver();
|
|
1884
|
-
const kVars = {};
|
|
1885
|
-
function getKVar(name) {
|
|
1886
|
-
if (!(name in kVars)) {
|
|
1887
|
-
kVars[name] = new kiwi.Variable(name);
|
|
1888
|
-
solver.addEditVariable(kVars[name], kiwi.Strength.weak);
|
|
1889
|
-
}
|
|
1890
|
-
return kVars[name];
|
|
1891
|
-
}
|
|
1892
|
-
for (const { selector, bounds: bounds2 } of involvedComponents) {
|
|
1893
|
-
const kvx = getKVar(`${selector}_x`);
|
|
1894
|
-
const kvy = getKVar(`${selector}_y`);
|
|
1895
|
-
solver.suggestValue(kvx, bounds2.center.x);
|
|
1896
|
-
solver.suggestValue(kvy, bounds2.center.y);
|
|
1897
|
-
}
|
|
1898
|
-
for (const constraint of constraints) {
|
|
1899
|
-
const props = constraint._parsedProps;
|
|
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
1871
|
// lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts
|
|
2042
1872
|
var hasExplicitPinMapping = (pa) => {
|
|
2043
1873
|
for (const side of [
|
|
@@ -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
|
|
@@ -3313,6 +3322,56 @@ function tryNow(fn) {
|
|
|
3313
3322
|
|
|
3314
3323
|
// lib/components/primitive-components/Trace.ts
|
|
3315
3324
|
import "zod";
|
|
3325
|
+
|
|
3326
|
+
// lib/utils/autorouting/getDominantDirection.ts
|
|
3327
|
+
function getDominantDirection(edge) {
|
|
3328
|
+
const delta = {
|
|
3329
|
+
x: edge.to.x - edge.from.x,
|
|
3330
|
+
y: edge.to.y - edge.from.y
|
|
3331
|
+
};
|
|
3332
|
+
const absX = Math.abs(delta.x);
|
|
3333
|
+
const absY = Math.abs(delta.y);
|
|
3334
|
+
if (absX > absY) {
|
|
3335
|
+
return delta.x > 0 ? "right" : "left";
|
|
3336
|
+
}
|
|
3337
|
+
return delta.y > 0 ? "down" : "up";
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
// lib/utils/schematic/getStubEdges.ts
|
|
3341
|
+
var getStubEdges = ({
|
|
3342
|
+
lastEdge,
|
|
3343
|
+
lastEdgePort,
|
|
3344
|
+
lastDominantDirection
|
|
3345
|
+
}) => {
|
|
3346
|
+
const edges = [];
|
|
3347
|
+
if (lastEdge && lastEdgePort) {
|
|
3348
|
+
const intermediatePoint = { x: lastEdge.to.x, y: lastEdge.to.y };
|
|
3349
|
+
if (lastDominantDirection === "left" || lastDominantDirection === "right") {
|
|
3350
|
+
intermediatePoint.x = lastEdgePort.position.x;
|
|
3351
|
+
edges.push({
|
|
3352
|
+
from: lastEdge.to,
|
|
3353
|
+
to: { ...intermediatePoint }
|
|
3354
|
+
});
|
|
3355
|
+
edges.push({
|
|
3356
|
+
from: intermediatePoint,
|
|
3357
|
+
to: { ...lastEdgePort.position }
|
|
3358
|
+
});
|
|
3359
|
+
} else {
|
|
3360
|
+
intermediatePoint.y = lastEdgePort.position.y;
|
|
3361
|
+
edges.push({
|
|
3362
|
+
from: lastEdge.to,
|
|
3363
|
+
to: { ...intermediatePoint }
|
|
3364
|
+
});
|
|
3365
|
+
edges.push({
|
|
3366
|
+
from: intermediatePoint,
|
|
3367
|
+
to: { ...lastEdgePort.position }
|
|
3368
|
+
});
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
return edges;
|
|
3372
|
+
};
|
|
3373
|
+
|
|
3374
|
+
// lib/components/primitive-components/Trace.ts
|
|
3316
3375
|
var portToObjective = (port) => {
|
|
3317
3376
|
const portPosition = port._getGlobalPcbPositionAfterLayout();
|
|
3318
3377
|
return {
|
|
@@ -3789,6 +3848,12 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
3789
3848
|
to: route[i + 1]
|
|
3790
3849
|
});
|
|
3791
3850
|
}
|
|
3851
|
+
const lastEdge = edges[edges.length - 1];
|
|
3852
|
+
const lastEdgePort = portsWithPosition[portsWithPosition.length - 1];
|
|
3853
|
+
const lastDominantDirection = getDominantDirection(lastEdge);
|
|
3854
|
+
edges.push(
|
|
3855
|
+
...getStubEdges({ lastEdge, lastEdgePort, lastDominantDirection })
|
|
3856
|
+
);
|
|
3792
3857
|
const trace = db.schematic_trace.insert({
|
|
3793
3858
|
source_trace_id: this.source_trace_id,
|
|
3794
3859
|
edges
|
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",
|