@classytic/labs 0.1.0 → 0.2.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 (455) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/biology/enzyme-rate/preset.mjs +5 -5
  3. package/dist/biology/genetic-cross/core.d.mts +7 -7
  4. package/dist/biology/genetic-cross/core.mjs +4 -4
  5. package/dist/biology/genetic-cross/grid.mjs +132 -123
  6. package/dist/biology/genetic-cross/preset.mjs +4 -4
  7. package/dist/biology/genetic-cross/sex-linked.mjs +7 -7
  8. package/dist/biology/photosynthesis-factors/preset.mjs +8 -8
  9. package/dist/biology/respiration/preset.mjs +4 -4
  10. package/dist/biology/sequence/central-dogma.mjs +5 -5
  11. package/dist/biology/sequence/core.d.mts +6 -6
  12. package/dist/biology/sequence/core.mjs +1 -1
  13. package/dist/biology/sequence/preset.mjs +6 -6
  14. package/dist/blocks/authoring.mjs +5 -5
  15. package/dist/blocks/biology.d.mts +2 -2
  16. package/dist/blocks/biology.mjs +5 -5
  17. package/dist/blocks/chem.d.mts +2 -2
  18. package/dist/blocks/chem.mjs +13 -13
  19. package/dist/blocks/circuits.d.mts +293 -4
  20. package/dist/blocks/circuits.mjs +874 -9
  21. package/dist/blocks/discrete.d.mts +30 -2
  22. package/dist/blocks/discrete.mjs +74 -4
  23. package/dist/blocks/economics.mjs +1 -1
  24. package/dist/blocks/geography.mjs +1 -1
  25. package/dist/blocks/geometry.mjs +3 -3
  26. package/dist/blocks/ict.d.mts +90 -1
  27. package/dist/blocks/ict.mjs +217 -7
  28. package/dist/blocks/index.d.mts +3064 -657
  29. package/dist/blocks/index.mjs +9 -9
  30. package/dist/blocks/lab-block.mjs +5 -5
  31. package/dist/blocks/lab-config.d.mts +1 -1
  32. package/dist/blocks/lab-config.mjs +4 -4
  33. package/dist/blocks/lab-gallery.d.mts +1 -1
  34. package/dist/blocks/lab-gallery.mjs +2 -2
  35. package/dist/blocks/language.d.mts +6 -6
  36. package/dist/blocks/language.mjs +12 -12
  37. package/dist/blocks/lesson.mjs +4 -4
  38. package/dist/blocks/math.d.mts +577 -11
  39. package/dist/blocks/math.mjs +1648 -14
  40. package/dist/blocks/ml.d.mts +45 -1
  41. package/dist/blocks/ml.mjs +80 -6
  42. package/dist/blocks/physics.d.mts +9 -4
  43. package/dist/blocks/physics.mjs +75 -28
  44. package/dist/blocks/statistics.mjs +1 -1
  45. package/dist/build/CircuitEditor.d.mts +14 -0
  46. package/dist/build/CircuitEditor.mjs +787 -0
  47. package/dist/build/CircuitPlayer.d.mts +19 -0
  48. package/dist/build/CircuitPlayer.mjs +53 -0
  49. package/dist/build/CircuitScene.d.mts +61 -0
  50. package/dist/build/CircuitScene.mjs +383 -0
  51. package/dist/build/contract.d.mts +116 -0
  52. package/dist/build/editor-ops.d.mts +65 -0
  53. package/dist/build/editor-ops.mjs +306 -0
  54. package/dist/build/editor-ui.mjs +121 -0
  55. package/dist/build/flow.d.mts +14 -0
  56. package/dist/build/flow.mjs +119 -0
  57. package/dist/build/index.d.mts +10 -0
  58. package/dist/build/index.mjs +10 -0
  59. package/dist/build/parts/ammeter.d.mts +1 -0
  60. package/dist/build/parts/ammeter.mjs +32 -0
  61. package/dist/build/parts/bulb.d.mts +1 -0
  62. package/dist/build/parts/bulb.mjs +50 -0
  63. package/dist/build/parts/capacitor.d.mts +1 -0
  64. package/dist/build/parts/capacitor.mjs +26 -0
  65. package/dist/build/parts/cell.d.mts +1 -0
  66. package/dist/build/parts/cell.mjs +40 -0
  67. package/dist/build/parts/diode.d.mts +1 -0
  68. package/dist/build/parts/diode.mjs +33 -0
  69. package/dist/build/parts/index.d.mts +5 -0
  70. package/dist/build/parts/index.mjs +43 -0
  71. package/dist/build/parts/mosfet.d.mts +1 -0
  72. package/dist/build/parts/mosfet.mjs +95 -0
  73. package/dist/build/parts/node.d.mts +1 -0
  74. package/dist/build/parts/node.mjs +32 -0
  75. package/dist/build/parts/resistor.d.mts +1 -0
  76. package/dist/build/parts/resistor.mjs +49 -0
  77. package/dist/build/parts/shared.mjs +42 -0
  78. package/dist/build/parts/switch.d.mts +1 -0
  79. package/dist/build/parts/switch.mjs +34 -0
  80. package/dist/build/parts.d.mts +1 -0
  81. package/dist/build/registry.d.mts +9 -0
  82. package/dist/build/registry.mjs +15 -0
  83. package/dist/build/solve.d.mts +8 -0
  84. package/dist/build/solve.mjs +0 -0
  85. package/dist/catalog/registry.d.mts +2 -2
  86. package/dist/catalog/templates.d.mts +1 -1
  87. package/dist/catalog/templates.mjs +6 -6
  88. package/dist/chem/battery.mjs +1 -1
  89. package/dist/chem/bohr-atom.mjs +4 -4
  90. package/dist/chem/diffusion/preset.mjs +4 -4
  91. package/dist/chem/electrochem/preset.mjs +5 -5
  92. package/dist/chem/equilibrium/preset.d.mts +1 -1
  93. package/dist/chem/equilibrium/preset.mjs +6 -6
  94. package/dist/chem/gas-box/preset.mjs +6 -6
  95. package/dist/chem/kinetics/preset.mjs +6 -6
  96. package/dist/chem/periodic-trends/preset.mjs +7 -7
  97. package/dist/chem/reaction-lab.mjs +3 -3
  98. package/dist/chem/reaction-profile.mjs +4 -4
  99. package/dist/chem/solution/dilution.mjs +6 -6
  100. package/dist/chem/solution/field.d.mts +2 -2
  101. package/dist/chem/solution/field.mjs +2 -2
  102. package/dist/chem/solution/solution-box.mjs +7 -7
  103. package/dist/chem/stoichiometry/preset.mjs +5 -5
  104. package/dist/chem/titration/preset.mjs +5 -5
  105. package/dist/circuits/ac-dc/asset.mjs +1 -1
  106. package/dist/circuits/ac-dc/preset.mjs +2 -2
  107. package/dist/circuits/brownout/index.d.mts +1 -0
  108. package/dist/circuits/brownout/preset.d.mts +22 -0
  109. package/dist/circuits/brownout/preset.mjs +399 -0
  110. package/dist/circuits/capacitor-leak/preset.mjs +13 -8
  111. package/dist/circuits/circuit/asset.mjs +71 -14
  112. package/dist/circuits/circuit/preset.mjs +23 -5
  113. package/dist/circuits/circuit-builder.mjs +60 -132
  114. package/dist/circuits/circuit-lab.mjs +60 -40
  115. package/dist/circuits/cmos-gate/index.d.mts +1 -0
  116. package/dist/circuits/cmos-gate/preset.d.mts +75 -0
  117. package/dist/circuits/cmos-gate/preset.mjs +1491 -0
  118. package/dist/circuits/diode/index.d.mts +1 -0
  119. package/dist/circuits/diode/preset.d.mts +25 -0
  120. package/dist/circuits/diode/preset.mjs +266 -0
  121. package/dist/circuits/index.d.mts +7 -1
  122. package/dist/circuits/index.mjs +7 -1
  123. package/dist/circuits/rc-charging/index.d.mts +1 -0
  124. package/dist/circuits/rc-charging/preset.d.mts +27 -0
  125. package/dist/circuits/rc-charging/preset.mjs +329 -0
  126. package/dist/circuits/semiconductor/index.d.mts +1 -0
  127. package/dist/circuits/semiconductor/preset.d.mts +102 -0
  128. package/dist/circuits/semiconductor/preset.mjs +1855 -0
  129. package/dist/circuits/transistor/index.d.mts +1 -0
  130. package/dist/circuits/transistor/preset.d.mts +27 -0
  131. package/dist/circuits/transistor/preset.mjs +329 -0
  132. package/dist/commerce/accounting/core.d.mts +1 -1
  133. package/dist/commerce/accounting/equation-balance.mjs +5 -5
  134. package/dist/commerce/accounting/journal-poster.mjs +8 -8
  135. package/dist/commerce/accounting/statement-sorter.mjs +4 -4
  136. package/dist/commerce/economics/core.d.mts +2 -2
  137. package/dist/commerce/economics/core.mjs +1 -1
  138. package/dist/commerce/economics/demand-shift-vs-move.mjs +6 -6
  139. package/dist/commerce/economics/elasticity-revenue.mjs +6 -6
  140. package/dist/commerce/economics/market-equilibrium.mjs +5 -5
  141. package/dist/core/easing.d.mts +3 -3
  142. package/dist/core/easing.mjs +2 -2
  143. package/dist/core/numeric.d.mts +3 -3
  144. package/dist/core/numeric.mjs +2 -2
  145. package/dist/core/reactive.d.mts +1 -1
  146. package/dist/core/reactive.mjs +1 -1
  147. package/dist/core/rng.d.mts +2 -2
  148. package/dist/core/rng.mjs +1 -1
  149. package/dist/core/tex.mjs +2 -2
  150. package/dist/core/timeline.d.mts +1 -1
  151. package/dist/core/timeline.mjs +1 -1
  152. package/dist/core/util.mjs +11 -1
  153. package/dist/discrete/arrangements/preset.mjs +6 -14
  154. package/dist/discrete/bayes/preset.mjs +43 -35
  155. package/dist/discrete/binomial/preset.mjs +2 -2
  156. package/dist/discrete/combination-studio/figure.d.mts +6 -0
  157. package/dist/discrete/combination-studio/figure.mjs +159 -0
  158. package/dist/discrete/combination-studio/index.d.mts +2 -0
  159. package/dist/discrete/combination-studio/preset.d.mts +44 -0
  160. package/dist/discrete/combination-studio/preset.mjs +440 -0
  161. package/dist/discrete/core/combinatorics.d.mts +23 -3
  162. package/dist/discrete/core/combinatorics.mjs +38 -3
  163. package/dist/discrete/core/pigeonhole.d.mts +1 -1
  164. package/dist/discrete/core/pigeonhole.mjs +1 -1
  165. package/dist/discrete/core/probability.d.mts +3 -3
  166. package/dist/discrete/core/probability.mjs +3 -3
  167. package/dist/discrete/core/sets.d.mts +1 -1
  168. package/dist/discrete/counting-slots/preset.mjs +8 -8
  169. package/dist/discrete/counting-tree/preset.mjs +65 -8
  170. package/dist/discrete/expected-value/preset.mjs +13 -13
  171. package/dist/discrete/hypergeometric/preset.mjs +48 -15
  172. package/dist/discrete/index.d.mts +4 -2
  173. package/dist/discrete/index.mjs +4 -2
  174. package/dist/discrete/karnaugh/preset.mjs +26 -20
  175. package/dist/discrete/lln/preset.mjs +44 -3
  176. package/dist/discrete/logic-circuit/preset.mjs +2 -2
  177. package/dist/discrete/monte-carlo/preset.d.mts +1 -1
  178. package/dist/discrete/monte-carlo/preset.mjs +14 -14
  179. package/dist/discrete/monty-hall/preset.mjs +6 -6
  180. package/dist/discrete/outcome-builder/preset.mjs +3 -3
  181. package/dist/discrete/pascal/preset.mjs +37 -7
  182. package/dist/discrete/rules.d.mts +20 -0
  183. package/dist/discrete/rules.mjs +264 -0
  184. package/dist/discrete/sample-space/preset.mjs +4 -4
  185. package/dist/discrete/selection/preset.mjs +7 -13
  186. package/dist/discrete/truth-table/preset.mjs +32 -9
  187. package/dist/discrete/venn/preset.mjs +71 -48
  188. package/dist/geography/cycle-lab/preset.mjs +17 -10
  189. package/dist/geography/cycles.d.mts +3 -3
  190. package/dist/geography/cycles.mjs +3 -3
  191. package/dist/geometry/board/preset.d.mts +2 -0
  192. package/dist/geometry/board/preset.mjs +11 -15
  193. package/dist/geometry/builder.mjs +3 -3
  194. package/dist/ict/number-systems/base-odometer.mjs +4 -4
  195. package/dist/ict/number-systems/bit-grouper.d.mts +1 -1
  196. package/dist/ict/number-systems/bit-grouper.mjs +4 -4
  197. package/dist/ict/number-systems/place-value-dial.d.mts +1 -1
  198. package/dist/ict/number-systems/place-value-dial.mjs +3 -3
  199. package/dist/ict/number-systems/wheel.d.mts +3 -3
  200. package/dist/ict/number-systems/wheel.mjs +4 -4
  201. package/dist/kit/annotate.mjs +3 -3
  202. package/dist/kit/answer-check.d.mts +2 -2
  203. package/dist/kit/answer-check.mjs +34 -6
  204. package/dist/kit/ask.d.mts +19 -0
  205. package/dist/kit/ask.mjs +46 -0
  206. package/dist/kit/bar-strip.mjs +53 -0
  207. package/dist/kit/calc.d.mts +33 -0
  208. package/dist/kit/calc.mjs +27 -0
  209. package/dist/kit/carrier-engine.mjs +147 -0
  210. package/dist/kit/clue-scene.d.mts +86 -0
  211. package/dist/kit/clue-scene.mjs +424 -0
  212. package/dist/kit/cluster.d.mts +30 -0
  213. package/dist/kit/cluster.mjs +81 -0
  214. package/dist/kit/controls.mjs +11 -5
  215. package/dist/kit/coords.d.mts +88 -0
  216. package/dist/kit/coords.mjs +192 -0
  217. package/dist/kit/data-scene.d.mts +27 -0
  218. package/dist/kit/data-scene.mjs +199 -0
  219. package/dist/kit/diagram.mjs +111 -50
  220. package/dist/kit/electronics.mjs +552 -60
  221. package/dist/kit/expr-analysis.d.mts +18 -6
  222. package/dist/kit/expr-analysis.mjs +82 -28
  223. package/dist/kit/frame.d.mts +3 -3
  224. package/dist/kit/frame.mjs +25 -6
  225. package/dist/kit/gameshow.mjs +2 -2
  226. package/dist/kit/index.d.mts +14 -2
  227. package/dist/kit/index.mjs +13 -1
  228. package/dist/kit/logic-gates.mjs +246 -47
  229. package/dist/kit/palette.mjs +26 -0
  230. package/dist/kit/pedagogy.d.mts +4 -4
  231. package/dist/kit/pedagogy.mjs +21 -17
  232. package/dist/kit/play.d.mts +1 -1
  233. package/dist/kit/play.mjs +3 -3
  234. package/dist/kit/predict.d.mts +55 -0
  235. package/dist/kit/predict.mjs +146 -0
  236. package/dist/kit/receipt.d.mts +29 -0
  237. package/dist/kit/receipt.mjs +94 -0
  238. package/dist/kit/rich.mjs +2 -2
  239. package/dist/kit/rule.d.mts +59 -0
  240. package/dist/kit/rule.mjs +215 -0
  241. package/dist/kit/scale.mjs +1 -1
  242. package/dist/kit/scene-library.d.mts +22 -0
  243. package/dist/kit/scene-library.mjs +311 -0
  244. package/dist/kit/scene-studio.d.mts +14 -0
  245. package/dist/kit/scene-studio.mjs +338 -0
  246. package/dist/kit/scenes.d.mts +31 -0
  247. package/dist/kit/scenes.mjs +569 -0
  248. package/dist/kit/slot-fill.d.mts +61 -0
  249. package/dist/kit/slot-fill.mjs +207 -0
  250. package/dist/kit/solve.d.mts +21 -0
  251. package/dist/kit/solve.mjs +75 -0
  252. package/dist/kit/space.mjs +5 -5
  253. package/dist/kit/steps.mjs +2 -2
  254. package/dist/kit/vessel.d.mts +69 -0
  255. package/dist/kit/vessel.mjs +191 -0
  256. package/dist/language/agreement/preset.mjs +2 -2
  257. package/dist/language/article-lens/preset.d.mts +1 -1
  258. package/dist/language/article-lens/preset.mjs +8 -8
  259. package/dist/language/deck.d.mts +3 -3
  260. package/dist/language/deck.mjs +1 -1
  261. package/dist/language/preposition-scene/preset.d.mts +2 -2
  262. package/dist/language/preposition-scene/preset.mjs +5 -5
  263. package/dist/language/sentence-builder/preset.mjs +5 -5
  264. package/dist/language/transform/preset.d.mts +2 -2
  265. package/dist/language/transform/preset.mjs +5 -5
  266. package/dist/language/ui.d.mts +3 -3
  267. package/dist/language/ui.mjs +4 -4
  268. package/dist/language/word-match/preset.mjs +3 -3
  269. package/dist/logic/LogicBuildLab.d.mts +22 -0
  270. package/dist/logic/LogicBuildLab.mjs +170 -0
  271. package/dist/logic/LogicEditScene.d.mts +31 -0
  272. package/dist/logic/LogicEditScene.mjs +276 -0
  273. package/dist/logic/LogicEditor.d.mts +14 -0
  274. package/dist/logic/LogicEditor.mjs +413 -0
  275. package/dist/logic/LogicScene.d.mts +32 -0
  276. package/dist/logic/LogicScene.mjs +277 -0
  277. package/dist/logic/contract.d.mts +72 -0
  278. package/dist/logic/display.d.mts +24 -0
  279. package/dist/logic/display.mjs +127 -0
  280. package/dist/logic/edit-ops.d.mts +44 -0
  281. package/dist/logic/edit-ops.mjs +177 -0
  282. package/dist/logic/evaluate.d.mts +11 -0
  283. package/dist/logic/evaluate.mjs +93 -0
  284. package/dist/logic/gates.d.mts +10 -0
  285. package/dist/logic/gates.mjs +73 -0
  286. package/dist/logic/index.d.mts +14 -0
  287. package/dist/logic/index.mjs +13 -0
  288. package/dist/logic/lab.d.mts +32 -0
  289. package/dist/logic/lab.mjs +160 -0
  290. package/dist/logic/presets.d.mts +12 -0
  291. package/dist/logic/presets.mjs +241 -0
  292. package/dist/logic/registry.d.mts +9 -0
  293. package/dist/logic/registry.mjs +15 -0
  294. package/dist/math/area-model/preset.mjs +70 -44
  295. package/dist/math/balance-algebra/preset.mjs +14 -5
  296. package/dist/math/broken-tree/index.d.mts +1 -0
  297. package/dist/math/broken-tree/preset.d.mts +26 -0
  298. package/dist/math/broken-tree/preset.mjs +435 -0
  299. package/dist/math/circle/index.d.mts +1 -0
  300. package/dist/math/circle/preset.d.mts +44 -0
  301. package/dist/math/circle/preset.mjs +198 -0
  302. package/dist/math/complex/core.d.mts +93 -0
  303. package/dist/math/complex/core.mjs +239 -0
  304. package/dist/math/complex/index.d.mts +3 -0
  305. package/dist/math/complex/preset.d.mts +31 -0
  306. package/dist/math/complex/preset.mjs +377 -0
  307. package/dist/math/complex/rules.d.mts +6 -0
  308. package/dist/math/complex/rules.mjs +121 -0
  309. package/dist/math/conic/index.d.mts +1 -0
  310. package/dist/math/conic/preset.d.mts +30 -0
  311. package/dist/math/conic/preset.mjs +334 -0
  312. package/dist/math/derivation.mjs +5 -5
  313. package/dist/math/derivative-explorer/preset.mjs +5 -5
  314. package/dist/math/domain-range/index.d.mts +1 -0
  315. package/dist/math/domain-range/preset.d.mts +33 -0
  316. package/dist/math/domain-range/preset.mjs +313 -0
  317. package/dist/math/fraction-bar/index.d.mts +1 -0
  318. package/dist/math/fraction-bar/preset.d.mts +27 -0
  319. package/dist/math/fraction-bar/preset.mjs +197 -0
  320. package/dist/math/function-machine/preset.mjs +2 -2
  321. package/dist/math/gradient-descent.mjs +6 -6
  322. package/dist/math/grapher/preset.d.mts +1 -1
  323. package/dist/math/grapher/preset.mjs +4 -4
  324. package/dist/math/harmonic-form/preset.mjs +6 -6
  325. package/dist/math/index.d.mts +27 -2
  326. package/dist/math/index.mjs +27 -2
  327. package/dist/math/integral-explorer/preset.mjs +2 -2
  328. package/dist/math/interactive/preset.mjs +3 -3
  329. package/dist/math/limit-explorer/preset.mjs +4 -4
  330. package/dist/math/linear-model/index.d.mts +1 -0
  331. package/dist/math/linear-model/preset.d.mts +53 -0
  332. package/dist/math/linear-model/preset.mjs +164 -0
  333. package/dist/math/linear-system/preset.mjs +4 -4
  334. package/dist/math/mystery-bucket/preset.mjs +6 -6
  335. package/dist/math/number-line/preset.mjs +3 -2
  336. package/dist/math/parabola/preset.mjs +4 -3
  337. package/dist/math/pattern/preset.mjs +7 -13
  338. package/dist/math/percent-bar/index.d.mts +1 -0
  339. package/dist/math/percent-bar/preset.d.mts +37 -0
  340. package/dist/math/percent-bar/preset.mjs +275 -0
  341. package/dist/math/poly/core.d.mts +50 -0
  342. package/dist/math/poly/core.mjs +268 -0
  343. package/dist/math/poly/index.d.mts +3 -0
  344. package/dist/math/poly/preset.d.mts +23 -0
  345. package/dist/math/poly/preset.mjs +141 -0
  346. package/dist/math/poly/steps.d.mts +10 -0
  347. package/dist/math/poly/steps.mjs +99 -0
  348. package/dist/math/rate-machine/index.d.mts +1 -0
  349. package/dist/math/rate-machine/preset.d.mts +35 -0
  350. package/dist/math/rate-machine/preset.mjs +281 -0
  351. package/dist/math/ratio-share/index.d.mts +1 -0
  352. package/dist/math/ratio-share/preset.d.mts +24 -0
  353. package/dist/math/ratio-share/preset.mjs +204 -0
  354. package/dist/math/receipt/index.d.mts +1 -0
  355. package/dist/math/receipt/preset.d.mts +22 -0
  356. package/dist/math/receipt/preset.mjs +137 -0
  357. package/dist/math/sequence-predict/index.d.mts +1 -0
  358. package/dist/math/sequence-predict/preset.d.mts +34 -0
  359. package/dist/math/sequence-predict/preset.mjs +130 -0
  360. package/dist/math/straight-line/index.d.mts +1 -0
  361. package/dist/math/straight-line/preset.d.mts +37 -0
  362. package/dist/math/straight-line/preset.mjs +374 -0
  363. package/dist/math/system-solve/index.d.mts +1 -0
  364. package/dist/math/system-solve/preset.d.mts +21 -0
  365. package/dist/math/system-solve/preset.mjs +227 -0
  366. package/dist/math/transform/index.d.mts +1 -0
  367. package/dist/math/transform/preset.d.mts +41 -0
  368. package/dist/math/transform/preset.mjs +343 -0
  369. package/dist/math/triangle-trig/preset.mjs +12 -9
  370. package/dist/math/trig/core.d.mts +37 -0
  371. package/dist/math/trig/core.mjs +150 -0
  372. package/dist/math/trig/diagrams.d.mts +1 -0
  373. package/dist/math/trig/diagrams.mjs +321 -0
  374. package/dist/math/trig/index.d.mts +3 -0
  375. package/dist/math/trig/preset.d.mts +25 -0
  376. package/dist/math/trig/preset.mjs +260 -0
  377. package/dist/math/trig/rules.d.mts +6 -0
  378. package/dist/math/trig/rules.mjs +159 -0
  379. package/dist/math/trig-explorer.mjs +4 -4
  380. package/dist/ml/boundary/preset.mjs +8 -3
  381. package/dist/ml/classifier/preset.mjs +31 -6
  382. package/dist/ml/kmeans/preset.mjs +4 -4
  383. package/dist/ml/knn/preset.mjs +47 -12
  384. package/dist/ml/regression/preset.mjs +36 -7
  385. package/dist/physics/atwood/preset.mjs +4 -4
  386. package/dist/physics/bullet-walls/preset.d.mts +1 -1
  387. package/dist/physics/bullet-walls/preset.mjs +7 -7
  388. package/dist/physics/carnot/preset.mjs +6 -6
  389. package/dist/physics/circular-motion/preset.mjs +36 -5
  390. package/dist/physics/collision-track/preset.mjs +35 -5
  391. package/dist/physics/efficiency/preset.d.mts +2 -2
  392. package/dist/physics/efficiency/preset.mjs +5 -5
  393. package/dist/physics/electric-field/preset.mjs +32 -23
  394. package/dist/physics/electric-flux/index.d.mts +1 -0
  395. package/dist/physics/electric-flux/preset.d.mts +29 -0
  396. package/dist/physics/electric-flux/preset.mjs +264 -0
  397. package/dist/physics/energy-skate/preset.mjs +5 -5
  398. package/dist/physics/entropy/preset.mjs +7 -7
  399. package/dist/physics/expansion/preset.mjs +13 -13
  400. package/dist/physics/exponential/asset.mjs +1 -1
  401. package/dist/physics/exponential/preset.mjs +4 -4
  402. package/dist/physics/gas-process/preset.mjs +3 -3
  403. package/dist/physics/gauss-law/index.d.mts +1 -0
  404. package/dist/physics/gauss-law/preset.d.mts +20 -0
  405. package/dist/physics/gauss-law/preset.mjs +286 -0
  406. package/dist/physics/gravitation/preset.mjs +7 -7
  407. package/dist/physics/gravity-drop.mjs +4 -4
  408. package/dist/physics/heat-transfer/preset.d.mts +1 -1
  409. package/dist/physics/heat-transfer/preset.mjs +10 -10
  410. package/dist/physics/impulse/preset.mjs +5 -5
  411. package/dist/physics/index.d.mts +4 -1
  412. package/dist/physics/index.mjs +4 -1
  413. package/dist/physics/kepler/preset.mjs +4 -4
  414. package/dist/physics/lever/preset.mjs +3 -3
  415. package/dist/physics/lorentz/preset.mjs +11 -11
  416. package/dist/physics/magnetism/preset.mjs +3 -3
  417. package/dist/physics/optics/preset.mjs +2 -2
  418. package/dist/physics/orbit-lab.mjs +5 -5
  419. package/dist/physics/projectile-lab.mjs +4 -4
  420. package/dist/physics/rain-relative/preset.mjs +5 -5
  421. package/dist/physics/ramp-forces/preset.mjs +5 -5
  422. package/dist/physics/river-boat.mjs +6 -6
  423. package/dist/physics/shm/preset.mjs +9 -9
  424. package/dist/physics/stopping-distance/preset.mjs +3 -3
  425. package/dist/physics/temperature-scales/preset.mjs +105 -116
  426. package/dist/physics/terminal-velocity/preset.mjs +5 -5
  427. package/dist/physics/thermal/preset.mjs +5 -5
  428. package/dist/physics/vector-board/preset.mjs +7 -6
  429. package/dist/physics/vector-scene.mjs +2 -2
  430. package/dist/physics/vector-types/preset.mjs +37 -3
  431. package/dist/physics/water-density/preset.mjs +12 -12
  432. package/dist/physics/waves/doppler.mjs +2 -2
  433. package/dist/physics/waves/preset.mjs +4 -4
  434. package/dist/physics/waves/ripple.mjs +6 -6
  435. package/dist/physics/waves/string.mjs +5 -5
  436. package/dist/physics/work-energy/preset.mjs +4 -4
  437. package/dist/physics/work-potential/index.d.mts +1 -0
  438. package/dist/physics/work-potential/preset.d.mts +20 -0
  439. package/dist/physics/work-potential/preset.mjs +276 -0
  440. package/dist/schemas/index.d.mts +6 -6
  441. package/dist/schemas/index.mjs +3 -3
  442. package/dist/statistics/center-spread/preset.mjs +3 -3
  443. package/dist/statistics/core/descriptive.d.mts +2 -2
  444. package/dist/statistics/core/descriptive.mjs +2 -2
  445. package/dist/statistics/core/normal.d.mts +3 -3
  446. package/dist/statistics/core/normal.mjs +3 -3
  447. package/dist/statistics/core/sequences.d.mts +1 -1
  448. package/dist/statistics/galton/preset.mjs +2 -2
  449. package/dist/statistics/histogram/preset.mjs +6 -6
  450. package/dist/statistics/normal/preset.mjs +2 -2
  451. package/dist/statistics/sampling/preset.mjs +4 -4
  452. package/dist/statistics/sequence/preset.mjs +58 -15
  453. package/dist/statistics/z-table/preset.mjs +17 -4
  454. package/package.json +11 -3
  455. package/styles.css +4 -1
