@tscircuit/core 0.0.33 → 0.0.35

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 CHANGED
@@ -3438,80 +3438,77 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
3438
3438
  doInitialPcbPrimitiveRender(): void;
3439
3439
  }
3440
3440
 
3441
+ declare const edgeSpecifiers: readonly ["leftedge", "rightedge", "topedge", "bottomedge", "center"];
3442
+ type EdgeSpecifier = (typeof edgeSpecifiers)[number];
3441
3443
  declare class Constraint extends PrimitiveComponent<typeof constraintProps> {
3444
+ componentName: string;
3442
3445
  get config(): {
3443
3446
  zodProps: z.ZodUnion<[z.ZodObject<{
3444
3447
  pcb: z.ZodOptional<z.ZodLiteral<true>>;
3445
- type: z.ZodOptional<z.ZodLiteral<"xdist">>;
3446
- xdist: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
3448
+ xDist: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
3447
3449
  left: z.ZodString;
3448
3450
  right: z.ZodString;
3449
3451
  edgeToEdge: z.ZodOptional<z.ZodLiteral<true>>;
3450
3452
  centerToCenter: z.ZodOptional<z.ZodLiteral<true>>;
3451
- fromLeftEdge: z.ZodOptional<z.ZodLiteral<true>>;
3452
- fromLeftCenter: z.ZodOptional<z.ZodLiteral<true>>;
3453
- toRightEdge: z.ZodOptional<z.ZodLiteral<true>>;
3454
- toRightCenter: z.ZodOptional<z.ZodLiteral<true>>;
3455
3453
  }, "strip", z.ZodTypeAny, {
3456
3454
  left: string;
3457
3455
  right: string;
3458
- xdist: number;
3459
- type?: "xdist" | undefined;
3456
+ xDist: number;
3460
3457
  pcb?: true | undefined;
3461
3458
  edgeToEdge?: true | undefined;
3462
3459
  centerToCenter?: true | undefined;
3463
- fromLeftEdge?: true | undefined;
3464
- fromLeftCenter?: true | undefined;
3465
- toRightEdge?: true | undefined;
3466
- toRightCenter?: true | undefined;
3467
3460
  }, {
3468
3461
  left: string;
3469
3462
  right: string;
3470
- xdist: string | number;
3471
- type?: "xdist" | undefined;
3463
+ xDist: string | number;
3472
3464
  pcb?: true | undefined;
3473
3465
  edgeToEdge?: true | undefined;
3474
3466
  centerToCenter?: true | undefined;
3475
- fromLeftEdge?: true | undefined;
3476
- fromLeftCenter?: true | undefined;
3477
- toRightEdge?: true | undefined;
3478
- toRightCenter?: true | undefined;
3479
3467
  }>, z.ZodObject<{
3480
3468
  pcb: z.ZodOptional<z.ZodLiteral<true>>;
3481
- type: z.ZodOptional<z.ZodLiteral<"ydist">>;
3482
- ydist: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
3469
+ yDist: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
3483
3470
  top: z.ZodString;
3484
3471
  bottom: z.ZodString;
3485
3472
  edgeToEdge: z.ZodOptional<z.ZodLiteral<true>>;
3486
3473
  centerToCenter: z.ZodOptional<z.ZodLiteral<true>>;
3487
- fromTopEdge: z.ZodOptional<z.ZodLiteral<true>>;
3488
- fromTopCenter: z.ZodOptional<z.ZodLiteral<true>>;
3489
- toBottomEdge: z.ZodOptional<z.ZodLiteral<true>>;
3490
- toBottomCenter: z.ZodOptional<z.ZodLiteral<true>>;
3491
3474
  }, "strip", z.ZodTypeAny, {
3492
3475
  top: string;
3493
3476
  bottom: string;
3494
- ydist: number;
3495
- type?: "ydist" | undefined;
3477
+ yDist: number;
3496
3478
  pcb?: true | undefined;
3497
3479
  edgeToEdge?: true | undefined;
3498
3480
  centerToCenter?: true | undefined;
3499
- fromTopEdge?: true | undefined;
3500
- fromTopCenter?: true | undefined;
3501
- toBottomEdge?: true | undefined;
3502
- toBottomCenter?: true | undefined;
3503
3481
  }, {
3504
3482
  top: string;
3505
3483
  bottom: string;
3506
- ydist: string | number;
3507
- type?: "ydist" | undefined;
3484
+ yDist: string | number;
3508
3485
  pcb?: true | undefined;
3509
3486
  edgeToEdge?: true | undefined;
3510
3487
  centerToCenter?: true | undefined;
3511
- fromTopEdge?: true | undefined;
3512
- fromTopCenter?: true | undefined;
3513
- toBottomEdge?: true | undefined;
3514
- toBottomCenter?: true | undefined;
3488
+ }>, z.ZodObject<{
3489
+ pcb: z.ZodOptional<z.ZodLiteral<true>>;
3490
+ sameY: z.ZodOptional<z.ZodLiteral<true>>;
3491
+ for: z.ZodArray<z.ZodString, "many">;
3492
+ }, "strip", z.ZodTypeAny, {
3493
+ for: string[];
3494
+ pcb?: true | undefined;
3495
+ sameY?: true | undefined;
3496
+ }, {
3497
+ for: string[];
3498
+ pcb?: true | undefined;
3499
+ sameY?: true | undefined;
3500
+ }>, z.ZodObject<{
3501
+ pcb: z.ZodOptional<z.ZodLiteral<true>>;
3502
+ sameX: z.ZodOptional<z.ZodLiteral<true>>;
3503
+ for: z.ZodArray<z.ZodString, "many">;
3504
+ }, "strip", z.ZodTypeAny, {
3505
+ for: string[];
3506
+ pcb?: true | undefined;
3507
+ sameX?: true | undefined;
3508
+ }, {
3509
+ for: string[];
3510
+ pcb?: true | undefined;
3511
+ sameX?: true | undefined;
3515
3512
  }>]>;
3516
3513
  };
3517
3514
  constructor(props: z.input<typeof constraintProps>);
@@ -3519,6 +3516,8 @@ declare class Constraint extends PrimitiveComponent<typeof constraintProps> {
3519
3516
  componentsWithSelectors: Array<{
3520
3517
  component: PrimitiveComponent<any>;
3521
3518
  selector: string;
3519
+ componentSelector: string;
3520
+ edge: EdgeSpecifier | undefined;
3522
3521
  }>;
3523
3522
  };
3524
3523
  }
