@classytic/labs 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/biology/enzyme-rate/preset.mjs +5 -5
  3. package/dist/biology/genetic-cross/core.d.mts +7 -7
  4. package/dist/biology/genetic-cross/core.mjs +4 -4
  5. package/dist/biology/genetic-cross/grid.mjs +132 -123
  6. package/dist/biology/genetic-cross/preset.mjs +4 -4
  7. package/dist/biology/genetic-cross/sex-linked.mjs +7 -7
  8. package/dist/biology/photosynthesis-factors/preset.mjs +8 -8
  9. package/dist/biology/respiration/preset.mjs +4 -4
  10. package/dist/biology/sequence/central-dogma.mjs +5 -5
  11. package/dist/biology/sequence/core.d.mts +6 -6
  12. package/dist/biology/sequence/core.mjs +1 -1
  13. package/dist/biology/sequence/preset.mjs +6 -6
  14. package/dist/blocks/authoring.mjs +5 -5
  15. package/dist/blocks/biology.d.mts +2 -2
  16. package/dist/blocks/biology.mjs +5 -5
  17. package/dist/blocks/chem.d.mts +2 -2
  18. package/dist/blocks/chem.mjs +13 -13
  19. package/dist/blocks/circuits.d.mts +293 -4
  20. package/dist/blocks/circuits.mjs +874 -9
  21. package/dist/blocks/discrete.d.mts +30 -2
  22. package/dist/blocks/discrete.mjs +74 -4
  23. package/dist/blocks/economics.mjs +1 -1
  24. package/dist/blocks/geography.mjs +1 -1
  25. package/dist/blocks/geometry.mjs +3 -3
  26. package/dist/blocks/ict.d.mts +90 -1
  27. package/dist/blocks/ict.mjs +217 -7
  28. package/dist/blocks/index.d.mts +3064 -657
  29. package/dist/blocks/index.mjs +9 -9
  30. package/dist/blocks/lab-block.mjs +5 -5
  31. package/dist/blocks/lab-config.d.mts +1 -1
  32. package/dist/blocks/lab-config.mjs +4 -4
  33. package/dist/blocks/lab-gallery.d.mts +1 -1
  34. package/dist/blocks/lab-gallery.mjs +2 -2
  35. package/dist/blocks/language.d.mts +6 -6
  36. package/dist/blocks/language.mjs +12 -12
  37. package/dist/blocks/lesson.mjs +4 -4
  38. package/dist/blocks/math.d.mts +577 -11
  39. package/dist/blocks/math.mjs +1648 -14
  40. package/dist/blocks/ml.d.mts +45 -1
  41. package/dist/blocks/ml.mjs +80 -6
  42. package/dist/blocks/physics.d.mts +9 -4
  43. package/dist/blocks/physics.mjs +75 -28
  44. package/dist/blocks/statistics.mjs +1 -1
  45. package/dist/build/CircuitEditor.d.mts +14 -0
  46. package/dist/build/CircuitEditor.mjs +787 -0
  47. package/dist/build/CircuitPlayer.d.mts +19 -0
  48. package/dist/build/CircuitPlayer.mjs +53 -0
  49. package/dist/build/CircuitScene.d.mts +61 -0
  50. package/dist/build/CircuitScene.mjs +383 -0
  51. package/dist/build/contract.d.mts +116 -0
  52. package/dist/build/editor-ops.d.mts +65 -0
  53. package/dist/build/editor-ops.mjs +306 -0
  54. package/dist/build/editor-ui.mjs +121 -0
  55. package/dist/build/flow.d.mts +14 -0
  56. package/dist/build/flow.mjs +119 -0
  57. package/dist/build/index.d.mts +10 -0
  58. package/dist/build/index.mjs +10 -0
  59. package/dist/build/parts/ammeter.d.mts +1 -0
  60. package/dist/build/parts/ammeter.mjs +32 -0
  61. package/dist/build/parts/bulb.d.mts +1 -0
  62. package/dist/build/parts/bulb.mjs +50 -0
  63. package/dist/build/parts/capacitor.d.mts +1 -0
  64. package/dist/build/parts/capacitor.mjs +26 -0
  65. package/dist/build/parts/cell.d.mts +1 -0
  66. package/dist/build/parts/cell.mjs +40 -0
  67. package/dist/build/parts/diode.d.mts +1 -0
  68. package/dist/build/parts/diode.mjs +33 -0
  69. package/dist/build/parts/index.d.mts +5 -0
  70. package/dist/build/parts/index.mjs +43 -0
  71. package/dist/build/parts/mosfet.d.mts +1 -0
  72. package/dist/build/parts/mosfet.mjs +95 -0
  73. package/dist/build/parts/node.d.mts +1 -0
  74. package/dist/build/parts/node.mjs +32 -0
  75. package/dist/build/parts/resistor.d.mts +1 -0
  76. package/dist/build/parts/resistor.mjs +49 -0
  77. package/dist/build/parts/shared.mjs +42 -0
  78. package/dist/build/parts/switch.d.mts +1 -0
  79. package/dist/build/parts/switch.mjs +34 -0
  80. package/dist/build/parts.d.mts +1 -0
  81. package/dist/build/registry.d.mts +9 -0
  82. package/dist/build/registry.mjs +15 -0
  83. package/dist/build/solve.d.mts +8 -0
  84. package/dist/build/solve.mjs +0 -0
  85. package/dist/catalog/registry.d.mts +2 -2
  86. package/dist/catalog/templates.d.mts +1 -1
  87. package/dist/catalog/templates.mjs +6 -6
  88. package/dist/chem/battery.mjs +1 -1
  89. package/dist/chem/bohr-atom.mjs +4 -4
  90. package/dist/chem/diffusion/preset.mjs +4 -4
  91. package/dist/chem/electrochem/preset.mjs +5 -5
  92. package/dist/chem/equilibrium/preset.d.mts +1 -1
  93. package/dist/chem/equilibrium/preset.mjs +6 -6
  94. package/dist/chem/gas-box/preset.mjs +6 -6
  95. package/dist/chem/kinetics/preset.mjs +6 -6
  96. package/dist/chem/periodic-trends/preset.mjs +7 -7
  97. package/dist/chem/reaction-lab.mjs +3 -3
  98. package/dist/chem/reaction-profile.mjs +4 -4
  99. package/dist/chem/solution/dilution.mjs +6 -6
  100. package/dist/chem/solution/field.d.mts +2 -2
  101. package/dist/chem/solution/field.mjs +2 -2
  102. package/dist/chem/solution/solution-box.mjs +7 -7
  103. package/dist/chem/stoichiometry/preset.mjs +5 -5
  104. package/dist/chem/titration/preset.mjs +5 -5
  105. package/dist/circuits/ac-dc/asset.mjs +1 -1
  106. package/dist/circuits/ac-dc/preset.mjs +2 -2
  107. package/dist/circuits/brownout/index.d.mts +1 -0
  108. package/dist/circuits/brownout/preset.d.mts +22 -0
  109. package/dist/circuits/brownout/preset.mjs +399 -0
  110. package/dist/circuits/capacitor-leak/preset.mjs +13 -8
  111. package/dist/circuits/circuit/asset.mjs +71 -14
  112. package/dist/circuits/circuit/preset.mjs +23 -5
  113. package/dist/circuits/circuit-builder.mjs +60 -132
  114. package/dist/circuits/circuit-lab.mjs +60 -40
  115. package/dist/circuits/cmos-gate/index.d.mts +1 -0
  116. package/dist/circuits/cmos-gate/preset.d.mts +75 -0
  117. package/dist/circuits/cmos-gate/preset.mjs +1491 -0
  118. package/dist/circuits/diode/index.d.mts +1 -0
  119. package/dist/circuits/diode/preset.d.mts +25 -0
  120. package/dist/circuits/diode/preset.mjs +266 -0
  121. package/dist/circuits/index.d.mts +7 -1
  122. package/dist/circuits/index.mjs +7 -1
  123. package/dist/circuits/rc-charging/index.d.mts +1 -0
  124. package/dist/circuits/rc-charging/preset.d.mts +27 -0
  125. package/dist/circuits/rc-charging/preset.mjs +329 -0
  126. package/dist/circuits/semiconductor/index.d.mts +1 -0
  127. package/dist/circuits/semiconductor/preset.d.mts +102 -0
  128. package/dist/circuits/semiconductor/preset.mjs +1855 -0
  129. package/dist/circuits/transistor/index.d.mts +1 -0
  130. package/dist/circuits/transistor/preset.d.mts +27 -0
  131. package/dist/circuits/transistor/preset.mjs +329 -0
  132. package/dist/commerce/accounting/core.d.mts +1 -1
  133. package/dist/commerce/accounting/equation-balance.mjs +5 -5
  134. package/dist/commerce/accounting/journal-poster.mjs +8 -8
  135. package/dist/commerce/accounting/statement-sorter.mjs +4 -4
  136. package/dist/commerce/economics/core.d.mts +2 -2
  137. package/dist/commerce/economics/core.mjs +1 -1
  138. package/dist/commerce/economics/demand-shift-vs-move.mjs +6 -6
  139. package/dist/commerce/economics/elasticity-revenue.mjs +6 -6
  140. package/dist/commerce/economics/market-equilibrium.mjs +5 -5
  141. package/dist/core/easing.d.mts +3 -3
  142. package/dist/core/easing.mjs +2 -2
  143. package/dist/core/numeric.d.mts +3 -3
  144. package/dist/core/numeric.mjs +2 -2
  145. package/dist/core/reactive.d.mts +1 -1
  146. package/dist/core/reactive.mjs +1 -1
  147. package/dist/core/rng.d.mts +2 -2
  148. package/dist/core/rng.mjs +1 -1
  149. package/dist/core/tex.mjs +2 -2
  150. package/dist/core/timeline.d.mts +1 -1
  151. package/dist/core/timeline.mjs +1 -1
  152. package/dist/core/util.mjs +11 -1
  153. package/dist/discrete/arrangements/preset.mjs +6 -14
  154. package/dist/discrete/bayes/preset.mjs +43 -35
  155. package/dist/discrete/binomial/preset.mjs +2 -2
  156. package/dist/discrete/combination-studio/figure.d.mts +6 -0
  157. package/dist/discrete/combination-studio/figure.mjs +159 -0
  158. package/dist/discrete/combination-studio/index.d.mts +2 -0
  159. package/dist/discrete/combination-studio/preset.d.mts +44 -0
  160. package/dist/discrete/combination-studio/preset.mjs +440 -0
  161. package/dist/discrete/core/combinatorics.d.mts +23 -3
  162. package/dist/discrete/core/combinatorics.mjs +38 -3
  163. package/dist/discrete/core/pigeonhole.d.mts +1 -1
  164. package/dist/discrete/core/pigeonhole.mjs +1 -1
  165. package/dist/discrete/core/probability.d.mts +3 -3
  166. package/dist/discrete/core/probability.mjs +3 -3
  167. package/dist/discrete/core/sets.d.mts +1 -1
  168. package/dist/discrete/counting-slots/preset.mjs +8 -8
  169. package/dist/discrete/counting-tree/preset.mjs +65 -8
  170. package/dist/discrete/expected-value/preset.mjs +13 -13
  171. package/dist/discrete/hypergeometric/preset.mjs +48 -15
  172. package/dist/discrete/index.d.mts +4 -2
  173. package/dist/discrete/index.mjs +4 -2
  174. package/dist/discrete/karnaugh/preset.mjs +26 -20
  175. package/dist/discrete/lln/preset.mjs +44 -3
  176. package/dist/discrete/logic-circuit/preset.mjs +2 -2
  177. package/dist/discrete/monte-carlo/preset.d.mts +1 -1
  178. package/dist/discrete/monte-carlo/preset.mjs +14 -14
  179. package/dist/discrete/monty-hall/preset.mjs +6 -6
  180. package/dist/discrete/outcome-builder/preset.mjs +3 -3
  181. package/dist/discrete/pascal/preset.mjs +37 -7
  182. package/dist/discrete/rules.d.mts +20 -0
  183. package/dist/discrete/rules.mjs +264 -0
  184. package/dist/discrete/sample-space/preset.mjs +4 -4
  185. package/dist/discrete/selection/preset.mjs +7 -13
  186. package/dist/discrete/truth-table/preset.mjs +32 -9
  187. package/dist/discrete/venn/preset.mjs +71 -48
  188. package/dist/geography/cycle-lab/preset.mjs +17 -10
  189. package/dist/geography/cycles.d.mts +3 -3
  190. package/dist/geography/cycles.mjs +3 -3
  191. package/dist/geometry/board/preset.d.mts +2 -0
  192. package/dist/geometry/board/preset.mjs +11 -15
  193. package/dist/geometry/builder.mjs +3 -3
  194. package/dist/ict/number-systems/base-odometer.mjs +4 -4
  195. package/dist/ict/number-systems/bit-grouper.d.mts +1 -1
  196. package/dist/ict/number-systems/bit-grouper.mjs +4 -4
  197. package/dist/ict/number-systems/place-value-dial.d.mts +1 -1
  198. package/dist/ict/number-systems/place-value-dial.mjs +3 -3
  199. package/dist/ict/number-systems/wheel.d.mts +3 -3
  200. package/dist/ict/number-systems/wheel.mjs +4 -4
  201. package/dist/kit/annotate.mjs +3 -3
  202. package/dist/kit/answer-check.d.mts +2 -2
  203. package/dist/kit/answer-check.mjs +34 -6
  204. package/dist/kit/ask.d.mts +19 -0
  205. package/dist/kit/ask.mjs +46 -0
  206. package/dist/kit/bar-strip.mjs +53 -0
  207. package/dist/kit/calc.d.mts +33 -0
  208. package/dist/kit/calc.mjs +27 -0
  209. package/dist/kit/carrier-engine.mjs +147 -0
  210. package/dist/kit/clue-scene.d.mts +86 -0
  211. package/dist/kit/clue-scene.mjs +424 -0
  212. package/dist/kit/cluster.d.mts +30 -0
  213. package/dist/kit/cluster.mjs +81 -0
  214. package/dist/kit/controls.mjs +11 -5
  215. package/dist/kit/coords.d.mts +88 -0
  216. package/dist/kit/coords.mjs +192 -0
  217. package/dist/kit/data-scene.d.mts +27 -0
  218. package/dist/kit/data-scene.mjs +199 -0
  219. package/dist/kit/diagram.mjs +111 -50
  220. package/dist/kit/electronics.mjs +552 -60
  221. package/dist/kit/expr-analysis.d.mts +18 -6
  222. package/dist/kit/expr-analysis.mjs +82 -28
  223. package/dist/kit/frame.d.mts +3 -3
  224. package/dist/kit/frame.mjs +25 -6
  225. package/dist/kit/gameshow.mjs +2 -2
  226. package/dist/kit/index.d.mts +14 -2
  227. package/dist/kit/index.mjs +13 -1
  228. package/dist/kit/logic-gates.mjs +246 -47
  229. package/dist/kit/palette.mjs +26 -0
  230. package/dist/kit/pedagogy.d.mts +4 -4
  231. package/dist/kit/pedagogy.mjs +21 -17
  232. package/dist/kit/play.d.mts +1 -1
  233. package/dist/kit/play.mjs +3 -3
  234. package/dist/kit/predict.d.mts +55 -0
  235. package/dist/kit/predict.mjs +146 -0
  236. package/dist/kit/receipt.d.mts +29 -0
  237. package/dist/kit/receipt.mjs +94 -0
  238. package/dist/kit/rich.mjs +2 -2
  239. package/dist/kit/rule.d.mts +59 -0
  240. package/dist/kit/rule.mjs +215 -0
  241. package/dist/kit/scale.mjs +1 -1
  242. package/dist/kit/scene-library.d.mts +22 -0
  243. package/dist/kit/scene-library.mjs +311 -0
  244. package/dist/kit/scene-studio.d.mts +14 -0
  245. package/dist/kit/scene-studio.mjs +338 -0
  246. package/dist/kit/scenes.d.mts +31 -0
  247. package/dist/kit/scenes.mjs +569 -0
  248. package/dist/kit/slot-fill.d.mts +61 -0
  249. package/dist/kit/slot-fill.mjs +207 -0
  250. package/dist/kit/solve.d.mts +21 -0
  251. package/dist/kit/solve.mjs +75 -0
  252. package/dist/kit/space.mjs +5 -5
  253. package/dist/kit/steps.mjs +2 -2
  254. package/dist/kit/vessel.d.mts +69 -0
  255. package/dist/kit/vessel.mjs +191 -0
  256. package/dist/language/agreement/preset.mjs +2 -2
  257. package/dist/language/article-lens/preset.d.mts +1 -1
  258. package/dist/language/article-lens/preset.mjs +8 -8
  259. package/dist/language/deck.d.mts +3 -3
  260. package/dist/language/deck.mjs +1 -1
  261. package/dist/language/preposition-scene/preset.d.mts +2 -2
  262. package/dist/language/preposition-scene/preset.mjs +5 -5
  263. package/dist/language/sentence-builder/preset.mjs +5 -5
  264. package/dist/language/transform/preset.d.mts +2 -2
  265. package/dist/language/transform/preset.mjs +5 -5
  266. package/dist/language/ui.d.mts +3 -3
  267. package/dist/language/ui.mjs +4 -4
  268. package/dist/language/word-match/preset.mjs +3 -3
  269. package/dist/logic/LogicBuildLab.d.mts +22 -0
  270. package/dist/logic/LogicBuildLab.mjs +170 -0
  271. package/dist/logic/LogicEditScene.d.mts +31 -0
  272. package/dist/logic/LogicEditScene.mjs +276 -0
  273. package/dist/logic/LogicEditor.d.mts +14 -0
  274. package/dist/logic/LogicEditor.mjs +413 -0
  275. package/dist/logic/LogicScene.d.mts +32 -0
  276. package/dist/logic/LogicScene.mjs +277 -0
  277. package/dist/logic/contract.d.mts +72 -0
  278. package/dist/logic/display.d.mts +24 -0
  279. package/dist/logic/display.mjs +127 -0
  280. package/dist/logic/edit-ops.d.mts +44 -0
  281. package/dist/logic/edit-ops.mjs +177 -0
  282. package/dist/logic/evaluate.d.mts +11 -0
  283. package/dist/logic/evaluate.mjs +93 -0
  284. package/dist/logic/gates.d.mts +10 -0
  285. package/dist/logic/gates.mjs +73 -0
  286. package/dist/logic/index.d.mts +14 -0
  287. package/dist/logic/index.mjs +13 -0
  288. package/dist/logic/lab.d.mts +32 -0
  289. package/dist/logic/lab.mjs +160 -0
  290. package/dist/logic/presets.d.mts +12 -0
  291. package/dist/logic/presets.mjs +241 -0
  292. package/dist/logic/registry.d.mts +9 -0
  293. package/dist/logic/registry.mjs +15 -0
  294. package/dist/math/area-model/preset.mjs +70 -44
  295. package/dist/math/balance-algebra/preset.mjs +14 -5
  296. package/dist/math/broken-tree/index.d.mts +1 -0
  297. package/dist/math/broken-tree/preset.d.mts +26 -0
  298. package/dist/math/broken-tree/preset.mjs +435 -0
  299. package/dist/math/circle/index.d.mts +1 -0
  300. package/dist/math/circle/preset.d.mts +44 -0
  301. package/dist/math/circle/preset.mjs +198 -0
  302. package/dist/math/complex/core.d.mts +93 -0
  303. package/dist/math/complex/core.mjs +239 -0
  304. package/dist/math/complex/index.d.mts +3 -0
  305. package/dist/math/complex/preset.d.mts +31 -0
  306. package/dist/math/complex/preset.mjs +377 -0
  307. package/dist/math/complex/rules.d.mts +6 -0
  308. package/dist/math/complex/rules.mjs +121 -0
  309. package/dist/math/conic/index.d.mts +1 -0
  310. package/dist/math/conic/preset.d.mts +30 -0
  311. package/dist/math/conic/preset.mjs +334 -0
  312. package/dist/math/derivation.mjs +5 -5
  313. package/dist/math/derivative-explorer/preset.mjs +5 -5
  314. package/dist/math/domain-range/index.d.mts +1 -0
  315. package/dist/math/domain-range/preset.d.mts +33 -0
  316. package/dist/math/domain-range/preset.mjs +313 -0
  317. package/dist/math/fraction-bar/index.d.mts +1 -0
  318. package/dist/math/fraction-bar/preset.d.mts +27 -0
  319. package/dist/math/fraction-bar/preset.mjs +197 -0
  320. package/dist/math/function-machine/preset.mjs +2 -2
  321. package/dist/math/gradient-descent.mjs +6 -6
  322. package/dist/math/grapher/preset.d.mts +1 -1
  323. package/dist/math/grapher/preset.mjs +4 -4
  324. package/dist/math/harmonic-form/preset.mjs +6 -6
  325. package/dist/math/index.d.mts +27 -2
  326. package/dist/math/index.mjs +27 -2
  327. package/dist/math/integral-explorer/preset.mjs +2 -2
  328. package/dist/math/interactive/preset.mjs +3 -3
  329. package/dist/math/limit-explorer/preset.mjs +4 -4
  330. package/dist/math/linear-model/index.d.mts +1 -0
  331. package/dist/math/linear-model/preset.d.mts +53 -0
  332. package/dist/math/linear-model/preset.mjs +164 -0
  333. package/dist/math/linear-system/preset.mjs +4 -4
  334. package/dist/math/mystery-bucket/preset.mjs +6 -6
  335. package/dist/math/number-line/preset.mjs +3 -2
  336. package/dist/math/parabola/preset.mjs +4 -3
  337. package/dist/math/pattern/preset.mjs +7 -13
  338. package/dist/math/percent-bar/index.d.mts +1 -0
  339. package/dist/math/percent-bar/preset.d.mts +37 -0
  340. package/dist/math/percent-bar/preset.mjs +275 -0
  341. package/dist/math/poly/core.d.mts +50 -0
  342. package/dist/math/poly/core.mjs +268 -0
  343. package/dist/math/poly/index.d.mts +3 -0
  344. package/dist/math/poly/preset.d.mts +23 -0
  345. package/dist/math/poly/preset.mjs +141 -0
  346. package/dist/math/poly/steps.d.mts +10 -0
  347. package/dist/math/poly/steps.mjs +99 -0
  348. package/dist/math/rate-machine/index.d.mts +1 -0
  349. package/dist/math/rate-machine/preset.d.mts +35 -0
  350. package/dist/math/rate-machine/preset.mjs +281 -0
  351. package/dist/math/ratio-share/index.d.mts +1 -0
  352. package/dist/math/ratio-share/preset.d.mts +24 -0
  353. package/dist/math/ratio-share/preset.mjs +204 -0
  354. package/dist/math/receipt/index.d.mts +1 -0
  355. package/dist/math/receipt/preset.d.mts +22 -0
  356. package/dist/math/receipt/preset.mjs +137 -0
  357. package/dist/math/sequence-predict/index.d.mts +1 -0
  358. package/dist/math/sequence-predict/preset.d.mts +34 -0
  359. package/dist/math/sequence-predict/preset.mjs +130 -0
  360. package/dist/math/straight-line/index.d.mts +1 -0
  361. package/dist/math/straight-line/preset.d.mts +37 -0
  362. package/dist/math/straight-line/preset.mjs +374 -0
  363. package/dist/math/system-solve/index.d.mts +1 -0
  364. package/dist/math/system-solve/preset.d.mts +21 -0
  365. package/dist/math/system-solve/preset.mjs +227 -0
  366. package/dist/math/transform/index.d.mts +1 -0
  367. package/dist/math/transform/preset.d.mts +41 -0
  368. package/dist/math/transform/preset.mjs +343 -0
  369. package/dist/math/triangle-trig/preset.mjs +12 -9
  370. package/dist/math/trig/core.d.mts +37 -0
  371. package/dist/math/trig/core.mjs +150 -0
  372. package/dist/math/trig/diagrams.d.mts +1 -0
  373. package/dist/math/trig/diagrams.mjs +321 -0
  374. package/dist/math/trig/index.d.mts +3 -0
  375. package/dist/math/trig/preset.d.mts +25 -0
  376. package/dist/math/trig/preset.mjs +260 -0
  377. package/dist/math/trig/rules.d.mts +6 -0
  378. package/dist/math/trig/rules.mjs +159 -0
  379. package/dist/math/trig-explorer.mjs +4 -4
  380. package/dist/ml/boundary/preset.mjs +8 -3
  381. package/dist/ml/classifier/preset.mjs +31 -6
  382. package/dist/ml/kmeans/preset.mjs +4 -4
  383. package/dist/ml/knn/preset.mjs +47 -12
  384. package/dist/ml/regression/preset.mjs +36 -7
  385. package/dist/physics/atwood/preset.mjs +4 -4
  386. package/dist/physics/bullet-walls/preset.d.mts +1 -1
  387. package/dist/physics/bullet-walls/preset.mjs +7 -7
  388. package/dist/physics/carnot/preset.mjs +6 -6
  389. package/dist/physics/circular-motion/preset.mjs +36 -5
  390. package/dist/physics/collision-track/preset.mjs +35 -5
  391. package/dist/physics/efficiency/preset.d.mts +2 -2
  392. package/dist/physics/efficiency/preset.mjs +5 -5
  393. package/dist/physics/electric-field/preset.mjs +32 -23
  394. package/dist/physics/electric-flux/index.d.mts +1 -0
  395. package/dist/physics/electric-flux/preset.d.mts +29 -0
  396. package/dist/physics/electric-flux/preset.mjs +264 -0
  397. package/dist/physics/energy-skate/preset.mjs +5 -5
  398. package/dist/physics/entropy/preset.mjs +7 -7
  399. package/dist/physics/expansion/preset.mjs +13 -13
  400. package/dist/physics/exponential/asset.mjs +1 -1
  401. package/dist/physics/exponential/preset.mjs +4 -4
  402. package/dist/physics/gas-process/preset.mjs +3 -3
  403. package/dist/physics/gauss-law/index.d.mts +1 -0
  404. package/dist/physics/gauss-law/preset.d.mts +20 -0
  405. package/dist/physics/gauss-law/preset.mjs +286 -0
  406. package/dist/physics/gravitation/preset.mjs +7 -7
  407. package/dist/physics/gravity-drop.mjs +4 -4
  408. package/dist/physics/heat-transfer/preset.d.mts +1 -1
  409. package/dist/physics/heat-transfer/preset.mjs +10 -10
  410. package/dist/physics/impulse/preset.mjs +5 -5
  411. package/dist/physics/index.d.mts +4 -1
  412. package/dist/physics/index.mjs +4 -1
  413. package/dist/physics/kepler/preset.mjs +4 -4
  414. package/dist/physics/lever/preset.mjs +3 -3
  415. package/dist/physics/lorentz/preset.mjs +11 -11
  416. package/dist/physics/magnetism/preset.mjs +3 -3
  417. package/dist/physics/optics/preset.mjs +2 -2
  418. package/dist/physics/orbit-lab.mjs +5 -5
  419. package/dist/physics/projectile-lab.mjs +4 -4
  420. package/dist/physics/rain-relative/preset.mjs +5 -5
  421. package/dist/physics/ramp-forces/preset.mjs +5 -5
  422. package/dist/physics/river-boat.mjs +6 -6
  423. package/dist/physics/shm/preset.mjs +9 -9
  424. package/dist/physics/stopping-distance/preset.mjs +3 -3
  425. package/dist/physics/temperature-scales/preset.mjs +105 -116
  426. package/dist/physics/terminal-velocity/preset.mjs +5 -5
  427. package/dist/physics/thermal/preset.mjs +5 -5
  428. package/dist/physics/vector-board/preset.mjs +7 -6
  429. package/dist/physics/vector-scene.mjs +2 -2
  430. package/dist/physics/vector-types/preset.mjs +37 -3
  431. package/dist/physics/water-density/preset.mjs +12 -12
  432. package/dist/physics/waves/doppler.mjs +2 -2
  433. package/dist/physics/waves/preset.mjs +4 -4
  434. package/dist/physics/waves/ripple.mjs +6 -6
  435. package/dist/physics/waves/string.mjs +5 -5
  436. package/dist/physics/work-energy/preset.mjs +4 -4
  437. package/dist/physics/work-potential/index.d.mts +1 -0
  438. package/dist/physics/work-potential/preset.d.mts +20 -0
  439. package/dist/physics/work-potential/preset.mjs +276 -0
  440. package/dist/schemas/index.d.mts +6 -6
  441. package/dist/schemas/index.mjs +3 -3
  442. package/dist/statistics/center-spread/preset.mjs +3 -3
  443. package/dist/statistics/core/descriptive.d.mts +2 -2
  444. package/dist/statistics/core/descriptive.mjs +2 -2
  445. package/dist/statistics/core/normal.d.mts +3 -3
  446. package/dist/statistics/core/normal.mjs +3 -3
  447. package/dist/statistics/core/sequences.d.mts +1 -1
  448. package/dist/statistics/galton/preset.mjs +2 -2
  449. package/dist/statistics/histogram/preset.mjs +6 -6
  450. package/dist/statistics/normal/preset.mjs +2 -2
  451. package/dist/statistics/sampling/preset.mjs +4 -4
  452. package/dist/statistics/sequence/preset.mjs +58 -15
  453. package/dist/statistics/z-table/preset.mjs +17 -4
  454. package/package.json +11 -3
  455. package/styles.css +4 -1
