forgecad 0.9.16 → 0.10.1

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 (162) hide show
  1. package/dist/assets/{AdminPage-CXvls4-J.js → AdminPage-DcCnj0qo.js} +1 -1
  2. package/dist/assets/{BenchmarkPage-B27zk8xL.js → BenchmarkPage-BVEpJSVk.js} +1 -1
  3. package/dist/assets/{BlogPage-CMAVvgQL.js → BlogPage-DHaGP50_.js} +1 -1
  4. package/dist/assets/{DocsPage-knf4I4h7.js → DocsPage-CDoxHkz8.js} +40 -859
  5. package/dist/assets/EditorApp-BJ0Dloyh.js +16446 -0
  6. package/dist/assets/{EmbedViewer-D7ZGlFjx.js → EmbedViewer-CRKZbY0y.js} +2 -2
  7. package/dist/assets/{LandingPageProofDriven-CnevhTE8.js → LandingPageProofDriven-BxHkYRE7.js} +1 -1
  8. package/dist/assets/{LegalPage-BPTUmqeg.js → LegalPage-B-u6FrVv.js} +1 -1
  9. package/dist/assets/{PricingPage-B0D4goG_.js → PricingPage-CzpZ6-Ce.js} +1 -1
  10. package/dist/assets/{SettingsPage-CFF-UgjI.js → SettingsPage-CIZSSAd0.js} +1 -1
  11. package/dist/assets/{app-CE3sYcV7.css → app-CjsbDlb7.css} +143 -0
  12. package/dist/assets/{app-T0pDcSX4.js → app-DaTMg3nH.js} +1310 -290
  13. package/dist/assets/cli/{render-C5pcIISc.js → render-DPf4AYJK.js} +55 -60
  14. package/dist/assets/{constructionHistoryWorker-Ba2Hm58b.js → constructionHistoryWorker-AwMMWSxg.js} +1103 -349
  15. package/dist/assets/{evalWorker-vkx310U2.js → evalWorker-CjZZWRWW.js} +5209 -2643
  16. package/dist/assets/{inspectWorker-BuTJDVX6.js → inspectWorker-CZsCFtQT.js} +1163 -409
  17. package/dist/assets/{jointPose-B_Cgedn9.js → jointPose-DzQOViQH.js} +1 -1
  18. package/dist/assets/{manifold-BWgsjmAM.js → manifold-BYlzU521.js} +1 -1
  19. package/dist/assets/{manifold-D6IFSkhH.js → manifold-DgXo0T5P.js} +2 -2
  20. package/dist/assets/{manifold-rZexZI0G.js → manifold-K1SkarlQ.js} +1 -1
  21. package/dist/assets/{reportWorker-0AGij1Ru.js → reportWorker-B9nWwSrB.js} +8501 -3393
  22. package/dist/assets/{scalar-sampling-budget-J5cuzxT1.js → scalar-sampling-budget-prBw_s8t.js} +6067 -3479
  23. package/dist/assets/{scanProxyWorker-Vl4Wxa1y.js → scanProxyWorker-2GtDLk-R.js} +1 -1
  24. package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
  25. package/dist/cli/render.html +1 -1
  26. package/dist/docs/index.html +3 -3
  27. package/dist/docs-raw/AI/usage.md +1 -1
  28. package/dist/docs-raw/CLI.md +77 -240
  29. package/dist/docs-raw/README.md +6 -0
  30. package/dist/docs-raw/component-model.md +17 -150
  31. package/dist/docs-raw/generated/assembly.md +188 -582
  32. package/dist/docs-raw/generated/concepts.md +259 -3501
  33. package/dist/docs-raw/generated/core.md +283 -1250
  34. package/dist/docs-raw/generated/curves.md +387 -1608
  35. package/dist/docs-raw/generated/legacy.md +162 -0
  36. package/dist/docs-raw/generated/lib.md +227 -85
  37. package/dist/docs-raw/generated/output.md +35 -99
  38. package/dist/docs-raw/generated/runtime-names.md +23 -23
  39. package/dist/docs-raw/generated/sdf.md +68 -284
  40. package/dist/docs-raw/generated/sheet-metal.md +68 -335
  41. package/dist/docs-raw/generated/sketch.md +240 -1161
  42. package/dist/docs-raw/generated/viewport.md +75 -316
  43. package/dist/docs-raw/generated/wood.md +21 -49
  44. package/dist/docs-raw/guides/coordinate-system.md +4 -42
  45. package/dist/docs-raw/guides/inspection-bundles.md +44 -442
  46. package/dist/docs-raw/guides/joint-design.md +18 -79
  47. package/dist/docs-raw/guides/positioning.md +21 -143
  48. package/dist/docs-raw/guides/scene-presentation.md +89 -0
  49. package/dist/docs-raw/guides/simready-quickstart.md +171 -0
  50. package/dist/docs-raw/simulation-workflow.md +273 -0
  51. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
  52. package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
  53. package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
  54. package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
  55. package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
  56. package/dist/docs-raw/skills/forgecad-lld.md +19 -113
  57. package/dist/docs-raw/skills/forgecad-make-a-model.md +112 -532
  58. package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
  59. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
  60. package/dist/docs-raw/skills/forgecad-project.md +13 -131
  61. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
  62. package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
  63. package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
  64. package/dist/docs-raw/skills/forgecad.md +19 -18
  65. package/dist/docs-raw/skills/index.md +2 -0
  66. package/dist/docs-raw/welcome.md +2 -2
  67. package/dist/index.html +2 -2
  68. package/dist/llms.txt +1 -2
  69. package/dist/sitemap.xml +25 -13
  70. package/dist-cli/{check-compiler-SYQ2PWOB.js → check-compiler-II7NLPAB.js} +1 -1
  71. package/dist-cli/{check-query-propagation-HIAGV62W.js → check-query-propagation-7462TR3R.js} +1 -1
  72. package/dist-cli/{chunk-SPZE3DUY.js → chunk-UWTJCGXF.js} +5848 -2915
  73. package/dist-cli/forgecad.js +3496 -703
  74. package/dist-skill/CONTEXT.md +1797 -7963
  75. package/dist-skill/SKILL.md +15 -15
  76. package/dist-skill/docs/API/core/concepts.md +27 -157
  77. package/dist-skill/docs/CLI.md +77 -240
  78. package/dist-skill/docs/generated/assembly.md +182 -532
  79. package/dist-skill/docs/generated/core.md +283 -1250
  80. package/dist-skill/docs/generated/curves.md +387 -1609
  81. package/dist-skill/docs/generated/lib.md +227 -85
  82. package/dist-skill/docs/generated/output.md +35 -99
  83. package/dist-skill/docs/generated/runtime-names.md +16 -21
  84. package/dist-skill/docs/generated/sdf.md +68 -284
  85. package/dist-skill/docs/generated/sheet-metal.md +68 -335
  86. package/dist-skill/docs/generated/sketch.md +240 -1160
  87. package/dist-skill/docs/generated/viewport.md +75 -223
  88. package/dist-skill/docs/generated/wood.md +21 -49
  89. package/dist-skill/docs/guides/coordinate-system.md +4 -42
  90. package/dist-skill/docs/guides/inspection-bundles.md +44 -442
  91. package/dist-skill/docs/guides/joint-design.md +18 -79
  92. package/dist-skill/docs/guides/positioning.md +21 -143
  93. package/dist-skill/docs/guides/scene-presentation.md +89 -0
  94. package/dist-skill/docs/guides/surface-members.md +26 -0
  95. package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
  96. package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
  97. package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
  98. package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
  99. package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
  100. package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
  101. package/dist-skill/library/forgecad-make-a-model/SKILL.md +110 -532
  102. package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
  103. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
  104. package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
  105. package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
  106. package/dist-skill/library/forgecad-project/SKILL.md +13 -133
  107. package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
  108. package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
  109. package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
  110. package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
  111. package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
  112. package/dist-skill/website/skills/forgecad-component-model.md +53 -0
  113. package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
  114. package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
  115. package/dist-skill/website/skills/forgecad-lld.md +41 -0
  116. package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
  117. package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
  118. package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
  119. package/dist-skill/website/skills/forgecad-project.md +26 -0
  120. package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
  121. package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
  122. package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
  123. package/dist-skill/website/skills/forgecad.md +122 -0
  124. package/dist-skill/website/skills/index.md +26 -0
  125. package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
  126. package/examples/api/conformal-product-ribbon.forge.js +1 -1
  127. package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
  128. package/examples/api/extrude-options.forge.js +4 -2
  129. package/examples/api/field-loft-drive-tip.forge.js +40 -0
  130. package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
  131. package/examples/api/highlight-debug.forge.js +10 -10
  132. package/examples/api/mesh-import-slats.forge.js +1 -1
  133. package/examples/api/real-product-curves.forge.js +1 -1
  134. package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
  135. package/examples/api/sdf-shapes.forge.js +2 -5
  136. package/examples/api/sketch-rounding-strategies.forge.js +6 -6
  137. package/examples/api/surface-member-bottle-cage.forge.js +3 -3
  138. package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
  139. package/examples/api/surface-member-razor-inlay.forge.js +1 -1
  140. package/examples/api/variable-sweep-test.forge.js +3 -3
  141. package/examples/mechanical/airplane-propeller.forge.js +74 -39
  142. package/examples/nurbs-surface.forge.js +1 -1
  143. package/examples/products/iphone.forge.js +1 -1
  144. package/examples/robotics/README.md +46 -0
  145. package/examples/robotics/scout-cam-rover-simready/README.md +119 -0
  146. package/examples/robotics/scout-cam-rover-simready/lib/dims.js +140 -0
  147. package/examples/robotics/scout-cam-rover-simready/main.forge.js +343 -0
  148. package/examples/robotics/scout-cam-rover-simready/parts/body.forge.js +304 -0
  149. package/examples/robotics/scout-cam-rover-simready/parts/chassis.forge.js +320 -0
  150. package/examples/robotics/scout-cam-rover-simready/parts/hardware.forge.js +21 -0
  151. package/examples/robotics/scout-cam-rover-simready/parts/turret.forge.js +70 -0
  152. package/examples/robotics/scout-cam-rover-simready/parts/wheel.forge.js +116 -0
  153. package/examples/robotics/simready-asset-crate.forge.js +79 -0
  154. package/examples/robotics/simready-diff-drive-rover.forge.js +141 -0
  155. package/examples/robotics/simready-parallel-gripper.forge.js +102 -0
  156. package/package.json +1 -1
  157. package/dist/assets/EditorApp-BHMQlJ-D.js +0 -14686
  158. package/dist/docs-raw/guides/geometry-conventions.md +0 -52
  159. package/dist/docs-raw/guides/modeling-recipes.md +0 -78
  160. package/dist-skill/docs/guides/geometry-conventions.md +0 -52
  161. package/dist-skill/docs/guides/modeling-recipes.md +0 -78
  162. package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
