@classytic/labs 0.1.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.
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/biology/enzyme-rate/index.d.mts +1 -0
- package/dist/biology/enzyme-rate/preset.d.mts +25 -0
- package/dist/biology/enzyme-rate/preset.mjs +256 -0
- package/dist/biology/genetic-cross/core.d.mts +64 -0
- package/dist/biology/genetic-cross/core.mjs +147 -0
- package/dist/biology/genetic-cross/grid.mjs +239 -0
- package/dist/biology/genetic-cross/index.d.mts +3 -0
- package/dist/biology/genetic-cross/preset.d.mts +26 -0
- package/dist/biology/genetic-cross/preset.mjs +184 -0
- package/dist/biology/genetic-cross/sex-linked.d.mts +27 -0
- package/dist/biology/genetic-cross/sex-linked.mjs +226 -0
- package/dist/biology/index.d.mts +11 -0
- package/dist/biology/index.mjs +12 -0
- package/dist/biology/photosynthesis-factors/index.d.mts +1 -0
- package/dist/biology/photosynthesis-factors/preset.d.mts +25 -0
- package/dist/biology/photosynthesis-factors/preset.mjs +270 -0
- package/dist/biology/punnett-cross/index.d.mts +1 -0
- package/dist/biology/punnett-cross/preset.d.mts +27 -0
- package/dist/biology/punnett-cross/preset.mjs +21 -0
- package/dist/biology/respiration/index.d.mts +1 -0
- package/dist/biology/respiration/preset.d.mts +17 -0
- package/dist/biology/respiration/preset.mjs +179 -0
- package/dist/biology/sequence/central-dogma.d.mts +17 -0
- package/dist/biology/sequence/central-dogma.mjs +339 -0
- package/dist/biology/sequence/core.d.mts +38 -0
- package/dist/biology/sequence/core.mjs +178 -0
- package/dist/biology/sequence/index.d.mts +3 -0
- package/dist/biology/sequence/preset.d.mts +20 -0
- package/dist/biology/sequence/preset.mjs +235 -0
- package/dist/blocks/accounting.d.mts +142 -0
- package/dist/blocks/accounting.mjs +446 -0
- package/dist/blocks/authoring.d.mts +12 -0
- package/dist/blocks/authoring.mjs +705 -0
- package/dist/blocks/biology.d.mts +197 -0
- package/dist/blocks/biology.mjs +513 -0
- package/dist/blocks/chem.d.mts +128 -0
- package/dist/blocks/chem.mjs +486 -0
- package/dist/blocks/circuits.d.mts +86 -0
- package/dist/blocks/circuits.mjs +348 -0
- package/dist/blocks/discrete.d.mts +62 -0
- package/dist/blocks/discrete.mjs +314 -0
- package/dist/blocks/economics.d.mts +56 -0
- package/dist/blocks/economics.mjs +203 -0
- package/dist/blocks/geography.d.mts +58 -0
- package/dist/blocks/geography.mjs +115 -0
- package/dist/blocks/geometry.d.mts +28 -0
- package/dist/blocks/geometry.mjs +160 -0
- package/dist/blocks/ict.d.mts +65 -0
- package/dist/blocks/ict.mjs +197 -0
- package/dist/blocks/index.d.mts +4555 -0
- package/dist/blocks/index.mjs +120 -0
- package/dist/blocks/lab-block.d.mts +16 -0
- package/dist/blocks/lab-block.mjs +74 -0
- package/dist/blocks/lab-config.d.mts +23 -0
- package/dist/blocks/lab-config.mjs +200 -0
- package/dist/blocks/lab-gallery.d.mts +30 -0
- package/dist/blocks/lab-gallery.mjs +208 -0
- package/dist/blocks/language.d.mts +349 -0
- package/dist/blocks/language.mjs +750 -0
- package/dist/blocks/lesson.d.mts +43 -0
- package/dist/blocks/lesson.mjs +140 -0
- package/dist/blocks/math.d.mts +411 -0
- package/dist/blocks/math.mjs +1536 -0
- package/dist/blocks/ml.d.mts +84 -0
- package/dist/blocks/ml.mjs +146 -0
- package/dist/blocks/physics.d.mts +259 -0
- package/dist/blocks/physics.mjs +868 -0
- package/dist/blocks/statistics.d.mts +29 -0
- package/dist/blocks/statistics.mjs +123 -0
- package/dist/catalog/index.d.mts +3 -0
- package/dist/catalog/index.mjs +8 -0
- package/dist/catalog/registry.d.mts +46 -0
- package/dist/catalog/registry.mjs +56 -0
- package/dist/catalog/templates.d.mts +11 -0
- package/dist/catalog/templates.mjs +141 -0
- package/dist/chem/battery.d.mts +16 -0
- package/dist/chem/battery.mjs +311 -0
- package/dist/chem/bohr-atom.d.mts +16 -0
- package/dist/chem/bohr-atom.mjs +212 -0
- package/dist/chem/diffusion/asset.mjs +76 -0
- package/dist/chem/diffusion/index.d.mts +1 -0
- package/dist/chem/diffusion/preset.d.mts +15 -0
- package/dist/chem/diffusion/preset.mjs +188 -0
- package/dist/chem/electrochem/index.d.mts +1 -0
- package/dist/chem/electrochem/preset.d.mts +23 -0
- package/dist/chem/electrochem/preset.mjs +402 -0
- package/dist/chem/equilibrium/index.d.mts +1 -0
- package/dist/chem/equilibrium/preset.d.mts +36 -0
- package/dist/chem/equilibrium/preset.mjs +416 -0
- package/dist/chem/gas-box/index.d.mts +1 -0
- package/dist/chem/gas-box/preset.d.mts +27 -0
- package/dist/chem/gas-box/preset.mjs +395 -0
- package/dist/chem/index.d.mts +16 -0
- package/dist/chem/index.mjs +17 -0
- package/dist/chem/kinetics/index.d.mts +1 -0
- package/dist/chem/kinetics/preset.d.mts +31 -0
- package/dist/chem/kinetics/preset.mjs +478 -0
- package/dist/chem/periodic-trends/index.d.mts +1 -0
- package/dist/chem/periodic-trends/preset.d.mts +21 -0
- package/dist/chem/periodic-trends/preset.mjs +831 -0
- package/dist/chem/reaction-lab.d.mts +18 -0
- package/dist/chem/reaction-lab.mjs +165 -0
- package/dist/chem/reaction-profile.d.mts +21 -0
- package/dist/chem/reaction-profile.mjs +287 -0
- package/dist/chem/solution/dilution.d.mts +27 -0
- package/dist/chem/solution/dilution.mjs +199 -0
- package/dist/chem/solution/field.d.mts +30 -0
- package/dist/chem/solution/field.mjs +145 -0
- package/dist/chem/solution/index.d.mts +3 -0
- package/dist/chem/solution/solution-box.d.mts +28 -0
- package/dist/chem/solution/solution-box.mjs +140 -0
- package/dist/chem/stoichiometry/index.d.mts +1 -0
- package/dist/chem/stoichiometry/preset.d.mts +29 -0
- package/dist/chem/stoichiometry/preset.mjs +392 -0
- package/dist/chem/titration/index.d.mts +1 -0
- package/dist/chem/titration/preset.d.mts +29 -0
- package/dist/chem/titration/preset.mjs +436 -0
- package/dist/circuits/ac-dc/asset.mjs +295 -0
- package/dist/circuits/ac-dc/index.d.mts +1 -0
- package/dist/circuits/ac-dc/preset.d.mts +16 -0
- package/dist/circuits/ac-dc/preset.mjs +134 -0
- package/dist/circuits/capacitor-leak/index.d.mts +1 -0
- package/dist/circuits/capacitor-leak/preset.d.mts +32 -0
- package/dist/circuits/capacitor-leak/preset.mjs +271 -0
- package/dist/circuits/circuit/asset.d.mts +6 -0
- package/dist/circuits/circuit/asset.mjs +367 -0
- package/dist/circuits/circuit/index.d.mts +2 -0
- package/dist/circuits/circuit/preset.d.mts +46 -0
- package/dist/circuits/circuit/preset.mjs +235 -0
- package/dist/circuits/circuit-builder.d.mts +30 -0
- package/dist/circuits/circuit-builder.mjs +412 -0
- package/dist/circuits/circuit-lab.d.mts +20 -0
- package/dist/circuits/circuit-lab.mjs +400 -0
- package/dist/circuits/index.d.mts +7 -0
- package/dist/circuits/index.mjs +8 -0
- package/dist/commerce/accounting/core.d.mts +48 -0
- package/dist/commerce/accounting/core.mjs +57 -0
- package/dist/commerce/accounting/equation-balance.d.mts +35 -0
- package/dist/commerce/accounting/equation-balance.mjs +292 -0
- package/dist/commerce/accounting/index.d.mts +4 -0
- package/dist/commerce/accounting/journal-poster.d.mts +29 -0
- package/dist/commerce/accounting/journal-poster.mjs +472 -0
- package/dist/commerce/accounting/statement-sorter.d.mts +25 -0
- package/dist/commerce/accounting/statement-sorter.mjs +304 -0
- package/dist/commerce/economics/core.d.mts +33 -0
- package/dist/commerce/economics/core.mjs +26 -0
- package/dist/commerce/economics/demand-shift-vs-move.d.mts +35 -0
- package/dist/commerce/economics/demand-shift-vs-move.mjs +324 -0
- package/dist/commerce/economics/elasticity-revenue.d.mts +31 -0
- package/dist/commerce/economics/elasticity-revenue.mjs +253 -0
- package/dist/commerce/economics/index.d.mts +4 -0
- package/dist/commerce/economics/market-equilibrium.d.mts +33 -0
- package/dist/commerce/economics/market-equilibrium.mjs +340 -0
- package/dist/commerce/index.d.mts +9 -0
- package/dist/commerce/index.mjs +10 -0
- package/dist/core/easing.d.mts +28 -0
- package/dist/core/easing.mjs +66 -0
- package/dist/core/index.d.mts +10 -0
- package/dist/core/index.mjs +11 -0
- package/dist/core/numeric.d.mts +37 -0
- package/dist/core/numeric.mjs +75 -0
- package/dist/core/reactive.d.mts +24 -0
- package/dist/core/reactive.mjs +51 -0
- package/dist/core/rng.d.mts +21 -0
- package/dist/core/rng.mjs +39 -0
- package/dist/core/tex.d.mts +14 -0
- package/dist/core/tex.mjs +44 -0
- package/dist/core/timeline.d.mts +34 -0
- package/dist/core/timeline.mjs +77 -0
- package/dist/core/util.d.mts +19 -0
- package/dist/core/util.mjs +31 -0
- package/dist/discrete/arrangements/preset.d.mts +28 -0
- package/dist/discrete/arrangements/preset.mjs +304 -0
- package/dist/discrete/bayes/preset.d.mts +33 -0
- package/dist/discrete/bayes/preset.mjs +476 -0
- package/dist/discrete/binomial/preset.d.mts +25 -0
- package/dist/discrete/binomial/preset.mjs +333 -0
- package/dist/discrete/core/combinatorics.d.mts +23 -0
- package/dist/discrete/core/combinatorics.mjs +57 -0
- package/dist/discrete/core/inclusionExclusion.d.mts +19 -0
- package/dist/discrete/core/inclusionExclusion.mjs +30 -0
- package/dist/discrete/core/pigeonhole.d.mts +15 -0
- package/dist/discrete/core/pigeonhole.mjs +24 -0
- package/dist/discrete/core/probability.d.mts +29 -0
- package/dist/discrete/core/probability.mjs +43 -0
- package/dist/discrete/core/sets.d.mts +21 -0
- package/dist/discrete/core/sets.mjs +45 -0
- package/dist/discrete/counting-slots/preset.d.mts +30 -0
- package/dist/discrete/counting-slots/preset.mjs +553 -0
- package/dist/discrete/counting-tree/index.d.mts +1 -0
- package/dist/discrete/counting-tree/preset.d.mts +44 -0
- package/dist/discrete/counting-tree/preset.mjs +364 -0
- package/dist/discrete/expected-value/preset.d.mts +28 -0
- package/dist/discrete/expected-value/preset.mjs +352 -0
- package/dist/discrete/hypergeometric/preset.d.mts +25 -0
- package/dist/discrete/hypergeometric/preset.mjs +330 -0
- package/dist/discrete/index.d.mts +26 -0
- package/dist/discrete/index.mjs +27 -0
- package/dist/discrete/karnaugh/index.d.mts +1 -0
- package/dist/discrete/karnaugh/preset.d.mts +30 -0
- package/dist/discrete/karnaugh/preset.mjs +452 -0
- package/dist/discrete/lln/asset.mjs +206 -0
- package/dist/discrete/lln/index.d.mts +1 -0
- package/dist/discrete/lln/preset.d.mts +17 -0
- package/dist/discrete/lln/preset.mjs +152 -0
- package/dist/discrete/logic-circuit/index.d.mts +1 -0
- package/dist/discrete/logic-circuit/preset.d.mts +47 -0
- package/dist/discrete/logic-circuit/preset.mjs +307 -0
- package/dist/discrete/monte-carlo/index.d.mts +1 -0
- package/dist/discrete/monte-carlo/preset.d.mts +64 -0
- package/dist/discrete/monte-carlo/preset.mjs +446 -0
- package/dist/discrete/monty-hall/index.d.mts +1 -0
- package/dist/discrete/monty-hall/preset.d.mts +23 -0
- package/dist/discrete/monty-hall/preset.mjs +491 -0
- package/dist/discrete/outcome-builder/preset.d.mts +24 -0
- package/dist/discrete/outcome-builder/preset.mjs +283 -0
- package/dist/discrete/pascal/preset.d.mts +24 -0
- package/dist/discrete/pascal/preset.mjs +372 -0
- package/dist/discrete/sample-space/index.d.mts +1 -0
- package/dist/discrete/sample-space/preset.d.mts +42 -0
- package/dist/discrete/sample-space/preset.mjs +395 -0
- package/dist/discrete/selection/preset.d.mts +33 -0
- package/dist/discrete/selection/preset.mjs +406 -0
- package/dist/discrete/truth-table/index.d.mts +1 -0
- package/dist/discrete/truth-table/preset.d.mts +30 -0
- package/dist/discrete/truth-table/preset.mjs +456 -0
- package/dist/discrete/venn/index.d.mts +1 -0
- package/dist/discrete/venn/preset.d.mts +32 -0
- package/dist/discrete/venn/preset.mjs +461 -0
- package/dist/geography/cycle-lab/index.d.mts +1 -0
- package/dist/geography/cycle-lab/preset.d.mts +25 -0
- package/dist/geography/cycle-lab/preset.mjs +254 -0
- package/dist/geography/cycles.d.mts +21 -0
- package/dist/geography/cycles.mjs +205 -0
- package/dist/geography/index.d.mts +4 -0
- package/dist/geography/index.mjs +5 -0
- package/dist/geometry/board/index.d.mts +1 -0
- package/dist/geometry/board/preset.d.mts +71 -0
- package/dist/geometry/board/preset.mjs +148 -0
- package/dist/geometry/builder.d.mts +18 -0
- package/dist/geometry/builder.mjs +332 -0
- package/dist/geometry/index.d.mts +4 -0
- package/dist/geometry/index.mjs +5 -0
- package/dist/geometry/intersecting-circles.d.mts +17 -0
- package/dist/geometry/intersecting-circles.mjs +104 -0
- package/dist/ict/index.d.mts +5 -0
- package/dist/ict/index.mjs +6 -0
- package/dist/ict/number-systems/base-odometer.d.mts +34 -0
- package/dist/ict/number-systems/base-odometer.mjs +160 -0
- package/dist/ict/number-systems/bit-grouper.d.mts +32 -0
- package/dist/ict/number-systems/bit-grouper.mjs +190 -0
- package/dist/ict/number-systems/index.d.mts +4 -0
- package/dist/ict/number-systems/place-value-dial.d.mts +29 -0
- package/dist/ict/number-systems/place-value-dial.mjs +153 -0
- package/dist/ict/number-systems/wheel.d.mts +73 -0
- package/dist/ict/number-systems/wheel.mjs +279 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.mjs +11 -0
- package/dist/kit/anim.mjs +52 -0
- package/dist/kit/annotate.mjs +116 -0
- package/dist/kit/answer-check.d.mts +38 -0
- package/dist/kit/answer-check.mjs +65 -0
- package/dist/kit/asset-util.mjs +15 -0
- package/dist/kit/controls.mjs +77 -0
- package/dist/kit/cycle.d.mts +44 -0
- package/dist/kit/cycle.mjs +188 -0
- package/dist/kit/diagram.mjs +176 -0
- package/dist/kit/electronics.mjs +357 -0
- package/dist/kit/expr-analysis.d.mts +37 -0
- package/dist/kit/expr-analysis.mjs +111 -0
- package/dist/kit/frame.d.mts +70 -0
- package/dist/kit/frame.mjs +205 -0
- package/dist/kit/freq-tree.mjs +99 -0
- package/dist/kit/gameshow.mjs +315 -0
- package/dist/kit/index.d.mts +5 -0
- package/dist/kit/index.mjs +6 -0
- package/dist/kit/logic-gates.d.mts +6 -0
- package/dist/kit/logic-gates.mjs +210 -0
- package/dist/kit/molecules.mjs +178 -0
- package/dist/kit/pedagogy.d.mts +126 -0
- package/dist/kit/pedagogy.mjs +331 -0
- package/dist/kit/play.d.mts +21 -0
- package/dist/kit/play.mjs +52 -0
- package/dist/kit/probability.mjs +141 -0
- package/dist/kit/proportion.mjs +112 -0
- package/dist/kit/reaction.mjs +102 -0
- package/dist/kit/rich.d.mts +10 -0
- package/dist/kit/rich.mjs +21 -0
- package/dist/kit/scale.mjs +230 -0
- package/dist/kit/space.mjs +326 -0
- package/dist/kit/steps.d.mts +24 -0
- package/dist/kit/steps.mjs +57 -0
- package/dist/kit/thermal.mjs +289 -0
- package/dist/language/agreement/index.d.mts +1 -0
- package/dist/language/agreement/preset.d.mts +27 -0
- package/dist/language/agreement/preset.mjs +113 -0
- package/dist/language/article-lens/index.d.mts +1 -0
- package/dist/language/article-lens/preset.d.mts +31 -0
- package/dist/language/article-lens/preset.mjs +125 -0
- package/dist/language/deck.d.mts +45 -0
- package/dist/language/deck.mjs +61 -0
- package/dist/language/icon.d.mts +40 -0
- package/dist/language/icon.mjs +73 -0
- package/dist/language/index.d.mts +10 -0
- package/dist/language/index.mjs +11 -0
- package/dist/language/preposition-scene/index.d.mts +1 -0
- package/dist/language/preposition-scene/preset.d.mts +34 -0
- package/dist/language/preposition-scene/preset.mjs +234 -0
- package/dist/language/sentence-builder/index.d.mts +1 -0
- package/dist/language/sentence-builder/preset.d.mts +32 -0
- package/dist/language/sentence-builder/preset.mjs +122 -0
- package/dist/language/transform/index.d.mts +1 -0
- package/dist/language/transform/preset.d.mts +31 -0
- package/dist/language/transform/preset.mjs +137 -0
- package/dist/language/ui.d.mts +53 -0
- package/dist/language/ui.mjs +88 -0
- package/dist/language/word-match/index.d.mts +1 -0
- package/dist/language/word-match/preset.d.mts +22 -0
- package/dist/language/word-match/preset.mjs +148 -0
- package/dist/math/area-model/asset.d.mts +6 -0
- package/dist/math/area-model/asset.mjs +270 -0
- package/dist/math/area-model/index.d.mts +2 -0
- package/dist/math/area-model/preset.d.mts +29 -0
- package/dist/math/area-model/preset.mjs +243 -0
- package/dist/math/balance-algebra/asset.d.mts +6 -0
- package/dist/math/balance-algebra/asset.mjs +150 -0
- package/dist/math/balance-algebra/index.d.mts +2 -0
- package/dist/math/balance-algebra/preset.d.mts +30 -0
- package/dist/math/balance-algebra/preset.mjs +228 -0
- package/dist/math/derivation.d.mts +22 -0
- package/dist/math/derivation.mjs +113 -0
- package/dist/math/derivative-explorer/index.d.mts +1 -0
- package/dist/math/derivative-explorer/preset.d.mts +19 -0
- package/dist/math/derivative-explorer/preset.mjs +227 -0
- package/dist/math/function-machine/index.d.mts +1 -0
- package/dist/math/function-machine/preset.d.mts +21 -0
- package/dist/math/function-machine/preset.mjs +177 -0
- package/dist/math/gradient-descent.d.mts +23 -0
- package/dist/math/gradient-descent.mjs +473 -0
- package/dist/math/grapher/index.d.mts +1 -0
- package/dist/math/grapher/preset.d.mts +40 -0
- package/dist/math/grapher/preset.mjs +313 -0
- package/dist/math/harmonic-form/index.d.mts +1 -0
- package/dist/math/harmonic-form/preset.d.mts +21 -0
- package/dist/math/harmonic-form/preset.mjs +387 -0
- package/dist/math/index.d.mts +25 -0
- package/dist/math/index.mjs +26 -0
- package/dist/math/integral-explorer/index.d.mts +1 -0
- package/dist/math/integral-explorer/preset.d.mts +23 -0
- package/dist/math/integral-explorer/preset.mjs +217 -0
- package/dist/math/interactive/index.d.mts +1 -0
- package/dist/math/interactive/preset.d.mts +72 -0
- package/dist/math/interactive/preset.mjs +202 -0
- package/dist/math/limit-explorer/index.d.mts +1 -0
- package/dist/math/limit-explorer/preset.d.mts +19 -0
- package/dist/math/limit-explorer/preset.mjs +216 -0
- package/dist/math/linear-system/index.d.mts +1 -0
- package/dist/math/linear-system/preset.d.mts +28 -0
- package/dist/math/linear-system/preset.mjs +164 -0
- package/dist/math/mystery-bucket/asset.d.mts +6 -0
- package/dist/math/mystery-bucket/asset.mjs +145 -0
- package/dist/math/mystery-bucket/index.d.mts +2 -0
- package/dist/math/mystery-bucket/preset.d.mts +36 -0
- package/dist/math/mystery-bucket/preset.mjs +116 -0
- package/dist/math/number-line/index.d.mts +1 -0
- package/dist/math/number-line/preset.d.mts +24 -0
- package/dist/math/number-line/preset.mjs +142 -0
- package/dist/math/parabola/index.d.mts +1 -0
- package/dist/math/parabola/preset.d.mts +13 -0
- package/dist/math/parabola/preset.mjs +79 -0
- package/dist/math/pattern/asset.d.mts +6 -0
- package/dist/math/pattern/asset.mjs +102 -0
- package/dist/math/pattern/index.d.mts +2 -0
- package/dist/math/pattern/preset.d.mts +32 -0
- package/dist/math/pattern/preset.mjs +294 -0
- package/dist/math/triangle-trig/index.d.mts +1 -0
- package/dist/math/triangle-trig/preset.d.mts +47 -0
- package/dist/math/triangle-trig/preset.mjs +245 -0
- package/dist/math/trig-explorer.d.mts +18 -0
- package/dist/math/trig-explorer.mjs +209 -0
- package/dist/ml/boundary/index.d.mts +1 -0
- package/dist/ml/boundary/preset.d.mts +24 -0
- package/dist/ml/boundary/preset.mjs +385 -0
- package/dist/ml/classifier/index.d.mts +1 -0
- package/dist/ml/classifier/preset.d.mts +25 -0
- package/dist/ml/classifier/preset.mjs +315 -0
- package/dist/ml/index.d.mts +6 -0
- package/dist/ml/index.mjs +7 -0
- package/dist/ml/kmeans/index.d.mts +1 -0
- package/dist/ml/kmeans/preset.d.mts +33 -0
- package/dist/ml/kmeans/preset.mjs +236 -0
- package/dist/ml/knn/index.d.mts +1 -0
- package/dist/ml/knn/preset.d.mts +28 -0
- package/dist/ml/knn/preset.mjs +279 -0
- package/dist/ml/regression/index.d.mts +1 -0
- package/dist/ml/regression/preset.d.mts +32 -0
- package/dist/ml/regression/preset.mjs +394 -0
- package/dist/physics/atwood/index.d.mts +1 -0
- package/dist/physics/atwood/preset.d.mts +23 -0
- package/dist/physics/atwood/preset.mjs +312 -0
- package/dist/physics/bullet-walls/index.d.mts +1 -0
- package/dist/physics/bullet-walls/preset.d.mts +28 -0
- package/dist/physics/bullet-walls/preset.mjs +373 -0
- package/dist/physics/carnot/index.d.mts +1 -0
- package/dist/physics/carnot/preset.d.mts +27 -0
- package/dist/physics/carnot/preset.mjs +427 -0
- package/dist/physics/circular-motion/index.d.mts +1 -0
- package/dist/physics/circular-motion/preset.d.mts +25 -0
- package/dist/physics/circular-motion/preset.mjs +293 -0
- package/dist/physics/collision-track/index.d.mts +1 -0
- package/dist/physics/collision-track/preset.d.mts +27 -0
- package/dist/physics/collision-track/preset.mjs +352 -0
- package/dist/physics/efficiency/index.d.mts +1 -0
- package/dist/physics/efficiency/preset.d.mts +33 -0
- package/dist/physics/efficiency/preset.mjs +343 -0
- package/dist/physics/electric-field/index.d.mts +1 -0
- package/dist/physics/electric-field/preset.d.mts +15 -0
- package/dist/physics/electric-field/preset.mjs +306 -0
- package/dist/physics/energy-skate/index.d.mts +1 -0
- package/dist/physics/energy-skate/preset.d.mts +25 -0
- package/dist/physics/energy-skate/preset.mjs +254 -0
- package/dist/physics/entropy/index.d.mts +1 -0
- package/dist/physics/entropy/preset.d.mts +18 -0
- package/dist/physics/entropy/preset.mjs +416 -0
- package/dist/physics/expansion/index.d.mts +1 -0
- package/dist/physics/expansion/preset.d.mts +26 -0
- package/dist/physics/expansion/preset.mjs +609 -0
- package/dist/physics/exponential/asset.mjs +221 -0
- package/dist/physics/exponential/index.d.mts +1 -0
- package/dist/physics/exponential/preset.d.mts +17 -0
- package/dist/physics/exponential/preset.mjs +182 -0
- package/dist/physics/gas-process/index.d.mts +1 -0
- package/dist/physics/gas-process/preset.d.mts +30 -0
- package/dist/physics/gas-process/preset.mjs +384 -0
- package/dist/physics/gravitation/index.d.mts +1 -0
- package/dist/physics/gravitation/preset.d.mts +24 -0
- package/dist/physics/gravitation/preset.mjs +345 -0
- package/dist/physics/gravity-drop.d.mts +9 -0
- package/dist/physics/gravity-drop.mjs +187 -0
- package/dist/physics/heat-transfer/index.d.mts +1 -0
- package/dist/physics/heat-transfer/preset.d.mts +27 -0
- package/dist/physics/heat-transfer/preset.mjs +626 -0
- package/dist/physics/impulse/index.d.mts +1 -0
- package/dist/physics/impulse/preset.d.mts +29 -0
- package/dist/physics/impulse/preset.mjs +453 -0
- package/dist/physics/index.d.mts +43 -0
- package/dist/physics/index.mjs +44 -0
- package/dist/physics/kepler/index.d.mts +1 -0
- package/dist/physics/kepler/preset.d.mts +27 -0
- package/dist/physics/kepler/preset.mjs +257 -0
- package/dist/physics/lever/asset.d.mts +6 -0
- package/dist/physics/lever/asset.mjs +220 -0
- package/dist/physics/lever/index.d.mts +2 -0
- package/dist/physics/lever/preset.d.mts +31 -0
- package/dist/physics/lever/preset.mjs +261 -0
- package/dist/physics/lorentz/index.d.mts +1 -0
- package/dist/physics/lorentz/preset.d.mts +29 -0
- package/dist/physics/lorentz/preset.mjs +367 -0
- package/dist/physics/magnetism/index.d.mts +1 -0
- package/dist/physics/magnetism/preset.d.mts +15 -0
- package/dist/physics/magnetism/preset.mjs +334 -0
- package/dist/physics/optics/asset.d.mts +6 -0
- package/dist/physics/optics/asset.mjs +234 -0
- package/dist/physics/optics/index.d.mts +2 -0
- package/dist/physics/optics/preset.d.mts +14 -0
- package/dist/physics/optics/preset.mjs +202 -0
- package/dist/physics/orbit-lab.d.mts +6 -0
- package/dist/physics/orbit-lab.mjs +222 -0
- package/dist/physics/projectile-lab.d.mts +10 -0
- package/dist/physics/projectile-lab.mjs +354 -0
- package/dist/physics/rain-relative/index.d.mts +1 -0
- package/dist/physics/rain-relative/preset.d.mts +19 -0
- package/dist/physics/rain-relative/preset.mjs +358 -0
- package/dist/physics/ramp-forces/index.d.mts +1 -0
- package/dist/physics/ramp-forces/preset.d.mts +36 -0
- package/dist/physics/ramp-forces/preset.mjs +550 -0
- package/dist/physics/river-boat.d.mts +22 -0
- package/dist/physics/river-boat.mjs +498 -0
- package/dist/physics/shm/index.d.mts +1 -0
- package/dist/physics/shm/preset.d.mts +33 -0
- package/dist/physics/shm/preset.mjs +554 -0
- package/dist/physics/stopping-distance/index.d.mts +1 -0
- package/dist/physics/stopping-distance/preset.d.mts +29 -0
- package/dist/physics/stopping-distance/preset.mjs +662 -0
- package/dist/physics/temperature-scales/index.d.mts +1 -0
- package/dist/physics/temperature-scales/preset.d.mts +15 -0
- package/dist/physics/temperature-scales/preset.mjs +353 -0
- package/dist/physics/terminal-velocity/index.d.mts +1 -0
- package/dist/physics/terminal-velocity/preset.d.mts +26 -0
- package/dist/physics/terminal-velocity/preset.mjs +404 -0
- package/dist/physics/thermal/index.d.mts +1 -0
- package/dist/physics/thermal/preset.d.mts +44 -0
- package/dist/physics/thermal/preset.mjs +373 -0
- package/dist/physics/vector-board/index.d.mts +1 -0
- package/dist/physics/vector-board/preset.d.mts +65 -0
- package/dist/physics/vector-board/preset.mjs +273 -0
- package/dist/physics/vector-board/view.d.mts +49 -0
- package/dist/physics/vector-board/view.mjs +58 -0
- package/dist/physics/vector-scene.d.mts +41 -0
- package/dist/physics/vector-scene.mjs +211 -0
- package/dist/physics/vector-types/index.d.mts +1 -0
- package/dist/physics/vector-types/preset.d.mts +27 -0
- package/dist/physics/vector-types/preset.mjs +192 -0
- package/dist/physics/water-density/index.d.mts +1 -0
- package/dist/physics/water-density/preset.d.mts +18 -0
- package/dist/physics/water-density/preset.mjs +439 -0
- package/dist/physics/waves/core.mjs +33 -0
- package/dist/physics/waves/doppler.d.mts +23 -0
- package/dist/physics/waves/doppler.mjs +260 -0
- package/dist/physics/waves/index.d.mts +4 -0
- package/dist/physics/waves/preset.d.mts +30 -0
- package/dist/physics/waves/preset.mjs +488 -0
- package/dist/physics/waves/ripple.d.mts +26 -0
- package/dist/physics/waves/ripple.mjs +234 -0
- package/dist/physics/waves/string.d.mts +29 -0
- package/dist/physics/waves/string.mjs +289 -0
- package/dist/physics/work-energy/index.d.mts +1 -0
- package/dist/physics/work-energy/preset.d.mts +17 -0
- package/dist/physics/work-energy/preset.mjs +341 -0
- package/dist/schemas/index.d.mts +235 -0
- package/dist/schemas/index.mjs +145 -0
- package/dist/statistics/center-spread/preset.d.mts +34 -0
- package/dist/statistics/center-spread/preset.mjs +323 -0
- package/dist/statistics/core/descriptive.d.mts +35 -0
- package/dist/statistics/core/descriptive.mjs +64 -0
- package/dist/statistics/core/normal.d.mts +21 -0
- package/dist/statistics/core/normal.mjs +37 -0
- package/dist/statistics/core/sequences.d.mts +27 -0
- package/dist/statistics/core/sequences.mjs +35 -0
- package/dist/statistics/galton/preset.d.mts +27 -0
- package/dist/statistics/galton/preset.mjs +331 -0
- package/dist/statistics/histogram/preset.d.mts +27 -0
- package/dist/statistics/histogram/preset.mjs +385 -0
- package/dist/statistics/index.d.mts +11 -0
- package/dist/statistics/index.mjs +12 -0
- package/dist/statistics/normal/preset.d.mts +30 -0
- package/dist/statistics/normal/preset.mjs +400 -0
- package/dist/statistics/sampling/preset.d.mts +32 -0
- package/dist/statistics/sampling/preset.mjs +406 -0
- package/dist/statistics/sequence/preset.d.mts +28 -0
- package/dist/statistics/sequence/preset.mjs +302 -0
- package/dist/statistics/z-table/preset.d.mts +28 -0
- package/dist/statistics/z-table/preset.mjs +348 -0
- package/package.json +266 -0
- package/styles.css +267 -0
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
import { LeverBalanceLab } from "../physics/lever/preset.mjs";
|
|
2
|
+
import { OpticsLab } from "../physics/optics/preset.mjs";
|
|
3
|
+
import { ProjectileLab } from "../physics/projectile-lab.mjs";
|
|
4
|
+
import { GravityDrop } from "../physics/gravity-drop.mjs";
|
|
5
|
+
import { RiverBoat } from "../physics/river-boat.mjs";
|
|
6
|
+
import { VectorTypesLab } from "../physics/vector-types/preset.mjs";
|
|
7
|
+
import { RainRelativeLab } from "../physics/rain-relative/preset.mjs";
|
|
8
|
+
import { StoppingDistanceLab } from "../physics/stopping-distance/preset.mjs";
|
|
9
|
+
import { RampForcesLab } from "../physics/ramp-forces/preset.mjs";
|
|
10
|
+
import { CollisionTrackLab } from "../physics/collision-track/preset.mjs";
|
|
11
|
+
import { ImpulseLab } from "../physics/impulse/preset.mjs";
|
|
12
|
+
import { BulletWallsLab } from "../physics/bullet-walls/preset.mjs";
|
|
13
|
+
import { CircularMotionLab } from "../physics/circular-motion/preset.mjs";
|
|
14
|
+
import { EnergySkateLab } from "../physics/energy-skate/preset.mjs";
|
|
15
|
+
import { SimpleHarmonicLab } from "../physics/shm/preset.mjs";
|
|
16
|
+
import { AtwoodLab } from "../physics/atwood/preset.mjs";
|
|
17
|
+
import { TerminalVelocityLab } from "../physics/terminal-velocity/preset.mjs";
|
|
18
|
+
import { KeplerLab } from "../physics/kepler/preset.mjs";
|
|
19
|
+
import { GravitationLab } from "../physics/gravitation/preset.mjs";
|
|
20
|
+
import { OrbitLab } from "../physics/orbit-lab.mjs";
|
|
21
|
+
import { WaveLab } from "../physics/waves/preset.mjs";
|
|
22
|
+
import { RippleTankLab } from "../physics/waves/ripple.mjs";
|
|
23
|
+
import { DopplerLab } from "../physics/waves/doppler.mjs";
|
|
24
|
+
import { StringReflectionLab } from "../physics/waves/string.mjs";
|
|
25
|
+
import { MagnetismLab } from "../physics/magnetism/preset.mjs";
|
|
26
|
+
import { LorentzForceLab } from "../physics/lorentz/preset.mjs";
|
|
27
|
+
import { HeatingCurveLab } from "../physics/thermal/preset.mjs";
|
|
28
|
+
import { HeatTransferLab } from "../physics/heat-transfer/preset.mjs";
|
|
29
|
+
import { ThermalExpansionLab } from "../physics/expansion/preset.mjs";
|
|
30
|
+
import { TemperatureScalesLab } from "../physics/temperature-scales/preset.mjs";
|
|
31
|
+
import { WaterDensityLab } from "../physics/water-density/preset.mjs";
|
|
32
|
+
import { GasProcessLab } from "../physics/gas-process/preset.mjs";
|
|
33
|
+
import { CarnotCycleLab } from "../physics/carnot/preset.mjs";
|
|
34
|
+
import { EntropyLab } from "../physics/entropy/preset.mjs";
|
|
35
|
+
import { EfficiencyLab } from "../physics/efficiency/preset.mjs";
|
|
36
|
+
import { ChipToggle, ConfigPanel, ConfigRow, JsonArea, NumField, RowsEditor, TagsField, TextField, coerceArray } from "./authoring.mjs";
|
|
37
|
+
import { VECTOR_BOARD_DEMO, VectorBoardView } from "../physics/vector-board/view.mjs";
|
|
38
|
+
import { controlConfigSchema, flatVecSchema, typePanelSchema } from "../schemas/index.mjs";
|
|
39
|
+
import { buildComponents, commonLabProps, labBlock } from "./lab-block.mjs";
|
|
40
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
41
|
+
import { z } from "zod";
|
|
42
|
+
import { defineBlock } from "@classytic/cms-ui/contract";
|
|
43
|
+
|
|
44
|
+
//#region src/blocks/physics.tsx
|
|
45
|
+
const ProjectileLabBlock = defineBlock({
|
|
46
|
+
key: "projectile-lab",
|
|
47
|
+
void: true,
|
|
48
|
+
label: "Projectile lab",
|
|
49
|
+
description: "Interactive projectile motion — tune angle & speed, hit a target.",
|
|
50
|
+
category: "interactive",
|
|
51
|
+
schema: z.object({
|
|
52
|
+
targetMeters: z.number().optional(),
|
|
53
|
+
g: z.number().optional()
|
|
54
|
+
}),
|
|
55
|
+
Component: ({ attributes }) => /* @__PURE__ */ jsx(ProjectileLab, {
|
|
56
|
+
targetMeters: attributes.targetMeters,
|
|
57
|
+
g: attributes.g
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
const OrbitLabBlock = defineBlock({
|
|
61
|
+
key: "orbit-lab",
|
|
62
|
+
void: true,
|
|
63
|
+
label: "Orbit lab",
|
|
64
|
+
description: "Interactive orbit — launch a satellite: crash, orbit, or escape.",
|
|
65
|
+
category: "interactive",
|
|
66
|
+
schema: z.object({}),
|
|
67
|
+
Component: () => /* @__PURE__ */ jsx(OrbitLab, {})
|
|
68
|
+
});
|
|
69
|
+
const GravityDropBlock = defineBlock({
|
|
70
|
+
key: "gravity-drop",
|
|
71
|
+
void: true,
|
|
72
|
+
label: "Gravity drop",
|
|
73
|
+
description: "Drop balls on three worlds — compare how gravity changes the fall.",
|
|
74
|
+
category: "interactive",
|
|
75
|
+
schema: z.object({ height: z.number().optional() }),
|
|
76
|
+
Component: ({ attributes }) => /* @__PURE__ */ jsx(GravityDrop, { height: attributes.height })
|
|
77
|
+
});
|
|
78
|
+
const RiverBoatBlock = defineBlock({
|
|
79
|
+
key: "river-boat",
|
|
80
|
+
void: true,
|
|
81
|
+
label: "River crossing (vectors)",
|
|
82
|
+
description: "Boat-and-river vector problem — step through tip-to-tail addition + component resolution.",
|
|
83
|
+
category: "interactive",
|
|
84
|
+
schema: z.object({
|
|
85
|
+
boatSpeed: z.number().optional(),
|
|
86
|
+
current: z.number().optional(),
|
|
87
|
+
riverWidth: z.number().optional(),
|
|
88
|
+
title: z.string().optional()
|
|
89
|
+
}),
|
|
90
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
91
|
+
const boatSpeed = typeof attributes.boatSpeed === "number" ? attributes.boatSpeed : 4;
|
|
92
|
+
const current = typeof attributes.current === "number" ? attributes.current : 2;
|
|
93
|
+
const riverWidth = typeof attributes.riverWidth === "number" ? attributes.riverWidth : 8;
|
|
94
|
+
const title = attributes.title ?? "Crossing a flowing river";
|
|
95
|
+
const widget = /* @__PURE__ */ jsx(RiverBoat, {
|
|
96
|
+
boatSpeed,
|
|
97
|
+
current,
|
|
98
|
+
riverWidth,
|
|
99
|
+
title
|
|
100
|
+
});
|
|
101
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
102
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
103
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
104
|
+
label: "Title",
|
|
105
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
106
|
+
value: title,
|
|
107
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
108
|
+
className: "flex-1"
|
|
109
|
+
})
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
112
|
+
label: "boat vᵦ",
|
|
113
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
114
|
+
value: boatSpeed,
|
|
115
|
+
onChange: (v) => updateAttributes({ boatSpeed: v })
|
|
116
|
+
})
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
119
|
+
label: "current vᵧ",
|
|
120
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
121
|
+
value: current,
|
|
122
|
+
onChange: (v) => updateAttributes({ current: v })
|
|
123
|
+
})
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
126
|
+
label: "river width",
|
|
127
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
128
|
+
value: riverWidth,
|
|
129
|
+
onChange: (v) => updateAttributes({ riverWidth: v })
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
] }), widget] });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
/** Simple lever authoring → the labs component's items[] API. */
|
|
136
|
+
function LeverPuzzle({ knownWeight = 4, knownDist = 3, unknownDist = 2, maxWeight = 12, controlId }) {
|
|
137
|
+
return /* @__PURE__ */ jsx(LeverBalanceLab, {
|
|
138
|
+
items: [{
|
|
139
|
+
side: "L",
|
|
140
|
+
dist: knownDist,
|
|
141
|
+
weight: knownWeight
|
|
142
|
+
}, {
|
|
143
|
+
side: "R",
|
|
144
|
+
dist: unknownDist,
|
|
145
|
+
weight: "unknown"
|
|
146
|
+
}],
|
|
147
|
+
maxWeight,
|
|
148
|
+
controlId
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const OpticsBlock = defineBlock({
|
|
152
|
+
key: "optics",
|
|
153
|
+
tag: "Optics",
|
|
154
|
+
void: true,
|
|
155
|
+
label: "Optics (reflect the ray)",
|
|
156
|
+
description: "Drag the source / mirrors so the light ray reflects into the target.",
|
|
157
|
+
category: "interactive",
|
|
158
|
+
schema: z.object({}),
|
|
159
|
+
Component: ({ mode }) => mode === "editing" ? /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(ConfigPanel, { children: /* @__PURE__ */ jsx("span", {
|
|
160
|
+
style: { opacity: .7 },
|
|
161
|
+
children: "No settings — drag the source, aim, or mirrors in the lesson."
|
|
162
|
+
}) }), /* @__PURE__ */ jsx(OpticsLab, {})] }) : /* @__PURE__ */ jsx(OpticsLab, {})
|
|
163
|
+
});
|
|
164
|
+
const LeverBlock = defineBlock({
|
|
165
|
+
key: "lever",
|
|
166
|
+
tag: "Lever",
|
|
167
|
+
void: true,
|
|
168
|
+
label: "Lever (balance the torque)",
|
|
169
|
+
description: "A known weight at a distance vs an unknown — set the unknown so turning effects match.",
|
|
170
|
+
category: "interactive",
|
|
171
|
+
schema: z.object({
|
|
172
|
+
knownWeight: z.number().default(4),
|
|
173
|
+
knownDist: z.number().default(3),
|
|
174
|
+
unknownDist: z.number().default(2),
|
|
175
|
+
controlId: z.string().optional()
|
|
176
|
+
}),
|
|
177
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
178
|
+
const { knownWeight = 4, knownDist = 3, unknownDist = 2 } = attributes;
|
|
179
|
+
const widget = /* @__PURE__ */ jsx(LeverPuzzle, {
|
|
180
|
+
knownWeight,
|
|
181
|
+
knownDist,
|
|
182
|
+
unknownDist,
|
|
183
|
+
controlId: attributes.controlId
|
|
184
|
+
});
|
|
185
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
186
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
187
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
188
|
+
label: "known weight",
|
|
189
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
190
|
+
value: knownWeight,
|
|
191
|
+
onChange: (v) => updateAttributes({ knownWeight: v })
|
|
192
|
+
})
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
195
|
+
label: "its distance",
|
|
196
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
197
|
+
value: knownDist,
|
|
198
|
+
onChange: (v) => updateAttributes({ knownDist: v })
|
|
199
|
+
})
|
|
200
|
+
}),
|
|
201
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
202
|
+
label: "unknown distance",
|
|
203
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
204
|
+
value: unknownDist,
|
|
205
|
+
onChange: (v) => updateAttributes({ unknownDist: v })
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
] }), widget] });
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
const VectorBoardBlock = defineBlock({
|
|
212
|
+
key: "vector-board",
|
|
213
|
+
tag: "VectorBoard",
|
|
214
|
+
void: true,
|
|
215
|
+
label: "Vector board (resultant / relative)",
|
|
216
|
+
description: "Drag vector heads; live resultant (sum) or relative velocity (diff, the rain case) + angle. Optional drag-to-match goal.",
|
|
217
|
+
category: "interactive",
|
|
218
|
+
schema: z.object({
|
|
219
|
+
vectors: z.array(flatVecSchema).default(VECTOR_BOARD_DEMO),
|
|
220
|
+
combine: z.enum([
|
|
221
|
+
"sum",
|
|
222
|
+
"diff",
|
|
223
|
+
"none"
|
|
224
|
+
]).default("sum"),
|
|
225
|
+
goalX: z.union([z.number(), z.string()]).optional(),
|
|
226
|
+
goalY: z.union([z.number(), z.string()]).optional(),
|
|
227
|
+
components: z.boolean().optional(),
|
|
228
|
+
angle: z.boolean().default(true),
|
|
229
|
+
objectives: z.array(z.string()).optional(),
|
|
230
|
+
hints: z.array(z.string()).optional(),
|
|
231
|
+
title: z.string().optional(),
|
|
232
|
+
prompt: z.string().optional()
|
|
233
|
+
}),
|
|
234
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
235
|
+
const vectors = coerceArray(attributes.vectors, VECTOR_BOARD_DEMO);
|
|
236
|
+
const objectives = coerceArray(attributes.objectives);
|
|
237
|
+
const hints = coerceArray(attributes.hints);
|
|
238
|
+
const widget = /* @__PURE__ */ jsx(VectorBoardView, {
|
|
239
|
+
vectors,
|
|
240
|
+
combine: attributes.combine,
|
|
241
|
+
goalX: attributes.goalX,
|
|
242
|
+
goalY: attributes.goalY,
|
|
243
|
+
components: attributes.components,
|
|
244
|
+
angle: attributes.angle,
|
|
245
|
+
objectives,
|
|
246
|
+
hints,
|
|
247
|
+
title: attributes.title,
|
|
248
|
+
prompt: attributes.prompt
|
|
249
|
+
});
|
|
250
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
251
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
252
|
+
/* @__PURE__ */ jsxs(ConfigRow, {
|
|
253
|
+
label: "combine",
|
|
254
|
+
children: [/* @__PURE__ */ jsx(ChipToggle, {
|
|
255
|
+
active: attributes.combine === "sum",
|
|
256
|
+
onClick: () => updateAttributes({ combine: "sum" }),
|
|
257
|
+
children: "sum"
|
|
258
|
+
}), /* @__PURE__ */ jsx(ChipToggle, {
|
|
259
|
+
active: attributes.combine === "diff",
|
|
260
|
+
onClick: () => updateAttributes({ combine: "diff" }),
|
|
261
|
+
children: "diff (relative)"
|
|
262
|
+
})]
|
|
263
|
+
}),
|
|
264
|
+
/* @__PURE__ */ jsxs(ConfigRow, {
|
|
265
|
+
label: "show",
|
|
266
|
+
children: [/* @__PURE__ */ jsx(ChipToggle, {
|
|
267
|
+
active: !!attributes.components,
|
|
268
|
+
onClick: () => updateAttributes({ components: !attributes.components }),
|
|
269
|
+
children: "components"
|
|
270
|
+
}), /* @__PURE__ */ jsx(ChipToggle, {
|
|
271
|
+
active: attributes.angle !== false,
|
|
272
|
+
onClick: () => updateAttributes({ angle: attributes.angle === false }),
|
|
273
|
+
children: "angle"
|
|
274
|
+
})]
|
|
275
|
+
}),
|
|
276
|
+
/* @__PURE__ */ jsxs(ConfigRow, {
|
|
277
|
+
label: "target",
|
|
278
|
+
children: [/* @__PURE__ */ jsx(TextField, {
|
|
279
|
+
value: String(attributes.goalX ?? ""),
|
|
280
|
+
onChange: (v) => updateAttributes({ goalX: v }),
|
|
281
|
+
placeholder: "x"
|
|
282
|
+
}), /* @__PURE__ */ jsx(TextField, {
|
|
283
|
+
value: String(attributes.goalY ?? ""),
|
|
284
|
+
onChange: (v) => updateAttributes({ goalY: v }),
|
|
285
|
+
placeholder: "y"
|
|
286
|
+
})]
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
289
|
+
label: "objectives",
|
|
290
|
+
children: /* @__PURE__ */ jsx(TagsField, {
|
|
291
|
+
value: objectives,
|
|
292
|
+
onChange: (v) => updateAttributes({ objectives: v }),
|
|
293
|
+
placeholder: "comma-separated goals"
|
|
294
|
+
})
|
|
295
|
+
}),
|
|
296
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
297
|
+
label: "hints",
|
|
298
|
+
children: /* @__PURE__ */ jsx(TagsField, {
|
|
299
|
+
value: hints,
|
|
300
|
+
onChange: (v) => updateAttributes({ hints: v }),
|
|
301
|
+
placeholder: "comma-separated hints"
|
|
302
|
+
})
|
|
303
|
+
}),
|
|
304
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
305
|
+
label: "vectors",
|
|
306
|
+
children: /* @__PURE__ */ jsx(RowsEditor, {
|
|
307
|
+
rows: vectors,
|
|
308
|
+
onChange: (v) => updateAttributes({ vectors: v }),
|
|
309
|
+
columns: [
|
|
310
|
+
{
|
|
311
|
+
key: "label",
|
|
312
|
+
label: "label"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
key: "dx",
|
|
316
|
+
label: "dx"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
key: "dy",
|
|
320
|
+
label: "dy"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
key: "color",
|
|
324
|
+
label: "color",
|
|
325
|
+
grow: true
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
key: "drag",
|
|
329
|
+
label: "drag",
|
|
330
|
+
type: "bool"
|
|
331
|
+
}
|
|
332
|
+
],
|
|
333
|
+
newRow: () => ({
|
|
334
|
+
label: "",
|
|
335
|
+
dx: 1,
|
|
336
|
+
dy: 1,
|
|
337
|
+
drag: true
|
|
338
|
+
}),
|
|
339
|
+
addLabel: "vector"
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
] }), widget] });
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
const VectorTypesBlock = defineBlock({
|
|
346
|
+
key: "vector-types",
|
|
347
|
+
tag: "VectorTypes",
|
|
348
|
+
void: true,
|
|
349
|
+
label: "Vector types (reference figure)",
|
|
350
|
+
description: "Labeled gallery: equal, negative, null, unit, parallel, position. The vectors-chapter opener.",
|
|
351
|
+
category: "interactive",
|
|
352
|
+
schema: z.object({
|
|
353
|
+
title: z.string().optional(),
|
|
354
|
+
types: z.array(typePanelSchema).optional()
|
|
355
|
+
}),
|
|
356
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
357
|
+
const types = attributes.types;
|
|
358
|
+
const widget = /* @__PURE__ */ jsx(VectorTypesLab, {
|
|
359
|
+
title: attributes.title,
|
|
360
|
+
types
|
|
361
|
+
});
|
|
362
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
363
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [/* @__PURE__ */ jsx(ConfigRow, {
|
|
364
|
+
label: "title",
|
|
365
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
366
|
+
value: attributes.title ?? "",
|
|
367
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
368
|
+
placeholder: "Types of vectors"
|
|
369
|
+
})
|
|
370
|
+
}), /* @__PURE__ */ jsx(ConfigRow, {
|
|
371
|
+
label: "panels (advanced)",
|
|
372
|
+
children: /* @__PURE__ */ jsx(JsonArea, {
|
|
373
|
+
value: types ?? [],
|
|
374
|
+
onChange: (v) => updateAttributes({ types: v }),
|
|
375
|
+
rows: 6
|
|
376
|
+
})
|
|
377
|
+
})] }), widget] });
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
const RainRelativeBlock = defineBlock({
|
|
381
|
+
key: "rain-relative",
|
|
382
|
+
tag: "RainRelative",
|
|
383
|
+
void: true,
|
|
384
|
+
label: "Rain on a moving car (relative velocity)",
|
|
385
|
+
description: "Animated rain that slants as the car speeds up — apparent velocity V_rain − V_car, with a live triangle + angle.",
|
|
386
|
+
category: "interactive",
|
|
387
|
+
schema: z.object({
|
|
388
|
+
maxSpeed: z.number().default(10),
|
|
389
|
+
start: z.number().default(0),
|
|
390
|
+
title: z.string().optional(),
|
|
391
|
+
prompt: z.string().optional()
|
|
392
|
+
}),
|
|
393
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
394
|
+
const widget = /* @__PURE__ */ jsx(RainRelativeLab, {
|
|
395
|
+
maxSpeed: attributes.maxSpeed,
|
|
396
|
+
start: attributes.start,
|
|
397
|
+
title: attributes.title,
|
|
398
|
+
prompt: attributes.prompt
|
|
399
|
+
});
|
|
400
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
401
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [/* @__PURE__ */ jsx(ConfigRow, {
|
|
402
|
+
label: "title",
|
|
403
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
404
|
+
value: attributes.title ?? "",
|
|
405
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
406
|
+
placeholder: "Rain on a moving car"
|
|
407
|
+
})
|
|
408
|
+
}), /* @__PURE__ */ jsx(ConfigRow, {
|
|
409
|
+
label: "max speed",
|
|
410
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
411
|
+
value: attributes.maxSpeed ?? 10,
|
|
412
|
+
onChange: (v) => updateAttributes({ maxSpeed: v })
|
|
413
|
+
})
|
|
414
|
+
})] }), widget] });
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
const StoppingDistanceBlock = defineBlock({
|
|
418
|
+
key: "stopping-distance",
|
|
419
|
+
tag: "StoppingDistance",
|
|
420
|
+
void: true,
|
|
421
|
+
label: "Stopping distance (drive & brake)",
|
|
422
|
+
description: "1-D kinematics: a car reacts then brakes; the road paints a blue thinking stripe + red braking stripe while synced v–t (area = distance) and s–t graphs share a playhead. ×2 speed shows thinking double but braking quadruple.",
|
|
423
|
+
category: "interactive",
|
|
424
|
+
schema: z.object({
|
|
425
|
+
speed: z.number().default(20),
|
|
426
|
+
reactionTime: z.number().default(.7),
|
|
427
|
+
deceleration: z.number().default(6),
|
|
428
|
+
predict: z.boolean().default(false),
|
|
429
|
+
showGraphs: z.boolean().default(false),
|
|
430
|
+
title: z.string().optional(),
|
|
431
|
+
prompt: z.string().optional()
|
|
432
|
+
}),
|
|
433
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
434
|
+
const widget = /* @__PURE__ */ jsx(StoppingDistanceLab, {
|
|
435
|
+
speed: attributes.speed,
|
|
436
|
+
reactionTime: attributes.reactionTime,
|
|
437
|
+
deceleration: attributes.deceleration,
|
|
438
|
+
predict: attributes.predict,
|
|
439
|
+
showGraphs: attributes.showGraphs,
|
|
440
|
+
title: attributes.title,
|
|
441
|
+
prompt: attributes.prompt
|
|
442
|
+
});
|
|
443
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
444
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
445
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
446
|
+
label: "title",
|
|
447
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
448
|
+
value: attributes.title ?? "",
|
|
449
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
450
|
+
placeholder: "Drive & Brake"
|
|
451
|
+
})
|
|
452
|
+
}),
|
|
453
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
454
|
+
label: "speed (m/s)",
|
|
455
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
456
|
+
value: attributes.speed ?? 20,
|
|
457
|
+
onChange: (v) => updateAttributes({ speed: v })
|
|
458
|
+
})
|
|
459
|
+
}),
|
|
460
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
461
|
+
label: "reaction (s)",
|
|
462
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
463
|
+
value: attributes.reactionTime ?? .7,
|
|
464
|
+
onChange: (v) => updateAttributes({ reactionTime: v })
|
|
465
|
+
})
|
|
466
|
+
}),
|
|
467
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
468
|
+
label: "brake (m/s²)",
|
|
469
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
470
|
+
value: attributes.deceleration ?? 6,
|
|
471
|
+
onChange: (v) => updateAttributes({ deceleration: v })
|
|
472
|
+
})
|
|
473
|
+
})
|
|
474
|
+
] }), widget] });
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
const RampForcesBlock = defineBlock({
|
|
478
|
+
key: "ramp-forces",
|
|
479
|
+
tag: "RampForces",
|
|
480
|
+
void: true,
|
|
481
|
+
label: "Ramp forces (F = ma on an incline)",
|
|
482
|
+
description: "Tilt the incline: the weight vector splits into mg sinθ (down-slope) + mg cosθ (into-slope), the normal force shrinks as you tilt (N = mg cosθ), a friction slider spans frictionless→sticky, and the crate slides at a = g(sinθ − μcosθ).",
|
|
483
|
+
category: "interactive",
|
|
484
|
+
schema: z.object({
|
|
485
|
+
angleDeg: z.number().default(30),
|
|
486
|
+
mass: z.number().default(2),
|
|
487
|
+
friction: z.number().default(.3),
|
|
488
|
+
showComponents: z.boolean().default(false),
|
|
489
|
+
title: z.string().optional(),
|
|
490
|
+
prompt: z.string().optional(),
|
|
491
|
+
controls: controlConfigSchema.optional().describe("hide/lock knobs: angle, push, mass, frictionStatic, frictionKinetic, components, release")
|
|
492
|
+
}),
|
|
493
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
494
|
+
const widget = /* @__PURE__ */ jsx(RampForcesLab, {
|
|
495
|
+
angleDeg: attributes.angleDeg,
|
|
496
|
+
mass: attributes.mass,
|
|
497
|
+
friction: attributes.friction,
|
|
498
|
+
showComponents: attributes.showComponents,
|
|
499
|
+
title: attributes.title,
|
|
500
|
+
prompt: attributes.prompt,
|
|
501
|
+
controlConfig: attributes.controls
|
|
502
|
+
});
|
|
503
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
504
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
505
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
506
|
+
label: "title",
|
|
507
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
508
|
+
value: attributes.title ?? "",
|
|
509
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
510
|
+
placeholder: "Tilt the Ramp"
|
|
511
|
+
})
|
|
512
|
+
}),
|
|
513
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
514
|
+
label: "angle (°)",
|
|
515
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
516
|
+
value: attributes.angleDeg ?? 30,
|
|
517
|
+
onChange: (v) => updateAttributes({ angleDeg: v })
|
|
518
|
+
})
|
|
519
|
+
}),
|
|
520
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
521
|
+
label: "friction μ",
|
|
522
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
523
|
+
value: attributes.friction ?? .3,
|
|
524
|
+
onChange: (v) => updateAttributes({ friction: v })
|
|
525
|
+
})
|
|
526
|
+
}),
|
|
527
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
528
|
+
label: "controls — e.g. { \"hide\": [\"mass\"], \"lock\": [\"angle\"] }",
|
|
529
|
+
children: /* @__PURE__ */ jsx(JsonArea, {
|
|
530
|
+
value: attributes.controls ?? {},
|
|
531
|
+
onChange: (v) => updateAttributes({ controls: v }),
|
|
532
|
+
rows: 3
|
|
533
|
+
})
|
|
534
|
+
})
|
|
535
|
+
] }), widget] });
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
const CollisionTrackBlock = defineBlock({
|
|
539
|
+
key: "collision-track",
|
|
540
|
+
tag: "CollisionTrack",
|
|
541
|
+
void: true,
|
|
542
|
+
label: "Collision track (momentum & elasticity)",
|
|
543
|
+
description: "Two carts collide; one elasticity slider morphs inelastic↔elastic. The momentum bar stays full while the KE bar leaks when sticky, and a constant-velocity centre-of-mass marker proves momentum is conserved either way.",
|
|
544
|
+
category: "interactive",
|
|
545
|
+
schema: z.object({
|
|
546
|
+
m1: z.number().default(1),
|
|
547
|
+
m2: z.number().default(1),
|
|
548
|
+
u1: z.number().default(4),
|
|
549
|
+
u2: z.number().default(-2),
|
|
550
|
+
elasticity: z.number().default(1),
|
|
551
|
+
showCenterOfMass: z.boolean().default(true),
|
|
552
|
+
title: z.string().optional(),
|
|
553
|
+
prompt: z.string().optional()
|
|
554
|
+
}),
|
|
555
|
+
Component: ({ attributes, mode, updateAttributes }) => {
|
|
556
|
+
const widget = /* @__PURE__ */ jsx(CollisionTrackLab, {
|
|
557
|
+
m1: attributes.m1,
|
|
558
|
+
m2: attributes.m2,
|
|
559
|
+
u1: attributes.u1,
|
|
560
|
+
u2: attributes.u2,
|
|
561
|
+
elasticity: attributes.elasticity,
|
|
562
|
+
showCenterOfMass: attributes.showCenterOfMass,
|
|
563
|
+
title: attributes.title,
|
|
564
|
+
prompt: attributes.prompt
|
|
565
|
+
});
|
|
566
|
+
if (mode !== "editing" || !updateAttributes) return widget;
|
|
567
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(ConfigPanel, { children: [
|
|
568
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
569
|
+
label: "title",
|
|
570
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
571
|
+
value: attributes.title ?? "",
|
|
572
|
+
onChange: (v) => updateAttributes({ title: v }),
|
|
573
|
+
placeholder: "Sticky or Bouncy?"
|
|
574
|
+
})
|
|
575
|
+
}),
|
|
576
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
577
|
+
label: "elasticity",
|
|
578
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
579
|
+
value: attributes.elasticity ?? 1,
|
|
580
|
+
onChange: (v) => updateAttributes({ elasticity: v })
|
|
581
|
+
})
|
|
582
|
+
}),
|
|
583
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
584
|
+
label: "m₁",
|
|
585
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
586
|
+
value: attributes.m1 ?? 1,
|
|
587
|
+
onChange: (v) => updateAttributes({ m1: v })
|
|
588
|
+
})
|
|
589
|
+
}),
|
|
590
|
+
/* @__PURE__ */ jsx(ConfigRow, {
|
|
591
|
+
label: "m₂",
|
|
592
|
+
children: /* @__PURE__ */ jsx(NumField, {
|
|
593
|
+
value: attributes.m2 ?? 1,
|
|
594
|
+
onChange: (v) => updateAttributes({ m2: v })
|
|
595
|
+
})
|
|
596
|
+
})
|
|
597
|
+
] }), widget] });
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
const common = commonLabProps;
|
|
601
|
+
const wlab = (key, label, description, schema, Comp, tag) => labBlock({
|
|
602
|
+
key,
|
|
603
|
+
label,
|
|
604
|
+
description,
|
|
605
|
+
schema,
|
|
606
|
+
Component: Comp,
|
|
607
|
+
tag
|
|
608
|
+
});
|
|
609
|
+
const waveSchema = z.object({
|
|
610
|
+
mode: z.enum([
|
|
611
|
+
"travelling",
|
|
612
|
+
"superpose",
|
|
613
|
+
"standing"
|
|
614
|
+
]).optional(),
|
|
615
|
+
amplitude: z.number().optional(),
|
|
616
|
+
wavelength: z.number().optional(),
|
|
617
|
+
frequency: z.number().optional(),
|
|
618
|
+
...common
|
|
619
|
+
});
|
|
620
|
+
const WaveBlock = wlab("wave-lab", "Waves (travelling / superposition / standing)", "One waves playground: shape a travelling wave (v=fλ), add a second for interference/beats, or lock two opposite waves into a standing wave with nodes/antinodes. Optional sound.", waveSchema, (a) => /* @__PURE__ */ jsx(WaveLab, { ...a }));
|
|
621
|
+
const rippleSchema = z.object({
|
|
622
|
+
wavelength: z.number().optional(),
|
|
623
|
+
view: z.enum(["ripples", "fringes"]).optional(),
|
|
624
|
+
...common
|
|
625
|
+
});
|
|
626
|
+
const RippleTankBlock = wlab("ripple-tank", "Ripple tank (2-D interference)", "Two draggable sources → live circular ripples or the static bright/dark interference fringes (Δ=nλ vs (n+½)λ).", rippleSchema, (a) => /* @__PURE__ */ jsx(RippleTankLab, { ...a }));
|
|
627
|
+
const dopplerSchema = z.object({
|
|
628
|
+
mach: z.number().optional(),
|
|
629
|
+
...common
|
|
630
|
+
});
|
|
631
|
+
const DopplerBlock = wlab("doppler", "Doppler effect", "A moving source bunches wavefronts ahead (higher pitch) and stretches them behind; past Mach 1 a shock cone forms. Drive-by siren via Web Audio.", dopplerSchema, (a) => /* @__PURE__ */ jsx(DopplerLab, { ...a }));
|
|
632
|
+
const stringSchema = z.object({
|
|
633
|
+
mode: z.enum(["pulse", "resonance"]).optional(),
|
|
634
|
+
end: z.enum(["fixed", "free"]).optional(),
|
|
635
|
+
frequency: z.number().optional(),
|
|
636
|
+
...common
|
|
637
|
+
});
|
|
638
|
+
const StringReflectionBlock = wlab("string-reflection", "Reflection & standing waves on a string", "A pulse reflects (fixed end inverts, free end upright); a continuous wave + its reflection lock into a standing wave at the resonant harmonics fₙ=n·c/2L.", stringSchema, (a) => /* @__PURE__ */ jsx(StringReflectionLab, { ...a }));
|
|
639
|
+
const magnetismSchema = z.object({ ...common });
|
|
640
|
+
const MagnetismBlock = wlab("magnetism", "Magnetism — field lines & compass", "Drag a bar magnet (or switch to a current-carrying wire); the field lines retrace live and a draggable compass needle aligns to the field.", magnetismSchema, (a) => /* @__PURE__ */ jsx(MagnetismLab, { ...a }));
|
|
641
|
+
const lorentzSchema = z.object({
|
|
642
|
+
charge: z.union([z.literal(1), z.literal(-1)]).optional(),
|
|
643
|
+
fieldOut: z.boolean().optional(),
|
|
644
|
+
B: z.number().optional(),
|
|
645
|
+
speed: z.number().optional(),
|
|
646
|
+
...common
|
|
647
|
+
});
|
|
648
|
+
const LorentzBlock = wlab("lorentz", "Lorentz force F = q·v×B", "A charge fired into a magnetic field curves (cyclotron motion); v, B, F shown perpendicular with the right-hand rule. Flip charge or field → the curve reverses. Cyclotron / aurora framing.", lorentzSchema, (a) => /* @__PURE__ */ jsx(LorentzForceLab, { ...a }));
|
|
649
|
+
const impulseSchema = z.object({
|
|
650
|
+
mass: z.number().optional(),
|
|
651
|
+
speed: z.number().optional(),
|
|
652
|
+
contact: z.number().optional(),
|
|
653
|
+
crackForce: z.number().optional(),
|
|
654
|
+
...common
|
|
655
|
+
});
|
|
656
|
+
const ImpulseBlock = wlab("impulse", "Impulse — catch the egg (J = F·Δt = Δp)", "Same ball, same speed → fixed impulse. Stretch the contact time and the force–time pulse morphs from a tall spike to a low bump with EQUAL shaded area, so the peak force plummets. A fragile egg cracks above its force limit — the number behind airbags, crumple zones and bending your knees.", impulseSchema, (a) => /* @__PURE__ */ jsx(ImpulseLab, { ...a }));
|
|
657
|
+
const bulletWallsSchema = z.object({
|
|
658
|
+
speed: z.number().optional(),
|
|
659
|
+
toughness: z.number().optional(),
|
|
660
|
+
planks: z.number().optional(),
|
|
661
|
+
mass: z.number().optional(),
|
|
662
|
+
...common
|
|
663
|
+
});
|
|
664
|
+
const BulletWallsBlock = wlab("bullet-walls", "Bullet through N planks (penetration)", "The classic \"how many planks?\" problem, predict-first: each plank drains a fixed chunk of energy (a fixed Δv²), so the bullet slows plank-by-plank and lodges when its kinetic energy runs out. Guess the count, fire, and watch v² = u² − 2as play out with a draining energy bar.", bulletWallsSchema, (a) => /* @__PURE__ */ jsx(BulletWallsLab, { ...a }));
|
|
665
|
+
const ccSchema = z.object({
|
|
666
|
+
hide: z.array(z.string()).optional(),
|
|
667
|
+
lock: z.array(z.string()).optional()
|
|
668
|
+
}).optional();
|
|
669
|
+
const circularSchema = z.object({
|
|
670
|
+
speed: z.number().optional(),
|
|
671
|
+
radius: z.number().optional(),
|
|
672
|
+
mass: z.number().optional(),
|
|
673
|
+
controlConfig: ccSchema,
|
|
674
|
+
...common
|
|
675
|
+
});
|
|
676
|
+
const CircularMotionBlock = wlab("circular-motion", "Circular motion — centripetal force & cut the string", "A ball whirls on a string: velocity stays tangent while the tension (centripetal force F = mv²/r) points to the centre, bending the path without changing speed. Cut the string and it flies off along the TANGENT — not radially outward — killing the classic misconception. Live F, ω and period.", circularSchema, (a) => /* @__PURE__ */ jsx(CircularMotionLab, { ...a }));
|
|
677
|
+
const energySkateSchema = z.object({
|
|
678
|
+
startHeight: z.number().optional(),
|
|
679
|
+
friction: z.boolean().optional(),
|
|
680
|
+
mass: z.number().optional(),
|
|
681
|
+
controlConfig: ccSchema,
|
|
682
|
+
...common
|
|
683
|
+
});
|
|
684
|
+
const EnergySkateBlock = wlab("energy-skate", "Energy skate park — KE ⇄ PE (+ heat)", "A skater released on a ramp: potential, kinetic and thermal bars always sum to the same total. Friction off → it returns to the same height forever; friction on → the heat bar grows and every peak is lower. Energy conservation and conversion, animated (the LOL bar chart).", energySkateSchema, (a) => /* @__PURE__ */ jsx(EnergySkateLab, { ...a }));
|
|
685
|
+
const shmSchema = z.object({
|
|
686
|
+
mode: z.enum(["spring", "pendulum"]).optional(),
|
|
687
|
+
k: z.number().optional(),
|
|
688
|
+
length: z.number().optional(),
|
|
689
|
+
mass: z.number().optional(),
|
|
690
|
+
amplitude: z.number().optional(),
|
|
691
|
+
controlConfig: ccSchema,
|
|
692
|
+
...common
|
|
693
|
+
});
|
|
694
|
+
const SimpleHarmonicBlock = wlab("shm", "Simple harmonic motion — spring & pendulum", "One a = −ω²x kernel, two skins. A restoring force ∝ displacement gives x(t) = A·cos(ωt), and a pen traces it out as a SINE — the bridge to the waves lessons. Spring: ω=√(k/m). Pendulum: ω=√(g/L), with the period independent of mass and amplitude. Live ω/T/f and a PE⇄KE energy split.", shmSchema, (a) => /* @__PURE__ */ jsx(SimpleHarmonicLab, { ...a }), "SimpleHarmonic");
|
|
695
|
+
const atwoodSchema = z.object({
|
|
696
|
+
m1: z.number().optional(),
|
|
697
|
+
m2: z.number().optional(),
|
|
698
|
+
...common
|
|
699
|
+
});
|
|
700
|
+
const AtwoodBlock = wlab("atwood", "Atwood machine — two masses over a pulley", "Two masses share one rope over a pulley. Only the difference in weight drives the system while the total mass resists it: a = (m₁−m₂)g/(m₁+m₂), tension T = 2m₁m₂g/(m₁+m₂). Equal masses balance; a tiny difference on big masses gives a slow, measurable a — how Atwood weighed gravity. Predict which side falls, then release.", atwoodSchema, (a) => /* @__PURE__ */ jsx(AtwoodLab, { ...a }));
|
|
701
|
+
const terminalSchema = z.object({
|
|
702
|
+
mass: z.number().optional(),
|
|
703
|
+
drag: z.number().optional(),
|
|
704
|
+
parachute: z.boolean().optional(),
|
|
705
|
+
controlConfig: ccSchema,
|
|
706
|
+
...common
|
|
707
|
+
});
|
|
708
|
+
const TerminalVelocityBlock = wlab("terminal-velocity", "Terminal velocity — the skydiver (air drag)", "A fall with air resistance: drag grows with speed (∝v²) until it balances gravity, so the speed levels off at v_t = √(mg/b). The weight arrow stays fixed while the drag arrow rises to meet it and the v–t curve flattens onto its asymptote (exact tanh solution). Pop the parachute and v_t collapses to a survivable speed.", terminalSchema, (a) => /* @__PURE__ */ jsx(TerminalVelocityLab, { ...a }));
|
|
709
|
+
const keplerSchema = z.object({
|
|
710
|
+
semiMajor: z.number().optional(),
|
|
711
|
+
eccentricity: z.number().optional(),
|
|
712
|
+
wedges: z.boolean().optional(),
|
|
713
|
+
controlConfig: ccSchema,
|
|
714
|
+
...common
|
|
715
|
+
});
|
|
716
|
+
const KeplerBlock = wlab("kepler", "Kepler’s laws — orbits & equal areas", "A planet on a true ellipse with the star at a focus (Kepler 1). Solving Kepler’s equation makes it genuinely speed up at perihelion, and the equal-time wedges it sweeps come out equal in area (Kepler 2) — fat-and-short near the star, thin-and-long far out. Stretch the orbit and the period grows as T² ∝ a³ (Kepler 3).", keplerSchema, (a) => /* @__PURE__ */ jsx(KeplerLab, { ...a }));
|
|
717
|
+
const gravitationSchema = z.object({
|
|
718
|
+
planetMass: z.number().optional(),
|
|
719
|
+
satMass: z.number().optional(),
|
|
720
|
+
...common
|
|
721
|
+
});
|
|
722
|
+
const GravitationBlock = wlab("gravitation", "Universal gravitation — the inverse-square law", "Newton’s F = G·M·m / r². Drag the satellite and the pull tracks 1/r²: double the distance and the force drops to a quarter (not a half). A live F–r curve marks your spot on the steep fall-off; the same law thins weight with altitude (g = GM/r²) and sets orbital speed v = √(GM/r).", gravitationSchema, (a) => /* @__PURE__ */ jsx(GravitationLab, { ...a }));
|
|
723
|
+
const heatTransferSchema = z.object({
|
|
724
|
+
mode: z.enum([
|
|
725
|
+
"conduction",
|
|
726
|
+
"convection",
|
|
727
|
+
"radiation"
|
|
728
|
+
]).optional(),
|
|
729
|
+
controlConfig: ccSchema,
|
|
730
|
+
...common
|
|
731
|
+
});
|
|
732
|
+
const HeatTransferBlock = wlab("heat-transfer", "Heat transfer — conduction / convection / radiation", "The three ways heat moves, each with its rate law and animation. Author a survey (all three) OR a focused lesson: set mode + controlConfig.hide=['mechanism'] to show conduction (or convection / radiation) on its own.", heatTransferSchema, (a) => /* @__PURE__ */ jsx(HeatTransferLab, { ...a }));
|
|
733
|
+
const thermalExpansionSchema = z.object({
|
|
734
|
+
mode: z.enum([
|
|
735
|
+
"length",
|
|
736
|
+
"area",
|
|
737
|
+
"volume",
|
|
738
|
+
"bimetallic"
|
|
739
|
+
]).optional(),
|
|
740
|
+
controlConfig: ccSchema,
|
|
741
|
+
...common
|
|
742
|
+
});
|
|
743
|
+
const ThermalExpansionBlock = wlab("thermal-expansion", "Thermal expansion — length / area / volume / bimetallic", "Heat a solid and it grows: ΔL=αLΔT, ΔA=2αAΔT, ΔV=3αVΔT, plus a bimetallic-strip thermostat. Author one case (e.g. mode:'area', controlConfig.hide=['what expands']) or the full set.", thermalExpansionSchema, (a) => /* @__PURE__ */ jsx(ThermalExpansionLab, { ...a }));
|
|
744
|
+
const heatingCurveSchema = z.object({
|
|
745
|
+
substance: z.enum(["water", "ethanol"]).optional().describe("preset to start from"),
|
|
746
|
+
substanceName: z.string().optional().describe("custom substance name (overrides the preset)"),
|
|
747
|
+
cSolid: z.number().optional(),
|
|
748
|
+
cLiquid: z.number().optional(),
|
|
749
|
+
cGas: z.number().optional(),
|
|
750
|
+
lFusion: z.number().optional().describe("latent heat of fusion, J/g"),
|
|
751
|
+
lVapor: z.number().optional().describe("latent heat of vaporisation, J/g"),
|
|
752
|
+
tMelt: z.number().optional(),
|
|
753
|
+
tBoil: z.number().optional(),
|
|
754
|
+
mass: z.number().optional().describe("initial sample mass, g"),
|
|
755
|
+
power: z.number().optional().describe("initial heating power, W (negative cools)"),
|
|
756
|
+
...common
|
|
757
|
+
});
|
|
758
|
+
const HeatingCurveBlock = wlab("heating-curve", "Heating curve — q=mcΔθ runs + latent plateaus", "Pour heat into ice and watch temperature climb in steps: sloped runs where a phase warms (q=mcΔθ) and flat plateaus where it melts/boils (q=mL). Burner + beaker + thermometer beside the live curve. AUTHOR the model: pick a preset OR declare a custom substance (specific + latent heats, melt/boil points) and the starting mass/power.", heatingCurveSchema, (a) => /* @__PURE__ */ jsx(HeatingCurveLab, { ...a }));
|
|
759
|
+
const gasProcessSchema = z.object({
|
|
760
|
+
kind: z.enum([
|
|
761
|
+
"isothermal",
|
|
762
|
+
"adiabatic",
|
|
763
|
+
"isobaric",
|
|
764
|
+
"isochoric"
|
|
765
|
+
]).optional(),
|
|
766
|
+
gas: z.enum(["monatomic", "diatomic"]).optional(),
|
|
767
|
+
moles: z.number().optional(),
|
|
768
|
+
tempK: z.number().optional().describe("initial temperature, K"),
|
|
769
|
+
volumeL: z.number().optional().describe("initial volume, L"),
|
|
770
|
+
...common
|
|
771
|
+
});
|
|
772
|
+
const GasProcessBlock = wlab("gas-process", "Gas processes — work = area under P–V", "Expand/compress an ideal gas isothermally, adiabatically, isobarically or isochorically. The shaded area under the P–V curve is the work; the first law ΔU = Q − W balances every term. A faint reference isotherm shows the adiabatic falling steeper.", gasProcessSchema, (a) => /* @__PURE__ */ jsx(GasProcessLab, { ...a }));
|
|
773
|
+
const carnotSchema = z.object({
|
|
774
|
+
hotK: z.number().optional().describe("hot reservoir temperature, K"),
|
|
775
|
+
coldK: z.number().optional().describe("cold reservoir temperature, K"),
|
|
776
|
+
gas: z.enum(["monatomic", "diatomic"]).optional(),
|
|
777
|
+
expansionRatio: z.number().optional().describe("isothermal expansion V₂/V₁"),
|
|
778
|
+
...common
|
|
779
|
+
});
|
|
780
|
+
const CarnotBlock = wlab("carnot", "Carnot cycle — P–V loop + T–S rectangle", "The most efficient heat engine, shown as a P–V loop (enclosed area = net work) and the same cycle as a T–S rectangle (heat in at Th, out at Tc). Efficiency η = 1 − Tc/Th, with the entropy bookkeeping ΔS = Qh/Th = Qc/Tc → net 0.", carnotSchema, (a) => /* @__PURE__ */ jsx(CarnotCycleLab, { ...a }));
|
|
781
|
+
const entropySchema = z.object({
|
|
782
|
+
mode: z.enum(["heat", "expansion"]).optional(),
|
|
783
|
+
...common
|
|
784
|
+
});
|
|
785
|
+
const EntropyBlock = wlab("entropy", "Entropy & the 2nd law — the one-way arrow", "Why heat flows hot→cold (ΔS_total = Q/Tc − Q/Th > 0) and a gas spreads into a vacuum (ΔS = nR·ln Vf/Vi). The total entropy of the universe always increases. Two modes: heat flow and free expansion.", entropySchema, (a) => /* @__PURE__ */ jsx(EntropyLab, { ...a }));
|
|
786
|
+
const tempScalesSchema = z.object({ ...common });
|
|
787
|
+
const TemperatureScalesBlock = wlab("temperature-scales", "Temperature scales — °C / °F / K", "One mercury column read against Celsius, Fahrenheit and Kelvin at once (F = 9⁄5·C + 32, K = C + 273.15). Fixed points marked; jump to absolute zero, ice, body, boiling. Shows why Kelvin starts at absolute zero.", tempScalesSchema, (a) => /* @__PURE__ */ jsx(TemperatureScalesLab, { ...a }));
|
|
788
|
+
const waterDensitySchema = z.object({
|
|
789
|
+
mode: z.enum(["anomaly", "lake"]).optional(),
|
|
790
|
+
...common
|
|
791
|
+
});
|
|
792
|
+
const WaterDensityBlock = wlab("water-density", "Water’s 4 °C anomaly — why ice floats", "Water is densest at 4 °C and expands again toward freezing, so ice floats. Drag the temperature on the density curve, or switch to the lake view to see why a pond freezes top-down (4 °C water and fish survive below the ice).", waterDensitySchema, (a) => /* @__PURE__ */ jsx(WaterDensityLab, { ...a }));
|
|
793
|
+
const efficiencySchema = z.object({
|
|
794
|
+
device: z.enum([
|
|
795
|
+
"incandescent",
|
|
796
|
+
"led",
|
|
797
|
+
"petrol-engine",
|
|
798
|
+
"electric-motor",
|
|
799
|
+
"power-station",
|
|
800
|
+
"human"
|
|
801
|
+
]).optional(),
|
|
802
|
+
deviceName: z.string().optional(),
|
|
803
|
+
inputJoules: z.number().optional().describe("energy supplied, J (100 → shares read as %)"),
|
|
804
|
+
streams: z.array(z.object({
|
|
805
|
+
label: z.string(),
|
|
806
|
+
share: z.number(),
|
|
807
|
+
kind: z.enum(["useful", "waste"]),
|
|
808
|
+
color: z.string().optional()
|
|
809
|
+
})).optional().describe("author your own energy breakdown"),
|
|
810
|
+
...common
|
|
811
|
+
});
|
|
812
|
+
const EfficiencyBlock = wlab("efficiency", "Efficiency — input→output ratio (Sankey)", "Efficiency as the fraction of energy that comes out useful: η = useful ÷ input, drawn as a Sankey energy flow that splits into a useful stream and wasted heat. Compare real devices (incandescent vs LED, engine vs motor) or AUTHOR your own breakdown via the streams field.", efficiencySchema, (a) => /* @__PURE__ */ jsx(EfficiencyLab, { ...a }));
|
|
813
|
+
const physicsBlocks = [
|
|
814
|
+
ProjectileLabBlock,
|
|
815
|
+
OrbitLabBlock,
|
|
816
|
+
GravityDropBlock,
|
|
817
|
+
RiverBoatBlock,
|
|
818
|
+
OpticsBlock,
|
|
819
|
+
LeverBlock,
|
|
820
|
+
VectorBoardBlock,
|
|
821
|
+
VectorTypesBlock,
|
|
822
|
+
RainRelativeBlock,
|
|
823
|
+
StoppingDistanceBlock,
|
|
824
|
+
RampForcesBlock,
|
|
825
|
+
CollisionTrackBlock,
|
|
826
|
+
WaveBlock,
|
|
827
|
+
RippleTankBlock,
|
|
828
|
+
DopplerBlock,
|
|
829
|
+
StringReflectionBlock,
|
|
830
|
+
MagnetismBlock,
|
|
831
|
+
LorentzBlock,
|
|
832
|
+
ImpulseBlock,
|
|
833
|
+
BulletWallsBlock,
|
|
834
|
+
CircularMotionBlock,
|
|
835
|
+
EnergySkateBlock,
|
|
836
|
+
SimpleHarmonicBlock,
|
|
837
|
+
AtwoodBlock,
|
|
838
|
+
TerminalVelocityBlock,
|
|
839
|
+
KeplerBlock,
|
|
840
|
+
GravitationBlock,
|
|
841
|
+
HeatTransferBlock,
|
|
842
|
+
ThermalExpansionBlock,
|
|
843
|
+
HeatingCurveBlock,
|
|
844
|
+
GasProcessBlock,
|
|
845
|
+
CarnotBlock,
|
|
846
|
+
EntropyBlock,
|
|
847
|
+
TemperatureScalesBlock,
|
|
848
|
+
WaterDensityBlock,
|
|
849
|
+
EfficiencyBlock
|
|
850
|
+
];
|
|
851
|
+
const physicsComponents = {
|
|
852
|
+
...buildComponents(physicsBlocks),
|
|
853
|
+
VectorBoard: VectorBoardView,
|
|
854
|
+
VectorTypes: VectorTypesLab,
|
|
855
|
+
RainRelative: RainRelativeLab,
|
|
856
|
+
StoppingDistance: StoppingDistanceLab,
|
|
857
|
+
RampForces: RampForcesLab,
|
|
858
|
+
CollisionTrack: CollisionTrackLab,
|
|
859
|
+
Optics: OpticsLab,
|
|
860
|
+
Lever: LeverPuzzle,
|
|
861
|
+
ProjectileLab,
|
|
862
|
+
RiverBoat,
|
|
863
|
+
OrbitLab,
|
|
864
|
+
GravityDrop
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
//#endregion
|
|
868
|
+
export { AtwoodBlock, BulletWallsBlock, CarnotBlock, CircularMotionBlock, CollisionTrackBlock, DopplerBlock, EfficiencyBlock, EnergySkateBlock, EntropyBlock, GasProcessBlock, GravitationBlock, GravityDropBlock, HeatTransferBlock, HeatingCurveBlock, ImpulseBlock, KeplerBlock, LeverBlock, LeverPuzzle, LorentzBlock, MagnetismBlock, OpticsBlock, OrbitLabBlock, ProjectileLabBlock, RainRelativeBlock, RampForcesBlock, RippleTankBlock, RiverBoatBlock, SimpleHarmonicBlock, StoppingDistanceBlock, StringReflectionBlock, TemperatureScalesBlock, TerminalVelocityBlock, ThermalExpansionBlock, VectorBoardBlock, VectorTypesBlock, WaterDensityBlock, WaveBlock, physicsBlocks, physicsComponents };
|