forgecad 0.6.3 → 0.7.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 (193) hide show
  1. package/README.md +2 -11
  2. package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-DAu1C1ST.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-Gc_BCdqC.js} +269 -143
  5. package/dist/assets/EditorApp-D9bJvtf7.js +11338 -0
  6. package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-DG1-oUSV.css} +459 -87
  7. package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-CEO8XbV8.js} +2 -4
  8. package/dist/assets/LandingPage-CdCuEOdC.js +451 -0
  9. package/dist/assets/PricingPage-BSrxu6d7.js +232 -0
  10. package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-FUCSIRq6.js} +129 -5
  11. package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-KoR0SNKq.js} +6770 -2914
  12. package/dist/assets/{index-2hfs_ub0.css → index-CyVd1D4D.css} +227 -53
  13. package/dist/assets/{Viewport-CoB46f5R.js → index-wTEK39at.js} +31385 -6439
  14. package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
  15. package/dist/assets/{manifold-CqNMHHKO.js → manifold-B1sGWdYk.js} +4 -3
  16. package/dist/assets/{manifold-Cce9wRFz.js → manifold-D7o0N50J.js} +1 -1
  17. package/dist/assets/{manifold-D6BeHIOo.js → manifold-G5sBaXzi.js} +1 -1
  18. package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-DYcRHhv9.js} +6798 -3341
  19. package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
  20. package/dist/docs-raw/generated/assembly.md +691 -112
  21. package/dist/docs-raw/generated/concepts.md +1225 -1400
  22. package/dist/docs-raw/generated/core.md +464 -1412
  23. package/dist/docs-raw/generated/curves.md +593 -117
  24. package/dist/docs-raw/generated/lib.md +38 -748
  25. package/dist/docs-raw/generated/output.md +139 -245
  26. package/dist/docs-raw/generated/sheet-metal.md +473 -21
  27. package/dist/docs-raw/generated/sketch.md +553 -349
  28. package/dist/docs-raw/generated/viewport.md +345 -303
  29. package/dist/docs-raw/generated/wood.md +104 -0
  30. package/dist/index.html +2 -2
  31. package/dist/sitemap.xml +6 -6
  32. package/dist-cli/chunk-PZ5AY32C.js +10 -0
  33. package/dist-cli/chunk-PZ5AY32C.js.map +1 -0
  34. package/dist-cli/forgecad.js +9435 -5407
  35. package/dist-cli/forgecad.js.map +1 -0
  36. package/dist-cli/solver-FV7TJZGI.js +365 -0
  37. package/dist-cli/solver-FV7TJZGI.js.map +1 -0
  38. package/dist-skill/CONTEXT.md +3186 -7145
  39. package/dist-skill/SKILL-dev.md +21 -63
  40. package/dist-skill/SKILL.md +12 -56
  41. package/dist-skill/docs/API/core/concepts.md +16 -98
  42. package/dist-skill/docs/CLI/export.md +91 -0
  43. package/dist-skill/docs/CLI/projects.md +107 -0
  44. package/dist-skill/docs/CLI/studio_publishing.md +52 -0
  45. package/dist-skill/docs/CLI/validation.md +66 -0
  46. package/dist-skill/docs/generated/assembly.md +691 -112
  47. package/dist-skill/docs/generated/core.md +464 -1412
  48. package/dist-skill/docs/generated/curves.md +593 -117
  49. package/dist-skill/docs/generated/lib.md +38 -748
  50. package/dist-skill/docs/generated/output.md +139 -245
  51. package/dist-skill/docs/generated/sheet-metal.md +473 -21
  52. package/dist-skill/docs/generated/sketch.md +553 -349
  53. package/dist-skill/docs/generated/viewport.md +345 -303
  54. package/dist-skill/docs/generated/wood.md +104 -0
  55. package/dist-skill/docs/guides/coordinate-system.md +11 -17
  56. package/dist-skill/docs/guides/geometry-conventions.md +13 -70
  57. package/dist-skill/docs/guides/modeling-recipes.md +22 -195
  58. package/dist-skill/docs/guides/positioning.md +88 -147
  59. package/dist-skill/docs-dev/API/core/concepts.md +51 -0
  60. package/dist-skill/docs-dev/API/core/sdf-advanced.md +92 -0
  61. package/dist-skill/docs-dev/API/core/sdf-primitives.md +58 -0
  62. package/dist-skill/docs-dev/API/core/sdf-workflow.md +42 -0
  63. package/dist-skill/docs-dev/CLI/export.md +91 -0
  64. package/dist-skill/docs-dev/CLI/projects.md +107 -0
  65. package/dist-skill/docs-dev/CLI/studio_publishing.md +52 -0
  66. package/dist-skill/docs-dev/CLI/validation.md +66 -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 +1 -3
  70. package/dist-skill/docs-dev/generated/assembly.md +771 -0
  71. package/dist-skill/docs-dev/generated/core.md +775 -0
  72. package/dist-skill/docs-dev/generated/curves.md +688 -0
  73. package/dist-skill/docs-dev/generated/lib.md +50 -0
  74. package/dist-skill/docs-dev/generated/output.md +234 -0
  75. package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
  76. package/dist-skill/docs-dev/generated/sketch.md +801 -0
  77. package/dist-skill/docs-dev/generated/viewport.md +486 -0
  78. package/dist-skill/docs-dev/generated/wood.md +104 -0
  79. package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
  80. package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
  81. package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
  82. package/dist-skill/docs-dev/guides/positioning.md +151 -0
  83. package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
  84. package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
  85. package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
  86. package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
  87. package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
  88. package/examples/api/attachTo-basics.forge.js +5 -5
  89. package/examples/api/boolean-operations.forge.js +3 -3
  90. package/examples/api/bounding-box-visualizer.forge.js +2 -2
  91. package/examples/api/clone-duplicate.forge.js +1 -1
  92. package/examples/api/colors-union-vs-array.forge.js +6 -6
  93. package/examples/api/connector-assembly.forge.js +4 -4
  94. package/examples/api/connector-basics.forge.js +2 -2
  95. package/examples/api/extrude-options.forge.js +4 -10
  96. package/examples/api/feature-created-faces.forge.js +6 -10
  97. package/examples/api/fillet-showcase.forge.js +1 -1
  98. package/examples/api/folded-service-panel-cover.forge.js +2 -2
  99. package/examples/api/group-test.forge.js +1 -1
  100. package/examples/api/group-vs-union.forge.js +1 -1
  101. package/examples/api/highlight-debug.forge.js +4 -0
  102. package/examples/api/js-module-pillars.js +1 -1
  103. package/examples/api/js-module-scene.js +2 -2
  104. package/examples/api/mesh-import-slats.forge.js +1 -1
  105. package/examples/api/pointAlong-orientation.forge.js +1 -1
  106. package/examples/api/profile-2020-b-slot6.forge.js +0 -1
  107. package/examples/api/route-perimeter-flange.forge.js +1 -1
  108. package/examples/api/sdf-rover-demo.forge.js +10 -10
  109. package/examples/api/sketch-on-face-demo.forge.js +2 -2
  110. package/examples/api/sketch-regions.forge.js +4 -4
  111. package/examples/api/transition-curves.forge.js +1 -1
  112. package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
  113. package/examples/api/variable-sweep-test.forge.js +2 -2
  114. package/examples/api/wood-joinery.forge.js +60 -0
  115. package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
  116. package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
  117. package/examples/experiments/drone-arm.forge.js +53 -0
  118. package/examples/furniture/adjustable-table.forge.js +2 -2
  119. package/examples/furniture/bathroom.forge.js +11 -11
  120. package/examples/furniture/chair.forge.js +1 -1
  121. package/examples/generative/crystal-growth.forge.js +2 -2
  122. package/examples/generative/frost-spires.forge.js +3 -3
  123. package/examples/generative/golden-spiral-tower.forge.js +3 -3
  124. package/examples/mechanical/3d-printer.forge.js +28 -28
  125. package/examples/mechanical/5-finger-robot-hand.forge.js +15 -15
  126. package/examples/mechanical/airplane-propeller.forge.js +2 -2
  127. package/examples/mechanical/fillet-enclosure.forge.js +1 -1
  128. package/examples/mechanical/headphone-hanger-v2.forge.js +2 -2
  129. package/examples/mechanical/robot_hand.forge.js +15 -15
  130. package/examples/mechanical/robot_hand_2.forge.js +9 -9
  131. package/examples/products/bottle.forge.js +1 -1
  132. package/examples/products/chess-set.forge.js +19 -19
  133. package/examples/products/classical-piano.forge.js +11 -11
  134. package/examples/products/clock.forge.js +12 -12
  135. package/examples/products/iphone.forge.js +8 -8
  136. package/examples/products/laptop.forge.js +15 -15
  137. package/examples/products/liquid-soap-dispenser.forge.js +18 -18
  138. package/examples/products/origami-fish.forge.js +8 -6
  139. package/examples/products/spiderman-cake.forge.js +4 -4
  140. package/examples/toolbox/bolted-joint.forge.js +2 -2
  141. package/package.json +7 -4
  142. package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
  143. package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
  144. package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
  145. package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
  146. package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
  147. package/dist/assets/index-1CYp3zUp.js +0 -1455
  148. package/dist/docs-raw/CLI.md +0 -865
  149. package/dist-skill/docs/API/API.md +0 -1666
  150. package/dist-skill/docs/API/README.md +0 -37
  151. package/dist-skill/docs/API/assembly/assembly.md +0 -617
  152. package/dist-skill/docs/API/core/edge-queries.md +0 -130
  153. package/dist-skill/docs/API/core/parameters.md +0 -122
  154. package/dist-skill/docs/API/core/reserved-terms.md +0 -137
  155. package/dist-skill/docs/API/core/sdf.md +0 -326
  156. package/dist-skill/docs/API/core/skill-cli.md +0 -194
  157. package/dist-skill/docs/API/core/skill-guide.md +0 -205
  158. package/dist-skill/docs/API/core/specs.md +0 -186
  159. package/dist-skill/docs/API/core/topology.md +0 -372
  160. package/dist-skill/docs/API/entities.md +0 -268
  161. package/dist-skill/docs/API/output/bom.md +0 -58
  162. package/dist-skill/docs/API/output/brep-export.md +0 -87
  163. package/dist-skill/docs/API/output/dimensions.md +0 -67
  164. package/dist-skill/docs/API/output/export.md +0 -110
  165. package/dist-skill/docs/API/output/gcode.md +0 -195
  166. package/dist-skill/docs/API/runtime/viewport.md +0 -420
  167. package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
  168. package/dist-skill/docs/API/sketch/anchor.md +0 -37
  169. package/dist-skill/docs/API/sketch/booleans.md +0 -91
  170. package/dist-skill/docs/API/sketch/core.md +0 -73
  171. package/dist-skill/docs/API/sketch/extrude.md +0 -62
  172. package/dist-skill/docs/API/sketch/on-face.md +0 -104
  173. package/dist-skill/docs/API/sketch/operations.md +0 -78
  174. package/dist-skill/docs/API/sketch/path.md +0 -75
  175. package/dist-skill/docs/API/sketch/primitives.md +0 -146
  176. package/dist-skill/docs/API/sketch/regions.md +0 -80
  177. package/dist-skill/docs/API/sketch/text.md +0 -108
  178. package/dist-skill/docs/API/sketch/transforms.md +0 -65
  179. package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
  180. package/dist-skill/docs/CLI.md +0 -865
  181. package/dist-skill/docs/INDEX.md +0 -94
  182. package/dist-skill/docs/RELEASING.md +0 -55
  183. package/dist-skill/docs/cli-monetization.md +0 -111
  184. package/dist-skill/docs/deployment.md +0 -281
  185. package/dist-skill/docs/generated/concepts.md +0 -2112
  186. package/dist-skill/docs/internals/shape-from-slices.md +0 -152
  187. package/dist-skill/docs/platform/admin.md +0 -45
  188. package/dist-skill/docs/platform/architecture.md +0 -79
  189. package/dist-skill/docs/platform/auth.md +0 -110
  190. package/dist-skill/docs/platform/email.md +0 -67
  191. package/dist-skill/docs/platform/projects.md +0 -111
  192. package/dist-skill/docs/platform/sharing.md +0 -90
  193. package/dist-skill/docs/runbook.md +0 -345
