@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
@@ -8,7 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/language/article-lens/preset.tsx
10
10
  /**
11
- * ArticleLens — choose a / an / the / — (no article).
11
+ * ArticleLens, choose a / an / the /, (no article).
12
12
  *
13
13
  * Bangla has no articles, so this is the highest-novelty English error for
14
14
  * Bangla speakers. The "lens" framing: tap the article that fits, and on a
@@ -19,15 +19,15 @@ const CHOICES = [
19
19
  "a",
20
20
  "an",
21
21
  "the",
22
- "—"
22
+ ", "
23
23
  ];
24
24
  const RULE = {
25
25
  a: "a → any one (new), before a consonant sound",
26
26
  an: "an → any one (new), before a vowel sound",
27
27
  the: "the → the specific one we both know",
28
- "—": "no article → general or uncountable"
28
+ ", ": "no article → general or uncountable"
29
29
  };
30
- function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose the article", prompt = "Bangla has no a/an/the — pick what English needs." }) {
30
+ function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose the article", prompt = "Bangla has no a/an/the: pick what English needs." }) {
31
31
  const [idx, setIdx] = useState(0);
32
32
  const [picked, setPicked] = useState(null);
33
33
  const [solvedCount, setSolvedCount] = useState(0);
@@ -50,7 +50,7 @@ function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose th
50
50
  },
51
51
  hintsUsed: hints.count
52
52
  });
53
- const blank = useMemo(() => picked === null ? "▢" : picked === "—" ? "∅" : picked, [picked]);
53
+ const blank = useMemo(() => picked === null ? "▢" : picked === ", " ? "∅" : picked, [picked]);
54
54
  if (!item) return null;
55
55
  const pick = (a) => {
56
56
  if (correct) return;
@@ -92,15 +92,15 @@ function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose th
92
92
  "data-state": picked === a ? correct ? "ok" : "no" : "idle",
93
93
  disabled: correct,
94
94
  onClick: () => pick(a),
95
- "aria-label": a === "—" ? "no article" : a,
96
- children: a === "—" ? "no article" : a
95
+ "aria-label": a === ", " ? "no article" : a,
96
+ children: a === ", " ? "no article" : a
97
97
  }, a))
98
98
  }),
99
99
  picked !== null && /* @__PURE__ */ jsx("p", {
100
100
  className: "lang-why",
101
101
  "data-state": correct ? "ok" : "no",
102
102
  "aria-live": "polite",
103
- children: correct ? item.why ?? RULE[item.answer] : "Not quite — try another."
103
+ children: correct ? item.why ?? RULE[item.answer] : "Not quite, try another."
104
104
  })
105
105
  ]
106
106
  });
@@ -1,7 +1,7 @@
1
1
  import { IconValue } from "./icon.mjs";
2
2
 
3
3
  //#region src/language/deck.d.ts
4
- /** Part of speech — drives the Montessori-style colour coding across grammar
4
+ /** Part of speech, drives the Montessori-style colour coding across grammar
5
5
  * labs so a learner builds one consistent visual intuition. */
6
6
  type Pos = 'noun' | 'verb' | 'article' | 'adjective' | 'preposition' | 'pronoun' | 'conjunction' | 'adverb' | 'other';
7
7
  declare const POS_LABEL: Record<Pos, string>;
