@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
@@ -0,0 +1,313 @@
1
+ 'use client';
2
+
3
+ import { clamp } from "../../core/util.mjs";
4
+ import { Callout, LabFrame } from "../../kit/frame.mjs";
5
+ import { useCheckpoint } from "../../kit/pedagogy.mjs";
6
+ import { LabAsk } from "../../kit/ask.mjs";
7
+ import { CoordPlane, num } from "../../kit/coords.mjs";
8
+ import { useEffect, useRef, useState } from "react";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ import { Dot, Label, MovableDot, Plot, Segment, compileExpr } from "@classytic/stage";
11
+
12
+ //#region src/math/domain-range/preset.tsx
13
+ /**
14
+ * DomainRangeLab, domain & range as SHADOWS. The big idea students miss is that
15
+ * domain/range aren't formulas to memorise; they're what you SEE when you let the
16
+ * curve cast two shadows:
17
+ *
18
+ * • shine a light from ABOVE → the curve's shadow on the x-axis is the DOMAIN
19
+ * (every input the function actually accepts), and
20
+ * • shine a light from the SIDE → the shadow on the y-axis is the RANGE
21
+ * (every output it can produce).
22
+ *
23
+ * On top of that, a "feed the machine" game: drag the input probe along the
24
+ * x-axis, it turns GREEN when the machine accepts the input (in the domain) and
25
+ * RED "undefined" when it doesn't (a pole like 1/(x−2), a √ of a negative, or an
26
+ * author-set restriction). So the SAME lab teaches every domain TYPE just by
27
+ * changing the expression: x² (range ≥ 0), √x (x ≥ 0), 1/x (x ≠ 0), √(9−x²)
28
+ * (the semicircle: domain [−3,3], range [0,3]), or a restricted interval.
29
+ *
30
+ * Built on the shared CoordPlane + the stage expr engine; authorable via props
31
+ * (equation, an optional domain restriction, a checked question).
32
+ */
33
+ const C_DOMAIN = "var(--stage-accent)";
34
+ const C_RANGE = "var(--stage-accent-2)";
35
+ const C_OK = "var(--stage-good)";
36
+ const C_BAD = "var(--stage-danger)";
37
+ const N = 1200;
38
+ /** Contiguous covered intervals of a sorted value set (split where the gap exceeds `gap`). */
39
+ function coveredIntervals(values, gap) {
40
+ const v = values.filter(Number.isFinite).sort((a, b) => a - b);
41
+ if (!v.length) return [];
42
+ const out = [];
43
+ let lo = v[0], prev = v[0];
44
+ for (let i = 1; i < v.length; i++) {
45
+ const x = v[i];
46
+ if (x - prev > gap) {
47
+ out.push([lo, prev]);
48
+ lo = x;
49
+ }
50
+ prev = x;
51
+ }
52
+ out.push([lo, prev]);
53
+ return out;
54
+ }
55
+ /** Sort + merge overlapping/adjacent intervals. */
56
+ function mergeIntervals(iv) {
57
+ const v = iv.filter((x) => x != null).sort((a, b) => a[0] - b[0]);
58
+ const out = [];
59
+ for (const [a, b] of v) {
60
+ const last = out[out.length - 1];
61
+ if (last && a <= last[1] + 1e-6) last[1] = Math.max(last[1], b);
62
+ else out.push([a, b]);
63
+ }
64
+ return out;
65
+ }
66
+ const fmtIntervals = (rs, eps) => rs.length ? rs.map(([a, b]) => b - a < eps ? `{${num(a)}}` : `[${num(a)}, ${num(b)}]`).join(" ∪ ") : ", ";
67
+ function DomainRangeLab({ equation = "sqrt(9 - x^2)", xRange = [-6, 6], yRange = "auto", restrict, probe, title = "Domain and range: the two shadows", prompt = "Drag the input probe: green = the machine accepts it (in the domain), red = undefined. The blue strip is every allowed input; the orange strip is every output.", ask, height = 400, activity = "domain-range" } = {}) {
68
+ const [x0, x1] = xRange;
69
+ const compiled = (() => {
70
+ const c = compileExpr(equation);
71
+ return c.error !== void 0 ? null : c;
72
+ })();
73
+ const inRestrict = (x) => !restrict || x >= restrict[0] - 1e-9 && x <= restrict[1] + 1e-9;
74
+ const f = (x) => compiled && inRestrict(x) ? compiled.fn({ x }) : NaN;
75
+ const dx = (x1 - x0) / N;
76
+ const pts = [];
77
+ for (let i = 0; i <= N; i++) {
78
+ const x = x0 + i * dx;
79
+ const y = f(x);
80
+ if (Number.isFinite(y)) pts.push([x, y]);
81
+ }
82
+ const [yMin, yMax] = (() => {
83
+ if (yRange !== "auto") return yRange;
84
+ if (!pts.length) return [-6, 6];
85
+ const s = pts.map((p) => p[1]).sort((a, b) => a - b);
86
+ const lo = Math.min(0, s[Math.floor(s.length * .02)] ?? -1);
87
+ const hi = Math.max(0, s[Math.floor(s.length * .98)] ?? 1);
88
+ const pad = Math.max(1, (hi - lo) * .12);
89
+ return [lo - pad, hi + pad];
90
+ })();
91
+ const yCap = Math.max(Math.abs(yMin), Math.abs(yMax)) * 3.5;
92
+ const domain = coveredIntervals(pts.filter(([, y]) => Math.abs(y) <= yCap).map(([x]) => x), dx * 2.5);
93
+ const range = mergeIntervals(domain.map(([a, b]) => {
94
+ let mn = Infinity, mx = -Infinity;
95
+ for (const [x, y] of pts) if (x >= a - 1e-9 && x <= b + 1e-9 && y >= yMin && y <= yMax) {
96
+ if (y < mn) mn = y;
97
+ if (y > mx) mx = y;
98
+ }
99
+ return Number.isFinite(mn) ? [mn, mx] : null;
100
+ }));
101
+ const [pxState, setPx] = useState(clamp(probe ?? (x0 + x1) / 2, x0, x1));
102
+ const pX = clamp(pxState, x0, x1);
103
+ const pY = f(pX);
104
+ const accepted = Number.isFinite(pY);
105
+ const visited = useRef({
106
+ min: pX,
107
+ max: pX
108
+ });
109
+ const [swept, setSwept] = useState(false);
110
+ useEffect(() => {
111
+ const v = visited.current;
112
+ if (pX < v.min) v.min = pX;
113
+ if (pX > v.max) v.max = pX;
114
+ if (!swept && v.max - v.min >= (x1 - x0) * .6) setSwept(true);
115
+ }, [
116
+ pX,
117
+ swept,
118
+ x0,
119
+ x1
120
+ ]);
121
+ useCheckpoint({
122
+ solved: swept,
123
+ activity
124
+ });
125
+ const figure = /* @__PURE__ */ jsxs(CoordPlane, {
126
+ view: {
127
+ xMin: x0,
128
+ xMax: x1,
129
+ yMin,
130
+ yMax
131
+ },
132
+ height,
133
+ preserveAspect: false,
134
+ ariaLabel: `Domain and range of ${equation}`,
135
+ children: [
136
+ compiled && /* @__PURE__ */ jsx(Plot.OfX, {
137
+ y: f,
138
+ color: "var(--stage-fg)",
139
+ weight: 2.5
140
+ }),
141
+ domain.map(([a, b], i) => /* @__PURE__ */ jsx(Segment, {
142
+ from: {
143
+ x: a,
144
+ y: 0
145
+ },
146
+ to: {
147
+ x: b,
148
+ y: 0
149
+ },
150
+ color: C_DOMAIN,
151
+ weight: 7
152
+ }, `d${i}`)),
153
+ domain.length > 0 && /* @__PURE__ */ jsx(Label, {
154
+ x: domain[0][0],
155
+ y: 0,
156
+ text: "domain",
157
+ color: C_DOMAIN,
158
+ size: 12,
159
+ dy: 18,
160
+ dx: 2,
161
+ anchor: "start"
162
+ }),
163
+ range.map(([a, b], i) => /* @__PURE__ */ jsx(Segment, {
164
+ from: {
165
+ x: 0,
166
+ y: a
167
+ },
168
+ to: {
169
+ x: 0,
170
+ y: b
171
+ },
172
+ color: C_RANGE,
173
+ weight: 7
174
+ }, `r${i}`)),
175
+ range.length > 0 && /* @__PURE__ */ jsx(Label, {
176
+ x: 0,
177
+ y: range[range.length - 1][1],
178
+ text: "range",
179
+ color: C_RANGE,
180
+ size: 12,
181
+ dx: 10,
182
+ anchor: "start"
183
+ }),
184
+ accepted ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
185
+ /* @__PURE__ */ jsx(Segment, {
186
+ from: {
187
+ x: pX,
188
+ y: 0
189
+ },
190
+ to: {
191
+ x: pX,
192
+ y: pY
193
+ },
194
+ color: C_OK,
195
+ weight: 1.5,
196
+ dashed: true
197
+ }),
198
+ /* @__PURE__ */ jsx(Segment, {
199
+ from: {
200
+ x: pX,
201
+ y: pY
202
+ },
203
+ to: {
204
+ x: 0,
205
+ y: pY
206
+ },
207
+ color: C_OK,
208
+ weight: 1.5,
209
+ dashed: true
210
+ }),
211
+ /* @__PURE__ */ jsx(Dot, {
212
+ x: pX,
213
+ y: pY,
214
+ r: 5,
215
+ color: C_OK
216
+ }),
217
+ /* @__PURE__ */ jsx(Dot, {
218
+ x: 0,
219
+ y: pY,
220
+ r: 5,
221
+ color: C_RANGE
222
+ })
223
+ ] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Segment, {
224
+ from: {
225
+ x: pX,
226
+ y: yMin
227
+ },
228
+ to: {
229
+ x: pX,
230
+ y: yMax
231
+ },
232
+ color: C_BAD,
233
+ weight: 1.5,
234
+ dashed: true
235
+ }), /* @__PURE__ */ jsx(Label, {
236
+ x: pX,
237
+ y: (yMin + yMax) / 2,
238
+ text: "undefined",
239
+ color: C_BAD,
240
+ size: 12,
241
+ dx: 8,
242
+ anchor: "start"
243
+ })] }),
244
+ /* @__PURE__ */ jsx(MovableDot, {
245
+ value: {
246
+ x: pX,
247
+ y: 0
248
+ },
249
+ onMove: (p) => setPx(clamp(p.x, x0, x1)),
250
+ constrain: "horizontal",
251
+ color: accepted ? C_OK : C_BAD,
252
+ ariaLabel: "input probe, drag along the x-axis"
253
+ })
254
+ ]
255
+ });
256
+ return /* @__PURE__ */ jsx(LabFrame, {
257
+ title,
258
+ prompt,
259
+ aside: /* @__PURE__ */ jsxs("div", {
260
+ style: {
261
+ display: "flex",
262
+ flexDirection: "column",
263
+ gap: 10
264
+ },
265
+ children: [/* @__PURE__ */ jsx("div", {
266
+ className: "lab-pill",
267
+ "data-state": accepted ? "ok" : "no",
268
+ role: "status",
269
+ style: { alignSelf: "flex-start" },
270
+ children: accepted ? `✓ f(${num(pX)}) = ${num(pY)}, accepted` : `✗ x = ${num(pX)} is not in the domain`
271
+ }), /* @__PURE__ */ jsx(Callout, {
272
+ tone: "result",
273
+ children: /* @__PURE__ */ jsxs("div", {
274
+ style: {
275
+ display: "grid",
276
+ gap: 6,
277
+ fontVariantNumeric: "tabular-nums",
278
+ fontSize: 13
279
+ },
280
+ children: [
281
+ /* @__PURE__ */ jsxs("span", { children: ["f(x) = ", /* @__PURE__ */ jsx("strong", { children: equation })] }),
282
+ /* @__PURE__ */ jsxs("span", {
283
+ style: { color: C_DOMAIN },
284
+ children: ["domain: ", /* @__PURE__ */ jsx("strong", { children: fmtIntervals(domain, dx * 3) })]
285
+ }),
286
+ /* @__PURE__ */ jsxs("span", {
287
+ style: { color: C_RANGE },
288
+ children: ["range: ", /* @__PURE__ */ jsx("strong", { children: fmtIntervals(range, (yMax - yMin) * .05) })]
289
+ }),
290
+ restrict && /* @__PURE__ */ jsxs("span", {
291
+ style: { color: "var(--stage-muted)" },
292
+ children: [
293
+ "restricted to [",
294
+ num(restrict[0]),
295
+ ", ",
296
+ num(restrict[1]),
297
+ "]"
298
+ ]
299
+ })
300
+ ]
301
+ })
302
+ })]
303
+ }),
304
+ footer: ask ? /* @__PURE__ */ jsx(LabAsk, {
305
+ ask,
306
+ activity
307
+ }) : void 0,
308
+ children: figure
309
+ });
310
+ }
311
+
312
+ //#endregion
313
+ export { DomainRangeLab };
@@ -0,0 +1 @@
1
+ import { FractionBarLab, FractionBarProps } from "./preset.mjs";
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/math/fraction-bar/preset.d.ts
4
+ interface FractionBarProps {
5
+ /** Number of equal parts the whole is cut into. Default 4. */
6
+ denom?: number;
7
+ /** Starting shaded parts. Default 0. */
8
+ num?: number;
9
+ /** Goal numerator; solved when that many parts are shaded. Omit to explore. */
10
+ target?: number;
11
+ /** If set, also show the fraction OF this quantity (k/n × whole). */
12
+ whole?: number;
13
+ unit?: string;
14
+ /** Second strip cut into this many parts, to show the equivalent fraction. */
15
+ compareDenom?: number;
16
+ /** Show the decimal + percent equivalents. Default true. */
17
+ showEquiv?: boolean;
18
+ /** Optional concrete twin (any level scene): the part-whole as a pie / jar / etc. */
19
+ scene?: string;
20
+ height?: number;
21
+ title?: string;
22
+ prompt?: string;
23
+ activity?: string;
24
+ }
25
+ declare function FractionBarLab(props?: FractionBarProps): ReactNode;
26
+ //#endregion
27
+ export { FractionBarLab, FractionBarProps };
@@ -0,0 +1,197 @@
1
+ 'use client';
2
+
3
+ import { gcd, round } from "../../core/util.mjs";
4
+ import { StatusPill } from "../../kit/controls.mjs";
5
+ import { ControlBar, LabFrame } from "../../kit/frame.mjs";
6
+ import { useCheckpoint } from "../../kit/pedagogy.mjs";
7
+ import { getScene } from "../../kit/scenes.mjs";
8
+ import { BarStrip } from "../../kit/bar-strip.mjs";
9
+ import { useEffect, useState } from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { MovableDot, Segment, Stage } from "@classytic/stage";
12
+
13
+ //#region src/math/fraction-bar/preset.tsx
14
+ /**
15
+ * FractionBarLab, the authorable PART-WHOLE / fraction manipulative: a strip is
16
+ * split into `denom` equal parts and the learner drags to shade `num` of them.
17
+ * The same shaded amount reads as a fraction, a decimal, a percent, and (when a
18
+ * `whole` is set) a concrete quantity, so k/n, 0.75, 75% and "15 of 20" are
19
+ * visibly ONE thing. An optional second strip at a different denominator makes
20
+ * EQUIVALENT fractions (¾ = 6⁄8) something you see by re-cutting the same length.
21
+ *
22
+ * One engine, many uses, all data: set denom, a target to shade, a whole+unit
23
+ * for "fraction of a quantity", or a compare denominator for equivalence. Built
24
+ * on the juiced <MovableDot> (snaps to the cell boundaries, live readout).
25
+ */
26
+ function FractionBarLab(props = {}) {
27
+ const { denom = 4, target, whole, unit = "", compareDenom, showEquiv = true, scene, height = 240, title = "Fractions", prompt = target != null ? `Shade ${target}/${denom} of the strip.` : "Drag to shade the strip.", activity = "fraction-bar" } = props;
28
+ const n = Math.max(1, Math.round(denom));
29
+ const clampN = (k) => Math.max(0, Math.min(n, Math.round(k)));
30
+ const [num, setNum] = useState(clampN(props.num ?? 0));
31
+ useEffect(() => {
32
+ setNum(clampN(props.num ?? 0));
33
+ }, [props.num, n]);
34
+ const solved = target != null && num === target;
35
+ const frac = num / n;
36
+ const g = gcd(num, n);
37
+ const simp = num > 0 && g > 1 ? `${num / g}/${n / g}` : null;
38
+ const fillColor = solved ? "var(--stage-good)" : "var(--stage-accent)";
39
+ useCheckpoint({
40
+ solved,
41
+ activity,
42
+ response: `${num}/${n}`
43
+ });
44
+ const hasCompare = compareDenom != null && compareDenom > 0;
45
+ const cmpShaded = hasCompare ? Math.round(frac * compareDenom) : 0;
46
+ const cmpExact = hasCompare ? Math.abs(frac * compareDenom - cmpShaded) < 1e-9 : false;
47
+ const Y_MAIN = hasCompare ? .75 : 0;
48
+ const Y_CMP = -.95;
49
+ const yMin = hasCompare ? -2.1 : -1.5;
50
+ const yMax = hasCompare ? 1.9 : 1.2;
51
+ const figure = /* @__PURE__ */ jsxs(Stage, {
52
+ view: {
53
+ xMin: -.55,
54
+ xMax: n + .55,
55
+ yMin,
56
+ yMax
57
+ },
58
+ height,
59
+ preserveAspect: false,
60
+ pad: 14,
61
+ ariaLabel: `Fraction strip showing ${num} of ${n} parts shaded`,
62
+ children: [
63
+ /* @__PURE__ */ jsx(BarStrip, {
64
+ span: n,
65
+ cells: n,
66
+ shaded: num,
67
+ y: Y_MAIN,
68
+ color: fillColor
69
+ }),
70
+ target != null && !solved && /* @__PURE__ */ jsx(Segment, {
71
+ from: {
72
+ x: target,
73
+ y: Y_MAIN - .85
74
+ },
75
+ to: {
76
+ x: target,
77
+ y: Y_MAIN + .85
78
+ },
79
+ color: "var(--stage-good)",
80
+ weight: 1.75,
81
+ opacity: .6,
82
+ dashed: true
83
+ }),
84
+ /* @__PURE__ */ jsx(MovableDot, {
85
+ value: {
86
+ x: num,
87
+ y: Y_MAIN
88
+ },
89
+ onMove: (p) => setNum(clampN(p.x)),
90
+ constrain: "horizontal",
91
+ range: {
92
+ min: 0,
93
+ max: n
94
+ },
95
+ snap: 1,
96
+ step: 1,
97
+ readout: () => `${num}/${n}`,
98
+ color: fillColor,
99
+ r: 9,
100
+ ariaLabel: "fraction boundary"
101
+ }),
102
+ hasCompare && /* @__PURE__ */ jsx(BarStrip, {
103
+ span: n,
104
+ cells: compareDenom,
105
+ shaded: cmpShaded,
106
+ y: Y_CMP,
107
+ color: "var(--stage-accent)",
108
+ weight: 26
109
+ })
110
+ ]
111
+ });
112
+ const controls = /* @__PURE__ */ jsxs(ControlBar, { children: [
113
+ /* @__PURE__ */ jsxs("span", {
114
+ style: {
115
+ fontWeight: 700,
116
+ fontSize: 17,
117
+ fontVariantNumeric: "tabular-nums"
118
+ },
119
+ children: [
120
+ num,
121
+ "/",
122
+ n
123
+ ]
124
+ }),
125
+ hasCompare && cmpShaded > 0 && /* @__PURE__ */ jsxs("span", {
126
+ style: {
127
+ opacity: .85,
128
+ fontVariantNumeric: "tabular-nums"
129
+ },
130
+ children: [
131
+ "= ",
132
+ cmpShaded,
133
+ "/",
134
+ compareDenom,
135
+ cmpExact ? "" : " (≈)"
136
+ ]
137
+ }),
138
+ simp && /* @__PURE__ */ jsxs("span", {
139
+ style: { opacity: .75 },
140
+ children: ["= ", simp]
141
+ }),
142
+ showEquiv && /* @__PURE__ */ jsxs("span", {
143
+ style: {
144
+ opacity: .75,
145
+ fontVariantNumeric: "tabular-nums"
146
+ },
147
+ children: [
148
+ "= ",
149
+ round(frac),
150
+ " = ",
151
+ round(frac * 100),
152
+ "%"
153
+ ]
154
+ }),
155
+ whole != null && /* @__PURE__ */ jsxs("span", {
156
+ style: {
157
+ opacity: .85,
158
+ fontVariantNumeric: "tabular-nums"
159
+ },
160
+ children: [
161
+ "= ",
162
+ round(frac * whole),
163
+ unit ? ` ${unit}` : "",
164
+ " of ",
165
+ whole
166
+ ]
167
+ }),
168
+ target != null && /* @__PURE__ */ jsx(StatusPill, {
169
+ ok: solved,
170
+ children: solved ? `✓ ${target}/${n}` : `shade ${target}/${n}`
171
+ })
172
+ ] });
173
+ const twin = scene && scene !== "none" ? getScene(scene)?.render({
174
+ frac,
175
+ guessTone: solved ? "ok" : "idle",
176
+ color: fillColor,
177
+ label: `${num}/${n}`,
178
+ width: 132,
179
+ height: 170
180
+ }) : null;
181
+ return /* @__PURE__ */ jsx(LabFrame, {
182
+ title,
183
+ prompt,
184
+ controls,
185
+ aside: twin ? /* @__PURE__ */ jsx("div", {
186
+ style: {
187
+ display: "grid",
188
+ placeItems: "center"
189
+ },
190
+ children: twin
191
+ }) : void 0,
192
+ children: figure
193
+ });
194
+ }
195
+
196
+ //#endregion
197
+ export { FractionBarLab };
@@ -9,7 +9,7 @@ import { Label, Polygon, Segment, Stage } from "@classytic/stage";
9
9
 