@@ -12,17 +12,17 @@ import { useControlSurface, useLearner } from "@classytic/stage";
12
12
 
13
13
  //#region src/discrete/truth-table/preset.tsx
14
14
  /**
15
- * TruthTableEngine — the GENERAL authorable truth-table tool. A creator declares
15
+ * TruthTableEngine, the GENERAL authorable truth-table tool. A creator declares
16
16
  * any propositional formula (¬ ∧ ∨ ⊕ → ↔, unicode or ASCII) and a mode; the lab
17
17
  * derives EVERYTHING from the stage logic kernel (parse → truth table → classify
18
- * → equivalence). No per-problem widget — one tool covers all of propositional
18
+ * → equivalence). No per-problem widget, one tool covers all of propositional
19
19
  * logic, from "fill the implication table" to "are these two equivalent?".
20
20
  *
21
21
  * Modes:
22
- * • show — full reference table with sub-expression columns built up
22
+ * • show , full reference table with sub-expression columns built up
23
23
  * textbook-style (vars → ¬p → q∧r → … → the whole formula).
24
- * • fill — learner toggles each output cell, then Check (graded per cell).
25
- * • classify — learner judges tautology / contradiction / contingency.
24
+ * • fill , learner toggles each output cell, then Check (graded per cell).
25
+ * • classify, learner judges tautology / contradiction / contingency.
26
26
  * Pass `compare` to put a second formula beside the first + an equivalence verdict
27
27
  * (De Morgan, contrapositive, p→q ≡ ¬p∨q …). Agent-drivable via `controlId`.
28
28
  */
