@classytic/labs 0.1.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 (547) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/dist/biology/enzyme-rate/index.d.mts +1 -0
  4. package/dist/biology/enzyme-rate/preset.d.mts +25 -0
  5. package/dist/biology/enzyme-rate/preset.mjs +256 -0
  6. package/dist/biology/genetic-cross/core.d.mts +64 -0
  7. package/dist/biology/genetic-cross/core.mjs +147 -0
  8. package/dist/biology/genetic-cross/grid.mjs +239 -0
  9. package/dist/biology/genetic-cross/index.d.mts +3 -0
  10. package/dist/biology/genetic-cross/preset.d.mts +26 -0
  11. package/dist/biology/genetic-cross/preset.mjs +184 -0
  12. package/dist/biology/genetic-cross/sex-linked.d.mts +27 -0
  13. package/dist/biology/genetic-cross/sex-linked.mjs +226 -0
  14. package/dist/biology/index.d.mts +11 -0
  15. package/dist/biology/index.mjs +12 -0
  16. package/dist/biology/photosynthesis-factors/index.d.mts +1 -0
  17. package/dist/biology/photosynthesis-factors/preset.d.mts +25 -0
  18. package/dist/biology/photosynthesis-factors/preset.mjs +270 -0
  19. package/dist/biology/punnett-cross/index.d.mts +1 -0
  20. package/dist/biology/punnett-cross/preset.d.mts +27 -0
  21. package/dist/biology/punnett-cross/preset.mjs +21 -0
  22. package/dist/biology/respiration/index.d.mts +1 -0
  23. package/dist/biology/respiration/preset.d.mts +17 -0
  24. package/dist/biology/respiration/preset.mjs +179 -0
  25. package/dist/biology/sequence/central-dogma.d.mts +17 -0
  26. package/dist/biology/sequence/central-dogma.mjs +339 -0
  27. package/dist/biology/sequence/core.d.mts +38 -0
  28. package/dist/biology/sequence/core.mjs +178 -0
  29. package/dist/biology/sequence/index.d.mts +3 -0
  30. package/dist/biology/sequence/preset.d.mts +20 -0
  31. package/dist/biology/sequence/preset.mjs +235 -0
  32. package/dist/blocks/accounting.d.mts +142 -0
  33. package/dist/blocks/accounting.mjs +446 -0
  34. package/dist/blocks/authoring.d.mts +12 -0
  35. package/dist/blocks/authoring.mjs +705 -0
  36. package/dist/blocks/biology.d.mts +197 -0
  37. package/dist/blocks/biology.mjs +513 -0
  38. package/dist/blocks/chem.d.mts +128 -0
  39. package/dist/blocks/chem.mjs +486 -0
  40. package/dist/blocks/circuits.d.mts +86 -0
  41. package/dist/blocks/circuits.mjs +348 -0
  42. package/dist/blocks/discrete.d.mts +62 -0
  43. package/dist/blocks/discrete.mjs +314 -0
  44. package/dist/blocks/economics.d.mts +56 -0
  45. package/dist/blocks/economics.mjs +203 -0
  46. package/dist/blocks/geography.d.mts +58 -0
  47. package/dist/blocks/geography.mjs +115 -0
  48. package/dist/blocks/geometry.d.mts +28 -0
  49. package/dist/blocks/geometry.mjs +160 -0
  50. package/dist/blocks/ict.d.mts +65 -0
  51. package/dist/blocks/ict.mjs +197 -0
  52. package/dist/blocks/index.d.mts +4555 -0
  53. package/dist/blocks/index.mjs +120 -0
  54. package/dist/blocks/lab-block.d.mts +16 -0
  55. package/dist/blocks/lab-block.mjs +74 -0
  56. package/dist/blocks/lab-config.d.mts +23 -0
  57. package/dist/blocks/lab-config.mjs +200 -0
  58. package/dist/blocks/lab-gallery.d.mts +30 -0
  59. package/dist/blocks/lab-gallery.mjs +208 -0
  60. package/dist/blocks/language.d.mts +349 -0
  61. package/dist/blocks/language.mjs +750 -0
  62. package/dist/blocks/lesson.d.mts +43 -0
  63. package/dist/blocks/lesson.mjs +140 -0
  64. package/dist/blocks/math.d.mts +411 -0
  65. package/dist/blocks/math.mjs +1536 -0
  66. package/dist/blocks/ml.d.mts +84 -0
  67. package/dist/blocks/ml.mjs +146 -0
  68. package/dist/blocks/physics.d.mts +259 -0
  69. package/dist/blocks/physics.mjs +868 -0
  70. package/dist/blocks/statistics.d.mts +29 -0
  71. package/dist/blocks/statistics.mjs +123 -0
  72. package/dist/catalog/index.d.mts +3 -0
  73. package/dist/catalog/index.mjs +8 -0
  74. package/dist/catalog/registry.d.mts +46 -0
  75. package/dist/catalog/registry.mjs +56 -0
  76. package/dist/catalog/templates.d.mts +11 -0
  77. package/dist/catalog/templates.mjs +141 -0
  78. package/dist/chem/battery.d.mts +16 -0
  79. package/dist/chem/battery.mjs +311 -0
  80. package/dist/chem/bohr-atom.d.mts +16 -0
  81. package/dist/chem/bohr-atom.mjs +212 -0
  82. package/dist/chem/diffusion/asset.mjs +76 -0
  83. package/dist/chem/diffusion/index.d.mts +1 -0
  84. package/dist/chem/diffusion/preset.d.mts +15 -0
  85. package/dist/chem/diffusion/preset.mjs +188 -0
  86. package/dist/chem/electrochem/index.d.mts +1 -0
  87. package/dist/chem/electrochem/preset.d.mts +23 -0
  88. package/dist/chem/electrochem/preset.mjs +402 -0
  89. package/dist/chem/equilibrium/index.d.mts +1 -0
  90. package/dist/chem/equilibrium/preset.d.mts +36 -0
  91. package/dist/chem/equilibrium/preset.mjs +416 -0
  92. package/dist/chem/gas-box/index.d.mts +1 -0
  93. package/dist/chem/gas-box/preset.d.mts +27 -0
  94. package/dist/chem/gas-box/preset.mjs +395 -0
  95. package/dist/chem/index.d.mts +16 -0
  96. package/dist/chem/index.mjs +17 -0
  97. package/dist/chem/kinetics/index.d.mts +1 -0
  98. package/dist/chem/kinetics/preset.d.mts +31 -0
  99. package/dist/chem/kinetics/preset.mjs +478 -0
  100. package/dist/chem/periodic-trends/index.d.mts +1 -0
  101. package/dist/chem/periodic-trends/preset.d.mts +21 -0
  102. package/dist/chem/periodic-trends/preset.mjs +831 -0
  103. package/dist/chem/reaction-lab.d.mts +18 -0
  104. package/dist/chem/reaction-lab.mjs +165 -0
  105. package/dist/chem/reaction-profile.d.mts +21 -0
  106. package/dist/chem/reaction-profile.mjs +287 -0
  107. package/dist/chem/solution/dilution.d.mts +27 -0
  108. package/dist/chem/solution/dilution.mjs +199 -0
  109. package/dist/chem/solution/field.d.mts +30 -0
  110. package/dist/chem/solution/field.mjs +145 -0
  111. package/dist/chem/solution/index.d.mts +3 -0
  112. package/dist/chem/solution/solution-box.d.mts +28 -0
  113. package/dist/chem/solution/solution-box.mjs +140 -0
  114. package/dist/chem/stoichiometry/index.d.mts +1 -0
  115. package/dist/chem/stoichiometry/preset.d.mts +29 -0
  116. package/dist/chem/stoichiometry/preset.mjs +392 -0
  117. package/dist/chem/titration/index.d.mts +1 -0
  118. package/dist/chem/titration/preset.d.mts +29 -0
  119. package/dist/chem/titration/preset.mjs +436 -0
  120. package/dist/circuits/ac-dc/asset.mjs +295 -0
  121. package/dist/circuits/ac-dc/index.d.mts +1 -0
  122. package/dist/circuits/ac-dc/preset.d.mts +16 -0
  123. package/dist/circuits/ac-dc/preset.mjs +134 -0
  124. package/dist/circuits/capacitor-leak/index.d.mts +1 -0
  125. package/dist/circuits/capacitor-leak/preset.d.mts +32 -0
  126. package/dist/circuits/capacitor-leak/preset.mjs +271 -0
  127. package/dist/circuits/circuit/asset.d.mts +6 -0
  128. package/dist/circuits/circuit/asset.mjs +367 -0
  129. package/dist/circuits/circuit/index.d.mts +2 -0
  130. package/dist/circuits/circuit/preset.d.mts +46 -0
  131. package/dist/circuits/circuit/preset.mjs +235 -0
  132. package/dist/circuits/circuit-builder.d.mts +30 -0
  133. package/dist/circuits/circuit-builder.mjs +412 -0
  134. package/dist/circuits/circuit-lab.d.mts +20 -0
  135. package/dist/circuits/circuit-lab.mjs +400 -0
  136. package/dist/circuits/index.d.mts +7 -0
  137. package/dist/circuits/index.mjs +8 -0
  138. package/dist/commerce/accounting/core.d.mts +48 -0
  139. package/dist/commerce/accounting/core.mjs +57 -0
  140. package/dist/commerce/accounting/equation-balance.d.mts +35 -0
  141. package/dist/commerce/accounting/equation-balance.mjs +292 -0
  142. package/dist/commerce/accounting/index.d.mts +4 -0
  143. package/dist/commerce/accounting/journal-poster.d.mts +29 -0
  144. package/dist/commerce/accounting/journal-poster.mjs +472 -0
  145. package/dist/commerce/accounting/statement-sorter.d.mts +25 -0
  146. package/dist/commerce/accounting/statement-sorter.mjs +304 -0
  147. package/dist/commerce/economics/core.d.mts +33 -0
  148. package/dist/commerce/economics/core.mjs +26 -0
  149. package/dist/commerce/economics/demand-shift-vs-move.d.mts +35 -0
  150. package/dist/commerce/economics/demand-shift-vs-move.mjs +324 -0
  151. package/dist/commerce/economics/elasticity-revenue.d.mts +31 -0
  152. package/dist/commerce/economics/elasticity-revenue.mjs +253 -0
  153. package/dist/commerce/economics/index.d.mts +4 -0
  154. package/dist/commerce/economics/market-equilibrium.d.mts +33 -0
  155. package/dist/commerce/economics/market-equilibrium.mjs +340 -0
  156. package/dist/commerce/index.d.mts +9 -0
  157. package/dist/commerce/index.mjs +10 -0
  158. package/dist/core/easing.d.mts +28 -0
  159. package/dist/core/easing.mjs +66 -0
  160. package/dist/core/index.d.mts +10 -0
  161. package/dist/core/index.mjs +11 -0
  162. package/dist/core/numeric.d.mts +37 -0
  163. package/dist/core/numeric.mjs +75 -0
  164. package/dist/core/reactive.d.mts +24 -0
  165. package/dist/core/reactive.mjs +51 -0
  166. package/dist/core/rng.d.mts +21 -0
  167. package/dist/core/rng.mjs +39 -0
  168. package/dist/core/tex.d.mts +14 -0
  169. package/dist/core/tex.mjs +44 -0
  170. package/dist/core/timeline.d.mts +34 -0
  171. package/dist/core/timeline.mjs +77 -0
  172. package/dist/core/util.d.mts +19 -0
  173. package/dist/core/util.mjs +31 -0
  174. package/dist/discrete/arrangements/preset.d.mts +28 -0
  175. package/dist/discrete/arrangements/preset.mjs +304 -0
  176. package/dist/discrete/bayes/preset.d.mts +33 -0
  177. package/dist/discrete/bayes/preset.mjs +476 -0
  178. package/dist/discrete/binomial/preset.d.mts +25 -0
  179. package/dist/discrete/binomial/preset.mjs +333 -0
  180. package/dist/discrete/core/combinatorics.d.mts +23 -0
  181. package/dist/discrete/core/combinatorics.mjs +57 -0
  182. package/dist/discrete/core/inclusionExclusion.d.mts +19 -0
  183. package/dist/discrete/core/inclusionExclusion.mjs +30 -0
  184. package/dist/discrete/core/pigeonhole.d.mts +15 -0
  185. package/dist/discrete/core/pigeonhole.mjs +24 -0
  186. package/dist/discrete/core/probability.d.mts +29 -0
  187. package/dist/discrete/core/probability.mjs +43 -0
  188. package/dist/discrete/core/sets.d.mts +21 -0
  189. package/dist/discrete/core/sets.mjs +45 -0
  190. package/dist/discrete/counting-slots/preset.d.mts +30 -0
  191. package/dist/discrete/counting-slots/preset.mjs +553 -0
  192. package/dist/discrete/counting-tree/index.d.mts +1 -0
  193. package/dist/discrete/counting-tree/preset.d.mts +44 -0
  194. package/dist/discrete/counting-tree/preset.mjs +364 -0
  195. package/dist/discrete/expected-value/preset.d.mts +28 -0
  196. package/dist/discrete/expected-value/preset.mjs +352 -0
  197. package/dist/discrete/hypergeometric/preset.d.mts +25 -0
  198. package/dist/discrete/hypergeometric/preset.mjs +330 -0
  199. package/dist/discrete/index.d.mts +26 -0
  200. package/dist/discrete/index.mjs +27 -0
  201. package/dist/discrete/karnaugh/index.d.mts +1 -0
  202. package/dist/discrete/karnaugh/preset.d.mts +30 -0
  203. package/dist/discrete/karnaugh/preset.mjs +452 -0
  204. package/dist/discrete/lln/asset.mjs +206 -0
  205. package/dist/discrete/lln/index.d.mts +1 -0
  206. package/dist/discrete/lln/preset.d.mts +17 -0
  207. package/dist/discrete/lln/preset.mjs +152 -0
  208. package/dist/discrete/logic-circuit/index.d.mts +1 -0
  209. package/dist/discrete/logic-circuit/preset.d.mts +47 -0
  210. package/dist/discrete/logic-circuit/preset.mjs +307 -0
  211. package/dist/discrete/monte-carlo/index.d.mts +1 -0
  212. package/dist/discrete/monte-carlo/preset.d.mts +64 -0
  213. package/dist/discrete/monte-carlo/preset.mjs +446 -0
  214. package/dist/discrete/monty-hall/index.d.mts +1 -0
  215. package/dist/discrete/monty-hall/preset.d.mts +23 -0
  216. package/dist/discrete/monty-hall/preset.mjs +491 -0
  217. package/dist/discrete/outcome-builder/preset.d.mts +24 -0
  218. package/dist/discrete/outcome-builder/preset.mjs +283 -0
  219. package/dist/discrete/pascal/preset.d.mts +24 -0
  220. package/dist/discrete/pascal/preset.mjs +372 -0
  221. package/dist/discrete/sample-space/index.d.mts +1 -0
  222. package/dist/discrete/sample-space/preset.d.mts +42 -0
  223. package/dist/discrete/sample-space/preset.mjs +395 -0
  224. package/dist/discrete/selection/preset.d.mts +33 -0
  225. package/dist/discrete/selection/preset.mjs +406 -0
  226. package/dist/discrete/truth-table/index.d.mts +1 -0
  227. package/dist/discrete/truth-table/preset.d.mts +30 -0
  228. package/dist/discrete/truth-table/preset.mjs +456 -0
  229. package/dist/discrete/venn/index.d.mts +1 -0
  230. package/dist/discrete/venn/preset.d.mts +32 -0
  231. package/dist/discrete/venn/preset.mjs +461 -0
  232. package/dist/geography/cycle-lab/index.d.mts +1 -0
  233. package/dist/geography/cycle-lab/preset.d.mts +25 -0
  234. package/dist/geography/cycle-lab/preset.mjs +254 -0
  235. package/dist/geography/cycles.d.mts +21 -0
  236. package/dist/geography/cycles.mjs +205 -0
  237. package/dist/geography/index.d.mts +4 -0
  238. package/dist/geography/index.mjs +5 -0
  239. package/dist/geometry/board/index.d.mts +1 -0
  240. package/dist/geometry/board/preset.d.mts +71 -0
  241. package/dist/geometry/board/preset.mjs +148 -0
  242. package/dist/geometry/builder.d.mts +18 -0
  243. package/dist/geometry/builder.mjs +332 -0
  244. package/dist/geometry/index.d.mts +4 -0
  245. package/dist/geometry/index.mjs +5 -0
  246. package/dist/geometry/intersecting-circles.d.mts +17 -0
  247. package/dist/geometry/intersecting-circles.mjs +104 -0
  248. package/dist/ict/index.d.mts +5 -0
  249. package/dist/ict/index.mjs +6 -0
  250. package/dist/ict/number-systems/base-odometer.d.mts +34 -0
  251. package/dist/ict/number-systems/base-odometer.mjs +160 -0
  252. package/dist/ict/number-systems/bit-grouper.d.mts +32 -0
  253. package/dist/ict/number-systems/bit-grouper.mjs +190 -0
  254. package/dist/ict/number-systems/index.d.mts +4 -0
  255. package/dist/ict/number-systems/place-value-dial.d.mts +29 -0
  256. package/dist/ict/number-systems/place-value-dial.mjs +153 -0
  257. package/dist/ict/number-systems/wheel.d.mts +73 -0
  258. package/dist/ict/number-systems/wheel.mjs +279 -0
  259. package/dist/index.d.mts +10 -0
  260. package/dist/index.mjs +11 -0
  261. package/dist/kit/anim.mjs +52 -0
  262. package/dist/kit/annotate.mjs +116 -0
  263. package/dist/kit/answer-check.d.mts +38 -0
  264. package/dist/kit/answer-check.mjs +65 -0
  265. package/dist/kit/asset-util.mjs +15 -0
  266. package/dist/kit/controls.mjs +77 -0
  267. package/dist/kit/cycle.d.mts +44 -0
  268. package/dist/kit/cycle.mjs +188 -0
  269. package/dist/kit/diagram.mjs +176 -0
  270. package/dist/kit/electronics.mjs +357 -0
  271. package/dist/kit/expr-analysis.d.mts +37 -0
  272. package/dist/kit/expr-analysis.mjs +111 -0
  273. package/dist/kit/frame.d.mts +70 -0
  274. package/dist/kit/frame.mjs +205 -0
  275. package/dist/kit/freq-tree.mjs +99 -0
  276. package/dist/kit/gameshow.mjs +315 -0
  277. package/dist/kit/index.d.mts +5 -0
  278. package/dist/kit/index.mjs +6 -0
  279. package/dist/kit/logic-gates.d.mts +6 -0
  280. package/dist/kit/logic-gates.mjs +210 -0
  281. package/dist/kit/molecules.mjs +178 -0
  282. package/dist/kit/pedagogy.d.mts +126 -0
  283. package/dist/kit/pedagogy.mjs +331 -0
  284. package/dist/kit/play.d.mts +21 -0
  285. package/dist/kit/play.mjs +52 -0
  286. package/dist/kit/probability.mjs +141 -0
  287. package/dist/kit/proportion.mjs +112 -0
  288. package/dist/kit/reaction.mjs +102 -0
  289. package/dist/kit/rich.d.mts +10 -0
  290. package/dist/kit/rich.mjs +21 -0
  291. package/dist/kit/scale.mjs +230 -0
  292. package/dist/kit/space.mjs +326 -0
  293. package/dist/kit/steps.d.mts +24 -0
  294. package/dist/kit/steps.mjs +57 -0
  295. package/dist/kit/thermal.mjs +289 -0
  296. package/dist/language/agreement/index.d.mts +1 -0
  297. package/dist/language/agreement/preset.d.mts +27 -0
  298. package/dist/language/agreement/preset.mjs +113 -0
  299. package/dist/language/article-lens/index.d.mts +1 -0
  300. package/dist/language/article-lens/preset.d.mts +31 -0
  301. package/dist/language/article-lens/preset.mjs +125 -0
  302. package/dist/language/deck.d.mts +45 -0
  303. package/dist/language/deck.mjs +61 -0
  304. package/dist/language/icon.d.mts +40 -0
  305. package/dist/language/icon.mjs +73 -0
  306. package/dist/language/index.d.mts +10 -0
  307. package/dist/language/index.mjs +11 -0
  308. package/dist/language/preposition-scene/index.d.mts +1 -0
  309. package/dist/language/preposition-scene/preset.d.mts +34 -0
  310. package/dist/language/preposition-scene/preset.mjs +234 -0
  311. package/dist/language/sentence-builder/index.d.mts +1 -0
  312. package/dist/language/sentence-builder/preset.d.mts +32 -0
  313. package/dist/language/sentence-builder/preset.mjs +122 -0
  314. package/dist/language/transform/index.d.mts +1 -0
  315. package/dist/language/transform/preset.d.mts +31 -0
  316. package/dist/language/transform/preset.mjs +137 -0
  317. package/dist/language/ui.d.mts +53 -0
  318. package/dist/language/ui.mjs +88 -0
  319. package/dist/language/word-match/index.d.mts +1 -0
  320. package/dist/language/word-match/preset.d.mts +22 -0
  321. package/dist/language/word-match/preset.mjs +148 -0
  322. package/dist/math/area-model/asset.d.mts +6 -0
  323. package/dist/math/area-model/asset.mjs +270 -0
  324. package/dist/math/area-model/index.d.mts +2 -0
  325. package/dist/math/area-model/preset.d.mts +29 -0
  326. package/dist/math/area-model/preset.mjs +243 -0
  327. package/dist/math/balance-algebra/asset.d.mts +6 -0
  328. package/dist/math/balance-algebra/asset.mjs +150 -0
  329. package/dist/math/balance-algebra/index.d.mts +2 -0
  330. package/dist/math/balance-algebra/preset.d.mts +30 -0
  331. package/dist/math/balance-algebra/preset.mjs +228 -0
  332. package/dist/math/derivation.d.mts +22 -0
  333. package/dist/math/derivation.mjs +113 -0
  334. package/dist/math/derivative-explorer/index.d.mts +1 -0
  335. package/dist/math/derivative-explorer/preset.d.mts +19 -0
  336. package/dist/math/derivative-explorer/preset.mjs +227 -0
  337. package/dist/math/function-machine/index.d.mts +1 -0
  338. package/dist/math/function-machine/preset.d.mts +21 -0
  339. package/dist/math/function-machine/preset.mjs +177 -0
  340. package/dist/math/gradient-descent.d.mts +23 -0
  341. package/dist/math/gradient-descent.mjs +473 -0
  342. package/dist/math/grapher/index.d.mts +1 -0
  343. package/dist/math/grapher/preset.d.mts +40 -0
  344. package/dist/math/grapher/preset.mjs +313 -0
  345. package/dist/math/harmonic-form/index.d.mts +1 -0
  346. package/dist/math/harmonic-form/preset.d.mts +21 -0
  347. package/dist/math/harmonic-form/preset.mjs +387 -0
  348. package/dist/math/index.d.mts +25 -0
  349. package/dist/math/index.mjs +26 -0
  350. package/dist/math/integral-explorer/index.d.mts +1 -0
  351. package/dist/math/integral-explorer/preset.d.mts +23 -0
  352. package/dist/math/integral-explorer/preset.mjs +217 -0
  353. package/dist/math/interactive/index.d.mts +1 -0
  354. package/dist/math/interactive/preset.d.mts +72 -0
  355. package/dist/math/interactive/preset.mjs +202 -0
  356. package/dist/math/limit-explorer/index.d.mts +1 -0
  357. package/dist/math/limit-explorer/preset.d.mts +19 -0
  358. package/dist/math/limit-explorer/preset.mjs +216 -0
  359. package/dist/math/linear-system/index.d.mts +1 -0
  360. package/dist/math/linear-system/preset.d.mts +28 -0
  361. package/dist/math/linear-system/preset.mjs +164 -0
  362. package/dist/math/mystery-bucket/asset.d.mts +6 -0
  363. package/dist/math/mystery-bucket/asset.mjs +145 -0
  364. package/dist/math/mystery-bucket/index.d.mts +2 -0
  365. package/dist/math/mystery-bucket/preset.d.mts +36 -0
  366. package/dist/math/mystery-bucket/preset.mjs +116 -0
  367. package/dist/math/number-line/index.d.mts +1 -0
  368. package/dist/math/number-line/preset.d.mts +24 -0
  369. package/dist/math/number-line/preset.mjs +142 -0
  370. package/dist/math/parabola/index.d.mts +1 -0
  371. package/dist/math/parabola/preset.d.mts +13 -0
  372. package/dist/math/parabola/preset.mjs +79 -0
  373. package/dist/math/pattern/asset.d.mts +6 -0
  374. package/dist/math/pattern/asset.mjs +102 -0
  375. package/dist/math/pattern/index.d.mts +2 -0
  376. package/dist/math/pattern/preset.d.mts +32 -0
  377. package/dist/math/pattern/preset.mjs +294 -0
  378. package/dist/math/triangle-trig/index.d.mts +1 -0
  379. package/dist/math/triangle-trig/preset.d.mts +47 -0
  380. package/dist/math/triangle-trig/preset.mjs +245 -0
  381. package/dist/math/trig-explorer.d.mts +18 -0
  382. package/dist/math/trig-explorer.mjs +209 -0
  383. package/dist/ml/boundary/index.d.mts +1 -0
  384. package/dist/ml/boundary/preset.d.mts +24 -0
  385. package/dist/ml/boundary/preset.mjs +385 -0
  386. package/dist/ml/classifier/index.d.mts +1 -0
  387. package/dist/ml/classifier/preset.d.mts +25 -0
  388. package/dist/ml/classifier/preset.mjs +315 -0
  389. package/dist/ml/index.d.mts +6 -0
  390. package/dist/ml/index.mjs +7 -0
  391. package/dist/ml/kmeans/index.d.mts +1 -0
  392. package/dist/ml/kmeans/preset.d.mts +33 -0
  393. package/dist/ml/kmeans/preset.mjs +236 -0
  394. package/dist/ml/knn/index.d.mts +1 -0
  395. package/dist/ml/knn/preset.d.mts +28 -0
  396. package/dist/ml/knn/preset.mjs +279 -0
  397. package/dist/ml/regression/index.d.mts +1 -0
  398. package/dist/ml/regression/preset.d.mts +32 -0
  399. package/dist/ml/regression/preset.mjs +394 -0
  400. package/dist/physics/atwood/index.d.mts +1 -0
  401. package/dist/physics/atwood/preset.d.mts +23 -0
  402. package/dist/physics/atwood/preset.mjs +312 -0
  403. package/dist/physics/bullet-walls/index.d.mts +1 -0
  404. package/dist/physics/bullet-walls/preset.d.mts +28 -0
  405. package/dist/physics/bullet-walls/preset.mjs +373 -0
  406. package/dist/physics/carnot/index.d.mts +1 -0
  407. package/dist/physics/carnot/preset.d.mts +27 -0
  408. package/dist/physics/carnot/preset.mjs +427 -0
  409. package/dist/physics/circular-motion/index.d.mts +1 -0
  410. package/dist/physics/circular-motion/preset.d.mts +25 -0
  411. package/dist/physics/circular-motion/preset.mjs +293 -0
  412. package/dist/physics/collision-track/index.d.mts +1 -0
  413. package/dist/physics/collision-track/preset.d.mts +27 -0
  414. package/dist/physics/collision-track/preset.mjs +352 -0
  415. package/dist/physics/efficiency/index.d.mts +1 -0
  416. package/dist/physics/efficiency/preset.d.mts +33 -0
  417. package/dist/physics/efficiency/preset.mjs +343 -0
  418. package/dist/physics/electric-field/index.d.mts +1 -0
  419. package/dist/physics/electric-field/preset.d.mts +15 -0
  420. package/dist/physics/electric-field/preset.mjs +306 -0
  421. package/dist/physics/energy-skate/index.d.mts +1 -0
  422. package/dist/physics/energy-skate/preset.d.mts +25 -0
  423. package/dist/physics/energy-skate/preset.mjs +254 -0
  424. package/dist/physics/entropy/index.d.mts +1 -0
  425. package/dist/physics/entropy/preset.d.mts +18 -0
  426. package/dist/physics/entropy/preset.mjs +416 -0
  427. package/dist/physics/expansion/index.d.mts +1 -0
  428. package/dist/physics/expansion/preset.d.mts +26 -0
  429. package/dist/physics/expansion/preset.mjs +609 -0
  430. package/dist/physics/exponential/asset.mjs +221 -0
  431. package/dist/physics/exponential/index.d.mts +1 -0
  432. package/dist/physics/exponential/preset.d.mts +17 -0
  433. package/dist/physics/exponential/preset.mjs +182 -0
  434. package/dist/physics/gas-process/index.d.mts +1 -0
  435. package/dist/physics/gas-process/preset.d.mts +30 -0
  436. package/dist/physics/gas-process/preset.mjs +384 -0
  437. package/dist/physics/gravitation/index.d.mts +1 -0
  438. package/dist/physics/gravitation/preset.d.mts +24 -0
  439. package/dist/physics/gravitation/preset.mjs +345 -0
  440. package/dist/physics/gravity-drop.d.mts +9 -0
  441. package/dist/physics/gravity-drop.mjs +187 -0
  442. package/dist/physics/heat-transfer/index.d.mts +1 -0
  443. package/dist/physics/heat-transfer/preset.d.mts +27 -0
  444. package/dist/physics/heat-transfer/preset.mjs +626 -0
  445. package/dist/physics/impulse/index.d.mts +1 -0
  446. package/dist/physics/impulse/preset.d.mts +29 -0
  447. package/dist/physics/impulse/preset.mjs +453 -0
  448. package/dist/physics/index.d.mts +43 -0
  449. package/dist/physics/index.mjs +44 -0
  450. package/dist/physics/kepler/index.d.mts +1 -0
  451. package/dist/physics/kepler/preset.d.mts +27 -0
  452. package/dist/physics/kepler/preset.mjs +257 -0
  453. package/dist/physics/lever/asset.d.mts +6 -0
  454. package/dist/physics/lever/asset.mjs +220 -0
  455. package/dist/physics/lever/index.d.mts +2 -0
  456. package/dist/physics/lever/preset.d.mts +31 -0
  457. package/dist/physics/lever/preset.mjs +261 -0
  458. package/dist/physics/lorentz/index.d.mts +1 -0
  459. package/dist/physics/lorentz/preset.d.mts +29 -0
  460. package/dist/physics/lorentz/preset.mjs +367 -0
  461. package/dist/physics/magnetism/index.d.mts +1 -0
  462. package/dist/physics/magnetism/preset.d.mts +15 -0
  463. package/dist/physics/magnetism/preset.mjs +334 -0
  464. package/dist/physics/optics/asset.d.mts +6 -0
  465. package/dist/physics/optics/asset.mjs +234 -0
  466. package/dist/physics/optics/index.d.mts +2 -0
  467. package/dist/physics/optics/preset.d.mts +14 -0
  468. package/dist/physics/optics/preset.mjs +202 -0
  469. package/dist/physics/orbit-lab.d.mts +6 -0
  470. package/dist/physics/orbit-lab.mjs +222 -0
  471. package/dist/physics/projectile-lab.d.mts +10 -0
  472. package/dist/physics/projectile-lab.mjs +354 -0
  473. package/dist/physics/rain-relative/index.d.mts +1 -0
  474. package/dist/physics/rain-relative/preset.d.mts +19 -0
  475. package/dist/physics/rain-relative/preset.mjs +358 -0
  476. package/dist/physics/ramp-forces/index.d.mts +1 -0
  477. package/dist/physics/ramp-forces/preset.d.mts +36 -0
  478. package/dist/physics/ramp-forces/preset.mjs +550 -0
  479. package/dist/physics/river-boat.d.mts +22 -0
  480. package/dist/physics/river-boat.mjs +498 -0
  481. package/dist/physics/shm/index.d.mts +1 -0
  482. package/dist/physics/shm/preset.d.mts +33 -0
  483. package/dist/physics/shm/preset.mjs +554 -0
  484. package/dist/physics/stopping-distance/index.d.mts +1 -0
  485. package/dist/physics/stopping-distance/preset.d.mts +29 -0
  486. package/dist/physics/stopping-distance/preset.mjs +662 -0
  487. package/dist/physics/temperature-scales/index.d.mts +1 -0
  488. package/dist/physics/temperature-scales/preset.d.mts +15 -0
  489. package/dist/physics/temperature-scales/preset.mjs +353 -0
  490. package/dist/physics/terminal-velocity/index.d.mts +1 -0
  491. package/dist/physics/terminal-velocity/preset.d.mts +26 -0
  492. package/dist/physics/terminal-velocity/preset.mjs +404 -0
  493. package/dist/physics/thermal/index.d.mts +1 -0
  494. package/dist/physics/thermal/preset.d.mts +44 -0
  495. package/dist/physics/thermal/preset.mjs +373 -0
  496. package/dist/physics/vector-board/index.d.mts +1 -0
  497. package/dist/physics/vector-board/preset.d.mts +65 -0
  498. package/dist/physics/vector-board/preset.mjs +273 -0
  499. package/dist/physics/vector-board/view.d.mts +49 -0
  500. package/dist/physics/vector-board/view.mjs +58 -0
  501. package/dist/physics/vector-scene.d.mts +41 -0
  502. package/dist/physics/vector-scene.mjs +211 -0
  503. package/dist/physics/vector-types/index.d.mts +1 -0
  504. package/dist/physics/vector-types/preset.d.mts +27 -0
  505. package/dist/physics/vector-types/preset.mjs +192 -0
  506. package/dist/physics/water-density/index.d.mts +1 -0
  507. package/dist/physics/water-density/preset.d.mts +18 -0
  508. package/dist/physics/water-density/preset.mjs +439 -0
  509. package/dist/physics/waves/core.mjs +33 -0
  510. package/dist/physics/waves/doppler.d.mts +23 -0
  511. package/dist/physics/waves/doppler.mjs +260 -0
  512. package/dist/physics/waves/index.d.mts +4 -0
  513. package/dist/physics/waves/preset.d.mts +30 -0
  514. package/dist/physics/waves/preset.mjs +488 -0
  515. package/dist/physics/waves/ripple.d.mts +26 -0
  516. package/dist/physics/waves/ripple.mjs +234 -0
  517. package/dist/physics/waves/string.d.mts +29 -0
  518. package/dist/physics/waves/string.mjs +289 -0
  519. package/dist/physics/work-energy/index.d.mts +1 -0
  520. package/dist/physics/work-energy/preset.d.mts +17 -0
  521. package/dist/physics/work-energy/preset.mjs +341 -0
  522. package/dist/schemas/index.d.mts +235 -0
  523. package/dist/schemas/index.mjs +145 -0
  524. package/dist/statistics/center-spread/preset.d.mts +34 -0
  525. package/dist/statistics/center-spread/preset.mjs +323 -0
  526. package/dist/statistics/core/descriptive.d.mts +35 -0
  527. package/dist/statistics/core/descriptive.mjs +64 -0
  528. package/dist/statistics/core/normal.d.mts +21 -0
  529. package/dist/statistics/core/normal.mjs +37 -0
  530. package/dist/statistics/core/sequences.d.mts +27 -0
  531. package/dist/statistics/core/sequences.mjs +35 -0
  532. package/dist/statistics/galton/preset.d.mts +27 -0
  533. package/dist/statistics/galton/preset.mjs +331 -0
  534. package/dist/statistics/histogram/preset.d.mts +27 -0
  535. package/dist/statistics/histogram/preset.mjs +385 -0
  536. package/dist/statistics/index.d.mts +11 -0
  537. package/dist/statistics/index.mjs +12 -0
  538. package/dist/statistics/normal/preset.d.mts +30 -0
  539. package/dist/statistics/normal/preset.mjs +400 -0
  540. package/dist/statistics/sampling/preset.d.mts +32 -0
  541. package/dist/statistics/sampling/preset.mjs +406 -0
  542. package/dist/statistics/sequence/preset.d.mts +28 -0
  543. package/dist/statistics/sequence/preset.mjs +302 -0
  544. package/dist/statistics/z-table/preset.d.mts +28 -0
  545. package/dist/statistics/z-table/preset.mjs +348 -0
  546. package/package.json +266 -0
  547. package/styles.css +267 -0
