forgecad 0.7.0 → 0.8.0

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 (158) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/{AdminPage-DAu1C1ST.js → AdminPage-D4bocK4E.js} +1 -1
  3. package/dist/assets/{DocsPage-Gc_BCdqC.js → DocsPage-D3A_g8V3.js} +85 -45
  4. package/dist/assets/{EditorApp-DG1-oUSV.css → EditorApp-BWYUSpUN.css} +133 -51
  5. package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
  6. package/dist/assets/{EmbedViewer-CEO8XbV8.js → EmbedViewer-kWjKaC_t.js} +1 -1
  7. package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
  8. package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
  9. package/dist/assets/{PricingPage-BSrxu6d7.js → PricingPage-BsU5vzEx.js} +1 -1
  10. package/dist/assets/{SettingsPage-FUCSIRq6.js → SettingsPage-PqvpAKIs.js} +1 -1
  11. package/dist/assets/{evalWorker-KoR0SNKq.js → evalWorker-C-hzNUMy.js} +2218 -286
  12. package/dist/assets/{index-wTEK39at.js → index-Pz321YAt.js} +7416 -1481
  13. package/dist/assets/{index-CyVd1D4D.css → index-ay13WNfa.css} +501 -2
  14. package/dist/assets/{manifold-B1sGWdYk.js → manifold-BcbjWLIo.js} +3 -3
  15. package/dist/assets/{manifold-D7o0N50J.js → manifold-DBckbFgx.js} +1 -1
  16. package/dist/assets/{manifold-G5sBaXzi.js → manifold-O2AAGXyj.js} +1 -1
  17. package/dist/assets/{reportWorker-DYcRHhv9.js → reportWorker-Dxr-5A7w.js} +2003 -259
  18. package/dist/docs/index.html +2 -2
  19. package/dist/docs-raw/CLI.md +488 -0
  20. package/dist/docs-raw/generated/assembly.md +19 -11
  21. package/dist/docs-raw/generated/concepts.md +1023 -360
  22. package/dist/docs-raw/generated/core.md +1165 -264
  23. package/dist/docs-raw/generated/curves.md +168 -1
  24. package/dist/docs-raw/generated/lib.md +10 -5
  25. package/dist/docs-raw/generated/output.md +1 -1
  26. package/dist/docs-raw/generated/sdf.md +208 -0
  27. package/dist/docs-raw/generated/sketch.md +1281 -329
  28. package/dist/docs-raw/generated/viewport.md +29 -2
  29. package/dist/index.html +2 -2
  30. package/dist/landing/proof-ams-adapter.png +0 -0
  31. package/dist/landing/proof-bolt-and-nut.png +0 -0
  32. package/dist/landing/proof-fillet-enclosure.png +0 -0
  33. package/dist/landing/proof-glasses.png +0 -0
  34. package/dist/landing/proof-gyroid.png +0 -0
  35. package/dist/sitemap.xml +6 -6
  36. package/dist-cli/forgecad.js +3148 -555
  37. package/dist-cli/forgecad.js.map +1 -1
  38. package/dist-cli/{solver-FV7TJZGI.js → solver-46FFSK2U.js} +1 -3
  39. package/dist-cli/{solver-FV7TJZGI.js.map → solver-46FFSK2U.js.map} +1 -1
  40. package/dist-skill/CONTEXT.md +3700 -1153
  41. package/dist-skill/SKILL-dev.md +15 -17
  42. package/dist-skill/SKILL.md +14 -9
  43. package/dist-skill/docs/API/core/concepts.md +28 -1
  44. package/dist-skill/docs/CLI.md +488 -0
  45. package/dist-skill/docs/generated/assembly.md +19 -11
  46. package/dist-skill/docs/generated/core.md +1165 -264
  47. package/dist-skill/docs/generated/curves.md +168 -1
  48. package/dist-skill/docs/generated/lib.md +10 -5
  49. package/dist-skill/docs/generated/output.md +1 -1
  50. package/dist-skill/docs/generated/sdf.md +208 -0
  51. package/dist-skill/docs/generated/sketch.md +1281 -329
  52. package/dist-skill/docs/generated/viewport.md +29 -2
  53. package/dist-skill/docs/guides/joint-design.md +78 -0
  54. package/dist-skill/docs-dev/API/core/concepts.md +28 -1
  55. package/dist-skill/docs-dev/CLI.md +488 -0
  56. package/dist-skill/docs-dev/coding.md +1 -1
  57. package/dist-skill/docs-dev/component-model.md +164 -0
  58. package/dist-skill/docs-dev/generated/assembly.md +19 -11
  59. package/dist-skill/docs-dev/generated/core.md +1165 -264
  60. package/dist-skill/docs-dev/generated/curves.md +168 -1
  61. package/dist-skill/docs-dev/generated/lib.md +10 -5
  62. package/dist-skill/docs-dev/generated/output.md +1 -1
  63. package/dist-skill/docs-dev/generated/sdf.md +208 -0
  64. package/dist-skill/docs-dev/generated/sketch.md +1281 -329
  65. package/dist-skill/docs-dev/generated/viewport.md +29 -2
  66. package/dist-skill/docs-dev/guides/joint-design.md +78 -0
  67. package/examples/api/attachTo-basics.forge.js +3 -3
  68. package/examples/api/bill-of-materials.forge.js +9 -9
  69. package/examples/api/bolt-pattern.forge.js +5 -5
  70. package/examples/api/boolean-operations.forge.js +2 -2
  71. package/examples/api/bounding-box-visualizer.forge.js +1 -1
  72. package/examples/api/clone-duplicate.forge.js +1 -1
  73. package/examples/api/connector-assembly.forge.js +4 -2
  74. package/examples/api/connector-basics.forge.js +5 -5
  75. package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
  76. package/examples/api/elbow-test.forge.js +3 -3
  77. package/examples/api/extrude-options.forge.js +4 -4
  78. package/examples/api/fillet-showcase.forge.js +1 -1
  79. package/examples/api/gears-tier1.forge.js +5 -5
  80. package/examples/api/group-test.forge.js +2 -2
  81. package/examples/api/mesh-import-slats.forge.js +3 -3
  82. package/examples/api/patterns.forge.js +3 -3
  83. package/examples/api/pointAlong-orientation.forge.js +2 -2
  84. package/examples/api/profile-2020-b-slot6.forge.js +4 -4
  85. package/examples/api/sketch-rounding-strategies.forge.js +1 -1
  86. package/examples/api/smooth-curve-connections.forge.js +1 -1
  87. package/examples/api/transition-curves.forge.js +3 -3
  88. package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
  89. package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
  90. package/examples/constraints/03-redundant-constraints.forge.js +2 -2
  91. package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
  92. package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
  93. package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
  94. package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
  95. package/examples/constraints/09-stress-spiral.forge.js +1 -1
  96. package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
  97. package/examples/constraints/11-surface-grid.forge.js +2 -2
  98. package/examples/constraints/12-surface-nested.forge.js +4 -4
  99. package/examples/constraints/13-surface-complex.forge.js +1 -1
  100. package/examples/exact-arc-housing.forge.js +12 -0
  101. package/examples/furniture/adjustable-table.forge.js +13 -13
  102. package/examples/furniture/bathroom.forge.js +15 -15
  103. package/examples/furniture/chair.forge.js +12 -12
  104. package/examples/furniture/picture-frame.forge.js +6 -6
  105. package/examples/furniture/shoe-rack-doors.forge.js +8 -8
  106. package/examples/furniture/shoe-rack.forge.js +7 -7
  107. package/examples/furniture/table-lamp.forge.js +8 -8
  108. package/examples/gcode/lissajous-vase.forge.js +4 -4
  109. package/examples/gcode/math-surface.forge.js +3 -3
  110. package/examples/gcode/parametric-vase.forge.js +4 -4
  111. package/examples/gcode/spiral-tower.forge.js +4 -4
  112. package/examples/generative/crystal-growth.forge.js +7 -7
  113. package/examples/generative/frost-spires.forge.js +6 -6
  114. package/examples/generative/golden-spiral-tower.forge.js +8 -8
  115. package/examples/generative/molten-forge.forge.js +6 -6
  116. package/examples/generative/neon-coral.forge.js +7 -7
  117. package/examples/mechanical/3d-printer.forge.js +9 -9
  118. package/examples/mechanical/5-finger-robot-hand.forge.js +4 -4
  119. package/examples/mechanical/airplane-propeller.forge.js +7 -7
  120. package/examples/mechanical/bolt-and-nut.forge.js +10 -10
  121. package/examples/mechanical/door-with-hinges.forge.js +7 -7
  122. package/examples/mechanical/fillet-enclosure.forge.js +14 -10
  123. package/examples/mechanical/headphone-hanger-v2.forge.js +9 -9
  124. package/examples/mechanical/robot_hand.forge.js +10 -10
  125. package/examples/mechanical/robot_hand_2.forge.js +17 -17
  126. package/examples/nurbs-surface.forge.js +8 -0
  127. package/examples/nurbs-tube.forge.js +7 -0
  128. package/examples/products/bottle.forge.js +7 -7
  129. package/examples/products/chess-set.forge.js +6 -6
  130. package/examples/products/classical-piano.forge.js +9 -9
  131. package/examples/products/clock.forge.js +21 -21
  132. package/examples/products/cup.forge.js +5 -5
  133. package/examples/products/iphone.forge.js +12 -12
  134. package/examples/products/laptop.forge.js +9 -9
  135. package/examples/products/laser-cut-box.forge.js +6 -6
  136. package/examples/products/laser-cut-tray.forge.js +6 -6
  137. package/examples/products/liquid-soap-dispenser.forge.js +5 -5
  138. package/examples/products/origami-fish.forge.js +6 -6
  139. package/examples/products/spiderman-cake.forge.js +2 -2
  140. package/examples/shelf/container.forge.js +5 -5
  141. package/examples/shelf/shelf-unit.forge.js +6 -6
  142. package/examples/toolbox/bolted-joint.forge.js +5 -5
  143. package/package.json +3 -1
  144. package/dist/assets/EditorApp-D9bJvtf7.js +0 -11338
  145. package/dist/assets/LandingPage-CdCuEOdC.js +0 -451
  146. package/dist-cli/chunk-PZ5AY32C.js +0 -10
  147. package/dist-cli/chunk-PZ5AY32C.js.map +0 -1
  148. package/dist-skill/docs/CLI/export.md +0 -91
  149. package/dist-skill/docs/CLI/projects.md +0 -107
  150. package/dist-skill/docs/CLI/studio_publishing.md +0 -52
  151. package/dist-skill/docs/CLI/validation.md +0 -66
  152. package/dist-skill/docs-dev/API/core/sdf-advanced.md +0 -92
  153. package/dist-skill/docs-dev/API/core/sdf-primitives.md +0 -58
  154. package/dist-skill/docs-dev/API/core/sdf-workflow.md +0 -42
  155. package/dist-skill/docs-dev/CLI/export.md +0 -91
  156. package/dist-skill/docs-dev/CLI/projects.md +0 -107
  157. package/dist-skill/docs-dev/CLI/studio_publishing.md +0 -52
  158. package/dist-skill/docs-dev/CLI/validation.md +0 -66