@@ -14,7 +14,7 @@ interface DeckItem {
14
14
  transliteration?: string;
15
15
  /** Optional audio: an uploaded media URL OR an external URL. Never generated. */
16
16
  audioUrl?: string;
17
- /** Optional picture for kids/visual decks — an emoji string, or an `IconRef`
17
+ /** Optional picture for kids/visual decks, an emoji string, or an `IconRef`
18
18
  * ({ kind:'emoji'|'svg'|'image', … }) for a registered SVG / uploaded image. */
19
19
  icon?: IconValue;
20
20
  /** Optional usage example (target language). */
@@ -38,7 +38,7 @@ declare function hasVoiceFor(lang: string): boolean;
38
38
  declare function canSpeak(item: DeckItem, lang: string): boolean;
39
39
  /** Play an item's audio. Returns false if nothing was playable. */
40
40
  declare function speak(item: DeckItem, lang: string): boolean;
41
- /** Deterministic shuffle (seeded LCG) — same input+seed → same order, so SSR
41
+ /** Deterministic shuffle (seeded LCG), same input+seed → same order, so SSR
42
42
  * and client agree. Never uses Math.random at module scope. */
43
43
  declare function seededShuffle<T>(arr: readonly T[], seed?: number): T[];
44
44
  //#endregion
@@ -39,7 +39,7 @@ function speak(item, lang) {
39
39
  }
40
40
  return false;
41
41
  }
42
- /** Deterministic shuffle (seeded LCG) — same input+seed → same order, so SSR
42
+ /** Deterministic shuffle (seeded LCG), same input+seed → same order, so SSR
43
43
  * and client agree. Never uses Math.random at module scope. */
44
44
  function seededShuffle(arr, seed = 1) {
45
45
  const a = arr.slice();
@@ -13,9 +13,9 @@ interface PrepItem {
13
13
  options: string[];
14
14
  /** Spatial relation to depict (positions the figure vs the landmark). */
15
15
  scene: Relation;
16
- /** The figure being placed — an emoji string or an `IconRef`. Default a ball. */
16
+ /** The figure being placed, an emoji string or an `IconRef`. Default a ball. */
17
17
  figure?: IconValue;
18
- /** The reference landmark — an emoji/`IconRef`, OR a backdrop key string
18
+ /** The reference landmark, an emoji/`IconRef`, OR a backdrop key string
19
19
  * ('sky'|'water'|'ground'|'room'). Default a box. */
20
20
  landmark?: IconValue;
21
21
  note?: string;
@@ -9,12 +9,12 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
 
10
10
  //#region src/language/preposition-scene/preset.tsx
11
11
  /**
12
- * PrepositionScene — pick the preposition that matches a spatial picture.
12
+ * PrepositionScene, pick the preposition that matches a spatial picture.
13
13
  *
14
14
  * Prepositions are inherently spatial, so each item shows a little scene (a
15
15
  * thing in / on / under / beside a box) and the learner names the relation.
16
16
  * The teaching point for Bangla speakers: English puts the preposition BEFORE
17
- * the noun ("on the box"), where Bangla uses a postposition AFTER it — so the
17
+ * the noun ("on the box"), where Bangla uses a postposition AFTER it, so the
18
18
  * answer slots in front of the noun and the note makes that contrast explicit.
19
19
  */
20
20
  const figAt = (left, top, scale = 1, opacity) => ({
@@ -96,7 +96,7 @@ function backdropFigPos(kind, rel) {
96
96
  if (kind === "ground") return hi ? figAt("50%", "20%") : lo ? figAt("50%", "86%") : figAt("50%", "60%");
97
97
  return figAt("50%", "48%");
98
98
  }
99
- /** Plain-text label for an icon value (emoji char or IconRef.alt) — for the
99
+ /** Plain-text label for an icon value (emoji char or IconRef.alt), for the
100
100
  * scene's aria-label, since the visuals themselves are decorative. */
101
101
  function iconLabel(v) {
102
102
  const r = normalizeIcon(v);
@@ -134,7 +134,7 @@ function SceneView({ relation, figure = "🔵", landmark = "📦" }) {
134
134
  ]
135
135
  });
136
136
  }
137
- function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the preposition — in English it comes BEFORE the noun." }) {
137
+ function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the preposition: in English it comes BEFORE the noun." }) {
138
138
  const [idx, setIdx] = useState(0);
139
139
  const [picked, setPicked] = useState(null);
140
140
  const [solvedCount, setSolvedCount] = useState(0);
@@ -211,7 +211,7 @@ function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the
211
211
  className: "lang-why",
212
212
  "data-state": correct ? "ok" : "no",
213
213
  "aria-live": "polite",
214
- children: correct ? item.note ?? `English: "${item.answer} ${item.noun}" — the preposition comes first.` : "Not quite — look at the picture."
214
+ children: correct ? item.note ?? `English: "${item.answer} ${item.noun}", the preposition comes first.` : "Not quite, look at the picture."
215
215
  })