package/dist/index.js CHANGED
@@ -213,8 +213,8 @@ var PrimitiveComponent = class extends Renderable {
213
213
  );
214
214
  if (!this.componentName) {
215
215
  this.componentName = this.constructor.name;
216
- this.lowercaseComponentName = this.componentName.toLowerCase();
217
216
  }
217
+ this.lowercaseComponentName = this.componentName.toLowerCase();
218
218
  }
219
219
  setProps(props) {
220
220
  const newProps = this.config.zodProps.parse({
@@ -522,11 +522,18 @@ var Footprint = class extends PrimitiveComponent {
522
522
  if (constraints.length === 0) return;
523
523
  const involvedComponents = constraints.flatMap(
524
524
  (constraint) => constraint._getAllReferencedComponents().componentsWithSelectors
525
- ).map(({ component, selector }) => ({
525
+ ).map(({ component, selector, componentSelector, edge }) => ({
526
526
  component,
527
527
  selector,
528
+ componentSelector,
529
+ edge,
528
530
  bounds: component._getCircuitJsonBounds()
529
531
  }));
532
+ if (involvedComponents.some((c) => c.edge)) {
533
+ throw new Error(
534
+ "edge constraints not implemented yet for footprint layout, contributions welcome!"
535
+ );
536
+ }
530
537
  function getComponentDetails(selector) {
531
538
  return involvedComponents.find(({ selector: s }) => s === selector);
532
539
  }
@@ -547,8 +554,8 @@ var Footprint = class extends PrimitiveComponent {
547
554
  }
548
555
  for (const constraint of constraints) {
549
556
  const props = constraint._parsedProps;
550
- if ("xdist" in props) {
551
- const { xdist, left, right, edgeToEdge, centerToCenter } = props;
557
+ if ("xDist" in props) {
558
+ const { xDist, left, right, edgeToEdge, centerToCenter } = props;
552
559
  const leftVar = getKVar(`${left}_x`);
553
560
  const rightVar = getKVar(`${right}_x`);
554
561
  const leftBounds = getComponentDetails(left)?.bounds;
@@ -559,7 +566,7 @@ var Footprint = class extends PrimitiveComponent {
559
566
  new kiwi.Constraint(
560
567
  expr,
561
568
  kiwi.Operator.Eq,
562
- props.xdist,
569
+ props.xDist,
563
570
  kiwi.Strength.required
564
571
  )
565
572
  );
@@ -574,13 +581,13 @@ var Footprint = class extends PrimitiveComponent {
574
581
  new kiwi.Constraint(
575
582
  expr,
576
583
  kiwi.Operator.Eq,
577
- props.xdist,
584
+ props.xDist,
578
585
  kiwi.Strength.required
579
586
  )
580
587
  );
581
588
  }
582
- } else if ("ydist" in props) {
583
- const { ydist, top, bottom, edgeToEdge, centerToCenter } = props;
589
+ } else if ("yDist" in props) {
590
+ const { yDist, top, bottom, edgeToEdge, centerToCenter } = props;
584
591
  const topVar = getKVar(`${top}_y`);
585
592
  const bottomVar = getKVar(`${bottom}_y`);
586
593
  const topBounds = getComponentDetails(top)?.bounds;
@@ -591,7 +598,7 @@ var Footprint = class extends PrimitiveComponent {
591
598
  new kiwi.Constraint(
592
599
  expr,
593
600
  kiwi.Operator.Eq,
594
- props.ydist,
601
+ props.yDist,
595
602
  kiwi.Strength.required
596
603
  )
597
604
  );
@@ -606,11 +613,37 @@ var Footprint = class extends PrimitiveComponent {
606
613
  new kiwi.Constraint(
607
614
  expr,
608
615
  kiwi.Operator.Eq,
609
- props.ydist,
616
+ props.yDist,
610
617
  kiwi.Strength.required
611
618
  )
612
619
  );
613
620
  }
621
+ } else if ("sameY" in props) {
622
+ const { for: selectors } = props;
623
+ if (selectors.length < 2) continue;
624
+ const vars = selectors.map((selector) => getKVar(`${selector}_y`));
625
+ const expr = new kiwi.Expression(...vars.slice(1));
626
+ solver.addConstraint(
627
+ new kiwi.Constraint(
628
+ expr,
629
+ kiwi.Operator.Eq,
630
+ vars[0],
631
+ kiwi.Strength.required
632
+ )
633
+ );
634
+ } else if ("sameX" in props) {
635
+ const { for: selectors } = props;
636
+ if (selectors.length < 2) continue;
637
+ const vars = selectors.map((selector) => getKVar(`${selector}_x`));
638
+ const expr = new kiwi.Expression(...vars.slice(1));
639
+ solver.addConstraint(
640
+ new kiwi.Constraint(
641
+ expr,
642
+ kiwi.Operator.Eq,
643
+ vars[0],
644
+ kiwi.Strength.required
645
+ )
646
+ );
614
647
  }
615
648
  }
616
649
  solver.updateVariables();
@@ -1236,7 +1269,6 @@ var PlatedHole = class extends PrimitiveComponent {
1236
1269
  doInitialPcbPrimitiveRender() {
1237
1270
  const { db } = this.root;
1238
1271
  const { _parsedProps: props } = this;
1239
- if (!props.portHints) return;
1240
1272
  const position = this._getGlobalPcbPositionBeforeLayout();
1241
1273
  if (props.shape === "circle") {
1242
1274
  const pcb_plated_hole = db.pcb_plated_hole.insert({
@@ -2942,7 +2974,15 @@ var Jumper = class extends NormalComponent {
2942
2974
  // lib/components/primitive-components/Constraint.ts
2943
2975
  import { constraintProps } from "@tscircuit/props";
2944
2976
  import "zod";
2977
+ var edgeSpecifiers = [
2978
+ "leftedge",
2979
+ "rightedge",
2980
+ "topedge",
2981
+ "bottomedge",
2982
+ "center"
2983
+ ];
2945
2984
  var Constraint2 = class extends PrimitiveComponent {
2985
+ componentName = "Constraint";
2946
2986
  get config() {
2947
2987
  return {
2948
2988
  zodProps: constraintProps
@@ -2953,23 +2993,38 @@ var Constraint2 = class extends PrimitiveComponent {
2953
2993
  if ("xdist" in props || "ydist" in props) {
2954
2994
  if (!("edgeToEdge" in props) && !("centerToCenter" in props)) {
2955
2995
  throw new Error(
2956
- "edgeToEdge, centerToCenter (or from*/to* props) must be set for xdist or ydist for <constraint />"
2996
+ `edgeToEdge, centerToCenter must be set for xDist or yDist for ${this}`
2957
2997
  );
2958
2998
  }
2959
2999
  }
3000
+ if ("for" in props && props.for.length < 2) {
3001
+ throw new Error(`"for" must have at least two selectors for ${this}`);
3002
+ }
2960
3003
  }
2961
3004
  _getAllReferencedComponents() {
2962
3005
  const componentsWithSelectors = [];
3006
+ const subcircuit = this.getSubcircuit();
3007
+ function addComponentFromSelector(selector) {
3008
+ const component = subcircuit.selectOne(selector);
3009
+ if (component) {
3010
+ const maybeEdge = selector.split(" ").pop();
3011
+ const edge = edgeSpecifiers.includes(maybeEdge) ? maybeEdge : void 0;
3012
+ componentsWithSelectors.push({
3013
+ selector,
3014
+ component,
3015
+ componentSelector: edge ? selector.replace(` ${edge}`, "") : selector,
3016
+ edge
3017
+ });
3018
+ }
3019
+ }
2963
3020
  for (const key of ["left", "right", "top", "bottom"]) {
2964
3021
  if (key in this._parsedProps) {
2965
- const selector = this._parsedProps[key];
2966
- const component = this.getSubcircuit().selectOne(selector);
2967
- if (component) {
2968
- componentsWithSelectors.push({
2969
- selector,
2970
- component
2971
- });
2972
- }
3022
+ addComponentFromSelector(this._parsedProps[key]);
3023
+ }
3024
+ }
3025
+ if ("for" in this._parsedProps) {
3026
+ for (const selector of this._parsedProps.for) {
3027
+ addComponentFromSelector(selector);
2973
3028
  }
2974
3029
  }
2975
3030
  return { componentsWithSelectors };
@@ -92,8 +92,8 @@ export abstract class PrimitiveComponent<
92
92
  ) as z.infer<ZodProps>
93
93
  if (!this.componentName) {
94
94
  this.componentName = this.constructor.name
95
- this.lowercaseComponentName = this.componentName.toLowerCase()
96
95
  }
96
+ this.lowercaseComponentName = this.componentName.toLowerCase()
97
97
  }
98
98
 
99
99
  setProps(props: Partial<z.input<ZodProps>>) {
@@ -2,7 +2,19 @@ import { constraintProps } from "@tscircuit/props"
2
2
  import { z } from "zod"
3
3
  import { PrimitiveComponent } from "../base-components/PrimitiveComponent"
4
4
 
5
+ const edgeSpecifiers = [
6
+ "leftedge",
7
+ "rightedge",
8
+ "topedge",
9
+ "bottomedge",
10
+ "center",
11
+ ] as const
12
+
13
+ export type EdgeSpecifier = (typeof edgeSpecifiers)[number]
14
+
5
15
  export class Constraint extends PrimitiveComponent<typeof constraintProps> {
16
+ componentName = "Constraint"
17
+
6
18
  get config() {
7
19
  return {
8
20
  zodProps: constraintProps,
@@ -13,34 +25,60 @@ export class Constraint extends PrimitiveComponent<typeof constraintProps> {
13
25
  super(props)
14
26
  if ("xdist" in props || "ydist" in props) {
15
27
  if (!("edgeToEdge" in props) && !("centerToCenter" in props)) {
28
+ // TODO don't throw an error if the selectors specify an edge
16
29
  throw new Error(
17
- "edgeToEdge, centerToCenter (or from*/to* props) must be set for xdist or ydist for <constraint />",
30
+ `edgeToEdge, centerToCenter must be set for xDist or yDist for ${this}`,
18
31
  )
19
32
  }
20
33
  }
34
+ if ("for" in props && props.for.length < 2) {
35
+ throw new Error(`"for" must have at least two selectors for ${this}`)
36
+ }
21
37
  }
22
38
 
23
39
  _getAllReferencedComponents(): {
24
40
  componentsWithSelectors: Array<{
25
41
  component: PrimitiveComponent<any>
26
42
  selector: string
43
+ componentSelector: string
44
+ edge: EdgeSpecifier | undefined
27
45
  }>
28
46
  } {
29
47
  const componentsWithSelectors: Array<{
30
48
  component: PrimitiveComponent<any>
31
49
  selector: string
50
+ componentSelector: string
51
+ edge: EdgeSpecifier | undefined
32
52
  }> = []
33
53
 
54
+ const subcircuit = this.getSubcircuit()
55
+
56
+ function addComponentFromSelector(selector: string) {
57
+ // TODO this selector has to be modified in case it contains a leftedge,
58
+ // center/topedge/rightedge indicator
59
+ const component = subcircuit.selectOne(selector)
60
+ if (component) {
61
+ const maybeEdge = selector.split(" ").pop() as EdgeSpecifier
62
+ const edge = edgeSpecifiers.includes(maybeEdge) ? maybeEdge : undefined
63
+
64
+ componentsWithSelectors.push({
65
+ selector,
66
+ component,
67
+ componentSelector: edge ? selector.replace(` ${edge}`, "") : selector,
68
+ edge,
69
+ })
70
+ }
71
+ }
72
+
34
73
  for (const key of ["left", "right", "top", "bottom"]) {
35
74
  if (key in this._parsedProps) {
36
- const selector = (this._parsedProps as any)[key] as string
37
- const component = this.getSubcircuit().selectOne(selector)
38
- if (component) {
39
- componentsWithSelectors.push({
40
- selector,
41
- component,
42
- })
43
- }
75
+ addComponentFromSelector((this._parsedProps as any)[key] as string)
76
+ }
77
+ }
78
+
79
+ if ("for" in this._parsedProps) {
80
+ for (const selector of this._parsedProps.for) {
81
+ addComponentFromSelector(selector)
44
82
  }
45
83
  }
46
84
 
@@ -23,12 +23,20 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
23
23
  (constraint) =>
24
24
  constraint._getAllReferencedComponents().componentsWithSelectors,
25
25
  )
26
- .map(({ component, selector }) => ({
26
+ .map(({ component, selector, componentSelector, edge }) => ({
27
27
  component,
28
28
  selector,
29
+ componentSelector,
30
+ edge,
29
31
  bounds: component._getCircuitJsonBounds(),
30
32
  }))
31
33
 
34
+ if (involvedComponents.some((c) => c.edge)) {
35
+ throw new Error(
36
+ "edge constraints not implemented yet for footprint layout, contributions welcome!",
37
+ )
38
+ }
39
+
32
40
  function getComponentDetails(selector: string) {
33
41
  return involvedComponents.find(({ selector: s }) => s === selector)
34
42
  }
@@ -56,8 +64,8 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
56
64
  for (const constraint of constraints) {
57
65
  const props = constraint._parsedProps
58
66
 
59
- if ("xdist" in props) {
60
- const { xdist, left, right, edgeToEdge, centerToCenter } = props
67
+ if ("xDist" in props) {
68
+ const { xDist, left, right, edgeToEdge, centerToCenter } = props
61
69
  const leftVar = getKVar(`${left}_x`)
62
70
  const rightVar = getKVar(`${right}_x`)
63
71
  const leftBounds = getComponentDetails(left)?.bounds!
@@ -70,7 +78,7 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
70
78
  new kiwi.Constraint(
71
79
  expr,
72
80
  kiwi.Operator.Eq,
73
- props.xdist,
81
+ props.xDist,
74
82
  kiwi.Strength.required,
75
83
  ),
76
84
  )
@@ -87,13 +95,13 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
87
95
  new kiwi.Constraint(
88
96
  expr,
89
97
  kiwi.Operator.Eq,
90
- props.xdist,
98
+ props.xDist,
91
99
  kiwi.Strength.required,
92
100
  ),
93
101
  )
94
102
  }
95
- } else if ("ydist" in props) {
96
- const { ydist, top, bottom, edgeToEdge, centerToCenter } = props
103
+ } else if ("yDist" in props) {
104
+ const { yDist, top, bottom, edgeToEdge, centerToCenter } = props
97
105
  const topVar = getKVar(`${top}_y`)
98
106
  const bottomVar = getKVar(`${bottom}_y`)
99
107
  const topBounds = getComponentDetails(top)?.bounds!
@@ -108,7 +116,7 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
108
116
  new kiwi.Constraint(
109
117
  expr,
110
118
  kiwi.Operator.Eq,
111
- props.ydist,
119
+ props.yDist,
112
120
  kiwi.Strength.required,
113
121
  ),
114
122
  )
@@ -125,11 +133,38 @@ export class Footprint extends PrimitiveComponent<typeof footprintProps> {
125
133
  new kiwi.Constraint(
126
134
  expr,
127
135
  kiwi.Operator.Eq,
128
- props.ydist,
136
+ props.yDist,
129
137
  kiwi.Strength.required,
130
138
  ),
131
139
  )
132
140
  }
141
+ } else if ("sameY" in props) {
142
+ const { for: selectors } = props
143
+ if (selectors.length < 2) continue
144
+ const vars = selectors.map((selector) => getKVar(`${selector}_y`))
145
+ const expr = new kiwi.Expression(...vars.slice(1))
146
+
147
+ solver.addConstraint(
148
+ new kiwi.Constraint(
149
+ expr,
150
+ kiwi.Operator.Eq,
151
+ vars[0],
152
+ kiwi.Strength.required,
153
+ ),
154
+ )
155
+ } else if ("sameX" in props) {
156
+ const { for: selectors } = props
157
+ if (selectors.length < 2) continue
158
+ const vars = selectors.map((selector) => getKVar(`${selector}_x`))
159
+ const expr = new kiwi.Expression(...vars.slice(1))
160
+ solver.addConstraint(
161
+ new kiwi.Constraint(
162
+ expr,
163
+ kiwi.Operator.Eq,
164
+ vars[0],
165
+ kiwi.Strength.required,
166
+ ),
167
+ )
133
168
  }
134
169
  }
135
170
 
@@ -79,7 +79,6 @@ export class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
79
79
  doInitialPcbPrimitiveRender(): void {
80
80
  const { db } = this.root!
81
81
  const { _parsedProps: props } = this
82
- if (!props.portHints) return
83
82
  const position = this._getGlobalPcbPositionBeforeLayout()
84
83
  if (props.shape === "circle") {
85
84
  const pcb_plated_hole = db.pcb_plated_hole.insert({
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tscircuit/core",
3
3
  "module": "index.ts",
4
4
  "type": "module",
5
- "version": "0.0.33",
5
+ "version": "0.0.35",
6
6
  "types": "dist/index.d.ts",
7
7
  "main": "dist/index.js",
8
8
  "files": [
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@lume/kiwi": "^0.4.3",
37
37
  "@tscircuit/infgrid-ijump-astar": "^0.0.6",
38
- "@tscircuit/props": "^0.0.61",
38
+ "@tscircuit/props": "^0.0.62",
39
39
  "@tscircuit/soup": "^0.0.66",
40
40
  "@tscircuit/soup-util": "0.0.18",
41
41
  "footprinter": "^0.0.44",