@tscircuit/props 0.0.716 → 0.0.718

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,26 @@
1
+ import { supplierProps, type SupplierProps } from "lib/common/layout"
2
+ import { expectTypesMatch } from "lib/typecheck"
3
+ import { z } from "zod"
4
+
5
+ /** Purchasing metadata shared by physical assembly elements, not CAD primitives. */
6
+ export interface AssemblyBomProps extends SupplierProps {
7
+ /** Alternative HTTP(S) purchase links, independent of supplier part numbers.
8
+ * Omitted and empty arrays are accepted. No SKU-to-URL mapping is inferred.
9
+ */
10
+ purchaseUrls?: string[]
11
+ }
12
+
13
+ export const assemblyBomProps = supplierProps.extend({
14
+ purchaseUrls: z
15
+ .array(
16
+ z
17
+ .string()
18
+ .url()
19
+ .refine((value) => /^https?:\/\//i.test(value), {
20
+ message: "Purchase links must use HTTP or HTTPS",
21
+ }),
22
+ )
23
+ .optional(),
24
+ })
25
+
26
+ expectTypesMatch<AssemblyBomProps, z.input<typeof assemblyBomProps>>(true)
@@ -1,9 +1,10 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { expectTypesMatch } from "lib/typecheck"
2
3
  import { z } from "zod"
3
4
 
4
5
  export type AssemblyCableStandard = "usb_c"
5
6
 
