@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
@@ -5,24 +5,24 @@ import { Chip, Slider } from "../../kit/controls.mjs";
5
5
  import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
6
6
  import { thermalColor } from "../../kit/thermal.mjs";
7
7
  import { useState } from "react";
8
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/physics/temperature-scales/preset.tsx
11
11
  /**
12
- * TemperatureScalesLab — one temperature, three rulers. A single mercury column is
12
+ * TemperatureScalesLab, one temperature, three rulers. A single mercury column is
13
13
  * read off the Celsius, Fahrenheit and Kelvin scales side by side, so you SEE that
14
14
  * they're the same physical thing measured with differently-placed zeros and
15
15
  * differently-sized degrees:
16
16
  *
17
- * • Celsius — 0 at water's freezing point, 100 at its boiling point
18
- * • Fahrenheit — F = (9/5)C + 32 (smaller degrees, offset zero)
19
- * • Kelvin — K = C + 273.15, starting at ABSOLUTE ZERO, where molecular
20
- * motion stops — so Kelvin never goes negative (that's why science uses it)
17
+ * • Celsius , 0 at water's freezing point, 100 at its boiling point
18
+ * • Fahrenheit, F = (9/5)C + 32 (smaller degrees, offset zero)
19
+ * • Kelvin , K = C + 273.15, starting at ABSOLUTE ZERO, where molecular
20
+ * motion stops, so Kelvin never goes negative (that's why science uses it)
21
21
  *
22
22
  * Drag the temperature or jump to a fixed point; all three readouts and the marked
23
23
  * fixed-point lines update together. Interactive, no simulation. Pure SVG, themed.
24
24
  */
25
- const W = 552, H = 430;
25
+ const W = 470, H = 430;
26
26
  const C_MIN = -273.15, C_MAX = 120;
27
27
  const Y_TOP = 60, Y_BOT = 352;
28
28
  const TX = 96;
@@ -31,25 +31,25 @@ const toK = (c) => c + 273.15;
31
31
  const yOf = (c) => Y_BOT - (c - C_MIN) / (C_MAX - C_MIN) * (Y_BOT - Y_TOP);
32
32
  const COLS = [
33
33
  {
34
- x: 190,
34
+ x: 200,
35
35
  name: "°C",
36
36
  val: (c) => c,
37
37
  unit: "°"
38
38
  },
39
39
  {
40
- x: 292,
40
+ x: 308,
41
41
  name: "°F",
42
42
  val: toF,
43
43
  unit: "°"
44
44
  },
45
45
  {
46
- x: 394,
46
+ x: 410,
47
47
  name: "K",
48
48
  val: toK,
49
49
  unit: ""
50
50
  }
51
51
  ];