@@ -12,7 +12,7 @@ const easeInOut = (t) => t < .5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2;
12
12
  const rushInto = (t) => 2 * smooth(t / 2);
13
13
  /** Decelerate to rest (manim `rush_from`). */
14
14
  const rushFrom = (t) => 2 * smooth(t / 2 + .5) - 1;
15
- /** Go to 1 then back to 0 (manim `there_and_back`) — great for pulses. */
15
+ /** Go to 1 then back to 0 (manim `there_and_back`), great for pulses. */
16
16
  const thereAndBack = (t) => smooth(t < .5 ? 2 * t : 2 * (1 - t));
17
17
  /** Overshoot then settle. */
18
18
  const elastic = (t) => {
@@ -49,7 +49,7 @@ function cubicBezier(x1, y1, x2, y2) {
49
49
  function squish(fn, a = .2, b = .8) {
50
50
  return (t) => t < a ? 0 : t > b ? 1 : fn((t - a) / (b - a));
51
51
  }
52
- /** Built-in registry — extend with `registerEasing` (see ./registry). */
52
+ /** Built-in registry, extend with `registerEasing` (see ./registry). */
53
53
  const EASINGS = {
54
54
  linear,
55
55
  smooth,
@@ -1,6 +1,6 @@
1
1
  //#region src/core/numeric.d.ts
2
2
  /**
3
- * numeric — small numerical-calculus helpers, used when an exact symbolic result
3
+ * numeric, small numerical-calculus helpers, used when an exact symbolic result
4
4
  * isn't available (e.g. a function the differentiator doesn't handle) or when a
5
5
  * widget just needs a number. Pure, dependency-free.
6
6
  */
@@ -17,7 +17,7 @@ declare function sampleFunction(fn: RealFn, range: [number, number], samples?: n
17
17
  /** Riemann sum of `fn` over `[a, b]` with `n` subintervals. A teaching estimate. */
18
18
  declare function riemannSum(fn: RealFn, range: [number, number], n: number, mode?: 'left' | 'right' | 'mid'): number;
19
19
  /**
20
- * Composite Simpson's rule — a high-accuracy definite-integral estimate (error
20
+ * Composite Simpson's rule, a high-accuracy definite-integral estimate (error
21
21
  * O(h⁴), vs O(h) for a Riemann sum). Used as the "reference" a Riemann sum
22
22
  * converges toward. `n` is forced even. Not exact, but accurate to ~machine
23
23
  * precision for smooth integrands at n≈1000.
@@ -26,7 +26,7 @@ declare function integrate(fn: RealFn, range: [number, number], n?: number): num
26
26
  /**
27
27
  * Estimate a one-sided limit of `fn` as x → c from `side` (+1 right, −1 left) by
28
28
  * sampling a shrinking sequence of offsets. Returns the closest-in value and
29
- * whether the sequence is *converging* (consecutive samples agree) — so callers
29
+ * whether the sequence is *converging* (consecutive samples agree), so callers
30
30
  * can honestly report "estimated limit" + confidence rather than a hard claim.
31
31
  */
32
32
  declare function estimateOneSidedLimit(fn: RealFn, c: number, side: 1 | -1): {
@@ -32,7 +32,7 @@ function riemannSum(fn, range, n, mode = "mid") {
32
32
  return sum * dx;
33
33
  }
34
34
  /**
35
- * Composite Simpson's rule — a high-accuracy definite-integral estimate (error
35
+ * Composite Simpson's rule, a high-accuracy definite-integral estimate (error
36
36
  * O(h⁴), vs O(h) for a Riemann sum). Used as the "reference" a Riemann sum
37
37
  * converges toward. `n` is forced even. Not exact, but accurate to ~machine
38
38
  * precision for smooth integrands at n≈1000.
@@ -48,7 +48,7 @@ function integrate(fn, range, n = 1e3) {
48
48
  /**
49
49
  * Estimate a one-sided limit of `fn` as x → c from `side` (+1 right, −1 left) by
50
50
  * sampling a shrinking sequence of offsets. Returns the closest-in value and
51
- * whether the sequence is *converging* (consecutive samples agree) — so callers
51
+ * whether the sequence is *converging* (consecutive samples agree), so callers
52
52
  * can honestly report "estimated limit" + confidence rather than a hard claim.
53
53
  */
54
54
  function estimateOneSidedLimit(fn, c, side) {
@@ -1,6 +1,6 @@
1
1
  //#region src/core/reactive.d.ts
2
2
  /**
3
- * Tiny reactive value — the `ValueTracker` / signal at the heart of
3
+ * Tiny reactive value, the `ValueTracker` / signal at the heart of
4
4
  * interactivity. A slider/drag updates a `value()`; anything derived from it
5
5
  * recomputes; React components bound via `useValue` repaint. Framework-light
6
6
  * (no external dep); the React glue is one hook.
@@ -2,7 +2,7 @@ import { useEffect, useReducer, useRef } from "react";
2
2
 
3
3
  //#region src/core/reactive.ts
4
4
  /**
5
- * Tiny reactive value — the `ValueTracker` / signal at the heart of
5
+ * Tiny reactive value, the `ValueTracker` / signal at the heart of
6
6
  * interactivity. A slider/drag updates a `value()`; anything derived from it
7
7
  * recomputes; React components bound via `useValue` repaint. Framework-light
8
8
  * (no external dep); the React glue is one hook.
@@ -1,6 +1,6 @@
1
1
  //#region src/core/rng.d.ts
2
2
  /**
3
- * Seeded PRNG — deterministic randomness so a simulation is REPLAYABLE (same
3
+ * Seeded PRNG, deterministic randomness so a simulation is REPLAYABLE (same
4
4
  * seed → same run; an agent can pin a seed, a lesson reproduces exactly, SSR /
5
5
  * Remotion stays stable). mulberry32: tiny, fast, good enough for teaching. This
6
6
  * is the canonical home (generic numerics live in core, per the shared-math rule);
@@ -15,7 +15,7 @@ declare function randInt(rng: Rng, lo: number, hi: number): number;
15
15
  declare function shuffle<T>(arr: readonly T[], rng: Rng): T[];
16
16
  /** Sample `k` distinct items (without replacement). */
17
17
  declare function sample<T>(arr: readonly T[], k: number, rng: Rng): T[];
18
- /** A normal (Gaussian) variate via Box–Muller — for sampling-distribution sims. */
18
+ /** A normal (Gaussian) variate via Box–Muller, for sampling-distribution sims. */
19
19
  declare function gaussian(rng: Rng, mu?: number, sigma?: number): number;
20
20
  //#endregion
21
21
  export { Rng, gaussian, mulberry32, randInt, sample, shuffle };
package/dist/core/rng.mjs CHANGED
@@ -27,7 +27,7 @@ function shuffle(arr, rng) {
27
27
  function sample(arr, k, rng) {
28
28
  return shuffle(arr, rng).slice(0, Math.max(0, Math.min(k, arr.length)));
29
29
  }
30
- /** A normal (Gaussian) variate via Box–Muller — for sampling-distribution sims. */
30
+ /** A normal (Gaussian) variate via Box–Muller, for sampling-distribution sims. */
31
31
  function gaussian(rng, mu = 0, sigma = 1) {
32
32
  let u = 0, v = 0;
33
33
  while (u === 0) u = rng();
package/dist/core/tex.mjs CHANGED
@@ -6,11 +6,11 @@ import { jsx } from "react/jsx-runtime";
6
6
 
7
7
  //#region src/core/tex.tsx
8
8
  /**
9
- * Tex — render a LaTeX string with KaTeX AT RENDER TIME, so the markup is
9
+ * Tex, render a LaTeX string with KaTeX AT RENDER TIME, so the markup is
10
10
  * identical on the server and client: SSR/static exports show real maths (not raw
11
11
  * `\cdot`/`\dfrac`), there's no raw-then-hydrate flash, and hydration matches.
12
12
  *
13
- * `katex` is a static import kept in this OWN module — stage/labs `neverBundle`
13
+ * `katex` is a static import kept in this OWN module, stage/labs `neverBundle`
14
14
  * leave it external, so only `<Tex>` importers pull it (the consumer resolves the
15
15
  * optional peer; non-Tex consumers never bundle it). If `renderToString` throws on
16
16
  * a malformed string we fall back to the raw LaTeX in a `<code>`. Pair with
@@ -27,7 +27,7 @@ interface Keyframe {
27
27
  /**
28
28
  * Pure multi-stage interpolation: build a `(t in [0,1]) => number` from
29
29
  * keyframes. The manim-style way to express richer programmatic animation
30
- * without a scheduler — drive `t` from `useTween`/`useFrameLoop`.
30
+ * without a scheduler, drive `t` from `useTween`/`useFrameLoop`.
31
31
  */
32
32
  declare function keyframes(frames: Keyframe[]): (t: number) => number;
33
33
  //#endregion
@@ -52,7 +52,7 @@ function useTween(opts) {
52
52
  /**
53
53
  * Pure multi-stage interpolation: build a `(t in [0,1]) => number` from
54
54
  * keyframes. The manim-style way to express richer programmatic animation
55
- * without a scheduler — drive `t` from `useTween`/`useFrameLoop`.
55
+ * without a scheduler, drive `t` from `useTween`/`useFrameLoop`.
56
56
  */
57
57
  function keyframes(frames) {
58
58
  const ks = [...frames].sort((a, b) => a.at - b.at);
@@ -13,6 +13,16 @@ function num(v, fallback) {
13
13
  }
14
14
  const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
15
15
  const lerp = (a, b, t) => a + (b - a) * t;
16
+ /** Round to `dp` decimal places (default 2), as a number. The shared rounding
17
+ * the part-whole bar labs (percent / fraction / ratio) all need for readouts. */
18
+ const round = (n, dp = 2) => Math.round(n * 10 ** dp) / 10 ** dp;
19
+ /** Greatest common divisor (Euclid), 0→1 so a ratio/fraction can always reduce. */
20
+ const gcd = (a, b) => {
21
+ a = Math.abs(a);
22
+ b = Math.abs(b);
23
+ while (b) [a, b] = [b, a % b];
24
+ return a || 1;
25
+ };
16
26
  const DEG = Math.PI / 180;
17
27
  /** Degrees → radians. */
18
28
  const toRad = (deg) => deg * DEG;
@@ -28,4 +38,4 @@ function remap(x, inMin, inMax, outMin, outMax, doClamp = false) {
28
38
  }
29
39
 
30
40
  //#endregion
31
- export { approxEq, clamp, cn, lerp, num, remap, toDeg, toRad };
41
+ export { approxEq, clamp, cn, gcd, lerp, num, remap, round, toDeg, toRad };
@@ -5,33 +5,25 @@ import { CheckButton, Chip, StatusPill, Stepper } from "../../kit/controls.mjs";
5
5
  import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
6
6
  import { HintLadder, RevealSolution, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
7
7
  import { factorial, multinomial } from "../core/combinatorics.mjs";
8
+ import { CATEGORICAL } from "../../kit/palette.mjs";
8
9
  import { useMemo, useState } from "react";
9
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
11
  import { useControlSurface } from "@classytic/stage";
11
12
 
12
13
  //#region src/discrete/arrangements/preset.tsx
13
14
  /**
14
- * ArrangementsLab — arranging things in a row when some are IDENTICAL (the multiset
15
+ * ArrangementsLab, arranging things in a row when some are IDENTICAL (the multiset
15
16
  * permutation the slots/selection labs don't cover). The classic MISSISSIPPI, or a
16
17
  * row of coloured beads. The derivation, made concrete: if all n were distinct
17
18
  * there'd be n! orders; but swapping two identical letters gives the SAME word, so
18
- * each real arrangement is counted (count of that letter)! times — divide it out:
19
+ * each real arrangement is counted (count of that letter)! times, divide it out:
19
20
  *
20
21
  * n! / (n₁! · n₂! · …) (the multinomial coefficient)
21
22
  *
22
23
  * You watch two identical tiles swap into the same row (the overcount), then the
23
24
  * formula falls out. Predict-then-check. Kernel = factorial / multinomial.
24
25
  */
25
- const PALETTE = [
26
- "#1c7ed6",
27
- "#e8590c",
28
- "#2f9e44",
29
- "#9c36b5",
30
- "#e03131",
31
- "#0ca678",
32
- "#f59f00",
33
- "#1098ad"
34
- ];
26
+ const PALETTE = CATEGORICAL;
35
27
  function fromWord(w) {
36
28
  const order = [], m = /* @__PURE__ */ new Map();
37
29
  for (const ch of w.toUpperCase()) {
@@ -111,7 +103,7 @@ function ArrangementsLab({ word, items, title = "Arrange with repeats", prompt,
111
103
  children: [
112
104
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("p", {
113
105
  className: "lab-field-label",
114
- children: [n, " items in a row — identical ones share a colour"]
106
+ children: [n, " items in a row, identical ones share a colour"]
115
107
  }), /* @__PURE__ */ jsx("div", {
116
108
  style: {
117
109
  display: "flex",
@@ -148,7 +140,7 @@ function ArrangementsLab({ word, items, title = "Arrange with repeats", prompt,
148
140
  style: { color: swapGroup.color },
149
141
  children: swapGroup.label
150
142
  }),
151
- "'s ⇄ — it's the ",
143
+ "'s ⇄, it's the ",
152
144
  /* @__PURE__ */ jsx("b", { children: "same row" }),
153
145
  ". So every arrangement is counted ",
154
146
  swapGroup.count,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { Chip, Slider } from "../../kit/controls.mjs";
4
4
  import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
5
- import { HintLadder, RevealSolution, useHints } from "../../kit/pedagogy.mjs";
5
+ import { ChallengeCard, HintLadder, RevealSolution, useChallenge, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
6
6
  import { bayes } from "../core/probability.mjs";
7
7
  import { ProportionModel } from "../../kit/proportion.mjs";
8
8
  import { FrequencyTree } from "../../kit/freq-tree.mjs";
@@ -14,8 +14,8 @@ import { SamplerCore } from "@classytic/stage/sim";
14
14
 
15
15
  //#region src/discrete/bayes/preset.tsx
16
16
  /**
17
- * BayesLab — base-rate neglect, taught Brilliant-style: ONE idea at a time, big.
18
- * THEORY (default): a 4-step walkthrough — (1) the rare population, (2) the test
17
+ * BayesLab, base-rate neglect, taught Brilliant-style: ONE idea at a time, big.
18
+ * THEORY (default): a 4-step walkthrough, (1) the rare population, (2) the test
19
19
  * catches most sick people, (3) but also flags many healthy ones, (4) so a
20
20
  * positive is usually a false alarm. Each step reveals one more layer of a large
21
21
  * area model; the frequency tree + answer land on the last step.
@@ -28,11 +28,10 @@ const FALSEPOS = "var(--stage-warn, #e8a020)";
28
28
  const MUTED = "var(--stage-muted)";
29
29
  const pct = (x) => `${(x * 100).toFixed(x < .01 ? 2 : 1)}%`;
30
30
  const r0 = (x) => Math.round(x);
31
- function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, population = 1e3, conditionLabels = ["disease", "healthy"], testLabels = ["test +", "test −"], predict = false, title = "Bayes — the base-rate trap", prompt, objectives, hints: hintList, controlId }) {
31
+ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, population = 1e3, conditionLabels = ["disease", "healthy"], testLabels = ["test +", "test −"], predict = false, title = "Bayes: the base-rate trap", prompt, objectives, hints: hintList, controlId }) {
32
32
  const [p, setP] = useState(prior);
33
33
  const [s, setS] = useState(sensitivity);
34
34
  const [f, setF] = useState(falsePositive);
35
- const [guess, setGuess] = useState(.5);
36
35
  const [revealed, setRevealed] = useState(!predict);
37
36
  const [mode, setMode] = useState("theory");
38
37
  const [perStep, setPerStep] = useState(50);
@@ -43,6 +42,33 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
43
42
  const posterior = bayes(s, p, f);
44
43
  const [has, not] = conditionLabels, [pos] = testLabels;
45
44
  const posShort = pos.replace("test ", "");
45
+ const predictQ = [{
46
+ id: "bayes-posterior",
47
+ prompt: `Of everyone who tests ${posShort}, roughly what fraction TRULY have the ${has}?`,
48
+ choices: [
49
+ {
50
+ value: "most",
51
+ label: "most of them"
52
+ },
53
+ {
54
+ value: "about-half",
55
+ label: "about half"
56
+ },
57
+ {
58
+ value: "small",
59
+ label: "only a small fraction"
60
+ }
61
+ ],
62
+ answer: "small",
63
+ explain: `Base-rate neglect: the ${has} is rare (prior ${pct(p)}), so even an accurate test produces far more false alarms than true positives, the posterior stays small.`
64
+ }];
65
+ const ch = useChallenge(predictQ);
66
+ if (predict && ch.allCorrect && !revealed) setRevealed(true);
67
+ useCheckpoint({
68
+ solved: ch.allCorrect,
69
+ activity: "bayes:predict",
70
+ hintsUsed: hints.count
71
+ });
46
72
  const N = population;
47
73
  const tp = N * p * s, fn = N * p * (1 - s), fp = N * (1 - p) * f, tn = N * (1 - p) * (1 - f);
48
74
  const sampling = mode === "sample";
@@ -96,7 +122,7 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
96
122
  useControlSurface(controlId, {
97
123
  prevalence: {
98
124
  type: "number",
99
- label: "prior P(A) — prevalence",
125
+ label: "prior P(A): prevalence",
100
126
  min: .001,
101
127
  max: .5,
102
128
  step: .001,
@@ -105,7 +131,7 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
105
131
  },
106
132
  sensitivity: {
107
133
  type: "number",
108
- label: "P(B|A) — true-positive rate",
134
+ label: "P(B|A): true-positive rate",
109
135
  min: .5,
110
136
  max: 1,
111
137
  step: .01,
@@ -114,7 +140,7 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
114
140
  },
115
141
  falsePositive: {
116
142
  type: "number",
117
- label: "P(B|¬A) — false-positive rate",
143
+ label: "P(B|¬A): false-positive rate",
118
144
  min: 0,
119
145
  max: .5,
120
146
  step: .01,
@@ -160,9 +186,9 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
160
186
  count: dHea
161
187
  }];
162
188
  const captions = [
163
- `Out of ${r0(N).toLocaleString()} people, only ${r0(tp + fn)} actually have the ${has} — it's rare (${pct(p)}).`,
189
+ `Out of ${r0(N).toLocaleString()} people, only ${r0(tp + fn)} actually have the ${has}, it's rare (${pct(p)}).`,
164
190
  `The test is sensitive: of those ${r0(tp + fn)} sick people it catches ${r0(tp)} (and misses ${r0(fn)}).`,
165
- `But the same test also flags ${r0(fp)} of the ${r0(fp + tn)} healthy people — false alarms.`,
191
+ `But the same test also flags ${r0(fp)} of the ${r0(fp + tn)} healthy people, false alarms.`,
166
192
  `So ${r0(tp + fp)} test ${posShort}, yet only ${r0(tp)} are truly sick → a positive means just ${pct(posterior)}.`
167
193
  ];
168
194
  const figure = /* @__PURE__ */ jsxs(Fragment$1, { children: [
@@ -257,29 +283,11 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
257
283
  ]
258
284
  })
259
285
  ]
260
- }) : /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("p", {
261
- className: "lab-prompt",
262
- children: [
263
- "🎯 Before the reveal — if you test ",
264
- posShort,
265
- ", what's the chance you actually have it?"
266
- ]
267
- }), /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
268
- label: "your guess",
269
- value: pct(guess),
270
- children: /* @__PURE__ */ jsx(Slider, {
271
- value: guess,
272
- min: 0,
273
- max: 1,
274
- step: .01,
275
- onChange: setGuess,
276
- ariaLabel: "your guess"
277
- })
278
- }), /* @__PURE__ */ jsx(Chip, {
279
- selected: false,
280
- onClick: () => setRevealed(true),
281
- children: "reveal"
282
- })] })] })] }) : void 0,
286
+ }) : /* @__PURE__ */ jsx(ChallengeCard, {
287
+ questions: predictQ,
288
+ state: ch,
289
+ title: "Predict first"
290
+ })] }) : void 0,
283
291
  controls: /* @__PURE__ */ jsxs(ControlBar, { children: [
284
292
  /* @__PURE__ */ jsx(Field, {
285
293
  label: "mode",
@@ -382,7 +390,7 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
382
390
  posShort,
383
391
  ") = ",
384
392
  pct(posterior),
385
- " — far below the test's accuracy, because the prior is only ",
393
+ ", far below the test's accuracy, because the prior is only ",
386
394
  pct(p),
387
395
  "."
388
396
  ] }),
@@ -395,7 +403,7 @@ function BayesLab({ prior = .01, sensitivity = .9, falsePositive = .09, populati
395
403
  });
396
404
  }
397
405
  /** The answer as a picture: of everyone who tests +, what red share truly has it.
398
- * A bar of JUST the positive region (true-positive red | false-positive orange) —
406
+ * A bar of JUST the positive region (true-positive red | false-positive orange) ,
399
407
  * the posterior IS the red fraction, legible at any prior (unlike the 1%-wide
400
408
  * column the area model degenerates to). minWidth keeps the red sliver visible. */
401
409
  function PositiveBar({ tp, fp, pos, has }) {
@@ -11,9 +11,9 @@ import { useControlSurface } from "@classytic/stage";
11
11
 
12
12
  //#region src/discrete/binomial/preset.tsx
13
13
  /**
14
- * BinomialDistributionLab — the bridge from counting to the bell. P(X=k successes
14
+ * BinomialDistributionLab, the bridge from counting to the bell. P(X=k successes
15
15
  * in n trials) = C(n,k)·pᵏ·(1−p)ⁿ⁻ᵏ, drawn as bars you can interrogate: click a bar
16
- * and the formula DERIVES itself — k successes happen C(n,k) ways (the Pascal /
16
+ * and the formula DERIVES itself, k successes happen C(n,k) ways (the Pascal /
17
17
  * counting number), each way has probability pᵏ for the successes times (1−p)ⁿ⁻ᵏ for
18
18
  * the failures. Slide p to watch it skew and (at ½) turn symmetric; slide n and flip
19
19
  * on the normal overlay to watch the binomial become the Galton-board bell. Mean np
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/discrete/combination-studio/figure.d.ts
4
+ type CharSlot = 'top' | 'bottom' | 'hat' | 'hold' | 'none';
5
+ //#endregion
6
+ export { CharSlot };
@@ -0,0 +1,159 @@
1
+ 'use client';
2
+
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+
5
+ //#region src/discrete/combination-studio/figure.tsx
6
+ const SKIN = "#e8b98c";
7
+ /** A friendly stick-ish person who wears the chosen garments. */
8
+ function CharacterFigure({ parts, size = 64, dim = false }) {
9
+ const { top = "#9aa3b2", bottom = "#5b6472", hat, hold } = parts;
10
+ return /* @__PURE__ */ jsxs("svg", {
11
+ width: size,
12
+ height: size,
13
+ viewBox: "0 0 64 64",
14
+ style: {
15
+ display: "block",
16
+ opacity: dim ? .28 : 1,
17
+ transition: "opacity .2s"
18
+ },
19
+ "aria-hidden": true,
20
+ children: [
21
+ /* @__PURE__ */ jsx("rect", {
22
+ x: "26",
23
+ y: "40",
24
+ width: "5",
25
+ height: "16",
26
+ rx: "2.5",
27
+ fill: bottom
28
+ }),
29
+ /* @__PURE__ */ jsx("rect", {
30
+ x: "33",
31
+ y: "40",
32
+ width: "5",
33
+ height: "16",
34
+ rx: "2.5",
35
+ fill: bottom
36
+ }),
37
+ /* @__PURE__ */ jsx("rect", {
38
+ x: "22",
39
+ y: "24",
40
+ width: "20",
41
+ height: "20",
42
+ rx: "6",
43
+ fill: top
44
+ }),
45
+ /* @__PURE__ */ jsx("rect", {
46
+ x: "17",
47
+ y: "26",
48
+ width: "5",
49
+ height: "14",
50
+ rx: "2.5",
51
+ fill: top
52
+ }),
53
+ /* @__PURE__ */ jsx("rect", {
54
+ x: "42",
55
+ y: "26",
56
+ width: "5",
57
+ height: "14",
58
+ rx: "2.5",
59
+ fill: top
60
+ }),
61
+ /* @__PURE__ */ jsx("circle", {
62
+ cx: "32",
63
+ cy: "16",
64
+ r: "9",
65
+ fill: SKIN
66
+ }),
67
+ hat && /* @__PURE__ */ jsx("path", {
68
+ d: "M20 13 Q32 -1 44 13 Z",
69
+ fill: hat
70
+ }),
71
+ hat && /* @__PURE__ */ jsx("rect", {
72
+ x: "18",
73
+ y: "12",
74
+ width: "28",
75
+ height: "3.4",
76
+ rx: "1.7",
77
+ fill: hat
78
+ }),
79
+ hold && /* @__PURE__ */ jsx("text", {
80
+ x: "47",
81
+ y: "44",
82
+ fontSize: "13",
83
+ textAnchor: "middle",
84
+ children: hold
85
+ })
86
+ ]
87
+ });
88
+ }
89
+ /** A stacked outcome card: one emoji (or colour swatch) per category. */
90
+ function ComboCard({ cells, size = 60, dim = false }) {
91
+ return /* @__PURE__ */ jsx("div", {
92
+ style: {
93
+ display: "flex",
94
+ flexDirection: "column",
95
+ alignItems: "center",
96
+ gap: 2,
97
+ opacity: dim ? .3 : 1,
98
+ transition: "opacity .2s",
99
+ width: size
100
+ },
101
+ "aria-hidden": true,
102
+ children: cells.map((c, i) => c.emoji ? /* @__PURE__ */ jsx("span", {
103
+ style: {
104
+ fontSize: size * .42,
105
+ lineHeight: 1
106
+ },
107
+ children: c.emoji
108
+ }, i) : /* @__PURE__ */ jsx("span", { style: {
109
+ width: size * .6,
110
+ height: size * .26,
111
+ borderRadius: 5,
112
+ background: c.color ?? "#9aa3b2"
113
+ } }, i))
114
+ });
115
+ }
116
+ /** A pickable option in a rack: the swatch/emoji + its label, selected ring. */
117
+ function OptionSwatch({ emoji, color, label, selected, onClick }) {
118
+ return /* @__PURE__ */ jsxs("button", {
119
+ type: "button",
120
+ onClick,
121
+ "aria-pressed": selected,
122
+ "aria-label": label,
123
+ style: {
124
+ display: "inline-flex",
125
+ flexDirection: "column",
126
+ alignItems: "center",
127
+ gap: 3,
128
+ cursor: "pointer",
129
+ padding: "6px 8px",
130
+ borderRadius: 10,
131
+ background: "transparent",
132
+ border: `2px solid ${selected ? "var(--stage-accent)" : "var(--stage-grid)"}`,
133
+ boxShadow: selected ? "0 0 0 3px color-mix(in oklab, var(--stage-accent) 22%, transparent)" : "none",
134
+ transition: "border-color .15s, box-shadow .15s"
135
+ },
136
+ children: [emoji ? /* @__PURE__ */ jsx("span", {
137
+ style: {
138
+ fontSize: 24,
139
+ lineHeight: 1
140
+ },
141
+ children: emoji
142
+ }) : /* @__PURE__ */ jsx("span", { style: {
143
+ width: 28,
144
+ height: 18,
145
+ borderRadius: 5,
146
+ background: color ?? "#9aa3b2"
147
+ } }), /* @__PURE__ */ jsx("span", {
148
+ style: {
149
+ fontSize: 11,
150
+ color: "var(--stage-muted)",
151
+ fontWeight: 600
152
+ },
153
+ children: label
154
+ })]
155
+ });
156
+ }
157
+
158
+ //#endregion
159
+ export { CharacterFigure, ComboCard, OptionSwatch };
@@ -0,0 +1,2 @@
1
+ import { CharSlot } from "./figure.mjs";
2
+ import { CombinationStudioLab, CombinationStudioProps, ComboCategory, ComboOption } from "./preset.mjs";
@@ -0,0 +1,44 @@
1
+ import { CharSlot } from "./figure.mjs";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/discrete/combination-studio/preset.d.ts
5
+ interface ComboOption {
6
+ id: string;
7
+ label: string;
8
+ emoji?: string;
9
+ color?: string;
10
+ }
11
+ interface ComboCategory {
12
+ id: string;
13
+ label: string;
14
+ slot?: CharSlot;
15
+ options: ComboOption[];
16
+ }
17
+ interface CombinationStudioProps {
18
+ /** The thing being built, e.g. "outfit", "sundae" (used in the headline + question). */
19
+ scenario?: string;
20
+ categories?: ComboCategory[];
21
+ /** 'character' assembles a person; 'card' stacks the chosen emoji (non-clothing). */
22
+ figure?: 'character' | 'card';
23
+ /** How many categories are in play at the start (rest revealed via + variable). */
24
+ startActive?: number;
25
+ /** Cap outcomes drawn on the wall. */
26
+ maxWall?: number;
27
+ title?: string;
28
+ prompt?: string;
29
+ objectives?: string[];
30
+ hints?: string[];
31
+ }
32
+ declare function CombinationStudioLab({
33
+ scenario,
34
+ categories,
35
+ figure,
36
+ startActive,
37
+ maxWall,
38
+ title,
39
+ prompt,
40
+ objectives,
41
+ hints: hintList
42
+ }?: CombinationStudioProps): ReactNode;
43
+ //#endregion
44
+ export { CombinationStudioLab, CombinationStudioProps, ComboCategory, ComboOption };