forgecad 0.6.3 → 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 (234) hide show
  1. package/README.md +3 -12
  2. package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-D4bocK4E.js} +250 -151
  3. package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
  4. package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-D3A_g8V3.js} +329 -163
  5. package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-BWYUSpUN.css} +590 -136
  6. package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
  7. package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-kWjKaC_t.js} +2 -4
  8. package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
  9. package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
  10. package/dist/assets/PricingPage-BsU5vzEx.js +232 -0
  11. package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-PqvpAKIs.js} +129 -5
  12. package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-C-hzNUMy.js} +8949 -3161
  13. package/dist/assets/{Viewport-CoB46f5R.js → index-Pz321YAt.js} +38382 -7501
  14. package/dist/assets/{index-2hfs_ub0.css → index-ay13WNfa.css} +726 -53
  15. package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
  16. package/dist/assets/{manifold-CqNMHHKO.js → manifold-BcbjWLIo.js} +4 -3
  17. package/dist/assets/{manifold-Cce9wRFz.js → manifold-DBckbFgx.js} +1 -1
  18. package/dist/assets/{manifold-D6BeHIOo.js → manifold-O2AAGXyj.js} +1 -1
  19. package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-Dxr-5A7w.js} +8760 -3559
  20. package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
  21. package/dist/docs/index.html +2 -2
  22. package/dist/docs-raw/CLI.md +341 -718
  23. package/dist/docs-raw/generated/assembly.md +699 -112
  24. package/dist/docs-raw/generated/concepts.md +1834 -1346
  25. package/dist/docs-raw/generated/core.md +1012 -1059
  26. package/dist/docs-raw/generated/curves.md +759 -116
  27. package/dist/docs-raw/generated/lib.md +43 -748
  28. package/dist/docs-raw/generated/output.md +139 -245
  29. package/dist/docs-raw/generated/sdf.md +208 -0
  30. package/dist/docs-raw/generated/sheet-metal.md +473 -21
  31. package/dist/docs-raw/generated/sketch.md +1518 -362
  32. package/dist/docs-raw/generated/viewport.md +368 -299
  33. package/dist/docs-raw/generated/wood.md +104 -0
  34. package/dist/index.html +2 -2
  35. package/dist/landing/proof-ams-adapter.png +0 -0
  36. package/dist/landing/proof-bolt-and-nut.png +0 -0
  37. package/dist/landing/proof-fillet-enclosure.png +0 -0
  38. package/dist/landing/proof-glasses.png +0 -0
  39. package/dist/landing/proof-gyroid.png +0 -0
  40. package/dist/sitemap.xml +6 -6
  41. package/dist-cli/forgecad.js +12321 -5700
  42. package/dist-cli/forgecad.js.map +1 -0
  43. package/dist-cli/solver-46FFSK2U.js +363 -0
  44. package/dist-cli/solver-46FFSK2U.js.map +1 -0
  45. package/dist-skill/CONTEXT.md +4890 -6302
  46. package/dist-skill/SKILL-dev.md +22 -66
  47. package/dist-skill/SKILL.md +20 -59
  48. package/dist-skill/docs/API/core/concepts.md +37 -92
  49. package/dist-skill/docs/CLI.md +341 -718
  50. package/dist-skill/docs/generated/assembly.md +699 -112
  51. package/dist-skill/docs/generated/core.md +1012 -1059
  52. package/dist-skill/docs/generated/curves.md +759 -116
  53. package/dist-skill/docs/generated/lib.md +43 -748
  54. package/dist-skill/docs/generated/output.md +139 -245
  55. package/dist-skill/docs/generated/sdf.md +208 -0
  56. package/dist-skill/docs/generated/sheet-metal.md +473 -21
  57. package/dist-skill/docs/generated/sketch.md +1518 -362
  58. package/dist-skill/docs/generated/viewport.md +368 -299
  59. package/dist-skill/docs/generated/wood.md +104 -0
  60. package/dist-skill/docs/guides/coordinate-system.md +11 -17
  61. package/dist-skill/docs/guides/geometry-conventions.md +13 -70
  62. package/dist-skill/docs/guides/joint-design.md +78 -0
  63. package/dist-skill/docs/guides/modeling-recipes.md +22 -195
  64. package/dist-skill/docs/guides/positioning.md +88 -147
  65. package/dist-skill/docs-dev/API/core/concepts.md +78 -0
  66. package/dist-skill/docs-dev/CLI.md +488 -0
  67. package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
  68. package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
  69. package/dist-skill/{docs → docs-dev}/coding.md +2 -4
  70. package/dist-skill/docs-dev/component-model.md +164 -0
  71. package/dist-skill/docs-dev/generated/assembly.md +779 -0
  72. package/dist-skill/docs-dev/generated/core.md +1676 -0
  73. package/dist-skill/docs-dev/generated/curves.md +855 -0
  74. package/dist-skill/docs-dev/generated/lib.md +55 -0
  75. package/dist-skill/docs-dev/generated/output.md +234 -0
  76. package/dist-skill/docs-dev/generated/sdf.md +208 -0
  77. package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
  78. package/dist-skill/docs-dev/generated/sketch.md +1753 -0
  79. package/dist-skill/docs-dev/generated/viewport.md +513 -0
  80. package/dist-skill/docs-dev/generated/wood.md +104 -0
  81. package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
  82. package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
  83. package/dist-skill/docs-dev/guides/joint-design.md +78 -0
  84. package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
  85. package/dist-skill/docs-dev/guides/positioning.md +151 -0
  86. package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
  87. package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
  88. package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
  89. package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
  90. package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
  91. package/examples/api/attachTo-basics.forge.js +8 -8
  92. package/examples/api/bill-of-materials.forge.js +9 -9
  93. package/examples/api/bolt-pattern.forge.js +5 -5
  94. package/examples/api/boolean-operations.forge.js +5 -5
  95. package/examples/api/bounding-box-visualizer.forge.js +3 -3
  96. package/examples/api/clone-duplicate.forge.js +2 -2
  97. package/examples/api/colors-union-vs-array.forge.js +6 -6
  98. package/examples/api/connector-assembly.forge.js +8 -6
  99. package/examples/api/connector-basics.forge.js +7 -7
  100. package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
  101. package/examples/api/elbow-test.forge.js +3 -3
  102. package/examples/api/extrude-options.forge.js +8 -14
  103. package/examples/api/feature-created-faces.forge.js +6 -10
  104. package/examples/api/fillet-showcase.forge.js +2 -2
  105. package/examples/api/folded-service-panel-cover.forge.js +2 -2
  106. package/examples/api/gears-tier1.forge.js +5 -5
  107. package/examples/api/group-test.forge.js +3 -3
  108. package/examples/api/group-vs-union.forge.js +1 -1
  109. package/examples/api/highlight-debug.forge.js +4 -0
  110. package/examples/api/js-module-pillars.js +1 -1
  111. package/examples/api/js-module-scene.js +2 -2
  112. package/examples/api/mesh-import-slats.forge.js +4 -4
  113. package/examples/api/patterns.forge.js +3 -3
  114. package/examples/api/pointAlong-orientation.forge.js +3 -3
  115. package/examples/api/profile-2020-b-slot6.forge.js +4 -5
  116. package/examples/api/route-perimeter-flange.forge.js +1 -1
  117. package/examples/api/sdf-rover-demo.forge.js +10 -10
  118. package/examples/api/sketch-on-face-demo.forge.js +2 -2
  119. package/examples/api/sketch-regions.forge.js +4 -4
  120. package/examples/api/sketch-rounding-strategies.forge.js +1 -1
  121. package/examples/api/smooth-curve-connections.forge.js +1 -1
  122. package/examples/api/transition-curves.forge.js +4 -4
  123. package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
  124. package/examples/api/variable-sweep-test.forge.js +2 -2
  125. package/examples/api/wood-joinery.forge.js +60 -0
  126. package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
  127. package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
  128. package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
  129. package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
  130. package/examples/constraints/03-redundant-constraints.forge.js +2 -2
  131. package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
  132. package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
  133. package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
  134. package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
  135. package/examples/constraints/09-stress-spiral.forge.js +1 -1
  136. package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
  137. package/examples/constraints/11-surface-grid.forge.js +2 -2
  138. package/examples/constraints/12-surface-nested.forge.js +4 -4
  139. package/examples/constraints/13-surface-complex.forge.js +1 -1
  140. package/examples/exact-arc-housing.forge.js +12 -0
  141. package/examples/experiments/drone-arm.forge.js +53 -0
  142. package/examples/furniture/adjustable-table.forge.js +15 -15
  143. package/examples/furniture/bathroom.forge.js +26 -26
  144. package/examples/furniture/chair.forge.js +13 -13
  145. package/examples/furniture/picture-frame.forge.js +6 -6
  146. package/examples/furniture/shoe-rack-doors.forge.js +8 -8
  147. package/examples/furniture/shoe-rack.forge.js +7 -7
  148. package/examples/furniture/table-lamp.forge.js +8 -8
  149. package/examples/gcode/lissajous-vase.forge.js +4 -4
  150. package/examples/gcode/math-surface.forge.js +3 -3
  151. package/examples/gcode/parametric-vase.forge.js +4 -4
  152. package/examples/gcode/spiral-tower.forge.js +4 -4
  153. package/examples/generative/crystal-growth.forge.js +9 -9
  154. package/examples/generative/frost-spires.forge.js +9 -9
  155. package/examples/generative/golden-spiral-tower.forge.js +11 -11
  156. package/examples/generative/molten-forge.forge.js +6 -6
  157. package/examples/generative/neon-coral.forge.js +7 -7
  158. package/examples/mechanical/3d-printer.forge.js +37 -37
  159. package/examples/mechanical/5-finger-robot-hand.forge.js +19 -19
  160. package/examples/mechanical/airplane-propeller.forge.js +9 -9
  161. package/examples/mechanical/bolt-and-nut.forge.js +10 -10
  162. package/examples/mechanical/door-with-hinges.forge.js +7 -7
  163. package/examples/mechanical/fillet-enclosure.forge.js +15 -11
  164. package/examples/mechanical/headphone-hanger-v2.forge.js +11 -11
  165. package/examples/mechanical/robot_hand.forge.js +24 -24
  166. package/examples/mechanical/robot_hand_2.forge.js +26 -26
  167. package/examples/nurbs-surface.forge.js +8 -0
  168. package/examples/nurbs-tube.forge.js +7 -0
  169. package/examples/products/bottle.forge.js +8 -8
  170. package/examples/products/chess-set.forge.js +25 -25
  171. package/examples/products/classical-piano.forge.js +20 -20
  172. package/examples/products/clock.forge.js +33 -33
  173. package/examples/products/cup.forge.js +5 -5
  174. package/examples/products/iphone.forge.js +20 -20
  175. package/examples/products/laptop.forge.js +24 -24
  176. package/examples/products/laser-cut-box.forge.js +6 -6
  177. package/examples/products/laser-cut-tray.forge.js +6 -6
  178. package/examples/products/liquid-soap-dispenser.forge.js +23 -23
  179. package/examples/products/origami-fish.forge.js +14 -12
  180. package/examples/products/spiderman-cake.forge.js +6 -6
  181. package/examples/shelf/container.forge.js +5 -5
  182. package/examples/shelf/shelf-unit.forge.js +6 -6
  183. package/examples/toolbox/bolted-joint.forge.js +7 -7
  184. package/package.json +9 -4
  185. package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
  186. package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
  187. package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
  188. package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
  189. package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
  190. package/dist/assets/index-1CYp3zUp.js +0 -1455
  191. package/dist-skill/docs/API/API.md +0 -1666
  192. package/dist-skill/docs/API/README.md +0 -37
  193. package/dist-skill/docs/API/assembly/assembly.md +0 -617
  194. package/dist-skill/docs/API/core/edge-queries.md +0 -130
  195. package/dist-skill/docs/API/core/parameters.md +0 -122
  196. package/dist-skill/docs/API/core/reserved-terms.md +0 -137
  197. package/dist-skill/docs/API/core/sdf.md +0 -326
  198. package/dist-skill/docs/API/core/skill-cli.md +0 -194
  199. package/dist-skill/docs/API/core/skill-guide.md +0 -205
  200. package/dist-skill/docs/API/core/specs.md +0 -186
  201. package/dist-skill/docs/API/core/topology.md +0 -372
  202. package/dist-skill/docs/API/entities.md +0 -268
  203. package/dist-skill/docs/API/output/bom.md +0 -58
  204. package/dist-skill/docs/API/output/brep-export.md +0 -87
  205. package/dist-skill/docs/API/output/dimensions.md +0 -67
  206. package/dist-skill/docs/API/output/export.md +0 -110
  207. package/dist-skill/docs/API/output/gcode.md +0 -195
  208. package/dist-skill/docs/API/runtime/viewport.md +0 -420
  209. package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
  210. package/dist-skill/docs/API/sketch/anchor.md +0 -37
  211. package/dist-skill/docs/API/sketch/booleans.md +0 -91
  212. package/dist-skill/docs/API/sketch/core.md +0 -73
  213. package/dist-skill/docs/API/sketch/extrude.md +0 -62
  214. package/dist-skill/docs/API/sketch/on-face.md +0 -104
  215. package/dist-skill/docs/API/sketch/operations.md +0 -78
  216. package/dist-skill/docs/API/sketch/path.md +0 -75
  217. package/dist-skill/docs/API/sketch/primitives.md +0 -146
  218. package/dist-skill/docs/API/sketch/regions.md +0 -80
  219. package/dist-skill/docs/API/sketch/text.md +0 -108
  220. package/dist-skill/docs/API/sketch/transforms.md +0 -65
  221. package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
  222. package/dist-skill/docs/INDEX.md +0 -94
  223. package/dist-skill/docs/RELEASING.md +0 -55
  224. package/dist-skill/docs/cli-monetization.md +0 -111
  225. package/dist-skill/docs/deployment.md +0 -281
  226. package/dist-skill/docs/generated/concepts.md +0 -2112
  227. package/dist-skill/docs/internals/shape-from-slices.md +0 -152
  228. package/dist-skill/docs/platform/admin.md +0 -45
  229. package/dist-skill/docs/platform/architecture.md +0 -79
  230. package/dist-skill/docs/platform/auth.md +0 -110
  231. package/dist-skill/docs/platform/email.md +0 -67
  232. package/dist-skill/docs/platform/projects.md +0 -111
  233. package/dist-skill/docs/platform/sharing.md +0 -90
  234. package/dist-skill/docs/runbook.md +0 -345