216
216
  ]
217
217
  });
@@ -10,16 +10,16 @@ import { jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/language/sentence-builder/preset.tsx
12
12
  /**
13
- * SentenceBuilder — order the words into a correct sentence.
13
+ * SentenceBuilder, order the words into a correct sentence.
14
14
  *
15
15
  * The flagship grammar lab: tiles are colour-coded by part of speech and carry
16
16
  * an optional L1 gloss, so a learner SEES the structure while building it. The
17
- * `prompt` shows the meaning (e.g. the learner's-language sentence) above —
17
+ * `prompt` shows the meaning (e.g. the learner's-language sentence) above ,
18
18
  * which is exactly how a Bangla speaker meets English word order: same meaning,
19
19
  * different slot order (SOV → SVO).
20
20
  *
21
21
  * Tap a tile in the bank to place it; tap a placed tile to take it back. No
22
- * drag — buttons are touch- and keyboard-friendly. Validates by resulting text,
22
+ * drag, buttons are touch- and keyboard-friendly. Validates by resulting text,
23
23
  * so duplicate/interchangeable words still pass.
24
24
  */
25
25
  function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr", title = "Build the sentence", hint = "Tap the words in the right order." }) {
@@ -80,7 +80,7 @@ function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr
80
80
  gloss: tiles[i].gloss,
81
81
  dir: targetDir,
82
82
  onClick: () => take(i),
83
- ariaLabel: `${tiles[i].text} — tap to remove`
83
+ ariaLabel: `${tiles[i].text}, tap to remove`
84
84
  }, i))
85
85
  }),
86
86
  /* @__PURE__ */ jsx("div", {
@@ -92,7 +92,7 @@ function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr
92
92
  gloss: tiles[i].gloss,
93
93
  dir: targetDir,
94
94
  onClick: () => place(i),
95
- ariaLabel: `${tiles[i].text} — tap to place`
95
+ ariaLabel: `${tiles[i].text}, tap to place`
96
96
  }, i))
97
97
  }),
98
98
  /* @__PURE__ */ jsx(LiveRegion, { children: checked ? correct ? "Correct word order" : "Not the right order yet" : "" })
@@ -8,9 +8,9 @@ interface TransformTile {
8
8
  gloss?: string;
9
9
  }
10
10
  interface TransformProps {
11
- /** Source sentence tiles (correct order) — shown read-only. */
11
+ /** Source sentence tiles (correct order), shown read-only. */
12
12
  from: TransformTile[];
13
- /** Target sentence tiles (correct order) — the learner rebuilds these. */
13
+ /** Target sentence tiles (correct order), the learner rebuilds these. */
14
14
  to: TransformTile[];
15
15
  /** What to do, e.g. "Make it a question". */
16
16
  instruction?: string;
@@ -10,11 +10,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/language/transform/preset.tsx
12
12
  /**
13
- * TransformLab — change one sentence into another and SEE what changed.
13
+ * TransformLab, change one sentence into another and SEE what changed.
14
14
  *
15
15
  * Shows the source sentence (read-only), an instruction ("Make it a question"),
16
16
  * and the learner rebuilds the target by tapping tiles. On success the words
17
- * that are NEW vs the source are ringed — so the rule (e.g. English injects
17
+ * that are NEW vs the source are ringed, so the rule (e.g. English injects
18
18
  * "Do" for a question; Bangla has no do-support) is visible, not just stated.
19
19
  */
20
20
  function TransformLab({ from, to, instruction = "Change the sentence.", note, title = "Transform it", targetDir = "ltr" }) {
@@ -90,7 +90,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
90
90
  dir: targetDir,
91
91
  selected: checked && correct && isNew(i),
92
92
  onClick: () => take(i),
93
- ariaLabel: `${to[i].text} — tap to remove`
93
+ ariaLabel: `${to[i].text}, tap to remove`
94
94
  }, i))