52
- const LINE_X0 = 152, LINE_X1 = 448, READOUT_X = 502;
52
+ const LINE_X0 = 152, LINE_X1 = 440;
53
53
  const FIXED = [
54
54
  {
55
55
  c: -273.15,
@@ -94,10 +94,10 @@ const PRESETS = [
94
94
  label: "boiling"
95
95
  }
96
96
  ];
97
- function TemperatureScalesLab({ title = "Temperature scales — one heat, three rulers", prompt = "Celsius, Fahrenheit and Kelvin measure the same temperature with different zeros and degree sizes. Drag it and watch all three — and see why Kelvin starts at absolute zero.", objectives = [
97
+ function TemperatureScalesLab({ title = "Temperature scales: one heat, three rulers", prompt = "Celsius, Fahrenheit and Kelvin measure the same temperature with different zeros and degree sizes. Drag it and watch all three, and see why Kelvin starts at absolute zero.", objectives = [
98
98
  "Convert between °C, °F and K: F = 9⁄5·C + 32, K = C + 273.15",
99
99
  "Place the fixed points (freezing 0/32/273, boiling 100/212/373)",
100
- "Explain why Kelvin is absolute — it starts where motion stops, so it’s never negative"
100
+ "Explain why Kelvin is absolute, it starts where motion stops, so it’s never negative"
101
101
  ] } = {}) {
102
102
  const [c, setC] = useState(25);
103
103
  const f = toF(c), k = toK(c);
@@ -199,124 +199,113 @@ function TemperatureScalesLab({ title = "Temperature scales — one heat, three
199
199
  stroke: col,
200
200
  strokeWidth: 2
201
201
  }),
202
- /* @__PURE__ */ jsx("circle", {
203
- cx: LINE_X1,
204
- cy: yC,
205
- r: 3.5,
206
- fill: col
207
- }),
208
- /* @__PURE__ */ jsxs("g", {
209
- transform: `translate(${READOUT_X}, ${yC})`,
210
- children: [
211
- /* @__PURE__ */ jsx("rect", {
212
- x: -46,
213
- y: -33,
214
- width: 92,
215
- height: 66,
216
- rx: 10,
217
- fill: "var(--stage-bg)",
218
- stroke: col,
219
- strokeWidth: 2
220
- }),
221
- /* @__PURE__ */ jsxs("text", {
222
- x: 0,
223
- y: -12,
224
- textAnchor: "middle",
225
- fontSize: 15,
226
- fontWeight: 800,
227
- fill: "var(--stage-fg)",
228
- style: { fontVariantNumeric: "tabular-nums" },
229
- children: [Math.round(c), " °C"]
230
- }),
231
- /* @__PURE__ */ jsxs("text", {
232
- x: 0,
233
- y: 7,
234
- textAnchor: "middle",
235
- fontSize: 12.5,
236
- fontWeight: 700,
237
- fill: "var(--stage-muted)",
238
- style: { fontVariantNumeric: "tabular-nums" },
239
- children: [Math.round(f), " °F"]
240
- }),
241
- /* @__PURE__ */ jsxs("text", {
242
- x: 0,
243
- y: 24,
244
- textAnchor: "middle",
245
- fontSize: 12.5,
246
- fontWeight: 700,
247
- fill: "var(--stage-muted)",
248
- style: { fontVariantNumeric: "tabular-nums" },
249
- children: [Math.round(k), " K"]
250
- })
251
- ]
202
+ COLS.map((co) => {
203
+ const v = Math.round(co.val(c));
204
+ return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
205
+ x: co.x - 25,
206
+ y: yC - 12,
207
+ width: 50,
208
+ height: 24,
209
+ rx: 7,
210
+ fill: "var(--stage-bg)",
211
+ stroke: col,
212
+ strokeWidth: 2
213
+ }), /* @__PURE__ */ jsxs("text", {
214
+ x: co.x,
215
+ y: yC + 4,
216
+ textAnchor: "middle",
217
+ fontSize: 12.5,
218
+ fontWeight: 800,
219
+ fill: "var(--stage-fg)",
220
+ style: { fontVariantNumeric: "tabular-nums" },
221
+ children: [v, co.unit]
222
+ })] }, `live-${co.name}`);
252
223
  })
253
224
  ]
254
225
  })
255
226
  });
256
227
  const near = FIXED.reduce((a, b) => Math.abs(b.c - c) < Math.abs(a.c - c) ? b : a);
