From b23986a647ff41f6ae0263d9211695bd92ab5a34 Mon Sep 17 00:00:00 2001 From: Severin Ibarluzea Date: Wed, 4 Nov 2026 23:31:53 -0800 Subject: [PATCH 1/2] Document assembly BOM purchasing props and TSX hierarchy --- docs/elements/assembly-device.mdx | 8 ++++ docs/elements/assembly-part.mdx | 61 ++++++++++++++++++++++++++ docs/elements/assembly-subassembly.mdx | 8 ++++ 3 files changed, 77 insertions(+) diff --git a/docs/elements/assembly-device.mdx b/docs/elements/assembly-device.mdx index 18b7c733..78e6af86 100644 --- a/docs/elements/assembly-device.mdx +++ b/docs/elements/assembly-device.mdx @@ -30,10 +30,18 @@ export default () => ( | Property | Description | |----------|-------------| | `name` | Optional device name. | +| `purchaseUrls` | Optional array of HTTP(S) purchase links for the device. | +| `supplierPartNumbers` | Optional supplier-to-SKU map for the device. | | `model` | Modelprinter string or HTTP(S) model URL. | | `modelUrl` | Imported CAD model URL. Use either `model` or `modelUrl`. | | `children` | Boards, motors, subassemblies, and screens. | +## Bill of materials + +A device contributes its own assembly BOM line when it has `model`, `modelUrl`, `purchaseUrls` or `supplierPartNumbers`. An explicitly empty `purchaseUrls={[]}` or `supplierPartNumbers={{}}` also opts it into a line. Each device line has quantity one. + +Without a model or purchasing metadata, the device is transparent to the assembly BOM: its materials attach to the nearest material ancestor, or become root entries. This lets a device organize the design without adding an extra material to purchase. See the [assembly BOM example](./assembly-part.mdx#bill-of-materials) for nesting, purchasing links and converter usage. + ## Modelprinter strings Use a modelprinter string directly in `model`; no modelcdn URL is needed. This display is 16 × 10 mm with a 5 mm cable. diff --git a/docs/elements/assembly-part.mdx b/docs/elements/assembly-part.mdx index 7b2a1d68..df499886 100644 --- a/docs/elements/assembly-part.mdx +++ b/docs/elements/assembly-part.mdx @@ -35,6 +35,8 @@ For a purchased bearing CAD file, replace `cadModel={bearingModel}` with `modelU |----------|-------------| | `name` | Required stable identity. Trimmed and must not be empty. | | `displayName` | Optional human-facing name. | +| `purchaseUrls` | Optional array of HTTP(S) purchase links, including Amazon or a manufacturer's store. | +| `supplierPartNumbers` | Optional supplier-to-SKU map, for example `{ jlcpcb: ["C123"] }`. | | `model` | Modelprinter/footprinter specification or an HTTP(S) model URL. | | `modelUrl` | Imported model URL or asset path. | | `cadModel` | Existing CAD formats and model-alignment transforms, including CAD JSX; see [`cadmodel`](./cadmodel.mdx). | @@ -45,6 +47,65 @@ For a purchased bearing CAD file, replace `cadModel={bearingModel}` with `modelU Supply at most one of `model`, `modelUrl`, or `cadModel`. Omit all three for a part with no geometry. `cadModel={null}` also keeps the identity without rendering a model; it cannot be combined with another model source. For a `jscad` JSX prop, use [`assembly.printedpart`](./assembly-printedpart.mdx). +## Bill of materials + +Assembly parts appear in the assembly bill of materials even when they have no CAD model. Use `purchaseUrls` for store links and `supplierPartNumbers` for supplier lookup identifiers. These are independent: URLs are not matched to SKUs by their position in an array, and a purchase link alone does not supply a price. + +```tsx +import { assembly } from "@tscircuit/core" + +export default () => ( + + + + {[1, 2].map((index) => ( + + ))} + + + +) +``` + +Replace the example URLs and SKU with your actual purchasing information. This example needs no geometry: it produces a housing material line with four children (cover, two screws and module). The model-less outer device contributes no line. + +Each assembly element contributes quantity **one**, regardless of how many CAD models it contains. Represent multiple physical instances with separate elements, as with the two screws above. Nesting determines BOM ownership; `mountedTo` determines placement and does not reparent BOM lines. `displayName`, where supported, supplies the material label; otherwise the label comes from `name`. + +The same purchasing props are available on `assembly.subassembly` (and its `assembly.cadassembly` alias), `assembly.device`, `assembly.bolt`, `assembly.printedpart`, `assembly.motor`, `assembly.screen` and `assembly.cable`. Reference surfaces, CAD primitives, drawings and explosion instructions do not add material lines. See [device BOM behavior](./assembly-device.mdx#bill-of-materials) for when a device contributes its own line. + +### Read the assembly BOM + +Core emits `cad_assembly_bom_item` records in Circuit JSON. Render the design, then use `convertCircuitJsonToAssemblyBom` from `circuit-json-to-bom-csv` (version 0.0.28 or later) to obtain the nested BOM: + +```tsx +import { Circuit } from "@tscircuit/core" +import { convertCircuitJsonToAssemblyBom } from "circuit-json-to-bom-csv" +import SensorAssembly from "./sensor-assembly" + +const circuit = new Circuit() +circuit.add() +await circuit.renderUntilSettled() + +const bom = await convertCircuitJsonToAssemblyBom({ + circuitJson: circuit.getCircuitJson(), +}) +``` + +Save the first example as `sensor-assembly.tsx`. Each resulting node exposes `name`, `quantity`, `total_quantity`, `purchase_urls` and `children`, with supplier identifiers when supplied. Remaining PCB components are grouped by their electrical subcircuits. Assembly materials do not enter the existing PCB manufacturing BOM CSV. + +Core records purchasing metadata without fetching prices. A consuming viewer can use a parts engine to quote supported supplier SKUs; arbitrary store links do not enable automatic pricing. Parent and child materials remain separate entries: nesting does not indicate that a parent's purchase price includes its children. + ## Placement and CAD alignment Standalone unmounted parts use the world origin. Nested parts inherit the nearest assembly's full placement, including tilt. A face mount sets the complete position and orientation; its children and reference surfaces follow that frame. Use `mountOffset` for in-plane adjustment and `mountGap` for separation. Both require `mountedTo`. diff --git a/docs/elements/assembly-subassembly.mdx b/docs/elements/assembly-subassembly.mdx index 7f02d76b..14c134b5 100644 --- a/docs/elements/assembly-subassembly.mdx +++ b/docs/elements/assembly-subassembly.mdx @@ -35,6 +35,8 @@ Offsets use the target face's local axes. Rotating a target frame changes the di |----------|-------------| | `name` | Required group name. | | `displayName` | Optional display label. | +| `purchaseUrls` | Optional array of HTTP(S) purchase links for this subassembly. | +| `supplierPartNumbers` | Optional supplier-to-SKU map for this subassembly. | | `model` | Modelprinter string or HTTP(S) model URL. | | `modelUrl` | Imported CAD model URL. | | `cadModel` | Model with advanced alignment options; see [`cadmodel`](./cadmodel.mdx). | @@ -46,6 +48,12 @@ Offsets use the target face's local axes. Rotating a target frame changes the di Choose at most one of `model`, `modelUrl`, or `cadModel`. Omit all three for a group with no model. Reference surfaces can be children of either kind of group. +## Bill of materials + +Each subassembly emits one assembly BOM material line, including a subassembly with no model. Nested assembly materials appear beneath their nearest material ancestor. `displayName` supplies the label when present; otherwise `name` is used. Moving the group with `mountedTo` does not change BOM ownership. + +Purchase links and supplier SKUs belong to the subassembly's own line. Its children remain separate materials; nesting does not mean their cost is included in the parent. See the [assembly BOM example](./assembly-part.mdx#bill-of-materials) for purchasing props, repeated parts and converting Circuit JSON to a nested BOM. + ## Group placement and model alignment A mount determines the group's full rigid frame, including tilt, and its children inherit that frame. Unmounted groups inherit their containing assembly's placement; a standalone unmounted group starts at the world origin. References resolve within the nearest `assembly.device`; qualify selectors when several groups contain parts with the same name. From 74dade59eb0ba6f5f4bcc8a990fcac7990f9b704 Mon Sep 17 00:00:00 2001 From: Severin Ibarluzea Date: Wed, 4 Nov 2026 23:34:58 -0800 Subject: [PATCH 2/2] Keep purchasing prop documentation minimal --- docs/elements/assembly-device.mdx | 10 +--- docs/elements/assembly-part.mdx | 63 +------------------------- docs/elements/assembly-subassembly.mdx | 10 +--- 3 files changed, 6 insertions(+), 77 deletions(-) diff --git a/docs/elements/assembly-device.mdx b/docs/elements/assembly-device.mdx index 78e6af86..ec458d89 100644 --- a/docs/elements/assembly-device.mdx +++ b/docs/elements/assembly-device.mdx @@ -30,18 +30,12 @@ export default () => ( | Property | Description | |----------|-------------| | `name` | Optional device name. | -| `purchaseUrls` | Optional array of HTTP(S) purchase links for the device. | -| `supplierPartNumbers` | Optional supplier-to-SKU map for the device. | +| `purchaseUrls` | Optional purchase links. | +| `supplierPartNumbers` | Optional supplier part numbers, e.g. `{ jlcpcb: ["C123"] }`. | | `model` | Modelprinter string or HTTP(S) model URL. | | `modelUrl` | Imported CAD model URL. Use either `model` or `modelUrl`. | | `children` | Boards, motors, subassemblies, and screens. | -## Bill of materials - -A device contributes its own assembly BOM line when it has `model`, `modelUrl`, `purchaseUrls` or `supplierPartNumbers`. An explicitly empty `purchaseUrls={[]}` or `supplierPartNumbers={{}}` also opts it into a line. Each device line has quantity one. - -Without a model or purchasing metadata, the device is transparent to the assembly BOM: its materials attach to the nearest material ancestor, or become root entries. This lets a device organize the design without adding an extra material to purchase. See the [assembly BOM example](./assembly-part.mdx#bill-of-materials) for nesting, purchasing links and converter usage. - ## Modelprinter strings Use a modelprinter string directly in `model`; no modelcdn URL is needed. This display is 16 × 10 mm with a 5 mm cable. diff --git a/docs/elements/assembly-part.mdx b/docs/elements/assembly-part.mdx index df499886..ddd4654b 100644 --- a/docs/elements/assembly-part.mdx +++ b/docs/elements/assembly-part.mdx @@ -35,8 +35,8 @@ For a purchased bearing CAD file, replace `cadModel={bearingModel}` with `modelU |----------|-------------| | `name` | Required stable identity. Trimmed and must not be empty. | | `displayName` | Optional human-facing name. | -| `purchaseUrls` | Optional array of HTTP(S) purchase links, including Amazon or a manufacturer's store. | -| `supplierPartNumbers` | Optional supplier-to-SKU map, for example `{ jlcpcb: ["C123"] }`. | +| `purchaseUrls` | Optional purchase links. | +| `supplierPartNumbers` | Optional supplier part numbers, e.g. `{ jlcpcb: ["C123"] }`. | | `model` | Modelprinter/footprinter specification or an HTTP(S) model URL. | | `modelUrl` | Imported model URL or asset path. | | `cadModel` | Existing CAD formats and model-alignment transforms, including CAD JSX; see [`cadmodel`](./cadmodel.mdx). | @@ -47,65 +47,6 @@ For a purchased bearing CAD file, replace `cadModel={bearingModel}` with `modelU Supply at most one of `model`, `modelUrl`, or `cadModel`. Omit all three for a part with no geometry. `cadModel={null}` also keeps the identity without rendering a model; it cannot be combined with another model source. For a `jscad` JSX prop, use [`assembly.printedpart`](./assembly-printedpart.mdx). -## Bill of materials - -Assembly parts appear in the assembly bill of materials even when they have no CAD model. Use `purchaseUrls` for store links and `supplierPartNumbers` for supplier lookup identifiers. These are independent: URLs are not matched to SKUs by their position in an array, and a purchase link alone does not supply a price. - -```tsx -import { assembly } from "@tscircuit/core" - -export default () => ( - - - - {[1, 2].map((index) => ( - - ))} - - - -) -``` - -Replace the example URLs and SKU with your actual purchasing information. This example needs no geometry: it produces a housing material line with four children (cover, two screws and module). The model-less outer device contributes no line. - -Each assembly element contributes quantity **one**, regardless of how many CAD models it contains. Represent multiple physical instances with separate elements, as with the two screws above. Nesting determines BOM ownership; `mountedTo` determines placement and does not reparent BOM lines. `displayName`, where supported, supplies the material label; otherwise the label comes from `name`. - -The same purchasing props are available on `assembly.subassembly` (and its `assembly.cadassembly` alias), `assembly.device`, `assembly.bolt`, `assembly.printedpart`, `assembly.motor`, `assembly.screen` and `assembly.cable`. Reference surfaces, CAD primitives, drawings and explosion instructions do not add material lines. See [device BOM behavior](./assembly-device.mdx#bill-of-materials) for when a device contributes its own line. - -### Read the assembly BOM - -Core emits `cad_assembly_bom_item` records in Circuit JSON. Render the design, then use `convertCircuitJsonToAssemblyBom` from `circuit-json-to-bom-csv` (version 0.0.28 or later) to obtain the nested BOM: - -```tsx -import { Circuit } from "@tscircuit/core" -import { convertCircuitJsonToAssemblyBom } from "circuit-json-to-bom-csv" -import SensorAssembly from "./sensor-assembly" - -const circuit = new Circuit() -circuit.add() -await circuit.renderUntilSettled() - -const bom = await convertCircuitJsonToAssemblyBom({ - circuitJson: circuit.getCircuitJson(), -}) -``` - -Save the first example as `sensor-assembly.tsx`. Each resulting node exposes `name`, `quantity`, `total_quantity`, `purchase_urls` and `children`, with supplier identifiers when supplied. Remaining PCB components are grouped by their electrical subcircuits. Assembly materials do not enter the existing PCB manufacturing BOM CSV. - -Core records purchasing metadata without fetching prices. A consuming viewer can use a parts engine to quote supported supplier SKUs; arbitrary store links do not enable automatic pricing. Parent and child materials remain separate entries: nesting does not indicate that a parent's purchase price includes its children. - ## Placement and CAD alignment Standalone unmounted parts use the world origin. Nested parts inherit the nearest assembly's full placement, including tilt. A face mount sets the complete position and orientation; its children and reference surfaces follow that frame. Use `mountOffset` for in-plane adjustment and `mountGap` for separation. Both require `mountedTo`. diff --git a/docs/elements/assembly-subassembly.mdx b/docs/elements/assembly-subassembly.mdx index 14c134b5..97678426 100644 --- a/docs/elements/assembly-subassembly.mdx +++ b/docs/elements/assembly-subassembly.mdx @@ -35,8 +35,8 @@ Offsets use the target face's local axes. Rotating a target frame changes the di |----------|-------------| | `name` | Required group name. | | `displayName` | Optional display label. | -| `purchaseUrls` | Optional array of HTTP(S) purchase links for this subassembly. | -| `supplierPartNumbers` | Optional supplier-to-SKU map for this subassembly. | +| `purchaseUrls` | Optional purchase links. | +| `supplierPartNumbers` | Optional supplier part numbers, e.g. `{ jlcpcb: ["C123"] }`. | | `model` | Modelprinter string or HTTP(S) model URL. | | `modelUrl` | Imported CAD model URL. | | `cadModel` | Model with advanced alignment options; see [`cadmodel`](./cadmodel.mdx). | @@ -48,12 +48,6 @@ Offsets use the target face's local axes. Rotating a target frame changes the di Choose at most one of `model`, `modelUrl`, or `cadModel`. Omit all three for a group with no model. Reference surfaces can be children of either kind of group. -## Bill of materials - -Each subassembly emits one assembly BOM material line, including a subassembly with no model. Nested assembly materials appear beneath their nearest material ancestor. `displayName` supplies the label when present; otherwise `name` is used. Moving the group with `mountedTo` does not change BOM ownership. - -Purchase links and supplier SKUs belong to the subassembly's own line. Its children remain separate materials; nesting does not mean their cost is included in the parent. See the [assembly BOM example](./assembly-part.mdx#bill-of-materials) for purchasing props, repeated parts and converting Circuit JSON to a nested BOM. - ## Group placement and model alignment A mount determines the group's full rigid frame, including tilt, and its children inherit that frame. Unmounted groups inherit their containing assembly's placement; a standalone unmounted group starts at the world origin. References resolve within the nearest `assembly.device`; qualify selectors when several groups contain parts with the same name.