@@ -31,6 +31,8 @@ const CLASSES = [
31
31
  "contradiction",
32
32
  "contingency"
33
33
  ];
34
+ /** 2^n rows: past this a truth table is impractical to render and unsafe for 32-bit shifts. */
35
+ const MAX_VARS = 12;
34
36
  /** Sub-expressions in build-up (post-order) order, deduped, vars/consts excluded;
35
37
  * the root formula is last. */
36
38
  function subformulas(n) {
@@ -83,8 +85,9 @@ function TruthTableLab({ formula, compare, mode: mode0 = "fill", breakdown = tru
83
85
  cmp
84
86
  ]);
85
87
  const envs = useMemo(() => {
88
+ if (vars.length > MAX_VARS) return [];
86
89
  const rows = [];
87
- for (let m = 0; m < 1 << vars.length; m++) {
90
+ for (let m = 0; m < 2 ** vars.length; m++) {
88
91
  const env = {};
89
92
  vars.forEach((v, i) => {
90
93
  env[v] = (m & 1 << vars.length - 1 - i) !== 0;
@@ -201,6 +204,26 @@ function TruthTableLab({ formula, compare, mode: mode0 = "fill", breakdown = tru
201
204
  ]
202
205
  })
203
206
  });
207
+ if (vars.length > MAX_VARS) return /* @__PURE__ */ jsx(LabFrame, {
208
+ title,
209
+ children: /* @__PURE__ */ jsxs("p", {
210
+ className: "lab-misconception",
211
+ role: "status",
212
+ children: [
213
+ /* @__PURE__ */ jsx("span", {
214
+ "aria-hidden": true,
215
+ children: "⚠"
216
+ }),
217
+ " This truth table has ",
218
+ vars.length,
219
+ " variables (",
220
+ 2 ** vars.length,
221
+ " rows). Keep it to ",
222
+ MAX_VARS,
223
+ " or fewer."
224
+ ]
225
+ })
226
+ });
204
227
  const th = {
205
228
  padding: "6px 12px",
206
229
  fontWeight: 700,
@@ -381,7 +404,7 @@ function TruthTableLab({ formula, compare, mode: mode0 = "fill", breakdown = tru
381
404
  className: "lab-bar",
382
405
  children: /* @__PURE__ */ jsx(StatusPill, {
383
406
  ok: equiv,
384
- children: equiv ? "Equivalent ✓ — identical columns" : "NOT equivalent — columns differ"
407
+ children: equiv ? "Equivalent ✓, identical columns" : "NOT equivalent, columns differ"
385
408
  })
386
409
  })
387
410
  ] });
@@ -419,7 +442,7 @@ function TruthTableLab({ formula, compare, mode: mode0 = "fill", breakdown = tru
419
442
  }),
420
443
  checked && /* @__PURE__ */ jsx(StatusPill, {
421
444
  ok: guess === cls,
422
- children: guess === cls ? `✓ ${cls}` : `Not quite — it’s a ${cls}`
445
+ children: guess === cls ? `✓ ${cls}` : `Not quite, it’s a ${cls}`
423
446
  })
424
447
  ] }),