228
+ const atFixed = Math.abs(near.c - c) < 1;
257
229
  return /* @__PURE__ */ jsx(LabFrame, {
258
230
  title,
259
231
  prompt,
260
232
  objectives,
261
- aside: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Callout, {
233
+ aside: /* @__PURE__ */ jsx(Callout, {
262
234
  tone: "result",
263
- children: /* @__PURE__ */ jsxs("span", {
235
+ children: /* @__PURE__ */ jsxs("div", {
264
236
  style: {
265
237
  display: "grid",
266
- gap: 2,
267
- fontVariantNumeric: "tabular-nums",
268
- fontWeight: 800
238
+ gap: 12
269
239
  },
270
- children: [/* @__PURE__ */ jsxs("span", {
271
- style: { fontSize: 17 },
272
- children: [c.toFixed(1), " °C"]
273
- }), /* @__PURE__ */ jsxs("span", { children: [
274
- f.toFixed(1),
275
- " °F · ",
276
- k.toFixed(1),
277
- " K"
278
- ] })]
279
- })
280
- }), /* @__PURE__ */ jsxs("div", {
281
- style: {
282
- display: "grid",
283
- gap: 8,
284
- padding: "8px 2px 0",
285
- fontSize: 13
286
- },
287
- children: [
288
- /* @__PURE__ */ jsx(Tex, {
289
- tex: "F = \\tfrac{9}{5}\\,C + 32",
290
- block: true
291
- }),
292
- /* @__PURE__ */ jsx(Tex, {
293
- tex: "K = C + 273.15",
294
- block: true
295
- }),
296
- /* @__PURE__ */ jsx(Callout, {
297
- tone: "info",
298
- children: /* @__PURE__ */ jsxs("span", { children: [
299
- /* @__PURE__ */ jsx("strong", {
240
+ children: [
241
+ /* @__PURE__ */ jsxs("div", {
242
+ style: {
243
+ display: "grid",
244
+ gap: 2,
245
+ fontVariantNumeric: "tabular-nums"
246
+ },
247
+ children: [
248
+ /* @__PURE__ */ jsxs("span", {
249
+ style: {
250
+ fontSize: 22,
251
+ fontWeight: 800
252
+ },
253
+ children: [c.toFixed(1), " °C"]
254
+ }),
255
+ /* @__PURE__ */ jsxs("span", {
256
+ style: {
257
+ fontWeight: 700,
258
+ color: "var(--stage-muted)"
259
+ },
260
+ children: [
261
+ f.toFixed(1),
262
+ " °F · ",
263
+ k.toFixed(1),
264
+ " K"
265
+ ]
266
+ }),
267
+ atFixed && /* @__PURE__ */ jsxs("span", {
268
+ style: {
269
+ color: "var(--stage-good)",
270
+ fontWeight: 700,
271
+ fontSize: 12
272
+ },
273
+ children: ["📍 ", near.label]
274
+ })
275
+ ]
276
+ }),
277
+ /* @__PURE__ */ jsxs("div", {
278
+ style: {
279
+ display: "grid",
280
+ gap: 6,
281
+ padding: "10px 12px",
282
+ borderRadius: 10,
283
+ background: "color-mix(in oklab, var(--stage-fg) 5%, transparent)",
284
+ fontSize: 13
285
+ },
286
+ children: [/* @__PURE__ */ jsx(Tex, {
287
+ tex: "F = \\tfrac{9}{5}\\,C + 32",
288
+ block: true
289
+ }), /* @__PURE__ */ jsx(Tex, {
290
+ tex: "K = C + 273.15",
291
+ block: true
292
+ })]
293
+ }),
294
+ /* @__PURE__ */ jsxs("p", {
295
+ style: {
296
+ margin: 0,
297
+ fontSize: 12.5,
298
+ lineHeight: 1.5,
299
+ color: "var(--stage-muted)"
300
+ },
301
+ children: [/* @__PURE__ */ jsx("strong", {
300
302
  style: { color: "var(--stage-fg)" },
301
303
  children: "Why Kelvin?"
302
- }),
303
- " It starts at ",
304
- /* @__PURE__ */ jsx("strong", {
305
- style: { color: "var(--stage-fg)" },
306
- children: "absolute zero"
307
- }),
308
- " (−273.15 °C), the coldest possible — molecules stop moving. So K is never negative, and doubling it really doubles the energy. C and F just put their zeros at handy everyday points."
309
- ] })
310
- }),
311
- Math.abs(near.c - c) < 1 && /* @__PURE__ */ jsxs("span", {
312
- style: {
313
- color: "var(--stage-good)",
314
- fontWeight: 700
315
- },
316
- children: ["📍 at ", near.label]
317
- })
318
- ]
319
- })] }),
304
+ }), " It starts at absolute zero (−273.15 °C), where molecules stop moving, so K is never negative and doubling it really doubles the energy. C and F just put their zeros at handy everyday points."]
305
+ })
306
+ ]
307
+ })
308
+ }),
320
309
  controls: /* @__PURE__ */ jsxs("div", {
321
310
  style: {
322
311
  display: "grid",
@@ -12,11 +12,11 @@ import { Label, Polyline, Segment, Stage, Vector } from "@classytic/stage";
12
12
 
13
13
  //#region src/physics/terminal-velocity/preset.tsx
14
14
  /**
15
- * TerminalVelocityLab — "The skydiver", why falling things stop speeding up.
15
+ * TerminalVelocityLab, "The skydiver", why falling things stop speeding up.
16
16
  *
17
17
  * A real fall isn't free fall: air pushes back with a drag that grows with speed
18
18
  * (∝ v²). Gravity (mg, constant) wins at first, but as v rises the drag catches
19
- * up until the two BALANCE — net force zero, acceleration zero, and the speed
19
+ * up until the two BALANCE, net force zero, acceleration zero, and the speed
20
20
  * levels off at the terminal velocity:
21
21
  *
22
22
  * m·dv/dt = mg − b·v² ⟹ v(t) = v_t·tanh(g·t / v_t), v_t = √(mg/b)
@@ -45,7 +45,7 @@ const TERMINAL_CHALLENGE = [{
45
45
  }
46
46
  ],
47
47
  answer: "zero",
48
- explain: "Drag balances weight, so net force is zero — the speed is constant, not the position."
48
+ explain: "Drag balances weight, so net force is zero, the speed is constant, not the position."
49
49
  }, {
50
50
  id: "when",
51
51
  prompt: "Terminal velocity happens when air resistance…",
@@ -70,7 +70,7 @@ const G = 9.8;
70
70
  const WIN = 14;
71
71
  const VMAX = 65;
72
72
  const CHUTE = 70;
73
- function TerminalVelocityLab({ mass = 80, drag = .4, parachute = false, title = "The skydiver — why you stop speeding up", prompt = "Air drag grows with speed until it balances gravity; then the net force is zero and the speed levels off at the terminal velocity v_t = √(mg/b). Watch the drag arrow rise to meet the weight, and the v–t curve flatten. Pop the parachute to crash v_t.", objectives, controlConfig }) {
73
+ function TerminalVelocityLab({ mass = 80, drag = .4, parachute = false, title = "The skydiver: why you stop speeding up", prompt = "Air drag grows with speed until it balances gravity; then the net force is zero and the speed levels off at the terminal velocity v_t = √(mg/b). Watch the drag arrow rise to meet the weight, and the v–t curve flatten. Pop the parachute to crash v_t.", objectives, controlConfig }) {
74
74
  const [m, setM] = useState(mass);
75
75
  const [d, setD] = useState(drag);
76
76
  const [chute, setChute] = useState(parachute);
@@ -348,7 +348,7 @@ function TerminalVelocityLab({ mass = 80, drag = .4, parachute = false, title =
348
348
  margin: 0
349
349
  },
350
350
  children: [
351
- "At v_t the drag exactly cancels the weight — zero net force, zero acceleration, constant speed. A parachute multiplies the drag, so v_t drops from a deadly ~",
351
+ "At v_t the drag exactly cancels the weight, zero net force, zero acceleration, constant speed. A parachute multiplies the drag, so v_t drops from a deadly ~",
352
352
  Math.round(Math.sqrt(m * G / d)),
353
353
  " m/s to a soft landing."
354
354
  ]
@@ -12,11 +12,11 @@ import { ETHANOL, ThermalCore, WATER } from "@classytic/stage/sim";
12
12
 
13
13
  //#region src/physics/thermal/preset.tsx
14
14
  /**
15
- * HeatingCurveLab — pour heat into ice and watch temperature climb in steps.
15
+ * HeatingCurveLab, pour heat into ice and watch temperature climb in steps.
16
16
  *
17
17
  * The whole heat story in one picture, driven by the shared `thermal` core: a
18
18
  * burner heats a beaker (ice → water → steam), a thermometer reads the temperature,
19
- * and the heating curve draws itself on the right — SLOPED runs where one phase
19
+ * and the heating curve draws itself on the right, SLOPED runs where one phase
20
20
  * warms (q = mcΔθ) and FLAT plateaus where it changes phase (q = mL, temperature
21
21
  * stuck while the latent heat goes in). The width of each part IS the heat it needs,
22
22
  * so water's huge boiling plateau (latent vaporisation ≫ everything) is impossible
@@ -26,7 +26,7 @@ import { ETHANOL, ThermalCore, WATER } from "@classytic/stage/sim";
26
26
  const W = 760, H = 440;
27
27
  const GX0 = 330, GX1 = 736, GY0 = 38, GY1 = 396;
28
28
  const kJ = (j) => `${(j / 1e3).toFixed(j < 1e4 ? 1 : 0)} kJ`;
29
- function HeatingCurveLab({ substance: sub0 = "water", title = "Heating curve — pour in heat, watch it climb in steps", prompt = "Heat ice until it melts, warms, and boils. Temperature RISES while one phase warms (q = mcΔθ) but stays FLAT during a phase change (q = mL).", objectives = [
29
+ function HeatingCurveLab({ substance: sub0 = "water", title = "Heating curve: pour in heat, watch it climb in steps", prompt = "Heat ice until it melts, warms, and boils. Temperature RISES while one phase warms (q = mcΔθ) but stays FLAT during a phase change (q = mL).", objectives = [
30
30
  "Read a heating curve: sloped = warming, flat = changing phase",
31
31
  "Use q = mcΔθ for a temperature change and q = mL for a phase change",
32
32
  "See why water’s boiling plateau is so wide (latent heat ≫ specific heat)"
@@ -288,7 +288,7 @@ function HeatingCurveLab({ substance: sub0 = "water", title = "Heating curve —
288
288
  },
289
289
  children: "sloped"
290
290
  }),
291
- " — warming one phase: ",
291
+ ", warming one phase: ",
292
292
  /* @__PURE__ */ jsx(Tex, { tex: "q = mc\\,\\Delta\\theta" })
293
293
  ] }), /* @__PURE__ */ jsxs("span", { children: [
294
294
  /* @__PURE__ */ jsx("span", {
@@ -298,7 +298,7 @@ function HeatingCurveLab({ substance: sub0 = "water", title = "Heating curve —
298
298
  },
299
299
  children: "flat"
300
300
  }),
301
- " — phase change: ",
301
+ ", phase change: ",
302
302
  /* @__PURE__ */ jsx(Tex, { tex: "q = mL" })
303
303
  ] })]