@@ -2,8 +2,8 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  var _a;
5
- import { u as useParams, e as useNavigate, r as reactExports, j as jsxRuntimeExports, L as Link } from "./vendor-react-Dt7-aaJH.js";
6
- import { H as HighlightJS, j as javascript$1 } from "./javascript-DCxGoE5Y.js";
5
+ import { u as useParams, h as useNavigate, r as reactExports, j as jsxRuntimeExports, L as Link } from "./vendor-react-CG3i_wp0.js";
6
+ import { H as HighlightJS, j as javascript$1 } from "./javascript-DAl8Gmyo.js";
7
7
  function M() {
8
8
  return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
9
9
  }
@@ -3721,7 +3721,7 @@ function slugify(text) {
3721
3721
  return text.toLowerCase().replace(/`/g, "").replace(/<[^>]*>/g, "").replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
3722
3722
  }
3723
3723
  const renderer = new g.Renderer();
3724
- renderer.code = function({ text, lang }) {
3724
+ renderer.code = ({ text, lang }) => {
3725
3725
  let highlighted;
3726
3726
  if (lang && HighlightJS.getLanguage(lang)) {
3727
3727
  highlighted = HighlightJS.highlight(text, { language: lang }).value;
@@ -3730,38 +3730,42 @@ renderer.code = function({ text, lang }) {
3730
3730
  }
3731
3731
  return `<pre class="fc-docs-code"><code class="hljs language-${lang || ""}">${highlighted}</code></pre>`;
3732
3732
  };
3733
- renderer.heading = function({ text, depth }) {
3733
+ renderer.heading = ({ text, depth }) => {
3734
3734
  const id = slugify(text);
3735
- return `<h${depth} id="${id}">${text}<a class="fc-docs-anchor" href="#${id}" aria-label="Link to this section">#</a></h${depth}>
3735
+ const html = g.parseInline(text, { async: false });
3736
+ return `<h${depth} id="${id}">${html}<a class="fc-docs-anchor" href="#${id}" aria-label="Link to this section">#</a></h${depth}>
3736
3737
  `;
3737
3738
  };
3738
- renderer.table = function({ header, rows }) {
3739
+ renderer.table = ({
3740
+ header,
3741
+ rows
3742
+ }) => {
3743
+ const inline = (t) => g.parseInline(t, { async: false });
3739
3744
  let html = '<table class="fc-docs-table"><thead><tr>';
3740
3745
  for (const cell of header) {
3741
3746
  const align = cell.align ? ` style="text-align:${cell.align}"` : "";
3742
- html += `<th${align}>${cell.text}</th>`;
3747
+ html += `<th${align}>${inline(cell.text)}</th>`;
3743
3748
  }
3744
3749
  html += "</tr></thead><tbody>";
3745
3750
  for (const row of rows) {
3746
3751
  html += "<tr>";
3747
3752
  for (const cell of row) {
3748
3753
  const align = cell.align ? ` style="text-align:${cell.align}"` : "";
3749
- html += `<td${align}>${cell.text}</td>`;
3754
+ html += `<td${align}>${inline(cell.text)}</td>`;
3750
3755
  }
3751
3756
  html += "</tr>";
3752
3757
  }
3753
3758
  html += "</tbody></table>";
3754
3759
  return html;
3755
3760
  };
3756
- renderer.codespan = function({ text }) {
3757
- return `<code class="fc-docs-inline-code">${text}</code>`;
3758
- };
3759
- renderer.blockquote = function({ text }) {
3760
- return `<blockquote class="fc-docs-blockquote">${text}</blockquote>`;
3761
- };
3761
+ renderer.codespan = ({ text }) => `<code class="fc-docs-inline-code">${text}</code>`;
3762
+ renderer.blockquote = ({ text }) => `<blockquote class="fc-docs-blockquote">${text}</blockquote>`;
3762
3763
  g.use({ renderer, gfm: true, breaks: false });
3764
+ function stripFrontmatter(md) {
3765
+ return md.replace(/^---\n[\s\S]*?\n---\n/, "");
3766
+ }
3763
3767
  function renderToHtml(md) {
3764
- return g.parse(md, { async: false });
3768
+ return g.parse(stripFrontmatter(md), { async: false });
3765
3769
  }
3766
3770
  const DOC_SECTIONS = [
3767
3771
  { slug: "core", title: "Core", description: "Primitives, booleans, transforms, patterns" },
@@ -3774,9 +3778,7 @@ const DOC_SECTIONS = [
3774
3778
  { slug: "viewport", title: "Viewport", description: "Camera, animation, scenes" },
3775
3779
  { slug: "concepts", title: "Concepts", description: "Semantic data structures" }
3776
3780
  ];
3777
- const CLI_SECTIONS = [
3778
- { slug: "cli", title: "CLI Reference", description: "Command-line tools and options" }
3779
- ];
3781
+ const CLI_SECTIONS = [{ slug: "cli", title: "CLI Reference", description: "Command-line tools and options" }];
3780
3782
  const ALL_SECTIONS = [...DOC_SECTIONS, ...CLI_SECTIONS];
3781
3783
  function buildSearchEntries(slug, sectionTitle, md) {
3782
3784
  const entries = [];
@@ -3810,17 +3812,45 @@ function buildSearchEntries(slug, sectionTitle, md) {
3810
3812
  const sigMatch = line.match(/^(\w+)\(.*\):/);
3811
3813
  if (sigMatch && !sig) sig = line.trim();
3812
3814
  if (!line.startsWith("```") && line.trim()) {
3813
- buffer.push(line.replace(/[#*`\[\]]/g, "").trim());
3815
+ buffer.push(line.replace(/[#*`[\]]/g, "").trim());
3814
3816
  }
3815
3817
  }
3816
3818
  flush();
3817
3819
  return entries;
3818
3820
  }
3819
- function SiteNav({ onSearchOpen }) {
3821
+ function SidebarToggle({ side, open, onClick }) {
3822
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3823
+ "button",
3824
+ {
3825
+ className: `fc-docs-sidebar-toggle ${side}`,
3826
+ onClick,
3827
+ type: "button",
3828
+ title: `${open ? "Hide" : "Show"} ${side === "left" ? "navigation" : "page outline"}`,
3829
+ children: side === "left" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3830
+ /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
3831
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 3v18" })
3832
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3833
+ /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
3834
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M15 3v18" })
3835
+ ] })
3836
+ }
3837
+ );
3838
+ }
3839
+ function SiteNav({
3840
+ onSearchOpen,
3841
+ showSidebar,
3842
+ showToc,
3843
+ onToggleSidebar,
3844
+ onToggleToc,
3845
+ hasToc
3846
+ }) {
3820
3847
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("nav", { className: "fc-docs-nav", children: [
3821
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Link, { to: "/", className: "fc-docs-nav-logo", children: [
3822
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 20 }, children: "⚒" }),
3823
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "ForgeCAD" })
3848
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-nav-left", children: [
3849
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarToggle, { side: "left", open: showSidebar, onClick: onToggleSidebar }),
3850
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Link, { to: "/", className: "fc-docs-nav-logo", children: [
3851
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 20 }, children: "⚒" }),
3852
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "ForgeCAD" })
3853
+ ] })
3824
3854
  ] }),