@@ -0,0 +1,232 @@
1
+ import { h as useNavigate, j as jsxRuntimeExports, L as Link } from "./vendor-react-CG3i_wp0.js";
2
+ import { u as useAuthStore, b as authFetch } from "./index-Pz321YAt.js";
3
+ const PLANS = [
4
+ {
5
+ interval: "monthly",
6
+ name: "Pro Monthly",
7
+ price: "$15",
8
+ period: "/mo",
9
+ features: [
10
+ "STEP & BREP export",
11
+ "High-quality Blender renders",
12
+ "GIF & MP4 capture",
13
+ "G-code & cutting layouts",
14
+ "SDF/URDF robotics export",
15
+ "500 MB cloud storage"
16
+ ]
17
+ },
18
+ {
19
+ interval: "annual",
20
+ name: "Pro Annual",
21
+ price: "$120",
22
+ period: "/yr",
23
+ highlight: "Save 33%",
24
+ features: [
25
+ "Everything in Monthly",
26
+ "Billed annually ($10/mo effective)",
27
+ "Priority support"
28
+ ]
29
+ },
30
+ {
31
+ interval: "lifetime",
32
+ name: "Pro Lifetime",
33
+ price: "$299",
34
+ period: "one-time",
35
+ highlight: "Best value",
36
+ features: [
37
+ "Everything in Pro, forever",
38
+ "No recurring payments",
39
+ "All future Pro features included"
40
+ ]
41
+ }
42
+ ];
43
+ const FREE_FEATURES = [
44
+ "Full CAD editor",
45
+ "Run .forge.js scripts",
46
+ "STL, 3MF, SVG export",
47
+ "Standard PNG render",
48
+ "50 MB cloud storage",
49
+ "Unlimited local projects"
50
+ ];
51
+ const cardStyle = {
52
+ background: "var(--fc-bgPanel)",
53
+ border: "1px solid var(--fc-border)",
54
+ borderRadius: 12,
55
+ padding: "32px 24px",
56
+ display: "flex",
57
+ flexDirection: "column",
58
+ flex: 1,
59
+ minWidth: 240
60
+ };
61
+ const highlightCardStyle = {
62
+ ...cardStyle,
63
+ border: "2px solid var(--fc-accent)",
64
+ position: "relative"
65
+ };
66
+ function PricingPage() {
67
+ const user = useAuthStore((s) => s.user);
68
+ const navigate = useNavigate();
69
+ const isPro = (user == null ? void 0 : user.plan) === "pro";
70
+ async function handleCheckout(interval) {
71
+ if (!user) {
72
+ navigate("/app");
73
+ return;
74
+ }
75
+ try {
76
+ const data = await authFetch("/api/billing/checkout", {
77
+ method: "POST",
78
+ body: JSON.stringify({ interval })
79
+ });
80
+ window.location.href = data.url;
81
+ } catch (err) {
82
+ alert(err instanceof Error ? err.message : "Failed to connect to billing service");
83
+ }
84
+ }
85
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { minHeight: "100vh", background: "var(--fc-bg)", color: "var(--fc-text)" }, children: [
86
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
87
+ "nav",
88
+ {
89
+ style: {
90
+ position: "fixed",
91
+ top: 0,
92
+ left: 0,
93
+ right: 0,
94
+ height: 56,
95
+ display: "flex",
96
+ alignItems: "center",
97
+ justifyContent: "space-between",
98
+ padding: "0 24px",
99
+ background: "var(--fc-bg)",
100
+ borderBottom: "1px solid var(--fc-border)",
101
+ zIndex: 100
102
+ },
103
+ children: [
104
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
105
+ Link,
106
+ {
107
+ to: "/",
108
+ style: { display: "flex", alignItems: "center", gap: 8, textDecoration: "none", color: "var(--fc-text)" },
109
+ children: [
110
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 20 }, children: "⚒" }),
111
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 16, fontWeight: 700, color: "var(--fc-accent)" }, children: "ForgeCAD" })
112
+ ]
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
116
+ Link,
117
+ {
118
+ to: "/app",
119
+ style: {
120
+ padding: "6px 16px",
121
+ fontSize: 14,
122
+ fontWeight: 600,
123
+ background: "var(--fc-accent)",
124
+ color: "var(--fc-accentText)",
125
+ borderRadius: 6,
126
+ textDecoration: "none"
127
+ },
128
+ children: "Open App"
129
+ }
130
+ )
131
+ ]
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { maxWidth: 1e3, margin: "0 auto", padding: "96px 24px 64px" }, children: [
135
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { textAlign: "center", marginBottom: 48 }, children: [
136
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { style: { fontSize: 36, fontWeight: 800, marginBottom: 12 }, children: "Simple, transparent pricing" }),
137
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: { fontSize: 16, color: "var(--fc-textMuted)", maxWidth: 500, margin: "0 auto" }, children: "ForgeCAD is free for hobbyists and students. Go Pro for professional CAD interchange and manufacturing outputs." })
138
+ ] }),
139
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginBottom: 48 }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
140
+ "div",
141
+ {
142
+ style: {
143
+ ...cardStyle,
144
+ maxWidth: 400,
145
+ margin: "0 auto",
146
+ background: "var(--fc-bg)"
147
+ },
148
+ children: [
149
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: 20, fontWeight: 700, marginBottom: 4 }, children: "Free" }),
150
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { fontSize: 32, fontWeight: 800, marginBottom: 16 }, children: [
151
+ "$0 ",
152
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 14, fontWeight: 400, color: "var(--fc-textMuted)" }, children: "forever" })
153
+ ] }),
154
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: FREE_FEATURES.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsx(
155
+ "li",
156
+ {
157
+ style: {
158
+ padding: "6px 0",
159
+ fontSize: 14,
160
+ color: "var(--fc-textMuted)",
161
+ borderBottom: "1px solid var(--fc-border)"
162
+ },
163
+ children: f
164
+ },
165
+ f
166
+ )) })
167
+ ]
168
+ }
169
+ ) }),
170
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", gap: 20, flexWrap: "wrap", justifyContent: "center" }, children: PLANS.map((plan) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: plan.highlight ? highlightCardStyle : cardStyle, children: [
171
+ plan.highlight && /* @__PURE__ */ jsxRuntimeExports.jsx(
172
+ "div",
173
+ {
174
+ style: {
175
+ position: "absolute",
176
+ top: -12,
177
+ left: "50%",
178
+ transform: "translateX(-50%)",
179
+ background: "var(--fc-accent)",
180
+ color: "var(--fc-accentText)",
181
+ padding: "2px 12px",
182
+ borderRadius: 10,
183
+ fontSize: 12,
184
+ fontWeight: 600
185
+ },
186
+ children: plan.highlight
187
+ }
188
+ ),
189
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: 18, fontWeight: 700, marginBottom: 4 }, children: plan.name }),
190
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { fontSize: 32, fontWeight: 800, marginBottom: 16 }, children: [
191
+ plan.price,
192
+ " ",
193
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 14, fontWeight: 400, color: "var(--fc-textMuted)" }, children: plan.period })
194
+ ] }),
195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { style: { listStyle: "none", padding: 0, margin: "0 0 24px", flex: 1 }, children: plan.features.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsx(
196
+ "li",
197
+ {
198
+ style: {
199
+ padding: "6px 0",
200
+ fontSize: 14,
201
+ color: "var(--fc-textMuted)",
202
+ borderBottom: "1px solid var(--fc-border)"
203
+ },
204
+ children: f
205
+ },
206
+ f
207
+ )) }),
208
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
209
+ "button",
210
+ {
211
+ onClick: () => handleCheckout(plan.interval),
212
+ disabled: isPro,
213
+ style: {
214
+ padding: "10px 20px",
215
+ fontSize: 14,
216
+ fontWeight: 600,
217
+ background: isPro ? "var(--fc-bgActive)" : "var(--fc-accent)",
218
+ color: isPro ? "var(--fc-textMuted)" : "var(--fc-accentText)",
219
+ border: "none",
220
+ borderRadius: 8,
221
+ cursor: isPro ? "default" : "pointer"
222
+ },
223
+ children: isPro ? "Current plan" : "Get started"
224
+ }
225
+ )
226
+ ] }, plan.interval)) })
227
+ ] })
228
+ ] });
229
+ }
230
+ export {
231
+ PricingPage
232
+ };
@@ -1,5 +1,5 @@
1
- import { r as reactExports, j as jsxRuntimeExports, L as Link } from "./vendor-react-Dt7-aaJH.js";
2
- import { u as useAuthStore, a as authFetch } from "./index-1CYp3zUp.js";
1
+ import { r as reactExports, j as jsxRuntimeExports, L as Link } from "./vendor-react-CG3i_wp0.js";
2
+ import { u as useAuthStore, b as authFetch } from "./index-Pz321YAt.js";
3
3
  function timeAgo(dateStr) {
4
4
  const ms = Date.now() - new Date(dateStr).getTime();
5
5
  const mins = Math.floor(ms / 6e4);
@@ -414,14 +414,50 @@ function PlanSection() {
414
414
  const storageLimitMB = isPro ? 500 : 50;
415
415
  const storageUsedMB = 17.2;
416
416
  const storagePercent = storageUsedMB / storageLimitMB * 100;
417
+ const [subscription, setSubscription] = reactExports.useState(null);
418
+ const [licenseKey, setLicenseKey] = reactExports.useState(null);
419
+ const [licenseExpiry, setLicenseExpiry] = reactExports.useState(null);
420
+ const [copied, setCopied] = reactExports.useState(false);
421
+ const [generating, setGenerating] = reactExports.useState(false);
422
+ reactExports.useEffect(() => {
423
+ authFetch("/api/billing/subscription").then((data) => setSubscription(data.subscription)).catch(() => {
424
+ });
425
+ }, []);
426
+ const generateLicenseKey = reactExports.useCallback(async () => {
427
+ setGenerating(true);
428
+ try {
429
+ const data = await authFetch("/api/license/generate", {
430
+ method: "POST"
431
+ });
432
+ setLicenseKey(data.token);
433
+ setLicenseExpiry(data.expiresAt);
434
+ } catch {
435
+ } finally {
436
+ setGenerating(false);
437
+ }
438
+ }, []);
439
+ const copyKey = reactExports.useCallback(() => {
440
+ if (!licenseKey) return;
441
+ navigator.clipboard.writeText(licenseKey);
442
+ setCopied(true);
443
+ setTimeout(() => setCopied(false), 2e3);
444
+ }, [licenseKey]);
445
+ const openBillingPortal = reactExports.useCallback(async () => {
446
+ try {
447
+ const data = await authFetch("/api/billing/portal", { method: "POST" });
448
+ window.location.href = data.url;
449
+ } catch {
450
+ }
451
+ }, []);
452
+ const intervalLabel = (subscription == null ? void 0 : subscription.interval) ? { monthly: "Monthly", annual: "Annual", lifetime: "Lifetime", "admin-granted": "Granted" }[subscription.interval] ?? subscription.interval : "";
417
453
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginBottom: 40 }, children: [
418
454
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { style: sectionHeaderStyle, children: "Plan & Usage" }),
419
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: sectionDescStyle, children: "Your current plan and storage." }),
455
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: sectionDescStyle, children: "Your current plan, billing, and CLI license." }),
420
456
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: cardBodyStyle, children: [
421
457
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 16 }, children: [
422
458
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
423
459
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontWeight: 600, fontSize: 16 }, children: [
424
- isPro ? "Pro" : "Free",
460
+ isPro ? `Pro ${intervalLabel}` : "Free",
425
461
  " Plan"
426
462
  ] }),