95
95
  }),
96
96
  /* @__PURE__ */ jsx("div", {
@@ -102,7 +102,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
102
102
  gloss: to[i].gloss,
103
103
  dir: targetDir,
104
104
  onClick: () => place(i),
105
- ariaLabel: `${to[i].text} — tap to place`
105
+ ariaLabel: `${to[i].text}, tap to place`
106
106
  }, i))
107
107
  }),
108
108
  checked && correct && note ? /* @__PURE__ */ jsx("p", {
@@ -118,7 +118,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
118
118
  prompt: instruction,
119
119
  aside: checked ? /* @__PURE__ */ jsx(StatusPill, {
120
120
  ok: correct,
121
- children: correct ? "✓ Done — see what changed" : "Not the right order yet"
121
+ children: correct ? "✓ Done, see what changed" : "Not the right order yet"
122
122
  }) : void 0,
123
123
  controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(CheckButton, {
124
124
  onClick: () => setChecked(true),
@@ -5,7 +5,7 @@ import { ReactNode } from "react";
5
5
  /**
6
6
  * True once the browser's TTS voice list is populated (it loads async).
7
7
  *
8
- * Starts `false` — NOT seeded from `getVoices()` — so the first client render
8
+ * Starts `false`, NOT seeded from `getVoices()`, so the first client render
9
9
  * matches the server (where there's no `speechSynthesis`). Seeding from the
10
10
  * live voice list would make a TTS-only item render its speaker button on the
11
11
  * client but not the server → a hydration mismatch that forces React to
@@ -14,11 +14,11 @@ import { ReactNode } from "react";
14
14
  */
15
15
  declare function useVoicesReady(): boolean;
16
16
  /**
17
- * A speaker button — renders nothing if the item can't be voiced.
17
+ * A speaker button, renders nothing if the item can't be voiced.
18
18
  *
19
19
  * `audioUrl` items can voice on the server too (no browser needed), so they
20
20
  * render the button consistently across SSR/hydration. Browser-TTS items only
21
- * become voiceable once `voicesReady` flips post-mount — gating on it (instead
21
+ * become voiceable once `voicesReady` flips post-mount, gating on it (instead
22
22
  * of querying `window.speechSynthesis` during render) keeps the first client
23
23
  * render identical to the server.
24
24
  */
@@ -6,7 +6,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
6
6
 
7
7
  //#region src/language/ui.tsx
8
8
  /**
9
- * Shared DOM UI for the language labs — Speaker button + POS-coloured Tile.
9
+ * Shared DOM UI for the language labs, Speaker button + POS-coloured Tile.
10
10
  * Themed via the `.lang-*` classes shipped in `@classytic/labs/styles.css`
11
11
  * (POS colours come from `--lang-pos-*` tokens). Kept here, not in the generic
12
12
  * `kit/controls`, so non-language labs pay nothing for it.
@@ -14,7 +14,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
14
14
  /**
15
15
  * True once the browser's TTS voice list is populated (it loads async).
16
16
  *
17
- * Starts `false` — NOT seeded from `getVoices()` — so the first client render
17
+ * Starts `false`, NOT seeded from `getVoices()`, so the first client render
18
18
  * matches the server (where there's no `speechSynthesis`). Seeding from the
19
19
  * live voice list would make a TTS-only item render its speaker button on the
20
20
  * client but not the server → a hydration mismatch that forces React to
@@ -35,11 +35,11 @@ function useVoicesReady() {
35
35
  return ready;
36
36
  }
37
37
  /**
38
- * A speaker button — renders nothing if the item can't be voiced.
38
+ * A speaker button, renders nothing if the item can't be voiced.
39
39
  *
40
40
  * `audioUrl` items can voice on the server too (no browser needed), so they
41
41
  * render the button consistently across SSR/hydration. Browser-TTS items only
42
- * become voiceable once `voicesReady` flips post-mount — gating on it (instead
42
+ * become voiceable once `voicesReady` flips post-mount, gating on it (instead
43
43
  * of querying `window.speechSynthesis` during render) keeps the first client
44
44
  * render identical to the server.
45
45
  */
@@ -11,11 +11,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
11
11
 
12
12
  //#region src/language/word-match/preset.tsx
13
13
  /**
14
- * WordMatch — pair each word with its meaning (or picture).
14
+ * WordMatch, pair each word with its meaning (or picture).
15
15
  *
16
16
  * Tap a word on the left, then its match on the right; a correct pair locks
17
- * green, a wrong pair flashes. Right side shows the translation, or — for kids /
18
- * concrete vocab — the item's icon (emoji/SVG), which is where image-based
17
+ * green, a wrong pair flashes. Right side shows the translation, or, for kids /
18
+ * concrete vocab, the item's icon (emoji/SVG), which is where image-based
19
19
  * learning genuinely helps (dual coding). Reads its whole content from a `Deck`,
20
20
  * so a new language pair is just new data.
21
21
  */
@@ -0,0 +1,22 @@
1
+ import { LogicDoc } from "./contract.mjs";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/logic/LogicBuildLab.d.ts
5
+ interface LogicBuildProps {
6
+ /** starting canvas. Defaults to a seed derived from the goal, or an empty board. */
7
+ doc?: LogicDoc;
8
+ /** a reference LogicDoc or preset key; when set, the lab grades against its truth table. */
9
+ goal?: LogicDoc | string;
10
+ title?: string;
11
+ prompt?: string;
12
+ activity?: string;
13
+ }
14
+ declare function LogicBuildLab({
15
+ doc: doc0,
16
+ goal,
17
+ title,
18
+ prompt,
19
+ activity
20
+ }?: LogicBuildProps): ReactNode;
21
+ //#endregion
22
+ export { LogicBuildLab, LogicBuildProps };
@@ -0,0 +1,170 @@
1
+ 'use client';
2
+
3
+ import { LabFrame } from "../kit/frame.mjs";
4
+ import { useCheckpoint } from "../kit/pedagogy.mjs";
5
+ import { evaluate } from "./evaluate.mjs";
6
+ import { presetDoc } from "./presets.mjs";
7
+ import { LogicEditor } from "./LogicEditor.mjs";
8
+ import { useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+
11
+ //#region src/logic/LogicBuildLab.tsx
12
+ /**
13
+ * LogicBuildLab — a build-your-own-circuit activity on top of LogicEditor. In sandbox mode it
14
+ * is an open canvas (build, wire, play, watch the signal glow). Given a `goal` (a reference
15
+ * LogicDoc or a preset key) it becomes a graded DLD task: the target truth table is shown, the
16
+ * learner wires gates, and the checkpoint fires when their circuit reproduces every target
17
+ * output column (matched by label, over every input combination). The seed canvas starts with
18
+ * the right switches and LEDs so the learner only has to wire the logic.
19
+ */
20
+ const SIZE = {
21
+ w: 640,
22
+ h: 360
23
+ };
24
+ const labelOf = (n) => n.label ?? n.id;
25
+ /** The column of `outputLabel` over every combination of `inputLabels` (given order); null if missing. */
26
+ function columnByLabels(doc, inputLabels, outputLabel) {
27
+ const idFor = inputLabels.map((lab) => doc.inputs.find((i) => labelOf(i) === lab)?.id);
28
+ if (idFor.some((id) => !id)) return null;
29
+ const out = doc.outputs.find((o) => labelOf(o) === outputLabel);
30
+ if (!out) return null;
31
+ const n = inputLabels.length;
32
+ if (n > 12) return null;
33
+ const col = [];
34
+ for (let m = 0; m < 2 ** n; m++) {
35
+ const setVals = new Map(idFor.map((id, k) => [id, Boolean(m >> n - 1 - k & 1)]));
36
+ const probe = {
37
+ ...doc,
38
+ inputs: doc.inputs.map((i) => setVals.has(i.id) ? {
39
+ ...i,
40
+ value: setVals.get(i.id)
41
+ } : i)
42
+ };
43
+ col.push(evaluate(probe).outputs[out.id] ?? false);
44
+ }
45
+ return col;
46
+ }
47
+ const eqCol = (a, b) => !!a && !!b && a.length === b.length && a.every((v, i) => v === b[i]);
48
+ /** Seed a starting canvas from the goal: its switches + empty LEDs, so the learner just wires gates. */
49
+ function seedFromGoal(goalDoc) {
50
+ return {
51
+ size: SIZE,
52
+ inputs: goalDoc.inputs.map((inp, i) => ({
53
+ id: `in${i + 1}`,
54
+ label: labelOf(inp),
55
+ value: false,
56
+ x: 40,
57
+ y: 36 + i * 58
58
+ })),
59
+ gates: [],
60
+ outputs: goalDoc.outputs.map((o, i) => ({
61
+ id: `out${i + 1}`,
62
+ in: "",
63
+ label: labelOf(o),
64
+ x: SIZE.w - 76,
65
+ y: 56 + i * 72
66
+ }))
67
+ };
68
+ }
69
+ function LogicBuildLab({ doc: doc0, goal, title = "Build the circuit", prompt, activity = "logic-build" } = {}) {
70
+ const goalDoc = goal === void 0 ? null : typeof goal === "string" ? presetDoc(goal) : goal;
71
+ const [doc, setDoc] = useState(() => doc0 ?? (goalDoc ? seedFromGoal(goalDoc) : {
72
+ size: SIZE,
73
+ inputs: [],
74
+ gates: [],
75
+ outputs: []
76
+ }));
77
+ const inputLabels = goalDoc ? goalDoc.inputs.map(labelOf) : [];
78
+ const targets = goalDoc ? goalDoc.outputs.map((o) => ({
79
+ label: labelOf(o),
80
+ col: columnByLabels(goalDoc, inputLabels, labelOf(o))
81
+ })) : [];
82
+ const matchedSame = goalDoc ? doc.inputs.length === goalDoc.inputs.length : false;
83
+ const perOutput = targets.map((t) => ({
84
+ label: t.label,
85
+ ok: matchedSame && eqCol(columnByLabels(doc, inputLabels, t.label), t.col)
86
+ }));
87
+ const solved = !!goalDoc && perOutput.length > 0 && perOutput.every((p) => p.ok);
88
+ useCheckpoint({
89
+ solved,
90
+ activity
91
+ });
92
+ const targetTable = goalDoc ? /* @__PURE__ */ jsx("div", {
93
+ style: { overflowX: "auto" },
94
+ children: /* @__PURE__ */ jsxs("table", {
95
+ style: {
96
+ borderCollapse: "collapse",
97
+ fontSize: 12,
98
+ fontVariantNumeric: "tabular-nums"
99
+ },
100
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [inputLabels.map((l) => /* @__PURE__ */ jsx("th", {
101
+ style: {
102
+ padding: "3px 7px",
103
+ color: "var(--stage-fg)",
104
+ borderBottom: "1px solid var(--stage-grid)"
105
+ },
106
+ children: l
107
+ }, l)), perOutput.map((p) => /* @__PURE__ */ jsxs("th", {
108
+ style: {
109
+ padding: "3px 7px",
110
+ color: p.ok ? "var(--stage-good)" : "var(--stage-accent)",
111
+ borderBottom: "1px solid var(--stage-grid)"
112
+ },
113
+ children: [p.label, p.ok ? " ✓" : ""]
114
+ }, p.label))] }) }), /* @__PURE__ */ jsx("tbody", { children: Array.from({ length: 1 << inputLabels.length }, (_, m) => /* @__PURE__ */ jsxs("tr", { children: [inputLabels.map((_l, k) => /* @__PURE__ */ jsx("td", {
115
+ style: {
116
+ padding: "3px 7px",
117
+ textAlign: "center",
118
+ color: "var(--stage-muted)"
119
+ },
120
+ children: m >> inputLabels.length - 1 - k & 1
121
+ }, k)), targets.map((t) => /* @__PURE__ */ jsx("td", {
122
+ style: {
123
+ padding: "3px 7px",
124
+ textAlign: "center",
125
+ fontWeight: 700,
126
+ color: t.col?.[m] ? "var(--stage-good)" : "var(--stage-fg)"
127
+ },
128
+ children: t.col?.[m] ? 1 : 0
129
+ }, t.label))] }, m)) })]
130
+ })
131
+ }) : null;
132
+ return /* @__PURE__ */ jsxs(LabFrame, {
133
+ title,
134
+ prompt: prompt ?? (goalDoc ? "Drag gates from the palette and wire them so each LED follows the target column for every input." : "Build any circuit: drop sources, gates, and LEDs, wire them up, and flip the switches to watch the signal flow."),
135
+ children: [goalDoc && /* @__PURE__ */ jsxs("div", {
136
+ style: {
137
+ display: "flex",
138
+ flexWrap: "wrap",
139
+ gap: 16,
140
+ alignItems: "flex-start",
141
+ marginBottom: 14
142
+ },
143
+ children: [/* @__PURE__ */ jsx("div", {
144
+ className: "lab-pill",
145
+ "data-state": solved ? "ok" : "no",
146
+ role: "status",
147
+ children: solved ? "✓ your circuit matches the target" : "wire gates so each output matches its column"
148
+ }), /* @__PURE__ */ jsxs("div", {
149
+ style: {
150
+ display: "flex",
151
+ flexDirection: "column",
152
+ gap: 4
153
+ },
154
+ children: [/* @__PURE__ */ jsx("span", {
155
+ style: {
156
+ fontSize: 12,
157
+ color: "var(--stage-muted)"
158
+ },
159
+ children: "target truth table (build a circuit that does this)"
160
+ }), targetTable]
161
+ })]
162
+ }), /* @__PURE__ */ jsx(LogicEditor, {
163
+ value: doc,
164
+ onChange: setDoc
165
+ })]
166
+ });
167
+ }
168
+
169
+ //#endregion
170
+ export { LogicBuildLab };
@@ -0,0 +1,31 @@
1
+ import { LogicDoc } from "./contract.mjs";
2
+ import { PortRef } from "./edit-ops.mjs";
3
+ import { PointerEvent, ReactNode } from "react";
4
+
5
+ //#region src/logic/LogicEditScene.d.ts
6
+ interface LogicEditSceneProps {
7
+ doc: LogicDoc;
8
+ selectedId?: string;
9
+ wireStart?: PortRef;
10
+ /** cursor position (canvas coords) while a wire is pending: the rubber-band trails to it. */
11
+ previewCursor?: {
12
+ x: number;
13
+ y: number;
14
+ };
15
+ onNodePointerDown?: (id: string, e: PointerEvent) => void;
16
+ onPortPointerDown?: (ref: PortRef, e: PointerEvent) => void;
17
+ onBackground?: () => void;
18
+ ariaLabel?: string;
19
+ }
20
+ declare function LogicEditScene({
21
+ doc,
22
+ selectedId,
23
+ wireStart,
24
+ previewCursor,
25
+ onNodePointerDown,
26
+ onPortPointerDown,
27
+ onBackground,
28
+ ariaLabel
29
+ }: LogicEditSceneProps): ReactNode;
30
+ //#endregion
31
+ export { LogicEditScene, LogicEditSceneProps };