6
- export interface AssemblyCableProps {
7
+ export interface AssemblyCableProps extends AssemblyBomProps {
7
8
  /** Stable assembly identity for the cable. */
8
9
  name: string
9
10
  /** Start connector selector or named assembly reference, e.g. MOTOR.wireside. */
@@ -23,6 +24,7 @@ export interface AssemblyCableProps {
23
24
 
24
25
  export const assemblyCableProps = z
25
26
  .object({
27
+ ...assemblyBomProps.shape,
26
28
  name: z.string().trim().min(1),
27
29
  from: z.string().trim().min(1),
28
30
  to: z.string().trim().min(1),
@@ -1,8 +1,9 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { url } from "lib/common/url"
2
3
  import { expectTypesMatch } from "lib/typecheck"
3
4
  import { z } from "zod"
4
5
 
5
- export interface AssemblyDeviceProps {
6
+ export interface AssemblyDeviceProps extends AssemblyBomProps {
6
7
  /** Product-level assembly identity. */
7
8
  name?: string
8
9
  /** Imported CAD model URL. Mutually exclusive with cadModel where supported. */
@@ -13,6 +14,7 @@ export interface AssemblyDeviceProps {
13
14
 
14
15
  export const assemblyDeviceProps = z
15
16
  .object({
17
+ ...assemblyBomProps.shape,
16
18
  name: z.string().optional(),
17
19
  model: z.string().trim().min(1).optional(),
18
20
  modelUrl: url
@@ -12,6 +12,7 @@ import { assemblyScreenProps } from "./screen"
12
12
  import { assemblySubassemblyProps } from "./subassembly"
13
13
  import { assemblyExplosionProps } from "./explosion"
14
14
 
15
+ export * from "./bom"
15
16
  export * from "./drawing"
16
17
  export * from "./board-mounting"
17
18
  export * from "./bolt"
@@ -1,3 +1,4 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import {
2
3
  type CadModelAxisDirection,
3
4
  cadModelAxisDirection,
@@ -12,7 +13,9 @@ import {
12
13
 
13
14
  export type AssemblyMotorStandard = "nema8" | "nema17" | "nema23"
14
15
 
15
- export interface AssemblyMotorProps extends AssemblyFaceMountProps {
16
+ export interface AssemblyMotorProps
17
+ extends AssemblyFaceMountProps,
18
+ AssemblyBomProps {
16
19
  /** Stable assembly identity used by selectors. */
17
20
  name: string
18
21
  /** Human-facing alternate to the stable name. */
@@ -37,6 +40,7 @@ export interface AssemblyMotorProps extends AssemblyFaceMountProps {
37
40
 
38
41
  export const assemblyMotorProps = z
39
42
  .object({
43
+ ...assemblyBomProps.shape,
40
44
  ...assemblyFaceMountShape,
41
45
  name: z.string().refine((value) => value.trim().length > 0, {
42
46
  message: "name cannot be empty",
@@ -1,3 +1,4 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { type CadModelProp, cadModelProp } from "lib/common/cadModel"
2
3
  import { url } from "lib/common/url"
3
4
  import { expectTypesMatch } from "lib/typecheck"
@@ -10,7 +11,9 @@ import {
10
11
  } from "./face-mounting"
11
12
 
12
13
  /** A generic component of an assembly, with optional CAD geometry. */
13
- export interface AssemblyPartProps extends AssemblyFaceMountProps {
14
+ export interface AssemblyPartProps
15
+ extends AssemblyFaceMountProps,
16
+ AssemblyBomProps {
14
17
  /** Stable identity used by assembly selectors. */
15
18
  name: string
16
19
  /** Human-facing alternate to the stable name. */
@@ -29,6 +32,7 @@ export interface AssemblyPartProps extends AssemblyFaceMountProps {
29
32
  // Keep model validation separate from ordinary face-mount pairing.
30
33
  export const assemblyPartBaseProps = z
31
34
  .object({
35
+ ...assemblyBomProps.shape,
32
36
  name: z.string().trim().min(1),
33
37
  displayName: z.string().optional(),
34
38
  model: z.string().trim().min(1).optional(),
@@ -1,3 +1,4 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { type CadModelProp, cadModelProp } from "lib/common/cadModel"
2
3
  import { url } from "lib/common/url"
3
4
  import { expectTypesMatch } from "lib/typecheck"
@@ -10,7 +11,9 @@ import {
10
11
  } from "./face-mounting"
11
12
 
12
13
  /** Provide exactly one of jscad, model, modelUrl, or cadModel. */
13
- export interface AssemblyPrintedPartProps extends AssemblyFaceMountProps {
14
+ export interface AssemblyPrintedPartProps
15
+ extends AssemblyFaceMountProps,
16
+ AssemblyBomProps {
14
17
  /** Stable identity used by assembly mounting selectors. */
15
18
  name: string
16
19
  displayName?: string
@@ -33,6 +36,7 @@ export interface AssemblyPrintedPartProps extends AssemblyFaceMountProps {
33
36
 
34
37
  export const assemblyPrintedPartProps = z
35
38
  .object({
39
+ ...assemblyBomProps.shape,
36
40
  ...assemblyFaceMountShape,
37
41
  name: z.string().trim().min(1),
38
42
  displayName: z.string().optional(),
@@ -1,9 +1,10 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { url } from "lib/common/url"
2
3
  import { type Distance, distance } from "lib/common/distance"
3
4
  import { expectTypesMatch } from "lib/typecheck"
4
5
  import { z } from "zod"
5
6
 
6
- export interface AssemblyScreenProps {
7
+ export interface AssemblyScreenProps extends AssemblyBomProps {
7
8
  /** Stable product-level identity for the screen assembly. */
8
9
  name: string
9
10
  /** Imported CAD model URL. Mutually exclusive with cadModel where supported. */
@@ -41,6 +42,7 @@ const positiveDistance = (fieldName: "width" | "height") =>
41
42
 
42
43
  export const assemblyScreenProps = z
43
44
  .object({
45
+ ...assemblyBomProps.shape,
44
46
  name: nonemptyString("name"),
45
47
  model: z.string().trim().min(1).optional(),
46
48
  modelUrl: url
@@ -1,3 +1,4 @@
1
+ import { assemblyBomProps, type AssemblyBomProps } from "./bom"
1
2
  import { url } from "lib/common/url"
2
3
  import { type CadModelProp, cadModelProp } from "lib/common/cadModel"
3
4
  import { expectTypesMatch } from "lib/typecheck"
@@ -9,7 +10,9 @@ import {
9
10
  type AssemblyFaceMountProps,
10
11
  } from "./face-mounting"
11
12
 
12
- export interface AssemblySubassemblyProps extends AssemblyFaceMountProps {
13
+ export interface AssemblySubassemblyProps
14
+ extends AssemblyFaceMountProps,
15
+ AssemblyBomProps {
13
16
  /** Stable identity used by selectors from other assembly elements. */
14
17
  name: string
15
18
  /** Imported CAD model URL. Mutually exclusive with cadModel where supported. */
@@ -26,6 +29,7 @@ export interface AssemblySubassemblyProps extends AssemblyFaceMountProps {
26
29
 
27
30
  export const assemblySubassemblyProps = z
28
31
  .object({
32
+ ...assemblyBomProps.shape,
29
33
  ...assemblyFaceMountShape,
30
34
  name: z.string().refine((value) => value.trim().length > 0, {
31
35
  message: "name cannot be empty",
@@ -0,0 +1,35 @@
1
+ import { expectTypesMatch } from "lib/typecheck"
2
+ import { z } from "zod"
3
+ import {
4
+ type SystemBlockPcbReferenceProps,
5
+ refineSystemBlockPcbReference,
6
+ systemBlockPcbReferenceShape,
7
+ } from "../systemblock/pcb-reference"
8
+
9
+ /** A functional block, optionally associated with one or more PCB components. */
10
+ export interface SystemBlockComponentProps
11
+ extends SystemBlockPcbReferenceProps {
12
+ /** Stable block identity, unique across its page; trimmed and nonempty. */
13
+ name: string
14
+ /** Human-facing title; consumers fall back to name when omitted. */
15
+ displayName?: string
16
+ /** Plain-text explanation of what the block does. */
17
+ description?: string
18
+ }
19
+
20
+ export const systemBlockComponentProps = z
21
+ .object({
22
+ ...systemBlockPcbReferenceShape,
23
+ name: z.string().trim().min(1),
24
+ displayName: z.string().trim().min(1).optional(),
25
+ description: z.string().optional(),
26
+ })
27
+ .superRefine(refineSystemBlockPcbReference)
28
+
29
+ export type SystemBlockComponentPropsInput = z.input<
30
+ typeof systemBlockComponentProps
31
+ >
32
+
33
+ expectTypesMatch<SystemBlockComponentProps, SystemBlockComponentPropsInput>(
34
+ true,
35
+ )
@@ -0,0 +1,35 @@
1
+ import { expectTypesMatch } from "lib/typecheck"
2
+ import { z } from "zod"
3
+
4
+ /** A logical relationship between two blocks; does not create electrical traces. */
5
+ export interface SystemBlockConnectionProps {
6
+ /** Optional stable connection identity, unique within its page when supplied. */
7
+ name?: string
8
+ /** Component name within the containing page, including inside nested groups. */
9
+ from: string
10
+ /** Component name within the same page; group names and pin selectors are not endpoints. */
11
+ to: string
12
+ /** Interface annotation such as I2C, SPI, or 3.3 V; not the connection's identity. */
13
+ label?: string
14
+ /** Relationship category; defaults to signal. */
15
+ kind?: "signal" | "power"
16
+ /** Arrowheads: from → to, both ends, or neither. Defaults to forward. */
17
+ direction?: "forward" | "both" | "none"
18
+ }
19
+
20
+ export const systemBlockConnectionProps = z.object({
21
+ name: z.string().trim().min(1).optional(),
22
+ from: z.string().trim().min(1),
23
+ to: z.string().trim().min(1),
24
+ label: z.string().optional(),
25
+ kind: z.enum(["signal", "power"]).default("signal"),
26
+ direction: z.enum(["forward", "both", "none"]).default("forward"),
27
+ })
28
+
29
+ export type SystemBlockConnectionPropsInput = z.input<
30
+ typeof systemBlockConnectionProps
31
+ >
32
+
33
+ expectTypesMatch<SystemBlockConnectionProps, SystemBlockConnectionPropsInput>(
34
+ true,
35
+ )
@@ -0,0 +1,34 @@
1
+ import { expectTypesMatch } from "lib/typecheck"
2
+ import type { ReactNode } from "react"
3
+ import { z } from "zod"
4
+ import {
5
+ type SystemBlockPcbReferenceProps,
6
+ refineSystemBlockPcbReference,
7
+ systemBlockPcbReferenceShape,
8
+ } from "../systemblock/pcb-reference"
9
+
10
+ /** A subsystem boundary containing blocks, nested groups, and connections. */
11
+ export interface SystemBlockGroupProps extends SystemBlockPcbReferenceProps {
12
+ /** Stable group identity, unique across its page; trimmed and nonempty. */
13
+ name: string
14
+ /** Human-facing title; consumers fall back to name when omitted. */
15
+ displayName?: string
16
+ /** Plain-text explanation of the subsystem's responsibility. */
17
+ description?: string
18
+ /** Preserved unchanged; grouping does not create electrical connectivity. */
19
+ children?: ReactNode
20
+ }
21
+
22
+ export const systemBlockGroupProps = z
23
+ .object({
24
+ ...systemBlockPcbReferenceShape,
25
+ name: z.string().trim().min(1),
26
+ displayName: z.string().trim().min(1).optional(),
27
+ description: z.string().optional(),
28
+ children: z.custom<ReactNode>().optional(),
29
+ })
30
+ .superRefine(refineSystemBlockPcbReference)
31
+
32
+ export type SystemBlockGroupPropsInput = z.input<typeof systemBlockGroupProps>
33
+
34
+ expectTypesMatch<SystemBlockGroupProps, SystemBlockGroupPropsInput>(true)
@@ -0,0 +1,29 @@
1
+ import { expectTypesMatch } from "lib/typecheck"
2
+ import type { ReactNode } from "react"
3
+ import { z } from "zod"
4
+
5
+ /** One high-level system overview, independent of schematic or PCB geometry. */
6
+ export interface SystemBlockPageProps {
7
+ /** Stable page identity, unique within the circuit; trimmed and nonempty. */
8
+ name: string
9
+ /** Human-facing title; consumers fall back to name when omitted. */
10
+ displayName?: string
11
+ /** Plain-text explanation of the system's purpose. */
12
+ description?: string
13
+ /** Preferred automatic layout direction; defaults to right. */
14
+ direction?: "right" | "left" | "down" | "up"
15
+ /** System blocks, nested groups, and connections; preserved unchanged. */
16
+ children?: ReactNode
17
+ }
18
+
19
+ export const systemBlockPageProps = z.object({
20
+ name: z.string().trim().min(1),
21
+ displayName: z.string().trim().min(1).optional(),
22
+ description: z.string().optional(),
23
+ direction: z.enum(["right", "left", "down", "up"]).default("right"),
24
+ children: z.custom<ReactNode>().optional(),
25
+ })
26
+
27
+ export type SystemBlockPagePropsInput = z.input<typeof systemBlockPageProps>
28
+
29
+ expectTypesMatch<SystemBlockPageProps, SystemBlockPagePropsInput>(true)
package/lib/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./common/direction"
2
2
  export * from "./common/commonShape"
3
3
  export * from "./assembly"
4
+ export * from "./systemblock"
4
5
  export * from "./enclosure"
5
6
  export * from "./common/portHints"
6
7
  export * from "./common/layout"
@@ -0,0 +1,18 @@
1
+ import { systemBlockPageProps } from "../components/system-block-page"
2
+ import { systemBlockGroupProps } from "../components/system-block-group"
3
+ import { systemBlockComponentProps } from "../components/system-block-component"
4
+ import { systemBlockConnectionProps } from "../components/system-block-connection"
5
+
6
+ export * from "../components/system-block-page"
7
+ export * from "../components/system-block-group"
8
+ export * from "../components/system-block-component"
9
+ export * from "../components/system-block-connection"
10
+ export type { SystemBlockPcbReferenceProps } from "./pcb-reference"
11
+
12
+ /** Validators for the systemblock JSX namespace; rendering is supplied by core. */
13
+ export const systemBlockProps = {
14
+ page: systemBlockPageProps,
15
+ group: systemBlockGroupProps,
16
+ component: systemBlockComponentProps,
17
+ connection: systemBlockConnectionProps,
18
+ } as const
@@ -0,0 +1,39 @@
1
+ import { z } from "zod"
2
+
3
+ /** Optional PCB associations shared only by system blocks and their groups. */
4
+ export interface SystemBlockPcbReferenceProps {
5
+ /** One PCB component name; mutually exclusive with pcbComponentNames. */
6
+ pcbComponentName?: string
7
+ /** Nonempty list of PCB component names; mutually exclusive with pcbComponentName. */
8
+ pcbComponentNames?: string[]
9
+ /**
10
+ * Named PCB subcircuit in which component names are resolved. Without component
11
+ * names, associates the entire subcircuit. Omitted uses the owning circuit scope.
12
+ * References are names, not selectors; resolution is performed by the consumer.
13
+ */
14
+ pcbSubcircuitName?: string
15
+ }
16
+
17
+ const pcbName = z.string().trim().min(1)
18
+
19
+ export const systemBlockPcbReferenceShape = {
20
+ pcbComponentName: pcbName.optional(),
21
+ pcbComponentNames: z.array(pcbName).min(1).optional(),
22
+ pcbSubcircuitName: pcbName.optional(),
23
+ }
24
+
25
+ export function refineSystemBlockPcbReference(
26
+ props: SystemBlockPcbReferenceProps,
27
+ ctx: z.RefinementCtx,
28
+ ) {
29
+ if (
30
+ props.pcbComponentName !== undefined &&
31
+ props.pcbComponentNames !== undefined
32
+ ) {
33
+ ctx.addIssue({
34
+ code: "custom",
35
+ path: ["pcbComponentNames"],
36
+ message: "Provide either pcbComponentName or pcbComponentNames, not both",
37
+ })
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/props",
3
- "version": "0.0.716",
3
+ "version": "0.0.718",
4
4
  "description": "Props for tscircuit builtin component types",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",