304
304
  })
@@ -11,16 +11,16 @@ import { Axes, Label, MovableDot, Segment, Stage, Vector, vec } from "@classytic
11
11
 
12
12
  //#region src/physics/vector-board/preset.tsx
13
13
  /**
14
- * VectorBoard — the GENERAL, authorable vector lab (CAIE/IGCSE).
14
+ * VectorBoard, the GENERAL, authorable vector lab (CAIE/IGCSE).
15
15
  *
16
16
  * A creator declares vectors (tail, components, colour, label, draggable) + how
17
17
  * to combine them (`sum` → resultant, tip-to-tail / parallelogram; `diff` →
18
18
  * relative velocity, the rain / "V_RC = V_C − V_A" case) + an optional
19
19
  * drag-to-match goal. From this one board: resultant addition, component
20
- * resolution, river-crossing, walking-home, relative-velocity — all as DATA.
20
+ * resolution, river-crossing, walking-home, relative-velocity, all as DATA.
21
21
  *
22
22
  * Built entirely on @classytic/stage primitives (Vector, MovableDot, Axes, vec
23
- * math, useLearner) + the shared LabeledVector / AngleArc helpers — nothing
23
+ * math, useLearner) + the shared LabeledVector / AngleArc helpers, nothing
24
24
  * reinvented. Drag a head, watch the resultant + angle update; land it on the
25
25
  * target to solve.
26
26
  */
