@tscircuit/props 0.0.647 → 0.0.648

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,67 @@
1
+ import { layer_ref } from "circuit-json"
2
+ import { z } from "zod"
3
+ import { distance } from "./distance"
4
+
5
+ const coordinate = distance.refine(Number.isFinite, "Coordinate must be finite")
6
+ const positiveDistance = distance.refine(
7
+ (value) => Number.isFinite(value) && value > 0,
8
+ "Distance must be positive and finite",
9
+ )
10
+ const routePoint = z.discriminatedUnion("route_type", [
11
+ z.object({
12
+ route_type: z.literal("wire"),
13
+ x: coordinate,
14
+ y: coordinate,
15
+ width: positiveDistance,
16
+ layer: layer_ref,
17
+ }),
18
+ z.object({
19
+ route_type: z.literal("via"),
20
+ x: coordinate,
21
+ y: coordinate,
22
+ from_layer: layer_ref,
23
+ to_layer: layer_ref,
24
+ via_diameter: positiveDistance.optional(),
25
+ via_hole_diameter: positiveDistance.optional(),
26
+ }),
27
+ ])
28
+
29
+ /**
30
+ * A saved route from a selected port to a fanout exit. Points are in the
31
+ * fanout's local PCB frame, in mm: +X right, +Y up, right-handed with +Z
32
+ * above the board. They are points (placement adds translation), not
33
+ * directions. Numeric distances are mm; unit strings are parsed to mm.
34
+ * Layers are physical board layers, independent of placement.
35
+ */
36
+ export const fanoutTracePath = z.object({
37
+ connection: z.string().min(1),
38
+ route: z
39
+ .array(routePoint)
40
+ .min(2)
41
+ .superRefine((route, ctx) => {
42
+ if (
43
+ route[0]?.route_type !== "wire" ||
44
+ route.at(-1)?.route_type !== "wire"
45
+ ) {
46
+ ctx.addIssue({
47
+ code: "custom",
48
+ message: "A fanout trace path must start and end with wire points",
49
+ })
50
+ }
51
+ let layer = route[0]?.route_type === "wire" ? route[0].layer : undefined
52
+ for (const point of route) {
53
+ if (
54
+ (point.route_type === "wire" ? point.layer : point.from_layer) !==
55
+ layer
56
+ ) {
57
+ ctx.addIssue({
58
+ code: "custom",
59
+ message: "A fanout trace path must use vias for layer changes",
60
+ })
61
+ }
62
+ if (point.route_type === "via") layer = point.to_layer
63
+ }
64
+ }),
65
+ })
66
+
67
+ export type FanoutTracePath = z.input<typeof fanoutTracePath>
@@ -1,3 +1,7 @@
1
+ import {
2
+ fanoutTracePath,
3
+ type FanoutTracePath,
4
+ } from "lib/common/fanoutTracePath"
1
5
  import { distance, type Distance } from "lib/common/distance"
2
6
  import { type FanoutProps, fanoutProps } from "lib/common/fanoutProps"
3
7
  import { expectTypesMatch } from "lib/typecheck"
@@ -17,6 +21,17 @@ export interface BreakoutProps
17
21
  * Defaults to the multilayer fanout autorouter.
18
22
  */
19
23
  autorouter?: AutorouterProp
24
+ /**
25
+ * Saved port-to-exit wire/via routes in the fanout's local PCB frame.
26
+ * Numeric distances are mm; unit strings are normalized to mm. Each route
27
+ * must start at its selected port and end at its fanout exit. Layers name
28
+ * physical board layers. Core creates the exits and preserves saved copper.
29
+ * When supplied, replaces automatic routing (including `autorouter`) for
30
+ * this fanout and must cover all its routing connections. Do not also add
31
+ * a breakoutpoint/fanoutpoint for the same port. Omitted by default; existing
32
+ * automatic fanouts are unchanged. No aliases or migration are required.
33
+ */
34
+ pcbTracePaths?: FanoutTracePath[]
20
35
  padding?: Distance
21
36
  paddingLeft?: Distance
22
37
  paddingRight?: Distance
@@ -35,6 +50,7 @@ const nonnegativeFanoutMargin = distance.refine((value) => value >= 0, {
35
50
 
36
51
  export const breakoutProps = subcircuitGroupProps.extend({
37
52
  autorouter: autorouterProp.default("fanout"),
53
+ pcbTracePaths: z.array(fanoutTracePath).optional(),
38
54
  padding: distance.optional(),
39
55
  paddingLeft: distance.optional(),
40
56
  paddingRight: distance.optional(),
package/lib/index.ts CHANGED
@@ -145,3 +145,5 @@ export * from "./common/ninePointAnchor"
145
145
  export * from "./common/fanoutBoundaryPadding"
146
146
  export * from "./common/fanoutProps"
147
147
  export * from "./common/implicitBreakoutPointSolver"
148
+
149
+ export * from "./common/fanoutTracePath"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/props",
3
- "version": "0.0.647",
3
+ "version": "0.0.648",
4
4
  "description": "Props for tscircuit builtin component types",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",