@@ -1,19 +1,20 @@
1
1
  // Filleted Electronics Enclosure — practical engineering part
2
2
  // Demonstrates: fillet() for professional-looking product design
3
3
 
4
- const width = param("Width", 80, { min: 50, max: 120, unit: "mm" });
5
- const depth = param("Depth", 50, { min: 30, max: 80, unit: "mm" });
6
- const height = param("Height", 25, { min: 15, max: 40, unit: "mm" });
7
- const wall = param("Wall", 2.5, { min: 1.5, max: 4, unit: "mm" });
8
- const outerR = param("Outer Fillet", 4, { min: 1, max: 10, unit: "mm" });
4
+ const width = Param.number("Width", 80, { min: 50, max: 120, unit: "mm" });
5
+ const depth = Param.number("Depth", 50, { min: 30, max: 80, unit: "mm" });
6
+ const height = Param.number("Height", 25, { min: 15, max: 40, unit: "mm" });
7
+ const wall = Param.number("Wall", 2.5, { min: 1.5, max: 4, unit: "mm" });
8
+ const outerR = Param.number("Outer Fillet", 4, { min: 1, max: 10, unit: "mm" });
9
9
 
10
10
  // ── Outer shell with rounded vertical edges ─────────────────────────────────
11
11
  const outer = box(width, depth, height);
12
12
  let enclosure = fillet(outer, outerR, { parallel: [0, 0, 1], convex: true });
13
13
 
14
14
  // ── Hollow interior ─────────────────────────────────────────────────────────
15
+ // box() is XY-centered, Z starts at 0 — cavity just needs a Z shift
15
16
  const cavity = box(width - wall * 2, depth - wall * 2, height - wall)
16
- .translate(width / 2, depth / 2, wall + (height - wall) / 2 + 0.01);
17
+ .translate(0, 0, wall + 0.01);
17
18
  enclosure = difference(enclosure, cavity);
18
19
 
19
20
  // ── Screw bosses ────────────────────────────────────────────────────────────
@@ -27,12 +28,15 @@ function screwBoss(x, y) {
27
28
  return difference(boss, hole);
28
29
  }
29
30
 
31
+ // Positions relative to centered box: -width/2..+width/2
32
+ const hw = width / 2;
33
+ const hd = depth / 2;
30
34
  enclosure = union(
31
35
  enclosure,
32
- screwBoss(inset, inset),
33
- screwBoss(width - inset, inset),
34
- screwBoss(inset, depth - inset),
35
- screwBoss(width - inset, depth - inset),
36
+ screwBoss(-hw + inset, -hd + inset),
37
+ screwBoss( hw - inset, -hd + inset),
38
+ screwBoss(-hw + inset, hd - inset),
39
+ screwBoss( hw - inset, hd - inset),
36
40
  );
37
41
 
38
42
  return enclosure;