427
463
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -443,7 +479,37 @@ function PlanSection() {
443
479
  }
444
480
  )
445
481
  ] }),
446
- !isPro && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { style: { ...btnPrimaryStyle, padding: "4px 10px", fontSize: 12 }, children: "Upgrade to Pro" })
482
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", gap: 8 }, children: [
483
+ isPro && (subscription == null ? void 0 : subscription.hasStripe) && /* @__PURE__ */ jsxRuntimeExports.jsx(
484
+ "button",
485
+ {
486
+ onClick: openBillingPortal,
487
+ style: { ...btnPrimaryStyle, padding: "4px 10px", fontSize: 12 },
488
+ children: "Manage Subscription"
489
+ }
490
+ ),
491
+ !isPro && /* @__PURE__ */ jsxRuntimeExports.jsx(
492
+ Link,
493
+ {
494
+ to: "/pricing",
495
+ style: {
496
+ ...btnPrimaryStyle,
497
+ padding: "4px 10px",
498
+ fontSize: 12,
499
+ textDecoration: "none",
500
+ display: "inline-block"
501
+ },
502
+ children: "Upgrade to Pro"
503
+ }
504
+ )
505
+ ] })
506
+ ] }),
507
+ subscription && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { fontSize: 12, color: "var(--fc-textMuted)", marginBottom: 16 }, children: [
508
+ subscription.currentPeriodEnd && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
509
+ "Next billing: ",
510
+ new Date(subscription.currentPeriodEnd).toLocaleDateString()
511
+ ] }),
512
+ subscription.canceledAt && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--fc-warning)" }, children: " (Canceled, active until period end)" })
447
513
  ] }),
