forgecad 0.9.2 → 0.9.3

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 (79) hide show
  1. package/LICENSE +7 -5
  2. package/README.md +1 -1
  3. package/README.public.md +24 -2
  4. package/dist/assets/{AdminPage-Bs4PiK00.js → AdminPage-4jihcEk_.js} +1 -1
  5. package/dist/assets/{BlogPage-DVmgN0ma.js → BlogPage-BvzruKtw.js} +1 -1
  6. package/dist/assets/{DocsPage-BP6wlsBN.js → DocsPage-DHbd-WS-.js} +13 -13
  7. package/dist/assets/{EditorApp-Arw2NnGJ.js → EditorApp-C5P2rBfh.js} +433 -84
  8. package/dist/assets/{EditorApp-VY9lXx0N.css → EditorApp-DS0AIUrZ.css} +25 -0
  9. package/dist/assets/{EmbedViewer-qgQiOahL.js → EmbedViewer-B70wQwlE.js} +2 -2
  10. package/dist/assets/{LandingPageProofDriven-DvhtmWOz.js → LandingPageProofDriven-DIsYTnep.js} +1 -1
  11. package/dist/assets/{PricingPage-Ck3CP2ti.css → PricingPage-BMedqFef.css} +48 -0
  12. package/dist/assets/{PricingPage-657oLvWh.js → PricingPage-YPOr12pP.js} +34 -6
  13. package/dist/assets/{SettingsPage-wNy3_2yn.js → SettingsPage-rntoyJ3b.js} +10 -13
  14. package/dist/assets/{app-BdBoMQeO.js → app-CWucmnLZ.js} +801 -1208
  15. package/dist/assets/cli/{render-Ci3jjyT1.js → render-DZHmUySW.js} +214 -23
  16. package/dist/assets/copy-CQKQppF-.js +8 -0
  17. package/dist/assets/{evalWorker-CMCAbK8r.js → evalWorker-C3dKxi9Y.js} +1117 -95
  18. package/dist/assets/{manifold-BMn-8Vf8.js → manifold-CQ3FhfWB.js} +1 -1
  19. package/dist/assets/{manifold-jlYQ6E5R.js → manifold-CU0G1yYL.js} +1 -1
  20. package/dist/assets/{manifold-DbyILno4.js → manifold-CYWZMfjB.js} +2 -2
  21. package/dist/assets/{renderSceneState-DAnqvxSt.js → renderSceneState-BBUrnsUN.js} +1 -1
  22. package/dist/assets/{reportWorker-BcRVMHK-.js → reportWorker-BhZ7DjxQ.js} +1091 -95
  23. package/dist/assets/{sectionPlaneMath-DXJ_TdIW.js → sectionPlaneMath-BxfokaJE.js} +1091 -95
  24. package/dist/cli/render.html +1 -1
  25. package/dist/docs/index.html +2 -2
  26. package/dist/docs-raw/AI/usage.md +182 -89
  27. package/dist/docs-raw/API/core/concepts.md +26 -0
  28. package/dist/docs-raw/CLI.md +58 -37
  29. package/dist/docs-raw/INDEX.md +81 -64
  30. package/dist/docs-raw/cli-monetization.md +9 -8
  31. package/dist/docs-raw/generated/concepts.md +111 -4
  32. package/dist/docs-raw/generated/core.md +2 -0
  33. package/dist/docs-raw/generated/curves.md +480 -1
  34. package/dist/docs-raw/generated/output.md +1 -0
  35. package/dist/docs-raw/generated/sketch.md +2 -0
  36. package/dist/docs-raw/generated/viewport.md +81 -3
  37. package/dist/docs-raw/product/user-outreach-email-templates.md +159 -0
  38. package/dist/docs-raw/skills/forgecad-image-replicator.md +1 -1
  39. package/dist/docs-raw/skills/forgecad-make-a-model.md +33 -4
  40. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +1 -1
  41. package/dist/docs-raw/skills/forgecad-project.md +1 -1
  42. package/dist/docs-raw/skills/forgecad-render-inspect.md +1 -1
  43. package/dist/docs-raw/skills/forgecad.md +2 -1
  44. package/dist/docs-raw/welcome.md +85 -137
  45. package/dist/index.html +1 -1
  46. package/dist/llms.txt +4 -3
  47. package/dist/sitemap.xml +6 -6
  48. package/dist-cli/forgecad.js +1413 -219
  49. package/dist-cli/forgecad.js.map +1 -1
  50. package/dist-skill/CONTEXT.md +594 -5
  51. package/dist-skill/SKILL-dev.md +2 -1
  52. package/dist-skill/SKILL.md +2 -1
  53. package/dist-skill/docs/API/core/concepts.md +26 -0
  54. package/dist-skill/docs/CLI.md +58 -37
  55. package/dist-skill/docs/generated/core.md +2 -0
  56. package/dist-skill/docs/generated/curves.md +480 -1
  57. package/dist-skill/docs/generated/output.md +1 -0
  58. package/dist-skill/docs/generated/sketch.md +2 -0
  59. package/dist-skill/docs/generated/viewport.md +81 -3
  60. package/dist-skill/docs-dev/API/core/concepts.md +26 -0
  61. package/dist-skill/docs-dev/CLI.md +58 -37
  62. package/dist-skill/docs-dev/generated/core.md +2 -0
  63. package/dist-skill/docs-dev/generated/curves.md +480 -1
  64. package/dist-skill/docs-dev/generated/output.md +1 -0
  65. package/dist-skill/docs-dev/generated/sketch.md +2 -0
  66. package/dist-skill/docs-dev/generated/viewport.md +81 -3
  67. package/dist-skill/library/README.md +0 -1
  68. package/dist-skill/library/forgecad-image-replicator/SKILL.md +1 -1
  69. package/dist-skill/library/forgecad-make-a-model/SKILL.md +33 -4
  70. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  71. package/dist-skill/library/forgecad-project/SKILL.md +1 -1
  72. package/dist-skill/library/forgecad-render-inspect/SKILL.md +1 -1
  73. package/examples/api/conformal-product-ribbon.forge.js +77 -0
  74. package/examples/api/render-labels.forge.js +33 -0
  75. package/examples/api/text2d-basics.forge.js +6 -3
  76. package/package.json +1 -1
  77. package/dist-skill/library/forgecad-deep-dive/SKILL.md +0 -120
  78. package/dist-skill/library/forgecad-deep-dive/agents/openai.yaml +0 -4
  79. package/dist-skill/library/forgecad-deep-dive/references/output-shape.md +0 -64