@@ -2,15 +2,15 @@
2
2
  // Clamps to the bottom edge of a desk, hook hangs below.
3
3
  // Designed for actual 3D printing / building.
4
4
 
5
- const deskThick = param("Desk Thickness", 25, { min: 15, max: 50, unit: "mm" });
6
- const clampDepth = param("Clamp Depth", 40, { min: 25, max: 70, unit: "mm" });
7
- const width = param("Width", 50, { min: 30, max: 80, unit: "mm" });
8
- const thick = param("Material Thick", 5, { min: 3, max: 10, unit: "mm" });
9
- const hookDrop = param("Hook Drop", 60, { min: 30, max: 100, unit: "mm" });
10
- const hookLen = param("Hook Length", 35, { min: 15, max: 60, unit: "mm" });
11
- const hookCurveR = param("Hook Curve R", 15, { min: 5, max: 30, unit: "mm" });
12
- const padThick = param("Pad Thickness", 2, { min: 1, max: 5, unit: "mm" });
13
- const boltHoleD = param("Bolt Hole", 5, { min: 0, max: 8, unit: "mm" });
5
+ const deskThick = Param.number("Desk Thickness", 25, { min: 15, max: 50, unit: "mm" });
6
+ const clampDepth = Param.number("Clamp Depth", 40, { min: 25, max: 70, unit: "mm" });
7
+ const width = Param.number("Width", 50, { min: 30, max: 80, unit: "mm" });
8
+ const thick = Param.number("Material Thick", 5, { min: 3, max: 10, unit: "mm" });
9
+ const hookDrop = Param.number("Hook Drop", 60, { min: 30, max: 100, unit: "mm" });
10
+ const hookLen = Param.number("Hook Length", 35, { min: 15, max: 60, unit: "mm" });
11
+ const hookCurveR = Param.number("Hook Curve R", 15, { min: 5, max: 30, unit: "mm" });
12
+ const padThick = Param.number("Pad Thickness", 2, { min: 1, max: 5, unit: "mm" });
13
+ const boltHoleD = Param.number("Bolt Hole", 5, { min: 0, max: 8, unit: "mm" });
14
14
 
15
15
  // The clamp is a C-shape that grips the desk edge.
16
16
  // Top jaw sits on top of desk, bottom jaw presses from below.
@@ -5,16 +5,16 @@
5
5
  // 3) Mount included: base, mast, wrist clevis
6
6
  // 4) Iterative construction: build primitives -> segments -> fingers -> full assembly
7
7
 
8
- const grip = param("Grip", 55, { min: 0, max: 100, unit: "%" });
9
- const fingerSpread = param("Finger Spread", 18, { min: 0, max: 35, unit: "°" });
10
- const thumbOpposition = param("Thumb Opposition", 42, { min: 20, max: 70, unit: "°" });
11
- const wristPitch = param("Wrist Pitch", 8, { min: -35, max: 45, unit: "°" });
12
- const explode = param("Explode", 0, { min: 0, max: 26, unit: "mm" });
13
-
14
- const scale = param("Scale", 1.0, { min: 0.75, max: 1.25, step: 0.01 });
15
- const pinD = param("Pin Diameter", 3.2, { min: 2.0, max: 5.0, step: 0.1, unit: "mm" }) * scale;
16
- const jointClearance = param("Joint Clearance", 0.32, { min: 0.2, max: 0.7, step: 0.02, unit: "mm" }) * scale;
17
- const wall = param("Min Wall", 2.4, { min: 1.6, max: 4.0, step: 0.1, unit: "mm" }) * scale;
8
+ const grip = Param.number("Grip", 55, { min: 0, max: 100, unit: "%" });
9
+ const fingerSpread = Param.number("Finger Spread", 18, { min: 0, max: 35, unit: "°" });
10
+ const thumbOpposition = Param.number("Thumb Opposition", 42, { min: 20, max: 70, unit: "°" });
11
+ const wristPitch = Param.number("Wrist Pitch", 8, { min: -35, max: 45, unit: "°" });
12
+ const explode = Param.number("Explode", 0, { min: 0, max: 26, unit: "mm" });
13
+
14
+ const scale = Param.number("Scale", 1.0, { min: 0.75, max: 1.25, step: 0.01 });
15
+ const pinD = Param.number("Pin Diameter", 3.2, { min: 2.0, max: 5.0, step: 0.1, unit: "mm" }) * scale;
16
+ const jointClearance = Param.number("Joint Clearance", 0.32, { min: 0.2, max: 0.7, step: 0.02, unit: "mm" }) * scale;
17
+ const wall = Param.number("Min Wall", 2.4, { min: 1.6, max: 4.0, step: 0.1, unit: "mm" }) * scale;
18
18
 
19
19
  // Core hand dimensions
20
20
  const palmW = 84 * scale;
@@ -3,24 +3,24 @@
3
3
  // Strategy: build small reliable modules, then combine with parametric kinematics.
4
4
 
5
5
  // ---- 1) Control params (motion + fabrication) ----
6
- const baseYaw = param("Base Yaw", 20, { min: -170, max: 170, unit: "°" });
7
- const shoulderPitch = param("Shoulder Pitch", 35, { min: -25, max: 105, unit: "°" });
8
- const elbowPitch = param("Elbow Pitch", 55, { min: -15, max: 135, unit: "°" });
9
- const wristPitch = param("Wrist Pitch", -20, { min: -100, max: 100, unit: "°" });
10
- const wristRoll = param("Wrist Roll", 10, { min: -180, max: 180, unit: "°" });
6
+ const baseYaw = Param.number("Base Yaw", 20, { min: -170, max: 170, unit: "°" });
7
+ const shoulderPitch = Param.number("Shoulder Pitch", 35, { min: -25, max: 105, unit: "°" });
8
+ const elbowPitch = Param.number("Elbow Pitch", 55, { min: -15, max: 135, unit: "°" });
9
+ const wristPitch = Param.number("Wrist Pitch", -20, { min: -100, max: 100, unit: "°" });
10
+ const wristRoll = Param.number("Wrist Roll", 10, { min: -180, max: 180, unit: "°" });
11
11
 
12
- const upperLen = param("Upper Arm Len", 210, { min: 140, max: 320, unit: "mm" });
13
- const foreLen = param("Forearm Len", 220, { min: 150, max: 340, unit: "mm" });
14
- const foreExtension = param("Forearm Ext", 70, { min: 0, max: 150, unit: "mm" });
12
+ const upperLen = Param.number("Upper Arm Len", 210, { min: 140, max: 320, unit: "mm" });
13
+ const foreLen = Param.number("Forearm Len", 220, { min: 150, max: 340, unit: "mm" });
14
+ const foreExtension = Param.number("Forearm Ext", 70, { min: 0, max: 150, unit: "mm" });
15
15
 