3825
3855
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-nav-links", children: [
3826
3856
  /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: onSearchOpen, className: "fc-docs-search-trigger", type: "button", children: [
@@ -3833,7 +3863,8 @@ function SiteNav({ onSearchOpen }) {
3833
3863
  ] }),
3834
3864
  /* @__PURE__ */ jsxRuntimeExports.jsx(Link, { to: "/docs", className: "fc-docs-nav-active", children: "Docs" }),
3835
3865
  false,
3836
- /* @__PURE__ */ jsxRuntimeExports.jsx(Link, { to: "/", className: "fc-docs-nav-cta", children: "Back to Editor" })
3866
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Link, { to: "/", className: "fc-docs-nav-cta", children: "Back to Editor" }),
3867
+ hasToc && /* @__PURE__ */ jsxRuntimeExports.jsx(SidebarToggle, { side: "right", open: showToc, onClick: onToggleToc })
3837
3868
  ] })
3838
3869
  ] });
3839
3870
  }
@@ -3868,11 +3899,7 @@ function Sidebar({ activeSlug }) {
3868
3899
  ))
3869
3900
  ] });
3870
3901
  }
3871
- function SearchOverlay({
3872
- open,
3873
- onClose,
3874
- searchIndex
3875
- }) {
3902
+ function SearchOverlay({ open, onClose, searchIndex }) {
3876
3903
  const inputRef = reactExports.useRef(null);
3877
3904
  const [query, setQuery] = reactExports.useState("");
3878
3905
  const [selected, setSelected] = reactExports.useState(0);
@@ -3894,101 +3921,197 @@ function SearchOverlay({
3894
3921
  reactExports.useEffect(() => {
3895
3922
  setSelected(0);
3896
3923
  }, [query]);
3897
- const selectResult = reactExports.useCallback((idx) => {
3898
- const hit = results[idx];
3899
- if (!hit) return;
3900
- onClose();
3901
- const anchor = hit.item.anchor ? `#${hit.item.anchor}` : "";
3902
- navigate(`/docs/${hit.item.slug}${anchor}`);
3903
- }, [results, onClose, navigate]);
3904
- const onKeyDown = reactExports.useCallback((e) => {
3905
- if (e.key === "ArrowDown") {
3906
- e.preventDefault();
3907
- setSelected((s) => Math.min(s + 1, results.length - 1));
3908
- } else if (e.key === "ArrowUp") {
3909
- e.preventDefault();
3910
- setSelected((s) => Math.max(s - 1, 0));
3911
- } else if (e.key === "Enter") {
3912
- e.preventDefault();
3913
- selectResult(selected);
3914
- } else if (e.key === "Escape") {
3915
- e.preventDefault();
3924
+ const selectResult = reactExports.useCallback(
3925
+ (idx) => {
3926
+ const hit = results[idx];
3927
+ if (!hit) return;
3916
3928
  onClose();
3917
- }
3918
- }, [results.length, selected, selectResult, onClose]);
3929
+ const anchor = hit.item.anchor ? `#${hit.item.anchor}` : "";
3930
+ navigate(`/docs/${hit.item.slug}${anchor}`);
3931
+ },
3932
+ [results, onClose, navigate]
3933
+ );
3934
+ const onKeyDown = reactExports.useCallback(
3935
+ (e) => {
3936
+ if (e.key === "ArrowDown") {
3937
+ e.preventDefault();
3938
+ setSelected((s) => Math.min(s + 1, results.length - 1));
3939
+ } else if (e.key === "ArrowUp") {
3940
+ e.preventDefault();
3941
+ setSelected((s) => Math.max(s - 1, 0));
3942
+ } else if (e.key === "Enter") {
3943
+ e.preventDefault();
3944
+ selectResult(selected);
3945
+ } else if (e.key === "Escape") {
3946
+ e.preventDefault();
3947
+ onClose();
3948
+ }
3949
+ },
3950
+ [results.length, selected, selectResult, onClose]
3951
+ );
3919
3952
  if (!open) return null;
3920
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-overlay", onClick: (e) => {
3921
- if (e.target === e.currentTarget) onClose();
3922
- }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-modal", children: [
3923
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-input-wrap", children: [
3924
- /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { color: "var(--fc-textDim)", flexShrink: 0 }, children: [
3925
- /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "11", cy: "11", r: "8" }),
3926
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "m21 21-4.35-4.35" })
3927
- ] }),
3928
- /* @__PURE__ */ jsxRuntimeExports.jsx(
3929
- "input",
3930
- {
3931
- ref: inputRef,
3932
- type: "text",
3933
- placeholder: "Search docs...",
3934
- value: query,
3935
- onChange: (e) => setQuery(e.target.value),
3936
- onKeyDown,
3937
- autoComplete: "off",
3938
- spellCheck: false
3939
- }
3940
- ),
3941
- /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "esc" })
3942
- ] }),
3943
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-results", children: [
3944
- query.trim() && results.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-empty", children: [
3945
- "No results for “",
3946
- query,
3947
- "”"
3948
- ] }),
3949
- results.map((hit, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
3950
- "div",
3951
- {
3952
- className: `fc-docs-search-result${i === selected ? " selected" : ""}`,
3953
- onClick: () => selectResult(i),
3954
- onMouseEnter: () => setSelected(i),
3955
- children: [
3956
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-title", children: hit.item.title }),
3957
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-category", children: hit.item.category }),
3958
- hit.item.content && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-snippet", children: hit.item.content.slice(0, 120) })
3959
- ]
3960
- },
3961
- `${hit.item.slug}-${hit.item.anchor}-${i}`
3962
- ))
3963
- ] }),
3964
- query.trim() && results.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-footer", children: [
3965
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
3966
- /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "↑↓" }),
3967
- " navigate"
3968
- ] }),
3969
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
3970
- /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "↵" }),
3971
- " open"
3972
- ] }),
3973
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
3974
- /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "esc" }),
3975
- " close"
3953
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
3954
+ "div",
3955
+ {
3956
+ className: "fc-docs-search-overlay",
3957
+ onClick: (e) => {
3958
+ if (e.target === e.currentTarget) onClose();
3959
+ },
3960
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-modal", children: [
3961
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-input-wrap", children: [
3962
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
3963
+ "svg",
3964
+ {
3965
+ width: "18",
3966
+ height: "18",
3967
+ viewBox: "0 0 24 24",
3968
+ fill: "none",
3969
+ stroke: "currentColor",
3970
+ strokeWidth: "2",
3971
+ style: { color: "var(--fc-textDim)", flexShrink: 0 },
3972
+ children: [
3973
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "11", cy: "11", r: "8" }),
3974
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "m21 21-4.35-4.35" })
3975
+ ]
3976
+ }
3977
+ ),
3978
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
3979
+ "input",
3980
+ {
3981
+ ref: inputRef,
3982
+ type: "text",
3983
+ placeholder: "Search docs...",
3984
+ value: query,
3985
+ onChange: (e) => setQuery(e.target.value),
3986
+ onKeyDown,
3987
+ autoComplete: "off",
3988
+ spellCheck: false
3989
+ }
3990
+ ),
3991
+ /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "esc" })
3992
+ ] }),
3993
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-results", children: [
3994
+ query.trim() && results.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-empty", children: [
3995
+ "No results for “",
3996
+ query,
3997
+ ""
3998
+ ] }),
3999
+ results.map((hit, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
4000
+ "div",
4001
+ {
4002
+ className: `fc-docs-search-result${i === selected ? " selected" : ""}`,
4003
+ onClick: () => selectResult(i),
4004
+ onMouseEnter: () => setSelected(i),
4005
+ children: [
4006
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-title", children: hit.item.title }),
4007
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-category", children: hit.item.category }),
4008
+ hit.item.content && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-search-result-snippet", children: hit.item.content.slice(0, 120) })
4009
+ ]
4010
+ },
4011
+ `${hit.item.slug}-${hit.item.anchor}-${i}`
4012
+ ))
4013
+ ] }),
4014
+ query.trim() && results.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-search-footer", children: [
4015
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
4016
+ /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "↑↓" }),
4017
+ " navigate"
4018
+ ] }),
4019
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
4020
+ /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "↵" }),
4021
+ " open"
4022
+ ] }),
4023
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
4024
+ /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "esc" }),
4025
+ " close"
4026
+ ] })
4027
+ ] })
3976
4028
  ] })