@@ -9,19 +9,18 @@ Folded sheet metal parts with flanges, bends, and flat pattern unfolding.
9
9
 
10
10
  ## Contents
11
11
 
12
- - [Sheet Metal](#sheet-metal) — `sheetMetal`
13
- - [Laser Cutting](#laser-cutting) — `kerfCompensateOutline`, `kerfCompensateTabs`, `kerfCompensateSlots`, `kerfCompensatePart`, `lookupKerf`, `flatPanel`, `flatPart`, `fingerJoint`, `tabSlot`, `assemblyPreview`, `assemblyInstructions`, `formatInstructions`, `laserKit`
12
+ - [Sheet Metal](#sheet-metal)
14
13
  - [SheetMetalPart](#sheetmetalpart)
15
14
  - [FlatPart](#flatpart)
16
15
  - [LaserKit](#laserkit)
17
16
  - [SHEET_METAL_EDGES](#sheet-metal-edges)
18
- - [COMMON_KERFS](#common-kerfs)
17
+ - [Laser](#laser)
19
18
 
20
19
  ## Functions
21
20
 
22
21
  ### Sheet Metal
23
22
 
24
- #### `sheetMetal()` — Create a parametric sheet metal part with flanges, bend allowances, and flat-pattern unfolding.
23
+ #### `sheetMetal(options: SheetMetalOptions): SheetMetalPart` — Create a parametric sheet metal part with flanges, bend allowances, and flat-pattern unfolding.
25
24
 
26
25
  `sheetMetal()` keeps one semantic model and derives both a folded 3D solid and an accurate flat pattern from it. The K-factor bend allowance is applied during unfolding. This is a strict v1 subset — it does not infer sheet metal from arbitrary solids.
27
26
 
@@ -53,10 +52,6 @@ const folded = cover.folded();
53
52
  const flat = cover.flatPattern();
54
53
  ```
55
54
 
56
- ```ts
57
- sheetMetal(options: SheetMetalOptions): SheetMetalPart
58
- ```
59
-
60
55
  **`SheetMetalOptions`**
61
56
 
62
57
  | Option | Type | Description |
@@ -67,197 +62,6 @@ sheetMetal(options: SheetMetalOptions): SheetMetalPart
67
62
  | `bendAllowance` | `{ kFactor: number; }` | Bend allowance model used when computing the flat-pattern developed length. Currently only K-factor is supported. The K-factor (0–1) describes how far the neutral axis sits from the inner bend surface. Typical values: - Soft materials / large radius: 0.50 - General sheet steel: 0.42–0.44 - Hard materials / tight radius: 0.30–0.38 |
68
63
  | `cornerRelief?` | `{ kind?: "rect"; size: number; }` | Corner relief cut at each bend intersection. Prevents material overlap when two flanges meet at a corner. Defaults to a rectangular relief sized to `bendRadius + thickness` if omitted. |
69
64
 
70
- ### Laser Cutting
71
-
72
- #### `kerfCompensateOutline()` — Apply kerf compensation to a complete part outline (outer boundary + holes).
73
-
74
- Offsets inward by half-kerf: the outer boundary shrinks and inner holes grow. This is correct because the laser beam removes material on both sides of the cut line.
75
-
76
- ```ts
77
- kerfCompensateOutline(sketch: Sketch, kerf: number): Sketch
78
- ```
79
-
80
- #### `kerfCompensateTabs()` — Apply kerf compensation to joint protrusions (tabs, fingers).
81
-
82
- These grow by half-kerf so they are slightly oversized and fit tightly in their mating slots after the laser removes material.
83
-
84
- ```ts
85
- kerfCompensateTabs(sketch: Sketch, kerf: number): Sketch
86
- ```
87
-
88
- #### `kerfCompensateSlots()` — Apply kerf compensation to joint cutouts (slots, holes that receive tabs).
89
-
90
- These grow by half-kerf so tabs can fit into them after the laser removes material from both sides of the slot walls.
91
-
92
- ```ts
93
- kerfCompensateSlots(sketch: Sketch, kerf: number): Sketch
94
- ```
95
-
96
- #### `kerfCompensatePart()` — Build a kerf-compensated part profile.
97
-
98
- 1. Start with the base profile.
99
- 2. Kerf-compensate each tab addition (grow by kerf/2), then union with base.
100
- 3. Kerf-compensate each slot subtraction (grow by kerf/2), then subtract from base.
101
- 4. Kerf-compensate the resulting outline (shrink by kerf/2).
102
-
103
- Order matters: joints modify geometry BEFORE outline compensation so the final inward offset applies uniformly to the assembled profile.
104
-
105
- ```ts
106
- kerfCompensatePart(baseProfile: Sketch, joints: PartJoints, kerf: number): Sketch
107
- ```
108
-
109
- **`PartJoints`**
110
- - `additions?: Sketch[]` — Geometry to ADD to the base profile (tabs, fingers protruding from edges).
111
- - `subtractions?: Sketch[]` — Geometry to SUBTRACT from the base profile (slots, holes for mating tabs).
112
-
113
- #### `lookupKerf()` — Look up kerf for a material + thickness + laser combo.
114
-
115
- If `laserType` is omitted, returns the first matching material + thickness entry. Returns `undefined` when no match is found.
116
-
117
- ```ts
118
- lookupKerf(material: string, thickness: number, laserType?: string): number | undefined
119
- ```
120
-
121
- #### `flatPanel()` — Create a rectangular flat panel with 4 named edges.
122
-
123
- Profile origin at bottom-left corner. Edges: bottom (y=0), right (x=width), top (y=height), left (x=0). Edge traversal follows CCW winding order.
124
-
125
- ```ts
126
- flatPanel(name: string, width: number, height: number, thickness: number, options?: FlatPartOptions): FlatPart
127
- ```
128
-
129
- `FlatPartOptions`: `{ material?: string, qty?: number, color?: string }`
130
-
131
- #### `flatPart()` — Create a flat part from an arbitrary profile with user-named edges.
132
-
133
- Edge normals are computed automatically (perpendicular to direction, rotated 90deg CW).
134
-
135
- ```ts
136
- flatPart(name: string, profile: Sketch, thickness: number, edges?: Record<string, { start: [ number, number ]; end: [ number, number ]; }>, options?: FlatPartOptions): FlatPart
137
- ```
138
-
139
- #### `fingerJoint()` — Connect two parts with finger joints along specified edges.
140
-
141
- Adds finger geometry to partA's edge, cuts matching slots from partB's edge. The joint profiles are positioned along each edge using rotation + translation.
142
-
143
- ```ts
144
- fingerJoint(partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: FingerJointOptions & { foldAngle?: number; }): void
145
- ```
146
-
147
- **`FingerJointOptions`**
148
-
149
- | Option | Type | Description |
150
- |--------|------|-------------|
151
- | `fingers?` | `number` | Explicit finger count (must be odd, >= 3). Default: auto from length/thickness. |
152
- | `fingerWidth?` | `number` | Explicit finger width. Default: auto. |
153
- | `clearance?` | `number` | Extra clearance per side (mm). Default: 0. |
154
- | `kerf?` | `number` | Laser kerf (mm). Default: 0. |
155
- | `endStyle?` | `"full" \| "half"` | Whether edge starts with full finger or half. Default: 'full'. |
156
-
157
- #### `tabSlot()` — Connect two parts with tab-and-slot joints along specified edges.
158
-
159
- Adds tab geometry to partA's edge, cuts matching slots from partB's edge.
160
-
161
- ```ts
162
- tabSlot(partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: TabSlotOptions & { foldAngle?: number; }): void
163
- ```
164
-
165
- **`TabSlotOptions`**
166
-
167
- | Option | Type | Description |
168
- |--------|------|-------------|
169
- | `tabCount?` | `number` | Number of tabs. Default: auto (length / (4 * thickness)). |
170
- | `tabWidth?` | `number` | Tab width. Default: 2 * thickness. |
171
- | `clearance?` | `number` | Extra clearance per side (mm). Default: 0. |
172
- | `kerf?` | `number` | Laser kerf (mm). Default: 0. |
173
- | `inset?` | `number` | Distance from panel edges to first/last tab center. Default: thickness. |
174
-
175
- #### `assemblyPreview()` — Generate a 3D assembly preview from flat parts and their joint records.
176
-
177
- The preview can fold joints partially or fully and optionally apply exploded spacing so part relationships are easier to inspect visually.
178
-
179
- ```ts
180
- assemblyPreview(parts: FlatPart[], joints: JointRecord[], options?: AssemblyPreviewOptions): AssemblyPreviewResult
181
- ```
182
-
183
- **`JointRecord`**
184
- - `foldAngle: number` — Fold angle in degrees. Default: 90.
185
- - Also: `type: "finger" | "tabSlot" | "snapFit", partA: string, partB: string, edgeA: string, edgeB: string`
186
-
187
- **`AssemblyPreviewOptions`**
188
- - `kerf?: number` — Kerf compensation passed to each part's solid(). Default: 0
189
- - `fold?: number` — Fold amount: 0 = flat layout, 1 = fully assembled. Default: 1
190
- - `explode?: number` — Explode distance: 0 = assembled, >0 = parts spread outward. Default: 0
191
-
192
- **`AssemblyPreviewResult`**
193
- - `shapes: ShapeGroup` — All part shapes grouped for display.
194
- - `partShapes: Map<string, Shape>` — Individual transformed shapes keyed by part name.
195
-
196
- #### `assemblyInstructions()` — Generate step-by-step assembly instructions from flat parts and joints.
197
-
198
- Algorithm:
199
-
200
- 1. Build adjacency graph from joints
201
- 2. Pick root part (most connections, or user-specified)
202
- 3. BFS from root, creating one step per part addition
203
- 4. Each step describes: which part to add, where it connects, how to orient it
204
-
205
- Heuristics for step ordering:
206
-
207
- - Start with the part that has the most connections (the base)
208
- - Add parts that connect to already-assembled parts first (BFS order)
209
- - Among candidates at the same BFS depth, prefer parts with more connections to already-assembled parts (structurally stable)
210
-
211
- ```ts
212
- assemblyInstructions(parts: FlatPart[], joints: JointRecord[], options?: AssemblyInstructionsOptions): AssemblyInstructionsResult
213
- ```
214
-
215
- **`AssemblyInstructionsOptions`**
216
- - `rootPart?: string` — Part to start from. Default: part with most joint connections.
217
-
218
- **`AssemblyInstructionsResult`**
219
- - `totalParts: number` — Total number of parts in the assembly.
220
- - `orphanParts: string[]` — Parts not connected to the joint graph (orphans).
221
- - Also: `steps: AssemblyStep[]`
222
-
223
- **`AssemblyStep`**
224
-
225
- | Option | Type | Description |
226
- |--------|------|-------------|
227
- | `stepNumber` | `number` | 1-based step number. |
228
- | `description` | `string` | Human-readable instruction. |
229
- | `partName` | `string` | The part being added in this step. |
230
- | `partNumber` | `number` | Part number (for cross-ref with cut sheets). |
231
- | `connectsTo` | `string` | Which existing part it connects to. |
232
- | `jointType` | `"finger" \| "tabSlot" \| "snapFit"` | Joint type used. |
233
- | `newPartEdge` | `string` | The edge on the new part. |
234
- | `existingPartEdge` | `string` | The edge on the existing part. |
235
- | `foldAngle` | `number` | Fold angle in degrees. |
236
- | `assembledParts` | `string[]` | Part names in the assembly so far (after this step). |
237
-
238
- #### `formatInstructions()` — Format assembly instructions as a human-readable text document.
239
-
240
- Includes a "Step 0" preamble identifying the base part, followed by numbered steps, and a note about any orphan parts.
241
-
242
- ```ts
243
- formatInstructions(result: AssemblyInstructionsResult): string
244
- ```
245
-
246
- #### `laserKit()` — Top-level factory for creating a LaserKit container.
247
-
248
- ```ts
249
- laserKit(options?: LaserKitOptions): LaserKit
250
- ```
251
-
252
- **`LaserKitOptions`**
253
-
254
- | Option | Type | Description |
255
- |--------|------|-------------|
256
- | `material?` | `string` | Default material label for parts that don't specify one. |
257
- | `sheetWidth?` | `number` | Stock sheet width in mm (default 600). |
258
- | `sheetHeight?` | `number` | Stock sheet height in mm (default 400). |
259
- | `kerf?` | `number` | Laser kerf in mm (default 0.2). |
260
-
261
65
  ---
262
66
 
263
67
  ## Classes
@@ -268,7 +72,7 @@ An immutable sheet metal part that accumulates flanges and cutouts.
268
72
 
269
73
  Each mutating method returns a **new** `SheetMetalPart`; the original is unchanged. The part does not produce geometry until you call `.folded()` or `.flatPattern()`.
270
74
 
271
- #### `flange()` — Add a 90° flange along one edge of the base panel.
75
+ #### `flange(edge: SheetMetalEdge, options: SheetMetalFlangeOptions): SheetMetalPart` — Add a 90° flange along one edge of the base panel.
272
76
 
273
77
  Each of the four edges (`'top'`, `'right'`, `'bottom'`, `'left'`) may carry at most one flange. Calling `.flange()` twice for the same edge throws.
274
78
 
@@ -280,15 +84,11 @@ const part = sheetMetal({ panel: { width: 100, height: 60 }, thickness: 1.5, ben
280
84
  .flange('bottom', { length: 15 });
281
85
  ```
282
86
 
283
- ```ts
284
- flange(edge: SheetMetalEdge, options: SheetMetalFlangeOptions): SheetMetalPart
285
- ```
286
-
287
87
  **`SheetMetalFlangeOptions`**
288
88
  - `length: number` — Flange leg length in mm, measured from the outside of the bend to the tip.
289
89
  - `angleDeg?: number` — Bend angle in degrees (default: `90`). Only `90°` is supported in v1. Values other than 90 will be rejected at build time.
290
90
 
291
- #### `cutout()` — Subtract a 2D sketch cutout from a planar region of the sheet metal part.
91
+ #### `cutout(region: SheetMetalPlanarRegionName, sketch: Sketch, options?: SheetMetalCutoutOptions): SheetMetalPart` — Subtract a 2D sketch cutout from a planar region of the sheet metal part.
292
92
 
293
93
  `region` must be `'panel'` or one of `'flange-top'`, `'flange-right'`, `'flange-bottom'`, `'flange-left'` (only available once the corresponding flange has been added). Cutouts inside bend regions are **not** supported in v1.
294
94
 
@@ -303,16 +103,12 @@ const part = sheetMetal({ panel: { width: 180, height: 110 }, thickness: 1.5, be
303
103
  .cutout('flange-top', roundedRect(26, 10, 5), { selfAnchor: 'center' });
304
104
  ```
305
105
 
306
- ```ts
307
- cutout(region: SheetMetalPlanarRegionName, sketch: Sketch, options?: SheetMetalCutoutOptions): SheetMetalPart
308
- ```
309
-
310
106
  **`SheetMetalCutoutOptions`**
311
107
  - `u?: number` — Horizontal offset within the region, measured from the region centre (mm). Default: `0`.
312
108
  - `v?: number` — Vertical offset within the region, measured from the region centre (mm). Default: `0`.
313
109
  - `selfAnchor?: Anchor` — Anchor point on the sketch that aligns to `(u, v)`. Use `'center'` for most cases. For asymmetric profiles, verify orientation by placing one test cutout before committing to the final position. Default: `'center'`.
314
110
 
315
- #### `regionNames()` — Return all semantic region names currently available on this part.
111
+ #### `regionNames(): SheetMetalRegionName[]` — Return all semantic region names currently available on this part.
316
112
 
317
113
  The returned list always includes `'panel'`. For every flange that has been added, the list also includes the corresponding `'flange-<edge>'` and `'bend-<edge>'` entries.
318
114
 
@@ -320,30 +116,18 @@ Use this to discover valid targets for `.cutout()` or for querying faces by regi
320
116
 
321
117
  Defended region names: `panel` | `flange-top` | `flange-right` | `flange-bottom` | `flange-left` | `bend-top` | `bend-right` | `bend-bottom` | `bend-left`
322
118
 
323
- ```ts
324
- regionNames(): SheetMetalRegionName[]
325
- ```
326
-
327
- #### `folded()` — Materialize the 3D folded solid.
119
+ #### `folded(): Shape` — Materialize the 3D folded solid.
328
120
 
329
121
  Applies all flanges (bent up at their configured angles) and all registered cutouts, then returns the resulting [`Shape`](/docs/core#shape). The shape is compiler-owned and exact-exportable (STEP, IGES, etc.).
330
122
 
331
123
  Prefer calling `.folded()` to validate each build step before proceeding to the final model.
332
124
 
333
- ```ts
334
- folded(): Shape
335
- ```
336
-
337
- #### `flatPattern()` — Materialize the flat-pattern (unfolded blank) for fabrication.
125
+ #### `flatPattern(): Shape` — Materialize the flat-pattern (unfolded blank) for fabrication.
338
126
 
339
127
  Unfolds all flanges using the K-factor bend allowance and lays the result flat in the XY plane. Cutouts are projected into the flat geometry. The returned shape is exact-exportable and ready for laser / waterjet / CNC nesting workflows.
340
128
 
341
129
  The developed length of each bend zone is: `BA = (bendRadius + kFactor × thickness) × angleDeg × π / 180`
342
130
 
343
- ```ts
344
- flatPattern(): Shape
345
- ```
346
-
347
131
  ### `FlatPart`
348
132
 
349
133
  **Properties:**
@@ -356,158 +140,107 @@ flatPattern(): Shape
356
140
 
357
141
  **Methods:**
358
142
 
359
- #### `edges()` — All edges as a read-only map.
360
-
361
- ```ts
362
- get edges(): ReadonlyMap<string, EdgeInfo>
363
- ```
364
-
365
- #### `edge()` — Look up a named edge. Throws if the edge does not exist.
366
-
367
- ```ts
368
- edge(name: string): EdgeInfo
369
- ```
370
-
371
- #### `edgeNames()` — All edge names on this part.
372
-
373
- ```ts
374
- edgeNames(): string[]
375
- ```
376
-
377
- #### `partNumber()` — BOM part number assigned to this flat part.
378
-
379
- ```ts
380
- get partNumber(): number
381
- ```
382
-
383
- #### `joints()` — Joint records that attach this part to other parts in the kit.
143
+ #### `get edges(): ReadonlyMap<string, EdgeInfo>` — All edges as a read-only map.
384
144
 
385
- ```ts
386
- get joints(): readonly JointRecord[]
387
- ```
145
+ #### `edge(name: string): EdgeInfo` — Look up a named edge. Throws if the edge does not exist.
388
146
 
389
- #### `quantity()` — Requested quantity of this part in the kit. Defaults to `1`.
147
+ #### `edgeNames(): string[]` — All edge names on this part.
390
148
 
391
- ```ts
392
- get quantity(): number
393
- ```
149
+ #### `get partNumber(): number` — BOM part number assigned to this flat part.
394
150
 
395
- #### `addGeometry()` — Add geometry (e.g. protruding tabs) to the part profile.
151
+ #### `get joints(): readonly JointRecord[]` — Joint records that attach this part to other parts in the kit.
396
152
 
397
- ```ts
398
- addGeometry(sketch: Sketch): void
399
- ```
153
+ #### `get quantity(): number` — Requested quantity of this part in the kit. Defaults to `1`.
400
154
 
401
- #### `subtractGeometry()` — Subtract geometry (e.g. slot cuts) from the part profile.
155
+ #### `addGeometry(sketch: Sketch): void` — Add geometry (e.g. protruding tabs) to the part profile.
402
156
 
403
- ```ts
404
- subtractGeometry(sketch: Sketch): void
405
- ```
157
+ #### `subtractGeometry(sketch: Sketch): void` — Subtract geometry (e.g. slot cuts) from the part profile.
406
158
 
407
- #### `addJoint()` — Record a joint connection for assembly preview.
159
+ #### `addJoint(record: JointRecord): void` — Record a joint connection for assembly preview.
408
160
 
409
- ```ts
410
- addJoint(record: JointRecord): void
411
- ```
412
-
413
- #### `profile()` — Final 2D profile with joints and optional kerf compensation.
414
-
415
- ```ts
416
- profile(kerf?: number): Sketch
417
- ```
161
+ **`JointRecord`**
162
+ - `foldAngle: number` — Fold angle in degrees. Default: 90.
163
+ - Also: `type: "finger" | "tabSlot" | "snapFit"`, `partA: string`, `partB: string`, `edgeA: string`, `edgeB: string`.
418
164
 
419
- #### `solid()` — 3D solid extrude the profile by material thickness.
165
+ #### `profile(kerf?: number): Sketch` — Final 2D profile with joints and optional kerf compensation.
420
166
 
421
- ```ts
422
- solid(kerf?: number): Shape
423
- ```
167
+ #### `solid(kerf?: number): Shape` — 3D solid — extrude the profile by material thickness.
424
168
 
425
169
  ### `LaserKit`
426
170
 
427
- #### `kerf()` — Laser kerf in mm.
171
+ #### `get kerf(): number` — Laser kerf in mm.
428
172
 
429
- ```ts
430
- get kerf(): number
431
- ```
173
+ #### `get parts(): readonly FlatPart[]` — All registered parts (flat, in insertion order).
432
174
 
433
- #### `parts()` — All registered parts (flat, in insertion order).
175
+ #### `get material(): string` — Default material label.
434
176
 
435
- ```ts
436
- get parts(): readonly FlatPart[]
437
- ```
177
+ #### `get sheetWidth(): number` — Stock sheet width in mm.
438
178
 
439
- #### `material()` — Default material label.
179
+ #### `get sheetHeight(): number` — Stock sheet height in mm.
440
180
 
441
- ```ts
442
- get material(): string
443
- ```
181
+ #### `addPart(part: FlatPart, overrides?: { qty?: number; }): this` — Register a flat part with this kit. Assigns a sequential part number and records the quantity.
444
182
 
445
- #### `sheetWidth()` — Stock sheet width in mm.
183
+ #### `cutSheets(): CuttingLayoutResult` — Generate nested cut sheets using guillotine bin-packing.
446
184
 
447
- ```ts
448
- get sheetWidth(): number
449
- ```
185
+ #### `bom(): LaserKitBomEntry[]` — Bill of materials listing every part with dimensions.
450
186
 
451
- #### `sheetHeight()`Stock sheet height in mm.
187
+ #### `partSvgs(): Map<string, string>` Individual SVG string for each part profile, keyed by part name.
452
188
 
453
- ```ts
454
- get sheetHeight(): number
455
- ```
189
+ #### `inventorySvg(): string` — Combined inventory SVG showing all parts in a labeled grid.
456
190
 
457
- #### `addPart()` — Register a flat part with this kit. Assigns a sequential part number and records the quantity.
191
+ #### `assemblyPreview(options?: Omit<AssemblyPreviewOptions, "kerf">): AssemblyPreviewResult` — 3D fold-up preview of the assembled kit.
458
192
 
459
- ```ts
460
- addPart(part: FlatPart, overrides?: { qty?: number; }): this
461
- ```
193
+ **`AssemblyPreviewOptions`**
194
+ - `kerf?: number` Kerf compensation passed to each part's solid(). Default: 0
195
+ - `fold?: number` — Fold amount: 0 = flat layout, 1 = fully assembled. Default: 1
196
+ - `explode?: number` — Explode distance: 0 = assembled, >0 = parts spread outward. Default: 0
462
197
 
463
- #### `cutSheets()` — Generate nested cut sheets using guillotine bin-packing.
198
+ #### `assemblyInstructions(options?: AssemblyInstructionsOptions): AssemblyInstructionsResult` — Step-by-step assembly instructions.
464
199
 
465
- ```ts
466
- cutSheets(): CuttingLayoutResult
467
- ```
200
+ **`AssemblyInstructionsOptions`**
201
+ - `rootPart?: string` — Part to start from. Default: part with most joint connections.
468
202
 
469
- #### [`bom()`](/docs/output#bom)Bill of materials listing every part with dimensions.
203
+ #### `formatInstructions(options?: AssemblyInstructionsOptions): string` — Human-readable assembly instructions text.
470
204
 
471
- ```ts
472
- bom(): LaserKitBomEntry[]
473
- ```
205
+ ---
474
206
 
475
- #### `partSvgs()` — Individual SVG string for each part profile, keyed by part name.
207
+ ## Constants
476
208
 
477
- ```ts
478
- partSvgs(): Map<string, string>
479
- ```
209
+ ### `SHEET_METAL_EDGES`
480
210
 
481
- #### `inventorySvg()` — Combined inventory SVG showing all parts in a labeled grid.
211
+ ### `Laser`
482
212
 
483
- ```ts
484
- inventorySvg(): string
485
- ```
213
+ Laser-cutting namespace — flat parts, joints, kits, kerf data, and assembly previews.
486
214
 
487
- #### `assemblyPreview()` 3D fold-up preview of the assembled kit.
215
+ **Workflow:** create parts with `Laser.panel()` / `Laser.part()`, connect them with `Laser.fingerJoint()` / `Laser.tabSlot()`, then collect them in a `Laser.kit()` for BOM, sheet nesting, SVG export, and assembly previews. The kit applies kerf compensation automatically from its `kerf` option.
488
216
 
489
- ```ts
490
- assemblyPreview(options?: Omit<AssemblyPreviewOptions, "kerf">): AssemblyPreviewResult
491
- ```
217
+ - `panel: (name: string, width: number, height: number, thickness: number, options?: FlatPartOptions) => FlatPart` — Create a rectangular flat panel with 4 named edges.
492
218
 
493
- #### `assemblyInstructions()` Step-by-step assembly instructions.
219
+ Profile origin at the bottom-left corner. Edges: `bottom` (y=0), `right` (x=width), `top` (y=height), `left` (x=0). Edge traversal follows CCW winding order.
220
+ - `part: (name: string, profile: Sketch, thickness: number, edges?: Record<string, { start: Vec2; end: Vec2; }>, options?: FlatPartOptions) => FlatPart` — Create a flat part from an arbitrary 2D profile with user-named edges.
494
221
 
495
- ```ts
496
- assemblyInstructions(options?: AssemblyInstructionsOptions): AssemblyInstructionsResult
497
- ```
222
+ Edge normals are computed automatically (perpendicular to the edge direction, rotated 90 degrees clockwise).
223
+ - `fingerJoint: (partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: FingerJointOptions & { foldAngle?: number; }) => void` — Connect two parts with finger joints along the named edges.
498
224
 
499
- #### `formatInstructions()` Human-readable assembly instructions text.
225
+ Adds finger geometry to partA's edge and cuts matching slots from partB's edge; the joint is also recorded on both parts for assembly previews and instructions.
226
+ - `tabSlot: (partA: FlatPart, edgeNameA: string, partB: FlatPart, edgeNameB: string, options?: TabSlotOptions & { foldAngle?: number; }) => void` — Connect two parts with tab-and-slot joints along the named edges.
500
227
 
501
- ```ts
502
- formatInstructions(options?: AssemblyInstructionsOptions): string
503
- ```
228
+ Adds tab geometry to partA's edge and cuts matching slots from partB's edge; the joint is also recorded on both parts for assembly previews and instructions.
229
+ - `kit: (options?: LaserKitOptions) => LaserKit` — Create a LaserKit container for a flat-pack project.
504
230
 
505
- ---
231
+ The kit collects FlatPart instances, assigns sequential part numbers, generates a bill of materials, nests parts onto cut sheets, exports SVG views, and produces kerf-compensated assembly previews and step-by-step instructions. Kerf compensation uses the kit's `kerf` option (default 0.2 mm).
232
+ - `assemblyPreview: (parts: FlatPart[], joints: JointRecord[], options?: AssemblyPreviewOptions) => AssemblyPreviewResult` — Generate a 3D assembly preview from flat parts and their joint records.
506
233
 
507
- ## Constants
234
+ Prefer `Laser.kit(...).assemblyPreview(options)` — the kit collects the joint records and applies its kerf automatically. This standalone form defaults `kerf` to 0.
235
+ - `instructions: (parts: FlatPart[], joints: JointRecord[], options?: AssemblyInstructionsOptions) => AssemblyInstructionsResult` — Generate step-by-step assembly instructions from flat parts and joints.
508
236
 
509
- ### `SHEET_METAL_EDGES`
237
+ Prefer `Laser.kit(...).assemblyInstructions(options)` — the kit collects the joint records for you. Steps are ordered BFS from the most-connected (base) part so each new part attaches to already-assembled parts.
238
+ - `formatInstructions: (result: AssemblyInstructionsResult) => string` — Format assembly instructions as a human-readable text document.
239
+
240
+ Includes a "Step 0" preamble identifying the base part, followed by numbered steps, and a note about any orphan parts.
241
+ - `lookupKerf: (material: string, thickness: number, laserType?: string) => number | undefined` — Look up kerf for a material + thickness + laser combo in `Laser.COMMON_KERFS`.
510
242
 
511
- ### `COMMON_KERFS`
243
+ If `laserType` is omitted, returns the first matching material + thickness entry. Returns `undefined` when no match is found. Always test-cut to verify kerf for a specific machine.
244
+ - `COMMON_KERFS: MaterialKerfEntry[]` — Common full-kerf values by material, thickness, and laser type.
512
245
 
513
- Common kerf values. Users should always test-cut to verify for their specific setup.
246
+ Reference data only — kerf varies per machine, lens, and focus; always test-cut to verify before committing a sheet.