@tscircuit/props 0.0.626 → 0.0.628

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.
@@ -0,0 +1,71 @@
1
+ export interface ImplicitBreakoutPoint {
2
+ readonly x: number
3
+ readonly y: number
4
+ }
5
+
6
+ export interface ImplicitBreakoutBounds {
7
+ readonly minX: number
8
+ readonly maxX: number
9
+ readonly minY: number
10
+ readonly maxY: number
11
+ }
12
+
13
+ export type ImplicitBreakoutEdge = "left" | "right" | "bottom" | "top"
14
+
15
+ export interface ImplicitBreakoutRegion {
16
+ readonly regionId: string
17
+ readonly bounds: ImplicitBreakoutBounds
18
+ readonly edge: ImplicitBreakoutEdge
19
+ }
20
+
21
+ export interface ImplicitBreakoutConnectionEndpoint {
22
+ readonly regionId: string
23
+ readonly position: ImplicitBreakoutPoint
24
+ }
25
+
26
+ export interface ImplicitBreakoutConnection {
27
+ readonly connectionId: string
28
+ readonly endpoints: readonly ImplicitBreakoutConnectionEndpoint[]
29
+ }
30
+
31
+ export interface ImplicitBreakoutDifferentialPair {
32
+ readonly type: "differential"
33
+ readonly connections: readonly [
34
+ ImplicitBreakoutConnection,
35
+ ImplicitBreakoutConnection,
36
+ ]
37
+ }
38
+
39
+ export type ImplicitBreakoutConnectionOrDifferentialPair =
40
+ | ImplicitBreakoutConnection
41
+ | ImplicitBreakoutDifferentialPair
42
+
43
+ export interface ImplicitBreakoutBus {
44
+ readonly busId: string
45
+ readonly connectionIds: readonly string[]
46
+ /** Ordered candidate layers that the solver may distribute this bus over. */
47
+ readonly targetLayers?: readonly string[]
48
+ }
49
+
50
+ export interface ImplicitBreakoutPointSolverInput {
51
+ readonly regions: readonly ImplicitBreakoutRegion[]
52
+ readonly connections: readonly ImplicitBreakoutConnectionOrDifferentialPair[]
53
+ readonly buses: readonly ImplicitBreakoutBus[]
54
+ readonly boundaryPointSpacing: number
55
+ }
56
+
57
+ export interface ImplicitBreakoutSolverPoint extends ImplicitBreakoutPoint {
58
+ readonly regionId: string
59
+ readonly connectionId: string
60
+ readonly layer: string
61
+ }
62
+
63
+ export interface ImplicitBreakoutPointSolverOutput {
64
+ readonly breakoutPoints: readonly ImplicitBreakoutSolverPoint[]
65
+ }
66
+
67
+ export type ImplicitBreakoutPointSolverFn = (
68
+ input: ImplicitBreakoutPointSolverInput,
69
+ ) =>
70
+ | ImplicitBreakoutPointSolverOutput
71
+ | Promise<ImplicitBreakoutPointSolverOutput>
@@ -33,6 +33,7 @@ import {
33
33
  } from "lib/common/schematicPinStyle"
34
34
  import { url } from "lib/common/url"
35
35
  import type { Connections } from "lib/utility-types/connections-and-selectors"
36
+ import type { ImplicitBreakoutPointSolverFn } from "lib/common/implicitBreakoutPointSolver"
36
37
 