@@ -18,9 +18,11 @@ Smooth curves, lofted surfaces, swept solids, splines, and high-level product sk
18
18
  - [QuinticHermiteCurve3D](#quintichermitecurve3d)
19
19
  - [ProductSkin](#productskin)
20
20
  - [ProductSurfaceRef](#productsurfaceref)
21
+ - [ProductSurfaceBuilder](#productsurfacebuilder)
21
22
  - [ProductSkinBuilder](#productskinbuilder)
22
23
  - [ProductStationBuilder](#productstationbuilder)
23
24
  - [ProductPanelBuilder](#productpanelbuilder)
25
+ - [ProductRibbonBuilder](#productribbonbuilder)
24
26
  - [ProductSpoutBuilder](#productspoutbuilder)
25
27
  - [ProductHandleBuilder](#producthandlebuilder)
26
28
  - [ProductHandleFeature](#producthandlefeature)
@@ -901,12 +903,31 @@ integrate(...details: Shape[]): Shape
901
903
  diagnostics(): ProductSkinDiagnostics
902
904
  ```
903
905
 
906
+ **`ProductSkinDiagnostics`**: `representation: ProductSkinRepresentation`, `lowering: string[]`, `warnings: string[]`, `stationNames: string[]`, `railNames: string[]`
907
+
908
+ **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
909
+
910
+ `"exact" | "sampled" | "mixed" | "fallback"`
911
+
904
912
  #### `uv()` — Create a side/u/v surface-ref query on this skin.
905
913
 
906
914
  ```ts
907
915
  uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
908
916
  ```
909
917
 
918
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
919
+
920
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
921
+
922
+ **`ProductSkinRefQuery`**
923
+
924
+ | Option | Type | Description |
925
+ |--------|------|-------------|
926
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
927
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
928
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
929
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
930
+
910
931
  #### `ref()` — Resolve a named ref published with Product.skin().refs(...).
911
932
 
912
933
  ```ts
@@ -919,18 +940,32 @@ ref(name: string): ProductSurfaceRef
919
940
  curveOnSurface(name: string, points: Array<Partial<ProductSkinRefQuery> & { side: ProductSkinSide; }>): ProductSurfaceRef[]
920
941
  ```
921
942
 
943
+ #### `surface()` — Create a fluent surface helper for refs and conformal features on one side of this skin.
944
+
945
+ Use this when several refs or ribbons share the same skin side; side-local helpers keep path points concise and make it harder to mix sides accidentally.
946
+
947
+ ```ts
948
+ surface(side: ProductSkinSide): ProductSurfaceBuilder
949
+ ```
950
+
922
951
  #### `stationAt()` — Interpolate center, width, and depth at a normalized v or absolute axis value.
923
952
 
924
953
  ```ts
925
- stationAt(vOrAxis: number): { center: Vec3; width: number; depth: number; dWidth: number; dDepth: number; axisValue: number; }
954
+ stationAt(vOrAxis: number): { ... }
926
955
  ```
927
956
 
957
+ **`ProductProfileKind`**
958
+
959
+ `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
960
+
928
961
  #### `frame()` — Build a local surface frame from a side/u/v query.
929
962
 
930
963
  ```ts
931
964
  frame(query: ProductSkinRefQuery): ProductSurfaceFrame
932
965
  ```
933
966
 
967
+ **`ProductSurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentU: Vec3`, `tangentV: Vec3`, `matrix: Mat4`, `skin: string`, `representation: ProductSkinRepresentation`
968
+
934
969
  ### `ProductSurfaceRef`
935
970
 
936
971
  **Properties:**
@@ -947,6 +982,25 @@ frame(query: ProductSkinRefQuery): ProductSurfaceFrame
947
982
  frame(overrides?: Partial<ProductSkinRefQuery>): ProductSurfaceFrame
948
983
  ```
949
984
 
985
+ **`ProductSkinRefQuery`**
986
+
987
+ | Option | Type | Description |
988
+ |--------|------|-------------|
989
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
990
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
991
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
992
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
993
+
994
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
995
+
996
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
997
+
998
+ **`ProductSurfaceFrame`**: `point: Vec3`, `normal: Vec3`, `tangentU: Vec3`, `tangentV: Vec3`, `matrix: Mat4`, `skin: string`, `representation: ProductSkinRepresentation`
999
+
1000
+ **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1001
+
1002
+ `"exact" | "sampled" | "mixed" | "fallback"`
1003
+
950
1004
  #### `with()` — Return a copy of this ref with side/u/v/offset overrides.
951
1005
 
952
1006
  ```ts
@@ -959,12 +1013,98 @@ with(overrides: Partial<ProductSkinRefQuery>): ProductSurfaceRef
959
1013
  attach(detail: Shape | ShapeGroup, options?: ProductAttachOptions): Shape | ShapeGroup
960
1014
  ```
961
1015
 
1016
+ `ProductAttachOptions`: `{ offset?: number, inset?: number }`
1017
+
962
1018
  #### `querySpec()` — Return the serializable side/u/v query behind this ref.
963
1019
 
964
1020
  ```ts
965
1021
  querySpec(): ProductSkinRefQuery
966
1022
  ```
967
1023
 
1024
+ ### `ProductSurfaceBuilder`
1025
+
1026
+ Fluent helper bound to one ProductSkin side for refs and side-local conformal features.
1027
+
1028
+ **Properties:**
1029
+
1030
+ | Property | Type | Description |
1031
+ |----------|------|-------------|
1032
+ | `side` | `ProductSkinSide` | — |
1033
+
1034
+ **Methods:**
1035
+
1036
+ #### `ref()` — Create a ref on this skin side.
1037
+
1038
+ ```ts
1039
+ ref(u?: number, v?: number, offset?: number): ProductSurfaceRef
1040
+ ```
1041
+
1042
+ #### `uv()` — Create a side/u/v query on this skin side.
1043
+
1044
+ ```ts
1045
+ uv(u?: number, v?: number, offset?: number): ProductSkinRefQuery
1046
+ ```
1047
+
1048
+ **`ProductSkinRefQuery`**
1049
+
1050
+ | Option | Type | Description |
1051
+ |--------|------|-------------|
1052
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1053
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1054
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1055
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1056
+
1057
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1058
+
1059
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1060
+
1061
+ #### `ribbon()` — Start a conformal ribbon on this skin side.
1062
+
1063
+ Path points use side-local `u`/`v` coordinates; this builder supplies the side. The returned ProductRibbonBuilder is already bound to the source skin and can be further configured before build(). Use `widthSamples` >= 3 when the ribbon must visibly wrap over curved product sections instead of behaving like a flat strip.
1064
+
1065
+ ```ts
1066
+ ribbon(name: string, points: ProductSurfacePathPoint[], options?: ProductRibbonBuildOptions): ProductRibbonBuilder
1067
+ ```
1068
+
1069
+ **`ProductSurfacePathPoint`**
1070
+ - `u?: number` — Across-side parameter on the bound side. Defaults to 0.5.
1071
+ - `v?: number` — Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5.
1072
+ - `offset?: number` — Positive distance away from the surface along the resolved normal.
1073
+
1074
+ **`ProductRibbonBuildOptions`** — Options shared by Product.ribbon() builders and Product.surface(...).ribbon(...).
1075
+
1076
+ | Option | Type | Description |
1077
+ |--------|------|-------------|
1078
+ | `width?` | `number` | Width across the surface in millimeters. |
1079
+ | `thickness?` | `number` | Solid thickness outward from the source surface in millimeters. |
1080
+ | `offset?` | `number` | Positive clearance between the source surface and the ribbon's inner face. |
1081
+ | `samples?` | `number` | Samples along the ribbon path. Higher values bend more smoothly. |
1082
+ | `widthSamples?` | `number` | Samples across the ribbon width. Use 3+ to visibly wrap over curved cross-sections. |
1083
+ | `resolution?` | `number` | Tessellation resolution passed to the lowered NURBS surface. |
1084
+ | `material?` | `ProductMaterial` | Apply a product material preset to the ribbon. |
1085
+ | `color?` | `string` | Apply a simple color override. |
1086
+
1087
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1088
+
1089
+ **`ShapeMaterialProps`**
1090
+
1091
+ | Option | Type | Description |
1092
+ |--------|------|-------------|
1093
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1094
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1095
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1096
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1097
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1098
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1099
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1100
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1101
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1102
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1103
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1104
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1105
+ | `specularColor?` | `string` | Specular highlight tint. |
1106
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1107
+
968
1108
  ### `ProductSkinBuilder`
969
1109
 
970
1110
  **Properties:**
@@ -981,24 +1121,55 @@ querySpec(): ProductSkinRefQuery
981
1121
  axis(axis: ProductSkinAxis): this
982
1122
  ```
983
1123
 
1124
+ **`ProductSkinAxis`** — Primary world axis used to order ProductSkin loft stations.
1125
+
1126
+ `"X" | "Y" | "Z"`
1127
+
984
1128
  #### `stations()` — Set named cross-section stations for the product skin.
985
1129
 
986
1130
  ```ts
987
1131
  stations(stations: Array<ProductStationBuilder | ProductStationSpec>): this
988
1132
  ```
989
1133
 
1134
+ `ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
1135
+
1136
+ `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1137
+
1138
+ **`ProductProfileKind`**
1139
+
1140
+ `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1141
+
990
1142
  #### `rails()` — Attach guide rails as ProductSkin IR metadata and diagnostics.
991
1143
 
992
1144
  ```ts
993
1145
  rails(rails: Record<string, ProductRailSpec>): this
994
1146
  ```
995
1147
 
1148
+ `ProductRailSpec`: `{ kind: ProductRailKind, points: Vec3[], degree?: number, name?: string }`
1149
+
1150
+ **`ProductRailKind`**
1151
+
1152
+ `"bezier" | "nurbs" | "polyline"`
1153
+
996
1154
  #### `ref()` — Publish a named semantic surface ref on the skin.
997
1155
 
998
1156
  ```ts
999
1157
  ref(name: string, query: ProductSkinRefQuery): this
1000
1158
  ```
1001
1159
 
1160
+ **`ProductSkinRefQuery`**
1161
+
1162
+ | Option | Type | Description |
1163
+ |--------|------|-------------|
1164
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1165
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1166
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1167
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1168
+
1169
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1170
+
1171
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1172
+
1002
1173
  #### `refs()` — Publish multiple named semantic surface refs on the skin.
1003
1174
 
1004
1175
  ```ts
@@ -1017,6 +1188,27 @@ uv(side: ProductSkinSide, u?: number, v?: number): ProductSkinRefQuery
1017
1188
  material(material: ProductMaterial): this
1018
1189
  ```
1019
1190
 
1191
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1192
+
1193
+ **`ShapeMaterialProps`**
1194
+
1195
+ | Option | Type | Description |
1196
+ |--------|------|-------------|
1197
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1198
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1199
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1200
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1201
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1202
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1203
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1204
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1205
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1206
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1207
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1208
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1209
+ | `specularColor?` | `string` | Specular highlight tint. |
1210
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1211
+
1020
1212
  #### `color()` — Apply a simple color override to the lowered skin.
1021
1213
 
1022
1214
  ```ts
@@ -1087,6 +1279,8 @@ oval(width: number, depth: number, options?: { segments?: number; }): this
1087
1279
  superEllipse(width: number, depth: number, options?: ProductStationSuperEllipseOptions): this
1088
1280
  ```
1089
1281
 
1282
+ `ProductStationSuperEllipseOptions`: `{ segments?: number, exponent?: number }`
1283
+
1090
1284
  #### [`roundedRect()`](/docs/sketch#roundedrect) — Use a rounded-rectangle cross-section with the given corner radius.
1091
1285
 
1092
1286
  ```ts
@@ -1117,6 +1311,14 @@ crown(amount: number): this
1117
1311
  toSpec(): ProductStationSpec
1118
1312
  ```
1119
1313
 
1314
+ `ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
1315
+
1316
+ `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1317
+
1318
+ **`ProductProfileKind`**
1319
+
1320
+ `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1321
+
1120
1322
  ### `ProductPanelBuilder`
1121
1323
 
1122
1324
  **Properties:**
@@ -1157,6 +1359,27 @@ thickness(thickness: number): this
1157
1359
  material(material: ProductMaterial): this
1158
1360
  ```
1159
1361
 
1362
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1363
+
1364
+ **`ShapeMaterialProps`**
1365
+
1366
+ | Option | Type | Description |
1367
+ |--------|------|-------------|
1368
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1369
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1370
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1371
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1372
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1373
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1374
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1375
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1376
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1377
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1378
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1379
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1380
+ | `specularColor?` | `string` | Specular highlight tint. |
1381
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1382
+
1160
1383
  #### `color()` — Apply a simple color override to the panel.
1161
1384
 
1162
1385
  ```ts
@@ -1175,6 +1398,202 @@ build(): Shape
1175
1398
  attachTo(ref: ProductRefInput, options?: ProductPanelAttachOptions): Shape
1176
1399
  ```
1177
1400
 
1401
+ **`ProductRefInput`**
1402
+
1403
+ `ProductSurfaceRef`
1404
+
1405
+ `ProductAttachOptions`: `{ offset?: number, inset?: number }`
1406
+
1407
+ `ProductPanelAttachOptions`: `{ at?: Partial<ProductSkinRefQuery>, thickness?: number, material?: ProductMaterial, color?: string }`
1408
+
1409
+ **`ProductSkinRefQuery`**
1410
+
1411
+ | Option | Type | Description |
1412
+ |--------|------|-------------|
1413
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1414
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1415
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1416
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1417
+
1418
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1419
+
1420
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1421
+
1422
+ ### `ProductRibbonBuilder`
1423
+
1424
+ Builder for thin trim, label, grip, and split-line features that bend with a ProductSkin surface.
1425
+
1426
+ **Properties:**
1427
+
1428
+ | Property | Type | Description |
1429
+ |----------|------|-------------|
1430
+ | `name` | `string` | — |
1431
+
1432
+ **Methods:**
1433
+
1434
+ #### `on()` — Follow a ProductSkin with side/u/v path queries or refs.
1435
+
1436
+ This is the highest-fidelity mode because every interpolated sample is resolved through ProductSkin.frame(), so the ribbon bends along the selected side as station width/depth changes. All query path points must stay on one side; split side transitions into separate ribbons.
1437
+
1438
+ ```ts
1439
+ on(skin: ProductSkin, points: ProductRibbonPathPoint[], options?: ProductRibbonBuildOptions): this
1440
+ ```
1441
+
1442
+ **`ProductRibbonPathPoint`** — Path point for Product.ribbon().on(...): either a side/u/v query or a resolved surface ref.
1443
+
1444
+ `ProductSkinRefQuery | ProductSurfaceRef`
1445
+
1446
+ **`ProductSkinRefQuery`**
1447
+
1448
+ | Option | Type | Description |
1449
+ |--------|------|-------------|
1450
+ | `side` | `ProductSkinSide` | Side of the product skin. `front` is the minimum axis cap, `rear`/`back` is the maximum axis cap. |
1451
+ | `u?` | `number` | Across-side parameter for side refs. Defaults to 0.5. |
1452
+ | `v?` | `number` | Along-axis parameter, 0 at the first cap and 1 at the rear/back cap. Defaults to 0.5. |
1453
+ | `offset?` | `number` | Positive distance away from the surface along the resolved normal. |
1454
+
1455
+ **`ProductSkinSide`** — Semantic side of a ProductSkin. `back` is accepted as an alias for `rear`.
1456
+
1457
+ `"left" | "right" | "top" | "bottom" | "front" | "rear" | "back"`
1458
+
1459
+ **`ProductRibbonBuildOptions`** — Options shared by Product.ribbon() builders and Product.surface(...).ribbon(...).
1460
+
1461
+ | Option | Type | Description |
1462
+ |--------|------|-------------|
1463
+ | `width?` | `number` | Width across the surface in millimeters. |
1464
+ | `thickness?` | `number` | Solid thickness outward from the source surface in millimeters. |
1465
+ | `offset?` | `number` | Positive clearance between the source surface and the ribbon's inner face. |
1466
+ | `samples?` | `number` | Samples along the ribbon path. Higher values bend more smoothly. |
1467
+ | `widthSamples?` | `number` | Samples across the ribbon width. Use 3+ to visibly wrap over curved cross-sections. |
1468
+ | `resolution?` | `number` | Tessellation resolution passed to the lowered NURBS surface. |
1469
+ | `material?` | `ProductMaterial` | Apply a product material preset to the ribbon. |
1470
+ | `color?` | `string` | Apply a simple color override. |
1471
+
1472
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1473
+
1474
+ **`ShapeMaterialProps`**
1475
+
1476
+ | Option | Type | Description |
1477
+ |--------|------|-------------|
1478
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1479
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1480
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1481
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1482
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1483
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1484
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1485
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1486
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1487
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1488
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1489
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1490
+ | `specularColor?` | `string` | Specular highlight tint. |
1491
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1492
+
1493
+ #### `fromRefs()` — Follow explicit surface refs.
1494
+
1495
+ Useful for named refs or paths assembled elsewhere. The builder resolves each ref frame and interpolates between those frames; use on(skin, points) when you need full skin-side sampling between sparse control points.
1496
+
1497
+ ```ts
1498
+ fromRefs(points: ProductSurfaceRef[], options?: ProductRibbonBuildOptions): this
1499
+ ```
1500
+
1501
+ #### `width()` — Set ribbon width in millimeters.
1502
+
1503
+ ```ts
1504
+ width(width: number): this
1505
+ ```
1506
+
1507
+ #### `thickness()` — Set solid thickness outward from the source surface in millimeters.
1508
+
1509
+ ```ts
1510
+ thickness(thickness: number): this
1511
+ ```
1512
+
1513
+ #### `offset()` — Set positive clearance between the source surface and the ribbon's inner face.
1514
+
1515
+ ```ts
1516
+ offset(offset: number): this
1517
+ ```
1518
+
1519
+ #### `samples()` — Set samples along the path.
1520
+
1521
+ ```ts
1522
+ samples(samples: number): this
1523
+ ```
1524
+
1525
+ #### `widthSamples()` — Set samples across the width. Use 3+ to bend over curved cross-sections.
1526
+
1527
+ ```ts
1528
+ widthSamples(samples: number): this
1529
+ ```
1530
+
1531
+ #### `resolution()` — Set NURBS tessellation resolution.
1532
+
1533
+ ```ts
1534
+ resolution(resolution: number): this
1535
+ ```
1536
+
1537
+ #### `material()` — Apply a product material preset.
1538
+
1539
+ ```ts
1540
+ material(material: ProductMaterial): this
1541
+ ```
1542
+
1543
+ #### `color()` — Apply a simple color override.
1544
+
1545
+ ```ts
1546
+ color(color: string): this
1547
+ ```
1548
+
1549
+ #### `build()` — Build a conformal ribbon as a thin NURBS surface solid.
1550
+
1551
+ ```ts
1552
+ build(options?: ProductRibbonBuildOptions): Shape
1553
+ ```
1554
+
1555
+ #### `buildWithDiagnostics()` — Build a conformal ribbon and return surface-feature diagnostics.
1556
+
1557
+ Use this while validating API usage or model fidelity; diagnostics report sampling counts, side-span clamping, lowering mode, and warnings that should be visible in reviews.
1558
+
1559
+ ```ts
1560
+ buildWithDiagnostics(options?: ProductRibbonBuildOptions): ProductRibbonResult
1561
+ ```
1562
+
1563
+ **`ProductRibbonResult`** — Shape plus diagnostics returned by ProductRibbonBuilder.buildWithDiagnostics().
1564
+ - `shape: Shape` — Lowered conformal ribbon shape.
1565
+ - `diagnostics: ProductRibbonDiagnostics` — Sampling and lowering diagnostics for the returned shape.
1566
+
1567
+ **`ProductRibbonDiagnostics`** — Diagnostics describing how a conformal ribbon was sampled and lowered.
1568
+
1569
+ | Option | Type | Description |
1570
+ |--------|------|-------------|
1571
+ | `name` | `string` | Ribbon shape name. |
1572
+ | `skin?` | `string` | Source skin name when the ribbon follows a ProductSkin directly. |
1573
+ | `side?` | `ProductSkinSide` | Source skin side when all path points are on one semantic side. |
1574
+ | `pathPointCount` | `number` | Number of control path points supplied before interpolation. |
1575
+ | `width` | `number` | Final ribbon width in millimeters. |
1576
+ | `thickness` | `number` | Final ribbon solid thickness in millimeters. |
1577
+ | `offset` | `number` | Final normal offset from the source surface in millimeters. |
1578
+ | `samples` | `number` | Final sample count along the ribbon path. |
1579
+ | `widthSamples` | `number` | Final sample count across the ribbon width. |
1580
+ | `resolution` | `number` | NURBS tessellation resolution used for the lowered surface. |
1581
+ | `lowering` | `"nurbsSurface"` | Lowering primitive used for the ribbon shape. |
1582
+ | `expectedFidelity` | `ProductSkinRepresentation` | Expected fidelity inherited from the source skin/ref sampling mode. |
1583
+ | `clampedUCount` | `number` | Number of generated width samples clamped to the valid side span. |
1584
+ | `maxUClampDistance` | `number` | Largest absolute u-distance lost to side-span clamping. |
1585
+ | `warnings` | `string[]` | Non-fatal sampling and lowering warnings. |
1586
+
1587
+ **`ProductSkinRepresentation`** — Reported lowering mode for ProductSkin and conformal feature diagnostics.
1588
+
1589
+ `"exact" | "sampled" | "mixed" | "fallback"`
1590
+
1591
+ #### `diagnostics()` — Return diagnostics from the most recent build, if this builder has been built.
1592
+
1593
+ ```ts
1594
+ diagnostics(): ProductRibbonDiagnostics | undefined
1595
+ ```
1596
+
1178
1597
  ### `ProductSpoutBuilder`
1179
1598
 
1180
1599
  **Properties:**
@@ -1197,6 +1616,14 @@ from(ref: ProductSurfaceRef): this
1197
1616
  sections(sections: Array<Sketch | ProductStationBuilder | ProductStationSpec>): this
1198
1617
  ```
1199
1618
 
1619
+ `ProductStationSpec`: `{ name: string, center: Vec3, profile: ProductStationProfile, crown?: number }`
1620
+
1621
+ `ProductStationProfile`: `{ sketch: Sketch, width: number, depth: number, kind: ProductProfileKind, radius?: number, exponent?: number }`
1622
+
1623
+ **`ProductProfileKind`**
1624
+
1625
+ `"oval" | "roundedRect" | "circle" | "superEllipse" | "custom"`
1626
+
1200
1627
  #### `projection()` — Set the projection length along the source ref normal.
1201
1628
 
1202
1629
  ```ts
@@ -1215,6 +1642,27 @@ edgeLength(value: number): this
1215
1642
  material(material: ProductMaterial): this
1216
1643
  ```
1217
1644
 
1645
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1646
+
1647
+ **`ShapeMaterialProps`**
1648
+
1649
+ | Option | Type | Description |
1650
+ |--------|------|-------------|
1651
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1652
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1653
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1654
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1655
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1656
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1657
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1658
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1659
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1660
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1661
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1662
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1663
+ | `specularColor?` | `string` | Specular highlight tint. |
1664
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1665
+
1218
1666
  #### `color()` — Apply a simple color override to the spout.
1219
1667
 
1220
1668
  ```ts
@@ -1233,6 +1681,8 @@ build(): Shape
1233
1681
  attach(options?: ProductAttachOptions): Shape
1234
1682
  ```
1235
1683
 
1684
+ `ProductAttachOptions`: `{ offset?: number, inset?: number }`
1685
+
1236
1686
  ### `ProductHandleBuilder`
1237
1687
 
1238
1688
  **Properties:**
@@ -1255,6 +1705,12 @@ between(upper: ProductSurfaceRef, lower: Vec3): this
1255
1705
  spine(points: Vec3[] | ProductRailSpec): this
1256
1706
  ```
1257
1707
 
1708
+ `ProductRailSpec`: `{ kind: ProductRailKind, points: Vec3[], degree?: number, name?: string }`
1709
+
1710
+ **`ProductRailKind`**
1711
+
1712
+ `"bezier" | "nurbs" | "polyline"`
1713
+
1258
1714
  #### `grip()` — Set the grip cross-section profile.
1259
1715
 
1260
1716
  ```ts
@@ -1267,6 +1723,27 @@ grip(profile: Sketch): this
1267
1723
  material(material: ProductMaterial): this
1268
1724
  ```
1269
1725
 
1726
+ `ProductMaterial`: `{ color?: string, material?: ShapeMaterialProps }`
1727
+
1728
+ **`ShapeMaterialProps`**
1729
+
1730
+ | Option | Type | Description |
1731
+ |--------|------|-------------|
1732
+ | `metalness?` | `number` | Metalness factor (0 = dielectric, 1 = metal). Default: 0.05 |
1733
+ | `roughness?` | `number` | Roughness factor (0 = mirror, 1 = fully diffuse). Default: 0.35 |
1734
+ | `emissive?` | `string` | Emissive glow color (hex string, e.g. "#ff6b35"). |
1735
+ | `emissiveIntensity?` | `number` | Emissive intensity multiplier. Default: 1 |
1736
+ | `opacity?` | `number` | Opacity (0 = fully transparent, 1 = fully opaque). Default: 1 |
1737
+ | `wireframe?` | `boolean` | Render as wireframe. Default: false |
1738
+ | `clearcoat?` | `number` | Clearcoat intensity (0–1). Default: 0.1 |
1739
+ | `clearcoatRoughness?` | `number` | Clearcoat roughness (0–1). Default: 0.4 |
1740
+ | `transmission?` | `number` | Glass/translucency transmission factor (0–1). Renderer support depends on target. |
1741
+ | `ior?` | `number` | Index of refraction for transmissive materials. Typical glass is ~1.45. |
1742
+ | `thickness?` | `number` | Approximate transmissive volume thickness in model units. |
1743
+ | `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
1744
+ | `specularColor?` | `string` | Specular highlight tint. |
1745
+ | `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
1746
+
1270
1747
  #### `padMaterial()` — Apply a product material preset to handle landing pads.
1271
1748
 
1272
1749
  ```ts
@@ -1363,7 +1840,9 @@ toGroup(): ShapeGroup
1363
1840
  - `describeProfile(sketch: Sketch, kind?: ProductProfileKind, radius?: number): ProductProfileDescriptor` — Describe a custom sketch as a product profile.
1364
1841
  - `scaleProfileTo(sketch: Sketch, width: number, depth: number): Sketch` — Scale an existing profile sketch to a target width/depth.
1365
1842
  - `ref(skin: ProductSkin, query: ProductSkinRefQuery): ProductSurfaceRef` — Create an ad-hoc ProductSurfaceRef from a skin and side/u/v query.
1843
+ - `surface(skin: ProductSkin, side: ProductSkinSide): ProductSurfaceBuilder` — Create a fluent surface helper for refs and conformal features on one side of a skin. Equivalent to skin.surface(side), useful when writing in Product.* namespace style.
1366
1844
  - `panel(name: string): ProductPanelBuilder` — Start a panel feature builder.
1845
+ - `ribbon(name: string): ProductRibbonBuilder` — Start a conformal ribbon/trim builder for details that should bend with a ProductSkin. Call .on(skin, points) for side/u/v sampling or .fromRefs(points) for explicit surface refs, then configure width, thickness, offset, sampling, material, and color before build().
1367
1846
  - `spout(name: string): ProductSpoutBuilder` — Start a spout/nozzle feature builder.
1368
1847
  - `handle(name: string): ProductHandleBuilder` — Start a handle feature builder.
1369
1848
  - `place(detail: Shape | ShapeGroup, ref: ProductRefInput, options?: ProductAttachOptions): Shape | ShapeGroup` — Place a shape or group on a ProductSurfaceRef.
@@ -23,6 +23,7 @@ BOM entries are accumulated during script execution and exported alongside the m
23
23
  - `quantity` must be a finite number `>= 0`. A quantity of `0` is silently ignored (useful for conditional scripting with `param()`-driven counts).
24
24
  - `unit` defaults to `"pieces"` when omitted or empty.
25
25
  - The assembly `solved.bom()` / `solved.bomCsv()` API is separate and covers per-part assembly metadata; this function is for free-form purchased-item annotation.
26
+ - `bom()` is injected into every `.forge.js` script. Call it directly; do not write `const { bom } = require(...)`, because top-level declarations named `bom` collide with the built-in runtime name.
26
27
 
27
28
  ```ts
28
29
  const tubeLen = param("Tube Length", 1200, { min: 300, max: 4000, unit: "mm" });
@@ -299,6 +299,8 @@ loadFont(source: string | ArrayBuffer, cacheKey?: string): opentype.Font
299
299
 
300
300
  The Sketch origin is at the left end of the text baseline by default. Use `align` and `baseline` options to adjust placement. Text is rendered using the bundled Inter font by default, or any TTF/OTF/WOFF font you provide.
301
301
 
302
+ `text2d()` creates real geometry. For non-exported explanatory labels in the viewport, prefer `Viewport.label()` so the text stays off the geometry and OCCT compile paths.
303
+
302
304
  Alignment reference table:
303
305
 
304
306
  | `align` | `baseline` | Origin |