16
- const gripperOpen = param("Gripper Open", 55, { min: 0, max: 90, unit: "mm" });
17
- const fingerCurl = param("Finger Curl", 72, { min: 0, max: 100, unit: "°" });
18
- const payloadType = param("Payload Type", 2, { min: 1, max: 4, integer: true });
19
- const payloadSize = param("Payload Size", 36, { min: 20, max: 65, unit: "mm" });
20
- const carryPayload = param("Carry Payload", 1, { min: 0, max: 1, integer: true });
16
+ const gripperOpen = Param.number("Gripper Open", 55, { min: 0, max: 90, unit: "mm" });
17
+ const fingerCurl = Param.number("Finger Curl", 72, { min: 0, max: 100, unit: "°" });
18
+ const payloadType = Param.number("Payload Type", 2, { min: 1, max: 4, integer: true });
19
+ const payloadSize = Param.number("Payload Size", 36, { min: 20, max: 65, unit: "mm" });
20
+ const carryPayload = Param.number("Carry Payload", 1, { min: 0, max: 1, integer: true });
21
21
 
22
- const exploded = param("Exploded", 0, { min: 0, max: 140, unit: "mm" });
23
- const sectionEnabled = param("Section Enabled", 0, { min: 0, max: 1, integer: true });
22
+ const exploded = Param.number("Exploded", 0, { min: 0, max: 140, unit: "mm" });
23
+ const sectionEnabled = Param.number("Section Enabled", 0, { min: 0, max: 1, integer: true });
24
24
 
25
25
  // ---- 2) Math + transform helpers ----