@@ -34,8 +34,8 @@ const PALETTE = [
34
34
  "var(--stage-good)"
35
35
  ];
36
36
  /**
37
- * Frame the board to everything that matters — origin, every arrow tip, the
38
- * resultant, and the goal — with padding, snapped to integers for clean axes.
37
+ * Frame the board to everything that matters, origin, every arrow tip, the
38
+ * resultant, and the goal, with padding, snapped to integers for clean axes.
39
39
  * Computed from the AUTHORED vectors (not live drag state) so the view stays put
40
40
  * while the learner drags, and the resultant can never shoot off-frame.
41
41
  */
@@ -90,7 +90,7 @@ function VectorBoardLab({ view: viewProp, vectors, combine = "sum", resultantLab
90
90
  const resDeg = resultant ? Math.round(toDeg(vec.angle(resultant))) : 0;
91
91
  const resColor = solved ? "var(--stage-good)" : resultantColor;
92
92
  const showResultant = !!resultant && !(combine === "sum" && vectors.length === 1);
93
- const misconception = goal && !solved && resultant && Math.abs(vec.mag(resultant) - vec.mag(goal.match)) < tol ? "Right length — now fix the direction (rotate it onto the target)." : void 0;
93
+ const misconception = goal && !solved && resultant && Math.abs(vec.mag(resultant) - vec.mag(goal.match)) < tol ? "Right length, now fix the direction (rotate it onto the target)." : void 0;
94
94
  const figure = /* @__PURE__ */ jsxs(Stage, {
95
95
  view,
96
96
  height,
@@ -230,6 +230,7 @@ function VectorBoardLab({ view: viewProp, vectors, combine = "sum", resultantLab
230
230
  min: Math.min(view.xMin, view.yMin),
231
231
  max: Math.max(view.xMax, view.yMax)
232
232
  },
233
+ snap: snap || 1,
233
234
  color: v.color ?? PALETTE[i % PALETTE.length],
234
235
  ariaLabel: `${v.label ?? "vector"} head`
235
236
  }, `d${v.id ?? i}`) : null)
@@ -9,7 +9,7 @@ import { Axes, Dot, Grid, MovableDot, Stage } from "@classytic/stage";
9
9
 
10
10
  //#region src/physics/vector-scene.tsx
11
11
  /**
12
- * VectorScene — a GENERAL vector-algebra board (not one problem), now on the
12
+ * VectorScene, a GENERAL vector-algebra board (not one problem), now on the
13
13
  * @classytic/stage engine (SVG arrows, draggable tips, accessible).
14
14
  *
15
15
  * A creator declares named vectors; some are draggable (drag the tip to set
@@ -201,7 +201,7 @@ function VectorScene({ vectors, view, title = "Vectors", height = 340 } = {}) {
201
201
  }) : void 0;
202
202
  return /* @__PURE__ */ jsx(LabFrame, {
203
203
  title,
204
- prompt: draggables.length > 0 ? "Drag a vector’s tip to change it — sums and components update live." : void 0,
204
+ prompt: draggables.length > 0 ? "Drag a vector’s tip to change it, sums and components update live." : void 0,
205
205
  aside,
206
206
  children: figure
207
207
  });
@@ -1,19 +1,20 @@
1
1
  'use client';
2
2
 
3
3
  import { LabFrame } from "../../kit/frame.mjs";
4
+ import { ChallengeCard, useChallenge, useCheckpoint } from "../../kit/pedagogy.mjs";
4
5
  import { Fragment } from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import { Dot, Label, Stage, Vector } from "@classytic/stage";
7
8
 
8
9
  //#region src/physics/vector-types/preset.tsx
9
10
  /**
10
- * VectorTypes — a labeled reference figure for the vectors chapter opener:
11
+ * VectorTypes, a labeled reference figure for the vectors chapter opener:
11
12
  * equal, negative, null, unit, parallel, position. These are DEFINITIONAL
12
13
  * (no manipulation builds intuition here), so per the engine's video-vs-
13
14
  * interactive rule it's a clean figure, not a puzzle. Data-driven: a creator
14
15
  * can pass their own panels; the default is the standard CAIE/IGCSE set.
15
16
  *
16
- * Reuses @classytic/stage `Vector`/`Dot`/`Label` — one mini <Stage> per panel.
17
+ * Reuses @classytic/stage `Vector`/`Dot`/`Label`, one mini <Stage> per panel.
17
18
  */
18
19
  const A = "var(--stage-accent)";
19
20
  const A2 = "var(--stage-accent-2)";
@@ -77,7 +78,7 @@ const DEFAULT_TYPES = [
77
78
  },
78
79
  {
79
80
  name: "Unit (â)",
80
- caption: "Magnitude 1 — direction only.",
81
+ caption: "Magnitude 1: direction only.",
81
82
  vectors: [{
82
83
  comp: {
83
84
  x: 1,
@@ -178,9 +179,42 @@ function Panel({ p }) {
178
179
  ]
179
180
  });
180
181
  }
182
+ const CHALLENGE = [{
183
+ id: "vector-vs-scalar",
184
+ prompt: "Which of these is a VECTOR (it has a direction, not just a size)?",
185
+ choices: [
186
+ {
187
+ value: "velocity",
188
+ label: "Velocity"
189
+ },
190
+ {
191
+ value: "speed",
192
+ label: "Speed"
193
+ },
194
+ {
195
+ value: "mass",
196
+ label: "Mass"
197
+ },
198
+ {
199
+ value: "temperature",
200
+ label: "Temperature"
201
+ }
202
+ ],
203
+ answer: "velocity",
204
+ explain: "Velocity is a vector: it carries a direction (e.g. 5 m/s north). Speed, mass and temperature are scalars: magnitude only."
205
+ }];
181
206
  function VectorTypesLab({ types = DEFAULT_TYPES, title = "Types of vectors" }) {
207
+ const ch = useChallenge(CHALLENGE);
208
+ useCheckpoint({
209
+ solved: ch.allCorrect,
210
+ activity: "vector-types"
211
+ });
182
212
  return /* @__PURE__ */ jsx(LabFrame, {
183
213
  title,
214
+ footer: /* @__PURE__ */ jsx(ChallengeCard, {
215
+ questions: CHALLENGE,
216
+ state: ch
217
+ }),
184
218
  children: /* @__PURE__ */ jsx("div", {
185
219
  className: "lang-typegrid",
186
220
  children: types.map((p, i) => /* @__PURE__ */ jsx(Panel, { p }, i))
@@ -8,14 +8,14 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/physics/water-density/preset.tsx
10
10
  /**
11
- * WaterDensityLab — water's strange, life-saving anomaly. Almost everything gets
11
+ * WaterDensityLab, water's strange, life-saving anomaly. Almost everything gets
12
12
  * denser as it cools, but water is DENSEST at about 4 °C; cool it further toward 0
13
- * and it expands again, and ice is less dense still — so ice floats.
13
+ * and it expands again, and ice is less dense still, so ice floats.
14
14
  *
15
- * • THE 4 °C ANOMALY — a density–temperature curve that peaks at 4 °C (zoomed in,
15
+ * • THE 4 °C ANOMALY, a density–temperature curve that peaks at 4 °C (zoomed in,
16
16
  * because the bump is tiny). Drag the temperature and watch the density rise to
17
17
  * a maximum at 4 °C, then fall.
18
- * • WHY LAKES FREEZE TOP-DOWN — a lake cross-section: the densest 4 °C water sinks
18
+ * • WHY LAKES FREEZE TOP-DOWN, a lake cross-section: the densest 4 °C water sinks
19
19
  * to the bottom, colder water sits above it, and ice forms on the surface. The
20
20
  * ice blanket insulates the liquid water below, so fish survive the winter.
21
21
  *
@@ -47,9 +47,9 @@ function densityOf(t) {
47
47
  }
48
48
  return SAMPLES[SAMPLES.length - 1][1];
49
49
  }
50
- function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C anomaly — why ice floats", prompt = "Almost everything shrinks as it cools, but water is densest at 4 °C and expands again toward freezing — so ice floats and lakes freeze from the top down.", objectives = [
50
+ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C anomaly: why ice floats", prompt = "Almost everything shrinks as it cools, but water is densest at 4 °C and expands again toward freezing, so ice floats and lakes freeze from the top down.", objectives = [
51
51
  "See water reach maximum density at about 4 °C (not at 0 °C)",
52
- "Explain why ice floats — it is LESS dense than liquid water",
52
+ "Explain why ice floats, it is LESS dense than liquid water",
53
53
  "Explain why a lake freezes top-down, leaving 4 °C water (and fish) below"
54
54
  ] } = {}) {
55
55
  const [mode, setMode] = useState(mode0);
@@ -219,7 +219,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
219
219
  y0: iceBot,
220
220
  y1: 150,
221
221
  t: 0,
222
- label: "0 °C — just above freezing"
222
+ label: "0 °C: just above freezing"
223
223
  },
224
224
  {
225
225
  y0: 150,
@@ -237,7 +237,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
237
237
  y0: 270,
238
238
  y1: bot,
239
239
  t: 4,
240
- label: "4 °C — densest water sinks here"
240
+ label: "4 °C: densest water sinks here"
241
241
  }
242
242
  ].map((b, i) => /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
243
243
  x: lx,
@@ -335,7 +335,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
335
335
  "at ",
336
336
  tC,
337
337
  " °C",
338
- Math.abs(tC - 4) < .6 ? " — maximum!" : ""
338
+ Math.abs(tC - 4) < .6 ? ", maximum!" : ""
339
339
  ]
340
340
  })
341
341
  }), /* @__PURE__ */ jsxs("div", {
@@ -347,7 +347,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
347
347
  color: "var(--stage-muted)"
348
348
  },
349
349
  children: [/* @__PURE__ */ jsxs("span", { children: [
350
- "As liquid water cools it gets denser — but only down to ",
350
+ "As liquid water cools it gets denser, but only down to ",
351
351
  /* @__PURE__ */ jsx("strong", {
352
352
  style: { color: "var(--stage-fg)" },
353
353
  children: "4 °C"
@@ -364,7 +364,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
364
364
  style: { color: "var(--stage-fg)" },
365
365
  children: [ICE_RHO, " kg/m³"]
366
366
  }),
367
- " — much less than water — which is why it floats."
367
+ ", much less than water, which is why it floats."
368
368
  ] })]
369
369
  })] }) : /* @__PURE__ */ jsxs("div", {
370
370
  style: {
@@ -390,7 +390,7 @@ function WaterDensityLab({ mode: mode0 = "anomaly", title = "Water’s 4 °C ano
390
390
  style: { color: "var(--stage-fg)" },
391
391
  children: "insulates"
392
392
  }),
393
- " the water beneath, so the lake never freezes solid — and the fish survive at 4 °C. If water were \"normal\", lakes would freeze bottom-up and kill everything."
393
+ " the water beneath, so the lake never freezes solid, and the fish survive at 4 °C. If water were \"normal\", lakes would freeze bottom-up and kill everything."
394
394
  ] })]
395
395
  }),
396
396
  controls: /* @__PURE__ */ jsxs("div", {
@@ -12,11 +12,11 @@ import { CanvasLayer, useControlSurface } from "@classytic/stage";
12
12
 
13
13
  //#region src/physics/waves/doppler.tsx
14
14
  /**
15
- * DopplerLab — why a passing siren drops in pitch. A source glides across the tank
15
+ * DopplerLab, why a passing siren drops in pitch. A source glides across the tank
16
16
  * emitting wavefronts at a steady rate; because it CHASES its own waves, the fronts
17
17
  * bunch up ahead (shorter λ → higher pitch) and spread out behind (longer λ → lower
18
18
  * pitch). Crank the speed past the wave speed (Mach > 1) and the fronts pile into a
19
- * shock CONE — the sonic boom. A fixed listener hears the classic high→low sweep as
19
+ * shock CONE, the sonic boom. A fixed listener hears the classic high→low sweep as
20
20
  * the source approaches then recedes; 🔊 plays that Doppler-shifted tone for real.
21
21
  *
22
22
  * f_observed = f_source · c / (c − v_radial)
@@ -12,12 +12,12 @@ import { CanvasLayer, useControlSurface, useFrameLoop } from "@classytic/stage";
12
12
 
13
13
  //#region src/physics/waves/preset.tsx
14
14
  /**
15
- * WaveLab — one playground for the whole of waves, animated on <CanvasLayer>.
16
- * • travelling — a wave you SHAPE (amplitude, wavelength, frequency); v = fλ falls
15
+ * WaveLab, one playground for the whole of waves, animated on <CanvasLayer>.
16
+ * • travelling, a wave you SHAPE (amplitude, wavelength, frequency); v = fλ falls
17
17
  * out live, with λ and A marked right on the wave.
18
- * • superpose — two waves add; line them up (constructive, 2A) or oppose them
18
+ * • superpose , two waves add; line them up (constructive, 2A) or oppose them
19
19
  * (destructive, flat), or detune the second → BEATS (a throbbing envelope).
20
- * • standing — two opposite waves lock into a standing wave: fixed NODES (never
20
+ * • standing , two opposite waves lock into a standing wave: fixed NODES (never
21
21
  * move) and ANTINODES (max swing), with a harmonic selector (λ = 2L/n).
22
22
  * Optional 🔊 maps the frequency into the audible range (two tones in beats mode, so
23
23
  * you HEAR the wah-wah). All maths from the wave kernel; honours reduced-motion.