448
514
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
449
515
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: 13, fontWeight: 500 }, children: "Storage" }),
@@ -495,6 +561,64 @@ function PlanSection() {
495
561
  )
496
562
  ] })
497
563
  ] }) }),
564
+ isPro && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
565
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { style: { fontSize: 14, fontWeight: 600, margin: "24px 0 8px" }, children: "CLI License Key" }),
566
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: cardBodyStyle, children: [
567
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: 12, color: "var(--fc-textMuted)", marginBottom: 12 }, children: "Use this key to unlock Pro features in the ForgeCAD CLI. Keys are valid for 30 days and auto-refresh." }),
568
+ licenseKey ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
569
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
570
+ "div",
571
+ {
572
+ style: {
573
+ fontFamily: "monospace",
574
+ fontSize: 12,
575
+ background: "var(--fc-bgActive)",
576
+ padding: "8px 12px",
577
+ borderRadius: 6,
578
+ wordBreak: "break-all",
579
+ marginBottom: 8
580
+ },
581
+ children: licenseKey
582
+ }
583
+ ),
584
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
585
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: copyKey, style: { ...btnPrimaryStyle, padding: "4px 10px", fontSize: 12 }, children: copied ? "Copied!" : "Copy" }),
586
+ licenseExpiry && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontSize: 11, color: "var(--fc-textMuted)" }, children: [
587
+ "Expires: ",
588
+ new Date(licenseExpiry).toLocaleDateString()
589
+ ] })
590
+ ] }),
591
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
592
+ "div",
593
+ {
594
+ style: {
595
+ marginTop: 12,
596
+ padding: "8px 12px",
597
+ background: "var(--fc-bg)",
598
+ borderRadius: 6,
599
+ fontSize: 12,
600
+ fontFamily: "monospace",
601
+ color: "var(--fc-textMuted)"
602
+ },
603
+ children: [
604
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginBottom: 4, color: "var(--fc-textDim)" }, children: "Quick start:" }),
605
+ "forgecad login",
606
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
607
+ "forgecad license activate"
608
+ ]
609
+ }
610
+ )
611
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
612
+ "button",
613
+ {
614
+ onClick: generateLicenseKey,
615
+ disabled: generating,
616
+ style: { ...btnPrimaryStyle, padding: "6px 14px", fontSize: 13 },
617
+ children: generating ? "Generating..." : "Generate License Key"
618
+ }
619
+ )
620
+ ] }) })
621
+ ] }),
498
622
  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { style: { fontSize: 14, fontWeight: 600, color: "var(--fc-error)", margin: "24px 0 8px" }, children: "Danger Zone" }),
499
623
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...cardStyle, borderColor: "rgba(248, 81, 73, 0.3)" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { ...cardBodyStyle, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16 }, children: [
500
624
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [