kicadts 0.0.1 → 0.0.2

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.
Files changed (78) hide show
  1. package/.github/workflows/bun-formatcheck.yml +26 -0
  2. package/.github/workflows/bun-pver-release.yml +70 -0
  3. package/.github/workflows/bun-test.yml +32 -0
  4. package/.github/workflows/bun-typecheck.yml +26 -0
  5. package/.vscode/settings.json +1 -1
  6. package/AGENTS.md +1 -0
  7. package/LICENSE +21 -0
  8. package/README.md +101 -91
  9. package/TODO.md +46 -0
  10. package/bunfig.toml +2 -2
  11. package/lib/sexpr/classes/At.ts +15 -0
  12. package/lib/sexpr/classes/Bus.ts +23 -3
  13. package/lib/sexpr/classes/BusEntry.ts +30 -3
  14. package/lib/sexpr/classes/EmbeddedFonts.ts +1 -3
  15. package/lib/sexpr/classes/Footprint.ts +157 -27
  16. package/lib/sexpr/classes/FootprintAttr.ts +3 -1
  17. package/lib/sexpr/classes/FootprintModel.ts +1 -4
  18. package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +3 -1
  19. package/lib/sexpr/classes/FootprintPad.ts +206 -54
  20. package/lib/sexpr/classes/FpArc.ts +23 -0
  21. package/lib/sexpr/classes/FpCircle.ts +24 -3
  22. package/lib/sexpr/classes/FpLine.ts +31 -3
  23. package/lib/sexpr/classes/FpPoly.ts +24 -4
  24. package/lib/sexpr/classes/FpRect.ts +24 -3
  25. package/lib/sexpr/classes/FpText.ts +43 -9
  26. package/lib/sexpr/classes/FpTextBox.ts +43 -5
  27. package/lib/sexpr/classes/GrLine.ts +20 -1
  28. package/lib/sexpr/classes/GrText.ts +38 -12
  29. package/lib/sexpr/classes/Image.ts +38 -11
  30. package/lib/sexpr/classes/Junction.ts +36 -4
  31. package/lib/sexpr/classes/KicadPcb.ts +49 -1
  32. package/lib/sexpr/classes/KicadSch.ts +119 -25
  33. package/lib/sexpr/classes/Label.ts +45 -5
  34. package/lib/sexpr/classes/NoConnect.ts +20 -3
  35. package/lib/sexpr/classes/PadLayers.ts +13 -1
  36. package/lib/sexpr/classes/PadOptions.ts +4 -5
  37. package/lib/sexpr/classes/PadPrimitiveGrArc.ts +22 -4
  38. package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +23 -4
  39. package/lib/sexpr/classes/PadPrimitives.ts +3 -1
  40. package/lib/sexpr/classes/PadSize.ts +15 -0
  41. package/lib/sexpr/classes/PadTeardrops.ts +3 -1
  42. package/lib/sexpr/classes/PcbGeneral.ts +14 -7
  43. package/lib/sexpr/classes/PcbLayerDefinition.ts +5 -1
  44. package/lib/sexpr/classes/Property.ts +64 -9
  45. package/lib/sexpr/classes/Pts.ts +7 -5
  46. package/lib/sexpr/classes/SchematicText.ts +39 -9
  47. package/lib/sexpr/classes/Segment.ts +21 -0
  48. package/lib/sexpr/classes/SegmentNet.ts +3 -1
  49. package/lib/sexpr/classes/Setup/PcbPlotParams.ts +10 -50
  50. package/lib/sexpr/classes/Setup/Setup.ts +12 -11
  51. package/lib/sexpr/classes/Setup/Stackup.ts +14 -19
  52. package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +3 -1
  53. package/lib/sexpr/classes/Setup/StackupProperties.ts +0 -1
  54. package/lib/sexpr/classes/Setup/base.ts +1 -3
  55. package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +0 -1
  56. package/lib/sexpr/classes/Sheet.ts +85 -3
  57. package/lib/sexpr/classes/SheetPin.ts +4 -1
  58. package/lib/sexpr/classes/Symbol.ts +176 -51
  59. package/lib/sexpr/classes/TextEffects.ts +25 -8
  60. package/lib/sexpr/classes/TitleBlock.ts +21 -4
  61. package/lib/sexpr/classes/Via.ts +38 -3
  62. package/lib/sexpr/classes/ViaNet.ts +2 -1
  63. package/lib/sexpr/classes/Wire.ts +23 -3
  64. package/lib/sexpr/classes/Xy.ts +1 -3
  65. package/lib/sexpr/classes/Zone.ts +1 -3
  66. package/lib/sexpr/parseToPrimitiveSExpr.ts +6 -1
  67. package/lib/sexpr/utils/strokeFromArgs.ts +5 -6
  68. package/lib/sexpr/utils/toStringValue.ts +2 -1
  69. package/package.json +2 -1
  70. package/scripts/download-references.ts +24 -22
  71. package/tests/fixtures/expectEqualPrimitiveSExpr.ts +6 -7
  72. package/tests/fixtures/png-matcher.ts +109 -0
  73. package/tests/fixtures/preload.ts +1 -0
  74. package/tests/sexpr/classes/FootprintPad.test.ts +8 -1
  75. package/tests/sexpr/classes/Image.test.ts +9 -1
  76. package/tests/sexpr/classes/KicadSch.test.ts +1 -3
  77. package/tests/sexpr/classes/Setup.test.ts +0 -1
  78. package/bun.lock +0 -48