37
38
  export const layoutConfig = z.object({
38
39
  layoutMode: z
@@ -342,6 +343,8 @@ export interface AutorouterConfig {
342
343
  | /** @deprecated Use "sequential_trace" */ "sequential-trace"
343
344
  local?: boolean
344
345
  algorithmFn?: (simpleRouteJson: any) => Promise<any>
346
+ /** Override the solver used to place implicit breakout points. */
347
+ implicitBreakoutPointSolverFn?: ImplicitBreakoutPointSolverFn
345
348
  preset?:
346
349
  | "sequential_trace"
347
350
  | "subcircuit"
@@ -423,6 +426,11 @@ export const autorouterConfig = z.object({
423
426
  (v) => typeof v === "function" || v === undefined,
424
427
  )
425
428
  .optional(),
429
+ implicitBreakoutPointSolverFn: z
430
+ .custom<ImplicitBreakoutPointSolverFn>(
431
+ (value) => typeof value === "function" || value === undefined,
432
+ )
433
+ .optional(),
426
434
  preset: z
427
435
  .enum([
428
436
  "sequential_trace",
@@ -45,6 +45,27 @@ export interface PinHeaderProps extends CommonComponentProps {
45
45
  */
46
46
  gender?: "male" | "female" | "unpopulated"
47
47
 
48
+ /**
49
+ * Mount the header on the top of the board, so it is connected to from
50
+ * above. An alias for `layer: "top"`, which is the default.
51
+ *
52
+ * Which side of the board a part sits on is `layer`, and only `layer`: the
53
+ * 3D model is always drawn top-side and consumers flip it for a bottom-layer
54
+ * component. Prefer these names on a connector, where "which side does the
55
+ * mating connector come from" is the question actually being asked.
56
+ */
57
+ connectsFromAbove?: boolean
58
+
59
+ /**
60
+ * Mount the header on the underside of the board, so it is connected to from
61
+ * below. An alias for `layer: "bottom"`.
62
+ *
63
+ * Not to be confused with `invert` on a footprint string, which installs a
64
+ * header BACKWARDS on whichever side it is on — long pins through the board
65
+ * rather than short ones.
66
+ */
67
+ connectsFromBelow?: boolean
68
+
48
69
  /**
49
70
  * Whether to show pin labels in silkscreen
50
71
  */
@@ -122,33 +143,61 @@ export interface PinHeaderProps extends CommonComponentProps {
122
143
  schHeight?: number | string
123
144
  }
124
145
 
125
- export const pinHeaderProps = commonComponentProps.extend({
126
- pinCount: z.number(),
127
- pitch: distance.optional(),
128
- schFacingDirection: z.enum(["up", "down", "left", "right"]).optional(),
129
- gender: z.enum(["male", "female", "unpopulated"]).optional().default("male"),
130
- showSilkscreenPinLabels: z.boolean().optional(),
131
- pcbPinLabels: z.record(z.string(), z.string()).optional(),
132
- doubleRow: z.boolean().optional(),
133
- rightAngle: z.boolean().optional(),
134
- pcbOrientation: pcbOrientationProp.optional(),
135
- holeDiameter: distance.optional(),
136
- platedDiameter: distance.optional(),
137
- pinLabels: z
138
- .record(z.string(), schematicPinLabel)
139
- .or(z.array(schematicPinLabel))
140
- .optional(),
141
- connections: z
142
- .custom<Connections>()
143
- .pipe(z.record(z.string(), connectionTarget))
144
- .optional(),
145
- facingDirection: z.enum(["left", "right"]).optional(),
146
- schPinArrangement: schematicPinArrangement.optional(),
147
- schPinStyle: schematicPinStyle.optional(),
148
- schPinSpacing: distance.optional(),
149
- schWidth: distance.optional(),
150
- schHeight: distance.optional(),
151
- })
146
+ export const pinHeaderProps = commonComponentProps
147
+ .extend({
148
+ pinCount: z.number(),
149
+ pitch: distance.optional(),
150
+ schFacingDirection: z.enum(["up", "down", "left", "right"]).optional(),
151
+ gender: z
152
+ .enum(["male", "female", "unpopulated"])
153
+ .optional()
154
+ .default("male"),
155
+ showSilkscreenPinLabels: z.boolean().optional(),
156
+ pcbPinLabels: z.record(z.string(), z.string()).optional(),
157
+ doubleRow: z.boolean().optional(),
158
+ rightAngle: z.boolean().optional(),
159
+ pcbOrientation: pcbOrientationProp.optional(),
160
+ holeDiameter: distance.optional(),
161
+ platedDiameter: distance.optional(),
162
+ pinLabels: z
163
+ .record(z.string(), schematicPinLabel)
164
+ .or(z.array(schematicPinLabel))
165
+ .optional(),
166
+ connections: z
167
+ .custom<Connections>()
168
+ .pipe(z.record(z.string(), connectionTarget))
169
+ .optional(),
170
+ facingDirection: z.enum(["left", "right"]).optional(),
171
+ schPinArrangement: schematicPinArrangement.optional(),
172
+ schPinStyle: schematicPinStyle.optional(),
173
+ schPinSpacing: distance.optional(),
174
+ schWidth: distance.optional(),
175
+ schHeight: distance.optional(),
176
+ connectsFromAbove: z.boolean().optional(),
177
+ connectsFromBelow: z.boolean().optional(),
178
+ })
179
+ // Resolved HERE rather than in each consumer: `layer` is read in dozens of
180
+ // places downstream, and an alias that only some of them understand is worse
181
+ // than no alias. After parsing there is one field to reason about again.
182
+ .superRefine((props, ctx) => {
183
+ if (props.connectsFromAbove && props.connectsFromBelow) {
184
+ ctx.addIssue({
185
+ code: z.ZodIssueCode.custom,
186
+ message:
187
+ "connectsFromAbove and connectsFromBelow are opposites; set at most one",
188
+ })
189
+ }
190
+ })
191
+ .transform((props) => {
192
+ const layer =
193
+ props.layer ??
194
+ (props.connectsFromBelow
195
+ ? ("bottom" as const)
196
+ : props.connectsFromAbove
197
+ ? ("top" as const)
198
+ : undefined)
199
+ return layer === undefined ? props : { ...props, layer }
200
+ })
152
201
 
153
202
  type InferredPinHeaderProps = z.input<typeof pinHeaderProps>
154
203
  expectTypesMatch<PinHeaderProps, InferredPinHeaderProps>(true)
package/lib/index.ts CHANGED
@@ -141,3 +141,4 @@ export * from "./utility-types/connections-and-selectors"
141
141
  export * from "./common/ninePointAnchor"
142
142
  export * from "./common/fanoutBoundaryPadding"
143
143
  export * from "./common/fanoutProps"
144
+ export * from "./common/implicitBreakoutPointSolver"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/props",
3
- "version": "0.0.626",
3
+ "version": "0.0.628",
4
4
  "description": "Props for tscircuit builtin component types",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",