3977
- ] })
3978
- ] }) });
4029
+ }
4030
+ );
4031
+ }
4032
+ function extractTocEntries(container) {
4033
+ var _a2;
4034
+ const headings = Array.from(container.querySelectorAll("h2, h3"));
4035
+ const entries = [];
4036
+ for (const h of headings) {
4037
+ const id = h.id;
4038
+ if (!id) continue;
4039
+ const text = ((_a2 = h.textContent) == null ? void 0 : _a2.replace(/#$/, "").trim()) || "";
4040
+ if (!text) continue;
4041
+ entries.push({ id, text, depth: parseInt(h.tagName[1]) });
4042
+ }
4043
+ return entries;
4044
+ }
4045
+ function OnThisPage({ contentRef, html }) {
4046
+ const [entries, setEntries] = reactExports.useState([]);
4047
+ const [activeId, setActiveId] = reactExports.useState("");
4048
+ reactExports.useEffect(() => {
4049
+ if (!html || !contentRef.current) {
4050
+ setEntries([]);
4051
+ return;
4052
+ }
4053
+ const raf = requestAnimationFrame(() => {
4054
+ if (contentRef.current) setEntries(extractTocEntries(contentRef.current));
4055
+ });
4056
+ return () => cancelAnimationFrame(raf);
4057
+ }, [html]);
4058
+ reactExports.useEffect(() => {
4059
+ if (entries.length === 0 || !contentRef.current) return;
4060
+ const scrollContainer = contentRef.current.closest(".fc-docs-main");
4061
+ if (!scrollContainer) return;
4062
+ const handleScroll = () => {
4063
+ var _a2;
4064
+ const headings = Array.from(((_a2 = contentRef.current) == null ? void 0 : _a2.querySelectorAll("h2, h3")) ?? []);
4065
+ let current = "";
4066
+ for (const h of headings) {
4067
+ if (h.getBoundingClientRect().top <= 100) current = h.id;
4068
+ else break;
4069
+ }
4070
+ setActiveId(current);
4071
+ };
4072
+ scrollContainer.addEventListener("scroll", handleScroll, { passive: true });
4073
+ handleScroll();
4074
+ return () => scrollContainer.removeEventListener("scroll", handleScroll);
4075
+ }, [entries, contentRef]);
4076
+ if (entries.length === 0) return null;
4077
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { className: "fc-docs-toc", children: [
4078
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fc-docs-toc-title", children: "On this page" }),
4079
+ entries.map((e) => /* @__PURE__ */ jsxRuntimeExports.jsx(
4080
+ "a",
4081
+ {
4082
+ href: `#${e.id}`,
4083
+ className: `fc-docs-toc-link${e.depth === 3 ? " indent" : ""}${activeId === e.id ? " active" : ""}`,
4084
+ onClick: (ev) => {
4085
+ var _a2;
4086
+ ev.preventDefault();
4087
+ const target = (_a2 = contentRef.current) == null ? void 0 : _a2.querySelector(`#${CSS.escape(e.id)}`);
4088
+ if (target) {
4089
+ target.scrollIntoView({ behavior: "smooth", block: "start" });
4090
+ history.replaceState(null, "", `#${e.id}`);
4091
+ }
4092
+ },
4093
+ children: e.text
4094
+ },
4095
+ e.id
4096
+ ))
4097
+ ] });
3979
4098
  }
3980
- function DocContent({ slug }) {
4099
+ function DocContent({ slug, contentRef, onHtml }) {
3981
4100
  const [html, setHtml] = reactExports.useState(null);
3982
4101
  const [error, setError] = reactExports.useState(null);
3983
- const contentRef = reactExports.useRef(null);
3984
4102
  reactExports.useEffect(() => {
3985
4103
  setHtml(null);
3986
4104
  setError(null);
4105
+ onHtml(null);
3987
4106
  const filename = slug === "cli" ? "CLI.md" : `generated/${slug}.md`;
3988
4107
  fetch(`/docs-raw/${filename}`).then((r) => {
3989
4108
  if (!r.ok) throw new Error(`Not found: ${filename}`);
3990
4109
  return r.text();
3991
- }).then((md) => setHtml(renderToHtml(md))).catch((e) => setError(e.message));
4110
+ }).then((md) => {
4111
+ const h = renderToHtml(md);
4112
+ setHtml(h);
4113
+ onHtml(h);
4114
+ }).catch((e) => setError(e.message));
3992
4115
  }, [slug]);
3993
4116
  reactExports.useEffect(() => {
3994
4117
  if (!html || !contentRef.current) return;
@@ -4031,14 +4154,7 @@ function DocContent({ slug }) {
4031
4154
  if (html === null) {
4032
4155
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { padding: 40, color: "var(--fc-textDim)" }, children: "Loading..." });
4033
4156
  }
4034
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
4035
- "div",
4036
- {
4037
- ref: contentRef,
4038
- className: "fc-docs-content",
4039
- dangerouslySetInnerHTML: { __html: html }
4040
- }
4041
- );
4157
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: contentRef, className: "fc-docs-content", dangerouslySetInnerHTML: { __html: html } });
4042
4158
  }