26
26
  function rad(deg) {
@@ -602,12 +602,12 @@ const sectionMarginZ = Math.max(30, (sceneBounds.max[2] - sceneBounds.min[2]) *
602
602
  const sectionDefaultX = (sceneBounds.min[0] + sceneBounds.max[0]) * 0.5;
603
603
  const sectionDefaultZ = (sceneBounds.min[2] + sceneBounds.max[2]) * 0.5;
604
604
 
605
- const sectionX = param("Section X", sectionDefaultX, {
605
+ const sectionX = Param.number("Section X", sectionDefaultX, {
606
606
  min: sceneBounds.min[0] - sectionMarginX,
607
607
  max: sceneBounds.max[0] + sectionMarginX,
608
608
  unit: "mm",
609
609
  });
610
- const sectionZ = param("Section Z", sectionDefaultZ, {
610
+ const sectionZ = Param.number("Section Z", sectionDefaultZ, {
611
611
  min: sceneBounds.min[2] - sectionMarginZ,
612
612
  max: sceneBounds.max[2] + sectionMarginZ,
613
613
  unit: "mm",
@@ -0,0 +1,8 @@
1
+ // Freeform NURBS surface — a gently curved panel
2
+ const grid = [
3
+ [[0,0,0], [10,0,2], [20,0,2], [30,0,0]],
4
+ [[0,10,1], [10,10,6], [20,10,6], [30,10,1]],
5
+ [[0,20,1], [10,20,6], [20,20,6], [30,20,1]],
6
+ [[0,30,0], [10,30,2], [20,30,2], [30,30,0]],
7
+ ];
8
+ return nurbsSurface(grid, { thickness: 1.5 });
@@ -0,0 +1,7 @@
1
+ // NURBS curve swept into a smooth tube
2
+ const curve = nurbs3d(
3
+ [[0,0,0], [15,8,0], [25,-3,10], [40,5,15], [50,0,5]],
4
+ { degree: 3 }
5
+ );
6
+ const tube = sweep(circle2d(2), curve);
7
+ return tube;
@@ -1,13 +1,13 @@
1
1
  // Water Bottle — revolve profile with cap
2
2
  // Demonstrates: revolve, polygon, difference, smoothing, multi-object
3
3
 
4
- const bodyH = param("Body Height", 180, { min: 120, max: 250, unit: "mm" });
5
- const bodyR = param("Body Radius", 35, { min: 25, max: 50, unit: "mm" });
6
- const neckH = param("Neck Height", 30, { min: 15, max: 50, unit: "mm" });
7
- const neckR = param("Neck Radius", 14, { min: 10, max: 25, unit: "mm" });
8
- const wall = param("Wall Thickness", 2, { min: 1, max: 5, unit: "mm" });
9
- const capH = param("Cap Height", 18, { min: 10, max: 30, unit: "mm" });
10
- const shoulderR = param("Shoulder Curve", 20, { min: 5, max: 40, unit: "mm" });
4
+ const bodyH = Param.number("Body Height", 180, { min: 120, max: 250, unit: "mm" });
5
+ const bodyR = Param.number("Body Radius", 35, { min: 25, max: 50, unit: "mm" });
6
+ const neckH = Param.number("Neck Height", 30, { min: 15, max: 50, unit: "mm" });
7
+ const neckR = Param.number("Neck Radius", 14, { min: 10, max: 25, unit: "mm" });
8
+ const wall = Param.number("Wall Thickness", 2, { min: 1, max: 5, unit: "mm" });
9
+ const capH = Param.number("Cap Height", 18, { min: 10, max: 30, unit: "mm" });
10
+ const shoulderR = Param.number("Shoulder Curve", 20, { min: 5, max: 40, unit: "mm" });
11
11
 
12
12
  // Outer profile — polygon traced from bottom-center up and around
13
13
  // Bottom flat → body → shoulder curve → neck
@@ -1,9 +1,9 @@
1
- const squareSize = param("Square Size", 36, { min: 24, max: 54, unit: "mm" });
2
- const boardThickness = param("Board Thickness", 14, { min: 8, max: 24, unit: "mm" });
3
- const borderWidth = param("Border Width", 10, { min: 4, max: 18, unit: "mm" });
4
- const tileHeight = param("Tile Height", 1.8, { min: 0.8, max: 4, step: 0.1, unit: "mm" });
5
- const pieceScale = param("Piece Scale", 1, { min: 0.8, max: 1.25, step: 0.01 });
6
- const pieceLift = param("Piece Lift", 0, { min: 0, max: 16, unit: "mm" });
1
+ const squareSize = Param.number("Square Size", 36, { min: 24, max: 54, unit: "mm" });
2
+ const boardThickness = Param.number("Board Thickness", 14, { min: 8, max: 24, unit: "mm" });
3
+ const borderWidth = Param.number("Border Width", 10, { min: 4, max: 18, unit: "mm" });
4
+ const tileHeight = Param.number("Tile Height", 1.8, { min: 0.8, max: 4, step: 0.1, unit: "mm" });
5
+ const pieceScale = Param.number("Piece Scale", 1, { min: 0.8, max: 1.25, step: 0.01 });
6
+ const pieceLift = Param.number("Piece Lift", 0, { min: 0, max: 16, unit: "mm" });
7
7
 
8
8
  const boardSize = squareSize * 8;
9
9
  const frameSize = boardSize + borderWidth * 2;
@@ -12,15 +12,15 @@
12
12
  - Bench
13
13
  */
14
14
 
15
- const bodyWidth = param("Body Width", 180, { min: 140, max: 240, unit: "mm" });
16
- const bodyLength = param("Body Length", 280, { min: 220, max: 360, unit: "mm" });
17
- const rimHeight = param("Rim Height", 28, { min: 20, max: 40, unit: "mm" });
18
- const lidThickness = param("Lid Thickness", 6, { min: 4, max: 10, unit: "mm" });
19
- const lidOpen = param("Lid Angle", 25, { min: 0, max: 50, unit: "°" });
20
- const legHeight = param("Leg Height", 60, { min: 45, max: 90, unit: "mm" });
21
- const legTopRadius = param("Leg Top Radius", 8, { min: 5, max: 12, unit: "mm" });
22
- const keyboardDepth = param("Keyboard Depth", 60, { min: 45, max: 80, unit: "mm" });
23
- const keyHeight = param("Key Height", 5, { min: 3, max: 8, unit: "mm" });
15
+ const bodyWidth = Param.number("Body Width", 180, { min: 140, max: 240, unit: "mm" });
16
+ const bodyLength = Param.number("Body Length", 280, { min: 220, max: 360, unit: "mm" });
17
+ const rimHeight = Param.number("Rim Height", 28, { min: 20, max: 40, unit: "mm" });
18
+ const lidThickness = Param.number("Lid Thickness", 6, { min: 4, max: 10, unit: "mm" });
19
+ const lidOpen = Param.number("Lid Angle", 25, { min: 0, max: 50, unit: "°" });
20
+ const legHeight = Param.number("Leg Height", 60, { min: 45, max: 90, unit: "mm" });
21
+ const legTopRadius = Param.number("Leg Top Radius", 8, { min: 5, max: 12, unit: "mm" });
22
+ const keyboardDepth = Param.number("Keyboard Depth", 60, { min: 45, max: 80, unit: "mm" });
23
+ const keyHeight = Param.number("Key Height", 5, { min: 3, max: 8, unit: "mm" });
24
24
 
25
25
  const rimThickness = Math.min(12, bodyWidth * 0.07);
26
26
  const keyboardWidth = bodyWidth * 0.9;
@@ -3,23 +3,23 @@
3
3
  // Returns named objects to preserve colors and enable individual visibility control
4
4
 
5
5
  // === Dimensions ===
6
- const diameter = param("Diameter", 220, { min: 80, max: 400, unit: "mm" });
7
- const depth = param("Depth", 18, { min: 8, max: 50, unit: "mm" });
8
- const rimWidth = param("Rim Width", 8, { min: 3, max: 30, unit: "mm" });
6
+ const diameter = Param.number("Diameter", 220, { min: 80, max: 400, unit: "mm" });
7
+ const depth = Param.number("Depth", 18, { min: 8, max: 50, unit: "mm" });
8
+ const rimWidth = Param.number("Rim Width", 8, { min: 3, max: 30, unit: "mm" });
9
9
 
10
10
  // === Time Settings — Default 10:10:30 (Apple display time) ===
11
- const hour = param("Hour", 10, { min: 1, max: 12, integer: true });
12
- const minute = param("Minute", 10, { min: 0, max: 59, integer: true });
13
- const second = param("Second", 30, { min: 0, max: 59, integer: true });
14
- const showSecondHand = param("Show Seconds", 1, { min: 0, max: 1, integer: true });
11
+ const hour = Param.number("Hour", 10, { min: 1, max: 12, integer: true });
12
+ const minute = Param.number("Minute", 10, { min: 0, max: 59, integer: true });
13
+ const second = Param.number("Second", 30, { min: 0, max: 59, integer: true });
14
+ const showSecondHand = Param.number("Show Seconds", 1, { min: 0, max: 1, integer: true });
15
15
 
16
16
  // === Color Customization ===
17
- const rimColor = param("Rim Color", 0, { min: 0, max: 3, integer: true }); // 0=silver, 1=gold, 2=black, 3=rose
18
- const faceColor = param("Face Color", 0, { min: 0, max: 2, integer: true }); // 0=white, 1=black, 2=cream
19
- const markerColor = param("Marker Color", 0, { min: 0, max: 2, integer: true }); // 0=black, 1=white, 2=gold
20
- const hourHandColor = param("Hour Hand Color", 0, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
21
- const minuteHandColor = param("Minute Hand Color", 1, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
22
- const secondHandColor = param("Second Hand Color", 3, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
17
+ const rimColor = Param.number("Rim Color", 0, { min: 0, max: 3, integer: true }); // 0=silver, 1=gold, 2=black, 3=rose
18
+ const faceColor = Param.number("Face Color", 0, { min: 0, max: 2, integer: true }); // 0=white, 1=black, 2=cream
19
+ const markerColor = Param.number("Marker Color", 0, { min: 0, max: 2, integer: true }); // 0=black, 1=white, 2=gold
20
+ const hourHandColor = Param.number("Hour Hand Color", 0, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
21
+ const minuteHandColor = Param.number("Minute Hand Color", 1, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
22
+ const secondHandColor = Param.number("Second Hand Color", 3, { min: 0, max: 3, integer: true }); // 0=black, 1=white, 2=gold, 3=red
23
23
 
24
24
  // Color palette
25
25
  const colors = {
@@ -61,8 +61,8 @@ const face = cylinder(2, innerRadius - 1)
61
61
  .color(faceHex);
62
62
 
63
63
  // === Hour Markers ===
64
- const markerLength = param("Marker Length", 10, { min: 5, max: 25, unit: "mm" });
65
- const markerWidth = param("Marker Width", 2.5, { min: 1, max: 6, unit: "mm" });
64
+ const markerLength = Param.number("Marker Length", 10, { min: 5, max: 25, unit: "mm" });
65
+ const markerWidth = Param.number("Marker Width", 2.5, { min: 1, max: 6, unit: "mm" });
66
66
 
67
67
  const markerShapes = [];
68
68
  for (let i = 0; i < 12; i++) {
@@ -86,12 +86,12 @@ for (let i = 0; i < 12; i++) {
86
86
  const markers = union(...markerShapes).color(markerHex);
87
87
 
88
88
  // === Clock Hands ===
89
- const hourHandLength = param("Hour Hand Length", 55, { min: 25, max: 110, unit: "mm" });
90
- const hourHandWidth = param("Hour Hand Width", 10, { min: 5, max: 20, unit: "mm" });
91
- const minuteHandLength = param("Minute Hand Length", 80, { min: 40, max: 160, unit: "mm" });
92
- const minuteHandWidth = param("Minute Hand Width", 7, { min: 3, max: 14, unit: "mm" });
93
- const secondHandLength = param("Second Hand Length", 85, { min: 50, max: 170, unit: "mm" });
94
- const secondHandWidth = param("Second Hand Width", 2, { min: 1, max: 5, unit: "mm" });
89
+ const hourHandLength = Param.number("Hour Hand Length", 55, { min: 25, max: 110, unit: "mm" });
90
+ const hourHandWidth = Param.number("Hour Hand Width", 10, { min: 5, max: 20, unit: "mm" });
91
+ const minuteHandLength = Param.number("Minute Hand Length", 80, { min: 40, max: 160, unit: "mm" });
92
+ const minuteHandWidth = Param.number("Minute Hand Width", 7, { min: 3, max: 14, unit: "mm" });
93
+ const secondHandLength = Param.number("Second Hand Length", 85, { min: 50, max: 170, unit: "mm" });
94
+ const secondHandWidth = Param.number("Second Hand Width", 2, { min: 1, max: 5, unit: "mm" });
95
95
 
96
96
  // Calculate hand angles (0 degrees = 12 o'clock, clockwise)
97
97
  const hourAngle = (hour % 12) * 30 + (minute / 60) * 30;
@@ -1,11 +1,11 @@
1
1
  // Cup with larger top than bottom
2
2
 
3
3
  // Parameters
4
- const height = param("Height", 80, { min: 40, max: 150, unit: "mm" });
5
- const topRadius = param("Top Radius", 35, { min: 20, max: 60, unit: "mm" });
6
- const bottomRadius = param("Bottom Radius", 25, { min: 15, max: 50, unit: "mm" });
7
- const wallThickness = param("Wall Thickness", 3, { min: 1, max: 8, unit: "mm" });
8
- const baseThickness = param("Base Thickness", 5, { min: 2, max: 10, unit: "mm" });
4
+ const height = Param.number("Height", 80, { min: 40, max: 150, unit: "mm" });
5
+ const topRadius = Param.number("Top Radius", 35, { min: 20, max: 60, unit: "mm" });
6
+ const bottomRadius = Param.number("Bottom Radius", 25, { min: 15, max: 50, unit: "mm" });
7
+ const wallThickness = Param.number("Wall Thickness", 3, { min: 1, max: 8, unit: "mm" });
8
+ const baseThickness = Param.number("Base Thickness", 5, { min: 2, max: 10, unit: "mm" });
9
9
 
10
10
  // Outer cup shape - tapered cylinder (truncated cone)
11
11
  const outerCup = cylinder(height, bottomRadius, topRadius);
@@ -2,11 +2,11 @@
2
2
  // Tests ForgeCAD's sketch→extrude + smoothing workflow
3
3
 
4
4
  // === Dimensions (roughly iPhone 15 Pro proportions) ===
5
- const w = param("Width", 71.6, { min: 60, max: 80, unit: "mm" });
6
- const h = param("Height", 146.6, { min: 120, max: 170, unit: "mm" });
7
- const d = param("Depth", 8.25, { min: 6, max: 12, unit: "mm" });
8
- const cornerR = param("Corner Radius", 10, { min: 2, max: 20, unit: "mm" });
9
- const edgeR = param("Edge Radius", 1.5, { min: 0, max: 3, step: 0.1, unit: "mm" });
5
+ const w = Param.number("Width", 71.6, { min: 60, max: 80, unit: "mm" });
6
+ const h = Param.number("Height", 146.6, { min: 120, max: 170, unit: "mm" });
7
+ const d = Param.number("Depth", 8.25, { min: 6, max: 12, unit: "mm" });
8
+ const cornerR = Param.number("Corner Radius", 10, { min: 2, max: 20, unit: "mm" });
9
+ const edgeR = Param.number("Edge Radius", 1.5, { min: 0, max: 3, step: 0.1, unit: "mm" });
10
10
 
11
11
  // === Body ===
12
12
  // Rounded-rect profile extruded to phone depth, then subdivision-smoothed
@@ -15,7 +15,7 @@ const bodyProfile = roundedRect(w, h, cornerR);
15
15
  let body = bodyProfile.extrude(d).translate(0, 0, -d / 2);
16
16
 
17
17
  // === Screen cutout (top +Z face = phone screen side) ===
18
- const screenInset = param("Screen Inset", 2, { min: 1, max: 5, unit: "mm" });
18
+ const screenInset = Param.number("Screen Inset", 2, { min: 1, max: 5, unit: "mm" });
19
19
  const screenDepth = 0.4;
20
20
  const screenW = w - screenInset * 2;
21
21
  const screenH = h - screenInset * 2;
@@ -34,9 +34,9 @@ const screenFill = roundedRect(screenW, screenH, screenR)
34
34
  .translate(0, 0, d / 2 - screenDepth);
35
35
 
36
36
  // === Camera island (bottom -Z face = phone back, upper-left area) ===
37
- const camSize = param("Camera Island", 36, { min: 25, max: 45, unit: "mm" });
37
+ const camSize = Param.number("Camera Island", 36, { min: 25, max: 45, unit: "mm" });
38
38
  const camR = 8;
39
- const camBump = param("Camera Bump", 1.5, { min: 0.5, max: 3, unit: "mm" });
39
+ const camBump = Param.number("Camera Bump", 1.5, { min: 0.5, max: 3, unit: "mm" });
40
40
  const camEdgeInset = 4;
41
41
  const camX = -w / 2 + camSize / 2 + camEdgeInset;
42
42
  const camY = h / 2 - camSize / 2 - camEdgeInset;
@@ -47,8 +47,8 @@ let camIsland = roundedRect(camSize, camSize, camR)
47
47
  .translate(0, 0, -d / 2 - camBump);
48
48
 
49
49
  // Camera lenses — 3 in L-pattern, positioned via entity geometry
50
- const lensR = param("Lens Radius", 6, { min: 3, max: 10, unit: "mm" });
51
- const lensGap = param("Lens Gap", 3, { min: 1, max: 8, unit: "mm" });
50
+ const lensR = Param.number("Lens Radius", 6, { min: 3, max: 10, unit: "mm" });
51
+ const lensGap = Param.number("Lens Gap", 3, { min: 1, max: 8, unit: "mm" });
52
52
 
53
53
  // Use Rectangle2D entity to derive lens positions from island bounds
54
54
  const camRect = Rectangle2D.fromCenterAndDimensions(point(camX, camY), camSize, camSize);
@@ -71,7 +71,7 @@ camIsland = camIsland.subtract(makeLens(lens1), makeLens(lens2), makeLens(lens3)
71
71
 
72
72
  // === Charging port (front -Y face = phone bottom edge) ===
73
73
  // pointAlong([0,1,0]) orients the extrusion along +Y so it cuts INTO the body
74
- const portW = param("Port Width", 9, { min: 6, max: 14, unit: "mm" });
74
+ const portW = Param.number("Port Width", 9, { min: 6, max: 14, unit: "mm" });
75
75
  const portH = 3;
76
76
  const portDepth = 4;
77
77
 
@@ -82,7 +82,7 @@ const portCut = roundedRect(portW, portH, portH / 2)
82
82
 
83
83
  // === Speaker & mic grille (front -Y face) ===
84
84
  const holeR = 0.5;
85
- const holeCount = param("Speaker Holes", 6, { min: 3, max: 10, integer: true });
85
+ const holeCount = Param.number("Speaker Holes", 6, { min: 3, max: 10, integer: true });
86
86
  const holeSpacing = 2.2;
87
87
  const grillX0 = portW / 2 + 5;
88
88
 
@@ -1,14 +1,14 @@
1
1
  // Laptop — parametric with opening hinge
2
2
  // Demonstrates: joint(), multi-object, roundedRect, boolean ops
3
3
 
4
- const w = param("Width", 320, { min: 250, max: 400, unit: "mm" });
5
- const d = param("Depth", 220, { min: 170, max: 300, unit: "mm" });
6
- const baseH = param("Base Height", 15, { min: 8, max: 25, unit: "mm" });
7
- const lidH = param("Lid Height", 6, { min: 3, max: 12, unit: "mm" });
8
- const cornerR = param("Corner Radius", 10, { min: 3, max: 25, unit: "mm" });
9
- const screenInset = param("Screen Bezel", 8, { min: 3, max: 20, unit: "mm" });
10
- const kbInsetX = param("KB Inset X", 25, { min: 10, max: 50, unit: "mm" });
11
- const kbInsetY = param("KB Inset Y", 15, { min: 8, max: 40, unit: "mm" });
4
+ const w = Param.number("Width", 320, { min: 250, max: 400, unit: "mm" });
5
+ const d = Param.number("Depth", 220, { min: 170, max: 300, unit: "mm" });
6
+ const baseH = Param.number("Base Height", 15, { min: 8, max: 25, unit: "mm" });
7
+ const lidH = Param.number("Lid Height", 6, { min: 3, max: 12, unit: "mm" });
8
+ const cornerR = Param.number("Corner Radius", 10, { min: 3, max: 25, unit: "mm" });
9
+ const screenInset = Param.number("Screen Bezel", 8, { min: 3, max: 20, unit: "mm" });
10
+ const kbInsetX = Param.number("KB Inset X", 25, { min: 10, max: 50, unit: "mm" });
11
+ const kbInsetY = Param.number("KB Inset Y", 15, { min: 8, max: 40, unit: "mm" });
12
12
 
13
13
  // ─── Base ───
14
14
  const baseProfile = roundedRect(w, d, cornerR);
@@ -119,7 +119,7 @@ const screenAtHinge = screenPanel.translate(0, -hingeY, 0)
119
119
  .rotateX(180)
120
120
  .translate(0, hingeY, hingeZ);
121
121
 
122
- const lidAngle = param("Lid Angle", 110, { min: 0, max: 135, unit: "°" });
122
+ const lidAngle = Param.number("Lid Angle", 110, { min: 0, max: 135, unit: "°" });
123
123
 
124
124
  const openLid = lidAtHinge.rotateAroundAxis([1, 0, 0], lidAngle, [0, hingeY, hingeZ]);
125
125
  const openScreen = screenAtHinge.rotateAroundAxis([1, 0, 0], lidAngle, [0, hingeY, hingeZ]);
@@ -20,12 +20,12 @@
20
20
  // joints re-adapt because they reference the panel edge lengths.
21
21
 
22
22
  // ── Parameters ─────────────────────────────────────────────────────
23
- const t = param('Thickness', 3, { min: 2, max: 6, step: 0.5 });
24
- const w = param('Width', 100, { min: 40, max: 300 });
25
- const d = param('Depth', 80, { min: 40, max: 200 });
26
- const h = param('Height', 50, { min: 20, max: 150 });
27
- const fold = param('Fold', 1, { min: 0, max: 1, step: 0.01 });
28
- const kerf = param('Kerf', 0.2, { min: 0, max: 0.5, step: 0.05 });
23
+ const t = Param.number('Thickness', 3, { min: 2, max: 6, step: 0.5 });
24
+ const w = Param.number('Width', 100, { min: 40, max: 300 });
25
+ const d = Param.number('Depth', 80, { min: 40, max: 200 });
26
+ const h = Param.number('Height', 50, { min: 20, max: 150 });
27
+ const fold = Param.number('Fold', 1, { min: 0, max: 1, step: 0.01 });
28
+ const kerf = Param.number('Kerf', 0.2, { min: 0, max: 0.5, step: 0.05 });
29
29
 
30
30
  // ── Create flat panels ─────────────────────────────────────────────
31
31
  // Each panel is a named rectangle with four edges: bottom, right, top, left.
@@ -15,12 +15,12 @@
15
15
  // • Step-by-step assembly instructions
16
16
 
17
17
  // ── Parameters ─────────────────────────────────────────────────────────
18
- const t = param('Thickness', 3, { min: 2, max: 6, step: 0.5 });
19
- const w = param('Width', 200, { min: 80, max: 400 });
20
- const d = param('Depth', 120, { min: 60, max: 250 });
21
- const h = param('Height', 50, { min: 20, max: 120 });
22
- const fold = param('Fold', 1, { min: 0, max: 1, step: 0.01 });
23
- const kerf = param('Kerf', 0.2, { min: 0, max: 0.5, step: 0.05 });
18
+ const t = Param.number('Thickness', 3, { min: 2, max: 6, step: 0.5 });
19
+ const w = Param.number('Width', 200, { min: 80, max: 400 });
20
+ const d = Param.number('Depth', 120, { min: 60, max: 250 });
21
+ const h = Param.number('Height', 50, { min: 20, max: 120 });
22
+ const fold = Param.number('Fold', 1, { min: 0, max: 1, step: 0.01 });
23
+ const kerf = Param.number('Kerf', 0.2, { min: 0, max: 0.5, step: 0.05 });
24
24
 
25
25
  // ── Flat panels ─────────────────────────────────────────────────────────
26
26
  // Named edges: bottom, right, top, left — CCW winding, origin at corner.
@@ -1,11 +1,11 @@
1
1
  // Liquid Soap Dispenser — staged dispense animation without fluid simulation.
2
2
  // Move "Dispense Progress" from 0 → 100 to preview one pump cycle.
3
3
 
4
- const bodyH = param("Bottle Height", 130, { min: 90, max: 180, unit: "mm" });
5
- const bodyR = param("Bottle Radius", 34, { min: 24, max: 45, unit: "mm" });
6
- const wall = param("Wall Thickness", 2.8, { min: 1.5, max: 5, unit: "mm" });
7
- const pumpStroke = param("Pump Stroke", 10, { min: 4, max: 18, unit: "mm" });
8
- const progressPct = param("Dispense Progress", 0, { min: 0, max: 100, unit: "%" });
4
+ const bodyH = Param.number("Bottle Height", 130, { min: 90, max: 180, unit: "mm" });
5
+ const bodyR = Param.number("Bottle Radius", 34, { min: 24, max: 45, unit: "mm" });
6
+ const wall = Param.number("Wall Thickness", 2.8, { min: 1.5, max: 5, unit: "mm" });
7
+ const pumpStroke = Param.number("Pump Stroke", 10, { min: 4, max: 18, unit: "mm" });
8
+ const progressPct = Param.number("Dispense Progress", 0, { min: 0, max: 100, unit: "%" });
9
9
 
10
10
  const progress = progressPct / 100;
11
11
  const clamp01 = (v) => Math.max(0, Math.min(1, v));
@@ -1,12 +1,12 @@
1
1
  // Origami Fish
2
2
  // Stylized folded-paper fish inspired by a side-view crane-fish form.
3
3
 
4
- const scale = param("Scale", 1.25, { min: 0.7, max: 1.9, step: 0.05 });
5
- const paper = param("Paper Thickness", 0.9, { min: 0.4, max: 2, step: 0.05, unit: "mm" });
6
- const fold = param("Fold", 30, { min: 0, max: 65, unit: "°" });
7
- const tailSpread = param("Tail Spread", 34, { min: 10, max: 70, unit: "°" });
8
- const tailDrop = param("Tail Drop", 26, { min: 0, max: 55, unit: "°" });
9
- const showStand = param("Show Stand", 1, { min: 0, max: 1, integer: true });
4
+ const scale = Param.number("Scale", 1.25, { min: 0.7, max: 1.9, step: 0.05 });
5
+ const paper = Param.number("Paper Thickness", 0.9, { min: 0.4, max: 2, step: 0.05, unit: "mm" });
6
+ const fold = Param.number("Fold", 30, { min: 0, max: 65, unit: "°" });
7
+ const tailSpread = Param.number("Tail Spread", 34, { min: 10, max: 70, unit: "°" });
8
+ const tailDrop = Param.number("Tail Drop", 26, { min: 0, max: 55, unit: "°" });
9
+ const showStand = Param.number("Show Stand", 1, { min: 0, max: 1, integer: true });
10
10
 
11
11
  const redMain = "#c51f3a";
12
12
  const redLight = "#d8324f";
@@ -1,8 +1,8 @@
1
1
  // Spider-Man Birthday Cake
2
2
  // A multi-tiered cake with Spider-Man colors and decorations.
3
3
 
4
- const tierHeight = param("Tier Height", 30, { min: 20, max: 50, unit: "mm" });
5
- const baseRadius = param("Base Radius", 60, { min: 40, max: 100, unit: "mm" });
4
+ const tierHeight = Param.number("Tier Height", 30, { min: 20, max: 50, unit: "mm" });
5
+ const baseRadius = Param.number("Base Radius", 60, { min: 40, max: 100, unit: "mm" });
6
6
 
7
7
  // Colors
8
8
  const spideyRed = '#e60000';
@@ -1,11 +1,11 @@
1
1
  // Storage Container — parametric open-top bin
2
2
  // Used by shelf-unit.forge.js via require()
3
3
 
4
- const w = param("Container Width", 120, { min: 60, max: 200, unit: "mm" });
5
- const d = param("Container Depth", 180, { min: 100, max: 300, unit: "mm" });
6
- const h = param("Container Height", 100, { min: 50, max: 200, unit: "mm" });
7
- const wall = param("Wall", 3, { min: 1.5, max: 6, unit: "mm" });
8
- const lipH = param("Lip Height", 5, { min: 2, max: 10, unit: "mm" });
4
+ const w = Param.number("Container Width", 120, { min: 60, max: 200, unit: "mm" });
5
+ const d = Param.number("Container Depth", 180, { min: 100, max: 300, unit: "mm" });
6
+ const h = Param.number("Container Height", 100, { min: 50, max: 200, unit: "mm" });
7
+ const wall = Param.number("Wall", 3, { min: 1.5, max: 6, unit: "mm" });
8
+ const lipH = Param.number("Lip Height", 5, { min: 2, max: 10, unit: "mm" });
9
9
 
10
10
  // Outer shell
11
11
  const outer = box(w, d, h);
@@ -1,12 +1,12 @@
1
1
  // Tool Shelf — multi-shelf unit with identical containers
2
2
  // Demonstrates require() for reusing the same container across shelves
3
3
 
4
- const shelfW = param("Shelf Width", 800, { min: 400, max: 1200, unit: "mm" });
5
- const shelfD = param("Shelf Depth", 200, { min: 150, max: 350, unit: "mm" });
6
- const totalH = param("Total Height", 1200, { min: 600, max: 1800, unit: "mm" });
7
- const boardT = param("Board Thickness", 18, { min: 12, max: 25, unit: "mm" });
8
- const rows = param("Shelf Rows", 4, { min: 2, max: 6, integer: true });
9
- const cols = param("Containers/Row", 3, { min: 1, max: 6, integer: true });
4
+ const shelfW = Param.number("Shelf Width", 800, { min: 400, max: 1200, unit: "mm" });
5
+ const shelfD = Param.number("Shelf Depth", 200, { min: 150, max: 350, unit: "mm" });
6
+ const totalH = Param.number("Total Height", 1200, { min: 600, max: 1800, unit: "mm" });
7
+ const boardT = Param.number("Board Thickness", 18, { min: 12, max: 25, unit: "mm" });
8
+ const rows = Param.number("Shelf Rows", 4, { min: 2, max: 6, integer: true });
9
+ const cols = Param.number("Containers/Row", 3, { min: 1, max: 6, integer: true });
10
10
 
11
11
  // Container dimensions (must match container.forge.js defaults or be close)
12
12
  const containerW = 120;
@@ -7,11 +7,11 @@
7
7
  // - BOM listing fastener quantities
8
8
  // - Optional exploded view
9
9
 
10
- const plateW = param("Plate Width", 60, { min: 40, max: 120, unit: "mm" });
11
- const plateD = param("Plate Depth", 40, { min: 30, max: 80, unit: "mm" });
12
- const topThick = param("Top Thick", 8, { min: 4, max: 20, unit: "mm" });
13
- const botThick = param("Bot Thick", 8, { min: 4, max: 20, unit: "mm" });
14
- const exploded = param("Explode", 0, { min: 0, max: 1, step: 1 });
10
+ const plateW = Param.number("Plate Width", 60, { min: 40, max: 120, unit: "mm" });
11
+ const plateD = Param.number("Plate Depth", 40, { min: 30, max: 80, unit: "mm" });
12
+ const topThick = Param.number("Top Thick", 8, { min: 4, max: 20, unit: "mm" });
13
+ const botThick = Param.number("Bot Thick", 8, { min: 4, max: 20, unit: "mm" });
14
+ const exploded = Param.number("Explode", 0, { min: 0, max: 1, step: 1 });
15
15
 
16
16
  // Bolt-circle inset from plate edge
17
17
  const inset = 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgecad",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Code-first parametric CAD for JavaScript/TypeScript, in the browser and CLI.",
5
5
  "license": "BUSL-1.1",
6
6
  "type": "module",
@@ -68,6 +68,7 @@
68
68
  "meta:path": "bash scripts/local-meta.sh path",
69
69
  "gen:types": "node scripts/gen-forge-types.mjs",
70
70
  "gen:docs": "node scripts/gen-api-docs.mjs",
71
+ "gen:cli-docs": "node scripts/gen-cli-docs.mjs",
71
72
  "refresh": "node scripts/refresh.mjs"
72
73
  },
73
74
  "dependencies": {
@@ -87,6 +88,7 @@
87
88
  "lz-string": "^1.5.0",
88
89
  "manifold-3d": "^3.4.0",
89
90
  "meshoptimizer": "^1.0.1",
91
+ "mp4-muxer": "^5.2.1",
90
92
  "nanoid": "^5.1.7",
91
93
  "opencascade.js": "2.0.0-beta.b5ff984",
92
94
  "opentype.js": "^1.3.4",