10
10
  //#region src/math/function-machine/preset.tsx
11
11
  /**
12
- * Function machine — a "predict the rule" interactive (Brilliant-style), built
12
+ * Function machine, a "predict the rule" interactive (Brilliant-style), built
13
13
  * on @classytic/stage: inputs → outputs with index-matched connectors, a rule
14
14
  * chip, multiple-choice rules, and a Check that reports to the learner seam. A
15
15
  * GENERAL tool: a creator passes any inputs/outputs/choices/answer.
@@ -165,7 +165,7 @@ function FunctionMachineLab({ prompt = "Which rule produces these outputs?", inp
165
165
  }),
166
166
  result === "wrong" && /* @__PURE__ */ jsx(StatusPill, {
167
167
  ok: false,
168
- children: "Not quite — try another rule"
168
+ children: "Not quite, try another rule"
169
169
  })
170
170
  ] }),
171
171
  footer: /* @__PURE__ */ jsx(LiveRegion, { children: result === "correct" ? "Correct." : result === "wrong" ? "Incorrect, try again." : "" }),
@@ -10,22 +10,22 @@ import { CanvasLayer, compileExpr, differentiate, evaluate, simplify, toLatex, u
10
10
 
11
11
  //#region src/math/gradient-descent.tsx
12
12
  /**
13
- * GradientDescent — the calculus that powers machine learning, made visible.
13
+ * GradientDescent, the calculus that powers machine learning, made visible.
14
14
  *
15
15
  * Plots a 2-variable "loss surface" f(x, y) as a heatmap, then walks downhill by
16
16
  * the rule that trains every neural net: step opposite the gradient,
17
17
  * (x, y) ← (x, y) − lr · ∇f, ∇f = [∂f/∂x, ∂f/∂y].
18
18
  *
19
- * The gradient is the engine's EXACT symbolic differentiator —
20
- * `differentiate(ast, 'x')` and `differentiate(ast, 'y')` — proving the scalar
19
+ * The gradient is the engine's EXACT symbolic differentiator ,
20
+ * `differentiate(ast, 'x')` and `differentiate(ast, 'y')`, proving the scalar
21
21
  * expr engine already does multivariable partials (numerical fallback otherwise).
22
22
  *
23
23
  * This is a genuine HIGH-ELEMENT-COUNT figure (a per-pixel-cell heatmap), so it
24
24
  * renders on the engine's `<CanvasLayer>` (zero-dep raw Canvas2D, HiDPI, shares
25
- * the coordinate system + clock) instead of one SVG node per cell — and instead
25
+ * the coordinate system + clock) instead of one SVG node per cell, and instead
26
26
  * of a heavy GPU dependency. Everything ELSE (controls, KaTeX, theming) is the
27
27
  * same kit every other lab uses. Drag the start point, tune the rate, watch it
28
- * converge — or diverge.
28
+ * converge, or diverge.
29
29
  */
30
30
  const VIRIDIS = [
31
31
  [
@@ -360,7 +360,7 @@ function GradientDescent({ equation = "x^2 + 2*y^2", range = [-3, 3], start = [2
360
360
  children: [
361
361
  "“",
362
362
  equation,
363
- "” — ",
363
+ "”, ",
364
364
  model.error
365
365
  ]
366
366
  })]
@@ -18,7 +18,7 @@ interface GrapherProps {
18
18
  params?: GraphParam[];
19
19
  xRange?: [number, number];
20
20
  yRange?: [number, number] | 'auto';
21
- /** `log` plots log₁₀(y) with decade ticks — for exponentials/rates. */
21
+ /** `log` plots log₁₀(y) with decade ticks, for exponentials/rates. */
22
22
  yScale?: 'linear' | 'log';
23
23
  title?: string;
24
24
  subtitle?: string;
@@ -8,11 +8,11 @@ import { Label, Plot, Segment, Stage, compileExpr } from "@classytic/stage";
8
8
 
9
9
  //#region src/math/grapher/preset.tsx
10
10
  /**
11
- * Grapher — a creator-authored equation/function plotter on the @classytic/stage
11
+ * Grapher, a creator-authored equation/function plotter on the @classytic/stage
12
12
  * engine. A creator types one or more formulas in `x` (and named params), optionally
13
13
  * exposes params as sliders, and gets a clean auto-scaled multi-curve plot.
14
14
  *
15
- * Framed, labelled axes (NOT through-origin) so it reads cleanly for ANY window —
15
+ * Framed, labelled axes (NOT through-origin) so it reads cleanly for ANY window ,
16
16
  * including off-origin ranges like x∈[250,400] where a 0-axis would sit off-screen.
17
17
  * Supports a LOG y-scale: essential for exponentials (e.g. Arrhenius rate ∝ e^(−Eₐ/RT)),
18
18
  * where a linear axis collapses the curve onto the baseline but a log axis makes it a
@@ -40,7 +40,7 @@ function niceTicks(min, max, target = 6) {
40
40
  for (let v = Math.ceil(min / step) * step; v <= max + step * 1e-6; v += step) out.push(Math.abs(v) < step * 1e-6 ? 0 : v);
41
41
  return out;
42
42
  }
43
- /** Integer (decade) ticks for a log axis — falls back to nice ticks for a sub-decade window. */
43
+ /** Integer (decade) ticks for a log axis, falls back to nice ticks for a sub-decade window. */
44
44
  function decadeTicks(min, max) {
45
45
  const lo = Math.ceil(min - 1e-9), hi = Math.floor(max + 1e-9);
46
46
  const out = [];
@@ -297,7 +297,7 @@ function Grapher({ equations, params = [], xRange = [-6.5, 6.5], yRange = "auto"
297
297
  children: errors.map((e, i) => /* @__PURE__ */ jsxs("div", { children: [
298
298
  "“",
299
299
  e.expr,
300
- "” — ",
300
+ "”, ",
301
301
  e.error
302
302
  ] }, i))
303
303
  })] });
@@ -11,19 +11,19 @@ import { Axes, Dot, Grid, Label, Plot, Segment, Stage, Vector } from "@classytic
11
11
 
12
12
  //#region src/math/harmonic-form/preset.tsx
13
13
  /**
14
- * HarmonicFormLab — "two waves are secretly one": a cos x + b sin x = R cos(x + α).
14
+ * HarmonicFormLab, "two waves are secretly one": a cos x + b sin x = R cos(x + α).
15
15
  *
16
16
  * The whole insight is that adding a cosine and a sine of the SAME frequency gives
17
- * a SINGLE shifted cosine — and you can SEE why with phasors. The cos term is a
17
+ * a SINGLE shifted cosine, and you can SEE why with phasors. The cos term is a
18
18
  * vector of length a along the axis; the sin term is a vector of length b at a
19
19
  * right angle to it (sin lags cos by 90°). Add them tip-to-tail and the resultant
20
- * has length R = √(a²+b²) at angle α — exactly the amplitude and phase of the one
20
+ * has length R = √(a²+b²) at angle α, exactly the amplitude and phase of the one
21
21
  * combined wave. Drag a and b: the phasor triangle and the three waves update live,
22
22
  * and the messy two-wave sum visibly collapses onto one clean R cos(x + α).
23
23
  *
24
24
  * This builds the INTUITION for the auxiliary-angle form (Edexcel "express in the
25
25
  * form R cos(x+α)"). The exact R and α arithmetic is left to written working / a
26
- * paired derivation — the lab is the picture, not the algebra.
26
+ * paired derivation, the lab is the picture, not the algebra.
27
27
  *
28
28
  * Convention: a cos x + b sin x = R cos(x + α) ⇒ a = R cos α, b = −R sin α, so
29
29
  * α = atan2(−b, a) and the resultant phasor is (a, −b). Tokenized SVG; accessible.
@@ -71,7 +71,7 @@ const HARMONIC_CHALLENGE = [{
71
71
  }
72
72
  ],
73
73
  answer: "up",
74
- explain: "R = √(a² + b²) is the hypotenuse — growing either coefficient lengthens it."
74
+ explain: "R = √(a² + b²) is the hypotenuse, growing either coefficient lengthens it."
75
75
  }];
76
76
  /** LaTeX for "a cos x ± b sin x", tidy for ±1 / 0 coefficients. */
77
77
  function lhsTex(a, b) {
@@ -369,7 +369,7 @@ function HarmonicFormLab({ a: a0 = 4, b: b0 = -3, title = "Express a cos x + b s
369
369
  /* @__PURE__ */ jsx(Tex$1, { tex: "R=\\sqrt{a^2+b^2}" }),
370
370
  " and it peaks at ",
371
371
  /* @__PURE__ */ jsx(Tex$1, { tex: "x=-\\alpha" }),
372
- " — the phasor's length and angle."
372
+ ", the phasor's length and angle."
373
373
  ]
374
374
  }),
375
375
  /* @__PURE__ */ jsx(ChallengeCard, {