4043
4159
  function DocsIndex() {
4044
4160
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-index", children: [
@@ -4068,6 +4184,10 @@ function DocsPage() {
4068
4184
  const navigate = useNavigate();
4069
4185
  const [searchOpen, setSearchOpen] = reactExports.useState(false);
4070
4186
  const [searchIndex, setSearchIndex] = reactExports.useState(null);
4187
+ const contentRef = reactExports.useRef(null);
4188
+ const [docHtml, setDocHtml] = reactExports.useState(null);
4189
+ const [showSidebar, setShowSidebar] = reactExports.useState(() => window.innerWidth > 900);
4190
+ const [showToc, setShowToc] = reactExports.useState(() => window.innerWidth > 1200);
4071
4191
  const buildSearchIndex = reactExports.useCallback(async () => {
4072
4192
  if (searchIndex) return;
4073
4193
  const entries = [];
@@ -4076,25 +4196,27 @@ function DocsPage() {
4076
4196
  try {
4077
4197
  const r = await fetch(`/docs-raw/${filename}`);
4078
4198
  if (!r.ok) return;
4079
- const md = await r.text();
4199
+ const md = stripFrontmatter(await r.text());
4080
4200
  entries.push(...buildSearchEntries(section.slug, section.title, md));
4081
4201
  } catch {
4082
4202
  }
4083
4203
  });
4084
4204
  await Promise.all(fetches);
4085
- setSearchIndex(new Fuse(entries, {
4086
- keys: [
4087
- { name: "title", weight: 0.45 },
4088
- { name: "signature", weight: 0.25 },
4089
- { name: "category", weight: 0.15 },
4090
- { name: "content", weight: 0.15 }
4091
- ],
4092
- threshold: 0.35,
4093
- distance: 100,
4094
- includeMatches: true,
4095
- minMatchCharLength: 1,
4096
- ignoreLocation: true
4097
- }));
4205
+ setSearchIndex(
4206
+ new Fuse(entries, {
4207
+ keys: [
4208
+ { name: "title", weight: 0.45 },
4209
+ { name: "signature", weight: 0.25 },
4210
+ { name: "category", weight: 0.15 },
4211
+ { name: "content", weight: 0.15 }
4212
+ ],
4213
+ threshold: 0.35,
4214
+ distance: 100,
4215
+ includeMatches: true,
4216
+ minMatchCharLength: 1,
4217
+ ignoreLocation: true
4218
+ })
4219
+ );
4098
4220
  }, [searchIndex]);
4099
4221
  const openSearch = reactExports.useCallback(() => {
4100
4222
  setSearchOpen(true);
@@ -4122,19 +4244,23 @@ function DocsPage() {
4122
4244
  return () => document.removeEventListener("keydown", handler);
4123
4245
  }, [slug, openSearch, navigate]);
4124
4246
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-layout", children: [
4125
- /* @__PURE__ */ jsxRuntimeExports.jsx(SiteNav, { onSearchOpen: openSearch }),
4126
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-body", children: [
4127
- /* @__PURE__ */ jsxRuntimeExports.jsx(Sidebar, { activeSlug: slug }),
4128
- /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "fc-docs-main", children: slug ? /* @__PURE__ */ jsxRuntimeExports.jsx(DocContent, { slug }) : /* @__PURE__ */ jsxRuntimeExports.jsx(DocsIndex, {}) })
4129
- ] }),
4130
4247
  /* @__PURE__ */ jsxRuntimeExports.jsx(
4131
- SearchOverlay,
4248
+ SiteNav,
4132
4249
  {
4133
- open: searchOpen,
4134
- onClose: () => setSearchOpen(false),
4135
- searchIndex
4250
+ onSearchOpen: openSearch,
4251
+ showSidebar,
4252
+ showToc,
4253
+ onToggleSidebar: () => setShowSidebar((s) => !s),
4254
+ onToggleToc: () => setShowToc((s) => !s),
4255
+ hasToc: !!slug
4136
4256
  }
4137
- )
4257
+ ),
4258
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fc-docs-body", children: [
4259
+ showSidebar && /* @__PURE__ */ jsxRuntimeExports.jsx(Sidebar, { activeSlug: slug }),
4260
+ /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "fc-docs-main", children: slug ? /* @__PURE__ */ jsxRuntimeExports.jsx(DocContent, { slug, contentRef, onHtml: setDocHtml }) : /* @__PURE__ */ jsxRuntimeExports.jsx(DocsIndex, {}) }),
4261
+ slug && showToc && /* @__PURE__ */ jsxRuntimeExports.jsx(OnThisPage, { contentRef, html: docHtml })
4262
+ ] }),
4263
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SearchOverlay, { open: searchOpen, onClose: () => setSearchOpen(false), searchIndex })
4138
4264
  ] });
4139
4265
  }
4140
4266
  export {