425
448
  !compare && mode === "fill" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CheckButton, {
@@ -428,7 +451,7 @@ function TruthTableLab({ formula, compare, mode: mode0 = "fill", breakdown = tru
428
451
  children: "Check"
429
452
  }), checked && /* @__PURE__ */ jsx(StatusPill, {
430
453
  ok: allFilledCorrect,
431
- children: allFilledCorrect ? "All correct ✓" : "Some cells are off — fix the red ones"
454
+ children: allFilledCorrect ? "All correct ✓" : "Some cells are off, fix the red ones"
432
455
  })] })
433
456
  ] }),
434
457
  footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [!compare && mode !== "show" && /* @__PURE__ */ jsx(RevealSolution, {
@@ -10,14 +10,14 @@ import { compileLogic, useControlSurface, useLearner } from "@classytic/stage";
10
10
 
11
11
  //#region src/discrete/venn/preset.tsx
12
12
  /**
13
- * VennSetBoard — the GENERAL sets + inclusion–exclusion tool (2 or 3 sets). The
13
+ * VennSetBoard, the GENERAL sets + inclusion–exclusion tool (2 or 3 sets). The
14
14
  * creator declares set MEMBERS; the lab places each element in its true region,
15
15
  * shows live region counts, and (explore) the inclusion–exclusion breakdown
16
- * |A∪B| = |A| + |B| − |A∩B| — the "overcount, then correct" spine made visible.
16
+ * |A∪B| = |A| + |B| − |A∩B|, the "overcount, then correct" spine made visible.
17
17
  *
18
18
  * The trinity made literal: a SET expression is a PROPOSITIONAL formula over
19
19
  * membership (∩↔∧, ∪↔∨, ᶜ↔¬), so "shade the region for A ∩ ¬B" runs on the SAME
20
- * `compileLogic` kernel as the truth-table lab — one source of truth.
20
+ * `compileLogic` kernel as the truth-table lab, one source of truth.
21
21
  *
22
22
  * Self-contained SVG (a fixed diagram, not a coordinate plot), so no Stage coords
23
23
  * needed; counts/IE come from `@classytic/labs/discrete/core`.
@@ -27,77 +27,77 @@ const GEO2 = {
27
27
  0,
28
28
  0,
29
29
  340,
30
- 210
30
+ 224
31
31
  ],
32
32
  circles: [{
33
33
  cx: 132,
34
- cy: 108,
35
- r: 84
34
+ cy: 118,
35
+ r: 82
36
36
  }, {
37
37
  cx: 208,
38
- cy: 108,
39
- r: 84
38
+ cy: 118,
39
+ r: 82
40
40
  }],
41
41
  centroids: {
42
- "10": [78, 108],
43
- "01": [262, 108],
44
- "11": [170, 108],
45
- "00": [38, 26]
42
+ "10": [80, 118],
43
+ "01": [260, 118],
44
+ "11": [170, 118],
45
+ "00": [40, 30]
46
46
  },
47
47
  labels: [{
48
- x: 70,
49
- y: 22
48
+ x: 104,
49
+ y: 26
50
50
  }, {
51
- x: 270,
52
- y: 22
51
+ x: 236,
52
+ y: 26
53
53
  }]
54
54
  };
55
55
  const GEO3 = {
56
56
  vb: [
57
57
  0,
58
58
  0,
59
- 340,
60
- 260
59
+ 360,
60
+ 306
61
61
  ],
62
62
  circles: [
63
63
  {
64
- cx: 132,
65
- cy: 102,
66
- r: 80
64
+ cx: 140,
65
+ cy: 116,
66
+ r: 78
67
67
  },
68
68
  {
69
- cx: 208,
70
- cy: 102,
71
- r: 80
69
+ cx: 220,
70
+ cy: 116,
71
+ r: 78
72
72
  },
73
73
  {
74
- cx: 170,
75
- cy: 168,
76
- r: 80
74
+ cx: 180,
75
+ cy: 186,
76
+ r: 78
77
77
  }
78
78
  ],
79
79
  centroids: {
80
- "100": [96, 78],
81
- "010": [244, 78],
82
- "001": [170, 210],
83
- "110": [170, 66],
84
- "101": [116, 144],
85
- "011": [224, 144],
86
- "111": [170, 118],
87
- "000": [38, 28]
80
+ "100": [104, 96],
81
+ "010": [256, 96],
82
+ "001": [180, 232],
83
+ "110": [180, 84],
84
+ "101": [132, 162],
85
+ "011": [228, 162],
86
+ "111": [180, 140],
87
+ "000": [44, 30]
88
88
  },
89
89
  labels: [
90
90
  {
91
- x: 78,
92
- y: 20
91
+ x: 104,
92
+ y: 30
93
93
  },
94
94
  {
95
- x: 262,
96
- y: 20
95
+ x: 256,
96
+ y: 30
97
97
  },
98
98
  {
99
- x: 170,
100
- y: 252
99
+ x: 180,
100
+ y: 296
101
101
  }
102
102
  ]
103
103
  };
@@ -274,6 +274,23 @@ function VennSetBoardLab({ sets, mode: mode0 = "explore", target, title = "Sets
274
274
  invoke: reset
275
275
  }
276
276
  });
277
+ if (n < 2 || n > 3) return /* @__PURE__ */ jsx(LabFrame, {
278
+ title,
279
+ prompt,
280
+ children: /* @__PURE__ */ jsxs("p", {
281
+ className: "lab-misconception",
282
+ role: "status",
283
+ children: [
284
+ /* @__PURE__ */ jsx("span", {
285
+ "aria-hidden": true,
286
+ children: "⚠"
287
+ }),
288
+ " The Venn lab supports 2 or 3 sets; you gave ",
289
+ n,
290
+ ". Reduce the number of sets."
291
+ ]
292
+ })
293
+ });
277
294
  const [vx, vy, vw, vh] = geo.vb;
278
295
  const showShade = mode === "shade";
279
296
  const figure = /* @__PURE__ */ jsx("div", {
@@ -307,10 +324,10 @@ function VennSetBoardLab({ sets, mode: mode0 = "explore", target, title = "Sets
307
324
  cy: c.cy,
308
325
  r: c.r,
309
326
  fill: PALETTE[i],
310
- fillOpacity: .06,
311
- stroke: "var(--stage-fg)",
312
- strokeOpacity: .5,
313
- strokeWidth: 1.5
327
+ fillOpacity: .09,
328
+ stroke: PALETTE[i],
329
+ strokeOpacity: .7,
330
+ strokeWidth: 2
314
331
  }, i)),
315
332
  geo.labels.map((l, i) => /* @__PURE__ */ jsx("text", {
316
333
  x: l.x,
@@ -319,20 +336,26 @@ function VennSetBoardLab({ sets, mode: mode0 = "explore", target, title = "Sets
319
336
  fontSize: 15,
320
337
  fontWeight: 800,
321
338
  textAnchor: "middle",
339
+ style: {
340
+ paintOrder: "stroke",
341
+ stroke: "var(--stage-bg)",
342
+ strokeWidth: 4,
343
+ strokeLinejoin: "round"
344
+ },
322
345
  children: names[i]
323
346
  }, i)),
324
347
  mode === "explore" && regions.filter((r) => r.count > 0 && r.sig !== "0".repeat(n)).map((r) => /* @__PURE__ */ jsx("text", {
325
348
  x: r.centroid[0],
326
349
  y: r.centroid[1],
327
350
  fill: "var(--stage-fg)",
328
- fontSize: 15,
351
+ fontSize: 16,
329
352
  fontWeight: 700,
330
353
  textAnchor: "middle",
331
354
  dominantBaseline: "central",
332
355
  style: {
333
356
  paintOrder: "stroke",
334
357
  stroke: "var(--stage-bg)",
335
- strokeWidth: 4,
358
+ strokeWidth: 4.5,
336
359
  strokeLinejoin: "round"
337
360
  },
338
361
  children: r.count
@@ -441,7 +464,7 @@ function VennSetBoardLab({ sets, mode: mode0 = "explore", target, title = "Sets
441
464
  }),
442
465
  checked && /* @__PURE__ */ jsx(StatusPill, {
443
466
  ok: correct,
444
- children: correct ? "✓ Exactly right" : "Not quite — adjust the regions"
467
+ children: correct ? "✓ Exactly right" : "Not quite, adjust the regions"
445
468
  })
446
469
  ] }) : void 0,
447
470
  footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [mode === "shade" && /* @__PURE__ */ jsx(RevealSolution, {
@@ -10,15 +10,15 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/geography/cycle-lab/preset.tsx
12
12
  /**
13
- * CycleLab — ONE authorable lab for every cycle (water, rock, carbon, nitrogen,
13
+ * CycleLab, ONE authorable lab for every cycle (water, rock, carbon, nitrogen,
14
14
  * food chains…). The creator/agent declares the model (nodes + process-labelled
15
15
  * edges) and a challenge; the shared CycleDiagram renders it. Not a bespoke
16
- * WaterCycle/RockCycle widget — the cycle is data.
16
+ * WaterCycle/RockCycle widget, the cycle is data.
17
17
  *
18
- * • challenge='trace' — click a stage; its outgoing arrows + the processes that
18
+ * • challenge='trace', click a stage; its outgoing arrows + the processes that
19
19
  * drive them light up. The branched rock/carbon cycles reveal that you don't
20
- * have to go all the way around — any rock can melt or re-weather.
21
- * • challenge='label-process' — the process names are stripped off the arrows
20
+ * have to go all the way around, any rock can melt or re-weather.
21
+ * • challenge='label-process', the process names are stripped off the arrows
22
22
  * into a tray; match each one to the transition it drives. That IS the IGCSE
23
23
  * skill, and it's unambiguous (clean rings like the water cycle).
24
24
  *
@@ -81,7 +81,7 @@ function TraceCycle({ nodes, edges, size, title, prompt, objectives, activity })
81
81
  size,
82
82
  activeId: active,
83
83
  onNodeClick: click,
84
- ariaLabel: `${title} — click a stage to trace its transitions`
84
+ ariaLabel: `${title}: a cycle diagram with ${nodes.length} stages (${nodes.map((nd) => nd.label).join(", ")}) connected by labelled process arrows. Activate a stage to trace its outgoing transitions and the processes that drive them.`
85
85
  })
86
86
  }), /* @__PURE__ */ jsx(LiveRegion, { children: active ? `${labelOf(active)} leads to ${out.map((e) => `${labelOf(e.to)} by ${e.label}`).join(", ") || "nothing further"}.` : "" })] });
87
87
  const footer = /* @__PURE__ */ jsxs("div", {
@@ -101,7 +101,7 @@ function TraceCycle({ nodes, edges, size, title, prompt, objectives, activity })
101
101
  /* @__PURE__ */ jsxs("span", {
102
102
  style: { color: "var(--stage-muted)" },
103
103
  children: [
104
- " —",
104
+ " , ",
105
105
  e.label,
106
106
  "→ "
107
107
  ]
@@ -126,7 +126,7 @@ function TraceCycle({ nodes, edges, size, title, prompt, objectives, activity })
126
126
  });
127
127
  return /* @__PURE__ */ jsx(LabFrame, {
128
128
  title,
129
- prompt: prompt ?? "Click each stage to trace where it goes — and which process drives the change.",
129
+ prompt: prompt ?? "Click each stage to trace where it goes, and which process drives the change.",
130
130
  objectives,
131
131
  footer,
132
132
  children: figure
@@ -171,9 +171,16 @@ function LabelProcess({ nodes, edges, size, title, prompt, objectives, hash: h,
171
171
  const fill = ok ? "var(--stage-good)" : bad ? "var(--stage-danger)" : "var(--stage-muted)";
172
172
  return /* @__PURE__ */ jsxs("g", {
173
173
  onClick: () => onSlot(key),
174
+ onKeyDown: (e) => {
175
+ if (e.key === "Enter" || e.key === " ") {
176
+ e.preventDefault();
177
+ onSlot(key);
178
+ }
179
+ },
174
180
  style: { cursor: "pointer" },
175
181
  role: "button",
176
- "aria-label": val ? `${val}${ok ? " correct" : " wrong"}` : "empty slot",
182
+ tabIndex: 0,
183
+ "aria-label": val ? `${val}, ${ok ? "correctly matched, activate to take it back" : "incorrect, activate to clear"}` : sel ? `Empty process slot, activate to place ${sel} here` : "Empty process slot, pick a process first, then activate to place it here",
177
184
  children: [/* @__PURE__ */ jsx("rect", {
178
185
  x: Math.round(mid.x - w / 2),
179
186
  y: mid.y - 10,
@@ -207,7 +214,7 @@ function LabelProcess({ nodes, edges, size, title, prompt, objectives, hash: h,
207
214
  edges,
208
215
  size,
209
216
  edgeSlot,
210
- ariaLabel: `${title} — match each process to its arrow`
217
+ ariaLabel: `${title}: a cycle diagram with ${nodes.length} stages (${nodes.map((nd) => nd.label).join(", ")}) and ${labelEdges.length} arrows whose process labels have been removed. Pick a process from the tray, then activate the arrow slot it drives to match it.`
211
218
  })
212
219
  }), /* @__PURE__ */ jsx(LiveRegion, { children: solved ? "All processes matched correctly." : `${solvedCount} of ${labelEdges.length} processes matched.` })] });
213
220
  const controls = /* @__PURE__ */ jsx(ControlBar, { children: /* @__PURE__ */ jsx(Field, {
@@ -5,11 +5,11 @@ interface CycleSpec {
5
5
  nodes: CycleNode[];
6
6
  edges: CycleEdge[];
7
7
  }
8
- /** Water cycle — a clean 5-stage ring; each edge is one distinct process. */
8
+ /** Water cycle, a clean 5-stage ring; each edge is one distinct process. */
9
9
  declare const WATER_CYCLE: CycleSpec;
10
- /** Rock cycle — a ring PLUS shortcuts: any rock can skip ahead (heat, re-weather). */
10
+ /** Rock cycle, a ring PLUS shortcuts: any rock can skip ahead (heat, re-weather). */
11
11
  declare const ROCK_CYCLE: CycleSpec;
12
- /** Carbon cycle — branched (CO₂ in/out by several routes); ties to photo/respiration. */
12
+ /** Carbon cycle, branched (CO₂ in/out by several routes); ties to photo/respiration. */
13
13
  declare const CARBON_CYCLE: CycleSpec;
14
14
  declare const CYCLE_PRESETS: {
15
15
  readonly water: CycleSpec;
@@ -1,5 +1,5 @@
1
1
  //#region src/geography/cycles.ts
2
- /** Water cycle — a clean 5-stage ring; each edge is one distinct process. */
2
+ /** Water cycle, a clean 5-stage ring; each edge is one distinct process. */
3
3
  const WATER_CYCLE = {
4
4
  nodes: [
5
5
  {
@@ -56,7 +56,7 @@ const WATER_CYCLE = {
56
56
  }
57
57
  ]
58
58
  };
59
- /** Rock cycle — a ring PLUS shortcuts: any rock can skip ahead (heat, re-weather). */
59
+ /** Rock cycle, a ring PLUS shortcuts: any rock can skip ahead (heat, re-weather). */
60
60
  const ROCK_CYCLE = {
61
61
  nodes: [
62
62
  {
@@ -123,7 +123,7 @@ const ROCK_CYCLE = {
123
123
  }
124
124
  ]
125
125
  };
126
- /** Carbon cycle — branched (CO₂ in/out by several routes); ties to photo/respiration. */
126
+ /** Carbon cycle, branched (CO₂ in/out by several routes); ties to photo/respiration. */
127
127
  const CARBON_CYCLE = {
128
128
  nodes: [
129
129
  {
@@ -55,6 +55,7 @@ interface GeometryBoardProps {
55
55
  scene?: GeoElement[];
56
56
  view?: View;
57
57
  title?: string;
58
+ prompt?: string;
58
59
  subtitle?: string;
59
60
  height?: number;
60
61
  }
@@ -65,6 +66,7 @@ declare function GeometryBoard({
65
66
  scene,
66
67
  view,
67
68
  title,
69
+ prompt,
68
70
  height
69
71
  }: GeometryBoardProps): ReactNode;
70
72
  //#endregion
@@ -1,16 +1,17 @@
1
1
  'use client';
2
2
 
3
+ import { LabFrame } from "../../kit/frame.mjs";
3
4
  import { useEffect, useMemo, useState } from "react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { jsx } from "react/jsx-runtime";
5
6
  import { Scene } from "@classytic/stage";
6
7
 
7
8
  //#region src/geometry/board/preset.tsx
8
9
  /**
9
- * GeometryBoard — a declarative interactive-geometry engine, now on the
10
+ * GeometryBoard, a declarative interactive-geometry engine, now on the
10
11
  * @classytic/stage scene model. A creator describes a CONSTRUCTION as a list of
11
12
  * `GeoElement`s; we convert it to a portable SceneDoc and let stage's resolver
12
13
  * do the dependency math (circle/line intersection, midpoints) + dragging +
13
- * a11y. The canvas geometry math is gone — stage already owns it.
14
+ * a11y. The canvas geometry math is gone, stage already owns it.
14
15
  *
15
16
  * <GeometryBoard scene={[
16
17
  * { type:'point', id:'A', x:3, y:0, draggable:true },
@@ -118,29 +119,24 @@ function geoSceneToDoc(scene, view) {
118
119
  bindings: []
119
120
  };
120
121
  }
121
- function GeometryBoard({ scene = [], view = DEFAULT_VIEW, title, height = 360 }) {
122
+ function GeometryBoard({ scene = [], view = DEFAULT_VIEW, title = "Geometry construction", prompt = "Drag the points to explore the construction.", height = 360 }) {
122
123
  const initial = useMemo(() => geoSceneToDoc(scene, view), [scene, view]);
123
124
  const [doc, setDoc] = useState(initial);
124
125
  useEffect(() => {
125
126
  setDoc(initial);
126
127
  }, [initial]);
127
- return /* @__PURE__ */ jsxs("div", {
128
- className: "not-prose",
129
- children: [title && /* @__PURE__ */ jsx("p", {
130
- style: {
131
- fontWeight: 600,
132
- marginBottom: 6
133
- },
134
- children: title
135
- }), /* @__PURE__ */ jsx(Scene, {
128
+ return /* @__PURE__ */ jsx(LabFrame, {
129
+ title,
130
+ prompt,
131
+ children: /* @__PURE__ */ jsx(Scene, {
136
132
  doc,
137
133
  onChange: setDoc,
138
134
  interactive: true,
139
135
  showGrid: true,
140
136
  showAxes: true,
141
137
  height,
142
- ariaLabel: title ?? "Geometry construction"
143
- })]
138
+ ariaLabel: title
139
+ })
144
140
  });
145
141
  }
146
142
 
@@ -7,7 +7,7 @@ import { Axes, Dot, Grid, Stage, ToolIcon, isCircleVal, isLineVal, isVec2, rende
7
7
 
8
8
  //#region src/geometry/builder.tsx
9
9
  /**
10
- * GeometryBuilder — a visual, click-to-build editor for a `GeometryBoard` scene.
10
+ * GeometryBuilder, a visual, click-to-build editor for a `GeometryBoard` scene.
11
11
  *
12
12
  * Pick a tool, click the board: drop points, connect them into segments/lines,
13
13
  * draw circles (centre → through-point), mark the intersection of two
@@ -16,7 +16,7 @@ import { Axes, Dot, Grid, Stage, ToolIcon, isCircleVal, isLineVal, isVec2, rende
16
16
  *
17
17
  * Now on the @classytic/stage engine: the construction is converted to a SceneDoc
18
18
  * and rendered with stage's resolver + `renderElements` (SVG, accessible, real
19
- * draggable points) — the canvas geometry math is gone. `GeometryBoard` is the
19
+ * draggable points), the canvas geometry math is gone. `GeometryBoard` is the
20
20
  * read-only render of this editor's output.
21
21
  */
22
22
  const TOOLS = [
@@ -303,7 +303,7 @@ function GeometryBuilder({ scene = [], onChange, title = "Build a construction",
303
303
  view: VIEW,
304
304
  height,
305
305
  onPointerMath: onBuild,
306
- ariaLabel: `Geometry construction editor — ${tool} tool`,
306
+ ariaLabel: `Geometry construction editor, ${tool} tool`,
307
307
  className: "cursor-crosshair",
308
308
  children: [
309
309
  /* @__PURE__ */ jsx(Grid, {}),
@@ -11,11 +11,11 @@ import { useInView } from "@classytic/stage";
11
11
 
12
12
  //#region src/ict/number-systems/base-odometer.tsx
13
13
  /**
14
- * BaseOdometer — the same quantity, ticking in every base at once.
14
+ * BaseOdometer, the same quantity, ticking in every base at once.
15
15
  *
16
16
  * Stacked odometer rows (one per base) all driven by ONE shared integer:
17
- * increment it and binary/octal/decimal/hex roll in lockstep — the binary row
18
- * rolls fastest (the rightmost-bit frequency cascade), hex barely moves — so
17
+ * increment it and binary/octal/decimal/hex roll in lockstep, the binary row
18
+ * rolls fastest (the rightmost-bit frequency cascade), hex barely moves, so
19
19
  * "base is a costume, not a different number" is something you watch, not read.
20
20
  * A race toggle auto-counts via the frame loop so the cascade plays as motion.
21
21
  * Composes the shared WheelRow (DRY: the wheel + carry animation live in one place).
@@ -31,7 +31,7 @@ function BaseOdometerLab({ bases = [
31
31
  8,
32
32
  10,
33
33
  16
34
- ], width = "auto", start = 0, max = 255, race = false, speed = 2, highlightBase, target, title = "Base odometer", prompt = "One quantity, every base at once — +1 and watch them all roll.", objectives }) {
34
+ ], width = "auto", start = 0, max = 255, race = false, speed = 2, highlightBase, target, title = "Base odometer", prompt = "One quantity, every base at once: +1 and watch them all roll.", objectives }) {
35
35
  const [value, setValue] = useState(Math.max(0, Math.min(max, Math.floor(start))));
36
36
  const [racing, setRacing] = useState(race);
37
37
  const acc = useRef(0);
@@ -7,7 +7,7 @@ interface BitGrouperProps {
7
7
  /** Group sizes offered as chips (4 = hex, 3 = octal). */
8
8
  groupings?: number[];
9
9
  start?: number;
10
- /** Pose "build this value" — reports via the learner seam when matched. */
10
+ /** Pose "build this value", reports via the learner seam when matched. */
11
11
  target?: {
12
12
  value: number;
13
13
  base: 16 | 8 | 2;
@@ -9,10 +9,10 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/ict/number-systems/bit-grouper.tsx
11
11
  /**
12
- * BitGrouper — slice a byte into nibbles and read the hex.
12
+ * BitGrouper, slice a byte into nibbles and read the hex.
13
13
  *
14
14
  * A strip of tappable bits that auto-slices into groups of k FROM THE RIGHT
15
- * (4 for hex, 3 for octal), translating each group to a hex/octal digit live —
15
+ * (4 for hex, 3 for octal), translating each group to a hex/octal digit live ,
16
16
  * the "group the bits" trick made physical. Flip between hex and octal to watch
17
17
  * the SAME bits re-slice and the leftmost group pad with zeros; in octal the top
18
18
  * group of a byte never exceeds 3 (greyed), which is exactly why hex won.
@@ -42,7 +42,7 @@ function sliceFromRight(value, width, k) {
42
42
  }
43
43
  return groups;
44
44
  }
45
- function BitGrouperLab({ width = 8, groupSize = 4, groupings = [4, 3], start = 0, target, showColor = false, title = "Bit grouper", prompt = "Tap the bits. Group from the right — 4 per hex digit, 3 per octal digit.", objectives }) {
45
+ function BitGrouperLab({ width = 8, groupSize = 4, groupings = [4, 3], start = 0, target, showColor = false, title = "Bit grouper", prompt = "Tap the bits. Group from the right: 4 per hex digit, 3 per octal digit.", objectives }) {
46
46
  const cap = (1 << width) - 1;
47
47
  const [value, setValue] = useState(Math.max(0, Math.min(cap, Math.floor(start))));
48
48
  const [k, setK] = useState(groupSize);
@@ -135,7 +135,7 @@ function BitGrouperLab({ width = 8, groupSize = 4, groupings = [4, 3], start = 0
135
135
  children: [
136
136
  "the greyed top octal group is only ",
137
137
  width % k,
138
- " bits — it never passes ",
138
+ " bits, it never passes ",
139
139
  (1 << width % k) - 1,
140
140
  ", so octal wastes the top of a byte (why hex won)"
141
141
  ]
@@ -5,7 +5,7 @@ interface PlaceValueDialProps {
5
5
  base?: number;
6
6
  width?: number;
7
7
  start?: number;
8
- /** Pose "spin the dials to N" — reports via the learner seam when matched. */
8
+ /** Pose "spin the dials to N", reports via the learner seam when matched. */
9
9
  target?: number;
10
10
  /** Base chips the learner can switch between (re-bases the same value). */
11
11
  bases?: number[];
@@ -10,13 +10,13 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/ict/number-systems/place-value-dial.tsx
12
12
  /**
13
- * PlaceValueDial — count in any base and watch the carry ripple.
13
+ * PlaceValueDial, count in any base and watch the carry ripple.
14
14
  *
15
15
  * A row of odometer wheels in base-N. +1 ticks the ones wheel; when it passes
16
- * N−1 it snaps to 0 and KICKS the next wheel up — the carry ripples left while
16
+ * N−1 it snaps to 0 and KICKS the next wheel up, the carry ripples left while
17
17
  * the power-of-N place values light up and sum to the live value. Re-base the
18
18
  * SAME count with the base chips to see "10 in any base means you ticked over
19
- * the base exactly once". In base-2 the wheels become ON/OFF cells — the
19
+ * the base exactly once". In base-2 the wheels become ON/OFF cells, the
20
20
  * "lightbulbs worth 1-2-4-8-16" picture. (Anti-pattern guard: weights stay on
21
21
  * screen, the carry is shown not hidden, and it works in both directions.)
22
22
  */
@@ -12,7 +12,7 @@ interface DigitWheelProps {
12
12
  digit: number;
13
13
  /** 0 (settled) → 1 (just changed); slides the digit stack while it decays. */
14
14
  roll?: number;
15
- /** +1 counted up, −1 counted down — direction the wheel rolls. */
15
+ /** +1 counted up, −1 counted down, direction the wheel rolls. */
16
16
  dir?: number;
17
17
  /** Non-zero digits read as "active" (accent); a zero is muted. */
18
18
  active?: boolean;
@@ -32,7 +32,7 @@ declare function DigitWheel({
32
32
  onTap,
33
33
  ariaLabel
34
34
  }: DigitWheelProps): ReactNode;
35
- /** A binary ON/OFF cell — the "lightbulb worth 2^n" picture for base-2 mode. */
35
+ /** A binary ON/OFF cell, the "lightbulb worth 2^n" picture for base-2 mode. */
36
36
  declare function BitCell({
37
37
  on,
38
38
  onTap,
@@ -56,7 +56,7 @@ interface WheelRowProps {
56
56
  }
57
57
  /**
58
58
  * A row of odometer wheels (or bit cells) for `value` in `base`, with the
59
- * carry-ripple roll animation OWNED here — the single reusable place-value
59
+ * carry-ripple roll animation OWNED here, the single reusable place-value
60
60
  * primitive both PlaceValueDial and BaseOdometer compose, so the animation +
61
61
  * weight rendering live in exactly one spot.
62
62
  */