@@ -0,0 +1,1536 @@
1
+ import { Grapher } from "../math/grapher/preset.mjs";
2
+ import { DerivativeExplorer } from "../math/derivative-explorer/preset.mjs";
3
+ import { IntegralExplorer } from "../math/integral-explorer/preset.mjs";
4
+ import { LimitExplorer } from "../math/limit-explorer/preset.mjs";
5
+ import { LinearSystemLab } from "../math/linear-system/preset.mjs";
6
+ import { NumberLineLab } from "../math/number-line/preset.mjs";
7
+ import { AreaModelLab } from "../math/area-model/preset.mjs";
8
+ import { GrowingPatternLab } from "../math/pattern/preset.mjs";
9
+ import { MysteryBucketLab } from "../math/mystery-bucket/preset.mjs";
10
+ import { BalanceAlgebraLab } from "../math/balance-algebra/preset.mjs";
11
+ import { VertexParabolaLab } from "../math/parabola/preset.mjs";
12
+ import { FunctionMachineLab } from "../math/function-machine/preset.mjs";
13
+ import { TRIG_FNS, TrigExplorer } from "../math/trig-explorer.mjs";
14
+ import { Derivation } from "../math/derivation.mjs";
15
+ import { GradientDescent } from "../math/gradient-descent.mjs";
16
+ import { InteractiveProblem } from "../math/interactive/preset.mjs";
17
+ import { TriangleTrig } from "../math/triangle-trig/preset.mjs";
18
+ import { ChipToggle, ConfigPanel, ConfigRow, NumField, SelectField, SmallButton, TextField } from "./authoring.mjs";
19
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
+ import { z } from "zod";
21
+ import { defineBlock } from "@classytic/cms-ui/contract";
22
+
23
+ //#region src/blocks/math.tsx
24
+ const resolveFns = (raw) => Array.isArray(raw) && raw.length ? raw : ["sin", "cos"];
25
+ const TrigExplorerBlock = defineBlock({
26
+ key: "trig-explorer",
27
+ void: true,
28
+ label: "Trig explorer",
29
+ description: "Unit circle ↔ wave — drag the angle; sin & cos trace out. (tan/cot: use Graph)",
30
+ category: "interactive",
31
+ schema: z.object({
32
+ functions: z.array(z.enum(["sin", "cos"])).optional(),
33
+ startDeg: z.number().optional()
34
+ }),
35
+ Component: ({ attributes, mode, updateAttributes }) => {
36
+ const fns = resolveFns(attributes.functions);
37
+ const widget = /* @__PURE__ */ jsx(TrigExplorer, {
38
+ functions: fns,
39
+ startDeg: attributes.startDeg
40
+ });
41
+ if (mode !== "editing" || !updateAttributes) return widget;
42
+ const toggle = (fn) => {
43
+ const next = fns.includes(fn) ? fns.filter((f) => f !== fn) : [...fns, fn];
44
+ updateAttributes({ functions: next.length ? next : fns });
45
+ };
46
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(ConfigPanel, { children: /* @__PURE__ */ jsx(ConfigRow, {
47
+ label: "Functions",
48
+ children: TRIG_FNS.map((fn) => /* @__PURE__ */ jsx(ChipToggle, {
49
+ active: fns.includes(fn),
50
+ onClick: () => toggle(fn),
51
+ children: fn
52
+ }, fn))
53
+ }) }), widget] });
54
+ }
55
+ });
56
+ const equationSchema = z.union([z.string(), z.object({
57
+ expr: z.string(),
58
+ color: z.string().optional()
59
+ })]);
60
+ const paramSchema = z.object({
61
+ name: z.string(),
62
+ min: z.number(),
63
+ max: z.number(),
64
+ step: z.number().optional(),
65
+ value: z.number()
66
+ });
67
+ const asExprStrings = (raw) => {
68
+ if (typeof raw === "string") return [raw];
69
+ if (Array.isArray(raw)) return raw.map((e) => typeof e === "string" ? e : String(e?.expr ?? ""));
70
+ return ["sin(x)"];
71
+ };
72
+ const asParams = (raw) => Array.isArray(raw) ? raw : [];
73
+ const GraphBlock = defineBlock({
74
+ key: "graph",
75
+ void: true,
76
+ label: "Graph (equation)",
77
+ description: "Plot equations you type — y = a·sin(b·x), x^2, … with learner sliders.",
78
+ category: "interactive",
79
+ schema: z.object({
80
+ equations: z.array(equationSchema).optional(),
81
+ params: z.array(paramSchema).optional(),
82
+ xRange: z.tuple([z.number(), z.number()]).optional(),
83
+ yScale: z.enum(["linear", "log"]).optional(),
84
+ title: z.string().optional()
85
+ }),
86
+ Component: ({ attributes, mode, updateAttributes }) => {
87
+ const equations = asExprStrings(attributes.equations);
88
+ const params = asParams(attributes.params);
89
+ const xRange = attributes.xRange ?? [-6.5, 6.5];
90
+ const yScale = attributes.yScale === "log" ? "log" : "linear";
91
+ const title = attributes.title ?? "Graph";
92
+ const widget = /* @__PURE__ */ jsx(Grapher, {
93
+ equations,
94
+ params,
95
+ xRange,
96
+ yScale,
97
+ title
98
+ });
99
+ if (mode !== "editing" || !updateAttributes) return widget;
100
+ const setEq = (i, v) => {
101
+ const next = [...equations];
102
+ next[i] = v;
103
+ updateAttributes({ equations: next });
104
+ };
105
+ const setParam = (i, patch) => {
106
+ updateAttributes({ params: params.map((p, j) => j === i ? {
107
+ ...p,
108
+ ...patch
109
+ } : p) });
110
+ };
111
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
112
+ /* @__PURE__ */ jsx(ConfigRow, {
113
+ label: "Title",
114
+ children: /* @__PURE__ */ jsx(TextField, {
115
+ value: title,
116
+ onChange: (v) => updateAttributes({ title: v }),
117
+ className: "flex-1"
118
+ })
119
+ }),
120
+ /* @__PURE__ */ jsxs("div", {
121
+ className: "space-y-1.5",
122
+ children: [
123
+ /* @__PURE__ */ jsx("span", {
124
+ className: "font-medium text-muted-foreground",
125
+ children: "Equations (use x and your slider names)"
126
+ }),
127
+ equations.map((eq, i) => /* @__PURE__ */ jsxs("div", {
128
+ className: "flex items-center gap-2",
129
+ children: [
130
+ /* @__PURE__ */ jsx("span", {
131
+ className: "font-mono text-muted-foreground",
132
+ children: "y ="
133
+ }),
134
+ /* @__PURE__ */ jsx(TextField, {
135
+ value: eq,
136
+ mono: true,
137
+ placeholder: "a*sin(b*x) + c",
138
+ onChange: (v) => setEq(i, v),
139
+ className: "flex-1"
140
+ }),
141
+ equations.length > 1 && /* @__PURE__ */ jsx(SmallButton, {
142
+ tone: "danger",
143
+ onClick: () => updateAttributes({ equations: equations.filter((_, j) => j !== i) }),
144
+ children: "✕"
145
+ })
146
+ ]
147
+ }, i)),
148
+ /* @__PURE__ */ jsx(SmallButton, {
149
+ onClick: () => updateAttributes({ equations: [...equations, ""] }),
150
+ children: "+ equation"
151
+ })
152
+ ]
153
+ }),
154
+ /* @__PURE__ */ jsxs("div", {
155
+ className: "space-y-1.5",
156
+ children: [
157
+ /* @__PURE__ */ jsx("span", {
158
+ className: "font-medium text-muted-foreground",
159
+ children: "Sliders (learner-draggable)"
160
+ }),
161
+ params.map((p, i) => /* @__PURE__ */ jsxs("div", {
162
+ className: "flex flex-wrap items-center gap-1.5",
163
+ children: [
164
+ /* @__PURE__ */ jsx(TextField, {
165
+ value: p.name,
166
+ mono: true,
167
+ placeholder: "a",
168
+ onChange: (v) => setParam(i, { name: v }),
169
+ className: "w-14"
170
+ }),
171
+ /* @__PURE__ */ jsx("span", {
172
+ className: "text-muted-foreground",
173
+ children: "from"
174
+ }),
175
+ /* @__PURE__ */ jsx(NumField, {
176
+ value: p.min,
177
+ onChange: (v) => setParam(i, { min: v })
178
+ }),
179
+ /* @__PURE__ */ jsx("span", {
180
+ className: "text-muted-foreground",
181
+ children: "to"
182
+ }),
183
+ /* @__PURE__ */ jsx(NumField, {
184
+ value: p.max,
185
+ onChange: (v) => setParam(i, { max: v })
186
+ }),
187
+ /* @__PURE__ */ jsx("span", {
188
+ className: "text-muted-foreground",
189
+ children: "="
190
+ }),
191
+ /* @__PURE__ */ jsx(NumField, {
192
+ value: p.value,
193
+ onChange: (v) => setParam(i, { value: v })
194
+ }),
195
+ /* @__PURE__ */ jsx(SmallButton, {
196
+ tone: "danger",
197
+ onClick: () => updateAttributes({ params: params.filter((_, j) => j !== i) }),
198
+ children: "✕"
199
+ })
200
+ ]
201
+ }, i)),
202
+ /* @__PURE__ */ jsx(SmallButton, {
203
+ onClick: () => updateAttributes({ params: [...params, {
204
+ name: nextParamName(params),
205
+ min: 0,
206
+ max: 3,
207
+ value: 1,
208
+ step: .1
209
+ }] }),
210
+ children: "+ slider"
211
+ })
212
+ ]
213
+ }),
214
+ /* @__PURE__ */ jsxs(ConfigRow, {
215
+ label: "x window",
216
+ children: [
217
+ /* @__PURE__ */ jsx(NumField, {
218
+ value: xRange[0],
219
+ onChange: (v) => updateAttributes({ xRange: [v, xRange[1]] })
220
+ }),
221
+ /* @__PURE__ */ jsx("span", {
222
+ className: "text-muted-foreground",
223
+ children: "to"
224
+ }),
225
+ /* @__PURE__ */ jsx(NumField, {
226
+ value: xRange[1],
227
+ onChange: (v) => updateAttributes({ xRange: [xRange[0], v] })
228
+ })
229
+ ]
230
+ }),
231
+ /* @__PURE__ */ jsxs(ConfigRow, {
232
+ label: "y scale",
233
+ children: [/* @__PURE__ */ jsx(ChipToggle, {
234
+ active: yScale !== "log",
235
+ onClick: () => updateAttributes({ yScale: "linear" }),
236
+ children: "linear"
237
+ }), /* @__PURE__ */ jsx(ChipToggle, {
238
+ active: yScale === "log",
239
+ onClick: () => updateAttributes({ yScale: "log" }),
240
+ children: "log"
241
+ })]
242
+ })
243
+ ] }), widget] });
244
+ }
245
+ });
246
+ const DerivativeExplorerBlock = defineBlock({
247
+ key: "derivative-explorer",
248
+ void: true,
249
+ label: "Derivative explorer",
250
+ description: "Drag a point; the secant becomes the exact tangent. Shows f′(x).",
251
+ category: "interactive",
252
+ schema: z.object({
253
+ equation: z.string().optional(),
254
+ xRange: z.tuple([z.number(), z.number()]).optional(),
255
+ startX: z.number().optional(),
256
+ title: z.string().optional()
257
+ }),
258
+ Component: ({ attributes, mode, updateAttributes }) => {
259
+ const equation = typeof attributes.equation === "string" && attributes.equation.trim() ? attributes.equation : "0.15*x^3 - x";
260
+ const xRange = attributes.xRange ?? [-4, 4];
261
+ const title = attributes.title ?? "The derivative is a slope";
262
+ const widget = /* @__PURE__ */ jsx(DerivativeExplorer, {
263
+ equation,
264
+ xRange,
265
+ startX: attributes.startX,
266
+ title
267
+ });
268
+ if (mode !== "editing" || !updateAttributes) return widget;
269
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
270
+ /* @__PURE__ */ jsx(ConfigRow, {
271
+ label: "Title",
272
+ children: /* @__PURE__ */ jsx(TextField, {
273
+ value: title,
274
+ onChange: (v) => updateAttributes({ title: v }),
275
+ className: "flex-1"
276
+ })
277
+ }),
278
+ /* @__PURE__ */ jsx(ConfigRow, {
279
+ label: "f(x) =",
280
+ children: /* @__PURE__ */ jsx(TextField, {
281
+ value: equation,
282
+ mono: true,
283
+ placeholder: "0.15*x^3 - x",
284
+ onChange: (v) => updateAttributes({ equation: v }),
285
+ className: "flex-1"
286
+ })
287
+ }),
288
+ /* @__PURE__ */ jsxs(ConfigRow, {
289
+ label: "x window",
290
+ children: [
291
+ /* @__PURE__ */ jsx(NumField, {
292
+ value: xRange[0],
293
+ onChange: (v) => updateAttributes({ xRange: [v, xRange[1]] })
294
+ }),
295
+ /* @__PURE__ */ jsx("span", {
296
+ className: "text-muted-foreground",
297
+ children: "to"
298
+ }),
299
+ /* @__PURE__ */ jsx(NumField, {
300
+ value: xRange[1],
301
+ onChange: (v) => updateAttributes({ xRange: [xRange[0], v] })
302
+ })
303
+ ]
304
+ })
305
+ ] }), widget] });
306
+ }
307
+ });
308
+ const GradientDescentBlock = defineBlock({
309
+ key: "gradient-descent",
310
+ void: true,
311
+ label: "Gradient descent",
312
+ description: "Walk downhill on a loss surface f(x,y) using exact ∂f/∂x, ∂f/∂y — the calculus behind ML.",
313
+ category: "interactive",
314
+ schema: z.object({
315
+ equation: z.string().optional(),
316
+ range: z.tuple([z.number(), z.number()]).optional(),
317
+ learningRate: z.number().optional(),
318
+ title: z.string().optional()
319
+ }),
320
+ Component: ({ attributes, mode, updateAttributes }) => {
321
+ const equation = typeof attributes.equation === "string" && attributes.equation.trim() ? attributes.equation : "x^2 + 2*y^2";
322
+ const range = attributes.range ?? [-3, 3];
323
+ const title = attributes.title ?? "Gradient descent";
324
+ const widget = /* @__PURE__ */ jsx(GradientDescent, {
325
+ equation,
326
+ range,
327
+ learningRate: attributes.learningRate,
328
+ title
329
+ });
330
+ if (mode !== "editing" || !updateAttributes) return widget;
331
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
332
+ /* @__PURE__ */ jsx(ConfigRow, {
333
+ label: "Title",
334
+ children: /* @__PURE__ */ jsx(TextField, {
335
+ value: title,
336
+ onChange: (v) => updateAttributes({ title: v }),
337
+ className: "flex-1"
338
+ })
339
+ }),
340
+ /* @__PURE__ */ jsx(ConfigRow, {
341
+ label: "f(x,y) =",
342
+ children: /* @__PURE__ */ jsx(TextField, {
343
+ value: equation,
344
+ mono: true,
345
+ placeholder: "x^2 + 2*y^2",
346
+ onChange: (v) => updateAttributes({ equation: v }),
347
+ className: "flex-1"
348
+ })
349
+ }),
350
+ /* @__PURE__ */ jsxs(ConfigRow, {
351
+ label: "region",
352
+ children: [
353
+ /* @__PURE__ */ jsx(NumField, {
354
+ value: range[0],
355
+ onChange: (v) => updateAttributes({ range: [v, range[1]] })
356
+ }),
357
+ /* @__PURE__ */ jsx("span", {
358
+ className: "text-muted-foreground",
359
+ children: "to"
360
+ }),
361
+ /* @__PURE__ */ jsx(NumField, {
362
+ value: range[1],
363
+ onChange: (v) => updateAttributes({ range: [range[0], v] })
364
+ })
365
+ ]
366
+ })
367
+ ] }), widget] });
368
+ }
369
+ });
370
+ const IntegralExplorerBlock = defineBlock({
371
+ key: "integral-explorer",
372
+ void: true,
373
+ label: "Integral explorer",
374
+ description: "Area under a curve via Riemann rectangles — drag endpoints, add n, converge.",
375
+ category: "interactive",
376
+ schema: z.object({
377
+ equation: z.string().optional(),
378
+ xRange: z.tuple([z.number(), z.number()]).optional(),
379
+ a: z.number().optional(),
380
+ b: z.number().optional(),
381
+ n: z.number().optional(),
382
+ title: z.string().optional()
383
+ }),
384
+ Component: ({ attributes, mode, updateAttributes }) => {
385
+ const equation = typeof attributes.equation === "string" && attributes.equation.trim() ? attributes.equation : "0.4*x^2 + 0.5";
386
+ const xRange = attributes.xRange ?? [-1, 4];
387
+ const title = attributes.title ?? "The integral is an area";
388
+ const widget = /* @__PURE__ */ jsx(IntegralExplorer, {
389
+ equation,
390
+ xRange,
391
+ a: attributes.a,
392
+ b: attributes.b,
393
+ n: attributes.n,
394
+ title
395
+ });
396
+ if (mode !== "editing" || !updateAttributes) return widget;
397
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
398
+ /* @__PURE__ */ jsx(ConfigRow, {
399
+ label: "Title",
400
+ children: /* @__PURE__ */ jsx(TextField, {
401
+ value: title,
402
+ onChange: (v) => updateAttributes({ title: v }),
403
+ className: "flex-1"
404
+ })
405
+ }),
406
+ /* @__PURE__ */ jsx(ConfigRow, {
407
+ label: "f(x) =",
408
+ children: /* @__PURE__ */ jsx(TextField, {
409
+ value: equation,
410
+ mono: true,
411
+ placeholder: "0.4*x^2 + 0.5",
412
+ onChange: (v) => updateAttributes({ equation: v }),
413
+ className: "flex-1"
414
+ })
415
+ }),
416
+ /* @__PURE__ */ jsxs(ConfigRow, {
417
+ label: "x window",
418
+ children: [
419
+ /* @__PURE__ */ jsx(NumField, {
420
+ value: xRange[0],
421
+ onChange: (v) => updateAttributes({ xRange: [v, xRange[1]] })
422
+ }),
423
+ /* @__PURE__ */ jsx("span", {
424
+ className: "text-muted-foreground",
425
+ children: "to"
426
+ }),
427
+ /* @__PURE__ */ jsx(NumField, {
428
+ value: xRange[1],
429
+ onChange: (v) => updateAttributes({ xRange: [xRange[0], v] })
430
+ })
431
+ ]
432
+ })
433
+ ] }), widget] });
434
+ }
435
+ });
436
+ const LimitExplorerBlock = defineBlock({
437
+ key: "limit-explorer",
438
+ void: true,
439
+ label: "Limit explorer",
440
+ description: "Approach x → c from both sides; see the limit even where f(c) is a hole.",
441
+ category: "interactive",
442
+ schema: z.object({
443
+ equation: z.string().optional(),
444
+ xRange: z.tuple([z.number(), z.number()]).optional(),
445
+ c: z.number().optional(),
446
+ title: z.string().optional()
447
+ }),
448
+ Component: ({ attributes, mode, updateAttributes }) => {
449
+ const equation = typeof attributes.equation === "string" && attributes.equation.trim() ? attributes.equation : "(x^2 - 1)/(x - 1)";
450
+ const xRange = attributes.xRange ?? [-1, 3];
451
+ const title = attributes.title ?? "Approaching a limit";
452
+ const widget = /* @__PURE__ */ jsx(LimitExplorer, {
453
+ equation,
454
+ xRange,
455
+ c: attributes.c,
456
+ title
457
+ });
458
+ if (mode !== "editing" || !updateAttributes) return widget;
459
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
460
+ /* @__PURE__ */ jsx(ConfigRow, {
461
+ label: "Title",
462
+ children: /* @__PURE__ */ jsx(TextField, {
463
+ value: title,
464
+ onChange: (v) => updateAttributes({ title: v }),
465
+ className: "flex-1"
466
+ })
467
+ }),
468
+ /* @__PURE__ */ jsx(ConfigRow, {
469
+ label: "f(x) =",
470
+ children: /* @__PURE__ */ jsx(TextField, {
471
+ value: equation,
472
+ mono: true,
473
+ placeholder: "(x^2 - 1)/(x - 1)",
474
+ onChange: (v) => updateAttributes({ equation: v }),
475
+ className: "flex-1"
476
+ })
477
+ }),
478
+ /* @__PURE__ */ jsxs(ConfigRow, {
479
+ label: "x window",
480
+ children: [
481
+ /* @__PURE__ */ jsx(NumField, {
482
+ value: xRange[0],
483
+ onChange: (v) => updateAttributes({ xRange: [v, xRange[1]] })
484
+ }),
485
+ /* @__PURE__ */ jsx("span", {
486
+ className: "text-muted-foreground",
487
+ children: "to"
488
+ }),
489
+ /* @__PURE__ */ jsx(NumField, {
490
+ value: xRange[1],
491
+ onChange: (v) => updateAttributes({ xRange: [xRange[0], v] })
492
+ })
493
+ ]
494
+ })
495
+ ] }), widget] });
496
+ }
497
+ });
498
+ const derivationStepSchema = z.union([z.string(), z.object({
499
+ tex: z.string(),
500
+ note: z.string().optional()
501
+ })]);
502
+ const asSteps = (raw) => {
503
+ if (!Array.isArray(raw)) return [{ tex: "a^2 + b^2 = c^2" }];
504
+ const out = raw.map((s) => typeof s === "string" ? { tex: s } : s).filter((s) => !!s && typeof s.tex === "string");
505
+ return out.length ? out : [{ tex: "a^2 + b^2 = c^2" }];
506
+ };
507
+ const DerivationBlock = defineBlock({
508
+ key: "derivation",
509
+ void: true,
510
+ label: "Derivation (steps)",
511
+ description: "A step-by-step equation derivation in LaTeX, revealed one line at a time.",
512
+ category: "interactive",
513
+ schema: z.object({
514
+ steps: z.array(derivationStepSchema).optional(),
515
+ title: z.string().optional()
516
+ }),
517
+ Component: ({ attributes, mode, updateAttributes }) => {
518
+ const steps = asSteps(attributes.steps);
519
+ const title = attributes.title ?? "Derivation";
520
+ const widget = /* @__PURE__ */ jsx(Derivation, {
521
+ steps,
522
+ title
523
+ });
524
+ if (mode !== "editing" || !updateAttributes) return widget;
525
+ const setStep = (i, patch) => updateAttributes({ steps: steps.map((s, j) => j === i ? {
526
+ ...s,
527
+ ...patch
528
+ } : s) });
529
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [/* @__PURE__ */ jsx(ConfigRow, {
530
+ label: "Title",
531
+ children: /* @__PURE__ */ jsx(TextField, {
532
+ value: title,
533
+ onChange: (v) => updateAttributes({ title: v }),
534
+ className: "flex-1"
535
+ })
536
+ }), /* @__PURE__ */ jsxs("div", {
537
+ className: "space-y-1.5",
538
+ children: [
539
+ /* @__PURE__ */ jsx("span", {
540
+ className: "font-medium text-muted-foreground",
541
+ children: "Steps (LaTeX + optional note)"
542
+ }),
543
+ steps.map((s, i) => /* @__PURE__ */ jsxs("div", {
544
+ className: "flex flex-wrap items-center gap-1.5",
545
+ children: [
546
+ /* @__PURE__ */ jsx("span", {
547
+ className: "font-mono text-muted-foreground",
548
+ children: i + 1
549
+ }),
550
+ /* @__PURE__ */ jsx(TextField, {
551
+ value: s.tex,
552
+ mono: true,
553
+ placeholder: "\\\\frac{y-y_P}{x-x_P} = ...",
554
+ onChange: (v) => setStep(i, { tex: v }),
555
+ className: "min-w-[12rem] flex-1"
556
+ }),
557
+ /* @__PURE__ */ jsx(TextField, {
558
+ value: s.note ?? "",
559
+ placeholder: "why…",
560
+ onChange: (v) => setStep(i, { note: v }),
561
+ className: "w-32"
562
+ }),
563
+ steps.length > 1 && /* @__PURE__ */ jsx(SmallButton, {
564
+ tone: "danger",
565
+ onClick: () => updateAttributes({ steps: steps.filter((_, j) => j !== i) }),
566
+ children: "✕"
567
+ })
568
+ ]
569
+ }, i)),
570
+ /* @__PURE__ */ jsx(SmallButton, {
571
+ onClick: () => updateAttributes({ steps: [...steps, { tex: "" }] }),
572
+ children: "+ step"
573
+ })
574
+ ]
575
+ })] }), widget] });
576
+ }
577
+ });
578
+ function nextParamName(params) {
579
+ const used = new Set(params.map((p) => p.name));
580
+ for (const n of [
581
+ "a",
582
+ "b",
583
+ "c",
584
+ "d",
585
+ "k",
586
+ "m",
587
+ "n",
588
+ "p",
589
+ "q"
590
+ ]) if (!used.has(n)) return n;
591
+ return `p${params.length + 1}`;
592
+ }
593
+ /** System-of-equations render: two clue lines (slope-intercept) from scalar
594
+ * props, so the editor form + MDX stay simple number fields. */
595
+ function LinearSystemView({ m1 = 1, b1 = 1, m2 = -1, b2 = 5 }) {
596
+ return /* @__PURE__ */ jsx(LinearSystemLab, { lines: [{
597
+ m: m1,
598
+ b: b1,
599
+ label: "clue A"
600
+ }, {
601
+ m: m2,
602
+ b: b2,
603
+ label: "clue B"
604
+ }] });
605
+ }
606
+ const LinearSystemBlock = defineBlock({
607
+ key: "linear-system",
608
+ tag: "LinearSystem",
609
+ void: true,
610
+ label: "System of equations (x & y)",
611
+ description: "Two clue lines on a grid — drag to the crossing point that obeys both. The advanced \"find x and y\" lab.",
612
+ category: "interactive",
613
+ schema: z.object({
614
+ m1: z.number().default(1),
615
+ b1: z.number().default(1),
616
+ m2: z.number().default(-1),
617
+ b2: z.number().default(5)
618
+ }),
619
+ Component: ({ attributes, mode, updateAttributes }) => {
620
+ const { m1 = 1, b1 = 1, m2 = -1, b2 = 5 } = attributes;
621
+ const widget = /* @__PURE__ */ jsx(LinearSystemView, {
622
+ m1,
623
+ b1,
624
+ m2,
625
+ b2
626
+ });
627
+ if (mode !== "editing" || !updateAttributes) return widget;
628
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [/* @__PURE__ */ jsxs(ConfigRow, {
629
+ label: "clue A: y =",
630
+ children: [
631
+ /* @__PURE__ */ jsx(NumField, {
632
+ value: m1,
633
+ onChange: (v) => updateAttributes({ m1: v })
634
+ }),
635
+ /* @__PURE__ */ jsx("span", {
636
+ className: "text-muted-foreground",
637
+ children: "x +"
638
+ }),
639
+ /* @__PURE__ */ jsx(NumField, {
640
+ value: b1,
641
+ onChange: (v) => updateAttributes({ b1: v })
642
+ })
643
+ ]
644
+ }), /* @__PURE__ */ jsxs(ConfigRow, {
645
+ label: "clue B: y =",
646
+ children: [
647
+ /* @__PURE__ */ jsx(NumField, {
648
+ value: m2,
649
+ onChange: (v) => updateAttributes({ m2: v })
650
+ }),
651
+ /* @__PURE__ */ jsx("span", {
652
+ className: "text-muted-foreground",
653
+ children: "x +"
654
+ }),
655
+ /* @__PURE__ */ jsx(NumField, {
656
+ value: b2,
657
+ onChange: (v) => updateAttributes({ b2: v })
658
+ })
659
+ ]
660
+ })] }), widget] });
661
+ }
662
+ });
663
+ const NumberLineBlock = defineBlock({
664
+ key: "number-line",
665
+ tag: "NumberLine",
666
+ void: true,
667
+ label: "Number line",
668
+ description: "A draggable marker on a number line (incl. below zero) — optionally pose a target to land on.",
669
+ category: "interactive",
670
+ schema: z.object({
671
+ min: z.number().default(-8),
672
+ max: z.number().default(8),
673
+ start: z.number().default(0),
674
+ target: z.number().optional()
675
+ }),
676
+ Component: ({ attributes, mode, updateAttributes }) => {
677
+ const { min = -8, max = 8, start = 0, target } = attributes;
678
+ const widget = /* @__PURE__ */ jsx(NumberLineLab, {
679
+ min,
680
+ max,
681
+ start,
682
+ target
683
+ });
684
+ if (mode !== "editing" || !updateAttributes) return widget;
685
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
686
+ /* @__PURE__ */ jsx(ConfigRow, {
687
+ label: "from",
688
+ children: /* @__PURE__ */ jsx(NumField, {
689
+ value: min,
690
+ onChange: (v) => updateAttributes({ min: v })
691
+ })
692
+ }),
693
+ /* @__PURE__ */ jsx(ConfigRow, {
694
+ label: "to",
695
+ children: /* @__PURE__ */ jsx(NumField, {
696
+ value: max,
697
+ onChange: (v) => updateAttributes({ max: v })
698
+ })
699
+ }),
700
+ /* @__PURE__ */ jsx(ConfigRow, {
701
+ label: "start",
702
+ children: /* @__PURE__ */ jsx(NumField, {
703
+ value: start,
704
+ onChange: (v) => updateAttributes({ start: v })
705
+ })
706
+ }),
707
+ /* @__PURE__ */ jsx(ConfigRow, {
708
+ label: "target",
709
+ children: /* @__PURE__ */ jsx(NumField, {
710
+ value: target ?? 0,
711
+ onChange: (v) => updateAttributes({ target: v })
712
+ })
713
+ })
714
+ ] }), widget] });
715
+ }
716
+ });
717
+ const MysteryBucketBlock = defineBlock({
718
+ key: "mystery-bucket",
719
+ tag: "MysteryBucket",
720
+ void: true,
721
+ label: "Mystery bucket (weigh the unknown)",
722
+ description: "Essentials opener — add unit weights until a balance is level to discover the hidden weight. No symbols.",
723
+ category: "interactive",
724
+ schema: z.object({
725
+ bucketWeight: z.number().default(5),
726
+ bucketCount: z.number().default(1),
727
+ maxWeights: z.number().default(12),
728
+ start: z.number().default(0)
729
+ }),
730
+ Component: ({ attributes, mode, updateAttributes }) => {
731
+ const { bucketWeight = 5, bucketCount = 1, maxWeights = 12, start = 0 } = attributes;
732
+ const widget = /* @__PURE__ */ jsx(MysteryBucketLab, {
733
+ bucketWeight,
734
+ bucketCount,
735
+ maxWeights,
736
+ start
737
+ });
738
+ if (mode !== "editing" || !updateAttributes) return widget;
739
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
740
+ /* @__PURE__ */ jsx(ConfigRow, {
741
+ label: "weight each",
742
+ children: /* @__PURE__ */ jsx(NumField, {
743
+ value: bucketWeight,
744
+ onChange: (v) => updateAttributes({ bucketWeight: v })
745
+ })
746
+ }),
747
+ /* @__PURE__ */ jsx(ConfigRow, {
748
+ label: "buckets",
749
+ children: /* @__PURE__ */ jsx(NumField, {
750
+ value: bucketCount,
751
+ onChange: (v) => updateAttributes({ bucketCount: v })
752
+ })
753
+ }),
754
+ /* @__PURE__ */ jsx(ConfigRow, {
755
+ label: "max weights",
756
+ children: /* @__PURE__ */ jsx(NumField, {
757
+ value: maxWeights,
758
+ onChange: (v) => updateAttributes({ maxWeights: v })
759
+ })
760
+ }),
761
+ /* @__PURE__ */ jsx(ConfigRow, {
762
+ label: "start at",
763
+ children: /* @__PURE__ */ jsx(NumField, {
764
+ value: start,
765
+ onChange: (v) => updateAttributes({ start: v })
766
+ })
767
+ })
768
+ ] }), widget] });
769
+ }
770
+ });
771
+ const BalanceAlgebraBlock = defineBlock({
772
+ key: "balance-algebra",
773
+ tag: "BalanceAlgebra",
774
+ void: true,
775
+ label: "Balance scale (algebra)",
776
+ description: "Drag x to balance a·x + b = c — learners solve a linear equation by balancing the scale.",
777
+ category: "interactive",
778
+ schema: z.object({
779
+ coef: z.number().default(2),
780
+ addend: z.number().default(1),
781
+ rhs: z.number().default(7),
782
+ answer: z.number().default(3),
783
+ controlId: z.string().optional()
784
+ }),
785
+ Component: ({ attributes, mode, updateAttributes }) => {
786
+ const { coef = 2, addend = 1, rhs = 7, answer = 3 } = attributes;
787
+ const widget = /* @__PURE__ */ jsx(BalanceAlgebraLab, {
788
+ coef,
789
+ addend,
790
+ rhs,
791
+ answer,
792
+ controlId: attributes.controlId
793
+ });
794
+ if (mode !== "editing" || !updateAttributes) return widget;
795
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
796
+ /* @__PURE__ */ jsx(ConfigRow, {
797
+ label: "coefficient a",
798
+ children: /* @__PURE__ */ jsx(NumField, {
799
+ value: coef,
800
+ onChange: (v) => updateAttributes({ coef: v })
801
+ })
802
+ }),
803
+ /* @__PURE__ */ jsx(ConfigRow, {
804
+ label: "addend b",
805
+ children: /* @__PURE__ */ jsx(NumField, {
806
+ value: addend,
807
+ onChange: (v) => updateAttributes({ addend: v })
808
+ })
809
+ }),
810
+ /* @__PURE__ */ jsx(ConfigRow, {
811
+ label: "right side c",
812
+ children: /* @__PURE__ */ jsx(NumField, {
813
+ value: rhs,
814
+ onChange: (v) => updateAttributes({ rhs: v })
815
+ })
816
+ }),
817
+ /* @__PURE__ */ jsx(ConfigRow, {
818
+ label: "answer x",
819
+ children: /* @__PURE__ */ jsx(NumField, {
820
+ value: answer,
821
+ onChange: (v) => updateAttributes({ answer: v })
822
+ })
823
+ })
824
+ ] }), widget] });
825
+ }
826
+ });
827
+ const VertexParabolaBlock = defineBlock({
828
+ key: "vertex-parabola",
829
+ tag: "VertexParabola",
830
+ void: true,
831
+ label: "Parabola (drag the vertex)",
832
+ description: "Drag the vertex of y = a(x−h)² + k; the curve + equation update live.",
833
+ category: "interactive",
834
+ schema: z.object({ a: z.number().default(1) }),
835
+ Component: ({ attributes, mode, updateAttributes }) => {
836
+ const { a = 1 } = attributes;
837
+ const widget = /* @__PURE__ */ jsx(VertexParabolaLab, { a });
838
+ if (mode !== "editing" || !updateAttributes) return widget;
839
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(ConfigPanel, { children: /* @__PURE__ */ jsx(ConfigRow, {
840
+ label: "stretch a",
841
+ children: /* @__PURE__ */ jsx(NumField, {
842
+ value: a,
843
+ onChange: (v) => updateAttributes({ a: v })
844
+ })
845
+ }) }), widget] });
846
+ }
847
+ });
848
+ const AreaModelBlock = defineBlock({
849
+ key: "area-model",
850
+ tag: "AreaModel",
851
+ void: true,
852
+ label: "Area model (algebra tiles)",
853
+ description: "(x+a)(x+b) as a partitioned rectangle — EXPAND (drag x) or FACTOR (find a, b).",
854
+ category: "interactive",
855
+ schema: z.object({
856
+ a: z.number().default(3),
857
+ b: z.number().default(2),
858
+ mode: z.enum(["expand", "factor"]).default("expand"),
859
+ controlId: z.string().optional()
860
+ }),
861
+ Component: ({ attributes, mode, updateAttributes }) => {
862
+ const { a = 3, b = 2, mode: m = "expand" } = attributes;
863
+ const widget = /* @__PURE__ */ jsx(AreaModelLab, {
864
+ a,
865
+ b,
866
+ mode: m,
867
+ controlId: attributes.controlId
868
+ });
869
+ if (mode !== "editing" || !updateAttributes) return widget;
870
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
871
+ /* @__PURE__ */ jsx(ConfigRow, {
872
+ label: "a in (x+a)",
873
+ children: /* @__PURE__ */ jsx(NumField, {
874
+ value: a,
875
+ onChange: (v) => updateAttributes({ a: v })
876
+ })
877
+ }),
878
+ /* @__PURE__ */ jsx(ConfigRow, {
879
+ label: "b in (x+b)",
880
+ children: /* @__PURE__ */ jsx(NumField, {
881
+ value: b,
882
+ onChange: (v) => updateAttributes({ b: v })
883
+ })
884
+ }),
885
+ /* @__PURE__ */ jsxs(ConfigRow, {
886
+ label: "mode",
887
+ children: [/* @__PURE__ */ jsx(ChipToggle, {
888
+ active: m !== "factor",
889
+ onClick: () => updateAttributes({ mode: "expand" }),
890
+ children: "expand"
891
+ }), /* @__PURE__ */ jsx(ChipToggle, {
892
+ active: m === "factor",
893
+ onClick: () => updateAttributes({ mode: "factor" }),
894
+ children: "factor"
895
+ })]
896
+ })
897
+ ] }), widget] });
898
+ }
899
+ });
900
+ const GrowingPatternBlock = defineBlock({
901
+ key: "growing-pattern",
902
+ tag: "GrowingPattern",
903
+ void: true,
904
+ label: "Pattern → formula",
905
+ description: "A figure grows by a·n + b; learners find the rule (hidden predict row forces extrapolation).",
906
+ category: "interactive",
907
+ schema: z.object({
908
+ a: z.number().default(2),
909
+ b: z.number().default(3),
910
+ steps: z.number().default(4),
911
+ controlId: z.string().optional()
912
+ }),
913
+ Component: ({ attributes, mode, updateAttributes }) => {
914
+ const { a = 2, b = 3, steps = 4 } = attributes;
915
+ const widget = /* @__PURE__ */ jsx(GrowingPatternLab, {
916
+ a,
917
+ b,
918
+ steps,
919
+ controlId: attributes.controlId
920
+ });
921
+ if (mode !== "editing" || !updateAttributes) return widget;
922
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
923
+ /* @__PURE__ */ jsx(ConfigRow, {
924
+ label: "per step a",
925
+ children: /* @__PURE__ */ jsx(NumField, {
926
+ value: a,
927
+ onChange: (v) => updateAttributes({ a: v })
928
+ })
929
+ }),
930
+ /* @__PURE__ */ jsx(ConfigRow, {
931
+ label: "constant b",
932
+ children: /* @__PURE__ */ jsx(NumField, {
933
+ value: b,
934
+ onChange: (v) => updateAttributes({ b: v })
935
+ })
936
+ }),
937
+ /* @__PURE__ */ jsx(ConfigRow, {
938
+ label: "figures shown",
939
+ children: /* @__PURE__ */ jsx(NumField, {
940
+ value: steps,
941
+ onChange: (v) => updateAttributes({ steps: v })
942
+ })
943
+ })
944
+ ] }), widget] });
945
+ }
946
+ });
947
+ const answerSchema = z.union([z.object({
948
+ kind: z.literal("number"),
949
+ value: z.number(),
950
+ tol: z.number().optional()
951
+ }), z.object({
952
+ kind: z.literal("expression"),
953
+ value: z.string()
954
+ })]);
955
+ const askSchema = z.object({
956
+ prompt: z.string(),
957
+ answer: answerSchema,
958
+ placeholder: z.string().optional()
959
+ });
960
+ const deriveSchema = z.object({
961
+ kind: z.enum([
962
+ "intersections",
963
+ "roots",
964
+ "tangent",
965
+ "normal",
966
+ "area"
967
+ ]),
968
+ of: z.union([z.number(), z.tuple([z.number(), z.number()])]).optional(),
969
+ at: z.union([z.number(), z.string()]).optional(),
970
+ between: z.tuple([z.number(), z.number()]).optional(),
971
+ from: z.union([z.number(), z.string()]).optional(),
972
+ to: z.union([z.number(), z.string()]).optional(),
973
+ label: z.string().optional()
974
+ });
975
+ const DERIVE_KINDS = [
976
+ "intersections",
977
+ "roots",
978
+ "tangent",
979
+ "normal",
980
+ "area"
981
+ ];
982
+ /** Shared "ask + check" authoring row, used by the engine and representation blocks. */
983
+ function AskEditor({ ask, onChange }) {
984
+ if (!ask) return /* @__PURE__ */ jsx(SmallButton, {
985
+ onClick: () => onChange({
986
+ prompt: "",
987
+ answer: {
988
+ kind: "number",
989
+ value: 0
990
+ }
991
+ }),
992
+ children: "+ question (checked answer)"
993
+ });
994
+ const isNum = ask.answer.kind === "number";
995
+ const setAns = (patch) => onChange({
996
+ ...ask,
997
+ answer: {
998
+ ...ask.answer,
999
+ ...patch
1000
+ }
1001
+ });
1002
+ return /* @__PURE__ */ jsxs("div", {
1003
+ className: "space-y-1.5",
1004
+ children: [
1005
+ /* @__PURE__ */ jsx("span", {
1006
+ className: "font-medium text-muted-foreground",
1007
+ children: "Question (graded)"
1008
+ }),
1009
+ /* @__PURE__ */ jsx(ConfigRow, {
1010
+ label: "Prompt",
1011
+ children: /* @__PURE__ */ jsx(TextField, {
1012
+ value: ask.prompt,
1013
+ onChange: (v) => onChange({
1014
+ ...ask,
1015
+ prompt: v
1016
+ }),
1017
+ className: "flex-1"
1018
+ })
1019
+ }),
1020
+ /* @__PURE__ */ jsxs(ConfigRow, {
1021
+ label: "Answer is",
1022
+ children: [/* @__PURE__ */ jsx(ChipToggle, {
1023
+ active: isNum,
1024
+ onClick: () => setAns({
1025
+ kind: "number",
1026
+ value: typeof ask.answer.value === "number" ? ask.answer.value : 0
1027
+ }),
1028
+ children: "a number"
1029
+ }), /* @__PURE__ */ jsx(ChipToggle, {
1030
+ active: !isNum,
1031
+ onClick: () => setAns({
1032
+ kind: "expression",
1033
+ value: String(ask.answer.value ?? "")
1034
+ }),
1035
+ children: "an expression"
1036
+ })]
1037
+ }),
1038
+ /* @__PURE__ */ jsxs(ConfigRow, {
1039
+ label: "Correct value",
1040
+ children: [
1041
+ isNum ? /* @__PURE__ */ jsx(NumField, {
1042
+ value: Number(ask.answer.value) || 0,
1043
+ onChange: (v) => setAns({ value: v })
1044
+ }) : /* @__PURE__ */ jsx(TextField, {
1045
+ value: String(ask.answer.value ?? ""),
1046
+ mono: true,
1047
+ placeholder: "6*x - 9",
1048
+ onChange: (v) => setAns({ value: v }),
1049
+ className: "flex-1"
1050
+ }),
1051
+ isNum && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
1052
+ className: "text-muted-foreground",
1053
+ children: "± tol"
1054
+ }), /* @__PURE__ */ jsx(NumField, {
1055
+ value: ask.answer.tol ?? .01,
1056
+ onChange: (v) => setAns({ tol: v })
1057
+ })] }),
1058
+ /* @__PURE__ */ jsx(SmallButton, {
1059
+ tone: "danger",
1060
+ onClick: () => onChange(void 0),
1061
+ children: "remove"
1062
+ })
1063
+ ]
1064
+ })
1065
+ ]
1066
+ });
1067
+ }
1068
+ const InteractiveProblemBlock = defineBlock({
1069
+ key: "interactive-problem",
1070
+ void: true,
1071
+ label: "Interactive problem (engine)",
1072
+ description: "Author equations + sliders, derive roots/intersections/tangent/normal/area, and grade a typed answer — no code.",
1073
+ category: "interactive",
1074
+ schema: z.object({
1075
+ equations: z.array(equationSchema).optional(),
1076
+ params: z.array(paramSchema).optional(),
1077
+ xRange: z.tuple([z.number(), z.number()]).optional(),
1078
+ yRange: z.union([z.tuple([z.number(), z.number()]), z.literal("auto")]).optional(),
1079
+ derive: z.array(deriveSchema).optional(),
1080
+ ask: askSchema.optional(),
1081
+ title: z.string().optional(),
1082
+ prompt: z.string().optional(),
1083
+ activity: z.string().optional()
1084
+ }),
1085
+ Component: ({ attributes, mode, updateAttributes }) => {
1086
+ const equations = asExprStrings(attributes.equations);
1087
+ const params = asParams(attributes.params);
1088
+ const xRange = attributes.xRange ?? [-6.5, 6.5];
1089
+ const yRange = attributes.yRange ?? "auto";
1090
+ const derive = Array.isArray(attributes.derive) ? attributes.derive : [];
1091
+ const ask = attributes.ask;
1092
+ const widget = /* @__PURE__ */ jsx(InteractiveProblem, {
1093
+ equations,
1094
+ params,
1095
+ xRange,
1096
+ yRange,
1097
+ derive,
1098
+ ask,
1099
+ title: attributes.title ?? "Interactive problem",
1100
+ prompt: attributes.prompt,
1101
+ activity: attributes.activity ?? "interactive-problem"
1102
+ });
1103
+ if (mode !== "editing" || !updateAttributes) return widget;
1104
+ const upd = updateAttributes;
1105
+ const setEq = (i, v) => updateAttributes({ equations: equations.map((e, j) => j === i ? v : e) });
1106
+ const setParam = (i, patch) => updateAttributes({ params: params.map((p, j) => j === i ? {
1107
+ ...p,
1108
+ ...patch
1109
+ } : p) });
1110
+ const setDerive = (i, patch) => upd({ derive: derive.map((d, j) => j === i ? {
1111
+ ...d,
1112
+ ...patch
1113
+ } : d) });
1114
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
1115
+ /* @__PURE__ */ jsx(ConfigRow, {
1116
+ label: "Title",
1117
+ children: /* @__PURE__ */ jsx(TextField, {
1118
+ value: attributes.title ?? "",
1119
+ placeholder: "Interactive problem",
1120
+ onChange: (v) => updateAttributes({ title: v }),
1121
+ className: "flex-1"
1122
+ })
1123
+ }),
1124
+ /* @__PURE__ */ jsx(ConfigRow, {
1125
+ label: "Prompt",
1126
+ children: /* @__PURE__ */ jsx(TextField, {
1127
+ value: attributes.prompt ?? "",
1128
+ placeholder: "what the learner does",
1129
+ onChange: (v) => updateAttributes({ prompt: v }),
1130
+ className: "flex-1"
1131
+ })
1132
+ }),
1133
+ /* @__PURE__ */ jsxs("div", {
1134
+ className: "space-y-1.5",
1135
+ children: [
1136
+ /* @__PURE__ */ jsx("span", {
1137
+ className: "font-medium text-muted-foreground",
1138
+ children: "Equations (use x and your slider names)"
1139
+ }),
1140
+ equations.map((eq, i) => /* @__PURE__ */ jsxs("div", {
1141
+ className: "flex items-center gap-2",
1142
+ children: [
1143
+ /* @__PURE__ */ jsxs("span", {
1144
+ className: "font-mono text-muted-foreground",
1145
+ children: [i, ": y ="]
1146
+ }),
1147
+ /* @__PURE__ */ jsx(TextField, {
1148
+ value: eq,
1149
+ mono: true,
1150
+ placeholder: "abs(p*x - q)",
1151
+ onChange: (v) => setEq(i, v),
1152
+ className: "flex-1"
1153
+ }),
1154
+ equations.length > 1 && /* @__PURE__ */ jsx(SmallButton, {
1155
+ tone: "danger",
1156
+ onClick: () => updateAttributes({ equations: equations.filter((_, j) => j !== i) }),
1157
+ children: "✕"
1158
+ })
1159
+ ]
1160
+ }, i)),
1161
+ /* @__PURE__ */ jsx(SmallButton, {
1162
+ onClick: () => updateAttributes({ equations: [...equations, ""] }),
1163
+ children: "+ equation"
1164
+ })
1165
+ ]
1166
+ }),
1167
+ /* @__PURE__ */ jsxs("div", {
1168
+ className: "space-y-1.5",
1169
+ children: [
1170
+ /* @__PURE__ */ jsx("span", {
1171
+ className: "font-medium text-muted-foreground",
1172
+ children: "Sliders (learner-draggable)"
1173
+ }),
1174
+ params.map((p, i) => /* @__PURE__ */ jsxs("div", {
1175
+ className: "flex flex-wrap items-center gap-1.5",
1176
+ children: [
1177
+ /* @__PURE__ */ jsx(TextField, {
1178
+ value: p.name,
1179
+ mono: true,
1180
+ placeholder: "k",
1181
+ onChange: (v) => setParam(i, { name: v }),
1182
+ className: "w-14"
1183
+ }),
1184
+ /* @__PURE__ */ jsx("span", {
1185
+ className: "text-muted-foreground",
1186
+ children: "from"
1187
+ }),
1188
+ /* @__PURE__ */ jsx(NumField, {
1189
+ value: p.min,
1190
+ onChange: (v) => setParam(i, { min: v })
1191
+ }),
1192
+ /* @__PURE__ */ jsx("span", {
1193
+ className: "text-muted-foreground",
1194
+ children: "to"
1195
+ }),
1196
+ /* @__PURE__ */ jsx(NumField, {
1197
+ value: p.max,
1198
+ onChange: (v) => setParam(i, { max: v })
1199
+ }),
1200
+ /* @__PURE__ */ jsx("span", {
1201
+ className: "text-muted-foreground",
1202
+ children: "="
1203
+ }),
1204
+ /* @__PURE__ */ jsx(NumField, {
1205
+ value: p.value,
1206
+ onChange: (v) => setParam(i, { value: v })
1207
+ }),
1208
+ /* @__PURE__ */ jsx(SmallButton, {
1209
+ tone: "danger",
1210
+ onClick: () => updateAttributes({ params: params.filter((_, j) => j !== i) }),
1211
+ children: "✕"
1212
+ })
1213
+ ]
1214
+ }, i)),
1215
+ /* @__PURE__ */ jsx(SmallButton, {
1216
+ onClick: () => updateAttributes({ params: [...params, {
1217
+ name: nextParamName(params),
1218
+ min: 0,
1219
+ max: 10,
1220
+ value: 1,
1221
+ step: 1
1222
+ }] }),
1223
+ children: "+ slider"
1224
+ })
1225
+ ]
1226
+ }),
1227
+ /* @__PURE__ */ jsxs("div", {
1228
+ className: "space-y-1.5",
1229
+ children: [
1230
+ /* @__PURE__ */ jsx("span", {
1231
+ className: "font-medium text-muted-foreground",
1232
+ children: "Derive (computed + drawn live)"
1233
+ }),
1234
+ derive.map((d, i) => {
1235
+ const kind = String(d.kind ?? "intersections");
1236
+ const ofA = Array.isArray(d.of) ? Number(d.of[0]) : Number(d.of ?? 0);
1237
+ const ofB = Array.isArray(d.of) ? Number(d.of[1] ?? 1) : 1;
1238
+ return /* @__PURE__ */ jsxs("div", {
1239
+ className: "flex flex-wrap items-center gap-1.5",
1240
+ children: [
1241
+ /* @__PURE__ */ jsx(SelectField, {
1242
+ value: kind,
1243
+ options: DERIVE_KINDS,
1244
+ onChange: (v) => setDerive(i, { kind: v })
1245
+ }),
1246
+ kind === "intersections" && /* @__PURE__ */ jsxs(Fragment, { children: [
1247
+ /* @__PURE__ */ jsx("span", {
1248
+ className: "text-muted-foreground",
1249
+ children: "of eq"
1250
+ }),
1251
+ /* @__PURE__ */ jsx(NumField, {
1252
+ value: ofA,
1253
+ onChange: (v) => setDerive(i, { of: [v, ofB] })
1254
+ }),
1255
+ /* @__PURE__ */ jsx("span", {
1256
+ className: "text-muted-foreground",
1257
+ children: "&"
1258
+ }),
1259
+ /* @__PURE__ */ jsx(NumField, {
1260
+ value: ofB,
1261
+ onChange: (v) => setDerive(i, { of: [ofA, v] })
1262
+ })
1263
+ ] }),
1264
+ kind === "roots" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
1265
+ className: "text-muted-foreground",
1266
+ children: "of eq"
1267
+ }), /* @__PURE__ */ jsx(NumField, {
1268
+ value: Number(d.of ?? 0),
1269
+ onChange: (v) => setDerive(i, { of: v })
1270
+ })] }),
1271
+ (kind === "tangent" || kind === "normal") && /* @__PURE__ */ jsxs(Fragment, { children: [
1272
+ /* @__PURE__ */ jsx("span", {
1273
+ className: "text-muted-foreground",
1274
+ children: "of eq"
1275
+ }),
1276
+ /* @__PURE__ */ jsx(NumField, {
1277
+ value: Number(d.of ?? 0),
1278
+ onChange: (v) => setDerive(i, { of: v })
1279
+ }),
1280
+ /* @__PURE__ */ jsx("span", {
1281
+ className: "text-muted-foreground",
1282
+ children: "at x"
1283
+ }),
1284
+ /* @__PURE__ */ jsx(TextField, {
1285
+ value: String(d.at ?? ""),
1286
+ mono: true,
1287
+ placeholder: "2 or a param",
1288
+ onChange: (v) => setDerive(i, { at: /^-?\d*\.?\d+$/.test(v) ? Number(v) : v }),
1289
+ className: "w-20"
1290
+ })
1291
+ ] }),
1292
+ kind === "area" && /* @__PURE__ */ jsxs(Fragment, { children: [
1293
+ /* @__PURE__ */ jsx("span", {
1294
+ className: "text-muted-foreground",
1295
+ children: "eqs"
1296
+ }),
1297
+ /* @__PURE__ */ jsx(NumField, {
1298
+ value: Array.isArray(d.between) ? Number(d.between[0]) : 0,
1299
+ onChange: (v) => setDerive(i, { between: [v, Array.isArray(d.between) ? Number(d.between[1] ?? 1) : 1] })
1300
+ }),
1301
+ /* @__PURE__ */ jsx(NumField, {
1302
+ value: Array.isArray(d.between) ? Number(d.between[1] ?? 1) : 1,
1303
+ onChange: (v) => setDerive(i, { between: [Array.isArray(d.between) ? Number(d.between[0]) : 0, v] })
1304
+ })
1305
+ ] }),
1306
+ /* @__PURE__ */ jsx(SmallButton, {
1307
+ tone: "danger",
1308
+ onClick: () => upd({ derive: derive.filter((_, j) => j !== i) }),
1309
+ children: "✕"
1310
+ })
1311
+ ]
1312
+ }, i);
1313
+ }),
1314
+ /* @__PURE__ */ jsx(SmallButton, {
1315
+ onClick: () => upd({ derive: [...derive, {
1316
+ kind: "intersections",
1317
+ of: [0, 1]
1318
+ }] }),
1319
+ children: "+ derive"
1320
+ })
1321
+ ]
1322
+ }),
1323
+ /* @__PURE__ */ jsxs(ConfigRow, {
1324
+ label: "x window",
1325
+ children: [
1326
+ /* @__PURE__ */ jsx(NumField, {
1327
+ value: xRange[0],
1328
+ onChange: (v) => updateAttributes({ xRange: [v, xRange[1]] })
1329
+ }),
1330
+ /* @__PURE__ */ jsx("span", {
1331
+ className: "text-muted-foreground",
1332
+ children: "to"
1333
+ }),
1334
+ /* @__PURE__ */ jsx(NumField, {
1335
+ value: xRange[1],
1336
+ onChange: (v) => updateAttributes({ xRange: [xRange[0], v] })
1337
+ })
1338
+ ]
1339
+ }),
1340
+ /* @__PURE__ */ jsxs(ConfigRow, {
1341
+ label: "y window",
1342
+ children: [
1343
+ /* @__PURE__ */ jsx(ChipToggle, {
1344
+ active: yRange === "auto",
1345
+ onClick: () => updateAttributes({ yRange: "auto" }),
1346
+ children: "auto"
1347
+ }),
1348
+ /* @__PURE__ */ jsx(ChipToggle, {
1349
+ active: yRange !== "auto",
1350
+ onClick: () => updateAttributes({ yRange: yRange === "auto" ? [-10, 10] : yRange }),
1351
+ children: "fixed"
1352
+ }),
1353
+ yRange !== "auto" && /* @__PURE__ */ jsxs(Fragment, { children: [
1354
+ /* @__PURE__ */ jsx(NumField, {
1355
+ value: yRange[0],
1356
+ onChange: (v) => updateAttributes({ yRange: [v, yRange[1]] })
1357
+ }),
1358
+ /* @__PURE__ */ jsx("span", {
1359
+ className: "text-muted-foreground",
1360
+ children: "to"
1361
+ }),
1362
+ /* @__PURE__ */ jsx(NumField, {
1363
+ value: yRange[1],
1364
+ onChange: (v) => updateAttributes({ yRange: [yRange[0], v] })
1365
+ })
1366
+ ] })
1367
+ ]
1368
+ }),
1369
+ /* @__PURE__ */ jsx(AskEditor, {
1370
+ ask,
1371
+ onChange: (a) => upd({ ask: a })
1372
+ })
1373
+ ] }), widget] });
1374
+ }
1375
+ });
1376
+ const TriangleTrigBlock = defineBlock({
1377
+ key: "triangle-trig",
1378
+ void: true,
1379
+ label: "Triangle trig (elevation/depression)",
1380
+ description: "A right triangle for elevation/depression: give an angle + one side, solve the rest, grade a typed answer.",
1381
+ category: "interactive",
1382
+ schema: z.object({
1383
+ angleDeg: z.number().optional(),
1384
+ leg: z.number().optional(),
1385
+ legKind: z.enum(["opposite", "adjacent"]).optional(),
1386
+ mode: z.enum([
1387
+ "elevation",
1388
+ "depression",
1389
+ "plain"
1390
+ ]).optional(),
1391
+ labels: z.object({
1392
+ opposite: z.string().optional(),
1393
+ adjacent: z.string().optional(),
1394
+ hypotenuse: z.string().optional(),
1395
+ angle: z.string().optional()
1396
+ }).optional(),
1397
+ drive: z.array(z.enum(["angle", "leg"])).optional(),
1398
+ ask: askSchema.optional(),
1399
+ title: z.string().optional(),
1400
+ prompt: z.string().optional(),
1401
+ activity: z.string().optional()
1402
+ }),
1403
+ Component: ({ attributes, mode, updateAttributes }) => {
1404
+ const a = attributes;
1405
+ const drive = Array.isArray(a.drive) ? a.drive : ["angle"];
1406
+ const labels = a.labels ?? {};
1407
+ const ask = attributes.ask;
1408
+ const widget = /* @__PURE__ */ jsx(TriangleTrig, {
1409
+ ...a,
1410
+ drive,
1411
+ ask
1412
+ });
1413
+ if (mode !== "editing" || !updateAttributes) return widget;
1414
+ const upd = updateAttributes;
1415
+ const toggleDrive = (k) => updateAttributes({ drive: drive.includes(k) ? drive.filter((d) => d !== k) : [...drive, k] });
1416
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
1417
+ /* @__PURE__ */ jsx(ConfigRow, {
1418
+ label: "Title",
1419
+ children: /* @__PURE__ */ jsx(TextField, {
1420
+ value: a.title ?? "",
1421
+ placeholder: "Angle of depression…",
1422
+ onChange: (v) => updateAttributes({ title: v }),
1423
+ className: "flex-1"
1424
+ })
1425
+ }),
1426
+ /* @__PURE__ */ jsx(ConfigRow, {
1427
+ label: "Angle θ (°)",
1428
+ children: /* @__PURE__ */ jsx(NumField, {
1429
+ value: a.angleDeg ?? 31,
1430
+ onChange: (v) => updateAttributes({ angleDeg: v })
1431
+ })
1432
+ }),
1433
+ /* @__PURE__ */ jsxs(ConfigRow, {
1434
+ label: "Given leg",
1435
+ children: [/* @__PURE__ */ jsx(NumField, {
1436
+ value: a.leg ?? 15,
1437
+ onChange: (v) => updateAttributes({ leg: v })
1438
+ }), /* @__PURE__ */ jsx(SelectField, {
1439
+ value: a.legKind ?? "opposite",
1440
+ options: ["opposite", "adjacent"],
1441
+ onChange: (v) => upd({ legKind: v })
1442
+ })]
1443
+ }),
1444
+ /* @__PURE__ */ jsx(ConfigRow, {
1445
+ label: "Framing",
1446
+ children: /* @__PURE__ */ jsx(SelectField, {
1447
+ value: a.mode ?? "depression",
1448
+ options: [
1449
+ "depression",
1450
+ "elevation",
1451
+ "plain"
1452
+ ],
1453
+ onChange: (v) => upd({ mode: v })
1454
+ })
1455
+ }),
1456
+ /* @__PURE__ */ jsxs(ConfigRow, {
1457
+ label: "Labels",
1458
+ children: [/* @__PURE__ */ jsx(TextField, {
1459
+ value: labels.opposite ?? "",
1460
+ placeholder: "opposite",
1461
+ onChange: (v) => updateAttributes({ labels: {
1462
+ ...labels,
1463
+ opposite: v
1464
+ } }),
1465
+ className: "w-24"
1466
+ }), /* @__PURE__ */ jsx(TextField, {
1467
+ value: labels.adjacent ?? "",
1468
+ placeholder: "adjacent",
1469
+ onChange: (v) => updateAttributes({ labels: {
1470
+ ...labels,
1471
+ adjacent: v
1472
+ } }),
1473
+ className: "w-24"
1474
+ })]
1475
+ }),
1476
+ /* @__PURE__ */ jsxs(ConfigRow, {
1477
+ label: "Draggable",
1478
+ children: [/* @__PURE__ */ jsx(ChipToggle, {
1479
+ active: drive.includes("angle"),
1480
+ onClick: () => toggleDrive("angle"),
1481
+ children: "angle"
1482
+ }), /* @__PURE__ */ jsx(ChipToggle, {
1483
+ active: drive.includes("leg"),
1484
+ onClick: () => toggleDrive("leg"),
1485
+ children: "given leg"
1486
+ })]
1487
+ }),
1488
+ /* @__PURE__ */ jsx(AskEditor, {
1489
+ ask,
1490
+ onChange: (a2) => upd({ ask: a2 })
1491
+ })
1492
+ ] }), widget] });
1493
+ }
1494
+ });
1495
+ /** All math labs blocks — spread into a host's `defineBlock` list. */
1496
+ const mathBlocks = [
1497
+ TrigExplorerBlock,
1498
+ GraphBlock,
1499
+ DerivativeExplorerBlock,
1500
+ GradientDescentBlock,
1501
+ IntegralExplorerBlock,
1502
+ LimitExplorerBlock,
1503
+ DerivationBlock,
1504
+ LinearSystemBlock,
1505
+ NumberLineBlock,
1506
+ MysteryBucketBlock,
1507
+ BalanceAlgebraBlock,
1508
+ VertexParabolaBlock,
1509
+ AreaModelBlock,
1510
+ GrowingPatternBlock,
1511
+ InteractiveProblemBlock,
1512
+ TriangleTrigBlock
1513
+ ];
1514
+ /** The MDX tag → component render map slice for the math domain. */
1515
+ const mathComponents = {
1516
+ MysteryBucket: MysteryBucketLab,
1517
+ NumberLine: NumberLineLab,
1518
+ LinearSystem: LinearSystemView,
1519
+ BalanceAlgebra: BalanceAlgebraLab,
1520
+ VertexParabola: VertexParabolaLab,
1521
+ AreaModel: AreaModelLab,
1522
+ GrowingPattern: GrowingPatternLab,
1523
+ FunctionMachine: FunctionMachineLab,
1524
+ Graph: Grapher,
1525
+ DerivativeExplorer,
1526
+ IntegralExplorer,
1527
+ LimitExplorer,
1528
+ GradientDescent,
1529
+ Derivation,
1530
+ TrigExplorer,
1531
+ InteractiveProblem,
1532
+ TriangleTrig
1533
+ };
1534
+
1535
+ //#endregion
1536
+ export { AreaModelBlock, BalanceAlgebraBlock, DerivationBlock, DerivativeExplorerBlock, GradientDescentBlock, GraphBlock, GrowingPatternBlock, IntegralExplorerBlock, InteractiveProblemBlock, LimitExplorerBlock, LinearSystemBlock, LinearSystemView, MysteryBucketBlock, NumberLineBlock, TriangleTrigBlock, TrigExplorerBlock, VertexParabolaBlock, mathBlocks, mathComponents };