@@ -3,7 +3,7 @@ import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
3
  import { printSExpr } from "../parseToPrimitiveSExpr"
4
4
  import { quoteSExprString } from "../utils/quoteSExprString"
5
5
  import { toStringValue } from "../utils/toStringValue"
6
- import { At } from "./At"
6
+ import { At, type AtInput } from "./At"
7
7
  import { Layer } from "./Layer"
8
8
  import { PropertyHide } from "./PropertyHide"
9
9
  import { PropertyUnlocked } from "./PropertyUnlocked"
@@ -31,7 +31,9 @@ const ensureSingleChild = (
31
31
  }
32
32
  }
33
33
 
34
- const primitiveToString = (value: PrimitiveSExpr | undefined): string | undefined => {
34
+ const primitiveToString = (
35
+ value: PrimitiveSExpr | undefined,
36
+ ): string | undefined => {
35
37
  if (value === undefined) {
36
38
  return undefined
37
39
  }
@@ -42,6 +44,17 @@ const primitiveToString = (value: PrimitiveSExpr | undefined): string | undefine
42
44
  return printSExpr(value)
43
45
  }
44
46
 
47
+ export interface PropertyConstructorParams {
48
+ key?: string
49
+ value?: string
50
+ position?: AtInput | Xy
51
+ layer?: Layer | Array<string | number> | string
52
+ uuid?: string | Uuid
53
+ effects?: TextEffects
54
+ unlocked?: boolean | PropertyUnlocked
55
+ hidden?: boolean | PropertyHide
56
+ }
57
+
45
58
  export class Property extends SxClass {
46
59
  static override token = "property"
47
60
  token = "property"
@@ -56,10 +69,51 @@ export class Property extends SxClass {
56
69
  private _sxUnlocked?: PropertyUnlocked
57
70
  private _sxHide?: PropertyHide
58
71
 
59
- constructor(key = "", value = "") {
72
+ constructor(
73
+ keyOrParams: string | PropertyConstructorParams = {},
74
+ value = "",
75
+ ) {
60
76
  super()
61
- this._key = key
62
- this._value = value
77
+
78
+ // Support both old constructor signature and new params interface
79
+ if (typeof keyOrParams === "string") {
80
+ this._key = keyOrParams
81
+ this._value = value
82
+ } else {
83
+ const params = keyOrParams
84
+ if (params.key !== undefined) {
85
+ this._key = params.key
86
+ }
87
+ if (params.value !== undefined) {
88
+ this._value = params.value
89
+ }
90
+ if (params.position !== undefined) {
91
+ this.position = params.position
92
+ }
93
+ if (params.layer !== undefined) {
94
+ this.layer = params.layer
95
+ }
96
+ if (params.uuid !== undefined) {
97
+ this.uuid = params.uuid
98
+ }
99
+ if (params.effects !== undefined) {
100
+ this.effects = params.effects
101
+ }
102
+ if (params.unlocked !== undefined) {
103
+ if (params.unlocked instanceof PropertyUnlocked) {
104
+ this._sxUnlocked = params.unlocked
105
+ } else {
106
+ this.unlocked = params.unlocked
107
+ }
108
+ }
109
+ if (params.hidden !== undefined) {
110
+ if (params.hidden instanceof PropertyHide) {
111
+ this._sxHide = params.hidden
112
+ } else {
113
+ this.hidden = params.hidden
114
+ }
115
+ }
116
+ }
63
117
  }
64
118
 
65
119
  static override fromSexprPrimitives(
@@ -152,9 +206,9 @@ export class Property extends SxClass {
152
206
  return this._sxAt ?? this._sxXy
153
207
  }
154
208
 
155
- set position(value: At | Xy | undefined) {
156
- if (value instanceof At) {
157
- this._sxAt = value
209
+ set position(value: AtInput | Xy | undefined) {
210
+ if (value === undefined) {
211
+ this._sxAt = undefined
158
212
  this._sxXy = undefined
159
213
  return
160
214
  }
@@ -163,7 +217,8 @@ export class Property extends SxClass {
163
217
  this._sxAt = undefined
164
218
  return
165
219
  }
166
- this._sxAt = undefined
220
+ // Handle AtInput (At, array, or object)
221
+ this._sxAt = At.from(value as AtInput)
167
222
  this._sxXy = undefined
168
223
  }
169
224
 
@@ -14,14 +14,14 @@ export class Pts extends SxClass {
14
14
  this.points = points
15
15
  }
16
16
 
17
- static override fromSexprPrimitives(
18
- primitiveSexprs: PrimitiveSExpr[],
19
- ): Pts {
17
+ static override fromSexprPrimitives(primitiveSexprs: PrimitiveSExpr[]): Pts {
20
18
  const points: Xy[] = []
21
19
 
22
20
  for (const primitive of primitiveSexprs) {
23
21
  if (!Array.isArray(primitive) || primitive.length === 0) {
24
- throw new Error(`Unexpected primitive inside pts: ${printSExpr(primitive)}`)
22
+ throw new Error(
23
+ `Unexpected primitive inside pts: ${printSExpr(primitive)}`,
24
+ )
25
25
  }
26
26
 
27
27
  const parsed = SxClass.parsePrimitiveSexpr(primitive, {
@@ -39,7 +39,9 @@ export class Pts extends SxClass {
39
39
  )
40
40
  }
41
41
 
42
- throw new Error(`Unable to parse child inside pts: ${printSExpr(primitive)}`)
42
+ throw new Error(
43
+ `Unable to parse child inside pts: ${printSExpr(primitive)}`,
44
+ )
43
45
  }
44
46
 
45
47
  return new Pts(points)
@@ -2,17 +2,20 @@ import { SxClass } from "../base-classes/SxClass"
2
2
  import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
3
  import { quoteSExprString } from "../utils/quoteSExprString"
4
4
  import { toStringValue } from "../utils/toStringValue"
5
- import { At } from "./At"
5
+ import { At, type AtInput } from "./At"
6
6
  import { ExcludeFromSim } from "./ExcludeFromSim"
7
7
  import { TextEffects } from "./TextEffects"
8
8
  import { Uuid } from "./Uuid"
9
9
 
10
- const SUPPORTED_TOKENS = new Set([
11
- "exclude_from_sim",
12
- "at",
13
- "effects",
14
- "uuid",
15
- ])
10
+ const SUPPORTED_TOKENS = new Set(["exclude_from_sim", "at", "effects", "uuid"])
11
+
12
+ export interface SchematicTextConstructorParams {
13
+ value?: string
14
+ excludeFromSim?: boolean | ExcludeFromSim
15
+ at?: AtInput
16
+ effects?: TextEffects
17
+ uuid?: string | Uuid
18
+ }
16
19
 
17
20
  export class SchematicText extends SxClass {
18
21
  static override token = "text"
@@ -25,6 +28,33 @@ export class SchematicText extends SxClass {
25
28
  private _sxEffects?: TextEffects
26
29
  private _sxUuid?: Uuid
27
30
 
31
+ constructor(params: SchematicTextConstructorParams = {}) {
32
+ super()
33
+
34
+ if (params.value !== undefined) {
35
+ this.value = params.value
36
+ }
37
+
38
+ if (params.excludeFromSim !== undefined) {
39
+ this.excludeFromSim =
40
+ typeof params.excludeFromSim === "boolean"
41
+ ? params.excludeFromSim
42
+ : params.excludeFromSim.value
43
+ }
44
+
45
+ if (params.at !== undefined) {
46
+ this.at = params.at
47
+ }
48
+
49
+ if (params.effects !== undefined) {
50
+ this.effects = params.effects
51
+ }
52
+
53
+ if (params.uuid !== undefined) {
54
+ this.uuid = params.uuid
55
+ }
56
+ }
57
+
28
58
  static override fromSexprPrimitives(
29
59
  primitiveSexprs: PrimitiveSExpr[],
30
60
  ): SchematicText {
@@ -96,8 +126,8 @@ export class SchematicText extends SxClass {
96
126
  return this._sxAt
97
127
  }
98
128
 
99
- set at(value: At | undefined) {
100
- this._sxAt = value
129
+ set at(value: AtInput | undefined) {
130
+ this._sxAt = value !== undefined ? At.from(value) : undefined
101
131
  }
102
132
 
103
133
  get effects(): TextEffects | undefined {
@@ -18,6 +18,16 @@ const SUPPORTED_SINGLE_TOKENS = new Set([
18
18
  "locked",
19
19
  ])
20
20
 
21
+ export interface SegmentConstructorParams {
22
+ start?: SegmentStart | { x: number; y: number }
23
+ end?: SegmentEnd | { x: number; y: number }
24
+ width?: Width | number
25
+ layer?: Layer | string | Array<string | number>
26
+ net?: SegmentNet | { id: number; name?: string }
27
+ uuid?: Uuid | string
28
+ locked?: boolean
29
+ }
30
+
21
31
  export class Segment extends SxClass {
22
32
  static override token = "segment"
23
33
  override token = "segment"
@@ -30,6 +40,17 @@ export class Segment extends SxClass {
30
40
  private _sxUuid?: Uuid
31
41
  private _sxLocked?: SegmentLocked
32
42
 
43
+ constructor(params: SegmentConstructorParams = {}) {
44
+ super()
45
+ if (params.start !== undefined) this.start = params.start
46
+ if (params.end !== undefined) this.end = params.end
47
+ if (params.width !== undefined) this.width = params.width
48
+ if (params.layer !== undefined) this.layer = params.layer
49
+ if (params.net !== undefined) this.net = params.net
50
+ if (params.uuid !== undefined) this.uuid = params.uuid
51
+ if (params.locked !== undefined) this.locked = params.locked
52
+ }
53
+
33
54
  static override fromSexprPrimitives(
34
55
  primitiveSexprs: PrimitiveSExpr[],
35
56
  ): Segment {
@@ -47,7 +47,9 @@ export class SegmentNet extends SxClass {
47
47
  }
48
48
 
49
49
  toObject(): { id: number; name?: string } {
50
- return this._name === undefined ? { id: this._id } : { id: this._id, name: this._name }
50
+ return this._name === undefined
51
+ ? { id: this._id }
52
+ : { id: this._id, name: this._name }
51
53
  }
52
54
 
53
55
  override getChildren(): SxClass[] {
@@ -208,11 +208,7 @@ export class PcbPlotParams extends SxClass {
208
208
  private setStringProperty<
209
209
  K extends PlotParamKey,
210
210
  T extends { new (value: string): PlotParamProperty<any> },
211
- >(
212
- key: K,
213
- value: string | undefined,
214
- ClassRef: T,
215
- ) {
211
+ >(key: K, value: string | undefined, ClassRef: T) {
216
212
  if (value === undefined) {
217
213
  this.clearProperty(key)
218
214
  return
@@ -223,11 +219,7 @@ export class PcbPlotParams extends SxClass {
223
219
  private setNumberProperty<
224
220
  K extends PlotParamKey,
225
221
  T extends { new (value: number): PlotParamProperty<any> },
226
- >(
227
- key: K,
228
- value: number | undefined,
229
- ClassRef: T,
230
- ) {
222
+ >(key: K, value: number | undefined, ClassRef: T) {
231
223
  if (value === undefined) {
232
224
  this.clearProperty(key)
233
225
  return
@@ -335,11 +327,7 @@ export class PcbPlotParams extends SxClass {
335
327
  }
336
328
 
337
329
  set excludeedgelayer(value: string | undefined) {
338
- this.setStringProperty(
339
- "excludeedgelayer",
340
- value,
341
- PlotParamExcludeEdgeLayer,
342
- )
330
+ this.setStringProperty("excludeedgelayer", value, PlotParamExcludeEdgeLayer)
343
331
  }
344
332
 
345
333
  get dashed_line_dash_ratio(): number | undefined {
@@ -447,11 +435,7 @@ export class PcbPlotParams extends SxClass {
447
435
  }
448
436
 
449
437
  set sketchpadsonfab(value: string | undefined) {
450
- this.setStringProperty(
451
- "sketchpadsonfab",
452
- value,
453
- PlotParamSketchPadsOnFab,
454
- )
438
+ this.setStringProperty("sketchpadsonfab", value, PlotParamSketchPadsOnFab)
455
439
  }
456
440
 
457
441
  get hidednponfab(): string | undefined {
@@ -475,11 +459,7 @@ export class PcbPlotParams extends SxClass {
475
459
  }
476
460
 
477
461
  set crossoutdnponfab(value: string | undefined) {
478
- this.setStringProperty(
479
- "crossoutdnponfab",
480
- value,
481
- PlotParamCrossoutDnpOnFab,
482
- )
462
+ this.setStringProperty("crossoutdnponfab", value, PlotParamCrossoutDnpOnFab)
483
463
  }
484
464
 
485
465
  get subtractmaskfromsilk(): string | undefined {
@@ -571,11 +551,7 @@ export class PcbPlotParams extends SxClass {
571
551
  }
572
552
 
573
553
  set hpglpendiameter(value: number | undefined) {
574
- this.setNumberProperty(
575
- "hpglpendiameter",
576
- value,
577
- PlotParamHpglPenDiameter,
578
- )
554
+ this.setNumberProperty("hpglpendiameter", value, PlotParamHpglPenDiameter)
579
555
  }
580
556
 
581
557
  get hpglpenoverlay(): number | undefined {
@@ -583,11 +559,7 @@ export class PcbPlotParams extends SxClass {
583
559
  }
584
560
 
585
561
  set hpglpenoverlay(value: number | undefined) {
586
- this.setNumberProperty(
587
- "hpglpenoverlay",
588
- value,
589
- PlotParamHpglPenOverlay,
590
- )
562
+ this.setNumberProperty("hpglpenoverlay", value, PlotParamHpglPenOverlay)
591
563
  }
592
564
 
593
565
  get pdf_front_fp_property_popups(): string | undefined {
@@ -647,11 +619,7 @@ export class PcbPlotParams extends SxClass {
647
619
  }
648
620
 
649
621
  set dxfimperialunits(value: string | undefined) {
650
- this.setStringProperty(
651
- "dxfimperialunits",
652
- value,
653
- PlotParamDxfImperialUnits,
654
- )
622
+ this.setStringProperty("dxfimperialunits", value, PlotParamDxfImperialUnits)
655
623
  }
656
624
 
657
625
  get dxfusepcbnewfont(): string | undefined {
@@ -659,11 +627,7 @@ export class PcbPlotParams extends SxClass {
659
627
  }
660
628
 
661
629
  set dxfusepcbnewfont(value: string | undefined) {
662
- this.setStringProperty(
663
- "dxfusepcbnewfont",
664
- value,
665
- PlotParamDxfUsePcbnewFont,
666
- )
630
+ this.setStringProperty("dxfusepcbnewfont", value, PlotParamDxfUsePcbnewFont)
667
631
  }
668
632
 
669
633
  get psnegative(): string | undefined {
@@ -719,11 +683,7 @@ export class PcbPlotParams extends SxClass {
719
683
  }
720
684
 
721
685
  set outputdirectory(value: string | undefined) {
722
- this.setStringProperty(
723
- "outputdirectory",
724
- value,
725
- PlotParamOutputDirectory,
726
- )
686
+ this.setStringProperty("outputdirectory", value, PlotParamOutputDirectory)
727
687
  }
728
688
  }
729
689
  SxClass.register(PcbPlotParams)
@@ -164,10 +164,7 @@ export class Setup extends SxClass {
164
164
  return children
165
165
  }
166
166
 
167
- private setProperty(
168
- key: SetupPropertyKey,
169
- instance: SxClass | undefined,
170
- ) {
167
+ private setProperty(key: SetupPropertyKey, instance: SxClass | undefined) {
171
168
  if (instance) {
172
169
  this._properties[key] = instance
173
170
  return
@@ -247,7 +244,11 @@ export class Setup extends SxClass {
247
244
  }
248
245
 
249
246
  set padToPasteClearance(value: number | undefined) {
250
- this.setNumberProperty("padToPasteClearance", value, SetupPadToPasteClearance)
247
+ this.setNumberProperty(
248
+ "padToPasteClearance",
249
+ value,
250
+ SetupPadToPasteClearance,
251
+ )
251
252
  }
252
253
 
253
254
  get padToPasteClearanceRatio(): number | undefined {
@@ -266,10 +267,8 @@ export class Setup extends SxClass {
266
267
  }
267
268
 
268
269
  get lastTraceWidth(): number | undefined {
269
- return this.getPropertyInstance(
270
- "lastTraceWidth",
271
- SetupLastTraceWidth,
272
- )?.value
270
+ return this.getPropertyInstance("lastTraceWidth", SetupLastTraceWidth)
271
+ ?.value
273
272
  }
274
273
 
275
274
  set lastTraceWidth(value: number | undefined) {
@@ -277,7 +276,8 @@ export class Setup extends SxClass {
277
276
  }
278
277
 
279
278
  get traceClearance(): number | undefined {
280
- return this.getPropertyInstance("traceClearance", SetupTraceClearance)?.value
279
+ return this.getPropertyInstance("traceClearance", SetupTraceClearance)
280
+ ?.value
281
281
  }
282
282
 
283
283
  set traceClearance(value: number | undefined) {
@@ -530,7 +530,8 @@ export class Setup extends SxClass {
530
530
  }
531
531
 
532
532
  get visibleElements(): string | undefined {
533
- return this.getPropertyInstance("visibleElements", SetupVisibleElements)?.value
533
+ return this.getPropertyInstance("visibleElements", SetupVisibleElements)
534
+ ?.value
534
535
  }
535
536
 
536
537
  set visibleElements(value: string | undefined) {
@@ -22,14 +22,16 @@ export class Stackup extends SxClass {
22
22
  private _sxCastellatedPads?: StackupCastellatedPads
23
23
  private _sxEdgePlating?: StackupEdgePlating
24
24
 
25
- constructor(opts: {
26
- layers?: StackupLayer[]
27
- copperFinish?: StackupCopperFinish
28
- dielectricConstraints?: StackupDielectricConstraints
29
- edgeConnector?: StackupEdgeConnector
30
- castellatedPads?: StackupCastellatedPads
31
- edgePlating?: StackupEdgePlating
32
- } = {}) {
25
+ constructor(
26
+ opts: {
27
+ layers?: StackupLayer[]
28
+ copperFinish?: StackupCopperFinish
29
+ dielectricConstraints?: StackupDielectricConstraints
30
+ edgeConnector?: StackupEdgeConnector
31
+ castellatedPads?: StackupCastellatedPads
32
+ edgePlating?: StackupEdgePlating
33
+ } = {},
34
+ ) {
33
35
  super()
34
36
  this.layers = opts.layers ?? []
35
37
  this._sxCopperFinish = opts.copperFinish
@@ -51,8 +53,7 @@ export class Stackup extends SxClass {
51
53
  dielectricConstraints:
52
54
  propertyMap.dielectric_constraints as StackupDielectricConstraints,
53
55
  edgeConnector: propertyMap.edge_connector as StackupEdgeConnector,
54
- castellatedPads:
55
- propertyMap.castellated_pads as StackupCastellatedPads,
56
+ castellatedPads: propertyMap.castellated_pads as StackupCastellatedPads,
56
57
  edgePlating: propertyMap.edge_plating as StackupEdgePlating,
57
58
  })
58
59
  }
@@ -75,9 +76,7 @@ export class Stackup extends SxClass {
75
76
  }
76
77
 
77
78
  set copperFinish(value: string | undefined) {
78
- this._sxCopperFinish = value
79
- ? new StackupCopperFinish(value)
80
- : undefined
79
+ this._sxCopperFinish = value ? new StackupCopperFinish(value) : undefined
81
80
  }
82
81
 
83
82
  get dielectricConstraints(): string | undefined {
@@ -95,9 +94,7 @@ export class Stackup extends SxClass {
95
94
  }
96
95
 
97
96
  set edgeConnector(value: string | undefined) {
98
- this._sxEdgeConnector = value
99
- ? new StackupEdgeConnector(value)
100
- : undefined
97
+ this._sxEdgeConnector = value ? new StackupEdgeConnector(value) : undefined
101
98
  }
102
99
 
103
100
  get castellatedPads(): string | undefined {
@@ -115,9 +112,7 @@ export class Stackup extends SxClass {
115
112
  }
116
113
 
117
114
  set edgePlating(value: string | undefined) {
118
- this._sxEdgePlating = value
119
- ? new StackupEdgePlating(value)
120
- : undefined
115
+ this._sxEdgePlating = value ? new StackupEdgePlating(value) : undefined
121
116
  }
122
117
 
123
118
  override getChildren(): SxClass[] {
@@ -4,7 +4,9 @@ import { toNumberValue } from "../../utils/toNumberValue"
4
4
 
5
5
  import { SingleValueProperty } from "./base"
6
6
 
7
- abstract class StackupLayerProperty<T extends string | number> extends SingleValueProperty<T> {
7
+ abstract class StackupLayerProperty<
8
+ T extends string | number,
9
+ > extends SingleValueProperty<T> {
8
10
  static override parentToken = "layer"
9
11
  }
10
12
 
@@ -38,4 +38,3 @@ export class StackupEdgePlating extends StackupSingleValueProperty<string> {
38
38
  token = "edge_plating"
39
39
  }
40
40
  SxClass.register(StackupEdgePlating)
41
-
@@ -56,9 +56,7 @@ export abstract class SingleValueProperty<
56
56
 
57
57
  protected formatValue(): string {
58
58
  if (typeof this._value === "string") {
59
- return this.quoteStringValue
60
- ? quoteSExprString(this._value)
61
- : this._value
59
+ return this.quoteStringValue ? quoteSExprString(this._value) : this._value
62
60
  }
63
61
  return `${this._value}`
64
62
  }
@@ -51,4 +51,3 @@ export class SetupGridOrigin extends SetupCoordinateProperty {
51
51
  token = "grid_origin"
52
52
  }
53
53
  SxClass.register(SetupGridOrigin)
54
-
@@ -4,7 +4,7 @@ import { indentLines } from "../utils/indentLines"
4
4
  import { quoteSExprString } from "../utils/quoteSExprString"
5
5
  import { toNumberValue } from "../utils/toNumberValue"
6
6
  import { toStringValue } from "../utils/toStringValue"
7
- import { At } from "./At"
7
+ import { At, type AtInput } from "./At"
8
8
  import { Color } from "./Color"
9
9
  import { Dnp } from "./Dnp"
10
10
  import { ExcludeFromSim } from "./ExcludeFromSim"
@@ -21,6 +21,22 @@ import { SheetFill } from "./SheetFill"
21
21
  import { SheetSize } from "./SheetSize"
22
22
  import { SheetProperty } from "./SheetProperty"
23
23
 
24
+ export interface SheetConstructorParams {
25
+ position?: AtInput
26
+ size?: SheetSize | { width: number; height: number }
27
+ excludeFromSim?: boolean | ExcludeFromSim
28
+ inBom?: boolean | InBom
29
+ onBoard?: boolean | OnBoard
30
+ dnp?: boolean | Dnp
31
+ fieldsAutoplaced?: boolean | FieldsAutoplaced
32
+ stroke?: Stroke
33
+ fill?: SheetFill
34
+ uuid?: string | Uuid
35
+ properties?: SheetProperty[]
36
+ pins?: SheetPin[]
37
+ instances?: SheetInstances
38
+ }
39
+
24
40
  export class Sheet extends SxClass {
25
41
  static override token = "sheet"
26
42
  token = "sheet"
@@ -39,6 +55,72 @@ export class Sheet extends SxClass {
39
55
  private _pins: SheetPin[] = []
40
56
  private _sxInstances?: SheetInstances
41
57
 
58
+ constructor(params: SheetConstructorParams = {}) {
59
+ super()
60
+
61
+ if (params.position !== undefined) {
62
+ this.position = params.position
63
+ }
64
+
65
+ if (params.size !== undefined) {
66
+ this.size = params.size
67
+ }
68
+
69
+ if (params.excludeFromSim !== undefined) {
70
+ this.excludeFromSim =
71
+ typeof params.excludeFromSim === "boolean"
72
+ ? params.excludeFromSim
73
+ : params.excludeFromSim.value
74
+ }
75
+
76
+ if (params.inBom !== undefined) {
77
+ this.inBom =
78
+ typeof params.inBom === "boolean" ? params.inBom : params.inBom.value
79
+ }
80
+
81
+ if (params.onBoard !== undefined) {
82
+ this.onBoard =
83
+ typeof params.onBoard === "boolean"
84
+ ? params.onBoard
85
+ : params.onBoard.value
86
+ }
87
+
88
+ if (params.dnp !== undefined) {
89
+ this.dnp = typeof params.dnp === "boolean" ? params.dnp : params.dnp.value
90
+ }
91
+
92
+ if (params.fieldsAutoplaced !== undefined) {
93
+ this.fieldsAutoplaced =
94
+ typeof params.fieldsAutoplaced === "boolean"
95
+ ? params.fieldsAutoplaced
96
+ : params.fieldsAutoplaced.value
97
+ }
98
+
99
+ if (params.stroke !== undefined) {
100
+ this.stroke = params.stroke
101
+ }
102
+
103
+ if (params.fill !== undefined) {
104
+ this.fill = params.fill
105
+ }
106
+
107
+ if (params.uuid !== undefined) {
108
+ this.uuid = params.uuid
109
+ }
110
+
111
+ if (params.properties !== undefined) {
112
+ this.properties = params.properties
113
+ }
114
+
115
+ if (params.pins !== undefined) {
116
+ this.pins = params.pins
117
+ }
118
+
119
+ if (params.instances !== undefined) {
120
+ this.instances = params.instances
121
+ }
122
+ }
123
+
42
124
  static override fromSexprPrimitives(
43
125
  primitiveSexprs: PrimitiveSExpr[],
44
126
  ): Sheet {
@@ -72,8 +154,8 @@ export class Sheet extends SxClass {
72
154
  return this._sxAt
73
155
  }
74
156
 
75
- set position(value: At | undefined) {
76
- this._sxAt = value
157
+ set position(value: AtInput | undefined) {
158
+ this._sxAt = value !== undefined ? At.from(value) : undefined
77
159
  }
78
160
 
79
161
  get size(): { width: number; height: number } | undefined {
@@ -48,7 +48,10 @@ export class SheetPin extends SxClass {
48
48
  }
49
49
 
50
50
  const electricalType = toStringValue(rawType)
51
- if (!electricalType || !electricalTypes.has(electricalType as SheetPinElectricalType)) {
51
+ if (
52
+ !electricalType ||
53
+ !electricalTypes.has(electricalType as SheetPinElectricalType)
54
+ ) {
52
55
  throw new Error(
53
56
  `sheet pin electrical type must be one of: ${Array.from(electricalTypes).join(", ")}`,
54
57
  )